wok-next rev 21072

Update Xorg packages
author Aleksej Bobylev <al.bobylev@gmail.com>
date Thu Dec 20 17:55:43 2018 +0200 (2018-12-20)
parents 4d9f82dabdbb
children 166472454f0c
files ---libva-intel-driver/receipt bdftopcf/.icon.png bdftopcf/receipt bitmap/.icon.png bitmap/receipt cf-files/.icon.png cf-files/receipt cmrt/receipt encodings/.icon.png encodings/receipt evieext/.icon.png evieext/receipt font-adobe-100dpi/.icon.png font-adobe-100dpi/receipt font-adobe-75dpi/.icon.png font-adobe-75dpi/receipt font-adobe-utopia-100dpi/.icon.png font-adobe-utopia-100dpi/receipt font-adobe-utopia-75dpi/.icon.png font-adobe-utopia-75dpi/receipt font-adobe-utopia-type1/.icon.png font-adobe-utopia-type1/receipt font-alias/.icon.png font-alias/receipt font-arabic-misc/.icon.png font-arabic-misc/receipt font-bh-100dpi/.icon.png font-bh-100dpi/receipt font-bh-75dpi/.icon.png font-bh-75dpi/receipt font-bh-lucidatypewriter-100dpi/.icon.png font-bh-lucidatypewriter-100dpi/receipt font-bh-lucidatypewriter-75dpi/.icon.png font-bh-lucidatypewriter-75dpi/receipt font-bh-ttf/.icon.png font-bh-ttf/receipt font-bh-type1/.icon.png font-bh-type1/receipt font-bitstream-100dpi/.icon.png font-bitstream-100dpi/receipt font-bitstream-75dpi/.icon.png font-bitstream-75dpi/receipt font-bitstream-type1/.icon.png font-bitstream-type1/receipt font-cronyx-cyrillic/.icon.png font-cronyx-cyrillic/receipt font-cursor-misc/.icon.png font-cursor-misc/receipt font-daewoo-misc/.icon.png font-daewoo-misc/receipt font-dec-misc/.icon.png font-dec-misc/receipt font-ibm-type1/.icon.png font-ibm-type1/receipt font-isas-misc/.icon.png font-isas-misc/receipt font-jis-misc/.icon.png font-jis-misc/receipt font-micro-misc/.icon.png font-micro-misc/receipt font-misc-cyrillic/.icon.png font-misc-cyrillic/receipt font-misc-ethiopic/.icon.png font-misc-ethiopic/receipt font-misc-meltho/.icon.png font-misc-meltho/description.txt font-misc-meltho/receipt font-misc-misc/.icon.png font-misc-misc/receipt font-mutt-misc/.icon.png font-mutt-misc/receipt font-schumacher-misc/.icon.png font-schumacher-misc/receipt font-screen-cyrillic/.icon.png font-screen-cyrillic/receipt font-sony-misc/.icon.png font-sony-misc/receipt font-sun-misc/.icon.png font-sun-misc/receipt font-util/.icon.png font-util/receipt font-winitzki-cyrillic/.icon.png font-winitzki-cyrillic/receipt font-xfree86-type1/.icon.png font-xfree86-type1/receipt fonts-crosextra-caladea/receipt fonttosfnt/.icon.png fonttosfnt/receipt fslsfonts/.icon.png fslsfonts/receipt fstobdf/.icon.png fstobdf/receipt gccmakedep/.icon.png gccmakedep/receipt iceauth/.icon.png iceauth/receipt imake/.icon.png imake/receipt intel-hybrid-driver/receipt intel-vaapi-driver/receipt libdmx/.icon.png libdmx/receipt libdrm/receipt libevdev/receipt libfontenc/.icon.png libfontenc/receipt libfs/.icon.png libfs/receipt libice/.icon.png libice/receipt libinput/receipt liblbxutil/.icon.png liblbxutil/receipt libpciaccess/.icon.png libpciaccess/receipt libpng/receipt libpng/stuff/patches/libpng-1.6.35-apng.patch libpng/stuff/patches/series libpng16/receipt libpng16/stuff/patches/libpng-1.6.35-apng.patch libpng16/stuff/patches/series libsm/.icon.png libsm/receipt libva-intel-driver/receipt libva/receipt libvdpau-va-gl/receipt libvdpau-va-gl/stuff/xorg.sh libvdpau/receipt libx11/.icon.png libx11/receipt libxau/.icon.png libxau/receipt libxaw/.icon.png libxaw/receipt libxaw3d/.icon.png libxaw3d/receipt libxcb/.icon.png libxcb/description.txt libxcb/receipt libxcomposite/.icon.png libxcomposite/receipt libxcursor/.icon.png libxcursor/receipt libxdamage/.icon.png libxdamage/receipt libxdmcp/.icon.png libxdmcp/receipt libxext/.icon.png libxext/receipt libxfixes/.icon.png libxfixes/receipt libxfont/.icon.png libxfont/receipt libxfont2/.icon.png libxfont2/receipt libxfontcache/.icon.png libxfontcache/receipt libxft/.icon.png libxft/receipt libxi/.icon.png libxi/receipt libxinerama/.icon.png libxinerama/receipt libxkbcommon/receipt libxkbfile/.icon.png libxkbfile/receipt libxmu/.icon.png libxmu/receipt libxp/.icon.png libxp/receipt libxpm/.icon.png libxpm/receipt libxrandr/.icon.png libxrandr/receipt libxrender/.icon.png libxrender/receipt libxres/.icon.png libxres/receipt libxscrnsaver/.icon.png libxscrnsaver/receipt libxshmfence/.icon.png libxshmfence/receipt libxt/.icon.png libxt/receipt libxtst/.icon.png libxtst/receipt libxv/.icon.png libxv/receipt libxvmc/.icon.png libxvmc/receipt libxxf86dga/.icon.png libxxf86dga/receipt libxxf86misc/.icon.png libxxf86misc/receipt libxxf86vm/.icon.png libxxf86vm/receipt links/receipt llvm/receipt luit/.icon.png luit/receipt makedepend/.icon.png makedepend/receipt mesa/.icon.png mesa/receipt mesa/stuff/patches/0005-c99_math-fix-build-issue-with-glibc-2.26.patch mesa/stuff/patches/series mkfontdir/.icon.png mkfontdir/receipt mkfontscale/.icon.png mkfontscale/receipt oclock/.icon.png oclock/receipt pixman/.icon.png pixman/description.txt pixman/receipt rgb/.icon.png rgb/receipt sessreg/.icon.png sessreg/receipt setxkbmap/.icon.png setxkbmap/receipt showfont/.icon.png showfont/receipt smproxy/.icon.png smproxy/receipt twm/.icon.png twm/receipt util-macros/.icon.png util-macros/receipt wayland-protocols/receipt wayland/.icon.png wayland/receipt x11perf/.icon.png x11perf/receipt xauth/.icon.png xauth/receipt xbacklight/.icon.png xbacklight/receipt xbitmaps/.icon.png xbitmaps/receipt xcalc/.icon.png xcalc/receipt xcb-proto/.icon.png xcb-proto/description.txt xcb-proto/receipt xcb-util-cursor/.icon.png xcb-util-cursor/receipt xcb-util-image/.icon.png xcb-util-image/receipt xcb-util-keysyms/.icon.png xcb-util-keysyms/receipt xcb-util-renderutil/.icon.png xcb-util-renderutil/receipt xcb-util-wm/.icon.png xcb-util-wm/receipt xcb-util/.icon.png xcb-util/description.txt xcb-util/receipt xclipboard/.icon.png xclipboard/receipt xclock/.icon.png xclock/receipt xcmsdb/.icon.png xcmsdb/receipt xcompmgr/.icon.png xcompmgr/receipt xcompmgr/stuff/autostart/xcompmgr.desktop xcompmgr/stuff/patches/46285.diff xcompmgr/stuff/patches/series xcursor-themes/.icon.png xcursor-themes/description.txt xcursor-themes/receipt xcursorgen/.icon.png xcursorgen/receipt xdpyinfo/.icon.png xdpyinfo/receipt xdriinfo/.icon.png xdriinfo/receipt xedit/.icon.png xedit/receipt xev/.icon.png xev/receipt xeyes/.icon.png xeyes/receipt xf86-input-acecad/.icon.png xf86-input-acecad/receipt xf86-input-elographics/.icon.png xf86-input-elographics/receipt xf86-input-evdev/.icon.png xf86-input-evdev/receipt xf86-input-fpit/.icon.png xf86-input-fpit/receipt xf86-input-hyperpen/.icon.png xf86-input-hyperpen/receipt xf86-input-joystick/.icon.png xf86-input-joystick/receipt xf86-input-keyboard/.icon.png xf86-input-keyboard/receipt xf86-input-libinput/.icon.png xf86-input-libinput/receipt xf86-input-mouse/.icon.png xf86-input-mouse/receipt xf86-input-mutouch/.icon.png xf86-input-mutouch/receipt xf86-input-penmount/.icon.png xf86-input-penmount/receipt xf86-input-synaptics/.icon.png xf86-input-synaptics/receipt xf86-input-vmmouse/.icon.png xf86-input-vmmouse/receipt xf86-input-void/.icon.png xf86-input-void/receipt xf86-input-wacom/.icon.png xf86-input-wacom/receipt xf86-video-amdgpu/.icon.png xf86-video-amdgpu/receipt xf86-video-apm/.icon.png xf86-video-apm/receipt xf86-video-apm/stuff/patches/mibstore.patch xf86-video-apm/stuff/patches/series xf86-video-ark/.icon.png xf86-video-ark/receipt xf86-video-ark/stuff/patches/mibstore.patch xf86-video-ark/stuff/patches/series xf86-video-ast/.icon.png xf86-video-ast/receipt xf86-video-ati/.icon.png xf86-video-ati/receipt xf86-video-chips/.icon.png xf86-video-chips/receipt xf86-video-cirrus/.icon.png xf86-video-cirrus/receipt xf86-video-dummy/.icon.png xf86-video-dummy/receipt xf86-video-dummy/stuff/patches/mibstore.patch xf86-video-dummy/stuff/patches/series xf86-video-fbdev/.icon.png xf86-video-fbdev/receipt xf86-video-fbturbo/.icon.png xf86-video-fbturbo/receipt xf86-video-geode/.icon.png xf86-video-geode/receipt xf86-video-glint/.icon.png xf86-video-glint/receipt xf86-video-i128/.icon.png xf86-video-i128/receipt xf86-video-i740/.icon.png xf86-video-i740/receipt xf86-video-intel/.icon.png xf86-video-intel/receipt xf86-video-intel/stuff/overrides xf86-video-intel/stuff/patches/git.patch xf86-video-intel/stuff/patches/series xf86-video-mach64/.icon.png xf86-video-mach64/receipt xf86-video-neomagic/.icon.png xf86-video-neomagic/receipt xf86-video-nouveau/.icon.png xf86-video-nouveau/receipt xf86-video-nouveau/stuff/nvidia.conf xf86-video-nv/.icon.png xf86-video-nv/receipt xf86-video-omap/.icon.png xf86-video-omap/receipt xf86-video-openchrome/.icon.png xf86-video-openchrome/receipt xf86-video-qxl/.icon.png xf86-video-qxl/receipt xf86-video-r128/.icon.png xf86-video-r128/receipt xf86-video-rendition/.icon.png xf86-video-rendition/receipt xf86-video-s3/.icon.png xf86-video-s3/receipt xf86-video-s3/stuff/patches/mibstore.patch xf86-video-s3/stuff/patches/series xf86-video-s3virge/.icon.png xf86-video-s3virge/receipt xf86-video-s3virge/stuff/patches/check-max-value.patch xf86-video-s3virge/stuff/patches/series xf86-video-savage/.icon.png xf86-video-savage/receipt xf86-video-savage/stuff/patches/0001-Add-check-for-max-HV-Value-to-ValidMode-hook.patch xf86-video-savage/stuff/patches/series xf86-video-siliconmotion/.icon.png xf86-video-siliconmotion/receipt xf86-video-sis/.icon.png xf86-video-sis/receipt xf86-video-sis/stuff/patches/0001-Remove-reference-to-virtualFrom.patch xf86-video-sis/stuff/patches/series xf86-video-sisusb/.icon.png xf86-video-sisusb/receipt xf86-video-suncg14/.icon.png xf86-video-suncg14/receipt xf86-video-suncg3/.icon.png xf86-video-suncg3/receipt xf86-video-suncg6/.icon.png xf86-video-suncg6/receipt xf86-video-sunffb/.icon.png xf86-video-sunffb/receipt xf86-video-sunleo/.icon.png xf86-video-sunleo/receipt xf86-video-suntcx/.icon.png xf86-video-suntcx/receipt xf86-video-tdfx/.icon.png xf86-video-tdfx/receipt xf86-video-trident/.icon.png xf86-video-trident/receipt xf86-video-vesa/.icon.png xf86-video-vesa/receipt xf86-video-vmware/.icon.png xf86-video-vmware/receipt xf86-video-xgixp/.icon.png xf86-video-xgixp/receipt xf86-video-xgixp/stuff/patches/git-fixes.patch xf86-video-xgixp/stuff/patches/series xfd/.icon.png xfd/receipt xfontsel/.icon.png xfontsel/receipt xfs/.icon.png xfs/receipt xfsinfo/.icon.png xfsinfo/receipt xgamma/.icon.png xgamma/receipt xhost/.icon.png xhost/receipt xinit/.icon.png xinit/receipt xinit/stuff/patches/06_move_serverauthfile_into_tmp.diff xinit/stuff/patches/series xinit/stuff/xserverrc xinput/.icon.png xinput/receipt xkbcomp/.icon.png xkbcomp/receipt xkbevd/.icon.png xkbevd/receipt xkbprint/.icon.png xkbprint/receipt xkbutils/.icon.png xkbutils/receipt xkeyboard-config/.icon.png xkeyboard-config/receipt xkill/.icon.png xkill/receipt xload/.icon.png xload/receipt xload/stuff/xorg-xload.desktop xlsatoms/.icon.png xlsatoms/receipt xlsclients/.icon.png xlsclients/receipt xlsfonts/.icon.png xlsfonts/receipt xmag/.icon.png xmag/receipt xmessage/.icon.png xmessage/receipt xmlto/receipt xmodmap/.icon.png xmodmap/receipt xorg-bdftopcf/.icon.png xorg-bdftopcf/receipt xorg-bitmap/.icon.png xorg-bitmap/receipt xorg-cf-files/receipt xorg-encodings/.icon.png xorg-encodings/receipt xorg-evieext/.icon.png xorg-evieext/receipt xorg-font-adobe-100dpi/.icon.png xorg-font-adobe-100dpi/receipt xorg-font-adobe-75dpi/.icon.png xorg-font-adobe-75dpi/receipt xorg-font-adobe-utopia-100dpi/.icon.png xorg-font-adobe-utopia-100dpi/receipt xorg-font-adobe-utopia-75dpi/.icon.png xorg-font-adobe-utopia-75dpi/receipt xorg-font-adobe-utopia-type1/.icon.png xorg-font-adobe-utopia-type1/receipt xorg-font-alias/.icon.png xorg-font-alias/receipt xorg-font-arabic-misc/.icon.png xorg-font-arabic-misc/receipt xorg-font-bh-100dpi/.icon.png xorg-font-bh-100dpi/receipt xorg-font-bh-75dpi/.icon.png xorg-font-bh-75dpi/receipt xorg-font-bh-lucidatypewriter-100dpi/.icon.png xorg-font-bh-lucidatypewriter-100dpi/receipt xorg-font-bh-lucidatypewriter-75dpi/.icon.png xorg-font-bh-lucidatypewriter-75dpi/receipt xorg-font-bh-ttf/.icon.png xorg-font-bh-ttf/receipt xorg-font-bh-type1/.icon.png xorg-font-bh-type1/receipt xorg-font-bitstream-100dpi/.icon.png xorg-font-bitstream-100dpi/receipt xorg-font-bitstream-75dpi/.icon.png xorg-font-bitstream-75dpi/receipt xorg-font-bitstream-type1/.icon.png xorg-font-bitstream-type1/receipt xorg-font-cronyx-cyrillic/.icon.png xorg-font-cronyx-cyrillic/receipt xorg-font-cursor-misc/.icon.png xorg-font-cursor-misc/receipt xorg-font-daewoo-misc/.icon.png xorg-font-daewoo-misc/receipt xorg-font-dec-misc/.icon.png xorg-font-dec-misc/receipt xorg-font-ibm-type1/.icon.png xorg-font-ibm-type1/receipt xorg-font-isas-misc/.icon.png xorg-font-isas-misc/receipt xorg-font-jis-misc/.icon.png xorg-font-jis-misc/receipt xorg-font-micro-misc/.icon.png xorg-font-micro-misc/receipt xorg-font-misc-cyrillic/.icon.png xorg-font-misc-cyrillic/receipt xorg-font-misc-ethiopic/.icon.png xorg-font-misc-ethiopic/receipt xorg-font-misc-meltho/.icon.png xorg-font-misc-meltho/description.txt xorg-font-misc-meltho/receipt xorg-font-misc-misc/.icon.png xorg-font-misc-misc/receipt xorg-font-mutt-misc/.icon.png xorg-font-mutt-misc/receipt xorg-font-schumacher-misc/.icon.png xorg-font-schumacher-misc/receipt xorg-font-screen-cyrillic/.icon.png xorg-font-screen-cyrillic/receipt xorg-font-sony-misc/.icon.png xorg-font-sony-misc/receipt xorg-font-sun-misc/.icon.png xorg-font-sun-misc/receipt xorg-font-util/.icon.png xorg-font-util/receipt xorg-font-winitzki-cyrillic/.icon.png xorg-font-winitzki-cyrillic/receipt xorg-font-xfree86-type1/.icon.png xorg-font-xfree86-type1/receipt xorg-fonttosfnt/.icon.png xorg-fonttosfnt/receipt xorg-fslsfonts/.icon.png xorg-fslsfonts/receipt xorg-fstobdf/.icon.png xorg-fstobdf/receipt xorg-gccmakedep/.icon.png xorg-gccmakedep/receipt xorg-iceauth/.icon.png xorg-iceauth/receipt xorg-imake/.icon.png xorg-imake/receipt xorg-libFS/.icon.png xorg-libFS/receipt xorg-libICE/.icon.png xorg-libICE/receipt xorg-libSM/.icon.png xorg-libSM/receipt xorg-libX11/.icon.png xorg-libX11/receipt xorg-libXScrnSaver/.icon.png xorg-libXScrnSaver/receipt xorg-libXau/.icon.png xorg-libXau/receipt xorg-libXaw/.icon.png xorg-libXaw/receipt xorg-libXaw3d/.icon.png xorg-libXaw3d/receipt xorg-libXcomposite/.icon.png xorg-libXcomposite/receipt xorg-libXcursor/.icon.png xorg-libXcursor/receipt xorg-libXdamage/.icon.png xorg-libXdamage/receipt xorg-libXdmcp/.icon.png xorg-libXdmcp/receipt xorg-libXext/.icon.png xorg-libXext/receipt xorg-libXfixes/.icon.png xorg-libXfixes/receipt xorg-libXfont/.icon.png xorg-libXfont/receipt xorg-libXfont2/.icon.png xorg-libXfont2/receipt xorg-libXfontcache/.icon.png xorg-libXfontcache/receipt xorg-libXft/.icon.png xorg-libXft/receipt xorg-libXi/.icon.png xorg-libXi/receipt xorg-libXinerama/.icon.png xorg-libXinerama/receipt xorg-libXmu/.icon.png xorg-libXmu/receipt xorg-libXp/.icon.png xorg-libXp/receipt xorg-libXpm/.icon.png xorg-libXpm/receipt xorg-libXrandr/.icon.png xorg-libXrandr/receipt xorg-libXrender/.icon.png xorg-libXrender/receipt xorg-libXres/.icon.png xorg-libXres/receipt xorg-libXt/.icon.png xorg-libXt/receipt xorg-libXtst/.icon.png xorg-libXtst/receipt xorg-libXv/.icon.png xorg-libXv/receipt xorg-libXvMC/.icon.png xorg-libXvMC/receipt xorg-libXxf86dga/.icon.png xorg-libXxf86dga/receipt xorg-libXxf86misc/.icon.png xorg-libXxf86misc/receipt xorg-libXxf86vm/.icon.png xorg-libXxf86vm/receipt xorg-libdmx/.icon.png xorg-libdmx/receipt xorg-libfontenc/.icon.png xorg-libfontenc/receipt xorg-liblbxutil/.icon.png xorg-liblbxutil/receipt xorg-libpciaccess/.icon.png xorg-libpciaccess/receipt xorg-libxcb/.icon.png xorg-libxcb/description.txt xorg-libxcb/receipt xorg-libxkbfile/.icon.png xorg-libxkbfile/receipt xorg-libxshmfence/.icon.png xorg-libxshmfence/receipt xorg-luit/.icon.png xorg-luit/receipt xorg-makedepend/.icon.png xorg-makedepend/receipt xorg-mkfontdir/.icon.png xorg-mkfontdir/receipt xorg-mkfontscale/.icon.png xorg-mkfontscale/receipt xorg-oclock/.icon.png xorg-oclock/receipt xorg-pixman/.icon.png xorg-pixman/description.txt xorg-pixman/receipt xorg-rgb/.icon.png xorg-rgb/receipt xorg-server/receipt xorg-server/stuff/overrides xorg-sessreg/.icon.png xorg-sessreg/receipt xorg-setxkbmap/.icon.png xorg-setxkbmap/receipt xorg-showfont/.icon.png xorg-showfont/receipt xorg-smproxy/.icon.png xorg-smproxy/receipt xorg-twm/.icon.png xorg-twm/receipt xorg-util-macros/.icon.png xorg-util-macros/receipt xorg-x11perf/.icon.png xorg-x11perf/receipt xorg-xauth/.icon.png xorg-xauth/receipt xorg-xbacklight/.icon.png xorg-xbacklight/receipt xorg-xbitmaps/.icon.png xorg-xbitmaps/receipt xorg-xcalc/.icon.png xorg-xcalc/receipt xorg-xcb-proto/.icon.png xorg-xcb-proto/description.txt xorg-xcb-proto/receipt xorg-xcb-util-cursor/.icon.png xorg-xcb-util-cursor/receipt xorg-xcb-util-image/.icon.png xorg-xcb-util-image/receipt xorg-xcb-util-keysyms/.icon.png xorg-xcb-util-keysyms/receipt xorg-xcb-util-renderutil/.icon.png xorg-xcb-util-renderutil/receipt xorg-xcb-util-wm/.icon.png xorg-xcb-util-wm/receipt xorg-xcb-util/.icon.png xorg-xcb-util/description.txt xorg-xcb-util/receipt xorg-xclipboard/.icon.png xorg-xclipboard/receipt xorg-xclock/.icon.png xorg-xclock/receipt xorg-xcmsdb/.icon.png xorg-xcmsdb/receipt xorg-xcompmgr/.icon.png xorg-xcompmgr/receipt xorg-xcompmgr/stuff/autostart/xcompmgr.desktop xorg-xcompmgr/stuff/patches/46285.diff xorg-xcompmgr/stuff/patches/series xorg-xcursor-themes/.icon.png xorg-xcursor-themes/description.txt xorg-xcursor-themes/receipt xorg-xcursorgen/.icon.png xorg-xcursorgen/receipt xorg-xdpyinfo/.icon.png xorg-xdpyinfo/receipt xorg-xdriinfo/.icon.png xorg-xdriinfo/receipt xorg-xedit/.icon.png xorg-xedit/receipt xorg-xev/.icon.png xorg-xev/receipt xorg-xeyes/.icon.png xorg-xeyes/receipt xorg-xf86-input-acecad/.icon.png xorg-xf86-input-acecad/receipt xorg-xf86-input-elographics/.icon.png xorg-xf86-input-elographics/receipt xorg-xf86-input-evdev/.icon.png xorg-xf86-input-evdev/receipt xorg-xf86-input-fpit/.icon.png xorg-xf86-input-fpit/receipt xorg-xf86-input-hyperpen/.icon.png xorg-xf86-input-hyperpen/receipt xorg-xf86-input-joystick/.icon.png xorg-xf86-input-joystick/receipt xorg-xf86-input-keyboard/.icon.png xorg-xf86-input-keyboard/receipt xorg-xf86-input-libinput/.icon.png xorg-xf86-input-libinput/receipt xorg-xf86-input-mouse/.icon.png xorg-xf86-input-mouse/receipt xorg-xf86-input-mutouch/.icon.png xorg-xf86-input-mutouch/receipt xorg-xf86-input-penmount/.icon.png xorg-xf86-input-penmount/receipt xorg-xf86-input-synaptics/.icon.png xorg-xf86-input-synaptics/receipt xorg-xf86-input-vmmouse/.icon.png xorg-xf86-input-vmmouse/receipt xorg-xf86-input-void/.icon.png xorg-xf86-input-void/receipt xorg-xf86-input-wacom/.icon.png xorg-xf86-input-wacom/receipt xorg-xf86-video-amdgpu/.icon.png xorg-xf86-video-amdgpu/receipt xorg-xf86-video-ast/.icon.png xorg-xf86-video-ast/receipt xorg-xf86-video-ati/.icon.png xorg-xf86-video-ati/receipt xorg-xf86-video-chips/.icon.png xorg-xf86-video-chips/receipt xorg-xf86-video-cirrus/.icon.png xorg-xf86-video-cirrus/receipt xorg-xf86-video-fbdev/.icon.png xorg-xf86-video-fbdev/receipt xorg-xf86-video-fbturbo/.icon.png xorg-xf86-video-fbturbo/receipt xorg-xf86-video-geode/.icon.png xorg-xf86-video-geode/receipt xorg-xf86-video-glint/.icon.png xorg-xf86-video-glint/receipt xorg-xf86-video-i740/.icon.png xorg-xf86-video-i740/receipt xorg-xf86-video-intel/.icon.png xorg-xf86-video-intel/receipt xorg-xf86-video-intel/stuff/patches/git.patch xorg-xf86-video-intel/stuff/patches/series xorg-xf86-video-mach64/.icon.png xorg-xf86-video-mach64/receipt xorg-xf86-video-neomagic/.icon.png xorg-xf86-video-neomagic/receipt xorg-xf86-video-nouveau/.icon.png xorg-xf86-video-nouveau/receipt xorg-xf86-video-nv/.icon.png xorg-xf86-video-nv/receipt xorg-xf86-video-omap/.icon.png xorg-xf86-video-omap/receipt xorg-xf86-video-openchrome/.icon.png xorg-xf86-video-openchrome/receipt xorg-xf86-video-qxl/.icon.png xorg-xf86-video-qxl/receipt xorg-xf86-video-r128/.icon.png xorg-xf86-video-r128/receipt xorg-xf86-video-rendition/.icon.png xorg-xf86-video-rendition/receipt xorg-xf86-video-s3virge/.icon.png xorg-xf86-video-s3virge/receipt xorg-xf86-video-s3virge/stuff/patches/check-max-value.patch xorg-xf86-video-s3virge/stuff/patches/series xorg-xf86-video-savage/.icon.png xorg-xf86-video-savage/receipt xorg-xf86-video-siliconmotion/.icon.png xorg-xf86-video-siliconmotion/receipt xorg-xf86-video-sis/.icon.png xorg-xf86-video-sis/receipt xorg-xf86-video-sisusb/.icon.png xorg-xf86-video-sisusb/receipt xorg-xf86-video-suncg14/.icon.png xorg-xf86-video-suncg14/receipt xorg-xf86-video-suncg3/.icon.png xorg-xf86-video-suncg3/receipt xorg-xf86-video-suncg6/.icon.png xorg-xf86-video-suncg6/receipt xorg-xf86-video-sunffb/.icon.png xorg-xf86-video-sunffb/receipt xorg-xf86-video-sunleo/.icon.png xorg-xf86-video-sunleo/receipt xorg-xf86-video-suntcx/.icon.png xorg-xf86-video-suntcx/receipt xorg-xf86-video-tdfx/.icon.png xorg-xf86-video-tdfx/receipt xorg-xf86-video-trident/.icon.png xorg-xf86-video-trident/receipt xorg-xf86-video-vesa/.icon.png xorg-xf86-video-vesa/receipt xorg-xf86-video-vmware/.icon.png xorg-xf86-video-vmware/receipt xorg-xfd/.icon.png xorg-xfd/receipt xorg-xfontsel/.icon.png xorg-xfontsel/receipt xorg-xfs/.icon.png xorg-xfs/receipt xorg-xfsinfo/.icon.png xorg-xfsinfo/receipt xorg-xgamma/.icon.png xorg-xgamma/receipt xorg-xhost/.icon.png xorg-xhost/receipt xorg-xinit/.icon.png xorg-xinit/receipt xorg-xinit/stuff/patches/06_move_serverauthfile_into_tmp.diff xorg-xinit/stuff/patches/series xorg-xinit/stuff/xserverrc xorg-xinput/.icon.png xorg-xinput/receipt xorg-xkbcomp/.icon.png xorg-xkbcomp/receipt xorg-xkbevd/.icon.png xorg-xkbevd/receipt xorg-xkbprint/.icon.png xorg-xkbprint/receipt xorg-xkbutils/.icon.png xorg-xkbutils/receipt xorg-xkeyboard-config/.icon.png xorg-xkeyboard-config/receipt xorg-xkill/.icon.png xorg-xkill/receipt xorg-xload/.icon.png xorg-xload/receipt xorg-xload/stuff/xorg-xload.desktop xorg-xlsatoms/.icon.png xorg-xlsatoms/receipt xorg-xlsclients/.icon.png xorg-xlsclients/receipt xorg-xlsfonts/.icon.png xorg-xlsfonts/receipt xorg-xmag/.icon.png xorg-xmag/receipt xorg-xmessage/.icon.png xorg-xmessage/receipt xorg-xmodmap/.icon.png xorg-xmodmap/receipt xorg-xorgproto/.icon.png xorg-xorgproto/receipt xorg-xpr/.icon.png xorg-xpr/receipt xorg-xprop/.icon.png xorg-xprop/receipt xorg-xrandr/.icon.png xorg-xrandr/receipt xorg-xrdb/.icon.png xorg-xrdb/receipt xorg-xrefresh/.icon.png xorg-xrefresh/receipt xorg-xset/.icon.png xorg-xset/receipt xorg-xset/stuff/xorg-xset.desktop xorg-xset/stuff/xset-screensaver.sh xorg-xsetmode/.icon.png xorg-xsetmode/receipt xorg-xsetpointer/.icon.png xorg-xsetpointer/receipt xorg-xsetroot/.icon.png xorg-xsetroot/receipt xorg-xsm/.icon.png xorg-xsm/receipt xorg-xtrans/.icon.png xorg-xtrans/receipt xorg-xvidtune/.icon.png xorg-xvidtune/receipt xorg-xvinfo/.icon.png xorg-xvinfo/receipt xorg-xwd/.icon.png xorg-xwd/receipt xorg-xwininfo/.icon.png xorg-xwininfo/receipt xorg-xwud/.icon.png xorg-xwud/receipt xorg/receipt xorgproto/.icon.png xorgproto/receipt xpr/.icon.png xpr/receipt xprop/.icon.png xprop/receipt xrandr/.icon.png xrandr/receipt xrdb/.icon.png xrdb/receipt xrefresh/.icon.png xrefresh/receipt xset/.icon.png xset/receipt xset/stuff/xorg-xset.desktop xset/stuff/xset-screensaver.sh xsetmode/.icon.png xsetmode/receipt xsetpointer/.icon.png xsetpointer/receipt xsetroot/.icon.png xsetroot/receipt xsm/.icon.png xsm/receipt xterm/.icon.png xterm/receipt xterm/stuff/xterm.desktop xtrans/.icon.png xtrans/receipt xvidtune/.icon.png xvidtune/receipt xvinfo/.icon.png xvinfo/receipt xwd/.icon.png xwd/receipt xwininfo/.icon.png xwininfo/receipt xwud/.icon.png xwud/receipt yaml/receipt
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/---libva-intel-driver/receipt	Thu Dec 20 17:55:43 2018 +0200
     1.3 @@ -0,0 +1,29 @@
     1.4 +# SliTaz package receipt v2.
     1.5 +
     1.6 +PACKAGE="libva-intel-driver"
     1.7 +VERSION="1.7.3"
     1.8 +CATEGORY="x-window"
     1.9 +SHORT_DESC="VA Intel driver"
    1.10 +MAINTAINER="al.bobylev@gmail.com"
    1.11 +LICENSE="other"
    1.12 +WEB_SITE="https://www.freedesktop.org/wiki/Software/vaapi/"
    1.13 +
    1.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
    1.15 +WGET_URL="https://www.freedesktop.org/software/vaapi/releases/$PACKAGE/$TARBALL"
    1.16 +
    1.17 +BUILD_DEPENDS="autoconf automake libtool python libdrm-dev libva-dev \
    1.18 +xorg-libpciaccess-dev xorg-libX11-dev"
    1.19 +
    1.20 +compile_rules() {
    1.21 +	autoreconf -fi &&
    1.22 +
    1.23 +	./configure $CONFIGURE_ARGS &&
    1.24 +	fix libtool &&
    1.25 +	make &&
    1.26 +	make install
    1.27 +}
    1.28 +
    1.29 +genpkg_rules() {
    1.30 +	copy @std
    1.31 +	DEPENDS="libdrm libdrm-intel xorg-libpciaccess"
    1.32 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/bdftopcf/.icon.png	Thu Dec 20 17:55:43 2018 +0200
     2.3 @@ -0,0 +1,1 @@
     2.4 +../xorg/.icon.png
     2.5 \ No newline at end of file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/bdftopcf/receipt	Thu Dec 20 17:55:43 2018 +0200
     3.3 @@ -0,0 +1,28 @@
     3.4 +# SliTaz package receipt v2.
     3.5 +
     3.6 +PACKAGE="bdftopcf"
     3.7 +VERSION="1.1"
     3.8 +CATEGORY="x-window"
     3.9 +SHORT_DESC="Convert X font from Bitmap Distribution Format to Portable \
    3.10 +Compiled Format"
    3.11 +MAINTAINER="pascal.bellard@slitaz.org"
    3.12 +LICENSE="MIT"
    3.13 +WEB_SITE="https://www.x.org/wiki/"
    3.14 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
    3.15 +
    3.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
    3.17 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
    3.18 +TARBALL_SHA1="48a783337a5aa49ebc102c9788ff0f43ea35c5c4"
    3.19 +
    3.20 +BUILD_DEPENDS="util-macros libxfont-dev xtrans"
    3.21 +DEPENDS="libxfont"
    3.22 +
    3.23 +compile_rules() {
    3.24 +	./configure $CONFIGURE_ARGS &&
    3.25 +	make &&
    3.26 +	make install
    3.27 +}
    3.28 +
    3.29 +TAGS="Xorg"
    3.30 +
    3.31 +PROVIDE="xorg-bdftopcf"
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/bitmap/.icon.png	Thu Dec 20 17:55:43 2018 +0200
     4.3 @@ -0,0 +1,1 @@
     4.4 +../xorg/.icon.png
     4.5 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/bitmap/receipt	Thu Dec 20 17:55:43 2018 +0200
     5.3 @@ -0,0 +1,30 @@
     5.4 +# SliTaz package receipt v2.
     5.5 +
     5.6 +PACKAGE="bitmap"
     5.7 +VERSION="1.0.8"
     5.8 +CATEGORY="x-window"
     5.9 +SHORT_DESC="XBM format bitmap editor and converter utilities"
    5.10 +MAINTAINER="al.bobylev@gmail.com"
    5.11 +LICENSE="MIT"
    5.12 +WEB_SITE="https://www.x.org/wiki/"
    5.13 +
    5.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
    5.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
    5.16 +TARBALL_SHA1="84fc49daa5411677d05a134ee2f7e76301fa89d8"
    5.17 +
    5.18 +BUILD_DEPENDS="util-macros libx11-dev libxmu-dev xorgproto xbitmaps libxaw-dev"
    5.19 +DEPENDS="libx11 libxaw libxmu libxt"
    5.20 +
    5.21 +COPY="@std @dev"
    5.22 +CONFIG_FILES="/etc/X11/app-defaults/Bitmap \
    5.23 +/etc/X11/app-defaults/Bitmap-color /etc/X11/app-defaults/Bitmap-nocase"
    5.24 +
    5.25 +compile_rules() {
    5.26 +	./configure $CONFIGURE_ARGS &&
    5.27 +	make &&
    5.28 +	make install
    5.29 +}
    5.30 +
    5.31 +TAGS="Xorg"
    5.32 +
    5.33 +PROVIDE="xorg-bitmap"
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/cf-files/.icon.png	Thu Dec 20 17:55:43 2018 +0200
     6.3 @@ -0,0 +1,1 @@
     6.4 +../xorg/.icon.png
     6.5 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/cf-files/receipt	Thu Dec 20 17:55:43 2018 +0200
     7.3 @@ -0,0 +1,19 @@
     7.4 +# SliTaz package receipt v2.
     7.5 +
     7.6 +PACKAGE="xorg-cf-files"
     7.7 +VERSION="1.0.6"
     7.8 +CATEGORY="development"
     7.9 +SHORT_DESC="Config files used by Xorg and Imake"
    7.10 +MAINTAINER="devel@slitaz.org"
    7.11 +LICENSE="MIT"
    7.12 +WEB_SITE="https://www.x.org/wiki/"
    7.13 +HOST_ARCH="any"
    7.14 +
    7.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
    7.16 +WGET_URL="$XORG_MIRROR/util/$TARBALL"
    7.17 +
    7.18 +compile_rules() {
    7.19 +	./configure $CONFIGURE_ARGS &&
    7.20 +	make &&
    7.21 +	make install
    7.22 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/cmrt/receipt	Thu Dec 20 17:55:43 2018 +0200
     8.3 @@ -0,0 +1,29 @@
     8.4 +# SliTaz package receipt v2.
     8.5 +
     8.6 +PACKAGE="cmrt"
     8.7 +VERSION="1.0.6"
     8.8 +CATEGORY="x-window"
     8.9 +SHORT_DESC="C for Media Runtime"
    8.10 +MAINTAINER="al.bobylev@gmail.com"
    8.11 +LICENSE="MIT"
    8.12 +WEB_SITE="https://github.com/intel/cmrt"
    8.13 +
    8.14 +TARBALL="$PACKAGE-$VERSION.tar.gz"
    8.15 +WGET_URL="https://github.com/intel/cmrt/archive/$VERSION.tar.gz"
    8.16 +TARBALL_SHA1="4f39fe24f96644a3ed1aa595ab3e7fb45386088a"
    8.17 +
    8.18 +BUILD_DEPENDS="automake libtool libdrm-dev libva-dev"
    8.19 +SPLIT="$PACKAGE-dev"
    8.20 +
    8.21 +DEPENDS="libdrm libdrm-intel"
    8.22 +CONFIG_FILES="/etc/cmrt.conf"
    8.23 +
    8.24 +compile_rules() {
    8.25 +	mkdir m4
    8.26 +
    8.27 +	./autogen.sh \
    8.28 +		$CONFIGURE_ARGS &&
    8.29 +	fix libtool &&
    8.30 +	make &&
    8.31 +	make install
    8.32 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/encodings/.icon.png	Thu Dec 20 17:55:43 2018 +0200
     9.3 @@ -0,0 +1,1 @@
     9.4 +../xorg/.icon.png
     9.5 \ No newline at end of file
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/encodings/receipt	Thu Dec 20 17:55:43 2018 +0200
    10.3 @@ -0,0 +1,27 @@
    10.4 +# SliTaz package receipt v2.
    10.5 +
    10.6 +PACKAGE="encodings"
    10.7 +VERSION="1.0.4"
    10.8 +CATEGORY="x-window"
    10.9 +SHORT_DESC="The XFree86/Xorg encoding files"
   10.10 +MAINTAINER="al.bobylev@gmail.com"
   10.11 +LICENSE="PublicDomain"
   10.12 +WEB_SITE="https://www.x.org/wiki/"
   10.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   10.14 +HOST_ARCH="any"
   10.15 +
   10.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   10.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   10.18 +TARBALL_SHA1="24ace2470403f85a0d393769204029bd8247992a"
   10.19 +
   10.20 +BUILD_DEPENDS="util-macros mkfontscale font-util-dev"
   10.21 +
   10.22 +compile_rules() {
   10.23 +	./configure $CONFIGURE_ARGS &&
   10.24 +	make &&
   10.25 +	make install
   10.26 +}
   10.27 +
   10.28 +TAGS="Xorg"
   10.29 +
   10.30 +PROVIDE="xorg-encodings"
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/evieext/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    11.3 @@ -0,0 +1,1 @@
    11.4 +../xorg/.icon.png
    11.5 \ No newline at end of file
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/evieext/receipt	Thu Dec 20 17:55:43 2018 +0200
    12.3 @@ -0,0 +1,29 @@
    12.4 +# SliTaz package receipt v2.
    12.5 +
    12.6 +PACKAGE="evieext"
    12.7 +VERSION="1.1.1"
    12.8 +CATEGORY="development"
    12.9 +SHORT_DESC="XEvIE extension header files"
   12.10 +MAINTAINER="devel@slitaz.org"
   12.11 +LICENSE="MIT"
   12.12 +WEB_SITE="https://www.x.org/wiki/"
   12.13 +HOST_ARCH="any"
   12.14 +
   12.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   12.16 +WGET_URL="$XORG_MIRROR/proto/$TARBALL"
   12.17 +TARBALL_SHA1="86d9545273b07961f0d5ba65c6c408371e10c0d2"
   12.18 +
   12.19 +BUILD_DEPENDS="util-macros"
   12.20 +DEPENDS="util-macros"
   12.21 +
   12.22 +COPY="@dev"
   12.23 +
   12.24 +compile_rules() {
   12.25 +	./configure $CONFIGURE_ARGS &&
   12.26 +	make &&
   12.27 +	make install
   12.28 +}
   12.29 +
   12.30 +TAGS="Xorg"
   12.31 +
   12.32 +PROVIDE="xorg-evieext"
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/font-adobe-100dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    13.3 @@ -0,0 +1,1 @@
    13.4 +../xorg/.icon.png
    13.5 \ No newline at end of file
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/font-adobe-100dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    14.3 @@ -0,0 +1,39 @@
    14.4 +# SliTaz package receipt v2.
    14.5 +
    14.6 +PACKAGE="font-adobe-100dpi"
    14.7 +VERSION="1.0.3"
    14.8 +CATEGORY="x-window"
    14.9 +SHORT_DESC="Adobe bitmap fonts Courier, Helvetica, New Century Schoolbook, \
   14.10 +Symbol, Times (100 DPI)"
   14.11 +MAINTAINER="al.bobylev@gmail.com"
   14.12 +LICENSE="MIT"
   14.13 +WEB_SITE="https://www.x.org/wiki/"
   14.14 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
   14.15 +HOST_ARCH="any"
   14.16 +REPOLOGY="fonts:adobe-100dpi"
   14.17 +
   14.18 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   14.19 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   14.20 +TARBALL_SHA1="53311cbd604f18bd9570727105a4222473d363e3"
   14.21 +
   14.22 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   14.23 +COOKOPTS="!gz" # too long
   14.24 +
   14.25 +compile_rules() {
   14.26 +	./configure \
   14.27 +		--disable-all-encodings \
   14.28 +		$CONFIGURE_ARGS &&
   14.29 +	make &&
   14.30 +	make install
   14.31 +}
   14.32 +
   14.33 +post_install() {
   14.34 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
   14.35 +}
   14.36 +post_remove() {
   14.37 +	chroot "$1/" fc-cache -r
   14.38 +}
   14.39 +
   14.40 +TAGS="Xorg font"
   14.41 +
   14.42 +PROVIDE="xorg-font-adobe-100dpi"
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/font-adobe-75dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    15.3 @@ -0,0 +1,1 @@
    15.4 +../xorg/.icon.png
    15.5 \ No newline at end of file
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/font-adobe-75dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    16.3 @@ -0,0 +1,39 @@
    16.4 +# SliTaz package receipt v2.
    16.5 +
    16.6 +PACKAGE="font-adobe-75dpi"
    16.7 +VERSION="1.0.3"
    16.8 +CATEGORY="x-window"
    16.9 +SHORT_DESC="Adobe bitmap fonts Courier, Helvetica, New Century Schoolbook, \
   16.10 +Symbol, Times (75 DPI)"
   16.11 +MAINTAINER="al.bobylev@gmail.com"
   16.12 +LICENSE="MIT"
   16.13 +WEB_SITE="https://www.x.org/wiki/"
   16.14 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
   16.15 +HOST_ARCH="any"
   16.16 +REPOLOGY="fonts:adobe-75dpi"
   16.17 +
   16.18 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   16.19 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   16.20 +TARBALL_SHA1="6a2ec569336b5646682a14eee3c7790274beffd1"
   16.21 +
   16.22 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   16.23 +COOKOPTS="!gz" # too long
   16.24 +
   16.25 +compile_rules() {
   16.26 +	./configure \
   16.27 +		--disable-all-encodings \
   16.28 +		$CONFIGURE_ARGS &&
   16.29 +	make &&
   16.30 +	make install
   16.31 +}
   16.32 +
   16.33 +post_install() {
   16.34 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi/
   16.35 +}
   16.36 +post_remove() {
   16.37 +	chroot "$1/" fc-cache -r
   16.38 +}
   16.39 +
   16.40 +TAGS="Xorg font"
   16.41 +
   16.42 +PROVIDE="xorg-font-adobe-75dpi"
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/font-adobe-utopia-100dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    17.3 @@ -0,0 +1,1 @@
    17.4 +../xorg/.icon.png
    17.5 \ No newline at end of file
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/font-adobe-utopia-100dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    18.3 @@ -0,0 +1,37 @@
    18.4 +# SliTaz package receipt v2.
    18.5 +
    18.6 +PACKAGE="font-adobe-utopia-100dpi"
    18.7 +VERSION="1.0.4"
    18.8 +CATEGORY="x-window"
    18.9 +SHORT_DESC="Adobe bitmap font Utopia (100 DPI)"
   18.10 +MAINTAINER="al.bobylev@gmail.com"
   18.11 +LICENSE="other"
   18.12 +WEB_SITE="https://www.x.org/wiki/"
   18.13 +HOST_ARCH="any"
   18.14 +REPOLOGY="fonts:adobe-utopia-100dpi"
   18.15 +
   18.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   18.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   18.18 +TARBALL_SHA1="9e80cf5bbd5522a5cfad2a9f8f8fce86de0f0226"
   18.19 +
   18.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   18.21 +COOKOPTS="!gz" # too long
   18.22 +
   18.23 +compile_rules() {
   18.24 +	./configure \
   18.25 +		--disable-all-encodings \
   18.26 +		$CONFIGURE_ARGS &&
   18.27 +	make &&
   18.28 +	make install
   18.29 +}
   18.30 +
   18.31 +post_install() {
   18.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
   18.33 +}
   18.34 +post_remove() {
   18.35 +	chroot "$1/" fc-cache -r
   18.36 +}
   18.37 +
   18.38 +TAGS="Xorg font"
   18.39 +
   18.40 +PROVIDE="xorg-font-adobe-utopia-100dpi"
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/font-adobe-utopia-75dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    19.3 @@ -0,0 +1,1 @@
    19.4 +../xorg/.icon.png
    19.5 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/font-adobe-utopia-75dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    20.3 @@ -0,0 +1,37 @@
    20.4 +# SliTaz package receipt v2.
    20.5 +
    20.6 +PACKAGE="font-adobe-utopia-75dpi"
    20.7 +VERSION="1.0.4"
    20.8 +CATEGORY="x-window"
    20.9 +SHORT_DESC="Adobe bitmap font Utopia (75 DPI)"
   20.10 +MAINTAINER="al.bobylev@gmail.com"
   20.11 +LICENSE="other"
   20.12 +WEB_SITE="https://www.x.org/wiki/"
   20.13 +HOST_ARCH="any"
   20.14 +REPOLOGY="fonts:adobe-utopia-75dpi"
   20.15 +
   20.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   20.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   20.18 +TARBALL_SHA1="50e837322a09f1a7c40fb78fc6aad1a157284507"
   20.19 +
   20.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   20.21 +COOKOPTS="!gz" # too long
   20.22 +
   20.23 +compile_rules() {
   20.24 +	./configure \
   20.25 +		--disable-all-encodings \
   20.26 +		$CONFIGURE_ARGS &&
   20.27 +	make &&
   20.28 +	make install
   20.29 +}
   20.30 +
   20.31 +post_install() {
   20.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
   20.33 +}
   20.34 +post_remove() {
   20.35 +	chroot "$1/" fc-cache -r
   20.36 +}
   20.37 +
   20.38 +TAGS="Xorg font"
   20.39 +
   20.40 +PROVIDE="xorg-font-adobe-utopia-75dpi"
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/font-adobe-utopia-type1/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    21.3 @@ -0,0 +1,1 @@
    21.4 +../xorg/.icon.png
    21.5 \ No newline at end of file
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/font-adobe-utopia-type1/receipt	Thu Dec 20 17:55:43 2018 +0200
    22.3 @@ -0,0 +1,35 @@
    22.4 +# SliTaz package receipt v2.
    22.5 +
    22.6 +PACKAGE="font-adobe-utopia-type1"
    22.7 +VERSION="1.0.4"
    22.8 +CATEGORY="x-window"
    22.9 +SHORT_DESC="Adobe Type 1 font Utopia"
   22.10 +MAINTAINER="al.bobylev@gmail.com"
   22.11 +LICENSE="other"
   22.12 +WEB_SITE="https://www.x.org/wiki/"
   22.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   22.14 +HOST_ARCH="any"
   22.15 +REPOLOGY="fonts:adobe-utopia-type1"
   22.16 +
   22.17 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   22.18 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   22.19 +TARBALL_SHA1="3113cfafb91c2c53df6a1fae57dca6c50fb8ce20"
   22.20 +
   22.21 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   22.22 +
   22.23 +compile_rules() {
   22.24 +	./configure $CONFIGURE_ARGS &&
   22.25 +	make &&
   22.26 +	make install
   22.27 +}
   22.28 +
   22.29 +post_install() {
   22.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
   22.31 +}
   22.32 +post_remove() {
   22.33 +	chroot "$1/" fc-cache -r
   22.34 +}
   22.35 +
   22.36 +TAGS="Xorg font"
   22.37 +
   22.38 +PROVIDE="xorg-font-adobe-utopia-type1"
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/font-alias/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    23.3 @@ -0,0 +1,1 @@
    23.4 +../xorg/.icon.png
    23.5 \ No newline at end of file
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/font-alias/receipt	Thu Dec 20 17:55:43 2018 +0200
    24.3 @@ -0,0 +1,27 @@
    24.4 +# SliTaz package receipt v2.
    24.5 +
    24.6 +PACKAGE="font-alias"
    24.7 +VERSION="1.0.3"
    24.8 +CATEGORY="x-window"
    24.9 +SHORT_DESC="X font aliases"
   24.10 +MAINTAINER="al.bobylev@gmail.com"
   24.11 +LICENSE="other"
   24.12 +WEB_SITE="https://www.x.org/wiki/"
   24.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   24.14 +HOST_ARCH="any"
   24.15 +
   24.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   24.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   24.18 +TARBALL_SHA1="96b0aa38f88a54ef32ab85d3eef6f29b0437f70d"
   24.19 +
   24.20 +BUILD_DEPENDS="util-macros font-util-dev"
   24.21 +
   24.22 +compile_rules() {
   24.23 +	./configure $CONFIGURE_ARGS &&
   24.24 +	make &&
   24.25 +	make install
   24.26 +}
   24.27 +
   24.28 +TAGS="Xorg"
   24.29 +
   24.30 +PROVIDE="xorg-font-alias"
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/font-arabic-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    25.3 @@ -0,0 +1,1 @@
    25.4 +../xorg/.icon.png
    25.5 \ No newline at end of file
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/font-arabic-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    26.3 @@ -0,0 +1,34 @@
    26.4 +# SliTaz package receipt v2.
    26.5 +
    26.6 +PACKAGE="font-arabic-misc"
    26.7 +VERSION="1.0.3"
    26.8 +CATEGORY="x-window"
    26.9 +SHORT_DESC="Misc Arabic fonts for X"
   26.10 +MAINTAINER="al.bobylev@gmail.com"
   26.11 +LICENSE="MIT"
   26.12 +WEB_SITE="https://www.x.org/wiki/"
   26.13 +HOST_ARCH="any"
   26.14 +REPOLOGY="fonts:arabic-misc"
   26.15 +
   26.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   26.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   26.18 +TARBALL_SHA1="322ae41e74deea8de11fa077fd0e0191927a667c"
   26.19 +
   26.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   26.21 +
   26.22 +compile_rules() {
   26.23 +	./configure $CONFIGURE_ARGS &&
   26.24 +	make &&
   26.25 +	make install
   26.26 +}
   26.27 +
   26.28 +post_install() {
   26.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   26.30 +}
   26.31 +post_remove() {
   26.32 +	chroot "$1/" fc-cache -r
   26.33 +}
   26.34 +
   26.35 +TAGS="Xorg font"
   26.36 +
   26.37 +PROVIDE="xorg-font-arabic-misc"
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/font-bh-100dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    27.3 @@ -0,0 +1,1 @@
    27.4 +../xorg/.icon.png
    27.5 \ No newline at end of file
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/font-bh-100dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    28.3 @@ -0,0 +1,37 @@
    28.4 +# SliTaz package receipt v2.
    28.5 +
    28.6 +PACKAGE="font-bh-100dpi"
    28.7 +VERSION="1.0.3"
    28.8 +CATEGORY="x-window"
    28.9 +SHORT_DESC="Bigelow & Holmes bitmap fonts Lucida and LucidaBright (100 DPI)"
   28.10 +MAINTAINER="al.bobylev@gmail.com"
   28.11 +LICENSE="MIT"
   28.12 +WEB_SITE="https://www.x.org/wiki/"
   28.13 +HOST_ARCH="any"
   28.14 +REPOLOGY="fonts:bh-100dpi"
   28.15 +
   28.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   28.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   28.18 +TARBALL_SHA1="47d5e50be9e78695017650a088da52bfcf1eeb40"
   28.19 +
   28.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   28.21 +COOKOPTS="!gz" # too long
   28.22 +
   28.23 +compile_rules() {
   28.24 +	./configure \
   28.25 +		--disable-all-encodings \
   28.26 +		$CONFIGURE_ARGS &&
   28.27 +	make &&
   28.28 +	make install
   28.29 +}
   28.30 +
   28.31 +post_install() {
   28.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
   28.33 +}
   28.34 +post_remove() {
   28.35 +	chroot "$1/" fc-cache -r
   28.36 +}
   28.37 +
   28.38 +TAGS="Xorg font"
   28.39 +
   28.40 +PROVIDE="xorg-font-bh-100dpi"
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/font-bh-75dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    29.3 @@ -0,0 +1,1 @@
    29.4 +../xorg/.icon.png
    29.5 \ No newline at end of file
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/font-bh-75dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    30.3 @@ -0,0 +1,37 @@
    30.4 +# SliTaz package receipt v2.
    30.5 +
    30.6 +PACKAGE="font-bh-75dpi"
    30.7 +VERSION="1.0.3"
    30.8 +CATEGORY="x-window"
    30.9 +SHORT_DESC="Bigelow & Holmes bitmap fonts Lucida and LucidaBright (75 DPI)"
   30.10 +MAINTAINER="al.bobylev@gmail.com"
   30.11 +LICENSE="MIT"
   30.12 +WEB_SITE="https://www.x.org/wiki/"
   30.13 +HOST_ARCH="any"
   30.14 +REPOLOGY="fonts:bh-75dpi"
   30.15 +
   30.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   30.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   30.18 +TARBALL_SHA1="7290567d42a0f5adb6a3ad170524bb7ed59871d7"
   30.19 +
   30.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   30.21 +COOKOPTS="!gz" # too long
   30.22 +
   30.23 +compile_rules() {
   30.24 +	./configure \
   30.25 +		--disable-all-encodings \
   30.26 +		$CONFIGURE_ARGS &&
   30.27 +	make &&
   30.28 +	make install
   30.29 +}
   30.30 +
   30.31 +post_install() {
   30.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
   30.33 +}
   30.34 +post_remove() {
   30.35 +	chroot "$1/" fc-cache -r
   30.36 +}
   30.37 +
   30.38 +TAGS="Xorg font"
   30.39 +
   30.40 +PROVIDE="xorg-font-bh-75dpi"
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/font-bh-lucidatypewriter-100dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    31.3 @@ -0,0 +1,1 @@
    31.4 +../xorg/.icon.png
    31.5 \ No newline at end of file
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/font-bh-lucidatypewriter-100dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    32.3 @@ -0,0 +1,37 @@
    32.4 +# SliTaz package receipt v2.
    32.5 +
    32.6 +PACKAGE="font-bh-lucidatypewriter-100dpi"
    32.7 +VERSION="1.0.3"
    32.8 +CATEGORY="x-window"
    32.9 +SHORT_DESC="Bigelow & Holmes bitmap font LucidaTypewriter (100 DPI)"
   32.10 +MAINTAINER="al.bobylev@gmail.com"
   32.11 +LICENSE="other"
   32.12 +WEB_SITE="https://www.x.org/wiki/"
   32.13 +HOST_ARCH="any"
   32.14 +REPOLOGY="fonts:bh-lucidatypewriter-100dpi"
   32.15 +
   32.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   32.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   32.18 +TARBALL_SHA1="bc4f804e49db8c6add04f52ffb1c0cd63e714b2c"
   32.19 +
   32.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   32.21 +COOKOPTS="!gz" # too long
   32.22 +
   32.23 +compile_rules() {
   32.24 +	./configure \
   32.25 +		--disable-all-encodings \
   32.26 +		$CONFIGURE_ARGS &&
   32.27 +	make &&
   32.28 +	make install
   32.29 +}
   32.30 +
   32.31 +post_install() {
   32.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
   32.33 +}
   32.34 +post_remove() {
   32.35 +	chroot "$1/" fc-cache -r
   32.36 +}
   32.37 +
   32.38 +TAGS="Xorg font"
   32.39 +
   32.40 +PROVIDE="xorg-font-bh-lucidatypewriter-100dpi"
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/font-bh-lucidatypewriter-75dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    33.3 @@ -0,0 +1,1 @@
    33.4 +../xorg/.icon.png
    33.5 \ No newline at end of file
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/font-bh-lucidatypewriter-75dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    34.3 @@ -0,0 +1,37 @@
    34.4 +# SliTaz package receipt v2.
    34.5 +
    34.6 +PACKAGE="font-bh-lucidatypewriter-75dpi"
    34.7 +VERSION="1.0.3"
    34.8 +CATEGORY="x-window"
    34.9 +SHORT_DESC="Bigelow & Holmes bitmap font LucidaTypewriter (75 DPI)"
   34.10 +MAINTAINER="al.bobylev@gmail.com"
   34.11 +LICENSE="other"
   34.12 +WEB_SITE="https://www.x.org/wiki/"
   34.13 +HOST_ARCH="any"
   34.14 +REPOLOGY="fonts:bh-lucidatypewriter-75dpi"
   34.15 +
   34.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   34.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   34.18 +TARBALL_SHA1="3c6678e6bbb2bd352baaf610a8f6aac9c5140c85"
   34.19 +
   34.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   34.21 +COOKOPTS="!gz" # too long
   34.22 +
   34.23 +compile_rules() {
   34.24 +	./configure \
   34.25 +		--disable-all-encodings \
   34.26 +		$CONFIGURE_ARGS &&
   34.27 +	make &&
   34.28 +	make install
   34.29 +}
   34.30 +
   34.31 +post_install() {
   34.32 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
   34.33 +}
   34.34 +post_remove() {
   34.35 +	chroot "$1/" fc-cache -r
   34.36 +}
   34.37 +
   34.38 +TAGS="Xorg font"
   34.39 +
   34.40 +PROVIDE="xorg-font-bh-lucidatypewriter-75dpi"
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/font-bh-ttf/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    35.3 @@ -0,0 +1,1 @@
    35.4 +../xorg/.icon.png
    35.5 \ No newline at end of file
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/font-bh-ttf/receipt	Thu Dec 20 17:55:43 2018 +0200
    36.3 @@ -0,0 +1,34 @@
    36.4 +# SliTaz package receipt v2.
    36.5 +
    36.6 +PACKAGE="font-bh-ttf"
    36.7 +VERSION="1.0.3"
    36.8 +CATEGORY="x-window"
    36.9 +SHORT_DESC="Bigelow & Holmes Luxi TTF fonts"
   36.10 +MAINTAINER="al.bobylev@gmail.com"
   36.11 +LICENSE="MIT"
   36.12 +WEB_SITE="https://www.x.org/wiki/"
   36.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   36.14 +HOST_ARCH="any"
   36.15 +
   36.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   36.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   36.18 +TARBALL_SHA1="f42ebd527096011040a312e0f9cdf78d64177419"
   36.19 +
   36.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir fontconfig-dev"
   36.21 +
   36.22 +compile_rules() {
   36.23 +	./configure $CONFIGURE_ARGS &&
   36.24 +	make &&
   36.25 +	make install
   36.26 +}
   36.27 +
   36.28 +post_install() {
   36.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/TTF
   36.30 +}
   36.31 +post_remove() {
   36.32 +	chroot "$1/" fc-cache -r
   36.33 +}
   36.34 +
   36.35 +TAGS="Xorg font"
   36.36 +
   36.37 +PROVIDE="xorg-font-bh-ttf"
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/font-bh-type1/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    37.3 @@ -0,0 +1,1 @@
    37.4 +../xorg/.icon.png
    37.5 \ No newline at end of file
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/font-bh-type1/receipt	Thu Dec 20 17:55:43 2018 +0200
    38.3 @@ -0,0 +1,35 @@
    38.4 +# SliTaz package receipt v2.
    38.5 +
    38.6 +PACKAGE="font-bh-type1"
    38.7 +VERSION="1.0.3"
    38.8 +CATEGORY="x-window"
    38.9 +SHORT_DESC="Bigelow & Holmes Luxi Type1 fonts"
   38.10 +MAINTAINER="al.bobylev@gmail.com"
   38.11 +LICENSE="MIT"
   38.12 +WEB_SITE="https://www.x.org/wiki/"
   38.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   38.14 +HOST_ARCH="any"
   38.15 +REPOLOGY="fonts:bh-type1"
   38.16 +
   38.17 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   38.18 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   38.19 +TARBALL_SHA1="69ff038d38015cd305a4cd4d1a921fe3bd08bbde"
   38.20 +
   38.21 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   38.22 +
   38.23 +compile_rules() {
   38.24 +	./configure $CONFIGURE_ARGS &&
   38.25 +	make &&
   38.26 +	make install
   38.27 +}
   38.28 +
   38.29 +post_install() {
   38.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
   38.31 +}
   38.32 +post_remove() {
   38.33 +	chroot "$1/" fc-cache -r
   38.34 +}
   38.35 +
   38.36 +TAGS="Xorg font"
   38.37 +
   38.38 +PROVIDE="xorg-font-bh-type1"
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/font-bitstream-100dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    39.3 @@ -0,0 +1,1 @@
    39.4 +../xorg/.icon.png
    39.5 \ No newline at end of file
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/font-bitstream-100dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    40.3 @@ -0,0 +1,35 @@
    40.4 +# SliTaz package receipt v2.
    40.5 +
    40.6 +PACKAGE="font-bitstream-100dpi"
    40.7 +VERSION="1.0.3"
    40.8 +CATEGORY="x-window"
    40.9 +SHORT_DESC="Bitstream bitmap fonts Charter, Terminal (100 DPI)"
   40.10 +MAINTAINER="al.bobylev@gmail.com"
   40.11 +LICENSE="MIT"
   40.12 +WEB_SITE="https://www.x.org/wiki/"
   40.13 +HOST_ARCH="any"
   40.14 +REPOLOGY="fonts:bitstream-100dpi"
   40.15 +
   40.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   40.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   40.18 +TARBALL_SHA1="138376f8683c09b9068c7c124842a7af9f0fcc2e"
   40.19 +
   40.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   40.21 +COOKOPTS="!gz" # too long
   40.22 +
   40.23 +compile_rules() {
   40.24 +	./configure $CONFIGURE_ARGS &&
   40.25 +	make &&
   40.26 +	make install
   40.27 +}
   40.28 +
   40.29 +post_install() {
   40.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
   40.31 +}
   40.32 +post_remove() {
   40.33 +	chroot "$1/" fc-cache -r
   40.34 +}
   40.35 +
   40.36 +TAGS="Xorg font"
   40.37 +
   40.38 +PROVIDE="xorg-font-bitstream-100dpi"
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/font-bitstream-75dpi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    41.3 @@ -0,0 +1,1 @@
    41.4 +../xorg/.icon.png
    41.5 \ No newline at end of file
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/font-bitstream-75dpi/receipt	Thu Dec 20 17:55:43 2018 +0200
    42.3 @@ -0,0 +1,35 @@
    42.4 +# SliTaz package receipt v2.
    42.5 +
    42.6 +PACKAGE="font-bitstream-75dpi"
    42.7 +VERSION="1.0.3"
    42.8 +CATEGORY="x-window"
    42.9 +SHORT_DESC="Bitstream bitmap fonts Charter, Terminal (75 DPI)"
   42.10 +MAINTAINER="al.bobylev@gmail.com"
   42.11 +LICENSE="MIT"
   42.12 +WEB_SITE="https://www.x.org/wiki/"
   42.13 +HOST_ARCH="any"
   42.14 +REPOLOGY="fonts:bitstream-75dpi"
   42.15 +
   42.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   42.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   42.18 +TARBALL_SHA1="975e9f7872483394ebd87610f8bbc924d99bea34"
   42.19 +
   42.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   42.21 +COOKOPTS="!gz" # too long
   42.22 +
   42.23 +compile_rules() {
   42.24 +	./configure $CONFIGURE_ARGS &&
   42.25 +	make &&
   42.26 +	make install
   42.27 +}
   42.28 +
   42.29 +post_install() {
   42.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
   42.31 +}
   42.32 +post_remove() {
   42.33 +	chroot "$1/" fc-cache -r
   42.34 +}
   42.35 +
   42.36 +TAGS="Xorg font"
   42.37 +
   42.38 +PROVIDE="xorg-font-bitstream-75dpi"
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/font-bitstream-type1/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    43.3 @@ -0,0 +1,1 @@
    43.4 +../xorg/.icon.png
    43.5 \ No newline at end of file
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/font-bitstream-type1/receipt	Thu Dec 20 17:55:43 2018 +0200
    44.3 @@ -0,0 +1,34 @@
    44.4 +# SliTaz package receipt v2.
    44.5 +
    44.6 +PACKAGE="font-bitstream-type1"
    44.7 +VERSION="1.0.3"
    44.8 +CATEGORY="x-window"
    44.9 +SHORT_DESC="Bitstream Type1 fonts Courier, Charter"
   44.10 +MAINTAINER="al.bobylev@gmail.com"
   44.11 +LICENSE="MIT"
   44.12 +WEB_SITE="https://www.x.org/wiki/"
   44.13 +HOST_ARCH="any"
   44.14 +REPOLOGY="fonts:bitstream-type1"
   44.15 +
   44.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   44.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   44.18 +TARBALL_SHA1="7633551be3525c501278e81259b22ad9a893de4d"
   44.19 +
   44.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   44.21 +
   44.22 +compile_rules() {
   44.23 +	./configure $CONFIGURE_ARGS &&
   44.24 +	make &&
   44.25 +	make install
   44.26 +}
   44.27 +
   44.28 +post_install() {
   44.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
   44.30 +}
   44.31 +post_remove() {
   44.32 +	chroot "$1/" fc-cache -r
   44.33 +}
   44.34 +
   44.35 +TAGS="Xorg font"
   44.36 +
   44.37 +PROVIDE="xorg-font-bitstream-type1"
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/font-cronyx-cyrillic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    45.3 @@ -0,0 +1,1 @@
    45.4 +../xorg/.icon.png
    45.5 \ No newline at end of file
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/font-cronyx-cyrillic/receipt	Thu Dec 20 17:55:43 2018 +0200
    46.3 @@ -0,0 +1,35 @@
    46.4 +# SliTaz package receipt v2.
    46.5 +
    46.6 +PACKAGE="font-cronyx-cyrillic"
    46.7 +VERSION="1.0.3"
    46.8 +CATEGORY="x-window"
    46.9 +SHORT_DESC="Cronyx bitmap fonts Courier, Helvetica, Times, Fixed"
   46.10 +MAINTAINER="al.bobylev@gmail.com"
   46.11 +LICENSE="other"
   46.12 +WEB_SITE="https://www.x.org/wiki/"
   46.13 +HOST_ARCH="any"
   46.14 +REPOLOGY="fonts:cronyx-cyrillic"
   46.15 +
   46.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   46.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   46.18 +TARBALL_SHA1="e5af8c2e8fb23955808a08bd38728ab3ad284d61"
   46.19 +
   46.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   46.21 +COOKOPTS="!gz" # too long
   46.22 +
   46.23 +compile_rules() {
   46.24 +	./configure $CONFIGURE_ARGS &&
   46.25 +	make &&
   46.26 +	make install
   46.27 +}
   46.28 +
   46.29 +post_install() {
   46.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
   46.31 +}
   46.32 +post_remove() {
   46.33 +	chroot "$1/" fc-cache -r
   46.34 +}
   46.35 +
   46.36 +TAGS="Xorg font"
   46.37 +
   46.38 +PROVIDE="xorg-font-cronyx-cyrillic"
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/font-cursor-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    47.3 @@ -0,0 +1,1 @@
    47.4 +../xorg/.icon.png
    47.5 \ No newline at end of file
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/font-cursor-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    48.3 @@ -0,0 +1,33 @@
    48.4 +# SliTaz package receipt v2.
    48.5 +
    48.6 +PACKAGE="font-cursor-misc"
    48.7 +VERSION="1.0.3"
    48.8 +CATEGORY="x-window"
    48.9 +SHORT_DESC="Misc bitmap set: cursor"
   48.10 +MAINTAINER="al.bobylev@gmail.com"
   48.11 +LICENSE="other"
   48.12 +WEB_SITE="https://www.x.org/wiki/"
   48.13 +HOST_ARCH="any"
   48.14 +
   48.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   48.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   48.17 +TARBALL_SHA1="1649271129bbeff3aeee70a9da87a8e5e59162c1"
   48.18 +
   48.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   48.20 +
   48.21 +compile_rules() {
   48.22 +	./configure $CONFIGURE_ARGS &&
   48.23 +	make &&
   48.24 +	make install
   48.25 +}
   48.26 +
   48.27 +post_install() {
   48.28 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   48.29 +}
   48.30 +post_remove() {
   48.31 +	chroot "$1/" fc-cache -r
   48.32 +}
   48.33 +
   48.34 +TAGS="Xorg font"
   48.35 +
   48.36 +PROVIDE="xorg-font-cursor-misc"
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/font-daewoo-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    49.3 @@ -0,0 +1,1 @@
    49.4 +../xorg/.icon.png
    49.5 \ No newline at end of file
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/font-daewoo-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    50.3 @@ -0,0 +1,35 @@
    50.4 +# SliTaz package receipt v2.
    50.5 +
    50.6 +PACKAGE="font-daewoo-misc"
    50.7 +VERSION="1.0.3"
    50.8 +CATEGORY="x-window"
    50.9 +SHORT_DESC="Daewoo bitmap fonts Gothic, Mincho"
   50.10 +MAINTAINER="al.bobylev@gmail.com"
   50.11 +LICENSE="other"
   50.12 +WEB_SITE="https://www.x.org/wiki/"
   50.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
   50.14 +HOST_ARCH="any"
   50.15 +
   50.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   50.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   50.18 +TARBALL_SHA1="0c7b24e08e6d42eb006d79ae7ab4bbf446d59f7a"
   50.19 +
   50.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   50.21 +COOKOPTS="!gz" # too long
   50.22 +
   50.23 +compile_rules() {
   50.24 +	./configure $CONFIGURE_ARGS &&
   50.25 +	make &&
   50.26 +	make install
   50.27 +}
   50.28 +
   50.29 +post_install() {
   50.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   50.31 +}
   50.32 +post_remove() {
   50.33 +	chroot "$1/" fc-cache -r
   50.34 +}
   50.35 +
   50.36 +TAGS="Xorg font"
   50.37 +
   50.38 +PROVIDE="xorg-font-daewoo-misc"
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/font-dec-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    51.3 @@ -0,0 +1,1 @@
    51.4 +../xorg/.icon.png
    51.5 \ No newline at end of file
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/font-dec-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    52.3 @@ -0,0 +1,34 @@
    52.4 +# SliTaz package receipt v2.
    52.5 +
    52.6 +PACKAGE="font-dec-misc"
    52.7 +VERSION="1.0.3"
    52.8 +CATEGORY="x-window"
    52.9 +SHORT_DESC="DEC misc bitmap sets: cursor, session"
   52.10 +MAINTAINER="al.bobylev@gmail.com"
   52.11 +LICENSE="MIT"
   52.12 +WEB_SITE="https://www.x.org/wiki/"
   52.13 +HOST_ARCH="any"
   52.14 +
   52.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   52.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   52.17 +TARBALL_SHA1="a748d35b8b0241abd3e1d85f80da318b529a74d0"
   52.18 +
   52.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   52.20 +COOKOPTS="!gz" # too long
   52.21 +
   52.22 +compile_rules() {
   52.23 +	./configure $CONFIGURE_ARGS &&
   52.24 +	make &&
   52.25 +	make install
   52.26 +}
   52.27 +
   52.28 +post_install() {
   52.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   52.30 +}
   52.31 +post_remove() {
   52.32 +	chroot "$1/" fc-cache -r
   52.33 +}
   52.34 +
   52.35 +TAGS="Xorg font"
   52.36 +
   52.37 +PROVIDE="xorg-font-dec-misc"
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/font-ibm-type1/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    53.3 @@ -0,0 +1,1 @@
    53.4 +../xorg/.icon.png
    53.5 \ No newline at end of file
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/font-ibm-type1/receipt	Thu Dec 20 17:55:43 2018 +0200
    54.3 @@ -0,0 +1,35 @@
    54.4 +# SliTaz package receipt v2.
    54.5 +
    54.6 +PACKAGE="font-ibm-type1"
    54.7 +VERSION="1.0.3"
    54.8 +CATEGORY="x-window"
    54.9 +SHORT_DESC="IBM Courier Type1 font"
   54.10 +MAINTAINER="al.bobylev@gmail.com"
   54.11 +LICENSE="MIT"
   54.12 +WEB_SITE="https://www.x.org/wiki/"
   54.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   54.14 +HOST_ARCH="any"
   54.15 +REPOLOGY="fonts:ibm-type1"
   54.16 +
   54.17 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   54.18 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   54.19 +TARBALL_SHA1="bfc7d0a3aa0f96bf61ea26d6b3f5afbbdd0f35f6"
   54.20 +
   54.21 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   54.22 +
   54.23 +compile_rules() {
   54.24 +	./configure $CONFIGURE_ARGS &&
   54.25 +	make &&
   54.26 +	make install
   54.27 +}
   54.28 +
   54.29 +post_install() {
   54.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
   54.31 +}
   54.32 +post_remove() {
   54.33 +	chroot "$1/" fc-cache -r
   54.34 +}
   54.35 +
   54.36 +TAGS="Xorg font"
   54.37 +
   54.38 +PROVIDE="xorg-font-ibm-type1"
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/font-isas-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    55.3 @@ -0,0 +1,1 @@
    55.4 +../xorg/.icon.png
    55.5 \ No newline at end of file
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/font-isas-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    56.3 @@ -0,0 +1,36 @@
    56.4 +# SliTaz package receipt v2.
    56.5 +
    56.6 +PACKAGE="font-isas-misc"
    56.7 +VERSION="1.0.3"
    56.8 +CATEGORY="x-window"
    56.9 +SHORT_DESC="ISAS bitmap fonts: Fangsong ti, Song ti"
   56.10 +MAINTAINER="al.bobylev@gmail.com"
   56.11 +LICENSE="MIT"
   56.12 +WEB_SITE="https://www.x.org/wiki/"
   56.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
   56.14 +HOST_ARCH="any"
   56.15 +REPOLOGY="fonts:isas-misc"
   56.16 +
   56.17 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   56.18 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   56.19 +TARBALL_SHA1="cbd9bf441b25362123c817b1aa7a7be1ee4a9321"
   56.20 +
   56.21 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   56.22 +COOKOPTS="!gz" # too long
   56.23 +
   56.24 +compile_rules() {
   56.25 +	./configure $CONFIGURE_ARGS &&
   56.26 +	make &&
   56.27 +	make install
   56.28 +}
   56.29 +
   56.30 +post_install() {
   56.31 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   56.32 +}
   56.33 +post_remove() {
   56.34 +	chroot "$1/" fc-cache -r
   56.35 +}
   56.36 +
   56.37 +TAGS="Xorg font"
   56.38 +
   56.39 +PROVIDE="xorg-font-isas-misc"
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/font-jis-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    57.3 @@ -0,0 +1,1 @@
    57.4 +../xorg/.icon.png
    57.5 \ No newline at end of file
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/font-jis-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    58.3 @@ -0,0 +1,35 @@
    58.4 +# SliTaz package receipt v2.
    58.5 +
    58.6 +PACKAGE="font-jis-misc"
    58.7 +VERSION="1.0.3"
    58.8 +CATEGORY="x-window"
    58.9 +SHORT_DESC="JIS bitmap font: Fixed"
   58.10 +MAINTAINER="al.bobylev@gmail.com"
   58.11 +LICENSE="other"
   58.12 +WEB_SITE="https://www.x.org/wiki/"
   58.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7legacy.html"
   58.14 +HOST_ARCH="any"
   58.15 +
   58.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   58.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   58.18 +TARBALL_SHA1="8c08c5fe01d4605f2886822cb3655548a6535e58"
   58.19 +
   58.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   58.21 +COOKOPTS="!gz" # too long
   58.22 +
   58.23 +compile_rules() {
   58.24 +	./configure $CONFIGURE_ARGS &&
   58.25 +	make &&
   58.26 +	make install
   58.27 +}
   58.28 +
   58.29 +post_install() {
   58.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   58.31 +}
   58.32 +post_remove() {
   58.33 +	chroot "$1/" fc-cache -r
   58.34 +}
   58.35 +
   58.36 +TAGS="Xorg font"
   58.37 +
   58.38 +PROVIDE="xorg-font-jis-misc"
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/font-micro-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    59.3 @@ -0,0 +1,1 @@
    59.4 +../xorg/.icon.png
    59.5 \ No newline at end of file
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/font-micro-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    60.3 @@ -0,0 +1,34 @@
    60.4 +# SliTaz package receipt v2.
    60.5 +
    60.6 +PACKAGE="font-micro-misc"
    60.7 +VERSION="1.0.3"
    60.8 +CATEGORY="x-window"
    60.9 +SHORT_DESC="Micro bitmap font"
   60.10 +MAINTAINER="al.bobylev@gmail.com"
   60.11 +LICENSE="PublicDomain"
   60.12 +WEB_SITE="https://www.x.org/wiki/"
   60.13 +HOST_ARCH="any"
   60.14 +REPOLOGY="fonts:micro-misc"
   60.15 +
   60.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   60.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   60.18 +TARBALL_SHA1="db3e912d41bda20f60b520c19e65bd7134ee1224"
   60.19 +
   60.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   60.21 +
   60.22 +compile_rules() {
   60.23 +	./configure $CONFIGURE_ARGS &&
   60.24 +	make &&
   60.25 +	make install
   60.26 +}
   60.27 +
   60.28 +post_install() {
   60.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   60.30 +}
   60.31 +post_remove() {
   60.32 +	chroot "$1/" fc-cache -r
   60.33 +}
   60.34 +
   60.35 +TAGS="Xorg font"
   60.36 +
   60.37 +PROVIDE="xorg-font-micro-misc"
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/font-misc-cyrillic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    61.3 @@ -0,0 +1,1 @@
    61.4 +../xorg/.icon.png
    61.5 \ No newline at end of file
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/font-misc-cyrillic/receipt	Thu Dec 20 17:55:43 2018 +0200
    62.3 @@ -0,0 +1,35 @@
    62.4 +# SliTaz package receipt v2.
    62.5 +
    62.6 +PACKAGE="font-misc-cyrillic"
    62.7 +VERSION="1.0.3"
    62.8 +CATEGORY="x-window"
    62.9 +SHORT_DESC="Misc Cyrillic bitmap font: Fixed"
   62.10 +MAINTAINER="al.bobylev@gmail.com"
   62.11 +LICENSE="other"
   62.12 +WEB_SITE="https://www.x.org/wiki/"
   62.13 +HOST_ARCH="any"
   62.14 +REPOLOGY="fonts:misc-cyrillic"
   62.15 +
   62.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   62.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   62.18 +TARBALL_SHA1="9c0e283ae59e7b05c0798fe0645cc822d22dcb0c"
   62.19 +
   62.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   62.21 +COOKOPTS="!gz" # too long
   62.22 +
   62.23 +compile_rules() {
   62.24 +	./configure $CONFIGURE_ARGS &&
   62.25 +	make &&
   62.26 +	make install
   62.27 +}
   62.28 +
   62.29 +post_install() {
   62.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
   62.31 +}
   62.32 +post_remove() {
   62.33 +	chroot "$1/" fc-cache -r
   62.34 +}
   62.35 +
   62.36 +TAGS="Xorg font"
   62.37 +
   62.38 +PROVIDE="xorg-font-misc-cyrillic"
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/font-misc-ethiopic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    63.3 @@ -0,0 +1,1 @@
    63.4 +../xorg/.icon.png
    63.5 \ No newline at end of file
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/font-misc-ethiopic/receipt	Thu Dec 20 17:55:43 2018 +0200
    64.3 @@ -0,0 +1,34 @@
    64.4 +# SliTaz package receipt v2.
    64.5 +
    64.6 +PACKAGE="font-misc-ethiopic"
    64.7 +VERSION="1.0.3"
    64.8 +CATEGORY="x-window"
    64.9 +SHORT_DESC="Ethiopic font Goha-Tibeb Zemen (OTF & TTF)"
   64.10 +MAINTAINER="al.bobylev@gmail.com"
   64.11 +LICENSE="MIT"
   64.12 +WEB_SITE="https://www.x.org/wiki/"
   64.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   64.14 +HOST_ARCH="any"
   64.15 +
   64.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   64.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   64.18 +TARBALL_SHA1="3f6af53047cb1206d737e8e8fbbbbb315c5419bb"
   64.19 +
   64.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   64.21 +
   64.22 +compile_rules() {
   64.23 +	./configure $CONFIGURE_ARGS &&
   64.24 +	make &&
   64.25 +	make install
   64.26 +}
   64.27 +
   64.28 +post_install() {
   64.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/OTF /usr/share/fonts/X11/TTF
   64.30 +}
   64.31 +post_remove() {
   64.32 +	chroot "$1/" fc-cache -r
   64.33 +}
   64.34 +
   64.35 +TAGS="Xorg font"
   64.36 +
   64.37 +PROVIDE="xorg-font-misc-ethiopic"
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/font-misc-meltho/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    65.3 @@ -0,0 +1,1 @@
    65.4 +../xorg/.icon.png
    65.5 \ No newline at end of file
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/font-misc-meltho/description.txt	Thu Dec 20 17:55:43 2018 +0200
    66.3 @@ -0,0 +1,23 @@
    66.4 +These fonts are designed for the display of Syriac text. They come from Beth
    66.5 +Mardutho: The Syriac Institute and are covered by a license which permits
    66.6 +redistribution but prohibits modification.
    66.7 +
    66.8 +The package contains the following font families:
    66.9 +
   66.10 +  * East Syriac Adiabene
   66.11 +  * East Syriac Ctesiphon
   66.12 +  * Estrangelo Antioch
   66.13 +  * Estrangelo Edessa
   66.14 +  * Estrangelo Midyat
   66.15 +  * Estrangelo Nisibin
   66.16 +  * Estrangelo Nisibin Outline
   66.17 +  * Estrangelo Quenneshrin
   66.18 +  * Estrangelo Talada
   66.19 +  * Estrangelo TurAbdin
   66.20 +  * Serto Batnan
   66.21 +  * Serto Jerusalem
   66.22 +  * Serto Jerusalem Outline
   66.23 +  * Serto Kharput
   66.24 +  * Serto Malankara
   66.25 +  * Serto Mardin
   66.26 +  * Serto Urhoy
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/font-misc-meltho/receipt	Thu Dec 20 17:55:43 2018 +0200
    67.3 @@ -0,0 +1,33 @@
    67.4 +# SliTaz package receipt v2.
    67.5 +
    67.6 +PACKAGE="font-misc-meltho"
    67.7 +VERSION="1.0.3"
    67.8 +CATEGORY="x-window"
    67.9 +SHORT_DESC="Syriac fonts (OTF)"
   67.10 +MAINTAINER="al.bobylev@gmail.com"
   67.11 +LICENSE="MIT"
   67.12 +WEB_SITE="https://www.x.org/wiki/"
   67.13 +HOST_ARCH="any"
   67.14 +
   67.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   67.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   67.17 +TARBALL_SHA1="f0693ea8fbc1d43177014155a0ecd2516348b51b"
   67.18 +
   67.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   67.20 +
   67.21 +compile_rules() {
   67.22 +	./configure $CONFIGURE_ARGS &&
   67.23 +	make &&
   67.24 +	make install
   67.25 +}
   67.26 +
   67.27 +post_install() {
   67.28 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/OTF
   67.29 +}
   67.30 +post_remove() {
   67.31 +	chroot "$1/" fc-cache -r
   67.32 +}
   67.33 +
   67.34 +TAGS="Xorg font"
   67.35 +
   67.36 +PROVIDE="xorg-font-misc-meltho"
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/font-misc-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    68.3 @@ -0,0 +1,1 @@
    68.4 +../xorg/.icon.png
    68.5 \ No newline at end of file
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/font-misc-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    69.3 @@ -0,0 +1,44 @@
    69.4 +# SliTaz package receipt v2.
    69.5 +
    69.6 +PACKAGE="font-misc-misc"
    69.7 +VERSION="1.1.2"
    69.8 +CATEGORY="x-window"
    69.9 +SHORT_DESC="Misc bitmap fixed fonts"
   69.10 +MAINTAINER="al.bobylev@gmail.com"
   69.11 +LICENSE="PublicDomain"
   69.12 +WEB_SITE="https://www.x.org/wiki/"
   69.13 +HOST_ARCH="any"
   69.14 +
   69.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   69.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   69.17 +TARBALL_SHA1="c6d28c56880807963175cbbd682fb6f75a35f77d"
   69.18 +
   69.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   69.20 +SPLIT="$PACKAGE-base $PACKAGE"
   69.21 +
   69.22 +COOKOPTS="!gz" # too long
   69.23 +
   69.24 +COPY_base="6x13.pcf.gz"
   69.25 +CAT_base="x-window|minimal set"
   69.26 +DEPENDS_base=" "
   69.27 +DEPENDS_std="$PACKAGE-base"
   69.28 +
   69.29 +compile_rules() {
   69.30 +	./configure \
   69.31 +		--disable-all-encodings \
   69.32 +		$CONFIGURE_ARGS &&
   69.33 +	make &&
   69.34 +	make install
   69.35 +}
   69.36 +
   69.37 +post_install() {
   69.38 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   69.39 +}
   69.40 +post_remove() {
   69.41 +	chroot "$1/" fc-cache -r
   69.42 +}
   69.43 +
   69.44 +TAGS="Xorg font"
   69.45 +
   69.46 +PROVIDE="xorg-font-misc-misc"
   69.47 +PROVIDE_base="xorg-base-fonts"
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/font-mutt-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    70.3 @@ -0,0 +1,1 @@
    70.4 +../xorg/.icon.png
    70.5 \ No newline at end of file
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/font-mutt-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    71.3 @@ -0,0 +1,35 @@
    71.4 +# SliTaz package receipt v2.
    71.5 +
    71.6 +PACKAGE="font-mutt-misc"
    71.7 +VERSION="1.0.3"
    71.8 +CATEGORY="x-window"
    71.9 +SHORT_DESC="Bitmap Arabic, Devanagari, Armenian font ClearlyU"
   71.10 +MAINTAINER="al.bobylev@gmail.com"
   71.11 +LICENSE="MIT"
   71.12 +WEB_SITE="https://www.x.org/wiki/"
   71.13 +HOST_ARCH="any"
   71.14 +REPOLOGY="fonts:mutt-misc"
   71.15 +
   71.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   71.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   71.18 +TARBALL_SHA1="245d3041d9138b7e4a00858228adad2de304043b"
   71.19 +
   71.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   71.21 +COOKOPTS="!gz" # too long
   71.22 +
   71.23 +compile_rules() {
   71.24 +	./configure $CONFIGURE_ARGS &&
   71.25 +	make &&
   71.26 +	make install
   71.27 +}
   71.28 +
   71.29 +post_install() {
   71.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   71.31 +}
   71.32 +post_remove() {
   71.33 +	chroot "$1/" fc-cache -r
   71.34 +}
   71.35 +
   71.36 +TAGS="Xorg font"
   71.37 +
   71.38 +PROVIDE="xorg-font-mutt-misc"
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/font-schumacher-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    72.3 @@ -0,0 +1,1 @@
    72.4 +../xorg/.icon.png
    72.5 \ No newline at end of file
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/font-schumacher-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    73.3 @@ -0,0 +1,36 @@
    73.4 +# SliTaz package receipt v2.
    73.5 +
    73.6 +PACKAGE="font-schumacher-misc"
    73.7 +VERSION="1.1.2"
    73.8 +CATEGORY="x-window"
    73.9 +SHORT_DESC="Schumacher bitmap font Clean"
   73.10 +MAINTAINER="al.bobylev@gmail.com"
   73.11 +LICENSE="MIT"
   73.12 +WEB_SITE="https://www.x.org/wiki/"
   73.13 +HOST_ARCH="any"
   73.14 +
   73.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   73.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   73.17 +TARBALL_SHA1="fbe3629e9dcc03d12300d4ebab64fd038ea98952"
   73.18 +
   73.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   73.20 +COOKOPTS="!gz" # too long
   73.21 +
   73.22 +compile_rules() {
   73.23 +	./configure \
   73.24 +		--disable-all-encodings \
   73.25 +		$CONFIGURE_ARGS &&
   73.26 +	make &&
   73.27 +	make install
   73.28 +}
   73.29 +
   73.30 +post_install() {
   73.31 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   73.32 +}
   73.33 +post_remove() {
   73.34 +	chroot "$1/" fc-cache -r
   73.35 +}
   73.36 +
   73.37 +TAGS="Xorg font"
   73.38 +
   73.39 +PROVIDE="xorg-font-schumacher-misc"
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/font-screen-cyrillic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    74.3 @@ -0,0 +1,1 @@
    74.4 +../xorg/.icon.png
    74.5 \ No newline at end of file
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/font-screen-cyrillic/receipt	Thu Dec 20 17:55:43 2018 +0200
    75.3 @@ -0,0 +1,35 @@
    75.4 +# SliTaz package receipt v2.
    75.5 +
    75.6 +PACKAGE="font-screen-cyrillic"
    75.7 +VERSION="1.0.4"
    75.8 +CATEGORY="x-window"
    75.9 +SHORT_DESC="Misc Screen Cyrillic bitmap font: Fixed"
   75.10 +MAINTAINER="al.bobylev@gmail.com"
   75.11 +LICENSE="other"
   75.12 +WEB_SITE="https://www.x.org/wiki/"
   75.13 +HOST_ARCH="any"
   75.14 +REPOLOGY="fonts:screen-cyrillic"
   75.15 +
   75.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   75.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   75.18 +TARBALL_SHA1="de1f0226f74d7e4d3ee9ab0b9c87478ab2a7db30"
   75.19 +
   75.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   75.21 +COOKOPTS="!gz" # too long
   75.22 +
   75.23 +compile_rules() {
   75.24 +	./configure $CONFIGURE_ARGS &&
   75.25 +	make &&
   75.26 +	make install
   75.27 +}
   75.28 +
   75.29 +post_install() {
   75.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
   75.31 +}
   75.32 +post_remove() {
   75.33 +	chroot "$1/" fc-cache -r
   75.34 +}
   75.35 +
   75.36 +TAGS="Xorg font"
   75.37 +
   75.38 +PROVIDE="xorg-font-screen-cyrillic"
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/font-sony-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    76.3 @@ -0,0 +1,1 @@
    76.4 +../xorg/.icon.png
    76.5 \ No newline at end of file
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/font-sony-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    77.3 @@ -0,0 +1,34 @@
    77.4 +# SliTaz package receipt v2.
    77.5 +
    77.6 +PACKAGE="font-sony-misc"
    77.7 +VERSION="1.0.3"
    77.8 +CATEGORY="x-window"
    77.9 +SHORT_DESC="Bitmap Sony fixed fonts"
   77.10 +MAINTAINER="al.bobylev@gmail.com"
   77.11 +LICENSE="MIT"
   77.12 +WEB_SITE="https://www.x.org/wiki/"
   77.13 +HOST_ARCH="any"
   77.14 +
   77.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   77.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   77.17 +TARBALL_SHA1="8d0dd87148283c8ac8c5ac37906b12fab5ddb1d8"
   77.18 +
   77.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   77.20 +COOKOPTS="!gz" # too long
   77.21 +
   77.22 +compile_rules() {
   77.23 +	./configure $CONFIGURE_ARGS &&
   77.24 +	make &&
   77.25 +	make install
   77.26 +}
   77.27 +
   77.28 +post_install() {
   77.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   77.30 +}
   77.31 +post_remove() {
   77.32 +	chroot "$1/" fc-cache -r
   77.33 +}
   77.34 +
   77.35 +TAGS="Xorg font"
   77.36 +
   77.37 +PROVIDE="xorg-font-sony-misc"
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/font-sun-misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    78.3 @@ -0,0 +1,1 @@
    78.4 +../xorg/.icon.png
    78.5 \ No newline at end of file
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/font-sun-misc/receipt	Thu Dec 20 17:55:43 2018 +0200
    79.3 @@ -0,0 +1,34 @@
    79.4 +# SliTaz package receipt v2.
    79.5 +
    79.6 +PACKAGE="font-sun-misc"
    79.7 +VERSION="1.0.3"
    79.8 +CATEGORY="x-window"
    79.9 +SHORT_DESC="Sun bitmap sets: OPEN LOOK cursor, OPEN LOOK glyph"
   79.10 +MAINTAINER="al.bobylev@gmail.com"
   79.11 +LICENSE="MIT"
   79.12 +WEB_SITE="https://www.x.org/wiki/"
   79.13 +HOST_ARCH="any"
   79.14 +
   79.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   79.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   79.17 +TARBALL_SHA1="6a72602557bb5dfe46c1ee3b56658aeed1e04f9d"
   79.18 +
   79.19 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   79.20 +COOKOPTS="!gz" # too long
   79.21 +
   79.22 +compile_rules() {
   79.23 +	./configure $CONFIGURE_ARGS &&
   79.24 +	make &&
   79.25 +	make install
   79.26 +}
   79.27 +
   79.28 +post_install() {
   79.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
   79.30 +}
   79.31 +post_remove() {
   79.32 +	chroot "$1/" fc-cache -r
   79.33 +}
   79.34 +
   79.35 +TAGS="Xorg font"
   79.36 +
   79.37 +PROVIDE="xorg-font-sun-misc"
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/font-util/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    80.3 @@ -0,0 +1,1 @@
    80.4 +../xorg/.icon.png
    80.5 \ No newline at end of file
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/font-util/receipt	Thu Dec 20 17:55:43 2018 +0200
    81.3 @@ -0,0 +1,27 @@
    81.4 +# SliTaz package receipt v2.
    81.5 +
    81.6 +PACKAGE="font-util"
    81.7 +VERSION="1.3.1"
    81.8 +CATEGORY="x-window"
    81.9 +SHORT_DESC="Font utilities dirs"
   81.10 +MAINTAINER="al.bobylev@gmail.com"
   81.11 +LICENSE="MIT"
   81.12 +WEB_SITE="https://www.x.org/wiki/"
   81.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   81.14 +
   81.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   81.16 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   81.17 +TARBALL_SHA1="0b16add3637c64b0bbaf1dd223b71b0421100c20"
   81.18 +
   81.19 +SPLIT="$PACKAGE-dev"
   81.20 +
   81.21 +compile_rules() {
   81.22 +	./configure $CONFIGURE_ARGS &&
   81.23 +	make &&
   81.24 +	make install
   81.25 +}
   81.26 +
   81.27 +TAGS="Xorg"
   81.28 +
   81.29 +PROVIDE_std="xorg-font-util"
   81.30 +PROVIDE_dev="xorg-font-util-dev"
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/font-winitzki-cyrillic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    82.3 @@ -0,0 +1,1 @@
    82.4 +../xorg/.icon.png
    82.5 \ No newline at end of file
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/font-winitzki-cyrillic/receipt	Thu Dec 20 17:55:43 2018 +0200
    83.3 @@ -0,0 +1,34 @@
    83.4 +# SliTaz package receipt v2.
    83.5 +
    83.6 +PACKAGE="font-winitzki-cyrillic"
    83.7 +VERSION="1.0.3"
    83.8 +CATEGORY="x-window"
    83.9 +SHORT_DESC="Winitzki Cyrillic bitmap font: Proof"
   83.10 +MAINTAINER="al.bobylev@gmail.com"
   83.11 +LICENSE="PublicDomain"
   83.12 +WEB_SITE="https://www.x.org/wiki/"
   83.13 +HOST_ARCH="any"
   83.14 +REPOLOGY="fonts:winitzki-cyrillic"
   83.15 +
   83.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   83.17 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   83.18 +TARBALL_SHA1="29249b49eac7e3f32d7a1a93808fcfd9d399011c"
   83.19 +
   83.20 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir bdftopcf"
   83.21 +
   83.22 +compile_rules() {
   83.23 +	./configure $CONFIGURE_ARGS &&
   83.24 +	make &&
   83.25 +	make install
   83.26 +}
   83.27 +
   83.28 +post_install() {
   83.29 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
   83.30 +}
   83.31 +post_remove() {
   83.32 +	chroot "$1/" fc-cache -r
   83.33 +}
   83.34 +
   83.35 +TAGS="Xorg font"
   83.36 +
   83.37 +PROVIDE="xorg-font-winitzki-cyrillic"
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/font-xfree86-type1/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    84.3 @@ -0,0 +1,1 @@
    84.4 +../xorg/.icon.png
    84.5 \ No newline at end of file
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/font-xfree86-type1/receipt	Thu Dec 20 17:55:43 2018 +0200
    85.3 @@ -0,0 +1,35 @@
    85.4 +# SliTaz package receipt v2.
    85.5 +
    85.6 +PACKAGE="font-xfree86-type1"
    85.7 +VERSION="1.0.4"
    85.8 +CATEGORY="x-window"
    85.9 +SHORT_DESC="Xfree86 Type1 Cursor font"
   85.10 +MAINTAINER="al.bobylev@gmail.com"
   85.11 +LICENSE="MIT"
   85.12 +WEB_SITE="https://www.x.org/wiki/"
   85.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
   85.14 +HOST_ARCH="any"
   85.15 +REPOLOGY="fonts:xfree86-type1"
   85.16 +
   85.17 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   85.18 +WGET_URL="$XORG_MIRROR/font/$TARBALL"
   85.19 +TARBALL_SHA1="1381f274a178cbd08627560e17a4a8f6653be3f7"
   85.20 +
   85.21 +BUILD_DEPENDS="util-macros font-util-dev mkfontdir"
   85.22 +
   85.23 +compile_rules() {
   85.24 +	./configure $CONFIGURE_ARGS &&
   85.25 +	make &&
   85.26 +	make install
   85.27 +}
   85.28 +
   85.29 +post_install() {
   85.30 +	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
   85.31 +}
   85.32 +post_remove() {
   85.33 +	chroot "$1/" fc-cache -r
   85.34 +}
   85.35 +
   85.36 +TAGS="Xorg font"
   85.37 +
   85.38 +PROVIDE="xorg-font-xfree86-type1"
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/fonts-crosextra-caladea/receipt	Thu Dec 20 17:55:43 2018 +0200
    86.3 @@ -0,0 +1,21 @@
    86.4 +# SliTaz package receipt v2.
    86.5 +
    86.6 +PACKAGE="fonts-crosextra-caladea"
    86.7 +VERSION="20130214"
    86.8 +CATEGORY="fonts"
    86.9 +LICENSE="Apache"
   86.10 +SHORT_DESC="Serif font metric-compatible with Cambria font"
   86.11 +MAINTAINER="al.bobylev@gmail.com"
   86.12 +WEB_SITE="https://fontlibrary.org/en/font/caladea"
   86.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/TTF-and-OTF-fonts.html#Caladea"
   86.14 +HOST_ARCH="any"
   86.15 +REPOLOGY="fonts:crosextra-caladea"
   86.16 +
   86.17 +TARBALL="crosextrafonts-$VERSION.tar.gz"
   86.18 +WGET_URL="http://gsdview.appspot.com/chromeos-localmirror/distfiles/$TARBALL"
   86.19 +TARBALL_SHA1="6f8f87cd21c4cd7e72031852eb90453dba3e2473"
   86.20 +
   86.21 +compile_rules() {
   86.22 +	mkdir -p $install/usr/share/fonts/TTF/
   86.23 +	install -m644 *.ttf $install/usr/share/fonts/TTF/
   86.24 +}
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/fonttosfnt/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    87.3 @@ -0,0 +1,1 @@
    87.4 +../xorg/.icon.png
    87.5 \ No newline at end of file
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/fonttosfnt/receipt	Thu Dec 20 17:55:43 2018 +0200
    88.3 @@ -0,0 +1,26 @@
    88.4 +# SliTaz package receipt v2.
    88.5 +
    88.6 +PACKAGE="fonttosfnt"
    88.7 +VERSION="1.0.5"
    88.8 +CATEGORY="x-window"
    88.9 +SHORT_DESC="Wrap a bitmap font in a sfnt (TrueType) wrapper"
   88.10 +MAINTAINER="pascal.bellard@slitaz.org"
   88.11 +LICENSE="MIT"
   88.12 +WEB_SITE="https://www.x.org/wiki/"
   88.13 +
   88.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   88.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
   88.16 +TARBALL_SHA1="acc1c8e47ba0fdc872442bf4fb087074b40ae618"
   88.17 +
   88.18 +BUILD_DEPENDS="xorgproto freetype-dev libfontenc-dev"
   88.19 +DEPENDS="freetype libfontenc"
   88.20 +
   88.21 +compile_rules() {
   88.22 +	./configure $CONFIGURE_ARGS &&
   88.23 +	make &&
   88.24 +	make install
   88.25 +}
   88.26 +
   88.27 +TAGS="Xorg"
   88.28 +
   88.29 +PROVIDE="xorg-fonttosfnt"
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/fslsfonts/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    89.3 @@ -0,0 +1,1 @@
    89.4 +../xorg/.icon.png
    89.5 \ No newline at end of file
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/fslsfonts/receipt	Thu Dec 20 17:55:43 2018 +0200
    90.3 @@ -0,0 +1,26 @@
    90.4 +# SliTaz package receipt v2.
    90.5 +
    90.6 +PACKAGE="fslsfonts"
    90.7 +VERSION="1.0.5"
    90.8 +CATEGORY="x-window"
    90.9 +SHORT_DESC="List fonts served by X font server"
   90.10 +MAINTAINER="al.bobylev@gmail.com"
   90.11 +LICENSE="MIT"
   90.12 +WEB_SITE="https://www.x.org/wiki/"
   90.13 +
   90.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   90.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
   90.16 +TARBALL_SHA1="0a0d37c65a8cdd3aff22d633b5ed164e864929d4"
   90.17 +
   90.18 +BUILD_DEPENDS="util-macros xorgproto libfs-dev"
   90.19 +DEPENDS="libfs"
   90.20 +
   90.21 +compile_rules() {
   90.22 +	./configure $CONFIGURE_ARGS &&
   90.23 +	make &&
   90.24 +	make install
   90.25 +}
   90.26 +
   90.27 +TAGS="Xorg"
   90.28 +
   90.29 +PROVIDE="xorg-fslsfonts"
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/fstobdf/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    91.3 @@ -0,0 +1,1 @@
    91.4 +../xorg/.icon.png
    91.5 \ No newline at end of file
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/fstobdf/receipt	Thu Dec 20 17:55:43 2018 +0200
    92.3 @@ -0,0 +1,26 @@
    92.4 +# SliTaz package receipt v2.
    92.5 +
    92.6 +PACKAGE="fstobdf"
    92.7 +VERSION="1.0.6"
    92.8 +CATEGORY="x-window"
    92.9 +SHORT_DESC="Generate BDF font from X font server"
   92.10 +MAINTAINER="al.bobylev@gmail.com"
   92.11 +LICENSE="MIT"
   92.12 +WEB_SITE="https://www.x.org/wiki/"
   92.13 +
   92.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   92.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
   92.16 +TARBALL_SHA1="aeafc2cd82092168d0bc4b94c5a27d7e070598fd"
   92.17 +
   92.18 +BUILD_DEPENDS="util-macros xorgproto libx11-dev libfs-dev"
   92.19 +DEPENDS="libfs libx11"
   92.20 +
   92.21 +compile_rules() {
   92.22 +	./configure $CONFIGURE_ARGS &&
   92.23 +	make &&
   92.24 +	make install
   92.25 +}
   92.26 +
   92.27 +TAGS="Xorg"
   92.28 +
   92.29 +PROVIDE="xorg-fstobdf"
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/gccmakedep/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    93.3 @@ -0,0 +1,1 @@
    93.4 +../xorg/.icon.png
    93.5 \ No newline at end of file
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/gccmakedep/receipt	Thu Dec 20 17:55:43 2018 +0200
    94.3 @@ -0,0 +1,26 @@
    94.4 +# SliTaz package receipt v2.
    94.5 +
    94.6 +PACKAGE="gccmakedep"
    94.7 +VERSION="1.0.3"
    94.8 +CATEGORY="x-window"
    94.9 +SHORT_DESC="X gccmakedep utility"
   94.10 +MAINTAINER="pascal.bellard@slitaz.org"
   94.11 +LICENSE="MIT"
   94.12 +WEB_SITE="https://www.x.org/wiki/"
   94.13 +HOST_ARCH="any"
   94.14 +
   94.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   94.16 +WGET_URL="$XORG_MIRROR/util/$TARBALL"
   94.17 +TARBALL_SHA1="03018e2fb9d7df4fec1623cedb1c090bc224f971"
   94.18 +
   94.19 +BUILD_DEPENDS="util-macros"
   94.20 +
   94.21 +compile_rules() {
   94.22 +	./configure $CONFIGURE_ARGS &&
   94.23 +	make &&
   94.24 +	make install
   94.25 +}
   94.26 +
   94.27 +TAGS="Xorg"
   94.28 +
   94.29 +PROVIDE="xorg-gccmakedep"
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/iceauth/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    95.3 @@ -0,0 +1,1 @@
    95.4 +../xorg/.icon.png
    95.5 \ No newline at end of file
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/iceauth/receipt	Thu Dec 20 17:55:43 2018 +0200
    96.3 @@ -0,0 +1,27 @@
    96.4 +# SliTaz package receipt v2.
    96.5 +
    96.6 +PACKAGE="iceauth"
    96.7 +VERSION="1.0.8"
    96.8 +CATEGORY="x-window"
    96.9 +SHORT_DESC="ICE authority file utility"
   96.10 +MAINTAINER="devel@slitaz.org"
   96.11 +LICENSE="MIT"
   96.12 +WEB_SITE="https://www.x.org/wiki/"
   96.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
   96.14 +
   96.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   96.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
   96.17 +TARBALL_SHA1="2ce23c40a17d98badeb8ce70d26e81a5ac0e178c"
   96.18 +
   96.19 +BUILD_DEPENDS="libice-dev"
   96.20 +DEPENDS="libice"
   96.21 +
   96.22 +compile_rules() {
   96.23 +	./configure $CONFIGURE_ARGS &&
   96.24 +	make &&
   96.25 +	make install
   96.26 +}
   96.27 +
   96.28 +TAGS="Xorg"
   96.29 +
   96.30 +PROVIDE="xorg-iceauth"
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/imake/.icon.png	Thu Dec 20 17:55:43 2018 +0200
    97.3 @@ -0,0 +1,1 @@
    97.4 +../xorg/.icon.png
    97.5 \ No newline at end of file
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/imake/receipt	Thu Dec 20 17:55:43 2018 +0200
    98.3 @@ -0,0 +1,26 @@
    98.4 +# SliTaz package receipt v2.
    98.5 +
    98.6 +PACKAGE="imake"
    98.7 +VERSION="1.0.7"
    98.8 +CATEGORY="x-window"
    98.9 +SHORT_DESC="X imake utility"
   98.10 +MAINTAINER="pascal.bellard@slitaz.org"
   98.11 +LICENSE="MIT"
   98.12 +WEB_SITE="https://www.x.org/wiki/"
   98.13 +
   98.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
   98.15 +WGET_URL="$XORG_MIRROR/util/$TARBALL"
   98.16 +TARBALL_SHA1="52e236776133f217d438622034b8603d201a6ec5"
   98.17 +
   98.18 +BUILD_DEPENDS="util-macros perl xorgproto"
   98.19 +DEPENDS="xorg-cf-files"
   98.20 +
   98.21 +compile_rules() {
   98.22 +	./configure $CONFIGURE_ARGS &&
   98.23 +	make &&
   98.24 +	make install
   98.25 +}
   98.26 +
   98.27 +TAGS="Xorg"
   98.28 +
   98.29 +PROVIDE="xorg-imake"
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/intel-hybrid-driver/receipt	Thu Dec 20 17:55:43 2018 +0200
    99.3 @@ -0,0 +1,25 @@
    99.4 +# SliTaz package receipt v2.
    99.5 +
    99.6 +PACKAGE="intel-hybrid-driver"
    99.7 +VERSION="1.0.2"
    99.8 +CATEGORY="x-window"
    99.9 +SHORT_DESC="VA driver for Intel G45 & HD Graphics family"
   99.10 +MAINTAINER="al.bobylev@gmail.com"
   99.11 +LICENSE="MIT"
   99.12 +WEB_SITE="https://github.com/01org/intel-hybrid-driver"
   99.13 +
   99.14 +TARBALL="$PACKAGE-$VERSION.tar.gz"
   99.15 +WGET_URL="https://github.com/01org/intel-hybrid-driver/archive/$VERSION.tar.gz"
   99.16 +TARBALL_SHA1="0a191a6eec16ca513e8882699657c91ca4ee87c8"
   99.17 +
   99.18 +BUILD_DEPENDS="automake libtool libdrm-dev cmrt-dev libva-dev libx11-dev \
   99.19 +mesa-dev"
   99.20 +DEPENDS="cmrt libdrm libdrm-intel"
   99.21 +
   99.22 +compile_rules() {
   99.23 +	./autogen.sh \
   99.24 +		$CONFIGURE_ARGS &&
   99.25 +	fix libtool &&
   99.26 +	make &&
   99.27 +	make install
   99.28 +}
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/intel-vaapi-driver/receipt	Thu Dec 20 17:55:43 2018 +0200
   100.3 @@ -0,0 +1,26 @@
   100.4 +# SliTaz package receipt v2.
   100.5 +
   100.6 +PACKAGE="intel-vaapi-driver"
   100.7 +VERSION="2.3.0"
   100.8 +CATEGORY="x-window"
   100.9 +SHORT_DESC="VA-API user mode driver for Intel GEN Graphics family"
  100.10 +MAINTAINER="al.bobylev@gmail.com"
  100.11 +LICENSE="MIT"
  100.12 +WEB_SITE="https://github.com/intel/intel-vaapi-driver"
  100.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#libva"
  100.14 +
  100.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  100.16 +WGET_URL="https://github.com/intel/intel-vaapi-driver/releases/download/$VERSION/$TARBALL"
  100.17 +TARBALL_SHA1="89096f99da753ac5858304e6c17f5dd9e7581d5b"
  100.18 +
  100.19 +BUILD_DEPENDS="libdrm-dev libva-dev libx11-dev"
  100.20 +DEPENDS="libdrm libdrm-intel"
  100.21 +
  100.22 +compile_rules() {
  100.23 +	./configure $CONFIGURE_ARGS &&
  100.24 +	fix libtool &&
  100.25 +	make &&
  100.26 +	make install
  100.27 +}
  100.28 +
  100.29 +PROVIDE="libva-intel-driver"
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/libdmx/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   101.3 @@ -0,0 +1,1 @@
   101.4 +../xorg/.icon.png
   101.5 \ No newline at end of file
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/libdmx/receipt	Thu Dec 20 17:55:43 2018 +0200
   102.3 @@ -0,0 +1,34 @@
   102.4 +# SliTaz package receipt v2.
   102.5 +
   102.6 +PACKAGE="libdmx"
   102.7 +VERSION="1.1.4"
   102.8 +CATEGORY="x-window"
   102.9 +SHORT_DESC="Xorg DMX library"
  102.10 +MAINTAINER="devel@slitaz.org"
  102.11 +LICENSE="MIT"
  102.12 +WEB_SITE="https://www.x.org/wiki/"
  102.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  102.14 +
  102.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  102.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  102.17 +TARBALL_SHA1="499e2540ca0e94ca858037865243c3c60908fd94"
  102.18 +
  102.19 +BUILD_DEPENDS="libx11-dev libxext-dev xorgproto"
  102.20 +SPLIT="$PACKAGE-dev"
  102.21 +
  102.22 +DEPENDS_std="libx11 libxext"
  102.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev libxext-dev"
  102.24 +
  102.25 +compile_rules() {
  102.26 +	./configure \
  102.27 +		--disable-static \
  102.28 +		$CONFIGURE_ARGS &&
  102.29 +	fix libtool &&
  102.30 +	make &&
  102.31 +	make install
  102.32 +}
  102.33 +
  102.34 +TAGS="Xorg"
  102.35 +
  102.36 +PROVIDE_std="xorg-libdmx"
  102.37 +PROVIDE_dev="xorg-libdmx-dev"
   103.1 --- a/libdrm/receipt	Thu Dec 13 00:46:54 2018 +0200
   103.2 +++ b/libdrm/receipt	Thu Dec 20 17:55:43 2018 +0200
   103.3 @@ -1,7 +1,7 @@
   103.4  # SliTaz package receipt v2.
   103.5  
   103.6  PACKAGE="libdrm"
   103.7 -VERSION="2.4.92"
   103.8 +VERSION="2.4.96"
   103.9  CATEGORY="x-window"
  103.10  SHORT_DESC="Freedesktop DRM Library"
  103.11  MAINTAINER="al.bobylev@gmail.com"
  103.12 @@ -11,78 +11,54 @@
  103.13  
  103.14  TARBALL="$PACKAGE-$VERSION.tar.bz2"
  103.15  WGET_URL="https://dri.freedesktop.org/libdrm/$TARBALL"
  103.16 +TARBALL_SHA1="51eb4c248a437b3f200bd1cd84461d3e0b60d71e"
  103.17  
  103.18 -BUILD_DEPENDS="autoconf automake libtool xorg-util-macros libxslt \
  103.19 -xorg-libpciaccess-dev cairo-dev eudev-dev libxslt docbook-xsl valgrind-dev"
  103.20 -SPLIT="$PACKAGE-amdgpu $PACKAGE-etnaviv $PACKAGE-exynos $PACKAGE-intel \
  103.21 -$PACKAGE-nouveau $PACKAGE-omap $PACKAGE-radeon $PACKAGE-tegra $PACKAGE-dev"
  103.22 +BUILD_DEPENDS="meson ninja util-macros libxslt libpciaccess-dev eudev-dev \
  103.23 +libxslt docbook-xsl valgrind-dev"
  103.24 +SPLIT="\
  103.25 +$PACKAGE-amdgpu  $PACKAGE-etnaviv $PACKAGE-exynos $PACKAGE-intel \
  103.26 +$PACKAGE-nouveau $PACKAGE-omap    $PACKAGE-radeon $PACKAGE-tegra $PACKAGE-dev"
  103.27 +
  103.28 +COPY_std="libdrm.so* libkms.so*"
  103.29 +COPY_amdgpu=" libdrm_amdgpu.so* amdgpu.ids"
  103.30 +COPY_etnaviv="libdrm_etnaviv.so*"
  103.31 +COPY_exynos=" libdrm_exynos.so*"
  103.32 +COPY_intel="  libdrm_intel.so*"
  103.33 +COPY_nouveau="libdrm_nouveau.so*"
  103.34 +COPY_omap="   libdrm_omap.so*"
  103.35 +COPY_radeon=" libdrm_radeon.so*"
  103.36 +COPY_tegra="  libdrm_tegra.so*"
  103.37 +
  103.38 +DEPENDS_std="eudev linux-drm libpciaccess" # all deps are implicit
  103.39 +DEPENDS_amdgpu="libdrm"
  103.40 +DEPENDS_etnaviv="libdrm"
  103.41 +DEPENDS_exynos="libdrm"
  103.42 +DEPENDS_intel="libdrm libpciaccess"
  103.43 +DEPENDS_nouveau="libdrm"
  103.44 +DEPENDS_omap="libdrm"
  103.45 +DEPENDS_radeon="libdrm"
  103.46 +DEPENDS_tegra="libdrm"
  103.47 +
  103.48 +CAT_amdgpu="x-window|AMDGPU API"
  103.49 +CAT_etnaviv="x-window|Etnaviv API"
  103.50 +CAT_exynos="x-window|EXYNOS API"
  103.51 +CAT_intel="x-window|Intel API"
  103.52 +CAT_nouveau="x-window|Nouveau API"
  103.53 +CAT_omap="x-window|OMAP API"
  103.54 +CAT_radeon="x-window|Radeon API"
  103.55 +CAT_tegra="x-window|Tegra API"
  103.56  
  103.57  compile_rules() {
  103.58 -	autoreconf -fiv &&
  103.59 -
  103.60 +	mkdir build
  103.61 +	cd    build
  103.62  	# Freedreno API and VC4 API enabled on the ARM
  103.63 -	GREP=grep \
  103.64 -	./configure \
  103.65 -		--enable-udev \
  103.66 -		--enable-vmwgfx \
  103.67 -		--enable-omap-experimental-api \
  103.68 -		--enable-exynos-experimental-api \
  103.69 -		--enable-tegra-experimental-api \
  103.70 -		--enable-etnaviv-experimental-api \
  103.71 -		$CONFIGURE_ARGS &&
  103.72 -	fix libtool &&
  103.73 -	make &&
  103.74 -	make install
  103.75 +	meson-wrapper \
  103.76 +		-Domap=true \
  103.77 +		-Dexynos=true \
  103.78 +		-Dtegra=true \
  103.79 +		-Detnaviv=true \
  103.80 +		-Dudev=true \
  103.81 +		&&
  103.82 +	ninja &&
  103.83 +	ninja install
  103.84  }
  103.85 -
  103.86 -genpkg_rules() {
  103.87 -	case $PACKAGE in
  103.88 -		libdrm)
  103.89 -			copy libdrm.so* libkms.so*
  103.90 -			DEPENDS="eudev linux-drm xorg-libpciaccess" # all deps are implicit
  103.91 -			;;
  103.92 -		*-amdgpu)
  103.93 -			copy libdrm_amdgpu.so* amdgpu.ids
  103.94 -			CAT="x-window|AMDGPU API"
  103.95 -			DEPENDS="libdrm"
  103.96 -			;;
  103.97 -		*-etnaviv)
  103.98 -			copy libdrm_etnaviv.so*
  103.99 -			CAT="x-window|Etnaviv API"
 103.100 -			DEPENDS="libdrm"
 103.101 -			;;
 103.102 -		*-exynos)
 103.103 -			copy libdrm_exynos.so*
 103.104 -			CAT="x-window|EXYNOS API"
 103.105 -			DEPENDS="libdrm"
 103.106 -			;;
 103.107 -		*-intel)
 103.108 -			copy libdrm_intel.so*
 103.109 -			CAT="x-window|Intel API"
 103.110 -			DEPENDS="libdrm xorg-libpciaccess"
 103.111 -			;;
 103.112 -		*-nouveau)
 103.113 -			copy libdrm_nouveau.so*
 103.114 -			CAT="x-window|Nouveau API"
 103.115 -			DEPENDS="libdrm"
 103.116 -			;;
 103.117 -		*-omap)
 103.118 -			copy libdrm_omap.so*
 103.119 -			CAT="x-window|OMAP API"
 103.120 -			DEPENDS="libdrm"
 103.121 -			;;
 103.122 -		*-radeon)
 103.123 -			copy libdrm_radeon.so*
 103.124 -			CAT="x-window|Radeon API"
 103.125 -			DEPENDS="libdrm"
 103.126 -			;;
 103.127 -		*-tegra)
 103.128 -			copy libdrm_tegra.so*
 103.129 -			CAT="x-window|Tegra API"
 103.130 -			DEPENDS="libdrm"
 103.131 -			;;
 103.132 -		*-dev)
 103.133 -			copy @dev
 103.134 -			;;
 103.135 -	esac
 103.136 -}
   104.1 --- a/libevdev/receipt	Thu Dec 13 00:46:54 2018 +0200
   104.2 +++ b/libevdev/receipt	Thu Dec 20 17:55:43 2018 +0200
   104.3 @@ -1,7 +1,7 @@
   104.4  # SliTaz package receipt v2.
   104.5  
   104.6  PACKAGE="libevdev"
   104.7 -VERSION="1.5.9"
   104.8 +VERSION="1.6.0"
   104.9  CATEGORY="x-window"
  104.10  SHORT_DESC="Common functions for Xorg input drivers"
  104.11  MAINTAINER="al.bobylev@gmail.com"
  104.12 @@ -11,6 +11,7 @@
  104.13  
  104.14  TARBALL="$PACKAGE-$VERSION.tar.xz"
  104.15  WGET_URL="http://www.freedesktop.org/software/libevdev/$TARBALL"
  104.16 +TARBALL_SHA1="ef584a500833fe737bacb89350f93314b07f1c42"
  104.17  
  104.18  BUILD_DEPENDS="check-dev python" # doxygen
  104.19  SPLIT="$PACKAGE-dev"
  104.20 @@ -23,10 +24,3 @@
  104.21  	make &&
  104.22  	make install
  104.23  }
  104.24 -
  104.25 -genpkg_rules() {
  104.26 -	case $PACKAGE in
  104.27 -		libevdev) copy @std;;
  104.28 -		*-dev)    copy @dev;;
  104.29 -	esac
  104.30 -}
   105.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.2 +++ b/libfontenc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   105.3 @@ -0,0 +1,1 @@
   105.4 +../xorg/.icon.png
   105.5 \ No newline at end of file
   106.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   106.2 +++ b/libfontenc/receipt	Thu Dec 20 17:55:43 2018 +0200
   106.3 @@ -0,0 +1,33 @@
   106.4 +# SliTaz package receipt v2.
   106.5 +
   106.6 +PACKAGE="libfontenc"
   106.7 +VERSION="1.1.3"
   106.8 +CATEGORY="x-window"
   106.9 +SHORT_DESC="Font encoding library"
  106.10 +MAINTAINER="devel@slitaz.org"
  106.11 +LICENSE="MIT"
  106.12 +WEB_SITE="https://www.x.org/wiki/"
  106.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  106.14 +
  106.15 +TARBALL="libfontenc-$VERSION.tar.bz2"
  106.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  106.17 +TARBALL_SHA1="312116f5156d6a8a2404c59560b60d53ddf1a09f"
  106.18 +
  106.19 +BUILD_DEPENDS="zlib-dev xorgproto font-util-dev"
  106.20 +SPLIT="$PACKAGE-dev"
  106.21 +
  106.22 +DEPENDS_std="zlib"
  106.23 +
  106.24 +compile_rules() {
  106.25 +	./configure \
  106.26 +		--disable-static \
  106.27 +		$CONFIGURE_ARGS &&
  106.28 +	fix libtool &&
  106.29 +	make &&
  106.30 +	make install
  106.31 +}
  106.32 +
  106.33 +TAGS="Xorg"
  106.34 +
  106.35 +PROVIDE_std="xorg-libfontenc"
  106.36 +PROVIDE_dev="xorg-libfontenc-dev"
   107.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   107.2 +++ b/libfs/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   107.3 @@ -0,0 +1,1 @@
   107.4 +../xorg/.icon.png
   107.5 \ No newline at end of file
   108.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.2 +++ b/libfs/receipt	Thu Dec 20 17:55:43 2018 +0200
   108.3 @@ -0,0 +1,33 @@
   108.4 +# SliTaz package receipt v2.
   108.5 +
   108.6 +PACKAGE="libfs"
   108.7 +VERSION="1.0.7"
   108.8 +CATEGORY="x-window"
   108.9 +SHORT_DESC="X Font Service client library"
  108.10 +MAINTAINER="pascal.bellard@slitaz.org"
  108.11 +LICENSE="MIT"
  108.12 +WEB_SITE="https://www.x.org/wiki/"
  108.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  108.14 +
  108.15 +TARBALL="libFS-$VERSION.tar.bz2"
  108.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  108.17 +TARBALL_SHA1="6af3035d9cbca31562e42a1060f6ce7b86a5d1d3"
  108.18 +
  108.19 +BUILD_DEPENDS="xorgproto xtrans"
  108.20 +SPLIT="$PACKAGE-dev"
  108.21 +
  108.22 +DEPENDS_dev="$PACKAGE xorgproto"
  108.23 +
  108.24 +compile_rules() {
  108.25 +	./configure \
  108.26 +		--disable-static \
  108.27 +		$CONFIGURE_ARGS &&
  108.28 +	fix libtool &&
  108.29 +	make &&
  108.30 +	make install
  108.31 +}
  108.32 +
  108.33 +TAGS="Xorg"
  108.34 +
  108.35 +PROVIDE_std="xorg-libFS"
  108.36 +PROVIDE_dev="xorg-libFS-dev"
   109.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.2 +++ b/libice/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   109.3 @@ -0,0 +1,1 @@
   109.4 +../xorg/.icon.png
   109.5 \ No newline at end of file
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/libice/receipt	Thu Dec 20 17:55:43 2018 +0200
   110.3 @@ -0,0 +1,37 @@
   110.4 +# SliTaz package receipt v2.
   110.5 +
   110.6 +PACKAGE="libice"
   110.7 +VERSION="1.0.9"
   110.8 +CATEGORY="x-window"
   110.9 +SHORT_DESC="Inter-Client Exchange library"
  110.10 +MAINTAINER="devel@slitaz.org"
  110.11 +LICENSE="MIT"
  110.12 +WEB_SITE="https://www.x.org/wiki/"
  110.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  110.14 +
  110.15 +TARBALL="libICE-$VERSION.tar.bz2"
  110.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  110.17 +TARBALL_SHA1="3c3a857a117ce48a1947a16860056e77cd494fdf"
  110.18 +
  110.19 +BUILD_DEPENDS="xorgproto xtrans"
  110.20 +SPLIT="$PACKAGE-dev"
  110.21 +
  110.22 +DEPENDS_dev="$PACKAGE xorgproto"
  110.23 +
  110.24 +compile_rules() {
  110.25 +	touch /root/missing /missing
  110.26 +
  110.27 +	# ICE_LIBS=-lpthread: fixes a change in glibc which breaks pulseaudio at runtime
  110.28 +	./configure \
  110.29 +		--disable-static \
  110.30 +		ICE_LIBS=-lpthread \
  110.31 +		$CONFIGURE_ARGS &&
  110.32 +	fix libtool &&
  110.33 +	make &&
  110.34 +	make install
  110.35 +}
  110.36 +
  110.37 +TAGS="Xorg"
  110.38 +
  110.39 +PROVIDE_std="xorg-libICE"
  110.40 +PROVIDE_dev="xorg-libICE-dev"
   111.1 --- a/libinput/receipt	Thu Dec 13 00:46:54 2018 +0200
   111.2 +++ b/libinput/receipt	Thu Dec 20 17:55:43 2018 +0200
   111.3 @@ -1,7 +1,7 @@
   111.4  # SliTaz package receipt v2.
   111.5  
   111.6  PACKAGE="libinput"
   111.7 -VERSION="1.12.1"
   111.8 +VERSION="1.12.4"
   111.9  CATEGORY="x-window"
  111.10  SHORT_DESC="Library that handles input devices for display servers"
  111.11  MAINTAINER="al.bobylev@gmail.com"
  111.12 @@ -11,10 +11,18 @@
  111.13  
  111.14  TARBALL="$PACKAGE-$VERSION.tar.xz"
  111.15  WGET_URL="http://www.freedesktop.org/software/libinput/$TARBALL"
  111.16 +TARBALL_SHA1="9c1a7a2fead7f03eb21a5a0f5ac3bff6af00ebf8"
  111.17  
  111.18  BUILD_DEPENDS="meson ninja eudev-dev mtdev-dev libevdev-dev gtk3-dev check-dev"
  111.19  SPLIT="$PACKAGE-debug-gui $PACKAGE $PACKAGE-dev"
  111.20  
  111.21 +COPY_debug_gui="libinput-debug-gui"
  111.22 +CAT_debug_gui="x-window|debug GUI"
  111.23 +
  111.24 +DEPENDS_debug_gui="cairo eudev glib gtk3 libevdev $PACKAGE"
  111.25 +DEPENDS_std="eudev libevdev mtdev"
  111.26 +DEPENDS_dev="$PACKAGE" # no libinput-debug-gui because of gtk3
  111.27 +
  111.28  compile_rules() {
  111.29  	mkdir build
  111.30  	cd    build
  111.31 @@ -27,21 +35,3 @@
  111.32  	ninja &&
  111.33  	ninja install
  111.34  }
  111.35 -
  111.36 -genpkg_rules() {
  111.37 -	case $PACKAGE in
  111.38 -		*-gui)
  111.39 -			copy libinput-debug-gui
  111.40 -			CAT="x-window|debug GUI"
  111.41 -			DEPENDS="cairo eudev glib gtk3 libevdev libinput"
  111.42 -			;;
  111.43 -		libinput)
  111.44 -			copy @std @rm
  111.45 -			DEPENDS="eudev libevdev mtdev"
  111.46 -			;;
  111.47 -		*-dev)
  111.48 -			copy @dev
  111.49 -			DEPENDS="libinput"
  111.50 -			;;
  111.51 -	esac
  111.52 -}
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/liblbxutil/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   112.3 @@ -0,0 +1,1 @@
   112.4 +../xorg/.icon.png
   112.5 \ No newline at end of file
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/liblbxutil/receipt	Thu Dec 20 17:55:43 2018 +0200
   113.3 @@ -0,0 +1,33 @@
   113.4 +# SliTaz package receipt v2.
   113.5 +
   113.6 +PACKAGE="liblbxutil"
   113.7 +VERSION="1.1.0"
   113.8 +CATEGORY="x-window"
   113.9 +SHORT_DESC="LBX utility routines"
  113.10 +MAINTAINER="al.bobylev@gmail.com"
  113.11 +LICENSE="MIT"
  113.12 +WEB_SITE="https://www.x.org/wiki/"
  113.13 +
  113.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  113.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  113.16 +TARBALL_SHA1="99616bab0ca0afeaa9c0a19222091b1ff4f18680"
  113.17 +
  113.18 +BUILD_DEPENDS="gfortran xorgproto zlib-dev"
  113.19 +SPLIT="$PACKAGE-dev"
  113.20 +
  113.21 +DEPENDS_std="zlib"
  113.22 +DEPENDS_dev="$PACKAGE zlib-dev"
  113.23 +
  113.24 +compile_rules() {
  113.25 +	./configure \
  113.26 +		--disable-static \
  113.27 +		$CONFIGURE_ARGS &&
  113.28 +	fix libtool &&
  113.29 +	make &&
  113.30 +	make install
  113.31 +}
  113.32 +
  113.33 +TAGS="Xorg"
  113.34 +
  113.35 +PROVIDE_std="xorg-liblbxutil"
  113.36 +PROVIDE_dev="xorg-liblbxutil-dev"
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/libpciaccess/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   114.3 @@ -0,0 +1,1 @@
   114.4 +../xorg/.icon.png
   114.5 \ No newline at end of file
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/libpciaccess/receipt	Thu Dec 20 17:55:43 2018 +0200
   115.3 @@ -0,0 +1,30 @@
   115.4 +# SliTaz package receipt v2.
   115.5 +
   115.6 +PACKAGE="libpciaccess"
   115.7 +VERSION="0.14"
   115.8 +CATEGORY="x-window"
   115.9 +SHORT_DESC="Xorg server module"
  115.10 +MAINTAINER="devel@slitaz.org"
  115.11 +LICENSE="MIT"
  115.12 +WEB_SITE="https://www.x.org/wiki/"
  115.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  115.14 +
  115.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  115.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  115.17 +TARBALL_SHA1="f70a958bf4e744cb4ee93be64e9bc52ac05cdaeb"
  115.18 +
  115.19 +SPLIT="$PACKAGE-dev"
  115.20 +
  115.21 +compile_rules() {
  115.22 +	./configure \
  115.23 +		--disable-static \
  115.24 +		$CONFIGURE_ARGS &&
  115.25 +	fix libtool &&
  115.26 +	make &&
  115.27 +	make install
  115.28 +}
  115.29 +
  115.30 +TAGS="Xorg"
  115.31 +
  115.32 +PROVIDE_std="xorg-libpciaccess"
  115.33 +PROVIDE_dev="xorg-libpciaccess-dev"
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/libpng/receipt	Thu Dec 20 17:55:43 2018 +0200
   116.3 @@ -0,0 +1,41 @@
   116.4 +# SliTaz package receipt v2.
   116.5 +
   116.6 +PACKAGE="libpng"
   116.7 +VERSION="1.6.36"
   116.8 +CATEGORY="libs"
   116.9 +SHORT_DESC="PNG images library 1.6 series with APNG support"
  116.10 +MAINTAINER="al.bobylev@gmail.com"
  116.11 +LICENSE="zlib/libpng"
  116.12 +WEB_SITE="http://www.libpng.org/pub/png/libpng.html"
  116.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/general/libpng.html"
  116.14 +
  116.15 +TARBALL="$PACKAGE-$VERSION.tar.xz"
  116.16 +WGET_URL="$SF_MIRROR/libpng/$TARBALL"
  116.17 +TARBALL_SHA1="aec9548c8319104226cc4c31d1f5e524f1b55295"
  116.18 +
  116.19 +BUILD_DEPENDS="zlib-dev"
  116.20 +SPLIT="$PACKAGE-dev"
  116.21 +
  116.22 +DEPENDS_std="zlib"
  116.23 +DEPENDS_dev="$PACKAGE zlib-dev"
  116.24 +
  116.25 +compile_rules() {
  116.26 +	# don't use --disable-static: optipng-static require such lib
  116.27 +
  116.28 +	LIBS=-lpthread \
  116.29 +	./configure \
  116.30 +		$CONFIGURE_ARGS &&
  116.31 +	fix libtool &&
  116.32 +	make &&
  116.33 +	make install || return 1
  116.34 +
  116.35 +	cook_pick_docs README libpng-manual.txt
  116.36 +
  116.37 +	# Misc png tools
  116.38 +	cd contrib/pngminus
  116.39 +	make PNGLIB="-L$install/usr/lib -lpng" -f makefile.std png2pnm pnm2png
  116.40 +	cp -a png2pnm pnm2png $install/usr/bin
  116.41 +}
  116.42 +
  116.43 +PROVIDE_std="libpng16"
  116.44 +PROVIDE_dev="libpng16-dev"
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/libpng/stuff/patches/libpng-1.6.35-apng.patch	Thu Dec 20 17:55:43 2018 +0200
   117.3 @@ -0,0 +1,1728 @@
   117.4 +diff -Naru libpng-1.6.35.org/png.h libpng-1.6.35/png.h
   117.5 +--- libpng-1.6.35.org/png.h	2018-07-21 19:16:37.185142931 +0900
   117.6 ++++ libpng-1.6.35/png.h	2018-07-21 19:16:16.327364638 +0900
   117.7 +@@ -361,6 +361,10 @@
   117.8 + #   include "pnglibconf.h"
   117.9 + #endif
  117.10 + 
  117.11 ++#define PNG_APNG_SUPPORTED
  117.12 ++#define PNG_READ_APNG_SUPPORTED
  117.13 ++#define PNG_WRITE_APNG_SUPPORTED
  117.14 ++
  117.15 + #ifndef PNG_VERSION_INFO_ONLY
  117.16 + /* Machine specific configuration. */
  117.17 + #  include "pngconf.h"
  117.18 +@@ -456,6 +460,17 @@
  117.19 +  * See pngconf.h for base types that vary by machine/system
  117.20 +  */
  117.21 + 
  117.22 ++#ifdef PNG_APNG_SUPPORTED
  117.23 ++/* dispose_op flags from inside fcTL */
  117.24 ++#define PNG_DISPOSE_OP_NONE        0x00U
  117.25 ++#define PNG_DISPOSE_OP_BACKGROUND  0x01U
  117.26 ++#define PNG_DISPOSE_OP_PREVIOUS    0x02U
  117.27 ++
  117.28 ++/* blend_op flags from inside fcTL */
  117.29 ++#define PNG_BLEND_OP_SOURCE        0x00U
  117.30 ++#define PNG_BLEND_OP_OVER          0x01U
  117.31 ++#endif /* PNG_APNG_SUPPORTED */
  117.32 ++
  117.33 + /* This triggers a compiler error in png.c, if png.c and png.h
  117.34 +  * do not agree upon the version number.
  117.35 +  */
  117.36 +@@ -777,6 +792,10 @@
  117.37 + #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
  117.38 + #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
  117.39 + #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
  117.40 ++#ifdef PNG_APNG_SUPPORTED
  117.41 ++#define PNG_INFO_acTL 0x20000U
  117.42 ++#define PNG_INFO_fcTL 0x40000U
  117.43 ++#endif
  117.44 + 
  117.45 + /* This is used for the transformation routines, as some of them
  117.46 +  * change these values for the row.  It also should enable using
  117.47 +@@ -814,6 +833,10 @@
  117.48 + #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  117.49 + typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
  117.50 + typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
  117.51 ++#ifdef PNG_APNG_SUPPORTED
  117.52 ++typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
  117.53 ++    png_uint_32));
  117.54 ++#endif
  117.55 + 
  117.56 + /* The following callback receives png_uint_32 row_number, int pass for the
  117.57 +  * png_bytep data of the row.  When transforming an interlaced image the
  117.58 +@@ -3257,6 +3280,74 @@
  117.59 + /*******************************************************************************
  117.60 +  *  END OF HARDWARE AND SOFTWARE OPTIONS
  117.61 +  ******************************************************************************/
  117.62 ++#ifdef PNG_APNG_SUPPORTED
  117.63 ++PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr,
  117.64 ++   png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
  117.65 ++
  117.66 ++PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr,
  117.67 ++   png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
  117.68 ++
  117.69 ++PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr,
  117.70 ++   png_infop info_ptr));
  117.71 ++
  117.72 ++PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr,
  117.73 ++   png_infop info_ptr));
  117.74 ++
  117.75 ++PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL,
  117.76 ++   (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
  117.77 ++   png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
  117.78 ++   png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
  117.79 ++   png_byte *blend_op));
  117.80 ++
  117.81 ++PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL,
  117.82 ++   (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
  117.83 ++   png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
  117.84 ++   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
  117.85 ++   png_byte blend_op));
  117.86 ++
  117.87 ++PNG_EXPORT(256, png_uint_32, png_get_next_frame_width,
  117.88 ++   (png_structp png_ptr, png_infop info_ptr));
  117.89 ++PNG_EXPORT(257, png_uint_32, png_get_next_frame_height,
  117.90 ++   (png_structp png_ptr, png_infop info_ptr));
  117.91 ++PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset,
  117.92 ++   (png_structp png_ptr, png_infop info_ptr));
  117.93 ++PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset,
  117.94 ++   (png_structp png_ptr, png_infop info_ptr));
  117.95 ++PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num,
  117.96 ++   (png_structp png_ptr, png_infop info_ptr));
  117.97 ++PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den,
  117.98 ++   (png_structp png_ptr, png_infop info_ptr));
  117.99 ++PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op,
 117.100 ++   (png_structp png_ptr, png_infop info_ptr));
 117.101 ++PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op,
 117.102 ++   (png_structp png_ptr, png_infop info_ptr));
 117.103 ++PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden,
 117.104 ++   (png_structp png_ptr, png_infop info_ptr));
 117.105 ++PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden,
 117.106 ++   (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
 117.107 ++
 117.108 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.109 ++PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr,
 117.110 ++   png_infop info_ptr));
 117.111 ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 117.112 ++PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr,
 117.113 ++   png_progressive_frame_ptr frame_info_fn,
 117.114 ++   png_progressive_frame_ptr frame_end_fn));
 117.115 ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 117.116 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.117 ++
 117.118 ++#ifdef PNG_WRITE_APNG_SUPPORTED
 117.119 ++PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr,
 117.120 ++   png_infop info_ptr, png_bytepp row_pointers,
 117.121 ++   png_uint_32 width, png_uint_32 height,
 117.122 ++   png_uint_32 x_offset, png_uint_32 y_offset,
 117.123 ++   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 117.124 ++   png_byte blend_op));
 117.125 ++
 117.126 ++PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
 117.127 ++   png_infop info_ptr));
 117.128 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
 117.129 ++#endif /* PNG_APNG_SUPPORTED */
 117.130 + 
 117.131 + /* Maintainer: Put new public prototypes here ^, in libpng.3, in project
 117.132 +  * defs, and in scripts/symbols.def.
 117.133 +@@ -3266,7 +3357,11 @@
 117.134 +  * one to use is one more than this.)
 117.135 +  */
 117.136 + #ifdef PNG_EXPORT_LAST_ORDINAL
 117.137 ++#ifdef PNG_APNG_SUPPORTED
 117.138 ++  PNG_EXPORT_LAST_ORDINAL(269);
 117.139 ++#else
 117.140 +   PNG_EXPORT_LAST_ORDINAL(249);
 117.141 ++#endif /* PNG_APNG_SUPPORTED */
 117.142 + #endif
 117.143 + 
 117.144 + #ifdef __cplusplus
 117.145 +diff -Naru libpng-1.6.35.org/pngget.c libpng-1.6.35/pngget.c
 117.146 +--- libpng-1.6.35.org/pngget.c	2018-07-21 19:16:37.185142931 +0900
 117.147 ++++ libpng-1.6.35/pngget.c	2018-07-21 19:16:16.229356281 +0900
 117.148 +@@ -1246,4 +1246,166 @@
 117.149 + #  endif
 117.150 + #endif
 117.151 + 
 117.152 ++#ifdef PNG_APNG_SUPPORTED
 117.153 ++png_uint_32 PNGAPI
 117.154 ++png_get_acTL(png_structp png_ptr, png_infop info_ptr,
 117.155 ++             png_uint_32 *num_frames, png_uint_32 *num_plays)
 117.156 ++{
 117.157 ++    png_debug1(1, "in %s retrieval function", "acTL");
 117.158 ++
 117.159 ++    if (png_ptr != NULL && info_ptr != NULL &&
 117.160 ++        (info_ptr->valid & PNG_INFO_acTL) &&
 117.161 ++        num_frames != NULL && num_plays != NULL)
 117.162 ++    {
 117.163 ++        *num_frames = info_ptr->num_frames;
 117.164 ++        *num_plays = info_ptr->num_plays;
 117.165 ++        return (1);
 117.166 ++    }
 117.167 ++
 117.168 ++    return (0);
 117.169 ++}
 117.170 ++
 117.171 ++png_uint_32 PNGAPI
 117.172 ++png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
 117.173 ++{
 117.174 ++    png_debug(1, "in png_get_num_frames()");
 117.175 ++
 117.176 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.177 ++        return (info_ptr->num_frames);
 117.178 ++    return (0);
 117.179 ++}
 117.180 ++
 117.181 ++png_uint_32 PNGAPI
 117.182 ++png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
 117.183 ++{
 117.184 ++    png_debug(1, "in png_get_num_plays()");
 117.185 ++
 117.186 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.187 ++        return (info_ptr->num_plays);
 117.188 ++    return (0);
 117.189 ++}
 117.190 ++
 117.191 ++png_uint_32 PNGAPI
 117.192 ++png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
 117.193 ++             png_uint_32 *width, png_uint_32 *height,
 117.194 ++             png_uint_32 *x_offset, png_uint_32 *y_offset,
 117.195 ++             png_uint_16 *delay_num, png_uint_16 *delay_den,
 117.196 ++             png_byte *dispose_op, png_byte *blend_op)
 117.197 ++{
 117.198 ++    png_debug1(1, "in %s retrieval function", "fcTL");
 117.199 ++
 117.200 ++    if (png_ptr != NULL && info_ptr != NULL &&
 117.201 ++        (info_ptr->valid & PNG_INFO_fcTL) &&
 117.202 ++        width != NULL && height != NULL &&
 117.203 ++        x_offset != NULL && y_offset != NULL &&
 117.204 ++        delay_num != NULL && delay_den != NULL &&
 117.205 ++        dispose_op != NULL && blend_op != NULL)
 117.206 ++    {
 117.207 ++        *width = info_ptr->next_frame_width;
 117.208 ++        *height = info_ptr->next_frame_height;
 117.209 ++        *x_offset = info_ptr->next_frame_x_offset;
 117.210 ++        *y_offset = info_ptr->next_frame_y_offset;
 117.211 ++        *delay_num = info_ptr->next_frame_delay_num;
 117.212 ++        *delay_den = info_ptr->next_frame_delay_den;
 117.213 ++        *dispose_op = info_ptr->next_frame_dispose_op;
 117.214 ++        *blend_op = info_ptr->next_frame_blend_op;
 117.215 ++        return (1);
 117.216 ++    }
 117.217 ++
 117.218 ++    return (0);
 117.219 ++}
 117.220 ++
 117.221 ++png_uint_32 PNGAPI
 117.222 ++png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
 117.223 ++{
 117.224 ++    png_debug(1, "in png_get_next_frame_width()");
 117.225 ++
 117.226 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.227 ++        return (info_ptr->next_frame_width);
 117.228 ++    return (0);
 117.229 ++}
 117.230 ++
 117.231 ++png_uint_32 PNGAPI
 117.232 ++png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
 117.233 ++{
 117.234 ++    png_debug(1, "in png_get_next_frame_height()");
 117.235 ++
 117.236 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.237 ++        return (info_ptr->next_frame_height);
 117.238 ++    return (0);
 117.239 ++}
 117.240 ++
 117.241 ++png_uint_32 PNGAPI
 117.242 ++png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
 117.243 ++{
 117.244 ++    png_debug(1, "in png_get_next_frame_x_offset()");
 117.245 ++
 117.246 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.247 ++        return (info_ptr->next_frame_x_offset);
 117.248 ++    return (0);
 117.249 ++}
 117.250 ++
 117.251 ++png_uint_32 PNGAPI
 117.252 ++png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
 117.253 ++{
 117.254 ++    png_debug(1, "in png_get_next_frame_y_offset()");
 117.255 ++
 117.256 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.257 ++        return (info_ptr->next_frame_y_offset);
 117.258 ++    return (0);
 117.259 ++}
 117.260 ++
 117.261 ++png_uint_16 PNGAPI
 117.262 ++png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
 117.263 ++{
 117.264 ++    png_debug(1, "in png_get_next_frame_delay_num()");
 117.265 ++
 117.266 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.267 ++        return (info_ptr->next_frame_delay_num);
 117.268 ++    return (0);
 117.269 ++}
 117.270 ++
 117.271 ++png_uint_16 PNGAPI
 117.272 ++png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
 117.273 ++{
 117.274 ++    png_debug(1, "in png_get_next_frame_delay_den()");
 117.275 ++
 117.276 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.277 ++        return (info_ptr->next_frame_delay_den);
 117.278 ++    return (0);
 117.279 ++}
 117.280 ++
 117.281 ++png_byte PNGAPI
 117.282 ++png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
 117.283 ++{
 117.284 ++    png_debug(1, "in png_get_next_frame_dispose_op()");
 117.285 ++
 117.286 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.287 ++        return (info_ptr->next_frame_dispose_op);
 117.288 ++    return (0);
 117.289 ++}
 117.290 ++
 117.291 ++png_byte PNGAPI
 117.292 ++png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
 117.293 ++{
 117.294 ++    png_debug(1, "in png_get_next_frame_blend_op()");
 117.295 ++
 117.296 ++    if (png_ptr != NULL && info_ptr != NULL)
 117.297 ++        return (info_ptr->next_frame_blend_op);
 117.298 ++    return (0);
 117.299 ++}
 117.300 ++
 117.301 ++png_byte PNGAPI
 117.302 ++png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
 117.303 ++{
 117.304 ++    png_debug(1, "in png_first_frame_is_hidden()");
 117.305 ++
 117.306 ++    if (png_ptr != NULL)
 117.307 ++       return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
 117.308 ++
 117.309 ++    PNG_UNUSED(info_ptr)
 117.310 ++
 117.311 ++    return 0;
 117.312 ++}
 117.313 ++#endif /* PNG_APNG_SUPPORTED */
 117.314 + #endif /* READ || WRITE */
 117.315 +diff -Naru libpng-1.6.35.org/pnginfo.h libpng-1.6.35/pnginfo.h
 117.316 +--- libpng-1.6.35.org/pnginfo.h	2018-07-21 19:16:37.185142931 +0900
 117.317 ++++ libpng-1.6.35/pnginfo.h	2018-07-21 19:16:16.228356197 +0900
 117.318 +@@ -263,5 +263,18 @@
 117.319 +    png_bytepp row_pointers;        /* the image bits */
 117.320 + #endif
 117.321 + 
 117.322 ++#ifdef PNG_APNG_SUPPORTED
 117.323 ++   png_uint_32 num_frames; /* including default image */
 117.324 ++   png_uint_32 num_plays;
 117.325 ++   png_uint_32 next_frame_width;
 117.326 ++   png_uint_32 next_frame_height;
 117.327 ++   png_uint_32 next_frame_x_offset;
 117.328 ++   png_uint_32 next_frame_y_offset;
 117.329 ++   png_uint_16 next_frame_delay_num;
 117.330 ++   png_uint_16 next_frame_delay_den;
 117.331 ++   png_byte next_frame_dispose_op;
 117.332 ++   png_byte next_frame_blend_op;
 117.333 ++#endif
 117.334 ++
 117.335 + };
 117.336 + #endif /* PNGINFO_H */
 117.337 +diff -Naru libpng-1.6.35.org/pngpread.c libpng-1.6.35/pngpread.c
 117.338 +--- libpng-1.6.35.org/pngpread.c	2018-07-21 19:16:37.185142931 +0900
 117.339 ++++ libpng-1.6.35/pngpread.c	2018-07-21 19:16:16.228356197 +0900
 117.340 +@@ -195,6 +195,106 @@
 117.341 + 
 117.342 +    chunk_name = png_ptr->chunk_name;
 117.343 + 
 117.344 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.345 ++   if (png_ptr->num_frames_read > 0 &&
 117.346 ++       png_ptr->num_frames_read < info_ptr->num_frames)
 117.347 ++   {
 117.348 ++      if (chunk_name == png_IDAT)
 117.349 ++      {
 117.350 ++         /* Discard trailing IDATs for the first frame */
 117.351 ++         if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
 117.352 ++            png_error(png_ptr, "out of place IDAT");
 117.353 ++
 117.354 ++         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.355 ++         {
 117.356 ++            png_push_save_buffer(png_ptr);
 117.357 ++            return;
 117.358 ++         }
 117.359 ++
 117.360 ++         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 117.361 ++         return;
 117.362 ++      }
 117.363 ++      else if (chunk_name == png_fdAT)
 117.364 ++      {
 117.365 ++         if (png_ptr->buffer_size < 4)
 117.366 ++         {
 117.367 ++            png_push_save_buffer(png_ptr);
 117.368 ++            return;
 117.369 ++         }
 117.370 ++
 117.371 ++         png_ensure_sequence_number(png_ptr, 4);
 117.372 ++
 117.373 ++         if (!(png_ptr->mode & PNG_HAVE_fcTL))
 117.374 ++         {
 117.375 ++            /* Discard trailing fdATs for frames other than the first */
 117.376 ++            if (png_ptr->num_frames_read < 2)
 117.377 ++               png_error(png_ptr, "out of place fdAT");
 117.378 ++
 117.379 ++            if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.380 ++            {
 117.381 ++               png_push_save_buffer(png_ptr);
 117.382 ++               return;
 117.383 ++            }
 117.384 ++
 117.385 ++            png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 117.386 ++            return;
 117.387 ++         }
 117.388 ++
 117.389 ++         else
 117.390 ++         {
 117.391 ++            /* frame data follows */
 117.392 ++            png_ptr->idat_size = png_ptr->push_length - 4;
 117.393 ++            png_ptr->mode |= PNG_HAVE_IDAT;
 117.394 ++            png_ptr->process_mode = PNG_READ_IDAT_MODE;
 117.395 ++
 117.396 ++            return;
 117.397 ++         }
 117.398 ++      }
 117.399 ++
 117.400 ++      else if (chunk_name == png_fcTL)
 117.401 ++      {
 117.402 ++         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.403 ++         {
 117.404 ++            png_push_save_buffer(png_ptr);
 117.405 ++            return;
 117.406 ++         }
 117.407 ++
 117.408 ++         png_read_reset(png_ptr);
 117.409 ++         png_ptr->mode &= ~PNG_HAVE_fcTL;
 117.410 ++
 117.411 ++         png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
 117.412 ++
 117.413 ++         if (!(png_ptr->mode & PNG_HAVE_fcTL))
 117.414 ++            png_error(png_ptr, "missing required fcTL chunk");
 117.415 ++
 117.416 ++         png_read_reinit(png_ptr, info_ptr);
 117.417 ++         png_progressive_read_reset(png_ptr);
 117.418 ++
 117.419 ++         if (png_ptr->frame_info_fn != NULL)
 117.420 ++            (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
 117.421 ++
 117.422 ++         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 117.423 ++
 117.424 ++         return;
 117.425 ++      }
 117.426 ++
 117.427 ++      else
 117.428 ++      {
 117.429 ++         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.430 ++         {
 117.431 ++            png_push_save_buffer(png_ptr);
 117.432 ++            return;
 117.433 ++         }
 117.434 ++         png_warning(png_ptr, "Skipped (ignored) a chunk "
 117.435 ++                              "between APNG chunks");
 117.436 ++         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 117.437 ++         return;
 117.438 ++      }
 117.439 ++
 117.440 ++      return;
 117.441 ++   }
 117.442 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.443 ++
 117.444 +    if (chunk_name == png_IDAT)
 117.445 +    {
 117.446 +       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
 117.447 +@@ -261,6 +361,9 @@
 117.448 + 
 117.449 +    else if (chunk_name == png_IDAT)
 117.450 +    {
 117.451 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.452 ++      png_have_info(png_ptr, info_ptr);
 117.453 ++#endif
 117.454 +       png_ptr->idat_size = png_ptr->push_length;
 117.455 +       png_ptr->process_mode = PNG_READ_IDAT_MODE;
 117.456 +       png_push_have_info(png_ptr, info_ptr);
 117.457 +@@ -406,6 +509,30 @@
 117.458 +       png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
 117.459 +    }
 117.460 + #endif
 117.461 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.462 ++   else if (chunk_name == png_acTL)
 117.463 ++   {
 117.464 ++      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.465 ++      {
 117.466 ++         png_push_save_buffer(png_ptr);
 117.467 ++         return;
 117.468 ++      }
 117.469 ++
 117.470 ++      png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
 117.471 ++   }
 117.472 ++
 117.473 ++   else if (chunk_name == png_fcTL)
 117.474 ++   {
 117.475 ++      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.476 ++      {
 117.477 ++         png_push_save_buffer(png_ptr);
 117.478 ++         return;
 117.479 ++      }
 117.480 ++
 117.481 ++      png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
 117.482 ++   }
 117.483 ++
 117.484 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.485 + 
 117.486 +    else
 117.487 +    {
 117.488 +@@ -539,7 +666,11 @@
 117.489 +       png_byte chunk_tag[4];
 117.490 + 
 117.491 +       /* TODO: this code can be commoned up with the same code in push_read */
 117.492 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.493 ++      PNG_PUSH_SAVE_BUFFER_IF_LT(12)
 117.494 ++#else
 117.495 +       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
 117.496 ++#endif
 117.497 +       png_push_fill_buffer(png_ptr, chunk_length, 4);
 117.498 +       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
 117.499 +       png_reset_crc(png_ptr);
 117.500 +@@ -547,17 +678,64 @@
 117.501 +       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
 117.502 +       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
 117.503 + 
 117.504 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.505 ++      if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
 117.506 ++      {
 117.507 ++          if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
 117.508 ++          {
 117.509 ++              png_ptr->process_mode = PNG_READ_CHUNK_MODE;
 117.510 ++              if (png_ptr->frame_end_fn != NULL)
 117.511 ++                 (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
 117.512 ++              png_ptr->num_frames_read++;
 117.513 ++              return;
 117.514 ++          }
 117.515 ++          else
 117.516 ++          {
 117.517 ++              if (png_ptr->chunk_name == png_IEND)
 117.518 ++                  png_error(png_ptr, "Not enough image data");
 117.519 ++              if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 117.520 ++              {
 117.521 ++                 png_push_save_buffer(png_ptr);
 117.522 ++                 return;
 117.523 ++              }
 117.524 ++              png_warning(png_ptr, "Skipping (ignoring) a chunk between "
 117.525 ++                                   "APNG chunks");
 117.526 ++              png_crc_finish(png_ptr, png_ptr->push_length);
 117.527 ++              png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 117.528 ++              return;
 117.529 ++          }
 117.530 ++      }
 117.531 ++      else
 117.532 ++#endif
 117.533 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.534 ++      if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
 117.535 ++#else
 117.536 +       if (png_ptr->chunk_name != png_IDAT)
 117.537 ++#endif
 117.538 +       {
 117.539 +          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
 117.540 + 
 117.541 +          if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
 117.542 +             png_error(png_ptr, "Not enough compressed data");
 117.543 + 
 117.544 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.545 ++         if (png_ptr->frame_end_fn != NULL)
 117.546 ++            (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
 117.547 ++         png_ptr->num_frames_read++;
 117.548 ++#endif
 117.549 ++
 117.550 +          return;
 117.551 +       }
 117.552 + 
 117.553 +       png_ptr->idat_size = png_ptr->push_length;
 117.554 ++
 117.555 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.556 ++      if (png_ptr->num_frames_read > 0)
 117.557 ++      {
 117.558 ++         png_ensure_sequence_number(png_ptr, 4);
 117.559 ++         png_ptr->idat_size -= 4;
 117.560 ++      }
 117.561 ++#endif
 117.562 +    }
 117.563 + 
 117.564 +    if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
 117.565 +@@ -631,6 +809,15 @@
 117.566 +    if (!(buffer_length > 0) || buffer == NULL)
 117.567 +       png_error(png_ptr, "No IDAT data (internal error)");
 117.568 + 
 117.569 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.570 ++   /* If the app is not APNG-aware, decode only the first frame */
 117.571 ++   if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
 117.572 ++   {
 117.573 ++     png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
 117.574 ++     return;
 117.575 ++   }
 117.576 ++#endif
 117.577 ++
 117.578 +    /* This routine must process all the data it has been given
 117.579 +     * before returning, calling the row callback as required to
 117.580 +     * handle the uncompressed results.
 117.581 +@@ -1085,6 +1272,18 @@
 117.582 +    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
 117.583 + }
 117.584 + 
 117.585 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.586 ++void PNGAPI
 117.587 ++png_set_progressive_frame_fn(png_structp png_ptr,
 117.588 ++   png_progressive_frame_ptr frame_info_fn,
 117.589 ++   png_progressive_frame_ptr frame_end_fn)
 117.590 ++{
 117.591 ++   png_ptr->frame_info_fn = frame_info_fn;
 117.592 ++   png_ptr->frame_end_fn = frame_end_fn;
 117.593 ++   png_ptr->apng_flags |= PNG_APNG_APP;
 117.594 ++}
 117.595 ++#endif
 117.596 ++
 117.597 + png_voidp PNGAPI
 117.598 + png_get_progressive_ptr(png_const_structrp png_ptr)
 117.599 + {
 117.600 +diff -Naru libpng-1.6.35.org/pngpriv.h libpng-1.6.35/pngpriv.h
 117.601 +--- libpng-1.6.35.org/pngpriv.h	2018-07-21 19:16:37.185142931 +0900
 117.602 ++++ libpng-1.6.35/pngpriv.h	2018-07-21 19:16:16.226356026 +0900
 117.603 +@@ -634,6 +634,10 @@
 117.604 + #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
 117.605 +                    /*             0x4000U (unused) */
 117.606 + #define PNG_IS_READ_STRUCT        0x8000U /* Else is a write struct */
 117.607 ++#ifdef PNG_APNG_SUPPORTED
 117.608 ++#define PNG_HAVE_acTL            0x10000U
 117.609 ++#define PNG_HAVE_fcTL            0x20000U
 117.610 ++#endif
 117.611 + 
 117.612 + /* Flags for the transformations the PNG library does on the image data */
 117.613 + #define PNG_BGR                 0x0001U
 117.614 +@@ -870,6 +874,16 @@
 117.615 + #define png_tRNS PNG_U32(116,  82,  78,  83)
 117.616 + #define png_zTXt PNG_U32(122,  84,  88, 116)
 117.617 + 
 117.618 ++#ifdef PNG_APNG_SUPPORTED
 117.619 ++#define png_acTL PNG_U32( 97,  99,  84,  76)
 117.620 ++#define png_fcTL PNG_U32(102,  99,  84,  76)
 117.621 ++#define png_fdAT PNG_U32(102, 100,  65,  84)
 117.622 ++
 117.623 ++/* For png_struct.apng_flags: */
 117.624 ++#define PNG_FIRST_FRAME_HIDDEN       0x0001U
 117.625 ++#define PNG_APNG_APP                 0x0002U
 117.626 ++#endif
 117.627 ++
 117.628 + /* The following will work on (signed char*) strings, whereas the get_uint_32
 117.629 +  * macro will fail on top-bit-set values because of the sign extension.
 117.630 +  */
 117.631 +@@ -1641,6 +1655,47 @@
 117.632 +     */
 117.633 + #endif
 117.634 + 
 117.635 ++#ifdef PNG_APNG_SUPPORTED
 117.636 ++PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
 117.637 ++   png_uint_32 width, png_uint_32 height,
 117.638 ++   png_uint_32 x_offset, png_uint_32 y_offset,
 117.639 ++   png_uint_16 delay_num, png_uint_16 delay_den,
 117.640 ++   png_byte dispose_op, png_byte blend_op), PNG_EMPTY);
 117.641 ++
 117.642 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.643 ++PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr,
 117.644 ++   png_uint_32 length),PNG_EMPTY);
 117.645 ++PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr,
 117.646 ++   png_uint_32 length),PNG_EMPTY);
 117.647 ++PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr,
 117.648 ++   png_uint_32 length),PNG_EMPTY);
 117.649 ++PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY);
 117.650 ++PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
 117.651 ++   png_uint_32 length),PNG_EMPTY);
 117.652 ++PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
 117.653 ++PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
 117.654 ++   png_infop info_ptr),PNG_EMPTY);
 117.655 ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 117.656 ++PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY);
 117.657 ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 117.658 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.659 ++
 117.660 ++#ifdef PNG_WRITE_APNG_SUPPORTED
 117.661 ++PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
 117.662 ++   png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
 117.663 ++PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
 117.664 ++   png_uint_32 width, png_uint_32 height,
 117.665 ++   png_uint_32 x_offset, png_uint_32 y_offset,
 117.666 ++   png_uint_16 delay_num, png_uint_16 delay_den,
 117.667 ++   png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
 117.668 ++PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
 117.669 ++   png_const_bytep data, png_size_t length),PNG_EMPTY);
 117.670 ++PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
 117.671 ++PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
 117.672 ++   png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
 117.673 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
 117.674 ++#endif /* PNG_APNG_SUPPORTED */
 117.675 ++
 117.676 + /* Added at libpng version 1.4.0 */
 117.677 + #ifdef PNG_COLORSPACE_SUPPORTED
 117.678 + /* These internal functions are for maintaining the colorspace structure within
 117.679 +diff -Naru libpng-1.6.35.org/pngread.c libpng-1.6.35/pngread.c
 117.680 +--- libpng-1.6.35.org/pngread.c	2018-07-21 19:16:37.186143016 +0900
 117.681 ++++ libpng-1.6.35/pngread.c	2018-07-21 19:16:16.224355855 +0900
 117.682 +@@ -161,6 +161,9 @@
 117.683 + 
 117.684 +       else if (chunk_name == png_IDAT)
 117.685 +       {
 117.686 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.687 ++         png_have_info(png_ptr, info_ptr);
 117.688 ++#endif
 117.689 +          png_ptr->idat_size = length;
 117.690 +          break;
 117.691 +       }
 117.692 +@@ -255,6 +258,17 @@
 117.693 +          png_handle_iTXt(png_ptr, info_ptr, length);
 117.694 + #endif
 117.695 + 
 117.696 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.697 ++      else if (chunk_name == png_acTL)
 117.698 ++         png_handle_acTL(png_ptr, info_ptr, length);
 117.699 ++
 117.700 ++      else if (chunk_name == png_fcTL)
 117.701 ++         png_handle_fcTL(png_ptr, info_ptr, length);
 117.702 ++
 117.703 ++      else if (chunk_name == png_fdAT)
 117.704 ++         png_handle_fdAT(png_ptr, info_ptr, length);
 117.705 ++#endif
 117.706 ++
 117.707 +       else
 117.708 +          png_handle_unknown(png_ptr, info_ptr, length,
 117.709 +              PNG_HANDLE_CHUNK_AS_DEFAULT);
 117.710 +@@ -262,6 +276,72 @@
 117.711 + }
 117.712 + #endif /* SEQUENTIAL_READ */
 117.713 + 
 117.714 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.715 ++void PNGAPI
 117.716 ++png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
 117.717 ++{
 117.718 ++    png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
 117.719 ++
 117.720 ++    png_debug(0, "Reading frame head");
 117.721 ++
 117.722 ++    if (!(png_ptr->mode & PNG_HAVE_acTL))
 117.723 ++        png_error(png_ptr, "attempt to png_read_frame_head() but "
 117.724 ++                           "no acTL present");
 117.725 ++
 117.726 ++    /* do nothing for the main IDAT */
 117.727 ++    if (png_ptr->num_frames_read == 0)
 117.728 ++        return;
 117.729 ++
 117.730 ++    png_read_reset(png_ptr);
 117.731 ++    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 117.732 ++    png_ptr->mode &= ~PNG_HAVE_fcTL;
 117.733 ++
 117.734 ++    have_chunk_after_DAT = 0;
 117.735 ++    for (;;)
 117.736 ++    {
 117.737 ++        png_uint_32 length = png_read_chunk_header(png_ptr);
 117.738 ++
 117.739 ++        if (png_ptr->chunk_name == png_IDAT)
 117.740 ++        {
 117.741 ++            /* discard trailing IDATs for the first frame */
 117.742 ++            if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
 117.743 ++                png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
 117.744 ++            png_crc_finish(png_ptr, length);
 117.745 ++        }
 117.746 ++
 117.747 ++        else if (png_ptr->chunk_name == png_fcTL)
 117.748 ++        {
 117.749 ++            png_handle_fcTL(png_ptr, info_ptr, length);
 117.750 ++            have_chunk_after_DAT = 1;
 117.751 ++        }
 117.752 ++
 117.753 ++        else if (png_ptr->chunk_name == png_fdAT)
 117.754 ++        {
 117.755 ++            png_ensure_sequence_number(png_ptr, length);
 117.756 ++
 117.757 ++            /* discard trailing fdATs for frames other than the first */
 117.758 ++            if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
 117.759 ++                png_crc_finish(png_ptr, length - 4);
 117.760 ++            else if(png_ptr->mode & PNG_HAVE_fcTL)
 117.761 ++            {
 117.762 ++                png_ptr->idat_size = length - 4;
 117.763 ++                png_ptr->mode |= PNG_HAVE_IDAT;
 117.764 ++
 117.765 ++                break;
 117.766 ++            }
 117.767 ++            else
 117.768 ++                png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
 117.769 ++        }
 117.770 ++        else
 117.771 ++        {
 117.772 ++            png_warning(png_ptr, "Skipped (ignored) a chunk "
 117.773 ++                                 "between APNG chunks");
 117.774 ++            png_crc_finish(png_ptr, length);
 117.775 ++        }
 117.776 ++    }
 117.777 ++}
 117.778 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.779 ++
 117.780 + /* Optional call to update the users info_ptr structure */
 117.781 + void PNGAPI
 117.782 + png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
 117.783 +diff -Naru libpng-1.6.35.org/pngrutil.c libpng-1.6.35/pngrutil.c
 117.784 +--- libpng-1.6.35.org/pngrutil.c	2018-07-21 19:16:37.187143101 +0900
 117.785 ++++ libpng-1.6.35/pngrutil.c	2018-07-21 19:16:16.220355514 +0900
 117.786 +@@ -865,6 +865,11 @@
 117.787 +    filter_type = buf[11];
 117.788 +    interlace_type = buf[12];
 117.789 + 
 117.790 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.791 ++   png_ptr->first_frame_width = width;
 117.792 ++   png_ptr->first_frame_height = height;
 117.793 ++#endif
 117.794 ++
 117.795 +    /* Set internal variables */
 117.796 +    png_ptr->width = width;
 117.797 +    png_ptr->height = height;
 117.798 +@@ -2858,6 +2863,179 @@
 117.799 + }
 117.800 + #endif
 117.801 + 
 117.802 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.803 ++void /* PRIVATE */
 117.804 ++png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 117.805 ++{
 117.806 ++    png_byte data[8];
 117.807 ++    png_uint_32 num_frames;
 117.808 ++    png_uint_32 num_plays;
 117.809 ++    png_uint_32 didSet;
 117.810 ++
 117.811 ++    png_debug(1, "in png_handle_acTL");
 117.812 ++
 117.813 ++    if (!(png_ptr->mode & PNG_HAVE_IHDR))
 117.814 ++    {
 117.815 ++        png_error(png_ptr, "Missing IHDR before acTL");
 117.816 ++    }
 117.817 ++    else if (png_ptr->mode & PNG_HAVE_IDAT)
 117.818 ++    {
 117.819 ++        png_warning(png_ptr, "Invalid acTL after IDAT skipped");
 117.820 ++        png_crc_finish(png_ptr, length);
 117.821 ++        return;
 117.822 ++    }
 117.823 ++    else if (png_ptr->mode & PNG_HAVE_acTL)
 117.824 ++    {
 117.825 ++        png_warning(png_ptr, "Duplicate acTL skipped");
 117.826 ++        png_crc_finish(png_ptr, length);
 117.827 ++        return;
 117.828 ++    }
 117.829 ++    else if (length != 8)
 117.830 ++    {
 117.831 ++        png_warning(png_ptr, "acTL with invalid length skipped");
 117.832 ++        png_crc_finish(png_ptr, length);
 117.833 ++        return;
 117.834 ++    }
 117.835 ++
 117.836 ++    png_crc_read(png_ptr, data, 8);
 117.837 ++    png_crc_finish(png_ptr, 0);
 117.838 ++
 117.839 ++    num_frames = png_get_uint_31(png_ptr, data);
 117.840 ++    num_plays = png_get_uint_31(png_ptr, data + 4);
 117.841 ++
 117.842 ++    /* the set function will do error checking on num_frames */
 117.843 ++    didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
 117.844 ++    if(didSet)
 117.845 ++        png_ptr->mode |= PNG_HAVE_acTL;
 117.846 ++}
 117.847 ++
 117.848 ++void /* PRIVATE */
 117.849 ++png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 117.850 ++{
 117.851 ++    png_byte data[22];
 117.852 ++    png_uint_32 width;
 117.853 ++    png_uint_32 height;
 117.854 ++    png_uint_32 x_offset;
 117.855 ++    png_uint_32 y_offset;
 117.856 ++    png_uint_16 delay_num;
 117.857 ++    png_uint_16 delay_den;
 117.858 ++    png_byte dispose_op;
 117.859 ++    png_byte blend_op;
 117.860 ++
 117.861 ++    png_debug(1, "in png_handle_fcTL");
 117.862 ++
 117.863 ++    png_ensure_sequence_number(png_ptr, length);
 117.864 ++
 117.865 ++    if (!(png_ptr->mode & PNG_HAVE_IHDR))
 117.866 ++    {
 117.867 ++        png_error(png_ptr, "Missing IHDR before fcTL");
 117.868 ++    }
 117.869 ++    else if (png_ptr->mode & PNG_HAVE_IDAT)
 117.870 ++    {
 117.871 ++        /* for any frames other then the first this message may be misleading,
 117.872 ++        * but correct. PNG_HAVE_IDAT is unset before the frame head is read
 117.873 ++        * i can't think of a better message */
 117.874 ++        png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
 117.875 ++        png_crc_finish(png_ptr, length-4);
 117.876 ++        return;
 117.877 ++    }
 117.878 ++    else if (png_ptr->mode & PNG_HAVE_fcTL)
 117.879 ++    {
 117.880 ++        png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
 117.881 ++        png_crc_finish(png_ptr, length-4);
 117.882 ++        return;
 117.883 ++    }
 117.884 ++    else if (length != 26)
 117.885 ++    {
 117.886 ++        png_warning(png_ptr, "fcTL with invalid length skipped");
 117.887 ++        png_crc_finish(png_ptr, length-4);
 117.888 ++        return;
 117.889 ++    }
 117.890 ++
 117.891 ++    png_crc_read(png_ptr, data, 22);
 117.892 ++    png_crc_finish(png_ptr, 0);
 117.893 ++
 117.894 ++    width = png_get_uint_31(png_ptr, data);
 117.895 ++    height = png_get_uint_31(png_ptr, data + 4);
 117.896 ++    x_offset = png_get_uint_31(png_ptr, data + 8);
 117.897 ++    y_offset = png_get_uint_31(png_ptr, data + 12);
 117.898 ++    delay_num = png_get_uint_16(data + 16);
 117.899 ++    delay_den = png_get_uint_16(data + 18);
 117.900 ++    dispose_op = data[20];
 117.901 ++    blend_op = data[21];
 117.902 ++
 117.903 ++    if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
 117.904 ++    {
 117.905 ++        png_warning(png_ptr, "fcTL for the first frame must have zero offset");
 117.906 ++        return;
 117.907 ++    }
 117.908 ++
 117.909 ++    if (info_ptr != NULL)
 117.910 ++    {
 117.911 ++        if (png_ptr->num_frames_read == 0 &&
 117.912 ++            (width != info_ptr->width || height != info_ptr->height))
 117.913 ++        {
 117.914 ++            png_warning(png_ptr, "size in first frame's fcTL must match "
 117.915 ++                               "the size in IHDR");
 117.916 ++            return;
 117.917 ++        }
 117.918 ++
 117.919 ++        /* The set function will do more error checking */
 117.920 ++        png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
 117.921 ++                                x_offset, y_offset, delay_num, delay_den,
 117.922 ++                                dispose_op, blend_op);
 117.923 ++
 117.924 ++        png_read_reinit(png_ptr, info_ptr);
 117.925 ++
 117.926 ++        png_ptr->mode |= PNG_HAVE_fcTL;
 117.927 ++    }
 117.928 ++}
 117.929 ++
 117.930 ++void /* PRIVATE */
 117.931 ++png_have_info(png_structp png_ptr, png_infop info_ptr)
 117.932 ++{
 117.933 ++    if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
 117.934 ++    {
 117.935 ++        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
 117.936 ++        info_ptr->num_frames++;
 117.937 ++    }
 117.938 ++}
 117.939 ++
 117.940 ++void /* PRIVATE */
 117.941 ++png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 117.942 ++{
 117.943 ++    png_ensure_sequence_number(png_ptr, length);
 117.944 ++
 117.945 ++    /* This function is only called from png_read_end(), png_read_info(),
 117.946 ++    * and png_push_read_chunk() which means that:
 117.947 ++    * - the user doesn't want to read this frame
 117.948 ++    * - or this is an out-of-place fdAT
 117.949 ++    * in either case it is safe to ignore the chunk with a warning */
 117.950 ++    png_warning(png_ptr, "ignoring fdAT chunk");
 117.951 ++    png_crc_finish(png_ptr, length - 4);
 117.952 ++    PNG_UNUSED(info_ptr)
 117.953 ++}
 117.954 ++
 117.955 ++void /* PRIVATE */
 117.956 ++png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
 117.957 ++{
 117.958 ++    png_byte data[4];
 117.959 ++    png_uint_32 sequence_number;
 117.960 ++
 117.961 ++    if (length < 4)
 117.962 ++        png_error(png_ptr, "invalid fcTL or fdAT chunk found");
 117.963 ++
 117.964 ++    png_crc_read(png_ptr, data, 4);
 117.965 ++    sequence_number = png_get_uint_31(png_ptr, data);
 117.966 ++
 117.967 ++    if (sequence_number != png_ptr->next_seq_num)
 117.968 ++        png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
 117.969 ++                           "number found");
 117.970 ++
 117.971 ++    png_ptr->next_seq_num++;
 117.972 ++}
 117.973 ++#endif /* PNG_READ_APNG_SUPPORTED */
 117.974 ++
 117.975 + #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 117.976 + /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
 117.977 + static int
 117.978 +@@ -4166,7 +4344,38 @@
 117.979 +       {
 117.980 +          uInt avail_in;
 117.981 +          png_bytep buffer;
 117.982 ++#ifdef PNG_READ_APNG_SUPPORTED
 117.983 ++         png_uint_32 bytes_to_skip = 0;
 117.984 ++
 117.985 ++         while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
 117.986 ++         {
 117.987 ++            png_crc_finish(png_ptr, bytes_to_skip);
 117.988 ++            bytes_to_skip = 0;
 117.989 + 
 117.990 ++            png_ptr->idat_size = png_read_chunk_header(png_ptr);
 117.991 ++            if (png_ptr->num_frames_read == 0)
 117.992 ++            {
 117.993 ++               if (png_ptr->chunk_name != png_IDAT)
 117.994 ++                  png_error(png_ptr, "Not enough image data");
 117.995 ++            }
 117.996 ++            else
 117.997 ++            {
 117.998 ++               if (png_ptr->chunk_name == png_IEND)
 117.999 ++                  png_error(png_ptr, "Not enough image data");
117.1000 ++               if (png_ptr->chunk_name != png_fdAT)
117.1001 ++               {
117.1002 ++                  png_warning(png_ptr, "Skipped (ignored) a chunk "
117.1003 ++                                       "between APNG chunks");
117.1004 ++                  bytes_to_skip = png_ptr->idat_size;
117.1005 ++                  continue;
117.1006 ++               }
117.1007 ++
117.1008 ++               png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
117.1009 ++
117.1010 ++               png_ptr->idat_size -= 4;
117.1011 ++            }
117.1012 ++         }
117.1013 ++#else
117.1014 +          while (png_ptr->idat_size == 0)
117.1015 +          {
117.1016 +             png_crc_finish(png_ptr, 0);
117.1017 +@@ -4178,7 +4387,7 @@
117.1018 +             if (png_ptr->chunk_name != png_IDAT)
117.1019 +                png_error(png_ptr, "Not enough image data");
117.1020 +          }
117.1021 +-
117.1022 ++#endif /* PNG_READ_APNG_SUPPORTED */
117.1023 +          avail_in = png_ptr->IDAT_read_size;
117.1024 + 
117.1025 +          if (avail_in > png_ptr->idat_size)
117.1026 +@@ -4241,6 +4450,9 @@
117.1027 + 
117.1028 +          png_ptr->mode |= PNG_AFTER_IDAT;
117.1029 +          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
117.1030 ++#ifdef PNG_READ_APNG_SUPPORTED
117.1031 ++         png_ptr->num_frames_read++;
117.1032 ++#endif
117.1033 + 
117.1034 +          if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
117.1035 +             png_chunk_benign_error(png_ptr, "Extra compressed data");
117.1036 +@@ -4679,4 +4891,80 @@
117.1037 + 
117.1038 +    png_ptr->flags |= PNG_FLAG_ROW_INIT;
117.1039 + }
117.1040 ++
117.1041 ++#ifdef PNG_READ_APNG_SUPPORTED
117.1042 ++/* This function is to be called after the main IDAT set has been read and
117.1043 ++ * before a new IDAT is read. It resets some parts of png_ptr
117.1044 ++ * to make them usable by the read functions again */
117.1045 ++void /* PRIVATE */
117.1046 ++png_read_reset(png_structp png_ptr)
117.1047 ++{
117.1048 ++    png_ptr->mode &= ~PNG_HAVE_IDAT;
117.1049 ++    png_ptr->mode &= ~PNG_AFTER_IDAT;
117.1050 ++    png_ptr->row_number = 0;
117.1051 ++    png_ptr->pass = 0;
117.1052 ++}
117.1053 ++
117.1054 ++void /* PRIVATE */
117.1055 ++png_read_reinit(png_structp png_ptr, png_infop info_ptr)
117.1056 ++{
117.1057 ++    png_ptr->width = info_ptr->next_frame_width;
117.1058 ++    png_ptr->height = info_ptr->next_frame_height;
117.1059 ++    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
117.1060 ++    png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
117.1061 ++        png_ptr->width);
117.1062 ++    if (png_ptr->prev_row)
117.1063 ++        memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
117.1064 ++}
117.1065 ++
117.1066 ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
117.1067 ++/* same as png_read_reset() but for the progressive reader */
117.1068 ++void /* PRIVATE */
117.1069 ++png_progressive_read_reset(png_structp png_ptr)
117.1070 ++{
117.1071 ++#ifdef PNG_READ_INTERLACING_SUPPORTED
117.1072 ++   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
117.1073 ++
117.1074 ++   /* Start of interlace block */
117.1075 ++    const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
117.1076 ++
117.1077 ++    /* Offset to next interlace block */
117.1078 ++    const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
117.1079 ++
117.1080 ++    /* Start of interlace block in the y direction */
117.1081 ++    const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
117.1082 ++
117.1083 ++    /* Offset to next interlace block in the y direction */
117.1084 ++    const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
117.1085 ++
117.1086 ++    if (png_ptr->interlaced)
117.1087 ++    {
117.1088 ++        if (!(png_ptr->transformations & PNG_INTERLACE))
117.1089 ++            png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
117.1090 ++                                png_pass_ystart[0]) / png_pass_yinc[0];
117.1091 ++        else
117.1092 ++            png_ptr->num_rows = png_ptr->height;
117.1093 ++
117.1094 ++        png_ptr->iwidth = (png_ptr->width +
117.1095 ++                           png_pass_inc[png_ptr->pass] - 1 -
117.1096 ++                           png_pass_start[png_ptr->pass]) /
117.1097 ++                           png_pass_inc[png_ptr->pass];
117.1098 ++    }
117.1099 ++    else
117.1100 ++#endif /* PNG_READ_INTERLACING_SUPPORTED */
117.1101 ++    {
117.1102 ++        png_ptr->num_rows = png_ptr->height;
117.1103 ++        png_ptr->iwidth = png_ptr->width;
117.1104 ++    }
117.1105 ++    png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
117.1106 ++    if (inflateReset(&(png_ptr->zstream)) != Z_OK)
117.1107 ++        png_error(png_ptr, "inflateReset failed");
117.1108 ++    png_ptr->zstream.avail_in = 0;
117.1109 ++    png_ptr->zstream.next_in = 0;
117.1110 ++    png_ptr->zstream.next_out = png_ptr->row_buf;
117.1111 ++    png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
117.1112 ++        png_ptr->iwidth) + 1;
117.1113 ++}
117.1114 ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
117.1115 ++#endif /* PNG_READ_APNG_SUPPORTED */
117.1116 + #endif /* READ */
117.1117 +diff -Naru libpng-1.6.35.org/pngset.c libpng-1.6.35/pngset.c
117.1118 +--- libpng-1.6.35.org/pngset.c	2018-07-21 19:16:37.188143186 +0900
117.1119 ++++ libpng-1.6.35/pngset.c	2018-07-21 19:16:16.256358584 +0900
117.1120 +@@ -288,6 +288,11 @@
117.1121 +    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
117.1122 + 
117.1123 +    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
117.1124 ++
117.1125 ++#ifdef PNG_APNG_SUPPORTED
117.1126 ++   /* for non-animated png. this may be overwritten from an acTL chunk later */
117.1127 ++   info_ptr->num_frames = 1;
117.1128 ++#endif
117.1129 + }
117.1130 + 
117.1131 + #ifdef PNG_oFFs_SUPPORTED
117.1132 +@@ -1158,6 +1163,147 @@
117.1133 + }
117.1134 + #endif /* sPLT */
117.1135 + 
117.1136 ++#ifdef PNG_APNG_SUPPORTED
117.1137 ++png_uint_32 PNGAPI
117.1138 ++png_set_acTL(png_structp png_ptr, png_infop info_ptr,
117.1139 ++    png_uint_32 num_frames, png_uint_32 num_plays)
117.1140 ++{
117.1141 ++    png_debug1(1, "in %s storage function", "acTL");
117.1142 ++
117.1143 ++    if (png_ptr == NULL || info_ptr == NULL)
117.1144 ++    {
117.1145 ++        png_warning(png_ptr,
117.1146 ++                    "Call to png_set_acTL() with NULL png_ptr "
117.1147 ++                    "or info_ptr ignored");
117.1148 ++        return (0);
117.1149 ++    }
117.1150 ++    if (num_frames == 0)
117.1151 ++    {
117.1152 ++        png_warning(png_ptr,
117.1153 ++                    "Ignoring attempt to set acTL with num_frames zero");
117.1154 ++        return (0);
117.1155 ++    }
117.1156 ++    if (num_frames > PNG_UINT_31_MAX)
117.1157 ++    {
117.1158 ++        png_warning(png_ptr,
117.1159 ++                    "Ignoring attempt to set acTL with num_frames > 2^31-1");
117.1160 ++        return (0);
117.1161 ++    }
117.1162 ++    if (num_plays > PNG_UINT_31_MAX)
117.1163 ++    {
117.1164 ++        png_warning(png_ptr,
117.1165 ++                    "Ignoring attempt to set acTL with num_plays "
117.1166 ++                    "> 2^31-1");
117.1167 ++        return (0);
117.1168 ++    }
117.1169 ++
117.1170 ++    info_ptr->num_frames = num_frames;
117.1171 ++    info_ptr->num_plays = num_plays;
117.1172 ++
117.1173 ++    info_ptr->valid |= PNG_INFO_acTL;
117.1174 ++
117.1175 ++    return (1);
117.1176 ++}
117.1177 ++
117.1178 ++/* delay_num and delay_den can hold any 16-bit values including zero */
117.1179 ++png_uint_32 PNGAPI
117.1180 ++png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
117.1181 ++    png_uint_32 width, png_uint_32 height,
117.1182 ++    png_uint_32 x_offset, png_uint_32 y_offset,
117.1183 ++    png_uint_16 delay_num, png_uint_16 delay_den,
117.1184 ++    png_byte dispose_op, png_byte blend_op)
117.1185 ++{
117.1186 ++    png_debug1(1, "in %s storage function", "fcTL");
117.1187 ++
117.1188 ++    if (png_ptr == NULL || info_ptr == NULL)
117.1189 ++    {
117.1190 ++        png_warning(png_ptr,
117.1191 ++                    "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
117.1192 ++                    "ignored");
117.1193 ++        return (0);
117.1194 ++    }
117.1195 ++
117.1196 ++    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
117.1197 ++                             delay_num, delay_den, dispose_op, blend_op);
117.1198 ++
117.1199 ++    if (blend_op == PNG_BLEND_OP_OVER)
117.1200 ++    {
117.1201 ++        if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
117.1202 ++            !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
117.1203 ++        {
117.1204 ++          png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
117.1205 ++                               "and wasteful for opaque images, ignored");
117.1206 ++          blend_op = PNG_BLEND_OP_SOURCE;
117.1207 ++        }
117.1208 ++    }
117.1209 ++
117.1210 ++    info_ptr->next_frame_width = width;
117.1211 ++    info_ptr->next_frame_height = height;
117.1212 ++    info_ptr->next_frame_x_offset = x_offset;
117.1213 ++    info_ptr->next_frame_y_offset = y_offset;
117.1214 ++    info_ptr->next_frame_delay_num = delay_num;
117.1215 ++    info_ptr->next_frame_delay_den = delay_den;
117.1216 ++    info_ptr->next_frame_dispose_op = dispose_op;
117.1217 ++    info_ptr->next_frame_blend_op = blend_op;
117.1218 ++
117.1219 ++    info_ptr->valid |= PNG_INFO_fcTL;
117.1220 ++
117.1221 ++    return (1);
117.1222 ++}
117.1223 ++
117.1224 ++void /* PRIVATE */
117.1225 ++png_ensure_fcTL_is_valid(png_structp png_ptr,
117.1226 ++    png_uint_32 width, png_uint_32 height,
117.1227 ++    png_uint_32 x_offset, png_uint_32 y_offset,
117.1228 ++    png_uint_16 delay_num, png_uint_16 delay_den,
117.1229 ++    png_byte dispose_op, png_byte blend_op)
117.1230 ++{
117.1231 ++    if (width == 0 || width > PNG_UINT_31_MAX)
117.1232 ++        png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
117.1233 ++    if (height == 0 || height > PNG_UINT_31_MAX)
117.1234 ++        png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
117.1235 ++    if (x_offset > PNG_UINT_31_MAX)
117.1236 ++        png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
117.1237 ++    if (y_offset > PNG_UINT_31_MAX)
117.1238 ++        png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
117.1239 ++    if (width + x_offset > png_ptr->first_frame_width ||
117.1240 ++        height + y_offset > png_ptr->first_frame_height)
117.1241 ++        png_error(png_ptr, "dimensions of a frame are greater than"
117.1242 ++                           "the ones in IHDR");
117.1243 ++
117.1244 ++    if (dispose_op != PNG_DISPOSE_OP_NONE &&
117.1245 ++        dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
117.1246 ++        dispose_op != PNG_DISPOSE_OP_PREVIOUS)
117.1247 ++        png_error(png_ptr, "invalid dispose_op in fcTL");
117.1248 ++
117.1249 ++    if (blend_op != PNG_BLEND_OP_SOURCE &&
117.1250 ++        blend_op != PNG_BLEND_OP_OVER)
117.1251 ++        png_error(png_ptr, "invalid blend_op in fcTL");
117.1252 ++
117.1253 ++    PNG_UNUSED(delay_num)
117.1254 ++    PNG_UNUSED(delay_den)
117.1255 ++}
117.1256 ++
117.1257 ++png_uint_32 PNGAPI
117.1258 ++png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
117.1259 ++                              png_byte is_hidden)
117.1260 ++{
117.1261 ++    png_debug(1, "in png_first_frame_is_hidden()");
117.1262 ++
117.1263 ++    if (png_ptr == NULL)
117.1264 ++        return 0;
117.1265 ++
117.1266 ++    if (is_hidden)
117.1267 ++        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
117.1268 ++    else
117.1269 ++        png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
117.1270 ++
117.1271 ++    PNG_UNUSED(info_ptr)
117.1272 ++
117.1273 ++    return 1;
117.1274 ++}
117.1275 ++#endif /* PNG_APNG_SUPPORTED */
117.1276 ++
117.1277 + #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
117.1278 + static png_byte
117.1279 + check_location(png_const_structrp png_ptr, int location)
117.1280 +diff -Naru libpng-1.6.35.org/pngstruct.h libpng-1.6.35/pngstruct.h
117.1281 +--- libpng-1.6.35.org/pngstruct.h	2018-07-21 19:16:37.188143186 +0900
117.1282 ++++ libpng-1.6.35/pngstruct.h	2018-07-21 19:16:16.214355003 +0900
117.1283 +@@ -403,6 +403,27 @@
117.1284 +    png_byte filter_type;
117.1285 + #endif
117.1286 + 
117.1287 ++#ifdef PNG_APNG_SUPPORTED
117.1288 ++   png_uint_32 apng_flags;
117.1289 ++   png_uint_32 next_seq_num;         /* next fcTL/fdAT chunk sequence number */
117.1290 ++   png_uint_32 first_frame_width;
117.1291 ++   png_uint_32 first_frame_height;
117.1292 ++
117.1293 ++#ifdef PNG_READ_APNG_SUPPORTED
117.1294 ++   png_uint_32 num_frames_read;      /* incremented after all image data of */
117.1295 ++                                     /* a frame is read */
117.1296 ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
117.1297 ++   png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
117.1298 ++   png_progressive_frame_ptr frame_end_fn;  /* frame data read callback */
117.1299 ++#endif
117.1300 ++#endif
117.1301 ++
117.1302 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1303 ++   png_uint_32 num_frames_to_write;
117.1304 ++   png_uint_32 num_frames_written;
117.1305 ++#endif
117.1306 ++#endif /* PNG_APNG_SUPPORTED */
117.1307 ++
117.1308 + /* New members added in libpng-1.2.0 */
117.1309 + 
117.1310 + /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
117.1311 +diff -Naru libpng-1.6.35.org/pngtest.c libpng-1.6.35/pngtest.c
117.1312 +--- libpng-1.6.35.org/pngtest.c	2018-07-21 19:16:37.188143186 +0900
117.1313 ++++ libpng-1.6.35/pngtest.c	2018-07-21 19:16:16.213354917 +0900
117.1314 +@@ -875,6 +875,10 @@
117.1315 +    volatile int num_passes;
117.1316 +    int pass;
117.1317 +    int bit_depth, color_type;
117.1318 ++#ifdef PNG_APNG_SUPPORTED
117.1319 ++   png_uint_32 num_frames;
117.1320 ++   png_uint_32 num_plays;
117.1321 ++#endif
117.1322 + 
117.1323 +    row_buf = NULL;
117.1324 +    error_parameters.file_name = inname;
117.1325 +@@ -1381,6 +1385,22 @@
117.1326 +       }
117.1327 +    }
117.1328 + #endif
117.1329 ++
117.1330 ++#ifdef PNG_APNG_SUPPORTED
117.1331 ++   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
117.1332 ++   {
117.1333 ++      if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays))
117.1334 ++      {
117.1335 ++         png_byte is_hidden;
117.1336 ++         pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)",
117.1337 ++                    num_frames, num_plays);
117.1338 ++         png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays);
117.1339 ++         is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr);
117.1340 ++         png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden);
117.1341 ++      }
117.1342 ++   }
117.1343 ++#endif
117.1344 ++
117.1345 + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
117.1346 +    {
117.1347 +       png_unknown_chunkp unknowns;
117.1348 +@@ -1461,6 +1481,110 @@
117.1349 +    t_misc += (t_stop - t_start);
117.1350 +    t_start = t_stop;
117.1351 + #endif
117.1352 ++#ifdef PNG_APNG_SUPPORTED
117.1353 ++   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
117.1354 ++   {
117.1355 ++      png_uint_32 frame;
117.1356 ++      for (frame = 0; frame < num_frames; frame++)
117.1357 ++      {
117.1358 ++         png_uint_32 frame_width;
117.1359 ++         png_uint_32 frame_height;
117.1360 ++         png_uint_32 x_offset;
117.1361 ++         png_uint_32 y_offset;
117.1362 ++         png_uint_16 delay_num;
117.1363 ++         png_uint_16 delay_den;
117.1364 ++         png_byte dispose_op;
117.1365 ++         png_byte blend_op;
117.1366 ++         png_read_frame_head(read_ptr, read_info_ptr);
117.1367 ++         if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL))
117.1368 ++         {
117.1369 ++            png_get_next_frame_fcTL(read_ptr, read_info_ptr,
117.1370 ++                                    &frame_width, &frame_height,
117.1371 ++                                    &x_offset, &y_offset,
117.1372 ++                                    &delay_num, &delay_den,
117.1373 ++                                    &dispose_op, &blend_op);
117.1374 ++         }
117.1375 ++         else
117.1376 ++         {
117.1377 ++            frame_width = width;
117.1378 ++            frame_height = height;
117.1379 ++            x_offset = 0;
117.1380 ++            y_offset = 0;
117.1381 ++            delay_num = 1;
117.1382 ++            delay_den = 1;
117.1383 ++            dispose_op = PNG_DISPOSE_OP_NONE;
117.1384 ++            blend_op = PNG_BLEND_OP_SOURCE;
117.1385 ++         }
117.1386 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1387 ++         png_write_frame_head(write_ptr, write_info_ptr, (png_bytepp)&row_buf,
117.1388 ++                              frame_width, frame_height,
117.1389 ++                              x_offset, y_offset,
117.1390 ++                              delay_num, delay_den,
117.1391 ++                              dispose_op, blend_op);
117.1392 ++#endif
117.1393 ++         for (pass = 0; pass < num_passes; pass++)
117.1394 ++         {
117.1395 ++#           ifdef calc_pass_height
117.1396 ++               png_uint_32 pass_height;
117.1397 ++
117.1398 ++               if (num_passes == 7) /* interlaced */
117.1399 ++               {
117.1400 ++                  if (PNG_PASS_COLS(frame_width, pass) > 0)
117.1401 ++                     pass_height = PNG_PASS_ROWS(frame_height, pass);
117.1402 ++
117.1403 ++                  else
117.1404 ++                     pass_height = 0;
117.1405 ++               }
117.1406 ++
117.1407 ++               else /* not interlaced */
117.1408 ++                  pass_height = frame_height;
117.1409 ++#           else
117.1410 ++#              define pass_height frame_height
117.1411 ++#           endif
117.1412 ++
117.1413 ++            pngtest_debug1("Writing row data for pass %d", pass);
117.1414 ++            for (y = 0; y < pass_height; y++)
117.1415 ++            {
117.1416 ++#ifndef SINGLE_ROWBUF_ALLOC
117.1417 ++               pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
117.1418 ++
117.1419 ++               row_buf = (png_bytep)png_malloc(read_ptr,
117.1420 ++                  png_get_rowbytes(read_ptr, read_info_ptr));
117.1421 ++
117.1422 ++               pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
117.1423 ++                  (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
117.1424 ++
117.1425 ++#endif /* !SINGLE_ROWBUF_ALLOC */
117.1426 ++               png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
117.1427 ++
117.1428 ++#ifdef PNG_WRITE_SUPPORTED
117.1429 ++#ifdef PNGTEST_TIMING
117.1430 ++               t_stop = (float)clock();
117.1431 ++               t_decode += (t_stop - t_start);
117.1432 ++               t_start = t_stop;
117.1433 ++#endif
117.1434 ++               png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
117.1435 ++#ifdef PNGTEST_TIMING
117.1436 ++               t_stop = (float)clock();
117.1437 ++               t_encode += (t_stop - t_start);
117.1438 ++               t_start = t_stop;
117.1439 ++#endif
117.1440 ++#endif /* PNG_WRITE_SUPPORTED */
117.1441 ++
117.1442 ++#ifndef SINGLE_ROWBUF_ALLOC
117.1443 ++               pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
117.1444 ++               png_free(read_ptr, row_buf);
117.1445 ++               row_buf = NULL;
117.1446 ++#endif /* !SINGLE_ROWBUF_ALLOC */
117.1447 ++            }
117.1448 ++         }
117.1449 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1450 ++         png_write_frame_tail(write_ptr, write_info_ptr);
117.1451 ++#endif
117.1452 ++      }
117.1453 ++   }
117.1454 ++   else
117.1455 ++#endif
117.1456 +    for (pass = 0; pass < num_passes; pass++)
117.1457 +    {
117.1458 + #     ifdef calc_pass_height
117.1459 +diff -Naru libpng-1.6.35.org/pngwrite.c libpng-1.6.35/pngwrite.c
117.1460 +--- libpng-1.6.35.org/pngwrite.c	2018-07-21 19:16:37.188143186 +0900
117.1461 ++++ libpng-1.6.35/pngwrite.c	2018-07-21 19:16:16.211354747 +0900
117.1462 +@@ -128,6 +128,10 @@
117.1463 +        * the application continues writing the PNG.  So check the 'invalid'
117.1464 +        * flag here too.
117.1465 +        */
117.1466 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1467 ++      if (info_ptr->valid & PNG_INFO_acTL)
117.1468 ++         png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
117.1469 ++#endif
117.1470 + #ifdef PNG_GAMMA_SUPPORTED
117.1471 + #  ifdef PNG_WRITE_gAMA_SUPPORTED
117.1472 +       if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
117.1473 +@@ -370,6 +374,11 @@
117.1474 +       png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
117.1475 + #endif
117.1476 + 
117.1477 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1478 ++   if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
117.1479 ++      png_error(png_ptr, "Not enough frames written");
117.1480 ++#endif
117.1481 ++
117.1482 +    /* See if user wants us to write information chunks */
117.1483 +    if (info_ptr != NULL)
117.1484 +    {
117.1485 +@@ -1461,6 +1470,43 @@
117.1486 + }
117.1487 + #endif
117.1488 + 
117.1489 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1490 ++void PNGAPI
117.1491 ++png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
117.1492 ++    png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
117.1493 ++    png_uint_32 x_offset, png_uint_32 y_offset,
117.1494 ++    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
117.1495 ++    png_byte blend_op)
117.1496 ++{
117.1497 ++    png_debug(1, "in png_write_frame_head");
117.1498 ++
117.1499 ++    /* there is a chance this has been set after png_write_info was called,
117.1500 ++    * so it would be set but not written. is there a way to be sure? */
117.1501 ++    if (!(info_ptr->valid & PNG_INFO_acTL))
117.1502 ++        png_error(png_ptr, "png_write_frame_head(): acTL not set");
117.1503 ++
117.1504 ++    png_write_reset(png_ptr);
117.1505 ++
117.1506 ++    png_write_reinit(png_ptr, info_ptr, width, height);
117.1507 ++
117.1508 ++    if ( !(png_ptr->num_frames_written == 0 &&
117.1509 ++           (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
117.1510 ++        png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
117.1511 ++                       delay_num, delay_den, dispose_op, blend_op);
117.1512 ++
117.1513 ++    PNG_UNUSED(row_pointers)
117.1514 ++}
117.1515 ++
117.1516 ++void PNGAPI
117.1517 ++png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
117.1518 ++{
117.1519 ++    png_debug(1, "in png_write_frame_tail");
117.1520 ++
117.1521 ++    png_ptr->num_frames_written++;
117.1522 ++
117.1523 ++    PNG_UNUSED(info_ptr)
117.1524 ++}
117.1525 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
117.1526 + 
117.1527 + #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
117.1528 + /* Initialize the write structure - general purpose utility. */
117.1529 +diff -Naru libpng-1.6.35.org/pngwutil.c libpng-1.6.35/pngwutil.c
117.1530 +--- libpng-1.6.35.org/pngwutil.c	2018-07-21 19:16:37.189143271 +0900
117.1531 ++++ libpng-1.6.35/pngwutil.c	2018-07-21 19:16:16.303362592 +0900
117.1532 +@@ -821,6 +821,11 @@
117.1533 +    /* Write the chunk */
117.1534 +    png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
117.1535 + 
117.1536 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1537 ++   png_ptr->first_frame_width = width;
117.1538 ++   png_ptr->first_frame_height = height;
117.1539 ++#endif
117.1540 ++
117.1541 +    if ((png_ptr->do_filter) == PNG_NO_FILTERS)
117.1542 +    {
117.1543 +       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
117.1544 +@@ -1002,8 +1007,17 @@
117.1545 +                optimize_cmf(data, png_image_size(png_ptr));
117.1546 + #endif
117.1547 + 
117.1548 +-         if (size > 0)
117.1549 +-            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
117.1550 ++            if (size > 0)
117.1551 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1552 ++            {
117.1553 ++               if (png_ptr->num_frames_written == 0)
117.1554 ++#endif
117.1555 ++               png_write_complete_chunk(png_ptr, png_IDAT, data, size);
117.1556 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1557 ++               else
117.1558 ++                  png_write_fdAT(png_ptr, data, size);
117.1559 ++            }
117.1560 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
117.1561 +          png_ptr->mode |= PNG_HAVE_IDAT;
117.1562 + 
117.1563 +          png_ptr->zstream.next_out = data;
117.1564 +@@ -1050,7 +1064,17 @@
117.1565 + #endif
117.1566 + 
117.1567 +          if (size > 0)
117.1568 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1569 ++         {
117.1570 ++            if (png_ptr->num_frames_written == 0)
117.1571 ++#endif
117.1572 +             png_write_complete_chunk(png_ptr, png_IDAT, data, size);
117.1573 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1574 ++            else
117.1575 ++               png_write_fdAT(png_ptr, data, size);
117.1576 ++         }
117.1577 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
117.1578 ++
117.1579 +          png_ptr->zstream.avail_out = 0;
117.1580 +          png_ptr->zstream.next_out = NULL;
117.1581 +          png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
117.1582 +@@ -1885,6 +1909,82 @@
117.1583 + }
117.1584 + #endif
117.1585 + 
117.1586 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1587 ++void /* PRIVATE */
117.1588 ++png_write_acTL(png_structp png_ptr,
117.1589 ++    png_uint_32 num_frames, png_uint_32 num_plays)
117.1590 ++{
117.1591 ++    png_byte buf[8];
117.1592 ++
117.1593 ++    png_debug(1, "in png_write_acTL");
117.1594 ++
117.1595 ++    png_ptr->num_frames_to_write = num_frames;
117.1596 ++
117.1597 ++    if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
117.1598 ++        num_frames--;
117.1599 ++
117.1600 ++    png_save_uint_32(buf, num_frames);
117.1601 ++    png_save_uint_32(buf + 4, num_plays);
117.1602 ++
117.1603 ++    png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
117.1604 ++}
117.1605 ++
117.1606 ++void /* PRIVATE */
117.1607 ++png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
117.1608 ++    png_uint_32 x_offset, png_uint_32 y_offset,
117.1609 ++    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
117.1610 ++    png_byte blend_op)
117.1611 ++{
117.1612 ++    png_byte buf[26];
117.1613 ++
117.1614 ++    png_debug(1, "in png_write_fcTL");
117.1615 ++
117.1616 ++    if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
117.1617 ++        png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
117.1618 ++    if (png_ptr->num_frames_written == 0 &&
117.1619 ++        (width != png_ptr->first_frame_width ||
117.1620 ++         height != png_ptr->first_frame_height))
117.1621 ++        png_error(png_ptr, "width and/or height in the first frame's fcTL "
117.1622 ++                           "don't match the ones in IHDR");
117.1623 ++
117.1624 ++    /* more error checking */
117.1625 ++    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
117.1626 ++                             delay_num, delay_den, dispose_op, blend_op);
117.1627 ++
117.1628 ++    png_save_uint_32(buf, png_ptr->next_seq_num);
117.1629 ++    png_save_uint_32(buf + 4, width);
117.1630 ++    png_save_uint_32(buf + 8, height);
117.1631 ++    png_save_uint_32(buf + 12, x_offset);
117.1632 ++    png_save_uint_32(buf + 16, y_offset);
117.1633 ++    png_save_uint_16(buf + 20, delay_num);
117.1634 ++    png_save_uint_16(buf + 22, delay_den);
117.1635 ++    buf[24] = dispose_op;
117.1636 ++    buf[25] = blend_op;
117.1637 ++
117.1638 ++    png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
117.1639 ++
117.1640 ++    png_ptr->next_seq_num++;
117.1641 ++}
117.1642 ++
117.1643 ++void /* PRIVATE */
117.1644 ++png_write_fdAT(png_structp png_ptr,
117.1645 ++    png_const_bytep data, png_size_t length)
117.1646 ++{
117.1647 ++    png_byte buf[4];
117.1648 ++
117.1649 ++    png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
117.1650 ++
117.1651 ++    png_save_uint_32(buf, png_ptr->next_seq_num);
117.1652 ++    png_write_chunk_data(png_ptr, buf, 4);
117.1653 ++
117.1654 ++    png_write_chunk_data(png_ptr, data, length);
117.1655 ++
117.1656 ++    png_write_chunk_end(png_ptr);
117.1657 ++
117.1658 ++    png_ptr->next_seq_num++;
117.1659 ++}
117.1660 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
117.1661 ++
117.1662 + /* Initializes the row writing capability of libpng */
117.1663 + void /* PRIVATE */
117.1664 + png_write_start_row(png_structrp png_ptr)
117.1665 +@@ -2778,4 +2878,39 @@
117.1666 +    }
117.1667 + #endif /* WRITE_FLUSH */
117.1668 + }
117.1669 ++
117.1670 ++#ifdef PNG_WRITE_APNG_SUPPORTED
117.1671 ++void /* PRIVATE */
117.1672 ++png_write_reset(png_structp png_ptr)
117.1673 ++{
117.1674 ++    png_ptr->row_number = 0;
117.1675 ++    png_ptr->pass = 0;
117.1676 ++    png_ptr->mode &= ~PNG_HAVE_IDAT;
117.1677 ++}
117.1678 ++
117.1679 ++void /* PRIVATE */
117.1680 ++png_write_reinit(png_structp png_ptr, png_infop info_ptr,
117.1681 ++                 png_uint_32 width, png_uint_32 height)
117.1682 ++{
117.1683 ++    if (png_ptr->num_frames_written == 0 &&
117.1684 ++        (width != png_ptr->first_frame_width ||
117.1685 ++         height != png_ptr->first_frame_height))
117.1686 ++        png_error(png_ptr, "width and/or height in the first frame's fcTL "
117.1687 ++                           "don't match the ones in IHDR");
117.1688 ++    if (width > png_ptr->first_frame_width ||
117.1689 ++        height > png_ptr->first_frame_height)
117.1690 ++        png_error(png_ptr, "width and/or height for a frame greater than"
117.1691 ++                           "the ones in IHDR");
117.1692 ++
117.1693 ++    png_set_IHDR(png_ptr, info_ptr, width, height,
117.1694 ++                 info_ptr->bit_depth, info_ptr->color_type,
117.1695 ++                 info_ptr->interlace_type, info_ptr->compression_type,
117.1696 ++                 info_ptr->filter_type);
117.1697 ++
117.1698 ++    png_ptr->width = width;
117.1699 ++    png_ptr->height = height;
117.1700 ++    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
117.1701 ++    png_ptr->usr_width = png_ptr->width;
117.1702 ++}
117.1703 ++#endif /* PNG_WRITE_APNG_SUPPORTED */
117.1704 + #endif /* WRITE */
117.1705 +diff -Naru libpng-1.6.35.org/scripts/symbols.def libpng-1.6.35/scripts/symbols.def
117.1706 +--- libpng-1.6.35.org/scripts/symbols.def	2018-07-21 19:16:37.192143527 +0900
117.1707 ++++ libpng-1.6.35/scripts/symbols.def	2018-07-21 19:16:16.206354321 +0900
117.1708 +@@ -254,3 +254,23 @@
117.1709 +  png_set_eXIf @247
117.1710 +  png_get_eXIf_1 @248
117.1711 +  png_set_eXIf_1 @249
117.1712 ++ png_get_acTL @250
117.1713 ++ png_set_acTL @251
117.1714 ++ png_get_num_frames @252
117.1715 ++ png_get_num_plays @253
117.1716 ++ png_get_next_frame_fcTL @254
117.1717 ++ png_set_next_frame_fcTL @255
117.1718 ++ png_get_next_frame_width @256
117.1719 ++ png_get_next_frame_height @257
117.1720 ++ png_get_next_frame_x_offset @258
117.1721 ++ png_get_next_frame_y_offset @259
117.1722 ++ png_get_next_frame_delay_num @260
117.1723 ++ png_get_next_frame_delay_den @261
117.1724 ++ png_get_next_frame_dispose_op @262
117.1725 ++ png_get_next_frame_blend_op @263
117.1726 ++ png_get_first_frame_is_hidden @264
117.1727 ++ png_set_first_frame_is_hidden @265
117.1728 ++ png_read_frame_head @266
117.1729 ++ png_set_progressive_frame_fn @267
117.1730 ++ png_write_frame_head @268
117.1731 ++ png_write_frame_tail @269
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/libpng/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   118.3 @@ -0,0 +1,5 @@
   118.4 +# This patch listed in the BLFS page, was downloaded using following address and
   118.5 +# unzipped:
   118.6 +# https://downloads.sourceforge.net/sourceforge/libpng-apng/libpng-1.6.35-apng.patch.gz
   118.7 +
   118.8 +-p1|libpng-1.6.35-apng.patch
   119.1 --- a/libpng16/receipt	Thu Dec 13 00:46:54 2018 +0200
   119.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.3 @@ -1,48 +0,0 @@
   119.4 -# SliTaz package receipt v2.
   119.5 -
   119.6 -PACKAGE="libpng16"
   119.7 -VERSION="1.6.35"
   119.8 -CATEGORY="libs"
   119.9 -SHORT_DESC="PNG images library 1.6 series with APNG support"
  119.10 -MAINTAINER="al.bobylev@gmail.com"
  119.11 -LICENSE="zlib/libpng"
  119.12 -WEB_SITE="http://www.libpng.org/pub/png/libpng.html"
  119.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/general/libpng.html"
  119.14 -REPOLOGY="libpng"
  119.15 -
  119.16 -TARBALL="libpng-$VERSION.tar.xz"
  119.17 -WGET_URL="$SF_MIRROR/libpng/$TARBALL"
  119.18 -
  119.19 -BUILD_DEPENDS="zlib-dev"
  119.20 -SPLIT="$PACKAGE-dev"
  119.21 -
  119.22 -compile_rules() {
  119.23 -	# don't use --disable-static: optipng-static require such lib
  119.24 -
  119.25 -	LIBS=-lpthread \
  119.26 -	./configure \
  119.27 -		$CONFIGURE_ARGS &&
  119.28 -	fix libtool &&
  119.29 -	make &&
  119.30 -	make install || return 1
  119.31 -
  119.32 -	cook_pick_docs README libpng-manual.txt
  119.33 -
  119.34 -	# Misc png tools
  119.35 -	cd contrib/pngminus
  119.36 -	make PNGLIB="-L$install/usr/lib -lpng" -f makefile.std png2pnm pnm2png
  119.37 -	cp -a png2pnm pnm2png $install/usr/bin
  119.38 -}
  119.39 -
  119.40 -genpkg_rules() {
  119.41 -	case $PACKAGE in
  119.42 -		libpng16)
  119.43 -			copy @std
  119.44 -			DEPENDS="zlib"
  119.45 -			;;
  119.46 -		*-dev)
  119.47 -			copy @dev
  119.48 -			DEPENDS="libpng16 zlib-dev"
  119.49 -			;;
  119.50 -	esac
  119.51 -}
   120.1 --- a/libpng16/stuff/patches/libpng-1.6.35-apng.patch	Thu Dec 13 00:46:54 2018 +0200
   120.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.3 @@ -1,1728 +0,0 @@
   120.4 -diff -Naru libpng-1.6.35.org/png.h libpng-1.6.35/png.h
   120.5 ---- libpng-1.6.35.org/png.h	2018-07-21 19:16:37.185142931 +0900
   120.6 -+++ libpng-1.6.35/png.h	2018-07-21 19:16:16.327364638 +0900
   120.7 -@@ -361,6 +361,10 @@
   120.8 - #   include "pnglibconf.h"
   120.9 - #endif
  120.10 - 
  120.11 -+#define PNG_APNG_SUPPORTED
  120.12 -+#define PNG_READ_APNG_SUPPORTED
  120.13 -+#define PNG_WRITE_APNG_SUPPORTED
  120.14 -+
  120.15 - #ifndef PNG_VERSION_INFO_ONLY
  120.16 - /* Machine specific configuration. */
  120.17 - #  include "pngconf.h"
  120.18 -@@ -456,6 +460,17 @@
  120.19 -  * See pngconf.h for base types that vary by machine/system
  120.20 -  */
  120.21 - 
  120.22 -+#ifdef PNG_APNG_SUPPORTED
  120.23 -+/* dispose_op flags from inside fcTL */
  120.24 -+#define PNG_DISPOSE_OP_NONE        0x00U
  120.25 -+#define PNG_DISPOSE_OP_BACKGROUND  0x01U
  120.26 -+#define PNG_DISPOSE_OP_PREVIOUS    0x02U
  120.27 -+
  120.28 -+/* blend_op flags from inside fcTL */
  120.29 -+#define PNG_BLEND_OP_SOURCE        0x00U
  120.30 -+#define PNG_BLEND_OP_OVER          0x01U
  120.31 -+#endif /* PNG_APNG_SUPPORTED */
  120.32 -+
  120.33 - /* This triggers a compiler error in png.c, if png.c and png.h
  120.34 -  * do not agree upon the version number.
  120.35 -  */
  120.36 -@@ -777,6 +792,10 @@
  120.37 - #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
  120.38 - #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
  120.39 - #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
  120.40 -+#ifdef PNG_APNG_SUPPORTED
  120.41 -+#define PNG_INFO_acTL 0x20000U
  120.42 -+#define PNG_INFO_fcTL 0x40000U
  120.43 -+#endif
  120.44 - 
  120.45 - /* This is used for the transformation routines, as some of them
  120.46 -  * change these values for the row.  It also should enable using
  120.47 -@@ -814,6 +833,10 @@
  120.48 - #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  120.49 - typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
  120.50 - typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
  120.51 -+#ifdef PNG_APNG_SUPPORTED
  120.52 -+typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
  120.53 -+    png_uint_32));
  120.54 -+#endif
  120.55 - 
  120.56 - /* The following callback receives png_uint_32 row_number, int pass for the
  120.57 -  * png_bytep data of the row.  When transforming an interlaced image the
  120.58 -@@ -3257,6 +3280,74 @@
  120.59 - /*******************************************************************************
  120.60 -  *  END OF HARDWARE AND SOFTWARE OPTIONS
  120.61 -  ******************************************************************************/
  120.62 -+#ifdef PNG_APNG_SUPPORTED
  120.63 -+PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr,
  120.64 -+   png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
  120.65 -+
  120.66 -+PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr,
  120.67 -+   png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
  120.68 -+
  120.69 -+PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr,
  120.70 -+   png_infop info_ptr));
  120.71 -+
  120.72 -+PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr,
  120.73 -+   png_infop info_ptr));
  120.74 -+
  120.75 -+PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL,
  120.76 -+   (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
  120.77 -+   png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
  120.78 -+   png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
  120.79 -+   png_byte *blend_op));
  120.80 -+
  120.81 -+PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL,
  120.82 -+   (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
  120.83 -+   png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
  120.84 -+   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
  120.85 -+   png_byte blend_op));
  120.86 -+
  120.87 -+PNG_EXPORT(256, png_uint_32, png_get_next_frame_width,
  120.88 -+   (png_structp png_ptr, png_infop info_ptr));
  120.89 -+PNG_EXPORT(257, png_uint_32, png_get_next_frame_height,
  120.90 -+   (png_structp png_ptr, png_infop info_ptr));
  120.91 -+PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset,
  120.92 -+   (png_structp png_ptr, png_infop info_ptr));
  120.93 -+PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset,
  120.94 -+   (png_structp png_ptr, png_infop info_ptr));
  120.95 -+PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num,
  120.96 -+   (png_structp png_ptr, png_infop info_ptr));
  120.97 -+PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den,
  120.98 -+   (png_structp png_ptr, png_infop info_ptr));
  120.99 -+PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op,
 120.100 -+   (png_structp png_ptr, png_infop info_ptr));
 120.101 -+PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op,
 120.102 -+   (png_structp png_ptr, png_infop info_ptr));
 120.103 -+PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden,
 120.104 -+   (png_structp png_ptr, png_infop info_ptr));
 120.105 -+PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden,
 120.106 -+   (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
 120.107 -+
 120.108 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.109 -+PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr,
 120.110 -+   png_infop info_ptr));
 120.111 -+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 120.112 -+PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr,
 120.113 -+   png_progressive_frame_ptr frame_info_fn,
 120.114 -+   png_progressive_frame_ptr frame_end_fn));
 120.115 -+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 120.116 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.117 -+
 120.118 -+#ifdef PNG_WRITE_APNG_SUPPORTED
 120.119 -+PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr,
 120.120 -+   png_infop info_ptr, png_bytepp row_pointers,
 120.121 -+   png_uint_32 width, png_uint_32 height,
 120.122 -+   png_uint_32 x_offset, png_uint_32 y_offset,
 120.123 -+   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 120.124 -+   png_byte blend_op));
 120.125 -+
 120.126 -+PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
 120.127 -+   png_infop info_ptr));
 120.128 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
 120.129 -+#endif /* PNG_APNG_SUPPORTED */
 120.130 - 
 120.131 - /* Maintainer: Put new public prototypes here ^, in libpng.3, in project
 120.132 -  * defs, and in scripts/symbols.def.
 120.133 -@@ -3266,7 +3357,11 @@
 120.134 -  * one to use is one more than this.)
 120.135 -  */
 120.136 - #ifdef PNG_EXPORT_LAST_ORDINAL
 120.137 -+#ifdef PNG_APNG_SUPPORTED
 120.138 -+  PNG_EXPORT_LAST_ORDINAL(269);
 120.139 -+#else
 120.140 -   PNG_EXPORT_LAST_ORDINAL(249);
 120.141 -+#endif /* PNG_APNG_SUPPORTED */
 120.142 - #endif
 120.143 - 
 120.144 - #ifdef __cplusplus
 120.145 -diff -Naru libpng-1.6.35.org/pngget.c libpng-1.6.35/pngget.c
 120.146 ---- libpng-1.6.35.org/pngget.c	2018-07-21 19:16:37.185142931 +0900
 120.147 -+++ libpng-1.6.35/pngget.c	2018-07-21 19:16:16.229356281 +0900
 120.148 -@@ -1246,4 +1246,166 @@
 120.149 - #  endif
 120.150 - #endif
 120.151 - 
 120.152 -+#ifdef PNG_APNG_SUPPORTED
 120.153 -+png_uint_32 PNGAPI
 120.154 -+png_get_acTL(png_structp png_ptr, png_infop info_ptr,
 120.155 -+             png_uint_32 *num_frames, png_uint_32 *num_plays)
 120.156 -+{
 120.157 -+    png_debug1(1, "in %s retrieval function", "acTL");
 120.158 -+
 120.159 -+    if (png_ptr != NULL && info_ptr != NULL &&
 120.160 -+        (info_ptr->valid & PNG_INFO_acTL) &&
 120.161 -+        num_frames != NULL && num_plays != NULL)
 120.162 -+    {
 120.163 -+        *num_frames = info_ptr->num_frames;
 120.164 -+        *num_plays = info_ptr->num_plays;
 120.165 -+        return (1);
 120.166 -+    }
 120.167 -+
 120.168 -+    return (0);
 120.169 -+}
 120.170 -+
 120.171 -+png_uint_32 PNGAPI
 120.172 -+png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
 120.173 -+{
 120.174 -+    png_debug(1, "in png_get_num_frames()");
 120.175 -+
 120.176 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.177 -+        return (info_ptr->num_frames);
 120.178 -+    return (0);
 120.179 -+}
 120.180 -+
 120.181 -+png_uint_32 PNGAPI
 120.182 -+png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
 120.183 -+{
 120.184 -+    png_debug(1, "in png_get_num_plays()");
 120.185 -+
 120.186 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.187 -+        return (info_ptr->num_plays);
 120.188 -+    return (0);
 120.189 -+}
 120.190 -+
 120.191 -+png_uint_32 PNGAPI
 120.192 -+png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
 120.193 -+             png_uint_32 *width, png_uint_32 *height,
 120.194 -+             png_uint_32 *x_offset, png_uint_32 *y_offset,
 120.195 -+             png_uint_16 *delay_num, png_uint_16 *delay_den,
 120.196 -+             png_byte *dispose_op, png_byte *blend_op)
 120.197 -+{
 120.198 -+    png_debug1(1, "in %s retrieval function", "fcTL");
 120.199 -+
 120.200 -+    if (png_ptr != NULL && info_ptr != NULL &&
 120.201 -+        (info_ptr->valid & PNG_INFO_fcTL) &&
 120.202 -+        width != NULL && height != NULL &&
 120.203 -+        x_offset != NULL && y_offset != NULL &&
 120.204 -+        delay_num != NULL && delay_den != NULL &&
 120.205 -+        dispose_op != NULL && blend_op != NULL)
 120.206 -+    {
 120.207 -+        *width = info_ptr->next_frame_width;
 120.208 -+        *height = info_ptr->next_frame_height;
 120.209 -+        *x_offset = info_ptr->next_frame_x_offset;
 120.210 -+        *y_offset = info_ptr->next_frame_y_offset;
 120.211 -+        *delay_num = info_ptr->next_frame_delay_num;
 120.212 -+        *delay_den = info_ptr->next_frame_delay_den;
 120.213 -+        *dispose_op = info_ptr->next_frame_dispose_op;
 120.214 -+        *blend_op = info_ptr->next_frame_blend_op;
 120.215 -+        return (1);
 120.216 -+    }
 120.217 -+
 120.218 -+    return (0);
 120.219 -+}
 120.220 -+
 120.221 -+png_uint_32 PNGAPI
 120.222 -+png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
 120.223 -+{
 120.224 -+    png_debug(1, "in png_get_next_frame_width()");
 120.225 -+
 120.226 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.227 -+        return (info_ptr->next_frame_width);
 120.228 -+    return (0);
 120.229 -+}
 120.230 -+
 120.231 -+png_uint_32 PNGAPI
 120.232 -+png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
 120.233 -+{
 120.234 -+    png_debug(1, "in png_get_next_frame_height()");
 120.235 -+
 120.236 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.237 -+        return (info_ptr->next_frame_height);
 120.238 -+    return (0);
 120.239 -+}
 120.240 -+
 120.241 -+png_uint_32 PNGAPI
 120.242 -+png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
 120.243 -+{
 120.244 -+    png_debug(1, "in png_get_next_frame_x_offset()");
 120.245 -+
 120.246 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.247 -+        return (info_ptr->next_frame_x_offset);
 120.248 -+    return (0);
 120.249 -+}
 120.250 -+
 120.251 -+png_uint_32 PNGAPI
 120.252 -+png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
 120.253 -+{
 120.254 -+    png_debug(1, "in png_get_next_frame_y_offset()");
 120.255 -+
 120.256 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.257 -+        return (info_ptr->next_frame_y_offset);
 120.258 -+    return (0);
 120.259 -+}
 120.260 -+
 120.261 -+png_uint_16 PNGAPI
 120.262 -+png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
 120.263 -+{
 120.264 -+    png_debug(1, "in png_get_next_frame_delay_num()");
 120.265 -+
 120.266 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.267 -+        return (info_ptr->next_frame_delay_num);
 120.268 -+    return (0);
 120.269 -+}
 120.270 -+
 120.271 -+png_uint_16 PNGAPI
 120.272 -+png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
 120.273 -+{
 120.274 -+    png_debug(1, "in png_get_next_frame_delay_den()");
 120.275 -+
 120.276 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.277 -+        return (info_ptr->next_frame_delay_den);
 120.278 -+    return (0);
 120.279 -+}
 120.280 -+
 120.281 -+png_byte PNGAPI
 120.282 -+png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
 120.283 -+{
 120.284 -+    png_debug(1, "in png_get_next_frame_dispose_op()");
 120.285 -+
 120.286 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.287 -+        return (info_ptr->next_frame_dispose_op);
 120.288 -+    return (0);
 120.289 -+}
 120.290 -+
 120.291 -+png_byte PNGAPI
 120.292 -+png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
 120.293 -+{
 120.294 -+    png_debug(1, "in png_get_next_frame_blend_op()");
 120.295 -+
 120.296 -+    if (png_ptr != NULL && info_ptr != NULL)
 120.297 -+        return (info_ptr->next_frame_blend_op);
 120.298 -+    return (0);
 120.299 -+}
 120.300 -+
 120.301 -+png_byte PNGAPI
 120.302 -+png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
 120.303 -+{
 120.304 -+    png_debug(1, "in png_first_frame_is_hidden()");
 120.305 -+
 120.306 -+    if (png_ptr != NULL)
 120.307 -+       return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
 120.308 -+
 120.309 -+    PNG_UNUSED(info_ptr)
 120.310 -+
 120.311 -+    return 0;
 120.312 -+}
 120.313 -+#endif /* PNG_APNG_SUPPORTED */
 120.314 - #endif /* READ || WRITE */
 120.315 -diff -Naru libpng-1.6.35.org/pnginfo.h libpng-1.6.35/pnginfo.h
 120.316 ---- libpng-1.6.35.org/pnginfo.h	2018-07-21 19:16:37.185142931 +0900
 120.317 -+++ libpng-1.6.35/pnginfo.h	2018-07-21 19:16:16.228356197 +0900
 120.318 -@@ -263,5 +263,18 @@
 120.319 -    png_bytepp row_pointers;        /* the image bits */
 120.320 - #endif
 120.321 - 
 120.322 -+#ifdef PNG_APNG_SUPPORTED
 120.323 -+   png_uint_32 num_frames; /* including default image */
 120.324 -+   png_uint_32 num_plays;
 120.325 -+   png_uint_32 next_frame_width;
 120.326 -+   png_uint_32 next_frame_height;
 120.327 -+   png_uint_32 next_frame_x_offset;
 120.328 -+   png_uint_32 next_frame_y_offset;
 120.329 -+   png_uint_16 next_frame_delay_num;
 120.330 -+   png_uint_16 next_frame_delay_den;
 120.331 -+   png_byte next_frame_dispose_op;
 120.332 -+   png_byte next_frame_blend_op;
 120.333 -+#endif
 120.334 -+
 120.335 - };
 120.336 - #endif /* PNGINFO_H */
 120.337 -diff -Naru libpng-1.6.35.org/pngpread.c libpng-1.6.35/pngpread.c
 120.338 ---- libpng-1.6.35.org/pngpread.c	2018-07-21 19:16:37.185142931 +0900
 120.339 -+++ libpng-1.6.35/pngpread.c	2018-07-21 19:16:16.228356197 +0900
 120.340 -@@ -195,6 +195,106 @@
 120.341 - 
 120.342 -    chunk_name = png_ptr->chunk_name;
 120.343 - 
 120.344 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.345 -+   if (png_ptr->num_frames_read > 0 &&
 120.346 -+       png_ptr->num_frames_read < info_ptr->num_frames)
 120.347 -+   {
 120.348 -+      if (chunk_name == png_IDAT)
 120.349 -+      {
 120.350 -+         /* Discard trailing IDATs for the first frame */
 120.351 -+         if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
 120.352 -+            png_error(png_ptr, "out of place IDAT");
 120.353 -+
 120.354 -+         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.355 -+         {
 120.356 -+            png_push_save_buffer(png_ptr);
 120.357 -+            return;
 120.358 -+         }
 120.359 -+
 120.360 -+         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 120.361 -+         return;
 120.362 -+      }
 120.363 -+      else if (chunk_name == png_fdAT)
 120.364 -+      {
 120.365 -+         if (png_ptr->buffer_size < 4)
 120.366 -+         {
 120.367 -+            png_push_save_buffer(png_ptr);
 120.368 -+            return;
 120.369 -+         }
 120.370 -+
 120.371 -+         png_ensure_sequence_number(png_ptr, 4);
 120.372 -+
 120.373 -+         if (!(png_ptr->mode & PNG_HAVE_fcTL))
 120.374 -+         {
 120.375 -+            /* Discard trailing fdATs for frames other than the first */
 120.376 -+            if (png_ptr->num_frames_read < 2)
 120.377 -+               png_error(png_ptr, "out of place fdAT");
 120.378 -+
 120.379 -+            if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.380 -+            {
 120.381 -+               png_push_save_buffer(png_ptr);
 120.382 -+               return;
 120.383 -+            }
 120.384 -+
 120.385 -+            png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 120.386 -+            return;
 120.387 -+         }
 120.388 -+
 120.389 -+         else
 120.390 -+         {
 120.391 -+            /* frame data follows */
 120.392 -+            png_ptr->idat_size = png_ptr->push_length - 4;
 120.393 -+            png_ptr->mode |= PNG_HAVE_IDAT;
 120.394 -+            png_ptr->process_mode = PNG_READ_IDAT_MODE;
 120.395 -+
 120.396 -+            return;
 120.397 -+         }
 120.398 -+      }
 120.399 -+
 120.400 -+      else if (chunk_name == png_fcTL)
 120.401 -+      {
 120.402 -+         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.403 -+         {
 120.404 -+            png_push_save_buffer(png_ptr);
 120.405 -+            return;
 120.406 -+         }
 120.407 -+
 120.408 -+         png_read_reset(png_ptr);
 120.409 -+         png_ptr->mode &= ~PNG_HAVE_fcTL;
 120.410 -+
 120.411 -+         png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
 120.412 -+
 120.413 -+         if (!(png_ptr->mode & PNG_HAVE_fcTL))
 120.414 -+            png_error(png_ptr, "missing required fcTL chunk");
 120.415 -+
 120.416 -+         png_read_reinit(png_ptr, info_ptr);
 120.417 -+         png_progressive_read_reset(png_ptr);
 120.418 -+
 120.419 -+         if (png_ptr->frame_info_fn != NULL)
 120.420 -+            (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
 120.421 -+
 120.422 -+         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 120.423 -+
 120.424 -+         return;
 120.425 -+      }
 120.426 -+
 120.427 -+      else
 120.428 -+      {
 120.429 -+         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.430 -+         {
 120.431 -+            png_push_save_buffer(png_ptr);
 120.432 -+            return;
 120.433 -+         }
 120.434 -+         png_warning(png_ptr, "Skipped (ignored) a chunk "
 120.435 -+                              "between APNG chunks");
 120.436 -+         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 120.437 -+         return;
 120.438 -+      }
 120.439 -+
 120.440 -+      return;
 120.441 -+   }
 120.442 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.443 -+
 120.444 -    if (chunk_name == png_IDAT)
 120.445 -    {
 120.446 -       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
 120.447 -@@ -261,6 +361,9 @@
 120.448 - 
 120.449 -    else if (chunk_name == png_IDAT)
 120.450 -    {
 120.451 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.452 -+      png_have_info(png_ptr, info_ptr);
 120.453 -+#endif
 120.454 -       png_ptr->idat_size = png_ptr->push_length;
 120.455 -       png_ptr->process_mode = PNG_READ_IDAT_MODE;
 120.456 -       png_push_have_info(png_ptr, info_ptr);
 120.457 -@@ -406,6 +509,30 @@
 120.458 -       png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
 120.459 -    }
 120.460 - #endif
 120.461 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.462 -+   else if (chunk_name == png_acTL)
 120.463 -+   {
 120.464 -+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.465 -+      {
 120.466 -+         png_push_save_buffer(png_ptr);
 120.467 -+         return;
 120.468 -+      }
 120.469 -+
 120.470 -+      png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
 120.471 -+   }
 120.472 -+
 120.473 -+   else if (chunk_name == png_fcTL)
 120.474 -+   {
 120.475 -+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.476 -+      {
 120.477 -+         png_push_save_buffer(png_ptr);
 120.478 -+         return;
 120.479 -+      }
 120.480 -+
 120.481 -+      png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
 120.482 -+   }
 120.483 -+
 120.484 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.485 - 
 120.486 -    else
 120.487 -    {
 120.488 -@@ -539,7 +666,11 @@
 120.489 -       png_byte chunk_tag[4];
 120.490 - 
 120.491 -       /* TODO: this code can be commoned up with the same code in push_read */
 120.492 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.493 -+      PNG_PUSH_SAVE_BUFFER_IF_LT(12)
 120.494 -+#else
 120.495 -       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
 120.496 -+#endif
 120.497 -       png_push_fill_buffer(png_ptr, chunk_length, 4);
 120.498 -       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
 120.499 -       png_reset_crc(png_ptr);
 120.500 -@@ -547,17 +678,64 @@
 120.501 -       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
 120.502 -       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
 120.503 - 
 120.504 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.505 -+      if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
 120.506 -+      {
 120.507 -+          if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
 120.508 -+          {
 120.509 -+              png_ptr->process_mode = PNG_READ_CHUNK_MODE;
 120.510 -+              if (png_ptr->frame_end_fn != NULL)
 120.511 -+                 (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
 120.512 -+              png_ptr->num_frames_read++;
 120.513 -+              return;
 120.514 -+          }
 120.515 -+          else
 120.516 -+          {
 120.517 -+              if (png_ptr->chunk_name == png_IEND)
 120.518 -+                  png_error(png_ptr, "Not enough image data");
 120.519 -+              if (png_ptr->push_length + 4 > png_ptr->buffer_size)
 120.520 -+              {
 120.521 -+                 png_push_save_buffer(png_ptr);
 120.522 -+                 return;
 120.523 -+              }
 120.524 -+              png_warning(png_ptr, "Skipping (ignoring) a chunk between "
 120.525 -+                                   "APNG chunks");
 120.526 -+              png_crc_finish(png_ptr, png_ptr->push_length);
 120.527 -+              png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
 120.528 -+              return;
 120.529 -+          }
 120.530 -+      }
 120.531 -+      else
 120.532 -+#endif
 120.533 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.534 -+      if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
 120.535 -+#else
 120.536 -       if (png_ptr->chunk_name != png_IDAT)
 120.537 -+#endif
 120.538 -       {
 120.539 -          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
 120.540 - 
 120.541 -          if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
 120.542 -             png_error(png_ptr, "Not enough compressed data");
 120.543 - 
 120.544 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.545 -+         if (png_ptr->frame_end_fn != NULL)
 120.546 -+            (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
 120.547 -+         png_ptr->num_frames_read++;
 120.548 -+#endif
 120.549 -+
 120.550 -          return;
 120.551 -       }
 120.552 - 
 120.553 -       png_ptr->idat_size = png_ptr->push_length;
 120.554 -+
 120.555 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.556 -+      if (png_ptr->num_frames_read > 0)
 120.557 -+      {
 120.558 -+         png_ensure_sequence_number(png_ptr, 4);
 120.559 -+         png_ptr->idat_size -= 4;
 120.560 -+      }
 120.561 -+#endif
 120.562 -    }
 120.563 - 
 120.564 -    if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
 120.565 -@@ -631,6 +809,15 @@
 120.566 -    if (!(buffer_length > 0) || buffer == NULL)
 120.567 -       png_error(png_ptr, "No IDAT data (internal error)");
 120.568 - 
 120.569 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.570 -+   /* If the app is not APNG-aware, decode only the first frame */
 120.571 -+   if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
 120.572 -+   {
 120.573 -+     png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
 120.574 -+     return;
 120.575 -+   }
 120.576 -+#endif
 120.577 -+
 120.578 -    /* This routine must process all the data it has been given
 120.579 -     * before returning, calling the row callback as required to
 120.580 -     * handle the uncompressed results.
 120.581 -@@ -1085,6 +1272,18 @@
 120.582 -    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
 120.583 - }
 120.584 - 
 120.585 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.586 -+void PNGAPI
 120.587 -+png_set_progressive_frame_fn(png_structp png_ptr,
 120.588 -+   png_progressive_frame_ptr frame_info_fn,
 120.589 -+   png_progressive_frame_ptr frame_end_fn)
 120.590 -+{
 120.591 -+   png_ptr->frame_info_fn = frame_info_fn;
 120.592 -+   png_ptr->frame_end_fn = frame_end_fn;
 120.593 -+   png_ptr->apng_flags |= PNG_APNG_APP;
 120.594 -+}
 120.595 -+#endif
 120.596 -+
 120.597 - png_voidp PNGAPI
 120.598 - png_get_progressive_ptr(png_const_structrp png_ptr)
 120.599 - {
 120.600 -diff -Naru libpng-1.6.35.org/pngpriv.h libpng-1.6.35/pngpriv.h
 120.601 ---- libpng-1.6.35.org/pngpriv.h	2018-07-21 19:16:37.185142931 +0900
 120.602 -+++ libpng-1.6.35/pngpriv.h	2018-07-21 19:16:16.226356026 +0900
 120.603 -@@ -634,6 +634,10 @@
 120.604 - #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
 120.605 -                    /*             0x4000U (unused) */
 120.606 - #define PNG_IS_READ_STRUCT        0x8000U /* Else is a write struct */
 120.607 -+#ifdef PNG_APNG_SUPPORTED
 120.608 -+#define PNG_HAVE_acTL            0x10000U
 120.609 -+#define PNG_HAVE_fcTL            0x20000U
 120.610 -+#endif
 120.611 - 
 120.612 - /* Flags for the transformations the PNG library does on the image data */
 120.613 - #define PNG_BGR                 0x0001U
 120.614 -@@ -870,6 +874,16 @@
 120.615 - #define png_tRNS PNG_U32(116,  82,  78,  83)
 120.616 - #define png_zTXt PNG_U32(122,  84,  88, 116)
 120.617 - 
 120.618 -+#ifdef PNG_APNG_SUPPORTED
 120.619 -+#define png_acTL PNG_U32( 97,  99,  84,  76)
 120.620 -+#define png_fcTL PNG_U32(102,  99,  84,  76)
 120.621 -+#define png_fdAT PNG_U32(102, 100,  65,  84)
 120.622 -+
 120.623 -+/* For png_struct.apng_flags: */
 120.624 -+#define PNG_FIRST_FRAME_HIDDEN       0x0001U
 120.625 -+#define PNG_APNG_APP                 0x0002U
 120.626 -+#endif
 120.627 -+
 120.628 - /* The following will work on (signed char*) strings, whereas the get_uint_32
 120.629 -  * macro will fail on top-bit-set values because of the sign extension.
 120.630 -  */
 120.631 -@@ -1641,6 +1655,47 @@
 120.632 -     */
 120.633 - #endif
 120.634 - 
 120.635 -+#ifdef PNG_APNG_SUPPORTED
 120.636 -+PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
 120.637 -+   png_uint_32 width, png_uint_32 height,
 120.638 -+   png_uint_32 x_offset, png_uint_32 y_offset,
 120.639 -+   png_uint_16 delay_num, png_uint_16 delay_den,
 120.640 -+   png_byte dispose_op, png_byte blend_op), PNG_EMPTY);
 120.641 -+
 120.642 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.643 -+PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr,
 120.644 -+   png_uint_32 length),PNG_EMPTY);
 120.645 -+PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr,
 120.646 -+   png_uint_32 length),PNG_EMPTY);
 120.647 -+PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr,
 120.648 -+   png_uint_32 length),PNG_EMPTY);
 120.649 -+PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY);
 120.650 -+PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
 120.651 -+   png_uint_32 length),PNG_EMPTY);
 120.652 -+PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
 120.653 -+PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
 120.654 -+   png_infop info_ptr),PNG_EMPTY);
 120.655 -+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 120.656 -+PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY);
 120.657 -+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 120.658 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.659 -+
 120.660 -+#ifdef PNG_WRITE_APNG_SUPPORTED
 120.661 -+PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
 120.662 -+   png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
 120.663 -+PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
 120.664 -+   png_uint_32 width, png_uint_32 height,
 120.665 -+   png_uint_32 x_offset, png_uint_32 y_offset,
 120.666 -+   png_uint_16 delay_num, png_uint_16 delay_den,
 120.667 -+   png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
 120.668 -+PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
 120.669 -+   png_const_bytep data, png_size_t length),PNG_EMPTY);
 120.670 -+PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
 120.671 -+PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
 120.672 -+   png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
 120.673 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
 120.674 -+#endif /* PNG_APNG_SUPPORTED */
 120.675 -+
 120.676 - /* Added at libpng version 1.4.0 */
 120.677 - #ifdef PNG_COLORSPACE_SUPPORTED
 120.678 - /* These internal functions are for maintaining the colorspace structure within
 120.679 -diff -Naru libpng-1.6.35.org/pngread.c libpng-1.6.35/pngread.c
 120.680 ---- libpng-1.6.35.org/pngread.c	2018-07-21 19:16:37.186143016 +0900
 120.681 -+++ libpng-1.6.35/pngread.c	2018-07-21 19:16:16.224355855 +0900
 120.682 -@@ -161,6 +161,9 @@
 120.683 - 
 120.684 -       else if (chunk_name == png_IDAT)
 120.685 -       {
 120.686 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.687 -+         png_have_info(png_ptr, info_ptr);
 120.688 -+#endif
 120.689 -          png_ptr->idat_size = length;
 120.690 -          break;
 120.691 -       }
 120.692 -@@ -255,6 +258,17 @@
 120.693 -          png_handle_iTXt(png_ptr, info_ptr, length);
 120.694 - #endif
 120.695 - 
 120.696 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.697 -+      else if (chunk_name == png_acTL)
 120.698 -+         png_handle_acTL(png_ptr, info_ptr, length);
 120.699 -+
 120.700 -+      else if (chunk_name == png_fcTL)
 120.701 -+         png_handle_fcTL(png_ptr, info_ptr, length);
 120.702 -+
 120.703 -+      else if (chunk_name == png_fdAT)
 120.704 -+         png_handle_fdAT(png_ptr, info_ptr, length);
 120.705 -+#endif
 120.706 -+
 120.707 -       else
 120.708 -          png_handle_unknown(png_ptr, info_ptr, length,
 120.709 -              PNG_HANDLE_CHUNK_AS_DEFAULT);
 120.710 -@@ -262,6 +276,72 @@
 120.711 - }
 120.712 - #endif /* SEQUENTIAL_READ */
 120.713 - 
 120.714 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.715 -+void PNGAPI
 120.716 -+png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
 120.717 -+{
 120.718 -+    png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
 120.719 -+
 120.720 -+    png_debug(0, "Reading frame head");
 120.721 -+
 120.722 -+    if (!(png_ptr->mode & PNG_HAVE_acTL))
 120.723 -+        png_error(png_ptr, "attempt to png_read_frame_head() but "
 120.724 -+                           "no acTL present");
 120.725 -+
 120.726 -+    /* do nothing for the main IDAT */
 120.727 -+    if (png_ptr->num_frames_read == 0)
 120.728 -+        return;
 120.729 -+
 120.730 -+    png_read_reset(png_ptr);
 120.731 -+    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
 120.732 -+    png_ptr->mode &= ~PNG_HAVE_fcTL;
 120.733 -+
 120.734 -+    have_chunk_after_DAT = 0;
 120.735 -+    for (;;)
 120.736 -+    {
 120.737 -+        png_uint_32 length = png_read_chunk_header(png_ptr);
 120.738 -+
 120.739 -+        if (png_ptr->chunk_name == png_IDAT)
 120.740 -+        {
 120.741 -+            /* discard trailing IDATs for the first frame */
 120.742 -+            if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
 120.743 -+                png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
 120.744 -+            png_crc_finish(png_ptr, length);
 120.745 -+        }
 120.746 -+
 120.747 -+        else if (png_ptr->chunk_name == png_fcTL)
 120.748 -+        {
 120.749 -+            png_handle_fcTL(png_ptr, info_ptr, length);
 120.750 -+            have_chunk_after_DAT = 1;
 120.751 -+        }
 120.752 -+
 120.753 -+        else if (png_ptr->chunk_name == png_fdAT)
 120.754 -+        {
 120.755 -+            png_ensure_sequence_number(png_ptr, length);
 120.756 -+
 120.757 -+            /* discard trailing fdATs for frames other than the first */
 120.758 -+            if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
 120.759 -+                png_crc_finish(png_ptr, length - 4);
 120.760 -+            else if(png_ptr->mode & PNG_HAVE_fcTL)
 120.761 -+            {
 120.762 -+                png_ptr->idat_size = length - 4;
 120.763 -+                png_ptr->mode |= PNG_HAVE_IDAT;
 120.764 -+
 120.765 -+                break;
 120.766 -+            }
 120.767 -+            else
 120.768 -+                png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
 120.769 -+        }
 120.770 -+        else
 120.771 -+        {
 120.772 -+            png_warning(png_ptr, "Skipped (ignored) a chunk "
 120.773 -+                                 "between APNG chunks");
 120.774 -+            png_crc_finish(png_ptr, length);
 120.775 -+        }
 120.776 -+    }
 120.777 -+}
 120.778 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.779 -+
 120.780 - /* Optional call to update the users info_ptr structure */
 120.781 - void PNGAPI
 120.782 - png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
 120.783 -diff -Naru libpng-1.6.35.org/pngrutil.c libpng-1.6.35/pngrutil.c
 120.784 ---- libpng-1.6.35.org/pngrutil.c	2018-07-21 19:16:37.187143101 +0900
 120.785 -+++ libpng-1.6.35/pngrutil.c	2018-07-21 19:16:16.220355514 +0900
 120.786 -@@ -865,6 +865,11 @@
 120.787 -    filter_type = buf[11];
 120.788 -    interlace_type = buf[12];
 120.789 - 
 120.790 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.791 -+   png_ptr->first_frame_width = width;
 120.792 -+   png_ptr->first_frame_height = height;
 120.793 -+#endif
 120.794 -+
 120.795 -    /* Set internal variables */
 120.796 -    png_ptr->width = width;
 120.797 -    png_ptr->height = height;
 120.798 -@@ -2858,6 +2863,179 @@
 120.799 - }
 120.800 - #endif
 120.801 - 
 120.802 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.803 -+void /* PRIVATE */
 120.804 -+png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 120.805 -+{
 120.806 -+    png_byte data[8];
 120.807 -+    png_uint_32 num_frames;
 120.808 -+    png_uint_32 num_plays;
 120.809 -+    png_uint_32 didSet;
 120.810 -+
 120.811 -+    png_debug(1, "in png_handle_acTL");
 120.812 -+
 120.813 -+    if (!(png_ptr->mode & PNG_HAVE_IHDR))
 120.814 -+    {
 120.815 -+        png_error(png_ptr, "Missing IHDR before acTL");
 120.816 -+    }
 120.817 -+    else if (png_ptr->mode & PNG_HAVE_IDAT)
 120.818 -+    {
 120.819 -+        png_warning(png_ptr, "Invalid acTL after IDAT skipped");
 120.820 -+        png_crc_finish(png_ptr, length);
 120.821 -+        return;
 120.822 -+    }
 120.823 -+    else if (png_ptr->mode & PNG_HAVE_acTL)
 120.824 -+    {
 120.825 -+        png_warning(png_ptr, "Duplicate acTL skipped");
 120.826 -+        png_crc_finish(png_ptr, length);
 120.827 -+        return;
 120.828 -+    }
 120.829 -+    else if (length != 8)
 120.830 -+    {
 120.831 -+        png_warning(png_ptr, "acTL with invalid length skipped");
 120.832 -+        png_crc_finish(png_ptr, length);
 120.833 -+        return;
 120.834 -+    }
 120.835 -+
 120.836 -+    png_crc_read(png_ptr, data, 8);
 120.837 -+    png_crc_finish(png_ptr, 0);
 120.838 -+
 120.839 -+    num_frames = png_get_uint_31(png_ptr, data);
 120.840 -+    num_plays = png_get_uint_31(png_ptr, data + 4);
 120.841 -+
 120.842 -+    /* the set function will do error checking on num_frames */
 120.843 -+    didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
 120.844 -+    if(didSet)
 120.845 -+        png_ptr->mode |= PNG_HAVE_acTL;
 120.846 -+}
 120.847 -+
 120.848 -+void /* PRIVATE */
 120.849 -+png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 120.850 -+{
 120.851 -+    png_byte data[22];
 120.852 -+    png_uint_32 width;
 120.853 -+    png_uint_32 height;
 120.854 -+    png_uint_32 x_offset;
 120.855 -+    png_uint_32 y_offset;
 120.856 -+    png_uint_16 delay_num;
 120.857 -+    png_uint_16 delay_den;
 120.858 -+    png_byte dispose_op;
 120.859 -+    png_byte blend_op;
 120.860 -+
 120.861 -+    png_debug(1, "in png_handle_fcTL");
 120.862 -+
 120.863 -+    png_ensure_sequence_number(png_ptr, length);
 120.864 -+
 120.865 -+    if (!(png_ptr->mode & PNG_HAVE_IHDR))
 120.866 -+    {
 120.867 -+        png_error(png_ptr, "Missing IHDR before fcTL");
 120.868 -+    }
 120.869 -+    else if (png_ptr->mode & PNG_HAVE_IDAT)
 120.870 -+    {
 120.871 -+        /* for any frames other then the first this message may be misleading,
 120.872 -+        * but correct. PNG_HAVE_IDAT is unset before the frame head is read
 120.873 -+        * i can't think of a better message */
 120.874 -+        png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
 120.875 -+        png_crc_finish(png_ptr, length-4);
 120.876 -+        return;
 120.877 -+    }
 120.878 -+    else if (png_ptr->mode & PNG_HAVE_fcTL)
 120.879 -+    {
 120.880 -+        png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
 120.881 -+        png_crc_finish(png_ptr, length-4);
 120.882 -+        return;
 120.883 -+    }
 120.884 -+    else if (length != 26)
 120.885 -+    {
 120.886 -+        png_warning(png_ptr, "fcTL with invalid length skipped");
 120.887 -+        png_crc_finish(png_ptr, length-4);
 120.888 -+        return;
 120.889 -+    }
 120.890 -+
 120.891 -+    png_crc_read(png_ptr, data, 22);
 120.892 -+    png_crc_finish(png_ptr, 0);
 120.893 -+
 120.894 -+    width = png_get_uint_31(png_ptr, data);
 120.895 -+    height = png_get_uint_31(png_ptr, data + 4);
 120.896 -+    x_offset = png_get_uint_31(png_ptr, data + 8);
 120.897 -+    y_offset = png_get_uint_31(png_ptr, data + 12);
 120.898 -+    delay_num = png_get_uint_16(data + 16);
 120.899 -+    delay_den = png_get_uint_16(data + 18);
 120.900 -+    dispose_op = data[20];
 120.901 -+    blend_op = data[21];
 120.902 -+
 120.903 -+    if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
 120.904 -+    {
 120.905 -+        png_warning(png_ptr, "fcTL for the first frame must have zero offset");
 120.906 -+        return;
 120.907 -+    }
 120.908 -+
 120.909 -+    if (info_ptr != NULL)
 120.910 -+    {
 120.911 -+        if (png_ptr->num_frames_read == 0 &&
 120.912 -+            (width != info_ptr->width || height != info_ptr->height))
 120.913 -+        {
 120.914 -+            png_warning(png_ptr, "size in first frame's fcTL must match "
 120.915 -+                               "the size in IHDR");
 120.916 -+            return;
 120.917 -+        }
 120.918 -+
 120.919 -+        /* The set function will do more error checking */
 120.920 -+        png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
 120.921 -+                                x_offset, y_offset, delay_num, delay_den,
 120.922 -+                                dispose_op, blend_op);
 120.923 -+
 120.924 -+        png_read_reinit(png_ptr, info_ptr);
 120.925 -+
 120.926 -+        png_ptr->mode |= PNG_HAVE_fcTL;
 120.927 -+    }
 120.928 -+}
 120.929 -+
 120.930 -+void /* PRIVATE */
 120.931 -+png_have_info(png_structp png_ptr, png_infop info_ptr)
 120.932 -+{
 120.933 -+    if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
 120.934 -+    {
 120.935 -+        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
 120.936 -+        info_ptr->num_frames++;
 120.937 -+    }
 120.938 -+}
 120.939 -+
 120.940 -+void /* PRIVATE */
 120.941 -+png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 120.942 -+{
 120.943 -+    png_ensure_sequence_number(png_ptr, length);
 120.944 -+
 120.945 -+    /* This function is only called from png_read_end(), png_read_info(),
 120.946 -+    * and png_push_read_chunk() which means that:
 120.947 -+    * - the user doesn't want to read this frame
 120.948 -+    * - or this is an out-of-place fdAT
 120.949 -+    * in either case it is safe to ignore the chunk with a warning */
 120.950 -+    png_warning(png_ptr, "ignoring fdAT chunk");
 120.951 -+    png_crc_finish(png_ptr, length - 4);
 120.952 -+    PNG_UNUSED(info_ptr)
 120.953 -+}
 120.954 -+
 120.955 -+void /* PRIVATE */
 120.956 -+png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
 120.957 -+{
 120.958 -+    png_byte data[4];
 120.959 -+    png_uint_32 sequence_number;
 120.960 -+
 120.961 -+    if (length < 4)
 120.962 -+        png_error(png_ptr, "invalid fcTL or fdAT chunk found");
 120.963 -+
 120.964 -+    png_crc_read(png_ptr, data, 4);
 120.965 -+    sequence_number = png_get_uint_31(png_ptr, data);
 120.966 -+
 120.967 -+    if (sequence_number != png_ptr->next_seq_num)
 120.968 -+        png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
 120.969 -+                           "number found");
 120.970 -+
 120.971 -+    png_ptr->next_seq_num++;
 120.972 -+}
 120.973 -+#endif /* PNG_READ_APNG_SUPPORTED */
 120.974 -+
 120.975 - #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 120.976 - /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
 120.977 - static int
 120.978 -@@ -4166,7 +4344,38 @@
 120.979 -       {
 120.980 -          uInt avail_in;
 120.981 -          png_bytep buffer;
 120.982 -+#ifdef PNG_READ_APNG_SUPPORTED
 120.983 -+         png_uint_32 bytes_to_skip = 0;
 120.984 -+
 120.985 -+         while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
 120.986 -+         {
 120.987 -+            png_crc_finish(png_ptr, bytes_to_skip);
 120.988 -+            bytes_to_skip = 0;
 120.989 - 
 120.990 -+            png_ptr->idat_size = png_read_chunk_header(png_ptr);
 120.991 -+            if (png_ptr->num_frames_read == 0)
 120.992 -+            {
 120.993 -+               if (png_ptr->chunk_name != png_IDAT)
 120.994 -+                  png_error(png_ptr, "Not enough image data");
 120.995 -+            }
 120.996 -+            else
 120.997 -+            {
 120.998 -+               if (png_ptr->chunk_name == png_IEND)
 120.999 -+                  png_error(png_ptr, "Not enough image data");
120.1000 -+               if (png_ptr->chunk_name != png_fdAT)
120.1001 -+               {
120.1002 -+                  png_warning(png_ptr, "Skipped (ignored) a chunk "
120.1003 -+                                       "between APNG chunks");
120.1004 -+                  bytes_to_skip = png_ptr->idat_size;
120.1005 -+                  continue;
120.1006 -+               }
120.1007 -+
120.1008 -+               png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
120.1009 -+
120.1010 -+               png_ptr->idat_size -= 4;
120.1011 -+            }
120.1012 -+         }
120.1013 -+#else
120.1014 -          while (png_ptr->idat_size == 0)
120.1015 -          {
120.1016 -             png_crc_finish(png_ptr, 0);
120.1017 -@@ -4178,7 +4387,7 @@
120.1018 -             if (png_ptr->chunk_name != png_IDAT)
120.1019 -                png_error(png_ptr, "Not enough image data");
120.1020 -          }
120.1021 --
120.1022 -+#endif /* PNG_READ_APNG_SUPPORTED */
120.1023 -          avail_in = png_ptr->IDAT_read_size;
120.1024 - 
120.1025 -          if (avail_in > png_ptr->idat_size)
120.1026 -@@ -4241,6 +4450,9 @@
120.1027 - 
120.1028 -          png_ptr->mode |= PNG_AFTER_IDAT;
120.1029 -          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
120.1030 -+#ifdef PNG_READ_APNG_SUPPORTED
120.1031 -+         png_ptr->num_frames_read++;
120.1032 -+#endif
120.1033 - 
120.1034 -          if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
120.1035 -             png_chunk_benign_error(png_ptr, "Extra compressed data");
120.1036 -@@ -4679,4 +4891,80 @@
120.1037 - 
120.1038 -    png_ptr->flags |= PNG_FLAG_ROW_INIT;
120.1039 - }
120.1040 -+
120.1041 -+#ifdef PNG_READ_APNG_SUPPORTED
120.1042 -+/* This function is to be called after the main IDAT set has been read and
120.1043 -+ * before a new IDAT is read. It resets some parts of png_ptr
120.1044 -+ * to make them usable by the read functions again */
120.1045 -+void /* PRIVATE */
120.1046 -+png_read_reset(png_structp png_ptr)
120.1047 -+{
120.1048 -+    png_ptr->mode &= ~PNG_HAVE_IDAT;
120.1049 -+    png_ptr->mode &= ~PNG_AFTER_IDAT;
120.1050 -+    png_ptr->row_number = 0;
120.1051 -+    png_ptr->pass = 0;
120.1052 -+}
120.1053 -+
120.1054 -+void /* PRIVATE */
120.1055 -+png_read_reinit(png_structp png_ptr, png_infop info_ptr)
120.1056 -+{
120.1057 -+    png_ptr->width = info_ptr->next_frame_width;
120.1058 -+    png_ptr->height = info_ptr->next_frame_height;
120.1059 -+    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
120.1060 -+    png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
120.1061 -+        png_ptr->width);
120.1062 -+    if (png_ptr->prev_row)
120.1063 -+        memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
120.1064 -+}
120.1065 -+
120.1066 -+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
120.1067 -+/* same as png_read_reset() but for the progressive reader */
120.1068 -+void /* PRIVATE */
120.1069 -+png_progressive_read_reset(png_structp png_ptr)
120.1070 -+{
120.1071 -+#ifdef PNG_READ_INTERLACING_SUPPORTED
120.1072 -+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
120.1073 -+
120.1074 -+   /* Start of interlace block */
120.1075 -+    const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
120.1076 -+
120.1077 -+    /* Offset to next interlace block */
120.1078 -+    const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
120.1079 -+
120.1080 -+    /* Start of interlace block in the y direction */
120.1081 -+    const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
120.1082 -+
120.1083 -+    /* Offset to next interlace block in the y direction */
120.1084 -+    const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
120.1085 -+
120.1086 -+    if (png_ptr->interlaced)
120.1087 -+    {
120.1088 -+        if (!(png_ptr->transformations & PNG_INTERLACE))
120.1089 -+            png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
120.1090 -+                                png_pass_ystart[0]) / png_pass_yinc[0];
120.1091 -+        else
120.1092 -+            png_ptr->num_rows = png_ptr->height;
120.1093 -+
120.1094 -+        png_ptr->iwidth = (png_ptr->width +
120.1095 -+                           png_pass_inc[png_ptr->pass] - 1 -
120.1096 -+                           png_pass_start[png_ptr->pass]) /
120.1097 -+                           png_pass_inc[png_ptr->pass];
120.1098 -+    }
120.1099 -+    else
120.1100 -+#endif /* PNG_READ_INTERLACING_SUPPORTED */
120.1101 -+    {
120.1102 -+        png_ptr->num_rows = png_ptr->height;
120.1103 -+        png_ptr->iwidth = png_ptr->width;
120.1104 -+    }
120.1105 -+    png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
120.1106 -+    if (inflateReset(&(png_ptr->zstream)) != Z_OK)
120.1107 -+        png_error(png_ptr, "inflateReset failed");
120.1108 -+    png_ptr->zstream.avail_in = 0;
120.1109 -+    png_ptr->zstream.next_in = 0;
120.1110 -+    png_ptr->zstream.next_out = png_ptr->row_buf;
120.1111 -+    png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
120.1112 -+        png_ptr->iwidth) + 1;
120.1113 -+}
120.1114 -+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
120.1115 -+#endif /* PNG_READ_APNG_SUPPORTED */
120.1116 - #endif /* READ */
120.1117 -diff -Naru libpng-1.6.35.org/pngset.c libpng-1.6.35/pngset.c
120.1118 ---- libpng-1.6.35.org/pngset.c	2018-07-21 19:16:37.188143186 +0900
120.1119 -+++ libpng-1.6.35/pngset.c	2018-07-21 19:16:16.256358584 +0900
120.1120 -@@ -288,6 +288,11 @@
120.1121 -    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
120.1122 - 
120.1123 -    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
120.1124 -+
120.1125 -+#ifdef PNG_APNG_SUPPORTED
120.1126 -+   /* for non-animated png. this may be overwritten from an acTL chunk later */
120.1127 -+   info_ptr->num_frames = 1;
120.1128 -+#endif
120.1129 - }
120.1130 - 
120.1131 - #ifdef PNG_oFFs_SUPPORTED
120.1132 -@@ -1158,6 +1163,147 @@
120.1133 - }
120.1134 - #endif /* sPLT */
120.1135 - 
120.1136 -+#ifdef PNG_APNG_SUPPORTED
120.1137 -+png_uint_32 PNGAPI
120.1138 -+png_set_acTL(png_structp png_ptr, png_infop info_ptr,
120.1139 -+    png_uint_32 num_frames, png_uint_32 num_plays)
120.1140 -+{
120.1141 -+    png_debug1(1, "in %s storage function", "acTL");
120.1142 -+
120.1143 -+    if (png_ptr == NULL || info_ptr == NULL)
120.1144 -+    {
120.1145 -+        png_warning(png_ptr,
120.1146 -+                    "Call to png_set_acTL() with NULL png_ptr "
120.1147 -+                    "or info_ptr ignored");
120.1148 -+        return (0);
120.1149 -+    }
120.1150 -+    if (num_frames == 0)
120.1151 -+    {
120.1152 -+        png_warning(png_ptr,
120.1153 -+                    "Ignoring attempt to set acTL with num_frames zero");
120.1154 -+        return (0);
120.1155 -+    }
120.1156 -+    if (num_frames > PNG_UINT_31_MAX)
120.1157 -+    {
120.1158 -+        png_warning(png_ptr,
120.1159 -+                    "Ignoring attempt to set acTL with num_frames > 2^31-1");
120.1160 -+        return (0);
120.1161 -+    }
120.1162 -+    if (num_plays > PNG_UINT_31_MAX)
120.1163 -+    {
120.1164 -+        png_warning(png_ptr,
120.1165 -+                    "Ignoring attempt to set acTL with num_plays "
120.1166 -+                    "> 2^31-1");
120.1167 -+        return (0);
120.1168 -+    }
120.1169 -+
120.1170 -+    info_ptr->num_frames = num_frames;
120.1171 -+    info_ptr->num_plays = num_plays;
120.1172 -+
120.1173 -+    info_ptr->valid |= PNG_INFO_acTL;
120.1174 -+
120.1175 -+    return (1);
120.1176 -+}
120.1177 -+
120.1178 -+/* delay_num and delay_den can hold any 16-bit values including zero */
120.1179 -+png_uint_32 PNGAPI
120.1180 -+png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
120.1181 -+    png_uint_32 width, png_uint_32 height,
120.1182 -+    png_uint_32 x_offset, png_uint_32 y_offset,
120.1183 -+    png_uint_16 delay_num, png_uint_16 delay_den,
120.1184 -+    png_byte dispose_op, png_byte blend_op)
120.1185 -+{
120.1186 -+    png_debug1(1, "in %s storage function", "fcTL");
120.1187 -+
120.1188 -+    if (png_ptr == NULL || info_ptr == NULL)
120.1189 -+    {
120.1190 -+        png_warning(png_ptr,
120.1191 -+                    "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
120.1192 -+                    "ignored");
120.1193 -+        return (0);
120.1194 -+    }
120.1195 -+
120.1196 -+    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
120.1197 -+                             delay_num, delay_den, dispose_op, blend_op);
120.1198 -+
120.1199 -+    if (blend_op == PNG_BLEND_OP_OVER)
120.1200 -+    {
120.1201 -+        if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
120.1202 -+            !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
120.1203 -+        {
120.1204 -+          png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
120.1205 -+                               "and wasteful for opaque images, ignored");
120.1206 -+          blend_op = PNG_BLEND_OP_SOURCE;
120.1207 -+        }
120.1208 -+    }
120.1209 -+
120.1210 -+    info_ptr->next_frame_width = width;
120.1211 -+    info_ptr->next_frame_height = height;
120.1212 -+    info_ptr->next_frame_x_offset = x_offset;
120.1213 -+    info_ptr->next_frame_y_offset = y_offset;
120.1214 -+    info_ptr->next_frame_delay_num = delay_num;
120.1215 -+    info_ptr->next_frame_delay_den = delay_den;
120.1216 -+    info_ptr->next_frame_dispose_op = dispose_op;
120.1217 -+    info_ptr->next_frame_blend_op = blend_op;
120.1218 -+
120.1219 -+    info_ptr->valid |= PNG_INFO_fcTL;
120.1220 -+
120.1221 -+    return (1);
120.1222 -+}
120.1223 -+
120.1224 -+void /* PRIVATE */
120.1225 -+png_ensure_fcTL_is_valid(png_structp png_ptr,
120.1226 -+    png_uint_32 width, png_uint_32 height,
120.1227 -+    png_uint_32 x_offset, png_uint_32 y_offset,
120.1228 -+    png_uint_16 delay_num, png_uint_16 delay_den,
120.1229 -+    png_byte dispose_op, png_byte blend_op)
120.1230 -+{
120.1231 -+    if (width == 0 || width > PNG_UINT_31_MAX)
120.1232 -+        png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
120.1233 -+    if (height == 0 || height > PNG_UINT_31_MAX)
120.1234 -+        png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
120.1235 -+    if (x_offset > PNG_UINT_31_MAX)
120.1236 -+        png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
120.1237 -+    if (y_offset > PNG_UINT_31_MAX)
120.1238 -+        png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
120.1239 -+    if (width + x_offset > png_ptr->first_frame_width ||
120.1240 -+        height + y_offset > png_ptr->first_frame_height)
120.1241 -+        png_error(png_ptr, "dimensions of a frame are greater than"
120.1242 -+                           "the ones in IHDR");
120.1243 -+
120.1244 -+    if (dispose_op != PNG_DISPOSE_OP_NONE &&
120.1245 -+        dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
120.1246 -+        dispose_op != PNG_DISPOSE_OP_PREVIOUS)
120.1247 -+        png_error(png_ptr, "invalid dispose_op in fcTL");
120.1248 -+
120.1249 -+    if (blend_op != PNG_BLEND_OP_SOURCE &&
120.1250 -+        blend_op != PNG_BLEND_OP_OVER)
120.1251 -+        png_error(png_ptr, "invalid blend_op in fcTL");
120.1252 -+
120.1253 -+    PNG_UNUSED(delay_num)
120.1254 -+    PNG_UNUSED(delay_den)
120.1255 -+}
120.1256 -+
120.1257 -+png_uint_32 PNGAPI
120.1258 -+png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
120.1259 -+                              png_byte is_hidden)
120.1260 -+{
120.1261 -+    png_debug(1, "in png_first_frame_is_hidden()");
120.1262 -+
120.1263 -+    if (png_ptr == NULL)
120.1264 -+        return 0;
120.1265 -+
120.1266 -+    if (is_hidden)
120.1267 -+        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
120.1268 -+    else
120.1269 -+        png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
120.1270 -+
120.1271 -+    PNG_UNUSED(info_ptr)
120.1272 -+
120.1273 -+    return 1;
120.1274 -+}
120.1275 -+#endif /* PNG_APNG_SUPPORTED */
120.1276 -+
120.1277 - #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
120.1278 - static png_byte
120.1279 - check_location(png_const_structrp png_ptr, int location)
120.1280 -diff -Naru libpng-1.6.35.org/pngstruct.h libpng-1.6.35/pngstruct.h
120.1281 ---- libpng-1.6.35.org/pngstruct.h	2018-07-21 19:16:37.188143186 +0900
120.1282 -+++ libpng-1.6.35/pngstruct.h	2018-07-21 19:16:16.214355003 +0900
120.1283 -@@ -403,6 +403,27 @@
120.1284 -    png_byte filter_type;
120.1285 - #endif
120.1286 - 
120.1287 -+#ifdef PNG_APNG_SUPPORTED
120.1288 -+   png_uint_32 apng_flags;
120.1289 -+   png_uint_32 next_seq_num;         /* next fcTL/fdAT chunk sequence number */
120.1290 -+   png_uint_32 first_frame_width;
120.1291 -+   png_uint_32 first_frame_height;
120.1292 -+
120.1293 -+#ifdef PNG_READ_APNG_SUPPORTED
120.1294 -+   png_uint_32 num_frames_read;      /* incremented after all image data of */
120.1295 -+                                     /* a frame is read */
120.1296 -+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
120.1297 -+   png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
120.1298 -+   png_progressive_frame_ptr frame_end_fn;  /* frame data read callback */
120.1299 -+#endif
120.1300 -+#endif
120.1301 -+
120.1302 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1303 -+   png_uint_32 num_frames_to_write;
120.1304 -+   png_uint_32 num_frames_written;
120.1305 -+#endif
120.1306 -+#endif /* PNG_APNG_SUPPORTED */
120.1307 -+
120.1308 - /* New members added in libpng-1.2.0 */
120.1309 - 
120.1310 - /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
120.1311 -diff -Naru libpng-1.6.35.org/pngtest.c libpng-1.6.35/pngtest.c
120.1312 ---- libpng-1.6.35.org/pngtest.c	2018-07-21 19:16:37.188143186 +0900
120.1313 -+++ libpng-1.6.35/pngtest.c	2018-07-21 19:16:16.213354917 +0900
120.1314 -@@ -875,6 +875,10 @@
120.1315 -    volatile int num_passes;
120.1316 -    int pass;
120.1317 -    int bit_depth, color_type;
120.1318 -+#ifdef PNG_APNG_SUPPORTED
120.1319 -+   png_uint_32 num_frames;
120.1320 -+   png_uint_32 num_plays;
120.1321 -+#endif
120.1322 - 
120.1323 -    row_buf = NULL;
120.1324 -    error_parameters.file_name = inname;
120.1325 -@@ -1381,6 +1385,22 @@
120.1326 -       }
120.1327 -    }
120.1328 - #endif
120.1329 -+
120.1330 -+#ifdef PNG_APNG_SUPPORTED
120.1331 -+   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
120.1332 -+   {
120.1333 -+      if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays))
120.1334 -+      {
120.1335 -+         png_byte is_hidden;
120.1336 -+         pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)",
120.1337 -+                    num_frames, num_plays);
120.1338 -+         png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays);
120.1339 -+         is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr);
120.1340 -+         png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden);
120.1341 -+      }
120.1342 -+   }
120.1343 -+#endif
120.1344 -+
120.1345 - #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
120.1346 -    {
120.1347 -       png_unknown_chunkp unknowns;
120.1348 -@@ -1461,6 +1481,110 @@
120.1349 -    t_misc += (t_stop - t_start);
120.1350 -    t_start = t_stop;
120.1351 - #endif
120.1352 -+#ifdef PNG_APNG_SUPPORTED
120.1353 -+   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
120.1354 -+   {
120.1355 -+      png_uint_32 frame;
120.1356 -+      for (frame = 0; frame < num_frames; frame++)
120.1357 -+      {
120.1358 -+         png_uint_32 frame_width;
120.1359 -+         png_uint_32 frame_height;
120.1360 -+         png_uint_32 x_offset;
120.1361 -+         png_uint_32 y_offset;
120.1362 -+         png_uint_16 delay_num;
120.1363 -+         png_uint_16 delay_den;
120.1364 -+         png_byte dispose_op;
120.1365 -+         png_byte blend_op;
120.1366 -+         png_read_frame_head(read_ptr, read_info_ptr);
120.1367 -+         if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL))
120.1368 -+         {
120.1369 -+            png_get_next_frame_fcTL(read_ptr, read_info_ptr,
120.1370 -+                                    &frame_width, &frame_height,
120.1371 -+                                    &x_offset, &y_offset,
120.1372 -+                                    &delay_num, &delay_den,
120.1373 -+                                    &dispose_op, &blend_op);
120.1374 -+         }
120.1375 -+         else
120.1376 -+         {
120.1377 -+            frame_width = width;
120.1378 -+            frame_height = height;
120.1379 -+            x_offset = 0;
120.1380 -+            y_offset = 0;
120.1381 -+            delay_num = 1;
120.1382 -+            delay_den = 1;
120.1383 -+            dispose_op = PNG_DISPOSE_OP_NONE;
120.1384 -+            blend_op = PNG_BLEND_OP_SOURCE;
120.1385 -+         }
120.1386 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1387 -+         png_write_frame_head(write_ptr, write_info_ptr, (png_bytepp)&row_buf,
120.1388 -+                              frame_width, frame_height,
120.1389 -+                              x_offset, y_offset,
120.1390 -+                              delay_num, delay_den,
120.1391 -+                              dispose_op, blend_op);
120.1392 -+#endif
120.1393 -+         for (pass = 0; pass < num_passes; pass++)
120.1394 -+         {
120.1395 -+#           ifdef calc_pass_height
120.1396 -+               png_uint_32 pass_height;
120.1397 -+
120.1398 -+               if (num_passes == 7) /* interlaced */
120.1399 -+               {
120.1400 -+                  if (PNG_PASS_COLS(frame_width, pass) > 0)
120.1401 -+                     pass_height = PNG_PASS_ROWS(frame_height, pass);
120.1402 -+
120.1403 -+                  else
120.1404 -+                     pass_height = 0;
120.1405 -+               }
120.1406 -+
120.1407 -+               else /* not interlaced */
120.1408 -+                  pass_height = frame_height;
120.1409 -+#           else
120.1410 -+#              define pass_height frame_height
120.1411 -+#           endif
120.1412 -+
120.1413 -+            pngtest_debug1("Writing row data for pass %d", pass);
120.1414 -+            for (y = 0; y < pass_height; y++)
120.1415 -+            {
120.1416 -+#ifndef SINGLE_ROWBUF_ALLOC
120.1417 -+               pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
120.1418 -+
120.1419 -+               row_buf = (png_bytep)png_malloc(read_ptr,
120.1420 -+                  png_get_rowbytes(read_ptr, read_info_ptr));
120.1421 -+
120.1422 -+               pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
120.1423 -+                  (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
120.1424 -+
120.1425 -+#endif /* !SINGLE_ROWBUF_ALLOC */
120.1426 -+               png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
120.1427 -+
120.1428 -+#ifdef PNG_WRITE_SUPPORTED
120.1429 -+#ifdef PNGTEST_TIMING
120.1430 -+               t_stop = (float)clock();
120.1431 -+               t_decode += (t_stop - t_start);
120.1432 -+               t_start = t_stop;
120.1433 -+#endif
120.1434 -+               png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
120.1435 -+#ifdef PNGTEST_TIMING
120.1436 -+               t_stop = (float)clock();
120.1437 -+               t_encode += (t_stop - t_start);
120.1438 -+               t_start = t_stop;
120.1439 -+#endif
120.1440 -+#endif /* PNG_WRITE_SUPPORTED */
120.1441 -+
120.1442 -+#ifndef SINGLE_ROWBUF_ALLOC
120.1443 -+               pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
120.1444 -+               png_free(read_ptr, row_buf);
120.1445 -+               row_buf = NULL;
120.1446 -+#endif /* !SINGLE_ROWBUF_ALLOC */
120.1447 -+            }
120.1448 -+         }
120.1449 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1450 -+         png_write_frame_tail(write_ptr, write_info_ptr);
120.1451 -+#endif
120.1452 -+      }
120.1453 -+   }
120.1454 -+   else
120.1455 -+#endif
120.1456 -    for (pass = 0; pass < num_passes; pass++)
120.1457 -    {
120.1458 - #     ifdef calc_pass_height
120.1459 -diff -Naru libpng-1.6.35.org/pngwrite.c libpng-1.6.35/pngwrite.c
120.1460 ---- libpng-1.6.35.org/pngwrite.c	2018-07-21 19:16:37.188143186 +0900
120.1461 -+++ libpng-1.6.35/pngwrite.c	2018-07-21 19:16:16.211354747 +0900
120.1462 -@@ -128,6 +128,10 @@
120.1463 -        * the application continues writing the PNG.  So check the 'invalid'
120.1464 -        * flag here too.
120.1465 -        */
120.1466 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1467 -+      if (info_ptr->valid & PNG_INFO_acTL)
120.1468 -+         png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
120.1469 -+#endif
120.1470 - #ifdef PNG_GAMMA_SUPPORTED
120.1471 - #  ifdef PNG_WRITE_gAMA_SUPPORTED
120.1472 -       if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
120.1473 -@@ -370,6 +374,11 @@
120.1474 -       png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
120.1475 - #endif
120.1476 - 
120.1477 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1478 -+   if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
120.1479 -+      png_error(png_ptr, "Not enough frames written");
120.1480 -+#endif
120.1481 -+
120.1482 -    /* See if user wants us to write information chunks */
120.1483 -    if (info_ptr != NULL)
120.1484 -    {
120.1485 -@@ -1461,6 +1470,43 @@
120.1486 - }
120.1487 - #endif
120.1488 - 
120.1489 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1490 -+void PNGAPI
120.1491 -+png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
120.1492 -+    png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
120.1493 -+    png_uint_32 x_offset, png_uint_32 y_offset,
120.1494 -+    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
120.1495 -+    png_byte blend_op)
120.1496 -+{
120.1497 -+    png_debug(1, "in png_write_frame_head");
120.1498 -+
120.1499 -+    /* there is a chance this has been set after png_write_info was called,
120.1500 -+    * so it would be set but not written. is there a way to be sure? */
120.1501 -+    if (!(info_ptr->valid & PNG_INFO_acTL))
120.1502 -+        png_error(png_ptr, "png_write_frame_head(): acTL not set");
120.1503 -+
120.1504 -+    png_write_reset(png_ptr);
120.1505 -+
120.1506 -+    png_write_reinit(png_ptr, info_ptr, width, height);
120.1507 -+
120.1508 -+    if ( !(png_ptr->num_frames_written == 0 &&
120.1509 -+           (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
120.1510 -+        png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
120.1511 -+                       delay_num, delay_den, dispose_op, blend_op);
120.1512 -+
120.1513 -+    PNG_UNUSED(row_pointers)
120.1514 -+}
120.1515 -+
120.1516 -+void PNGAPI
120.1517 -+png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
120.1518 -+{
120.1519 -+    png_debug(1, "in png_write_frame_tail");
120.1520 -+
120.1521 -+    png_ptr->num_frames_written++;
120.1522 -+
120.1523 -+    PNG_UNUSED(info_ptr)
120.1524 -+}
120.1525 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
120.1526 - 
120.1527 - #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
120.1528 - /* Initialize the write structure - general purpose utility. */
120.1529 -diff -Naru libpng-1.6.35.org/pngwutil.c libpng-1.6.35/pngwutil.c
120.1530 ---- libpng-1.6.35.org/pngwutil.c	2018-07-21 19:16:37.189143271 +0900
120.1531 -+++ libpng-1.6.35/pngwutil.c	2018-07-21 19:16:16.303362592 +0900
120.1532 -@@ -821,6 +821,11 @@
120.1533 -    /* Write the chunk */
120.1534 -    png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
120.1535 - 
120.1536 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1537 -+   png_ptr->first_frame_width = width;
120.1538 -+   png_ptr->first_frame_height = height;
120.1539 -+#endif
120.1540 -+
120.1541 -    if ((png_ptr->do_filter) == PNG_NO_FILTERS)
120.1542 -    {
120.1543 -       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
120.1544 -@@ -1002,8 +1007,17 @@
120.1545 -                optimize_cmf(data, png_image_size(png_ptr));
120.1546 - #endif
120.1547 - 
120.1548 --         if (size > 0)
120.1549 --            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
120.1550 -+            if (size > 0)
120.1551 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1552 -+            {
120.1553 -+               if (png_ptr->num_frames_written == 0)
120.1554 -+#endif
120.1555 -+               png_write_complete_chunk(png_ptr, png_IDAT, data, size);
120.1556 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1557 -+               else
120.1558 -+                  png_write_fdAT(png_ptr, data, size);
120.1559 -+            }
120.1560 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
120.1561 -          png_ptr->mode |= PNG_HAVE_IDAT;
120.1562 - 
120.1563 -          png_ptr->zstream.next_out = data;
120.1564 -@@ -1050,7 +1064,17 @@
120.1565 - #endif
120.1566 - 
120.1567 -          if (size > 0)
120.1568 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1569 -+         {
120.1570 -+            if (png_ptr->num_frames_written == 0)
120.1571 -+#endif
120.1572 -             png_write_complete_chunk(png_ptr, png_IDAT, data, size);
120.1573 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1574 -+            else
120.1575 -+               png_write_fdAT(png_ptr, data, size);
120.1576 -+         }
120.1577 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
120.1578 -+
120.1579 -          png_ptr->zstream.avail_out = 0;
120.1580 -          png_ptr->zstream.next_out = NULL;
120.1581 -          png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
120.1582 -@@ -1885,6 +1909,82 @@
120.1583 - }
120.1584 - #endif
120.1585 - 
120.1586 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1587 -+void /* PRIVATE */
120.1588 -+png_write_acTL(png_structp png_ptr,
120.1589 -+    png_uint_32 num_frames, png_uint_32 num_plays)
120.1590 -+{
120.1591 -+    png_byte buf[8];
120.1592 -+
120.1593 -+    png_debug(1, "in png_write_acTL");
120.1594 -+
120.1595 -+    png_ptr->num_frames_to_write = num_frames;
120.1596 -+
120.1597 -+    if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
120.1598 -+        num_frames--;
120.1599 -+
120.1600 -+    png_save_uint_32(buf, num_frames);
120.1601 -+    png_save_uint_32(buf + 4, num_plays);
120.1602 -+
120.1603 -+    png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
120.1604 -+}
120.1605 -+
120.1606 -+void /* PRIVATE */
120.1607 -+png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
120.1608 -+    png_uint_32 x_offset, png_uint_32 y_offset,
120.1609 -+    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
120.1610 -+    png_byte blend_op)
120.1611 -+{
120.1612 -+    png_byte buf[26];
120.1613 -+
120.1614 -+    png_debug(1, "in png_write_fcTL");
120.1615 -+
120.1616 -+    if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
120.1617 -+        png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
120.1618 -+    if (png_ptr->num_frames_written == 0 &&
120.1619 -+        (width != png_ptr->first_frame_width ||
120.1620 -+         height != png_ptr->first_frame_height))
120.1621 -+        png_error(png_ptr, "width and/or height in the first frame's fcTL "
120.1622 -+                           "don't match the ones in IHDR");
120.1623 -+
120.1624 -+    /* more error checking */
120.1625 -+    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
120.1626 -+                             delay_num, delay_den, dispose_op, blend_op);
120.1627 -+
120.1628 -+    png_save_uint_32(buf, png_ptr->next_seq_num);
120.1629 -+    png_save_uint_32(buf + 4, width);
120.1630 -+    png_save_uint_32(buf + 8, height);
120.1631 -+    png_save_uint_32(buf + 12, x_offset);
120.1632 -+    png_save_uint_32(buf + 16, y_offset);
120.1633 -+    png_save_uint_16(buf + 20, delay_num);
120.1634 -+    png_save_uint_16(buf + 22, delay_den);
120.1635 -+    buf[24] = dispose_op;
120.1636 -+    buf[25] = blend_op;
120.1637 -+
120.1638 -+    png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
120.1639 -+
120.1640 -+    png_ptr->next_seq_num++;
120.1641 -+}
120.1642 -+
120.1643 -+void /* PRIVATE */
120.1644 -+png_write_fdAT(png_structp png_ptr,
120.1645 -+    png_const_bytep data, png_size_t length)
120.1646 -+{
120.1647 -+    png_byte buf[4];
120.1648 -+
120.1649 -+    png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
120.1650 -+
120.1651 -+    png_save_uint_32(buf, png_ptr->next_seq_num);
120.1652 -+    png_write_chunk_data(png_ptr, buf, 4);
120.1653 -+
120.1654 -+    png_write_chunk_data(png_ptr, data, length);
120.1655 -+
120.1656 -+    png_write_chunk_end(png_ptr);
120.1657 -+
120.1658 -+    png_ptr->next_seq_num++;
120.1659 -+}
120.1660 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
120.1661 -+
120.1662 - /* Initializes the row writing capability of libpng */
120.1663 - void /* PRIVATE */
120.1664 - png_write_start_row(png_structrp png_ptr)
120.1665 -@@ -2778,4 +2878,39 @@
120.1666 -    }
120.1667 - #endif /* WRITE_FLUSH */
120.1668 - }
120.1669 -+
120.1670 -+#ifdef PNG_WRITE_APNG_SUPPORTED
120.1671 -+void /* PRIVATE */
120.1672 -+png_write_reset(png_structp png_ptr)
120.1673 -+{
120.1674 -+    png_ptr->row_number = 0;
120.1675 -+    png_ptr->pass = 0;
120.1676 -+    png_ptr->mode &= ~PNG_HAVE_IDAT;
120.1677 -+}
120.1678 -+
120.1679 -+void /* PRIVATE */
120.1680 -+png_write_reinit(png_structp png_ptr, png_infop info_ptr,
120.1681 -+                 png_uint_32 width, png_uint_32 height)
120.1682 -+{
120.1683 -+    if (png_ptr->num_frames_written == 0 &&
120.1684 -+        (width != png_ptr->first_frame_width ||
120.1685 -+         height != png_ptr->first_frame_height))
120.1686 -+        png_error(png_ptr, "width and/or height in the first frame's fcTL "
120.1687 -+                           "don't match the ones in IHDR");
120.1688 -+    if (width > png_ptr->first_frame_width ||
120.1689 -+        height > png_ptr->first_frame_height)
120.1690 -+        png_error(png_ptr, "width and/or height for a frame greater than"
120.1691 -+                           "the ones in IHDR");
120.1692 -+
120.1693 -+    png_set_IHDR(png_ptr, info_ptr, width, height,
120.1694 -+                 info_ptr->bit_depth, info_ptr->color_type,
120.1695 -+                 info_ptr->interlace_type, info_ptr->compression_type,
120.1696 -+                 info_ptr->filter_type);
120.1697 -+
120.1698 -+    png_ptr->width = width;
120.1699 -+    png_ptr->height = height;
120.1700 -+    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
120.1701 -+    png_ptr->usr_width = png_ptr->width;
120.1702 -+}
120.1703 -+#endif /* PNG_WRITE_APNG_SUPPORTED */
120.1704 - #endif /* WRITE */
120.1705 -diff -Naru libpng-1.6.35.org/scripts/symbols.def libpng-1.6.35/scripts/symbols.def
120.1706 ---- libpng-1.6.35.org/scripts/symbols.def	2018-07-21 19:16:37.192143527 +0900
120.1707 -+++ libpng-1.6.35/scripts/symbols.def	2018-07-21 19:16:16.206354321 +0900
120.1708 -@@ -254,3 +254,23 @@
120.1709 -  png_set_eXIf @247
120.1710 -  png_get_eXIf_1 @248
120.1711 -  png_set_eXIf_1 @249
120.1712 -+ png_get_acTL @250
120.1713 -+ png_set_acTL @251
120.1714 -+ png_get_num_frames @252
120.1715 -+ png_get_num_plays @253
120.1716 -+ png_get_next_frame_fcTL @254
120.1717 -+ png_set_next_frame_fcTL @255
120.1718 -+ png_get_next_frame_width @256
120.1719 -+ png_get_next_frame_height @257
120.1720 -+ png_get_next_frame_x_offset @258
120.1721 -+ png_get_next_frame_y_offset @259
120.1722 -+ png_get_next_frame_delay_num @260
120.1723 -+ png_get_next_frame_delay_den @261
120.1724 -+ png_get_next_frame_dispose_op @262
120.1725 -+ png_get_next_frame_blend_op @263
120.1726 -+ png_get_first_frame_is_hidden @264
120.1727 -+ png_set_first_frame_is_hidden @265
120.1728 -+ png_read_frame_head @266
120.1729 -+ png_set_progressive_frame_fn @267
120.1730 -+ png_write_frame_head @268
120.1731 -+ png_write_frame_tail @269
   121.1 --- a/libpng16/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   121.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.3 @@ -1,5 +0,0 @@
   121.4 -# This patch listed in the BLFS page, was downloaded using following address and
   121.5 -# unzipped:
   121.6 -# https://downloads.sourceforge.net/sourceforge/libpng-apng/libpng-1.6.35-apng.patch.gz
   121.7 -
   121.8 --p1|libpng-1.6.35-apng.patch
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/libsm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   122.3 @@ -0,0 +1,1 @@
   122.4 +../xorg/.icon.png
   122.5 \ No newline at end of file
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/libsm/receipt	Thu Dec 20 17:55:43 2018 +0200
   123.3 @@ -0,0 +1,34 @@
   123.4 +# SliTaz package receipt v2.
   123.5 +
   123.6 +PACKAGE="libsm"
   123.7 +VERSION="1.2.3"
   123.8 +CATEGORY="x-window"
   123.9 +SHORT_DESC="Session Management library"
  123.10 +MAINTAINER="devel@slitaz.org"
  123.11 +LICENSE="MIT"
  123.12 +WEB_SITE="https://www.x.org/wiki/"
  123.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  123.14 +
  123.15 +TARBALL="libSM-$VERSION.tar.bz2"
  123.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  123.17 +TARBALL_SHA1="437d7b13fa2eba325df3a106f177df46ccec6546"
  123.18 +
  123.19 +BUILD_DEPENDS="libice-dev xtrans util-linux-uuid-dev"
  123.20 +SPLIT="$PACKAGE-dev"
  123.21 +
  123.22 +DEPENDS_std="util-linux-uuid libice"
  123.23 +DEPENDS_dev="$PACKAGE libice-dev xorgproto"
  123.24 +
  123.25 +compile_rules() {
  123.26 +	./configure \
  123.27 +		--disable-static \
  123.28 +		$CONFIGURE_ARGS &&
  123.29 +	fix libtool &&
  123.30 +	make &&
  123.31 +	make install
  123.32 +}
  123.33 +
  123.34 +TAGS="Xorg"
  123.35 +
  123.36 +PROVIDE_std="xorg-libSM"
  123.37 +PROVIDE_dev="xorg-libSM-dev"
   124.1 --- a/libva-intel-driver/receipt	Thu Dec 13 00:46:54 2018 +0200
   124.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.3 @@ -1,29 +0,0 @@
   124.4 -# SliTaz package receipt v2.
   124.5 -
   124.6 -PACKAGE="libva-intel-driver"
   124.7 -VERSION="1.7.3"
   124.8 -CATEGORY="x-window"
   124.9 -SHORT_DESC="VA Intel driver"
  124.10 -MAINTAINER="al.bobylev@gmail.com"
  124.11 -LICENSE="other"
  124.12 -WEB_SITE="https://www.freedesktop.org/wiki/Software/vaapi/"
  124.13 -
  124.14 -TARBALL="$PACKAGE-$VERSION.tar.bz2"
  124.15 -WGET_URL="https://www.freedesktop.org/software/vaapi/releases/$PACKAGE/$TARBALL"
  124.16 -
  124.17 -BUILD_DEPENDS="autoconf automake libtool python libdrm-dev libva-dev \
  124.18 -xorg-libpciaccess-dev xorg-libX11-dev"
  124.19 -
  124.20 -compile_rules() {
  124.21 -	autoreconf -fi &&
  124.22 -
  124.23 -	./configure $CONFIGURE_ARGS &&
  124.24 -	fix libtool &&
  124.25 -	make &&
  124.26 -	make install
  124.27 -}
  124.28 -
  124.29 -genpkg_rules() {
  124.30 -	copy @std
  124.31 -	DEPENDS="libdrm libdrm-intel xorg-libpciaccess"
  124.32 -}
   125.1 --- a/libva/receipt	Thu Dec 13 00:46:54 2018 +0200
   125.2 +++ b/libva/receipt	Thu Dec 20 17:55:43 2018 +0200
   125.3 @@ -1,37 +1,29 @@
   125.4  # SliTaz package receipt v2.
   125.5  
   125.6  PACKAGE="libva"
   125.7 -VERSION="1.8.2"
   125.8 +VERSION="2.3.0"
   125.9  CATEGORY="x-window"
  125.10  SHORT_DESC="Userspace Video Acceleration (VA) library"
  125.11  MAINTAINER="al.bobylev@gmail.com"
  125.12  LICENSE="MIT"
  125.13 -WEB_SITE="https://www.freedesktop.org/wiki/Software/vaapi/"
  125.14 +WEB_SITE="https://github.com/intel/libva"
  125.15 +# https://www.freedesktop.org/wiki/Software/vaapi/ - old
  125.16 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#libva"
  125.17  
  125.18  TARBALL="$PACKAGE-$VERSION.tar.bz2"
  125.19 -WGET_URL="https://www.freedesktop.org/software/vaapi/releases/libva/$TARBALL"
  125.20 +WGET_URL="https://github.com/intel/libva/releases/download/$VERSION/$TARBALL"
  125.21 +TARBALL_SHA1="e1138529355cce78fa2edc7c5b1c5aeb40dd0ce5"
  125.22  
  125.23 -BUILD_DEPENDS="libdrm-dev xorg-libX11-dev xorg-libXext-dev xorg-libXfixes-dev \
  125.24 -mesa-dev expat-dev xorg-libxshmfence-dev wayland-dev"
  125.25 +BUILD_DEPENDS="libdrm-dev libx11-dev libxext-dev libxfixes-dev mesa-dev \
  125.26 +expat-dev libxshmfence-dev wayland-dev"
  125.27  SPLIT="$PACKAGE-dev"
  125.28  
  125.29 +DEPENDS_std="libdrm libx11 libxext libxfixes mesa wayland"
  125.30 +DEPENDS_dev="$PACKAGE wayland-dev"
  125.31 +
  125.32  compile_rules() {
  125.33  	./configure $CONFIGURE_ARGS &&
  125.34  	fix libtool &&
  125.35  	make &&
  125.36  	make install
  125.37  }
  125.38 -
  125.39 -genpkg_rules() {
  125.40 -	case $PACKAGE in
  125.41 -		libva)
  125.42 -			copy @std
  125.43 -			DEPENDS="libdrm mesa wayland xorg-libX11 xorg-libXext \
  125.44 -			xorg-libXfixes"
  125.45 -			;;
  125.46 -		*-dev)
  125.47 -			copy @dev
  125.48 -			DEPENDS="libva wayland-dev"
  125.49 -			;;
  125.50 -	esac
  125.51 -}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/libvdpau-va-gl/receipt	Thu Dec 20 17:55:43 2018 +0200
   126.3 @@ -0,0 +1,31 @@
   126.4 +# SliTaz package receipt v2.
   126.5 +
   126.6 +PACKAGE="libvdpau-va-gl"
   126.7 +VERSION="0.4.2"
   126.8 +CATEGORY="x-window"
   126.9 +SHORT_DESC="VDPAU driver with OpenGL/VAAPI backend"
  126.10 +MAINTAINER="al.bobylev@gmail.com"
  126.11 +LICENSE="MIT"
  126.12 +WEB_SITE="https://github.com/i-rinat/libvdpau-va-gl"
  126.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#libvdpau-va-gl"
  126.14 +
  126.15 +TARBALL="$PACKAGE-$VERSION.tar.gz"
  126.16 +WGET_URL="https://github.com/i-rinat/libvdpau-va-gl/releases/download/v$VERSION/$TARBALL"
  126.17 +TARBALL_SHA1="a9ae1851a6f12312a98fc89d12bcb2de1f2af9c8"
  126.18 +
  126.19 +BUILD_DEPENDS="cmake libx11-dev libva-dev mesa-dev"
  126.20 +DEPENDS="libva libx11 mesa"
  126.21 +
  126.22 +compile_rules() {
  126.23 +	mkdir build
  126.24 +	cd    build
  126.25 +
  126.26 +	cmake \
  126.27 +		-DCMAKE_BUILD_TYPE=Release \
  126.28 +		-DCMAKE_INSTALL_PREFIX=/usr \
  126.29 +		.. &&
  126.30 +	make &&
  126.31 +	make install || return 1
  126.32 +
  126.33 +	install -Dm755 $stuff/xorg.sh $install/etc/profile.d/xorg.sh
  126.34 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/libvdpau-va-gl/stuff/xorg.sh	Thu Dec 20 17:55:43 2018 +0200
   127.3 @@ -0,0 +1,1 @@
   127.4 +export VDPAU_DRIVER=va_gl
   128.1 --- a/libvdpau/receipt	Thu Dec 13 00:46:54 2018 +0200
   128.2 +++ b/libvdpau/receipt	Thu Dec 20 17:55:43 2018 +0200
   128.3 @@ -7,32 +7,21 @@
   128.4  MAINTAINER="al.bobylev@gmail.com"
   128.5  LICENSE="MIT"
   128.6  WEB_SITE="https://www.freedesktop.org/wiki/Software/VDPAU/"
   128.7 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#libvdpau"
   128.8  
   128.9  TARBALL="$PACKAGE-$VERSION.tar.bz2"
  128.10  WGET_URL="http://people.freedesktop.org/~aplattner/vdpau/$TARBALL"
  128.11 +TARBALL_SHA1="86516e2a962fd34f65d49115d6ddf15fd912f579"
  128.12  
  128.13 -BUILD_DEPENDS="xorg-libX11-dev xorg-xorgproto xorg-libXext-dev"
  128.14 +BUILD_DEPENDS="libx11-dev xorgproto libxext-dev"
  128.15  SPLIT="$PACKAGE-dev"
  128.16  
  128.17 +DEPENDS_std="libx11 libxau libxdmcp libxext libxcb"
  128.18 +DEPENDS_dev="$PACKAGE libx11-dev libxau-dev libxdmcp-dev libxext-dev libxcb-dev"
  128.19 +
  128.20  compile_rules() {
  128.21  	./configure $CONFIGURE_ARGS &&
  128.22  	fix libtool &&
  128.23  	make &&
  128.24  	make install
  128.25  }
  128.26 -
  128.27 -genpkg_rules() {
  128.28 -	case $PACKAGE in
  128.29 -		libvdpau)
  128.30 -			copy @std
  128.31 -			DEPENDS="xorg-libX11 xorg-libXau xorg-libXdmcp xorg-libXext \
  128.32 -			xorg-libxcb"
  128.33 -			;;
  128.34 -		*-dev)
  128.35 -			copy @dev
  128.36 -			DEPENDS="libvdpau xorg-libX11-dev xorg-libXau-dev \
  128.37 -			xorg-libXdmcp-dev xorg-libXext-dev xorg-libxcb-dev"
  128.38 -			;;
  128.39 -	esac
  128.40 -}
  128.41 -
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/libx11/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   129.3 @@ -0,0 +1,1 @@
   129.4 +../xorg/.icon.png
   129.5 \ No newline at end of file
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/libx11/receipt	Thu Dec 20 17:55:43 2018 +0200
   130.3 @@ -0,0 +1,40 @@
   130.4 +# SliTaz package receipt v2.
   130.5 +
   130.6 +PACKAGE="libx11"
   130.7 +VERSION="1.6.7"
   130.8 +CATEGORY="x-window"
   130.9 +SHORT_DESC="X11 Client library"
  130.10 +MAINTAINER="devel@slitaz.org"
  130.11 +LICENSE="MIT"
  130.12 +WEB_SITE="https://www.x.org/wiki/"
  130.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  130.14 +
  130.15 +TARBALL="libX11-$VERSION.tar.bz2"
  130.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  130.17 +TARBALL_SHA1="5076f7853713d7db958a05f6fd1c18f7e111a0ad"
  130.18 +
  130.19 +BUILD_DEPENDS="xtrans libxcb-dev xorgproto libxau-dev libxdmcp-dev perl"
  130.20 +SPLIT="$PACKAGE-dev"
  130.21 +
  130.22 +COPY_std="*.so* XErrorDB Xcms.txt compose.dir locale.alias locale.dir \
  130.23 +C/ en_US.UTF-8/" # split -> locale-* packages
  130.24 +
  130.25 +DEPENDS_std="libxcb"
  130.26 +DEPENDS_dev="$PACKAGE xorgproto libxcb-dev"
  130.27 +
  130.28 +compile_rules() {
  130.29 +	./configure \
  130.30 +		--disable-static \
  130.31 +		$CONFIGURE_ARGS &&
  130.32 +	fix libtool &&
  130.33 +	make &&
  130.34 +	make install
  130.35 +
  130.36 +	# strip whitespace - reduce size
  130.37 +	find $install -name Compose -exec sed -i 's|\t| |g; s|  *| |g; /^$/d' '{}' \+
  130.38 +}
  130.39 +
  130.40 +TAGS="Xorg"
  130.41 +
  130.42 +PROVIDE_std="xorg-libX11"
  130.43 +PROVIDE_dev="xorg-libX11-dev"
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/libxau/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   131.3 @@ -0,0 +1,1 @@
   131.4 +../xorg/.icon.png
   131.5 \ No newline at end of file
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/libxau/receipt	Thu Dec 20 17:55:43 2018 +0200
   132.3 @@ -0,0 +1,33 @@
   132.4 +# SliTaz package receipt v2.
   132.5 +
   132.6 +PACKAGE="libxau"
   132.7 +VERSION="1.0.8"
   132.8 +CATEGORY="x-window"
   132.9 +SHORT_DESC="X Authorization routines"
  132.10 +MAINTAINER="devel@slitaz.org"
  132.11 +LICENSE="MIT"
  132.12 +WEB_SITE="https://www.x.org/wiki/"
  132.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libXau.html"
  132.14 +
  132.15 +TARBALL="libXau-$VERSION.tar.bz2"
  132.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  132.17 +TARBALL_SHA1="d9512d6869e022d4e9c9d33f6d6199eda4ad096b"
  132.18 +
  132.19 +BUILD_DEPENDS="xorgproto"
  132.20 +SPLIT="$PACKAGE-dev"
  132.21 +
  132.22 +DEPENDS_dev="$PACKAGE xorgproto"
  132.23 +
  132.24 +compile_rules() {
  132.25 +	./configure \
  132.26 +		--disable-static \
  132.27 +		$CONFIGURE_ARGS &&
  132.28 +	fix libtool &&
  132.29 +	make &&
  132.30 +	make install
  132.31 +}
  132.32 +
  132.33 +TAGS="Xorg"
  132.34 +
  132.35 +PROVIDE_std="xorg-libXau"
  132.36 +PROVIDE_dev="xorg-libXau-dev"
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/libxaw/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   133.3 @@ -0,0 +1,1 @@
   133.4 +../xorg/.icon.png
   133.5 \ No newline at end of file
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/libxaw/receipt	Thu Dec 20 17:55:43 2018 +0200
   134.3 @@ -0,0 +1,36 @@
   134.4 +# SliTaz package receipt v2.
   134.5 +
   134.6 +PACKAGE="libxaw"
   134.7 +VERSION="1.0.13"
   134.8 +CATEGORY="x-window"
   134.9 +SHORT_DESC="Athena Widgets toolkit"
  134.10 +MAINTAINER="devel@slitaz.org"
  134.11 +LICENSE="MIT"
  134.12 +WEB_SITE="https://www.x.org/wiki/"
  134.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  134.14 +
  134.15 +TARBALL="libXaw-$VERSION.tar.bz2"
  134.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  134.17 +TARBALL_SHA1="15f891fb88aae966b3064dcc1510790a0ebc75a0"
  134.18 +
  134.19 +BUILD_DEPENDS="libxmu-dev libxpm-dev util-linux-uuid-dev"
  134.20 +SPLIT="$PACKAGE-dev"
  134.21 +
  134.22 +DEPENDS_std="libx11 libxext libxmu libxpm libxt"
  134.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxmu-dev libxpm-dev libxt-dev \
  134.24 +xorgproto"
  134.25 +
  134.26 +compile_rules() {
  134.27 +	./configure \
  134.28 +		--disable-static \
  134.29 +		--disable-xaw6 \
  134.30 +		$CONFIGURE_ARGS &&
  134.31 +	fix libtool &&
  134.32 +	make &&
  134.33 +	make install
  134.34 +}
  134.35 +
  134.36 +TAGS="Xorg"
  134.37 +
  134.38 +PROVIDE_std="xorg-libXaw"
  134.39 +PROVIDE_dev="xorg-libXaw-dev"
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/libxaw3d/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   135.3 @@ -0,0 +1,1 @@
   135.4 +../xorg/.icon.png
   135.5 \ No newline at end of file
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/libxaw3d/receipt	Thu Dec 20 17:55:43 2018 +0200
   136.3 @@ -0,0 +1,31 @@
   136.4 +# SliTaz package receipt v2.
   136.5 +
   136.6 +PACKAGE="libxaw3d"
   136.7 +VERSION="1.6.2"
   136.8 +CATEGORY="x-window"
   136.9 +SHORT_DESC="Xorg server module"
  136.10 +MAINTAINER="pascal.bellard@slitaz.org"
  136.11 +LICENSE="MIT"
  136.12 +WEB_SITE="https://www.x.org/wiki/"
  136.13 +
  136.14 +TARBALL="libXaw3d-$VERSION.tar.bz2"
  136.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  136.16 +TARBALL_SHA1="0b1db72e9d5be0edae57cda213860c0289fac12f"
  136.17 +
  136.18 +BUILD_DEPENDS="libxmu-dev util-linux-uuid-dev"
  136.19 +SPLIT="$PACKAGE-dev"
  136.20 +
  136.21 +DEPENDS_std="libx11 libxext libxmu libxt"
  136.22 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxmu-dev libxt-dev xorgproto"
  136.23 +
  136.24 +compile_rules() {
  136.25 +	./configure $CONFIGURE_ARGS &&
  136.26 +	fix libtool &&
  136.27 +	make &&
  136.28 +	make install
  136.29 +}
  136.30 +
  136.31 +TAGS="Xorg"
  136.32 +
  136.33 +PROVIDE_std="xorg-libXaw3d"
  136.34 +PROVIDE_dev="xorg-libXaw3d-dev"
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/libxcb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   137.3 @@ -0,0 +1,1 @@
   137.4 +../xorg/.icon.png
   137.5 \ No newline at end of file
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/libxcb/description.txt	Thu Dec 20 17:55:43 2018 +0200
   138.3 @@ -0,0 +1,3 @@
   138.4 +The X protocol C-language Binding (XCB) is a replacement for Xlib featuring
   138.5 +a small footprint, latency hiding, direct access to the protocol, improved
   138.6 +threading support, and extensibility.
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/libxcb/receipt	Thu Dec 20 17:55:43 2018 +0200
   139.3 @@ -0,0 +1,40 @@
   139.4 +# SliTaz package receipt v2.
   139.5 +
   139.6 +PACKAGE="libxcb"
   139.7 +VERSION="1.13.1"
   139.8 +CATEGORY="x-window"
   139.9 +SHORT_DESC="A C binding to the X11 protocol"
  139.10 +MAINTAINER="devel@slitaz.org"
  139.11 +LICENSE="MIT"
  139.12 +WEB_SITE="https://xcb.freedesktop.org/"
  139.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libxcb.html"
  139.14 +
  139.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  139.16 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  139.17 +TARBALL_SHA1="2ab17a1bb2a44e0a9cb0b26bcf899689ba1bbb3b"
  139.18 +
  139.19 +BUILD_DEPENDS="libxslt-dev xcb-proto libxau-dev libxdmcp-dev"
  139.20 +SPLIT="$PACKAGE-dev"
  139.21 +
  139.22 +DEPENDS_std="libxau libxdmcp"
  139.23 +DEPENDS_dev="$PACKAGE libxau-dev libxdmcp-dev"
  139.24 +
  139.25 +compile_rules() {
  139.26 +	sed -i "s|pthread-stubs||" configure
  139.27 +
  139.28 +	./configure \
  139.29 +		--disable-static \
  139.30 +		--enable-xinput \
  139.31 +		--enable-xprint \
  139.32 +		$CONFIGURE_ARGS &&
  139.33 +	fix libtool &&
  139.34 +	make &&
  139.35 +	make install || return 1
  139.36 +
  139.37 +	chown -R 0:0 $install
  139.38 +}
  139.39 +
  139.40 +TAGS="Xorg"
  139.41 +
  139.42 +PROVIDE_std="xorg-libxcb"
  139.43 +PROVIDE_dev="xorg-libxcb-dev"
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/libxcomposite/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   140.3 @@ -0,0 +1,1 @@
   140.4 +../xorg/.icon.png
   140.5 \ No newline at end of file
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/libxcomposite/receipt	Thu Dec 20 17:55:43 2018 +0200
   141.3 @@ -0,0 +1,34 @@
   141.4 +# SliTaz package receipt v2.
   141.5 +
   141.6 +PACKAGE="libxcomposite"
   141.7 +VERSION="0.4.4"
   141.8 +CATEGORY="x-window"
   141.9 +SHORT_DESC="Composite Extension"
  141.10 +MAINTAINER="devel@slitaz.org"
  141.11 +LICENSE="MIT"
  141.12 +WEB_SITE="https://www.x.org/wiki/"
  141.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  141.14 +
  141.15 +TARBALL="libXcomposite-$VERSION.tar.bz2"
  141.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  141.17 +TARBALL_SHA1="75fd0b996e56e12db1d84e9b63549c5c3f2631ca"
  141.18 +
  141.19 +BUILD_DEPENDS="xorgproto libxfixes-dev"
  141.20 +SPLIT="$PACKAGE-dev"
  141.21 +
  141.22 +DEPENDS_std="libx11"
  141.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev libxfixes-dev"
  141.24 +
  141.25 +compile_rules() {
  141.26 +	./configure \
  141.27 +		--disable-static \
  141.28 +		$CONFIGURE_ARGS &&
  141.29 +	fix libtool &&
  141.30 +	make &&
  141.31 +	make install
  141.32 +}
  141.33 +
  141.34 +TAGS="Xorg"
  141.35 +
  141.36 +PROVIDE_std="xorg-libXcomposite"
  141.37 +PROVIDE_dev="xorg-libXcomposite-dev"
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/libxcursor/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   142.3 @@ -0,0 +1,1 @@
   142.4 +../xorg/.icon.png
   142.5 \ No newline at end of file
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/libxcursor/receipt	Thu Dec 20 17:55:43 2018 +0200
   143.3 @@ -0,0 +1,34 @@
   143.4 +# SliTaz package receipt v2.
   143.5 +
   143.6 +PACKAGE="libxcursor"
   143.7 +VERSION="1.1.15"
   143.8 +CATEGORY="x-window"
   143.9 +SHORT_DESC="Cursor extension"
  143.10 +MAINTAINER="devel@slitaz.org"
  143.11 +LICENSE="MIT"
  143.12 +WEB_SITE="https://www.x.org/wiki/"
  143.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  143.14 +
  143.15 +TARBALL="libXcursor-$VERSION.tar.bz2"
  143.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  143.17 +TARBALL_SHA1="3e19f991f244b7fa31566adce7ead078424296cf"
  143.18 +
  143.19 +BUILD_DEPENDS="libxrender-dev libxfixes-dev"
  143.20 +SPLIT="$PACKAGE-dev"
  143.21 +
  143.22 +DEPENDS_std="libx11 libxfixes libxrender"
  143.23 +DEPENDS_dev="$PACKAGE libx11-dev libxfixes-dev libxrender-dev xorgproto"
  143.24 +
  143.25 +compile_rules() {
  143.26 +	./configure \
  143.27 +		--disable-static \
  143.28 +		$CONFIGURE_ARGS &&
  143.29 +	fix libtool &&
  143.30 +	make &&
  143.31 +	make install
  143.32 +}
  143.33 +
  143.34 +TAGS="Xorg"
  143.35 +
  143.36 +PROVIDE_std="xorg-libXcursor"
  143.37 +PROVIDE_dev="xorg-libXcursor-dev"
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/libxdamage/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   144.3 @@ -0,0 +1,1 @@
   144.4 +../xorg/.icon.png
   144.5 \ No newline at end of file
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/libxdamage/receipt	Thu Dec 20 17:55:43 2018 +0200
   145.3 @@ -0,0 +1,34 @@
   145.4 +# SliTaz package receipt v2.
   145.5 +
   145.6 +PACKAGE="libxdamage"
   145.7 +VERSION="1.1.4"
   145.8 +CATEGORY="x-window"
   145.9 +SHORT_DESC="Damage extension"
  145.10 +MAINTAINER="devel@slitaz.org"
  145.11 +LICENSE="MIT"
  145.12 +WEB_SITE="https://www.x.org/wiki/"
  145.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  145.14 +
  145.15 +TARBALL="libXdamage-$VERSION.tar.bz2"
  145.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  145.17 +TARBALL_SHA1="c3fc0f4b02dce2239bf46c82a5f06b06585720ae"
  145.18 +
  145.19 +BUILD_DEPENDS="xorgproto libxfixes-dev"
  145.20 +SPLIT="$PACKAGE-dev"
  145.21 +
  145.22 +DEPENDS_std="libx11"
  145.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev libxfixes-dev"
  145.24 +
  145.25 +compile_rules() {
  145.26 +	./configure \
  145.27 +		--disable-static \
  145.28 +		$CONFIGURE_ARGS &&
  145.29 +	fix libtool &&
  145.30 +	make &&
  145.31 +	make install
  145.32 +}
  145.33 +
  145.34 +TAGS="Xorg"
  145.35 +
  145.36 +PROVIDE_std="xorg-libXdamage"
  145.37 +PROVIDE_dev="xorg-libXdamage-dev"
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/libxdmcp/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   146.3 @@ -0,0 +1,1 @@
   146.4 +../xorg/.icon.png
   146.5 \ No newline at end of file
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/libxdmcp/receipt	Thu Dec 20 17:55:43 2018 +0200
   147.3 @@ -0,0 +1,33 @@
   147.4 +# SliTaz package receipt v2.
   147.5 +
   147.6 +PACKAGE="libxdmcp"
   147.7 +VERSION="1.1.2"
   147.8 +CATEGORY="x-window"
   147.9 +SHORT_DESC="X Display Manager Control Protocol routines"
  147.10 +MAINTAINER="devel@slitaz.org"
  147.11 +LICENSE="MIT"
  147.12 +WEB_SITE="https://www.x.org/wiki/"
  147.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libXdmcp.html"
  147.14 +
  147.15 +TARBALL="libXdmcp-$VERSION.tar.bz2"
  147.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  147.17 +TARBALL_SHA1="3c09eabb0617c275b5ab09fae021d279a4832cac"
  147.18 +
  147.19 +BUILD_DEPENDS="xorgproto"
  147.20 +SPLIT="$PACKAGE-dev"
  147.21 +
  147.22 +DEPENDS_dev="$PACKAGE xorgproto"
  147.23 +
  147.24 +compile_rules() {
  147.25 +	./configure \
  147.26 +		--disable-static \
  147.27 +		$CONFIGURE_ARGS &&
  147.28 +	fix libtool &&
  147.29 +	make &&
  147.30 +	make install
  147.31 +}
  147.32 +
  147.33 +TAGS="Xorg"
  147.34 +
  147.35 +PROVIDE_std="xorg-libXdmcp"
  147.36 +PROVIDE_dev="xorg-libXdmcp-dev"
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/libxext/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   148.3 @@ -0,0 +1,1 @@
   148.4 +../xorg/.icon.png
   148.5 \ No newline at end of file
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/libxext/receipt	Thu Dec 20 17:55:43 2018 +0200
   149.3 @@ -0,0 +1,34 @@
   149.4 +# SliTaz package receipt v2.
   149.5 +
   149.6 +PACKAGE="libxext"
   149.7 +VERSION="1.3.3"
   149.8 +CATEGORY="x-window"
   149.9 +SHORT_DESC="Common X Extensions library"
  149.10 +MAINTAINER="devel@slitaz.org"
  149.11 +LICENSE="MIT"
  149.12 +WEB_SITE="https://www.x.org/wiki/"
  149.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  149.14 +
  149.15 +TARBALL="libXext-$VERSION.tar.bz2"
  149.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  149.17 +TARBALL_SHA1="43abab84101159563e68d9923353cc0b3af44f07"
  149.18 +
  149.19 +BUILD_DEPENDS="libx11-dev xorgproto"
  149.20 +SPLIT="$PACKAGE-dev"
  149.21 +
  149.22 +DEPENDS_std="libx11"
  149.23 +DEPENDS_dev="$PACKAGE libx11-dev xorgproto"
  149.24 +
  149.25 +compile_rules() {
  149.26 +	./configure \
  149.27 +		--disable-static \
  149.28 +		$CONFIGURE_ARGS &&
  149.29 +	fix libtool &&
  149.30 +	make &&
  149.31 +	make install
  149.32 +}
  149.33 +
  149.34 +TAGS="Xorg"
  149.35 +
  149.36 +PROVIDE_std="xorg-libXext"
  149.37 +PROVIDE_dev="xorg-libXext-dev"
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/libxfixes/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   150.3 @@ -0,0 +1,1 @@
   150.4 +../xorg/.icon.png
   150.5 \ No newline at end of file
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/libxfixes/receipt	Thu Dec 20 17:55:43 2018 +0200
   151.3 @@ -0,0 +1,34 @@
   151.4 +# SliTaz package receipt v2.
   151.5 +
   151.6 +PACKAGE="libxfixes"
   151.7 +VERSION="5.0.3"
   151.8 +CATEGORY="x-window"
   151.9 +SHORT_DESC="X-Fixes extension"
  151.10 +MAINTAINER="devel@slitaz.org"
  151.11 +LICENSE="MIT"
  151.12 +WEB_SITE="https://www.x.org/wiki/"
  151.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  151.14 +
  151.15 +TARBALL="libXfixes-$VERSION.tar.bz2"
  151.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  151.17 +TARBALL_SHA1="ca86342d129c02435a9ee46e38fdf1a04d6b4b91"
  151.18 +
  151.19 +BUILD_DEPENDS="xorgproto libx11-dev"
  151.20 +SPLIT="$PACKAGE-dev"
  151.21 +
  151.22 +DEPENDS_std="xorg-libx11"
  151.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev"
  151.24 +
  151.25 +compile_rules() {
  151.26 +	./configure \
  151.27 +		--disable-static \
  151.28 +		$CONFIGURE_ARGS &&
  151.29 +	fix libtool &&
  151.30 +	make &&
  151.31 +	make install
  151.32 +}
  151.33 +
  151.34 +TAGS="Xorg"
  151.35 +
  151.36 +PROVIDE_std="xorg-libXfixes"
  151.37 +PROVIDE_dev="xorg-libXfixes-dev"
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/libxfont/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   152.3 @@ -0,0 +1,1 @@
   152.4 +../xorg/.icon.png
   152.5 \ No newline at end of file
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/libxfont/receipt	Thu Dec 20 17:55:43 2018 +0200
   153.3 @@ -0,0 +1,33 @@
   153.4 +# SliTaz package receipt v2.
   153.5 +
   153.6 +PACKAGE="libxfont"
   153.7 +VERSION="1.5.4"
   153.8 +CATEGORY="x-window"
   153.9 +SHORT_DESC="X font handling library for server & utilities"
  153.10 +MAINTAINER="devel@slitaz.org"
  153.11 +LICENSE="MIT"
  153.12 +WEB_SITE="https://www.x.org/wiki/"
  153.13 +
  153.14 +TARBALL="libXfont-$VERSION.tar.bz2"
  153.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  153.16 +TARBALL_SHA1="9db050f63b9c4cb19e0dbb40575558ccb95719ca"
  153.17 +
  153.18 +BUILD_DEPENDS="bzip2-dev freetype-dev zlib-dev xtrans xorgproto libfontenc-dev"
  153.19 +SPLIT="$PACKAGE-dev"
  153.20 +
  153.21 +DEPENDS_std="freetype libfontenc zlib"
  153.22 +DEPENDS_dev="$PACKAGE freetype-dev xorgproto libfontenc-dev zlib-dev"
  153.23 +
  153.24 +compile_rules() {
  153.25 +	./configure \
  153.26 +		--disable-static \
  153.27 +		$CONFIGURE_ARGS &&
  153.28 +	fix libtool &&
  153.29 +	make &&
  153.30 +	make install
  153.31 +}
  153.32 +
  153.33 +TAGS="Xorg"
  153.34 +
  153.35 +PROVIDE_std="xorg-libXfont"
  153.36 +PROVIDE_dev="xorg-libXfont-dev"
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/libxfont2/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   154.3 @@ -0,0 +1,1 @@
   154.4 +../xorg/.icon.png
   154.5 \ No newline at end of file
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/libxfont2/receipt	Thu Dec 20 17:55:43 2018 +0200
   155.3 @@ -0,0 +1,34 @@
   155.4 +# SliTaz package receipt v2.
   155.5 +
   155.6 +PACKAGE="libxfont2"
   155.7 +VERSION="2.0.3"
   155.8 +CATEGORY="x-window"
   155.9 +SHORT_DESC="X font2 handling library for server & utilities"
  155.10 +MAINTAINER="al.bobylev@gmail.com"
  155.11 +LICENSE="MIT"
  155.12 +WEB_SITE="https://www.x.org/wiki/"
  155.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  155.14 +
  155.15 +TARBALL="libXfont2-$VERSION.tar.bz2"
  155.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  155.17 +TARBALL_SHA1="1110f1ad4061d9e8131ecb941757480e3e32bca0"
  155.18 +
  155.19 +BUILD_DEPENDS="util-macros freetype-dev xtrans xorgproto libfontenc-dev"
  155.20 +SPLIT="$PACKAGE-dev"
  155.21 +
  155.22 +DEPENDS_std="freetype libfontenc zlib"
  155.23 +DEPENDS_dev="$PACKAGE freetype-dev xorgproto libfontenc-dev zlib-dev"
  155.24 +
  155.25 +compile_rules() {
  155.26 +	./configure \
  155.27 +		--disable-static \
  155.28 +		$CONFIGURE_ARGS &&
  155.29 +	fix libtool &&
  155.30 +	make &&
  155.31 +	make install
  155.32 +}
  155.33 +
  155.34 +TAGS="Xorg"
  155.35 +
  155.36 +PROVIDE_std="xorg-libXfont2"
  155.37 +PROVIDE_dev="xorg-libXfont2-dev"
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/libxfontcache/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   156.3 @@ -0,0 +1,1 @@
   156.4 +../xorg/.icon.png
   156.5 \ No newline at end of file
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/libxfontcache/receipt	Thu Dec 20 17:55:43 2018 +0200
   157.3 @@ -0,0 +1,33 @@
   157.4 +# SliTaz package receipt v2.
   157.5 +
   157.6 +PACKAGE="libxfontcache"
   157.7 +VERSION="1.0.5"
   157.8 +CATEGORY="x-window"
   157.9 +SHORT_DESC="X-TrueType font cache extension client library"
  157.10 +MAINTAINER="al.bobylev@gmail.com"
  157.11 +LICENSE="MIT"
  157.12 +WEB_SITE="https://www.x.org/wiki/"
  157.13 +
  157.14 +TARBALL="libXfontcache-$VERSION.tar.bz2"
  157.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  157.16 +TARBALL_SHA1="9e9bfee1a143cbe9486830d53f8f9cc0a91be472"
  157.17 +
  157.18 +BUILD_DEPENDS="gfortran libx11-dev libxext-dev xorgproto"
  157.19 +SPLIT="$PACKAGE-dev"
  157.20 +
  157.21 +DEPENDS_std="libx11 libxext"
  157.22 +DEPENDS="$PACKAGE xorgproto libx11-dev libxext-dev"
  157.23 +
  157.24 +compile_rules() {
  157.25 +	./configure \
  157.26 +		--disable-static \
  157.27 +		$CONFIGURE_ARGS &&
  157.28 +	fix libtool &&
  157.29 +	make &&
  157.30 +	make install
  157.31 +}
  157.32 +
  157.33 +TAGS="Xorg"
  157.34 +
  157.35 +PROVIDE_std="xorg-libXfontcache"
  157.36 +PROVIDE_dev="xorg-libXfontcache-dev"
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/libxft/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   158.3 @@ -0,0 +1,1 @@
   158.4 +../xorg/.icon.png
   158.5 \ No newline at end of file
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/libxft/receipt	Thu Dec 20 17:55:43 2018 +0200
   159.3 @@ -0,0 +1,34 @@
   159.4 +# SliTaz package receipt v2.
   159.5 +
   159.6 +PACKAGE="libxft"
   159.7 +VERSION="2.3.2"
   159.8 +CATEGORY="x-window"
   159.9 +SHORT_DESC="Client side font rendering library"
  159.10 +MAINTAINER="devel@slitaz.org"
  159.11 +LICENSE="MIT"
  159.12 +WEB_SITE="https://www.x.org/wiki/"
  159.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  159.14 +
  159.15 +TARBALL="libXft-$VERSION.tar.bz2"
  159.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  159.17 +TARBALL_SHA1="e025d790a7b6c4d283a78d8df06615cb10278e2d"
  159.18 +
  159.19 +BUILD_DEPENDS="libxrender-dev freetype-dev fontconfig-dev libxml2-dev"
  159.20 +SPLIT="$PACKAGE-dev"
  159.21 +
  159.22 +DEPENDS_std="fontconfig freetype libx11 libxrender"
  159.23 +DEPENDS_dev="$PACKAGE fontconfig-dev freetype-dev libxrender-dev xorgproto"
  159.24 +
  159.25 +compile_rules() {
  159.26 +	./configure \
  159.27 +		--disable-static \
  159.28 +		$CONFIGURE_ARGS &&
  159.29 +	fix libtool &&
  159.30 +	make &&
  159.31 +	make install
  159.32 +}
  159.33 +
  159.34 +TAGS="Xorg"
  159.35 +
  159.36 +PROVIDE_std="xorg-libXft"
  159.37 +PROVIDE_dev="xorg-libXft-dev"
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/libxi/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   160.3 @@ -0,0 +1,1 @@
   160.4 +../xorg/.icon.png
   160.5 \ No newline at end of file
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/libxi/receipt	Thu Dec 20 17:55:43 2018 +0200
   161.3 @@ -0,0 +1,34 @@
   161.4 +# SliTaz package receipt v2.
   161.5 +
   161.6 +PACKAGE="libxi"
   161.7 +VERSION="1.7.9"
   161.8 +CATEGORY="x-window"
   161.9 +SHORT_DESC="X Input Extension library"
  161.10 +MAINTAINER="devel@slitaz.org"
  161.11 +LICENSE="MIT"
  161.12 +WEB_SITE="https://www.x.org/wiki/"
  161.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  161.14 +
  161.15 +TARBALL="libXi-$VERSION.tar.bz2"
  161.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  161.17 +TARBALL_SHA1="70d1148c39c0eaa7d7c18370f20709383271f669"
  161.18 +
  161.19 +BUILD_DEPENDS="libxext-dev libxfixes-dev xorgproto"
  161.20 +SPLIT="$PACKAGE-dev"
  161.21 +
  161.22 +DEPENDS_std="libx11 libxext"
  161.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev libxext-dev libxfixes-dev"
  161.24 +
  161.25 +compile_rules() {
  161.26 +	./configure \
  161.27 +		--disable-static \
  161.28 +		$CONFIGURE_ARGS &&
  161.29 +	fix libtool &&
  161.30 +	make &&
  161.31 +	make install
  161.32 +}
  161.33 +
  161.34 +TAGS="Xorg"
  161.35 +
  161.36 +PROVIDE_std="xorg-libXi"
  161.37 +PROVIDE_dev="xorg-libXi-dev"
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/libxinerama/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   162.3 @@ -0,0 +1,1 @@
   162.4 +../xorg/.icon.png
   162.5 \ No newline at end of file
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/libxinerama/receipt	Thu Dec 20 17:55:43 2018 +0200
   163.3 @@ -0,0 +1,34 @@
   163.4 +# SliTaz package receipt v2.
   163.5 +
   163.6 +PACKAGE="libxinerama"
   163.7 +VERSION="1.1.4"
   163.8 +CATEGORY="x-window"
   163.9 +SHORT_DESC="Xinerama protocol library"
  163.10 +MAINTAINER="devel@slitaz.org"
  163.11 +LICENSE="MIT"
  163.12 +WEB_SITE="https://www.x.org/wiki/"
  163.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  163.14 +
  163.15 +TARBALL="libXinerama-$VERSION.tar.bz2"
  163.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  163.17 +TARBALL_SHA1="34a1d9908ffbd46805d2357c6b05f5e341a8dc7c"
  163.18 +
  163.19 +BUILD_DEPENDS="libxext-dev xorgproto"
  163.20 +SPLIT="$PACKAGE-dev"
  163.21 +
  163.22 +DEPENDS_std="libx11 libxext"
  163.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  163.24 +
  163.25 +compile_rules() {
  163.26 +	./configure \
  163.27 +		--disable-static \
  163.28 +		$CONFIGURE_ARGS &&
  163.29 +	fix libtool &&
  163.30 +	make &&
  163.31 +	make install
  163.32 +}
  163.33 +
  163.34 +TAGS="Xorg"
  163.35 +
  163.36 +PROVIDE_std="xorg-libXinerama"
  163.37 +PROVIDE_dev="xorg-libXinerama-dev"
   164.1 --- a/libxkbcommon/receipt	Thu Dec 13 00:46:54 2018 +0200
   164.2 +++ b/libxkbcommon/receipt	Thu Dec 20 17:55:43 2018 +0200
   164.3 @@ -1,7 +1,7 @@
   164.4  # SliTaz package receipt v2.
   164.5  
   164.6  PACKAGE="libxkbcommon"
   164.7 -VERSION="0.7.2"
   164.8 +VERSION="0.8.2"
   164.9  CATEGORY="x-window"
  164.10  SHORT_DESC="Keyboard handling library using XKB data"
  164.11  MAINTAINER="al.bobylev@gmail.com"
  164.12 @@ -11,12 +11,24 @@
  164.13  
  164.14  TARBALL="$PACKAGE-$VERSION.tar.xz"
  164.15  WGET_URL="http://xkbcommon.org/download/$TARBALL"
  164.16 +TARBALL_SHA1="5589b09b8490392573bba5527cc0cc82824028b1"
  164.17  
  164.18 -BUILD_DEPENDS="xorg-libxcb-dev xorg-util-macros xorg-xkeyboard-config-dev \
  164.19 -bison wayland-protocols-dev wayland-dev"
  164.20 +BUILD_DEPENDS="libxcb-dev util-macros xkeyboard-config-dev bison \
  164.21 +wayland-protocols-dev wayland-dev"
  164.22  SPLIT="$PACKAGE-x11 $PACKAGE $PACKAGE-dev \
  164.23  $PACKAGE-wayland:w $PACKAGE-wayland-dev:w"
  164.24  
  164.25 +COPY_x11="libxkbcommon-x11.so*"
  164.26 +COPY_wayland="@std"
  164.27 +COPY_wayland_dev="@dev"
  164.28 +
  164.29 +DEPENDS_x11="libxkbcommon libxcb   xkeyboard-config libx11"
  164.30 +DEPENDS_dev="$PACKAGE $PACKAGE-x11 libxcb-dev"
  164.31 +DEPENDS_wayland_dev="$PACKAGE-wayland"
  164.32 +
  164.33 +CAT_wayland="x-window|Wayland support"
  164.34 +CAT_wayland_dev="development|development files with Wayland support"
  164.35 +
  164.36  compile_rules() {
  164.37  	case $SET in
  164.38  		'') SET_ARGS='--disable-wayland --enable-x11';;
  164.39 @@ -31,31 +43,3 @@
  164.40  	make &&
  164.41  	make install
  164.42  }
  164.43 -
  164.44 -genpkg_rules() {
  164.45 -	case $PACKAGE in
  164.46 -		libxkbcommon-x11)
  164.47 -			copy libxkbcommon-x11.so*
  164.48 -			DEPENDS="libxkbcommon xorg-libXau xorg-libXdmcp xorg-libxcb   \
  164.49 -			xorg-xkeyboard-config xorg-libX11"
  164.50 -			;;
  164.51 -		libxkbcommon)
  164.52 -			copy @std @rm
  164.53 -			DEPENDS=" "
  164.54 -			;;
  164.55 -		libxkbcommon-dev)
  164.56 -			copy @dev
  164.57 -			DEPENDS="libxkbcommon libxkbcommon-x11 \
  164.58 -			xorg-libXau-dev xorg-libXdmcp-dev xorg-libxcb-dev"
  164.59 -			;;
  164.60 -
  164.61 -		libxkbcommon-wayland)
  164.62 -			CAT="x-window|Wayland support"
  164.63 -			copy @std
  164.64 -			;;
  164.65 -		libxkbcommon-wayland-dev)
  164.66 -			CAT="development|development files with Wayland support"
  164.67 -			copy @dev
  164.68 -			;;
  164.69 -	esac
  164.70 -}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/libxkbfile/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   165.3 @@ -0,0 +1,1 @@
   165.4 +../xorg/.icon.png
   165.5 \ No newline at end of file
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/libxkbfile/receipt	Thu Dec 20 17:55:43 2018 +0200
   166.3 @@ -0,0 +1,34 @@
   166.4 +# SliTaz package receipt v2.
   166.5 +
   166.6 +PACKAGE="libxkbfile"
   166.7 +VERSION="1.0.9"
   166.8 +CATEGORY="x-window"
   166.9 +SHORT_DESC="XKB file handling routines"
  166.10 +MAINTAINER="devel@slitaz.org"
  166.11 +LICENSE="MIT"
  166.12 +WEB_SITE="https://www.x.org/wiki/"
  166.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  166.14 +
  166.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  166.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  166.17 +TARBALL_SHA1="d708d3415212febbc67d4d996d02d7e3218e13ad"
  166.18 +
  166.19 +BUILD_DEPENDS="libx11-dev libxcb-dev libxau-dev libxdmcp-dev"
  166.20 +SPLIT="$PACKAGE-dev"
  166.21 +
  166.22 +DEPENDS_std="libx11"
  166.23 +DEPENDS_dev="$PACKAGE xorgproto libx11-dev"
  166.24 +
  166.25 +compile_rules() {
  166.26 +	./configure \
  166.27 +		--disable-static \
  166.28 +		$CONFIGURE_ARGS &&
  166.29 +	fix libtool &&
  166.30 +	make &&
  166.31 +	make install
  166.32 +}
  166.33 +
  166.34 +TAGS="Xorg"
  166.35 +
  166.36 +PROVIDE_std="xorg-libxkbfile"
  166.37 +PROVIDE_dev="xorg-libxkbfile-dev"
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/libxmu/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   167.3 @@ -0,0 +1,1 @@
   167.4 +../xorg/.icon.png
   167.5 \ No newline at end of file
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/libxmu/receipt	Thu Dec 20 17:55:43 2018 +0200
   168.3 @@ -0,0 +1,34 @@
   168.4 +# SliTaz package receipt v2.
   168.5 +
   168.6 +PACKAGE="libxmu"
   168.7 +VERSION="1.1.2"
   168.8 +CATEGORY="x-window"
   168.9 +SHORT_DESC="X miscellaneous utility routines"
  168.10 +MAINTAINER="devel@slitaz.org"
  168.11 +LICENSE="MIT"
  168.12 +WEB_SITE="https://www.x.org/wiki/"
  168.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  168.14 +
  168.15 +TARBALL="libXmu-$VERSION.tar.bz2"
  168.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  168.17 +TARBALL_SHA1="7e6aeef726743d21aa272c424e7d7996e92599eb"
  168.18 +
  168.19 +BUILD_DEPENDS="libxext-dev libxt-dev util-linux-uuid-dev"
  168.20 +SPLIT="$PACKAGE-dev"
  168.21 +
  168.22 +DEPENDS_std="libx11 libxext libxt"
  168.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxt-dev xorgproto"
  168.24 +
  168.25 +compile_rules() {
  168.26 +	./configure \
  168.27 +		--disable-static \
  168.28 +		$CONFIGURE_ARGS &&
  168.29 +	fix libtool &&
  168.30 +	make &&
  168.31 +	make install
  168.32 +}
  168.33 +
  168.34 +TAGS="Xorg"
  168.35 +
  168.36 +PROVIDE_std="xorg-libXmu"
  168.37 +PROVIDE_dev="xorg-libXmu-dev"
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/libxp/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   169.3 @@ -0,0 +1,1 @@
   169.4 +../xorg/.icon.png
   169.5 \ No newline at end of file
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/libxp/receipt	Thu Dec 20 17:55:43 2018 +0200
   170.3 @@ -0,0 +1,34 @@
   170.4 +# SliTaz package receipt v2.
   170.5 +
   170.6 +PACKAGE="libxp"
   170.7 +VERSION="1.0.3"
   170.8 +CATEGORY="development"
   170.9 +SHORT_DESC="Allow client applications to render to non-display devices"
  170.10 +MAINTAINER="devel@slitaz.org"
  170.11 +LICENSE="MIT"
  170.12 +WEB_SITE="https://www.x.org/wiki/"
  170.13 +
  170.14 +TARBALL="libXp-$VERSION.tar.bz2"
  170.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  170.16 +TARBALL_SHA1="9e10371ca8961b50c2d69150a88fc031455699d1"
  170.17 +
  170.18 +BUILD_DEPENDS="util-macros libx11-dev libxext-dev libxau-dev xorgproto"
  170.19 +SPLIT="$PACKAGE-dev"
  170.20 +
  170.21 +DEPENDS_std="libxcb libx11 libxau libxdmcp libxext"
  170.22 +DEPENDS_dev="$PACKAGE libxcb-dev libx11-dev libxau-dev libxdmcp-dev \
  170.23 +libxext-dev xorgproto"
  170.24 +
  170.25 +compile_rules() {
  170.26 +	./configure \
  170.27 +		--disable-static \
  170.28 +		$CONFIGURE_ARGS &&
  170.29 +	fix libtool &&
  170.30 +	make &&
  170.31 +	make install
  170.32 +}
  170.33 +
  170.34 +TAGS="Xorg"
  170.35 +
  170.36 +PROVIDE_std="xorg-libXp"
  170.37 +PROVIDE_dev="xorg-libXp-dev"
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/libxpm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   171.3 @@ -0,0 +1,1 @@
   171.4 +../xorg/.icon.png
   171.5 \ No newline at end of file
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/libxpm/receipt	Thu Dec 20 17:55:43 2018 +0200
   172.3 @@ -0,0 +1,41 @@
   172.4 +# SliTaz package receipt v2.
   172.5 +
   172.6 +PACKAGE="libxpm"
   172.7 +VERSION="3.5.12"
   172.8 +CATEGORY="x-window"
   172.9 +SHORT_DESC="XPM format pixmap library"
  172.10 +MAINTAINER="devel@slitaz.org"
  172.11 +LICENSE="MIT"
  172.12 +WEB_SITE="https://www.x.org/wiki/"
  172.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  172.14 +
  172.15 +TARBALL="libXpm-$VERSION.tar.bz2"
  172.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  172.17 +TARBALL_SHA1="4e22fefe61714209539b08051b5287bcd9ecfd04"
  172.18 +
  172.19 +BUILD_DEPENDS="libxt-dev libxext-dev libsm-dev util-linux-uuid-dev gettext-dev"
  172.20 +SPLIT="$PACKAGE-util $PACKAGE-dev"
  172.21 +
  172.22 +COPY_std="*.so*"
  172.23 +COPY_util="bin/"
  172.24 +
  172.25 +DEPENDS_std="libx11"
  172.26 +DEPENDS_util="$PACKAGE libx11 libxext libxt"
  172.27 +DEPENDS_dev="$PACKAGE $PACKAGE-util libx11-dev"
  172.28 +
  172.29 +CAT_util="x-window|utilities"
  172.30 +
  172.31 +compile_rules() {
  172.32 +	./configure \
  172.33 +		--disable-static \
  172.34 +		$CONFIGURE_ARGS &&
  172.35 +	fix libtool &&
  172.36 +	make &&
  172.37 +	make install
  172.38 +}
  172.39 +
  172.40 +TAGS="Xorg"
  172.41 +
  172.42 +PROVIDE_std="xorg-libXpm"
  172.43 +PROVIDE_util="xorg-libXpm-util"
  172.44 +PROVIDE_dev="xorg-libXpm-dev"
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/libxrandr/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   173.3 @@ -0,0 +1,1 @@
   173.4 +../xorg/.icon.png
   173.5 \ No newline at end of file
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/libxrandr/receipt	Thu Dec 20 17:55:43 2018 +0200
   174.3 @@ -0,0 +1,34 @@
   174.4 +# SliTaz package receipt v2.
   174.5 +
   174.6 +PACKAGE="libxrandr"
   174.7 +VERSION="1.5.1"
   174.8 +CATEGORY="x-window"
   174.9 +SHORT_DESC="Xrandr extension library"
  174.10 +MAINTAINER="devel@slitaz.org"
  174.11 +LICENSE="MIT"
  174.12 +WEB_SITE="https://www.x.org/wiki/libraries/libxrandr/"
  174.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  174.14 +
  174.15 +TARBALL="libXrandr-$VERSION.tar.bz2"
  174.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  174.17 +TARBALL_SHA1="7232fe2648b96fed531208c3ad2ba0be61990041"
  174.18 +
  174.19 +BUILD_DEPENDS="xorgproto libxext-dev libxrender-dev"
  174.20 +SPLIT="$PACKAGE-dev"
  174.21 +
  174.22 +DEPENDS_std="libx11 libxext libxrender"
  174.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxrender-dev xorgproto"
  174.24 +
  174.25 +compile_rules() {
  174.26 +	./configure \
  174.27 +		--disable-static \
  174.28 +		$CONFIGURE_ARGS &&
  174.29 +	fix libtool &&
  174.30 +	make &&
  174.31 +	make install
  174.32 +}
  174.33 +
  174.34 +TAGS="Xorg"
  174.35 +
  174.36 +PROVIDE_std="xorg-libXrandr"
  174.37 +PROVIDE_dev="xorg-libXrandr-dev"
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/libxrender/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   175.3 @@ -0,0 +1,1 @@
   175.4 +../xorg/.icon.png
   175.5 \ No newline at end of file
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/libxrender/receipt	Thu Dec 20 17:55:43 2018 +0200
   176.3 @@ -0,0 +1,34 @@
   176.4 +# SliTaz package receipt v2.
   176.5 +
   176.6 +PACKAGE="libxrender"
   176.7 +VERSION="0.9.10"
   176.8 +CATEGORY="x-window"
   176.9 +SHORT_DESC="RENDER extension library"
  176.10 +MAINTAINER="devel@slitaz.org"
  176.11 +LICENSE="MIT"
  176.12 +WEB_SITE="https://www.x.org/wiki/"
  176.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  176.14 +
  176.15 +TARBALL="libXrender-$VERSION.tar.bz2"
  176.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  176.17 +TARBALL_SHA1="d55106de9260c2377c19d271d9b677744a6c7e81"
  176.18 +
  176.19 +BUILD_DEPENDS="libx11-dev xorgproto"
  176.20 +SPLIT="$PACKAGE-dev"
  176.21 +
  176.22 +DEPENDS_std="libx11"
  176.23 +DEPENDS_dev="$PACKAGE libx11-dev xorgproto"
  176.24 +
  176.25 +compile_rules() {
  176.26 +	./configure \
  176.27 +		--disable-static \
  176.28 +		$CONFIGURE_ARGS &&
  176.29 +	fix libtool &&
  176.30 +	make &&
  176.31 +	make install
  176.32 +}
  176.33 +
  176.34 +TAGS="Xorg"
  176.35 +
  176.36 +PROVIDE_std="xorg-libXrender"
  176.37 +PROVIDE_dev="xorg-libXrender-dev"
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/libxres/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   177.3 @@ -0,0 +1,1 @@
   177.4 +../xorg/.icon.png
   177.5 \ No newline at end of file
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/libxres/receipt	Thu Dec 20 17:55:43 2018 +0200
   178.3 @@ -0,0 +1,34 @@
   178.4 +# SliTaz package receipt v2.
   178.5 +
   178.6 +PACKAGE="libxres"
   178.7 +VERSION="1.2.0"
   178.8 +CATEGORY="x-window"
   178.9 +SHORT_DESC="X Resource extension"
  178.10 +MAINTAINER="pascal.bellard@slitaz.org"
  178.11 +LICENSE="MIT"
  178.12 +WEB_SITE="https://www.x.org/wiki/"
  178.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  178.14 +
  178.15 +TARBALL="libXres-$VERSION.tar.bz2"
  178.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  178.17 +TARBALL_SHA1="b6996ab05460a3b7311f02da23ddf117a5442fd9"
  178.18 +
  178.19 +BUILD_DEPENDS="libx11-dev libxext-dev xorgproto"
  178.20 +SPLIT="$PACKAGE-dev"
  178.21 +
  178.22 +DEPENDS_std="libx11 libxext"
  178.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  178.24 +
  178.25 +compile_rules() {
  178.26 +	./configure \
  178.27 +		--disable-static \
  178.28 +		$CONFIGURE_ARGS &&
  178.29 +	fix libtool &&
  178.30 +	make &&
  178.31 +	make install
  178.32 +}
  178.33 +
  178.34 +TAGS="Xorg"
  178.35 +
  178.36 +PROVIDE_std="xorg-libXres"
  178.37 +PROVIDE_dev="xorg-libXres-dev"
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/libxscrnsaver/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   179.3 @@ -0,0 +1,1 @@
   179.4 +../xorg/.icon.png
   179.5 \ No newline at end of file
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/libxscrnsaver/receipt	Thu Dec 20 17:55:43 2018 +0200
   180.3 @@ -0,0 +1,34 @@
   180.4 +# SliTaz package receipt v2.
   180.5 +
   180.6 +PACKAGE="libxscrnsaver"
   180.7 +VERSION="1.2.3"
   180.8 +CATEGORY="x-window"
   180.9 +SHORT_DESC="MIT-SCREEN-SAVER extension"
  180.10 +MAINTAINER="al.bobylev@gmail.com"
  180.11 +LICENSE="MIT"
  180.12 +WEB_SITE="https://www.x.org/wiki/"
  180.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  180.14 +
  180.15 +TARBALL="libXScrnSaver-$VERSION.tar.bz2"
  180.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  180.17 +TARBALL_SHA1="70c791c5755a298ecf1a0823e239a24fa4b2b42f"
  180.18 +
  180.19 +BUILD_DEPENDS="libxext-dev xorgproto"
  180.20 +SPLIT="$PACKAGE-dev"
  180.21 +
  180.22 +DEPENDS_std="libx11 libxext"
  180.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  180.24 +
  180.25 +compile_rules() {
  180.26 +	./configure \
  180.27 +		--disable-static \
  180.28 +		$CONFIGURE_ARGS &&
  180.29 +	fix libtool &&
  180.30 +	make &&
  180.31 +	make install
  180.32 +}
  180.33 +
  180.34 +TAGS="Xorg"
  180.35 +
  180.36 +PROVIDE_std="xorg-libXScrnSaver"
  180.37 +PROVIDE_dev="xorg-libXScrnSaver-dev"
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/libxshmfence/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   181.3 @@ -0,0 +1,1 @@
   181.4 +../xorg/.icon.png
   181.5 \ No newline at end of file
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/libxshmfence/receipt	Thu Dec 20 17:55:43 2018 +0200
   182.3 @@ -0,0 +1,31 @@
   182.4 +# SliTaz package receipt v2.
   182.5 +
   182.6 +PACKAGE="libxshmfence"
   182.7 +VERSION="1.3"
   182.8 +CATEGORY="x-window"
   182.9 +SHORT_DESC="Xorg server Shared Memory Fence library"
  182.10 +MAINTAINER="al.bobylev@gmail.com"
  182.11 +LICENSE="MIT"
  182.12 +WEB_SITE="https://www.x.org/wiki/"
  182.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  182.14 +
  182.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  182.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  182.17 +TARBALL_SHA1="3472218fc0e8ee8183533d22dbcd4bbe90bf3ab8"
  182.18 +
  182.19 +BUILD_DEPENDS="xorgproto"
  182.20 +SPLIT="$PACKAGE-dev"
  182.21 +
  182.22 +compile_rules() {
  182.23 +	./configure \
  182.24 +		--disable-static \
  182.25 +		$CONFIGURE_ARGS &&
  182.26 +	fix libtool &&
  182.27 +	make &&
  182.28 +	make install
  182.29 +}
  182.30 +
  182.31 +TAGS="Xorg"
  182.32 +
  182.33 +PROVIDE_std="xorg-libxshmfence"
  182.34 +PROVIDE_dev="xorg-libxshmfence-dev"
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/libxt/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   183.3 @@ -0,0 +1,1 @@
   183.4 +../xorg/.icon.png
   183.5 \ No newline at end of file
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/libxt/receipt	Thu Dec 20 17:55:43 2018 +0200
   184.3 @@ -0,0 +1,35 @@
   184.4 +# SliTaz package receipt v2.
   184.5 +
   184.6 +PACKAGE="libxt"
   184.7 +VERSION="1.1.5"
   184.8 +CATEGORY="x-window"
   184.9 +SHORT_DESC="X Toolkit Intrinsics library"
  184.10 +MAINTAINER="devel@slitaz.org"
  184.11 +LICENSE="MIT"
  184.12 +WEB_SITE="https://www.x.org/wiki/"
  184.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  184.14 +
  184.15 +TARBALL="libXt-$VERSION.tar.bz2"
  184.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  184.17 +TARBALL_SHA1="c79e2c4f7de5259a2ade458817a139b66a043d59"
  184.18 +
  184.19 +BUILD_DEPENDS="libsm-dev libx11-dev glib-dev util-linux-uuid-dev"
  184.20 +SPLIT="$PACKAGE-dev"
  184.21 +
  184.22 +DEPENDS_std="libice libsm libx11"
  184.23 +DEPENDS_dev="$PACKAGE libice-dev libsm-dev libx11-dev xorgproto"
  184.24 +
  184.25 +compile_rules() {
  184.26 +	./configure \
  184.27 +		--disable-static \
  184.28 +		--with-appdefaultdir=/etc/X11/app-defaults \
  184.29 +		$CONFIGURE_ARGS &&
  184.30 +	fix libtool &&
  184.31 +	make &&
  184.32 +	make install
  184.33 +}
  184.34 +
  184.35 +TAGS="Xorg"
  184.36 +
  184.37 +PROVIDE_std="xorg-libXt"
  184.38 +PROVIDE_dev="xorg-libXt-dev"
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/libxtst/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   185.3 @@ -0,0 +1,1 @@
   185.4 +../xorg/.icon.png
   185.5 \ No newline at end of file
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/libxtst/receipt	Thu Dec 20 17:55:43 2018 +0200
   186.3 @@ -0,0 +1,34 @@
   186.4 +# SliTaz package receipt v2.
   186.5 +
   186.6 +PACKAGE="libxtst"
   186.7 +VERSION="1.2.3"
   186.8 +CATEGORY="x-window"
   186.9 +SHORT_DESC="Xorg server module"
  186.10 +MAINTAINER="devel@slitaz.org"
  186.11 +LICENSE="MIT"
  186.12 +WEB_SITE="https://www.x.org/wiki/"
  186.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  186.14 +
  186.15 +TARBALL="libXtst-$VERSION.tar.bz2"
  186.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  186.17 +TARBALL_SHA1="27d004db631bee3a82155d3caf961d9584207d36"
  186.18 +
  186.19 +BUILD_DEPENDS="xorgproto libxext-dev libxi-dev"
  186.20 +SPLIT="$PACKAGE-dev"
  186.21 +
  186.22 +DEPENDS_std="libx11 libxext"
  186.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxi-dev xorgproto"
  186.24 +
  186.25 +compile_rules() {
  186.26 +	./configure \
  186.27 +		--disable-static \
  186.28 +		$CONFIGURE_ARGS
  186.29 +	fix libtool &&
  186.30 +	make &&
  186.31 +	make install
  186.32 +}
  186.33 +
  186.34 +TAGS="Xorg"
  186.35 +
  186.36 +PROVIDE_std="xorg-libXtst"
  186.37 +PROVIDE_dev="xorg-libXtst-dev"
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/libxv/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   187.3 @@ -0,0 +1,1 @@
   187.4 +../xorg/.icon.png
   187.5 \ No newline at end of file
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/libxv/receipt	Thu Dec 20 17:55:43 2018 +0200
   188.3 @@ -0,0 +1,34 @@
   188.4 +# SliTaz package receipt v2.
   188.5 +
   188.6 +PACKAGE="libxv"
   188.7 +VERSION="1.0.11"
   188.8 +CATEGORY="x-window"
   188.9 +SHORT_DESC="Xvideo extension library"
  188.10 +MAINTAINER="devel@slitaz.org"
  188.11 +LICENSE="MIT"
  188.12 +WEB_SITE="https://www.x.org/wiki/"
  188.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  188.14 +
  188.15 +TARBALL="libXv-$VERSION.tar.bz2"
  188.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  188.17 +TARBALL_SHA1="d79f9c56faedd682f420fa68bb9d7ff755b84579"
  188.18 +
  188.19 +BUILD_DEPENDS="libxext-dev xorgproto"
  188.20 +SPLIT="$PACKAGE-dev"
  188.21 +
  188.22 +DEPENDS_std="libx11 libxext"
  188.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  188.24 +
  188.25 +compile_rules() {
  188.26 +	./configure \
  188.27 +		--disable-static \
  188.28 +		$CONFIGURE_ARGS &&
  188.29 +	fix libtool &&
  188.30 +	make &&
  188.31 +	make install
  188.32 +}
  188.33 +
  188.34 +TAGS="Xorg"
  188.35 +
  188.36 +PROVIDE_std="xorg-libXv"
  188.37 +PROVIDE_dev="xorg-libXv-dev"
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/libxvmc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   189.3 @@ -0,0 +1,1 @@
   189.4 +../xorg/.icon.png
   189.5 \ No newline at end of file
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/libxvmc/receipt	Thu Dec 20 17:55:43 2018 +0200
   190.3 @@ -0,0 +1,34 @@
   190.4 +# SliTaz package receipt v2.
   190.5 +
   190.6 +PACKAGE="libxvmc"
   190.7 +VERSION="1.0.10"
   190.8 +CATEGORY="x-window"
   190.9 +SHORT_DESC="Xorg server module"
  190.10 +MAINTAINER="devel@slitaz.org"
  190.11 +LICENSE="MIT"
  190.12 +WEB_SITE="https://www.x.org/wiki/"
  190.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  190.14 +
  190.15 +TARBALL="libXvMC-$VERSION.tar.bz2"
  190.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  190.17 +TARBALL_SHA1="8c50ee4a43aff84d807da2122ec6b0d8e3ce4635"
  190.18 +
  190.19 +BUILD_DEPENDS="libxv-dev"
  190.20 +SPLIT="$PACKAGE-dev"
  190.21 +
  190.22 +DEPENDS_std="libx11 libxext"
  190.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev libxv-dev xorgproto"
  190.24 +
  190.25 +compile_rules() {
  190.26 +	./configure \
  190.27 +		--disable-static \
  190.28 +		$CONFIGURE_ARGS &&
  190.29 +	fix libtool &&
  190.30 +	make &&
  190.31 +	make install
  190.32 +}
  190.33 +
  190.34 +TAGS="Xorg"
  190.35 +
  190.36 +PROVIDE_std="xorg-libXvMC"
  190.37 +PROVIDE_dev="xorg-libXvMC-dev"
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/libxxf86dga/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   191.3 @@ -0,0 +1,1 @@
   191.4 +../xorg/.icon.png
   191.5 \ No newline at end of file
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/libxxf86dga/receipt	Thu Dec 20 17:55:43 2018 +0200
   192.3 @@ -0,0 +1,34 @@
   192.4 +# SliTaz package receipt v2.
   192.5 +
   192.6 +PACKAGE="libxxf86dga"
   192.7 +VERSION="1.1.4"
   192.8 +CATEGORY="x-window"
   192.9 +SHORT_DESC="Xorg server module"
  192.10 +MAINTAINER="pascal.bellard@slitaz.org"
  192.11 +LICENSE="MIT"
  192.12 +WEB_SITE="https://www.x.org/wiki/"
  192.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  192.14 +
  192.15 +TARBALL="libXxf86dga-$VERSION.tar.bz2"
  192.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  192.17 +TARBALL_SHA1="51f2fc8d5d5fb398cf3c66735789feadb9aaeba9"
  192.18 +
  192.19 +BUILD_DEPENDS="libx11-dev xorgproto libxext-dev"
  192.20 +SPLIT="$PACKAGE-dev"
  192.21 +
  192.22 +DEPENDS_std="libx11 libxext"
  192.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  192.24 +
  192.25 +compile_rules() {
  192.26 +	./configure \
  192.27 +		--disable-static \
  192.28 +		$CONFIGURE_ARGS &&
  192.29 +	fix libtool &&
  192.30 +	make &&
  192.31 +	make install
  192.32 +}
  192.33 +
  192.34 +TAGS="Xorg"
  192.35 +
  192.36 +PROVIDE_std="xorg-libXxf86dga"
  192.37 +PROVIDE_dev="xorg-libXxf86dga-dev"
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/libxxf86misc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   193.3 @@ -0,0 +1,1 @@
   193.4 +../xorg/.icon.png
   193.5 \ No newline at end of file
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/libxxf86misc/receipt	Thu Dec 20 17:55:43 2018 +0200
   194.3 @@ -0,0 +1,33 @@
   194.4 +# SliTaz package receipt v2.
   194.5 +
   194.6 +PACKAGE="libxxf86misc"
   194.7 +VERSION="1.0.4"
   194.8 +CATEGORY="x-window"
   194.9 +SHORT_DESC="XFree86-MISC extension library"
  194.10 +MAINTAINER="al.bobylev@gmail.com"
  194.11 +LICENSE="MIT"
  194.12 +WEB_SITE="https://www.x.org/wiki/"
  194.13 +
  194.14 +TARBALL="libXxf86misc-$VERSION.tar.bz2"
  194.15 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  194.16 +TARBALL_SHA1="2676f1b0df7ca3ed1e01a0a51420c27c25737d02"
  194.17 +
  194.18 +BUILD_DEPENDS="util-macros libx11-dev xorgproto libxext-dev"
  194.19 +SPLIT="$PACKAGE-dev"
  194.20 +
  194.21 +DEPENDS_std="libx11 libxext"
  194.22 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  194.23 +
  194.24 +compile_rules() {
  194.25 +	./configure \
  194.26 +		--disable-static \
  194.27 +		$CONFIGURE_ARGS &&
  194.28 +	fix libtool &&
  194.29 +	make &&
  194.30 +	make install
  194.31 +}
  194.32 +
  194.33 +TAGS="Xorg"
  194.34 +
  194.35 +PROVIDE_std="xorg-libXxf86misc"
  194.36 +PROVIDE_dev="xorg-libXxf86misc-dev"
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/libxxf86vm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   195.3 @@ -0,0 +1,1 @@
   195.4 +../xorg/.icon.png
   195.5 \ No newline at end of file
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/libxxf86vm/receipt	Thu Dec 20 17:55:43 2018 +0200
   196.3 @@ -0,0 +1,34 @@
   196.4 +# SliTaz package receipt v2.
   196.5 +
   196.6 +PACKAGE="libxxf86vm"
   196.7 +VERSION="1.1.4"
   196.8 +CATEGORY="x-window"
   196.9 +SHORT_DESC="XFree86-VidMode extension library"
  196.10 +MAINTAINER="devel@slitaz.org"
  196.11 +LICENSE="MIT"
  196.12 +WEB_SITE="https://www.x.org/wiki/"
  196.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  196.14 +
  196.15 +TARBALL="libXxf86vm-$VERSION.tar.bz2"
  196.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  196.17 +TARBALL_SHA1="78ef18ca2be157131899e01c62679e247409a13f"
  196.18 +
  196.19 +BUILD_DEPENDS="libx11-dev libxext-dev xorgproto"
  196.20 +SPLIT="$PACKAGE-dev"
  196.21 +
  196.22 +DEPENDS_std="libx11 libxext"
  196.23 +DEPENDS_dev="$PACKAGE libx11-dev libxext-dev xorgproto"
  196.24 +
  196.25 +compile_rules() {
  196.26 +	./configure \
  196.27 +		--disable-static \
  196.28 +		$CONFIGURE_ARGS &&
  196.29 +	fix libtool &&
  196.30 +	make &&
  196.31 +	make install
  196.32 +}
  196.33 +
  196.34 +TAGS="Xorg"
  196.35 +
  196.36 +PROVIDE_std="xorg-libXxf86vm"
  196.37 +PROVIDE_dev="xorg-libXxf86vm-dev"
   197.1 --- a/links/receipt	Thu Dec 13 00:46:54 2018 +0200
   197.2 +++ b/links/receipt	Thu Dec 20 17:55:43 2018 +0200
   197.3 @@ -1,7 +1,7 @@
   197.4  # SliTaz package receipt v2.
   197.5  
   197.6  PACKAGE="links"
   197.7 -VERSION="2.14"
   197.8 +VERSION="2.17"
   197.9  CATEGORY="network"
  197.10  SHORT_DESC="Light and fast web browser"
  197.11  MAINTAINER="devel@slitaz.org"
  197.12 @@ -11,11 +11,27 @@
  197.13  
  197.14  TARBALL="$PACKAGE-$VERSION.tar.bz2"
  197.15  WGET_URL="http://links.twibright.com/download/$TARBALL"
  197.16 +TARBALL_SHA1="296670173368f1962c25604e2bdb78cf8d8d33e4"
  197.17  
  197.18 -BUILD_DEPENDS="gpm-dev openssl-dev zlib-dev bzip2-dev xz-dev xorg-libX11-dev \
  197.19 -xorg-libXt-dev libpng16-dev libjpeg-turbo-dev tiff-dev directfb-dev"
  197.20 +BUILD_DEPENDS="gpm-dev openssl-dev zlib-dev bzip2-dev xz-dev libx11-dev \
  197.21 +libxt-dev libpng-dev libjpeg-turbo-dev tiff-dev directfb-dev"
  197.22  SPLIT="$PACKAGE-dfb:dfb $PACKAGE-cli:cli"
  197.23  
  197.24 +COPY_dfb="@std"
  197.25 +COPY_cli="@std"
  197.26 +
  197.27 +DEPENDS_std="bzlib libgomp libjpeg-turbo liblzma libpng openssl tiff libx11 \
  197.28 +zlib"
  197.29 +DEPENDS_dfb="bzlib directfb libgomp libjpeg-turbo liblzma libpng openssl tiff \
  197.30 +zlib"
  197.31 +DEPENDS_cli="bzlib liblzma openssl zlib"
  197.32 +
  197.33 +SUGGESTED_std="gpm"
  197.34 +PROVIDE_dfb="links"
  197.35 +PROVIDE_cli="links"
  197.36 +
  197.37 +TAGS="web-browser"
  197.38 +
  197.39  compile_rules() {
  197.40  	case $SET in
  197.41  		'')  SET_ARGS='--enable-graphics --without-directfb --with-x';;
  197.42 @@ -32,26 +48,3 @@
  197.43  	install -Dm644 $src/graphics/links.xpm $install/usr/share/pixmaps/links.xpm
  197.44  	install -Dm644 $stuff/links.html       $install/usr/share/webhome/links.html
  197.45  }
  197.46 -
  197.47 -genpkg_rules() {
  197.48 -	case $PACKAGE in
  197.49 -		links)
  197.50 -			copy @std
  197.51 -			DEPENDS="bzlib libgomp libjpeg-turbo liblzma libpng16 openssl tiff \
  197.52 -			xorg-libX11 zlib"
  197.53 -			SUGGESTED="gpm"
  197.54 -			;;
  197.55 -		links-dfb)
  197.56 -			copy @std
  197.57 -			DEPENDS="bzlib directfb libgomp libjpeg-turbo liblzma libpng16 \
  197.58 -			openssl tiff zlib"
  197.59 -			PROVIDE="links"
  197.60 -			;;
  197.61 -		links-cli)
  197.62 -			copy @std
  197.63 -			DEPENDS="bzlib liblzma openssl zlib"
  197.64 -			PROVIDE="links"
  197.65 -			;;
  197.66 -	esac
  197.67 -	TAGS="web-browser"
  197.68 -}
   198.1 --- a/llvm/receipt	Thu Dec 13 00:46:54 2018 +0200
   198.2 +++ b/llvm/receipt	Thu Dec 20 17:55:43 2018 +0200
   198.3 @@ -1,7 +1,7 @@
   198.4  # SliTaz package receipt v2.
   198.5  
   198.6  PACKAGE="llvm"
   198.7 -VERSION="5.0.0"
   198.8 +VERSION="7.0.0"
   198.9  CATEGORY="development"
  198.10  SHORT_DESC="LLVM (Low Level Virtual Machine): collection of modular and \
  198.11  reusable compiler and toolchain technologies"
  198.12 @@ -11,12 +11,15 @@
  198.13  
  198.14  TARBALL="$PACKAGE-$VERSION.src.tar.xz"
  198.15  WGET_URL="${WEB_SITE}releases/$VERSION/$TARBALL"
  198.16 +TARBALL_SHA1="27503a22614626e935a05b609ab4211be72cd78b"
  198.17  
  198.18 -BUILD_DEPENDS="cmake zlib-dev libffi-dev python"
  198.19 -SPLIT="$PACKAGE-dev $PACKAGE-libs"
  198.20 +BUILD_DEPENDS="cmake zlib-dev libffi-dev ninja"
  198.21 +SPLIT="libllvm $PACKAGE $PACKAGE-dev"
  198.22 +
  198.23 +DEPENDS_std="libffi libllvm"
  198.24 +DEPENDS_libllvm="libffi"
  198.25  
  198.26  compile_rules() {
  198.27 -#	fix math
  198.28  	mkdir build
  198.29  	cd    build
  198.30  
  198.31 @@ -25,28 +28,14 @@
  198.32  		-DCMAKE_INSTALL_PREFIX=/usr \
  198.33  		-DLLVM_ENABLE_FFI=ON \
  198.34  		-DCMAKE_BUILD_TYPE=Release \
  198.35 -		-DBUILD_SHARED_LIBS=ON \
  198.36 -		-DLLVM_TARGETS_TO_BUILD="host;AMDGPU" \
  198.37 +		-DLLVM_BUILD_LLVM_DYLIB=ON \
  198.38 +		-DLLVM_LINK_LLVM_DYLIB=ON \
  198.39 +		-DLLVM_TARGETS_TO_BUILD="host;AMDGPU;BPF" \
  198.40 +		-DLLVM_BUILD_TESTS=ON \
  198.41  		-Wno-dev \
  198.42 +		-G Ninja \
  198.43  		.. &&
  198.44 -	make &&
  198.45 -	make install
  198.46 +	ninja install
  198.47  }
  198.48  
  198.49 -genpkg_rules() {
  198.50 -	case $PACKAGE in
  198.51 -		llvm)
  198.52 -			DEPENDS="libffi gcc-lib-base llvm-libs"
  198.53 -			copy bin/
  198.54 -			;;
  198.55 -		llvm-dev)
  198.56 -			DEPENDS="llvm"
  198.57 -			copy include/ cmake/
  198.58 -			;;
  198.59 -		llvm-libs)
  198.60 -			CAT="libs|libraries"
  198.61 -			DEPENDS="libffi gcc-lib-base"
  198.62 -			copy *.so*
  198.63 -			;;
  198.64 -	esac
  198.65 -}
  198.66 +PROVIDE_libllvm="llvm-libs"
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/luit/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   199.3 @@ -0,0 +1,1 @@
   199.4 +../xorg/.icon.png
   199.5 \ No newline at end of file
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/luit/receipt	Thu Dec 20 17:55:43 2018 +0200
   200.3 @@ -0,0 +1,29 @@
   200.4 +# SliTaz package receipt v2.
   200.5 +
   200.6 +PACKAGE="luit"
   200.7 +VERSION="1.1.1"
   200.8 +CATEGORY="x-window"
   200.9 +SHORT_DESC="Convert terminal i/o from legacy encodings to UTF-8"
  200.10 +MAINTAINER="al.bobylev@gmail.com"
  200.11 +LICENSE="MIT"
  200.12 +WEB_SITE="https://www.x.org/wiki/"
  200.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  200.14 +
  200.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  200.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  200.17 +TARBALL_SHA1="3130c14d7267cecce0ba2280643844b48cca49b0"
  200.18 +
  200.19 +BUILD_DEPENDS="util-macros libfontenc-dev libx11-dev"
  200.20 +DEPENDS="libfontenc"
  200.21 +
  200.22 +compile_rules() {
  200.23 +	sed -i -e "/D_XOPEN/s/5/6/" configure
  200.24 +
  200.25 +	./configure $CONFIGURE_ARGS &&
  200.26 +	make &&
  200.27 +	make install
  200.28 +}
  200.29 +
  200.30 +TAGS="Xorg"
  200.31 +
  200.32 +PROVIDE="xorg-luit"
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/makedepend/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   201.3 @@ -0,0 +1,1 @@
   201.4 +../xorg/.icon.png
   201.5 \ No newline at end of file
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/makedepend/receipt	Thu Dec 20 17:55:43 2018 +0200
   202.3 @@ -0,0 +1,26 @@
   202.4 +# SliTaz package receipt v2.
   202.5 +
   202.6 +PACKAGE="makedepend"
   202.7 +VERSION="1.0.5"
   202.8 +CATEGORY="development"
   202.9 +SHORT_DESC="Create dependencies in makefiles"
  202.10 +MAINTAINER="devel@slitaz.org"
  202.11 +LICENSE="MIT"
  202.12 +WEB_SITE="https://www.x.org/wiki/"
  202.13 +
  202.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  202.15 +WGET_URL="$XORG_MIRROR/util/$TARBALL"
  202.16 +TARBALL_SHA1="2599afa039d2070bae9df6ce43da288b3a4adf97"
  202.17 +
  202.18 +BUILD_DEPENDS="xorgproto"
  202.19 +DEPENDS="xorgproto"
  202.20 +
  202.21 +compile_rules() {
  202.22 +	./configure $CONFIGURE_ARGS &&
  202.23 +	make &&
  202.24 +	make install
  202.25 +}
  202.26 +
  202.27 +TAGS="Xorg"
  202.28 +
  202.29 +PROVIDE="xorg-makedepend"
   203.1 Binary file mesa/.icon.png has changed
   204.1 --- a/mesa/receipt	Thu Dec 13 00:46:54 2018 +0200
   204.2 +++ b/mesa/receipt	Thu Dec 20 17:55:43 2018 +0200
   204.3 @@ -1,7 +1,7 @@
   204.4  # SliTaz package receipt v2.
   204.5  
   204.6  PACKAGE="mesa"
   204.7 -VERSION="17.3.4"
   204.8 +VERSION="18.3.1"
   204.9  CATEGORY="x-window"
  204.10  SHORT_DESC="Open-source implementaton of OpenGL"
  204.11  MAINTAINER="al.bobylev@gmail.com"
  204.12 @@ -9,29 +9,64 @@
  204.13  WEB_SITE="https://www.mesa3d.org/"
  204.14  LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/mesa.html"
  204.15  
  204.16 -TARBALL="mesa-$VERSION.tar.xz"
  204.17 +TARBALL="$PACKAGE-$VERSION.tar.xz"
  204.18  WGET_URL="https://mesa.freedesktop.org/archive/$TARBALL"
  204.19 +TARBALL_SHA1="50ba2d37647fea77ea19416e8a6ffed34c313330"
  204.20  
  204.21 -BUILD_DEPENDS="autoconf automake libtool python libdrm-dev libgcrypt-dev \
  204.22 -eudev-dev xorg-xorgproto \
  204.23 -xorg-libxcb-dev xorg-libxshmfence-dev xorg-libX11-dev xorg-libXext-dev \
  204.24 -xorg-libXdamage-dev xorg-libXfixes-dev xorg-libXxf86vm-dev expat-dev \
  204.25 -elfutils-dev llvm-dev xorg-libpciaccess-dev wayland-dev libva-dev libvdpau-dev \
  204.26 -wayland-protocols-dev libatomic zlib-dev xorg-libXi-dev"
  204.27 -BUILD_DEPENDS="${BUILD_DEPENDS/libva-dev/}"
  204.28 -SPLIT="$PACKAGE-dri $PACKAGE-libegl $PACKAGE-libgbm $PACKAGE-osmesa \
  204.29 -$PACKAGE-libswrAVX $PACKAGE-libwayland-egl $PACKAGE-libxatracker $PACKAGE-vdpau \
  204.30 -$PACKAGE $PACKAGE-dev"
  204.31 +BUILD_DEPENDS="python libdrm-dev libgcrypt-dev eudev-dev xorgproto \
  204.32 +libxcb-dev libxshmfence-dev libx11-dev libxext-dev libxdamage-dev \
  204.33 +libxfixes-dev libxxf86vm-dev expat-dev elfutils-dev llvm-dev libpciaccess-dev \
  204.34 +wayland-dev libva-dev libvdpau-dev wayland-protocols-dev libatomic zlib-dev \
  204.35 +libxi-dev libxrandr-dev"
  204.36 +BUILD_DEPENDS="${BUILD_DEPENDS/libva-dev/}" # dep loop mesa<->libva
  204.37 +SPLIT="\
  204.38 +$PACKAGE-dri    $PACKAGE-libegl       $PACKAGE-libgbm \
  204.39 +$PACKAGE-osmesa $PACKAGE-libxatracker $PACKAGE-vdpau \
  204.40 +$PACKAGE        $PACKAGE-dev"
  204.41 +
  204.42 +COPY_dri="lib/dri/ 90-DRI.conf"
  204.43 +COPY_libegl="libEGL.so*"
  204.44 +COPY_libgbm="libgbm.so*"
  204.45 +COPY_osmesa="libOSMesa.so*"
  204.46 +COPY_libxatracker="libxatracker.so*"
  204.47 +COPY_vdpau="lib/vdpau/"
  204.48 +COPY_std="@std @rm"
  204.49 +
  204.50 +DEPENDS_dri="elfutils expat libdrm libdrm-amdgpu libdrm-etnaviv libdrm-intel \
  204.51 +libdrm-nouveau libdrm-radeon libllvm mesa zlib"
  204.52 +DEPENDS_libegl="expat libdrm libx11 libxcb libxshmfence mesa mesa-libgbm wayland zlib"
  204.53 +DEPENDS_libgbm="expat libdrm wayland zlib"
  204.54 +DEPENDS_osmesa="mesa zlib"
  204.55 +DEPENDS_libxatracker="expat libdrm libdrm-intel libdrm-nouveau libllvm zlib"
  204.56 +DEPENDS_vdpau="elfutils expat libdrm libdrm-amdgpu libdrm-nouveau \
  204.57 +libdrm-radeon libllvm libx11 libxcb libxshmfence zlib"
  204.58 +DEPENDS_std="expat libdrm libx11 libxcb libxdamage libxext libxfixes \
  204.59 +libxshmfence libxxf86vm"
  204.60 +DEPENDS_dev="$PACKAGE $PACKAGE-dri $PACKAGE-libegl $PACKAGE-libgbm \
  204.61 +$PACKAGE-osmesa $PACKAGE-libxatracker $PACKAGE-vdpau \
  204.62 +libdrm-dev wayland-dev libx11-dev libxcb-dev libxdamage-dev libxext-dev \
  204.63 +libxfixes-dev libxxf86vm-dev"
  204.64 +
  204.65 +CAT_dri="x-window|Direct Rendering Infrastructure"
  204.66 +CAT_libegl="x-window|EGL library"
  204.67 +CAT_libgbm="x-window|Graphics Buffer Manager library"
  204.68 +CAT_osmesa="x-window|Off-screen Rendering library"
  204.69 +CAT_libxatracker="x-window|Xorg Gallium3D acceleration library"
  204.70 +CAT_vdpau="x-window|VDPAU drivers"
  204.71 +CAT_std="x-window|main OpenGL libraries"
  204.72 +
  204.73 +SUGGESTED_std="nvidia"
  204.74 +PROVIDE_std="libgl"
  204.75 +CONFIG_FILES_std="/etc/drirc"
  204.76  
  204.77  compile_rules() {
  204.78 -	# Removed from the full list: freedreno,vc4
  204.79 -	# because we haven't appropriate libdrm-* packages (they are only for ARM)
  204.80 -	GLL_DRV="i915,nouveau,r300,r600,radeonsi,svga,swrast,swr,virgl,etnaviv,imx"
  204.81 +	# Removed from the full list:
  204.82 +	#  - freedreno,vc4 (they are only for ARM)
  204.83 +	#  - swr (it doesn't build)
  204.84 +	GLL_DRV="i915,nouveau,r300,r600,radeonsi,svga,swrast,virgl,etnaviv,imx"
  204.85  
  204.86 -	sed -i "/pthread_stubs_possible=/s/yes/no/" configure.ac
  204.87 -	./autogen.sh \
  204.88 -		CFLAGS='-O2' CXXFLAGS='-O2' \
  204.89 -		--enable-texture-float \
  204.90 +	./configure \
  204.91 +		CFLAGS='-O2' CXXFLAGS='-O2' LDFLAGS=-lLLVM \
  204.92  		--enable-gles1 \
  204.93  		--enable-gles2 \
  204.94  		--enable-osmesa \
  204.95 @@ -48,71 +83,3 @@
  204.96  	cook_pick_docs docs/*
  204.97  	install -Dm644 $stuff/90-DRI.conf $install/etc/X11/xorg.conf.d/90-DRI.conf
  204.98  }
  204.99 -
 204.100 -genpkg_rules() {
 204.101 -	case $PACKAGE in
 204.102 -		*-dri)
 204.103 -			copy lib/dri/ 90-DRI.conf
 204.104 -			CAT="x-window|Direct Rendering Infrastructure"
 204.105 -			DEPENDS="elfutils expat libdrm libdrm-amdgpu libdrm-etnaviv \
 204.106 -			libdrm-intel libdrm-nouveau libdrm-radeon llvm-libs mesa \
 204.107 -			xorg-libX11 xorg-libxcb xorg-libxshmfence zlib"
 204.108 -			;;
 204.109 -		*-libegl)
 204.110 -			copy libEGL.so*
 204.111 -			CAT="x-window|EGL library"
 204.112 -			DEPENDS="expat libdrm mesa-libgbm wayland xorg-libX11 \
 204.113 -			xorg-libxcb xorg-libxshmfence zlib"
 204.114 -			;;
 204.115 -		*-libgbm)
 204.116 -			copy libgbm.so*
 204.117 -			CAT="x-window|Graphics Buffer Manager library"
 204.118 -			DEPENDS="expat libdrm wayland"
 204.119 -			;;
 204.120 -		*-osmesa)
 204.121 -			copy libOSMesa.so*
 204.122 -			CAT="x-window|Off-screen Rendering library"
 204.123 -			DEPENDS="mesa zlib"
 204.124 -			;;
 204.125 -		*-libwayland-egl)
 204.126 -			copy libwayland-egl.so*
 204.127 -			CAT="x-window|Wayland EGL library"
 204.128 -			DEPENDS=" "
 204.129 -			;;
 204.130 -		*-libxatracker)
 204.131 -			copy libxatracker.so*
 204.132 -			CAT="x-window|Xorg Gallium3D acceleration library"
 204.133 -			DEPENDS="expat libdrm libdrm-intel libdrm-nouveau llvm-libs zlib"
 204.134 -			;;
 204.135 -		*-vdpau)
 204.136 -			copy lib/vdpau/
 204.137 -			CAT="x-window|VDPAU drivers"
 204.138 -			DEPENDS="elfutils expat libdrm libdrm-amdgpu libdrm-nouveau \
 204.139 -			libdrm-radeon llvm-libs xorg-libX11 xorg-libxcb xorg-libxshmfence \
 204.140 -			zlib"
 204.141 -			;;
 204.142 -		*-libswrAVX)
 204.143 -			copy libswrAVX*so*
 204.144 -			CAT="x-window|Fast software rendering driver for CPU with AVX"
 204.145 -			DEPENDS=" "
 204.146 -			;;
 204.147 -		mesa)
 204.148 -			copy @std @rm
 204.149 -			CAT="x-window|main OpenGL libraries"
 204.150 -			DEPENDS="expat libdrm xorg-libX11 xorg-libXdamage xorg-libXext \
 204.151 -			xorg-libXfixes xorg-libXxf86vm xorg-libxcb xorg-libxshmfence"
 204.152 -			SUGGESTED="nvidia"
 204.153 -			PROVIDE="libgl"
 204.154 -			CONFIG_FILES="/etc/drirc"
 204.155 -			;;
 204.156 -		*-dev)
 204.157 -			copy @dev
 204.158 -			DEPENDS="mesa mesa-dri mesa-libegl mesa-libgbm \
 204.159 -			mesa-osmesa mesa-libwayland-egl mesa-libxatracker \
 204.160 -			mesa-vdpau \
 204.161 -			libdrm-dev wayland-dev xorg-libX11-dev xorg-libXdamage-dev \
 204.162 -			xorg-libXext-dev xorg-libXfixes-dev xorg-libXxf86vm-dev \
 204.163 -			xorg-libxcb-dev"
 204.164 -			;;
 204.165 -	esac
 204.166 -}
   205.1 --- a/mesa/stuff/patches/0005-c99_math-fix-build-issue-with-glibc-2.26.patch	Thu Dec 13 00:46:54 2018 +0200
   205.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.3 @@ -1,81 +0,0 @@
   205.4 -From f8ef875d8b5313d8f15f8680dc0c512c10756ea8 Mon Sep 17 00:00:00 2001
   205.5 -From: Romain Naour <romain.naour@gmail.com>
   205.6 -Date: Sat, 26 Aug 2017 19:20:56 +0200
   205.7 -Subject: [PATCH] c99_math: fix build issue with glibc >= 2.26
   205.8 -MIME-Version: 1.0
   205.9 -Content-Type: text/plain; charset=UTF-8
  205.10 -Content-Transfer-Encoding: 8bit
  205.11 -
  205.12 -The workaround is not required anymore since glibc 2.26 and
  205.13 -trigger a build issue:
  205.14 -
  205.15 -In file included from ../../src/gallium/auxiliary/util/u_math.h:44:0,
  205.16 -                 from ../../src/mesa/main/macros.h:35,
  205.17 -                 from glsl_types.cpp:25:
  205.18 -../../include/c99_math.h:196:12: error: « std::fpclassify »  was not declared in this scope
  205.19 - using std::fpclassify;
  205.20 -            ^~~~~~~~~~
  205.21 -../../include/c99_math.h:197:12: error: « std::isfinite »  was not declared in this scope
  205.22 - using std::isfinite;
  205.23 -            ^~~~~~~~
  205.24 -../../include/c99_math.h:198:12: error: « std::isinf »  was not declared in this scope
  205.25 - using std::isinf;
  205.26 -            ^~~~~
  205.27 -../../include/c99_math.h:199:12: error: « std::isnan »  was not declared in this scope
  205.28 - using std::isnan;
  205.29 -            ^~~~~
  205.30 -../../include/c99_math.h:200:12: error: « std::isnormal »  was not declared in this scope
  205.31 - using std::isnormal;
  205.32 -            ^~~~~~~~
  205.33 -../../include/c99_math.h:201:12: error: « std::signbit »  was not declared in this scope
  205.34 - using std::signbit;
  205.35 -            ^~~~~~~
  205.36 -../../include/c99_math.h:202:12: error: « std::isgreater »  was not declared in this scope
  205.37 - using std::isgreater;
  205.38 -            ^~~~~~~~~
  205.39 -../../include/c99_math.h:203:12: error: « std::isgreaterequal »  was not declared in this scope
  205.40 - using std::isgreaterequal;
  205.41 -            ^~~~~~~~~~~~~~
  205.42 -../../include/c99_math.h:204:12: error: « std::isless »  was not declared in this scope
  205.43 - using std::isless;
  205.44 -            ^~~~~~
  205.45 -../../include/c99_math.h:205:12: error: « std::islessequal »  was not declared in this scope
  205.46 - using std::islessequal;
  205.47 -            ^~~~~~~~~~~
  205.48 -../../include/c99_math.h:206:12: error: « std::islessgreater »  was not declared in this scope
  205.49 - using std::islessgreater;
  205.50 -            ^~~~~~~~~~~~~
  205.51 -../../include/c99_math.h:207:12: error: « std::isunordered »  was not declared in this scope
  205.52 - using std::isunordered;
  205.53 -            ^~~~~~~~~~~
  205.54 -
  205.55 -Signed-off-by: Romain Naour <romain.naour@gmail.com>
  205.56 ----
  205.57 - include/c99_math.h | 5 +++++
  205.58 - 1 file changed, 5 insertions(+)
  205.59 -
  205.60 -diff --git a/include/c99_math.h b/include/c99_math.h
  205.61 -index e906c26..6fd257e 100644
  205.62 ---- a/include/c99_math.h
  205.63 -+++ b/include/c99_math.h
  205.64 -@@ -193,6 +193,10 @@ fpclassify(double x)
  205.65 - #if __cplusplus >= 201103L && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 23))
  205.66 - #include <cmath>
  205.67 - 
  205.68 -+/* This workaround is not necessary since Glibc 2.26
  205.69 -+ * https://sourceware.org/git/?p=glibc.git;a=commit;h=2072f5c34ede81dde9e0d953d57a0690a66b0f12
  205.70 -+ */
  205.71 -+#if (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 25)
  205.72 - using std::fpclassify;
  205.73 - using std::isfinite;
  205.74 - using std::isinf;
  205.75 -@@ -206,6 +210,7 @@ using std::islessequal;
  205.76 - using std::islessgreater;
  205.77 - using std::isunordered;
  205.78 - #endif
  205.79 -+#endif
  205.80 - 
  205.81 - 
  205.82 - #endif /* #define _C99_MATH_H_ */
  205.83 --- 
  205.84 -2.9.5
   206.1 --- a/mesa/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   206.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.3 @@ -1,2 +0,0 @@
   206.4 -# from http://patchwork.ozlabs.org/patch/809139/
   206.5 -0005-c99_math-fix-build-issue-with-glibc-2.26.patch
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/mkfontdir/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   207.3 @@ -0,0 +1,1 @@
   207.4 +../xorg/.icon.png
   207.5 \ No newline at end of file
   208.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   208.2 +++ b/mkfontdir/receipt	Thu Dec 20 17:55:43 2018 +0200
   208.3 @@ -0,0 +1,28 @@
   208.4 +# SliTaz package receipt v2.
   208.5 +
   208.6 +PACKAGE="mkfontdir"
   208.7 +VERSION="1.0.7"
   208.8 +CATEGORY="x-window"
   208.9 +SHORT_DESC="Create an index of X font files in a directory"
  208.10 +MAINTAINER="pascal.bellard@slitaz.org"
  208.11 +LICENSE="MIT"
  208.12 +WEB_SITE="https://www.x.org/wiki/"
  208.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  208.14 +HOST_ARCH="any"
  208.15 +
  208.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  208.17 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  208.18 +TARBALL_SHA1="3c06dad8a5fbf7362b51fb7d6b1ab805eba40336"
  208.19 +
  208.20 +BUILD_DEPENDS="util-macros"
  208.21 +DEPENDS="   mkfontscale"
  208.22 +
  208.23 +compile_rules() {
  208.24 +	./configure $CONFIGURE_ARGS &&
  208.25 +	make &&
  208.26 +	make install
  208.27 +}
  208.28 +
  208.29 +TAGS="Xorg fonts"
  208.30 +
  208.31 +PROVIDE="xorg-mkfontdir"
   209.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   209.2 +++ b/mkfontscale/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   209.3 @@ -0,0 +1,1 @@
   209.4 +../xorg/.icon.png
   209.5 \ No newline at end of file
   210.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   210.2 +++ b/mkfontscale/receipt	Thu Dec 20 17:55:43 2018 +0200
   210.3 @@ -0,0 +1,27 @@
   210.4 +# SliTaz package receipt v2.
   210.5 +
   210.6 +PACKAGE="mkfontscale"
   210.7 +VERSION="1.1.3"
   210.8 +CATEGORY="x-window"
   210.9 +SHORT_DESC="Create an index of scalable font files for X"
  210.10 +MAINTAINER="pascal.bellard@slitaz.org"
  210.11 +LICENSE="MIT"
  210.12 +WEB_SITE="https://www.x.org/wiki/"
  210.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  210.14 +
  210.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  210.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  210.17 +TARBALL_SHA1="2fdbd7c6cc5b0678f2c5d10d2350a809d576e9e5"
  210.18 +
  210.19 +BUILD_DEPENDS="util-macros libfontenc-dev freetype-dev xorgproto"
  210.20 +DEPENDS="freetype libfontenc zlib"
  210.21 +
  210.22 +compile_rules() {
  210.23 +	./configure $CONFIGURE_ARGS &&
  210.24 +	make &&
  210.25 +	make install
  210.26 +}
  210.27 +
  210.28 +TAGS="Xorg fonts"
  210.29 +
  210.30 +PROVIDE="xorg-mkfontscale"
   211.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   211.2 +++ b/oclock/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   211.3 @@ -0,0 +1,1 @@
   211.4 +../xorg/.icon.png
   211.5 \ No newline at end of file
   212.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   212.2 +++ b/oclock/receipt	Thu Dec 20 17:55:43 2018 +0200
   212.3 @@ -0,0 +1,28 @@
   212.4 +# SliTaz package receipt v2.
   212.5 +
   212.6 +PACKAGE="oclock"
   212.7 +VERSION="1.0.4"
   212.8 +CATEGORY="x-window"
   212.9 +SHORT_DESC="Round X clock"
  212.10 +MAINTAINER="al.bobylev@gmail.com"
  212.11 +LICENSE="MIT"
  212.12 +WEB_SITE="https://www.x.org/wiki/"
  212.13 +
  212.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  212.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  212.16 +TARBALL_SHA1="0bc8f3f44290950f60af894e20e0ceb0c5e8e862"
  212.17 +
  212.18 +BUILD_DEPENDS="util-macros libx11-dev libxmu-dev libxext-dev libxt-dev \
  212.19 +libxkbfile-dev"
  212.20 +DEPENDS="libx11 libxext libxmu libxt libxkbfile"
  212.21 +CONFIG_FILES="/etc/X11/app-defaults/Clock-color"
  212.22 +
  212.23 +compile_rules() {
  212.24 +	./configure $CONFIGURE_ARGS &&
  212.25 +	make &&
  212.26 +	make install
  212.27 +}
  212.28 +
  212.29 +TAGS="Xorg"
  212.30 +
  212.31 +PROVIDE="xorg-oclock"
   213.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   213.2 +++ b/pixman/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   213.3 @@ -0,0 +1,1 @@
   213.4 +../xorg/.icon.png
   213.5 \ No newline at end of file
   214.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   214.2 +++ b/pixman/description.txt	Thu Dec 20 17:55:43 2018 +0200
   214.3 @@ -0,0 +1,3 @@
   214.4 +A library for manipulating pixel regions -- a set of Y-X banded rectangles,
   214.5 +image compositing using the Porter/Duff model and implicit mask generation for
   214.6 +geometric primitives including trapezoids, triangles, and rectangles.
   215.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   215.2 +++ b/pixman/receipt	Thu Dec 20 17:55:43 2018 +0200
   215.3 @@ -0,0 +1,31 @@
   215.4 +# SliTaz package receipt v2.
   215.5 +
   215.6 +PACKAGE="pixman"
   215.7 +VERSION="0.36.0"
   215.8 +CATEGORY="x-window"
   215.9 +SHORT_DESC="Pixel-manipulation library for X and Cairo"
  215.10 +MAINTAINER="devel@slitaz.org"
  215.11 +LICENSE="MIT"
  215.12 +WEB_SITE="https://www.cairographics.org/"
  215.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/general/pixman.html"
  215.14 +
  215.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  215.16 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  215.17 +TARBALL_SHA1="10d85590beee287a508a148297808a66d1ce11cd"
  215.18 +
  215.19 +BUILD_DEPENDS="libpng-dev"
  215.20 +SPLIT="$PACKAGE-dev"
  215.21 +
  215.22 +compile_rules() {
  215.23 +	./configure \
  215.24 +		--disable-static \
  215.25 +		$CONFIGURE_ARGS &&
  215.26 +	fix libtool &&
  215.27 +	make &&
  215.28 +	make install
  215.29 +}
  215.30 +
  215.31 +TAGS="Xorg"
  215.32 +
  215.33 +PROVIDE_std="xorg-pixman"
  215.34 +PROVIDE_dev="xorg-pixman-dev"
   216.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   216.2 +++ b/rgb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   216.3 @@ -0,0 +1,1 @@
   216.4 +../xorg/.icon.png
   216.5 \ No newline at end of file
   217.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   217.2 +++ b/rgb/receipt	Thu Dec 20 17:55:43 2018 +0200
   217.3 @@ -0,0 +1,27 @@
   217.4 +# SliTaz package receipt v2.
   217.5 +
   217.6 +PACKAGE="rgb"
   217.7 +VERSION="1.0.6"
   217.8 +CATEGORY="x-window"
   217.9 +SHORT_DESC="X colorname to RGB mapping database"
  217.10 +MAINTAINER="devel@slitaz.org"
  217.11 +LICENSE="MIT"
  217.12 +WEB_SITE="https://www.x.org/wiki/"
  217.13 +
  217.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  217.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  217.16 +TARBALL_SHA1="542fade81a74f8a6beaea8cb517bdf1033fc6b71"
  217.17 +
  217.18 +BUILD_DEPENDS="xorgproto"
  217.19 +
  217.20 +compile_rules() {
  217.21 +	touch /root/missing
  217.22 +
  217.23 +	./configure $CONFIGURE_ARGS &&
  217.24 +	make &&
  217.25 +	make install
  217.26 +}
  217.27 +
  217.28 +TAGS="Xorg"
  217.29 +
  217.30 +PROVIDE="xorg-rgb"
   218.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   218.2 +++ b/sessreg/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   218.3 @@ -0,0 +1,1 @@
   218.4 +../xorg/.icon.png
   218.5 \ No newline at end of file
   219.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   219.2 +++ b/sessreg/receipt	Thu Dec 20 17:55:43 2018 +0200
   219.3 @@ -0,0 +1,26 @@
   219.4 +# SliTaz package receipt v2.
   219.5 +
   219.6 +PACKAGE="sessreg"
   219.7 +VERSION="1.1.1"
   219.8 +CATEGORY="x-window"
   219.9 +SHORT_DESC="Register X sessions in system utmp/utmpx databases"
  219.10 +MAINTAINER="al.bobylev@gmail.com"
  219.11 +LICENSE="MIT"
  219.12 +WEB_SITE="https://www.x.org/wiki/"
  219.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  219.14 +
  219.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  219.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  219.17 +TARBALL_SHA1="09437d9da0b88acde6ca67e231870899023cc3d2"
  219.18 +
  219.19 +BUILD_DEPENDS="util-macros xorgproto"
  219.20 +
  219.21 +compile_rules() {
  219.22 +	./configure $CONFIGURE_ARGS &&
  219.23 +	make &&
  219.24 +	make install
  219.25 +}
  219.26 +
  219.27 +TAGS="Xorg"
  219.28 +
  219.29 +PROVIDE="xorg-sessreg"
   220.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   220.2 +++ b/setxkbmap/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   220.3 @@ -0,0 +1,1 @@
   220.4 +../xorg/.icon.png
   220.5 \ No newline at end of file
   221.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   221.2 +++ b/setxkbmap/receipt	Thu Dec 20 17:55:43 2018 +0200
   221.3 @@ -0,0 +1,27 @@
   221.4 +# SliTaz package receipt v2.
   221.5 +
   221.6 +PACKAGE="setxkbmap"
   221.7 +VERSION="1.3.1"
   221.8 +CATEGORY="x-window"
   221.9 +SHORT_DESC="Set the keyboard using the X Keyboard Extension"
  221.10 +MAINTAINER="pascal.bellard@slitaz.org"
  221.11 +LICENSE="MIT"
  221.12 +WEB_SITE="https://www.x.org/wiki/"
  221.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  221.14 +
  221.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  221.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  221.17 +TARBALL_SHA1="560a02cf6f7db1f79739a4f2bd4f8050c7eb6f43"
  221.18 +
  221.19 +BUILD_DEPENDS="util-macros libxkbfile-dev libx11-dev"
  221.20 +DEPENDS="libx11 libxkbfile" # xkeyboard-config?
  221.21 +
  221.22 +compile_rules() {
  221.23 +	./configure $CONFIGURE_ARGS &&
  221.24 +	make &&
  221.25 +	make install
  221.26 +}
  221.27 +
  221.28 +TAGS="Xorg"
  221.29 +
  221.30 +PROVIDE="xorg-setxkbmap"
   222.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   222.2 +++ b/showfont/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   222.3 @@ -0,0 +1,1 @@
   222.4 +../xorg/.icon.png
   222.5 \ No newline at end of file
   223.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   223.2 +++ b/showfont/receipt	Thu Dec 20 17:55:43 2018 +0200
   223.3 @@ -0,0 +1,26 @@
   223.4 +# SliTaz package receipt v2.
   223.5 +
   223.6 +PACKAGE="showfont"
   223.7 +VERSION="1.0.5"
   223.8 +CATEGORY="x-window"
   223.9 +SHORT_DESC="Show information about X font from font server"
  223.10 +MAINTAINER="al.bobylev@gmail.com"
  223.11 +LICENSE="MIT"
  223.12 +WEB_SITE="https://www.x.org/wiki/"
  223.13 +
  223.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  223.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  223.16 +TARBALL_SHA1="203f4e655333723af7b2c47a85dfba8258f22ebc"
  223.17 +
  223.18 +BUILD_DEPENDS="util-macros libfs-dev"
  223.19 +DEPENDS="libfs"
  223.20 +
  223.21 +compile_rules() {
  223.22 +	./configure $CONFIGURE_ARGS &&
  223.23 +	make &&
  223.24 +	make install
  223.25 +}
  223.26 +
  223.27 +TAGS="Xorg"
  223.28 +
  223.29 +PROVIDE="xorg-showfont"
   224.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   224.2 +++ b/smproxy/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   224.3 @@ -0,0 +1,1 @@
   224.4 +../xorg/.icon.png
   224.5 \ No newline at end of file
   225.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   225.2 +++ b/smproxy/receipt	Thu Dec 20 17:55:43 2018 +0200
   225.3 @@ -0,0 +1,27 @@
   225.4 +# SliTaz package receipt v2.
   225.5 +
   225.6 +PACKAGE="smproxy"
   225.7 +VERSION="1.0.6"
   225.8 +CATEGORY="x-window"
   225.9 +SHORT_DESC="Session Manager Proxy"
  225.10 +MAINTAINER="al.bobylev@gmail.com"
  225.11 +LICENSE="MIT"
  225.12 +WEB_SITE="https://www.x.org/wiki/"
  225.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  225.14 +
  225.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  225.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  225.17 +TARBALL_SHA1="bbb374ad7e184af7bcada70b90df81f82b9b71ad"
  225.18 +
  225.19 +BUILD_DEPENDS="util-macros libsm-dev libice-dev libxt-dev libxmu-dev"
  225.20 +DEPENDS="libice libsm libx11 libxmu libxt"
  225.21 +
  225.22 +compile_rules() {
  225.23 +	./configure $CONFIGURE_ARGS &&
  225.24 +	make &&
  225.25 +	make install
  225.26 +}
  225.27 +
  225.28 +TAGS="Xorg"
  225.29 +
  225.30 +PROVIDE="xorg-smproxy"
   226.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.2 +++ b/twm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   226.3 @@ -0,0 +1,1 @@
   226.4 +../xorg/.icon.png
   226.5 \ No newline at end of file
   227.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   227.2 +++ b/twm/receipt	Thu Dec 20 17:55:43 2018 +0200
   227.3 @@ -0,0 +1,31 @@
   227.4 +# SliTaz package receipt v2.
   227.5 +
   227.6 +PACKAGE="twm"
   227.7 +VERSION="1.0.10"
   227.8 +CATEGORY="x-window"
   227.9 +SHORT_DESC="Simple window manager"
  227.10 +MAINTAINER="al.bobylev@gmail.com"
  227.11 +LICENSE="MIT"
  227.12 +WEB_SITE="https://en.wikipedia.org/wiki/Twm"
  227.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/twm.html"
  227.14 +
  227.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  227.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  227.17 +TARBALL_SHA1="f632a47620dfe6d75b003839d269b14fa22b262e"
  227.18 +
  227.19 +BUILD_DEPENDS="util-macros libx11-dev libxext-dev libxt-dev libxmu-dev"
  227.20 +DEPENDS="libice libsm libx11 libxext libxmu libxt"
  227.21 +
  227.22 +CONFIG_FILES="/etc/X11/app-defaults/system.twmrc"
  227.23 +
  227.24 +compile_rules() {
  227.25 +	sed -i '/^rcdir =/s,^\(rcdir = \).*,\1/etc/X11/app-defaults,' src/Makefile.in
  227.26 +
  227.27 +	./configure $CONFIGURE_ARGS &&
  227.28 +	make &&
  227.29 +	make install
  227.30 +}
  227.31 +
  227.32 +TAGS="Xorg"
  227.33 +
  227.34 +PROVIDE="xorg-twm"
   228.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   228.2 +++ b/util-macros/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   228.3 @@ -0,0 +1,1 @@
   228.4 +../xorg/.icon.png
   228.5 \ No newline at end of file
   229.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   229.2 +++ b/util-macros/receipt	Thu Dec 20 17:55:43 2018 +0200
   229.3 @@ -0,0 +1,28 @@
   229.4 +# SliTaz package receipt v2.
   229.5 +
   229.6 +PACKAGE="util-macros"
   229.7 +VERSION="1.19.2"
   229.8 +CATEGORY="development"
   229.9 +SHORT_DESC="Autoconf macros used in X modular configure.ac files"
  229.10 +MAINTAINER="devel@slitaz.org"
  229.11 +LICENSE="MIT"
  229.12 +WEB_SITE="https://www.x.org/wiki/"
  229.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/util-macros.html"
  229.14 +HOST_ARCH="any"
  229.15 +
  229.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  229.17 +WGET_URL="$XORG_MIRROR/util/$TARBALL"
  229.18 +TARBALL_SHA1="e8b3a6f2bfde22440fca0974da53da18821a4ee6"
  229.19 +
  229.20 +COPY="@dev"
  229.21 +DEPENDS="m4"
  229.22 +
  229.23 +compile_rules() {
  229.24 +	./configure $CONFIGURE_ARGS &&
  229.25 +	make &&
  229.26 +	make install
  229.27 +}
  229.28 +
  229.29 +TAGS="Xorg"
  229.30 +
  229.31 +PROVIDE="xorg-util-macros"
   230.1 --- a/wayland-protocols/receipt	Thu Dec 13 00:46:54 2018 +0200
   230.2 +++ b/wayland-protocols/receipt	Thu Dec 20 17:55:43 2018 +0200
   230.3 @@ -1,16 +1,18 @@
   230.4  # SliTaz package receipt v2.
   230.5  
   230.6  PACKAGE="wayland-protocols"
   230.7 -VERSION="1.13"
   230.8 +VERSION="1.17"
   230.9  CATEGORY="system-tools"
  230.10  SHORT_DESC="Additional Wayland protocols"
  230.11  MAINTAINER="al.bobylev@gmail.com"
  230.12  LICENSE="LGPL2.1"
  230.13  WEB_SITE="https://wayland.freedesktop.org/"
  230.14  LFS="http://www.linuxfromscratch.org/blfs/view/svn/general/wayland-protocols.html"
  230.15 +HOST_ARCH="any"
  230.16  
  230.17  TARBALL="$PACKAGE-$VERSION.tar.xz"
  230.18  WGET_URL="https://wayland.freedesktop.org/releases/$TARBALL"
  230.19 +TARBALL_SHA1="7d2569c838c776545e3eb1b1049b9c37178aae24"
  230.20  
  230.21  BUILD_DEPENDS="wayland-dev"
  230.22  SPLIT="$PACKAGE-dev"
  230.23 @@ -20,10 +22,3 @@
  230.24  	make &&
  230.25  	make install
  230.26  }
  230.27 -
  230.28 -genpkg_rules() {
  230.29 -	case $PACKAGE in
  230.30 -		wayland-protocols) copy @std;;
  230.31 -		*-dev)             copy @dev;;
  230.32 -	esac
  230.33 -}
   231.1 Binary file wayland/.icon.png has changed
   232.1 --- a/wayland/receipt	Thu Dec 13 00:46:54 2018 +0200
   232.2 +++ b/wayland/receipt	Thu Dec 20 17:55:43 2018 +0200
   232.3 @@ -1,7 +1,7 @@
   232.4  # SliTaz package receipt v2.
   232.5  
   232.6  PACKAGE="wayland"
   232.7 -VERSION="1.14.0"
   232.8 +VERSION="1.16.0"
   232.9  CATEGORY="x-window"
  232.10  SHORT_DESC="Wayland simpler X display server protocol"
  232.11  MAINTAINER="devel@slitaz.org"
  232.12 @@ -11,10 +11,13 @@
  232.13  
  232.14  TARBALL="$PACKAGE-$VERSION.tar.xz"
  232.15  WGET_URL="http://wayland.freedesktop.org/releases/$TARBALL"
  232.16 +TARBALL_SHA1="24c63a5045c653dcfa24efd10fa7c7de89aca9ef"
  232.17  
  232.18  BUILD_DEPENDS="libffi-dev expat-dev libxml2-dev"
  232.19  SPLIT="$PACKAGE-dev"
  232.20  
  232.21 +DEPENDS="expat libffi libxml2"
  232.22 +
  232.23  compile_rules() {
  232.24  	./configure \
  232.25  		--disable-static \
  232.26 @@ -24,15 +27,3 @@
  232.27  	make &&
  232.28  	make install
  232.29  }
  232.30 -
  232.31 -genpkg_rules() {
  232.32 -	case $PACKAGE in
  232.33 -		wayland)
  232.34 -			copy @std
  232.35 -			DEPENDS="expat libffi libxml2"
  232.36 -			;;
  232.37 -		*-dev)
  232.38 -			copy @dev
  232.39 -			;;
  232.40 -	esac
  232.41 -}
   233.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   233.2 +++ b/x11perf/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   233.3 @@ -0,0 +1,1 @@
   233.4 +../xorg/.icon.png
   233.5 \ No newline at end of file
   234.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   234.2 +++ b/x11perf/receipt	Thu Dec 20 17:55:43 2018 +0200
   234.3 @@ -0,0 +1,28 @@
   234.4 +# SliTaz package receipt v2.
   234.5 +
   234.6 +PACKAGE="x11perf"
   234.7 +VERSION="1.6.0"
   234.8 +CATEGORY="x-window"
   234.9 +SHORT_DESC="Utility who runs one or more performance tests and reports"
  234.10 +MAINTAINER="paul@slitaz.org"
  234.11 +LICENSE="MIT"
  234.12 +WEB_SITE="https://www.x.org/wiki/"
  234.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  234.14 +
  234.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  234.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  234.17 +TARBALL_SHA1="de4960357e077fddd3d3a33f72f579981efc7fa4"
  234.18 +
  234.19 +BUILD_DEPENDS="util-macros libx11-dev libxmu-dev xorgproto libxrender-dev \
  234.20 +libxft-dev"
  234.21 +DEPENDS="libx11 libxext libxft libxmu libxrender"
  234.22 +
  234.23 +compile_rules() {
  234.24 +	./configure $CONFIGURE_ARGS &&
  234.25 +	make &&
  234.26 +	make install
  234.27 +}
  234.28 +
  234.29 +TAGS="Xorg"
  234.30 +
  234.31 +PROVIDE="xorg-x11perf"
   235.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   235.2 +++ b/xauth/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   235.3 @@ -0,0 +1,1 @@
   235.4 +../xorg/.icon.png
   235.5 \ No newline at end of file
   236.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   236.2 +++ b/xauth/receipt	Thu Dec 20 17:55:43 2018 +0200
   236.3 @@ -0,0 +1,30 @@
   236.4 +# SliTaz package receipt v2.
   236.5 +
   236.6 +PACKAGE="xauth"
   236.7 +VERSION="1.0.10"
   236.8 +CATEGORY="x-window"
   236.9 +SHORT_DESC="X authority file utility"
  236.10 +MAINTAINER="devel@slitaz.org"
  236.11 +LICENSE="MIT"
  236.12 +WEB_SITE="https://www.x.org/wiki/"
  236.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  236.14 +
  236.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  236.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  236.17 +TARBALL_SHA1="87946b2af3ff13705d8eb60adae5c0bcdf839967"
  236.18 +
  236.19 +BUILD_DEPENDS="libxmu-dev"
  236.20 +DEPENDS="libx11 libxau libxext libxmu"
  236.21 +
  236.22 +compile_rules() {
  236.23 +	./configure $CONFIGURE_ARGS &&
  236.24 +	make &&
  236.25 +	make install
  236.26 +
  236.27 +#	mkdir -p $install/usr/X11R6
  236.28 +#	ln -s ../bin $install/usr/X11R6/bin
  236.29 +}
  236.30 +
  236.31 +TAGS="Xorg"
  236.32 +
  236.33 +PROVIDE="xorg-xauth"
   237.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   237.2 +++ b/xbacklight/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   237.3 @@ -0,0 +1,1 @@
   237.4 +../xorg/.icon.png
   237.5 \ No newline at end of file
   238.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   238.2 +++ b/xbacklight/receipt	Thu Dec 20 17:55:43 2018 +0200
   238.3 @@ -0,0 +1,27 @@
   238.4 +# SliTaz package receipt v2.
   238.5 +
   238.6 +PACKAGE="xbacklight"
   238.7 +VERSION="1.2.2"
   238.8 +CATEGORY="x-window"
   238.9 +SHORT_DESC="Adjust backlight brightness using RandR extension"
  238.10 +MAINTAINER="devel@slitaz.org"
  238.11 +LICENSE="MIT"
  238.12 +WEB_SITE="https://www.x.org/wiki/"
  238.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  238.14 +
  238.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  238.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  238.17 +TARBALL_SHA1="8cc84c4b2e23e99bfa72239847af4b42ae89669e"
  238.18 +
  238.19 +BUILD_DEPENDS="util-macros libxcb-dev xcb-util-dev libxrandr-dev"
  238.20 +DEPENDS="libxcb xcb-util"
  238.21 +
  238.22 +compile_rules() {
  238.23 +	./configure $CONFIGURE_ARGS &&
  238.24 +	make &&
  238.25 +	make install
  238.26 +}
  238.27 +
  238.28 +TAGS="Xorg power backlight"
  238.29 +
  238.30 +PROVIDE="xorg-xbacklight"
   239.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   239.2 +++ b/xbitmaps/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   239.3 @@ -0,0 +1,1 @@
   239.4 +../xorg/.icon.png
   239.5 \ No newline at end of file
   240.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   240.2 +++ b/xbitmaps/receipt	Thu Dec 20 17:55:43 2018 +0200
   240.3 @@ -0,0 +1,30 @@
   240.4 +# SliTaz package receipt v2.
   240.5 +
   240.6 +PACKAGE="xbitmaps"
   240.7 +VERSION="1.1.2"
   240.8 +CATEGORY="development"
   240.9 +SHORT_DESC="Standard set of X bitmaps"
  240.10 +MAINTAINER="devel@slitaz.org"
  240.11 +LICENSE="MIT"
  240.12 +WEB_SITE="https://www.x.org/wiki/"
  240.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xbitmaps.html"
  240.14 +HOST_ARCH="any"
  240.15 +
  240.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  240.17 +WGET_URL="$XORG_MIRROR/data/$TARBALL"
  240.18 +TARBALL_SHA1="1cb0e485a66280e9a64b48426140b8a0de9cf169"
  240.19 +
  240.20 +BUILD_DEPENDS="util-macros"
  240.21 +
  240.22 +COPY="@dev"
  240.23 +DEPENDS="util-macros"
  240.24 +
  240.25 +compile_rules() {
  240.26 +	./configure $CONFIGURE_ARGS &&
  240.27 +	make &&
  240.28 +	make install
  240.29 +}
  240.30 +
  240.31 +TAGS="Xorg"
  240.32 +
  240.33 +PROVIDE="xorg-xbitmaps"
   241.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   241.2 +++ b/xcalc/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   241.3 @@ -0,0 +1,1 @@
   241.4 +../xorg/.icon.png
   241.5 \ No newline at end of file
   242.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   242.2 +++ b/xcalc/receipt	Thu Dec 20 17:55:43 2018 +0200
   242.3 @@ -0,0 +1,28 @@
   242.4 +# SliTaz package receipt v2.
   242.5 +
   242.6 +PACKAGE="xcalc"
   242.7 +VERSION="1.0.6"
   242.8 +CATEGORY="x-window"
   242.9 +SHORT_DESC="Scientific calculator for X"
  242.10 +MAINTAINER="al.bobylev@gmail.com"
  242.11 +LICENSE="MIT"
  242.12 +WEB_SITE="https://www.x.org/wiki/"
  242.13 +
  242.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  242.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  242.16 +TARBALL_SHA1="4f9e14b9ff91e3976b702bdad92f639df80cf406"
  242.17 +
  242.18 +BUILD_DEPENDS="util-macros libxaw-dev libxt-dev libx11-dev xorgproto"
  242.19 +DEPENDS="libx11 libxaw libxt"
  242.20 +
  242.21 +CONFIG_FILES="/etc/X11/app-defaults/XCalc /etc/X11/app-defaults/XCalc-color"
  242.22 +
  242.23 +compile_rules() {
  242.24 +	./configure $CONFIGURE_ARGS &&
  242.25 +	make &&
  242.26 +	make install
  242.27 +}
  242.28 +
  242.29 +TAGS="Xorg"
  242.30 +
  242.31 +PROVIDE="xorg-xcalc"
   243.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   243.2 +++ b/xcb-proto/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   243.3 @@ -0,0 +1,1 @@
   243.4 +../xorg/.icon.png
   243.5 \ No newline at end of file
   244.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   244.2 +++ b/xcb-proto/description.txt	Thu Dec 20 17:55:43 2018 +0200
   244.3 @@ -0,0 +1,3 @@
   244.4 +The X protocol C-language Binding (XCB) is a replacement for Xlib featuring
   244.5 +a small footprint, latency hiding, direct access to the protocol, improved
   244.6 +threading support, and extensibility.
   245.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   245.2 +++ b/xcb-proto/receipt	Thu Dec 20 17:55:43 2018 +0200
   245.3 @@ -0,0 +1,30 @@
   245.4 +# SliTaz package receipt v2.
   245.5 +
   245.6 +PACKAGE="xcb-proto"
   245.7 +VERSION="1.13"
   245.8 +CATEGORY="development"
   245.9 +SHORT_DESC="X protocol descriptions for XCB"
  245.10 +MAINTAINER="devel@slitaz.org"
  245.11 +LICENSE="MIT"
  245.12 +WEB_SITE="https://xcb.freedesktop.org/"
  245.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-proto.html"
  245.14 +HOST_ARCH="any"
  245.15 +
  245.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  245.17 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  245.18 +TARBALL_SHA1="f7fa35ab59af18cecadbe83fe705281dcfd82ffd"
  245.19 +
  245.20 +BUILD_DEPENDS="python-dev libxml2-tools"
  245.21 +
  245.22 +COPY="@std @dev"
  245.23 +DEPENDS="python"
  245.24 +
  245.25 +compile_rules() {
  245.26 +	./configure $CONFIGURE_ARGS &&
  245.27 +	make &&
  245.28 +	make install
  245.29 +}
  245.30 +
  245.31 +TAGS="Xorg"
  245.32 +
  245.33 +PROVIDE="xorg-xcb-proto"
   246.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   246.2 +++ b/xcb-util-cursor/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   246.3 @@ -0,0 +1,1 @@
   246.4 +../xorg/.icon.png
   246.5 \ No newline at end of file
   247.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   247.2 +++ b/xcb-util-cursor/receipt	Thu Dec 20 17:55:43 2018 +0200
   247.3 @@ -0,0 +1,35 @@
   247.4 +# SliTaz package receipt v2.
   247.5 +
   247.6 +PACKAGE="xcb-util-cursor"
   247.7 +VERSION="0.1.3"
   247.8 +CATEGORY="x-window"
   247.9 +SHORT_DESC="Module that implements the XCB cursor library"
  247.10 +MAINTAINER="al.bobylev@gmail.com"
  247.11 +LICENSE="MIT"
  247.12 +WEB_SITE="https://xcb.freedesktop.org/"
  247.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-cursor.html"
  247.14 +
  247.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  247.16 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  247.17 +TARBALL_SHA1="26562eb6d4151307f7b6a53453d360ecfc0563ac"
  247.18 +
  247.19 +BUILD_DEPENDS="libxcb-dev xcb-util-dev xcb-util-renderutil-dev \
  247.20 +xcb-util-image-dev"
  247.21 +SPLIT="$PACKAGE-dev"
  247.22 +
  247.23 +DEPENDS_std="libxcb xcb-util-image xcb-util-renderutil"
  247.24 +DEPENDS_dev="$PACKAGE libxcb-dev xcb-util-image-dev xcb-util-renderutil-dev"
  247.25 +
  247.26 +compile_rules() {
  247.27 +	./configure \
  247.28 +		--disable-static \
  247.29 +		$CONFIGURE_ARGS &&
  247.30 +	fix libtool &&
  247.31 +	make &&
  247.32 +	make install
  247.33 +}
  247.34 +
  247.35 +TAGS="Xorg"
  247.36 +
  247.37 +PROVIDE_std="xorg-xcb-util-cursor"
  247.38 +PROVIDE_dev="xorg-xcb-util-cursor-dev"
   248.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   248.2 +++ b/xcb-util-image/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   248.3 @@ -0,0 +1,1 @@
   248.4 +../xorg/.icon.png
   248.5 \ No newline at end of file
   249.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   249.2 +++ b/xcb-util-image/receipt	Thu Dec 20 17:55:43 2018 +0200
   249.3 @@ -0,0 +1,35 @@
   249.4 +# SliTaz package receipt v2.
   249.5 +
   249.6 +PACKAGE="xcb-util-image"
   249.7 +VERSION="0.4.0"
   249.8 +CATEGORY="x-window"
   249.9 +SHORT_DESC="Utility libraries for XC Binding - Port of Xlib's XImage and \
  249.10 +XShmImage functions"
  249.11 +MAINTAINER="devel@slitaz.org"
  249.12 +LICENSE="MIT"
  249.13 +WEB_SITE="https://xcb.freedesktop.org/"
  249.14 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-image.html"
  249.15 +
  249.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  249.17 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  249.18 +TARBALL_SHA1="c9c9361781911a47b28f74fc6ebe0abd1273fae4"
  249.19 +
  249.20 +BUILD_DEPENDS="libxcb-dev xcb-util-dev"
  249.21 +SPLIT="$PACKAGE-dev"
  249.22 +
  249.23 +DEPENDS_std="libxcb xcb-util"
  249.24 +DEPENDS_dev="$PACKAGE libxcb-dev"
  249.25 +
  249.26 +compile_rules() {
  249.27 +	./configure \
  249.28 +		--disable-static \
  249.29 +		$CONFIGURE_ARGS &&
  249.30 +	fix libtool &&
  249.31 +	make &&
  249.32 +	make install
  249.33 +}
  249.34 +
  249.35 +TAGS="Xorg"
  249.36 +
  249.37 +PROVIDE_std="xorg-xcb-util-image"
  249.38 +PROVIDE_dev="xorg-xcb-util-image-dev"
   250.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   250.2 +++ b/xcb-util-keysyms/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   250.3 @@ -0,0 +1,1 @@
   250.4 +../xorg/.icon.png
   250.5 \ No newline at end of file
   251.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   251.2 +++ b/xcb-util-keysyms/receipt	Thu Dec 20 17:55:43 2018 +0200
   251.3 @@ -0,0 +1,34 @@
   251.4 +# SliTaz package receipt v2.
   251.5 +
   251.6 +PACKAGE="xcb-util-keysyms"
   251.7 +VERSION="0.4.0"
   251.8 +CATEGORY="x-window"
   251.9 +SHORT_DESC="Utility libraries for XC Binding"
  251.10 +MAINTAINER="devel@slitaz.org"
  251.11 +LICENSE="GPL"
  251.12 +WEB_SITE="https://xcb.freedesktop.org/"
  251.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-keysyms.html"
  251.14 +
  251.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  251.16 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  251.17 +TARBALL_SHA1="ff02ee8ac22c53848af50c0a6a6b00feb002c1cb"
  251.18 +
  251.19 +BUILD_DEPENDS="libxcb-dev"
  251.20 +SPLIT="$PACKAGE-dev"
  251.21 +
  251.22 +DEPENDS_std="libxcb"
  251.23 +DEPENDS_dev="$PACKAGE libxcb-dev"
  251.24 +
  251.25 +compile_rules() {
  251.26 +	./configure \
  251.27 +		--disable-static \
  251.28 +		$CONFIGURE_ARGS &&
  251.29 +	fix libtool &&
  251.30 +	make &&
  251.31 +	make install
  251.32 +}
  251.33 +
  251.34 +TAGS="Xorg"
  251.35 +
  251.36 +PROVIDE_std="xorg-xcb-util-keysyms"
  251.37 +PROVIDE_dev="xorg-xcb-util-keysyms-dev"
   252.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   252.2 +++ b/xcb-util-renderutil/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   252.3 @@ -0,0 +1,1 @@
   252.4 +../xorg/.icon.png
   252.5 \ No newline at end of file
   253.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   253.2 +++ b/xcb-util-renderutil/receipt	Thu Dec 20 17:55:43 2018 +0200
   253.3 @@ -0,0 +1,34 @@
   253.4 +# SliTaz package receipt v2.
   253.5 +
   253.6 +PACKAGE="xcb-util-renderutil"
   253.7 +VERSION="0.3.9"
   253.8 +CATEGORY="x-window"
   253.9 +SHORT_DESC="Additional extension to the XCB library"
  253.10 +MAINTAINER="al.bobylev@gmail.com"
  253.11 +LICENSE="MIT"
  253.12 +WEB_SITE="https://xcb.freedesktop.org/"
  253.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-renderutil.html"
  253.14 +
  253.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  253.16 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  253.17 +TARBALL_SHA1="cb533b1d039f833f070e7d6398c221a31d30d5e2"
  253.18 +
  253.19 +BUILD_DEPENDS="libxcb-dev"
  253.20 +SPLIT="$PACKAGE-dev"
  253.21 +
  253.22 +DEPENDS_std="libxcb"
  253.23 +DEPENDS_dev="$PACKAGE libxcb-dev"
  253.24 +
  253.25 +compile_rules() {
  253.26 +	./configure \
  253.27 +		--disable-static \
  253.28 +		$CONFIGURE_ARGS &&
  253.29 +	fix libtool &&
  253.30 +	make &&
  253.31 +	make install
  253.32 +}
  253.33 +
  253.34 +TAGS="Xorg"
  253.35 +
  253.36 +PROVIDE_std="xorg-xcb-util-renderutil"
  253.37 +PROVIDE_dev="xorg-xcb-util-renderutil-dev"
   254.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   254.2 +++ b/xcb-util-wm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   254.3 @@ -0,0 +1,1 @@
   254.4 +../xorg/.icon.png
   254.5 \ No newline at end of file
   255.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   255.2 +++ b/xcb-util-wm/receipt	Thu Dec 20 17:55:43 2018 +0200
   255.3 @@ -0,0 +1,35 @@
   255.4 +# SliTaz package receipt v2.
   255.5 +
   255.6 +PACKAGE="xcb-util-wm"
   255.7 +VERSION="0.4.1"
   255.8 +CATEGORY="x-window"
   255.9 +SHORT_DESC="Utility libraries for XC Binding - client and window-manager \
  255.10 +helpers for ICCCM"
  255.11 +MAINTAINER="devel@slitaz.org"
  255.12 +LICENSE="MIT"
  255.13 +WEB_SITE="https://xcb.freedesktop.org/"
  255.14 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-wm.html"
  255.15 +
  255.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  255.17 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  255.18 +TARBALL_SHA1="7006c52b961c123355320bfc30477cdf90c8bbb7"
  255.19 +
  255.20 +BUILD_DEPENDS="libxcb-dev"
  255.21 +SPLIT="$PACKAGE-dev"
  255.22 +
  255.23 +DEPENDS_std="libxcb"
  255.24 +DEPENDS_dev="$PACKAGE libxcb-dev"
  255.25 +
  255.26 +compile_rules() {
  255.27 +	./configure \
  255.28 +		--disable-static \
  255.29 +		$CONFIGURE_ARGS &&
  255.30 +	fix libtool &&
  255.31 +	make &&
  255.32 +	make install
  255.33 +}
  255.34 +
  255.35 +TAGS="Xorg"
  255.36 +
  255.37 +PROVIDE_std="xorg-xcb-util-wm"
  255.38 +PROVIDE_dev="xorg-xcb-util-wm-dev"
   256.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   256.2 +++ b/xcb-util/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   256.3 @@ -0,0 +1,1 @@
   256.4 +../xorg/.icon.png
   256.5 \ No newline at end of file
   257.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   257.2 +++ b/xcb-util/description.txt	Thu Dec 20 17:55:43 2018 +0200
   257.3 @@ -0,0 +1,6 @@
   257.4 +The XCB util modules provides a number of libraries which sit on top of libxcb,
   257.5 +the core X protocol library, and some of the extension libraries. These
   257.6 +experimental libraries provide convenience functions and interfaces which make
   257.7 +the raw X protocol more usable. Some of the libraries also provide client-side
   257.8 +code which is not strictly part of the X protocol but which have traditionally
   257.9 +been provided by Xlib.
   258.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   258.2 +++ b/xcb-util/receipt	Thu Dec 20 17:55:43 2018 +0200
   258.3 @@ -0,0 +1,34 @@
   258.4 +# SliTaz package receipt v2.
   258.5 +
   258.6 +PACKAGE="xcb-util"
   258.7 +VERSION="0.4.0"
   258.8 +CATEGORY="x-window"
   258.9 +SHORT_DESC="XCB Utilites"
  258.10 +MAINTAINER="devel@slitaz.org"
  258.11 +LICENSE="MIT"
  258.12 +WEB_SITE="https://xcb.freedesktop.org/"
  258.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util.html"
  258.14 +
  258.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  258.16 +WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  258.17 +TARBALL_SHA1="7f2e9b7efcc2c34eb1d6ae312c3d73b075832e46"
  258.18 +
  258.19 +BUILD_DEPENDS="libxcb-dev gperf"
  258.20 +SPLIT="$PACKAGE-dev"
  258.21 +
  258.22 +DEPENDS_std="libxcb"
  258.23 +DEPENDS_dev="$PACKAGE libxcb-dev"
  258.24 +
  258.25 +compile_rules() {
  258.26 +	./configure \
  258.27 +		--disable-static \
  258.28 +		$CONFIGURE_ARGS &&
  258.29 +	fix libtool &&
  258.30 +	make &&
  258.31 +	make install
  258.32 +}
  258.33 +
  258.34 +TAGS="Xorg"
  258.35 +
  258.36 +PROVIDE_std="xorg-xcb-util"
  258.37 +PROVIDE_dev="xorg-xcb-util-dev"
   259.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   259.2 +++ b/xclipboard/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   259.3 @@ -0,0 +1,1 @@
   259.4 +../xorg/.icon.png
   259.5 \ No newline at end of file
   260.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   260.2 +++ b/xclipboard/receipt	Thu Dec 20 17:55:43 2018 +0200
   260.3 @@ -0,0 +1,28 @@
   260.4 +# SliTaz package receipt v2.
   260.5 +
   260.6 +PACKAGE="xclipboard"
   260.7 +VERSION="1.1.3"
   260.8 +CATEGORY="x-window"
   260.9 +SHORT_DESC="X clipboard manager"
  260.10 +MAINTAINER="al.bobylev@gmail.com"
  260.11 +LICENSE="MIT"
  260.12 +WEB_SITE="https://www.x.org/wiki/"
  260.13 +
  260.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  260.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  260.16 +TARBALL_SHA1="971ac3900b4eb5ad54f3c3d9527e96ccdcb9e504"
  260.17 +
  260.18 +BUILD_DEPENDS="util-macros libxaw-dev libxmu-dev libxt-dev libx11-dev xorgproto"
  260.19 +DEPENDS="libx11 libxaw libxmu libxt"
  260.20 +
  260.21 +CONFIG_FILES="/etc/X11/app-defaults/XClipboard"
  260.22 +
  260.23 +compile_rules() {
  260.24 +	./configure $CONFIGURE_ARGS &&
  260.25 +	make &&
  260.26 +	make install
  260.27 +}
  260.28 +
  260.29 +TAGS="Xorg"
  260.30 +
  260.31 +PROVIDE="xorg-xclipboard"
   261.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   261.2 +++ b/xclock/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   261.3 @@ -0,0 +1,1 @@
   261.4 +../xorg/.icon.png
   261.5 \ No newline at end of file
   262.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   262.2 +++ b/xclock/receipt	Thu Dec 20 17:55:43 2018 +0200
   262.3 @@ -0,0 +1,30 @@
   262.4 +# SliTaz package receipt v2.
   262.5 +
   262.6 +PACKAGE="xclock"
   262.7 +VERSION="1.0.7"
   262.8 +CATEGORY="x-window"
   262.9 +SHORT_DESC="X clock"
  262.10 +MAINTAINER="devel@slitaz.org"
  262.11 +LICENSE="MIT"
  262.12 +WEB_SITE="https://www.x.org/wiki/"
  262.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xclock.html"
  262.14 +
  262.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  262.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  262.17 +TARBALL_SHA1="1b54b96e057469f90a00a9f1ca79ed056cbde271"
  262.18 +
  262.19 +BUILD_DEPENDS="util-macros libxaw-dev libxmu-dev libx11-dev libxrender-dev \
  262.20 +libxft-dev libxkbfile-dev"
  262.21 +DEPENDS="libx11 libxaw libxft libxmu libxrender libxt libxkbfile"
  262.22 +
  262.23 +CONFIG_FILES="/etc/X11/app-defaults/XClock /etc/X11/app-defaults/XClock-color"
  262.24 +
  262.25 +compile_rules() {
  262.26 +	./configure $CONFIGURE_ARGS &&
  262.27 +	make &&
  262.28 +	make install
  262.29 +}
  262.30 +
  262.31 +TAGS="Xorg"
  262.32 +
  262.33 +PROVIDE="xorg-xclock"
   263.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   263.2 +++ b/xcmsdb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   263.3 @@ -0,0 +1,1 @@
   263.4 +../xorg/.icon.png
   263.5 \ No newline at end of file
   264.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   264.2 +++ b/xcmsdb/receipt	Thu Dec 20 17:55:43 2018 +0200
   264.3 @@ -0,0 +1,27 @@
   264.4 +# SliTaz package receipt v2.
   264.5 +
   264.6 +PACKAGE="xcmsdb"
   264.7 +VERSION="1.0.5"
   264.8 +CATEGORY="x-window"
   264.9 +SHORT_DESC="Device Color Characterization utility for X Color Management System"
  264.10 +MAINTAINER="al.bobylev@gmail.com"
  264.11 +LICENSE="MIT"
  264.12 +WEB_SITE="https://www.x.org/wiki/"
  264.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  264.14 +
  264.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  264.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  264.17 +TARBALL_SHA1="b1d09b1a9a4324fa86c85340ae47cc34743423a9"
  264.18 +
  264.19 +BUILD_DEPENDS="util-macros libx11-dev"
  264.20 +DEPENDS="libx11"
  264.21 +
  264.22 +compile_rules() {
  264.23 +	./configure $CONFIGURE_ARGS &&
  264.24 +	make &&
  264.25 +	make install
  264.26 +}
  264.27 +
  264.28 +TAGS="Xorg"
  264.29 +
  264.30 +PROVIDE="xorg-xcmsdb"
   265.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   265.2 +++ b/xcompmgr/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   265.3 @@ -0,0 +1,1 @@
   265.4 +../xorg/.icon.png
   265.5 \ No newline at end of file
   266.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   266.2 +++ b/xcompmgr/receipt	Thu Dec 20 17:55:43 2018 +0200
   266.3 @@ -0,0 +1,30 @@
   266.4 +# SliTaz package receipt v2.
   266.5 +
   266.6 +PACKAGE="xcompmgr"
   266.7 +VERSION="1.1.7"
   266.8 +CATEGORY="x-window"
   266.9 +SHORT_DESC="X composite manager"
  266.10 +MAINTAINER="devel@slitaz.org"
  266.11 +LICENSE="MIT"
  266.12 +WEB_SITE="https://www.x.org/wiki/"
  266.13 +
  266.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  266.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  266.16 +TARBALL_SHA1="5590d1bdd2669f083e4c2bb25edd89cce8abbd58"
  266.17 +
  266.18 +BUILD_DEPENDS="util-macros libxcomposite-dev libxfixes-dev libxdamage-dev \
  266.19 +libxrender-dev libxext-dev"
  266.20 +DEPENDS="libx11 libxcomposite libxdamage libxext libxfixes libxrender"
  266.21 +
  266.22 +compile_rules() {
  266.23 +	./configure $CONFIGURE_ARGS &&
  266.24 +	make &&
  266.25 +	make install || return 1
  266.26 +
  266.27 +	install -Dm644 $stuff/autostart/xcompmgr.desktop \
  266.28 +		$install/etc/xdg/autostart/xcompmgr.desktop
  266.29 +}
  266.30 +
  266.31 +TAGS="Xorg"
  266.32 +
  266.33 +PROVIDE="xorg-xcompmgr"
   267.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   267.2 +++ b/xcompmgr/stuff/autostart/xcompmgr.desktop	Thu Dec 20 17:55:43 2018 +0200
   267.3 @@ -0,0 +1,8 @@
   267.4 +[Desktop Entry]
   267.5 +Type=Application
   267.6 +Name=Desktop effects with Xcompmgr
   267.7 +Name[fr]=Effects de bureau avec Xcompmgr
   267.8 +Name[pt]=Efeitos do desktop com Xcompmgr
   267.9 +Name[pt_BR]=Efeitos do desktop com Xcompmgr
  267.10 +Exec=xcompmgr -c -r 10 -o 0.5
  267.11 +NotShowIn=LXDE;XFCE;Razor;
   268.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   268.2 +++ b/xcompmgr/stuff/patches/46285.diff	Thu Dec 20 17:55:43 2018 +0200
   268.3 @@ -0,0 +1,28 @@
   268.4 +--- a/xcompmgr.c	2011-11-19 01:49:52.000000000 -0600
   268.5 ++++ b/xcompmgr.c	2012-08-11 21:58:58.000000000 -0500
   268.6 +@@ -1028,7 +1028,6 @@
   268.7 + 	{
   268.8 + 	    w->borderClip = XFixesCreateRegion (dpy, NULL, 0);
   268.9 + 	    XFixesCopyRegion (dpy, w->borderClip, region);
  268.10 +-	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  268.11 + 	}
  268.12 + 	w->prev_trans = t;
  268.13 + 	t = w;
  268.14 +@@ -1080,6 +1079,8 @@
  268.15 + 	if (w->mode == WINDOW_TRANS)
  268.16 + 	{
  268.17 + 	    int	x, y, wid, hei;
  268.18 ++	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  268.19 ++	    XFixesSetPictureClipRegion(dpy, rootBuffer, 0, 0, w->borderClip);
  268.20 + #if HAS_NAME_WINDOW_PIXMAP
  268.21 + 	    x = w->a.x;
  268.22 + 	    y = w->a.y;
  268.23 +@@ -1099,6 +1100,8 @@
  268.24 + 	else if (w->mode == WINDOW_ARGB)
  268.25 + 	{
  268.26 + 	    int	x, y, wid, hei;
  268.27 ++	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  268.28 ++	    XFixesSetPictureClipRegion(dpy, rootBuffer, 0, 0, w->borderClip);
  268.29 + #if HAS_NAME_WINDOW_PIXMAP
  268.30 + 	    x = w->a.x;
  268.31 + 	    y = w->a.y;
   269.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   269.2 +++ b/xcompmgr/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   269.3 @@ -0,0 +1,1 @@
   269.4 +46285.diff # bugs.freedesktop.org/show_bug.cgi?id=46285
   270.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   270.2 +++ b/xcursor-themes/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   270.3 @@ -0,0 +1,1 @@
   270.4 +../xorg/.icon.png
   270.5 \ No newline at end of file
   271.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   271.2 +++ b/xcursor-themes/description.txt	Thu Dec 20 17:55:43 2018 +0200
   271.3 @@ -0,0 +1,3 @@
   271.4 +This is a default set of cursor themes for use with libXcursor, originally
   271.5 +created for the XFree86 Project, and now shipped as part of the X.Org software
   271.6 +distribution.
   272.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   272.2 +++ b/xcursor-themes/receipt	Thu Dec 20 17:55:43 2018 +0200
   272.3 @@ -0,0 +1,27 @@
   272.4 +# SliTaz package receipt v2.
   272.5 +
   272.6 +PACKAGE="xcursor-themes"
   272.7 +VERSION="1.0.5"
   272.8 +CATEGORY="x-window"
   272.9 +SHORT_DESC="Standard set of X cursors"
  272.10 +MAINTAINER="al.bobylev@gmail.com"
  272.11 +LICENSE="MIT"
  272.12 +WEB_SITE="https://www.x.org/wiki/"
  272.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcursor-themes.html"
  272.14 +HOST_ARCH="any"
  272.15 +
  272.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  272.17 +WGET_URL="$XORG_MIRROR/data/$TARBALL"
  272.18 +TARBALL_SHA1="6caae6cdb441003a42305f964c32bac21c34626f"
  272.19 +
  272.20 +BUILD_DEPENDS="util-macros xcursorgen libxcursor-dev"
  272.21 +
  272.22 +compile_rules() {
  272.23 +	./configure $CONFIGURE_ARGS &&
  272.24 +	make &&
  272.25 +	make install
  272.26 +}
  272.27 +
  272.28 +TAGS="Xorg"
  272.29 +
  272.30 +PROVIDE="xorg-xcursor-themes"
   273.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   273.2 +++ b/xcursorgen/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   273.3 @@ -0,0 +1,1 @@
   273.4 +../xorg/.icon.png
   273.5 \ No newline at end of file
   274.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   274.2 +++ b/xcursorgen/receipt	Thu Dec 20 17:55:43 2018 +0200
   274.3 @@ -0,0 +1,27 @@
   274.4 +# SliTaz package receipt v2.
   274.5 +
   274.6 +PACKAGE="xcursorgen"
   274.7 +VERSION="1.0.6"
   274.8 +CATEGORY="x-window"
   274.9 +SHORT_DESC="Create an X cursor file from PNG images"
  274.10 +MAINTAINER="devel@slitaz.org"
  274.11 +LICENSE="MIT"
  274.12 +WEB_SITE="https://www.x.org/wiki/"
  274.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  274.14 +
  274.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  274.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  274.17 +TARBALL_SHA1="e6d5cc03ce1829cc7eea39526ca7b8688aac468b"
  274.18 +
  274.19 +BUILD_DEPENDS="util-macros libx11-dev libxcursor-dev libpng-dev"
  274.20 +DEPENDS="libpng libx11 libxcursor"
  274.21 +
  274.22 +compile_rules() {
  274.23 +	./configure $CONFIGURE_ARGS &&
  274.24 +	make &&
  274.25 +	make install
  274.26 +}
  274.27 +
  274.28 +TAGS="Xorg"
  274.29 +
  274.30 +PROVIDE="xorg-xcursorgen"
   275.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   275.2 +++ b/xdpyinfo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   275.3 @@ -0,0 +1,1 @@
   275.4 +../xorg/.icon.png
   275.5 \ No newline at end of file
   276.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   276.2 +++ b/xdpyinfo/receipt	Thu Dec 20 17:55:43 2018 +0200
   276.3 @@ -0,0 +1,30 @@
   276.4 +# SliTaz package receipt v2.
   276.5 +
   276.6 +PACKAGE="xdpyinfo"
   276.7 +VERSION="1.3.2"
   276.8 +CATEGORY="x-window"
   276.9 +SHORT_DESC="Display information utility for X"
  276.10 +MAINTAINER="devel@slitaz.org"
  276.11 +LICENSE="MIT"
  276.12 +WEB_SITE="https://www.x.org/wiki/"
  276.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  276.14 +
  276.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  276.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  276.17 +TARBALL_SHA1="0922fc31f8fc82ac20e326a6c9eb33ed7d57ad87"
  276.18 +
  276.19 +BUILD_DEPENDS="util-macros libxext-dev libx11-dev libxtst-dev libxcb-dev \
  276.20 +xorgproto libxxf86vm-dev libxxf86dga-dev libxrender-dev libxcomposite-dev \
  276.21 +libxinerama-dev libdmx-dev libxxf86misc-dev"
  276.22 +DEPENDS="libx11 libxcomposite libxext libxi libxinerama libxrender libxtst \
  276.23 +libxxf86dga libxxf86misc libxxf86vm libdmx libxcb"
  276.24 +
  276.25 +compile_rules() {
  276.26 +	./configure $CONFIGURE_ARGS &&
  276.27 +	make &&
  276.28 +	make install
  276.29 +}
  276.30 +
  276.31 +TAGS="Xorg display"
  276.32 +
  276.33 +PROVIDE="xorg-xdpyinfo"
   277.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   277.2 +++ b/xdriinfo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   277.3 @@ -0,0 +1,1 @@
   277.4 +../xorg/.icon.png
   277.5 \ No newline at end of file
   278.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   278.2 +++ b/xdriinfo/receipt	Thu Dec 20 17:55:43 2018 +0200
   278.3 @@ -0,0 +1,28 @@
   278.4 +# SliTaz package receipt v2.
   278.5 +
   278.6 +PACKAGE="xdriinfo"
   278.7 +VERSION="1.0.6"
   278.8 +CATEGORY="x-window"
   278.9 +SHORT_DESC="Query configuration information of DRI drivers"
  278.10 +MAINTAINER="devel@slitaz.org"
  278.11 +LICENSE="MIT"
  278.12 +WEB_SITE="https://www.x.org/wiki/"
  278.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  278.14 +
  278.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  278.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  278.17 +TARBALL_SHA1="11682ae1f04a311b832651d78bbf4c6ac77f0ed9"
  278.18 +
  278.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto mesa-dev"
  278.20 +DEPENDS="mesa libx11"
  278.21 +SUGGESTED="nvidia"
  278.22 +
  278.23 +compile_rules() {
  278.24 +	./configure $CONFIGURE_ARGS &&
  278.25 +	make &&
  278.26 +	make install
  278.27 +}
  278.28 +
  278.29 +TAGS="Xorg"
  278.30 +
  278.31 +PROVIDE="xorg-xdriinfo"
   279.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   279.2 +++ b/xedit/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   279.3 @@ -0,0 +1,1 @@
   279.4 +../xorg/.icon.png
   279.5 \ No newline at end of file
   280.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   280.2 +++ b/xedit/receipt	Thu Dec 20 17:55:43 2018 +0200
   280.3 @@ -0,0 +1,28 @@
   280.4 +# SliTaz package receipt v2.
   280.5 +
   280.6 +PACKAGE="xedit"
   280.7 +VERSION="1.2.2"
   280.8 +CATEGORY="x-window"
   280.9 +SHORT_DESC="Simple text editor for X"
  280.10 +MAINTAINER="pascal.bellard@slitaz.org"
  280.11 +LICENSE="MIT"
  280.12 +WEB_SITE="https://www.x.org/wiki/"
  280.13 +
  280.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  280.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  280.16 +TARBALL_SHA1="f37b5d0f8ec461955f0419dbb1890d8cf63d179d"
  280.17 +
  280.18 +BUILD_DEPENDS="util-macros libxaw-dev libxmu-dev libxt-dev libx11-dev"
  280.19 +DEPENDS="libx11 libxaw libxmu libxt"
  280.20 +
  280.21 +CONFIG_FILES="/etc/X11/app-defaults/Xedit /etc/X11/app-defaults/Xedit-color"
  280.22 +
  280.23 +compile_rules() {
  280.24 +	./configure $CONFIGURE_ARGS &&
  280.25 +	make &&
  280.26 +	make install
  280.27 +}
  280.28 +
  280.29 +TAGS="Xorg text-editor"
  280.30 +
  280.31 +PROVIDE="xorg-xedit"
   281.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   281.2 +++ b/xev/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   281.3 @@ -0,0 +1,1 @@
   281.4 +../xorg/.icon.png
   281.5 \ No newline at end of file
   282.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   282.2 +++ b/xev/receipt	Thu Dec 20 17:55:43 2018 +0200
   282.3 @@ -0,0 +1,27 @@
   282.4 +# SliTaz package receipt v2.
   282.5 +
   282.6 +PACKAGE="xev"
   282.7 +VERSION="1.2.2"
   282.8 +CATEGORY="x-window"
   282.9 +SHORT_DESC="Print contents of X events"
  282.10 +MAINTAINER="devel@slitaz.org"
  282.11 +LICENSE="MIT"
  282.12 +WEB_SITE="https://www.x.org/wiki/"
  282.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  282.14 +
  282.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  282.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  282.17 +TARBALL_SHA1="e737bc46c58b9bb10f0af9883dce203bbed708aa"
  282.18 +
  282.19 +BUILD_DEPENDS="util-macros libx11-dev libxrandr-dev"
  282.20 +DEPENDS="libx11 libxrandr"
  282.21 +
  282.22 +compile_rules() {
  282.23 +	./configure $CONFIGURE_ARGS &&
  282.24 +	make &&
  282.25 +	make install
  282.26 +}
  282.27 +
  282.28 +TAGS="Xorg debug"
  282.29 +
  282.30 +PROVIDE="xorg-xev"
   283.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   283.2 +++ b/xeyes/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   283.3 @@ -0,0 +1,1 @@
   283.4 +../xorg/.icon.png
   283.5 \ No newline at end of file
   284.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   284.2 +++ b/xeyes/receipt	Thu Dec 20 17:55:43 2018 +0200
   284.3 @@ -0,0 +1,27 @@
   284.4 +# SliTaz package receipt v2.
   284.5 +
   284.6 +PACKAGE="xeyes"
   284.7 +VERSION="1.1.2"
   284.8 +CATEGORY="x-window"
   284.9 +SHORT_DESC="Follow the mouse/SHAPE extension X demo"
  284.10 +MAINTAINER="pascal.bellard@slitaz.org"
  284.11 +LICENSE="MIT"
  284.12 +WEB_SITE="https://www.x.org/wiki/"
  284.13 +
  284.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  284.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  284.16 +TARBALL_SHA1="458987f8accdbd8abf993ee51030391cf584d2e8"
  284.17 +
  284.18 +BUILD_DEPENDS="util-macros libx11-dev libxt-dev libxext-dev libxmu-dev \
  284.19 +libxrender-dev"
  284.20 +DEPENDS="libx11 libxext libxmu libxrender libxt"
  284.21 +
  284.22 +compile_rules() {
  284.23 +	./configure $CONFIGURE_ARGS &&
  284.24 +	make &&
  284.25 +	make install
  284.26 +}
  284.27 +
  284.28 +TAGS="Xorg"
  284.29 +
  284.30 +PROVIDE="xorg-xeyes"
   285.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   285.2 +++ b/xf86-input-acecad/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   285.3 @@ -0,0 +1,1 @@
   285.4 +../xorg/.icon.png
   285.5 \ No newline at end of file
   286.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   286.2 +++ b/xf86-input-acecad/receipt	Thu Dec 20 17:55:43 2018 +0200
   286.3 @@ -0,0 +1,28 @@
   286.4 +# SliTaz package receipt v2.
   286.5 +
   286.6 +PACKAGE="xf86-input-acecad"
   286.7 +VERSION="1.5.0" # 2011-05-04
   286.8 +CATEGORY="x-window"
   286.9 +SHORT_DESC="Xorg input driver for Acecad Flair devices"
  286.10 +MAINTAINER="al.bobylev@gmail.com"
  286.11 +LICENSE="MIT"
  286.12 +WEB_SITE="https://www.x.org/wiki/"
  286.13 +REPOLOGY="xdrv:acecad"
  286.14 +
  286.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  286.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  286.17 +TARBALL_SHA1="410cee68e4435dc95774fb389fcefae1b2ffe3d1"
  286.18 +
  286.19 +BUILD_DEPENDS="util-macros xorg-server-dev sysfsutils-dev"
  286.20 +DEPENDS="sysfsutils xorg-server"
  286.21 +
  286.22 +compile_rules() {
  286.23 +	./configure $CONFIGURE_ARGS &&
  286.24 +	fix libtool &&
  286.25 +	make &&
  286.26 +	make install
  286.27 +}
  286.28 +
  286.29 +TAGS="Xorg"
  286.30 +
  286.31 +PROVIDE="xorg-xf86-input-acecad"
   287.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   287.2 +++ b/xf86-input-elographics/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   287.3 @@ -0,0 +1,1 @@
   287.4 +../xorg/.icon.png
   287.5 \ No newline at end of file
   288.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   288.2 +++ b/xf86-input-elographics/receipt	Thu Dec 20 17:55:43 2018 +0200
   288.3 @@ -0,0 +1,28 @@
   288.4 +# SliTaz package receipt v2.
   288.5 +
   288.6 +PACKAGE="xf86-input-elographics"
   288.7 +VERSION="1.4.1" # 2012-08-20
   288.8 +CATEGORY="x-window"
   288.9 +SHORT_DESC="Xorg input driver for Elographics touchscreen devices"
  288.10 +MAINTAINER="devel@slitaz.org"
  288.11 +LICENSE="MIT"
  288.12 +WEB_SITE="https://www.x.org/wiki/"
  288.13 +REPOLOGY="xdrv:elographics"
  288.14 +
  288.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  288.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  288.17 +TARBALL_SHA1="78455583a34ccd209edc1aba5538926df4faf47f"
  288.18 +
  288.19 +BUILD_DEPENDS="xorg-server-dev xorgproto"
  288.20 +DEPENDS="xorg-server"
  288.21 +
  288.22 +compile_rules() {
  288.23 +	./configure $CONFIGURE_ARGS &&
  288.24 +	fix libtool &&
  288.25 +	make &&
  288.26 +	make install
  288.27 +}
  288.28 +
  288.29 +TAGS="Xorg"
  288.30 +
  288.31 +PROVIDE="xorg-xf86-input-elographics"
   289.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   289.2 +++ b/xf86-input-evdev/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   289.3 @@ -0,0 +1,1 @@
   289.4 +../xorg/.icon.png
   289.5 \ No newline at end of file
   290.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   290.2 +++ b/xf86-input-evdev/receipt	Thu Dec 20 17:55:43 2018 +0200
   290.3 @@ -0,0 +1,33 @@
   290.4 +# SliTaz package receipt v2.
   290.5 +
   290.6 +PACKAGE="xf86-input-evdev"
   290.7 +VERSION="2.10.6" # 2018-05-29
   290.8 +CATEGORY="x-window"
   290.9 +SHORT_DESC="Generic Linux input driver"
  290.10 +MAINTAINER="devel@slitaz.org"
  290.11 +LICENSE="MIT"
  290.12 +WEB_SITE="https://www.x.org/wiki/"
  290.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-evdev-driver"
  290.14 +REPOLOGY="xdrv:evdev"
  290.15 +
  290.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  290.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  290.18 +TARBALL_SHA1="660de292d5a40e2b8f385965c6a4e149c981ba59"
  290.19 +
  290.20 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto eudev-dev libevdev-dev \
  290.21 +mtdev-dev"
  290.22 +SPLIT="$PACKAGE-dev"
  290.23 +
  290.24 +DEPENDS_std="eudev libevdev mtdev"
  290.25 +
  290.26 +compile_rules() {
  290.27 +	./configure $CONFIGURE_ARGS &&
  290.28 +	fix libtool &&
  290.29 +	make &&
  290.30 +	make install
  290.31 +}
  290.32 +
  290.33 +TAGS="Xorg"
  290.34 +
  290.35 +PROVIDE_std="xorg-xf86-input-evdev"
  290.36 +PROVIDE_dev="xorg-xf86-input-evdev-dev"
   291.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   291.2 +++ b/xf86-input-fpit/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   291.3 @@ -0,0 +1,1 @@
   291.4 +../xorg/.icon.png
   291.5 \ No newline at end of file
   292.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   292.2 +++ b/xf86-input-fpit/receipt	Thu Dec 20 17:55:43 2018 +0200
   292.3 @@ -0,0 +1,28 @@
   292.4 +# SliTaz package receipt v2.
   292.5 +
   292.6 +PACKAGE="xf86-input-fpit"
   292.7 +VERSION="1.4.0" # 2011-06-27
   292.8 +CATEGORY="x-window"
   292.9 +SHORT_DESC="Xorg input driver for Fujitsu Stylistic Tablet PCs"
  292.10 +MAINTAINER="al.bobylev@gmail.com"
  292.11 +LICENSE="MIT"
  292.12 +WEB_SITE="https://www.x.org/wiki/"
  292.13 +REPOLOGY="xdrv:fpit"
  292.14 +
  292.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  292.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  292.17 +TARBALL_SHA1="9305d30ae22d37c6b5bb975adc8ecda9b1d6c5e6"
  292.18 +
  292.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  292.20 +DEPENDS="xorg-server"
  292.21 +
  292.22 +compile_rules() {
  292.23 +	./configure $CONFIGURE_ARGS &&
  292.24 +	fix libtool &&
  292.25 +	make &&
  292.26 +	make install
  292.27 +}
  292.28 +
  292.29 +TAGS="Xorg"
  292.30 +
  292.31 +PROVIDE="xorg-xf86-input-fpit"
   293.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   293.2 +++ b/xf86-input-hyperpen/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   293.3 @@ -0,0 +1,1 @@
   293.4 +../xorg/.icon.png
   293.5 \ No newline at end of file
   294.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   294.2 +++ b/xf86-input-hyperpen/receipt	Thu Dec 20 17:55:43 2018 +0200
   294.3 @@ -0,0 +1,28 @@
   294.4 +# SliTaz package receipt v2.
   294.5 +
   294.6 +PACKAGE="xf86-input-hyperpen"
   294.7 +VERSION="1.4.1" # 2011-07-05
   294.8 +CATEGORY="x-window"
   294.9 +SHORT_DESC="Xorg input driver for Aiptek HyperPen 6000"
  294.10 +MAINTAINER="al.bobylev@gmail.com"
  294.11 +LICENSE="MIT"
  294.12 +WEB_SITE="https://www.x.org/wiki/"
  294.13 +REPOLOGY="xdrv:hyperpen"
  294.14 +
  294.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  294.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  294.17 +TARBALL_SHA1="4a3555310e812dc895b7493b11f7377314c36a75"
  294.18 +
  294.19 +BUILD_DEPENDS="xorg-server-dev"
  294.20 +DEPENDS="xorg-server"
  294.21 +
  294.22 +compile_rules() {
  294.23 +	./configure $CONFIGURE_ARGS &&
  294.24 +	fix libtool &&
  294.25 +	make &&
  294.26 +	make install
  294.27 +}
  294.28 +
  294.29 +TAGS="Xorg"
  294.30 +
  294.31 +PROVIDE="xorg-xf86-input-hyperpen"
   295.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   295.2 +++ b/xf86-input-joystick/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   295.3 @@ -0,0 +1,1 @@
   295.4 +../xorg/.icon.png
   295.5 \ No newline at end of file
   296.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   296.2 +++ b/xf86-input-joystick/receipt	Thu Dec 20 17:55:43 2018 +0200
   296.3 @@ -0,0 +1,33 @@
   296.4 +# SliTaz package receipt v2.
   296.5 +
   296.6 +PACKAGE="xf86-input-joystick"
   296.7 +VERSION="1.6.3" # 2016-11-17
   296.8 +CATEGORY="x-window"
   296.9 +SHORT_DESC="Xorg input driver for controlling the pointer with a joystick \
  296.10 +device"
  296.11 +MAINTAINER="al.bobylev@gmail.com"
  296.12 +LICENSE="MIT"
  296.13 +WEB_SITE="https://www.x.org/wiki/"
  296.14 +REPOLOGY="xdrv:joystick"
  296.15 +
  296.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  296.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  296.18 +TARBALL_SHA1="b8664249d50ed266556877e15e3782c40614459c"
  296.19 +
  296.20 +BUILD_DEPENDS="util-macros xorg-server-dev"
  296.21 +SPLIT="$PACKAGE-dev"
  296.22 +
  296.23 +DEPENDS_std="xorg-server"
  296.24 +DEPENDS_dev="$PACKAGE xorg-server-dev"
  296.25 +
  296.26 +compile_rules() {
  296.27 +	./configure $CONFIGURE_ARGS &&
  296.28 +	fix libtool &&
  296.29 +	make &&
  296.30 +	make install
  296.31 +}
  296.32 +
  296.33 +TAGS="Xorg"
  296.34 +
  296.35 +PROVIDE_std="xorg-xf86-input-joystick"
  296.36 +PROVIDE_dev="xorg-xf86-input-joystick-dev"
   297.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   297.2 +++ b/xf86-input-keyboard/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   297.3 @@ -0,0 +1,1 @@
   297.4 +../xorg/.icon.png
   297.5 \ No newline at end of file
   298.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   298.2 +++ b/xf86-input-keyboard/receipt	Thu Dec 20 17:55:43 2018 +0200
   298.3 @@ -0,0 +1,28 @@
   298.4 +# SliTaz package receipt v2.
   298.5 +
   298.6 +PACKAGE="xf86-input-keyboard"
   298.7 +VERSION="1.9.0" # 2016-11-17
   298.8 +CATEGORY="x-window"
   298.9 +SHORT_DESC="Xorg input driver for keyboards"
  298.10 +MAINTAINER="devel@slitaz.org"
  298.11 +LICENSE="MIT"
  298.12 +WEB_SITE="https://www.x.org/wiki/"
  298.13 +REPOLOGY="xdrv:keyboard"
  298.14 +
  298.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  298.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  298.17 +TARBALL_SHA1="24b5d84d221a75650f390ff63315912bf9a94992"
  298.18 +
  298.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  298.20 +DEPENDS="xorg-server"
  298.21 +
  298.22 +compile_rules() {
  298.23 +	./configure $CONFIGURE_ARGS &&
  298.24 +	fix libtool &&
  298.25 +	make &&
  298.26 +	make install
  298.27 +}
  298.28 +
  298.29 +TAGS="Xorg"
  298.30 +
  298.31 +PROVIDE="xorg-xf86-input-keyboard"
   299.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   299.2 +++ b/xf86-input-libinput/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   299.3 @@ -0,0 +1,1 @@
   299.4 +../xorg/.icon.png
   299.5 \ No newline at end of file
   300.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   300.2 +++ b/xf86-input-libinput/receipt	Thu Dec 20 17:55:43 2018 +0200
   300.3 @@ -0,0 +1,35 @@
   300.4 +# SliTaz package receipt v2.
   300.5 +
   300.6 +PACKAGE="xf86-input-libinput"
   300.7 +VERSION="0.28.1" # 2018-10-14
   300.8 +CATEGORY="x-window"
   300.9 +SHORT_DESC="libinput-based X.Org input driver"
  300.10 +MAINTAINER="al.bobylev@gmail.com"
  300.11 +LICENSE="MIT"
  300.12 +WEB_SITE="https://www.x.org/wiki/"
  300.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-libinput-driver"
  300.14 +REPOLOGY="xdrv:libinput"
  300.15 +
  300.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  300.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  300.18 +TARBALL_SHA1="f72f298c23fa993857ff1a9a06754f2f5962b376"
  300.19 +
  300.20 +BUILD_DEPENDS="util-macros xorg-server-dev libinput-dev mtdev-dev libevdev-dev \
  300.21 +eudev-dev"
  300.22 +SPLIT="$PACKAGE-dev"
  300.23 +
  300.24 +DEPENDS_std="xorg-server eudev libevdev libinput mtdev"
  300.25 +DEPENDS_dev="$PACKAGE xorg-server-dev eudev-dev libevdev-dev libinput-dev \
  300.26 +mtdev-dev"
  300.27 +
  300.28 +compile_rules() {
  300.29 +	./configure $CONFIGURE_ARGS &&
  300.30 +	fix libtool &&
  300.31 +	make &&
  300.32 +	make install
  300.33 +}
  300.34 +
  300.35 +TAGS="Xorg"
  300.36 +
  300.37 +PROVIDE_std="xorg-xf86-input-libinput"
  300.38 +PROVIDE_dev="xorg-xf86-input-libinput-dev"
   301.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   301.2 +++ b/xf86-input-mouse/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   301.3 @@ -0,0 +1,1 @@
   301.4 +../xorg/.icon.png
   301.5 \ No newline at end of file
   302.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   302.2 +++ b/xf86-input-mouse/receipt	Thu Dec 20 17:55:43 2018 +0200
   302.3 @@ -0,0 +1,32 @@
   302.4 +# SliTaz package receipt v2.
   302.5 +
   302.6 +PACKAGE="xf86-input-mouse"
   302.7 +VERSION="1.9.3" # 2018-06-19
   302.8 +CATEGORY="x-window"
   302.9 +SHORT_DESC="Xorg mouse input driver"
  302.10 +MAINTAINER="devel@slitaz.org"
  302.11 +LICENSE="MIT"
  302.12 +WEB_SITE="https://www.x.org/wiki/"
  302.13 +REPOLOGY="xdrv:mouse"
  302.14 +
  302.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  302.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  302.17 +TARBALL_SHA1="b3982998808ba43117fc066c4ecc94ce67c5818e"
  302.18 +
  302.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  302.20 +SPLIT="$PACKAGE-dev"
  302.21 +
  302.22 +DEPENDS_std="xorg-server" # implicit
  302.23 +DEPENDS_dev="$PACKAGE xorg-server-dev" # implicit
  302.24 +
  302.25 +compile_rules() {
  302.26 +	./configure $CONFIGURE_ARGS &&
  302.27 +	fix libtool &&
  302.28 +	make &&
  302.29 +	make install
  302.30 +}
  302.31 +
  302.32 +TAGS="Xorg"
  302.33 +
  302.34 +PROVIDE_std="xorg-xf86-input-mouse"
  302.35 +PROVIDE_dev="xorg-xf86-input-mouse-dev"
   303.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   303.2 +++ b/xf86-input-mutouch/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   303.3 @@ -0,0 +1,1 @@
   303.4 +../xorg/.icon.png
   303.5 \ No newline at end of file
   304.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   304.2 +++ b/xf86-input-mutouch/receipt	Thu Dec 20 17:55:43 2018 +0200
   304.3 @@ -0,0 +1,28 @@
   304.4 +# SliTaz package receipt v2.
   304.5 +
   304.6 +PACKAGE="xf86-input-mutouch"
   304.7 +VERSION="1.3.0" # 2011-06-28
   304.8 +CATEGORY="x-window"
   304.9 +SHORT_DESC="Xorg input driver for Microtouch devices"
  304.10 +MAINTAINER="devel@slitaz.org"
  304.11 +LICENSE="MIT"
  304.12 +WEB_SITE="https://www.x.org/wiki/"
  304.13 +REPOLOGY="xdrv:mutouch"
  304.14 +
  304.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  304.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  304.17 +TARBALL_SHA1="55702932f9ecef29bf9b096b9fdc45aa45614db5"
  304.18 +
  304.19 +BUILD_DEPENDS="xorg-server-dev"
  304.20 +DEPENDS="xorg-server"
  304.21 +
  304.22 +compile_rules() {
  304.23 +	./configure $CONFIGURE_ARGS &&
  304.24 +	fix libtool &&
  304.25 +	make &&
  304.26 +	make install
  304.27 +}
  304.28 +
  304.29 +TAGS="Xorg"
  304.30 +
  304.31 +PROVIDE="xorg-xf86-input-mutouch"
   305.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   305.2 +++ b/xf86-input-penmount/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   305.3 @@ -0,0 +1,1 @@
   305.4 +../xorg/.icon.png
   305.5 \ No newline at end of file
   306.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   306.2 +++ b/xf86-input-penmount/receipt	Thu Dec 20 17:55:43 2018 +0200
   306.3 @@ -0,0 +1,28 @@
   306.4 +# SliTaz package receipt v2.
   306.5 +
   306.6 +PACKAGE="xf86-input-penmount"
   306.7 +VERSION="1.5.0" # 2011-06-28
   306.8 +CATEGORY="x-window"
   306.9 +SHORT_DESC="Xorg input driver for PenMount devices"
  306.10 +MAINTAINER="al.bobylev@gmail.com"
  306.11 +LICENSE="MIT"
  306.12 +WEB_SITE="https://www.x.org/wiki/"
  306.13 +REPOLOGY="xdrv:penmount"
  306.14 +
  306.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  306.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  306.17 +TARBALL_SHA1="39ed2dd2b22f8bf9366b187e4d7801a24c24cb31"
  306.18 +
  306.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  306.20 +DEPENDS="xorg-server"
  306.21 +
  306.22 +compile_rules() {
  306.23 +	./configure $CONFIGURE_ARGS &&
  306.24 +	fix libtool &&
  306.25 +	make &&
  306.26 +	make install
  306.27 +}
  306.28 +
  306.29 +TAGS="Xorg"
  306.30 +
  306.31 +PROVIDE="xorg-xf86-input-penmount"
   307.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   307.2 +++ b/xf86-input-synaptics/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   307.3 @@ -0,0 +1,1 @@
   307.4 +../xorg/.icon.png
   307.5 \ No newline at end of file
   308.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   308.2 +++ b/xf86-input-synaptics/receipt	Thu Dec 20 17:55:43 2018 +0200
   308.3 @@ -0,0 +1,33 @@
   308.4 +# SliTaz package receipt v2.
   308.5 +
   308.6 +PACKAGE="xf86-input-synaptics"
   308.7 +VERSION="1.9.1" # 2018-05-29
   308.8 +CATEGORY="x-window"
   308.9 +SHORT_DESC="Xorg input driver for touchpads"
  308.10 +MAINTAINER="devel@slitaz.org"
  308.11 +LICENSE="MIT"
  308.12 +WEB_SITE="https://www.x.org/wiki/"
  308.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-synaptics-driver"
  308.14 +REPOLOGY="xdrv:synaptics"
  308.15 +
  308.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  308.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  308.18 +TARBALL_SHA1="07eeef716820105cae959bbc3aa103e2fcfd0084"
  308.19 +
  308.20 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto libevdev-dev libxi-dev \
  308.21 +libxtst-dev"
  308.22 +SPLIT="$PACKAGE-dev"
  308.23 +
  308.24 +DEPENDS_std="libevdev libx11 libxi libxtst"
  308.25 +
  308.26 +compile_rules() {
  308.27 +	./configure $CONFIGURE_ARGS &&
  308.28 +	fix libtool &&
  308.29 +	make &&
  308.30 +	make install
  308.31 +}
  308.32 +
  308.33 +TAGS="Xorg"
  308.34 +
  308.35 +PROVIDE_std="xorg-xf86-input-synaptics"
  308.36 +PROVIDE_dev="xorg-xf86-input-synaptics-dev"
   309.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   309.2 +++ b/xf86-input-vmmouse/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   309.3 @@ -0,0 +1,1 @@
   309.4 +../xorg/.icon.png
   309.5 \ No newline at end of file
   310.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   310.2 +++ b/xf86-input-vmmouse/receipt	Thu Dec 20 17:55:43 2018 +0200
   310.3 @@ -0,0 +1,33 @@
   310.4 +# SliTaz package receipt v2.
   310.5 +
   310.6 +PACKAGE="xf86-input-vmmouse"
   310.7 +VERSION="13.1.0" # 2015-06-25
   310.8 +CATEGORY="x-window"
   310.9 +SHORT_DESC="Xorg input driver for VMware Mouse"
  310.10 +MAINTAINER="al.bobylev@gmail.com"
  310.11 +LICENSE="MIT"
  310.12 +WEB_SITE="https://www.x.org/wiki/"
  310.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-vmmouse-driver"
  310.14 +REPOLOGY="xdrv:vmmouse"
  310.15 +
  310.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  310.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  310.18 +TARBALL_SHA1="c00fbf985b22a86901fa905a8037005bca96d805"
  310.19 +
  310.20 +BUILD_DEPENDS="util-macros xorg-server-dev eudev-dev"
  310.21 +DEPENDS="xorg-server eudev"
  310.22 +
  310.23 +compile_rules() {
  310.24 +	./configure \
  310.25 +		--without-hal-fdi-dir \
  310.26 +		--without-hal-callouts-dir \
  310.27 +		--with-udev-rules-dir=/lib/udev/rules.d \
  310.28 +		$CONFIGURE_ARGS &&
  310.29 +	fix libtool &&
  310.30 +	make &&
  310.31 +	make install
  310.32 +}
  310.33 +
  310.34 +TAGS="Xorg"
  310.35 +
  310.36 +PROVIDE="xorg-xf86-input-vmmouse"
   311.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   311.2 +++ b/xf86-input-void/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   311.3 @@ -0,0 +1,1 @@
   311.4 +../xorg/.icon.png
   311.5 \ No newline at end of file
   312.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   312.2 +++ b/xf86-input-void/receipt	Thu Dec 20 17:55:43 2018 +0200
   312.3 @@ -0,0 +1,28 @@
   312.4 +# SliTaz package receipt v2.
   312.5 +
   312.6 +PACKAGE="xf86-input-void"
   312.7 +VERSION="1.4.1" # 2015-04-20
   312.8 +CATEGORY="x-window"
   312.9 +SHORT_DESC="Dummy/null Xorg input driver"
  312.10 +MAINTAINER="devel@slitaz.org"
  312.11 +LICENSE="MIT"
  312.12 +WEB_SITE="https://www.x.org/wiki/"
  312.13 +REPOLOGY="xdrv:void"
  312.14 +
  312.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  312.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  312.17 +TARBALL_SHA1="40c4e9aa7997ee24626aa0b8ecd9e7ac82a5fd63"
  312.18 +
  312.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  312.20 +DEPENDS="xorg-server"
  312.21 +
  312.22 +compile_rules() {
  312.23 +	./configure $CONFIGURE_ARGS &&
  312.24 +	fix libtool &&
  312.25 +	make &&
  312.26 +	make install
  312.27 +}
  312.28 +
  312.29 +TAGS="Xorg"
  312.30 +
  312.31 +PROVIDE="xorg-xf86-input-void"
   313.1 Binary file xf86-input-wacom/.icon.png has changed
   314.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   314.2 +++ b/xf86-input-wacom/receipt	Thu Dec 20 17:55:43 2018 +0200
   314.3 @@ -0,0 +1,37 @@
   314.4 +# SliTaz package receipt v2.
   314.5 +
   314.6 +PACKAGE="xf86-input-wacom"
   314.7 +VERSION="0.36.1" # 2018-03-19
   314.8 +CATEGORY="x-window"
   314.9 +SHORT_DESC="X input driver for Wacom and Wacom-like tablets"
  314.10 +MAINTAINER="al.bobylev@gmail.com"
  314.11 +LICENSE="GPL2"
  314.12 +WEB_SITE="https://linuxwacom.github.io/"
  314.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-wacom-driver"
  314.14 +REPOLOGY="xdrv:wacom"
  314.15 +
  314.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  314.17 +WGET_URL="https://github.com/linuxwacom/xf86-input-wacom/releases/download/xf86-input-wacom-$VERSION/$TARBALL"
  314.18 +TARBALL_SHA1="51d1b198f86bf7609b0464ce34a93c90f1ef557c"
  314.19 +
  314.20 +BUILD_DEPENDS="util-macros xorg-server-dev libxext-dev xorgproto libxi-dev \
  314.21 +libxrandr-dev libxinerama-dev eudev-dev"
  314.22 +SPLIT="$PACKAGE-dev"
  314.23 +
  314.24 +DEPENDS_std="eudev libx11 libxau libxdmcp libxext libxi libxinerama libxrandr \
  314.25 +libxrender libxcb"
  314.26 +DEPENDS_dev="$PACKAGE xorg-server-dev"
  314.27 +
  314.28 +compile_rules() {
  314.29 +	./configure \
  314.30 +		--with-systemd-unit-dir=no \
  314.31 +		$CONFIGURE_ARGS &&
  314.32 +	fix libtool &&
  314.33 +	make &&
  314.34 +	make install
  314.35 +}
  314.36 +
  314.37 +TAGS="Xorg"
  314.38 +
  314.39 +PROVIDE_std="xorg-xf86-input-wacom"
  314.40 +PROVIDE_dev="xorg-xf86-input-wacom-dev"
   315.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   315.2 +++ b/xf86-video-amdgpu/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   315.3 @@ -0,0 +1,1 @@
   315.4 +../xorg/.icon.png
   315.5 \ No newline at end of file
   316.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   316.2 +++ b/xf86-video-amdgpu/receipt	Thu Dec 20 17:55:43 2018 +0200
   316.3 @@ -0,0 +1,31 @@
   316.4 +# SliTaz package receipt v2.
   316.5 +
   316.6 +PACKAGE="xf86-video-amdgpu"
   316.7 +VERSION="18.1.0" # 2018-09-14
   316.8 +CATEGORY="x-window"
   316.9 +SHORT_DESC="AMD Rx/HDxxxx video driver"
  316.10 +MAINTAINER="al.bobylev@gmail.com"
  316.11 +LICENSE="MIT"
  316.12 +WEB_SITE="https://www.x.org/wiki/"
  316.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-amdgpu-driver"
  316.14 +REPOLOGY="xdrv:amdgpu"
  316.15 +
  316.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  316.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  316.18 +TARBALL_SHA1="d3097af7da3b56396721e214f348e7ceb5f3a358"
  316.19 +
  316.20 +BUILD_DEPENDS="util-macros xorg-server-dev libdrm-dev expat-dev"
  316.21 +DEPENDS="libdrm-amdgpu mesa-libgbm"
  316.22 +
  316.23 +compile_rules() {
  316.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  316.25 +
  316.26 +	./configure $CONFIGURE_ARGS &&
  316.27 +	fix libtool &&
  316.28 +	make &&
  316.29 +	make install
  316.30 +}
  316.31 +
  316.32 +TAGS="Xorg display"
  316.33 +
  316.34 +PROVIDE="xorg-xf86-video-amdgpu"
   317.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   317.2 +++ b/xf86-video-apm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   317.3 @@ -0,0 +1,1 @@
   317.4 +../xorg/.icon.png
   317.5 \ No newline at end of file
   318.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   318.2 +++ b/xf86-video-apm/receipt	Thu Dec 20 17:55:43 2018 +0200
   318.3 @@ -0,0 +1,30 @@
   318.4 +# SliTaz package receipt v2.
   318.5 +
   318.6 +PACKAGE="xf86-video-apm"
   318.7 +VERSION="1.2.5" # 2012-07-17
   318.8 +CATEGORY="x-window"
   318.9 +SHORT_DESC="Xorg driver for Alliance ProMotion video cards"
  318.10 +MAINTAINER="al.bobylev@gmail.com"
  318.11 +LICENSE="MIT"
  318.12 +WEB_SITE="https://www.x.org/wiki/"
  318.13 +REPOLOGY="xdrv:apm"
  318.14 +
  318.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  318.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  318.17 +TARBALL_SHA1="a4cdb587f94c0fd28bea92b2469ea1e55d6d6589"
  318.18 +
  318.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  318.20 +DEPENDS="xorg-server"
  318.21 +
  318.22 +compile_rules() {
  318.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  318.24 +
  318.25 +	./configure $CONFIGURE_ARGS &&
  318.26 +	fix libtool &&
  318.27 +	make &&
  318.28 +	make install
  318.29 +}
  318.30 +
  318.31 +TAGS="Xorg display"
  318.32 +
  318.33 +PROVIDE="xorg-xf86-video-apm"
   319.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   319.2 +++ b/xf86-video-apm/stuff/patches/mibstore.patch	Thu Dec 20 17:55:43 2018 +0200
   319.3 @@ -0,0 +1,23 @@
   319.4 +From 9f67408e4f078e907fbf4feb45cfdcfd0cdebcca Mon Sep 17 00:00:00 2001
   319.5 +From: Adam Jackson <ajax@redhat.com>
   319.6 +Date: Thu, 10 Jan 2013 03:03:29 +0000
   319.7 +Subject: Remove #include "mibstore.h"
   319.8 +
   319.9 +Signed-off-by: Adam Jackson <ajax@redhat.com>
  319.10 +---
  319.11 +diff --git a/src/apm.h b/src/apm.h
  319.12 +index a3c06f8..365e5e2 100644
  319.13 +--- a/src/apm.h
  319.14 ++++ b/src/apm.h
  319.15 +@@ -33,9 +33,6 @@
  319.16 + /* All drivers initialising the SW cursor need this */
  319.17 + #include "mipointer.h"
  319.18 + 
  319.19 +-/* All drivers implementing backing store need this */
  319.20 +-#include "mibstore.h"
  319.21 +-
  319.22 + /* I2C support */
  319.23 + #include "xf86i2c.h"
  319.24 + 
  319.25 +--
  319.26 +cgit v0.9.0.2-2-gbebe
   320.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   320.2 +++ b/xf86-video-apm/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   320.3 @@ -0,0 +1,3 @@
   320.4 +# From Alpine Linux:
   320.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-apm?h=master
   320.6 +mibstore.patch
   321.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   321.2 +++ b/xf86-video-ark/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   321.3 @@ -0,0 +1,1 @@
   321.4 +../xorg/.icon.png
   321.5 \ No newline at end of file
   322.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   322.2 +++ b/xf86-video-ark/receipt	Thu Dec 20 17:55:43 2018 +0200
   322.3 @@ -0,0 +1,30 @@
   322.4 +# SliTaz package receipt v2.
   322.5 +
   322.6 +PACKAGE="xf86-video-ark"
   322.7 +VERSION="0.7.5" # 2012-07-17
   322.8 +CATEGORY="x-window"
   322.9 +SHORT_DESC="Xorg driver for ark video cards"
  322.10 +MAINTAINER="al.bobylev@gmail.com"
  322.11 +LICENSE="MIT"
  322.12 +WEB_SITE="https://www.x.org/wiki/"
  322.13 +REPOLOGY="xdrv:ark"
  322.14 +
  322.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  322.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  322.17 +TARBALL_SHA1="6abadee761f1a49b399361ecbcecef4e4a097c0d"
  322.18 +
  322.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  322.20 +DEPENDS="xorg-server"
  322.21 +
  322.22 +compile_rules() {
  322.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  322.24 +
  322.25 +	./configure $CONFIGURE_ARGS &&
  322.26 +	fix libtool &&
  322.27 +	make &&
  322.28 +	make install
  322.29 +}
  322.30 +
  322.31 +TAGS="Xorg display"
  322.32 +
  322.33 +PROVIDE="xorg-xf86-video-ark"
   323.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   323.2 +++ b/xf86-video-ark/stuff/patches/mibstore.patch	Thu Dec 20 17:55:43 2018 +0200
   323.3 @@ -0,0 +1,18 @@
   323.4 +--- ./src/ark_driver.c.orig	2013-03-07 10:16:06.584081552 +0000
   323.5 ++++ ./src/ark_driver.c	2013-03-07 10:16:23.270892075 +0000
   323.6 +@@ -39,7 +39,6 @@
   323.7 + #include "compiler.h"
   323.8 + #include "mipointer.h"
   323.9 + #include "micmap.h"
  323.10 +-#include "mibstore.h"
  323.11 + #include "fb.h"
  323.12 + #include "ark.h"
  323.13 + 
  323.14 +@@ -538,7 +537,6 @@
  323.15 + 
  323.16 + 	fbPictureInit (pScreen, 0, 0);
  323.17 + 
  323.18 +-	miInitializeBackingStore(pScreen);
  323.19 + 	xf86SetBackingStore(pScreen);
  323.20 + 
  323.21 + 	if (!pARK->NoAccel) {
   324.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   324.2 +++ b/xf86-video-ark/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   324.3 @@ -0,0 +1,3 @@
   324.4 +# From Alpine Linux:
   324.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-ark?h=master
   324.6 +mibstore.patch
   325.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   325.2 +++ b/xf86-video-ast/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   325.3 @@ -0,0 +1,1 @@
   325.4 +../xorg/.icon.png
   325.5 \ No newline at end of file
   326.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   326.2 +++ b/xf86-video-ast/receipt	Thu Dec 20 17:55:43 2018 +0200
   326.3 @@ -0,0 +1,30 @@
   326.4 +# SliTaz package receipt v2.
   326.5 +
   326.6 +PACKAGE="xf86-video-ast"
   326.7 +VERSION="1.1.5" # 2015-08-19
   326.8 +CATEGORY="x-window"
   326.9 +SHORT_DESC="Xorg driver for ASpeed Technologies video cards"
  326.10 +MAINTAINER="al.bobylev@gmail.com"
  326.11 +LICENSE="MIT"
  326.12 +WEB_SITE="https://www.x.org/wiki/"
  326.13 +REPOLOGY="xdrv:ast"
  326.14 +
  326.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  326.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  326.17 +TARBALL_SHA1="34a610e506079f32b240335520200457aa72d4c2"
  326.18 +
  326.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  326.20 +DEPENDS="xorg-server"
  326.21 +
  326.22 +compile_rules() {
  326.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  326.24 +
  326.25 +	./configure $CONFIGURE_ARGS &&
  326.26 +	fix libtool &&
  326.27 +	make &&
  326.28 +	make install
  326.29 +}
  326.30 +
  326.31 +TAGS="Xorg display"
  326.32 +
  326.33 +PROVIDE="xorg-xf86-video-ast"
   327.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   327.2 +++ b/xf86-video-ati/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   327.3 @@ -0,0 +1,1 @@
   327.4 +../xorg/.icon.png
   327.5 \ No newline at end of file
   328.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   328.2 +++ b/xf86-video-ati/receipt	Thu Dec 20 17:55:43 2018 +0200
   328.3 @@ -0,0 +1,32 @@
   328.4 +# SliTaz package receipt v2.
   328.5 +
   328.6 +PACKAGE="xf86-video-ati"
   328.7 +VERSION="18.1.0" # 2018-09-14
   328.8 +CATEGORY="x-window"
   328.9 +SHORT_DESC="Xorg wrapper driver for ATI video cards"
  328.10 +MAINTAINER="devel@slitaz.org"
  328.11 +LICENSE="MIT"
  328.12 +WEB_SITE="https://www.x.org/wiki/ati/"
  328.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-ati-driver"
  328.14 +REPOLOGY="xdrv:ati"
  328.15 +
  328.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  328.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  328.18 +TARBALL_SHA1="87beb7d09f5b722570adda9a5a1822cbd19e7059"
  328.19 +
  328.20 +BUILD_DEPENDS="util-macros xorg-server-dev libxrandr-dev libxrender-dev \
  328.21 +libxv-dev libdrm-dev eudev-dev"
  328.22 +DEPENDS="eudev libdrm-radeon libpciaccess"
  328.23 +
  328.24 +compile_rules() {
  328.25 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  328.26 +
  328.27 +	./configure $CONFIGURE_ARGS &&
  328.28 +	fix libtool &&
  328.29 +	make &&
  328.30 +	make install
  328.31 +}
  328.32 +
  328.33 +TAGS="Xorg display"
  328.34 +
  328.35 +PROVIDE="xorg-xf86-video-ati"
   329.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   329.2 +++ b/xf86-video-chips/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   329.3 @@ -0,0 +1,1 @@
   329.4 +../xorg/.icon.png
   329.5 \ No newline at end of file
   330.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   330.2 +++ b/xf86-video-chips/receipt	Thu Dec 20 17:55:43 2018 +0200
   330.3 @@ -0,0 +1,30 @@
   330.4 +# SliTaz package receipt v2.
   330.5 +
   330.6 +PACKAGE="xf86-video-chips"
   330.7 +VERSION="1.2.7" # 2017-01-17
   330.8 +CATEGORY="x-window"
   330.9 +SHORT_DESC="Xorg driver for Chips and Technologies video processors"
  330.10 +MAINTAINER="al.bobylev@gmail.com"
  330.11 +LICENSE="MIT"
  330.12 +WEB_SITE="https://www.x.org/wiki/"
  330.13 +REPOLOGY="xdrv:chips"
  330.14 +
  330.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  330.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  330.17 +TARBALL_SHA1="ec0944c94b50a0b2078af6a025226e5f383422ce"
  330.18 +
  330.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  330.20 +DEPENDS="xorg-server"
  330.21 +
  330.22 +compile_rules() {
  330.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  330.24 +
  330.25 +	./configure $CONFIGURE_ARGS &&
  330.26 +	fix libtool &&
  330.27 +	make &&
  330.28 +	make install
  330.29 +}
  330.30 +
  330.31 +TAGS="Xorg display"
  330.32 +
  330.33 +PROVIDE="xorg-xf86-video-chips"
   331.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   331.2 +++ b/xf86-video-cirrus/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   331.3 @@ -0,0 +1,1 @@
   331.4 +../xorg/.icon.png
   331.5 \ No newline at end of file
   332.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   332.2 +++ b/xf86-video-cirrus/receipt	Thu Dec 20 17:55:43 2018 +0200
   332.3 @@ -0,0 +1,30 @@
   332.4 +# SliTaz package receipt v2.
   332.5 +
   332.6 +PACKAGE="xf86-video-cirrus"
   332.7 +VERSION="1.5.3" # 2015-05-06
   332.8 +CATEGORY="x-window"
   332.9 +SHORT_DESC="Xorg driver for Cirrus cards"
  332.10 +MAINTAINER="pascal.bellard@slitaz.org"
  332.11 +LICENSE="MIT"
  332.12 +WEB_SITE="https://www.x.org/wiki/cirrus/"
  332.13 +REPOLOGY="xdrv:cirrus"
  332.14 +
  332.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  332.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  332.17 +TARBALL_SHA1="545cbedb42e5a5ce6bdf0b9bc30a826908f284e5"
  332.18 +
  332.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  332.20 +DEPENDS="xorg-server"
  332.21 +
  332.22 +compile_rules() {
  332.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  332.24 +
  332.25 +	./configure $CONFIGURE_ARGS &&
  332.26 +	fix libtool &&
  332.27 +	make &&
  332.28 +	make install
  332.29 +}
  332.30 +
  332.31 +TAGS="Xorg display"
  332.32 +
  332.33 +PROVIDE="xorg-xf86-video-cirrus"
   333.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   333.2 +++ b/xf86-video-dummy/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   333.3 @@ -0,0 +1,1 @@
   333.4 +../xorg/.icon.png
   333.5 \ No newline at end of file
   334.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   334.2 +++ b/xf86-video-dummy/receipt	Thu Dec 20 17:55:43 2018 +0200
   334.3 @@ -0,0 +1,30 @@
   334.4 +# SliTaz package receipt v2.
   334.5 +
   334.6 +PACKAGE="xf86-video-dummy"
   334.7 +VERSION="0.3.8" # 2016-12-14
   334.8 +CATEGORY="x-window"
   334.9 +SHORT_DESC="Xorg dummy driver for video cards"
  334.10 +MAINTAINER="al.bobylev@gmail.com"
  334.11 +LICENSE="MIT"
  334.12 +WEB_SITE="https://www.x.org/wiki/"
  334.13 +REPOLOGY="xdrv:dummy"
  334.14 +
  334.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  334.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  334.17 +TARBALL_SHA1="6d24be1c693214935b298bf6f9457ee464d5c4fd"
  334.18 +
  334.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  334.20 +DEPENDS="xorg-server"
  334.21 +
  334.22 +compile_rules() {
  334.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  334.24 +
  334.25 +	./configure $CONFIGURE_ARGS &&
  334.26 +	fix libtool &&
  334.27 +	make &&
  334.28 +	make install
  334.29 +}
  334.30 +
  334.31 +TAGS="Xorg display"
  334.32 +
  334.33 +PROVIDE="xorg-xf86-video-dummy"
   335.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   335.2 +++ b/xf86-video-dummy/stuff/patches/mibstore.patch	Thu Dec 20 17:55:43 2018 +0200
   335.3 @@ -0,0 +1,18 @@
   335.4 +--- ./src/ark_driver.c.orig	2013-03-07 10:16:06.584081552 +0000
   335.5 ++++ ./src/ark_driver.c	2013-03-07 10:16:23.270892075 +0000
   335.6 +@@ -39,7 +39,6 @@
   335.7 + #include "compiler.h"
   335.8 + #include "mipointer.h"
   335.9 + #include "micmap.h"
  335.10 +-#include "mibstore.h"
  335.11 + #include "fb.h"
  335.12 + #include "ark.h"
  335.13 + 
  335.14 +@@ -538,7 +537,6 @@
  335.15 + 
  335.16 + 	fbPictureInit (pScreen, 0, 0);
  335.17 + 
  335.18 +-	miInitializeBackingStore(pScreen);
  335.19 + 	xf86SetBackingStore(pScreen);
  335.20 + 
  335.21 + 	if (!pARK->NoAccel) {
   336.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   336.2 +++ b/xf86-video-dummy/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   336.3 @@ -0,0 +1,3 @@
   336.4 +# From Alpine Linux:
   336.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-ark?h=master
   336.6 +mibstore.patch
   337.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   337.2 +++ b/xf86-video-fbdev/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   337.3 @@ -0,0 +1,1 @@
   337.4 +../xorg/.icon.png
   337.5 \ No newline at end of file
   338.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   338.2 +++ b/xf86-video-fbdev/receipt	Thu Dec 20 17:55:43 2018 +0200
   338.3 @@ -0,0 +1,32 @@
   338.4 +# SliTaz package receipt v2.
   338.5 +
   338.6 +PACKAGE="xf86-video-fbdev"
   338.7 +VERSION="0.5.0" # 2018-05-30
   338.8 +CATEGORY="x-window"
   338.9 +SHORT_DESC="Xorg video driver for framebuffer device"
  338.10 +MAINTAINER="devel@slitaz.org"
  338.11 +LICENSE="MIT"
  338.12 +WEB_SITE="https://www.x.org/wiki/fbdev/"
  338.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-fbdev-driver"
  338.14 +REPOLOGY="xdrv:fbdev"
  338.15 +
  338.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  338.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  338.18 +TARBALL_SHA1="8d79ec615cb54436ff96dc94b74775db6dc47aff"
  338.19 +
  338.20 +BUILD_DEPENDS="util-macros xorg-server-dev libxrandr-dev libxrender-dev \
  338.21 +libxv-dev xorgproto"
  338.22 +DEPENDS="xorg-server" # implicit
  338.23 +
  338.24 +compile_rules() {
  338.25 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  338.26 +
  338.27 +	./configure $CONFIGURE_ARGS &&
  338.28 +	fix libtool &&
  338.29 +	make &&
  338.30 +	make install
  338.31 +}
  338.32 +
  338.33 +TAGS="Xorg display"
  338.34 +
  338.35 +PROVIDE="xorg-xf86-video-fbdev"
   339.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   339.2 +++ b/xf86-video-fbturbo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   339.3 @@ -0,0 +1,1 @@
   339.4 +../xorg/.icon.png
   339.5 \ No newline at end of file
   340.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   340.2 +++ b/xf86-video-fbturbo/receipt	Thu Dec 20 17:55:43 2018 +0200
   340.3 @@ -0,0 +1,32 @@
   340.4 +# SliTaz package receipt v2.
   340.5 +
   340.6 +PACKAGE="xf86-video-fbturbo"
   340.7 +VERSION="0.4.0.postgit20151006" # 2015-10-06
   340.8 +COMMIT="f9a6ed7"
   340.9 +CATEGORY="x-window"
  340.10 +SHORT_DESC="Xorg DDX driver for ARM devices (Allwinner, RPi and others)"
  340.11 +MAINTAINER="devel@slitaz.org"
  340.12 +LICENSE="MIT"
  340.13 +WEB_SITE="https://github.com/ssvb/xf86-video-fbturbo"
  340.14 +REPOLOGY="xdrv:fbturbo"
  340.15 +
  340.16 +TARBALL="$PACKAGE-$VERSION.tar.gz"
  340.17 +WGET_URL="$WEB_SITE/archive/${COMMIT:-VERSION}.tar.gz"
  340.18 +TARBALL_SHA1="947fa3d5db6431ef281e1fa475618c1228b38c52"
  340.19 +
  340.20 +BUILD_DEPENDS="util-macros xorg-server-dev automake autoconf libtool"
  340.21 +DEPENDS="xorg-server"
  340.22 +
  340.23 +compile_rules() {
  340.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  340.25 +
  340.26 +	autoreconf -vi
  340.27 +	./configure $CONFIGURE_ARGS &&
  340.28 +	fix libtool &&
  340.29 +	make &&
  340.30 +	make install
  340.31 +}
  340.32 +
  340.33 +TAGS="Xorg display"
  340.34 +
  340.35 +PROVIDE="xorg-xf86-video-fbturbo"
   341.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   341.2 +++ b/xf86-video-geode/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   341.3 @@ -0,0 +1,1 @@
   341.4 +../xorg/.icon.png
   341.5 \ No newline at end of file
   342.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   342.2 +++ b/xf86-video-geode/receipt	Thu Dec 20 17:55:43 2018 +0200
   342.3 @@ -0,0 +1,31 @@
   342.4 +# SliTaz package receipt v2.
   342.5 +
   342.6 +PACKAGE="xf86-video-geode"
   342.7 +VERSION="2.11.19" # 2016-12-12
   342.8 +CATEGORY="x-window"
   342.9 +SHORT_DESC="Xorg video driver for AMD Geode GX and LX video cards"
  342.10 +MAINTAINER="devel@slitaz.org"
  342.11 +LICENSE="MIT"
  342.12 +WEB_SITE="https://www.x.org/wiki/GeodeDriver/"
  342.13 +REPOLOGY="xdrv:geode"
  342.14 +HOST_ARCH="i486"
  342.15 +
  342.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  342.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  342.18 +TARBALL_SHA1="aaa8bc5be88f22b802c01cad813c259f02a46945"
  342.19 +
  342.20 +BUILD_DEPENDS="util-macros xorg-server-dev"
  342.21 +DEPENDS="xorg-server"
  342.22 +
  342.23 +compile_rules() {
  342.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  342.25 +
  342.26 +	./configure $CONFIGURE_ARGS &&
  342.27 +	fix libtool &&
  342.28 +	make &&
  342.29 +	make install
  342.30 +}
  342.31 +
  342.32 +TAGS="Xorg display"
  342.33 +
  342.34 +PROVIDE="xorg-xf86-video-geode"
   343.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   343.2 +++ b/xf86-video-glint/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   343.3 @@ -0,0 +1,1 @@
   343.4 +../xorg/.icon.png
   343.5 \ No newline at end of file
   344.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   344.2 +++ b/xf86-video-glint/receipt	Thu Dec 20 17:55:43 2018 +0200
   344.3 @@ -0,0 +1,31 @@
   344.4 +# SliTaz package receipt v2.
   344.5 +
   344.6 +PACKAGE="xf86-video-glint"
   344.7 +VERSION="1.2.9" # 2017-01-17
   344.8 +CATEGORY="x-window"
   344.9 +SHORT_DESC="Xorg driver for 3Dlabs & Texas Instruments GLINT/Permedia based \
  344.10 +video cards"
  344.11 +MAINTAINER="al.bobylev@gmail.com"
  344.12 +LICENSE="MIT"
  344.13 +WEB_SITE="https://www.x.org/wiki/"
  344.14 +REPOLOGY="xdrv:glint"
  344.15 +
  344.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  344.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  344.18 +TARBALL_SHA1="93b56f77d5d57f7b8746f58a5098a05ca9825b1d"
  344.19 +
  344.20 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto"
  344.21 +DEPENDS="xorg-server"
  344.22 +
  344.23 +compile_rules() {
  344.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  344.25 +
  344.26 +	./configure $CONFIGURE_ARGS &&
  344.27 +	fix libtool &&
  344.28 +	make &&
  344.29 +	make install
  344.30 +}
  344.31 +
  344.32 +TAGS="Xorg display"
  344.33 +
  344.34 +PROVIDE="xorg-xf86-video-glint"
   345.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   345.2 +++ b/xf86-video-i128/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   345.3 @@ -0,0 +1,1 @@
   345.4 +../xorg/.icon.png
   345.5 \ No newline at end of file
   346.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   346.2 +++ b/xf86-video-i128/receipt	Thu Dec 20 17:55:43 2018 +0200
   346.3 @@ -0,0 +1,30 @@
   346.4 +# SliTaz package receipt v2.
   346.5 +
   346.6 +PACKAGE="xf86-video-i128"
   346.7 +VERSION="1.4.0" # 2018-12-07
   346.8 +CATEGORY="x-window"
   346.9 +SHORT_DESC="Xorg driver for Number 9 I128 video cards"
  346.10 +MAINTAINER="al.bobylev@gmail.com"
  346.11 +LICENSE="MIT"
  346.12 +WEB_SITE="https://www.x.org/wiki/"
  346.13 +REPOLOGY="xdrv:i128"
  346.14 +
  346.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  346.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  346.17 +TARBALL_SHA1="56d5b897b2695222c13e59d2ade74620a99e1011"
  346.18 +
  346.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  346.20 +DEPENDS="xorg-server"
  346.21 +
  346.22 +compile_rules() {
  346.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  346.24 +
  346.25 +	./configure $CONFIGURE_ARGS &&
  346.26 +	fix libtool &&
  346.27 +	make &&
  346.28 +	make install
  346.29 +}
  346.30 +
  346.31 +TAGS="Xorg display"
  346.32 +
  346.33 +PROVIDE="xorg-xf86-video-i128"
   347.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   347.2 +++ b/xf86-video-i740/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   347.3 @@ -0,0 +1,1 @@
   347.4 +../xorg/.icon.png
   347.5 \ No newline at end of file
   348.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   348.2 +++ b/xf86-video-i740/receipt	Thu Dec 20 17:55:43 2018 +0200
   348.3 @@ -0,0 +1,30 @@
   348.4 +# SliTaz package receipt v2.
   348.5 +
   348.6 +PACKAGE="xf86-video-i740"
   348.7 +VERSION="1.4.0" # 2018-12-06
   348.8 +CATEGORY="x-window"
   348.9 +SHORT_DESC="Xorg driver for Intel i740 video cards"
  348.10 +MAINTAINER="devel@slitaz.org"
  348.11 +LICENSE="MIT"
  348.12 +WEB_SITE="https://www.x.org/wiki/i740/"
  348.13 +REPOLOGY="xdrv:i740"
  348.14 +
  348.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  348.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  348.17 +TARBALL_SHA1="acbbc042f18d796b39588516b6cbb03684d99cd6"
  348.18 +
  348.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  348.20 +DEPENDS="xorg-server"
  348.21 +
  348.22 +compile_rules() {
  348.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  348.24 +
  348.25 +	./configure $CONFIGURE_ARGS &&
  348.26 +	fix libtool &&
  348.27 +	make &&
  348.28 +	make install
  348.29 +}
  348.30 +
  348.31 +TAGS="Xorg display"
  348.32 +
  348.33 +PROVIDE="xorg-xf86-video-i740"
   349.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   349.2 +++ b/xf86-video-intel/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   349.3 @@ -0,0 +1,1 @@
   349.4 +../xorg/.icon.png
   349.5 \ No newline at end of file
   350.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   350.2 +++ b/xf86-video-intel/receipt	Thu Dec 20 17:55:43 2018 +0200
   350.3 @@ -0,0 +1,46 @@
   350.4 +# SliTaz package receipt v2.
   350.5 +
   350.6 +PACKAGE="xf86-video-intel"
   350.7 +VERSION="2.99.917" # 2014-12-21
   350.8 +CATEGORY="x-window"
   350.9 +SHORT_DESC="Xorg driver for Intel integrated graphics chipsets"
  350.10 +MAINTAINER="devel@slitaz.org"
  350.11 +LICENSE="MIT"
  350.12 +WEB_SITE="https://www.x.org/wiki/intel/"
  350.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-intel-driver"
  350.14 +REPOLOGY="xdrv:intel"
  350.15 +
  350.16 +TARBALL="xf86-video-intel-$VERSION.tar.bz2"
  350.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  350.18 +TARBALL_SHA1="9af9ded7a29026c211e5eb50a547e3e33976301d"
  350.19 +
  350.20 +BUILD_DEPENDS="util-macros eudev-dev libx11-dev libxcomposite-dev \
  350.21 +libxdamage-dev libxrender-dev libxrandr-dev cairo-dev libxshmfence-dev \
  350.22 +libxxf86vm-dev libdrm-dev libxinerama-dev libxcursor-dev libxtst-dev \
  350.23 +libxscrnsaver-dev xorg-server-dev libxvmc-dev xcb-util-dev libxfont2-dev \
  350.24 +automake libtool git"
  350.25 +DEPENDS="eudev libdrm libdrm-intel libx11 libxscrnsaver libxcursor libxdamage \
  350.26 +libxext libxfixes libxinerama libxrandr libxrender libxtst libxv libxvmc \
  350.27 +libxcb libxshmfence pixman xcb-util"
  350.28 +
  350.29 +compile_rules() {
  350.30 +	autoreconf -vif
  350.31 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  350.32 +
  350.33 +	./configure \
  350.34 +		--enable-kms-only \
  350.35 +		--enable-uxa \
  350.36 +		--enable-xvmc \
  350.37 +		--disable-selective-werror \
  350.38 +		--with-default-dri=3 \
  350.39 +		$CONFIGURE_ARGS &&
  350.40 +	fix libtool &&
  350.41 +	make &&
  350.42 +	make install || return 1
  350.43 +
  350.44 +	chmod o-x $install/usr/libexec/xf86-video-intel-backlight-helper
  350.45 +}
  350.46 +
  350.47 +TAGS="Xorg display"
  350.48 +
  350.49 +PROVIDE="xorg-xf86-video-intel"
   351.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   351.2 +++ b/xf86-video-intel/stuff/overrides	Thu Dec 20 17:55:43 2018 +0200
   351.3 @@ -0,0 +1,1 @@
   351.4 +4754 /usr/libexec/xf86-video-intel-backlight-helper
   352.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   352.2 +++ b/xf86-video-intel/stuff/patches/git.patch	Thu Dec 20 17:55:43 2018 +0200
   352.3 @@ -0,0 +1,43164 @@
   352.4 +diff --git a/Makefile.am b/Makefile.am
   352.5 +index 418fdc92..de5fbe12 100644
   352.6 +--- a/Makefile.am
   352.7 ++++ b/Makefile.am
   352.8 +@@ -18,14 +18,16 @@
   352.9 + #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  352.10 + #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  352.11 + 
  352.12 +-ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
  352.13 ++#Having problems passing through user flags as libtool complains
  352.14 ++#ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
  352.15 ++ACLOCAL_AMFLAGS = -I m4
  352.16 + 
  352.17 + SUBDIRS = man libobj xvmc src tools
  352.18 + 
  352.19 + MAINTAINERCLEANFILES = ChangeLog INSTALL
  352.20 + 
  352.21 + if HAVE_X11
  352.22 +-SUBDIRS += test
  352.23 ++SUBDIRS += test benchmarks
  352.24 + endif
  352.25 + 
  352.26 + .PHONY: ChangeLog INSTALL
  352.27 +diff --git a/NEWS b/NEWS
  352.28 +index 604b9cce..0e200332 100644
  352.29 +--- a/NEWS
  352.30 ++++ b/NEWS
  352.31 +@@ -21,7 +21,7 @@ should make one more snapshot before an imminent release.
  352.32 +    Before kernel 3.19, O_NONBLOCK support is broken and so we must avoid
  352.33 +    reading if we are not expecting an event.
  352.34 + 
  352.35 +- * Backwards compatibilty fix for fake triple buffering with PRIME and
  352.36 ++ * Backwards compatibility fix for fake triple buffering with PRIME and
  352.37 +    Xorg-1.15
  352.38 +    https://bugs.freedesktop.org/show_bug.cgi?id=85144#c12
  352.39 + 
  352.40 +@@ -51,7 +51,7 @@ should make one more snapshot before an imminent release.
  352.41 + Snapshot 2.99.916 (2014-09-08)
  352.42 + ==============================
  352.43 + Quick update for MST in UXA - we need to hook up the RandR outputs for
  352.44 +-dynamicaly added connectors.
  352.45 ++dynamically added connectors.
  352.46 + 
  352.47 + 
  352.48 + Snapshot 2.99.915 (2014-09-08)
  352.49 +@@ -503,7 +503,7 @@ release.
  352.50 +    backlight property is queried whilst the connector is disabled
  352.51 +    https://bugs.freedesktop.org/show_bug.cgi?id=70406
  352.52 + 
  352.53 +- * Pad GETCONNECTOR ioctl for compatability between 32/64-bit userspace
  352.54 ++ * Pad GETCONNECTOR ioctl for compatibility between 32/64-bit userspace
  352.55 +    and kernel
  352.56 + 
  352.57 +  * Handle long glyph runs correctly
  352.58 +@@ -523,7 +523,7 @@ snapshot beforehand to push out the bug fixes from the last week.
  352.59 + 
  352.60 +  * Fix video output using sprites when changing the image size
  352.61 + 
  352.62 +- * Apply more restrictive tile constaints for 915g class devices
  352.63 ++ * Apply more restrictive tile constraints for 915g class devices
  352.64 +    https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1232546
  352.65 + 
  352.66 +  * Ensure all overlapping rectangles are drawn for XRenderFillRectangles
  352.67 +@@ -1132,7 +1132,7 @@ operation.
  352.68 +  * Explicitly prevent ring-switching for synchronized rendering to
  352.69 +    scanouts (for vsync).
  352.70 + 
  352.71 +- * Clip dirty region to slave pixmaps (otherwise UDL is nigh unusuable)
  352.72 ++ * Clip dirty region to slave pixmaps (otherwise UDL is nigh unusable)
  352.73 +    https://bugs.freedesktop.org/show_bug.cgi?id=59539
  352.74 + 
  352.75 + 
  352.76 +@@ -1226,7 +1226,7 @@ Release 2.20.15 (2012-12-03)
  352.77 + ============================
  352.78 + And lo, enabling more of the common acceleration paths for gen4 revealed
  352.79 + another lurking bug - something is wrong with how we prepare Y-tiling
  352.80 +-surfaces for rendering. For the time being, we can surreptiously disable
  352.81 ++surfaces for rendering. For the time being, we can surreptitiously disable
  352.82 + them for gen4 and avoid hitting GPU hangs.
  352.83 + 
  352.84 +  * Avoid clobbering the render state after failing to convert the
  352.85 +@@ -1515,7 +1515,7 @@ Release 2.20.5 (2012-08-26)
  352.86 + Another silly bug found, another small bugfix release. The goal was for
  352.87 + the driver to bind to all Intel devices supported by the kernel.
  352.88 + Unfortunately we were too successful and started claiming Pouslbo,
  352.89 +-Medfield and Cedarview devices which are still encumbered by propietary
  352.90 ++Medfield and Cedarview devices which are still encumbered by proprietary
  352.91 + IP and not supported by this driver.
  352.92 + 
  352.93 + Bugs fixed since 2.20.4:
  352.94 +diff --git a/README b/README
  352.95 +index cf4d88d8..348983b4 100644
  352.96 +--- a/README
  352.97 ++++ b/README
  352.98 +@@ -15,9 +15,9 @@ Intel graphics chipsets including:
  352.99 + 	G/Q33,G/Q35,G41,G/Q43,G/GM/Q45
 352.100 + 	PineView-M (Atom N400 series)
 352.101 + 	PineView-D (Atom D400/D500 series)
 352.102 +-	Intel(R) HD Graphics: 2000-6000,
 352.103 +-	Intel(R) Iris(TM) Graphics: 5100/6100, and
 352.104 +-	Intel(R) Iris(TM) Pro Graphics: 5200/6200/P6300.
 352.105 ++	Intel(R) HD Graphics,
 352.106 ++	Intel(R) Iris(TM) Graphics,
 352.107 ++	Intel(R) Iris(TM) Pro Graphics.
 352.108 + 
 352.109 + Where to get more information about the driver
 352.110 + ----------------------------------------------
 352.111 +diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
 352.112 +new file mode 100644
 352.113 +index 00000000..301c0129
 352.114 +--- /dev/null
 352.115 ++++ b/benchmarks/.gitignore
 352.116 +@@ -0,0 +1,2 @@
 352.117 ++dri2-swap
 352.118 ++dri3-swap
 352.119 +diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am
 352.120 +new file mode 100644
 352.121 +index 00000000..4976e8a3
 352.122 +--- /dev/null
 352.123 ++++ b/benchmarks/Makefile.am
 352.124 +@@ -0,0 +1,14 @@
 352.125 ++AM_CFLAGS = @CWARNFLAGS@ $(X11_CFLAGS) $(DRM_CFLAGS)
 352.126 ++LDADD = $(X11_LIBS) $(DRM_LIBS) $(CLOCK_GETTIME_LIBS)
 352.127 ++
 352.128 ++check_PROGRAMS =
 352.129 ++
 352.130 ++if DRI2
 352.131 ++check_PROGRAMS += dri2-swap
 352.132 ++endif
 352.133 ++
 352.134 ++if DRI3
 352.135 ++check_PROGRAMS += dri3-swap
 352.136 ++AM_CFLAGS += $(X11_DRI3_CFLAGS)
 352.137 ++LDADD += $(X11_DRI3_LIBS)
 352.138 ++endif
 352.139 +diff --git a/benchmarks/dri2-swap.c b/benchmarks/dri2-swap.c
 352.140 +new file mode 100644
 352.141 +index 00000000..3d9d30aa
 352.142 +--- /dev/null
 352.143 ++++ b/benchmarks/dri2-swap.c
 352.144 +@@ -0,0 +1,588 @@
 352.145 ++/*
 352.146 ++ * Copyright (c) 2015 Intel Corporation
 352.147 ++ *
 352.148 ++ * Permission is hereby granted, free of charge, to any person obtaining a
 352.149 ++ * copy of this software and associated documentation files (the "Software"),
 352.150 ++ * to deal in the Software without restriction, including without limitation
 352.151 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 352.152 ++ * and/or sell copies of the Software, and to permit persons to whom the
 352.153 ++ * Software is furnished to do so, subject to the following conditions:
 352.154 ++ *
 352.155 ++ * The above copyright notice and this permission notice (including the next
 352.156 ++ * paragraph) shall be included in all copies or substantial portions of the
 352.157 ++ * Software.
 352.158 ++ *
 352.159 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 352.160 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 352.161 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 352.162 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 352.163 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 352.164 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 352.165 ++ * SOFTWARE.
 352.166 ++ *
 352.167 ++ */
 352.168 ++
 352.169 ++#ifdef HAVE_CONFIG_H
 352.170 ++#include "config.h"
 352.171 ++#endif
 352.172 ++
 352.173 ++#include <X11/Xlib.h>
 352.174 ++#include <X11/Xatom.h>
 352.175 ++#include <X11/Xlib-xcb.h>
 352.176 ++#include <X11/Xutil.h>
 352.177 ++#include <X11/Xlibint.h>
 352.178 ++#include <X11/extensions/dpms.h>
 352.179 ++#include <X11/extensions/randr.h>
 352.180 ++#include <X11/extensions/Xcomposite.h>
 352.181 ++#include <X11/extensions/Xdamage.h>
 352.182 ++#include <X11/extensions/Xrandr.h>
 352.183 ++#include <xcb/xcb.h>
 352.184 ++#include <xcb/dri2.h>
 352.185 ++#include <xf86drm.h>
 352.186 ++
 352.187 ++#include <stdio.h>
 352.188 ++#include <string.h>
 352.189 ++#include <fcntl.h>
 352.190 ++#include <unistd.h>
 352.191 ++#include <assert.h>
 352.192 ++#include <errno.h>
 352.193 ++#include <setjmp.h>
 352.194 ++#include <signal.h>
 352.195 ++
 352.196 ++#include <X11/Xlibint.h>
 352.197 ++#include <X11/extensions/Xext.h>
 352.198 ++#include <X11/extensions/extutil.h>
 352.199 ++#include <X11/extensions/dri2proto.h>
 352.200 ++#include <X11/extensions/dri2tokens.h>
 352.201 ++#include <X11/extensions/Xfixes.h>
 352.202 ++
 352.203 ++static char dri2ExtensionName[] = DRI2_NAME;
 352.204 ++static XExtensionInfo *dri2Info;
 352.205 ++static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
 352.206 ++
 352.207 ++static Bool
 352.208 ++DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
 352.209 ++static Status
 352.210 ++DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
 352.211 ++static int
 352.212 ++DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
 352.213 ++
 352.214 ++static /* const */ XExtensionHooks dri2ExtensionHooks = {
 352.215 ++  NULL,                   /* create_gc */
 352.216 ++  NULL,                   /* copy_gc */
 352.217 ++  NULL,                   /* flush_gc */
 352.218 ++  NULL,                   /* free_gc */
 352.219 ++  NULL,                   /* create_font */
 352.220 ++  NULL,                   /* free_font */
 352.221 ++  DRI2CloseDisplay,       /* close_display */
 352.222 ++  DRI2WireToEvent,        /* wire_to_event */
 352.223 ++  DRI2EventToWire,        /* event_to_wire */
 352.224 ++  DRI2Error,              /* error */
 352.225 ++  NULL,                   /* error_string */
 352.226 ++};
 352.227 ++
 352.228 ++static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
 352.229 ++                                   dri2Info,
 352.230 ++                                   dri2ExtensionName,
 352.231 ++                                   &dri2ExtensionHooks,
 352.232 ++                                   0, NULL)
 352.233 ++
 352.234 ++static Bool
 352.235 ++DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
 352.236 ++{
 352.237 ++   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.238 ++
 352.239 ++   XextCheckExtension(dpy, info, dri2ExtensionName, False);
 352.240 ++
 352.241 ++   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
 352.242 ++#ifdef X_DRI2SwapBuffers
 352.243 ++   case DRI2_BufferSwapComplete:
 352.244 ++      return False;
 352.245 ++#endif
 352.246 ++#ifdef DRI2_InvalidateBuffers
 352.247 ++   case DRI2_InvalidateBuffers:
 352.248 ++      return False;
 352.249 ++#endif
 352.250 ++   default:
 352.251 ++      /* client doesn't support server event */
 352.252 ++      break;
 352.253 ++   }
 352.254 ++
 352.255 ++   return False;
 352.256 ++}
 352.257 ++
 352.258 ++/* We don't actually support this.  It doesn't make sense for clients to
 352.259 ++ * send each other DRI2 events.
 352.260 ++ */
 352.261 ++static Status
 352.262 ++DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
 352.263 ++{
 352.264 ++   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.265 ++
 352.266 ++   XextCheckExtension(dpy, info, dri2ExtensionName, False);
 352.267 ++
 352.268 ++   switch (event->type) {
 352.269 ++   default:
 352.270 ++      /* client doesn't support server event */
 352.271 ++      break;
 352.272 ++   }
 352.273 ++
 352.274 ++   return Success;
 352.275 ++}
 352.276 ++
 352.277 ++static int
 352.278 ++DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
 352.279 ++{
 352.280 ++	if (err->majorCode == codes->major_opcode &&
 352.281 ++	    err->errorCode == BadDrawable &&
 352.282 ++	    err->minorCode == X_DRI2CopyRegion)
 352.283 ++		return True;
 352.284 ++
 352.285 ++	/* If the X drawable was destroyed before the GLX drawable, the
 352.286 ++	 * DRI2 drawble will be gone by the time we call
 352.287 ++	 * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
 352.288 ++	if (err->majorCode == codes->major_opcode &&
 352.289 ++	    err->errorCode == BadDrawable &&
 352.290 ++	    err->minorCode == X_DRI2DestroyDrawable)
 352.291 ++		return True;
 352.292 ++
 352.293 ++	/* If the server is non-local DRI2Connect will raise BadRequest.
 352.294 ++	 * Swallow this so that DRI2Connect can signal this in its return code */
 352.295 ++	if (err->majorCode == codes->major_opcode &&
 352.296 ++	    err->minorCode == X_DRI2Connect &&
 352.297 ++	    err->errorCode == BadRequest) {
 352.298 ++		*ret_code = False;
 352.299 ++		return True;
 352.300 ++	}
 352.301 ++
 352.302 ++	return False;
 352.303 ++}
 352.304 ++
 352.305 ++static Bool
 352.306 ++DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
 352.307 ++{
 352.308 ++	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.309 ++
 352.310 ++	if (XextHasExtension(info)) {
 352.311 ++		*eventBase = info->codes->first_event;
 352.312 ++		*errorBase = info->codes->first_error;
 352.313 ++		return True;
 352.314 ++	}
 352.315 ++
 352.316 ++	return False;
 352.317 ++}
 352.318 ++
 352.319 ++static Bool
 352.320 ++DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
 352.321 ++{
 352.322 ++	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.323 ++	xDRI2ConnectReply rep;
 352.324 ++	xDRI2ConnectReq *req;
 352.325 ++
 352.326 ++	XextCheckExtension(dpy, info, dri2ExtensionName, False);
 352.327 ++
 352.328 ++	LockDisplay(dpy);
 352.329 ++	GetReq(DRI2Connect, req);
 352.330 ++	req->reqType = info->codes->major_opcode;
 352.331 ++	req->dri2ReqType = X_DRI2Connect;
 352.332 ++	req->window = window;
 352.333 ++	req->driverType = DRI2DriverDRI;
 352.334 ++	if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
 352.335 ++		UnlockDisplay(dpy);
 352.336 ++		SyncHandle();
 352.337 ++		return False;
 352.338 ++	}
 352.339 ++
 352.340 ++	if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
 352.341 ++		UnlockDisplay(dpy);
 352.342 ++		SyncHandle();
 352.343 ++		return False;
 352.344 ++	}
 352.345 ++
 352.346 ++	*driverName = Xmalloc(rep.driverNameLength + 1);
 352.347 ++	if (*driverName == NULL) {
 352.348 ++		_XEatData(dpy,
 352.349 ++			  ((rep.driverNameLength + 3) & ~3) +
 352.350 ++			  ((rep.deviceNameLength + 3) & ~3));
 352.351 ++		UnlockDisplay(dpy);
 352.352 ++		SyncHandle();
 352.353 ++		return False;
 352.354 ++	}
 352.355 ++	_XReadPad(dpy, *driverName, rep.driverNameLength);
 352.356 ++	(*driverName)[rep.driverNameLength] = '\0';
 352.357 ++
 352.358 ++	*deviceName = Xmalloc(rep.deviceNameLength + 1);
 352.359 ++	if (*deviceName == NULL) {
 352.360 ++		Xfree(*driverName);
 352.361 ++		_XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
 352.362 ++		UnlockDisplay(dpy);
 352.363 ++		SyncHandle();
 352.364 ++		return False;
 352.365 ++	}
 352.366 ++	_XReadPad(dpy, *deviceName, rep.deviceNameLength);
 352.367 ++	(*deviceName)[rep.deviceNameLength] = '\0';
 352.368 ++
 352.369 ++	UnlockDisplay(dpy);
 352.370 ++	SyncHandle();
 352.371 ++
 352.372 ++	return True;
 352.373 ++}
 352.374 ++
 352.375 ++static Bool
 352.376 ++DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
 352.377 ++{
 352.378 ++	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.379 ++	xDRI2AuthenticateReq *req;
 352.380 ++	xDRI2AuthenticateReply rep;
 352.381 ++
 352.382 ++	XextCheckExtension(dpy, info, dri2ExtensionName, False);
 352.383 ++
 352.384 ++	LockDisplay(dpy);
 352.385 ++	GetReq(DRI2Authenticate, req);
 352.386 ++	req->reqType = info->codes->major_opcode;
 352.387 ++	req->dri2ReqType = X_DRI2Authenticate;
 352.388 ++	req->window = window;
 352.389 ++	req->magic = magic;
 352.390 ++
 352.391 ++	if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
 352.392 ++		UnlockDisplay(dpy);
 352.393 ++		SyncHandle();
 352.394 ++		return False;
 352.395 ++	}
 352.396 ++
 352.397 ++	UnlockDisplay(dpy);
 352.398 ++	SyncHandle();
 352.399 ++
 352.400 ++	return rep.authenticated;
 352.401 ++}
 352.402 ++
 352.403 ++static void
 352.404 ++DRI2CreateDrawable(Display * dpy, XID drawable)
 352.405 ++{
 352.406 ++	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.407 ++	xDRI2CreateDrawableReq *req;
 352.408 ++
 352.409 ++	XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
 352.410 ++
 352.411 ++	LockDisplay(dpy);
 352.412 ++	GetReq(DRI2CreateDrawable, req);
 352.413 ++	req->reqType = info->codes->major_opcode;
 352.414 ++	req->dri2ReqType = X_DRI2CreateDrawable;
 352.415 ++	req->drawable = drawable;
 352.416 ++	UnlockDisplay(dpy);
 352.417 ++	SyncHandle();
 352.418 ++}
 352.419 ++
 352.420 ++static void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
 352.421 ++{
 352.422 ++    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 352.423 ++    xDRI2SwapIntervalReq *req;
 352.424 ++
 352.425 ++    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
 352.426 ++
 352.427 ++    LockDisplay(dpy);
 352.428 ++    GetReq(DRI2SwapInterval, req);
 352.429 ++    req->reqType = info->codes->major_opcode;
 352.430 ++    req->dri2ReqType = X_DRI2SwapInterval;
 352.431 ++    req->drawable = drawable;
 352.432 ++    req->interval = interval;
 352.433 ++    UnlockDisplay(dpy);
 352.434 ++    SyncHandle();
 352.435 ++}
 352.436 ++
 352.437 ++static int _x_error_occurred;
 352.438 ++
 352.439 ++static int
 352.440 ++_check_error_handler(Display     *display,
 352.441 ++		     XErrorEvent *event)
 352.442 ++{
 352.443 ++	fprintf(stderr,
 352.444 ++		"X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
 352.445 ++	       DisplayString(display),
 352.446 ++	       event->serial,
 352.447 ++	       event->error_code,
 352.448 ++	       event->request_code,
 352.449 ++	       event->minor_code);
 352.450 ++	_x_error_occurred++;
 352.451 ++	return False; /* ignored */
 352.452 ++}
 352.453 ++
 352.454 ++static double elapsed(const struct timespec *start,
 352.455 ++		      const struct timespec *end)
 352.456 ++{
 352.457 ++	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
 352.458 ++}
 352.459 ++
 352.460 ++static void run(Display *dpy, Window win)
 352.461 ++{
 352.462 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
 352.463 ++	struct timespec start, end;
 352.464 ++	int n, completed = 0;
 352.465 ++
 352.466 ++	clock_gettime(CLOCK_MONOTONIC, &start);
 352.467 ++	do {
 352.468 ++		for (n = 0; n < 1000; n++) {
 352.469 ++			unsigned int attachments[] = { DRI2BufferBackLeft };
 352.470 ++			unsigned int seq[2];
 352.471 ++
 352.472 ++			seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
 352.473 ++								 0, 0, 0, 0, 0, 0).sequence;
 352.474 ++
 352.475 ++
 352.476 ++			seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
 352.477 ++								1, 1, attachments).sequence;
 352.478 ++
 352.479 ++			xcb_flush(c);
 352.480 ++			xcb_discard_reply(c, seq[0]);
 352.481 ++			xcb_discard_reply(c, seq[1]);
 352.482 ++			completed++;
 352.483 ++		}
 352.484 ++		clock_gettime(CLOCK_MONOTONIC, &end);
 352.485 ++	} while (end.tv_sec < start.tv_sec + 10);
 352.486 ++
 352.487 ++	printf("%f\n", completed / (elapsed(&start, &end) / 1000000));
 352.488 ++}
 352.489 ++
 352.490 ++static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
 352.491 ++{
 352.492 ++	XRRScreenResources *res;
 352.493 ++
 352.494 ++	res = XRRGetScreenResourcesCurrent(dpy, window);
 352.495 ++	if (res == NULL)
 352.496 ++		res = XRRGetScreenResources(dpy, window);
 352.497 ++
 352.498 ++	return res;
 352.499 ++}
 352.500 ++
 352.501 ++static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
 352.502 ++{
 352.503 ++	int i;
 352.504 ++
 352.505 ++	for (i = 0; i < res->nmode; i++) {
 352.506 ++		if (res->modes[i].id == id)
 352.507 ++			return &res->modes[i];
 352.508 ++	}
 352.509 ++
 352.510 ++	return NULL;
 352.511 ++}
 352.512 ++
 352.513 ++static int dri2_open(Display *dpy)
 352.514 ++{
 352.515 ++	drm_auth_t auth;
 352.516 ++	char *driver, *device;
 352.517 ++	int fd;
 352.518 ++
 352.519 ++	if (!DRI2QueryExtension(dpy, &fd, &fd))
 352.520 ++		return -1;
 352.521 ++
 352.522 ++	if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
 352.523 ++		return -1;
 352.524 ++
 352.525 ++	fd = open(device, O_RDWR);
 352.526 ++	if (fd < 0)
 352.527 ++		return -1;
 352.528 ++
 352.529 ++	if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
 352.530 ++		return -1;
 352.531 ++
 352.532 ++	if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
 352.533 ++		return -1;
 352.534 ++
 352.535 ++	return fd;
 352.536 ++}
 352.537 ++
 352.538 ++static void fullscreen(Display *dpy, Window win)
 352.539 ++{
 352.540 ++	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
 352.541 ++	XChangeProperty(dpy, win,
 352.542 ++			XInternAtom(dpy, "_NET_WM_STATE", False),
 352.543 ++			XA_ATOM, 32, PropModeReplace,
 352.544 ++			(unsigned char *)&atom, 1);
 352.545 ++}
 352.546 ++
 352.547 ++static int has_composite(Display *dpy)
 352.548 ++{
 352.549 ++	int event, error;
 352.550 ++	int major, minor;
 352.551 ++
 352.552 ++	if (!XDamageQueryExtension (dpy, &event, &error))
 352.553 ++		return 0;
 352.554 ++
 352.555 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
 352.556 ++		return 0;
 352.557 ++
 352.558 ++	XCompositeQueryVersion(dpy, &major, &minor);
 352.559 ++
 352.560 ++	return major > 0 || minor >= 4;
 352.561 ++}
 352.562 ++
 352.563 ++int main(int argc, char **argv)
 352.564 ++{
 352.565 ++	Display *dpy;
 352.566 ++	Window root, win;
 352.567 ++	XRRScreenResources *res;
 352.568 ++	XRRCrtcInfo **original_crtc;
 352.569 ++	XSetWindowAttributes attr;
 352.570 ++	enum window { ROOT, FULLSCREEN, WINDOW } w = FULLSCREEN;
 352.571 ++	enum visible {REDIRECTED, NORMAL } v = NORMAL;
 352.572 ++	enum display { OFF, ON } d = OFF;
 352.573 ++	int width, height;
 352.574 ++	int i, fd;
 352.575 ++	int c;
 352.576 ++
 352.577 ++	while ((c = getopt(argc, argv, "d:v:w:")) != -1) {
 352.578 ++		switch (c) {
 352.579 ++		case 'd':
 352.580 ++			if (strcmp(optarg, "off") == 0)
 352.581 ++				d = OFF;
 352.582 ++			else if (strcmp(optarg, "on") == 0)
 352.583 ++				d = ON;
 352.584 ++			else
 352.585 ++				abort();
 352.586 ++			break;
 352.587 ++
 352.588 ++		case 'v':
 352.589 ++			if (strcmp(optarg, "redirected") == 0)
 352.590 ++				v = REDIRECTED;
 352.591 ++			else if (strcmp(optarg, "normal") == 0)
 352.592 ++				v = NORMAL;
 352.593 ++			else
 352.594 ++				abort();
 352.595 ++			break;
 352.596 ++
 352.597 ++		case 'w':
 352.598 ++			if (strcmp(optarg, "fullscreen") == 0)
 352.599 ++				w = FULLSCREEN;
 352.600 ++			else if (strcmp(optarg, "window") == 0)
 352.601 ++				w = WINDOW;
 352.602 ++			else if (strcmp(optarg, "root") == 0)
 352.603 ++				w = ROOT;
 352.604 ++			else
 352.605 ++				abort();
 352.606 ++			break;
 352.607 ++		}
 352.608 ++	}
 352.609 ++
 352.610 ++	attr.override_redirect = 1;
 352.611 ++
 352.612 ++	dpy = XOpenDisplay(NULL);
 352.613 ++	if (dpy == NULL)
 352.614 ++		return 77;
 352.615 ++
 352.616 ++	width = DisplayWidth(dpy, DefaultScreen(dpy));
 352.617 ++	height = DisplayHeight(dpy, DefaultScreen(dpy));
 352.618 ++
 352.619 ++	fd = dri2_open(dpy);
 352.620 ++	if (fd < 0)
 352.621 ++		return 77;
 352.622 ++
 352.623 ++	if (DPMSQueryExtension(dpy, &i, &i))
 352.624 ++		DPMSDisable(dpy);
 352.625 ++
 352.626 ++	root = DefaultRootWindow(dpy);
 352.627 ++
 352.628 ++	signal(SIGALRM, SIG_IGN);
 352.629 ++	XSetErrorHandler(_check_error_handler);
 352.630 ++
 352.631 ++	res = NULL;
 352.632 ++	if (XRRQueryVersion(dpy, &i, &i))
 352.633 ++		res = _XRRGetScreenResourcesCurrent(dpy, root);
 352.634 ++	if (res == NULL)
 352.635 ++		return 77;
 352.636 ++
 352.637 ++	if (v == REDIRECTED && !has_composite(dpy))
 352.638 ++		return 77;
 352.639 ++
 352.640 ++	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
 352.641 ++	for (i = 0; i < res->ncrtc; i++)
 352.642 ++		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
 352.643 ++
 352.644 ++	for (i = 0; i < res->ncrtc; i++)
 352.645 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 352.646 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
 352.647 ++
 352.648 ++	DRI2CreateDrawable(dpy, root);
 352.649 ++	DRI2SwapInterval(dpy, root, 0);
 352.650 ++
 352.651 ++	if (d != OFF) {
 352.652 ++		for (i = 0; i < res->noutput; i++) {
 352.653 ++			XRROutputInfo *output;
 352.654 ++			XRRModeInfo *mode;
 352.655 ++
 352.656 ++			output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
 352.657 ++			if (output == NULL)
 352.658 ++				continue;
 352.659 ++
 352.660 ++			mode = NULL;
 352.661 ++			if (res->nmode)
 352.662 ++				mode = lookup_mode(res, output->modes[0]);
 352.663 ++			if (mode == NULL)
 352.664 ++				continue;
 352.665 ++
 352.666 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[0], CurrentTime,
 352.667 ++					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
 352.668 ++			width = mode->width;
 352.669 ++			height = mode->height;
 352.670 ++			break;
 352.671 ++		}
 352.672 ++		if (i == res->noutput) {
 352.673 ++			_x_error_occurred = 77;
 352.674 ++			goto restore;
 352.675 ++		}
 352.676 ++	}
 352.677 ++
 352.678 ++	if (w == ROOT) {
 352.679 ++		run(dpy, root);
 352.680 ++	} else if (w == FULLSCREEN) {
 352.681 ++		win = XCreateWindow(dpy, root,
 352.682 ++				    0, 0, width, height, 0,
 352.683 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
 352.684 ++				    InputOutput,
 352.685 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
 352.686 ++				    CWOverrideRedirect, &attr);
 352.687 ++		DRI2CreateDrawable(dpy, win);
 352.688 ++		DRI2SwapInterval(dpy, win, 0);
 352.689 ++		if (v == REDIRECTED) {
 352.690 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
 352.691 ++			XDamageCreate(dpy, win, XDamageReportRawRectangles);
 352.692 ++		} else
 352.693 ++			fullscreen(dpy, win);
 352.694 ++		XMapWindow(dpy, win);
 352.695 ++		run(dpy, win);
 352.696 ++	} else if (w == WINDOW) {
 352.697 ++		win = XCreateWindow(dpy, root,
 352.698 ++				    0, 0, width/2, height/2, 0,
 352.699 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
 352.700 ++				    InputOutput,
 352.701 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
 352.702 ++				    CWOverrideRedirect, &attr);
 352.703 ++		DRI2CreateDrawable(dpy, win);
 352.704 ++		DRI2SwapInterval(dpy, win, 0);
 352.705 ++		if (v == REDIRECTED) {
 352.706 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
 352.707 ++			XDamageCreate(dpy, win, XDamageReportRawRectangles);
 352.708 ++		}
 352.709 ++		XMapWindow(dpy, win);
 352.710 ++		run(dpy, win);
 352.711 ++	}
 352.712 ++
 352.713 ++restore:
 352.714 ++	for (i = 0; i < res->ncrtc; i++)
 352.715 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 352.716 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
 352.717 ++
 352.718 ++	for (i = 0; i < res->ncrtc; i++)
 352.719 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 352.720 ++				 original_crtc[i]->x,
 352.721 ++				 original_crtc[i]->y,
 352.722 ++				 original_crtc[i]->mode,
 352.723 ++				 original_crtc[i]->rotation,
 352.724 ++				 original_crtc[i]->outputs,
 352.725 ++				 original_crtc[i]->noutput);
 352.726 ++
 352.727 ++	if (DPMSQueryExtension(dpy, &i, &i))
 352.728 ++		DPMSEnable(dpy);
 352.729 ++
 352.730 ++	XSync(dpy, True);
 352.731 ++	return _x_error_occurred;
 352.732 ++}
 352.733 +diff --git a/benchmarks/dri3-swap.c b/benchmarks/dri3-swap.c
 352.734 +new file mode 100644
 352.735 +index 00000000..4dd423b3
 352.736 +--- /dev/null
 352.737 ++++ b/benchmarks/dri3-swap.c
 352.738 +@@ -0,0 +1,595 @@
 352.739 ++/*
 352.740 ++ * Copyright (c) 2015 Intel Corporation
 352.741 ++ *
 352.742 ++ * Permission is hereby granted, free of charge, to any person obtaining a
 352.743 ++ * copy of this software and associated documentation files (the "Software"),
 352.744 ++ * to deal in the Software without restriction, including without limitation
 352.745 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 352.746 ++ * and/or sell copies of the Software, and to permit persons to whom the
 352.747 ++ * Software is furnished to do so, subject to the following conditions:
 352.748 ++ *
 352.749 ++ * The above copyright notice and this permission notice (including the next
 352.750 ++ * paragraph) shall be included in all copies or substantial portions of the
 352.751 ++ * Software.
 352.752 ++ *
 352.753 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 352.754 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 352.755 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 352.756 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 352.757 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 352.758 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 352.759 ++ * SOFTWARE.
 352.760 ++ *
 352.761 ++ */
 352.762 ++
 352.763 ++#ifdef HAVE_CONFIG_H
 352.764 ++#include "config.h"
 352.765 ++#endif
 352.766 ++
 352.767 ++#include <X11/Xlib.h>
 352.768 ++#include <X11/Xatom.h>
 352.769 ++#include <X11/Xlib-xcb.h>
 352.770 ++#include <X11/xshmfence.h>
 352.771 ++#include <X11/Xutil.h>
 352.772 ++#include <X11/Xlibint.h>
 352.773 ++#include <X11/extensions/Xcomposite.h>
 352.774 ++#include <X11/extensions/Xdamage.h>
 352.775 ++#include <X11/extensions/dpms.h>
 352.776 ++#include <X11/extensions/randr.h>
 352.777 ++#include <X11/extensions/Xrandr.h>
 352.778 ++#include <xcb/xcb.h>
 352.779 ++#include <xcb/present.h>
 352.780 ++#include <xcb/dri3.h>
 352.781 ++#include <xcb/xfixes.h>
 352.782 ++#include <xf86drm.h>
 352.783 ++#include <i915_drm.h>
 352.784 ++
 352.785 ++#include <stdio.h>
 352.786 ++#include <string.h>
 352.787 ++#include <fcntl.h>
 352.788 ++#include <unistd.h>
 352.789 ++#include <assert.h>
 352.790 ++#include <errno.h>
 352.791 ++#include <setjmp.h>
 352.792 ++#include <signal.h>
 352.793 ++
 352.794 ++struct dri3_fence {
 352.795 ++	XID xid;
 352.796 ++	void *addr;
 352.797 ++};
 352.798 ++
 352.799 ++static int _x_error_occurred;
 352.800 ++static uint32_t stamp;
 352.801 ++
 352.802 ++struct list {
 352.803 ++    struct list *next, *prev;
 352.804 ++};
 352.805 ++
 352.806 ++static void
 352.807 ++list_init(struct list *list)
 352.808 ++{
 352.809 ++    list->next = list->prev = list;
 352.810 ++}
 352.811 ++
 352.812 ++static inline void
 352.813 ++__list_add(struct list *entry,
 352.814 ++	    struct list *prev,
 352.815 ++	    struct list *next)
 352.816 ++{
 352.817 ++    next->prev = entry;
 352.818 ++    entry->next = next;
 352.819 ++    entry->prev = prev;
 352.820 ++    prev->next = entry;
 352.821 ++}
 352.822 ++
 352.823 ++static inline void
 352.824 ++list_add(struct list *entry, struct list *head)
 352.825 ++{
 352.826 ++    __list_add(entry, head, head->next);
 352.827 ++}
 352.828 ++
 352.829 ++static inline void
 352.830 ++__list_del(struct list *prev, struct list *next)
 352.831 ++{
 352.832 ++	next->prev = prev;
 352.833 ++	prev->next = next;
 352.834 ++}
 352.835 ++
 352.836 ++static inline void
 352.837 ++_list_del(struct list *entry)
 352.838 ++{
 352.839 ++    __list_del(entry->prev, entry->next);
 352.840 ++}
 352.841 ++
 352.842 ++static inline void
 352.843 ++list_move(struct list *list, struct list *head)
 352.844 ++{
 352.845 ++	if (list->prev != head) {
 352.846 ++		_list_del(list);
 352.847 ++		list_add(list, head);
 352.848 ++	}
 352.849 ++}
 352.850 ++
 352.851 ++#define __container_of(ptr, sample, member)				\
 352.852 ++    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
 352.853 ++
 352.854 ++#define list_for_each_entry(pos, head, member)				\
 352.855 ++    for (pos = __container_of((head)->next, pos, member);		\
 352.856 ++	 &pos->member != (head);					\
 352.857 ++	 pos = __container_of(pos->member.next, pos, member))
 352.858 ++
 352.859 ++static int
 352.860 ++_check_error_handler(Display     *display,
 352.861 ++		     XErrorEvent *event)
 352.862 ++{
 352.863 ++	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
 352.864 ++	       DisplayString(display),
 352.865 ++	       event->serial,
 352.866 ++	       event->error_code,
 352.867 ++	       event->request_code,
 352.868 ++	       event->minor_code);
 352.869 ++	_x_error_occurred++;
 352.870 ++	return False; /* ignored */
 352.871 ++}
 352.872 ++
 352.873 ++static int dri3_create_fence(Display *dpy,
 352.874 ++			     Pixmap pixmap,
 352.875 ++			     struct dri3_fence *fence)
 352.876 ++{
 352.877 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
 352.878 ++	struct dri3_fence f;
 352.879 ++	int fd;
 352.880 ++
 352.881 ++	fd = xshmfence_alloc_shm();
 352.882 ++	if (fd < 0)
 352.883 ++		return -1;
 352.884 ++
 352.885 ++	f.addr = xshmfence_map_shm(fd);
 352.886 ++	if (f.addr == NULL) {
 352.887 ++		close(fd);
 352.888 ++		return -1;
 352.889 ++	}
 352.890 ++
 352.891 ++	f.xid = xcb_generate_id(c);
 352.892 ++	xcb_dri3_fence_from_fd(c, pixmap, f.xid, 0, fd);
 352.893 ++
 352.894 ++	*fence = f;
 352.895 ++	return 0;
 352.896 ++}
 352.897 ++
 352.898 ++static double elapsed(const struct timespec *start,
 352.899 ++		      const struct timespec *end)
 352.900 ++{
 352.901 ++	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
 352.902 ++}
 352.903 ++
 352.904 ++struct buffer {
 352.905 ++	struct list link;
 352.906 ++	Pixmap pixmap;
 352.907 ++	struct dri3_fence fence;
 352.908 ++	int fd;
 352.909 ++	int busy;
 352.910 ++};
 352.911 ++
 352.912 ++static void run(Display *dpy, Window win)
 352.913 ++{
 352.914 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
 352.915 ++	struct timespec start, end;
 352.916 ++#define N_BACK 8
 352.917 ++	struct buffer buffer[N_BACK];
 352.918 ++	struct list mru;
 352.919 ++	Window root;
 352.920 ++	unsigned int width, height;
 352.921 ++	unsigned border, depth;
 352.922 ++	unsigned present_flags = XCB_PRESENT_OPTION_ASYNC;
 352.923 ++	xcb_xfixes_region_t update = 0;
 352.924 ++	int completed = 0;
 352.925 ++	int queued = 0;
 352.926 ++	uint32_t eid;
 352.927 ++	void *Q;
 352.928 ++	int i, n;
 352.929 ++
 352.930 ++	list_init(&mru);
 352.931 ++
 352.932 ++	XGetGeometry(dpy, win,
 352.933 ++		     &root, &i, &n, &width, &height, &border, &depth);
 352.934 ++
 352.935 ++	_x_error_occurred = 0;
 352.936 ++
 352.937 ++	for (n = 0; n < N_BACK; n++) {
 352.938 ++		xcb_dri3_buffer_from_pixmap_reply_t *reply;
 352.939 ++		int *fds;
 352.940 ++
 352.941 ++		buffer[n].pixmap =
 352.942 ++			XCreatePixmap(dpy, win, width, height, depth);
 352.943 ++		buffer[n].fence.xid = 0;
 352.944 ++		buffer[n].fd = -1;
 352.945 ++
 352.946 ++		if (dri3_create_fence(dpy, win, &buffer[n].fence))
 352.947 ++			return;
 352.948 ++
 352.949 ++		reply = xcb_dri3_buffer_from_pixmap_reply (c,
 352.950 ++							   xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
 352.951 ++							   NULL);
 352.952 ++		if (reply == NULL)
 352.953 ++			return;
 352.954 ++
 352.955 ++		fds = xcb_dri3_buffer_from_pixmap_reply_fds (c, reply);
 352.956 ++		buffer[n].fd = fds[0];
 352.957 ++		free(reply);
 352.958 ++
 352.959 ++		/* start idle */
 352.960 ++		xshmfence_trigger(buffer[n].fence.addr);
 352.961 ++		buffer[n].busy = 0;
 352.962 ++		list_add(&buffer[n].link, &mru);
 352.963 ++	}
 352.964 ++
 352.965 ++	eid = xcb_generate_id(c);
 352.966 ++	xcb_present_select_input(c, eid, win,
 352.967 ++                                 XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY |
 352.968 ++                                 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
 352.969 ++	Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
 352.970 ++
 352.971 ++	clock_gettime(CLOCK_MONOTONIC, &start);
 352.972 ++	do {
 352.973 ++		for (n = 0; n < 1000; n++) {
 352.974 ++			struct buffer *tmp, *b = NULL;
 352.975 ++			list_for_each_entry(tmp, &mru, link) {
 352.976 ++				if (!tmp->busy) {
 352.977 ++					b = tmp;
 352.978 ++					break;
 352.979 ++				}
 352.980 ++			}
 352.981 ++			while (b == NULL) {
 352.982 ++				xcb_present_generic_event_t *ev;
 352.983 ++
 352.984 ++				ev = (xcb_present_generic_event_t *)
 352.985 ++					xcb_wait_for_special_event(c, Q);
 352.986 ++				if (ev == NULL)
 352.987 ++					abort();
 352.988 ++
 352.989 ++				do {
 352.990 ++					switch (ev->evtype) {
 352.991 ++					case XCB_PRESENT_COMPLETE_NOTIFY:
 352.992 ++						completed++;
 352.993 ++						queued--;
 352.994 ++						break;
 352.995 ++
 352.996 ++					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
 352.997 ++						{
 352.998 ++							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
 352.999 ++							assert(ie->serial < N_BACK);
352.1000 ++							buffer[ie->serial].busy = 0;
352.1001 ++							if (b == NULL)
352.1002 ++								b = &buffer[ie->serial];
352.1003 ++							break;
352.1004 ++						}
352.1005 ++					}
352.1006 ++					free(ev);
352.1007 ++				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
352.1008 ++			}
352.1009 ++
352.1010 ++			b->busy = 1;
352.1011 ++			if (b->fence.xid) {
352.1012 ++				xshmfence_await(b->fence.addr);
352.1013 ++				xshmfence_reset(b->fence.addr);
352.1014 ++			}
352.1015 ++			xcb_present_pixmap(c, win, b->pixmap, b - buffer,
352.1016 ++					   0, /* valid */
352.1017 ++					   update, /* update */
352.1018 ++					   0, /* x_off */
352.1019 ++					   0, /* y_off */
352.1020 ++					   None,
352.1021 ++					   None, /* wait fence */
352.1022 ++					   b->fence.xid,
352.1023 ++					   present_flags,
352.1024 ++					   0, /* target msc */
352.1025 ++					   0, /* divisor */
352.1026 ++					   0, /* remainder */
352.1027 ++					   0, NULL);
352.1028 ++			list_move(&b->link, &mru);
352.1029 ++			queued++;
352.1030 ++			xcb_flush(c);
352.1031 ++		}
352.1032 ++		clock_gettime(CLOCK_MONOTONIC, &end);
352.1033 ++	} while (end.tv_sec < start.tv_sec + 10);
352.1034 ++
352.1035 ++	while (queued) {
352.1036 ++		xcb_present_generic_event_t *ev;
352.1037 ++
352.1038 ++		ev = (xcb_present_generic_event_t *)
352.1039 ++			xcb_wait_for_special_event(c, Q);
352.1040 ++		if (ev == NULL)
352.1041 ++			abort();
352.1042 ++
352.1043 ++		do {
352.1044 ++			switch (ev->evtype) {
352.1045 ++			case XCB_PRESENT_COMPLETE_NOTIFY:
352.1046 ++				completed++;
352.1047 ++				queued--;
352.1048 ++				break;
352.1049 ++
352.1050 ++			case XCB_PRESENT_EVENT_IDLE_NOTIFY:
352.1051 ++				break;
352.1052 ++			}
352.1053 ++			free(ev);
352.1054 ++		} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
352.1055 ++	}
352.1056 ++	clock_gettime(CLOCK_MONOTONIC, &end);
352.1057 ++
352.1058 ++	printf("%f\n", completed / (elapsed(&start, &end) / 1000000));
352.1059 ++}
352.1060 ++
352.1061 ++static int has_present(Display *dpy)
352.1062 ++{
352.1063 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.1064 ++	xcb_generic_error_t *error = NULL;
352.1065 ++	void *reply;
352.1066 ++
352.1067 ++	reply = xcb_present_query_version_reply(c,
352.1068 ++						xcb_present_query_version(c,
352.1069 ++									  XCB_PRESENT_MAJOR_VERSION,
352.1070 ++									  XCB_PRESENT_MINOR_VERSION),
352.1071 ++						&error);
352.1072 ++
352.1073 ++	free(reply);
352.1074 ++	free(error);
352.1075 ++	if (reply == NULL) {
352.1076 ++		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
352.1077 ++		return 0;
352.1078 ++	}
352.1079 ++
352.1080 ++	return 1;
352.1081 ++}
352.1082 ++
352.1083 ++static int has_composite(Display *dpy)
352.1084 ++{
352.1085 ++	int event, error;
352.1086 ++	int major, minor;
352.1087 ++
352.1088 ++	if (!XDamageQueryExtension (dpy, &event, &error))
352.1089 ++		return 0;
352.1090 ++
352.1091 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
352.1092 ++		return 0;
352.1093 ++
352.1094 ++	XCompositeQueryVersion(dpy, &major, &minor);
352.1095 ++
352.1096 ++	return major > 0 || minor >= 4;
352.1097 ++}
352.1098 ++
352.1099 ++static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
352.1100 ++{
352.1101 ++	XRRScreenResources *res;
352.1102 ++
352.1103 ++	res = XRRGetScreenResourcesCurrent(dpy, window);
352.1104 ++	if (res == NULL)
352.1105 ++		res = XRRGetScreenResources(dpy, window);
352.1106 ++
352.1107 ++	return res;
352.1108 ++}
352.1109 ++
352.1110 ++static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
352.1111 ++{
352.1112 ++	int i;
352.1113 ++
352.1114 ++	for (i = 0; i < res->nmode; i++) {
352.1115 ++		if (res->modes[i].id == id)
352.1116 ++			return &res->modes[i];
352.1117 ++	}
352.1118 ++
352.1119 ++	return NULL;
352.1120 ++}
352.1121 ++
352.1122 ++static void fullscreen(Display *dpy, Window win)
352.1123 ++{
352.1124 ++	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
352.1125 ++	XChangeProperty(dpy, win,
352.1126 ++			XInternAtom(dpy, "_NET_WM_STATE", False),
352.1127 ++			XA_ATOM, 32, PropModeReplace,
352.1128 ++			(unsigned char *)&atom, 1);
352.1129 ++}
352.1130 ++
352.1131 ++static int dri3_query_version(Display *dpy, int *major, int *minor)
352.1132 ++{
352.1133 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.1134 ++	xcb_dri3_query_version_reply_t *reply;
352.1135 ++	xcb_generic_error_t *error;
352.1136 ++
352.1137 ++	*major = *minor = -1;
352.1138 ++
352.1139 ++	reply = xcb_dri3_query_version_reply(c,
352.1140 ++					     xcb_dri3_query_version(c,
352.1141 ++								    XCB_DRI3_MAJOR_VERSION,
352.1142 ++								    XCB_DRI3_MINOR_VERSION),
352.1143 ++					     &error);
352.1144 ++	free(error);
352.1145 ++	if (reply == NULL)
352.1146 ++		return -1;
352.1147 ++
352.1148 ++	*major = reply->major_version;
352.1149 ++	*minor = reply->minor_version;
352.1150 ++	free(reply);
352.1151 ++
352.1152 ++	return 0;
352.1153 ++}
352.1154 ++
352.1155 ++static int has_dri3(Display *dpy)
352.1156 ++{
352.1157 ++	const xcb_query_extension_reply_t *ext;
352.1158 ++	int major, minor;
352.1159 ++
352.1160 ++	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
352.1161 ++	if (ext == NULL || !ext->present)
352.1162 ++		return 0;
352.1163 ++
352.1164 ++	if (dri3_query_version(dpy, &major, &minor) < 0)
352.1165 ++		return 0;
352.1166 ++
352.1167 ++	return major >= 0;
352.1168 ++}
352.1169 ++
352.1170 ++int main(int argc, char **argv)
352.1171 ++{
352.1172 ++	Display *dpy;
352.1173 ++	Window root, win;
352.1174 ++	XRRScreenResources *res;
352.1175 ++	XRRCrtcInfo **original_crtc;
352.1176 ++	XSetWindowAttributes attr;
352.1177 ++	enum window { ROOT, FULLSCREEN, WINDOW } w = FULLSCREEN;
352.1178 ++	enum visible {REDIRECTED, NORMAL } v = NORMAL;
352.1179 ++	enum display { OFF, ON } d = OFF;
352.1180 ++	int width, height;
352.1181 ++	int i;
352.1182 ++
352.1183 ++	while ((i = getopt(argc, argv, "d:v:w:")) != -1) {
352.1184 ++		switch (i) {
352.1185 ++		case 'd':
352.1186 ++			if (strcmp(optarg, "off") == 0)
352.1187 ++				d = OFF;
352.1188 ++			else if (strcmp(optarg, "on") == 0)
352.1189 ++				d = ON;
352.1190 ++			else
352.1191 ++				abort();
352.1192 ++			break;
352.1193 ++
352.1194 ++		case 'v':
352.1195 ++			if (strcmp(optarg, "redirected") == 0)
352.1196 ++				v = REDIRECTED;
352.1197 ++			else if (strcmp(optarg, "normal") == 0)
352.1198 ++				v = NORMAL;
352.1199 ++			else
352.1200 ++				abort();
352.1201 ++			break;
352.1202 ++
352.1203 ++		case 'w':
352.1204 ++			if (strcmp(optarg, "fullscreen") == 0)
352.1205 ++				w = FULLSCREEN;
352.1206 ++			else if (strcmp(optarg, "window") == 0)
352.1207 ++				w = WINDOW;
352.1208 ++			else if (strcmp(optarg, "root") == 0)
352.1209 ++				w = ROOT;
352.1210 ++			else
352.1211 ++				abort();
352.1212 ++			break;
352.1213 ++		}
352.1214 ++	}
352.1215 ++
352.1216 ++	attr.override_redirect = 1;
352.1217 ++
352.1218 ++	dpy = XOpenDisplay(NULL);
352.1219 ++	if (dpy == NULL)
352.1220 ++		return 77;
352.1221 ++
352.1222 ++	width = DisplayWidth(dpy, DefaultScreen(dpy));
352.1223 ++	height = DisplayHeight(dpy, DefaultScreen(dpy));
352.1224 ++
352.1225 ++	if (!has_present(dpy))
352.1226 ++		return 77;
352.1227 ++
352.1228 ++	if (!has_dri3(dpy))
352.1229 ++		return 77;
352.1230 ++
352.1231 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.1232 ++		DPMSDisable(dpy);
352.1233 ++
352.1234 ++	root = DefaultRootWindow(dpy);
352.1235 ++
352.1236 ++	signal(SIGALRM, SIG_IGN);
352.1237 ++	XSetErrorHandler(_check_error_handler);
352.1238 ++
352.1239 ++	res = NULL;
352.1240 ++	if (XRRQueryVersion(dpy, &i, &i))
352.1241 ++		res = _XRRGetScreenResourcesCurrent(dpy, root);
352.1242 ++	if (res == NULL)
352.1243 ++		return 77;
352.1244 ++
352.1245 ++	if (v == REDIRECTED && !has_composite(dpy))
352.1246 ++		return 77;
352.1247 ++
352.1248 ++	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
352.1249 ++	for (i = 0; i < res->ncrtc; i++)
352.1250 ++		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
352.1251 ++
352.1252 ++	for (i = 0; i < res->ncrtc; i++)
352.1253 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.1254 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
352.1255 ++
352.1256 ++	if (d != OFF) {
352.1257 ++		for (i = 0; i < res->noutput; i++) {
352.1258 ++			XRROutputInfo *output;
352.1259 ++			XRRModeInfo *mode;
352.1260 ++
352.1261 ++			output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
352.1262 ++			if (output == NULL)
352.1263 ++				continue;
352.1264 ++
352.1265 ++			mode = NULL;
352.1266 ++			if (res->nmode)
352.1267 ++				mode = lookup_mode(res, output->modes[0]);
352.1268 ++			if (mode == NULL)
352.1269 ++				continue;
352.1270 ++
352.1271 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[0], CurrentTime,
352.1272 ++					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
352.1273 ++			width = mode->width;
352.1274 ++			height = mode->height;
352.1275 ++			break;
352.1276 ++		}
352.1277 ++		if (i == res->noutput) {
352.1278 ++			_x_error_occurred = 77;
352.1279 ++			goto restore;
352.1280 ++		}
352.1281 ++	}
352.1282 ++
352.1283 ++	if (w == ROOT) {
352.1284 ++		run(dpy, root);
352.1285 ++	} else if (w == FULLSCREEN) {
352.1286 ++		win = XCreateWindow(dpy, root,
352.1287 ++				    0, 0, width, height, 0,
352.1288 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.1289 ++				    InputOutput,
352.1290 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.1291 ++				    CWOverrideRedirect, &attr);
352.1292 ++		if (v == REDIRECTED) {
352.1293 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.1294 ++			XDamageCreate(dpy, win, XDamageReportRawRectangles);
352.1295 ++		} else
352.1296 ++			fullscreen(dpy, win);
352.1297 ++		XMapWindow(dpy, win);
352.1298 ++		run(dpy, win);
352.1299 ++	} else if (w == WINDOW) {
352.1300 ++		win = XCreateWindow(dpy, root,
352.1301 ++				    0, 0, width/2, height/2, 0,
352.1302 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.1303 ++				    InputOutput,
352.1304 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.1305 ++				    CWOverrideRedirect, &attr);
352.1306 ++		if (v == REDIRECTED) {
352.1307 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.1308 ++			XDamageCreate(dpy, win, XDamageReportRawRectangles);
352.1309 ++		}
352.1310 ++		XMapWindow(dpy, win);
352.1311 ++		run(dpy, win);
352.1312 ++	}
352.1313 ++
352.1314 ++restore:
352.1315 ++	for (i = 0; i < res->ncrtc; i++)
352.1316 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.1317 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
352.1318 ++
352.1319 ++	for (i = 0; i < res->ncrtc; i++)
352.1320 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.1321 ++				 original_crtc[i]->x,
352.1322 ++				 original_crtc[i]->y,
352.1323 ++				 original_crtc[i]->mode,
352.1324 ++				 original_crtc[i]->rotation,
352.1325 ++				 original_crtc[i]->outputs,
352.1326 ++				 original_crtc[i]->noutput);
352.1327 ++
352.1328 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.1329 ++		DPMSEnable(dpy);
352.1330 ++
352.1331 ++	XSync(dpy, True);
352.1332 ++	return _x_error_occurred;
352.1333 ++}
352.1334 +diff --git a/configure.ac b/configure.ac
352.1335 +index 61bea435..d13917ec 100644
352.1336 +--- a/configure.ac
352.1337 ++++ b/configure.ac
352.1338 +@@ -195,18 +195,24 @@ AC_ARG_ENABLE(udev,
352.1339 +               [UDEV="$enableval"],
352.1340 +               [UDEV=auto])
352.1341 + 
352.1342 ++udev_msg=" disabled"
352.1343 + if test "x$UDEV" != "xno"; then
352.1344 + 	PKG_CHECK_MODULES(UDEV, [libudev], [udev="yes"], [udev="no"])
352.1345 ++	AC_CHECK_HEADERS([sys/stat.h], [], [udev="no"])
352.1346 + 	if test "x$UDEV" = "xyes" -a "x$udev" != "xyes"; then
352.1347 + 		AC_MSG_ERROR([udev support requested but not found (libudev)])
352.1348 + 	fi
352.1349 + 	if test "x$udev" = "xyes"; then
352.1350 + 		AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
352.1351 ++		udev_msg=" yes"
352.1352 ++	else
352.1353 ++		udev_msg=" no"
352.1354 + 	fi
352.1355 + fi
352.1356 + 
352.1357 +-PKG_CHECK_MODULES(X11, [x11 xrender xrandr xext xfixes cairo cairo-xlib-xrender pixman-1 libpng], [x11="yes"], [x11="no"])
352.1358 ++PKG_CHECK_MODULES(X11, [x11 x11-xcb xcb-dri2 xcomposite xdamage xrender xrandr xext xfixes cairo cairo-xlib-xrender pixman-1 libpng], [x11="yes"], [x11="no"])
352.1359 + AM_CONDITIONAL(HAVE_X11, test "x$x11" = "xyes")
352.1360 ++echo X11_CLFAGS="$X11_CLFAGS" X11_LIBS="$X11_LIBS"
352.1361 + 
352.1362 + cpuid="yes"
352.1363 + AC_TRY_LINK([
352.1364 +@@ -270,10 +276,13 @@ if test "x$shm" = "xyes"; then
352.1365 + 	AC_DEFINE([HAVE_MIT_SHM], 1, [Define to 1 if MIT-SHM is available])
352.1366 + fi
352.1367 + 
352.1368 +-PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-present x11-xcb xshmfence x11 xrender xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
352.1369 ++PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-xfixes xcb-present x11-xcb xshmfence x11 xcomposite xdamage xrender xrandr xxf86vm xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
352.1370 + AM_CONDITIONAL(X11_DRI3, test "x$x11_dri3" = "xyes" -a "x$shm" = "xyes")
352.1371 + AM_CONDITIONAL(X11_SHM, test "x$shm" = "xyes")
352.1372 + 
352.1373 ++PKG_CHECK_MODULES(X11_VM, [xxf86vm], [x11_vm="yes"], [x11_vm="no"])
352.1374 ++AM_CONDITIONAL(X11_VM, test "x$x11_vm" = "xyes")
352.1375 ++
352.1376 + AC_ARG_ENABLE(tools,
352.1377 +               AS_HELP_STRING([--disable-tools],
352.1378 + 			     [Enable building and installing the miscellaneous tools [default=auto]]),
352.1379 +@@ -285,7 +294,7 @@ if test "x$shm" != "xyes"; then
352.1380 + 	tools="no"
352.1381 + fi
352.1382 + if test "x$tools" != "xno"; then
352.1383 +-	ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xext x11 pixman-1"
352.1384 ++	ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xscrnsaver xext x11 pixman-1"
352.1385 + 	extra_cflags=""
352.1386 + 
352.1387 + 	ignore="xinerama"
352.1388 +@@ -307,6 +316,8 @@ if test "x$tools" != "xno"; then
352.1389 + 		tools="no"
352.1390 + 	fi
352.1391 + 
352.1392 ++	PKG_CHECK_MODULES(TOOL_CURSOR, [xfixes x11 libpng], [cursor="yes"], [ivo="no"])
352.1393 ++
352.1394 + 	IVO_CFLAGS="$IVO_CFLAGS $extra_cflags"
352.1395 + fi
352.1396 + if test "x$tools" != "xno"; then
352.1397 +@@ -315,6 +326,7 @@ fi
352.1398 + AC_MSG_CHECKING([whether to build additional tools])
352.1399 + AC_MSG_RESULT([$tools])
352.1400 + AM_CONDITIONAL(BUILD_TOOLS, test "x$tools" != "xno")
352.1401 ++AM_CONDITIONAL(BUILD_TOOL_CURSOR, test "x$cursor" = "xyes")
352.1402 + 
352.1403 + # Define a configure option for an alternate module directory
352.1404 + AC_ARG_WITH(xorg-module-dir,
352.1405 +@@ -339,10 +351,20 @@ AC_ARG_ENABLE(dri2,
352.1406 + 	      [DRI2=$enableval],
352.1407 + 	      [DRI2=yes])
352.1408 + AC_ARG_ENABLE(dri3,
352.1409 +-	      AS_HELP_STRING([--enable-dri3],
352.1410 +-			     [Enable DRI3 support [[default=no]]]),
352.1411 ++	      AS_HELP_STRING([--disable-dri3],
352.1412 ++			     [Disable DRI3 support [[default=yes]]]),
352.1413 + 	      [DRI3=$enableval],
352.1414 +-	      [DRI3=no])
352.1415 ++	      [DRI3=yes])
352.1416 ++AC_ARG_WITH(default-dri,
352.1417 ++	    AS_HELP_STRING([--with-default-dri],
352.1418 ++			   [Select the default maximum DRI level [default 2]]),
352.1419 ++	      [DRI_DEFAULT=$withval],
352.1420 ++	      [DRI_DEFAULT=2])
352.1421 ++if test "x$DRI_DEFAULT" = "x0"; then
352.1422 ++	AC_DEFINE(DEFAULT_DRI_LEVEL, 0,[Default DRI level])
352.1423 ++else
352.1424 ++	AC_DEFINE(DEFAULT_DRI_LEVEL, ~0, [Default DRI level])
352.1425 ++fi
352.1426 + 
352.1427 + AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc],
352.1428 +                                   [Disable XvMC support [[default=yes]]]),
352.1429 +@@ -375,14 +397,12 @@ AC_ARG_ENABLE(ums-only,
352.1430 + required_xorg_server_version=1.6
352.1431 + required_pixman_version=0.16
352.1432 + 
352.1433 +-if pkg-config --exists 'pixman-1 >= 0.27.1'; then
352.1434 +-	AC_DEFINE([HAS_PIXMAN_GLYPHS], 1, [Enable pixman glyph cache])
352.1435 +-fi
352.1436 +-
352.1437 +-if pkg-config --exists 'pixman-1 >= 0.24.0'; then
352.1438 +-	AC_DEFINE([HAS_PIXMAN_TRIANGLES], 1, [Enable pixman triangle rasterisation])
352.1439 +-fi
352.1440 +-
352.1441 ++PKG_CHECK_EXISTS([pixman-1 >= 0.24.0],
352.1442 ++		 AC_DEFINE([HAS_PIXMAN_TRIANGLES], 1, [Enable pixman triangle rasterisation])
352.1443 ++		 [])
352.1444 ++PKG_CHECK_EXISTS([pixman-1 >= 0.27.1],
352.1445 ++		 [AC_DEFINE([HAS_PIXMAN_GLYPHS], 1, [Enable pixman glyph cache])],
352.1446 ++		 [])
352.1447 + # Store the list of server defined optional extensions in REQUIRED_MODULES
352.1448 + XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
352.1449 + XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
352.1450 +@@ -398,24 +418,25 @@ AC_ARG_ENABLE(sna,
352.1451 + 	      [SNA="$enableval"],
352.1452 + 	      [SNA=auto])
352.1453 + 
352.1454 ++AC_CHECK_HEADERS([dev/wscons/wsconsio.h])
352.1455 ++AC_FUNC_ALLOCA
352.1456 ++AC_HEADER_MAJOR
352.1457 ++
352.1458 + if test "x$SNA" != "xno"; then
352.1459 + 	AC_DEFINE(USE_SNA, 1, [Enable SNA support])
352.1460 + 	AC_CHECK_HEADERS([sys/sysinfo.h], AC_CHECK_MEMBERS([struct sysinfo.totalram], [], [], [[#include <sys/sysinfo.h>]]))
352.1461 + fi
352.1462 + 
352.1463 + uxa_requires_libdrm=2.4.52
352.1464 ++uxa_requires_pixman=0.24.0
352.1465 ++
352.1466 + AC_ARG_ENABLE(uxa,
352.1467 + 	      AS_HELP_STRING([--enable-uxa],
352.1468 + 			     [Enable Unified Acceleration Architecture (UXA) [default=auto]]),
352.1469 + 	      [UXA="$enableval"],
352.1470 + 	      [UXA=auto])
352.1471 + if test "x$UXA" = "xauto"; then
352.1472 +-	if ! pkg-config --exists "libdrm_intel >= $uxa_requires_libdrm"; then
352.1473 +-		UXA=no
352.1474 +-	fi
352.1475 +-	if ! pkg-config --exists 'pixman-1 >= 0.24.0'; then
352.1476 +-		UXA=no
352.1477 +-	fi
352.1478 ++	PKG_CHECK_EXISTS([libdrm_intel >= $uxa_requires_libdrm pixman-1 >= $uxa_requires_pixman], [], [UXA=no])
352.1479 + fi
352.1480 + if test "x$UXA" != "xno"; then
352.1481 + 	AC_DEFINE(USE_UXA, 1, [Enable UXA support])
352.1482 +@@ -424,8 +445,10 @@ if test "x$UXA" != "xno"; then
352.1483 + 	UXA=yes
352.1484 + fi
352.1485 + 
352.1486 +-PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
352.1487 ++PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto damageproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
352.1488 + ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server`
352.1489 ++XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server`
352.1490 ++PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1`
352.1491 + 
352.1492 + if test "x$ONLY_UMS" = "xyes"; then
352.1493 + 	UMS="yes"
352.1494 +@@ -519,7 +542,12 @@ AC_MSG_RESULT([$have_dri1])
352.1495 + AM_CONDITIONAL(DRI1, test "x$have_dri1" != "xno")
352.1496 + if test "x$have_dri1" != "xno"; then
352.1497 +         AC_DEFINE(HAVE_DRI1,1,[Enable DRI1 driver support])
352.1498 +-	dri_msg="$dri_msg DRI1"
352.1499 ++	str="DRI1"
352.1500 ++	if test "x$DRI_DEFAULT" = "x1"; then
352.1501 ++		AC_DEFINE(DEFAULT_DRI_LEVEL,1,[Default DRI level])
352.1502 ++		str="*$str"
352.1503 ++	fi
352.1504 ++	dri_msg="$dri_msg $str"
352.1505 + else
352.1506 +         DRI1_CFLAGS=""
352.1507 +         DRI1_LIBS=""
352.1508 +@@ -576,7 +604,12 @@ AM_CONDITIONAL(DRI2, test "x$have_dri2" != "xno")
352.1509 + AC_MSG_RESULT([$have_dri2])
352.1510 + if test "x$have_dri2" != "xno"; then
352.1511 +         AC_DEFINE(HAVE_DRI2,1,[Enable DRI2 driver support])
352.1512 +-	dri_msg="$dri_msg DRI2"
352.1513 ++	str="DRI2"
352.1514 ++	if test "x$DRI_DEFAULT" = "x2"; then
352.1515 ++		AC_DEFINE(DEFAULT_DRI_LEVEL,2,[Default DRI level])
352.1516 ++		str="*$str"
352.1517 ++	fi
352.1518 ++	dri_msg="$dri_msg $str"
352.1519 + else
352.1520 + 	if test "x$DRI" = "xyes" -a "x$DRI2" != "xno" -a "x$KMS" = "xyes"; then
352.1521 + 		AC_MSG_ERROR([DRI2 requested but prerequisites not found])
352.1522 +@@ -591,13 +624,21 @@ AM_CONDITIONAL(DRI3, test "x$have_dri3" != "xno")
352.1523 + AC_MSG_RESULT([$have_dri3])
352.1524 + if test "x$have_dri3" != "xno"; then
352.1525 +         AC_DEFINE(HAVE_DRI3,1,[Enable DRI3 driver support])
352.1526 +-	dri_msg="$dri_msg DRI3"
352.1527 ++	str="DRI3"
352.1528 ++	if test "x$DRI_DEFAULT" = "x3"; then
352.1529 ++		AC_DEFINE(DEFAULT_DRI_LEVEL,3,[Default DRI level])
352.1530 ++		str="*$str"
352.1531 ++	fi
352.1532 ++	dri_msg="$dri_msg $str"
352.1533 + else
352.1534 + 	if test "x$DRI" = "xyes" -a "x$DRI3" != "xno" -a "x$KMS" = "xyes"; then
352.1535 + 		AC_MSG_ERROR([DRI3 requested but prerequisites not found])
352.1536 + 	fi
352.1537 + fi
352.1538 + 
352.1539 ++AC_MSG_CHECKING([default DRI support])
352.1540 ++AC_MSG_RESULT([$DEFAULT_DRI_DEFAULT])
352.1541 ++
352.1542 + AC_CHECK_HEADERS([X11/extensions/dpmsconst.h])
352.1543 + 
352.1544 + PRESENT="no"
352.1545 +@@ -711,27 +752,6 @@ if test "x$TEARFREE" = "xyes"; then
352.1546 + 	xp_msg="$xp_msg TearFree"
352.1547 + fi
352.1548 + 
352.1549 +-AC_ARG_ENABLE(rendernode,
352.1550 +-	      AS_HELP_STRING([--enable-rendernode],
352.1551 +-			     [Enable use of render nodes (experimental) [default=no]]),
352.1552 +-	      [RENDERNODE="$enableval"],
352.1553 +-	      [RENDERNODE="no"])
352.1554 +-AM_CONDITIONAL(USE_RENDERNODE, test "x$RENDERNODE" = "xyes")
352.1555 +-if test "x$RENDERNODE" = "xyes"; then
352.1556 +-	AC_DEFINE(USE_RENDERNODE,1,[Assume "rendernode" support])
352.1557 +-	xp_msg="$xp_msg rendernode"
352.1558 +-fi
352.1559 +-
352.1560 +-AC_ARG_ENABLE(wc-mmap,
352.1561 +-	      AS_HELP_STRING([--enable-wc-mmap],
352.1562 +-			     [Enable use of WriteCombining mmaps [default=no]]),
352.1563 +-	      [WC_MMAP="$enableval"],
352.1564 +-	      [WC_MMAP="no"])
352.1565 +-if test "x$WC_MMAP" = "xyes"; then
352.1566 +-	AC_DEFINE(USE_WC_MMAP,1,[Enable use of WriteCombining mmaps])
352.1567 +-	xp_msg="$xp_msg mmap(wc)"
352.1568 +-fi
352.1569 +-
352.1570 + AC_ARG_ENABLE(create2,
352.1571 + 	      AS_HELP_STRING([--enable-create2],
352.1572 + 			     [Enable use of create2 ioctl (experimental) [default=no]]),
352.1573 +@@ -848,6 +868,7 @@ AC_CONFIG_FILES([
352.1574 +                 xvmc/shader/mc/Makefile
352.1575 +                 xvmc/shader/vld/Makefile
352.1576 + 		test/Makefile
352.1577 ++		benchmarks/Makefile
352.1578 + 		tools/Makefile
352.1579 + 		tools/org.x.xf86-video-intel.backlight-helper.policy
352.1580 + ])
352.1581 +@@ -855,7 +876,7 @@ AC_OUTPUT
352.1582 + 
352.1583 + echo ""
352.1584 + echo ""
352.1585 +-test -e `pwd $0`/README && cat `pwd $0`/README
352.1586 ++cat $srcdir/README
352.1587 + 
352.1588 + accel_msg=""
352.1589 + if test "x$SNA" != "xno"; then
352.1590 +@@ -895,13 +916,15 @@ fi
352.1591 + 
352.1592 + echo ""
352.1593 + echo "AC_PACKAGE_STRING will be compiled with:"
352.1594 +-echo "  Xorg Video ABI version: $ABI_VERSION"
352.1595 ++echo "  Xorg Video ABI version: $ABI_VERSION (xorg-server-$XSERVER_VERSION)"
352.1596 ++echo "  pixman version: pixman-1-$PIXMAN_VERSION"
352.1597 + echo "  Acceleration backends:$accel_msg"
352.1598 + echo "  Additional debugging support?$debug_msg"
352.1599 + echo "  Support for Kernel Mode Setting? $KMS"
352.1600 + echo "  Support for legacy User Mode Setting (for i810)? $UMS"
352.1601 + echo "  Support for Direct Rendering Infrastructure:$dri_msg"
352.1602 + echo "  Support for Xv motion compensation (XvMC and libXvMC):$xvmc_msg"
352.1603 ++echo "  Support for display hotplug notifications (udev):$udev_msg"
352.1604 + echo "  Build additional tools and utilities?$tools_msg"
352.1605 + if test -n "$xp_msg"; then
352.1606 + echo "  Experimental support:$xp_msg"
352.1607 +diff --git a/libobj/alloca.c b/libobj/alloca.c
352.1608 +new file mode 100644
352.1609 +index 00000000..883e1e9f
352.1610 +--- /dev/null
352.1611 ++++ b/libobj/alloca.c
352.1612 +@@ -0,0 +1,4 @@
352.1613 ++void *alloca(size_t sz)
352.1614 ++{
352.1615 ++	return NULL;
352.1616 ++}
352.1617 +diff --git a/man/intel.man b/man/intel.man
352.1618 +index 17515206..be398fbe 100644
352.1619 +--- a/man/intel.man
352.1620 ++++ b/man/intel.man
352.1621 +@@ -27,9 +27,9 @@ supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM,
352.1622 + 865G, 915G, 915GM, 945G, 945GM, 965G, 965Q, 946GZ, 965GM, 945GME,
352.1623 + G33, Q33, Q35, G35, GM45, G45, Q45, G43, G41 chipsets, Pineview-M in
352.1624 + Atom N400 series, Pineview-D in Atom D400/D500 series,
352.1625 +-Intel(R) HD Graphics: 2000-6000,
352.1626 +-Intel(R) Iris(TM) Graphics: 5100/6100, and
352.1627 +-Intel(R) Iris(TM) Pro Graphics: 5200/6200/P6300.
352.1628 ++Intel(R) HD Graphics,
352.1629 ++Intel(R) Iris(TM) Graphics,
352.1630 ++Intel(R) Iris(TM) Pro Graphics.
352.1631 + 
352.1632 + .SH CONFIGURATION DETAILS
352.1633 + Please refer to __xconfigfile__(__filemansuffix__) for general configuration
352.1634 +@@ -112,8 +112,8 @@ The default is 8192 if AGP allocable memory is < 128 MB, 16384 if < 192 MB,
352.1635 + 24576 if higher. DRI require at least a value of 16384. Higher values may give
352.1636 + better 3D performance, at expense of available system memory.
352.1637 + .TP
352.1638 +-.BI "Option \*qNoAccel\*q \*q" boolean \*q
352.1639 +-Disable or enable acceleration.
352.1640 ++.BI "Option \*qAccel\*q \*q" boolean \*q
352.1641 ++Enable or disable acceleration.
352.1642 + .IP
352.1643 + Default: acceleration is enabled.
352.1644 + 
352.1645 +@@ -122,8 +122,8 @@ The following driver
352.1646 + .B Options
352.1647 + are supported for the 830M and later chipsets:
352.1648 + .TP
352.1649 +-.BI "Option \*qNoAccel\*q \*q" boolean \*q
352.1650 +-Disable or enable acceleration.
352.1651 ++.BI "Option \*qAccel\*q \*q" boolean \*q
352.1652 ++Enable or disable acceleration.
352.1653 + .IP
352.1654 + Default: acceleration is enabled.
352.1655 + .TP
352.1656 +@@ -201,6 +201,16 @@ that choice by specifying the entry under /sys/class/backlight to use.
352.1657 + .IP
352.1658 + Default: Automatic selection.
352.1659 + .TP
352.1660 ++.BI "Option \*qCustomEDID\*q \*q" string \*q
352.1661 ++Override the probed EDID on particular outputs. Sometimes the manufacturer
352.1662 ++supplied EDID is corrupt or lacking a few usable modes and supplying a
352.1663 ++corrected EDID may be easier than specifying every modeline. This option
352.1664 ++allows to pass the path to load an EDID from per output. The format is a
352.1665 ++comma separated string of output:path pairs, e.g.
352.1666 ++DP1:/path/to/dp1.edid,DP2:/path/to/dp2.edid
352.1667 ++.IP
352.1668 ++Default: No override, use manufacturer supplied EDIDs.
352.1669 ++.TP
352.1670 + .BI "Option \*qFallbackDebug\*q \*q" boolean \*q
352.1671 + Enable printing of debugging information on acceleration fallbacks to the
352.1672 + server log.
352.1673 +@@ -225,6 +235,15 @@ i.e. perform synchronous rendering.
352.1674 + .IP
352.1675 + Default: Disabled
352.1676 + .TP
352.1677 ++.BI "Option \*qHWRotation\*q \*q" boolean \*q
352.1678 ++Override the use of native hardware rotation and force the use of software,
352.1679 ++but GPU accelerated where possible, rotation. On some platforms the hardware
352.1680 ++can scanout directly into a rotated output bypassing the intermediate rendering
352.1681 ++and extra allocations required for software implemented rotation (i.e. native
352.1682 ++rotation uses less resources, is quicker and uses less power). This allows you
352.1683 ++to disable the native rotation in case of errors.
352.1684 ++.IP
352.1685 ++Default: Enabled (use hardware rotation)
352.1686 + .TP
352.1687 + .BI "Option \*qVSync\*q \*q" boolean \*q
352.1688 + This option controls the use of commands to synchronise rendering with the
352.1689 +@@ -324,13 +343,29 @@ Default: 0
352.1690 + .BI "Option \*qZaphodHeads\*q \*q" string \*q
352.1691 + .IP
352.1692 + Specify the randr output(s) to use with zaphod mode for a particular driver
352.1693 +-instance.  If you this option you must use it with all instances of the
352.1694 +-driver
352.1695 ++instance.  If you set this option you must use it with all instances of the
352.1696 ++driver. By default, each head is assigned only one CRTC (which limits
352.1697 ++using multiple outputs with that head to cloned mode). CRTC can be manually
352.1698 ++assigned to individual heads by preceding the output names with a comma
352.1699 ++delimited list of pipe numbers followed by a colon. Note that different pipes
352.1700 ++may be limited in their functionality and some outputs may only work with
352.1701 ++different pipes.
352.1702 + .br
352.1703 + For example:
352.1704 ++
352.1705 ++.RS
352.1706 + .B
352.1707 + Option \*qZaphodHeads\*q \*qLVDS1,VGA1\*q
352.1708 +-will assign xrandr outputs LVDS1 and VGA0 to this instance of the driver.
352.1709 ++
352.1710 ++will assign xrandr outputs LVDS1 and VGA1 to this instance of the driver.
352.1711 ++.RE
352.1712 ++
352.1713 ++.RS
352.1714 ++.B
352.1715 ++Option \*qZaphodHeads\*q \*q0,2:HDMI1,DP2\*q
352.1716 ++
352.1717 ++will assign xrandr outputs HDMI1 and DP2 and CRTCs 0 and 2 to this instance of the driver.
352.1718 ++.RE
352.1719 + 
352.1720 + .SH OUTPUT CONFIGURATION
352.1721 + On 830M and better chipsets, the driver supports runtime configuration of
352.1722 +@@ -431,11 +466,11 @@ First DVI SDVO output
352.1723 + Second DVI SDVO output
352.1724 + 
352.1725 + .SS "TMDS-1", "TMDS-2", "HDMI-1", "HDMI-2"
352.1726 +-DVI/HDMI outputs. Avaliable common properties include:
352.1727 ++DVI/HDMI outputs. Available common properties include:
352.1728 + .TP
352.1729 + \fBBROADCAST_RGB\fP - method used to set RGB color range
352.1730 + Adjusting this property allows you to set RGB color range on each
352.1731 +-channel in order to match HDTV requirment(default 0 for full
352.1732 ++channel in order to match HDTV requirement(default 0 for full
352.1733 + range). Setting 1 means RGB color range is 16-235, 0 means RGB color
352.1734 + range is 0-255 on each channel.  (Full range is 0-255, not 16-235)
352.1735 + 
352.1736 +diff --git a/src/backlight.c b/src/backlight.c
352.1737 +index 9f239867..fcbb279f 100644
352.1738 +--- a/src/backlight.c
352.1739 ++++ b/src/backlight.c
352.1740 +@@ -34,6 +34,12 @@
352.1741 + #include <sys/stat.h>
352.1742 + #include <sys/ioctl.h>
352.1743 + 
352.1744 ++#if MAJOR_IN_MKDEV
352.1745 ++#include <sys/mkdev.h>
352.1746 ++#elif MAJOR_IN_SYSMACROS
352.1747 ++#include <sys/sysmacros.h>
352.1748 ++#endif
352.1749 ++
352.1750 + #include <stdio.h>
352.1751 + #include <stdlib.h>
352.1752 + #include <string.h>
352.1753 +@@ -42,6 +48,7 @@
352.1754 + #include <fcntl.h>
352.1755 + #include <unistd.h>
352.1756 + #include <dirent.h>
352.1757 ++#include <errno.h>
352.1758 + 
352.1759 + #include <xorg-server.h>
352.1760 + #include <xf86.h>
352.1761 +@@ -84,7 +91,7 @@ void backlight_init(struct backlight *b)
352.1762 + 	b->has_power = 0;
352.1763 + }
352.1764 + 
352.1765 +-#ifdef __OpenBSD__
352.1766 ++#ifdef HAVE_DEV_WSCONS_WSCONSIO_H
352.1767 + 
352.1768 + #include <dev/wscons/wsconsio.h>
352.1769 + #include <xf86Priv.h>
352.1770 +@@ -122,6 +129,11 @@ int backlight_get(struct backlight *b)
352.1771 + 	return param.curval;
352.1772 + }
352.1773 + 
352.1774 ++char *backlight_find_for_device(struct pci_device *pci)
352.1775 ++{
352.1776 ++	return NULL;
352.1777 ++}
352.1778 ++
352.1779 + int backlight_open(struct backlight *b, char *iface)
352.1780 + {
352.1781 + 	struct wsdisplay_param param;
352.1782 +@@ -146,12 +158,9 @@ int backlight_open(struct backlight *b, char *iface)
352.1783 + 	return param.curval;
352.1784 + }
352.1785 + 
352.1786 +-enum backlight_type backlight_exists(const char *iface)
352.1787 ++int backlight_exists(const char *iface)
352.1788 + {
352.1789 +-	if (iface != NULL)
352.1790 +-		return BL_NONE;
352.1791 +-
352.1792 +-	return BL_PLATFORM;
352.1793 ++	return iface == NULL;
352.1794 + }
352.1795 + 
352.1796 + int backlight_on(struct backlight *b)
352.1797 +@@ -163,6 +172,7 @@ int backlight_off(struct backlight *b)
352.1798 + {
352.1799 + 	return 0;
352.1800 + }
352.1801 ++
352.1802 + #else
352.1803 + 
352.1804 + static int
352.1805 +@@ -213,6 +223,24 @@ __backlight_read(const char *iface, const char *file)
352.1806 + }
352.1807 + 
352.1808 + static int
352.1809 ++writen(int fd, const char *value, int len)
352.1810 ++{
352.1811 ++	int ret;
352.1812 ++
352.1813 ++	do {
352.1814 ++		ret = write(fd, value, len);
352.1815 ++		if (ret < 0) {
352.1816 ++			if (errno == EAGAIN || errno == EINTR)
352.1817 ++				continue;
352.1818 ++
352.1819 ++			return ret;
352.1820 ++		}
352.1821 ++	} while (value += ret, len -= ret);
352.1822 ++
352.1823 ++	return 0;
352.1824 ++}
352.1825 ++
352.1826 ++static int
352.1827 + __backlight_write(const char *iface, const char *file, const char *value)
352.1828 + {
352.1829 + 	int fd, ret;
352.1830 +@@ -221,7 +249,7 @@ __backlight_write(const char *iface, const char *file, const char *value)
352.1831 + 	if (fd < 0)
352.1832 + 		return -1;
352.1833 + 
352.1834 +-	ret = write(fd, value, strlen(value)+1);
352.1835 ++	ret = writen(fd, value, strlen(value)+1);
352.1836 + 	close(fd);
352.1837 + 
352.1838 + 	return ret;
352.1839 +@@ -244,10 +272,10 @@ static const char *known_interfaces[] = {
352.1840 + 	"intel_backlight",
352.1841 + };
352.1842 + 
352.1843 +-static enum backlight_type __backlight_type(const char *iface)
352.1844 ++static int __backlight_type(const char *iface)
352.1845 + {
352.1846 + 	char buf[1024];
352.1847 +-	int fd, v;
352.1848 ++	int fd, v, i;
352.1849 + 
352.1850 + 	v = -1;
352.1851 + 	fd = __backlight_open(iface, "type", O_RDONLY);
352.1852 +@@ -261,39 +289,41 @@ static enum backlight_type __backlight_type(const char *iface)
352.1853 + 		buf[v] = '\0';
352.1854 + 
352.1855 + 		if (strcmp(buf, "raw") == 0)
352.1856 +-			v = BL_RAW;
352.1857 ++			v = BL_RAW << 8;
352.1858 + 		else if (strcmp(buf, "platform") == 0)
352.1859 +-			v = BL_PLATFORM;
352.1860 ++			v = BL_PLATFORM << 8;
352.1861 + 		else if (strcmp(buf, "firmware") == 0)
352.1862 +-			v = BL_FIRMWARE;
352.1863 ++			v = BL_FIRMWARE << 8;
352.1864 + 		else
352.1865 +-			v = BL_NAMED;
352.1866 ++			v = BL_NAMED << 8;
352.1867 + 	} else
352.1868 +-		v = BL_NAMED;
352.1869 ++		v = BL_NAMED << 8;
352.1870 + 
352.1871 +-	if (v == BL_NAMED) {
352.1872 +-		int i;
352.1873 +-		for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
352.1874 +-			if (strcmp(iface, known_interfaces[i]) == 0)
352.1875 +-				break;
352.1876 +-		}
352.1877 +-		v += i;
352.1878 ++	for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
352.1879 ++		if (strcmp(iface, known_interfaces[i]) == 0)
352.1880 ++			break;
352.1881 + 	}
352.1882 ++	v += i;
352.1883 + 
352.1884 + 	return v;
352.1885 + }
352.1886 + 
352.1887 +-enum backlight_type backlight_exists(const char *iface)
352.1888 ++static int __backlight_exists(const char *iface)
352.1889 + {
352.1890 + 	if (__backlight_read(iface, "brightness") < 0)
352.1891 +-		return BL_NONE;
352.1892 ++		return -1;
352.1893 + 
352.1894 + 	if (__backlight_read(iface, "max_brightness") <= 0)
352.1895 +-		return BL_NONE;
352.1896 ++		return -1;
352.1897 + 
352.1898 + 	return __backlight_type(iface);
352.1899 + }
352.1900 + 
352.1901 ++int backlight_exists(const char *iface)
352.1902 ++{
352.1903 ++	return __backlight_exists(iface) != -1;
352.1904 ++}
352.1905 ++
352.1906 + static int __backlight_init(struct backlight *b, char *iface, int fd)
352.1907 + {
352.1908 + 	b->fd = fd_move_cloexec(fd_set_nonblock(fd));
352.1909 +@@ -399,7 +429,50 @@ __backlight_find(void)
352.1910 + 			continue;
352.1911 + 
352.1912 + 		/* Fallback to priority list of known iface for old kernels */
352.1913 +-		v = backlight_exists(de->d_name);
352.1914 ++		v = __backlight_exists(de->d_name);
352.1915 ++		if (v < 0)
352.1916 ++			continue;
352.1917 ++
352.1918 ++		if (v < best_type) {
352.1919 ++			char *copy = strdup(de->d_name);
352.1920 ++			if (copy) {
352.1921 ++				free(best_iface);
352.1922 ++				best_iface = copy;
352.1923 ++				best_type = v;
352.1924 ++			}
352.1925 ++		}
352.1926 ++	}
352.1927 ++	closedir(dir);
352.1928 ++
352.1929 ++	return best_iface;
352.1930 ++}
352.1931 ++
352.1932 ++char *backlight_find_for_device(struct pci_device *pci)
352.1933 ++{
352.1934 ++	char path[200];
352.1935 ++	unsigned best_type = INT_MAX;
352.1936 ++	char *best_iface = NULL;
352.1937 ++	DIR *dir;
352.1938 ++	struct dirent *de;
352.1939 ++
352.1940 ++	snprintf(path, sizeof(path),
352.1941 ++		 "/sys/bus/pci/devices/%04x:%02x:%02x.%d/backlight",
352.1942 ++		 pci->domain, pci->bus, pci->dev, pci->func);
352.1943 ++
352.1944 ++	dir = opendir(path);
352.1945 ++	if (dir == NULL)
352.1946 ++		return NULL;
352.1947 ++
352.1948 ++	while ((de = readdir(dir))) {
352.1949 ++		int v;
352.1950 ++
352.1951 ++		if (*de->d_name == '.')
352.1952 ++			continue;
352.1953 ++
352.1954 ++		v = __backlight_exists(de->d_name);
352.1955 ++		if (v < 0)
352.1956 ++			continue;
352.1957 ++
352.1958 + 		if (v < best_type) {
352.1959 + 			char *copy = strdup(de->d_name);
352.1960 + 			if (copy) {
352.1961 +@@ -416,14 +489,17 @@ __backlight_find(void)
352.1962 + 
352.1963 + int backlight_open(struct backlight *b, char *iface)
352.1964 + {
352.1965 +-	int level;
352.1966 ++	int level, type;
352.1967 + 
352.1968 + 	if (iface == NULL)
352.1969 + 		iface = __backlight_find();
352.1970 + 	if (iface == NULL)
352.1971 + 		goto err;
352.1972 + 
352.1973 +-	b->type = __backlight_type(iface);
352.1974 ++	type = __backlight_type(iface);
352.1975 ++	if (type < 0)
352.1976 ++		goto err;
352.1977 ++	b->type = type >> 8;
352.1978 + 
352.1979 + 	b->max = __backlight_read(iface, "max_brightness");
352.1980 + 	if (b->max <= 0)
352.1981 +@@ -447,7 +523,7 @@ err:
352.1982 + int backlight_set(struct backlight *b, int level)
352.1983 + {
352.1984 + 	char val[BACKLIGHT_VALUE_LEN];
352.1985 +-	int len, ret = 0;
352.1986 ++	int len;
352.1987 + 
352.1988 + 	if (b->iface == NULL)
352.1989 + 		return 0;
352.1990 +@@ -456,10 +532,7 @@ int backlight_set(struct backlight *b, int level)
352.1991 + 		level = b->max;
352.1992 + 
352.1993 + 	len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level);
352.1994 +-	if (write(b->fd, val, len) != len)
352.1995 +-		ret = -1;
352.1996 +-
352.1997 +-	return ret;
352.1998 ++	return writen(b->fd, val, len);
352.1999 + }
352.2000 + 
352.2001 + int backlight_get(struct backlight *b)
352.2002 +@@ -517,43 +590,6 @@ void backlight_disable(struct backlight *b)
352.2003 + void backlight_close(struct backlight *b)
352.2004 + {
352.2005 + 	backlight_disable(b);
352.2006 +-	if (b->pid)
352.2007 ++	if (b->pid > 0)
352.2008 + 		waitpid(b->pid, NULL, 0);
352.2009 + }
352.2010 +-
352.2011 +-char *backlight_find_for_device(struct pci_device *pci)
352.2012 +-{
352.2013 +-	char path[200];
352.2014 +-	unsigned best_type = INT_MAX;
352.2015 +-	char *best_iface = NULL;
352.2016 +-	DIR *dir;
352.2017 +-	struct dirent *de;
352.2018 +-
352.2019 +-	snprintf(path, sizeof(path),
352.2020 +-		 "/sys/bus/pci/devices/%04x:%02x:%02x.%d/backlight",
352.2021 +-		 pci->domain, pci->bus, pci->dev, pci->func);
352.2022 +-
352.2023 +-	dir = opendir(path);
352.2024 +-	if (dir == NULL)
352.2025 +-		return NULL;
352.2026 +-
352.2027 +-	while ((de = readdir(dir))) {
352.2028 +-		int v;
352.2029 +-
352.2030 +-		if (*de->d_name == '.')
352.2031 +-			continue;
352.2032 +-
352.2033 +-		v = backlight_exists(de->d_name);
352.2034 +-		if (v < best_type) {
352.2035 +-			char *copy = strdup(de->d_name);
352.2036 +-			if (copy) {
352.2037 +-				free(best_iface);
352.2038 +-				best_iface = copy;
352.2039 +-				best_type = v;
352.2040 +-			}
352.2041 +-		}
352.2042 +-	}
352.2043 +-	closedir(dir);
352.2044 +-
352.2045 +-	return best_iface;
352.2046 +-}
352.2047 +diff --git a/src/backlight.h b/src/backlight.h
352.2048 +index bb0e28bc..ba17755b 100644
352.2049 +--- a/src/backlight.h
352.2050 ++++ b/src/backlight.h
352.2051 +@@ -43,7 +43,7 @@ struct backlight {
352.2052 + 	int pid, fd;
352.2053 + };
352.2054 + 
352.2055 +-enum backlight_type backlight_exists(const char *iface);
352.2056 ++int backlight_exists(const char *iface);
352.2057 + 
352.2058 + void backlight_init(struct backlight *backlight);
352.2059 + int backlight_open(struct backlight *backlight, char *iface);
352.2060 +diff --git a/src/compat-api.h b/src/compat-api.h
352.2061 +index d09e1fb3..05797a08 100644
352.2062 +--- a/src/compat-api.h
352.2063 ++++ b/src/compat-api.h
352.2064 +@@ -30,6 +30,7 @@
352.2065 + 
352.2066 + #include <xorg-server.h>
352.2067 + #include <xorgVersion.h>
352.2068 ++#include <xf86Module.h>
352.2069 + 
352.2070 + #include <picturestr.h>
352.2071 + #ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR
352.2072 +@@ -39,7 +40,17 @@
352.2073 + 
352.2074 + #ifndef XF86_HAS_SCRN_CONV
352.2075 + #define xf86ScreenToScrn(s) xf86Screens[(s)->myNum]
352.2076 ++#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,1,0,0,0)
352.2077 + #define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex]
352.2078 ++#else
352.2079 ++#define xf86ScrnToScreen(s) ((s)->pScreen)
352.2080 ++#endif
352.2081 ++#else
352.2082 ++#define xf86ScrnToScreen(s) ((s)->pScreen)
352.2083 ++#endif
352.2084 ++
352.2085 ++#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22
352.2086 ++#define HAVE_NOTIFY_FD 1
352.2087 + #endif
352.2088 + 
352.2089 + #ifndef XF86_SCRN_INTERFACE
352.2090 +@@ -131,6 +142,17 @@ region_rects(const RegionRec *r)
352.2091 + 	return r->data ? (const BoxRec *)(r->data + 1) :  &r->extents;
352.2092 + }
352.2093 + 
352.2094 ++inline static void
352.2095 ++region_get_boxes(const RegionRec *r, const BoxRec **s, const BoxRec **e)
352.2096 ++{
352.2097 ++	int n;
352.2098 ++	if (r->data)
352.2099 ++		*s = region_boxptr(r), n = r->data->numRects;
352.2100 ++	else
352.2101 ++		*s = &r->extents, n = 1;
352.2102 ++	*e = *s + n;
352.2103 ++}
352.2104 ++
352.2105 + #ifndef INCLUDE_LEGACY_REGION_DEFINES
352.2106 + #define RegionCreate(r, s) REGION_CREATE(NULL, r, s)
352.2107 + #define RegionBreak(r) REGION_BREAK(NULL, r)
352.2108 +@@ -223,4 +245,19 @@ static inline void FreePixmap(PixmapPtr pixmap)
352.2109 + 			  dstx, dsty)
352.2110 + #endif
352.2111 + 
352.2112 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
352.2113 ++#define isGPU(S) (S)->is_gpu
352.2114 ++#else
352.2115 ++#define isGPU(S) 0
352.2116 ++#endif
352.2117 ++
352.2118 ++#if HAS_DIRTYTRACKING_ROTATION
352.2119 ++#define PixmapSyncDirtyHelper(d, dd) PixmapSyncDirtyHelper(d)
352.2120 ++#endif
352.2121 ++
352.2122 ++#if !HAVE_NOTIFY_FD
352.2123 ++#define SetNotifyFd(fd, cb, mode, data) AddGeneralSocket(fd);
352.2124 ++#define RemoveNotifyFd(fd) RemoveGeneralSocket(fd)
352.2125 ++#endif
352.2126 ++
352.2127 + #endif
352.2128 +diff --git a/src/i915_pciids.h b/src/i915_pciids.h
352.2129 +index 180ad0e6..466c7159 100644
352.2130 +--- a/src/i915_pciids.h
352.2131 ++++ b/src/i915_pciids.h
352.2132 +@@ -134,7 +134,7 @@
352.2133 + #define INTEL_IVB_Q_IDS(info) \
352.2134 + 	INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */
352.2135 + 
352.2136 +-#define INTEL_HSW_D_IDS(info) \
352.2137 ++#define INTEL_HSW_IDS(info) \
352.2138 + 	INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \
352.2139 + 	INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \
352.2140 + 	INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \
352.2141 +@@ -179,9 +179,7 @@
352.2142 + 	INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \
352.2143 + 	INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \
352.2144 + 	INTEL_VGA_DEVICE(0x0D1E, info), /* CRW GT2 reserved */ \
352.2145 +-	INTEL_VGA_DEVICE(0x0D2E, info)  /* CRW GT3 reserved */ \
352.2146 +-
352.2147 +-#define INTEL_HSW_M_IDS(info) \
352.2148 ++	INTEL_VGA_DEVICE(0x0D2E, info),  /* CRW GT3 reserved */ \
352.2149 + 	INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \
352.2150 + 	INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \
352.2151 + 	INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \
352.2152 +@@ -198,60 +196,48 @@
352.2153 + 	INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \
352.2154 + 	INTEL_VGA_DEVICE(0x0D26, info)  /* CRW GT3 mobile */
352.2155 + 
352.2156 +-#define INTEL_VLV_M_IDS(info) \
352.2157 ++#define INTEL_VLV_IDS(info) \
352.2158 + 	INTEL_VGA_DEVICE(0x0f30, info), \
352.2159 + 	INTEL_VGA_DEVICE(0x0f31, info), \
352.2160 + 	INTEL_VGA_DEVICE(0x0f32, info), \
352.2161 + 	INTEL_VGA_DEVICE(0x0f33, info), \
352.2162 +-	INTEL_VGA_DEVICE(0x0157, info)
352.2163 +-
352.2164 +-#define INTEL_VLV_D_IDS(info) \
352.2165 ++	INTEL_VGA_DEVICE(0x0157, info), \
352.2166 + 	INTEL_VGA_DEVICE(0x0155, info)
352.2167 + 
352.2168 +-#define _INTEL_BDW_M(gt, id, info) \
352.2169 +-	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info)
352.2170 +-#define _INTEL_BDW_D(gt, id, info) \
352.2171 +-	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info)
352.2172 +-
352.2173 +-#define _INTEL_BDW_M_IDS(gt, info) \
352.2174 +-	_INTEL_BDW_M(gt, 0x1602, info), /* ULT */ \
352.2175 +-	_INTEL_BDW_M(gt, 0x1606, info), /* ULT */ \
352.2176 +-	_INTEL_BDW_M(gt, 0x160B, info), /* Iris */ \
352.2177 +-	_INTEL_BDW_M(gt, 0x160E, info) /* ULX */
352.2178 +-
352.2179 +-#define _INTEL_BDW_D_IDS(gt, info) \
352.2180 +-	_INTEL_BDW_D(gt, 0x160A, info), /* Server */ \
352.2181 +-	_INTEL_BDW_D(gt, 0x160D, info) /* Workstation */
352.2182 +-
352.2183 +-#define INTEL_BDW_GT12M_IDS(info) \
352.2184 +-	_INTEL_BDW_M_IDS(1, info), \
352.2185 +-	_INTEL_BDW_M_IDS(2, info)
352.2186 +-
352.2187 +-#define INTEL_BDW_GT12D_IDS(info) \
352.2188 +-	_INTEL_BDW_D_IDS(1, info), \
352.2189 +-	_INTEL_BDW_D_IDS(2, info)
352.2190 +-
352.2191 +-#define INTEL_BDW_GT3M_IDS(info) \
352.2192 +-	_INTEL_BDW_M_IDS(3, info)
352.2193 +-
352.2194 +-#define INTEL_BDW_GT3D_IDS(info) \
352.2195 +-	_INTEL_BDW_D_IDS(3, info)
352.2196 +-
352.2197 +-#define INTEL_BDW_RSVDM_IDS(info) \
352.2198 +-	_INTEL_BDW_M_IDS(4, info)
352.2199 +-
352.2200 +-#define INTEL_BDW_RSVDD_IDS(info) \
352.2201 +-	_INTEL_BDW_D_IDS(4, info)
352.2202 +-
352.2203 +-#define INTEL_BDW_M_IDS(info) \
352.2204 +-	INTEL_BDW_GT12M_IDS(info), \
352.2205 +-	INTEL_BDW_GT3M_IDS(info), \
352.2206 +-	INTEL_BDW_RSVDM_IDS(info)
352.2207 +-
352.2208 +-#define INTEL_BDW_D_IDS(info) \
352.2209 +-	INTEL_BDW_GT12D_IDS(info), \
352.2210 +-	INTEL_BDW_GT3D_IDS(info), \
352.2211 +-	INTEL_BDW_RSVDD_IDS(info)
352.2212 ++#define INTEL_BDW_GT12_IDS(info)  \
352.2213 ++	INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
352.2214 ++	INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \
352.2215 ++	INTEL_VGA_DEVICE(0x160B, info), /* GT1 Iris */ \
352.2216 ++	INTEL_VGA_DEVICE(0x160E, info), /* GT1 ULX */ \
352.2217 ++	INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */ \
352.2218 ++	INTEL_VGA_DEVICE(0x1616, info), /* GT2 ULT */ \
352.2219 ++	INTEL_VGA_DEVICE(0x161B, info), /* GT2 ULT */ \
352.2220 ++	INTEL_VGA_DEVICE(0x161E, info),  /* GT2 ULX */ \
352.2221 ++	INTEL_VGA_DEVICE(0x160A, info), /* GT1 Server */ \
352.2222 ++	INTEL_VGA_DEVICE(0x160D, info), /* GT1 Workstation */ \
352.2223 ++	INTEL_VGA_DEVICE(0x161A, info), /* GT2 Server */ \
352.2224 ++	INTEL_VGA_DEVICE(0x161D, info)  /* GT2 Workstation */
352.2225 ++
352.2226 ++#define INTEL_BDW_GT3_IDS(info) \
352.2227 ++	INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \
352.2228 ++	INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \
352.2229 ++	INTEL_VGA_DEVICE(0x162B, info), /* Iris */ \
352.2230 ++	INTEL_VGA_DEVICE(0x162E, info),  /* ULX */\
352.2231 ++	INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
352.2232 ++	INTEL_VGA_DEVICE(0x162D, info)  /* Workstation */
352.2233 ++
352.2234 ++#define INTEL_BDW_RSVD_IDS(info) \
352.2235 ++	INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
352.2236 ++	INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
352.2237 ++	INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
352.2238 ++	INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
352.2239 ++	INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
352.2240 ++	INTEL_VGA_DEVICE(0x163D, info)  /* Workstation */
352.2241 ++
352.2242 ++#define INTEL_BDW_IDS(info) \
352.2243 ++	INTEL_BDW_GT12_IDS(info), \
352.2244 ++	INTEL_BDW_GT3_IDS(info), \
352.2245 ++	INTEL_BDW_RSVD_IDS(info)
352.2246 + 
352.2247 + #define INTEL_CHV_IDS(info) \
352.2248 + 	INTEL_VGA_DEVICE(0x22b0, info), \
352.2249 +@@ -259,21 +245,85 @@
352.2250 + 	INTEL_VGA_DEVICE(0x22b2, info), \
352.2251 + 	INTEL_VGA_DEVICE(0x22b3, info)
352.2252 + 
352.2253 +-#define INTEL_SKL_IDS(info) \
352.2254 +-	INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
352.2255 ++#define INTEL_SKL_GT1_IDS(info)	\
352.2256 + 	INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */ \
352.2257 +-	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
352.2258 +-	INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
352.2259 + 	INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */ \
352.2260 ++	INTEL_VGA_DEVICE(0x1902, info), /* DT  GT1 */ \
352.2261 ++	INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
352.2262 ++	INTEL_VGA_DEVICE(0x190A, info) /* SRV GT1 */
352.2263 ++
352.2264 ++#define INTEL_SKL_GT2_IDS(info)	\
352.2265 ++	INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
352.2266 ++	INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
352.2267 + 	INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */ \
352.2268 + 	INTEL_VGA_DEVICE(0x1912, info), /* DT  GT2 */ \
352.2269 +-	INTEL_VGA_DEVICE(0x1902, info), /* DT  GT1 */ \
352.2270 + 	INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */ \
352.2271 +-	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
352.2272 +-	INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
352.2273 + 	INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */ \
352.2274 +-	INTEL_VGA_DEVICE(0x192A, info), /* SRV GT3 */ \
352.2275 +-	INTEL_VGA_DEVICE(0x190A, info), /* SRV GT1 */ \
352.2276 + 	INTEL_VGA_DEVICE(0x191D, info)  /* WKS GT2 */
352.2277 + 
352.2278 ++#define INTEL_SKL_GT3_IDS(info) \
352.2279 ++	INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
352.2280 ++	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
352.2281 ++	INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
352.2282 ++	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
352.2283 ++	INTEL_VGA_DEVICE(0x192D, info)  /* SRV GT3 */
352.2284 ++
352.2285 ++#define INTEL_SKL_GT4_IDS(info) \
352.2286 ++	INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \
352.2287 ++	INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \
352.2288 ++	INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \
352.2289 ++	INTEL_VGA_DEVICE(0x192A, info), /* SRV GT4 */ \
352.2290 ++	INTEL_VGA_DEVICE(0x193A, info)  /* SRV GT4e */
352.2291 ++
352.2292 ++#define INTEL_SKL_IDS(info)	 \
352.2293 ++	INTEL_SKL_GT1_IDS(info), \
352.2294 ++	INTEL_SKL_GT2_IDS(info), \
352.2295 ++	INTEL_SKL_GT3_IDS(info), \
352.2296 ++	INTEL_SKL_GT4_IDS(info)
352.2297 ++
352.2298 ++#define INTEL_BXT_IDS(info) \
352.2299 ++	INTEL_VGA_DEVICE(0x0A84, info), \
352.2300 ++	INTEL_VGA_DEVICE(0x1A84, info), \
352.2301 ++	INTEL_VGA_DEVICE(0x1A85, info), \
352.2302 ++	INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \
352.2303 ++	INTEL_VGA_DEVICE(0x5A85, info)  /* APL HD Graphics 500 */
352.2304 ++
352.2305 ++#define INTEL_GLK_IDS(info) \
352.2306 ++	INTEL_VGA_DEVICE(0x3184, info), \
352.2307 ++	INTEL_VGA_DEVICE(0x3185, info)
352.2308 ++
352.2309 ++#define INTEL_KBL_GT1_IDS(info)	\
352.2310 ++	INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
352.2311 ++	INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
352.2312 ++	INTEL_VGA_DEVICE(0x5917, info), /* DT  GT1.5 */ \
352.2313 ++	INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
352.2314 ++	INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
352.2315 ++	INTEL_VGA_DEVICE(0x5902, info), /* DT  GT1 */ \
352.2316 ++	INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */ \
352.2317 ++	INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
352.2318 ++	INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
352.2319 ++
352.2320 ++#define INTEL_KBL_GT2_IDS(info)	\
352.2321 ++	INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
352.2322 ++	INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
352.2323 ++	INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
352.2324 ++	INTEL_VGA_DEVICE(0x5912, info), /* DT  GT2 */ \
352.2325 ++	INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
352.2326 ++	INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
352.2327 ++	INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
352.2328 ++
352.2329 ++#define INTEL_KBL_GT3_IDS(info) \
352.2330 ++	INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */ \
352.2331 ++	INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
352.2332 ++	INTEL_VGA_DEVICE(0x5927, info) /* ULT GT3 */
352.2333 ++
352.2334 ++#define INTEL_KBL_GT4_IDS(info) \
352.2335 ++	INTEL_VGA_DEVICE(0x593B, info) /* Halo GT4 */
352.2336 ++
352.2337 ++#define INTEL_KBL_IDS(info) \
352.2338 ++	INTEL_KBL_GT1_IDS(info), \
352.2339 ++	INTEL_KBL_GT2_IDS(info), \
352.2340 ++	INTEL_KBL_GT3_IDS(info), \
352.2341 ++	INTEL_KBL_GT4_IDS(info)
352.2342 ++
352.2343 + #endif /* _I915_PCIIDS_H */
352.2344 +diff --git a/src/intel_device.c b/src/intel_device.c
352.2345 +index 140e1536..c4910cd8 100644
352.2346 +--- a/src/intel_device.c
352.2347 ++++ b/src/intel_device.c
352.2348 +@@ -38,6 +38,12 @@
352.2349 + #include <dirent.h>
352.2350 + #include <errno.h>
352.2351 + 
352.2352 ++#if MAJOR_IN_MKDEV
352.2353 ++#include <sys/mkdev.h>
352.2354 ++#elif MAJOR_IN_SYSMACROS
352.2355 ++#include <sys/sysmacros.h>
352.2356 ++#endif
352.2357 ++
352.2358 + #include <pciaccess.h>
352.2359 + 
352.2360 + #include <xorg-server.h>
352.2361 +@@ -197,9 +203,15 @@ static inline struct intel_device *intel_device(ScrnInfoPtr scrn)
352.2362 + 	return xf86GetEntityPrivate(scrn->entityList[0], intel_device_key)->ptr;
352.2363 + }
352.2364 + 
352.2365 ++static const char *kernel_module_names[] ={
352.2366 ++	"i915",
352.2367 ++	NULL,
352.2368 ++};
352.2369 ++
352.2370 + static int is_i915_device(int fd)
352.2371 + {
352.2372 + 	drm_version_t version;
352.2373 ++	const char **kn;
352.2374 + 	char name[5] = "";
352.2375 + 
352.2376 + 	memset(&version, 0, sizeof(version));
352.2377 +@@ -209,7 +221,22 @@ static int is_i915_device(int fd)
352.2378 + 	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
352.2379 + 		return 0;
352.2380 + 
352.2381 +-	return strcmp("i915", name) == 0;
352.2382 ++	for (kn = kernel_module_names; *kn; kn++)
352.2383 ++		if (strcmp(*kn, name) == 0)
352.2384 ++			return 1;
352.2385 ++
352.2386 ++	return 0;
352.2387 ++}
352.2388 ++
352.2389 ++static int load_i915_kernel_module(void)
352.2390 ++{
352.2391 ++	const char **kn;
352.2392 ++
352.2393 ++	for (kn = kernel_module_names; *kn; kn++)
352.2394 ++		if (xf86LoadKernelModule(*kn))
352.2395 ++			return 0;
352.2396 ++
352.2397 ++	return -1;
352.2398 + }
352.2399 + 
352.2400 + static int is_i915_gem(int fd)
352.2401 +@@ -336,7 +363,7 @@ static int __intel_open_device__pci(const struct pci_device *pci)
352.2402 + 
352.2403 + 		sprintf(path + base, "driver");
352.2404 + 		if (stat(path, &st)) {
352.2405 +-			if (xf86LoadKernelModule("i915"))
352.2406 ++			if (load_i915_kernel_module())
352.2407 + 				return -1;
352.2408 + 			(void)xf86LoadKernelModule("fbcon");
352.2409 + 		}
352.2410 +@@ -399,7 +426,7 @@ static int __intel_open_device__legacy(const struct pci_device *pci)
352.2411 + 
352.2412 + 	ret = drmCheckModesettingSupported(id);
352.2413 + 	if (ret) {
352.2414 +-		if (xf86LoadKernelModule("i915"))
352.2415 ++		if (load_i915_kernel_module() == 0)
352.2416 + 			ret = drmCheckModesettingSupported(id);
352.2417 + 		if (ret)
352.2418 + 			return -1;
352.2419 +@@ -461,9 +488,9 @@ static int is_render_node(int fd, struct stat *st)
352.2420 + 
352.2421 + static char *find_render_node(int fd)
352.2422 + {
352.2423 +-#if defined(USE_RENDERNODE)
352.2424 + 	struct stat master, render;
352.2425 + 	char buf[128];
352.2426 ++	int i;
352.2427 + 
352.2428 + 	/* Are we a render-node ourselves? */
352.2429 + 	if (is_render_node(fd, &master))
352.2430 +@@ -472,9 +499,17 @@ static char *find_render_node(int fd)
352.2431 + 	sprintf(buf, "/dev/dri/renderD%d", (int)((master.st_rdev | 0x80) & 0xbf));
352.2432 + 	if (stat(buf, &render) == 0 &&
352.2433 + 	    master.st_mode == render.st_mode &&
352.2434 +-	    render.st_rdev == ((master.st_rdev | 0x80) & 0xbf))
352.2435 ++	    render.st_rdev == (master.st_rdev | 0x80))
352.2436 + 		return strdup(buf);
352.2437 +-#endif
352.2438 ++
352.2439 ++	/* Misaligned card <-> renderD, do a full search */
352.2440 ++	for (i = 0; i < 16; i++) {
352.2441 ++		sprintf(buf, "/dev/dri/renderD%d", i + 128);
352.2442 ++		if (stat(buf, &render) == 0 &&
352.2443 ++		    master.st_mode == render.st_mode &&
352.2444 ++		    render.st_rdev == (master.st_rdev | 0x80))
352.2445 ++			return strdup(buf);
352.2446 ++	}
352.2447 + 
352.2448 + 	return NULL;
352.2449 + }
352.2450 +@@ -608,6 +643,27 @@ err_path:
352.2451 + 	return -1;
352.2452 + }
352.2453 + 
352.2454 ++void intel_close_device(int entity_num)
352.2455 ++{
352.2456 ++	struct intel_device *dev;
352.2457 ++
352.2458 ++	if (intel_device_key == -1)
352.2459 ++		return;
352.2460 ++
352.2461 ++	dev = xf86GetEntityPrivate(entity_num, intel_device_key)->ptr;
352.2462 ++	xf86GetEntityPrivate(entity_num, intel_device_key)->ptr = NULL;
352.2463 ++	if (!dev)
352.2464 ++		return;
352.2465 ++
352.2466 ++	if (dev->master_count == 0) /* Don't close server-fds */
352.2467 ++		close(dev->fd);
352.2468 ++
352.2469 ++	if (dev->render_node != dev->master_node)
352.2470 ++		free(dev->render_node);
352.2471 ++	free(dev->master_node);
352.2472 ++	free(dev);
352.2473 ++}
352.2474 ++
352.2475 + int __intel_peek_fd(ScrnInfoPtr scrn)
352.2476 + {
352.2477 + 	struct intel_device *dev;
352.2478 +@@ -672,6 +728,12 @@ struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd)
352.2479 + 	return dev;
352.2480 + }
352.2481 + 
352.2482 ++const char *intel_get_master_name(struct intel_device *dev)
352.2483 ++{
352.2484 ++	assert(dev && dev->master_node);
352.2485 ++	return dev->master_node;
352.2486 ++}
352.2487 ++
352.2488 + const char *intel_get_client_name(struct intel_device *dev)
352.2489 + {
352.2490 + 	assert(dev && dev->render_node);
352.2491 +diff --git a/src/intel_driver.h b/src/intel_driver.h
352.2492 +index 28ed1a0e..bece88a0 100644
352.2493 +--- a/src/intel_driver.h
352.2494 ++++ b/src/intel_driver.h
352.2495 +@@ -124,9 +124,11 @@ int intel_entity_get_devid(int index);
352.2496 + int intel_open_device(int entity_num,
352.2497 + 		      const struct pci_device *pci,
352.2498 + 		      struct xf86_platform_device *dev);
352.2499 ++void intel_close_device(int entity_num);
352.2500 + int __intel_peek_fd(ScrnInfoPtr scrn);
352.2501 + struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd);
352.2502 + int intel_has_render_node(struct intel_device *dev);
352.2503 ++const char *intel_get_master_name(struct intel_device *dev);
352.2504 + const char *intel_get_client_name(struct intel_device *dev);
352.2505 + int intel_get_client_fd(struct intel_device *dev);
352.2506 + int intel_get_device_id(struct intel_device *dev);
352.2507 +diff --git a/src/intel_list.h b/src/intel_list.h
352.2508 +index 51af825d..c8a3187a 100644
352.2509 +--- a/src/intel_list.h
352.2510 ++++ b/src/intel_list.h
352.2511 +@@ -306,8 +306,7 @@ list_is_empty(const struct list *head)
352.2512 +     list_entry((ptr)->prev, type, member)
352.2513 + 
352.2514 + #define __container_of(ptr, sample, member)				\
352.2515 +-    (void *)((char *)(ptr)						\
352.2516 +-	     - ((char *)&(sample)->member - (char *)(sample)))
352.2517 ++    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
352.2518 + /**
352.2519 +  * Loop through the list given by head and set pos to struct in the list.
352.2520 +  *
352.2521 +@@ -392,17 +391,50 @@ static inline void list_move_tail(struct list *list, struct list *head)
352.2522 + #define list_last_entry(ptr, type, member) \
352.2523 +     list_entry((ptr)->prev, type, member)
352.2524 + 
352.2525 +-#define list_for_each_entry_reverse(pos, head, member)				\
352.2526 ++#define list_for_each_entry_reverse(pos, head, member)			\
352.2527 +     for (pos = __container_of((head)->prev, pos, member);		\
352.2528 + 	 &pos->member != (head);					\
352.2529 + 	 pos = __container_of(pos->member.prev, pos, member))
352.2530 + 
352.2531 + #endif
352.2532 + 
352.2533 ++#define list_for_each_entry_safe_from(pos, tmp, head, member)		\
352.2534 ++    for (tmp = __container_of(pos->member.next, pos, member);		\
352.2535 ++	 &pos->member != (head);					\
352.2536 ++	 pos = tmp, tmp = __container_of(tmp->member.next, tmp, member))
352.2537 ++
352.2538 + #undef container_of
352.2539 + #define container_of(ptr, type, member) \
352.2540 + 	((type *)((char *)(ptr) - (char *) &((type *)0)->member))
352.2541 + 
352.2542 ++static inline void __list_splice(const struct list *list,
352.2543 ++				 struct list *prev,
352.2544 ++				 struct list *next)
352.2545 ++{
352.2546 ++	struct list *first = list->next;
352.2547 ++	struct list *last = list->prev;
352.2548 ++
352.2549 ++	first->prev = prev;
352.2550 ++	prev->next = first;
352.2551 ++
352.2552 ++	last->next = next;
352.2553 ++	next->prev = last;
352.2554 ++}
352.2555 ++
352.2556 ++static inline void list_splice(const struct list *list,
352.2557 ++			       struct list *head)
352.2558 ++{
352.2559 ++	if (!list_is_empty(list))
352.2560 ++		__list_splice(list, head, head->next);
352.2561 ++}
352.2562 ++
352.2563 ++static inline void list_splice_tail(const struct list *list,
352.2564 ++				    struct list *head)
352.2565 ++{
352.2566 ++	if (!list_is_empty(list))
352.2567 ++		__list_splice(list, head->prev, head);
352.2568 ++}
352.2569 ++
352.2570 + static inline int list_is_singular(const struct list *list)
352.2571 + {
352.2572 + 	return list->next == list->prev;
352.2573 +diff --git a/src/intel_module.c b/src/intel_module.c
352.2574 +index 102d52aa..2e97b5ea 100644
352.2575 +--- a/src/intel_module.c
352.2576 ++++ b/src/intel_module.c
352.2577 +@@ -126,6 +126,17 @@ static const struct intel_device_info intel_skylake_info = {
352.2578 + 	.gen = 0110,
352.2579 + };
352.2580 + 
352.2581 ++static const struct intel_device_info intel_broxton_info = {
352.2582 ++	.gen = 0111,
352.2583 ++};
352.2584 ++
352.2585 ++static const struct intel_device_info intel_kabylake_info = {
352.2586 ++	.gen = 0112,
352.2587 ++};
352.2588 ++
352.2589 ++static const struct intel_device_info intel_geminilake_info = {
352.2590 ++	.gen = 0113,
352.2591 ++};
352.2592 + 
352.2593 + static const SymTabRec intel_chipsets[] = {
352.2594 + 	{PCI_CHIP_I810,				"i810"},
352.2595 +@@ -234,30 +245,63 @@ static const SymTabRec intel_chipsets[] = {
352.2596 + 	{0x0157, "HD Graphics"},
352.2597 + 
352.2598 + 	/* Broadwell Marketing names */
352.2599 +-	{0x1602, "HD graphics"},
352.2600 +-	{0x1606, "HD graphics"},
352.2601 +-	{0x160B, "HD graphics"},
352.2602 +-	{0x160A, "HD graphics"},
352.2603 +-	{0x160D, "HD graphics"},
352.2604 +-	{0x160E, "HD graphics"},
352.2605 +-	{0x1612, "HD graphics 5600"},
352.2606 +-	{0x1616, "HD graphics 5500"},
352.2607 +-	{0x161B, "HD graphics"},
352.2608 +-	{0x161A, "HD graphics"},
352.2609 +-	{0x161D, "HD graphics"},
352.2610 +-	{0x161E, "HD graphics 5300"},
352.2611 +-	{0x1622, "Iris Pro graphics 6200"},
352.2612 +-	{0x1626, "HD graphics 6000"},
352.2613 +-	{0x162B, "Iris graphics 6100"},
352.2614 +-	{0x162A, "Iris Pro graphics P6300"},
352.2615 +-	{0x162D, "HD graphics"},
352.2616 +-	{0x162E, "HD graphics"},
352.2617 +-	{0x1632, "HD graphics"},
352.2618 +-	{0x1636, "HD graphics"},
352.2619 +-	{0x163B, "HD graphics"},
352.2620 +-	{0x163A, "HD graphics"},
352.2621 +-	{0x163D, "HD graphics"},
352.2622 +-	{0x163E, "HD graphics"},
352.2623 ++	{0x1602, "HD Graphics"},
352.2624 ++	{0x1606, "HD Graphics"},
352.2625 ++	{0x160B, "HD Graphics"},
352.2626 ++	{0x160A, "HD Graphics"},
352.2627 ++	{0x160D, "HD Graphics"},
352.2628 ++	{0x160E, "HD Graphics"},
352.2629 ++	{0x1612, "HD Graphics 5600"},
352.2630 ++	{0x1616, "HD Graphics 5500"},
352.2631 ++	{0x161B, "HD Graphics"},
352.2632 ++	{0x161A, "HD Graphics"},
352.2633 ++	{0x161D, "HD Graphics"},
352.2634 ++	{0x161E, "HD Graphics 5300"},
352.2635 ++	{0x1622, "Iris Pro Graphics 6200"},
352.2636 ++	{0x1626, "HD Graphics 6000"},
352.2637 ++	{0x162B, "Iris Graphics 6100"},
352.2638 ++	{0x162A, "Iris Pro Graphics P6300"},
352.2639 ++	{0x162D, "HD Graphics"},
352.2640 ++	{0x162E, "HD Graphics"},
352.2641 ++	{0x1632, "HD Graphics"},
352.2642 ++	{0x1636, "HD Graphics"},
352.2643 ++	{0x163B, "HD Graphics"},
352.2644 ++	{0x163A, "HD Graphics"},
352.2645 ++	{0x163D, "HD Graphics"},
352.2646 ++	{0x163E, "HD Graphics"},
352.2647 ++
352.2648 ++	/* Cherryview (Cherrytrail/Braswell) */
352.2649 ++	{0x22b0, "HD Graphics"},
352.2650 ++	{0x22b1, "HD Graphics"},
352.2651 ++	{0x22b2, "HD Graphics"},
352.2652 ++	{0x22b3, "HD Graphics"},
352.2653 ++
352.2654 ++	/* Skylake */
352.2655 ++	{0x1902, "HD Graphics 510"},
352.2656 ++	{0x1906, "HD Graphics 510"},
352.2657 ++	{0x190B, "HD Graphics 510"},
352.2658 ++	{0x1912, "HD Graphics 530"},
352.2659 ++	{0x1916, "HD Graphics 520"},
352.2660 ++	{0x191B, "HD Graphics 530"},
352.2661 ++	{0x191D, "HD Graphics P530"},
352.2662 ++	{0x191E, "HD Graphics 515"},
352.2663 ++	{0x1921, "HD Graphics 520"},
352.2664 ++	{0x1926, "Iris Graphics 540"},
352.2665 ++	{0x1927, "Iris Graphics 550"},
352.2666 ++	{0x192B, "Iris Graphics 555"},
352.2667 ++	{0x192D, "Iris Graphics P555"},
352.2668 ++	{0x1932, "Iris Pro Graphics 580"},
352.2669 ++	{0x193A, "Iris Pro Graphics P580"},
352.2670 ++	{0x193B, "Iris Pro Graphics 580"},
352.2671 ++	{0x193D, "Iris Pro Graphics P580"},
352.2672 ++
352.2673 ++	/* Broxton (Apollolake) */
352.2674 ++	{0x5A84, "HD Graphics 505"},
352.2675 ++	{0x5A85, "HD Graphics 500"},
352.2676 ++
352.2677 ++	/* Kabylake */
352.2678 ++	{0x5916, "HD Graphics 620"},
352.2679 ++	{0x591E, "HD Graphics 615"},
352.2680 + 
352.2681 + 	/* When adding new identifiers, also update:
352.2682 + 	 * 1. intel_identify()
352.2683 +@@ -305,18 +349,14 @@ static const struct pci_id_match intel_device_match[] = {
352.2684 + 	INTEL_IVB_D_IDS(&intel_ivybridge_info),
352.2685 + 	INTEL_IVB_M_IDS(&intel_ivybridge_info),
352.2686 + 
352.2687 +-	INTEL_HSW_D_IDS(&intel_haswell_info),
352.2688 +-	INTEL_HSW_M_IDS(&intel_haswell_info),
352.2689 +-
352.2690 +-	INTEL_VLV_D_IDS(&intel_valleyview_info),
352.2691 +-	INTEL_VLV_M_IDS(&intel_valleyview_info),
352.2692 +-
352.2693 +-	INTEL_BDW_D_IDS(&intel_broadwell_info),
352.2694 +-	INTEL_BDW_M_IDS(&intel_broadwell_info),
352.2695 +-
352.2696 ++	INTEL_HSW_IDS(&intel_haswell_info),
352.2697 ++	INTEL_VLV_IDS(&intel_valleyview_info),
352.2698 ++	INTEL_BDW_IDS(&intel_broadwell_info),
352.2699 + 	INTEL_CHV_IDS(&intel_cherryview_info),
352.2700 +-
352.2701 + 	INTEL_SKL_IDS(&intel_skylake_info),
352.2702 ++	INTEL_BXT_IDS(&intel_broxton_info),
352.2703 ++	INTEL_KBL_IDS(&intel_kabylake_info),
352.2704 ++	INTEL_GLK_IDS(&intel_geminilake_info),
352.2705 + 
352.2706 + 	INTEL_VGA_DEVICE(PCI_MATCH_ANY, &intel_generic_info),
352.2707 + #endif
352.2708 +@@ -448,9 +488,9 @@ static void intel_identify(int flags)
352.2709 + 	if (unique != stack)
352.2710 + 		free(unique);
352.2711 + 
352.2712 +-	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) HD Graphics: 2000-6000\n");
352.2713 +-	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Graphics: 5100, 6100\n");
352.2714 +-	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Pro Graphics: 5200, 6200, P6300\n");
352.2715 ++	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) HD Graphics\n");
352.2716 ++	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Graphics\n");
352.2717 ++	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Pro Graphics\n");
352.2718 + }
352.2719 + 
352.2720 + static Bool intel_driver_func(ScrnInfoPtr pScrn,
352.2721 +@@ -508,6 +548,9 @@ static enum accel_method { NOACCEL, SNA, UXA } get_accel_method(void)
352.2722 + 	if (hosted())
352.2723 + 		return SNA;
352.2724 + 
352.2725 ++	if (xf86configptr == NULL) /* X -configure */
352.2726 ++		return SNA;
352.2727 ++
352.2728 + 	dev = _xf86findDriver("intel", xf86configptr->conf_device_lst);
352.2729 + 	if (dev && dev->dev_option_lst) {
352.2730 + 		const char *s;
352.2731 +@@ -582,10 +625,17 @@ intel_scrn_create(DriverPtr		driver,
352.2732 + 	case NOACCEL:
352.2733 + #endif
352.2734 + 	case UXA:
352.2735 +-		  return intel_init_scrn(scrn);
352.2736 ++		return intel_init_scrn(scrn);
352.2737 + #endif
352.2738 + 
352.2739 +-	default: break;
352.2740 ++	default:
352.2741 ++#if USE_SNA
352.2742 ++		return sna_init_scrn(scrn, entity_num);
352.2743 ++#elif USE_UXA
352.2744 ++		return intel_init_scrn(scrn);
352.2745 ++#else
352.2746 ++		break;
352.2747 ++#endif
352.2748 + 	}
352.2749 + #endif
352.2750 + 
352.2751 +@@ -604,6 +654,8 @@ static Bool intel_pci_probe(DriverPtr		driver,
352.2752 + 			    struct pci_device	*pci,
352.2753 + 			    intptr_t		match_data)
352.2754 + {
352.2755 ++	Bool ret;
352.2756 ++
352.2757 + 	if (intel_open_device(entity_num, pci, NULL) == -1) {
352.2758 + #if UMS
352.2759 + 		switch (pci->device_id) {
352.2760 +@@ -621,7 +673,11 @@ static Bool intel_pci_probe(DriverPtr		driver,
352.2761 + #endif
352.2762 + 	}
352.2763 + 
352.2764 +-	return intel_scrn_create(driver, entity_num, match_data, 0);
352.2765 ++	ret = intel_scrn_create(driver, entity_num, match_data, 0);
352.2766 ++	if (!ret)
352.2767 ++		intel_close_device(entity_num);
352.2768 ++
352.2769 ++	return ret;
352.2770 + }
352.2771 + 
352.2772 + #ifdef XSERVER_PLATFORM_BUS
352.2773 +@@ -644,9 +700,16 @@ intel_platform_probe(DriverPtr driver,
352.2774 + 
352.2775 + 	/* if we get any flags we don't understand fail to probe for now */
352.2776 + 	if (flags)
352.2777 +-		return FALSE;
352.2778 ++		goto err;
352.2779 ++
352.2780 ++	if (!intel_scrn_create(driver, entity_num, match_data, scrn_flags))
352.2781 ++		goto err;
352.2782 + 
352.2783 +-	return intel_scrn_create(driver, entity_num, match_data, scrn_flags);
352.2784 ++	return TRUE;
352.2785 ++
352.2786 ++err:
352.2787 ++	intel_close_device(entity_num);
352.2788 ++	return FALSE;
352.2789 + }
352.2790 + #endif
352.2791 + 
352.2792 +diff --git a/src/intel_options.c b/src/intel_options.c
352.2793 +index ff8541a4..7f253ac1 100644
352.2794 +--- a/src/intel_options.c
352.2795 ++++ b/src/intel_options.c
352.2796 +@@ -2,18 +2,24 @@
352.2797 + #include "config.h"
352.2798 + #endif
352.2799 + 
352.2800 ++#include <xorg-server.h>
352.2801 ++#include <xorgVersion.h>
352.2802 ++#include <xf86Parser.h>
352.2803 ++
352.2804 + #include "intel_options.h"
352.2805 + 
352.2806 + const OptionInfoRec intel_options[] = {
352.2807 +-	{OPTION_ACCEL_DISABLE,	"NoAccel",	OPTV_BOOLEAN,	{0},	0},
352.2808 ++	{OPTION_ACCEL_ENABLE,	"Accel",	OPTV_BOOLEAN,	{0},	0},
352.2809 + 	{OPTION_ACCEL_METHOD,	"AccelMethod",	OPTV_STRING,	{0},	0},
352.2810 + 	{OPTION_BACKLIGHT,	"Backlight",	OPTV_STRING,	{0},	0},
352.2811 ++	{OPTION_EDID,		"CustomEDID",	OPTV_STRING,	{0},	0},
352.2812 + 	{OPTION_DRI,		"DRI",		OPTV_STRING,	{0},	0},
352.2813 + 	{OPTION_PRESENT,	"Present",	OPTV_BOOLEAN,	{0},	1},
352.2814 + 	{OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	0},
352.2815 + 	{OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	0},
352.2816 + 	{OPTION_TILING_2D,	"Tiling",	OPTV_BOOLEAN,	{0},	1},
352.2817 + 	{OPTION_TILING_FB,	"LinearFramebuffer",	OPTV_BOOLEAN,	{0},	0},
352.2818 ++	{OPTION_ROTATION,	"HWRotation",	OPTV_BOOLEAN,	{0},	1},
352.2819 + 	{OPTION_VSYNC,		"VSync",	OPTV_BOOLEAN,	{0},	1},
352.2820 + 	{OPTION_PAGEFLIP,	"PageFlip",	OPTV_BOOLEAN,	{0},	1},
352.2821 + 	{OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN,	{0},	1},
352.2822 +@@ -21,7 +27,6 @@ const OptionInfoRec intel_options[] = {
352.2823 + 	{OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, 0},
352.2824 + 	{OPTION_HOTPLUG,	"HotPlug",	OPTV_BOOLEAN,	{0},	1},
352.2825 + 	{OPTION_REPROBE,	"ReprobeOutputs", OPTV_BOOLEAN,	{0},	0},
352.2826 +-	{OPTION_DELETE_DP12,	"DeleteUnusedDP12Displays", OPTV_BOOLEAN,	{0},	0},
352.2827 + #ifdef INTEL_XVMC
352.2828 + 	{OPTION_XVMC,		"XvMC",		OPTV_BOOLEAN,	{0},	1},
352.2829 + #endif
352.2830 +@@ -54,3 +59,85 @@ OptionInfoPtr intel_options_get(ScrnInfoPtr scrn)
352.2831 + 
352.2832 + 	return options;
352.2833 + }
352.2834 ++
352.2835 ++Bool intel_option_cast_to_bool(OptionInfoPtr options, int id, Bool val)
352.2836 ++{
352.2837 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.2838 ++	xf86getBoolValue(&val, xf86GetOptValString(options, id));
352.2839 ++#endif
352.2840 ++	return val;
352.2841 ++}
352.2842 ++
352.2843 ++static int
352.2844 ++namecmp(const char *s1, const char *s2)
352.2845 ++{
352.2846 ++	char c1, c2;
352.2847 ++
352.2848 ++	if (!s1 || *s1 == 0) {
352.2849 ++		if (!s2 || *s2 == 0)
352.2850 ++			return 0;
352.2851 ++		else
352.2852 ++			return 1;
352.2853 ++	}
352.2854 ++
352.2855 ++	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.2856 ++		s1++;
352.2857 ++
352.2858 ++	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.2859 ++		s2++;
352.2860 ++
352.2861 ++	c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.2862 ++	c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.2863 ++	while (c1 == c2) {
352.2864 ++		if (c1 == '\0')
352.2865 ++			return 0;
352.2866 ++
352.2867 ++		s1++;
352.2868 ++		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.2869 ++			s1++;
352.2870 ++
352.2871 ++		s2++;
352.2872 ++		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.2873 ++			s2++;
352.2874 ++
352.2875 ++		c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.2876 ++		c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.2877 ++	}
352.2878 ++
352.2879 ++	return c1 - c2;
352.2880 ++}
352.2881 ++
352.2882 ++unsigned intel_option_cast_to_unsigned(OptionInfoPtr options, int id, unsigned val)
352.2883 ++{
352.2884 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.2885 ++	const char *str = xf86GetOptValString(options, id);
352.2886 ++#else
352.2887 ++	const char *str = NULL;
352.2888 ++#endif
352.2889 ++	unsigned v;
352.2890 ++
352.2891 ++	if (str == NULL || *str == '\0')
352.2892 ++		return val;
352.2893 ++
352.2894 ++	if (namecmp(str, "on") == 0)
352.2895 ++		return val;
352.2896 ++	if (namecmp(str, "true") == 0)
352.2897 ++		return val;
352.2898 ++	if (namecmp(str, "yes") == 0)
352.2899 ++		return val;
352.2900 ++
352.2901 ++	if (namecmp(str, "0") == 0)
352.2902 ++		return 0;
352.2903 ++	if (namecmp(str, "off") == 0)
352.2904 ++		return 0;
352.2905 ++	if (namecmp(str, "false") == 0)
352.2906 ++		return 0;
352.2907 ++	if (namecmp(str, "no") == 0)
352.2908 ++		return 0;
352.2909 ++
352.2910 ++	v = atoi(str);
352.2911 ++	if (v)
352.2912 ++		return v;
352.2913 ++
352.2914 ++	return val;
352.2915 ++}
352.2916 +diff --git a/src/intel_options.h b/src/intel_options.h
352.2917 +index 7e2cbd9b..43635f1f 100644
352.2918 +--- a/src/intel_options.h
352.2919 ++++ b/src/intel_options.h
352.2920 +@@ -12,15 +12,17 @@
352.2921 +  */
352.2922 + 
352.2923 + enum intel_options {
352.2924 +-	OPTION_ACCEL_DISABLE,
352.2925 ++	OPTION_ACCEL_ENABLE,
352.2926 + 	OPTION_ACCEL_METHOD,
352.2927 + 	OPTION_BACKLIGHT,
352.2928 ++	OPTION_EDID,
352.2929 + 	OPTION_DRI,
352.2930 + 	OPTION_PRESENT,
352.2931 + 	OPTION_VIDEO_KEY,
352.2932 + 	OPTION_COLOR_KEY,
352.2933 + 	OPTION_TILING_2D,
352.2934 + 	OPTION_TILING_FB,
352.2935 ++	OPTION_ROTATION,
352.2936 + 	OPTION_VSYNC,
352.2937 + 	OPTION_PAGEFLIP,
352.2938 + 	OPTION_SWAPBUFFERS_WAIT,
352.2939 +@@ -28,7 +30,6 @@ enum intel_options {
352.2940 + 	OPTION_PREFER_OVERLAY,
352.2941 + 	OPTION_HOTPLUG,
352.2942 + 	OPTION_REPROBE,
352.2943 +-	OPTION_DELETE_DP12,
352.2944 + #if defined(XvMCExtension) && defined(ENABLE_XVMC)
352.2945 + 	OPTION_XVMC,
352.2946 + #define INTEL_XVMC 1
352.2947 +@@ -51,5 +52,7 @@ enum intel_options {
352.2948 + 
352.2949 + extern const OptionInfoRec intel_options[];
352.2950 + OptionInfoPtr intel_options_get(ScrnInfoPtr scrn);
352.2951 ++unsigned intel_option_cast_to_unsigned(OptionInfoPtr, int id, unsigned val);
352.2952 ++Bool intel_option_cast_to_bool(OptionInfoPtr, int id, Bool val);
352.2953 + 
352.2954 + #endif /* INTEL_OPTIONS_H */
352.2955 +diff --git a/src/legacy/i810/i810_common.h b/src/legacy/i810/i810_common.h
352.2956 +index 4cc10e8b..8355708c 100644
352.2957 +--- a/src/legacy/i810/i810_common.h
352.2958 ++++ b/src/legacy/i810/i810_common.h
352.2959 +@@ -52,7 +52,7 @@
352.2960 + 
352.2961 + #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
352.2962 + 
352.2963 +-/* Using usleep() makes things noticably slow. */
352.2964 ++/* Using usleep() makes things noticeably slow. */
352.2965 + #if 0
352.2966 + #define DELAY(x) usleep(x)
352.2967 + #else
352.2968 +@@ -185,7 +185,7 @@ enum {
352.2969 +  *    - zbuffer linear offset and pitch -- also invarient
352.2970 +  *    - drawing origin in back and depth buffers.
352.2971 +  *
352.2972 +- * Keep the depth/back buffer state here to acommodate private buffers
352.2973 ++ * Keep the depth/back buffer state here to accommodate private buffers
352.2974 +  * in the future.
352.2975 +  */
352.2976 + #define I810_DESTREG_DI0  0		/* CMD_OP_DESTBUFFER_INFO (2 dwords) */
352.2977 +diff --git a/src/legacy/i810/i810_hwmc.c b/src/legacy/i810/i810_hwmc.c
352.2978 +index 7cb9c1ab..58661b0a 100644
352.2979 +--- a/src/legacy/i810/i810_hwmc.c
352.2980 ++++ b/src/legacy/i810/i810_hwmc.c
352.2981 +@@ -171,7 +171,7 @@ static XF86MCAdaptorPtr ppAdapt[1] =
352.2982 +  *
352.2983 +  *  I810InitMC
352.2984 +  *
352.2985 +- *  Initialize the hardware motion compenstation extention for this 
352.2986 ++ *  Initialize the hardware motion compensation extension for this
352.2987 +  *  hardware. The initialization routines want the address of the pointers
352.2988 +  *  to the structures, not the address of the structures. This means we
352.2989 +  *  allocate (or create static?) the pointer memory and pass that 
352.2990 +diff --git a/src/legacy/i810/i810_memory.c b/src/legacy/i810/i810_memory.c
352.2991 +index c3de2777..6f274836 100644
352.2992 +--- a/src/legacy/i810/i810_memory.c
352.2993 ++++ b/src/legacy/i810/i810_memory.c
352.2994 +@@ -76,7 +76,7 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn)
352.2995 +    unsigned long size = pScrn->videoRam * 1024UL;
352.2996 +    I810Ptr pI810 = I810PTR(pScrn);
352.2997 +    int key;
352.2998 +-   long tom = 0;
352.2999 ++   unsigned long tom = 0;
352.3000 +    unsigned long physical;
352.3001 + 
352.3002 +    if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
352.3003 +@@ -132,8 +132,8 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn)
352.3004 +     * Keep it 512K aligned for the sake of tiled regions.
352.3005 +     */
352.3006 + 
352.3007 +-   tom += 0x7ffff;
352.3008 +-   tom &= ~0x7ffff;
352.3009 ++   tom += 0x7ffffUL;
352.3010 ++   tom &= ~0x7ffffUL;
352.3011 + 
352.3012 +    if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
352.3013 +       pI810->DcacheOffset = tom;
352.3014 +diff --git a/src/legacy/i810/i810_reg.h b/src/legacy/i810/i810_reg.h
352.3015 +index 54faeb3d..fa091c5b 100644
352.3016 +--- a/src/legacy/i810/i810_reg.h
352.3017 ++++ b/src/legacy/i810/i810_reg.h
352.3018 +@@ -245,7 +245,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
352.3019 +  * not sure they refer to local (graphics) memory.
352.3020 +  *
352.3021 +  * These details are for the local memory control registers,
352.3022 +- * (pp301-310).  The test machines are not equiped with local memory,
352.3023 ++ * (pp301-310).  The test machines are not equipped with local memory,
352.3024 +  * so nothing is tested.  Only a single row seems to be supported.
352.3025 +  */
352.3026 + #define DRAM_ROW_TYPE      0x3000
352.3027 +diff --git a/src/legacy/i810/i810_video.c b/src/legacy/i810/i810_video.c
352.3028 +index be49b91d..af683c81 100644
352.3029 +--- a/src/legacy/i810/i810_video.c
352.3030 ++++ b/src/legacy/i810/i810_video.c
352.3031 +@@ -77,7 +77,11 @@ static int I810PutImage( ScrnInfoPtr,
352.3032 + static int I810QueryImageAttributes(ScrnInfoPtr, 
352.3033 + 	int, unsigned short *, unsigned short *,  int *, int *);
352.3034 + 
352.3035 ++#if !HAVE_NOTIFY_FD
352.3036 + static void I810BlockHandler(BLOCKHANDLER_ARGS_DECL);
352.3037 ++#else
352.3038 ++static void I810BlockHandler(void *data, void *_timeout);
352.3039 ++#endif
352.3040 + 
352.3041 + #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
352.3042 + 
352.3043 +@@ -418,8 +422,14 @@ I810SetupImageVideo(ScreenPtr screen)
352.3044 + 
352.3045 +     pI810->adaptor = adapt;
352.3046 + 
352.3047 ++#if !HAVE_NOTIFY_FD
352.3048 +     pI810->BlockHandler = screen->BlockHandler;
352.3049 +     screen->BlockHandler = I810BlockHandler;
352.3050 ++#else
352.3051 ++    RegisterBlockAndWakeupHandlers(I810BlockHandler,
352.3052 ++				   (ServerWakeupHandlerProcPtr)NoopDDA,
352.3053 ++				   pScrn);
352.3054 ++#endif
352.3055 + 
352.3056 +     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
352.3057 +     xvContrast   = MAKE_ATOM("XV_CONTRAST");
352.3058 +@@ -1135,6 +1145,7 @@ I810QueryImageAttributes(
352.3059 +     return size;
352.3060 + }
352.3061 + 
352.3062 ++#if !HAVE_NOTIFY_FD
352.3063 + static void
352.3064 + I810BlockHandler (BLOCKHANDLER_ARGS_DECL)
352.3065 + {
352.3066 +@@ -1172,6 +1183,38 @@ I810BlockHandler (BLOCKHANDLER_ARGS_DECL)
352.3067 +         }
352.3068 +     }
352.3069 + }
352.3070 ++#else
352.3071 ++static void
352.3072 ++I810BlockHandler(void *data, void *_timeout)
352.3073 ++{
352.3074 ++    ScrnInfoPtr pScrn = data;
352.3075 ++    I810Ptr      pI810 = I810PTR(pScrn);
352.3076 ++    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
352.3077 ++    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
352.3078 ++
352.3079 ++    if(pPriv->videoStatus & TIMER_MASK) {
352.3080 ++	UpdateCurrentTime();
352.3081 ++	if(pPriv->videoStatus & OFF_TIMER) {
352.3082 ++	    if(pPriv->offTime < currentTime.milliseconds) {
352.3083 ++		/* Turn off the overlay */
352.3084 ++		overlay->OV0CMD &= 0xFFFFFFFE;
352.3085 ++		OVERLAY_UPDATE(pI810->OverlayPhysical);
352.3086 ++
352.3087 ++		pPriv->videoStatus = FREE_TIMER;
352.3088 ++		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
352.3089 ++	    }
352.3090 ++	} else {  /* FREE_TIMER */
352.3091 ++	    if(pPriv->freeTime < currentTime.milliseconds) {
352.3092 ++		if(pPriv->linear) {
352.3093 ++		   xf86FreeOffscreenLinear(pPriv->linear);
352.3094 ++		   pPriv->linear = NULL;
352.3095 ++		}
352.3096 ++		pPriv->videoStatus = 0;
352.3097 ++	    }
352.3098 ++        }
352.3099 ++    }
352.3100 ++}
352.3101 ++#endif
352.3102 + 
352.3103 + 
352.3104 + /***************************************************************************
352.3105 +@@ -1373,7 +1416,6 @@ I810DisplaySurface(
352.3106 +       UpdateCurrentTime();
352.3107 +       pI810Priv->videoStatus = FREE_TIMER;
352.3108 +       pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
352.3109 +-      pScrn->pScreen->BlockHandler = I810BlockHandler;
352.3110 +     }
352.3111 + 
352.3112 +     return Success;
352.3113 +diff --git a/src/legacy/i810/xvmc/I810XvMC.c b/src/legacy/i810/xvmc/I810XvMC.c
352.3114 +index e6b63d30..a538e999 100644
352.3115 +--- a/src/legacy/i810/xvmc/I810XvMC.c
352.3116 ++++ b/src/legacy/i810/xvmc/I810XvMC.c
352.3117 +@@ -61,7 +61,7 @@ static int event_base;
352.3118 + // Arguments: pI810XvMC private data structure from the current context.
352.3119 + // Notes: We faked the drmMapBufs for the i810's security so now we have
352.3120 + //   to insert an allocated page into the correct spot in the faked
352.3121 +-//   list to keep up appearences.
352.3122 ++//   list to keep up appearances.
352.3123 + //   Concept for this function was taken from Mesa sources.
352.3124 + // Returns: drmBufPtr containing the information about the allocated page.
352.3125 + ***************************************************************************/
352.3126 +@@ -188,7 +188,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
352.3127 + 
352.3128 +   /* Check for drm */
352.3129 +   if(! drmAvailable()) {
352.3130 +-    printf("Direct Rendering is not avilable on this system!\n");
352.3131 ++    printf("Direct Rendering is not available on this system!\n");
352.3132 +     return BadAlloc;
352.3133 +   }
352.3134 + 
352.3135 +@@ -3279,7 +3279,7 @@ _X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
352.3136 + //   display - Connection to X server
352.3137 + //   surface - Surface to flush
352.3138 + // Info:
352.3139 +-//   This command is a noop for i810 becuase we always dispatch buffers in
352.3140 ++//   This command is a noop for i810 because we always dispatch buffers in
352.3141 + //   render. There is little gain to be had with 4k buffers.
352.3142 + // Returns: Status
352.3143 + ***************************************************************************/
352.3144 +diff --git a/src/render_program/exa_wm.g4i b/src/render_program/exa_wm.g4i
352.3145 +index 5d3d45b1..587b581c 100644
352.3146 +--- a/src/render_program/exa_wm.g4i
352.3147 ++++ b/src/render_program/exa_wm.g4i
352.3148 +@@ -57,7 +57,7 @@ define(`mask_dw_dy', `g6.4<0,1,0>F')
352.3149 + define(`mask_wo',    `g6.12<0,1,0>F')
352.3150 + 
352.3151 + /*
352.3152 +- * Local variables. Pairs must be aligned on even reg boundry
352.3153 ++ * Local variables. Pairs must be aligned on even reg boundary
352.3154 +  */
352.3155 + 
352.3156 + /* this holds the X dest coordinates */
352.3157 +diff --git a/src/render_program/exa_wm_yuv_rgb.g8a b/src/render_program/exa_wm_yuv_rgb.g8a
352.3158 +index 7def0930..34973ba8 100644
352.3159 +--- a/src/render_program/exa_wm_yuv_rgb.g8a
352.3160 ++++ b/src/render_program/exa_wm_yuv_rgb.g8a
352.3161 +@@ -76,7 +76,7 @@ add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
352.3162 +     /* 
352.3163 +      * R = Y + Cr * 1.596
352.3164 +      */
352.3165 +-mov (8)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
352.3166 ++mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
352.3167 + mac.sat(8) src_sample_r_01<1>F	Crn_01<8,8,1>F	1.596F	    { compr align1 };
352.3168 +      
352.3169 + mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
352.3170 +@@ -84,7 +84,7 @@ mac.sat(8) src_sample_r_23<1>F	Crn_23<8,8,1>F	1.596F	    { compr align1 };
352.3171 +     /*
352.3172 +      * G = Crn * -0.813 + Cbn * -0.392 + Y
352.3173 +      */
352.3174 +-mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
352.3175 ++mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
352.3176 + mac (8)    acc0<1>F		Crn_01<8,8,1>F    	-0.813F	    { compr align1 };
352.3177 + mac.sat(8) src_sample_g_01<1>F	Cbn_01<8,8,1>F    	-0.392F	    { compr align1 };
352.3178 + 
352.3179 +diff --git a/src/render_program/exa_wm_yuv_rgb.g8b b/src/render_program/exa_wm_yuv_rgb.g8b
352.3180 +index 44949538..2cd6fc44 100644
352.3181 +--- a/src/render_program/exa_wm_yuv_rgb.g8b
352.3182 ++++ b/src/render_program/exa_wm_yuv_rgb.g8b
352.3183 +@@ -6,7 +6,7 @@
352.3184 +    { 0x80600048, 0x21c03ae8, 0x3e8d02c0, 0x3fcc49ba },
352.3185 +    { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
352.3186 +    { 0x80600048, 0x21e03ae8, 0x3e8d02e0, 0x3fcc49ba },
352.3187 +-   { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
352.3188 ++   { 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
352.3189 +    { 0x00600048, 0x24003ae0, 0x3e8d02c0, 0xbf5020c5 },
352.3190 +    { 0x80600048, 0x22003ae8, 0x3e8d0340, 0xbec8b439 },
352.3191 +    { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
352.3192 +diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
352.3193 +index e09a8d49..adf13963 100644
352.3194 +--- a/src/sna/Makefile.am
352.3195 ++++ b/src/sna/Makefile.am
352.3196 +@@ -107,6 +107,8 @@ libsna_la_SOURCES = \
352.3197 + 	gen8_render.h \
352.3198 + 	gen8_vertex.c \
352.3199 + 	gen8_vertex.h \
352.3200 ++	gen9_render.c \
352.3201 ++	gen9_render.h \
352.3202 + 	xassert.h \
352.3203 + 	$(NULL)
352.3204 + 
352.3205 +diff --git a/src/sna/blt.c b/src/sna/blt.c
352.3206 +index b5bfee69..cb90437a 100644
352.3207 +--- a/src/sna/blt.c
352.3208 ++++ b/src/sna/blt.c
352.3209 +@@ -30,112 +30,608 @@
352.3210 + #endif
352.3211 + 
352.3212 + #include "sna.h"
352.3213 ++#include <pixman.h>
352.3214 + 
352.3215 +-#if __x86_64__
352.3216 +-#define USE_SSE2 1
352.3217 +-#endif
352.3218 +-
352.3219 +-#if USE_SSE2
352.3220 ++#if defined(sse2)
352.3221 ++#pragma GCC push_options
352.3222 ++#pragma GCC target("sse2,inline-all-stringops,fpmath=sse")
352.3223 ++#pragma GCC optimize("Ofast")
352.3224 + #include <xmmintrin.h>
352.3225 + 
352.3226 + #if __x86_64__
352.3227 + #define have_sse2() 1
352.3228 + #else
352.3229 +-enum {
352.3230 +-	MMX = 0x1,
352.3231 +-	MMX_EXTENSIONS = 0x2,
352.3232 +-	SSE = 0x6,
352.3233 +-	SSE2 = 0x8,
352.3234 +-	CMOV = 0x10
352.3235 +-};
352.3236 +-
352.3237 +-#ifdef __GNUC__
352.3238 +-static unsigned int
352.3239 +-detect_cpu_features(void)
352.3240 +-{
352.3241 +-	unsigned int features;
352.3242 +-	unsigned int result = 0;
352.3243 +-
352.3244 +-	char vendor[13];
352.3245 +-	vendor[0] = 0;
352.3246 +-	vendor[12] = 0;
352.3247 +-
352.3248 +-	asm (
352.3249 +-	     "pushf\n"
352.3250 +-	     "pop %%eax\n"
352.3251 +-	     "mov %%eax, %%ecx\n"
352.3252 +-	     "xor $0x00200000, %%eax\n"
352.3253 +-	     "push %%eax\n"
352.3254 +-	     "popf\n"
352.3255 +-	     "pushf\n"
352.3256 +-	     "pop %%eax\n"
352.3257 +-	     "mov $0x0, %%edx\n"
352.3258 +-	     "xor %%ecx, %%eax\n"
352.3259 +-	     "jz 1f\n"
352.3260 +-
352.3261 +-	     "mov $0x00000000, %%eax\n"
352.3262 +-	     "push %%ebx\n"
352.3263 +-	     "cpuid\n"
352.3264 +-	     "mov %%ebx, %%eax\n"
352.3265 +-	     "pop %%ebx\n"
352.3266 +-	     "mov %%eax, %1\n"
352.3267 +-	     "mov %%edx, %2\n"
352.3268 +-	     "mov %%ecx, %3\n"
352.3269 +-	     "mov $0x00000001, %%eax\n"
352.3270 +-	     "push %%ebx\n"
352.3271 +-	     "cpuid\n"
352.3272 +-	     "pop %%ebx\n"
352.3273 +-	     "1:\n"
352.3274 +-	     "mov %%edx, %0\n"
352.3275 +-	     : "=r" (result), "=m" (vendor[0]), "=m" (vendor[4]), "=m" (vendor[8])
352.3276 +-	     :: "%eax", "%ecx", "%edx");
352.3277 +-
352.3278 +-	features = 0;
352.3279 +-	if (result) {
352.3280 +-		/* result now contains the standard feature bits */
352.3281 +-		if (result & (1 << 15))
352.3282 +-			features |= CMOV;
352.3283 +-		if (result & (1 << 23))
352.3284 +-			features |= MMX;
352.3285 +-		if (result & (1 << 25))
352.3286 +-			features |= SSE;
352.3287 +-		if (result & (1 << 26))
352.3288 +-			features |= SSE2;
352.3289 +-	}
352.3290 +-	return features;
352.3291 +-}
352.3292 +-#else
352.3293 +-static unsigned int detect_cpu_features(void) { return 0; }
352.3294 +-#endif
352.3295 +-
352.3296 + static bool have_sse2(void)
352.3297 + {
352.3298 + 	static int sse2_present = -1;
352.3299 + 
352.3300 + 	if (sse2_present == -1)
352.3301 +-		sse2_present = detect_cpu_features() & SSE2;
352.3302 ++		sse2_present = sna_cpu_detect() & SSE2;
352.3303 + 
352.3304 + 	return sse2_present;
352.3305 + }
352.3306 + #endif
352.3307 + 
352.3308 +-static inline __m128i
352.3309 ++static force_inline __m128i
352.3310 + xmm_create_mask_32(uint32_t mask)
352.3311 + {
352.3312 + 	return _mm_set_epi32(mask, mask, mask, mask);
352.3313 + }
352.3314 + 
352.3315 +-static inline __m128i
352.3316 ++static force_inline __m128i
352.3317 ++xmm_load_128(const __m128i *src)
352.3318 ++{
352.3319 ++	return _mm_load_si128(src);
352.3320 ++}
352.3321 ++
352.3322 ++static force_inline __m128i
352.3323 + xmm_load_128u(const __m128i *src)
352.3324 + {
352.3325 + 	return _mm_loadu_si128(src);
352.3326 + }
352.3327 + 
352.3328 +-static inline void
352.3329 ++static force_inline void
352.3330 + xmm_save_128(__m128i *dst, __m128i data)
352.3331 + {
352.3332 + 	_mm_store_si128(dst, data);
352.3333 + }
352.3334 ++
352.3335 ++static force_inline void
352.3336 ++xmm_save_128u(__m128i *dst, __m128i data)
352.3337 ++{
352.3338 ++	_mm_storeu_si128(dst, data);
352.3339 ++}
352.3340 ++
352.3341 ++static force_inline void
352.3342 ++to_sse128xN(uint8_t *dst, const uint8_t *src, int bytes)
352.3343 ++{
352.3344 ++	int i;
352.3345 ++
352.3346 ++	for (i = 0; i < bytes / 128; i++) {
352.3347 ++		__m128i xmm0, xmm1, xmm2, xmm3;
352.3348 ++		__m128i xmm4, xmm5, xmm6, xmm7;
352.3349 ++
352.3350 ++		xmm0 = xmm_load_128u((const __m128i*)src + 0);
352.3351 ++		xmm1 = xmm_load_128u((const __m128i*)src + 1);
352.3352 ++		xmm2 = xmm_load_128u((const __m128i*)src + 2);
352.3353 ++		xmm3 = xmm_load_128u((const __m128i*)src + 3);
352.3354 ++		xmm4 = xmm_load_128u((const __m128i*)src + 4);
352.3355 ++		xmm5 = xmm_load_128u((const __m128i*)src + 5);
352.3356 ++		xmm6 = xmm_load_128u((const __m128i*)src + 6);
352.3357 ++		xmm7 = xmm_load_128u((const __m128i*)src + 7);
352.3358 ++
352.3359 ++		xmm_save_128((__m128i*)dst + 0, xmm0);
352.3360 ++		xmm_save_128((__m128i*)dst + 1, xmm1);
352.3361 ++		xmm_save_128((__m128i*)dst + 2, xmm2);
352.3362 ++		xmm_save_128((__m128i*)dst + 3, xmm3);
352.3363 ++		xmm_save_128((__m128i*)dst + 4, xmm4);
352.3364 ++		xmm_save_128((__m128i*)dst + 5, xmm5);
352.3365 ++		xmm_save_128((__m128i*)dst + 6, xmm6);
352.3366 ++		xmm_save_128((__m128i*)dst + 7, xmm7);
352.3367 ++
352.3368 ++		dst += 128;
352.3369 ++		src += 128;
352.3370 ++	}
352.3371 ++}
352.3372 ++
352.3373 ++static force_inline void
352.3374 ++to_sse64(uint8_t *dst, const uint8_t *src)
352.3375 ++{
352.3376 ++	__m128i xmm1, xmm2, xmm3, xmm4;
352.3377 ++
352.3378 ++	xmm1 = xmm_load_128u((const __m128i*)src + 0);
352.3379 ++	xmm2 = xmm_load_128u((const __m128i*)src + 1);
352.3380 ++	xmm3 = xmm_load_128u((const __m128i*)src + 2);
352.3381 ++	xmm4 = xmm_load_128u((const __m128i*)src + 3);
352.3382 ++
352.3383 ++	xmm_save_128((__m128i*)dst + 0, xmm1);
352.3384 ++	xmm_save_128((__m128i*)dst + 1, xmm2);
352.3385 ++	xmm_save_128((__m128i*)dst + 2, xmm3);
352.3386 ++	xmm_save_128((__m128i*)dst + 3, xmm4);
352.3387 ++}
352.3388 ++
352.3389 ++static force_inline void
352.3390 ++to_sse32(uint8_t *dst, const uint8_t *src)
352.3391 ++{
352.3392 ++	__m128i xmm1, xmm2;
352.3393 ++
352.3394 ++	xmm1 = xmm_load_128u((const __m128i*)src + 0);
352.3395 ++	xmm2 = xmm_load_128u((const __m128i*)src + 1);
352.3396 ++
352.3397 ++	xmm_save_128((__m128i*)dst + 0, xmm1);
352.3398 ++	xmm_save_128((__m128i*)dst + 1, xmm2);
352.3399 ++}
352.3400 ++
352.3401 ++static force_inline void
352.3402 ++to_sse16(uint8_t *dst, const uint8_t *src)
352.3403 ++{
352.3404 ++	xmm_save_128((__m128i*)dst, xmm_load_128u((const __m128i*)src));
352.3405 ++}
352.3406 ++
352.3407 ++static void to_memcpy(uint8_t *dst, const uint8_t *src, unsigned len)
352.3408 ++{
352.3409 ++	assert(len);
352.3410 ++	if ((uintptr_t)dst & 15) {
352.3411 ++		if (len <= 16 - ((uintptr_t)dst & 15)) {
352.3412 ++			memcpy(dst, src, len);
352.3413 ++			return;
352.3414 ++		}
352.3415 ++
352.3416 ++		if ((uintptr_t)dst & 1) {
352.3417 ++			assert(len >= 1);
352.3418 ++			*dst++ = *src++;
352.3419 ++			len--;
352.3420 ++		}
352.3421 ++		if ((uintptr_t)dst & 2) {
352.3422 ++			assert(((uintptr_t)dst & 1) == 0);
352.3423 ++			assert(len >= 2);
352.3424 ++			*(uint16_t *)dst = *(const uint16_t *)src;
352.3425 ++			dst += 2;
352.3426 ++			src += 2;
352.3427 ++			len -= 2;
352.3428 ++		}
352.3429 ++		if ((uintptr_t)dst & 4) {
352.3430 ++			assert(((uintptr_t)dst & 3) == 0);
352.3431 ++			assert(len >= 4);
352.3432 ++			*(uint32_t *)dst = *(const uint32_t *)src;
352.3433 ++			dst += 4;
352.3434 ++			src += 4;
352.3435 ++			len -= 4;
352.3436 ++		}
352.3437 ++		if ((uintptr_t)dst & 8) {
352.3438 ++			assert(((uintptr_t)dst & 7) == 0);
352.3439 ++			assert(len >= 8);
352.3440 ++			*(uint64_t *)dst = *(const uint64_t *)src;
352.3441 ++			dst += 8;
352.3442 ++			src += 8;
352.3443 ++			len -= 8;
352.3444 ++		}
352.3445 ++	}
352.3446 ++
352.3447 ++	assert(((uintptr_t)dst & 15) == 0);
352.3448 ++	while (len >= 64) {
352.3449 ++		to_sse64(dst, src);
352.3450 ++		dst += 64;
352.3451 ++		src += 64;
352.3452 ++		len -= 64;
352.3453 ++	}
352.3454 ++	if (len == 0)
352.3455 ++		return;
352.3456 ++
352.3457 ++	if (len & 32) {
352.3458 ++		to_sse32(dst, src);
352.3459 ++		dst += 32;
352.3460 ++		src += 32;
352.3461 ++	}
352.3462 ++	if (len & 16) {
352.3463 ++		to_sse16(dst, src);
352.3464 ++		dst += 16;
352.3465 ++		src += 16;
352.3466 ++	}
352.3467 ++	if (len & 8) {
352.3468 ++		*(uint64_t *)dst = *(uint64_t *)src;
352.3469 ++		dst += 8;
352.3470 ++		src += 8;
352.3471 ++	}
352.3472 ++	if (len & 4) {
352.3473 ++		*(uint32_t *)dst = *(uint32_t *)src;
352.3474 ++		dst += 4;
352.3475 ++		src += 4;
352.3476 ++	}
352.3477 ++	memcpy(dst, src, len & 3);
352.3478 ++}
352.3479 ++
352.3480 ++static void
352.3481 ++memcpy_to_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
352.3482 ++				   int32_t src_stride, int32_t dst_stride,
352.3483 ++				   int16_t src_x, int16_t src_y,
352.3484 ++				   int16_t dst_x, int16_t dst_y,
352.3485 ++				   uint16_t width, uint16_t height)
352.3486 ++{
352.3487 ++	const unsigned tile_width = 512;
352.3488 ++	const unsigned tile_height = 8;
352.3489 ++	const unsigned tile_size = 4096;
352.3490 ++
352.3491 ++	const unsigned cpp = bpp / 8;
352.3492 ++	const unsigned tile_pixels = tile_width / cpp;
352.3493 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.3494 ++	const unsigned tile_mask = tile_pixels - 1;
352.3495 ++
352.3496 ++	unsigned offset_x, length_x;
352.3497 ++
352.3498 ++	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.3499 ++	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.3500 ++	assert(src != dst);
352.3501 ++
352.3502 ++	if (src_x | src_y)
352.3503 ++		src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
352.3504 ++	width *= cpp;
352.3505 ++	assert(src_stride >= width);
352.3506 ++
352.3507 ++	if (dst_x & tile_mask) {
352.3508 ++		offset_x = (dst_x & tile_mask) * cpp;
352.3509 ++		length_x = min(tile_width - offset_x, width);
352.3510 ++	} else
352.3511 ++		length_x = 0;
352.3512 ++	dst = (uint8_t *)dst + (dst_x >> tile_shift) * tile_size;
352.3513 ++
352.3514 ++	while (height--) {
352.3515 ++		unsigned w = width;
352.3516 ++		const uint8_t *src_row = src;
352.3517 ++		uint8_t *tile_row = dst;
352.3518 ++
352.3519 ++		src = (const uint8_t *)src + src_stride;
352.3520 ++
352.3521 ++		tile_row += dst_y / tile_height * dst_stride * tile_height;
352.3522 ++		tile_row += (dst_y & (tile_height-1)) * tile_width;
352.3523 ++		dst_y++;
352.3524 ++
352.3525 ++		if (length_x) {
352.3526 ++			to_memcpy(tile_row + offset_x, src_row, length_x);
352.3527 ++
352.3528 ++			tile_row += tile_size;
352.3529 ++			src_row = (const uint8_t *)src_row + length_x;
352.3530 ++			w -= length_x;
352.3531 ++		}
352.3532 ++		while (w >= tile_width) {
352.3533 ++			assert(((uintptr_t)tile_row & (tile_width - 1)) == 0);
352.3534 ++			to_sse128xN(assume_aligned(tile_row, tile_width),
352.3535 ++				    src_row, tile_width);
352.3536 ++			tile_row += tile_size;
352.3537 ++			src_row = (const uint8_t *)src_row + tile_width;
352.3538 ++			w -= tile_width;
352.3539 ++		}
352.3540 ++		if (w) {
352.3541 ++			assert(((uintptr_t)tile_row & (tile_width - 1)) == 0);
352.3542 ++			to_memcpy(assume_aligned(tile_row, tile_width),
352.3543 ++				  src_row, w);
352.3544 ++		}
352.3545 ++	}
352.3546 ++}
352.3547 ++
352.3548 ++static force_inline void
352.3549 ++from_sse128xNu(uint8_t *dst, const uint8_t *src, int bytes)
352.3550 ++{
352.3551 ++	int i;
352.3552 ++
352.3553 ++	assert(((uintptr_t)src & 15) == 0);
352.3554 ++
352.3555 ++	for (i = 0; i < bytes / 128; i++) {
352.3556 ++		__m128i xmm0, xmm1, xmm2, xmm3;
352.3557 ++		__m128i xmm4, xmm5, xmm6, xmm7;
352.3558 ++
352.3559 ++		xmm0 = xmm_load_128((const __m128i*)src + 0);
352.3560 ++		xmm1 = xmm_load_128((const __m128i*)src + 1);
352.3561 ++		xmm2 = xmm_load_128((const __m128i*)src + 2);
352.3562 ++		xmm3 = xmm_load_128((const __m128i*)src + 3);
352.3563 ++		xmm4 = xmm_load_128((const __m128i*)src + 4);
352.3564 ++		xmm5 = xmm_load_128((const __m128i*)src + 5);
352.3565 ++		xmm6 = xmm_load_128((const __m128i*)src + 6);
352.3566 ++		xmm7 = xmm_load_128((const __m128i*)src + 7);
352.3567 ++
352.3568 ++		xmm_save_128u((__m128i*)dst + 0, xmm0);
352.3569 ++		xmm_save_128u((__m128i*)dst + 1, xmm1);
352.3570 ++		xmm_save_128u((__m128i*)dst + 2, xmm2);
352.3571 ++		xmm_save_128u((__m128i*)dst + 3, xmm3);
352.3572 ++		xmm_save_128u((__m128i*)dst + 4, xmm4);
352.3573 ++		xmm_save_128u((__m128i*)dst + 5, xmm5);
352.3574 ++		xmm_save_128u((__m128i*)dst + 6, xmm6);
352.3575 ++		xmm_save_128u((__m128i*)dst + 7, xmm7);
352.3576 ++
352.3577 ++		dst += 128;
352.3578 ++		src += 128;
352.3579 ++	}
352.3580 ++}
352.3581 ++
352.3582 ++static force_inline void
352.3583 ++from_sse128xNa(uint8_t *dst, const uint8_t *src, int bytes)
352.3584 ++{
352.3585 ++	int i;
352.3586 ++
352.3587 ++	assert(((uintptr_t)dst & 15) == 0);
352.3588 ++	assert(((uintptr_t)src & 15) == 0);
352.3589 ++
352.3590 ++	for (i = 0; i < bytes / 128; i++) {
352.3591 ++		__m128i xmm0, xmm1, xmm2, xmm3;
352.3592 ++		__m128i xmm4, xmm5, xmm6, xmm7;
352.3593 ++
352.3594 ++		xmm0 = xmm_load_128((const __m128i*)src + 0);
352.3595 ++		xmm1 = xmm_load_128((const __m128i*)src + 1);
352.3596 ++		xmm2 = xmm_load_128((const __m128i*)src + 2);
352.3597 ++		xmm3 = xmm_load_128((const __m128i*)src + 3);
352.3598 ++		xmm4 = xmm_load_128((const __m128i*)src + 4);
352.3599 ++		xmm5 = xmm_load_128((const __m128i*)src + 5);
352.3600 ++		xmm6 = xmm_load_128((const __m128i*)src + 6);
352.3601 ++		xmm7 = xmm_load_128((const __m128i*)src + 7);
352.3602 ++
352.3603 ++		xmm_save_128((__m128i*)dst + 0, xmm0);
352.3604 ++		xmm_save_128((__m128i*)dst + 1, xmm1);
352.3605 ++		xmm_save_128((__m128i*)dst + 2, xmm2);
352.3606 ++		xmm_save_128((__m128i*)dst + 3, xmm3);
352.3607 ++		xmm_save_128((__m128i*)dst + 4, xmm4);
352.3608 ++		xmm_save_128((__m128i*)dst + 5, xmm5);
352.3609 ++		xmm_save_128((__m128i*)dst + 6, xmm6);
352.3610 ++		xmm_save_128((__m128i*)dst + 7, xmm7);
352.3611 ++
352.3612 ++		dst += 128;
352.3613 ++		src += 128;
352.3614 ++	}
352.3615 ++}
352.3616 ++
352.3617 ++static force_inline void
352.3618 ++from_sse64u(uint8_t *dst, const uint8_t *src)
352.3619 ++{
352.3620 ++	__m128i xmm1, xmm2, xmm3, xmm4;
352.3621 ++
352.3622 ++	assert(((uintptr_t)src & 15) == 0);
352.3623 ++
352.3624 ++	xmm1 = xmm_load_128((const __m128i*)src + 0);
352.3625 ++	xmm2 = xmm_load_128((const __m128i*)src + 1);
352.3626 ++	xmm3 = xmm_load_128((const __m128i*)src + 2);
352.3627 ++	xmm4 = xmm_load_128((const __m128i*)src + 3);
352.3628 ++
352.3629 ++	xmm_save_128u((__m128i*)dst + 0, xmm1);
352.3630 ++	xmm_save_128u((__m128i*)dst + 1, xmm2);
352.3631 ++	xmm_save_128u((__m128i*)dst + 2, xmm3);
352.3632 ++	xmm_save_128u((__m128i*)dst + 3, xmm4);
352.3633 ++}
352.3634 ++
352.3635 ++static force_inline void
352.3636 ++from_sse64a(uint8_t *dst, const uint8_t *src)
352.3637 ++{
352.3638 ++	__m128i xmm1, xmm2, xmm3, xmm4;
352.3639 ++
352.3640 ++	assert(((uintptr_t)dst & 15) == 0);
352.3641 ++	assert(((uintptr_t)src & 15) == 0);
352.3642 ++
352.3643 ++	xmm1 = xmm_load_128((const __m128i*)src + 0);
352.3644 ++	xmm2 = xmm_load_128((const __m128i*)src + 1);
352.3645 ++	xmm3 = xmm_load_128((const __m128i*)src + 2);
352.3646 ++	xmm4 = xmm_load_128((const __m128i*)src + 3);
352.3647 ++
352.3648 ++	xmm_save_128((__m128i*)dst + 0, xmm1);
352.3649 ++	xmm_save_128((__m128i*)dst + 1, xmm2);
352.3650 ++	xmm_save_128((__m128i*)dst + 2, xmm3);
352.3651 ++	xmm_save_128((__m128i*)dst + 3, xmm4);
352.3652 ++}
352.3653 ++
352.3654 ++static force_inline void
352.3655 ++from_sse32u(uint8_t *dst, const uint8_t *src)
352.3656 ++{
352.3657 ++	__m128i xmm1, xmm2;
352.3658 ++
352.3659 ++	xmm1 = xmm_load_128((const __m128i*)src + 0);
352.3660 ++	xmm2 = xmm_load_128((const __m128i*)src + 1);
352.3661 ++
352.3662 ++	xmm_save_128u((__m128i*)dst + 0, xmm1);
352.3663 ++	xmm_save_128u((__m128i*)dst + 1, xmm2);
352.3664 ++}
352.3665 ++
352.3666 ++static force_inline void
352.3667 ++from_sse32a(uint8_t *dst, const uint8_t *src)
352.3668 ++{
352.3669 ++	__m128i xmm1, xmm2;
352.3670 ++
352.3671 ++	assert(((uintptr_t)dst & 15) == 0);
352.3672 ++	assert(((uintptr_t)src & 15) == 0);
352.3673 ++
352.3674 ++	xmm1 = xmm_load_128((const __m128i*)src + 0);
352.3675 ++	xmm2 = xmm_load_128((const __m128i*)src + 1);
352.3676 ++
352.3677 ++	xmm_save_128((__m128i*)dst + 0, xmm1);
352.3678 ++	xmm_save_128((__m128i*)dst + 1, xmm2);
352.3679 ++}
352.3680 ++
352.3681 ++static force_inline void
352.3682 ++from_sse16u(uint8_t *dst, const uint8_t *src)
352.3683 ++{
352.3684 ++	assert(((uintptr_t)src & 15) == 0);
352.3685 ++
352.3686 ++	xmm_save_128u((__m128i*)dst, xmm_load_128((const __m128i*)src));
352.3687 ++}
352.3688 ++
352.3689 ++static force_inline void
352.3690 ++from_sse16a(uint8_t *dst, const uint8_t *src)
352.3691 ++{
352.3692 ++	assert(((uintptr_t)dst & 15) == 0);
352.3693 ++	assert(((uintptr_t)src & 15) == 0);
352.3694 ++
352.3695 ++	xmm_save_128((__m128i*)dst, xmm_load_128((const __m128i*)src));
352.3696 ++}
352.3697 ++
352.3698 ++static void
352.3699 ++memcpy_from_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
352.3700 ++				     int32_t src_stride, int32_t dst_stride,
352.3701 ++				     int16_t src_x, int16_t src_y,
352.3702 ++				     int16_t dst_x, int16_t dst_y,
352.3703 ++				     uint16_t width, uint16_t height)
352.3704 ++{
352.3705 ++	const unsigned tile_width = 512;
352.3706 ++	const unsigned tile_height = 8;
352.3707 ++	const unsigned tile_size = 4096;
352.3708 ++
352.3709 ++	const unsigned cpp = bpp / 8;
352.3710 ++	const unsigned tile_pixels = tile_width / cpp;
352.3711 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.3712 ++	const unsigned tile_mask = tile_pixels - 1;
352.3713 ++
352.3714 ++	unsigned length_x, offset_x;
352.3715 ++
352.3716 ++	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.3717 ++	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.3718 ++	assert(src != dst);
352.3719 ++
352.3720 ++	if (dst_x | dst_y)
352.3721 ++		dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
352.3722 ++	width *= cpp;
352.3723 ++	assert(dst_stride >= width);
352.3724 ++	if (src_x & tile_mask) {
352.3725 ++		offset_x = (src_x & tile_mask) * cpp;
352.3726 ++		length_x = min(tile_width - offset_x, width);
352.3727 ++		dst_stride -= width;
352.3728 ++		dst_stride += (width - length_x) & 15;
352.3729 ++	} else {
352.3730 ++		offset_x = 0;
352.3731 ++		dst_stride -= width & ~15;
352.3732 ++	}
352.3733 ++	assert(dst_stride >= 0);
352.3734 ++	src = (const uint8_t *)src + (src_x >> tile_shift) * tile_size;
352.3735 ++
352.3736 ++	while (height--) {
352.3737 ++		unsigned w = width;
352.3738 ++		const uint8_t *tile_row = src;
352.3739 ++
352.3740 ++		tile_row += src_y / tile_height * src_stride * tile_height;
352.3741 ++		tile_row += (src_y & (tile_height-1)) * tile_width;
352.3742 ++		src_y++;
352.3743 ++
352.3744 ++		if (offset_x) {
352.3745 ++			memcpy(dst, tile_row + offset_x, length_x);
352.3746 ++			tile_row += tile_size;
352.3747 ++			dst = (uint8_t *)dst + length_x;
352.3748 ++			w -= length_x;
352.3749 ++		}
352.3750 ++
352.3751 ++		if ((uintptr_t)dst & 15) {
352.3752 ++			while (w >= tile_width) {
352.3753 ++				from_sse128xNu(dst,
352.3754 ++					       assume_aligned(tile_row, tile_width),
352.3755 ++					       tile_width);
352.3756 ++				tile_row += tile_size;
352.3757 ++				dst = (uint8_t *)dst + tile_width;
352.3758 ++				w -= tile_width;
352.3759 ++			}
352.3760 ++			while (w >= 64) {
352.3761 ++				from_sse64u(dst, tile_row);
352.3762 ++				tile_row += 64;
352.3763 ++				dst = (uint8_t *)dst + 64;
352.3764 ++				w -= 64;
352.3765 ++			}
352.3766 ++			if (w & 32) {
352.3767 ++				from_sse32u(dst, tile_row);
352.3768 ++				tile_row += 32;
352.3769 ++				dst = (uint8_t *)dst + 32;
352.3770 ++			}
352.3771 ++			if (w & 16) {
352.3772 ++				from_sse16u(dst, tile_row);
352.3773 ++				tile_row += 16;
352.3774 ++				dst = (uint8_t *)dst + 16;
352.3775 ++			}
352.3776 ++			memcpy(dst, assume_aligned(tile_row, 16), w & 15);
352.3777 ++		} else {
352.3778 ++			while (w >= tile_width) {
352.3779 ++				from_sse128xNa(assume_aligned(dst, 16),
352.3780 ++					       assume_aligned(tile_row, tile_width),
352.3781 ++					       tile_width);
352.3782 ++				tile_row += tile_size;
352.3783 ++				dst = (uint8_t *)dst + tile_width;
352.3784 ++				w -= tile_width;
352.3785 ++			}
352.3786 ++			while (w >= 64) {
352.3787 ++				from_sse64a(dst, tile_row);
352.3788 ++				tile_row += 64;
352.3789 ++				dst = (uint8_t *)dst + 64;
352.3790 ++				w -= 64;
352.3791 ++			}
352.3792 ++			if (w & 32) {
352.3793 ++				from_sse32a(dst, tile_row);
352.3794 ++				tile_row += 32;
352.3795 ++				dst = (uint8_t *)dst + 32;
352.3796 ++			}
352.3797 ++			if (w & 16) {
352.3798 ++				from_sse16a(dst, tile_row);
352.3799 ++				tile_row += 16;
352.3800 ++				dst = (uint8_t *)dst + 16;
352.3801 ++			}
352.3802 ++			memcpy(assume_aligned(dst, 16),
352.3803 ++			       assume_aligned(tile_row, 16),
352.3804 ++			       w & 15);
352.3805 ++		}
352.3806 ++		dst = (uint8_t *)dst + dst_stride;
352.3807 ++	}
352.3808 ++}
352.3809 ++
352.3810 ++static void
352.3811 ++memcpy_between_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
352.3812 ++					int32_t src_stride, int32_t dst_stride,
352.3813 ++					int16_t src_x, int16_t src_y,
352.3814 ++					int16_t dst_x, int16_t dst_y,
352.3815 ++					uint16_t width, uint16_t height)
352.3816 ++{
352.3817 ++	const unsigned tile_width = 512;
352.3818 ++	const unsigned tile_height = 8;
352.3819 ++	const unsigned tile_size = 4096;
352.3820 ++
352.3821 ++	const unsigned cpp = bpp / 8;
352.3822 ++	const unsigned tile_pixels = tile_width / cpp;
352.3823 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.3824 ++	const unsigned tile_mask = tile_pixels - 1;
352.3825 ++
352.3826 ++	unsigned ox, lx;
352.3827 ++
352.3828 ++	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.3829 ++	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.3830 ++	assert(src != dst);
352.3831 ++
352.3832 ++	width *= cpp;
352.3833 ++	dst_stride *= tile_height;
352.3834 ++	src_stride *= tile_height;
352.3835 ++
352.3836 ++	assert((dst_x & tile_mask) == (src_x & tile_mask));
352.3837 ++	if (dst_x & tile_mask) {
352.3838 ++		ox = (dst_x & tile_mask) * cpp;
352.3839 ++		lx = min(tile_width - ox, width);
352.3840 ++		assert(lx != 0);
352.3841 ++	} else
352.3842 ++		lx = 0;
352.3843 ++
352.3844 ++	if (dst_x)
352.3845 ++		dst = (uint8_t *)dst + (dst_x >> tile_shift) * tile_size;
352.3846 ++	if (src_x)
352.3847 ++		src = (const uint8_t *)src + (src_x >> tile_shift) * tile_size;
352.3848 ++
352.3849 ++	while (height--) {
352.3850 ++		const uint8_t *src_row;
352.3851 ++		uint8_t *dst_row;
352.3852 ++		unsigned w = width;
352.3853 ++
352.3854 ++		dst_row = dst;
352.3855 ++		dst_row += dst_y / tile_height * dst_stride;
352.3856 ++		dst_row += (dst_y & (tile_height-1)) * tile_width;
352.3857 ++		dst_y++;
352.3858 ++
352.3859 ++		src_row = src;
352.3860 ++		src_row += src_y / tile_height * src_stride;
352.3861 ++		src_row += (src_y & (tile_height-1)) * tile_width;
352.3862 ++		src_y++;
352.3863 ++
352.3864 ++		if (lx) {
352.3865 ++			to_memcpy(dst_row + ox, src_row + ox, lx);
352.3866 ++			dst_row += tile_size;
352.3867 ++			src_row += tile_size;
352.3868 ++			w -= lx;
352.3869 ++		}
352.3870 ++		while (w >= tile_width) {
352.3871 ++			assert(((uintptr_t)dst_row & (tile_width - 1)) == 0);
352.3872 ++			assert(((uintptr_t)src_row & (tile_width - 1)) == 0);
352.3873 ++			to_sse128xN(assume_aligned(dst_row, tile_width),
352.3874 ++				    assume_aligned(src_row, tile_width),
352.3875 ++				    tile_width);
352.3876 ++			dst_row += tile_size;
352.3877 ++			src_row += tile_size;
352.3878 ++			w -= tile_width;
352.3879 ++		}
352.3880 ++		if (w) {
352.3881 ++			assert(((uintptr_t)dst_row & (tile_width - 1)) == 0);
352.3882 ++			assert(((uintptr_t)src_row & (tile_width - 1)) == 0);
352.3883 ++			to_memcpy(assume_aligned(dst_row, tile_width),
352.3884 ++				  assume_aligned(src_row, tile_width),
352.3885 ++				  w);
352.3886 ++		}
352.3887 ++	}
352.3888 ++}
352.3889 ++
352.3890 ++#pragma GCC push_options
352.3891 + #endif
352.3892 + 
352.3893 + fast void
352.3894 +@@ -257,7 +753,8 @@ memcpy_to_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
352.3895 + 			if (dst_x & tile_mask) {
352.3896 + 				const unsigned x = (dst_x & tile_mask) * cpp;
352.3897 + 				const unsigned len = min(tile_width - x, w);
352.3898 +-				memcpy(tile_row + x, src, len);
352.3899 ++				memcpy(assume_misaligned(tile_row + x, tile_width, x),
352.3900 ++				       src, len);
352.3901 + 
352.3902 + 				tile_row += tile_size;
352.3903 + 				src = (const uint8_t *)src + len;
352.3904 +@@ -265,13 +762,13 @@ memcpy_to_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
352.3905 + 			}
352.3906 + 		}
352.3907 + 		while (w >= tile_width) {
352.3908 +-			memcpy(tile_row, src, tile_width);
352.3909 +-
352.3910 ++			memcpy(assume_aligned(tile_row, tile_width),
352.3911 ++			       src, tile_width);
352.3912 + 			tile_row += tile_size;
352.3913 + 			src = (const uint8_t *)src + tile_width;
352.3914 + 			w -= tile_width;
352.3915 + 		}
352.3916 +-		memcpy(tile_row, src, w);
352.3917 ++		memcpy(assume_aligned(tile_row, tile_width), src, w);
352.3918 + 		src = (const uint8_t *)src + src_stride + w;
352.3919 + 		dst_y++;
352.3920 + 	}
352.3921 +@@ -313,7 +810,7 @@ memcpy_from_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
352.3922 + 			if (src_x & tile_mask) {
352.3923 + 				const unsigned x = (src_x & tile_mask) * cpp;
352.3924 + 				const unsigned len = min(tile_width - x, w);
352.3925 +-				memcpy(dst, tile_row + x, len);
352.3926 ++				memcpy(dst, assume_misaligned(tile_row + x, tile_width, x), len);
352.3927 + 
352.3928 + 				tile_row += tile_size;
352.3929 + 				dst = (uint8_t *)dst + len;
352.3930 +@@ -321,440 +818,371 @@ memcpy_from_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
352.3931 + 			}
352.3932 + 		}
352.3933 + 		while (w >= tile_width) {
352.3934 +-			memcpy(dst, tile_row, tile_width);
352.3935 ++			memcpy(dst,
352.3936 ++			       assume_aligned(tile_row, tile_width),
352.3937 ++			       tile_width);
352.3938 + 
352.3939 + 			tile_row += tile_size;
352.3940 + 			dst = (uint8_t *)dst + tile_width;
352.3941 + 			w -= tile_width;
352.3942 + 		}
352.3943 +-		memcpy(dst, tile_row, w);
352.3944 ++		memcpy(dst, assume_aligned(tile_row, tile_width), w);
352.3945 + 		dst = (uint8_t *)dst + dst_stride + w;
352.3946 + 		src_y++;
352.3947 + 	}
352.3948 + }
352.3949 + 
352.3950 +-fast_memcpy static void
352.3951 +-memcpy_to_tiled_x__swizzle_9(const void *src, void *dst, int bpp,
352.3952 +-			     int32_t src_stride, int32_t dst_stride,
352.3953 +-			     int16_t src_x, int16_t src_y,
352.3954 +-			     int16_t dst_x, int16_t dst_y,
352.3955 +-			     uint16_t width, uint16_t height)
352.3956 ++static fast_memcpy void
352.3957 ++memcpy_between_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
352.3958 ++				  int32_t src_stride, int32_t dst_stride,
352.3959 ++				  int16_t src_x, int16_t src_y,
352.3960 ++				  int16_t dst_x, int16_t dst_y,
352.3961 ++				  uint16_t width, uint16_t height)
352.3962 + {
352.3963 + 	const unsigned tile_width = 512;
352.3964 + 	const unsigned tile_height = 8;
352.3965 + 	const unsigned tile_size = 4096;
352.3966 + 
352.3967 + 	const unsigned cpp = bpp / 8;
352.3968 +-	const unsigned stride_tiles = dst_stride / tile_width;
352.3969 +-	const unsigned swizzle_pixels = 64 / cpp;
352.3970 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.3971 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.3972 +-
352.3973 +-	unsigned x, y;
352.3974 ++	const unsigned tile_pixels = tile_width / cpp;
352.3975 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.3976 ++	const unsigned tile_mask = tile_pixels - 1;
352.3977 + 
352.3978 + 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.3979 + 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.3980 ++	assert(src != dst);
352.3981 ++	assert((dst_x & tile_mask) == (src_x & tile_mask));
352.3982 + 
352.3983 +-	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
352.3984 +-
352.3985 +-	for (y = 0; y < height; ++y) {
352.3986 +-		const uint32_t dy = y + dst_y;
352.3987 +-		const uint32_t tile_row =
352.3988 +-			(dy / tile_height * stride_tiles * tile_size +
352.3989 +-			 (dy & (tile_height-1)) * tile_width);
352.3990 +-		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
352.3991 +-		uint32_t dx = dst_x, offset;
352.3992 +-
352.3993 +-		x = width * cpp;
352.3994 +-		if (dx & (swizzle_pixels - 1)) {
352.3995 +-			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
352.3996 +-			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
352.3997 +-			offset = tile_row +
352.3998 +-				(dx >> tile_pixels) * tile_size +
352.3999 +-				(dx & tile_mask) * cpp;
352.4000 +-			offset ^= (offset >> 3) & 64;
352.4001 +-
352.4002 +-			memcpy((char *)dst + offset, src_row, length * cpp);
352.4003 +-
352.4004 +-			src_row += length * cpp;
352.4005 +-			x -= length * cpp;
352.4006 +-			dx += length;
352.4007 +-		}
352.4008 +-		while (x >= 64) {
352.4009 +-			offset = tile_row +
352.4010 +-				(dx >> tile_pixels) * tile_size +
352.4011 +-				(dx & tile_mask) * cpp;
352.4012 +-			offset ^= (offset >> 3) & 64;
352.4013 +-
352.4014 +-			memcpy((char *)dst + offset, src_row, 64);
352.4015 +-
352.4016 +-			src_row += 64;
352.4017 +-			x -= 64;
352.4018 +-			dx += swizzle_pixels;
352.4019 +-		}
352.4020 +-		if (x) {
352.4021 +-			offset = tile_row +
352.4022 +-				(dx >> tile_pixels) * tile_size +
352.4023 +-				(dx & tile_mask) * cpp;
352.4024 +-			offset ^= (offset >> 3) & 64;
352.4025 +-			memcpy((char *)dst + offset, src_row, x);
352.4026 +-		}
352.4027 +-	}
352.4028 +-}
352.4029 ++	while (height--) {
352.4030 ++		unsigned w = width * cpp;
352.4031 ++		uint8_t *dst_row = dst;
352.4032 ++		const uint8_t *src_row = src;
352.4033 + 
352.4034 +-fast_memcpy static void
352.4035 +-memcpy_from_tiled_x__swizzle_9(const void *src, void *dst, int bpp,
352.4036 +-			       int32_t src_stride, int32_t dst_stride,
352.4037 +-			       int16_t src_x, int16_t src_y,
352.4038 +-			       int16_t dst_x, int16_t dst_y,
352.4039 +-			       uint16_t width, uint16_t height)
352.4040 +-{
352.4041 +-	const unsigned tile_width = 512;
352.4042 +-	const unsigned tile_height = 8;
352.4043 +-	const unsigned tile_size = 4096;
352.4044 ++		dst_row += dst_y / tile_height * dst_stride * tile_height;
352.4045 ++		dst_row += (dst_y & (tile_height-1)) * tile_width;
352.4046 ++		if (dst_x)
352.4047 ++			dst_row += (dst_x >> tile_shift) * tile_size;
352.4048 ++		dst_y++;
352.4049 + 
352.4050 +-	const unsigned cpp = bpp / 8;
352.4051 +-	const unsigned stride_tiles = src_stride / tile_width;
352.4052 +-	const unsigned swizzle_pixels = 64 / cpp;
352.4053 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.4054 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.4055 ++		src_row += src_y / tile_height * src_stride * tile_height;
352.4056 ++		src_row += (src_y & (tile_height-1)) * tile_width;
352.4057 ++		if (src_x)
352.4058 ++			src_row += (src_x >> tile_shift) * tile_size;
352.4059 ++		src_y++;
352.4060 + 
352.4061 +-	unsigned x, y;
352.4062 ++		if (dst_x & tile_mask) {
352.4063 ++			const unsigned x = (dst_x & tile_mask) * cpp;
352.4064 ++			const unsigned len = min(tile_width - x, w);
352.4065 + 
352.4066 +-	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.4067 +-	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.4068 ++			memcpy(assume_misaligned(dst_row + x, tile_width, x),
352.4069 ++			       assume_misaligned(src_row + x, tile_width, x),
352.4070 ++			       len);
352.4071 + 
352.4072 +-	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
352.4073 +-
352.4074 +-	for (y = 0; y < height; ++y) {
352.4075 +-		const uint32_t sy = y + src_y;
352.4076 +-		const uint32_t tile_row =
352.4077 +-			(sy / tile_height * stride_tiles * tile_size +
352.4078 +-			 (sy & (tile_height-1)) * tile_width);
352.4079 +-		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
352.4080 +-		uint32_t sx = src_x, offset;
352.4081 +-
352.4082 +-		x = width * cpp;
352.4083 +-		if (sx & (swizzle_pixels - 1)) {
352.4084 +-			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
352.4085 +-			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
352.4086 +-			offset = tile_row +
352.4087 +-				(sx >> tile_pixels) * tile_size +
352.4088 +-				(sx & tile_mask) * cpp;
352.4089 +-			offset ^= (offset >> 3) & 64;
352.4090 +-
352.4091 +-			memcpy(dst_row, (const char *)src + offset, length * cpp);
352.4092 +-
352.4093 +-			dst_row += length * cpp;
352.4094 +-			x -= length * cpp;
352.4095 +-			sx += length;
352.4096 ++			dst_row += tile_size;
352.4097 ++			src_row += tile_size;
352.4098 ++			w -= len;
352.4099 + 		}
352.4100 +-		while (x >= 64) {
352.4101 +-			offset = tile_row +
352.4102 +-				(sx >> tile_pixels) * tile_size +
352.4103 +-				(sx & tile_mask) * cpp;
352.4104 +-			offset ^= (offset >> 3) & 64;
352.4105 + 
352.4106 +-			memcpy(dst_row, (const char *)src + offset, 64);
352.4107 +-
352.4108 +-			dst_row += 64;
352.4109 +-			x -= 64;
352.4110 +-			sx += swizzle_pixels;
352.4111 +-		}
352.4112 +-		if (x) {
352.4113 +-			offset = tile_row +
352.4114 +-				(sx >> tile_pixels) * tile_size +
352.4115 +-				(sx & tile_mask) * cpp;
352.4116 +-			offset ^= (offset >> 3) & 64;
352.4117 +-			memcpy(dst_row, (const char *)src + offset, x);
352.4118 ++		while (w >= tile_width) {
352.4119 ++			memcpy(assume_aligned(dst_row, tile_width),
352.4120 ++			       assume_aligned(src_row, tile_width),
352.4121 ++			       tile_width);
352.4122 ++			dst_row += tile_size;
352.4123 ++			src_row += tile_size;
352.4124 ++			w -= tile_width;
352.4125 + 		}
352.4126 ++		memcpy(assume_aligned(dst_row, tile_width),
352.4127 ++		       assume_aligned(src_row, tile_width),
352.4128 ++		       w);
352.4129 + 	}
352.4130 + }
352.4131 + 
352.4132 +-fast_memcpy static void
352.4133 +-memcpy_to_tiled_x__swizzle_9_10(const void *src, void *dst, int bpp,
352.4134 +-				int32_t src_stride, int32_t dst_stride,
352.4135 +-				int16_t src_x, int16_t src_y,
352.4136 +-				int16_t dst_x, int16_t dst_y,
352.4137 +-				uint16_t width, uint16_t height)
352.4138 +-{
352.4139 +-	const unsigned tile_width = 512;
352.4140 +-	const unsigned tile_height = 8;
352.4141 +-	const unsigned tile_size = 4096;
352.4142 +-
352.4143 +-	const unsigned cpp = bpp / 8;
352.4144 +-	const unsigned stride_tiles = dst_stride / tile_width;
352.4145 +-	const unsigned swizzle_pixels = 64 / cpp;
352.4146 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.4147 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.4148 ++#define memcpy_to_tiled_x(swizzle) \
352.4149 ++fast_memcpy static void \
352.4150 ++memcpy_to_tiled_x__##swizzle (const void *src, void *dst, int bpp, \
352.4151 ++			      int32_t src_stride, int32_t dst_stride, \
352.4152 ++			      int16_t src_x, int16_t src_y, \
352.4153 ++			      int16_t dst_x, int16_t dst_y, \
352.4154 ++			      uint16_t width, uint16_t height) \
352.4155 ++{ \
352.4156 ++	const unsigned tile_width = 512; \
352.4157 ++	const unsigned tile_height = 8; \
352.4158 ++	const unsigned tile_size = 4096; \
352.4159 ++	const unsigned cpp = bpp / 8; \
352.4160 ++	const unsigned stride_tiles = dst_stride / tile_width; \
352.4161 ++	const unsigned swizzle_pixels = 64 / cpp; \
352.4162 ++	const unsigned tile_pixels = ffs(tile_width / cpp) - 1; \
352.4163 ++	const unsigned tile_mask = (1 << tile_pixels) - 1; \
352.4164 ++	unsigned x, y; \
352.4165 ++	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n", \
352.4166 ++	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride)); \
352.4167 ++	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp; \
352.4168 ++	for (y = 0; y < height; ++y) { \
352.4169 ++		const uint32_t dy = y + dst_y; \
352.4170 ++		const uint32_t tile_row = \
352.4171 ++			(dy / tile_height * stride_tiles * tile_size + \
352.4172 ++			 (dy & (tile_height-1)) * tile_width); \
352.4173 ++		const uint8_t *src_row = (const uint8_t *)src + src_stride * y; \
352.4174 ++		uint32_t dx = dst_x; \
352.4175 ++		x = width * cpp; \
352.4176 ++		if (dx & (swizzle_pixels - 1)) { \
352.4177 ++			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels); \
352.4178 ++			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx; \
352.4179 ++			uint32_t offset = \
352.4180 ++				tile_row + \
352.4181 ++				(dx >> tile_pixels) * tile_size + \
352.4182 ++				(dx & tile_mask) * cpp; \
352.4183 ++			memcpy((char *)dst + swizzle(offset), src_row, length * cpp); \
352.4184 ++			src_row += length * cpp; \
352.4185 ++			x -= length * cpp; \
352.4186 ++			dx += length; \
352.4187 ++		} \
352.4188 ++		while (x >= 64) { \
352.4189 ++			uint32_t offset = \
352.4190 ++				tile_row + \
352.4191 ++				(dx >> tile_pixels) * tile_size + \
352.4192 ++				(dx & tile_mask) * cpp; \
352.4193 ++			memcpy(assume_aligned((char *)dst+swizzle(offset),64), \
352.4194 ++			       src_row, 64); \
352.4195 ++			src_row += 64; \
352.4196 ++			x -= 64; \
352.4197 ++			dx += swizzle_pixels; \
352.4198 ++		} \
352.4199 ++		if (x) { \
352.4200 ++			uint32_t offset = \
352.4201 ++				tile_row + \
352.4202 ++				(dx >> tile_pixels) * tile_size + \
352.4203 ++				(dx & tile_mask) * cpp; \
352.4204 ++			memcpy(assume_aligned((char *)dst + swizzle(offset), 64), src_row, x); \
352.4205 ++		} \
352.4206 ++	} \
352.4207 ++}
352.4208 + 
352.4209 +-	unsigned x, y;
352.4210 ++#define memcpy_from_tiled_x(swizzle) \
352.4211 ++fast_memcpy static void \
352.4212 ++memcpy_from_tiled_x__##swizzle (const void *src, void *dst, int bpp, \
352.4213 ++				int32_t src_stride, int32_t dst_stride, \
352.4214 ++				int16_t src_x, int16_t src_y, \
352.4215 ++				int16_t dst_x, int16_t dst_y, \
352.4216 ++				uint16_t width, uint16_t height) \
352.4217 ++{ \
352.4218 ++	const unsigned tile_width = 512; \
352.4219 ++	const unsigned tile_height = 8; \
352.4220 ++	const unsigned tile_size = 4096; \
352.4221 ++	const unsigned cpp = bpp / 8; \
352.4222 ++	const unsigned stride_tiles = src_stride / tile_width; \
352.4223 ++	const unsigned swizzle_pixels = 64 / cpp; \
352.4224 ++	const unsigned tile_pixels = ffs(tile_width / cpp) - 1; \
352.4225 ++	const unsigned tile_mask = (1 << tile_pixels) - 1; \
352.4226 ++	unsigned x, y; \
352.4227 ++	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n", \
352.4228 ++	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride)); \
352.4229 ++	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp; \
352.4230 ++	for (y = 0; y < height; ++y) { \
352.4231 ++		const uint32_t sy = y + src_y; \
352.4232 ++		const uint32_t tile_row = \
352.4233 ++			(sy / tile_height * stride_tiles * tile_size + \
352.4234 ++			 (sy & (tile_height-1)) * tile_width); \
352.4235 ++		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y; \
352.4236 ++		uint32_t sx = src_x; \
352.4237 ++		x = width * cpp; \
352.4238 ++		if (sx & (swizzle_pixels - 1)) { \
352.4239 ++			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels); \
352.4240 ++			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx; \
352.4241 ++			uint32_t offset = \
352.4242 ++				tile_row + \
352.4243 ++				(sx >> tile_pixels) * tile_size + \
352.4244 ++				(sx & tile_mask) * cpp; \
352.4245 ++			memcpy(dst_row, (const char *)src + swizzle(offset), length * cpp); \
352.4246 ++			dst_row += length * cpp; \
352.4247 ++			x -= length * cpp; \
352.4248 ++			sx += length; \
352.4249 ++		} \
352.4250 ++		while (x >= 64) { \
352.4251 ++			uint32_t offset = \
352.4252 ++				tile_row + \
352.4253 ++				(sx >> tile_pixels) * tile_size + \
352.4254 ++				(sx & tile_mask) * cpp; \
352.4255 ++			memcpy(dst_row, assume_aligned((const char *)src + swizzle(offset), 64), 64); \
352.4256 ++			dst_row += 64; \
352.4257 ++			x -= 64; \
352.4258 ++			sx += swizzle_pixels; \
352.4259 ++		} \
352.4260 ++		if (x) { \
352.4261 ++			uint32_t offset = \
352.4262 ++				tile_row + \
352.4263 ++				(sx >> tile_pixels) * tile_size + \
352.4264 ++				(sx & tile_mask) * cpp; \
352.4265 ++			memcpy(dst_row, assume_aligned((const char *)src + swizzle(offset), 64), x); \
352.4266 ++		} \
352.4267 ++	} \
352.4268 ++}
352.4269 + 
352.4270 +-	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.4271 +-	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.4272 ++#define swizzle_9(X) ((X) ^ (((X) >> 3) & 64))
352.4273 ++memcpy_to_tiled_x(swizzle_9)
352.4274 ++memcpy_from_tiled_x(swizzle_9)
352.4275 ++#undef swizzle_9
352.4276 + 
352.4277 +-	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
352.4278 +-
352.4279 +-	for (y = 0; y < height; ++y) {
352.4280 +-		const uint32_t dy = y + dst_y;
352.4281 +-		const uint32_t tile_row =
352.4282 +-			(dy / tile_height * stride_tiles * tile_size +
352.4283 +-			 (dy & (tile_height-1)) * tile_width);
352.4284 +-		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
352.4285 +-		uint32_t dx = dst_x, offset;
352.4286 +-
352.4287 +-		x = width * cpp;
352.4288 +-		if (dx & (swizzle_pixels - 1)) {
352.4289 +-			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
352.4290 +-			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
352.4291 +-			offset = tile_row +
352.4292 +-				(dx >> tile_pixels) * tile_size +
352.4293 +-				(dx & tile_mask) * cpp;
352.4294 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4295 +-
352.4296 +-			memcpy((char *)dst + offset, src_row, length * cpp);
352.4297 +-
352.4298 +-			src_row += length * cpp;
352.4299 +-			x -= length * cpp;
352.4300 +-			dx += length;
352.4301 +-		}
352.4302 +-		while (x >= 64) {
352.4303 +-			offset = tile_row +
352.4304 +-				(dx >> tile_pixels) * tile_size +
352.4305 +-				(dx & tile_mask) * cpp;
352.4306 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4307 ++#define swizzle_9_10(X) ((X) ^ ((((X) ^ ((X) >> 1)) >> 3) & 64))
352.4308 ++memcpy_to_tiled_x(swizzle_9_10)
352.4309 ++memcpy_from_tiled_x(swizzle_9_10)
352.4310 ++#undef swizzle_9_10
352.4311 + 
352.4312 +-			memcpy((char *)dst + offset, src_row, 64);
352.4313 ++#define swizzle_9_11(X) ((X) ^ ((((X) ^ ((X) >> 2)) >> 3) & 64))
352.4314 ++memcpy_to_tiled_x(swizzle_9_11)
352.4315 ++memcpy_from_tiled_x(swizzle_9_11)
352.4316 ++#undef swizzle_9_11
352.4317 + 
352.4318 +-			src_row += 64;
352.4319 +-			x -= 64;
352.4320 +-			dx += swizzle_pixels;
352.4321 +-		}
352.4322 +-		if (x) {
352.4323 +-			offset = tile_row +
352.4324 +-				(dx >> tile_pixels) * tile_size +
352.4325 +-				(dx & tile_mask) * cpp;
352.4326 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4327 +-			memcpy((char *)dst + offset, src_row, x);
352.4328 +-		}
352.4329 +-	}
352.4330 +-}
352.4331 ++#define swizzle_9_10_11(X) ((X) ^ ((((X) ^ ((X) >> 1) ^ ((X) >> 2)) >> 3) & 64))
352.4332 ++memcpy_to_tiled_x(swizzle_9_10_11)
352.4333 ++memcpy_from_tiled_x(swizzle_9_10_11)
352.4334 ++#undef swizzle_9_10_11
352.4335 + 
352.4336 +-fast_memcpy static void
352.4337 +-memcpy_from_tiled_x__swizzle_9_10(const void *src, void *dst, int bpp,
352.4338 +-				  int32_t src_stride, int32_t dst_stride,
352.4339 +-				  int16_t src_x, int16_t src_y,
352.4340 +-				  int16_t dst_x, int16_t dst_y,
352.4341 +-				  uint16_t width, uint16_t height)
352.4342 ++static fast_memcpy void
352.4343 ++memcpy_to_tiled_x__gen2(const void *src, void *dst, int bpp,
352.4344 ++			int32_t src_stride, int32_t dst_stride,
352.4345 ++			int16_t src_x, int16_t src_y,
352.4346 ++			int16_t dst_x, int16_t dst_y,
352.4347 ++			uint16_t width, uint16_t height)
352.4348 + {
352.4349 +-	const unsigned tile_width = 512;
352.4350 +-	const unsigned tile_height = 8;
352.4351 +-	const unsigned tile_size = 4096;
352.4352 ++	const unsigned tile_width = 128;
352.4353 ++	const unsigned tile_height = 16;
352.4354 ++	const unsigned tile_size = 2048;
352.4355 + 
352.4356 + 	const unsigned cpp = bpp / 8;
352.4357 +-	const unsigned stride_tiles = src_stride / tile_width;
352.4358 +-	const unsigned swizzle_pixels = 64 / cpp;
352.4359 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.4360 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.4361 +-
352.4362 +-	unsigned x, y;
352.4363 ++	const unsigned tile_pixels = tile_width / cpp;
352.4364 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.4365 ++	const unsigned tile_mask = tile_pixels - 1;
352.4366 + 
352.4367 + 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.4368 + 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.4369 ++	assert(src != dst);
352.4370 + 
352.4371 +-	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
352.4372 +-
352.4373 +-	for (y = 0; y < height; ++y) {
352.4374 +-		const uint32_t sy = y + src_y;
352.4375 +-		const uint32_t tile_row =
352.4376 +-			(sy / tile_height * stride_tiles * tile_size +
352.4377 +-			 (sy & (tile_height-1)) * tile_width);
352.4378 +-		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
352.4379 +-		uint32_t sx = src_x, offset;
352.4380 +-
352.4381 +-		x = width * cpp;
352.4382 +-		if (sx & (swizzle_pixels - 1)) {
352.4383 +-			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
352.4384 +-			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
352.4385 +-			offset = tile_row +
352.4386 +-				(sx >> tile_pixels) * tile_size +
352.4387 +-				(sx & tile_mask) * cpp;
352.4388 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4389 +-
352.4390 +-			memcpy(dst_row, (const char *)src + offset, length * cpp);
352.4391 +-
352.4392 +-			dst_row += length * cpp;
352.4393 +-			x -= length * cpp;
352.4394 +-			sx += length;
352.4395 +-		}
352.4396 +-		while (x >= 64) {
352.4397 +-			offset = tile_row +
352.4398 +-				(sx >> tile_pixels) * tile_size +
352.4399 +-				(sx & tile_mask) * cpp;
352.4400 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4401 +-
352.4402 +-			memcpy(dst_row, (const char *)src + offset, 64);
352.4403 +-
352.4404 +-			dst_row += 64;
352.4405 +-			x -= 64;
352.4406 +-			sx += swizzle_pixels;
352.4407 +-		}
352.4408 +-		if (x) {
352.4409 +-			offset = tile_row +
352.4410 +-				(sx >> tile_pixels) * tile_size +
352.4411 +-				(sx & tile_mask) * cpp;
352.4412 +-			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
352.4413 +-			memcpy(dst_row, (const char *)src + offset, x);
352.4414 +-		}
352.4415 +-	}
352.4416 +-}
352.4417 +-
352.4418 +-fast_memcpy static void
352.4419 +-memcpy_to_tiled_x__swizzle_9_11(const void *src, void *dst, int bpp,
352.4420 +-				int32_t src_stride, int32_t dst_stride,
352.4421 +-				int16_t src_x, int16_t src_y,
352.4422 +-				int16_t dst_x, int16_t dst_y,
352.4423 +-				uint16_t width, uint16_t height)
352.4424 +-{
352.4425 +-	const unsigned tile_width = 512;
352.4426 +-	const unsigned tile_height = 8;
352.4427 +-	const unsigned tile_size = 4096;
352.4428 +-
352.4429 +-	const unsigned cpp = bpp / 8;
352.4430 +-	const unsigned stride_tiles = dst_stride / tile_width;
352.4431 +-	const unsigned swizzle_pixels = 64 / cpp;
352.4432 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.4433 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.4434 ++	if (src_x | src_y)
352.4435 ++		src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
352.4436 ++	assert(src_stride >= width * cpp);
352.4437 ++	src_stride -= width * cpp;
352.4438 + 
352.4439 +-	unsigned x, y;
352.4440 ++	while (height--) {
352.4441 ++		unsigned w = width * cpp;
352.4442 ++		uint8_t *tile_row = dst;
352.4443 + 
352.4444 +-	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.4445 +-	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.4446 ++		tile_row += dst_y / tile_height * dst_stride * tile_height;
352.4447 ++		tile_row += (dst_y & (tile_height-1)) * tile_width;
352.4448 ++		if (dst_x) {
352.4449 ++			tile_row += (dst_x >> tile_shift) * tile_size;
352.4450 ++			if (dst_x & tile_mask) {
352.4451 ++				const unsigned x = (dst_x & tile_mask) * cpp;
352.4452 ++				const unsigned len = min(tile_width - x, w);
352.4453 ++				memcpy(assume_misaligned(tile_row + x, tile_width, x), src, len);
352.4454 + 
352.4455 +-	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
352.4456 +-
352.4457 +-	for (y = 0; y < height; ++y) {
352.4458 +-		const uint32_t dy = y + dst_y;
352.4459 +-		const uint32_t tile_row =
352.4460 +-			(dy / tile_height * stride_tiles * tile_size +
352.4461 +-			 (dy & (tile_height-1)) * tile_width);
352.4462 +-		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
352.4463 +-		uint32_t dx = dst_x, offset;
352.4464 +-
352.4465 +-		x = width * cpp;
352.4466 +-		if (dx & (swizzle_pixels - 1)) {
352.4467 +-			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
352.4468 +-			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
352.4469 +-			offset = tile_row +
352.4470 +-				(dx >> tile_pixels) * tile_size +
352.4471 +-				(dx & tile_mask) * cpp;
352.4472 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4473 +-			memcpy((char *)dst + offset, src_row, length * cpp);
352.4474 +-
352.4475 +-			src_row += length * cpp;
352.4476 +-			x -= length * cpp;
352.4477 +-			dx += length;
352.4478 ++				tile_row += tile_size;
352.4479 ++				src = (const uint8_t *)src + len;
352.4480 ++				w -= len;
352.4481 ++			}
352.4482 + 		}
352.4483 +-		while (x >= 64) {
352.4484 +-			offset = tile_row +
352.4485 +-				(dx >> tile_pixels) * tile_size +
352.4486 +-				(dx & tile_mask) * cpp;
352.4487 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4488 +-
352.4489 +-			memcpy((char *)dst + offset, src_row, 64);
352.4490 ++		while (w >= tile_width) {
352.4491 ++			memcpy(assume_aligned(tile_row, tile_width),
352.4492 ++			       src, tile_width);
352.4493 + 
352.4494 +-			src_row += 64;
352.4495 +-			x -= 64;
352.4496 +-			dx += swizzle_pixels;
352.4497 +-		}
352.4498 +-		if (x) {
352.4499 +-			offset = tile_row +
352.4500 +-				(dx >> tile_pixels) * tile_size +
352.4501 +-				(dx & tile_mask) * cpp;
352.4502 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4503 +-			memcpy((char *)dst + offset, src_row, x);
352.4504 ++			tile_row += tile_size;
352.4505 ++			src = (const uint8_t *)src + tile_width;
352.4506 ++			w -= tile_width;
352.4507 + 		}
352.4508 ++		memcpy(assume_aligned(tile_row, tile_width), src, w);
352.4509 ++		src = (const uint8_t *)src + src_stride + w;
352.4510 ++		dst_y++;
352.4511 + 	}
352.4512 + }
352.4513 + 
352.4514 +-fast_memcpy static void
352.4515 +-memcpy_from_tiled_x__swizzle_9_11(const void *src, void *dst, int bpp,
352.4516 +-				  int32_t src_stride, int32_t dst_stride,
352.4517 +-				  int16_t src_x, int16_t src_y,
352.4518 +-				  int16_t dst_x, int16_t dst_y,
352.4519 +-				  uint16_t width, uint16_t height)
352.4520 ++static fast_memcpy void
352.4521 ++memcpy_from_tiled_x__gen2(const void *src, void *dst, int bpp,
352.4522 ++			  int32_t src_stride, int32_t dst_stride,
352.4523 ++			  int16_t src_x, int16_t src_y,
352.4524 ++			  int16_t dst_x, int16_t dst_y,
352.4525 ++			  uint16_t width, uint16_t height)
352.4526 + {
352.4527 +-	const unsigned tile_width = 512;
352.4528 +-	const unsigned tile_height = 8;
352.4529 +-	const unsigned tile_size = 4096;
352.4530 ++	const unsigned tile_width = 128;
352.4531 ++	const unsigned tile_height = 16;
352.4532 ++	const unsigned tile_size = 2048;
352.4533 + 
352.4534 + 	const unsigned cpp = bpp / 8;
352.4535 +-	const unsigned stride_tiles = src_stride / tile_width;
352.4536 +-	const unsigned swizzle_pixels = 64 / cpp;
352.4537 +-	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
352.4538 +-	const unsigned tile_mask = (1 << tile_pixels) - 1;
352.4539 +-
352.4540 +-	unsigned x, y;
352.4541 ++	const unsigned tile_pixels = tile_width / cpp;
352.4542 ++	const unsigned tile_shift = ffs(tile_pixels) - 1;
352.4543 ++	const unsigned tile_mask = tile_pixels - 1;
352.4544 + 
352.4545 + 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
352.4546 + 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
352.4547 ++	assert(src != dst);
352.4548 + 
352.4549 +-	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
352.4550 +-
352.4551 +-	for (y = 0; y < height; ++y) {
352.4552 +-		const uint32_t sy = y + src_y;
352.4553 +-		const uint32_t tile_row =
352.4554 +-			(sy / tile_height * stride_tiles * tile_size +
352.4555 +-			 (sy & (tile_height-1)) * tile_width);
352.4556 +-		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
352.4557 +-		uint32_t sx = src_x, offset;
352.4558 +-
352.4559 +-		x = width * cpp;
352.4560 +-		if (sx & (swizzle_pixels - 1)) {
352.4561 +-			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
352.4562 +-			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
352.4563 +-			offset = tile_row +
352.4564 +-				(sx >> tile_pixels) * tile_size +
352.4565 +-				(sx & tile_mask) * cpp;
352.4566 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4567 +-			memcpy(dst_row, (const char *)src + offset, length * cpp);
352.4568 +-
352.4569 +-			dst_row += length * cpp;
352.4570 +-			x -= length * cpp;
352.4571 +-			sx += length;
352.4572 +-		}
352.4573 +-		while (x >= 64) {
352.4574 +-			offset = tile_row +
352.4575 +-				(sx >> tile_pixels) * tile_size +
352.4576 +-				(sx & tile_mask) * cpp;
352.4577 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4578 ++	if (dst_x | dst_y)
352.4579 ++		dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
352.4580 ++	assert(dst_stride >= width * cpp);
352.4581 ++	dst_stride -= width * cpp;
352.4582 ++
352.4583 ++	while (height--) {
352.4584 ++		unsigned w = width * cpp;
352.4585 ++		const uint8_t *tile_row = src;
352.4586 + 
352.4587 +-			memcpy(dst_row, (const char *)src + offset, 64);
352.4588 ++		tile_row += src_y / tile_height * src_stride * tile_height;
352.4589 ++		tile_row += (src_y & (tile_height-1)) * tile_width;
352.4590 ++		if (src_x) {
352.4591 ++			tile_row += (src_x >> tile_shift) * tile_size;
352.4592 ++			if (src_x & tile_mask) {
352.4593 ++				const unsigned x = (src_x & tile_mask) * cpp;
352.4594 ++				const unsigned len = min(tile_width - x, w);
352.4595 ++				memcpy(dst, assume_misaligned(tile_row + x, tile_width, x), len);
352.4596 + 
352.4597 +-			dst_row += 64;
352.4598 +-			x -= 64;
352.4599 +-			sx += swizzle_pixels;
352.4600 ++				tile_row += tile_size;
352.4601 ++				dst = (uint8_t *)dst + len;
352.4602 ++				w -= len;
352.4603 ++			}
352.4604 + 		}
352.4605 +-		if (x) {
352.4606 +-			offset = tile_row +
352.4607 +-				(sx >> tile_pixels) * tile_size +
352.4608 +-				(sx & tile_mask) * cpp;
352.4609 +-			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
352.4610 +-			memcpy(dst_row, (const char *)src + offset, x);
352.4611 ++		while (w >= tile_width) {
352.4612 ++			memcpy(dst,
352.4613 ++			       assume_aligned(tile_row, tile_width),
352.4614 ++			       tile_width);
352.4615 ++
352.4616 ++			tile_row += tile_size;
352.4617 ++			dst = (uint8_t *)dst + tile_width;
352.4618 ++			w -= tile_width;
352.4619 + 		}
352.4620 ++		memcpy(dst, assume_aligned(tile_row, tile_width), w);
352.4621 ++		dst = (uint8_t *)dst + dst_stride + w;
352.4622 ++		src_y++;
352.4623 + 	}
352.4624 + }
352.4625 + 
352.4626 +-void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling)
352.4627 ++void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling, unsigned cpu)
352.4628 + {
352.4629 ++	if (kgem->gen < 030) {
352.4630 ++		if (swizzling == I915_BIT_6_SWIZZLE_NONE) {
352.4631 ++			DBG(("%s: gen2, no swizzling\n", __FUNCTION__));
352.4632 ++			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__gen2;
352.4633 ++			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__gen2;
352.4634 ++		} else
352.4635 ++			DBG(("%s: no detiling with swizzle functions for gen2\n", __FUNCTION__));
352.4636 ++		return;
352.4637 ++	}
352.4638 ++
352.4639 + 	switch (swizzling) {
352.4640 + 	default:
352.4641 + 		DBG(("%s: unknown swizzling, %d\n", __FUNCTION__, swizzling));
352.4642 + 		break;
352.4643 + 	case I915_BIT_6_SWIZZLE_NONE:
352.4644 + 		DBG(("%s: no swizzling\n", __FUNCTION__));
352.4645 +-		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0;
352.4646 +-		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0;
352.4647 ++#if defined(sse2)
352.4648 ++		if (cpu & SSE2) {
352.4649 ++			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0__sse2;
352.4650 ++			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0__sse2;
352.4651 ++			kgem->memcpy_between_tiled_x = memcpy_between_tiled_x__swizzle_0__sse2;
352.4652 ++		} else
352.4653 ++#endif
352.4654 ++	       	{
352.4655 ++			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0;
352.4656 ++			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0;
352.4657 ++			kgem->memcpy_between_tiled_x = memcpy_between_tiled_x__swizzle_0;
352.4658 ++		}
352.4659 + 		break;
352.4660 + 	case I915_BIT_6_SWIZZLE_9:
352.4661 + 		DBG(("%s: 6^9 swizzling\n", __FUNCTION__));
352.4662 +@@ -771,6 +1199,11 @@ void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling)
352.4663 + 		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_9_11;
352.4664 + 		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_9_11;
352.4665 + 		break;
352.4666 ++	case I915_BIT_6_SWIZZLE_9_10_11:
352.4667 ++		DBG(("%s: 6^9^10^11 swizzling\n", __FUNCTION__));
352.4668 ++		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_9_10_11;
352.4669 ++		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_9_10_11;
352.4670 ++		break;
352.4671 + 	}
352.4672 + }
352.4673 + 
352.4674 +@@ -995,7 +1428,7 @@ memcpy_xor(const void *src, void *dst, int bpp,
352.4675 + 				height = 1;
352.4676 + 			}
352.4677 + 
352.4678 +-#if USE_SSE2
352.4679 ++#if defined(sse2) && __x86_64__
352.4680 + 			if (have_sse2()) {
352.4681 + 				do {
352.4682 + 					uint32_t *d = (uint32_t *)dst_bytes;
352.4683 +@@ -1118,3 +1551,241 @@ memcpy_xor(const void *src, void *dst, int bpp,
352.4684 + 		}
352.4685 + 	}
352.4686 + }
352.4687 ++
352.4688 ++#define BILINEAR_INTERPOLATION_BITS 4
352.4689 ++static inline int
352.4690 ++bilinear_weight(pixman_fixed_t x)
352.4691 ++{
352.4692 ++	return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) &
352.4693 ++		((1 << BILINEAR_INTERPOLATION_BITS) - 1);
352.4694 ++}
352.4695 ++
352.4696 ++#if BILINEAR_INTERPOLATION_BITS <= 4
352.4697 ++/* Inspired by Filter_32_opaque from Skia */
352.4698 ++static inline uint32_t
352.4699 ++bilinear_interpolation(uint32_t tl, uint32_t tr,
352.4700 ++		       uint32_t bl, uint32_t br,
352.4701 ++		       int distx, int disty)
352.4702 ++{
352.4703 ++	int distxy, distxiy, distixy, distixiy;
352.4704 ++	uint32_t lo, hi;
352.4705 ++
352.4706 ++	distx <<= (4 - BILINEAR_INTERPOLATION_BITS);
352.4707 ++	disty <<= (4 - BILINEAR_INTERPOLATION_BITS);
352.4708 ++
352.4709 ++	distxy = distx * disty;
352.4710 ++	distxiy = (distx << 4) - distxy;	/* distx * (16 - disty) */
352.4711 ++	distixy = (disty << 4) - distxy;	/* disty * (16 - distx) */
352.4712 ++	distixiy =
352.4713 ++		16 * 16 - (disty << 4) -
352.4714 ++		(distx << 4) + distxy; /* (16 - distx) * (16 - disty) */
352.4715 ++
352.4716 ++	lo = (tl & 0xff00ff) * distixiy;
352.4717 ++	hi = ((tl >> 8) & 0xff00ff) * distixiy;
352.4718 ++
352.4719 ++	lo += (tr & 0xff00ff) * distxiy;
352.4720 ++	hi += ((tr >> 8) & 0xff00ff) * distxiy;
352.4721 ++
352.4722 ++	lo += (bl & 0xff00ff) * distixy;
352.4723 ++	hi += ((bl >> 8) & 0xff00ff) * distixy;
352.4724 ++
352.4725 ++	lo += (br & 0xff00ff) * distxy;
352.4726 ++	hi += ((br >> 8) & 0xff00ff) * distxy;
352.4727 ++
352.4728 ++	return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff);
352.4729 ++}
352.4730 ++#elif SIZEOF_LONG > 4
352.4731 ++static inline uint32_t
352.4732 ++bilinear_interpolation(uint32_t tl, uint32_t tr,
352.4733 ++		       uint32_t bl, uint32_t br,
352.4734 ++		       int distx, int disty)
352.4735 ++{
352.4736 ++	uint64_t distxy, distxiy, distixy, distixiy;
352.4737 ++	uint64_t tl64, tr64, bl64, br64;
352.4738 ++	uint64_t f, r;
352.4739 ++
352.4740 ++	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
352.4741 ++	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
352.4742 ++
352.4743 ++	distxy = distx * disty;
352.4744 ++	distxiy = distx * (256 - disty);
352.4745 ++	distixy = (256 - distx) * disty;
352.4746 ++	distixiy = (256 - distx) * (256 - disty);
352.4747 ++
352.4748 ++	/* Alpha and Blue */
352.4749 ++	tl64 = tl & 0xff0000ff;
352.4750 ++	tr64 = tr & 0xff0000ff;
352.4751 ++	bl64 = bl & 0xff0000ff;
352.4752 ++	br64 = br & 0xff0000ff;
352.4753 ++
352.4754 ++	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
352.4755 ++	r = f & 0x0000ff0000ff0000ull;
352.4756 ++
352.4757 ++	/* Red and Green */
352.4758 ++	tl64 = tl;
352.4759 ++	tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
352.4760 ++
352.4761 ++	tr64 = tr;
352.4762 ++	tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
352.4763 ++
352.4764 ++	bl64 = bl;
352.4765 ++	bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
352.4766 ++
352.4767 ++	br64 = br;
352.4768 ++	br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
352.4769 ++
352.4770 ++	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
352.4771 ++	r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
352.4772 ++
352.4773 ++	return (uint32_t)(r >> 16);
352.4774 ++}
352.4775 ++#else
352.4776 ++static inline uint32_t
352.4777 ++bilinear_interpolation(uint32_t tl, uint32_t tr,
352.4778 ++		       uint32_t bl, uint32_t br,
352.4779 ++		       int distx, int disty)
352.4780 ++{
352.4781 ++	int distxy, distxiy, distixy, distixiy;
352.4782 ++	uint32_t f, r;
352.4783 ++
352.4784 ++	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
352.4785 ++	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
352.4786 ++
352.4787 ++	distxy = distx * disty;
352.4788 ++	distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
352.4789 ++	distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
352.4790 ++	distixiy =
352.4791 ++		256 * 256 - (disty << 8) -
352.4792 ++		(distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */
352.4793 ++
352.4794 ++	/* Blue */
352.4795 ++	r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
352.4796 ++	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
352.4797 ++
352.4798 ++	/* Green */
352.4799 ++	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
352.4800 ++	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
352.4801 ++	r |= f & 0xff000000;
352.4802 ++
352.4803 ++	tl >>= 16;
352.4804 ++	tr >>= 16;
352.4805 ++	bl >>= 16;
352.4806 ++	br >>= 16;
352.4807 ++	r >>= 16;
352.4808 ++
352.4809 ++	/* Red */
352.4810 ++	f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
352.4811 ++	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
352.4812 ++	r |= f & 0x00ff0000;
352.4813 ++
352.4814 ++	/* Alpha */
352.4815 ++	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
352.4816 ++	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
352.4817 ++	r |= f & 0xff000000;
352.4818 ++
352.4819 ++	return r;
352.4820 ++}
352.4821 ++#endif
352.4822 ++
352.4823 ++static inline uint32_t convert_pixel(const uint8_t *p, int x)
352.4824 ++{
352.4825 ++	return ((uint32_t *)p)[x];
352.4826 ++}
352.4827 ++
352.4828 ++fast void
352.4829 ++affine_blt(const void *src, void *dst, int bpp,
352.4830 ++	   int16_t src_x, int16_t src_y,
352.4831 ++	   int16_t src_width, int16_t src_height,
352.4832 ++	   int32_t src_stride,
352.4833 ++	   int16_t dst_x, int16_t dst_y,
352.4834 ++	   uint16_t dst_width, uint16_t dst_height,
352.4835 ++	   int32_t dst_stride,
352.4836 ++	   const struct pixman_f_transform *t)
352.4837 ++{
352.4838 ++	static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
352.4839 ++	const pixman_fixed_t ux = pixman_double_to_fixed(t->m[0][0]);
352.4840 ++	const pixman_fixed_t uy = pixman_double_to_fixed(t->m[1][0]);
352.4841 ++	int i, j;
352.4842 ++
352.4843 ++	assert(bpp == 32);
352.4844 ++
352.4845 ++	for (j = 0; j < dst_height; j++) {
352.4846 ++		pixman_fixed_t x, y;
352.4847 ++		struct pixman_f_vector v;
352.4848 ++		uint32_t *b;
352.4849 ++
352.4850 ++		/* reference point is the center of the pixel */
352.4851 ++		v.v[0] = dst_x + 0.5;
352.4852 ++		v.v[1] = dst_y + j + 0.5;
352.4853 ++		v.v[2] = 1.0;
352.4854 ++
352.4855 ++		pixman_f_transform_point_3d(t, &v);
352.4856 ++
352.4857 ++		x = pixman_double_to_fixed(v.v[0]);
352.4858 ++		x += pixman_int_to_fixed(src_x - dst_x);
352.4859 ++		y = pixman_double_to_fixed(v.v[1]);
352.4860 ++		y +=  pixman_int_to_fixed(src_y - dst_y);
352.4861 ++
352.4862 ++		b = (uint32_t*)((uint8_t *)dst + (dst_y + j) * dst_stride + dst_x * bpp / 8);
352.4863 ++		for (i = 0; i < dst_width; i++) {
352.4864 ++			const uint8_t *row1;
352.4865 ++			const uint8_t *row2;
352.4866 ++			int x1, y1, x2, y2;
352.4867 ++			uint32_t tl, tr, bl, br;
352.4868 ++			int32_t fx, fy;
352.4869 ++
352.4870 ++			x1 = x - pixman_fixed_1/2;
352.4871 ++			y1 = y - pixman_fixed_1/2;
352.4872 ++
352.4873 ++			fx = bilinear_weight(x1);
352.4874 ++			fy = bilinear_weight(y1);
352.4875 ++
352.4876 ++			x1 = pixman_fixed_to_int(x1);
352.4877 ++			x2 = x1 + 1;
352.4878 ++			y1 = pixman_fixed_to_int(y1);
352.4879 ++			y2 = y1 + 1;
352.4880 ++
352.4881 ++			if (x1 >= src_width  || x2 < 0 ||
352.4882 ++			    y1 >= src_height || y2 < 0) {
352.4883 ++				b[i] = 0;
352.4884 ++				goto next;
352.4885 ++			}
352.4886 ++
352.4887 ++			if (y2 == 0) {
352.4888 ++				row1 = zero;
352.4889 ++			} else {
352.4890 ++				row1 = (uint8_t *)src + src_stride * y1;
352.4891 ++				row1 += bpp / 8 * x1;
352.4892 ++			}
352.4893 ++
352.4894 ++			if (y1 == src_height - 1) {
352.4895 ++				row2 = zero;
352.4896 ++			} else {
352.4897 ++				row2 = (uint8_t *)src + src_stride * y2;
352.4898 ++				row2 += bpp / 8 * x1;
352.4899 ++			}
352.4900 ++
352.4901 ++			if (x2 == 0) {
352.4902 ++				tl = 0;
352.4903 ++				bl = 0;
352.4904 ++			} else {
352.4905 ++				tl = convert_pixel(row1, 0);
352.4906 ++				bl = convert_pixel(row2, 0);
352.4907 ++			}
352.4908 ++
352.4909 ++			if (x1 == src_width - 1) {
352.4910 ++				tr = 0;
352.4911 ++				br = 0;
352.4912 ++			} else {
352.4913 ++				tr = convert_pixel(row1, 1);
352.4914 ++				br = convert_pixel(row2, 1);
352.4915 ++			}
352.4916 ++
352.4917 ++			b[i] = bilinear_interpolation(tl, tr, bl, br, fx, fy);
352.4918 ++
352.4919 ++next:
352.4920 ++			x += ux;
352.4921 ++			y += uy;
352.4922 ++		}
352.4923 ++	}
352.4924 ++}
352.4925 +diff --git a/src/sna/brw/brw_eu_emit.c b/src/sna/brw/brw_eu_emit.c
352.4926 +index 00c984d9..154f939a 100644
352.4927 +--- a/src/sna/brw/brw_eu_emit.c
352.4928 ++++ b/src/sna/brw/brw_eu_emit.c
352.4929 +@@ -178,7 +178,7 @@ validate_reg(struct brw_instruction *insn, struct brw_reg reg)
352.4930 + 	}
352.4931 + 
352.4932 + 	if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
352.4933 +-	    reg.file == BRW_ARF_NULL)
352.4934 ++	    reg.nr == BRW_ARF_NULL)
352.4935 + 		return;
352.4936 + 
352.4937 + 	assert(reg.hstride >= 0 && reg.hstride < ARRAY_SIZE(hstride_for_reg));
352.4938 +@@ -700,7 +700,7 @@ push_if_stack(struct brw_compile *p, struct brw_instruction *inst)
352.4939 +  *
352.4940 +  * When the matching 'else' instruction is reached (presumably by
352.4941 +  * countdown of the instruction count patched in by our ELSE/ENDIF
352.4942 +- * functions), the relevent flags are inverted.
352.4943 ++ * functions), the relevant flags are inverted.
352.4944 +  *
352.4945 +  * When the matching 'endif' instruction is reached, the flags are
352.4946 +  * popped off.  If the stack is now empty, normal execution resumes.
352.4947 +diff --git a/src/sna/compiler.h b/src/sna/compiler.h
352.4948 +index ff412179..0f3775ec 100644
352.4949 +--- a/src/sna/compiler.h
352.4950 ++++ b/src/sna/compiler.h
352.4951 +@@ -39,6 +39,7 @@
352.4952 + #define pure __attribute__((pure))
352.4953 + #define tightly_packed __attribute__((__packed__))
352.4954 + #define flatten __attribute__((flatten))
352.4955 ++#define nonnull __attribute__((nonnull))
352.4956 + #define page_aligned __attribute__((aligned(4096)))
352.4957 + #else
352.4958 + #define likely(expr) (expr)
352.4959 +@@ -51,18 +52,15 @@
352.4960 + #define pure
352.4961 + #define tighly_packed
352.4962 + #define flatten
352.4963 ++#define nonnull
352.4964 + #define page_aligned
352.4965 + #endif
352.4966 + 
352.4967 + #define HAS_GCC(major, minor) defined(__GNUC__) && (__GNUC__ > (major) || __GNUC__ == (major) && __GNUC_MINOR__ >= (minor))
352.4968 + 
352.4969 + #if HAS_GCC(4, 5)
352.4970 +-#define sse2 __attribute__((target("sse2,fpmath=sse")))
352.4971 +-#define sse4_2 __attribute__((target("sse4.2,sse2,fpmath=sse")))
352.4972 +-#endif
352.4973 +-
352.4974 +-#if HAS_GCC(4, 7)
352.4975 +-#define avx2 __attribute__((target("avx2,sse4.2,sse2,fpmath=sse")))
352.4976 ++#define sse2 fast __attribute__((target("sse2,fpmath=sse")))
352.4977 ++#define sse4_2 fast __attribute__((target("sse4.2,sse2,fpmath=sse")))
352.4978 + #endif
352.4979 + 
352.4980 + #if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
352.4981 +@@ -71,10 +69,17 @@
352.4982 + #define fast
352.4983 + #endif
352.4984 + 
352.4985 +-#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
352.4986 +-#define fast_memcpy __attribute__((optimize("Ofast"))) __attribute__((target("inline-all-stringops")))
352.4987 +-#elif HAS_GCC(4, 5) && defined(__OPTIMIZE__)
352.4988 +-#define fast_memcpy __attribute__((target("inline-all-stringops")))
352.4989 ++#if HAS_GCC(4, 7)
352.4990 ++#define avx2 fast __attribute__((target("avx2,avx,sse4.2,sse2,fpmath=sse")))
352.4991 ++#define assume_aligned(ptr, align) __builtin_assume_aligned((ptr), (align))
352.4992 ++#define assume_misaligned(ptr, align, offset) __builtin_assume_aligned((ptr), (align), (offset))
352.4993 ++#else
352.4994 ++#define assume_aligned(ptr, align) (ptr)
352.4995 ++#define assume_misaligned(ptr, align, offset) (ptr)
352.4996 ++#endif
352.4997 ++
352.4998 ++#if HAS_GCC(4, 5) && defined(__OPTIMIZE__)
352.4999 ++#define fast_memcpy fast __attribute__((target("inline-all-stringops")))
352.5000 + #else
352.5001 + #define fast_memcpy
352.5002 + #endif
352.5003 +diff --git a/src/sna/fb/fb.h b/src/sna/fb/fb.h
352.5004 +index 8bf9008a..90431747 100644
352.5005 +--- a/src/sna/fb/fb.h
352.5006 ++++ b/src/sna/fb/fb.h
352.5007 +@@ -24,10 +24,6 @@
352.5008 + #ifndef FB_H
352.5009 + #define FB_H
352.5010 + 
352.5011 +-#ifdef HAVE_CONFIG_H
352.5012 +-#include "config.h"
352.5013 +-#endif
352.5014 +-
352.5015 + #include <xorg-server.h>
352.5016 + #include <servermd.h>
352.5017 + #include <gcstruct.h>
352.5018 +diff --git a/src/sna/fb/fbimage.c b/src/sna/fb/fbimage.c
352.5019 +index 5af23890..cc81c85b 100644
352.5020 +--- a/src/sna/fb/fbimage.c
352.5021 ++++ b/src/sna/fb/fbimage.c
352.5022 +@@ -229,13 +229,19 @@ fbGetImage(DrawablePtr drawable,
352.5023 + 		FbBits pm;
352.5024 + 
352.5025 + 		pm = fbReplicatePixel(planeMask, srcBpp);
352.5026 ++
352.5027 + 		dstStride = PixmapBytePad(w, drawable->depth);
352.5028 +-		if (pm != FB_ALLONES)
352.5029 +-			memset(d, 0, dstStride * h);
352.5030 + 		dstStride /= sizeof(FbStip);
352.5031 ++
352.5032 + 		fbBltStip((FbStip *)(src + (y + srcYoff) * srcStride), srcStride,
352.5033 + 			  (x + srcXoff) * srcBpp,
352.5034 +-			  dst, dstStride, 0, w * srcBpp, h, GXcopy, pm, srcBpp);
352.5035 ++			  dst, dstStride, 0, w * srcBpp, h, GXcopy, FB_ALLONES, srcBpp);
352.5036 ++
352.5037 ++		if (pm != FB_ALLONES) {
352.5038 ++			int i = dstStride * h;
352.5039 ++			while (i--)
352.5040 ++				*dst++ &= pm;
352.5041 ++		}
352.5042 + 	} else {
352.5043 + 		dstStride = BitmapBytePad(w) / sizeof(FbStip);
352.5044 + 		fbBltPlane(src + (y + srcYoff) * srcStride,
352.5045 +diff --git a/src/sna/fb/fbpict.h b/src/sna/fb/fbpict.h
352.5046 +index 932032f9..20877777 100644
352.5047 +--- a/src/sna/fb/fbpict.h
352.5048 ++++ b/src/sna/fb/fbpict.h
352.5049 +@@ -24,10 +24,6 @@
352.5050 + #ifndef FBPICT_H
352.5051 + #define FBPICT_H
352.5052 + 
352.5053 +-#ifdef HAVE_CONFIG_H
352.5054 +-#include "config.h"
352.5055 +-#endif
352.5056 +-
352.5057 + #include <xorg-server.h>
352.5058 + #include <picturestr.h>
352.5059 + 
352.5060 +diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
352.5061 +index 1104f462..49ad16a3 100644
352.5062 +--- a/src/sna/gen2_render.c
352.5063 ++++ b/src/sna/gen2_render.c
352.5064 +@@ -35,6 +35,7 @@
352.5065 + #include "sna_reg.h"
352.5066 + #include "sna_render.h"
352.5067 + #include "sna_render_inline.h"
352.5068 ++#include "sna_video.h"
352.5069 + 
352.5070 + #include "gen2_render.h"
352.5071 + 
352.5072 +@@ -48,6 +49,7 @@
352.5073 + 
352.5074 + #define MAX_3D_SIZE 2048
352.5075 + #define MAX_3D_PITCH 8192
352.5076 ++#define MAX_INLINE (1 << 18)
352.5077 + 
352.5078 + #define BATCH(v) batch_emit(sna, v)
352.5079 + #define BATCH_F(v) batch_emit_float(sna, v)
352.5080 +@@ -596,39 +598,43 @@ gen2_get_batch(struct sna *sna, const struct sna_composite_op *op)
352.5081 + 		gen2_emit_invariant(sna);
352.5082 + }
352.5083 + 
352.5084 +-static void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op)
352.5085 ++static void gen2_emit_target(struct sna *sna,
352.5086 ++			     struct kgem_bo *bo,
352.5087 ++			     int width,
352.5088 ++			     int height,
352.5089 ++			     int format)
352.5090 + {
352.5091 +-	assert(!too_large(op->dst.width, op->dst.height));
352.5092 +-	assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= MAX_3D_PITCH);
352.5093 ++	assert(!too_large(width, height));
352.5094 ++	assert(bo->pitch >= 8 && bo->pitch <= MAX_3D_PITCH);
352.5095 + 	assert(sna->render.vertex_offset == 0);
352.5096 + 
352.5097 +-	assert(op->dst.bo->unique_id);
352.5098 +-	if (sna->render_state.gen2.target == op->dst.bo->unique_id) {
352.5099 +-		kgem_bo_mark_dirty(op->dst.bo);
352.5100 ++	assert(bo->unique_id);
352.5101 ++	if (sna->render_state.gen2.target == bo->unique_id) {
352.5102 ++		kgem_bo_mark_dirty(bo);
352.5103 + 		return;
352.5104 + 	}
352.5105 + 
352.5106 + 	BATCH(_3DSTATE_BUF_INFO_CMD);
352.5107 + 	BATCH(BUF_3D_ID_COLOR_BACK |
352.5108 +-	      gen2_buf_tiling(op->dst.bo->tiling) |
352.5109 +-	      BUF_3D_PITCH(op->dst.bo->pitch));
352.5110 ++	      gen2_buf_tiling(bo->tiling) |
352.5111 ++	      BUF_3D_PITCH(bo->pitch));
352.5112 + 	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
352.5113 +-			     op->dst.bo,
352.5114 ++			     bo,
352.5115 + 			     I915_GEM_DOMAIN_RENDER << 16 |
352.5116 + 			     I915_GEM_DOMAIN_RENDER,
352.5117 + 			     0));
352.5118 + 
352.5119 + 	BATCH(_3DSTATE_DST_BUF_VARS_CMD);
352.5120 +-	BATCH(gen2_get_dst_format(op->dst.format));
352.5121 ++	BATCH(gen2_get_dst_format(format));
352.5122 + 
352.5123 + 	BATCH(_3DSTATE_DRAW_RECT_CMD);
352.5124 + 	BATCH(0);
352.5125 + 	BATCH(0);	/* ymin, xmin */
352.5126 +-	BATCH(DRAW_YMAX(op->dst.height - 1) |
352.5127 +-	      DRAW_XMAX(op->dst.width - 1));
352.5128 ++	BATCH(DRAW_YMAX(height - 1) |
352.5129 ++	      DRAW_XMAX(width - 1));
352.5130 + 	BATCH(0);	/* yorig, xorig */
352.5131 + 
352.5132 +-	sna->render_state.gen2.target = op->dst.bo->unique_id;
352.5133 ++	sna->render_state.gen2.target = bo->unique_id;
352.5134 + }
352.5135 + 
352.5136 + static void gen2_disable_logic_op(struct sna *sna)
352.5137 +@@ -701,7 +707,11 @@ static void gen2_emit_composite_state(struct sna *sna,
352.5138 + 		kgem_clear_dirty(&sna->kgem);
352.5139 + 	}
352.5140 + 
352.5141 +-	gen2_emit_target(sna, op);
352.5142 ++	gen2_emit_target(sna,
352.5143 ++			 op->dst.bo,
352.5144 ++			 op->dst.width,
352.5145 ++			 op->dst.height,
352.5146 ++			 op->dst.format);
352.5147 + 
352.5148 + 	unwind = sna->kgem.nbatch;
352.5149 + 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5150 +@@ -1190,7 +1200,13 @@ inline static int gen2_get_rectangles(struct sna *sna,
352.5151 + 			sna->render.vertex_offset = sna->kgem.nbatch;
352.5152 + 			BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST);
352.5153 + 		}
352.5154 +-	}
352.5155 ++
352.5156 ++		need = 0;
352.5157 ++	} else
352.5158 ++		need = sna->kgem.nbatch - sna->render.vertex_offset;
352.5159 ++
352.5160 ++	if (rem > MAX_INLINE - need)
352.5161 ++		rem = MAX_INLINE -need;
352.5162 + 
352.5163 + 	if (want > 1 && want * size > rem)
352.5164 + 		want = rem / size;
352.5165 +@@ -1572,12 +1588,12 @@ gen2_composite_picture(struct sna *sna,
352.5166 + 		if (channel->repeat &&
352.5167 + 		    (x >= 0 &&
352.5168 + 		     y >= 0 &&
352.5169 +-		     x + w < pixmap->drawable.width &&
352.5170 +-		     y + h < pixmap->drawable.height)) {
352.5171 ++		     x + w <= pixmap->drawable.width &&
352.5172 ++		     y + h <= pixmap->drawable.height)) {
352.5173 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.5174 + 			if (priv && priv->clear) {
352.5175 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.5176 +-				return gen2_composite_solid_init(sna, channel, priv->clear_color);
352.5177 ++				return gen2_composite_solid_init(sna, channel, solid_color(picture->format, priv->clear_color));
352.5178 + 			}
352.5179 + 		}
352.5180 + 	} else
352.5181 +@@ -1619,7 +1635,9 @@ gen2_composite_set_target(struct sna *sna,
352.5182 + 	} else
352.5183 + 		sna_render_picture_extents(dst, &box);
352.5184 + 
352.5185 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.5186 ++	hint = PREFER_GPU | RENDER_GPU;
352.5187 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.5188 ++		hint |= FORCE_GPU;
352.5189 + 	if (!partial) {
352.5190 + 		hint |= IGNORE_DAMAGE;
352.5191 + 		if (w == op->dst.width && h == op->dst.height)
352.5192 +@@ -2423,7 +2441,11 @@ static void gen2_emit_composite_spans_state(struct sna *sna,
352.5193 + 	uint32_t unwind;
352.5194 + 
352.5195 + 	gen2_get_batch(sna, &op->base);
352.5196 +-	gen2_emit_target(sna, &op->base);
352.5197 ++	gen2_emit_target(sna,
352.5198 ++			 op->base.dst.bo,
352.5199 ++			 op->base.dst.width,
352.5200 ++			 op->base.dst.height,
352.5201 ++			 op->base.dst.format);
352.5202 + 
352.5203 + 	unwind = sna->kgem.nbatch;
352.5204 + 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5205 +@@ -2706,7 +2728,11 @@ static void gen2_emit_fill_composite_state(struct sna *sna,
352.5206 + 	uint32_t ls1;
352.5207 + 
352.5208 + 	gen2_get_batch(sna, op);
352.5209 +-	gen2_emit_target(sna, op);
352.5210 ++	gen2_emit_target(sna,
352.5211 ++			 op->dst.bo,
352.5212 ++			 op->dst.width,
352.5213 ++			 op->dst.height,
352.5214 ++			 op->dst.format);
352.5215 + 
352.5216 + 	ls1 = sna->kgem.nbatch;
352.5217 + 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5218 +@@ -2868,7 +2894,11 @@ static void gen2_emit_fill_state(struct sna *sna,
352.5219 + 	uint32_t ls1;
352.5220 + 
352.5221 + 	gen2_get_batch(sna, op);
352.5222 +-	gen2_emit_target(sna, op);
352.5223 ++	gen2_emit_target(sna,
352.5224 ++			 op->dst.bo,
352.5225 ++			 op->dst.width,
352.5226 ++			 op->dst.height,
352.5227 ++			 op->dst.format);
352.5228 + 
352.5229 + 	ls1 = sna->kgem.nbatch;
352.5230 + 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5231 +@@ -3102,6 +3132,276 @@ gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
352.5232 + }
352.5233 + 
352.5234 + static void
352.5235 ++gen2_emit_video_state(struct sna *sna,
352.5236 ++		      struct sna_video *video,
352.5237 ++		      struct sna_video_frame *frame,
352.5238 ++		      PixmapPtr pixmap,
352.5239 ++		      struct kgem_bo *dst_bo,
352.5240 ++		      int width, int height,
352.5241 ++		      bool bilinear)
352.5242 ++{
352.5243 ++	uint32_t ms1, v, unwind;
352.5244 ++
352.5245 ++	gen2_emit_target(sna, dst_bo, width, height,
352.5246 ++			 sna_format_for_depth(pixmap->drawable.depth));
352.5247 ++
352.5248 ++	unwind = sna->kgem.nbatch;
352.5249 ++	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5250 ++	      I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
352.5251 ++	BATCH(1 << 12);
352.5252 ++	BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
352.5253 ++	BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
352.5254 ++	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
352.5255 ++		   sna->kgem.batch + unwind + 1,
352.5256 ++		   3 * sizeof(uint32_t)) == 0)
352.5257 ++		sna->kgem.nbatch = unwind;
352.5258 ++	else
352.5259 ++		sna->render_state.gen2.ls1 = unwind;
352.5260 ++
352.5261 ++	gen2_disable_logic_op(sna);
352.5262 ++
352.5263 ++	unwind = sna->kgem.nbatch;
352.5264 ++	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
352.5265 ++	      LOAD_TEXTURE_BLEND_STAGE(0) | 1);
352.5266 ++	BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT |
352.5267 ++	      TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0);
352.5268 ++	BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT |
352.5269 ++	      TB0A_OP_ARG1 | TB0A_ARG1_SEL_ONE);
352.5270 ++	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
352.5271 ++		   sna->kgem.batch + unwind + 1,
352.5272 ++		   2 * sizeof(uint32_t)) == 0)
352.5273 ++		sna->kgem.nbatch = unwind;
352.5274 ++	else
352.5275 ++		sna->render_state.gen2.ls2 = unwind;
352.5276 ++
352.5277 ++	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(0) | 4);
352.5278 ++	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
352.5279 ++			     frame->bo,
352.5280 ++			     I915_GEM_DOMAIN_SAMPLER << 16,
352.5281 ++			     0));
352.5282 ++	ms1 = MAPSURF_422 | TM0S1_COLORSPACE_CONVERSION;
352.5283 ++	switch (frame->id) {
352.5284 ++	case FOURCC_YUY2:
352.5285 ++		ms1 |= MT_422_YCRCB_NORMAL;
352.5286 ++		break;
352.5287 ++	case FOURCC_UYVY:
352.5288 ++		ms1 |= MT_422_YCRCB_SWAPY;
352.5289 ++		break;
352.5290 ++	}
352.5291 ++	BATCH(((frame->height - 1) << TM0S1_HEIGHT_SHIFT) |
352.5292 ++	      ((frame->width - 1)  << TM0S1_WIDTH_SHIFT) |
352.5293 ++	      ms1 |
352.5294 ++	      gen2_sampler_tiling_bits(frame->bo->tiling));
352.5295 ++	BATCH((frame->pitch[0] / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
352.5296 ++	if (bilinear)
352.5297 ++		BATCH(FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT |
352.5298 ++		      FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT |
352.5299 ++		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
352.5300 ++	else
352.5301 ++		BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
352.5302 ++		      FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
352.5303 ++		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
352.5304 ++	BATCH(0);	/* default color */
352.5305 ++
352.5306 ++	BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(0) |
352.5307 ++	      ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | TEXCOORDTYPE_CARTESIAN |
352.5308 ++	      ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
352.5309 ++	      ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
352.5310 ++
352.5311 ++	v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D;
352.5312 ++	if (sna->render_state.gen2.vft != v) {
352.5313 ++		BATCH(v);
352.5314 ++		sna->render_state.gen2.vft = v;
352.5315 ++	}
352.5316 ++}
352.5317 ++
352.5318 ++static void
352.5319 ++gen2_video_get_batch(struct sna *sna, struct kgem_bo *bo)
352.5320 ++{
352.5321 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
352.5322 ++
352.5323 ++	if (!kgem_check_batch(&sna->kgem, 120) ||
352.5324 ++	    !kgem_check_reloc(&sna->kgem, 4) ||
352.5325 ++	    !kgem_check_exec(&sna->kgem, 2)) {
352.5326 ++		_kgem_submit(&sna->kgem);
352.5327 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.5328 ++	}
352.5329 ++
352.5330 ++	if (sna->render_state.gen2.need_invariant)
352.5331 ++		gen2_emit_invariant(sna);
352.5332 ++}
352.5333 ++
352.5334 ++static int
352.5335 ++gen2_get_inline_rectangles(struct sna *sna, int want, int floats_per_vertex)
352.5336 ++{
352.5337 ++	int size = floats_per_vertex * 3;
352.5338 ++	int rem = batch_space(sna) - 1;
352.5339 ++
352.5340 ++	if (rem > MAX_INLINE)
352.5341 ++		rem = MAX_INLINE;
352.5342 ++
352.5343 ++	if (size * want > rem)
352.5344 ++		want = rem / size;
352.5345 ++
352.5346 ++	return want;
352.5347 ++}
352.5348 ++
352.5349 ++static bool
352.5350 ++gen2_render_video(struct sna *sna,
352.5351 ++		  struct sna_video *video,
352.5352 ++		  struct sna_video_frame *frame,
352.5353 ++		  RegionPtr dstRegion,
352.5354 ++		  PixmapPtr pixmap)
352.5355 ++{
352.5356 ++	struct sna_pixmap *priv = sna_pixmap(pixmap);
352.5357 ++	const BoxRec *pbox = region_rects(dstRegion);
352.5358 ++	int nbox = region_num_rects(dstRegion);
352.5359 ++	int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
352.5360 ++	int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
352.5361 ++	int src_width = frame->src.x2 - frame->src.x1;
352.5362 ++	int src_height = frame->src.y2 - frame->src.y1;
352.5363 ++	float src_offset_x, src_offset_y;
352.5364 ++	float src_scale_x, src_scale_y;
352.5365 ++	int pix_xoff, pix_yoff;
352.5366 ++	struct kgem_bo *dst_bo;
352.5367 ++	bool bilinear;
352.5368 ++	int copy = 0;
352.5369 ++
352.5370 ++	DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__,
352.5371 ++	     src_width, src_height, frame->width, frame->height, dst_width, dst_height));
352.5372 ++
352.5373 ++	assert(priv->gpu_bo);
352.5374 ++	dst_bo = priv->gpu_bo;
352.5375 ++
352.5376 ++	bilinear = src_width != dst_width || src_height != dst_height;
352.5377 ++
352.5378 ++	src_scale_x = (float)src_width / dst_width / frame->width;
352.5379 ++	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
352.5380 ++
352.5381 ++	src_scale_y = (float)src_height / dst_height / frame->height;
352.5382 ++	src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
352.5383 ++	DBG(("%s: src offset (%f, %f), scale (%f, %f)\n",
352.5384 ++	     __FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y));
352.5385 ++
352.5386 ++	if (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
352.5387 ++	    dst_bo->pitch > MAX_3D_PITCH) {
352.5388 ++		int bpp = pixmap->drawable.bitsPerPixel;
352.5389 ++
352.5390 ++		if (too_large(dst_width, dst_height))
352.5391 ++			return false;
352.5392 ++
352.5393 ++		dst_bo = kgem_create_2d(&sna->kgem,
352.5394 ++					dst_width, dst_height, bpp,
352.5395 ++					kgem_choose_tiling(&sna->kgem,
352.5396 ++							   I915_TILING_X,
352.5397 ++							   dst_width, dst_height, bpp),
352.5398 ++					0);
352.5399 ++		if (!dst_bo)
352.5400 ++			return false;
352.5401 ++
352.5402 ++		pix_xoff = -dstRegion->extents.x1;
352.5403 ++		pix_yoff = -dstRegion->extents.y1;
352.5404 ++		copy = 1;
352.5405 ++	} else {
352.5406 ++		/* Set up the offset for translating from the given region
352.5407 ++		 * (in screen coordinates) to the backing pixmap.
352.5408 ++		 */
352.5409 ++#ifdef COMPOSITE
352.5410 ++		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.5411 ++		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.5412 ++#else
352.5413 ++		pix_xoff = 0;
352.5414 ++		pix_yoff = 0;
352.5415 ++#endif
352.5416 ++
352.5417 ++		dst_width  = pixmap->drawable.width;
352.5418 ++		dst_height = pixmap->drawable.height;
352.5419 ++	}
352.5420 ++
352.5421 ++	gen2_video_get_batch(sna, dst_bo);
352.5422 ++	gen2_emit_video_state(sna, video, frame, pixmap,
352.5423 ++			      dst_bo, dst_width, dst_height, bilinear);
352.5424 ++	do {
352.5425 ++		int nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
352.5426 ++		if (nbox_this_time == 0) {
352.5427 ++			gen2_video_get_batch(sna, dst_bo);
352.5428 ++			gen2_emit_video_state(sna, video, frame, pixmap,
352.5429 ++					      dst_bo, dst_width, dst_height, bilinear);
352.5430 ++			nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
352.5431 ++			assert(nbox_this_time);
352.5432 ++		}
352.5433 ++		nbox -= nbox_this_time;
352.5434 ++
352.5435 ++		BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST |
352.5436 ++		      ((12 * nbox_this_time) - 1));
352.5437 ++		do {
352.5438 ++			int box_x1 = pbox->x1;
352.5439 ++			int box_y1 = pbox->y1;
352.5440 ++			int box_x2 = pbox->x2;
352.5441 ++			int box_y2 = pbox->y2;
352.5442 ++
352.5443 ++			pbox++;
352.5444 ++
352.5445 ++			DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n",
352.5446 ++			     __FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff,
352.5447 ++			     box_x1 * src_scale_x + src_offset_x,
352.5448 ++			     box_y1 * src_scale_y + src_offset_y,
352.5449 ++			     box_x2 * src_scale_x + src_offset_x,
352.5450 ++			     box_y2 * src_scale_y + src_offset_y));
352.5451 ++
352.5452 ++			/* bottom right */
352.5453 ++			BATCH_F(box_x2 + pix_xoff);
352.5454 ++			BATCH_F(box_y2 + pix_yoff);
352.5455 ++			BATCH_F(box_x2 * src_scale_x + src_offset_x);
352.5456 ++			BATCH_F(box_y2 * src_scale_y + src_offset_y);
352.5457 ++
352.5458 ++			/* bottom left */
352.5459 ++			BATCH_F(box_x1 + pix_xoff);
352.5460 ++			BATCH_F(box_y2 + pix_yoff);
352.5461 ++			BATCH_F(box_x1 * src_scale_x + src_offset_x);
352.5462 ++			BATCH_F(box_y2 * src_scale_y + src_offset_y);
352.5463 ++
352.5464 ++			/* top left */
352.5465 ++			BATCH_F(box_x1 + pix_xoff);
352.5466 ++			BATCH_F(box_y1 + pix_yoff);
352.5467 ++			BATCH_F(box_x1 * src_scale_x + src_offset_x);
352.5468 ++			BATCH_F(box_y1 * src_scale_y + src_offset_y);
352.5469 ++		} while (--nbox_this_time);
352.5470 ++	} while (nbox);
352.5471 ++
352.5472 ++	if (copy) {
352.5473 ++#ifdef COMPOSITE
352.5474 ++		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.5475 ++		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.5476 ++#else
352.5477 ++		pix_xoff = 0;
352.5478 ++		pix_yoff = 0;
352.5479 ++#endif
352.5480 ++		sna_blt_copy_boxes(sna, GXcopy,
352.5481 ++				   dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
352.5482 ++				   priv->gpu_bo, pix_xoff, pix_yoff,
352.5483 ++				   pixmap->drawable.bitsPerPixel,
352.5484 ++				   region_rects(dstRegion),
352.5485 ++				   region_num_rects(dstRegion));
352.5486 ++
352.5487 ++		kgem_bo_destroy(&sna->kgem, dst_bo);
352.5488 ++	}
352.5489 ++
352.5490 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.5491 ++		if ((pix_xoff | pix_yoff) == 0) {
352.5492 ++			sna_damage_add(&priv->gpu_damage, dstRegion);
352.5493 ++		} else {
352.5494 ++			sna_damage_add_boxes(&priv->gpu_damage,
352.5495 ++					     region_rects(dstRegion),
352.5496 ++					     region_num_rects(dstRegion),
352.5497 ++					     pix_xoff, pix_yoff);
352.5498 ++		}
352.5499 ++	}
352.5500 ++
352.5501 ++	return true;
352.5502 ++}
352.5503 ++
352.5504 ++static void
352.5505 + gen2_render_copy_setup_source(struct sna_composite_channel *channel,
352.5506 + 			      const DrawableRec *draw,
352.5507 + 			      struct kgem_bo *bo)
352.5508 +@@ -3176,7 +3476,11 @@ static void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op
352.5509 + 			      PIPELINE_FLUSH_TEXTURE_CACHE);
352.5510 + 		kgem_clear_dirty(&sna->kgem);
352.5511 + 	}
352.5512 +-	gen2_emit_target(sna, op);
352.5513 ++	gen2_emit_target(sna,
352.5514 ++			 op->dst.bo,
352.5515 ++			 op->dst.width,
352.5516 ++			 op->dst.height,
352.5517 ++			 op->dst.format);
352.5518 + 
352.5519 + 	ls1 = sna->kgem.nbatch;
352.5520 + 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
352.5521 +@@ -3511,7 +3815,7 @@ const char *gen2_render_init(struct sna *sna, const char *backend)
352.5522 + 	render->copy = gen2_render_copy;
352.5523 + 	render->copy_boxes = gen2_render_copy_boxes;
352.5524 + 
352.5525 +-	/* XXX YUV color space conversion for video? */
352.5526 ++	render->video = gen2_render_video;
352.5527 + 
352.5528 + 	render->reset = gen2_render_reset;
352.5529 + 	render->flush = gen2_render_flush;
352.5530 +diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
352.5531 +index 78289f00..4459a562 100644
352.5532 +--- a/src/sna/gen3_render.c
352.5533 ++++ b/src/sna/gen3_render.c
352.5534 +@@ -448,14 +448,14 @@ gen3_emit_composite_boxes_constant(const struct sna_composite_op *op,
352.5535 + 				   float *v)
352.5536 + {
352.5537 + 	do {
352.5538 +-		v[0] = box->x2;
352.5539 +-		v[1] = box->y2;
352.5540 ++		v[0] = box->x2 + op->dst.x;
352.5541 ++		v[1] = box->y2 + op->dst.y;
352.5542 + 
352.5543 +-		v[2] = box->x1;
352.5544 +-		v[3] = box->y2;
352.5545 ++		v[2] = box->x1 + op->dst.x;
352.5546 ++		v[3] = box->y2 + op->dst.y;
352.5547 + 
352.5548 +-		v[4] = box->x1;
352.5549 +-		v[5] = box->y1;
352.5550 ++		v[4] = box->x1 + op->dst.x;
352.5551 ++		v[5] = box->y1 + op->dst.y;
352.5552 + 
352.5553 + 		box++;
352.5554 + 		v += 6;
352.5555 +@@ -494,18 +494,18 @@ gen3_emit_composite_boxes_identity_gradient(const struct sna_composite_op *op,
352.5556 + 					    float *v)
352.5557 + {
352.5558 + 	do {
352.5559 +-		v[0] = box->x2;
352.5560 +-		v[1] = box->y2;
352.5561 ++		v[0] = box->x2 + op->dst.x;
352.5562 ++		v[1] = box->y2 + op->dst.y;
352.5563 + 		v[2] = box->x2 + op->src.offset[0];
352.5564 + 		v[3] = box->y2 + op->src.offset[1];
352.5565 + 
352.5566 +-		v[4] = box->x1;
352.5567 +-		v[5] = box->y2;
352.5568 ++		v[4] = box->x1 + op->dst.x;
352.5569 ++		v[5] = box->y2 + op->dst.y;
352.5570 + 		v[6] = box->x1 + op->src.offset[0];
352.5571 + 		v[7] = box->y2 + op->src.offset[1];
352.5572 + 
352.5573 +-		v[8] = box->x1;
352.5574 +-		v[9] = box->y1;
352.5575 ++		v[8] = box->x1 + op->dst.x;
352.5576 ++		v[9] = box->y1 + op->dst.y;
352.5577 + 		v[10] = box->x1 + op->src.offset[0];
352.5578 + 		v[11] = box->y1 + op->src.offset[1];
352.5579 + 
352.5580 +@@ -531,6 +531,7 @@ gen3_emit_composite_primitive_affine_gradient(struct sna *sna,
352.5581 + 
352.5582 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5583 + 	sna->render.vertex_used += 12;
352.5584 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5585 + 
352.5586 + 	v[0] = dst_x + r->width;
352.5587 + 	v[1] = dst_y + r->height;
352.5588 +@@ -559,22 +560,22 @@ gen3_emit_composite_boxes_affine_gradient(const struct sna_composite_op *op,
352.5589 + 	const PictTransform *transform = op->src.transform;
352.5590 + 
352.5591 + 	do {
352.5592 +-		v[0] = box->x2;
352.5593 +-		v[1] = box->y2;
352.5594 ++		v[0] = box->x2 + op->dst.x;
352.5595 ++		v[1] = box->y2 + op->dst.y;
352.5596 + 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
352.5597 + 					    box->y2 + op->src.offset[1],
352.5598 + 					    transform, op->src.scale,
352.5599 + 					    &v[2], &v[3]);
352.5600 + 
352.5601 +-		v[4] = box->x1;
352.5602 +-		v[5] = box->y2;
352.5603 ++		v[4] = box->x1 + op->dst.x;
352.5604 ++		v[5] = box->y2 + op->dst.y;
352.5605 + 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
352.5606 + 					    box->y2 + op->src.offset[1],
352.5607 + 					    transform, op->src.scale,
352.5608 + 					    &v[6], &v[7]);
352.5609 + 
352.5610 +-		v[8] = box->x1;
352.5611 +-		v[9] = box->y1;
352.5612 ++		v[8] = box->x1 + op->dst.x;
352.5613 ++		v[9] = box->y1 + op->dst.y;
352.5614 + 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
352.5615 + 					    box->y1 + op->src.offset[1],
352.5616 + 					    transform, op->src.scale,
352.5617 +@@ -596,6 +597,7 @@ gen3_emit_composite_primitive_identity_source(struct sna *sna,
352.5618 + 
352.5619 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5620 + 	sna->render.vertex_used += 12;
352.5621 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5622 + 
352.5623 + 	v[8] = v[4] = r->dst.x + op->dst.x;
352.5624 + 	v[0] = v[4] + w;
352.5625 +@@ -643,6 +645,7 @@ gen3_emit_composite_primitive_identity_source_no_offset(struct sna *sna,
352.5626 + 
352.5627 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5628 + 	sna->render.vertex_used += 12;
352.5629 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5630 + 
352.5631 + 	v[8] = v[4] = r->dst.x;
352.5632 + 	v[9] = r->dst.y;
352.5633 +@@ -693,6 +696,7 @@ gen3_emit_composite_primitive_affine_source(struct sna *sna,
352.5634 + 
352.5635 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5636 + 	sna->render.vertex_used += 12;
352.5637 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5638 + 
352.5639 + 	v[0] = dst_x + r->width;
352.5640 + 	v[5] = v[1] = dst_y + r->height;
352.5641 +@@ -720,10 +724,10 @@ gen3_emit_composite_boxes_affine_source(const struct sna_composite_op *op,
352.5642 + 	const PictTransform *transform = op->src.transform;
352.5643 + 
352.5644 + 	do {
352.5645 +-		v[0] = box->x2;
352.5646 +-		v[5] = v[1] = box->y2;
352.5647 +-		v[8] = v[4] = box->x1;
352.5648 +-		v[9] = box->y1;
352.5649 ++		v[0] = box->x2 + op->dst.x;
352.5650 ++		v[5] = v[1] = box->y2 + op->dst.y;
352.5651 ++		v[8] = v[4] = box->x1 + op->dst.x;
352.5652 ++		v[9] = box->y1 + op->dst.y;
352.5653 + 
352.5654 + 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
352.5655 + 					    box->y2 + op->src.offset[1],
352.5656 +@@ -756,6 +760,7 @@ gen3_emit_composite_primitive_constant_identity_mask(struct sna *sna,
352.5657 + 
352.5658 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5659 + 	sna->render.vertex_used += 12;
352.5660 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5661 + 
352.5662 + 	v[8] = v[4] = r->dst.x + op->dst.x;
352.5663 + 	v[0] = v[4] + w;
352.5664 +@@ -781,6 +786,7 @@ gen3_emit_composite_primitive_constant_identity_mask_no_offset(struct sna *sna,
352.5665 + 
352.5666 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5667 + 	sna->render.vertex_used += 12;
352.5668 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5669 + 
352.5670 + 	v[8] = v[4] = r->dst.x;
352.5671 + 	v[9] = r->dst.y;
352.5672 +@@ -817,6 +823,7 @@ gen3_emit_composite_primitive_identity_source_mask(struct sna *sna,
352.5673 + 
352.5674 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5675 + 	sna->render.vertex_used += 18;
352.5676 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5677 + 
352.5678 + 	v[0] = dst_x + w;
352.5679 + 	v[1] = dst_y + h;
352.5680 +@@ -862,6 +869,7 @@ gen3_emit_composite_primitive_affine_source_mask(struct sna *sna,
352.5681 + 
352.5682 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5683 + 	sna->render.vertex_used += 18;
352.5684 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5685 + 
352.5686 + 	v[0] = dst_x + w;
352.5687 + 	v[1] = dst_y + h;
352.5688 +@@ -978,6 +986,7 @@ gen3_emit_composite_primitive_constant__sse2(struct sna *sna,
352.5689 + 
352.5690 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5691 + 	sna->render.vertex_used += 6;
352.5692 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5693 + 
352.5694 + 	v[4] = v[2] = r->dst.x + op->dst.x;
352.5695 + 	v[5] = r->dst.y + op->dst.y;
352.5696 +@@ -993,10 +1002,10 @@ gen3_emit_composite_boxes_constant__sse2(const struct sna_composite_op *op,
352.5697 + 					 float *v)
352.5698 + {
352.5699 + 	do {
352.5700 +-		v[0] = box->x2;
352.5701 +-		v[3] = v[1] = box->y2;
352.5702 +-		v[4] = v[2] = box->x1;
352.5703 +-		v[5] = box->y1;
352.5704 ++		v[0] = box->x2 + op->dst.x;
352.5705 ++		v[3] = v[1] = box->y2 + op->dst.y;
352.5706 ++		v[4] = v[2] = box->x1 + op->dst.x;
352.5707 ++		v[5] = box->y1 + op->dst.y;
352.5708 + 
352.5709 + 		box++;
352.5710 + 		v += 6;
352.5711 +@@ -1013,6 +1022,7 @@ gen3_emit_composite_primitive_identity_gradient__sse2(struct sna *sna,
352.5712 + 
352.5713 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5714 + 	sna->render.vertex_used += 12;
352.5715 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5716 + 
352.5717 + 	x = r->dst.x + op->dst.x;
352.5718 + 	y = r->dst.y + op->dst.y;
352.5719 +@@ -1035,10 +1045,10 @@ gen3_emit_composite_boxes_identity_gradient__sse2(const struct sna_composite_op
352.5720 + 						  float *v)
352.5721 + {
352.5722 + 	do {
352.5723 +-		v[0] = box->x2;
352.5724 +-		v[5] = v[1] = box->y2;
352.5725 +-		v[8] = v[4] = box->x1;
352.5726 +-		v[9] = box->y1;
352.5727 ++		v[0] = box->x2 + op->dst.x;
352.5728 ++		v[5] = v[1] = box->y2 + op->dst.y;
352.5729 ++		v[8] = v[4] = box->x1 + op->dst.x;
352.5730 ++		v[9] = box->y1 + op->dst.y;
352.5731 + 
352.5732 + 		v[2] = box->x2 + op->src.offset[0];
352.5733 + 		v[7] = v[3] = box->y2 + op->src.offset[1];
352.5734 +@@ -1067,6 +1077,7 @@ gen3_emit_composite_primitive_affine_gradient__sse2(struct sna *sna,
352.5735 + 
352.5736 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5737 + 	sna->render.vertex_used += 12;
352.5738 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5739 + 
352.5740 + 	v[0] = dst_x + r->width;
352.5741 + 	v[1] = dst_y + r->height;
352.5742 +@@ -1095,22 +1106,22 @@ gen3_emit_composite_boxes_affine_gradient__sse2(const struct sna_composite_op *o
352.5743 + 	const PictTransform *transform = op->src.transform;
352.5744 + 
352.5745 + 	do {
352.5746 +-		v[0] = box->x2;
352.5747 +-		v[1] = box->y2;
352.5748 ++		v[0] = box->x2 + op->dst.x;
352.5749 ++		v[1] = box->y2 + op->dst.y;
352.5750 + 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
352.5751 + 					    box->y2 + op->src.offset[1],
352.5752 + 					    transform, op->src.scale,
352.5753 + 					    &v[2], &v[3]);
352.5754 + 
352.5755 +-		v[4] = box->x1;
352.5756 +-		v[5] = box->y2;
352.5757 ++		v[4] = box->x1 + op->dst.x;
352.5758 ++		v[5] = box->y2 + op->dst.y;
352.5759 + 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
352.5760 + 					    box->y2 + op->src.offset[1],
352.5761 + 					    transform, op->src.scale,
352.5762 + 					    &v[6], &v[7]);
352.5763 + 
352.5764 +-		v[8] = box->x1;
352.5765 +-		v[9] = box->y1;
352.5766 ++		v[8] = box->x1 + op->dst.x;
352.5767 ++		v[9] = box->y1 + op->dst.y;
352.5768 + 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
352.5769 + 					    box->y1 + op->src.offset[1],
352.5770 + 					    transform, op->src.scale,
352.5771 +@@ -1132,6 +1143,7 @@ gen3_emit_composite_primitive_identity_source__sse2(struct sna *sna,
352.5772 + 
352.5773 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5774 + 	sna->render.vertex_used += 12;
352.5775 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5776 + 
352.5777 + 	v[8] = v[4] = r->dst.x + op->dst.x;
352.5778 + 	v[0] = v[4] + w;
352.5779 +@@ -1179,6 +1191,7 @@ gen3_emit_composite_primitive_identity_source_no_offset__sse2(struct sna *sna,
352.5780 + 
352.5781 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5782 + 	sna->render.vertex_used += 12;
352.5783 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5784 + 
352.5785 + 	v[8] = v[4] = r->dst.x;
352.5786 + 	v[9] = r->dst.y;
352.5787 +@@ -1227,8 +1240,12 @@ gen3_emit_composite_primitive_affine_source__sse2(struct sna *sna,
352.5788 + 	int src_y = r->src.y + (int)op->src.offset[1];
352.5789 + 	float *v;
352.5790 + 
352.5791 ++	DBG(("%s: src=(%d, %d), dst=(%d, %d), size=%dx%d\n",
352.5792 ++	     __FUNCTION__, src_x, src_y, dst_x, dst_y, r->width, r->height));
352.5793 ++
352.5794 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5795 + 	sna->render.vertex_used += 12;
352.5796 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5797 + 
352.5798 + 	v[0] = dst_x + r->width;
352.5799 + 	v[5] = v[1] = dst_y + r->height;
352.5800 +@@ -1256,10 +1273,13 @@ gen3_emit_composite_boxes_affine_source__sse2(const struct sna_composite_op *op,
352.5801 + 	const PictTransform *transform = op->src.transform;
352.5802 + 
352.5803 + 	do {
352.5804 +-		v[0] = box->x2;
352.5805 +-		v[5] = v[1] = box->y2;
352.5806 +-		v[8] = v[4] = box->x1;
352.5807 +-		v[9] = box->y1;
352.5808 ++		DBG(("%s: box=(%d, %d), (%d, %d), src.offset=(%d, %d)\n",
352.5809 ++		     __FUNCTION__, box->x1, box->y1, box->x2, box->y2, op->src.offset[0], op->src.offset[1]));
352.5810 ++
352.5811 ++		v[0] = box->x2 + op->dst.x;
352.5812 ++		v[5] = v[1] = box->y2 + op->dst.y;
352.5813 ++		v[8] = v[4] = box->x1 + op->dst.x;
352.5814 ++		v[9] = box->y1 + op->dst.y;
352.5815 + 
352.5816 + 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
352.5817 + 					    box->y2 + op->src.offset[1],
352.5818 +@@ -1292,6 +1312,7 @@ gen3_emit_composite_primitive_constant_identity_mask__sse2(struct sna *sna,
352.5819 + 
352.5820 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5821 + 	sna->render.vertex_used += 12;
352.5822 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5823 + 
352.5824 + 	v[8] = v[4] = r->dst.x + op->dst.x;
352.5825 + 	v[0] = v[4] + w;
352.5826 +@@ -1317,6 +1338,7 @@ gen3_emit_composite_primitive_constant_identity_mask_no_offset__sse2(struct sna
352.5827 + 
352.5828 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5829 + 	sna->render.vertex_used += 12;
352.5830 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5831 + 
352.5832 + 	v[8] = v[4] = r->dst.x;
352.5833 + 	v[9] = r->dst.y;
352.5834 +@@ -1353,6 +1375,7 @@ gen3_emit_composite_primitive_identity_source_mask__sse2(struct sna *sna,
352.5835 + 
352.5836 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5837 + 	sna->render.vertex_used += 18;
352.5838 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5839 + 
352.5840 + 	v[0] = dst_x + w;
352.5841 + 	v[1] = dst_y + h;
352.5842 +@@ -1398,6 +1421,7 @@ gen3_emit_composite_primitive_affine_source_mask__sse2(struct sna *sna,
352.5843 + 
352.5844 + 	v = sna->render.vertices + sna->render.vertex_used;
352.5845 + 	sna->render.vertex_used += 18;
352.5846 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5847 + 
352.5848 + 	v[0] = dst_x + w;
352.5849 + 	v[1] = dst_y + h;
352.5850 +@@ -2233,6 +2257,7 @@ static void gen3_vertex_flush(struct sna *sna)
352.5851 + static int gen3_vertex_finish(struct sna *sna)
352.5852 + {
352.5853 + 	struct kgem_bo *bo;
352.5854 ++	unsigned hint, size;
352.5855 + 
352.5856 + 	DBG(("%s: used=%d/%d, vbo active? %d\n",
352.5857 + 	     __FUNCTION__, sna->render.vertex_used, sna->render.vertex_size,
352.5858 +@@ -2243,6 +2268,7 @@ static int gen3_vertex_finish(struct sna *sna)
352.5859 + 
352.5860 + 	sna_vertex_wait__locked(&sna->render);
352.5861 + 
352.5862 ++	hint = CREATE_GTT_MAP;
352.5863 + 	bo = sna->render.vbo;
352.5864 + 	if (bo) {
352.5865 + 		DBG(("%s: reloc = %d\n", __FUNCTION__,
352.5866 +@@ -2251,7 +2277,7 @@ static int gen3_vertex_finish(struct sna *sna)
352.5867 + 		if (sna->render.vertex_reloc[0]) {
352.5868 + 			sna->kgem.batch[sna->render.vertex_reloc[0]] =
352.5869 + 				kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
352.5870 +-					       bo, I915_GEM_DOMAIN_VERTEX << 16, 0);
352.5871 ++					       bo, I915_GEM_DOMAIN_VERTEX << 16 | KGEM_RELOC_FENCED, 0);
352.5872 + 
352.5873 + 			sna->render.vertex_reloc[0] = 0;
352.5874 + 		}
352.5875 +@@ -2260,17 +2286,29 @@ static int gen3_vertex_finish(struct sna *sna)
352.5876 + 		sna->render.vbo = NULL;
352.5877 + 
352.5878 + 		kgem_bo_destroy(&sna->kgem, bo);
352.5879 ++		hint |= CREATE_CACHED | CREATE_NO_THROTTLE;
352.5880 + 	}
352.5881 + 
352.5882 ++	size = 256*1024;
352.5883 + 	sna->render.vertices = NULL;
352.5884 +-	sna->render.vbo = kgem_create_linear(&sna->kgem,
352.5885 +-					     256*1024, CREATE_GTT_MAP);
352.5886 +-	if (sna->render.vbo)
352.5887 ++	sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
352.5888 ++	while (sna->render.vbo == NULL && size > sizeof(sna->render.vertex_data)) {
352.5889 ++		size /= 2;
352.5890 ++		sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
352.5891 ++	}
352.5892 ++	if (sna->render.vbo == NULL)
352.5893 ++		sna->render.vbo = kgem_create_linear(&sna->kgem,
352.5894 ++						     256*1024, CREATE_GTT_MAP);
352.5895 ++	if (sna->render.vbo &&
352.5896 ++	    kgem_check_bo(&sna->kgem, sna->render.vbo, NULL))
352.5897 + 		sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo);
352.5898 + 	if (sna->render.vertices == NULL) {
352.5899 +-		if (sna->render.vbo)
352.5900 ++		if (sna->render.vbo) {
352.5901 + 			kgem_bo_destroy(&sna->kgem, sna->render.vbo);
352.5902 +-		sna->render.vbo = NULL;
352.5903 ++			sna->render.vbo = NULL;
352.5904 ++		}
352.5905 ++		sna->render.vertices = sna->render.vertex_data;
352.5906 ++		sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
352.5907 + 		return 0;
352.5908 + 	}
352.5909 + 	assert(sna->render.vbo->snoop == false);
352.5910 +@@ -2280,8 +2318,14 @@ static int gen3_vertex_finish(struct sna *sna)
352.5911 + 		       sna->render.vertex_data,
352.5912 + 		       sizeof(float)*sna->render.vertex_used);
352.5913 + 	}
352.5914 +-	sna->render.vertex_size = 64 * 1024 - 1;
352.5915 +-	return sna->render.vertex_size - sna->render.vertex_used;
352.5916 ++
352.5917 ++	size = __kgem_bo_size(sna->render.vbo)/4;
352.5918 ++	if (size >= UINT16_MAX)
352.5919 ++		size = UINT16_MAX - 1;
352.5920 ++	assert(size > sna->render.vertex_used);
352.5921 ++
352.5922 ++	sna->render.vertex_size = size;
352.5923 ++	return size - sna->render.vertex_used;
352.5924 + }
352.5925 + 
352.5926 + static void gen3_vertex_close(struct sna *sna)
352.5927 +@@ -2345,7 +2389,7 @@ static void gen3_vertex_close(struct sna *sna)
352.5928 + 	DBG(("%s: reloc = %d\n", __FUNCTION__, sna->render.vertex_reloc[0]));
352.5929 + 	sna->kgem.batch[sna->render.vertex_reloc[0]] =
352.5930 + 		kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
352.5931 +-			       bo, I915_GEM_DOMAIN_VERTEX << 16, delta);
352.5932 ++			       bo, I915_GEM_DOMAIN_VERTEX << 16 | KGEM_RELOC_FENCED, delta);
352.5933 + 	sna->render.vertex_reloc[0] = 0;
352.5934 + 
352.5935 + 	if (sna->render.vbo == NULL) {
352.5936 +@@ -2580,6 +2624,7 @@ gen3_render_composite_boxes(struct sna *sna,
352.5937 + 
352.5938 + 		v = sna->render.vertices + sna->render.vertex_used;
352.5939 + 		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
352.5940 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5941 + 
352.5942 + 		op->emit_boxes(op, box, nbox_this_time, v);
352.5943 + 		box += nbox_this_time;
352.5944 +@@ -2604,6 +2649,7 @@ gen3_render_composite_boxes__thread(struct sna *sna,
352.5945 + 
352.5946 + 		v = sna->render.vertices + sna->render.vertex_used;
352.5947 + 		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
352.5948 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.5949 + 
352.5950 + 		sna_vertex_acquire__locked(&sna->render);
352.5951 + 		sna_vertex_unlock(&sna->render);
352.5952 +@@ -3065,7 +3111,7 @@ gen3_composite_picture(struct sna *sna,
352.5953 + 
352.5954 + 	if (sna_picture_is_clear(picture, x, y, w, h, &color)) {
352.5955 + 		DBG(("%s: clear drawable [%08x]\n", __FUNCTION__, color));
352.5956 +-		return gen3_init_solid(channel, color_convert(color, picture->format, PICT_a8r8g8b8));
352.5957 ++		return gen3_init_solid(channel, solid_color(picture->format, color));
352.5958 + 	}
352.5959 + 
352.5960 + 	if (!gen3_check_repeat(picture))
352.5961 +@@ -3097,12 +3143,12 @@ gen3_composite_picture(struct sna *sna,
352.5962 + 		if (channel->repeat ||
352.5963 + 		    (x >= 0 &&
352.5964 + 		     y >= 0 &&
352.5965 +-		     x + w < pixmap->drawable.width &&
352.5966 +-		     y + h < pixmap->drawable.height)) {
352.5967 ++		     x + w <= pixmap->drawable.width &&
352.5968 ++		     y + h <= pixmap->drawable.height)) {
352.5969 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.5970 + 			if (priv && priv->clear) {
352.5971 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.5972 +-				return gen3_init_solid(channel, priv->clear_color);
352.5973 ++				return gen3_init_solid(channel, solid_color(picture->format, priv->clear_color));
352.5974 + 			}
352.5975 + 		}
352.5976 + 	} else {
352.5977 +@@ -3182,7 +3228,9 @@ gen3_composite_set_target(struct sna *sna,
352.5978 + 	} else
352.5979 + 		sna_render_picture_extents(dst, &box);
352.5980 + 
352.5981 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.5982 ++	hint = PREFER_GPU | RENDER_GPU;
352.5983 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.5984 ++		hint |= FORCE_GPU;
352.5985 + 	if (!partial) {
352.5986 + 		hint |= IGNORE_DAMAGE;
352.5987 + 		if (w == op->dst.width && h == op->dst.height)
352.5988 +@@ -3645,8 +3693,11 @@ gen3_render_composite(struct sna *sna,
352.5989 + 			}
352.5990 + 		}
352.5991 + 	}
352.5992 +-	DBG(("%s: final src/mask type=%d/%d, affine=%d/%d\n", __FUNCTION__,
352.5993 ++	DBG(("%s: final src/mask type=%d/%d [constant? %d/%d], transform? %d/%d, affine=%d/%d\n", __FUNCTION__,
352.5994 + 	     tmp->src.u.gen3.type, tmp->mask.u.gen3.type,
352.5995 ++	     is_constant_ps(tmp->src.u.gen3.type),
352.5996 ++	     is_constant_ps(tmp->mask.u.gen3.type),
352.5997 ++	     !!tmp->src.transform, !!tmp->mask.transform,
352.5998 + 	     tmp->src.is_affine, tmp->mask.is_affine));
352.5999 + 
352.6000 + 	tmp->prim_emit = gen3_emit_composite_primitive;
352.6001 +@@ -3862,6 +3913,7 @@ gen3_emit_composite_spans_primitive_zero(struct sna *sna,
352.6002 + {
352.6003 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6004 + 	sna->render.vertex_used += 6;
352.6005 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6006 + 
352.6007 + 	v[0] = op->base.dst.x + box->x2;
352.6008 + 	v[1] = op->base.dst.y + box->y2;
352.6009 +@@ -3901,6 +3953,7 @@ gen3_emit_composite_spans_primitive_zero_no_offset(struct sna *sna,
352.6010 + {
352.6011 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6012 + 	sna->render.vertex_used += 6;
352.6013 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6014 + 
352.6015 + 	v[0] = box->x2;
352.6016 + 	v[3] = v[1] = box->y2;
352.6017 +@@ -3932,6 +3985,7 @@ gen3_emit_composite_spans_primitive_constant(struct sna *sna,
352.6018 + {
352.6019 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6020 + 	sna->render.vertex_used += 9;
352.6021 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6022 + 
352.6023 + 	v[0] = op->base.dst.x + box->x2;
352.6024 + 	v[6] = v[3] = op->base.dst.x + box->x1;
352.6025 +@@ -3966,6 +4020,7 @@ gen3_emit_composite_spans_primitive_constant_no_offset(struct sna *sna,
352.6026 + {
352.6027 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6028 + 	sna->render.vertex_used += 9;
352.6029 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6030 + 
352.6031 + 	v[0] = box->x2;
352.6032 + 	v[6] = v[3] = box->x1;
352.6033 +@@ -3999,6 +4054,7 @@ gen3_emit_composite_spans_primitive_identity_source(struct sna *sna,
352.6034 + {
352.6035 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6036 + 	sna->render.vertex_used += 15;
352.6037 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6038 + 
352.6039 + 	v[0] = op->base.dst.x + box->x2;
352.6040 + 	v[1] = op->base.dst.y + box->y2;
352.6041 +@@ -4060,6 +4116,7 @@ gen3_emit_composite_spans_primitive_affine_source(struct sna *sna,
352.6042 + 
352.6043 + 	v = sna->render.vertices + sna->render.vertex_used;
352.6044 + 	sna->render.vertex_used += 15;
352.6045 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6046 + 
352.6047 + 	v[0]  = op->base.dst.x + box->x2;
352.6048 + 	v[6]  = v[1] = op->base.dst.y + box->y2;
352.6049 +@@ -4125,6 +4182,7 @@ gen3_emit_composite_spans_primitive_identity_gradient(struct sna *sna,
352.6050 + {
352.6051 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6052 + 	sna->render.vertex_used += 15;
352.6053 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6054 + 
352.6055 + 	v[0] = op->base.dst.x + box->x2;
352.6056 + 	v[1] = op->base.dst.y + box->y2;
352.6057 +@@ -4184,6 +4242,7 @@ gen3_emit_composite_spans_primitive_constant__sse2(struct sna *sna,
352.6058 + {
352.6059 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6060 + 	sna->render.vertex_used += 9;
352.6061 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6062 + 
352.6063 + 	v[0] = op->base.dst.x + box->x2;
352.6064 + 	v[6] = v[3] = op->base.dst.x + box->x1;
352.6065 +@@ -4229,6 +4288,7 @@ gen3_render_composite_spans_constant_box__sse2(struct sna *sna,
352.6066 + 
352.6067 + 	v = sna->render.vertices + sna->render.vertex_used;
352.6068 + 	sna->render.vertex_used += 9;
352.6069 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6070 + 
352.6071 + 	v[0] = box->x2;
352.6072 + 	v[6] = v[3] = box->x1;
352.6073 +@@ -4259,6 +4319,7 @@ gen3_render_composite_spans_constant_thread__sse2__boxes(struct sna *sna,
352.6074 + 
352.6075 + 		v = sna->render.vertices + sna->render.vertex_used;
352.6076 + 		sna->render.vertex_used += nbox_this_time * 9;
352.6077 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6078 + 
352.6079 + 		sna_vertex_acquire__locked(&sna->render);
352.6080 + 		sna_vertex_unlock(&sna->render);
352.6081 +@@ -4287,6 +4348,7 @@ gen3_emit_composite_spans_primitive_constant__sse2__no_offset(struct sna *sna,
352.6082 + {
352.6083 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6084 + 	sna->render.vertex_used += 9;
352.6085 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6086 + 
352.6087 + 	v[0] = box->x2;
352.6088 + 	v[6] = v[3] = box->x1;
352.6089 +@@ -4320,6 +4382,7 @@ gen3_emit_composite_spans_primitive_identity_source__sse2(struct sna *sna,
352.6090 + {
352.6091 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6092 + 	sna->render.vertex_used += 15;
352.6093 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6094 + 
352.6095 + 	v[0] = op->base.dst.x + box->x2;
352.6096 + 	v[1] = op->base.dst.y + box->y2;
352.6097 +@@ -4380,6 +4443,7 @@ gen3_emit_composite_spans_primitive_affine_source__sse2(struct sna *sna,
352.6098 + 
352.6099 + 	v = sna->render.vertices + sna->render.vertex_used;
352.6100 + 	sna->render.vertex_used += 15;
352.6101 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6102 + 
352.6103 + 	v[0]  = op->base.dst.x + box->x2;
352.6104 + 	v[6]  = v[1] = op->base.dst.y + box->y2;
352.6105 +@@ -4445,6 +4509,7 @@ gen3_emit_composite_spans_primitive_identity_gradient__sse2(struct sna *sna,
352.6106 + {
352.6107 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6108 + 	sna->render.vertex_used += 15;
352.6109 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6110 + 
352.6111 + 	v[0] = op->base.dst.x + box->x2;
352.6112 + 	v[1] = op->base.dst.y + box->y2;
352.6113 +@@ -4504,6 +4569,7 @@ gen3_emit_composite_spans_primitive_affine_gradient__sse2(struct sna *sna,
352.6114 + 	PictTransform *transform = op->base.src.transform;
352.6115 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6116 + 	sna->render.vertex_used += 15;
352.6117 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6118 + 
352.6119 + 	v[0] = op->base.dst.x + box->x2;
352.6120 + 	v[1] = op->base.dst.y + box->y2;
352.6121 +@@ -4577,6 +4643,7 @@ gen3_emit_composite_spans_primitive_affine_gradient(struct sna *sna,
352.6122 + 	PictTransform *transform = op->base.src.transform;
352.6123 + 	float *v = sna->render.vertices + sna->render.vertex_used;
352.6124 + 	sna->render.vertex_used += 15;
352.6125 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6126 + 
352.6127 + 	v[0] = op->base.dst.x + box->x2;
352.6128 + 	v[1] = op->base.dst.y + box->y2;
352.6129 +@@ -4676,6 +4743,7 @@ gen3_render_composite_spans_constant_box(struct sna *sna,
352.6130 + 
352.6131 + 	v = sna->render.vertices + sna->render.vertex_used;
352.6132 + 	sna->render.vertex_used += 9;
352.6133 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6134 + 
352.6135 + 	v[0] = box->x2;
352.6136 + 	v[6] = v[3] = box->x1;
352.6137 +@@ -4706,6 +4774,7 @@ gen3_render_composite_spans_constant_thread_boxes(struct sna *sna,
352.6138 + 
352.6139 + 		v = sna->render.vertices + sna->render.vertex_used;
352.6140 + 		sna->render.vertex_used += nbox_this_time * 9;
352.6141 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6142 + 
352.6143 + 		sna_vertex_acquire__locked(&sna->render);
352.6144 + 		sna_vertex_unlock(&sna->render);
352.6145 +@@ -4795,6 +4864,7 @@ gen3_render_composite_spans_boxes__thread(struct sna *sna,
352.6146 + 
352.6147 + 		v = sna->render.vertices + sna->render.vertex_used;
352.6148 + 		sna->render.vertex_used += nbox_this_time * op->base.floats_per_rect;
352.6149 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.6150 + 
352.6151 + 		sna_vertex_acquire__locked(&sna->render);
352.6152 + 		sna_vertex_unlock(&sna->render);
352.6153 +@@ -5436,17 +5506,7 @@ gen3_render_video(struct sna *sna,
352.6154 + 		pix_yoff = -dstRegion->extents.y1;
352.6155 + 		copy = 1;
352.6156 + 	} else {
352.6157 +-		/* Set up the offset for translating from the given region
352.6158 +-		 * (in screen coordinates) to the backing pixmap.
352.6159 +-		 */
352.6160 +-#ifdef COMPOSITE
352.6161 +-		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.6162 +-		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.6163 +-#else
352.6164 +-		pix_xoff = 0;
352.6165 +-		pix_yoff = 0;
352.6166 +-#endif
352.6167 +-
352.6168 ++		pix_xoff = pix_yoff = 0;
352.6169 + 		dst_width  = pixmap->drawable.width;
352.6170 + 		dst_height = pixmap->drawable.height;
352.6171 + 	}
352.6172 +@@ -5502,16 +5562,9 @@ gen3_render_video(struct sna *sna,
352.6173 + 	} while (nbox);
352.6174 + 
352.6175 + 	if (copy) {
352.6176 +-#ifdef COMPOSITE
352.6177 +-		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.6178 +-		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.6179 +-#else
352.6180 +-		pix_xoff = 0;
352.6181 +-		pix_yoff = 0;
352.6182 +-#endif
352.6183 + 		sna_blt_copy_boxes(sna, GXcopy,
352.6184 + 				   dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
352.6185 +-				   priv->gpu_bo, pix_xoff, pix_yoff,
352.6186 ++				   priv->gpu_bo, 0, 0,
352.6187 + 				   pixmap->drawable.bitsPerPixel,
352.6188 + 				   region_rects(dstRegion),
352.6189 + 				   region_num_rects(dstRegion));
352.6190 +@@ -5519,21 +5572,8 @@ gen3_render_video(struct sna *sna,
352.6191 + 		kgem_bo_destroy(&sna->kgem, dst_bo);
352.6192 + 	}
352.6193 + 
352.6194 +-	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.6195 +-		if ((pix_xoff | pix_yoff) == 0) {
352.6196 +-			sna_damage_add(&priv->gpu_damage, dstRegion);
352.6197 +-			sna_damage_subtract(&priv->cpu_damage, dstRegion);
352.6198 +-		} else {
352.6199 +-			sna_damage_add_boxes(&priv->gpu_damage,
352.6200 +-					     region_rects(dstRegion),
352.6201 +-					     region_num_rects(dstRegion),
352.6202 +-					     pix_xoff, pix_yoff);
352.6203 +-			sna_damage_subtract_boxes(&priv->cpu_damage,
352.6204 +-						  region_rects(dstRegion),
352.6205 +-						  region_num_rects(dstRegion),
352.6206 +-						  pix_xoff, pix_yoff);
352.6207 +-		}
352.6208 +-	}
352.6209 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.6210 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.6211 + 
352.6212 + 	return true;
352.6213 + }
352.6214 +diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
352.6215 +index 6c2d3808..72a98aee 100644
352.6216 +--- a/src/sna/gen4_render.c
352.6217 ++++ b/src/sna/gen4_render.c
352.6218 +@@ -1405,8 +1405,8 @@ gen4_render_video(struct sna *sna,
352.6219 + 	int src_height = frame->src.y2 - frame->src.y1;
352.6220 + 	float src_offset_x, src_offset_y;
352.6221 + 	float src_scale_x, src_scale_y;
352.6222 +-	int nbox, pix_xoff, pix_yoff;
352.6223 + 	const BoxRec *box;
352.6224 ++	int nbox;
352.6225 + 
352.6226 + 	DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__,
352.6227 + 	     src_width, src_height, dst_width, dst_height));
352.6228 +@@ -1445,17 +1445,6 @@ gen4_render_video(struct sna *sna,
352.6229 + 	gen4_align_vertex(sna, &tmp);
352.6230 + 	gen4_video_bind_surfaces(sna, &tmp);
352.6231 + 
352.6232 +-	/* Set up the offset for translating from the given region (in screen
352.6233 +-	 * coordinates) to the backing pixmap.
352.6234 +-	 */
352.6235 +-#ifdef COMPOSITE
352.6236 +-	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.6237 +-	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.6238 +-#else
352.6239 +-	pix_xoff = 0;
352.6240 +-	pix_yoff = 0;
352.6241 +-#endif
352.6242 +-
352.6243 + 	src_scale_x = (float)src_width / dst_width / frame->width;
352.6244 + 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
352.6245 + 
352.6246 +@@ -1473,34 +1462,26 @@ gen4_render_video(struct sna *sna,
352.6247 + 		nbox -= n;
352.6248 + 
352.6249 + 		do {
352.6250 +-			BoxRec r;
352.6251 +-
352.6252 +-			r.x1 = box->x1 + pix_xoff;
352.6253 +-			r.x2 = box->x2 + pix_xoff;
352.6254 +-			r.y1 = box->y1 + pix_yoff;
352.6255 +-			r.y2 = box->y2 + pix_yoff;
352.6256 +-
352.6257 +-			OUT_VERTEX(r.x2, r.y2);
352.6258 ++			OUT_VERTEX(box->x2, box->y2);
352.6259 + 			OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.6260 + 			OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6261 + 
352.6262 +-			OUT_VERTEX(r.x1, r.y2);
352.6263 ++			OUT_VERTEX(box->x1, box->y2);
352.6264 + 			OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6265 + 			OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6266 + 
352.6267 +-			OUT_VERTEX(r.x1, r.y1);
352.6268 ++			OUT_VERTEX(box->x1, box->y1);
352.6269 + 			OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6270 + 			OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.6271 + 
352.6272 +-			if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.6273 +-				sna_damage_add_box(&priv->gpu_damage, &r);
352.6274 +-				sna_damage_subtract_box(&priv->cpu_damage, &r);
352.6275 +-			}
352.6276 + 			box++;
352.6277 + 		} while (--n);
352.6278 + 	} while (nbox);
352.6279 + 	gen4_vertex_flush(sna);
352.6280 + 
352.6281 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.6282 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.6283 ++
352.6284 + 	return true;
352.6285 + }
352.6286 + 
352.6287 +@@ -1585,12 +1566,14 @@ gen4_composite_picture(struct sna *sna,
352.6288 + 		if (channel->repeat &&
352.6289 + 		    (x >= 0 &&
352.6290 + 		     y >= 0 &&
352.6291 +-		     x + w < pixmap->drawable.width &&
352.6292 +-		     y + h < pixmap->drawable.height)) {
352.6293 ++		     x + w <= pixmap->drawable.width &&
352.6294 ++		     y + h <= pixmap->drawable.height)) {
352.6295 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.6296 + 			if (priv && priv->clear) {
352.6297 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.6298 +-				return gen4_channel_init_solid(sna, channel, priv->clear_color);
352.6299 ++				return gen4_channel_init_solid(sna, channel,
352.6300 ++							       solid_color(picture->format,
352.6301 ++									   priv->clear_color));
352.6302 + 			}
352.6303 + 		}
352.6304 + 	} else
352.6305 +@@ -1664,7 +1647,9 @@ gen4_composite_set_target(struct sna *sna,
352.6306 + 	} else
352.6307 + 		sna_render_picture_extents(dst, &box);
352.6308 + 
352.6309 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.6310 ++	hint = PREFER_GPU | RENDER_GPU;
352.6311 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.6312 ++		hint |= FORCE_GPU;
352.6313 + 	if (!partial) {
352.6314 + 		hint |= IGNORE_DAMAGE;
352.6315 + 		if (w == op->dst.width && h == op->dst.height)
352.6316 +@@ -2738,6 +2723,20 @@ gen4_render_fill_boxes(struct sna *sna,
352.6317 + 	tmp.dst.format = format;
352.6318 + 	tmp.dst.bo = dst_bo;
352.6319 + 
352.6320 ++	sna_render_composite_redirect_init(&tmp);
352.6321 ++	if (too_large(dst->width, dst->height)) {
352.6322 ++		BoxRec extents;
352.6323 ++
352.6324 ++		boxes_extents(box, n, &extents);
352.6325 ++		if (!sna_render_composite_redirect(sna, &tmp,
352.6326 ++						   extents.x1, extents.y1,
352.6327 ++						   extents.x2 - extents.x1,
352.6328 ++						   extents.y2 - extents.y1,
352.6329 ++						   n > 1))
352.6330 ++			return sna_tiling_fill_boxes(sna, op, format, color,
352.6331 ++						     dst, dst_bo, box, n);
352.6332 ++	}
352.6333 ++
352.6334 + 	gen4_channel_init_solid(sna, &tmp.src, pixel);
352.6335 + 
352.6336 + 	tmp.is_affine = true;
352.6337 +@@ -2748,8 +2747,10 @@ gen4_render_fill_boxes(struct sna *sna,
352.6338 + 
352.6339 + 	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.6340 + 		kgem_submit(&sna->kgem);
352.6341 +-		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL))
352.6342 ++		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.6343 ++			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.6344 + 			return false;
352.6345 ++		}
352.6346 + 	}
352.6347 + 
352.6348 + 	gen4_align_vertex(sna, &tmp);
352.6349 +@@ -2765,6 +2766,7 @@ gen4_render_fill_boxes(struct sna *sna,
352.6350 + 
352.6351 + 	gen4_vertex_flush(sna);
352.6352 + 	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.6353 ++	sna_render_composite_redirect_done(sna, &tmp);
352.6354 + 	return true;
352.6355 + }
352.6356 + 
352.6357 +diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
352.6358 +index 37cf1ff9..fb3e79bf 100644
352.6359 +--- a/src/sna/gen5_render.c
352.6360 ++++ b/src/sna/gen5_render.c
352.6361 +@@ -1355,8 +1355,8 @@ gen5_render_video(struct sna *sna,
352.6362 + 	int src_height = frame->src.y2 - frame->src.y1;
352.6363 + 	float src_offset_x, src_offset_y;
352.6364 + 	float src_scale_x, src_scale_y;
352.6365 +-	int nbox, pix_xoff, pix_yoff;
352.6366 + 	const BoxRec *box;
352.6367 ++	int nbox;
352.6368 + 
352.6369 + 	DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__,
352.6370 + 	     src_width, src_height, dst_width, dst_height));
352.6371 +@@ -1395,17 +1395,6 @@ gen5_render_video(struct sna *sna,
352.6372 + 	gen5_align_vertex(sna, &tmp);
352.6373 + 	gen5_video_bind_surfaces(sna, &tmp);
352.6374 + 
352.6375 +-	/* Set up the offset for translating from the given region (in screen
352.6376 +-	 * coordinates) to the backing pixmap.
352.6377 +-	 */
352.6378 +-#ifdef COMPOSITE
352.6379 +-	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.6380 +-	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.6381 +-#else
352.6382 +-	pix_xoff = 0;
352.6383 +-	pix_yoff = 0;
352.6384 +-#endif
352.6385 +-
352.6386 + 	src_scale_x = (float)src_width / dst_width / frame->width;
352.6387 + 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
352.6388 + 
352.6389 +@@ -1415,35 +1404,27 @@ gen5_render_video(struct sna *sna,
352.6390 + 	box = region_rects(dstRegion);
352.6391 + 	nbox = region_num_rects(dstRegion);
352.6392 + 	while (nbox--) {
352.6393 +-		BoxRec r;
352.6394 +-
352.6395 +-		r.x1 = box->x1 + pix_xoff;
352.6396 +-		r.x2 = box->x2 + pix_xoff;
352.6397 +-		r.y1 = box->y1 + pix_yoff;
352.6398 +-		r.y2 = box->y2 + pix_yoff;
352.6399 +-
352.6400 + 		gen5_get_rectangles(sna, &tmp, 1, gen5_video_bind_surfaces);
352.6401 + 
352.6402 +-		OUT_VERTEX(r.x2, r.y2);
352.6403 ++		OUT_VERTEX(box->x2, box->y2);
352.6404 + 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.6405 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6406 + 
352.6407 +-		OUT_VERTEX(r.x1, r.y2);
352.6408 ++		OUT_VERTEX(box->x1, box->y2);
352.6409 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6410 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6411 + 
352.6412 +-		OUT_VERTEX(r.x1, r.y1);
352.6413 ++		OUT_VERTEX(box->x1, box->y1);
352.6414 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6415 + 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.6416 + 
352.6417 +-		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.6418 +-			sna_damage_add_box(&priv->gpu_damage, &r);
352.6419 +-			sna_damage_subtract_box(&priv->cpu_damage, &r);
352.6420 +-		}
352.6421 + 		box++;
352.6422 + 	}
352.6423 +-
352.6424 + 	gen4_vertex_flush(sna);
352.6425 ++
352.6426 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.6427 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.6428 ++
352.6429 + 	return true;
352.6430 + }
352.6431 + 
352.6432 +@@ -1524,12 +1505,12 @@ gen5_composite_picture(struct sna *sna,
352.6433 + 		if (channel->repeat ||
352.6434 + 		    (x >= 0 &&
352.6435 + 		     y >= 0 &&
352.6436 +-		     x + w < pixmap->drawable.width &&
352.6437 +-		     y + h < pixmap->drawable.height)) {
352.6438 ++		     x + w <= pixmap->drawable.width &&
352.6439 ++		     y + h <= pixmap->drawable.height)) {
352.6440 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.6441 + 			if (priv && priv->clear) {
352.6442 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.6443 +-				return gen4_channel_init_solid(sna, channel, priv->clear_color);
352.6444 ++				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
352.6445 + 			}
352.6446 + 		}
352.6447 + 	} else
352.6448 +@@ -1618,7 +1599,9 @@ gen5_composite_set_target(struct sna *sna,
352.6449 + 	} else
352.6450 + 		sna_render_picture_extents(dst, &box);
352.6451 + 
352.6452 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.6453 ++	hint = PREFER_GPU | RENDER_GPU;
352.6454 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.6455 ++		hint |= FORCE_GPU;
352.6456 + 	if (!partial) {
352.6457 + 		hint |= IGNORE_DAMAGE;
352.6458 + 		if (w == op->dst.width && h == op->dst.height)
352.6459 +@@ -2734,6 +2717,19 @@ gen5_render_fill_boxes(struct sna *sna,
352.6460 + 	tmp.dst.format = format;
352.6461 + 	tmp.dst.bo = dst_bo;
352.6462 + 
352.6463 ++	if (too_large(dst->width, dst->height)) {
352.6464 ++		BoxRec extents;
352.6465 ++
352.6466 ++		boxes_extents(box, n, &extents);
352.6467 ++		if (!sna_render_composite_redirect(sna, &tmp,
352.6468 ++						   extents.x1, extents.y1,
352.6469 ++						   extents.x2 - extents.x1,
352.6470 ++						   extents.y2 - extents.y1,
352.6471 ++						   n > 1))
352.6472 ++			return sna_tiling_fill_boxes(sna, op, format, color,
352.6473 ++						     dst, dst_bo, box, n);
352.6474 ++	}
352.6475 ++
352.6476 + 	tmp.src.bo = sna_render_get_solid(sna, pixel);
352.6477 + 	tmp.src.filter = SAMPLER_FILTER_NEAREST;
352.6478 + 	tmp.src.repeat = SAMPLER_EXTEND_REPEAT;
352.6479 +@@ -2780,6 +2776,7 @@ gen5_render_fill_boxes(struct sna *sna,
352.6480 + 
352.6481 + 	gen4_vertex_flush(sna);
352.6482 + 	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.6483 ++	sna_render_composite_redirect_done(sna, &tmp);
352.6484 + 	return true;
352.6485 + }
352.6486 + 
352.6487 +diff --git a/src/sna/gen6_common.h b/src/sna/gen6_common.h
352.6488 +index 6668620b..b53ec0c9 100644
352.6489 +--- a/src/sna/gen6_common.h
352.6490 ++++ b/src/sna/gen6_common.h
352.6491 +@@ -30,8 +30,8 @@
352.6492 + 
352.6493 + #include "sna.h"
352.6494 + 
352.6495 +-#define NO_RING_SWITCH 0
352.6496 +-#define PREFER_RENDER 0
352.6497 ++#define NO_RING_SWITCH(sna) (!(sna)->kgem.has_semaphores)
352.6498 ++#define PREFER_RENDER 0 /* -1 -> BLT, 1 -> RENDER */
352.6499 + 
352.6500 + static inline bool is_uncached(struct sna *sna,
352.6501 + 			       struct kgem_bo *bo)
352.6502 +@@ -46,40 +46,28 @@ inline static bool can_switch_to_blt(struct sna *sna,
352.6503 + 	if (sna->kgem.ring != KGEM_RENDER)
352.6504 + 		return true;
352.6505 + 
352.6506 +-	if (NO_RING_SWITCH)
352.6507 +-		return false;
352.6508 +-
352.6509 +-	if (!sna->kgem.has_semaphores)
352.6510 +-		return false;
352.6511 +-
352.6512 +-	if (flags & COPY_LAST)
352.6513 +-		return true;
352.6514 +-
352.6515 + 	if (bo && RQ_IS_BLT(bo->rq))
352.6516 + 		return true;
352.6517 + 
352.6518 +-	if (sna->render_state.gt < 2)
352.6519 +-		return true;
352.6520 ++	if (bo && bo->tiling == I915_TILING_Y)
352.6521 ++		return false;
352.6522 + 
352.6523 +-	return kgem_ring_is_idle(&sna->kgem, KGEM_BLT);
352.6524 +-}
352.6525 ++	if (bo && !kgem_bo_can_blt(&sna->kgem, bo))
352.6526 ++		return false;
352.6527 + 
352.6528 +-inline static bool can_switch_to_render(struct sna *sna,
352.6529 +-					struct kgem_bo *bo)
352.6530 +-{
352.6531 +-	if (sna->kgem.ring == KGEM_RENDER)
352.6532 ++	if (sna->render_state.gt < 2)
352.6533 + 		return true;
352.6534 + 
352.6535 +-	if (NO_RING_SWITCH)
352.6536 ++	if (bo && RQ_IS_RENDER(bo->rq))
352.6537 + 		return false;
352.6538 + 
352.6539 +-	if (!sna->kgem.has_semaphores)
352.6540 ++	if (NO_RING_SWITCH(sna))
352.6541 + 		return false;
352.6542 + 
352.6543 +-	if (bo && !RQ_IS_BLT(bo->rq) && !is_uncached(sna, bo))
352.6544 ++	if (flags & COPY_LAST)
352.6545 + 		return true;
352.6546 + 
352.6547 +-	return !kgem_ring_is_idle(&sna->kgem, KGEM_RENDER);
352.6548 ++	return kgem_ring_is_idle(&sna->kgem, KGEM_BLT);
352.6549 + }
352.6550 + 
352.6551 + static inline bool untiled_tlb_miss(struct kgem_bo *bo)
352.6552 +@@ -90,57 +78,95 @@ static inline bool untiled_tlb_miss(struct kgem_bo *bo)
352.6553 + 	return bo->tiling == I915_TILING_NONE && bo->pitch >= 4096;
352.6554 + }
352.6555 + 
352.6556 +-static int prefer_blt_bo(struct sna *sna, struct kgem_bo *bo)
352.6557 ++static int prefer_blt_bo(struct sna *sna,
352.6558 ++			 struct kgem_bo *src,
352.6559 ++			 struct kgem_bo *dst)
352.6560 + {
352.6561 ++	assert(dst != NULL);
352.6562 ++
352.6563 + 	if (PREFER_RENDER)
352.6564 + 		return PREFER_RENDER < 0;
352.6565 + 
352.6566 +-	if (bo->rq)
352.6567 +-		return RQ_IS_BLT(bo->rq);
352.6568 ++	if (dst->rq)
352.6569 ++		return RQ_IS_BLT(dst->rq);
352.6570 + 
352.6571 + 	if (sna->flags & SNA_POWERSAVE)
352.6572 + 		return true;
352.6573 + 
352.6574 +-	return bo->tiling == I915_TILING_NONE || is_uncached(sna, bo);
352.6575 +-}
352.6576 ++	if (src) {
352.6577 ++		if (sna->render_state.gt > 1)
352.6578 ++			return false;
352.6579 + 
352.6580 +-inline static bool force_blt_ring(struct sna *sna)
352.6581 +-{
352.6582 +-	if (sna->flags & SNA_POWERSAVE)
352.6583 ++		if (src->rq)
352.6584 ++			return RQ_IS_BLT(src->rq);
352.6585 ++
352.6586 ++		if (src->tiling == I915_TILING_Y)
352.6587 ++			return false;
352.6588 ++        } else {
352.6589 ++                if (sna->render_state.gt > 2)
352.6590 ++                        return false;
352.6591 ++        }
352.6592 ++
352.6593 ++	if (sna->render_state.gt < 2)
352.6594 + 		return true;
352.6595 + 
352.6596 ++	return dst->tiling == I915_TILING_NONE || is_uncached(sna, dst);
352.6597 ++}
352.6598 ++
352.6599 ++inline static bool force_blt_ring(struct sna *sna, struct kgem_bo *bo)
352.6600 ++{
352.6601 + 	if (sna->kgem.mode == KGEM_RENDER)
352.6602 + 		return false;
352.6603 + 
352.6604 ++	if (NO_RING_SWITCH(sna))
352.6605 ++		return sna->kgem.ring == KGEM_BLT;
352.6606 ++
352.6607 ++	if (bo->tiling == I915_TILING_Y)
352.6608 ++		return false;
352.6609 ++
352.6610 ++	if (sna->flags & SNA_POWERSAVE)
352.6611 ++		return true;
352.6612 ++
352.6613 + 	if (sna->render_state.gt < 2)
352.6614 + 		return true;
352.6615 + 
352.6616 + 	return false;
352.6617 + }
352.6618 + 
352.6619 +-inline static bool prefer_blt_ring(struct sna *sna,
352.6620 +-				   struct kgem_bo *bo,
352.6621 +-				   unsigned flags)
352.6622 ++nonnull inline static bool
352.6623 ++prefer_blt_ring(struct sna *sna, struct kgem_bo *bo, unsigned flags)
352.6624 + {
352.6625 + 	if (PREFER_RENDER)
352.6626 + 		return PREFER_RENDER < 0;
352.6627 + 
352.6628 +-	assert(!force_blt_ring(sna));
352.6629 +-	assert(!kgem_bo_is_render(bo));
352.6630 ++	assert(!force_blt_ring(sna, bo));
352.6631 ++	assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna));
352.6632 ++
352.6633 ++	if (kgem_bo_is_blt(bo))
352.6634 ++		return true;
352.6635 + 
352.6636 + 	return can_switch_to_blt(sna, bo, flags);
352.6637 + }
352.6638 + 
352.6639 +-inline static bool prefer_render_ring(struct sna *sna,
352.6640 +-				      struct kgem_bo *bo)
352.6641 ++nonnull inline static bool
352.6642 ++prefer_render_ring(struct sna *sna, struct kgem_bo *bo)
352.6643 + {
352.6644 ++	if (sna->kgem.ring == KGEM_RENDER)
352.6645 ++		return true;
352.6646 ++
352.6647 ++	if (sna->kgem.ring != KGEM_NONE && NO_RING_SWITCH(sna))
352.6648 ++                return false;
352.6649 ++
352.6650 ++	if (kgem_bo_is_render(bo))
352.6651 ++		return true;
352.6652 ++
352.6653 + 	if (sna->flags & SNA_POWERSAVE)
352.6654 + 		return false;
352.6655 + 
352.6656 +-	if (sna->render_state.gt < 2)
352.6657 +-		return false;
352.6658 ++	if (!prefer_blt_bo(sna, NULL, bo))
352.6659 ++		return true;
352.6660 + 
352.6661 +-	return can_switch_to_render(sna, bo);
352.6662 ++	return !kgem_ring_is_idle(&sna->kgem, KGEM_RENDER);
352.6663 + }
352.6664 + 
352.6665 + inline static bool
352.6666 +@@ -153,25 +179,20 @@ prefer_blt_composite(struct sna *sna, struct sna_composite_op *tmp)
352.6667 + 	    untiled_tlb_miss(tmp->src.bo))
352.6668 + 		return true;
352.6669 + 
352.6670 +-	if (force_blt_ring(sna))
352.6671 ++	if (force_blt_ring(sna, tmp->dst.bo))
352.6672 + 		return true;
352.6673 + 
352.6674 +-	if (kgem_bo_is_render(tmp->dst.bo) ||
352.6675 +-	    kgem_bo_is_render(tmp->src.bo))
352.6676 +-		return false;
352.6677 +-
352.6678 + 	if (prefer_render_ring(sna, tmp->dst.bo))
352.6679 + 		return false;
352.6680 + 
352.6681 + 	if (!prefer_blt_ring(sna, tmp->dst.bo, 0))
352.6682 + 		return false;
352.6683 + 
352.6684 +-	return prefer_blt_bo(sna, tmp->dst.bo) || prefer_blt_bo(sna, tmp->src.bo);
352.6685 ++	return prefer_blt_bo(sna, tmp->src.bo, tmp->dst.bo);
352.6686 + }
352.6687 + 
352.6688 +-static inline bool prefer_blt_fill(struct sna *sna,
352.6689 +-				   struct kgem_bo *bo,
352.6690 +-				   unsigned flags)
352.6691 ++nonnull static inline bool
352.6692 ++prefer_blt_fill(struct sna *sna, struct kgem_bo *bo, unsigned flags)
352.6693 + {
352.6694 + 	if (PREFER_RENDER)
352.6695 + 		return PREFER_RENDER < 0;
352.6696 +@@ -179,24 +200,21 @@ static inline bool prefer_blt_fill(struct sna *sna,
352.6697 + 	if (untiled_tlb_miss(bo))
352.6698 + 		return true;
352.6699 + 
352.6700 +-	if (force_blt_ring(sna))
352.6701 ++	if (force_blt_ring(sna, bo))
352.6702 + 		return true;
352.6703 + 
352.6704 + 	if ((flags & (FILL_POINTS | FILL_SPANS)) == 0) {
352.6705 +-		if (kgem_bo_is_render(bo))
352.6706 +-			return false;
352.6707 +-
352.6708 + 		if (prefer_render_ring(sna, bo))
352.6709 + 			return false;
352.6710 + 
352.6711 + 		if (!prefer_blt_ring(sna, bo, 0))
352.6712 + 			return false;
352.6713 + 	} else {
352.6714 +-	    if (can_switch_to_blt(sna, bo, 0))
352.6715 ++	    if (can_switch_to_blt(sna, bo, COPY_LAST))
352.6716 + 		    return true;
352.6717 + 	}
352.6718 + 
352.6719 +-	return prefer_blt_bo(sna, bo);
352.6720 ++	return prefer_blt_bo(sna, NULL, bo);
352.6721 + }
352.6722 + 
352.6723 + void gen6_render_context_switch(struct kgem *kgem, int new_mode);
352.6724 +diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
352.6725 +index 25044685..6b69f216 100644
352.6726 +--- a/src/sna/gen6_render.c
352.6727 ++++ b/src/sna/gen6_render.c
352.6728 +@@ -1633,9 +1633,9 @@ gen6_render_video(struct sna *sna,
352.6729 + 	int src_height = frame->src.y2 - frame->src.y1;
352.6730 + 	float src_offset_x, src_offset_y;
352.6731 + 	float src_scale_x, src_scale_y;
352.6732 +-	int nbox, pix_xoff, pix_yoff;
352.6733 + 	unsigned filter;
352.6734 + 	const BoxRec *box;
352.6735 ++	int nbox;
352.6736 + 
352.6737 + 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
352.6738 + 	     __FUNCTION__,
352.6739 +@@ -1686,17 +1686,6 @@ gen6_render_video(struct sna *sna,
352.6740 + 	gen6_align_vertex(sna, &tmp);
352.6741 + 	gen6_emit_video_state(sna, &tmp);
352.6742 + 
352.6743 +-	/* Set up the offset for translating from the given region (in screen
352.6744 +-	 * coordinates) to the backing pixmap.
352.6745 +-	 */
352.6746 +-#ifdef COMPOSITE
352.6747 +-	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.6748 +-	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.6749 +-#else
352.6750 +-	pix_xoff = 0;
352.6751 +-	pix_yoff = 0;
352.6752 +-#endif
352.6753 +-
352.6754 + 	src_scale_x = (float)src_width / dst_width / frame->width;
352.6755 + 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
352.6756 + 
352.6757 +@@ -1706,35 +1695,27 @@ gen6_render_video(struct sna *sna,
352.6758 + 	box = region_rects(dstRegion);
352.6759 + 	nbox = region_num_rects(dstRegion);
352.6760 + 	while (nbox--) {
352.6761 +-		BoxRec r;
352.6762 +-
352.6763 +-		r.x1 = box->x1 + pix_xoff;
352.6764 +-		r.x2 = box->x2 + pix_xoff;
352.6765 +-		r.y1 = box->y1 + pix_yoff;
352.6766 +-		r.y2 = box->y2 + pix_yoff;
352.6767 +-
352.6768 + 		gen6_get_rectangles(sna, &tmp, 1, gen6_emit_video_state);
352.6769 + 
352.6770 +-		OUT_VERTEX(r.x2, r.y2);
352.6771 ++		OUT_VERTEX(box->x2, box->y2);
352.6772 + 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.6773 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6774 + 
352.6775 +-		OUT_VERTEX(r.x1, r.y2);
352.6776 ++		OUT_VERTEX(box->x1, box->y2);
352.6777 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6778 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.6779 + 
352.6780 +-		OUT_VERTEX(r.x1, r.y1);
352.6781 ++		OUT_VERTEX(box->x1, box->y1);
352.6782 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.6783 + 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.6784 + 
352.6785 +-		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.6786 +-			sna_damage_add_box(&priv->gpu_damage, &r);
352.6787 +-			sna_damage_subtract_box(&priv->cpu_damage, &r);
352.6788 +-		}
352.6789 + 		box++;
352.6790 + 	}
352.6791 +-
352.6792 + 	gen4_vertex_flush(sna);
352.6793 ++
352.6794 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.6795 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.6796 ++
352.6797 + 	return true;
352.6798 + }
352.6799 + 
352.6800 +@@ -1815,12 +1796,12 @@ gen6_composite_picture(struct sna *sna,
352.6801 + 		if (channel->repeat &&
352.6802 + 		    (x >= 0 &&
352.6803 + 		     y >= 0 &&
352.6804 +-		     x + w < pixmap->drawable.width &&
352.6805 +-		     y + h < pixmap->drawable.height)) {
352.6806 ++		     x + w <= pixmap->drawable.width &&
352.6807 ++		     y + h <= pixmap->drawable.height)) {
352.6808 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.6809 + 			if (priv && priv->clear) {
352.6810 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.6811 +-				return gen4_channel_init_solid(sna, channel, priv->clear_color);
352.6812 ++				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
352.6813 + 			}
352.6814 + 		}
352.6815 + 	} else
352.6816 +@@ -1927,7 +1908,9 @@ gen6_composite_set_target(struct sna *sna,
352.6817 + 	} else
352.6818 + 		sna_render_picture_extents(dst, &box);
352.6819 + 
352.6820 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.6821 ++	hint = PREFER_GPU | RENDER_GPU;
352.6822 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.6823 ++		hint |= FORCE_GPU;
352.6824 + 	if (!partial) {
352.6825 + 		hint |= IGNORE_DAMAGE;
352.6826 + 		if (w == op->dst.width && h == op->dst.height)
352.6827 +@@ -1965,46 +1948,77 @@ gen6_composite_set_target(struct sna *sna,
352.6828 + 
352.6829 + static bool
352.6830 + try_blt(struct sna *sna,
352.6831 +-	PicturePtr dst, PicturePtr src,
352.6832 +-	int width, int height)
352.6833 ++	uint8_t op,
352.6834 ++	PicturePtr src,
352.6835 ++	PicturePtr mask,
352.6836 ++	PicturePtr dst,
352.6837 ++	int16_t src_x, int16_t src_y,
352.6838 ++	int16_t msk_x, int16_t msk_y,
352.6839 ++	int16_t dst_x, int16_t dst_y,
352.6840 ++	int16_t width, int16_t height,
352.6841 ++	unsigned flags,
352.6842 ++	struct sna_composite_op *tmp)
352.6843 + {
352.6844 + 	struct kgem_bo *bo;
352.6845 + 
352.6846 + 	if (sna->kgem.mode == KGEM_BLT) {
352.6847 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.6848 +-		return true;
352.6849 ++		goto execute;
352.6850 + 	}
352.6851 + 
352.6852 + 	if (too_large(width, height)) {
352.6853 + 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
352.6854 + 		     __FUNCTION__, width, height));
352.6855 +-		return true;
352.6856 ++		goto execute;
352.6857 + 	}
352.6858 + 
352.6859 + 	bo = __sna_drawable_peek_bo(dst->pDrawable);
352.6860 + 	if (bo == NULL)
352.6861 +-		return true;
352.6862 +-	if (bo->rq)
352.6863 +-		return RQ_IS_BLT(bo->rq);
352.6864 ++		goto execute;
352.6865 ++
352.6866 ++	if (untiled_tlb_miss(bo))
352.6867 ++		goto execute;
352.6868 ++
352.6869 ++	if (bo->rq) {
352.6870 ++		if (RQ_IS_BLT(bo->rq))
352.6871 ++			goto execute;
352.6872 ++
352.6873 ++		return false;
352.6874 ++	}
352.6875 ++
352.6876 ++	if (bo->tiling == I915_TILING_Y)
352.6877 ++		goto upload;
352.6878 ++
352.6879 ++	if (src->pDrawable == dst->pDrawable &&
352.6880 ++	    can_switch_to_blt(sna, bo, 0))
352.6881 ++		goto execute;
352.6882 + 
352.6883 + 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
352.6884 +-		return true;
352.6885 ++		goto execute;
352.6886 + 
352.6887 + 	if (src->pDrawable) {
352.6888 +-		bo = __sna_drawable_peek_bo(src->pDrawable);
352.6889 +-		if (bo == NULL)
352.6890 +-			return true;
352.6891 ++		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
352.6892 ++		if (s == NULL)
352.6893 ++			goto execute;
352.6894 + 
352.6895 +-		if (prefer_blt_bo(sna, bo))
352.6896 +-			return true;
352.6897 ++		if (prefer_blt_bo(sna, s, bo))
352.6898 ++			goto execute;
352.6899 + 	}
352.6900 + 
352.6901 + 	if (sna->kgem.ring == KGEM_BLT) {
352.6902 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.6903 +-		return true;
352.6904 ++		goto execute;
352.6905 + 	}
352.6906 + 
352.6907 +-	return false;
352.6908 ++upload:
352.6909 ++	flags |= COMPOSITE_UPLOAD;
352.6910 ++execute:
352.6911 ++	return sna_blt_composite(sna, op,
352.6912 ++				 src, dst,
352.6913 ++				 src_x, src_y,
352.6914 ++				 dst_x, dst_y,
352.6915 ++				 width, height,
352.6916 ++				 flags, tmp);
352.6917 + }
352.6918 + 
352.6919 + static bool
352.6920 +@@ -2234,13 +2248,13 @@ gen6_render_composite(struct sna *sna,
352.6921 + 	     width, height, sna->kgem.ring));
352.6922 + 
352.6923 + 	if (mask == NULL &&
352.6924 +-	    try_blt(sna, dst, src, width, height) &&
352.6925 +-	    sna_blt_composite(sna, op,
352.6926 +-			      src, dst,
352.6927 +-			      src_x, src_y,
352.6928 +-			      dst_x, dst_y,
352.6929 +-			      width, height,
352.6930 +-			      flags, tmp))
352.6931 ++	    try_blt(sna, op,
352.6932 ++		    src, mask, dst,
352.6933 ++		    src_x, src_y,
352.6934 ++		    msk_x, msk_y,
352.6935 ++		    dst_x, dst_y,
352.6936 ++		    width, height,
352.6937 ++		    flags, tmp))
352.6938 + 		return true;
352.6939 + 
352.6940 + 	if (gen6_composite_fallback(sna, src, mask, dst))
352.6941 +@@ -2676,27 +2690,35 @@ static inline bool prefer_blt_copy(struct sna *sna,
352.6942 + 	if (sna->kgem.ring == KGEM_BLT)
352.6943 + 		return true;
352.6944 + 
352.6945 +-	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
352.6946 ++	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
352.6947 ++		return false;
352.6948 ++
352.6949 ++	if ((flags & COPY_SMALL || src_bo == dst_bo) &&
352.6950 ++	    can_switch_to_blt(sna, dst_bo, flags))
352.6951 + 		return true;
352.6952 + 
352.6953 + 	if (untiled_tlb_miss(src_bo) ||
352.6954 + 	    untiled_tlb_miss(dst_bo))
352.6955 + 		return true;
352.6956 + 
352.6957 +-	if (force_blt_ring(sna))
352.6958 ++	if (force_blt_ring(sna, dst_bo))
352.6959 + 		return true;
352.6960 + 
352.6961 + 	if (kgem_bo_is_render(dst_bo) ||
352.6962 + 	    kgem_bo_is_render(src_bo))
352.6963 + 		return false;
352.6964 + 
352.6965 ++	if (flags & COPY_LAST &&
352.6966 ++            can_switch_to_blt(sna, dst_bo, flags))
352.6967 ++		return true;
352.6968 ++
352.6969 + 	if (prefer_render_ring(sna, dst_bo))
352.6970 + 		return false;
352.6971 + 
352.6972 + 	if (!prefer_blt_ring(sna, dst_bo, flags))
352.6973 + 		return false;
352.6974 + 
352.6975 +-	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
352.6976 ++	return prefer_blt_bo(sna, src_bo, dst_bo);
352.6977 + }
352.6978 + 
352.6979 + static bool
352.6980 +@@ -2758,8 +2780,7 @@ fallback_blt:
352.6981 + 		assert(src->depth == dst->depth);
352.6982 + 		assert(src->width == dst->width);
352.6983 + 		assert(src->height == dst->height);
352.6984 +-		return sna_render_copy_boxes__overlap(sna, alu,
352.6985 +-						      src, src_bo,
352.6986 ++		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
352.6987 + 						      src_dx, src_dy,
352.6988 + 						      dst_dx, dst_dy,
352.6989 + 						      box, n, &extents);
352.6990 +diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
352.6991 +index 2ecfd641..aabb8693 100644
352.6992 +--- a/src/sna/gen7_render.c
352.6993 ++++ b/src/sna/gen7_render.c
352.6994 +@@ -60,8 +60,6 @@
352.6995 + #define NO_FILL_ONE 0
352.6996 + #define NO_FILL_CLEAR 0
352.6997 + 
352.6998 +-#define NO_RING_SWITCH 0
352.6999 +-
352.7000 + #define USE_8_PIXEL_DISPATCH 1
352.7001 + #define USE_16_PIXEL_DISPATCH 1
352.7002 + #define USE_32_PIXEL_DISPATCH 0
352.7003 +@@ -149,7 +147,7 @@ static const struct gt_info hsw_gt1_info = {
352.7004 + 	.max_vs_threads = 70,
352.7005 + 	.max_gs_threads = 70,
352.7006 + 	.max_wm_threads =
352.7007 +-		(102 - 1) << HSW_PS_MAX_THREADS_SHIFT |
352.7008 ++		(70 - 1) << HSW_PS_MAX_THREADS_SHIFT |
352.7009 + 		1 << HSW_PS_SAMPLE_MASK_SHIFT,
352.7010 + 	.urb = { 128, 640, 256, 8 },
352.7011 + 	.gt = 1,
352.7012 +@@ -209,6 +207,12 @@ static const uint32_t ps_kernel_planar[][4] = {
352.7013 + #include "exa_wm_write.g7b"
352.7014 + };
352.7015 + 
352.7016 ++static const uint32_t ps_kernel_rgb[][4] = {
352.7017 ++#include "exa_wm_src_affine.g7b"
352.7018 ++#include "exa_wm_src_sample_argb.g7b"
352.7019 ++#include "exa_wm_write.g7b"
352.7020 ++};
352.7021 ++
352.7022 + #define KERNEL(kernel_enum, kernel, num_surfaces) \
352.7023 +     [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces}
352.7024 + #define NOKERNEL(kernel_enum, func, num_surfaces) \
352.7025 +@@ -218,7 +222,7 @@ static const struct wm_kernel_info {
352.7026 + 	const void *data;
352.7027 + 	unsigned int size;
352.7028 + 	int num_surfaces;
352.7029 +-} wm_kernels[] = {
352.7030 ++} wm_kernels[GEN7_WM_KERNEL_COUNT] = {
352.7031 + 	NOKERNEL(NOMASK, brw_wm_kernel__affine, 2),
352.7032 + 	NOKERNEL(NOMASK_P, brw_wm_kernel__projective, 2),
352.7033 + 
352.7034 +@@ -236,6 +240,7 @@ static const struct wm_kernel_info {
352.7035 + 
352.7036 + 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
352.7037 + 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
352.7038 ++	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
352.7039 + };
352.7040 + #undef KERNEL
352.7041 + 
352.7042 +@@ -810,7 +815,7 @@ gen7_emit_cc(struct sna *sna, uint32_t blend_offset)
352.7043 + 
352.7044 + 	DBG(("%s: blend = %x\n", __FUNCTION__, blend_offset));
352.7045 + 
352.7046 +-	/* XXX can have upto 8 blend states preload, selectable via
352.7047 ++	/* XXX can have up to 8 blend states preload, selectable via
352.7048 + 	 * Render Target Index. What other side-effects of Render Target Index?
352.7049 + 	 */
352.7050 + 
352.7051 +@@ -1792,7 +1797,9 @@ static void gen7_emit_video_state(struct sna *sna,
352.7052 + 			frame->pitch[0];
352.7053 + 		n_src = 6;
352.7054 + 	} else {
352.7055 +-		if (frame->id == FOURCC_UYVY)
352.7056 ++		if (frame->id == FOURCC_RGB888)
352.7057 ++			src_surf_format = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
352.7058 ++		else if (frame->id == FOURCC_UYVY)
352.7059 + 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY;
352.7060 + 		else
352.7061 + 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL;
352.7062 +@@ -1826,6 +1833,23 @@ static void gen7_emit_video_state(struct sna *sna,
352.7063 + 	gen7_emit_state(sna, op, offset | dirty);
352.7064 + }
352.7065 + 
352.7066 ++static unsigned select_video_kernel(const struct sna_video_frame *frame)
352.7067 ++{
352.7068 ++	switch (frame->id) {
352.7069 ++	case FOURCC_YV12:
352.7070 ++	case FOURCC_I420:
352.7071 ++	case FOURCC_XVMC:
352.7072 ++		return GEN7_WM_KERNEL_VIDEO_PLANAR;
352.7073 ++
352.7074 ++	case FOURCC_RGB888:
352.7075 ++	case FOURCC_RGB565:
352.7076 ++		return GEN7_WM_KERNEL_VIDEO_RGB;
352.7077 ++
352.7078 ++	default:
352.7079 ++		return GEN7_WM_KERNEL_VIDEO_PACKED;
352.7080 ++	}
352.7081 ++}
352.7082 ++
352.7083 + static bool
352.7084 + gen7_render_video(struct sna *sna,
352.7085 + 		  struct sna_video *video,
352.7086 +@@ -1841,9 +1865,9 @@ gen7_render_video(struct sna *sna,
352.7087 + 	int src_height = frame->src.y2 - frame->src.y1;
352.7088 + 	float src_offset_x, src_offset_y;
352.7089 + 	float src_scale_x, src_scale_y;
352.7090 +-	int nbox, pix_xoff, pix_yoff;
352.7091 + 	unsigned filter;
352.7092 + 	const BoxRec *box;
352.7093 ++	int nbox;
352.7094 + 
352.7095 + 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
352.7096 + 	     __FUNCTION__,
352.7097 +@@ -1878,9 +1902,7 @@ gen7_render_video(struct sna *sna,
352.7098 + 		GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
352.7099 + 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
352.7100 + 			       NO_BLEND,
352.7101 +-			       is_planar_fourcc(frame->id) ?
352.7102 +-			       GEN7_WM_KERNEL_VIDEO_PLANAR :
352.7103 +-			       GEN7_WM_KERNEL_VIDEO_PACKED,
352.7104 ++			       select_video_kernel(frame),
352.7105 + 			       2);
352.7106 + 	tmp.priv = frame;
352.7107 + 
352.7108 +@@ -1896,17 +1918,6 @@ gen7_render_video(struct sna *sna,
352.7109 + 	gen7_align_vertex(sna, &tmp);
352.7110 + 	gen7_emit_video_state(sna, &tmp);
352.7111 + 
352.7112 +-	/* Set up the offset for translating from the given region (in screen
352.7113 +-	 * coordinates) to the backing pixmap.
352.7114 +-	 */
352.7115 +-#ifdef COMPOSITE
352.7116 +-	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.7117 +-	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.7118 +-#else
352.7119 +-	pix_xoff = 0;
352.7120 +-	pix_yoff = 0;
352.7121 +-#endif
352.7122 +-
352.7123 + 	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
352.7124 + 	     __FUNCTION__,
352.7125 + 	     frame->src.x1, frame->src.y1,
352.7126 +@@ -1928,45 +1939,36 @@ gen7_render_video(struct sna *sna,
352.7127 + 	box = region_rects(dstRegion);
352.7128 + 	nbox = region_num_rects(dstRegion);
352.7129 + 	while (nbox--) {
352.7130 +-		BoxRec r;
352.7131 +-
352.7132 +-		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
352.7133 ++		DBG(("%s: dst=(%d, %d), (%d, %d); src=(%f, %f), (%f, %f)\n",
352.7134 + 		     __FUNCTION__,
352.7135 + 		     box->x1, box->y1,
352.7136 + 		     box->x2, box->y2,
352.7137 +-		     pix_xoff, pix_yoff,
352.7138 + 		     box->x1 * src_scale_x + src_offset_x,
352.7139 + 		     box->y1 * src_scale_y + src_offset_y,
352.7140 + 		     box->x2 * src_scale_x + src_offset_x,
352.7141 + 		     box->y2 * src_scale_y + src_offset_y));
352.7142 + 
352.7143 +-		r.x1 = box->x1 + pix_xoff;
352.7144 +-		r.x2 = box->x2 + pix_xoff;
352.7145 +-		r.y1 = box->y1 + pix_yoff;
352.7146 +-		r.y2 = box->y2 + pix_yoff;
352.7147 +-
352.7148 + 		gen7_get_rectangles(sna, &tmp, 1, gen7_emit_video_state);
352.7149 + 
352.7150 +-		OUT_VERTEX(r.x2, r.y2);
352.7151 ++		OUT_VERTEX(box->x2, box->y2);
352.7152 + 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.7153 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.7154 + 
352.7155 +-		OUT_VERTEX(r.x1, r.y2);
352.7156 ++		OUT_VERTEX(box->x1, box->y2);
352.7157 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.7158 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.7159 + 
352.7160 +-		OUT_VERTEX(r.x1, r.y1);
352.7161 ++		OUT_VERTEX(box->x1, box->y1);
352.7162 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.7163 + 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.7164 + 
352.7165 +-		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.7166 +-			sna_damage_add_box(&priv->gpu_damage, &r);
352.7167 +-			sna_damage_subtract_box(&priv->cpu_damage, &r);
352.7168 +-		}
352.7169 + 		box++;
352.7170 + 	}
352.7171 +-
352.7172 + 	gen4_vertex_flush(sna);
352.7173 ++
352.7174 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.7175 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.7176 ++
352.7177 + 	return true;
352.7178 + }
352.7179 + 
352.7180 +@@ -2048,12 +2050,13 @@ gen7_composite_picture(struct sna *sna,
352.7181 + 		if (channel->repeat ||
352.7182 + 		    (x >= 0 &&
352.7183 + 		     y >= 0 &&
352.7184 +-		     x + w < pixmap->drawable.width &&
352.7185 +-		     y + h < pixmap->drawable.height)) {
352.7186 ++		     x + w <= pixmap->drawable.width &&
352.7187 ++		     y + h <= pixmap->drawable.height)) {
352.7188 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.7189 + 			if (priv && priv->clear) {
352.7190 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.7191 +-				return gen4_channel_init_solid(sna, channel, priv->clear_color);
352.7192 ++				return gen4_channel_init_solid(sna, channel,
352.7193 ++							       solid_color(picture->format, priv->clear_color));
352.7194 + 			}
352.7195 + 		}
352.7196 + 	} else
352.7197 +@@ -2147,7 +2150,9 @@ gen7_composite_set_target(struct sna *sna,
352.7198 + 	} else
352.7199 + 		sna_render_picture_extents(dst, &box);
352.7200 + 
352.7201 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.7202 ++	hint = PREFER_GPU | RENDER_GPU;
352.7203 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.7204 ++		hint |= FORCE_GPU;
352.7205 + 	if (!partial) {
352.7206 + 		hint |= IGNORE_DAMAGE;
352.7207 + 		if (w == op->dst.width && h == op->dst.height)
352.7208 +@@ -2185,46 +2190,78 @@ gen7_composite_set_target(struct sna *sna,
352.7209 + 
352.7210 + static bool
352.7211 + try_blt(struct sna *sna,
352.7212 +-	PicturePtr dst, PicturePtr src,
352.7213 +-	int width, int height)
352.7214 ++	uint8_t op,
352.7215 ++	PicturePtr src,
352.7216 ++	PicturePtr mask,
352.7217 ++	PicturePtr dst,
352.7218 ++	int16_t src_x, int16_t src_y,
352.7219 ++	int16_t msk_x, int16_t msk_y,
352.7220 ++	int16_t dst_x, int16_t dst_y,
352.7221 ++	int16_t width, int16_t height,
352.7222 ++	unsigned flags,
352.7223 ++	struct sna_composite_op *tmp)
352.7224 + {
352.7225 + 	struct kgem_bo *bo;
352.7226 + 
352.7227 + 	if (sna->kgem.mode == KGEM_BLT) {
352.7228 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.7229 +-		return true;
352.7230 ++		goto execute;
352.7231 + 	}
352.7232 + 
352.7233 + 	if (too_large(width, height)) {
352.7234 + 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
352.7235 + 		     __FUNCTION__, width, height));
352.7236 +-		return true;
352.7237 ++		goto execute;
352.7238 + 	}
352.7239 + 
352.7240 + 	bo = __sna_drawable_peek_bo(dst->pDrawable);
352.7241 + 	if (bo == NULL)
352.7242 +-		return true;
352.7243 +-	if (bo->rq)
352.7244 +-		return RQ_IS_BLT(bo->rq);
352.7245 ++		goto execute;
352.7246 ++
352.7247 ++	if (untiled_tlb_miss(bo))
352.7248 ++		goto execute;
352.7249 ++
352.7250 ++	if (bo->rq) {
352.7251 ++		if (RQ_IS_BLT(bo->rq))
352.7252 ++			goto execute;
352.7253 ++
352.7254 ++		return false;
352.7255 ++	}
352.7256 ++
352.7257 ++	if (bo->tiling == I915_TILING_Y)
352.7258 ++		goto upload;
352.7259 ++
352.7260 ++	if (src->pDrawable == dst->pDrawable &&
352.7261 ++	    (sna->render_state.gt < 3 || width*height < 1024) &&
352.7262 ++	    can_switch_to_blt(sna, bo, 0))
352.7263 ++		goto execute;
352.7264 + 
352.7265 + 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
352.7266 +-		return true;
352.7267 ++		goto execute;
352.7268 + 
352.7269 + 	if (src->pDrawable) {
352.7270 +-		bo = __sna_drawable_peek_bo(src->pDrawable);
352.7271 +-		if (bo == NULL)
352.7272 +-			return true;
352.7273 ++		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
352.7274 ++		if (s == NULL)
352.7275 ++			goto upload;
352.7276 + 
352.7277 +-		if (prefer_blt_bo(sna, bo))
352.7278 +-			return true;
352.7279 ++		if (prefer_blt_bo(sna, s, bo))
352.7280 ++			goto execute;
352.7281 + 	}
352.7282 + 
352.7283 + 	if (sna->kgem.ring == KGEM_BLT) {
352.7284 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.7285 +-		return true;
352.7286 ++		goto execute;
352.7287 + 	}
352.7288 + 
352.7289 +-	return false;
352.7290 ++upload:
352.7291 ++	flags |= COMPOSITE_UPLOAD;
352.7292 ++execute:
352.7293 ++	return sna_blt_composite(sna, op,
352.7294 ++				 src, dst,
352.7295 ++				 src_x, src_y,
352.7296 ++				 dst_x, dst_y,
352.7297 ++				 width, height,
352.7298 ++				 flags, tmp);
352.7299 + }
352.7300 + 
352.7301 + static bool
352.7302 +@@ -2454,13 +2491,13 @@ gen7_render_composite(struct sna *sna,
352.7303 + 	     width, height, sna->kgem.mode, sna->kgem.ring));
352.7304 + 
352.7305 + 	if (mask == NULL &&
352.7306 +-	    try_blt(sna, dst, src, width, height) &&
352.7307 +-	    sna_blt_composite(sna, op,
352.7308 +-			      src, dst,
352.7309 +-			      src_x, src_y,
352.7310 +-			      dst_x, dst_y,
352.7311 +-			      width, height,
352.7312 +-			      flags, tmp))
352.7313 ++	    try_blt(sna, op,
352.7314 ++		    src, mask, dst,
352.7315 ++		    src_x, src_y,
352.7316 ++		    msk_x, msk_y,
352.7317 ++		    dst_x, dst_y,
352.7318 ++		    width, height,
352.7319 ++		    flags, tmp))
352.7320 + 		return true;
352.7321 + 
352.7322 + 	if (gen7_composite_fallback(sna, src, mask, dst))
352.7323 +@@ -2878,27 +2915,37 @@ prefer_blt_copy(struct sna *sna,
352.7324 + 
352.7325 + 	assert((flags & COPY_SYNC) == 0);
352.7326 + 
352.7327 +-	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
352.7328 +-		return true;
352.7329 +-
352.7330 + 	if (untiled_tlb_miss(src_bo) ||
352.7331 + 	    untiled_tlb_miss(dst_bo))
352.7332 + 		return true;
352.7333 + 
352.7334 +-	if (force_blt_ring(sna))
352.7335 ++	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
352.7336 ++		return false;
352.7337 ++
352.7338 ++	if (force_blt_ring(sna, dst_bo))
352.7339 ++		return true;
352.7340 ++
352.7341 ++	if ((flags & COPY_SMALL ||
352.7342 ++	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
352.7343 ++            can_switch_to_blt(sna, dst_bo, flags))
352.7344 + 		return true;
352.7345 + 
352.7346 + 	if (kgem_bo_is_render(dst_bo) ||
352.7347 + 	    kgem_bo_is_render(src_bo))
352.7348 + 		return false;
352.7349 + 
352.7350 ++	if (flags & COPY_LAST &&
352.7351 ++	    sna->render_state.gt < 3 &&
352.7352 ++            can_switch_to_blt(sna, dst_bo, flags))
352.7353 ++		return true;
352.7354 ++
352.7355 + 	if (prefer_render_ring(sna, dst_bo))
352.7356 + 		return false;
352.7357 + 
352.7358 + 	if (!prefer_blt_ring(sna, dst_bo, flags))
352.7359 + 		return false;
352.7360 + 
352.7361 +-	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
352.7362 ++	return prefer_blt_bo(sna, src_bo, dst_bo);
352.7363 + }
352.7364 + 
352.7365 + static bool
352.7366 +@@ -2946,7 +2993,7 @@ fallback_blt:
352.7367 + 		     &extents)) {
352.7368 + 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
352.7369 + 
352.7370 +-		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
352.7371 ++		if ((big || !prefer_render_ring(sna, dst_bo)) &&
352.7372 + 		    sna_blt_copy_boxes(sna, alu,
352.7373 + 				       src_bo, src_dx, src_dy,
352.7374 + 				       dst_bo, dst_dx, dst_dy,
352.7375 +@@ -2961,8 +3008,7 @@ fallback_blt:
352.7376 + 		assert(src->depth == dst->depth);
352.7377 + 		assert(src->width == dst->width);
352.7378 + 		assert(src->height == dst->height);
352.7379 +-		return sna_render_copy_boxes__overlap(sna, alu,
352.7380 +-						      src, src_bo,
352.7381 ++		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
352.7382 + 						      src_dx, src_dy,
352.7383 + 						      dst_dx, dst_dy,
352.7384 + 						      box, n, &extents);
352.7385 +diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
352.7386 +index 6eb11452..445983b1 100644
352.7387 +--- a/src/sna/gen8_render.c
352.7388 ++++ b/src/sna/gen8_render.c
352.7389 +@@ -106,6 +106,12 @@ static const uint32_t ps_kernel_planar[][4] = {
352.7390 + #include "exa_wm_yuv_rgb.g8b"
352.7391 + #include "exa_wm_write.g8b"
352.7392 + };
352.7393 ++
352.7394 ++static const uint32_t ps_kernel_rgb[][4] = {
352.7395 ++#include "exa_wm_src_affine.g8b"
352.7396 ++#include "exa_wm_src_sample_argb.g8b"
352.7397 ++#include "exa_wm_write.g8b"
352.7398 ++};
352.7399 + #endif
352.7400 + 
352.7401 + #define SURFACE_DW (64 / sizeof(uint32_t));
352.7402 +@@ -119,7 +125,7 @@ static const struct wm_kernel_info {
352.7403 + 	const void *data;
352.7404 + 	unsigned int size;
352.7405 + 	int num_surfaces;
352.7406 +-} wm_kernels[] = {
352.7407 ++} wm_kernels[GEN8_WM_KERNEL_COUNT] = {
352.7408 + 	NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2),
352.7409 + 	NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2),
352.7410 + 
352.7411 +@@ -138,6 +144,7 @@ static const struct wm_kernel_info {
352.7412 + #if !NO_VIDEO
352.7413 + 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
352.7414 + 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
352.7415 ++	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
352.7416 + #endif
352.7417 + };
352.7418 + #undef KERNEL
352.7419 +@@ -205,6 +212,33 @@ static const struct blendinfo {
352.7420 + #define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
352.7421 + #define OUT_VERTEX_F(v) vertex_emit(sna, v)
352.7422 + 
352.7423 ++struct gt_info {
352.7424 ++	const char *name;
352.7425 ++	struct {
352.7426 ++		int max_vs_entries;
352.7427 ++	} urb;
352.7428 ++};
352.7429 ++
352.7430 ++static const struct gt_info bdw_gt_info = {
352.7431 ++	.name = "Broadwell (gen8)",
352.7432 ++	.urb = { .max_vs_entries = 960 },
352.7433 ++};
352.7434 ++
352.7435 ++static bool is_bdw(struct sna *sna)
352.7436 ++{
352.7437 ++	return sna->kgem.gen == 0100;
352.7438 ++}
352.7439 ++
352.7440 ++static const struct gt_info chv_gt_info = {
352.7441 ++	.name = "Cherryview (gen8)",
352.7442 ++	.urb = { .max_vs_entries = 640 },
352.7443 ++};
352.7444 ++
352.7445 ++static bool is_chv(struct sna *sna)
352.7446 ++{
352.7447 ++	return sna->kgem.gen == 0101;
352.7448 ++}
352.7449 ++
352.7450 + static inline bool too_large(int width, int height)
352.7451 + {
352.7452 + 	return width > GEN8_MAX_SIZE || height > GEN8_MAX_SIZE;
352.7453 +@@ -462,7 +496,7 @@ gen8_emit_urb(struct sna *sna)
352.7454 + {
352.7455 + 	/* num of VS entries must be divisible by 8 if size < 9 */
352.7456 + 	OUT_BATCH(GEN8_3DSTATE_URB_VS | (2 - 2));
352.7457 +-	OUT_BATCH(960 << URB_ENTRY_NUMBER_SHIFT |
352.7458 ++	OUT_BATCH(sna->render_state.gen8.info->urb.max_vs_entries << URB_ENTRY_NUMBER_SHIFT |
352.7459 + 		  (2 - 1) << URB_ENTRY_SIZE_SHIFT |
352.7460 + 		  4 << URB_STARTING_ADDRESS_SHIFT);
352.7461 + 
352.7462 +@@ -873,7 +907,7 @@ gen8_emit_cc(struct sna *sna, uint32_t blend)
352.7463 + 	assert(blend / GEN8_BLENDFACTOR_COUNT > 0);
352.7464 + 	assert(blend % GEN8_BLENDFACTOR_COUNT > 0);
352.7465 + 
352.7466 +-	/* XXX can have upto 8 blend states preload, selectable via
352.7467 ++	/* XXX can have up to 8 blend states preload, selectable via
352.7468 + 	 * Render Target Index. What other side-effects of Render Target Index?
352.7469 + 	 */
352.7470 + 
352.7471 +@@ -1167,6 +1201,7 @@ gen8_emit_pipe_stall(struct sna *sna)
352.7472 + {
352.7473 + 	OUT_BATCH(GEN8_PIPE_CONTROL | (6 - 2));
352.7474 + 	OUT_BATCH(PIPE_CONTROL_CS_STALL |
352.7475 ++		  PIPE_CONTROL_FLUSH |
352.7476 + 		  PIPE_CONTROL_STALL_AT_SCOREBOARD);
352.7477 + 	OUT_BATCH64(0);
352.7478 + 	OUT_BATCH64(0);
352.7479 +@@ -1876,12 +1911,12 @@ gen8_composite_picture(struct sna *sna,
352.7480 + 		if (channel->repeat ||
352.7481 + 		    (x >= 0 &&
352.7482 + 		     y >= 0 &&
352.7483 +-		     x + w < pixmap->drawable.width &&
352.7484 +-		     y + h < pixmap->drawable.height)) {
352.7485 ++		     x + w <= pixmap->drawable.width &&
352.7486 ++		     y + h <= pixmap->drawable.height)) {
352.7487 + 			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.7488 + 			if (priv && priv->clear) {
352.7489 + 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.7490 +-				return gen4_channel_init_solid(sna, channel, priv->clear_color);
352.7491 ++				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
352.7492 + 			}
352.7493 + 		}
352.7494 + 	} else
352.7495 +@@ -1961,7 +1996,9 @@ gen8_composite_set_target(struct sna *sna,
352.7496 + 	} else
352.7497 + 		sna_render_picture_extents(dst, &box);
352.7498 + 
352.7499 +-	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
352.7500 ++	hint = PREFER_GPU | RENDER_GPU;
352.7501 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.7502 ++		hint |= FORCE_GPU;
352.7503 + 	if (!partial) {
352.7504 + 		hint |= IGNORE_DAMAGE;
352.7505 + 		if (w == op->dst.width && h == op->dst.height)
352.7506 +@@ -2002,46 +2039,78 @@ gen8_composite_set_target(struct sna *sna,
352.7507 + 
352.7508 + static bool
352.7509 + try_blt(struct sna *sna,
352.7510 +-	PicturePtr dst, PicturePtr src,
352.7511 +-	int width, int height)
352.7512 ++	uint8_t op,
352.7513 ++	PicturePtr src,
352.7514 ++	PicturePtr mask,
352.7515 ++	PicturePtr dst,
352.7516 ++	int16_t src_x, int16_t src_y,
352.7517 ++	int16_t msk_x, int16_t msk_y,
352.7518 ++	int16_t dst_x, int16_t dst_y,
352.7519 ++	int16_t width, int16_t height,
352.7520 ++	unsigned flags,
352.7521 ++	struct sna_composite_op *tmp)
352.7522 + {
352.7523 + 	struct kgem_bo *bo;
352.7524 + 
352.7525 + 	if (sna->kgem.mode == KGEM_BLT) {
352.7526 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.7527 +-		return true;
352.7528 ++		goto execute;
352.7529 + 	}
352.7530 + 
352.7531 + 	if (too_large(width, height)) {
352.7532 + 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
352.7533 + 		     __FUNCTION__, width, height));
352.7534 +-		return true;
352.7535 ++		goto execute;
352.7536 + 	}
352.7537 + 
352.7538 + 	bo = __sna_drawable_peek_bo(dst->pDrawable);
352.7539 + 	if (bo == NULL)
352.7540 +-		return true;
352.7541 +-	if (bo->rq)
352.7542 +-		return RQ_IS_BLT(bo->rq);
352.7543 ++		goto execute;
352.7544 ++
352.7545 ++	if (untiled_tlb_miss(bo))
352.7546 ++		goto execute;
352.7547 ++
352.7548 ++	if (bo->rq) {
352.7549 ++		if (RQ_IS_BLT(bo->rq))
352.7550 ++			goto execute;
352.7551 ++
352.7552 ++		return false;
352.7553 ++	}
352.7554 ++
352.7555 ++	if (bo->tiling == I915_TILING_Y)
352.7556 ++		goto upload;
352.7557 + 
352.7558 + 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
352.7559 +-		return true;
352.7560 ++		goto execute;
352.7561 ++
352.7562 ++	if (src->pDrawable == dst->pDrawable &&
352.7563 ++	    (sna->render_state.gt < 3 || width*height < 1024) &&
352.7564 ++	    can_switch_to_blt(sna, bo, 0))
352.7565 ++		goto execute;
352.7566 + 
352.7567 + 	if (src->pDrawable) {
352.7568 +-		bo = __sna_drawable_peek_bo(src->pDrawable);
352.7569 +-		if (bo == NULL)
352.7570 +-			return true;
352.7571 ++		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
352.7572 ++		if (s == NULL)
352.7573 ++			goto upload;
352.7574 + 
352.7575 +-		if (prefer_blt_bo(sna, bo))
352.7576 +-			return RQ_IS_BLT(bo->rq);
352.7577 ++		if (prefer_blt_bo(sna, s, bo))
352.7578 ++			goto execute;
352.7579 + 	}
352.7580 + 
352.7581 + 	if (sna->kgem.ring == KGEM_BLT) {
352.7582 + 		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.7583 +-		return true;
352.7584 ++		goto execute;
352.7585 + 	}
352.7586 + 
352.7587 +-	return false;
352.7588 ++upload:
352.7589 ++	flags |= COMPOSITE_UPLOAD;
352.7590 ++execute:
352.7591 ++	return sna_blt_composite(sna, op,
352.7592 ++				 src, dst,
352.7593 ++				 src_x, src_y,
352.7594 ++				 dst_x, dst_y,
352.7595 ++				 width, height,
352.7596 ++				 flags, tmp);
352.7597 + }
352.7598 + 
352.7599 + static bool
352.7600 +@@ -2271,13 +2340,13 @@ gen8_render_composite(struct sna *sna,
352.7601 + 	     width, height, sna->kgem.mode, sna->kgem.ring));
352.7602 + 
352.7603 + 	if (mask == NULL &&
352.7604 +-	    try_blt(sna, dst, src, width, height) &&
352.7605 +-	    sna_blt_composite(sna, op,
352.7606 +-			      src, dst,
352.7607 +-			      src_x, src_y,
352.7608 +-			      dst_x, dst_y,
352.7609 +-			      width, height,
352.7610 +-			      flags, tmp))
352.7611 ++	    try_blt(sna, op,
352.7612 ++		    src, mask, dst,
352.7613 ++		    src_x, src_y,
352.7614 ++		    msk_x, msk_y,
352.7615 ++		    dst_x, dst_y,
352.7616 ++		    width, height,
352.7617 ++		    flags, tmp))
352.7618 + 		return true;
352.7619 + 
352.7620 + 	if (gen8_composite_fallback(sna, src, mask, dst))
352.7621 +@@ -2700,27 +2769,37 @@ prefer_blt_copy(struct sna *sna,
352.7622 + 
352.7623 + 	assert((flags & COPY_SYNC) == 0);
352.7624 + 
352.7625 +-	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
352.7626 +-		return true;
352.7627 +-
352.7628 + 	if (untiled_tlb_miss(src_bo) ||
352.7629 + 	    untiled_tlb_miss(dst_bo))
352.7630 + 		return true;
352.7631 + 
352.7632 +-	if (force_blt_ring(sna))
352.7633 ++	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
352.7634 ++		return false;
352.7635 ++
352.7636 ++	if (force_blt_ring(sna, dst_bo))
352.7637 ++		return true;
352.7638 ++
352.7639 ++	if ((flags & COPY_SMALL ||
352.7640 ++	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
352.7641 ++	    can_switch_to_blt(sna, dst_bo, flags))
352.7642 + 		return true;
352.7643 + 
352.7644 + 	if (kgem_bo_is_render(dst_bo) ||
352.7645 + 	    kgem_bo_is_render(src_bo))
352.7646 + 		return false;
352.7647 + 
352.7648 ++	if (flags & COPY_LAST &&
352.7649 ++	    sna->render_state.gt < 3 &&
352.7650 ++            can_switch_to_blt(sna, dst_bo, flags))
352.7651 ++		return true;
352.7652 ++
352.7653 + 	if (prefer_render_ring(sna, dst_bo))
352.7654 + 		return false;
352.7655 + 
352.7656 + 	if (!prefer_blt_ring(sna, dst_bo, flags))
352.7657 + 		return false;
352.7658 + 
352.7659 +-	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
352.7660 ++	return prefer_blt_bo(sna, src_bo, dst_bo);
352.7661 + }
352.7662 + 
352.7663 + static bool
352.7664 +@@ -2770,7 +2849,7 @@ fallback_blt:
352.7665 + 		     &extents)) {
352.7666 + 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
352.7667 + 
352.7668 +-		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
352.7669 ++		if ((big || !prefer_render_ring(sna, dst_bo)) &&
352.7670 + 		    sna_blt_copy_boxes(sna, alu,
352.7671 + 				       src_bo, src_dx, src_dy,
352.7672 + 				       dst_bo, dst_dx, dst_dy,
352.7673 +@@ -2785,8 +2864,7 @@ fallback_blt:
352.7674 + 		assert(src->depth == dst->depth);
352.7675 + 		assert(src->width == dst->width);
352.7676 + 		assert(src->height == dst->height);
352.7677 +-		return sna_render_copy_boxes__overlap(sna, alu,
352.7678 +-						      src, src_bo,
352.7679 ++		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
352.7680 + 						      src_dx, src_dy,
352.7681 + 						      dst_dx, dst_dy,
352.7682 + 						      box, n, &extents);
352.7683 +@@ -3665,7 +3743,9 @@ static void gen8_emit_video_state(struct sna *sna,
352.7684 + 			frame->pitch[0];
352.7685 + 		n_src = 6;
352.7686 + 	} else {
352.7687 +-		if (frame->id == FOURCC_UYVY)
352.7688 ++		if (frame->id == FOURCC_RGB888)
352.7689 ++			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
352.7690 ++		else if (frame->id == FOURCC_UYVY)
352.7691 + 			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
352.7692 + 		else
352.7693 + 			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
352.7694 +@@ -3697,6 +3777,23 @@ static void gen8_emit_video_state(struct sna *sna,
352.7695 + 	gen8_emit_state(sna, op, offset);
352.7696 + }
352.7697 + 
352.7698 ++static unsigned select_video_kernel(const struct sna_video_frame *frame)
352.7699 ++{
352.7700 ++	switch (frame->id) {
352.7701 ++	case FOURCC_YV12:
352.7702 ++	case FOURCC_I420:
352.7703 ++	case FOURCC_XVMC:
352.7704 ++		return GEN8_WM_KERNEL_VIDEO_PLANAR;
352.7705 ++
352.7706 ++	case FOURCC_RGB888:
352.7707 ++	case FOURCC_RGB565:
352.7708 ++		return GEN8_WM_KERNEL_VIDEO_RGB;
352.7709 ++
352.7710 ++	default:
352.7711 ++		return GEN8_WM_KERNEL_VIDEO_PACKED;
352.7712 ++	}
352.7713 ++}
352.7714 ++
352.7715 + static bool
352.7716 + gen8_render_video(struct sna *sna,
352.7717 + 		  struct sna_video *video,
352.7718 +@@ -3712,9 +3809,9 @@ gen8_render_video(struct sna *sna,
352.7719 + 	int src_height = frame->src.y2 - frame->src.y1;
352.7720 + 	float src_offset_x, src_offset_y;
352.7721 + 	float src_scale_x, src_scale_y;
352.7722 +-	int nbox, pix_xoff, pix_yoff;
352.7723 + 	unsigned filter;
352.7724 + 	const BoxRec *box;
352.7725 ++	int nbox;
352.7726 + 
352.7727 + 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
352.7728 + 	     __FUNCTION__,
352.7729 +@@ -3743,6 +3840,11 @@ gen8_render_video(struct sna *sna,
352.7730 + 	tmp.floats_per_vertex = 3;
352.7731 + 	tmp.floats_per_rect = 9;
352.7732 + 
352.7733 ++	DBG(("%s: scaling?=%d, planar?=%d [%x]\n",
352.7734 ++	     __FUNCTION__,
352.7735 ++	     src_width != dst_width || src_height != dst_height,
352.7736 ++	     is_planar_fourcc(frame->id), frame->id));
352.7737 ++
352.7738 + 	if (src_width == dst_width && src_height == dst_height)
352.7739 + 		filter = SAMPLER_FILTER_NEAREST;
352.7740 + 	else
352.7741 +@@ -3752,9 +3854,7 @@ gen8_render_video(struct sna *sna,
352.7742 + 		GEN8_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
352.7743 + 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
352.7744 + 			       NO_BLEND,
352.7745 +-			       is_planar_fourcc(frame->id) ?
352.7746 +-			       GEN8_WM_KERNEL_VIDEO_PLANAR :
352.7747 +-			       GEN8_WM_KERNEL_VIDEO_PACKED,
352.7748 ++			       select_video_kernel(frame),
352.7749 + 			       2);
352.7750 + 	tmp.priv = frame;
352.7751 + 
352.7752 +@@ -3770,17 +3870,6 @@ gen8_render_video(struct sna *sna,
352.7753 + 	gen8_align_vertex(sna, &tmp);
352.7754 + 	gen8_emit_video_state(sna, &tmp);
352.7755 + 
352.7756 +-	/* Set up the offset for translating from the given region (in screen
352.7757 +-	 * coordinates) to the backing pixmap.
352.7758 +-	 */
352.7759 +-#ifdef COMPOSITE
352.7760 +-	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
352.7761 +-	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
352.7762 +-#else
352.7763 +-	pix_xoff = 0;
352.7764 +-	pix_yoff = 0;
352.7765 +-#endif
352.7766 +-
352.7767 + 	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
352.7768 + 	     __FUNCTION__,
352.7769 + 	     frame->src.x1, frame->src.y1,
352.7770 +@@ -3802,45 +3891,36 @@ gen8_render_video(struct sna *sna,
352.7771 + 	box = region_rects(dstRegion);
352.7772 + 	nbox = region_num_rects(dstRegion);
352.7773 + 	while (nbox--) {
352.7774 +-		BoxRec r;
352.7775 +-
352.7776 + 		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
352.7777 + 		     __FUNCTION__,
352.7778 + 		     box->x1, box->y1,
352.7779 + 		     box->x2, box->y2,
352.7780 +-		     pix_xoff, pix_yoff,
352.7781 + 		     box->x1 * src_scale_x + src_offset_x,
352.7782 + 		     box->y1 * src_scale_y + src_offset_y,
352.7783 + 		     box->x2 * src_scale_x + src_offset_x,
352.7784 + 		     box->y2 * src_scale_y + src_offset_y));
352.7785 + 
352.7786 +-		r.x1 = box->x1 + pix_xoff;
352.7787 +-		r.x2 = box->x2 + pix_xoff;
352.7788 +-		r.y1 = box->y1 + pix_yoff;
352.7789 +-		r.y2 = box->y2 + pix_yoff;
352.7790 +-
352.7791 + 		gen8_get_rectangles(sna, &tmp, 1, gen8_emit_video_state);
352.7792 + 
352.7793 +-		OUT_VERTEX(r.x2, r.y2);
352.7794 ++		OUT_VERTEX(box->x2, box->y2);
352.7795 + 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.7796 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.7797 + 
352.7798 +-		OUT_VERTEX(r.x1, r.y2);
352.7799 ++		OUT_VERTEX(box->x1, box->y2);
352.7800 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.7801 + 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.7802 + 
352.7803 +-		OUT_VERTEX(r.x1, r.y1);
352.7804 ++		OUT_VERTEX(box->x1, box->y1);
352.7805 + 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.7806 + 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.7807 + 
352.7808 +-		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
352.7809 +-			sna_damage_add_box(&priv->gpu_damage, &r);
352.7810 +-			sna_damage_subtract_box(&priv->cpu_damage, &r);
352.7811 +-		}
352.7812 + 		box++;
352.7813 + 	}
352.7814 +-
352.7815 + 	gen8_vertex_flush(sna);
352.7816 ++
352.7817 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.7818 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.7819 ++
352.7820 + 	return true;
352.7821 + }
352.7822 + #endif
352.7823 +@@ -3896,6 +3976,13 @@ static bool gen8_render_setup(struct sna *sna)
352.7824 + 		state->gt = ((devid >> 4) & 0xf) + 1;
352.7825 + 	DBG(("%s: gt=%d\n", __FUNCTION__, state->gt));
352.7826 + 
352.7827 ++	if (is_bdw(sna))
352.7828 ++		state->info = &bdw_gt_info;
352.7829 ++	else if (is_chv(sna))
352.7830 ++		state->info = &chv_gt_info;
352.7831 ++	else
352.7832 ++		return false;
352.7833 ++
352.7834 + 	sna_static_stream_init(&general);
352.7835 + 
352.7836 + 	/* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
352.7837 +@@ -4007,5 +4094,5 @@ const char *gen8_render_init(struct sna *sna, const char *backend)
352.7838 + 
352.7839 + 	sna->render.max_3d_size = GEN8_MAX_SIZE;
352.7840 + 	sna->render.max_3d_pitch = 1 << 18;
352.7841 +-	return "Broadwell";
352.7842 ++	return sna->render_state.gen8.info->name;
352.7843 + }
352.7844 +diff --git a/src/sna/gen8_render.h b/src/sna/gen8_render.h
352.7845 +index eb4928e7..e6a8dc55 100644
352.7846 +--- a/src/sna/gen8_render.h
352.7847 ++++ b/src/sna/gen8_render.h
352.7848 +@@ -335,6 +335,7 @@
352.7849 + #define PIPE_CONTROL_IS_FLUSH      (1 << 11)
352.7850 + #define PIPE_CONTROL_TC_FLUSH      (1 << 10)
352.7851 + #define PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
352.7852 ++#define PIPE_CONTROL_FLUSH         (1 << 7)
352.7853 + #define PIPE_CONTROL_GLOBAL_GTT    (1 << 2)
352.7854 + #define PIPE_CONTROL_LOCAL_PGTT    (0 << 2)
352.7855 + #define PIPE_CONTROL_STALL_AT_SCOREBOARD   (1 << 1)
352.7856 +diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c
352.7857 +new file mode 100644
352.7858 +index 00000000..e5f12c72
352.7859 +--- /dev/null
352.7860 ++++ b/src/sna/gen9_render.c
352.7861 +@@ -0,0 +1,4156 @@
352.7862 ++/*
352.7863 ++ * Copyright © 2012,2013 Intel Corporation
352.7864 ++ *
352.7865 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.7866 ++ * copy of this software and associated documentation files (the "Software"),
352.7867 ++ * to deal in the Software without restriction, including without limitation
352.7868 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.7869 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.7870 ++ * Software is furnished to do so, subject to the following conditions:
352.7871 ++ *
352.7872 ++ * The above copyright notice and this permission notice (including the next
352.7873 ++ * paragraph) shall be included in all copies or substantial portions of the
352.7874 ++ * Software.
352.7875 ++ *
352.7876 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.7877 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.7878 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.7879 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.7880 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
352.7881 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
352.7882 ++ * SOFTWARE.
352.7883 ++ *
352.7884 ++ * Authors:
352.7885 ++ *    Chris Wilson <chris@chris-wilson.co.uk>
352.7886 ++ *
352.7887 ++ */
352.7888 ++
352.7889 ++#ifdef HAVE_CONFIG_H
352.7890 ++#include "config.h"
352.7891 ++#endif
352.7892 ++
352.7893 ++#include "sna.h"
352.7894 ++#include "sna_reg.h"
352.7895 ++#include "sna_render.h"
352.7896 ++#include "sna_render_inline.h"
352.7897 ++#include "sna_video.h"
352.7898 ++
352.7899 ++#include "gen9_render.h"
352.7900 ++#include "gen8_eu.h"
352.7901 ++#include "gen4_common.h"
352.7902 ++#include "gen4_source.h"
352.7903 ++#include "gen4_vertex.h"
352.7904 ++#include "gen6_common.h"
352.7905 ++#include "gen8_vertex.h"
352.7906 ++
352.7907 ++#define SIM 1
352.7908 ++
352.7909 ++#define ALWAYS_INVALIDATE 0
352.7910 ++#define ALWAYS_FLUSH 0
352.7911 ++#define ALWAYS_STALL 0
352.7912 ++
352.7913 ++#define NO_COMPOSITE 0
352.7914 ++#define NO_COMPOSITE_SPANS 0
352.7915 ++#define NO_COPY 0
352.7916 ++#define NO_COPY_BOXES 0
352.7917 ++#define NO_FILL 0
352.7918 ++#define NO_FILL_BOXES 0
352.7919 ++#define NO_FILL_ONE 0
352.7920 ++#define NO_FILL_CLEAR 0
352.7921 ++#define NO_VIDEO 0
352.7922 ++
352.7923 ++#define USE_8_PIXEL_DISPATCH 1
352.7924 ++#define USE_16_PIXEL_DISPATCH 1
352.7925 ++#define USE_32_PIXEL_DISPATCH 0
352.7926 ++
352.7927 ++#if !USE_8_PIXEL_DISPATCH && !USE_16_PIXEL_DISPATCH && !USE_32_PIXEL_DISPATCH
352.7928 ++#error "Must select at least 8, 16 or 32 pixel dispatch"
352.7929 ++#endif
352.7930 ++
352.7931 ++#define GEN9_MAX_SIZE 16384
352.7932 ++#define GEN9_GT_BIAS 1 /* Each GT is bigger than previous gen */
352.7933 ++
352.7934 ++/* XXX Todo
352.7935 ++ *
352.7936 ++ * STR (software tiled rendering) mode. No, really.
352.7937 ++ * 64x32 pixel blocks align with the rendering cache. Worth considering.
352.7938 ++ */
352.7939 ++
352.7940 ++#define is_aligned(x, y) (((x) & ((y) - 1)) == 0)
352.7941 ++
352.7942 ++/* Pipeline stages:
352.7943 ++ *  1. Command Streamer (CS)
352.7944 ++ *  2. Vertex Fetch (VF)
352.7945 ++ *  3. Vertex Shader (VS)
352.7946 ++ *  4. Hull Shader (HS)
352.7947 ++ *  5. Tesselation Engine (TE)
352.7948 ++ *  6. Domain Shader (DS)
352.7949 ++ *  7. Geometry Shader (GS)
352.7950 ++ *  8. Stream Output Logic (SOL)
352.7951 ++ *  9. Clipper (CLIP)
352.7952 ++ * 10. Strip/Fan (SF)
352.7953 ++ * 11. Windower/Masker (WM)
352.7954 ++ * 12. Color Calculator (CC)
352.7955 ++ */
352.7956 ++
352.7957 ++#if !NO_VIDEO
352.7958 ++static const uint32_t ps_kernel_packed[][4] = {
352.7959 ++#include "exa_wm_src_affine.g8b"
352.7960 ++#include "exa_wm_src_sample_argb.g8b"
352.7961 ++#include "exa_wm_yuv_rgb.g8b"
352.7962 ++#include "exa_wm_write.g8b"
352.7963 ++};
352.7964 ++
352.7965 ++static const uint32_t ps_kernel_planar[][4] = {
352.7966 ++#include "exa_wm_src_affine.g8b"
352.7967 ++#include "exa_wm_src_sample_planar.g8b"
352.7968 ++#include "exa_wm_yuv_rgb.g8b"
352.7969 ++#include "exa_wm_write.g8b"
352.7970 ++};
352.7971 ++
352.7972 ++static const uint32_t ps_kernel_rgb[][4] = {
352.7973 ++#include "exa_wm_src_affine.g8b"
352.7974 ++#include "exa_wm_src_sample_argb.g8b"
352.7975 ++#include "exa_wm_write.g8b"
352.7976 ++};
352.7977 ++#endif
352.7978 ++
352.7979 ++#define SURFACE_DW (64 / sizeof(uint32_t));
352.7980 ++
352.7981 ++#define KERNEL(kernel_enum, kernel, num_surfaces) \
352.7982 ++    [GEN9_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces}
352.7983 ++#define NOKERNEL(kernel_enum, func, num_surfaces) \
352.7984 ++    [GEN9_WM_KERNEL_##kernel_enum] = {#kernel_enum, (void *)func, 0, num_surfaces}
352.7985 ++static const struct wm_kernel_info {
352.7986 ++	const char *name;
352.7987 ++	const void *data;
352.7988 ++	unsigned int size;
352.7989 ++	int num_surfaces;
352.7990 ++} wm_kernels[] = {
352.7991 ++	NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2),
352.7992 ++	NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2),
352.7993 ++
352.7994 ++	NOKERNEL(MASK, gen8_wm_kernel__affine_mask, 3),
352.7995 ++	NOKERNEL(MASK_P, gen8_wm_kernel__projective_mask, 3),
352.7996 ++
352.7997 ++	NOKERNEL(MASKCA, gen8_wm_kernel__affine_mask_ca, 3),
352.7998 ++	NOKERNEL(MASKCA_P, gen8_wm_kernel__projective_mask_ca, 3),
352.7999 ++
352.8000 ++	NOKERNEL(MASKSA, gen8_wm_kernel__affine_mask_sa, 3),
352.8001 ++	NOKERNEL(MASKSA_P, gen8_wm_kernel__projective_mask_sa, 3),
352.8002 ++
352.8003 ++	NOKERNEL(OPACITY, gen8_wm_kernel__affine_opacity, 2),
352.8004 ++	NOKERNEL(OPACITY_P, gen8_wm_kernel__projective_opacity, 2),
352.8005 ++
352.8006 ++#if !NO_VIDEO
352.8007 ++	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
352.8008 ++	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
352.8009 ++	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
352.8010 ++#endif
352.8011 ++};
352.8012 ++#undef KERNEL
352.8013 ++
352.8014 ++static const struct blendinfo {
352.8015 ++	uint8_t src_alpha;
352.8016 ++	uint8_t src_blend;
352.8017 ++	uint8_t dst_blend;
352.8018 ++} gen9_blend_op[] = {
352.8019 ++	/* Clear */	{0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
352.8020 ++	/* Src */	{0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO},
352.8021 ++	/* Dst */	{0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE},
352.8022 ++	/* Over */	{1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA},
352.8023 ++	/* OverReverse */ {0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE},
352.8024 ++	/* In */	{0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO},
352.8025 ++	/* InReverse */	{1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA},
352.8026 ++	/* Out */	{0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO},
352.8027 ++	/* OutReverse */ {1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA},
352.8028 ++	/* Atop */	{1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
352.8029 ++	/* AtopReverse */ {1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA},
352.8030 ++	/* Xor */	{1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
352.8031 ++	/* Add */	{0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
352.8032 ++};
352.8033 ++
352.8034 ++/**
352.8035 ++ * Highest-valued BLENDFACTOR used in gen9_blend_op.
352.8036 ++ *
352.8037 ++ * This leaves out GEN9_BLENDFACTOR_INV_DST_COLOR,
352.8038 ++ * GEN9_BLENDFACTOR_INV_CONST_{COLOR,ALPHA},
352.8039 ++ * GEN9_BLENDFACTOR_INV_SRC1_{COLOR,ALPHA}
352.8040 ++ */
352.8041 ++#define GEN9_BLENDFACTOR_COUNT (BLENDFACTOR_INV_DST_ALPHA + 1)
352.8042 ++
352.8043 ++#define GEN9_BLEND_STATE_PADDED_SIZE	ALIGN(sizeof(struct gen9_blend_state), 64)
352.8044 ++
352.8045 ++#define BLEND_OFFSET(s, d) \
352.8046 ++	((d != BLENDFACTOR_ZERO) << 15 | ((s) * GEN9_BLENDFACTOR_COUNT + (d)) << 4)
352.8047 ++
352.8048 ++#define NO_BLEND BLEND_OFFSET(BLENDFACTOR_ONE, BLENDFACTOR_ZERO)
352.8049 ++#define CLEAR BLEND_OFFSET(BLENDFACTOR_ZERO, BLENDFACTOR_ZERO)
352.8050 ++
352.8051 ++#define SAMPLER_OFFSET(sf, se, mf, me) \
352.8052 ++	(((((sf) * EXTEND_COUNT + (se)) * FILTER_COUNT + (mf)) * EXTEND_COUNT + (me)) + 2)
352.8053 ++
352.8054 ++#define VERTEX_2s2s 0
352.8055 ++
352.8056 ++#define COPY_SAMPLER 0
352.8057 ++#define COPY_VERTEX VERTEX_2s2s
352.8058 ++#define COPY_FLAGS(a) GEN9_SET_FLAGS(COPY_SAMPLER, (a) == GXcopy ? NO_BLEND : CLEAR, GEN9_WM_KERNEL_NOMASK, COPY_VERTEX)
352.8059 ++
352.8060 ++#define FILL_SAMPLER 1
352.8061 ++#define FILL_VERTEX VERTEX_2s2s
352.8062 ++#define FILL_FLAGS(op, format) GEN9_SET_FLAGS(FILL_SAMPLER, gen9_get_blend((op), false, (format)), GEN9_WM_KERNEL_NOMASK, FILL_VERTEX)
352.8063 ++#define FILL_FLAGS_NOBLEND GEN9_SET_FLAGS(FILL_SAMPLER, NO_BLEND, GEN9_WM_KERNEL_NOMASK, FILL_VERTEX)
352.8064 ++
352.8065 ++#define GEN9_SAMPLER(f) (((f) >> 20) & 0xfff)
352.8066 ++#define GEN9_BLEND(f) (((f) >> 4) & 0x7ff)
352.8067 ++#define GEN9_READS_DST(f) (((f) >> 15) & 1)
352.8068 ++#define GEN9_KERNEL(f) (((f) >> 16) & 0xf)
352.8069 ++#define GEN9_VERTEX(f) (((f) >> 0) & 0xf)
352.8070 ++#define GEN9_SET_FLAGS(S, B, K, V)  ((S) << 20 | (K) << 16 | (B) | (V))
352.8071 ++
352.8072 ++#define OUT_BATCH(v) batch_emit(sna, v)
352.8073 ++#define OUT_BATCH64(v) batch_emit64(sna, v)
352.8074 ++#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
352.8075 ++#define OUT_VERTEX_F(v) vertex_emit(sna, v)
352.8076 ++
352.8077 ++struct gt_info {
352.8078 ++	const char *name;
352.8079 ++	struct {
352.8080 ++		int max_vs_entries;
352.8081 ++	} urb;
352.8082 ++};
352.8083 ++
352.8084 ++static const struct gt_info min_gt_info = {
352.8085 ++	.name = "Skylake (gen9)",
352.8086 ++	.urb = { .max_vs_entries = 240 },
352.8087 ++};
352.8088 ++
352.8089 ++static const struct gt_info skl_gt_info = {
352.8090 ++	.name = "Skylake (gen9)",
352.8091 ++	.urb = { .max_vs_entries = 960 },
352.8092 ++};
352.8093 ++
352.8094 ++static const struct gt_info bxt_gt_info = {
352.8095 ++	.name = "Broxton (gen9)",
352.8096 ++	.urb = { .max_vs_entries = 320 },
352.8097 ++};
352.8098 ++
352.8099 ++static const struct gt_info kbl_gt_info = {
352.8100 ++	.name = "Kabylake (gen9)",
352.8101 ++	.urb = { .max_vs_entries = 960 },
352.8102 ++};
352.8103 ++
352.8104 ++static const struct gt_info glk_gt_info = {
352.8105 ++	.name = "Geminilake (gen9)",
352.8106 ++	.urb = { .max_vs_entries = 320 },
352.8107 ++};
352.8108 ++
352.8109 ++static bool is_skl(struct sna *sna)
352.8110 ++{
352.8111 ++	return sna->kgem.gen == 0110;
352.8112 ++}
352.8113 ++
352.8114 ++static bool is_bxt(struct sna *sna)
352.8115 ++{
352.8116 ++	return sna->kgem.gen == 0111;
352.8117 ++}
352.8118 ++
352.8119 ++static bool is_kbl(struct sna *sna)
352.8120 ++{
352.8121 ++	return sna->kgem.gen == 0112;
352.8122 ++}
352.8123 ++
352.8124 ++static bool is_glk(struct sna *sna)
352.8125 ++{
352.8126 ++	return sna->kgem.gen == 0113;
352.8127 ++}
352.8128 ++
352.8129 ++
352.8130 ++static inline bool too_large(int width, int height)
352.8131 ++{
352.8132 ++	return width > GEN9_MAX_SIZE || height > GEN9_MAX_SIZE;
352.8133 ++}
352.8134 ++
352.8135 ++static inline bool unaligned(struct kgem_bo *bo, int bpp)
352.8136 ++{
352.8137 ++	/* XXX What exactly do we need to meet H_ALIGN and V_ALIGN? */
352.8138 ++#if 0
352.8139 ++	int x, y;
352.8140 ++
352.8141 ++	if (bo->proxy == NULL)
352.8142 ++		return false;
352.8143 ++
352.8144 ++	/* Assume that all tiled proxies are constructed correctly. */
352.8145 ++	if (bo->tiling)
352.8146 ++		return false;
352.8147 ++
352.8148 ++	DBG(("%s: checking alignment of a linear proxy, offset=%d, pitch=%d, bpp=%d: => (%d, %d)\n",
352.8149 ++	     __FUNCTION__, bo->delta, bo->pitch, bpp,
352.8150 ++	     8 * (bo->delta % bo->pitch) / bpp, bo->delta / bo->pitch));
352.8151 ++
352.8152 ++	/* This may be a random userptr map, check that it meets the
352.8153 ++	 * render alignment of SURFACE_VALIGN_4 | SURFACE_HALIGN_4.
352.8154 ++	 */
352.8155 ++	y = bo->delta / bo->pitch;
352.8156 ++	if (y & 3)
352.8157 ++		return true;
352.8158 ++
352.8159 ++	x = 8 * (bo->delta - y * bo->pitch);
352.8160 ++	if (x & (4*bpp - 1))
352.8161 ++	    return true;
352.8162 ++
352.8163 ++	return false;
352.8164 ++#else
352.8165 ++	return false;
352.8166 ++#endif
352.8167 ++}
352.8168 ++
352.8169 ++static uint32_t gen9_get_blend(int op,
352.8170 ++			       bool has_component_alpha,
352.8171 ++			       uint32_t dst_format)
352.8172 ++{
352.8173 ++	uint32_t src, dst;
352.8174 ++
352.8175 ++	COMPILE_TIME_ASSERT(BLENDFACTOR_INV_DST_ALPHA*GEN9_BLENDFACTOR_COUNT + BLENDFACTOR_INV_DST_ALPHA <= 0x7ff);
352.8176 ++
352.8177 ++	src = gen9_blend_op[op].src_blend;
352.8178 ++	dst = gen9_blend_op[op].dst_blend;
352.8179 ++
352.8180 ++	/* If there's no dst alpha channel, adjust the blend op so that
352.8181 ++	 * we'll treat it always as 1.
352.8182 ++	 */
352.8183 ++	if (PICT_FORMAT_A(dst_format) == 0) {
352.8184 ++		if (src == BLENDFACTOR_DST_ALPHA)
352.8185 ++			src = BLENDFACTOR_ONE;
352.8186 ++		else if (src == BLENDFACTOR_INV_DST_ALPHA)
352.8187 ++			src = BLENDFACTOR_ZERO;
352.8188 ++	}
352.8189 ++
352.8190 ++	/* If the source alpha is being used, then we should only be in a
352.8191 ++	 * case where the source blend factor is 0, and the source blend
352.8192 ++	 * value is the mask channels multiplied by the source picture's alpha.
352.8193 ++	 */
352.8194 ++	if (has_component_alpha && gen9_blend_op[op].src_alpha) {
352.8195 ++		if (dst == BLENDFACTOR_SRC_ALPHA)
352.8196 ++			dst = BLENDFACTOR_SRC_COLOR;
352.8197 ++		else if (dst == BLENDFACTOR_INV_SRC_ALPHA)
352.8198 ++			dst = BLENDFACTOR_INV_SRC_COLOR;
352.8199 ++	}
352.8200 ++
352.8201 ++	DBG(("blend op=%d, dst=%x [A=%d] => src=%d, dst=%d => offset=%x\n",
352.8202 ++	     op, dst_format, PICT_FORMAT_A(dst_format),
352.8203 ++	     src, dst, (int)(BLEND_OFFSET(src, dst)>>4)));
352.8204 ++	assert(BLEND_OFFSET(src, dst) >> 4 <= 0xfff);
352.8205 ++	return BLEND_OFFSET(src, dst);
352.8206 ++}
352.8207 ++
352.8208 ++static uint32_t gen9_get_card_format(PictFormat format)
352.8209 ++{
352.8210 ++	switch (format) {
352.8211 ++	default:
352.8212 ++		return -1;
352.8213 ++	case PICT_a8r8g8b8:
352.8214 ++		return SURFACEFORMAT_B8G8R8A8_UNORM;
352.8215 ++	case PICT_x8r8g8b8:
352.8216 ++		return SURFACEFORMAT_B8G8R8X8_UNORM;
352.8217 ++	case PICT_a8b8g8r8:
352.8218 ++		return SURFACEFORMAT_R8G8B8A8_UNORM;
352.8219 ++	case PICT_x8b8g8r8:
352.8220 ++		return SURFACEFORMAT_R8G8B8X8_UNORM;
352.8221 ++#ifdef PICT_a2r10g10b10
352.8222 ++	case PICT_a2r10g10b10:
352.8223 ++		return SURFACEFORMAT_B10G10R10A2_UNORM;
352.8224 ++	case PICT_x2r10g10b10:
352.8225 ++		return SURFACEFORMAT_B10G10R10X2_UNORM;
352.8226 ++#endif
352.8227 ++	case PICT_r8g8b8:
352.8228 ++		return SURFACEFORMAT_R8G8B8_UNORM;
352.8229 ++	case PICT_r5g6b5:
352.8230 ++		return SURFACEFORMAT_B5G6R5_UNORM;
352.8231 ++	case PICT_a1r5g5b5:
352.8232 ++		return SURFACEFORMAT_B5G5R5A1_UNORM;
352.8233 ++	case PICT_a8:
352.8234 ++		return SURFACEFORMAT_A8_UNORM;
352.8235 ++	case PICT_a4r4g4b4:
352.8236 ++		return SURFACEFORMAT_B4G4R4A4_UNORM;
352.8237 ++	}
352.8238 ++}
352.8239 ++
352.8240 ++static uint32_t gen9_get_dest_format(PictFormat format)
352.8241 ++{
352.8242 ++	switch (format) {
352.8243 ++	default:
352.8244 ++		return -1;
352.8245 ++	case PICT_a8r8g8b8:
352.8246 ++	case PICT_x8r8g8b8:
352.8247 ++		return SURFACEFORMAT_B8G8R8A8_UNORM;
352.8248 ++	case PICT_a8b8g8r8:
352.8249 ++	case PICT_x8b8g8r8:
352.8250 ++		return SURFACEFORMAT_R8G8B8A8_UNORM;
352.8251 ++#ifdef PICT_a2r10g10b10
352.8252 ++	case PICT_a2r10g10b10:
352.8253 ++	case PICT_x2r10g10b10:
352.8254 ++		return SURFACEFORMAT_B10G10R10A2_UNORM;
352.8255 ++#endif
352.8256 ++	case PICT_r5g6b5:
352.8257 ++		return SURFACEFORMAT_B5G6R5_UNORM;
352.8258 ++	case PICT_x1r5g5b5:
352.8259 ++	case PICT_a1r5g5b5:
352.8260 ++		return SURFACEFORMAT_B5G5R5A1_UNORM;
352.8261 ++	case PICT_a8:
352.8262 ++		return SURFACEFORMAT_A8_UNORM;
352.8263 ++	case PICT_a4r4g4b4:
352.8264 ++	case PICT_x4r4g4b4:
352.8265 ++		return SURFACEFORMAT_B4G4R4A4_UNORM;
352.8266 ++	}
352.8267 ++}
352.8268 ++
352.8269 ++static bool gen9_check_dst_format(PictFormat format)
352.8270 ++{
352.8271 ++	if (gen9_get_dest_format(format) != -1)
352.8272 ++		return true;
352.8273 ++
352.8274 ++	DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format));
352.8275 ++	return false;
352.8276 ++}
352.8277 ++
352.8278 ++static bool gen9_check_format(uint32_t format)
352.8279 ++{
352.8280 ++	if (gen9_get_card_format(format) != -1)
352.8281 ++		return true;
352.8282 ++
352.8283 ++	DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format));
352.8284 ++	return false;
352.8285 ++}
352.8286 ++
352.8287 ++static uint32_t gen9_filter(uint32_t filter)
352.8288 ++{
352.8289 ++	switch (filter) {
352.8290 ++	default:
352.8291 ++		assert(0);
352.8292 ++	case PictFilterNearest:
352.8293 ++		return SAMPLER_FILTER_NEAREST;
352.8294 ++	case PictFilterBilinear:
352.8295 ++		return SAMPLER_FILTER_BILINEAR;
352.8296 ++	}
352.8297 ++}
352.8298 ++
352.8299 ++static uint32_t gen9_check_filter(PicturePtr picture)
352.8300 ++{
352.8301 ++	switch (picture->filter) {
352.8302 ++	case PictFilterNearest:
352.8303 ++	case PictFilterBilinear:
352.8304 ++		return true;
352.8305 ++	default:
352.8306 ++		return false;
352.8307 ++	}
352.8308 ++}
352.8309 ++
352.8310 ++static uint32_t gen9_repeat(uint32_t repeat)
352.8311 ++{
352.8312 ++	switch (repeat) {
352.8313 ++	default:
352.8314 ++		assert(0);
352.8315 ++	case RepeatNone:
352.8316 ++		return SAMPLER_EXTEND_NONE;
352.8317 ++	case RepeatNormal:
352.8318 ++		return SAMPLER_EXTEND_REPEAT;
352.8319 ++	case RepeatPad:
352.8320 ++		return SAMPLER_EXTEND_PAD;
352.8321 ++	case RepeatReflect:
352.8322 ++		return SAMPLER_EXTEND_REFLECT;
352.8323 ++	}
352.8324 ++}
352.8325 ++
352.8326 ++static bool gen9_check_repeat(PicturePtr picture)
352.8327 ++{
352.8328 ++	if (!picture->repeat)
352.8329 ++		return true;
352.8330 ++
352.8331 ++	switch (picture->repeatType) {
352.8332 ++	case RepeatNone:
352.8333 ++	case RepeatNormal:
352.8334 ++	case RepeatPad:
352.8335 ++	case RepeatReflect:
352.8336 ++		return true;
352.8337 ++	default:
352.8338 ++		return false;
352.8339 ++	}
352.8340 ++}
352.8341 ++
352.8342 ++static int
352.8343 ++gen9_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine)
352.8344 ++{
352.8345 ++	int base;
352.8346 ++
352.8347 ++	if (has_mask) {
352.8348 ++		if (is_ca) {
352.8349 ++			if (gen9_blend_op[op].src_alpha)
352.8350 ++				base = GEN9_WM_KERNEL_MASKSA;
352.8351 ++			else
352.8352 ++				base = GEN9_WM_KERNEL_MASKCA;
352.8353 ++		} else
352.8354 ++			base = GEN9_WM_KERNEL_MASK;
352.8355 ++	} else
352.8356 ++		base = GEN9_WM_KERNEL_NOMASK;
352.8357 ++
352.8358 ++	return base + !is_affine;
352.8359 ++}
352.8360 ++
352.8361 ++static void
352.8362 ++gen9_emit_push_constants(struct sna *sna)
352.8363 ++{
352.8364 ++#if SIM
352.8365 ++	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_VS | (2 - 2));
352.8366 ++	OUT_BATCH(0);
352.8367 ++
352.8368 ++	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_HS | (2 - 2));
352.8369 ++	OUT_BATCH(0);
352.8370 ++
352.8371 ++	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_DS | (2 - 2));
352.8372 ++	OUT_BATCH(0);
352.8373 ++
352.8374 ++	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_GS | (2 - 2));
352.8375 ++	OUT_BATCH(0);
352.8376 ++
352.8377 ++	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_PS | (2 - 2));
352.8378 ++	OUT_BATCH(0);
352.8379 ++#endif
352.8380 ++}
352.8381 ++
352.8382 ++static void
352.8383 ++gen9_emit_urb(struct sna *sna)
352.8384 ++{
352.8385 ++	/* num of VS entries must be divisible by 8 if size < 9 */
352.8386 ++	OUT_BATCH(GEN9_3DSTATE_URB_VS | (2 - 2));
352.8387 ++	OUT_BATCH(sna->render_state.gen9.info->urb.max_vs_entries << URB_ENTRY_NUMBER_SHIFT |
352.8388 ++		  (2 - 1) << URB_ENTRY_SIZE_SHIFT |
352.8389 ++		  4 << URB_STARTING_ADDRESS_SHIFT);
352.8390 ++
352.8391 ++	OUT_BATCH(GEN9_3DSTATE_URB_HS | (2 - 2));
352.8392 ++	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
352.8393 ++		  4 << URB_STARTING_ADDRESS_SHIFT);
352.8394 ++
352.8395 ++	OUT_BATCH(GEN9_3DSTATE_URB_DS | (2 - 2));
352.8396 ++	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
352.8397 ++		  4 << URB_STARTING_ADDRESS_SHIFT);
352.8398 ++
352.8399 ++	OUT_BATCH(GEN9_3DSTATE_URB_GS | (2 - 2));
352.8400 ++	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
352.8401 ++		  4 << URB_STARTING_ADDRESS_SHIFT);
352.8402 ++}
352.8403 ++
352.8404 ++static void
352.8405 ++gen9_emit_state_base_address(struct sna *sna)
352.8406 ++{
352.8407 ++	uint32_t num_pages;
352.8408 ++
352.8409 ++	assert(sna->kgem.surface - sna->kgem.nbatch <= 16384);
352.8410 ++
352.8411 ++	/* WaBindlessSurfaceStateModifyEnable:skl,bxt */
352.8412 ++	OUT_BATCH(GEN9_STATE_BASE_ADDRESS | (19 - 1 - 2));
352.8413 ++	OUT_BATCH64(0); /* general */
352.8414 ++	OUT_BATCH(0); /* stateless dataport */
352.8415 ++	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* surface */
352.8416 ++				     sna->kgem.nbatch,
352.8417 ++				     NULL,
352.8418 ++				     I915_GEM_DOMAIN_INSTRUCTION << 16,
352.8419 ++				     BASE_ADDRESS_MODIFY));
352.8420 ++	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* dynamic */
352.8421 ++				     sna->kgem.nbatch,
352.8422 ++				     sna->render_state.gen9.general_bo,
352.8423 ++				     I915_GEM_DOMAIN_INSTRUCTION << 16,
352.8424 ++				     BASE_ADDRESS_MODIFY));
352.8425 ++	OUT_BATCH64(0); /* indirect */
352.8426 ++	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* instruction */
352.8427 ++				     sna->kgem.nbatch,
352.8428 ++				     sna->render_state.gen9.general_bo,
352.8429 ++				     I915_GEM_DOMAIN_INSTRUCTION << 16,
352.8430 ++				     BASE_ADDRESS_MODIFY));
352.8431 ++	/* upper bounds */
352.8432 ++	num_pages = sna->render_state.gen9.general_bo->size.pages.count;
352.8433 ++	OUT_BATCH(0); /* general */
352.8434 ++	OUT_BATCH(num_pages << 12 | 1); /* dynamic */
352.8435 ++	OUT_BATCH(0); /* indirect */
352.8436 ++	OUT_BATCH(num_pages << 12 | 1); /* instruction */
352.8437 ++
352.8438 ++	/* Bindless */
352.8439 ++	OUT_BATCH(0);
352.8440 ++	OUT_BATCH(0);
352.8441 ++	OUT_BATCH(0);
352.8442 ++}
352.8443 ++
352.8444 ++static void
352.8445 ++gen9_emit_vs_invariant(struct sna *sna)
352.8446 ++{
352.8447 ++	OUT_BATCH(GEN9_3DSTATE_VS | (9 - 2));
352.8448 ++	OUT_BATCH64(0); /* no VS kernel */
352.8449 ++	OUT_BATCH(0);
352.8450 ++	OUT_BATCH64(0); /* scratch */
352.8451 ++	OUT_BATCH(0);
352.8452 ++	OUT_BATCH(1 << 1); /* pass-through */
352.8453 ++	OUT_BATCH(1 << 16 | 1 << 21); /* urb write to SBE */
352.8454 ++
352.8455 ++#if SIM
352.8456 ++	OUT_BATCH(GEN9_3DSTATE_CONSTANT_VS | (11 - 2));
352.8457 ++	OUT_BATCH(0);
352.8458 ++	OUT_BATCH(0);
352.8459 ++	OUT_BATCH64(0);
352.8460 ++	OUT_BATCH64(0);
352.8461 ++	OUT_BATCH64(0);
352.8462 ++	OUT_BATCH64(0);
352.8463 ++
352.8464 ++	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_VS | (2 - 2));
352.8465 ++	OUT_BATCH(0);
352.8466 ++
352.8467 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_VS | (2 - 2));
352.8468 ++	OUT_BATCH(0);
352.8469 ++#endif
352.8470 ++}
352.8471 ++
352.8472 ++static void
352.8473 ++gen9_emit_hs_invariant(struct sna *sna)
352.8474 ++{
352.8475 ++	OUT_BATCH(GEN9_3DSTATE_HS | (9 - 2));
352.8476 ++	OUT_BATCH(0);
352.8477 ++	OUT_BATCH(0);
352.8478 ++	OUT_BATCH64(0); /* no HS kernel */
352.8479 ++	OUT_BATCH64(0); /* scratch */
352.8480 ++	OUT_BATCH(0);
352.8481 ++	OUT_BATCH(0); /* pass-through */
352.8482 ++
352.8483 ++#if SIM
352.8484 ++	OUT_BATCH(GEN9_3DSTATE_CONSTANT_HS | (11 - 2));
352.8485 ++	OUT_BATCH(0);
352.8486 ++	OUT_BATCH(0);
352.8487 ++	OUT_BATCH64(0);
352.8488 ++	OUT_BATCH64(0);
352.8489 ++	OUT_BATCH64(0);
352.8490 ++	OUT_BATCH64(0);
352.8491 ++
352.8492 ++#if 1
352.8493 ++	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_HS | (2 - 2));
352.8494 ++	OUT_BATCH(0);
352.8495 ++
352.8496 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_HS | (2 - 2));
352.8497 ++	OUT_BATCH(0);
352.8498 ++#endif
352.8499 ++#endif
352.8500 ++}
352.8501 ++
352.8502 ++static void
352.8503 ++gen9_emit_te_invariant(struct sna *sna)
352.8504 ++{
352.8505 ++	OUT_BATCH(GEN9_3DSTATE_TE | (4 - 2));
352.8506 ++	OUT_BATCH(0);
352.8507 ++	OUT_BATCH(0);
352.8508 ++	OUT_BATCH(0);
352.8509 ++}
352.8510 ++
352.8511 ++static void
352.8512 ++gen9_emit_ds_invariant(struct sna *sna)
352.8513 ++{
352.8514 ++	OUT_BATCH(GEN9_3DSTATE_DS | (11 - 2));
352.8515 ++	OUT_BATCH64(0); /* no kernel */
352.8516 ++	OUT_BATCH(0);
352.8517 ++	OUT_BATCH64(0); /* scratch */
352.8518 ++	OUT_BATCH(0);
352.8519 ++	OUT_BATCH(0);
352.8520 ++	OUT_BATCH(0);
352.8521 ++	OUT_BATCH(0);
352.8522 ++	OUT_BATCH(0);
352.8523 ++
352.8524 ++#if SIM
352.8525 ++	OUT_BATCH(GEN9_3DSTATE_CONSTANT_DS | (11 - 2));
352.8526 ++	OUT_BATCH(0);
352.8527 ++	OUT_BATCH(0);
352.8528 ++	OUT_BATCH64(0);
352.8529 ++	OUT_BATCH64(0);
352.8530 ++	OUT_BATCH64(0);
352.8531 ++	OUT_BATCH64(0);
352.8532 ++
352.8533 ++#if 1
352.8534 ++	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_DS | (2 - 2));
352.8535 ++	OUT_BATCH(0);
352.8536 ++
352.8537 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_DS | (2 - 2));
352.8538 ++	OUT_BATCH(0);
352.8539 ++#endif
352.8540 ++#endif
352.8541 ++}
352.8542 ++
352.8543 ++static void
352.8544 ++gen9_emit_gs_invariant(struct sna *sna)
352.8545 ++{
352.8546 ++	OUT_BATCH(GEN9_3DSTATE_GS | (10 - 2));
352.8547 ++	OUT_BATCH64(0); /* no GS kernel */
352.8548 ++	OUT_BATCH(0);
352.8549 ++	OUT_BATCH64(0); /* scratch */
352.8550 ++	OUT_BATCH(0);
352.8551 ++	OUT_BATCH(0); /* pass-through */
352.8552 ++	OUT_BATCH(0);
352.8553 ++	OUT_BATCH(0);
352.8554 ++
352.8555 ++#if SIM
352.8556 ++	OUT_BATCH(GEN9_3DSTATE_CONSTANT_GS | (11 - 2));
352.8557 ++	OUT_BATCH(0);
352.8558 ++	OUT_BATCH(0);
352.8559 ++	OUT_BATCH64(0);
352.8560 ++	OUT_BATCH64(0);
352.8561 ++	OUT_BATCH64(0);
352.8562 ++	OUT_BATCH64(0);
352.8563 ++
352.8564 ++#if 1
352.8565 ++	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_GS | (2 - 2));
352.8566 ++	OUT_BATCH(0);
352.8567 ++
352.8568 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_GS | (2 - 2));
352.8569 ++	OUT_BATCH(0);
352.8570 ++#endif
352.8571 ++#endif
352.8572 ++}
352.8573 ++
352.8574 ++static void
352.8575 ++gen9_emit_sol_invariant(struct sna *sna)
352.8576 ++{
352.8577 ++	OUT_BATCH(GEN9_3DSTATE_STREAMOUT | (5 - 2));
352.8578 ++	OUT_BATCH(0);
352.8579 ++	OUT_BATCH(0);
352.8580 ++	OUT_BATCH(0);
352.8581 ++	OUT_BATCH(0);
352.8582 ++}
352.8583 ++
352.8584 ++static void
352.8585 ++gen9_emit_sf_invariant(struct sna *sna)
352.8586 ++{
352.8587 ++	OUT_BATCH(GEN9_3DSTATE_SF | (4 - 2));
352.8588 ++	OUT_BATCH(0);
352.8589 ++	OUT_BATCH(0);
352.8590 ++	OUT_BATCH(0);
352.8591 ++}
352.8592 ++
352.8593 ++static void
352.8594 ++gen9_emit_clip_invariant(struct sna *sna)
352.8595 ++{
352.8596 ++	OUT_BATCH(GEN9_3DSTATE_CLIP | (4 - 2));
352.8597 ++	OUT_BATCH(0);
352.8598 ++	OUT_BATCH(0); /* pass-through */
352.8599 ++	OUT_BATCH(0);
352.8600 ++
352.8601 ++	OUT_BATCH(GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP | (2 - 2));
352.8602 ++	OUT_BATCH(0);
352.8603 ++
352.8604 ++	OUT_BATCH(GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_CC | (2 - 2));
352.8605 ++	OUT_BATCH(0);
352.8606 ++}
352.8607 ++
352.8608 ++static void
352.8609 ++gen9_emit_null_depth_buffer(struct sna *sna)
352.8610 ++{
352.8611 ++	OUT_BATCH(GEN9_3DSTATE_DEPTH_BUFFER | (8 - 2));
352.8612 ++#if 1
352.8613 ++	OUT_BATCH(SURFACE_NULL << DEPTH_BUFFER_TYPE_SHIFT |
352.8614 ++		  DEPTHFORMAT_D32_FLOAT << DEPTH_BUFFER_FORMAT_SHIFT);
352.8615 ++#else
352.8616 ++	OUT_BATCH(SURFACE_2D << DEPTH_BUFFER_TYPE_SHIFT |
352.8617 ++		  DEPTHFORMAT_D16_UNORM << DEPTH_BUFFER_FORMAT_SHIFT);
352.8618 ++#endif
352.8619 ++	OUT_BATCH64(0);
352.8620 ++	OUT_BATCH(0);
352.8621 ++	OUT_BATCH(0);
352.8622 ++	OUT_BATCH(0);
352.8623 ++	OUT_BATCH(0);
352.8624 ++
352.8625 ++#if SIM
352.8626 ++	OUT_BATCH(GEN9_3DSTATE_HIER_DEPTH_BUFFER | (5 - 2));
352.8627 ++	OUT_BATCH(0);
352.8628 ++	OUT_BATCH64(0);
352.8629 ++	OUT_BATCH(0);
352.8630 ++#endif
352.8631 ++
352.8632 ++#if SIM
352.8633 ++	OUT_BATCH(GEN9_3DSTATE_STENCIL_BUFFER | (5 - 2));
352.8634 ++	OUT_BATCH(0);
352.8635 ++	OUT_BATCH64(0);
352.8636 ++	OUT_BATCH(0);
352.8637 ++#endif
352.8638 ++
352.8639 ++#if SIM
352.8640 ++	OUT_BATCH(GEN9_3DSTATE_WM_DEPTH_STENCIL | (4 - 2));
352.8641 ++	OUT_BATCH(0);
352.8642 ++	OUT_BATCH(0);
352.8643 ++	OUT_BATCH(0);
352.8644 ++#endif
352.8645 ++
352.8646 ++#if SIM
352.8647 ++	OUT_BATCH(GEN9_3DSTATE_CLEAR_PARAMS | (3 - 2));
352.8648 ++	OUT_BATCH(0);
352.8649 ++	OUT_BATCH(0);
352.8650 ++#endif
352.8651 ++}
352.8652 ++
352.8653 ++static void
352.8654 ++gen9_emit_wm_invariant(struct sna *sna)
352.8655 ++{
352.8656 ++	gen9_emit_null_depth_buffer(sna);
352.8657 ++
352.8658 ++#if SIM
352.8659 ++	OUT_BATCH(GEN9_3DSTATE_SCISSOR_STATE_POINTERS | (2 - 2));
352.8660 ++	OUT_BATCH(0);
352.8661 ++#endif
352.8662 ++
352.8663 ++	OUT_BATCH(GEN9_3DSTATE_WM | (2 - 2));
352.8664 ++	//OUT_BATCH(WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC); /* XXX */
352.8665 ++	OUT_BATCH(WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
352.8666 ++
352.8667 ++#if SIM
352.8668 ++	OUT_BATCH(GEN9_3DSTATE_WM_CHROMAKEY | (2 - 2));
352.8669 ++	OUT_BATCH(0);
352.8670 ++#endif
352.8671 ++
352.8672 ++#if 0
352.8673 ++	OUT_BATCH(GEN9_3DSTATE_WM_HZ_OP | (5 - 2));
352.8674 ++	OUT_BATCH(0);
352.8675 ++	OUT_BATCH(0);
352.8676 ++	OUT_BATCH(0);
352.8677 ++	OUT_BATCH(0);
352.8678 ++#endif
352.8679 ++
352.8680 ++	OUT_BATCH(GEN9_3DSTATE_PS_EXTRA | (2 - 2));
352.8681 ++	OUT_BATCH(PSX_PIXEL_SHADER_VALID |
352.8682 ++		  PSX_ATTRIBUTE_ENABLE);
352.8683 ++
352.8684 ++	OUT_BATCH(GEN9_3DSTATE_RASTER | (5 - 2));
352.8685 ++	OUT_BATCH(RASTER_FRONT_WINDING_CCW |
352.8686 ++		  RASTER_CULL_NONE);
352.8687 ++	OUT_BATCH(0);
352.8688 ++	OUT_BATCH(0);
352.8689 ++	OUT_BATCH(0);
352.8690 ++
352.8691 ++	OUT_BATCH(GEN9_3DSTATE_SBE_SWIZ | (11 - 2));
352.8692 ++	OUT_BATCH(0);
352.8693 ++	OUT_BATCH(0);
352.8694 ++	OUT_BATCH(0);
352.8695 ++	OUT_BATCH(0);
352.8696 ++	OUT_BATCH(0);
352.8697 ++	OUT_BATCH(0);
352.8698 ++	OUT_BATCH(0);
352.8699 ++	OUT_BATCH(0);
352.8700 ++	OUT_BATCH(0);
352.8701 ++	OUT_BATCH(0);
352.8702 ++
352.8703 ++#if SIM
352.8704 ++	OUT_BATCH(GEN9_3DSTATE_CONSTANT_PS | (11 - 2));
352.8705 ++	OUT_BATCH(0);
352.8706 ++	OUT_BATCH(0);
352.8707 ++	OUT_BATCH64(0);
352.8708 ++	OUT_BATCH64(0);
352.8709 ++	OUT_BATCH64(0);
352.8710 ++	OUT_BATCH64(0);
352.8711 ++#endif
352.8712 ++}
352.8713 ++
352.8714 ++static void
352.8715 ++gen9_emit_cc_invariant(struct sna *sna)
352.8716 ++{
352.8717 ++}
352.8718 ++
352.8719 ++static void
352.8720 ++gen9_emit_vf_invariant(struct sna *sna)
352.8721 ++{
352.8722 ++	int n;
352.8723 ++
352.8724 ++#if 1
352.8725 ++	OUT_BATCH(GEN9_3DSTATE_VF | (2 - 2));
352.8726 ++	OUT_BATCH(0);
352.8727 ++#endif
352.8728 ++
352.8729 ++	OUT_BATCH(GEN9_3DSTATE_VF_SGVS | (2 - 2));
352.8730 ++	OUT_BATCH(0);
352.8731 ++
352.8732 ++	OUT_BATCH(GEN9_3DSTATE_VF_TOPOLOGY | (2 - 2));
352.8733 ++	OUT_BATCH(RECTLIST);
352.8734 ++
352.8735 ++	OUT_BATCH(GEN9_3DSTATE_VF_STATISTICS | 0);
352.8736 ++
352.8737 ++	for (n = 1; n <= 3; n++) {
352.8738 ++		OUT_BATCH(GEN9_3DSTATE_VF_INSTANCING | (3 - 2));
352.8739 ++		OUT_BATCH(n);
352.8740 ++		OUT_BATCH(0);
352.8741 ++	}
352.8742 ++}
352.8743 ++
352.8744 ++static void
352.8745 ++gen9_emit_invariant(struct sna *sna)
352.8746 ++{
352.8747 ++	OUT_BATCH(GEN9_PIPELINE_SELECT |
352.8748 ++		  PIPELINE_SELECTION_MASK |
352.8749 ++		  PIPELINE_SELECT_3D);
352.8750 ++
352.8751 ++#if SIM
352.8752 ++	OUT_BATCH(GEN9_STATE_SIP | (3 - 2));
352.8753 ++	OUT_BATCH64(0);
352.8754 ++#endif
352.8755 ++
352.8756 ++	OUT_BATCH(GEN9_3DSTATE_MULTISAMPLE | (2 - 2));
352.8757 ++	OUT_BATCH(MULTISAMPLE_PIXEL_LOCATION_CENTER |
352.8758 ++		  MULTISAMPLE_NUMSAMPLES_1); /* 1 sample/pixel */
352.8759 ++
352.8760 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLE_MASK | (2 - 2));
352.8761 ++	OUT_BATCH(1);
352.8762 ++
352.8763 ++#if SIM
352.8764 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLE_PATTERN | (5 - 2));
352.8765 ++	OUT_BATCH(0);
352.8766 ++	OUT_BATCH(0);
352.8767 ++	OUT_BATCH(0);
352.8768 ++	//OUT_BATCH(8<<20 | 8<<16);
352.8769 ++	OUT_BATCH(0);
352.8770 ++#endif
352.8771 ++
352.8772 ++	gen9_emit_push_constants(sna);
352.8773 ++	gen9_emit_urb(sna);
352.8774 ++
352.8775 ++	gen9_emit_state_base_address(sna);
352.8776 ++
352.8777 ++	gen9_emit_vf_invariant(sna);
352.8778 ++	gen9_emit_vs_invariant(sna);
352.8779 ++	gen9_emit_hs_invariant(sna);
352.8780 ++	gen9_emit_te_invariant(sna);
352.8781 ++	gen9_emit_ds_invariant(sna);
352.8782 ++	gen9_emit_gs_invariant(sna);
352.8783 ++	gen9_emit_sol_invariant(sna);
352.8784 ++	gen9_emit_clip_invariant(sna);
352.8785 ++	gen9_emit_sf_invariant(sna);
352.8786 ++	gen9_emit_wm_invariant(sna);
352.8787 ++	gen9_emit_cc_invariant(sna);
352.8788 ++
352.8789 ++	sna->render_state.gen9.needs_invariant = false;
352.8790 ++}
352.8791 ++
352.8792 ++static void
352.8793 ++gen9_emit_cc(struct sna *sna, uint32_t blend)
352.8794 ++{
352.8795 ++	struct gen9_render_state *render = &sna->render_state.gen9;
352.8796 ++
352.8797 ++	if (render->blend == blend)
352.8798 ++		return;
352.8799 ++
352.8800 ++	DBG(("%s: blend=%x (current=%x), src=%d, dst=%d\n",
352.8801 ++	     __FUNCTION__, blend, render->blend,
352.8802 ++	     blend / GEN9_BLENDFACTOR_COUNT,
352.8803 ++	     blend % GEN9_BLENDFACTOR_COUNT));
352.8804 ++
352.8805 ++	assert(blend < GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT);
352.8806 ++	assert(blend / GEN9_BLENDFACTOR_COUNT > 0);
352.8807 ++	assert(blend % GEN9_BLENDFACTOR_COUNT > 0);
352.8808 ++
352.8809 ++	/* XXX can have up to 8 blend states preload, selectable via
352.8810 ++	 * Render Target Index. What other side-effects of Render Target Index?
352.8811 ++	 */
352.8812 ++
352.8813 ++	OUT_BATCH(GEN9_3DSTATE_PS_BLEND | (2 - 2));
352.8814 ++	if (blend != GEN9_BLEND(NO_BLEND)) {
352.8815 ++		uint32_t src = blend / GEN9_BLENDFACTOR_COUNT;
352.8816 ++		uint32_t dst = blend % GEN9_BLENDFACTOR_COUNT;
352.8817 ++		OUT_BATCH(PS_BLEND_HAS_WRITEABLE_RT |
352.8818 ++			  PS_BLEND_COLOR_BLEND_ENABLE |
352.8819 ++			  src << PS_BLEND_SRC_ALPHA_SHIFT |
352.8820 ++			  dst << PS_BLEND_DST_ALPHA_SHIFT |
352.8821 ++			  src << PS_BLEND_SRC_SHIFT |
352.8822 ++			  dst << PS_BLEND_DST_SHIFT);
352.8823 ++	} else
352.8824 ++		OUT_BATCH(PS_BLEND_HAS_WRITEABLE_RT);
352.8825 ++
352.8826 ++	assert(is_aligned(render->cc_blend + blend * GEN9_BLEND_STATE_PADDED_SIZE, 64));
352.8827 ++	OUT_BATCH(GEN9_3DSTATE_BLEND_STATE_POINTERS | (2 - 2));
352.8828 ++	OUT_BATCH((render->cc_blend + blend * GEN9_BLEND_STATE_PADDED_SIZE) | 1);
352.8829 ++
352.8830 ++	/* Force a CC_STATE pointer change to improve blend performance */
352.8831 ++	OUT_BATCH(GEN9_3DSTATE_CC_STATE_POINTERS | (2 - 2));
352.8832 ++	OUT_BATCH(0);
352.8833 ++
352.8834 ++	render->blend = blend;
352.8835 ++}
352.8836 ++
352.8837 ++static void
352.8838 ++gen9_emit_sampler(struct sna *sna, uint32_t state)
352.8839 ++{
352.8840 ++	if (sna->render_state.gen9.samplers == state)
352.8841 ++		return;
352.8842 ++
352.8843 ++	sna->render_state.gen9.samplers = state;
352.8844 ++
352.8845 ++	DBG(("%s: sampler = %x\n", __FUNCTION__, state));
352.8846 ++
352.8847 ++	assert(2 * sizeof(struct gen9_sampler_state) == 32);
352.8848 ++	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_PS | (2 - 2));
352.8849 ++	OUT_BATCH(sna->render_state.gen9.wm_state + state * 2 * sizeof(struct gen9_sampler_state));
352.8850 ++}
352.8851 ++
352.8852 ++static void
352.8853 ++gen9_emit_sf(struct sna *sna, bool has_mask)
352.8854 ++{
352.8855 ++	int num_sf_outputs = has_mask ? 2 : 1;
352.8856 ++
352.8857 ++	if (sna->render_state.gen9.num_sf_outputs == num_sf_outputs)
352.8858 ++		return;
352.8859 ++
352.8860 ++	DBG(("%s: num_sf_outputs=%d\n", __FUNCTION__, num_sf_outputs));
352.8861 ++
352.8862 ++	sna->render_state.gen9.num_sf_outputs = num_sf_outputs;
352.8863 ++
352.8864 ++	OUT_BATCH(GEN9_3DSTATE_SBE | (6 - 2));
352.8865 ++	OUT_BATCH(num_sf_outputs << SBE_NUM_OUTPUTS_SHIFT |
352.8866 ++		  SBE_FORCE_VERTEX_URB_READ_LENGTH | /* forced is faster */
352.8867 ++		  SBE_FORCE_VERTEX_URB_READ_OFFSET |
352.8868 ++		  1 << SBE_URB_ENTRY_READ_LENGTH_SHIFT |
352.8869 ++		  1 << SBE_URB_ENTRY_READ_OFFSET_SHIFT);
352.8870 ++	OUT_BATCH(0);
352.8871 ++	OUT_BATCH(0);
352.8872 ++        OUT_BATCH(SBE_ACTIVE_COMPONENT_XYZW << 0 |
352.8873 ++		  SBE_ACTIVE_COMPONENT_XYZW << 1);
352.8874 ++        OUT_BATCH(0);
352.8875 ++}
352.8876 ++
352.8877 ++static void
352.8878 ++gen9_emit_wm(struct sna *sna, int kernel)
352.8879 ++{
352.8880 ++	const uint32_t *kernels;
352.8881 ++
352.8882 ++	assert(kernel < ARRAY_SIZE(wm_kernels));
352.8883 ++	if (sna->render_state.gen9.kernel == kernel)
352.8884 ++		return;
352.8885 ++
352.8886 ++	sna->render_state.gen9.kernel = kernel;
352.8887 ++	kernels = sna->render_state.gen9.wm_kernel[kernel];
352.8888 ++
352.8889 ++	DBG(("%s: switching to %s, num_surfaces=%d (8-wide? %d, 16-wide? %d, 32-wide? %d)\n",
352.8890 ++	     __FUNCTION__,
352.8891 ++	     wm_kernels[kernel].name,
352.8892 ++	     wm_kernels[kernel].num_surfaces,
352.8893 ++	     kernels[0], kernels[1], kernels[2]));
352.8894 ++	assert(is_aligned(kernels[0], 64));
352.8895 ++	assert(is_aligned(kernels[1], 64));
352.8896 ++	assert(is_aligned(kernels[2], 64));
352.8897 ++
352.8898 ++	OUT_BATCH(GEN9_3DSTATE_PS | (12 - 2));
352.8899 ++	OUT_BATCH64(kernels[0] ?: kernels[1] ?: kernels[2]);
352.8900 ++	OUT_BATCH(1 << PS_SAMPLER_COUNT_SHIFT |
352.8901 ++		  PS_VECTOR_MASK_ENABLE |
352.8902 ++		  wm_kernels[kernel].num_surfaces << PS_BINDING_TABLE_ENTRY_COUNT_SHIFT);
352.8903 ++	OUT_BATCH64(0); /* scratch address */
352.8904 ++	OUT_BATCH(PS_MAX_THREADS |
352.8905 ++		  (kernels[0] ? PS_8_DISPATCH_ENABLE : 0) |
352.8906 ++		  (kernels[1] ? PS_16_DISPATCH_ENABLE : 0) |
352.8907 ++		  (kernels[2] ? PS_32_DISPATCH_ENABLE : 0));
352.8908 ++	OUT_BATCH((kernels[0] ? 4 : kernels[1] ? 6 : 8) << PS_DISPATCH_START_GRF_SHIFT_0 |
352.8909 ++		  8 << PS_DISPATCH_START_GRF_SHIFT_1 |
352.8910 ++		  6 << PS_DISPATCH_START_GRF_SHIFT_2);
352.8911 ++	OUT_BATCH64(kernels[2]);
352.8912 ++	OUT_BATCH64(kernels[1]);
352.8913 ++}
352.8914 ++
352.8915 ++static bool
352.8916 ++gen9_emit_binding_table(struct sna *sna, uint16_t offset)
352.8917 ++{
352.8918 ++	if (sna->render_state.gen9.surface_table == offset)
352.8919 ++		return false;
352.8920 ++
352.8921 ++	/* Binding table pointers */
352.8922 ++	assert(is_aligned(4*offset, 32));
352.8923 ++	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_PS | (2 - 2));
352.8924 ++	OUT_BATCH(offset*4);
352.8925 ++
352.8926 ++	sna->render_state.gen9.surface_table = offset;
352.8927 ++	return true;
352.8928 ++}
352.8929 ++
352.8930 ++static bool
352.8931 ++gen9_emit_drawing_rectangle(struct sna *sna,
352.8932 ++			    const struct sna_composite_op *op)
352.8933 ++{
352.8934 ++	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
352.8935 ++	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
352.8936 ++
352.8937 ++	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
352.8938 ++	assert(!too_large(op->dst.width, op->dst.height));
352.8939 ++
352.8940 ++	if (sna->render_state.gen9.drawrect_limit == limit &&
352.8941 ++	    sna->render_state.gen9.drawrect_offset == offset)
352.8942 ++		return true;
352.8943 ++
352.8944 ++	sna->render_state.gen9.drawrect_offset = offset;
352.8945 ++	sna->render_state.gen9.drawrect_limit = limit;
352.8946 ++
352.8947 ++	OUT_BATCH(GEN9_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
352.8948 ++	OUT_BATCH(0);
352.8949 ++	OUT_BATCH(limit);
352.8950 ++	OUT_BATCH(offset);
352.8951 ++	return false;
352.8952 ++}
352.8953 ++
352.8954 ++static void
352.8955 ++gen9_emit_vertex_elements(struct sna *sna,
352.8956 ++			  const struct sna_composite_op *op)
352.8957 ++{
352.8958 ++	/*
352.8959 ++	 * vertex data in vertex buffer
352.8960 ++	 *    position: (x, y)
352.8961 ++	 *    texture coordinate 0: (u0, v0) if (is_affine is true) else (u0, v0, w0)
352.8962 ++	 *    texture coordinate 1 if (has_mask is true): same as above
352.8963 ++	 */
352.8964 ++	struct gen9_render_state *render = &sna->render_state.gen9;
352.8965 ++	uint32_t src_format, dw;
352.8966 ++	int id = GEN9_VERTEX(op->u.gen9.flags);
352.8967 ++	bool has_mask;
352.8968 ++
352.8969 ++	DBG(("%s: setup id=%d\n", __FUNCTION__, id));
352.8970 ++
352.8971 ++	if (render->ve_id == id)
352.8972 ++		return;
352.8973 ++	render->ve_id = id;
352.8974 ++
352.8975 ++	if (render->ve_dirty) {
352.8976 ++		/* dummy primitive to flush vertex before change? */
352.8977 ++		OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
352.8978 ++		OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
352.8979 ++		OUT_BATCH(0);
352.8980 ++		OUT_BATCH(0);
352.8981 ++		OUT_BATCH(1);	/* single instance */
352.8982 ++		OUT_BATCH(0);	/* start instance location */
352.8983 ++		OUT_BATCH(0);	/* index buffer offset, ignored */
352.8984 ++	}
352.8985 ++
352.8986 ++	/* The VUE layout
352.8987 ++	 *    dword 0-3: pad (0.0, 0.0, 0.0. 0.0)
352.8988 ++	 *    dword 4-7: position (x, y, 1.0, 1.0),
352.8989 ++	 *    dword 8-11: texture coordinate 0 (u0, v0, w0, 1.0)
352.8990 ++	 *    dword 12-15: texture coordinate 1 (u1, v1, w1, 1.0)
352.8991 ++	 *
352.8992 ++	 * dword 4-15 are fetched from vertex buffer
352.8993 ++	 */
352.8994 ++	has_mask = (id >> 2) != 0;
352.8995 ++	OUT_BATCH(GEN9_3DSTATE_VERTEX_ELEMENTS |
352.8996 ++		((2 * (3 + has_mask)) + 1 - 2));
352.8997 ++
352.8998 ++	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
352.8999 ++		  SURFACEFORMAT_R32G32B32A32_FLOAT << VE_FORMAT_SHIFT |
352.9000 ++		  0 << VE_OFFSET_SHIFT);
352.9001 ++	OUT_BATCH(COMPONENT_STORE_0 << VE_COMPONENT_0_SHIFT |
352.9002 ++		  COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT |
352.9003 ++		  COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT |
352.9004 ++		  COMPONENT_STORE_0 << VE_COMPONENT_3_SHIFT);
352.9005 ++
352.9006 ++	/* x,y */
352.9007 ++	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
352.9008 ++		  SURFACEFORMAT_R16G16_SSCALED << VE_FORMAT_SHIFT |
352.9009 ++		  0 << VE_OFFSET_SHIFT);
352.9010 ++	OUT_BATCH(COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT |
352.9011 ++		  COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT |
352.9012 ++		  COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT |
352.9013 ++		  COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT);
352.9014 ++
352.9015 ++	/* u0, v0, w0 */
352.9016 ++	DBG(("%s: first channel %d floats, offset=4\n", __FUNCTION__, id & 3));
352.9017 ++	dw = COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT;
352.9018 ++	switch (id & 3) {
352.9019 ++	default:
352.9020 ++		assert(0);
352.9021 ++	case 0:
352.9022 ++		src_format = SURFACEFORMAT_R16G16_SSCALED;
352.9023 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9024 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
352.9025 ++		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
352.9026 ++		break;
352.9027 ++	case 1:
352.9028 ++		src_format = SURFACEFORMAT_R32_FLOAT;
352.9029 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9030 ++		dw |= COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT;
352.9031 ++		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
352.9032 ++		break;
352.9033 ++	case 2:
352.9034 ++		src_format = SURFACEFORMAT_R32G32_FLOAT;
352.9035 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9036 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
352.9037 ++		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
352.9038 ++		break;
352.9039 ++	case 3:
352.9040 ++		src_format = SURFACEFORMAT_R32G32B32_FLOAT;
352.9041 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9042 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
352.9043 ++		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_2_SHIFT;
352.9044 ++		break;
352.9045 ++	}
352.9046 ++	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
352.9047 ++		  src_format << VE_FORMAT_SHIFT |
352.9048 ++		  4 << VE_OFFSET_SHIFT);
352.9049 ++	OUT_BATCH(dw);
352.9050 ++
352.9051 ++	/* u1, v1, w1 */
352.9052 ++	if (has_mask) {
352.9053 ++		unsigned offset = 4 + ((id & 3) ?: 1) * sizeof(float);
352.9054 ++		DBG(("%s: second channel %d floats, offset=%d\n", __FUNCTION__, (id >> 2) & 3, offset));
352.9055 ++		dw = COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT;
352.9056 ++		switch (id >> 2) {
352.9057 ++		case 1:
352.9058 ++			src_format = SURFACEFORMAT_R32_FLOAT;
352.9059 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9060 ++			dw |= COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT;
352.9061 ++			dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
352.9062 ++			break;
352.9063 ++		default:
352.9064 ++			assert(0);
352.9065 ++		case 2:
352.9066 ++			src_format = SURFACEFORMAT_R32G32_FLOAT;
352.9067 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9068 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
352.9069 ++			dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
352.9070 ++			break;
352.9071 ++		case 3:
352.9072 ++			src_format = SURFACEFORMAT_R32G32B32_FLOAT;
352.9073 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
352.9074 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
352.9075 ++			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_2_SHIFT;
352.9076 ++			break;
352.9077 ++		}
352.9078 ++		OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
352.9079 ++			  src_format << VE_FORMAT_SHIFT |
352.9080 ++			  offset << VE_OFFSET_SHIFT);
352.9081 ++		OUT_BATCH(dw);
352.9082 ++	}
352.9083 ++
352.9084 ++	render->ve_dirty = true;
352.9085 ++}
352.9086 ++
352.9087 ++inline static void
352.9088 ++gen9_emit_pipe_invalidate(struct sna *sna)
352.9089 ++{
352.9090 ++	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
352.9091 ++	OUT_BATCH(PIPE_CONTROL_WC_FLUSH |
352.9092 ++		  PIPE_CONTROL_TC_FLUSH |
352.9093 ++		  PIPE_CONTROL_CS_STALL);
352.9094 ++	OUT_BATCH64(0);
352.9095 ++	OUT_BATCH64(0);
352.9096 ++}
352.9097 ++
352.9098 ++inline static void
352.9099 ++gen9_emit_pipe_flush(struct sna *sna, bool need_stall)
352.9100 ++{
352.9101 ++	unsigned stall;
352.9102 ++
352.9103 ++	stall = 0;
352.9104 ++	if (need_stall)
352.9105 ++		stall = (PIPE_CONTROL_CS_STALL |
352.9106 ++			 PIPE_CONTROL_STALL_AT_SCOREBOARD);
352.9107 ++
352.9108 ++	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
352.9109 ++	OUT_BATCH(PIPE_CONTROL_WC_FLUSH | stall);
352.9110 ++	OUT_BATCH64(0);
352.9111 ++	OUT_BATCH64(0);
352.9112 ++}
352.9113 ++
352.9114 ++inline static void
352.9115 ++gen9_emit_pipe_stall(struct sna *sna)
352.9116 ++{
352.9117 ++	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
352.9118 ++	OUT_BATCH(PIPE_CONTROL_CS_STALL |
352.9119 ++		  PIPE_CONTROL_FLUSH |
352.9120 ++		  PIPE_CONTROL_STALL_AT_SCOREBOARD);
352.9121 ++	OUT_BATCH64(0);
352.9122 ++	OUT_BATCH64(0);
352.9123 ++}
352.9124 ++
352.9125 ++static void
352.9126 ++gen9_emit_state(struct sna *sna,
352.9127 ++		const struct sna_composite_op *op,
352.9128 ++		uint16_t wm_binding_table)
352.9129 ++{
352.9130 ++	bool need_invalidate;
352.9131 ++	bool need_flush;
352.9132 ++	bool need_stall;
352.9133 ++
352.9134 ++	assert(op->dst.bo->exec);
352.9135 ++
352.9136 ++	need_flush = wm_binding_table & 1 ||
352.9137 ++		(sna->render_state.gen9.emit_flush && GEN9_READS_DST(op->u.gen9.flags));
352.9138 ++	if (ALWAYS_FLUSH)
352.9139 ++		need_flush = true;
352.9140 ++
352.9141 ++	wm_binding_table &= ~1;
352.9142 ++
352.9143 ++	need_stall = sna->render_state.gen9.surface_table != wm_binding_table;
352.9144 ++
352.9145 ++	need_invalidate = kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo);
352.9146 ++	if (ALWAYS_INVALIDATE)
352.9147 ++		need_invalidate = true;
352.9148 ++
352.9149 ++	need_stall &= gen9_emit_drawing_rectangle(sna, op);
352.9150 ++	if (ALWAYS_STALL)
352.9151 ++		need_stall = true;
352.9152 ++
352.9153 ++	if (need_invalidate) {
352.9154 ++		gen9_emit_pipe_invalidate(sna);
352.9155 ++		kgem_clear_dirty(&sna->kgem);
352.9156 ++		assert(op->dst.bo->exec);
352.9157 ++		kgem_bo_mark_dirty(op->dst.bo);
352.9158 ++
352.9159 ++		need_flush = false;
352.9160 ++		need_stall = false;
352.9161 ++	}
352.9162 ++	if (need_flush) {
352.9163 ++		gen9_emit_pipe_flush(sna, need_stall);
352.9164 ++		need_stall = false;
352.9165 ++	}
352.9166 ++	if (need_stall)
352.9167 ++		gen9_emit_pipe_stall(sna);
352.9168 ++
352.9169 ++	gen9_emit_cc(sna, GEN9_BLEND(op->u.gen9.flags));
352.9170 ++	gen9_emit_sampler(sna, GEN9_SAMPLER(op->u.gen9.flags));
352.9171 ++	gen9_emit_sf(sna, GEN9_VERTEX(op->u.gen9.flags) >> 2);
352.9172 ++	gen9_emit_wm(sna, GEN9_KERNEL(op->u.gen9.flags));
352.9173 ++	gen9_emit_vertex_elements(sna, op);
352.9174 ++	gen9_emit_binding_table(sna, wm_binding_table);
352.9175 ++
352.9176 ++	sna->render_state.gen9.emit_flush = GEN9_READS_DST(op->u.gen9.flags);
352.9177 ++}
352.9178 ++
352.9179 ++static bool gen9_magic_ca_pass(struct sna *sna,
352.9180 ++			       const struct sna_composite_op *op)
352.9181 ++{
352.9182 ++	struct gen9_render_state *state = &sna->render_state.gen9;
352.9183 ++
352.9184 ++	if (!op->need_magic_ca_pass)
352.9185 ++		return false;
352.9186 ++
352.9187 ++	DBG(("%s: CA fixup (%d -> %d)\n", __FUNCTION__,
352.9188 ++	     sna->render.vertex_start, sna->render.vertex_index));
352.9189 ++
352.9190 ++	gen9_emit_pipe_stall(sna);
352.9191 ++
352.9192 ++	gen9_emit_cc(sna,
352.9193 ++		     GEN9_BLEND(gen9_get_blend(PictOpAdd, true,
352.9194 ++					       op->dst.format)));
352.9195 ++	gen9_emit_wm(sna,
352.9196 ++		     gen9_choose_composite_kernel(PictOpAdd,
352.9197 ++						  true, true,
352.9198 ++						  op->is_affine));
352.9199 ++
352.9200 ++	OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
352.9201 ++	OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
352.9202 ++	OUT_BATCH(sna->render.vertex_index - sna->render.vertex_start);
352.9203 ++	OUT_BATCH(sna->render.vertex_start);
352.9204 ++	OUT_BATCH(1);	/* single instance */
352.9205 ++	OUT_BATCH(0);	/* start instance location */
352.9206 ++	OUT_BATCH(0);	/* index buffer offset, ignored */
352.9207 ++
352.9208 ++	state->last_primitive = sna->kgem.nbatch;
352.9209 ++	state->ve_dirty = false;
352.9210 ++	return true;
352.9211 ++}
352.9212 ++
352.9213 ++static void null_create(struct sna_static_stream *stream)
352.9214 ++{
352.9215 ++	/* A bunch of zeros useful for legacy border color and depth-stencil */
352.9216 ++	sna_static_stream_map(stream, 64, 64);
352.9217 ++}
352.9218 ++
352.9219 ++static void
352.9220 ++sampler_state_init(struct gen9_sampler_state *sampler_state,
352.9221 ++		   sampler_filter_t filter,
352.9222 ++		   sampler_extend_t extend)
352.9223 ++{
352.9224 ++	COMPILE_TIME_ASSERT(sizeof(*sampler_state) == 4*sizeof(uint32_t));
352.9225 ++
352.9226 ++	sampler_state->ss0.lod_preclamp = 2;	/* GL mode */
352.9227 ++	sampler_state->ss0.default_color_mode = 1;
352.9228 ++
352.9229 ++	switch (filter) {
352.9230 ++	default:
352.9231 ++	case SAMPLER_FILTER_NEAREST:
352.9232 ++		sampler_state->ss0.min_filter = MAPFILTER_NEAREST;
352.9233 ++		sampler_state->ss0.mag_filter = MAPFILTER_NEAREST;
352.9234 ++		break;
352.9235 ++	case SAMPLER_FILTER_BILINEAR:
352.9236 ++		sampler_state->ss0.min_filter = MAPFILTER_LINEAR;
352.9237 ++		sampler_state->ss0.mag_filter = MAPFILTER_LINEAR;
352.9238 ++		break;
352.9239 ++	}
352.9240 ++
352.9241 ++	/* XXX bicubic filter using MAPFILTER_FLEXIBLE */
352.9242 ++
352.9243 ++	switch (extend) {
352.9244 ++	default:
352.9245 ++	case SAMPLER_EXTEND_NONE:
352.9246 ++		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
352.9247 ++		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
352.9248 ++		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
352.9249 ++		break;
352.9250 ++	case SAMPLER_EXTEND_REPEAT:
352.9251 ++		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_WRAP;
352.9252 ++		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_WRAP;
352.9253 ++		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_WRAP;
352.9254 ++		break;
352.9255 ++	case SAMPLER_EXTEND_PAD:
352.9256 ++		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_CLAMP;
352.9257 ++		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_CLAMP;
352.9258 ++		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_CLAMP;
352.9259 ++		break;
352.9260 ++	case SAMPLER_EXTEND_REFLECT:
352.9261 ++		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_MIRROR;
352.9262 ++		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_MIRROR;
352.9263 ++		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_MIRROR;
352.9264 ++		break;
352.9265 ++	}
352.9266 ++}
352.9267 ++
352.9268 ++static void
352.9269 ++sampler_copy_init(struct gen9_sampler_state *ss)
352.9270 ++{
352.9271 ++	sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
352.9272 ++	ss->ss3.non_normalized_coord = 1;
352.9273 ++
352.9274 ++	sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
352.9275 ++}
352.9276 ++
352.9277 ++static void
352.9278 ++sampler_fill_init(struct gen9_sampler_state *ss)
352.9279 ++{
352.9280 ++	sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_REPEAT);
352.9281 ++	ss->ss3.non_normalized_coord = 1;
352.9282 ++
352.9283 ++	sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
352.9284 ++}
352.9285 ++
352.9286 ++static uint32_t
352.9287 ++gen9_tiling_bits(uint32_t tiling)
352.9288 ++{
352.9289 ++	switch (tiling) {
352.9290 ++	default: assert(0);
352.9291 ++	case I915_TILING_NONE: return 0;
352.9292 ++	case I915_TILING_X: return SURFACE_TILED;
352.9293 ++	case I915_TILING_Y: return SURFACE_TILED | SURFACE_TILED_Y;
352.9294 ++	}
352.9295 ++}
352.9296 ++
352.9297 ++#define MOCS_PTE (1 << 1)
352.9298 ++#define MOCS_WB (2 << 1)
352.9299 ++
352.9300 ++/**
352.9301 ++ * Sets up the common fields for a surface state buffer for the given
352.9302 ++ * picture in the given surface state buffer.
352.9303 ++ */
352.9304 ++static uint32_t
352.9305 ++gen9_bind_bo(struct sna *sna,
352.9306 ++	     struct kgem_bo *bo,
352.9307 ++	     uint32_t width,
352.9308 ++	     uint32_t height,
352.9309 ++	     uint32_t format,
352.9310 ++	     bool is_dst)
352.9311 ++{
352.9312 ++	uint32_t *ss;
352.9313 ++	uint32_t domains;
352.9314 ++	int offset;
352.9315 ++	uint32_t is_scanout = is_dst && bo->scanout;
352.9316 ++
352.9317 ++	/* After the first bind, we manage the cache domains within the batch */
352.9318 ++	offset = kgem_bo_get_binding(bo, format | is_dst << 30 | is_scanout << 31);
352.9319 ++	if (offset) {
352.9320 ++		if (is_dst)
352.9321 ++			kgem_bo_mark_dirty(bo);
352.9322 ++		assert(offset >= sna->kgem.surface);
352.9323 ++		return offset * sizeof(uint32_t);
352.9324 ++	}
352.9325 ++
352.9326 ++	offset = sna->kgem.surface -= SURFACE_DW;
352.9327 ++	ss = sna->kgem.batch + offset;
352.9328 ++	ss[0] = (SURFACE_2D << SURFACE_TYPE_SHIFT |
352.9329 ++		 gen9_tiling_bits(bo->tiling) |
352.9330 ++		 format << SURFACE_FORMAT_SHIFT |
352.9331 ++		 SURFACE_VALIGN_4 | SURFACE_HALIGN_4);
352.9332 ++	if (is_dst) {
352.9333 ++		ss[0] |= SURFACE_RC_READ_WRITE;
352.9334 ++		domains = I915_GEM_DOMAIN_RENDER << 16 |I915_GEM_DOMAIN_RENDER;
352.9335 ++	} else
352.9336 ++		domains = I915_GEM_DOMAIN_SAMPLER << 16;
352.9337 ++	ss[1] = (is_scanout || (is_dst && is_uncached(sna, bo))) ? MOCS_PTE << 24 : MOCS_WB << 24;
352.9338 ++	ss[2] = ((width - 1)  << SURFACE_WIDTH_SHIFT |
352.9339 ++		 (height - 1) << SURFACE_HEIGHT_SHIFT);
352.9340 ++	ss[3] = (bo->pitch - 1) << SURFACE_PITCH_SHIFT;
352.9341 ++	ss[4] = 0;
352.9342 ++	ss[5] = 0;
352.9343 ++	ss[6] = 0;
352.9344 ++	ss[7] = SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA);
352.9345 ++	*(uint64_t *)(ss+8) = kgem_add_reloc64(&sna->kgem, offset + 8, bo, domains, 0);
352.9346 ++	ss[10] = 0;
352.9347 ++	ss[11] = 0;
352.9348 ++	ss[12] = 0;
352.9349 ++	ss[13] = 0;
352.9350 ++	ss[14] = 0;
352.9351 ++	ss[15] = 0;
352.9352 ++
352.9353 ++	kgem_bo_set_binding(bo, format | is_dst << 30 | is_scanout << 31, offset);
352.9354 ++
352.9355 ++	DBG(("[%x] bind bo(handle=%d, addr=%lx), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> %s\n",
352.9356 ++	     offset, bo->handle, *(uint64_t *)(ss+8),
352.9357 ++	     format, width, height, bo->pitch, bo->tiling,
352.9358 ++	     domains & 0xffff ? "render" : "sampler"));
352.9359 ++
352.9360 ++	return offset * sizeof(uint32_t);
352.9361 ++}
352.9362 ++
352.9363 ++static void gen9_emit_vertex_buffer(struct sna *sna,
352.9364 ++				    const struct sna_composite_op *op)
352.9365 ++{
352.9366 ++	int id = GEN9_VERTEX(op->u.gen9.flags);
352.9367 ++
352.9368 ++	OUT_BATCH(GEN9_3DSTATE_VERTEX_BUFFERS | (5 - 2));
352.9369 ++	OUT_BATCH(id << VB_INDEX_SHIFT | VB_MODIFY_ENABLE |
352.9370 ++		  4*op->floats_per_vertex);
352.9371 ++	sna->render.vertex_reloc[sna->render.nvertex_reloc++] = sna->kgem.nbatch;
352.9372 ++	OUT_BATCH64(0);
352.9373 ++	OUT_BATCH(~0); /* buffer size: disabled */
352.9374 ++
352.9375 ++	sna->render.vb_id |= 1 << id;
352.9376 ++}
352.9377 ++
352.9378 ++static void gen9_emit_primitive(struct sna *sna)
352.9379 ++{
352.9380 ++	if (sna->kgem.nbatch == sna->render_state.gen9.last_primitive) {
352.9381 ++		sna->render.vertex_offset = sna->kgem.nbatch - 5;
352.9382 ++		return;
352.9383 ++	}
352.9384 ++
352.9385 ++	OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
352.9386 ++	OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
352.9387 ++	sna->render.vertex_offset = sna->kgem.nbatch;
352.9388 ++	OUT_BATCH(0);	/* vertex count, to be filled in later */
352.9389 ++	OUT_BATCH(sna->render.vertex_index);
352.9390 ++	OUT_BATCH(1);	/* single instance */
352.9391 ++	OUT_BATCH(0);	/* start instance location */
352.9392 ++	OUT_BATCH(0);	/* index buffer offset, ignored */
352.9393 ++	sna->render.vertex_start = sna->render.vertex_index;
352.9394 ++
352.9395 ++	sna->render_state.gen9.last_primitive = sna->kgem.nbatch;
352.9396 ++	sna->render_state.gen9.ve_dirty = false;
352.9397 ++}
352.9398 ++
352.9399 ++static bool gen9_rectangle_begin(struct sna *sna,
352.9400 ++				 const struct sna_composite_op *op)
352.9401 ++{
352.9402 ++	int id = 1 << GEN9_VERTEX(op->u.gen9.flags);
352.9403 ++	int ndwords;
352.9404 ++
352.9405 ++	if (sna_vertex_wait__locked(&sna->render) && sna->render.vertex_offset)
352.9406 ++		return true;
352.9407 ++
352.9408 ++	ndwords = op->need_magic_ca_pass ? 60 : 6;
352.9409 ++	if ((sna->render.vb_id & id) == 0)
352.9410 ++		ndwords += 5;
352.9411 ++	if (!kgem_check_batch(&sna->kgem, ndwords))
352.9412 ++		return false;
352.9413 ++
352.9414 ++	if ((sna->render.vb_id & id) == 0)
352.9415 ++		gen9_emit_vertex_buffer(sna, op);
352.9416 ++
352.9417 ++	gen9_emit_primitive(sna);
352.9418 ++	return true;
352.9419 ++}
352.9420 ++
352.9421 ++static int gen9_get_rectangles__flush(struct sna *sna,
352.9422 ++				      const struct sna_composite_op *op)
352.9423 ++{
352.9424 ++	/* Preventing discarding new vbo after lock contention */
352.9425 ++	if (sna_vertex_wait__locked(&sna->render)) {
352.9426 ++		int rem = vertex_space(sna);
352.9427 ++		if (rem > op->floats_per_rect)
352.9428 ++			return rem;
352.9429 ++	}
352.9430 ++
352.9431 ++	if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 65 : 6))
352.9432 ++		return 0;
352.9433 ++	if (!kgem_check_reloc_and_exec(&sna->kgem, 2))
352.9434 ++		return 0;
352.9435 ++
352.9436 ++	if (sna->render.vertex_offset) {
352.9437 ++		gen8_vertex_flush(sna);
352.9438 ++		if (gen9_magic_ca_pass(sna, op)) {
352.9439 ++			gen9_emit_pipe_invalidate(sna);
352.9440 ++			gen9_emit_cc(sna, GEN9_BLEND(op->u.gen9.flags));
352.9441 ++			gen9_emit_wm(sna, GEN9_KERNEL(op->u.gen9.flags));
352.9442 ++		}
352.9443 ++	}
352.9444 ++
352.9445 ++	return gen8_vertex_finish(sna);
352.9446 ++}
352.9447 ++
352.9448 ++inline static int gen9_get_rectangles(struct sna *sna,
352.9449 ++				      const struct sna_composite_op *op,
352.9450 ++				      int want,
352.9451 ++				      void (*emit_state)(struct sna *sna, const struct sna_composite_op *op))
352.9452 ++{
352.9453 ++	int rem;
352.9454 ++
352.9455 ++	assert(want);
352.9456 ++
352.9457 ++start:
352.9458 ++	rem = vertex_space(sna);
352.9459 ++	if (unlikely(rem < op->floats_per_rect)) {
352.9460 ++		DBG(("flushing vbo for %s: %d < %d\n",
352.9461 ++		     __FUNCTION__, rem, op->floats_per_rect));
352.9462 ++		rem = gen9_get_rectangles__flush(sna, op);
352.9463 ++		if (unlikely(rem == 0))
352.9464 ++			goto flush;
352.9465 ++	}
352.9466 ++
352.9467 ++	if (unlikely(sna->render.vertex_offset == 0)) {
352.9468 ++		if (!gen9_rectangle_begin(sna, op))
352.9469 ++			goto flush;
352.9470 ++		else
352.9471 ++			goto start;
352.9472 ++	}
352.9473 ++
352.9474 ++	assert(rem <= vertex_space(sna));
352.9475 ++	assert(op->floats_per_rect <= rem);
352.9476 ++	if (want > 1 && want * op->floats_per_rect > rem)
352.9477 ++		want = rem / op->floats_per_rect;
352.9478 ++
352.9479 ++	assert(want > 0);
352.9480 ++	sna->render.vertex_index += 3*want;
352.9481 ++	return want;
352.9482 ++
352.9483 ++flush:
352.9484 ++	if (sna->render.vertex_offset) {
352.9485 ++		gen8_vertex_flush(sna);
352.9486 ++		gen9_magic_ca_pass(sna, op);
352.9487 ++	}
352.9488 ++	sna_vertex_wait__locked(&sna->render);
352.9489 ++	_kgem_submit(&sna->kgem);
352.9490 ++	emit_state(sna, op);
352.9491 ++	goto start;
352.9492 ++}
352.9493 ++
352.9494 ++inline static uint32_t *gen9_composite_get_binding_table(struct sna *sna,
352.9495 ++							 uint16_t *offset)
352.9496 ++{
352.9497 ++	uint32_t *table;
352.9498 ++
352.9499 ++	assert(sna->kgem.surface <= 16384);
352.9500 ++	sna->kgem.surface -= SURFACE_DW;
352.9501 ++	/* Clear all surplus entries to zero in case of prefetch */
352.9502 ++	table = memset(sna->kgem.batch + sna->kgem.surface, 0, 64);
352.9503 ++
352.9504 ++	DBG(("%s(%x)\n", __FUNCTION__, 4*sna->kgem.surface));
352.9505 ++
352.9506 ++	*offset = sna->kgem.surface;
352.9507 ++	return table;
352.9508 ++}
352.9509 ++
352.9510 ++static void
352.9511 ++gen9_get_batch(struct sna *sna, const struct sna_composite_op *op)
352.9512 ++{
352.9513 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo);
352.9514 ++
352.9515 ++	if (!kgem_check_batch_with_surfaces(&sna->kgem, 150, 2*(1+3))) {
352.9516 ++		DBG(("%s: flushing batch: %d < %d+%d\n",
352.9517 ++		     __FUNCTION__, sna->kgem.surface - sna->kgem.nbatch,
352.9518 ++		     150, 4*8*2));
352.9519 ++		_kgem_submit(&sna->kgem);
352.9520 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.9521 ++	}
352.9522 ++
352.9523 ++	assert(sna->kgem.mode == KGEM_RENDER);
352.9524 ++	assert(sna->kgem.ring == KGEM_RENDER);
352.9525 ++
352.9526 ++	if (sna->render_state.gen9.needs_invariant)
352.9527 ++		gen9_emit_invariant(sna);
352.9528 ++}
352.9529 ++
352.9530 ++static void gen9_emit_composite_state(struct sna *sna,
352.9531 ++				      const struct sna_composite_op *op)
352.9532 ++{
352.9533 ++	uint32_t *binding_table;
352.9534 ++	uint16_t offset, dirty;
352.9535 ++
352.9536 ++	gen9_get_batch(sna, op);
352.9537 ++
352.9538 ++	binding_table = gen9_composite_get_binding_table(sna, &offset);
352.9539 ++
352.9540 ++	dirty = kgem_bo_is_dirty(op->dst.bo);
352.9541 ++
352.9542 ++	binding_table[0] =
352.9543 ++		gen9_bind_bo(sna,
352.9544 ++			    op->dst.bo, op->dst.width, op->dst.height,
352.9545 ++			    gen9_get_dest_format(op->dst.format),
352.9546 ++			    true);
352.9547 ++	binding_table[1] =
352.9548 ++		gen9_bind_bo(sna,
352.9549 ++			     op->src.bo, op->src.width, op->src.height,
352.9550 ++			     op->src.card_format,
352.9551 ++			     false);
352.9552 ++	if (op->mask.bo) {
352.9553 ++		binding_table[2] =
352.9554 ++			gen9_bind_bo(sna,
352.9555 ++				     op->mask.bo,
352.9556 ++				     op->mask.width,
352.9557 ++				     op->mask.height,
352.9558 ++				     op->mask.card_format,
352.9559 ++				     false);
352.9560 ++	}
352.9561 ++
352.9562 ++	if (sna->kgem.surface == offset &&
352.9563 ++	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table &&
352.9564 ++	    (op->mask.bo == NULL ||
352.9565 ++	     sna->kgem.batch[sna->render_state.gen9.surface_table+2] == binding_table[2])) {
352.9566 ++		sna->kgem.surface += SURFACE_DW;
352.9567 ++		offset = sna->render_state.gen9.surface_table;
352.9568 ++	}
352.9569 ++
352.9570 ++	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
352.9571 ++		dirty = 0;
352.9572 ++
352.9573 ++	gen9_emit_state(sna, op, offset | dirty);
352.9574 ++}
352.9575 ++
352.9576 ++static void
352.9577 ++gen9_align_vertex(struct sna *sna, const struct sna_composite_op *op)
352.9578 ++{
352.9579 ++	if (op->floats_per_vertex != sna->render_state.gen9.floats_per_vertex) {
352.9580 ++		DBG(("aligning vertex: was %d, now %d floats per vertex\n",
352.9581 ++		     sna->render_state.gen9.floats_per_vertex, op->floats_per_vertex));
352.9582 ++		gen8_vertex_align(sna, op);
352.9583 ++		sna->render_state.gen9.floats_per_vertex = op->floats_per_vertex;
352.9584 ++	}
352.9585 ++}
352.9586 ++
352.9587 ++fastcall static void
352.9588 ++gen9_render_composite_blt(struct sna *sna,
352.9589 ++			  const struct sna_composite_op *op,
352.9590 ++			  const struct sna_composite_rectangles *r)
352.9591 ++{
352.9592 ++	gen9_get_rectangles(sna, op, 1, gen9_emit_composite_state);
352.9593 ++	op->prim_emit(sna, op, r);
352.9594 ++}
352.9595 ++
352.9596 ++fastcall static void
352.9597 ++gen9_render_composite_box(struct sna *sna,
352.9598 ++			  const struct sna_composite_op *op,
352.9599 ++			  const BoxRec *box)
352.9600 ++{
352.9601 ++	struct sna_composite_rectangles r;
352.9602 ++
352.9603 ++	gen9_get_rectangles(sna, op, 1, gen9_emit_composite_state);
352.9604 ++
352.9605 ++	DBG(("  %s: (%d, %d), (%d, %d)\n",
352.9606 ++	     __FUNCTION__,
352.9607 ++	     box->x1, box->y1, box->x2, box->y2));
352.9608 ++
352.9609 ++	r.dst.x = box->x1;
352.9610 ++	r.dst.y = box->y1;
352.9611 ++	r.width  = box->x2 - box->x1;
352.9612 ++	r.height = box->y2 - box->y1;
352.9613 ++	r.src = r.mask = r.dst;
352.9614 ++
352.9615 ++	op->prim_emit(sna, op, &r);
352.9616 ++}
352.9617 ++
352.9618 ++static void
352.9619 ++gen9_render_composite_boxes__blt(struct sna *sna,
352.9620 ++				 const struct sna_composite_op *op,
352.9621 ++				 const BoxRec *box, int nbox)
352.9622 ++{
352.9623 ++	DBG(("composite_boxes(%d)\n", nbox));
352.9624 ++
352.9625 ++	do {
352.9626 ++		int nbox_this_time;
352.9627 ++
352.9628 ++		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
352.9629 ++						     gen9_emit_composite_state);
352.9630 ++		nbox -= nbox_this_time;
352.9631 ++
352.9632 ++		do {
352.9633 ++			struct sna_composite_rectangles r;
352.9634 ++
352.9635 ++			DBG(("  %s: (%d, %d), (%d, %d)\n",
352.9636 ++			     __FUNCTION__,
352.9637 ++			     box->x1, box->y1, box->x2, box->y2));
352.9638 ++
352.9639 ++			r.dst.x = box->x1;
352.9640 ++			r.dst.y = box->y1;
352.9641 ++			r.width  = box->x2 - box->x1;
352.9642 ++			r.height = box->y2 - box->y1;
352.9643 ++			r.src = r.mask = r.dst;
352.9644 ++
352.9645 ++			op->prim_emit(sna, op, &r);
352.9646 ++			box++;
352.9647 ++		} while (--nbox_this_time);
352.9648 ++	} while (nbox);
352.9649 ++}
352.9650 ++
352.9651 ++static void
352.9652 ++gen9_render_composite_boxes(struct sna *sna,
352.9653 ++			    const struct sna_composite_op *op,
352.9654 ++			    const BoxRec *box, int nbox)
352.9655 ++{
352.9656 ++	DBG(("%s: nbox=%d\n", __FUNCTION__, nbox));
352.9657 ++
352.9658 ++	do {
352.9659 ++		int nbox_this_time;
352.9660 ++		float *v;
352.9661 ++
352.9662 ++		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
352.9663 ++						     gen9_emit_composite_state);
352.9664 ++		assert(nbox_this_time);
352.9665 ++		nbox -= nbox_this_time;
352.9666 ++
352.9667 ++		v = sna->render.vertices + sna->render.vertex_used;
352.9668 ++		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
352.9669 ++
352.9670 ++		op->emit_boxes(op, box, nbox_this_time, v);
352.9671 ++		box += nbox_this_time;
352.9672 ++	} while (nbox);
352.9673 ++}
352.9674 ++
352.9675 ++static void
352.9676 ++gen9_render_composite_boxes__thread(struct sna *sna,
352.9677 ++				    const struct sna_composite_op *op,
352.9678 ++				    const BoxRec *box, int nbox)
352.9679 ++{
352.9680 ++	DBG(("%s: nbox=%d\n", __FUNCTION__, nbox));
352.9681 ++
352.9682 ++	sna_vertex_lock(&sna->render);
352.9683 ++	do {
352.9684 ++		int nbox_this_time;
352.9685 ++		float *v;
352.9686 ++
352.9687 ++		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
352.9688 ++						     gen9_emit_composite_state);
352.9689 ++		assert(nbox_this_time);
352.9690 ++		nbox -= nbox_this_time;
352.9691 ++
352.9692 ++		v = sna->render.vertices + sna->render.vertex_used;
352.9693 ++		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
352.9694 ++
352.9695 ++		sna_vertex_acquire__locked(&sna->render);
352.9696 ++		sna_vertex_unlock(&sna->render);
352.9697 ++
352.9698 ++		op->emit_boxes(op, box, nbox_this_time, v);
352.9699 ++		box += nbox_this_time;
352.9700 ++
352.9701 ++		sna_vertex_lock(&sna->render);
352.9702 ++		sna_vertex_release__locked(&sna->render);
352.9703 ++	} while (nbox);
352.9704 ++	sna_vertex_unlock(&sna->render);
352.9705 ++}
352.9706 ++
352.9707 ++static uint32_t
352.9708 ++gen9_create_blend_state(struct sna_static_stream *stream)
352.9709 ++{
352.9710 ++	char *base, *ptr;
352.9711 ++	int src, dst;
352.9712 ++
352.9713 ++	COMPILE_TIME_ASSERT(((GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT << 4) & (1 << 15)) == 0);
352.9714 ++
352.9715 ++	base = sna_static_stream_map(stream,
352.9716 ++				     GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT * GEN9_BLEND_STATE_PADDED_SIZE,
352.9717 ++				     64);
352.9718 ++
352.9719 ++	ptr = base;
352.9720 ++	for (src = 0; src < GEN9_BLENDFACTOR_COUNT; src++) {
352.9721 ++		for (dst = 0; dst < GEN9_BLENDFACTOR_COUNT; dst++) {
352.9722 ++			struct gen9_blend_state *blend =
352.9723 ++				(struct gen9_blend_state *)ptr;
352.9724 ++
352.9725 ++			assert(((ptr - base) & 63) == 0);
352.9726 ++			COMPILE_TIME_ASSERT(sizeof(blend->common) == 4);
352.9727 ++			COMPILE_TIME_ASSERT(sizeof(blend->rt) == 8);
352.9728 ++			COMPILE_TIME_ASSERT((char *)&blend->rt - (char *)blend == 4);
352.9729 ++
352.9730 ++			blend->rt.post_blend_clamp = 1;
352.9731 ++			blend->rt.pre_blend_clamp = 1;
352.9732 ++
352.9733 ++			blend->rt.color_blend =
352.9734 ++				!(dst == BLENDFACTOR_ZERO && src == BLENDFACTOR_ONE);
352.9735 ++			blend->rt.dest_blend_factor = dst;
352.9736 ++			blend->rt.source_blend_factor = src;
352.9737 ++			blend->rt.color_blend_function = BLENDFUNCTION_ADD;
352.9738 ++
352.9739 ++			blend->rt.dest_alpha_blend_factor = dst;
352.9740 ++			blend->rt.source_alpha_blend_factor = src;
352.9741 ++			blend->rt.alpha_blend_function = BLENDFUNCTION_ADD;
352.9742 ++
352.9743 ++			ptr += GEN9_BLEND_STATE_PADDED_SIZE;
352.9744 ++		}
352.9745 ++	}
352.9746 ++
352.9747 ++	return sna_static_stream_offsetof(stream, base);
352.9748 ++}
352.9749 ++
352.9750 ++static int
352.9751 ++gen9_composite_picture(struct sna *sna,
352.9752 ++		       PicturePtr picture,
352.9753 ++		       struct sna_composite_channel *channel,
352.9754 ++		       int x, int y,
352.9755 ++		       int w, int h,
352.9756 ++		       int dst_x, int dst_y,
352.9757 ++		       bool precise)
352.9758 ++{
352.9759 ++	PixmapPtr pixmap;
352.9760 ++	uint32_t color;
352.9761 ++	int16_t dx, dy;
352.9762 ++
352.9763 ++	DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n",
352.9764 ++	     __FUNCTION__, x, y, w, h, dst_x, dst_y));
352.9765 ++
352.9766 ++	channel->is_solid = false;
352.9767 ++	channel->card_format = -1;
352.9768 ++
352.9769 ++	if (sna_picture_is_solid(picture, &color))
352.9770 ++		return gen4_channel_init_solid(sna, channel, color);
352.9771 ++
352.9772 ++	if (picture->pDrawable == NULL) {
352.9773 ++		int ret;
352.9774 ++
352.9775 ++		if (picture->pSourcePict->type == SourcePictTypeLinear)
352.9776 ++			return gen4_channel_init_linear(sna, picture, channel,
352.9777 ++							x, y,
352.9778 ++							w, h,
352.9779 ++							dst_x, dst_y);
352.9780 ++
352.9781 ++		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
352.9782 ++		ret = -1;
352.9783 ++		if (!precise)
352.9784 ++			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
352.9785 ++								      x, y, w, h, dst_x, dst_y);
352.9786 ++		if (ret == -1)
352.9787 ++			ret = sna_render_picture_fixup(sna, picture, channel,
352.9788 ++						       x, y, w, h, dst_x, dst_y);
352.9789 ++		return ret;
352.9790 ++	}
352.9791 ++
352.9792 ++	if (picture->alphaMap) {
352.9793 ++		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
352.9794 ++		return sna_render_picture_fixup(sna, picture, channel,
352.9795 ++						x, y, w, h, dst_x, dst_y);
352.9796 ++	}
352.9797 ++
352.9798 ++	if (!gen9_check_repeat(picture))
352.9799 ++		return sna_render_picture_fixup(sna, picture, channel,
352.9800 ++						x, y, w, h, dst_x, dst_y);
352.9801 ++
352.9802 ++	if (!gen9_check_filter(picture))
352.9803 ++		return sna_render_picture_fixup(sna, picture, channel,
352.9804 ++						x, y, w, h, dst_x, dst_y);
352.9805 ++
352.9806 ++	channel->repeat = picture->repeat ? picture->repeatType : RepeatNone;
352.9807 ++	channel->filter = picture->filter;
352.9808 ++
352.9809 ++	pixmap = get_drawable_pixmap(picture->pDrawable);
352.9810 ++	get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy);
352.9811 ++
352.9812 ++	x += dx + picture->pDrawable->x;
352.9813 ++	y += dy + picture->pDrawable->y;
352.9814 ++
352.9815 ++	channel->is_affine = sna_transform_is_affine(picture->transform);
352.9816 ++	if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) {
352.9817 ++		DBG(("%s: integer translation (%d, %d), removing\n",
352.9818 ++		     __FUNCTION__, dx, dy));
352.9819 ++		x += dx;
352.9820 ++		y += dy;
352.9821 ++		channel->transform = NULL;
352.9822 ++		channel->filter = PictFilterNearest;
352.9823 ++
352.9824 ++		if (channel->repeat ||
352.9825 ++		    (x >= 0 &&
352.9826 ++		     y >= 0 &&
352.9827 ++		     x + w <= pixmap->drawable.width &&
352.9828 ++		     y + h <= pixmap->drawable.height)) {
352.9829 ++			struct sna_pixmap *priv = sna_pixmap(pixmap);
352.9830 ++			if (priv && priv->clear) {
352.9831 ++				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
352.9832 ++				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
352.9833 ++			}
352.9834 ++		}
352.9835 ++	} else
352.9836 ++		channel->transform = picture->transform;
352.9837 ++
352.9838 ++	channel->pict_format = picture->format;
352.9839 ++	channel->card_format = gen9_get_card_format(picture->format);
352.9840 ++	if (channel->card_format == (unsigned)-1)
352.9841 ++		return sna_render_picture_convert(sna, picture, channel, pixmap,
352.9842 ++						  x, y, w, h, dst_x, dst_y,
352.9843 ++						  false);
352.9844 ++
352.9845 ++	if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
352.9846 ++		DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__,
352.9847 ++		     pixmap->drawable.width, pixmap->drawable.height));
352.9848 ++		return sna_render_picture_extract(sna, picture, channel,
352.9849 ++						  x, y, w, h, dst_x, dst_y);
352.9850 ++	}
352.9851 ++
352.9852 ++	return sna_render_pixmap_bo(sna, channel, pixmap,
352.9853 ++				    x, y, w, h, dst_x, dst_y);
352.9854 ++}
352.9855 ++
352.9856 ++inline static bool gen9_composite_channel_convert(struct sna_composite_channel *channel)
352.9857 ++{
352.9858 ++	if (unaligned(channel->bo, PICT_FORMAT_BPP(channel->pict_format)))
352.9859 ++		return false;
352.9860 ++
352.9861 ++	channel->repeat = gen9_repeat(channel->repeat);
352.9862 ++	channel->filter = gen9_filter(channel->filter);
352.9863 ++	if (channel->card_format == (unsigned)-1)
352.9864 ++		channel->card_format = gen9_get_card_format(channel->pict_format);
352.9865 ++	assert(channel->card_format != (unsigned)-1);
352.9866 ++
352.9867 ++	return true;
352.9868 ++}
352.9869 ++
352.9870 ++static void gen9_render_composite_done(struct sna *sna,
352.9871 ++				       const struct sna_composite_op *op)
352.9872 ++{
352.9873 ++	if (sna->render.vertex_offset) {
352.9874 ++		gen8_vertex_flush(sna);
352.9875 ++		gen9_magic_ca_pass(sna, op);
352.9876 ++	}
352.9877 ++
352.9878 ++	if (op->mask.bo)
352.9879 ++		kgem_bo_destroy(&sna->kgem, op->mask.bo);
352.9880 ++	if (op->src.bo)
352.9881 ++		kgem_bo_destroy(&sna->kgem, op->src.bo);
352.9882 ++
352.9883 ++	sna_render_composite_redirect_done(sna, op);
352.9884 ++}
352.9885 ++
352.9886 ++inline static bool
352.9887 ++gen9_composite_set_target(struct sna *sna,
352.9888 ++			  struct sna_composite_op *op,
352.9889 ++			  PicturePtr dst,
352.9890 ++			  int x, int y, int w, int h,
352.9891 ++			  bool partial)
352.9892 ++{
352.9893 ++	BoxRec box;
352.9894 ++	unsigned int hint;
352.9895 ++
352.9896 ++	DBG(("%s: (%d, %d)x(%d, %d), partial?=%d\n", __FUNCTION__, x, y, w, h, partial));
352.9897 ++
352.9898 ++	op->dst.pixmap = get_drawable_pixmap(dst->pDrawable);
352.9899 ++	op->dst.format = dst->format;
352.9900 ++	op->dst.width  = op->dst.pixmap->drawable.width;
352.9901 ++	op->dst.height = op->dst.pixmap->drawable.height;
352.9902 ++
352.9903 ++	if (w | h) {
352.9904 ++		assert(w && h);
352.9905 ++		box.x1 = x;
352.9906 ++		box.y1 = y;
352.9907 ++		box.x2 = x + w;
352.9908 ++		box.y2 = y + h;
352.9909 ++	} else
352.9910 ++		sna_render_picture_extents(dst, &box);
352.9911 ++
352.9912 ++	hint = PREFER_GPU | RENDER_GPU;
352.9913 ++	if (!need_tiling(sna, op->dst.width, op->dst.height))
352.9914 ++		hint |= FORCE_GPU;
352.9915 ++	if (!partial) {
352.9916 ++		hint |= IGNORE_DAMAGE;
352.9917 ++		if (w == op->dst.width && h == op->dst.height)
352.9918 ++			hint |= REPLACES;
352.9919 ++	}
352.9920 ++
352.9921 ++	op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage);
352.9922 ++	if (op->dst.bo == NULL)
352.9923 ++		return false;
352.9924 ++
352.9925 ++	assert(!op->damage || !DAMAGE_IS_ALL(*op->damage));
352.9926 ++
352.9927 ++	if (unaligned(op->dst.bo, dst->pDrawable->bitsPerPixel))
352.9928 ++		return false;
352.9929 ++
352.9930 ++	if (hint & REPLACES) {
352.9931 ++		struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap);
352.9932 ++		kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
352.9933 ++	}
352.9934 ++
352.9935 ++	get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
352.9936 ++			    &op->dst.x, &op->dst.y);
352.9937 ++
352.9938 ++	DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n",
352.9939 ++	     __FUNCTION__,
352.9940 ++	     op->dst.pixmap->drawable.serialNumber, (int)op->dst.format,
352.9941 ++	     op->dst.width, op->dst.height,
352.9942 ++	     op->dst.bo->pitch,
352.9943 ++	     op->dst.x, op->dst.y,
352.9944 ++	     op->damage ? *op->damage : (void *)-1));
352.9945 ++
352.9946 ++	assert(op->dst.bo->proxy == NULL);
352.9947 ++
352.9948 ++	if (too_large(op->dst.width, op->dst.height) &&
352.9949 ++	    !sna_render_composite_redirect(sna, op, x, y, w, h, partial))
352.9950 ++		return false;
352.9951 ++
352.9952 ++	return true;
352.9953 ++}
352.9954 ++
352.9955 ++static bool
352.9956 ++try_blt(struct sna *sna,
352.9957 ++	uint8_t op,
352.9958 ++	PicturePtr src,
352.9959 ++	PicturePtr mask,
352.9960 ++	PicturePtr dst,
352.9961 ++	int16_t src_x, int16_t src_y,
352.9962 ++	int16_t msk_x, int16_t msk_y,
352.9963 ++	int16_t dst_x, int16_t dst_y,
352.9964 ++	int16_t width, int16_t height,
352.9965 ++	unsigned flags,
352.9966 ++	struct sna_composite_op *tmp)
352.9967 ++{
352.9968 ++	struct kgem_bo *bo;
352.9969 ++
352.9970 ++	if (sna->kgem.mode == KGEM_BLT) {
352.9971 ++		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.9972 ++		goto execute;
352.9973 ++	}
352.9974 ++
352.9975 ++	if (too_large(width, height)) {
352.9976 ++		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
352.9977 ++		     __FUNCTION__, width, height));
352.9978 ++		goto execute;
352.9979 ++	}
352.9980 ++
352.9981 ++	bo = __sna_drawable_peek_bo(dst->pDrawable);
352.9982 ++	if (bo == NULL)
352.9983 ++		goto execute;
352.9984 ++
352.9985 ++	if (untiled_tlb_miss(bo))
352.9986 ++		goto execute;
352.9987 ++
352.9988 ++	if (bo->rq) {
352.9989 ++		if (RQ_IS_BLT(bo->rq))
352.9990 ++			goto execute;
352.9991 ++
352.9992 ++		return false;
352.9993 ++	}
352.9994 ++
352.9995 ++	if (bo->tiling == I915_TILING_Y)
352.9996 ++		goto upload;
352.9997 ++
352.9998 ++	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
352.9999 ++		goto execute;
352.10000 ++
352.10001 ++	if (src->pDrawable == dst->pDrawable &&
352.10002 ++	    (sna->render_state.gt < 3 || width*height < 1024) &&
352.10003 ++	    can_switch_to_blt(sna, bo, 0))
352.10004 ++		goto execute;
352.10005 ++
352.10006 ++	if (src->pDrawable) {
352.10007 ++		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
352.10008 ++		if (s == NULL)
352.10009 ++			goto upload;
352.10010 ++
352.10011 ++		if (prefer_blt_bo(sna, s, bo))
352.10012 ++			goto execute;
352.10013 ++	}
352.10014 ++
352.10015 ++	if (sna->kgem.ring == KGEM_BLT) {
352.10016 ++		DBG(("%s: already performing BLT\n", __FUNCTION__));
352.10017 ++		goto execute;
352.10018 ++	}
352.10019 ++
352.10020 ++upload:
352.10021 ++	flags |= COMPOSITE_UPLOAD;
352.10022 ++execute:
352.10023 ++	return sna_blt_composite(sna, op,
352.10024 ++				 src, dst,
352.10025 ++				 src_x, src_y,
352.10026 ++				 dst_x, dst_y,
352.10027 ++				 width, height,
352.10028 ++				 flags, tmp);
352.10029 ++}
352.10030 ++
352.10031 ++static bool
352.10032 ++check_gradient(PicturePtr picture, bool precise)
352.10033 ++{
352.10034 ++	if (picture->pDrawable)
352.10035 ++		return false;
352.10036 ++
352.10037 ++	switch (picture->pSourcePict->type) {
352.10038 ++	case SourcePictTypeSolidFill:
352.10039 ++	case SourcePictTypeLinear:
352.10040 ++		return false;
352.10041 ++	default:
352.10042 ++		return precise;
352.10043 ++	}
352.10044 ++}
352.10045 ++
352.10046 ++static bool
352.10047 ++has_alphamap(PicturePtr p)
352.10048 ++{
352.10049 ++	return p->alphaMap != NULL;
352.10050 ++}
352.10051 ++
352.10052 ++static bool
352.10053 ++need_upload(PicturePtr p)
352.10054 ++{
352.10055 ++	return p->pDrawable && unattached(p->pDrawable) && untransformed(p);
352.10056 ++}
352.10057 ++
352.10058 ++static bool
352.10059 ++source_is_busy(PixmapPtr pixmap)
352.10060 ++{
352.10061 ++	struct sna_pixmap *priv = sna_pixmap(pixmap);
352.10062 ++	if (priv == NULL || priv->clear)
352.10063 ++		return false;
352.10064 ++
352.10065 ++	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
352.10066 ++		return true;
352.10067 ++
352.10068 ++	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
352.10069 ++		return true;
352.10070 ++
352.10071 ++	return priv->gpu_damage && !priv->cpu_damage;
352.10072 ++}
352.10073 ++
352.10074 ++static bool
352.10075 ++source_fallback(PicturePtr p, PixmapPtr pixmap, bool precise)
352.10076 ++{
352.10077 ++	if (sna_picture_is_solid(p, NULL))
352.10078 ++		return false;
352.10079 ++
352.10080 ++	if (p->pSourcePict)
352.10081 ++		return check_gradient(p, precise);
352.10082 ++
352.10083 ++	if (!gen9_check_repeat(p) || !gen9_check_format(p->format))
352.10084 ++		return true;
352.10085 ++
352.10086 ++	if (pixmap && source_is_busy(pixmap))
352.10087 ++		return false;
352.10088 ++
352.10089 ++	return has_alphamap(p) || !gen9_check_filter(p) || need_upload(p);
352.10090 ++}
352.10091 ++
352.10092 ++static bool
352.10093 ++gen9_composite_fallback(struct sna *sna,
352.10094 ++			PicturePtr src,
352.10095 ++			PicturePtr mask,
352.10096 ++			PicturePtr dst)
352.10097 ++{
352.10098 ++	PixmapPtr src_pixmap;
352.10099 ++	PixmapPtr mask_pixmap;
352.10100 ++	PixmapPtr dst_pixmap;
352.10101 ++	bool src_fallback, mask_fallback;
352.10102 ++
352.10103 ++	if (!gen9_check_dst_format(dst->format)) {
352.10104 ++		DBG(("%s: unknown destination format: %d\n",
352.10105 ++		     __FUNCTION__, dst->format));
352.10106 ++		return true;
352.10107 ++	}
352.10108 ++
352.10109 ++	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
352.10110 ++
352.10111 ++	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
352.10112 ++	src_fallback = source_fallback(src, src_pixmap,
352.10113 ++				       dst->polyMode == PolyModePrecise);
352.10114 ++
352.10115 ++	if (mask) {
352.10116 ++		mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL;
352.10117 ++		mask_fallback = source_fallback(mask, mask_pixmap,
352.10118 ++						dst->polyMode == PolyModePrecise);
352.10119 ++	} else {
352.10120 ++		mask_pixmap = NULL;
352.10121 ++		mask_fallback = false;
352.10122 ++	}
352.10123 ++
352.10124 ++	/* If we are using the destination as a source and need to
352.10125 ++	 * readback in order to upload the source, do it all
352.10126 ++	 * on the cpu.
352.10127 ++	 */
352.10128 ++	if (src_pixmap == dst_pixmap && src_fallback) {
352.10129 ++		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
352.10130 ++		return true;
352.10131 ++	}
352.10132 ++	if (mask_pixmap == dst_pixmap && mask_fallback) {
352.10133 ++		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
352.10134 ++		return true;
352.10135 ++	}
352.10136 ++
352.10137 ++	/* If anything is on the GPU, push everything out to the GPU */
352.10138 ++	if (dst_use_gpu(dst_pixmap)) {
352.10139 ++		DBG(("%s: dst is already on the GPU, try to use GPU\n",
352.10140 ++		     __FUNCTION__));
352.10141 ++		return false;
352.10142 ++	}
352.10143 ++
352.10144 ++	if (src_pixmap && !src_fallback) {
352.10145 ++		DBG(("%s: src is already on the GPU, try to use GPU\n",
352.10146 ++		     __FUNCTION__));
352.10147 ++		return false;
352.10148 ++	}
352.10149 ++	if (mask_pixmap && !mask_fallback) {
352.10150 ++		DBG(("%s: mask is already on the GPU, try to use GPU\n",
352.10151 ++		     __FUNCTION__));
352.10152 ++		return false;
352.10153 ++	}
352.10154 ++
352.10155 ++	/* However if the dst is not on the GPU and we need to
352.10156 ++	 * render one of the sources using the CPU, we may
352.10157 ++	 * as well do the entire operation in place onthe CPU.
352.10158 ++	 */
352.10159 ++	if (src_fallback) {
352.10160 ++		DBG(("%s: dst is on the CPU and src will fallback\n",
352.10161 ++		     __FUNCTION__));
352.10162 ++		return true;
352.10163 ++	}
352.10164 ++
352.10165 ++	if (mask && mask_fallback) {
352.10166 ++		DBG(("%s: dst is on the CPU and mask will fallback\n",
352.10167 ++		     __FUNCTION__));
352.10168 ++		return true;
352.10169 ++	}
352.10170 ++
352.10171 ++	if (too_large(dst_pixmap->drawable.width,
352.10172 ++		      dst_pixmap->drawable.height) &&
352.10173 ++	    dst_is_cpu(dst_pixmap)) {
352.10174 ++		DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__));
352.10175 ++		return true;
352.10176 ++	}
352.10177 ++
352.10178 ++	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
352.10179 ++	     __FUNCTION__));
352.10180 ++	return dst_use_cpu(dst_pixmap);
352.10181 ++}
352.10182 ++
352.10183 ++static int
352.10184 ++reuse_source(struct sna *sna,
352.10185 ++	     PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
352.10186 ++	     PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
352.10187 ++{
352.10188 ++	uint32_t color;
352.10189 ++
352.10190 ++	if (src_x != msk_x || src_y != msk_y)
352.10191 ++		return false;
352.10192 ++
352.10193 ++	if (src == mask) {
352.10194 ++		DBG(("%s: mask is source\n", __FUNCTION__));
352.10195 ++		*mc = *sc;
352.10196 ++		mc->bo = kgem_bo_reference(mc->bo);
352.10197 ++		return true;
352.10198 ++	}
352.10199 ++
352.10200 ++	if (sna_picture_is_solid(mask, &color))
352.10201 ++		return gen4_channel_init_solid(sna, mc, color);
352.10202 ++
352.10203 ++	if (sc->is_solid)
352.10204 ++		return false;
352.10205 ++
352.10206 ++	if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
352.10207 ++		return false;
352.10208 ++
352.10209 ++	DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
352.10210 ++
352.10211 ++	if (!sna_transform_equal(src->transform, mask->transform))
352.10212 ++		return false;
352.10213 ++
352.10214 ++	if (!sna_picture_alphamap_equal(src, mask))
352.10215 ++		return false;
352.10216 ++
352.10217 ++	if (!gen9_check_repeat(mask))
352.10218 ++		return false;
352.10219 ++
352.10220 ++	if (!gen9_check_filter(mask))
352.10221 ++		return false;
352.10222 ++
352.10223 ++	if (!gen9_check_format(mask->format))
352.10224 ++		return false;
352.10225 ++
352.10226 ++	DBG(("%s: reusing source channel for mask with a twist\n",
352.10227 ++	     __FUNCTION__));
352.10228 ++
352.10229 ++	*mc = *sc;
352.10230 ++	mc->repeat = gen9_repeat(mask->repeat ? mask->repeatType : RepeatNone);
352.10231 ++	mc->filter = gen9_filter(mask->filter);
352.10232 ++	mc->pict_format = mask->format;
352.10233 ++	mc->card_format = gen9_get_card_format(mask->format);
352.10234 ++	mc->bo = kgem_bo_reference(mc->bo);
352.10235 ++	return true;
352.10236 ++}
352.10237 ++
352.10238 ++static bool
352.10239 ++gen9_render_composite(struct sna *sna,
352.10240 ++		      uint8_t op,
352.10241 ++		      PicturePtr src,
352.10242 ++		      PicturePtr mask,
352.10243 ++		      PicturePtr dst,
352.10244 ++		      int16_t src_x, int16_t src_y,
352.10245 ++		      int16_t msk_x, int16_t msk_y,
352.10246 ++		      int16_t dst_x, int16_t dst_y,
352.10247 ++		      int16_t width, int16_t height,
352.10248 ++		      unsigned flags,
352.10249 ++		      struct sna_composite_op *tmp)
352.10250 ++{
352.10251 ++	if (op >= ARRAY_SIZE(gen9_blend_op))
352.10252 ++		return false;
352.10253 ++
352.10254 ++	DBG(("%s: %dx%d, current mode=%d/%d\n", __FUNCTION__,
352.10255 ++	     width, height, sna->kgem.mode, sna->kgem.ring));
352.10256 ++
352.10257 ++	if (mask == NULL &&
352.10258 ++	    try_blt(sna, op,
352.10259 ++		    src, mask, dst,
352.10260 ++		    src_x, src_y,
352.10261 ++		    msk_x, msk_y,
352.10262 ++		    dst_x, dst_y,
352.10263 ++		    width, height,
352.10264 ++		    flags, tmp))
352.10265 ++		return true;
352.10266 ++
352.10267 ++	if (gen9_composite_fallback(sna, src, mask, dst))
352.10268 ++		goto fallback;
352.10269 ++
352.10270 ++	if (need_tiling(sna, width, height))
352.10271 ++		return sna_tiling_composite(op, src, mask, dst,
352.10272 ++					    src_x, src_y,
352.10273 ++					    msk_x, msk_y,
352.10274 ++					    dst_x, dst_y,
352.10275 ++					    width, height,
352.10276 ++					    tmp);
352.10277 ++
352.10278 ++	if (op == PictOpClear && src == sna->clear)
352.10279 ++		op = PictOpSrc;
352.10280 ++	tmp->op = op;
352.10281 ++	if (!gen9_composite_set_target(sna, tmp, dst,
352.10282 ++				       dst_x, dst_y, width, height,
352.10283 ++				       flags & COMPOSITE_PARTIAL || op > PictOpSrc))
352.10284 ++		goto fallback;
352.10285 ++
352.10286 ++	switch (gen9_composite_picture(sna, src, &tmp->src,
352.10287 ++				       src_x, src_y,
352.10288 ++				       width, height,
352.10289 ++				       dst_x, dst_y,
352.10290 ++				       dst->polyMode == PolyModePrecise)) {
352.10291 ++	case -1:
352.10292 ++		goto cleanup_dst;
352.10293 ++	case 0:
352.10294 ++		if (!gen4_channel_init_solid(sna, &tmp->src, 0))
352.10295 ++			goto cleanup_dst;
352.10296 ++		/* fall through to fixup */
352.10297 ++	case 1:
352.10298 ++		/* Did we just switch rings to prepare the source? */
352.10299 ++		if (mask == NULL &&
352.10300 ++		    (prefer_blt_composite(sna, tmp) ||
352.10301 ++		     unaligned(tmp->src.bo, PICT_FORMAT_BPP(tmp->src.pict_format))) &&
352.10302 ++		    sna_blt_composite__convert(sna,
352.10303 ++					       dst_x, dst_y, width, height,
352.10304 ++					       tmp))
352.10305 ++			return true;
352.10306 ++
352.10307 ++		if (!gen9_composite_channel_convert(&tmp->src))
352.10308 ++			goto cleanup_src;
352.10309 ++
352.10310 ++		break;
352.10311 ++	}
352.10312 ++
352.10313 ++	tmp->is_affine = tmp->src.is_affine;
352.10314 ++	tmp->has_component_alpha = false;
352.10315 ++	tmp->need_magic_ca_pass = false;
352.10316 ++
352.10317 ++	tmp->mask.bo = NULL;
352.10318 ++	tmp->mask.filter = SAMPLER_FILTER_NEAREST;
352.10319 ++	tmp->mask.repeat = SAMPLER_EXTEND_NONE;
352.10320 ++
352.10321 ++	if (mask) {
352.10322 ++		if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
352.10323 ++			tmp->has_component_alpha = true;
352.10324 ++
352.10325 ++			/* Check if it's component alpha that relies on a source alpha and on
352.10326 ++			 * the source value.  We can only get one of those into the single
352.10327 ++			 * source value that we get to blend with.
352.10328 ++			 */
352.10329 ++			if (gen9_blend_op[op].src_alpha &&
352.10330 ++			    (gen9_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
352.10331 ++				if (op != PictOpOver)
352.10332 ++					goto cleanup_src;
352.10333 ++
352.10334 ++				tmp->need_magic_ca_pass = true;
352.10335 ++				tmp->op = PictOpOutReverse;
352.10336 ++			}
352.10337 ++		}
352.10338 ++
352.10339 ++		if (!reuse_source(sna,
352.10340 ++				  src, &tmp->src, src_x, src_y,
352.10341 ++				  mask, &tmp->mask, msk_x, msk_y)) {
352.10342 ++			switch (gen9_composite_picture(sna, mask, &tmp->mask,
352.10343 ++						       msk_x, msk_y,
352.10344 ++						       width, height,
352.10345 ++						       dst_x, dst_y,
352.10346 ++						       dst->polyMode == PolyModePrecise)) {
352.10347 ++			case -1:
352.10348 ++				goto cleanup_src;
352.10349 ++			case 0:
352.10350 ++				if (!gen4_channel_init_solid(sna, &tmp->mask, 0))
352.10351 ++					goto cleanup_src;
352.10352 ++				/* fall through to fixup */
352.10353 ++			case 1:
352.10354 ++				if (!gen9_composite_channel_convert(&tmp->mask))
352.10355 ++					goto cleanup_mask;
352.10356 ++				break;
352.10357 ++			}
352.10358 ++		}
352.10359 ++
352.10360 ++		tmp->is_affine &= tmp->mask.is_affine;
352.10361 ++	}
352.10362 ++
352.10363 ++	tmp->u.gen9.flags =
352.10364 ++		GEN9_SET_FLAGS(SAMPLER_OFFSET(tmp->src.filter,
352.10365 ++					      tmp->src.repeat,
352.10366 ++					      tmp->mask.filter,
352.10367 ++					      tmp->mask.repeat),
352.10368 ++			       gen9_get_blend(tmp->op,
352.10369 ++					      tmp->has_component_alpha,
352.10370 ++					      tmp->dst.format),
352.10371 ++			       gen9_choose_composite_kernel(tmp->op,
352.10372 ++							    tmp->mask.bo != NULL,
352.10373 ++							    tmp->has_component_alpha,
352.10374 ++							    tmp->is_affine),
352.10375 ++			       gen4_choose_composite_emitter(sna, tmp));
352.10376 ++
352.10377 ++	tmp->blt   = gen9_render_composite_blt;
352.10378 ++	tmp->box   = gen9_render_composite_box;
352.10379 ++	tmp->boxes = gen9_render_composite_boxes__blt;
352.10380 ++	if (tmp->emit_boxes){
352.10381 ++		tmp->boxes = gen9_render_composite_boxes;
352.10382 ++		tmp->thread_boxes = gen9_render_composite_boxes__thread;
352.10383 ++	}
352.10384 ++	tmp->done  = gen9_render_composite_done;
352.10385 ++
352.10386 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo);
352.10387 ++	if (!kgem_check_bo(&sna->kgem,
352.10388 ++			   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
352.10389 ++			   NULL)) {
352.10390 ++		kgem_submit(&sna->kgem);
352.10391 ++		if (!kgem_check_bo(&sna->kgem,
352.10392 ++				   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
352.10393 ++				   NULL))
352.10394 ++			goto cleanup_mask;
352.10395 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.10396 ++	}
352.10397 ++
352.10398 ++	gen9_align_vertex(sna, tmp);
352.10399 ++	gen9_emit_composite_state(sna, tmp);
352.10400 ++	return true;
352.10401 ++
352.10402 ++cleanup_mask:
352.10403 ++	if (tmp->mask.bo) {
352.10404 ++		kgem_bo_destroy(&sna->kgem, tmp->mask.bo);
352.10405 ++		tmp->mask.bo = NULL;
352.10406 ++	}
352.10407 ++cleanup_src:
352.10408 ++	if (tmp->src.bo) {
352.10409 ++		kgem_bo_destroy(&sna->kgem, tmp->src.bo);
352.10410 ++		tmp->src.bo = NULL;
352.10411 ++	}
352.10412 ++cleanup_dst:
352.10413 ++	if (tmp->redirect.real_bo) {
352.10414 ++		kgem_bo_destroy(&sna->kgem, tmp->dst.bo);
352.10415 ++		tmp->redirect.real_bo = NULL;
352.10416 ++	}
352.10417 ++fallback:
352.10418 ++	return (mask == NULL &&
352.10419 ++		sna_blt_composite(sna, op,
352.10420 ++				  src, dst,
352.10421 ++				  src_x, src_y,
352.10422 ++				  dst_x, dst_y,
352.10423 ++				  width, height,
352.10424 ++				  flags | COMPOSITE_FALLBACK, tmp));
352.10425 ++}
352.10426 ++
352.10427 ++#if !NO_COMPOSITE_SPANS
352.10428 ++fastcall static void
352.10429 ++gen9_render_composite_spans_box(struct sna *sna,
352.10430 ++				const struct sna_composite_spans_op *op,
352.10431 ++				const BoxRec *box, float opacity)
352.10432 ++{
352.10433 ++	DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n",
352.10434 ++	     __FUNCTION__,
352.10435 ++	     op->base.src.offset[0], op->base.src.offset[1],
352.10436 ++	     opacity,
352.10437 ++	     op->base.dst.x, op->base.dst.y,
352.10438 ++	     box->x1, box->y1,
352.10439 ++	     box->x2 - box->x1,
352.10440 ++	     box->y2 - box->y1));
352.10441 ++
352.10442 ++	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_composite_state);
352.10443 ++	op->prim_emit(sna, op, box, opacity);
352.10444 ++}
352.10445 ++
352.10446 ++static void
352.10447 ++gen9_render_composite_spans_boxes(struct sna *sna,
352.10448 ++				  const struct sna_composite_spans_op *op,
352.10449 ++				  const BoxRec *box, int nbox,
352.10450 ++				  float opacity)
352.10451 ++{
352.10452 ++	DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
352.10453 ++	     __FUNCTION__, nbox,
352.10454 ++	     op->base.src.offset[0], op->base.src.offset[1],
352.10455 ++	     opacity,
352.10456 ++	     op->base.dst.x, op->base.dst.y));
352.10457 ++
352.10458 ++	do {
352.10459 ++		int nbox_this_time;
352.10460 ++
352.10461 ++		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
352.10462 ++						     gen9_emit_composite_state);
352.10463 ++		nbox -= nbox_this_time;
352.10464 ++
352.10465 ++		do {
352.10466 ++			DBG(("  %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
352.10467 ++			     box->x1, box->y1,
352.10468 ++			     box->x2 - box->x1,
352.10469 ++			     box->y2 - box->y1));
352.10470 ++
352.10471 ++			op->prim_emit(sna, op, box++, opacity);
352.10472 ++		} while (--nbox_this_time);
352.10473 ++	} while (nbox);
352.10474 ++}
352.10475 ++
352.10476 ++fastcall static void
352.10477 ++gen9_render_composite_spans_boxes__thread(struct sna *sna,
352.10478 ++					  const struct sna_composite_spans_op *op,
352.10479 ++					  const struct sna_opacity_box *box,
352.10480 ++					  int nbox)
352.10481 ++{
352.10482 ++	DBG(("%s: nbox=%d, src=+(%d, %d), dst=+(%d, %d)\n",
352.10483 ++	     __FUNCTION__, nbox,
352.10484 ++	     op->base.src.offset[0], op->base.src.offset[1],
352.10485 ++	     op->base.dst.x, op->base.dst.y));
352.10486 ++
352.10487 ++	sna_vertex_lock(&sna->render);
352.10488 ++	do {
352.10489 ++		int nbox_this_time;
352.10490 ++		float *v;
352.10491 ++
352.10492 ++		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
352.10493 ++						     gen9_emit_composite_state);
352.10494 ++		assert(nbox_this_time);
352.10495 ++		nbox -= nbox_this_time;
352.10496 ++
352.10497 ++		v = sna->render.vertices + sna->render.vertex_used;
352.10498 ++		sna->render.vertex_used += nbox_this_time * op->base.floats_per_rect;
352.10499 ++
352.10500 ++		sna_vertex_acquire__locked(&sna->render);
352.10501 ++		sna_vertex_unlock(&sna->render);
352.10502 ++
352.10503 ++		op->emit_boxes(op, box, nbox_this_time, v);
352.10504 ++		box += nbox_this_time;
352.10505 ++
352.10506 ++		sna_vertex_lock(&sna->render);
352.10507 ++		sna_vertex_release__locked(&sna->render);
352.10508 ++	} while (nbox);
352.10509 ++	sna_vertex_unlock(&sna->render);
352.10510 ++}
352.10511 ++
352.10512 ++fastcall static void
352.10513 ++gen9_render_composite_spans_done(struct sna *sna,
352.10514 ++				 const struct sna_composite_spans_op *op)
352.10515 ++{
352.10516 ++	if (sna->render.vertex_offset)
352.10517 ++		gen8_vertex_flush(sna);
352.10518 ++
352.10519 ++	DBG(("%s()\n", __FUNCTION__));
352.10520 ++
352.10521 ++	if (op->base.src.bo)
352.10522 ++		kgem_bo_destroy(&sna->kgem, op->base.src.bo);
352.10523 ++
352.10524 ++	sna_render_composite_redirect_done(sna, &op->base);
352.10525 ++}
352.10526 ++
352.10527 ++static bool
352.10528 ++gen9_check_composite_spans(struct sna *sna,
352.10529 ++			   uint8_t op, PicturePtr src, PicturePtr dst,
352.10530 ++			   int16_t width, int16_t height, unsigned flags)
352.10531 ++{
352.10532 ++	if (op >= ARRAY_SIZE(gen9_blend_op))
352.10533 ++		return false;
352.10534 ++
352.10535 ++	if (gen9_composite_fallback(sna, src, NULL, dst))
352.10536 ++		return false;
352.10537 ++
352.10538 ++	if (need_tiling(sna, width, height) &&
352.10539 ++	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
352.10540 ++		DBG(("%s: fallback, tiled operation not on GPU\n",
352.10541 ++		     __FUNCTION__));
352.10542 ++		return false;
352.10543 ++	}
352.10544 ++
352.10545 ++	return true;
352.10546 ++}
352.10547 ++
352.10548 ++static bool
352.10549 ++gen9_render_composite_spans(struct sna *sna,
352.10550 ++			    uint8_t op,
352.10551 ++			    PicturePtr src,
352.10552 ++			    PicturePtr dst,
352.10553 ++			    int16_t src_x,  int16_t src_y,
352.10554 ++			    int16_t dst_x,  int16_t dst_y,
352.10555 ++			    int16_t width,  int16_t height,
352.10556 ++			    unsigned flags,
352.10557 ++			    struct sna_composite_spans_op *tmp)
352.10558 ++{
352.10559 ++	DBG(("%s: %dx%d with flags=%x, current mode=%d\n", __FUNCTION__,
352.10560 ++	     width, height, flags, sna->kgem.ring));
352.10561 ++
352.10562 ++	assert(gen9_check_composite_spans(sna, op, src, dst, width, height, flags));
352.10563 ++
352.10564 ++	if (need_tiling(sna, width, height)) {
352.10565 ++		DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n",
352.10566 ++		     __FUNCTION__, width, height));
352.10567 ++		return sna_tiling_composite_spans(op, src, dst,
352.10568 ++						  src_x, src_y, dst_x, dst_y,
352.10569 ++						  width, height, flags, tmp);
352.10570 ++	}
352.10571 ++
352.10572 ++	tmp->base.op = op;
352.10573 ++	if (!gen9_composite_set_target(sna, &tmp->base, dst,
352.10574 ++				       dst_x, dst_y, width, height, true))
352.10575 ++		return false;
352.10576 ++
352.10577 ++	switch (gen9_composite_picture(sna, src, &tmp->base.src,
352.10578 ++				       src_x, src_y,
352.10579 ++				       width, height,
352.10580 ++				       dst_x, dst_y,
352.10581 ++				       dst->polyMode == PolyModePrecise)) {
352.10582 ++	case -1:
352.10583 ++		goto cleanup_dst;
352.10584 ++	case 0:
352.10585 ++		if (!gen4_channel_init_solid(sna, &tmp->base.src, 0))
352.10586 ++			goto cleanup_dst;
352.10587 ++		/* fall through to fixup */
352.10588 ++	case 1:
352.10589 ++		if (!gen9_composite_channel_convert(&tmp->base.src))
352.10590 ++			goto cleanup_src;
352.10591 ++		break;
352.10592 ++	}
352.10593 ++	tmp->base.mask.bo = NULL;
352.10594 ++
352.10595 ++	tmp->base.is_affine = tmp->base.src.is_affine;
352.10596 ++	tmp->base.need_magic_ca_pass = false;
352.10597 ++
352.10598 ++	tmp->base.u.gen9.flags =
352.10599 ++		GEN9_SET_FLAGS(SAMPLER_OFFSET(tmp->base.src.filter,
352.10600 ++					      tmp->base.src.repeat,
352.10601 ++					      SAMPLER_FILTER_NEAREST,
352.10602 ++					      SAMPLER_EXTEND_PAD),
352.10603 ++			       gen9_get_blend(tmp->base.op, false, tmp->base.dst.format),
352.10604 ++			       GEN9_WM_KERNEL_OPACITY | !tmp->base.is_affine,
352.10605 ++			       gen4_choose_spans_emitter(sna, tmp));
352.10606 ++
352.10607 ++	tmp->box   = gen9_render_composite_spans_box;
352.10608 ++	tmp->boxes = gen9_render_composite_spans_boxes;
352.10609 ++	if (tmp->emit_boxes)
352.10610 ++		tmp->thread_boxes = gen9_render_composite_spans_boxes__thread;
352.10611 ++	tmp->done  = gen9_render_composite_spans_done;
352.10612 ++
352.10613 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->base.dst.bo);
352.10614 ++	if (!kgem_check_bo(&sna->kgem,
352.10615 ++			   tmp->base.dst.bo, tmp->base.src.bo,
352.10616 ++			   NULL)) {
352.10617 ++		kgem_submit(&sna->kgem);
352.10618 ++		if (!kgem_check_bo(&sna->kgem,
352.10619 ++				   tmp->base.dst.bo, tmp->base.src.bo,
352.10620 ++				   NULL))
352.10621 ++			goto cleanup_src;
352.10622 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.10623 ++	}
352.10624 ++
352.10625 ++	gen9_align_vertex(sna, &tmp->base);
352.10626 ++	gen9_emit_composite_state(sna, &tmp->base);
352.10627 ++	return true;
352.10628 ++
352.10629 ++cleanup_src:
352.10630 ++	if (tmp->base.src.bo)
352.10631 ++		kgem_bo_destroy(&sna->kgem, tmp->base.src.bo);
352.10632 ++cleanup_dst:
352.10633 ++	if (tmp->base.redirect.real_bo)
352.10634 ++		kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
352.10635 ++	return false;
352.10636 ++}
352.10637 ++#endif
352.10638 ++
352.10639 ++static void
352.10640 ++gen9_emit_copy_state(struct sna *sna,
352.10641 ++		     const struct sna_composite_op *op)
352.10642 ++{
352.10643 ++	uint32_t *binding_table;
352.10644 ++	uint16_t offset, dirty;
352.10645 ++
352.10646 ++	gen9_get_batch(sna, op);
352.10647 ++
352.10648 ++	binding_table = gen9_composite_get_binding_table(sna, &offset);
352.10649 ++
352.10650 ++	dirty = kgem_bo_is_dirty(op->dst.bo);
352.10651 ++
352.10652 ++	binding_table[0] =
352.10653 ++		gen9_bind_bo(sna,
352.10654 ++			     op->dst.bo, op->dst.width, op->dst.height,
352.10655 ++			     gen9_get_dest_format(op->dst.format),
352.10656 ++			     true);
352.10657 ++	binding_table[1] =
352.10658 ++		gen9_bind_bo(sna,
352.10659 ++			     op->src.bo, op->src.width, op->src.height,
352.10660 ++			     op->src.card_format,
352.10661 ++			     false);
352.10662 ++
352.10663 ++	if (sna->kgem.surface == offset &&
352.10664 ++	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table) {
352.10665 ++		sna->kgem.surface += SURFACE_DW;
352.10666 ++		offset = sna->render_state.gen9.surface_table;
352.10667 ++	}
352.10668 ++
352.10669 ++	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
352.10670 ++		dirty = 0;
352.10671 ++
352.10672 ++	assert(!GEN9_READS_DST(op->u.gen9.flags));
352.10673 ++	gen9_emit_state(sna, op, offset | dirty);
352.10674 ++}
352.10675 ++
352.10676 ++static inline bool
352.10677 ++prefer_blt_copy(struct sna *sna,
352.10678 ++		struct kgem_bo *src_bo,
352.10679 ++		struct kgem_bo *dst_bo,
352.10680 ++		unsigned flags)
352.10681 ++{
352.10682 ++	if (sna->kgem.mode == KGEM_BLT)
352.10683 ++		return true;
352.10684 ++
352.10685 ++	assert((flags & COPY_SYNC) == 0);
352.10686 ++
352.10687 ++	if (untiled_tlb_miss(src_bo) ||
352.10688 ++	    untiled_tlb_miss(dst_bo))
352.10689 ++		return true;
352.10690 ++
352.10691 ++	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
352.10692 ++		return false;
352.10693 ++
352.10694 ++	if (force_blt_ring(sna, dst_bo))
352.10695 ++		return true;
352.10696 ++
352.10697 ++	if ((flags & COPY_SMALL ||
352.10698 ++	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
352.10699 ++	    can_switch_to_blt(sna, dst_bo, flags))
352.10700 ++		return true;
352.10701 ++
352.10702 ++	if (kgem_bo_is_render(dst_bo) ||
352.10703 ++	    kgem_bo_is_render(src_bo))
352.10704 ++		return false;
352.10705 ++
352.10706 ++	if (flags & COPY_LAST &&
352.10707 ++	    sna->render_state.gt < 3 &&
352.10708 ++            can_switch_to_blt(sna, dst_bo, flags))
352.10709 ++		return true;
352.10710 ++
352.10711 ++	if (prefer_render_ring(sna, dst_bo))
352.10712 ++		return false;
352.10713 ++
352.10714 ++	if (!prefer_blt_ring(sna, dst_bo, flags))
352.10715 ++		return false;
352.10716 ++
352.10717 ++	return prefer_blt_bo(sna, src_bo, dst_bo);
352.10718 ++}
352.10719 ++
352.10720 ++static bool
352.10721 ++gen9_render_copy_boxes(struct sna *sna, uint8_t alu,
352.10722 ++		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
352.10723 ++		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
352.10724 ++		       const BoxRec *box, int n, unsigned flags)
352.10725 ++{
352.10726 ++	struct sna_composite_op tmp;
352.10727 ++	BoxRec extents;
352.10728 ++
352.10729 ++	DBG(("%s (%d, %d)->(%d, %d) x %d, alu=%x, flags=%x, self-copy=%d, overlaps? %d\n",
352.10730 ++	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n, alu, flags,
352.10731 ++	     src_bo == dst_bo,
352.10732 ++	     overlaps(sna,
352.10733 ++		      src_bo, src_dx, src_dy,
352.10734 ++		      dst_bo, dst_dx, dst_dy,
352.10735 ++		      box, n, flags, &extents)));
352.10736 ++
352.10737 ++	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
352.10738 ++	    sna_blt_compare_depth(src, dst) &&
352.10739 ++	    sna_blt_copy_boxes(sna, alu,
352.10740 ++			       src_bo, src_dx, src_dy,
352.10741 ++			       dst_bo, dst_dx, dst_dy,
352.10742 ++			       dst->bitsPerPixel,
352.10743 ++			       box, n))
352.10744 ++		return true;
352.10745 ++
352.10746 ++	if (!(alu == GXcopy || alu == GXclear) ||
352.10747 ++	    unaligned(src_bo, src->bitsPerPixel) ||
352.10748 ++	    unaligned(dst_bo, dst->bitsPerPixel)) {
352.10749 ++fallback_blt:
352.10750 ++		DBG(("%s: fallback blt\n", __FUNCTION__));
352.10751 ++		if (!sna_blt_compare_depth(src, dst))
352.10752 ++			return false;
352.10753 ++
352.10754 ++		return sna_blt_copy_boxes_fallback(sna, alu,
352.10755 ++						   src, src_bo, src_dx, src_dy,
352.10756 ++						   dst, dst_bo, dst_dx, dst_dy,
352.10757 ++						   box, n);
352.10758 ++	}
352.10759 ++
352.10760 ++	if (overlaps(sna,
352.10761 ++		     src_bo, src_dx, src_dy,
352.10762 ++		     dst_bo, dst_dx, dst_dy,
352.10763 ++		     box, n, flags,
352.10764 ++		     &extents)) {
352.10765 ++		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
352.10766 ++
352.10767 ++		if ((big || !prefer_render_ring(sna, dst_bo)) &&
352.10768 ++		    sna_blt_copy_boxes(sna, alu,
352.10769 ++				       src_bo, src_dx, src_dy,
352.10770 ++				       dst_bo, dst_dx, dst_dy,
352.10771 ++				       dst->bitsPerPixel,
352.10772 ++				       box, n))
352.10773 ++			return true;
352.10774 ++
352.10775 ++		if (big)
352.10776 ++			goto fallback_blt;
352.10777 ++
352.10778 ++		assert(src_bo == dst_bo);
352.10779 ++		assert(src->depth == dst->depth);
352.10780 ++		assert(src->width == dst->width);
352.10781 ++		assert(src->height == dst->height);
352.10782 ++		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
352.10783 ++						      src_dx, src_dy,
352.10784 ++						      dst_dx, dst_dy,
352.10785 ++						      box, n, &extents);
352.10786 ++	}
352.10787 ++
352.10788 ++	if (dst->depth == src->depth) {
352.10789 ++		tmp.dst.format = sna_render_format_for_depth(dst->depth);
352.10790 ++		tmp.src.pict_format = tmp.dst.format;
352.10791 ++	} else {
352.10792 ++		tmp.dst.format = sna_format_for_depth(dst->depth);
352.10793 ++		tmp.src.pict_format = sna_format_for_depth(src->depth);
352.10794 ++	}
352.10795 ++	if (!gen9_check_format(tmp.src.pict_format))
352.10796 ++		goto fallback_blt;
352.10797 ++
352.10798 ++	tmp.dst.pixmap = (PixmapPtr)dst;
352.10799 ++	tmp.dst.width  = dst->width;
352.10800 ++	tmp.dst.height = dst->height;
352.10801 ++	tmp.dst.bo = dst_bo;
352.10802 ++	tmp.dst.x = tmp.dst.y = 0;
352.10803 ++	tmp.damage = NULL;
352.10804 ++
352.10805 ++	sna_render_composite_redirect_init(&tmp);
352.10806 ++	if (too_large(tmp.dst.width, tmp.dst.height)) {
352.10807 ++		int i;
352.10808 ++
352.10809 ++		extents = box[0];
352.10810 ++		for (i = 1; i < n; i++) {
352.10811 ++			if (box[i].x1 < extents.x1)
352.10812 ++				extents.x1 = box[i].x1;
352.10813 ++			if (box[i].y1 < extents.y1)
352.10814 ++				extents.y1 = box[i].y1;
352.10815 ++
352.10816 ++			if (box[i].x2 > extents.x2)
352.10817 ++				extents.x2 = box[i].x2;
352.10818 ++			if (box[i].y2 > extents.y2)
352.10819 ++				extents.y2 = box[i].y2;
352.10820 ++		}
352.10821 ++
352.10822 ++		if (!sna_render_composite_redirect(sna, &tmp,
352.10823 ++						   extents.x1 + dst_dx,
352.10824 ++						   extents.y1 + dst_dy,
352.10825 ++						   extents.x2 - extents.x1,
352.10826 ++						   extents.y2 - extents.y1,
352.10827 ++						   n > 1))
352.10828 ++			goto fallback_tiled;
352.10829 ++	}
352.10830 ++
352.10831 ++	tmp.src.card_format = gen9_get_card_format(tmp.src.pict_format);
352.10832 ++	if (too_large(src->width, src->height)) {
352.10833 ++		int i;
352.10834 ++
352.10835 ++		extents = box[0];
352.10836 ++		for (i = 1; i < n; i++) {
352.10837 ++			if (box[i].x1 < extents.x1)
352.10838 ++				extents.x1 = box[i].x1;
352.10839 ++			if (box[i].y1 < extents.y1)
352.10840 ++				extents.y1 = box[i].y1;
352.10841 ++
352.10842 ++			if (box[i].x2 > extents.x2)
352.10843 ++				extents.x2 = box[i].x2;
352.10844 ++			if (box[i].y2 > extents.y2)
352.10845 ++				extents.y2 = box[i].y2;
352.10846 ++		}
352.10847 ++
352.10848 ++		if (!sna_render_pixmap_partial(sna, src, src_bo, &tmp.src,
352.10849 ++					       extents.x1 + src_dx,
352.10850 ++					       extents.y1 + src_dy,
352.10851 ++					       extents.x2 - extents.x1,
352.10852 ++					       extents.y2 - extents.y1))
352.10853 ++			goto fallback_tiled_dst;
352.10854 ++	} else {
352.10855 ++		tmp.src.bo = src_bo;
352.10856 ++		tmp.src.width  = src->width;
352.10857 ++		tmp.src.height = src->height;
352.10858 ++		tmp.src.offset[0] = tmp.src.offset[1] = 0;
352.10859 ++	}
352.10860 ++
352.10861 ++	tmp.mask.bo = NULL;
352.10862 ++
352.10863 ++	tmp.floats_per_vertex = 2;
352.10864 ++	tmp.floats_per_rect = 6;
352.10865 ++	tmp.need_magic_ca_pass = 0;
352.10866 ++
352.10867 ++	tmp.u.gen9.flags = COPY_FLAGS(alu);
352.10868 ++
352.10869 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo);
352.10870 ++	if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) {
352.10871 ++		kgem_submit(&sna->kgem);
352.10872 ++		if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) {
352.10873 ++			if (tmp.src.bo != src_bo)
352.10874 ++				kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.10875 ++			if (tmp.redirect.real_bo)
352.10876 ++				kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
352.10877 ++			goto fallback_blt;
352.10878 ++		}
352.10879 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.10880 ++	}
352.10881 ++
352.10882 ++	src_dx += tmp.src.offset[0];
352.10883 ++	src_dy += tmp.src.offset[1];
352.10884 ++
352.10885 ++	dst_dx += tmp.dst.x;
352.10886 ++	dst_dy += tmp.dst.y;
352.10887 ++
352.10888 ++	tmp.dst.x = tmp.dst.y = 0;
352.10889 ++
352.10890 ++	gen9_align_vertex(sna, &tmp);
352.10891 ++	gen9_emit_copy_state(sna, &tmp);
352.10892 ++
352.10893 ++	do {
352.10894 ++		int16_t *v;
352.10895 ++		int n_this_time;
352.10896 ++
352.10897 ++		n_this_time = gen9_get_rectangles(sna, &tmp, n,
352.10898 ++						  gen9_emit_copy_state);
352.10899 ++		n -= n_this_time;
352.10900 ++
352.10901 ++		v = (int16_t *)(sna->render.vertices + sna->render.vertex_used);
352.10902 ++		sna->render.vertex_used += 6 * n_this_time;
352.10903 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.10904 ++		do {
352.10905 ++
352.10906 ++			DBG(("	(%d, %d) -> (%d, %d) + (%d, %d)\n",
352.10907 ++			     box->x1 + src_dx, box->y1 + src_dy,
352.10908 ++			     box->x1 + dst_dx, box->y1 + dst_dy,
352.10909 ++			     box->x2 - box->x1, box->y2 - box->y1));
352.10910 ++			v[0] = box->x2 + dst_dx;
352.10911 ++			v[2] = box->x2 + src_dx;
352.10912 ++			v[1]  = v[5] = box->y2 + dst_dy;
352.10913 ++			v[3]  = v[7] = box->y2 + src_dy;
352.10914 ++			v[8]  = v[4] = box->x1 + dst_dx;
352.10915 ++			v[10] = v[6] = box->x1 + src_dx;
352.10916 ++			v[9]  = box->y1 + dst_dy;
352.10917 ++			v[11] = box->y1 + src_dy;
352.10918 ++			v += 12; box++;
352.10919 ++		} while (--n_this_time);
352.10920 ++	} while (n);
352.10921 ++
352.10922 ++	gen8_vertex_flush(sna);
352.10923 ++	sna_render_composite_redirect_done(sna, &tmp);
352.10924 ++	if (tmp.src.bo != src_bo)
352.10925 ++		kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.10926 ++	return true;
352.10927 ++
352.10928 ++fallback_tiled_dst:
352.10929 ++	if (tmp.redirect.real_bo)
352.10930 ++		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
352.10931 ++fallback_tiled:
352.10932 ++	DBG(("%s: fallback tiled\n", __FUNCTION__));
352.10933 ++	if (sna_blt_compare_depth(src, dst) &&
352.10934 ++	    sna_blt_copy_boxes(sna, alu,
352.10935 ++			       src_bo, src_dx, src_dy,
352.10936 ++			       dst_bo, dst_dx, dst_dy,
352.10937 ++			       dst->bitsPerPixel,
352.10938 ++			       box, n))
352.10939 ++		return true;
352.10940 ++
352.10941 ++	return sna_tiling_copy_boxes(sna, alu,
352.10942 ++				     src, src_bo, src_dx, src_dy,
352.10943 ++				     dst, dst_bo, dst_dx, dst_dy,
352.10944 ++				     box, n);
352.10945 ++}
352.10946 ++
352.10947 ++static void
352.10948 ++gen9_render_copy_blt(struct sna *sna,
352.10949 ++		     const struct sna_copy_op *op,
352.10950 ++		     int16_t sx, int16_t sy,
352.10951 ++		     int16_t w,  int16_t h,
352.10952 ++		     int16_t dx, int16_t dy)
352.10953 ++{
352.10954 ++	int16_t *v;
352.10955 ++
352.10956 ++	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_copy_state);
352.10957 ++
352.10958 ++	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.10959 ++	sna->render.vertex_used += 6;
352.10960 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.10961 ++
352.10962 ++	v[0]  = dx+w; v[1]  = dy+h;
352.10963 ++	v[2]  = sx+w; v[3]  = sy+h;
352.10964 ++	v[4]  = dx;   v[5]  = dy+h;
352.10965 ++	v[6]  = sx;   v[7]  = sy+h;
352.10966 ++	v[8]  = dx;   v[9]  = dy;
352.10967 ++	v[10] = sx;   v[11] = sy;
352.10968 ++}
352.10969 ++
352.10970 ++static void
352.10971 ++gen9_render_copy_done(struct sna *sna, const struct sna_copy_op *op)
352.10972 ++{
352.10973 ++	if (sna->render.vertex_offset)
352.10974 ++		gen8_vertex_flush(sna);
352.10975 ++}
352.10976 ++
352.10977 ++static bool
352.10978 ++gen9_render_copy(struct sna *sna, uint8_t alu,
352.10979 ++		 PixmapPtr src, struct kgem_bo *src_bo,
352.10980 ++		 PixmapPtr dst, struct kgem_bo *dst_bo,
352.10981 ++		 struct sna_copy_op *op)
352.10982 ++{
352.10983 ++	DBG(("%s (alu=%d, src=(%dx%d), dst=(%dx%d))\n",
352.10984 ++	     __FUNCTION__, alu,
352.10985 ++	     src->drawable.width, src->drawable.height,
352.10986 ++	     dst->drawable.width, dst->drawable.height));
352.10987 ++
352.10988 ++	if (prefer_blt_copy(sna, src_bo, dst_bo, 0) &&
352.10989 ++	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
352.10990 ++	    sna_blt_copy(sna, alu,
352.10991 ++			 src_bo, dst_bo,
352.10992 ++			 dst->drawable.bitsPerPixel,
352.10993 ++			 op))
352.10994 ++		return true;
352.10995 ++
352.10996 ++	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
352.10997 ++	    too_large(src->drawable.width, src->drawable.height) ||
352.10998 ++	    too_large(dst->drawable.width, dst->drawable.height) ||
352.10999 ++	    unaligned(src_bo, src->drawable.bitsPerPixel) ||
352.11000 ++	    unaligned(dst_bo, dst->drawable.bitsPerPixel)) {
352.11001 ++fallback:
352.11002 ++		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
352.11003 ++			return false;
352.11004 ++
352.11005 ++		return sna_blt_copy(sna, alu, src_bo, dst_bo,
352.11006 ++				    dst->drawable.bitsPerPixel,
352.11007 ++				    op);
352.11008 ++	}
352.11009 ++
352.11010 ++	if (dst->drawable.depth == src->drawable.depth) {
352.11011 ++		op->base.dst.format = sna_render_format_for_depth(dst->drawable.depth);
352.11012 ++		op->base.src.pict_format = op->base.dst.format;
352.11013 ++	} else {
352.11014 ++		op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
352.11015 ++		op->base.src.pict_format = sna_format_for_depth(src->drawable.depth);
352.11016 ++	}
352.11017 ++	if (!gen9_check_format(op->base.src.pict_format))
352.11018 ++		goto fallback;
352.11019 ++
352.11020 ++	op->base.dst.pixmap = dst;
352.11021 ++	op->base.dst.width  = dst->drawable.width;
352.11022 ++	op->base.dst.height = dst->drawable.height;
352.11023 ++	op->base.dst.bo = dst_bo;
352.11024 ++
352.11025 ++	op->base.src.bo = src_bo;
352.11026 ++	op->base.src.card_format =
352.11027 ++		gen9_get_card_format(op->base.src.pict_format);
352.11028 ++	op->base.src.width  = src->drawable.width;
352.11029 ++	op->base.src.height = src->drawable.height;
352.11030 ++
352.11031 ++	op->base.mask.bo = NULL;
352.11032 ++
352.11033 ++	op->base.floats_per_vertex = 2;
352.11034 ++	op->base.floats_per_rect = 6;
352.11035 ++
352.11036 ++	op->base.u.gen9.flags = COPY_FLAGS(alu);
352.11037 ++
352.11038 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
352.11039 ++	if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
352.11040 ++		kgem_submit(&sna->kgem);
352.11041 ++		if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
352.11042 ++			goto fallback;
352.11043 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11044 ++	}
352.11045 ++
352.11046 ++	gen9_align_vertex(sna, &op->base);
352.11047 ++	gen9_emit_copy_state(sna, &op->base);
352.11048 ++
352.11049 ++	op->blt  = gen9_render_copy_blt;
352.11050 ++	op->done = gen9_render_copy_done;
352.11051 ++	return true;
352.11052 ++}
352.11053 ++
352.11054 ++static void
352.11055 ++gen9_emit_fill_state(struct sna *sna, const struct sna_composite_op *op)
352.11056 ++{
352.11057 ++	uint32_t *binding_table;
352.11058 ++	uint16_t offset, dirty;
352.11059 ++
352.11060 ++	/* XXX Render Target Fast Clear
352.11061 ++	 * Set RTFC Enable in PS and render a rectangle.
352.11062 ++	 * Limited to a clearing the full MSC surface only with a
352.11063 ++	 * specific kernel.
352.11064 ++	 */
352.11065 ++
352.11066 ++	gen9_get_batch(sna, op);
352.11067 ++
352.11068 ++	binding_table = gen9_composite_get_binding_table(sna, &offset);
352.11069 ++
352.11070 ++	dirty = kgem_bo_is_dirty(op->dst.bo);
352.11071 ++
352.11072 ++	binding_table[0] =
352.11073 ++		gen9_bind_bo(sna,
352.11074 ++			     op->dst.bo, op->dst.width, op->dst.height,
352.11075 ++			     gen9_get_dest_format(op->dst.format),
352.11076 ++			     true);
352.11077 ++	binding_table[1] =
352.11078 ++		gen9_bind_bo(sna,
352.11079 ++			     op->src.bo, 1, 1,
352.11080 ++			     SURFACEFORMAT_B8G8R8A8_UNORM,
352.11081 ++			     false);
352.11082 ++
352.11083 ++	if (sna->kgem.surface == offset &&
352.11084 ++	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table) {
352.11085 ++		sna->kgem.surface += SURFACE_DW;
352.11086 ++		offset = sna->render_state.gen9.surface_table;
352.11087 ++	}
352.11088 ++
352.11089 ++	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
352.11090 ++		dirty = 0;
352.11091 ++
352.11092 ++	gen9_emit_state(sna, op, offset | dirty);
352.11093 ++}
352.11094 ++
352.11095 ++static bool
352.11096 ++gen9_render_fill_boxes(struct sna *sna,
352.11097 ++		       CARD8 op,
352.11098 ++		       PictFormat format,
352.11099 ++		       const xRenderColor *color,
352.11100 ++		       const DrawableRec *dst, struct kgem_bo *dst_bo,
352.11101 ++		       const BoxRec *box, int n)
352.11102 ++{
352.11103 ++	struct sna_composite_op tmp;
352.11104 ++	uint32_t pixel;
352.11105 ++
352.11106 ++	DBG(("%s (op=%d, color=(%04x, %04x, %04x, %04x) [%08x])\n",
352.11107 ++	     __FUNCTION__, op,
352.11108 ++	     color->red, color->green, color->blue, color->alpha, (int)format));
352.11109 ++
352.11110 ++	if (op >= ARRAY_SIZE(gen9_blend_op)) {
352.11111 ++		DBG(("%s: fallback due to unhandled blend op: %d\n",
352.11112 ++		     __FUNCTION__, op));
352.11113 ++		return false;
352.11114 ++	}
352.11115 ++
352.11116 ++	if (prefer_blt_fill(sna, dst_bo, FILL_BOXES) ||
352.11117 ++	    !gen9_check_dst_format(format) ||
352.11118 ++	    unaligned(dst_bo, PICT_FORMAT_BPP(format))) {
352.11119 ++		uint8_t alu = GXinvalid;
352.11120 ++
352.11121 ++		if (op <= PictOpSrc) {
352.11122 ++			pixel = 0;
352.11123 ++			if (op == PictOpClear)
352.11124 ++				alu = GXclear;
352.11125 ++			else if (sna_get_pixel_from_rgba(&pixel,
352.11126 ++							 color->red,
352.11127 ++							 color->green,
352.11128 ++							 color->blue,
352.11129 ++							 color->alpha,
352.11130 ++							 format))
352.11131 ++				alu = GXcopy;
352.11132 ++		}
352.11133 ++
352.11134 ++		if (alu != GXinvalid &&
352.11135 ++		    sna_blt_fill_boxes(sna, alu,
352.11136 ++				       dst_bo, dst->bitsPerPixel,
352.11137 ++				       pixel, box, n))
352.11138 ++			return true;
352.11139 ++
352.11140 ++		if (!gen9_check_dst_format(format))
352.11141 ++			return false;
352.11142 ++	}
352.11143 ++
352.11144 ++	if (op == PictOpClear) {
352.11145 ++		pixel = 0;
352.11146 ++		op = PictOpSrc;
352.11147 ++	} else if (!sna_get_pixel_from_rgba(&pixel,
352.11148 ++					    color->red,
352.11149 ++					    color->green,
352.11150 ++					    color->blue,
352.11151 ++					    color->alpha,
352.11152 ++					    PICT_a8r8g8b8))
352.11153 ++		return false;
352.11154 ++
352.11155 ++	DBG(("%s(%08x x %d [(%d, %d), (%d, %d) ...])\n",
352.11156 ++	     __FUNCTION__, pixel, n,
352.11157 ++	     box[0].x1, box[0].y1, box[0].x2, box[0].y2));
352.11158 ++
352.11159 ++	tmp.dst.pixmap = (PixmapPtr)dst;
352.11160 ++	tmp.dst.width  = dst->width;
352.11161 ++	tmp.dst.height = dst->height;
352.11162 ++	tmp.dst.format = format;
352.11163 ++	tmp.dst.bo = dst_bo;
352.11164 ++	tmp.dst.x = tmp.dst.y = 0;
352.11165 ++	tmp.damage = NULL;
352.11166 ++
352.11167 ++	sna_render_composite_redirect_init(&tmp);
352.11168 ++	if (too_large(dst->width, dst->height)) {
352.11169 ++		BoxRec extents;
352.11170 ++
352.11171 ++		boxes_extents(box, n, &extents);
352.11172 ++		if (!sna_render_composite_redirect(sna, &tmp,
352.11173 ++						   extents.x1, extents.y1,
352.11174 ++						   extents.x2 - extents.x1,
352.11175 ++						   extents.y2 - extents.y1,
352.11176 ++						   n > 1))
352.11177 ++			return sna_tiling_fill_boxes(sna, op, format, color,
352.11178 ++						     dst, dst_bo, box, n);
352.11179 ++	}
352.11180 ++
352.11181 ++	tmp.src.bo = sna_render_get_solid(sna, pixel);
352.11182 ++	tmp.mask.bo = NULL;
352.11183 ++
352.11184 ++	tmp.floats_per_vertex = 2;
352.11185 ++	tmp.floats_per_rect = 6;
352.11186 ++	tmp.need_magic_ca_pass = false;
352.11187 ++
352.11188 ++	tmp.u.gen9.flags = FILL_FLAGS(op, format);
352.11189 ++
352.11190 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
352.11191 ++	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.11192 ++		kgem_submit(&sna->kgem);
352.11193 ++		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.11194 ++			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11195 ++			tmp.src.bo = NULL;
352.11196 ++
352.11197 ++			if (tmp.redirect.real_bo) {
352.11198 ++				kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
352.11199 ++				tmp.redirect.real_bo = NULL;
352.11200 ++			}
352.11201 ++
352.11202 ++			return false;
352.11203 ++		}
352.11204 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11205 ++	}
352.11206 ++
352.11207 ++	gen9_align_vertex(sna, &tmp);
352.11208 ++	gen9_emit_fill_state(sna, &tmp);
352.11209 ++
352.11210 ++	do {
352.11211 ++		int n_this_time;
352.11212 ++		int16_t *v;
352.11213 ++
352.11214 ++		n_this_time = gen9_get_rectangles(sna, &tmp, n,
352.11215 ++						  gen9_emit_fill_state);
352.11216 ++		n -= n_this_time;
352.11217 ++
352.11218 ++		v = (int16_t *)(sna->render.vertices + sna->render.vertex_used);
352.11219 ++		sna->render.vertex_used += 6 * n_this_time;
352.11220 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11221 ++		do {
352.11222 ++			DBG(("	(%d, %d), (%d, %d)\n",
352.11223 ++			     box->x1, box->y1, box->x2, box->y2));
352.11224 ++
352.11225 ++			v[0] = box->x2;
352.11226 ++			v[5] = v[1] = box->y2;
352.11227 ++			v[8] = v[4] = box->x1;
352.11228 ++			v[9] = box->y1;
352.11229 ++			v[2] = v[3]  = v[7]  = 1;
352.11230 ++			v[6] = v[10] = v[11] = 0;
352.11231 ++			v += 12; box++;
352.11232 ++		} while (--n_this_time);
352.11233 ++	} while (n);
352.11234 ++
352.11235 ++	gen8_vertex_flush(sna);
352.11236 ++	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11237 ++	sna_render_composite_redirect_done(sna, &tmp);
352.11238 ++	return true;
352.11239 ++}
352.11240 ++
352.11241 ++static void
352.11242 ++gen9_render_fill_op_blt(struct sna *sna,
352.11243 ++			const struct sna_fill_op *op,
352.11244 ++			int16_t x, int16_t y, int16_t w, int16_t h)
352.11245 ++{
352.11246 ++	int16_t *v;
352.11247 ++
352.11248 ++	DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
352.11249 ++
352.11250 ++	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_fill_state);
352.11251 ++
352.11252 ++	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.11253 ++	sna->render.vertex_used += 6;
352.11254 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11255 ++
352.11256 ++	v[0] = x+w;
352.11257 ++	v[4] = v[8] = x;
352.11258 ++	v[1] = v[5] = y+h;
352.11259 ++	v[9] = y;
352.11260 ++
352.11261 ++	v[2] = v[3]  = v[7]  = 1;
352.11262 ++	v[6] = v[10] = v[11] = 0;
352.11263 ++}
352.11264 ++
352.11265 ++fastcall static void
352.11266 ++gen9_render_fill_op_box(struct sna *sna,
352.11267 ++			const struct sna_fill_op *op,
352.11268 ++			const BoxRec *box)
352.11269 ++{
352.11270 ++	int16_t *v;
352.11271 ++
352.11272 ++	DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
352.11273 ++	     box->x1, box->y1, box->x2, box->y2));
352.11274 ++
352.11275 ++	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_fill_state);
352.11276 ++
352.11277 ++	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.11278 ++	sna->render.vertex_used += 6;
352.11279 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11280 ++
352.11281 ++	v[0] = box->x2;
352.11282 ++	v[8] = v[4] = box->x1;
352.11283 ++	v[5] = v[1] = box->y2;
352.11284 ++	v[9] = box->y1;
352.11285 ++
352.11286 ++	v[7] = v[2]  = v[3]  = 1;
352.11287 ++	v[6] = v[10] = v[11] = 0;
352.11288 ++}
352.11289 ++
352.11290 ++fastcall static void
352.11291 ++gen9_render_fill_op_boxes(struct sna *sna,
352.11292 ++			  const struct sna_fill_op *op,
352.11293 ++			  const BoxRec *box,
352.11294 ++			  int nbox)
352.11295 ++{
352.11296 ++	DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__,
352.11297 ++	     box->x1, box->y1, box->x2, box->y2, nbox));
352.11298 ++
352.11299 ++	do {
352.11300 ++		int nbox_this_time;
352.11301 ++		int16_t *v;
352.11302 ++
352.11303 ++		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
352.11304 ++						     gen9_emit_fill_state);
352.11305 ++		nbox -= nbox_this_time;
352.11306 ++
352.11307 ++		v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.11308 ++		sna->render.vertex_used += 6 * nbox_this_time;
352.11309 ++		assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11310 ++
352.11311 ++		do {
352.11312 ++			v[0] = box->x2;
352.11313 ++			v[8] = v[4] = box->x1;
352.11314 ++			v[5] = v[1] = box->y2;
352.11315 ++			v[9] = box->y1;
352.11316 ++			v[7] = v[2]  = v[3]  = 1;
352.11317 ++			v[6] = v[10] = v[11] = 0;
352.11318 ++			box++; v += 12;
352.11319 ++		} while (--nbox_this_time);
352.11320 ++	} while (nbox);
352.11321 ++}
352.11322 ++
352.11323 ++static void
352.11324 ++gen9_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op)
352.11325 ++{
352.11326 ++	if (sna->render.vertex_offset)
352.11327 ++		gen8_vertex_flush(sna);
352.11328 ++	kgem_bo_destroy(&sna->kgem, op->base.src.bo);
352.11329 ++}
352.11330 ++
352.11331 ++static bool
352.11332 ++gen9_render_fill(struct sna *sna, uint8_t alu,
352.11333 ++		 PixmapPtr dst, struct kgem_bo *dst_bo,
352.11334 ++		 uint32_t color, unsigned flags,
352.11335 ++		 struct sna_fill_op *op)
352.11336 ++{
352.11337 ++	DBG(("%s: (alu=%d, color=%x)\n", __FUNCTION__, alu, color));
352.11338 ++
352.11339 ++	if (prefer_blt_fill(sna, dst_bo, flags) &&
352.11340 ++	    sna_blt_fill(sna, alu,
352.11341 ++			 dst_bo, dst->drawable.bitsPerPixel,
352.11342 ++			 color,
352.11343 ++			 op))
352.11344 ++		return true;
352.11345 ++
352.11346 ++	if (!(alu == GXcopy || alu == GXclear) ||
352.11347 ++	    too_large(dst->drawable.width, dst->drawable.height) ||
352.11348 ++	    unaligned(dst_bo, dst->drawable.bitsPerPixel))
352.11349 ++		return sna_blt_fill(sna, alu,
352.11350 ++				    dst_bo, dst->drawable.bitsPerPixel,
352.11351 ++				    color,
352.11352 ++				    op);
352.11353 ++
352.11354 ++	if (alu == GXclear)
352.11355 ++		color = 0;
352.11356 ++
352.11357 ++	op->base.dst.pixmap = dst;
352.11358 ++	op->base.dst.width  = dst->drawable.width;
352.11359 ++	op->base.dst.height = dst->drawable.height;
352.11360 ++	op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
352.11361 ++	op->base.dst.bo = dst_bo;
352.11362 ++	op->base.dst.x = op->base.dst.y = 0;
352.11363 ++
352.11364 ++	op->base.src.bo =
352.11365 ++		sna_render_get_solid(sna,
352.11366 ++				     sna_rgba_for_color(color,
352.11367 ++							dst->drawable.depth));
352.11368 ++	op->base.mask.bo = NULL;
352.11369 ++
352.11370 ++	op->base.need_magic_ca_pass = false;
352.11371 ++	op->base.floats_per_vertex = 2;
352.11372 ++	op->base.floats_per_rect = 6;
352.11373 ++
352.11374 ++	op->base.u.gen9.flags = FILL_FLAGS_NOBLEND;
352.11375 ++
352.11376 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
352.11377 ++	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.11378 ++		kgem_submit(&sna->kgem);
352.11379 ++		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
352.11380 ++			kgem_bo_destroy(&sna->kgem, op->base.src.bo);
352.11381 ++			return false;
352.11382 ++		}
352.11383 ++
352.11384 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11385 ++	}
352.11386 ++
352.11387 ++	gen9_align_vertex(sna, &op->base);
352.11388 ++	gen9_emit_fill_state(sna, &op->base);
352.11389 ++
352.11390 ++	op->blt   = gen9_render_fill_op_blt;
352.11391 ++	op->box   = gen9_render_fill_op_box;
352.11392 ++	op->boxes = gen9_render_fill_op_boxes;
352.11393 ++	op->points = NULL;
352.11394 ++	op->done  = gen9_render_fill_op_done;
352.11395 ++	return true;
352.11396 ++}
352.11397 ++
352.11398 ++static bool
352.11399 ++gen9_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
352.11400 ++			     uint32_t color,
352.11401 ++			     int16_t x1, int16_t y1, int16_t x2, int16_t y2,
352.11402 ++			     uint8_t alu)
352.11403 ++{
352.11404 ++	BoxRec box;
352.11405 ++
352.11406 ++	box.x1 = x1;
352.11407 ++	box.y1 = y1;
352.11408 ++	box.x2 = x2;
352.11409 ++	box.y2 = y2;
352.11410 ++
352.11411 ++	return sna_blt_fill_boxes(sna, alu,
352.11412 ++				  bo, dst->drawable.bitsPerPixel,
352.11413 ++				  color, &box, 1);
352.11414 ++}
352.11415 ++
352.11416 ++static bool
352.11417 ++gen9_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
352.11418 ++		     uint32_t color,
352.11419 ++		     int16_t x1, int16_t y1,
352.11420 ++		     int16_t x2, int16_t y2,
352.11421 ++		     uint8_t alu)
352.11422 ++{
352.11423 ++	struct sna_composite_op tmp;
352.11424 ++	int16_t *v;
352.11425 ++
352.11426 ++	/* Prefer to use the BLT if already engaged */
352.11427 ++	if (prefer_blt_fill(sna, bo, FILL_BOXES) &&
352.11428 ++	    gen9_render_fill_one_try_blt(sna, dst, bo, color,
352.11429 ++					 x1, y1, x2, y2, alu))
352.11430 ++		return true;
352.11431 ++
352.11432 ++	/* Must use the BLT if we can't RENDER... */
352.11433 ++	if (!(alu == GXcopy || alu == GXclear) ||
352.11434 ++	    too_large(dst->drawable.width, dst->drawable.height) ||
352.11435 ++	    unaligned(bo, dst->drawable.bitsPerPixel))
352.11436 ++		return gen9_render_fill_one_try_blt(sna, dst, bo, color,
352.11437 ++						    x1, y1, x2, y2, alu);
352.11438 ++
352.11439 ++	if (alu == GXclear)
352.11440 ++		color = 0;
352.11441 ++
352.11442 ++	tmp.dst.pixmap = dst;
352.11443 ++	tmp.dst.width  = dst->drawable.width;
352.11444 ++	tmp.dst.height = dst->drawable.height;
352.11445 ++	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
352.11446 ++	tmp.dst.bo = bo;
352.11447 ++	tmp.dst.x = tmp.dst.y = 0;
352.11448 ++
352.11449 ++	tmp.src.bo =
352.11450 ++		sna_render_get_solid(sna,
352.11451 ++				     sna_rgba_for_color(color,
352.11452 ++							dst->drawable.depth));
352.11453 ++	tmp.mask.bo = NULL;
352.11454 ++
352.11455 ++	tmp.floats_per_vertex = 2;
352.11456 ++	tmp.floats_per_rect = 6;
352.11457 ++	tmp.need_magic_ca_pass = false;
352.11458 ++
352.11459 ++	tmp.u.gen9.flags = FILL_FLAGS_NOBLEND;
352.11460 ++
352.11461 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
352.11462 ++	if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
352.11463 ++		kgem_submit(&sna->kgem);
352.11464 ++		if (kgem_check_bo(&sna->kgem, bo, NULL)) {
352.11465 ++			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11466 ++			return false;
352.11467 ++		}
352.11468 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11469 ++	}
352.11470 ++
352.11471 ++	gen9_align_vertex(sna, &tmp);
352.11472 ++	gen9_emit_fill_state(sna, &tmp);
352.11473 ++
352.11474 ++	gen9_get_rectangles(sna, &tmp, 1, gen9_emit_fill_state);
352.11475 ++
352.11476 ++	DBG(("	(%d, %d), (%d, %d)\n", x1, y1, x2, y2));
352.11477 ++
352.11478 ++	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.11479 ++	sna->render.vertex_used += 6;
352.11480 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11481 ++
352.11482 ++	v[0] = x2;
352.11483 ++	v[8] = v[4] = x1;
352.11484 ++	v[5] = v[1] = y2;
352.11485 ++	v[9] = y1;
352.11486 ++	v[7] = v[2]  = v[3]  = 1;
352.11487 ++	v[6] = v[10] = v[11] = 0;
352.11488 ++
352.11489 ++	gen8_vertex_flush(sna);
352.11490 ++	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11491 ++
352.11492 ++	return true;
352.11493 ++}
352.11494 ++
352.11495 ++static bool
352.11496 ++gen9_render_clear_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
352.11497 ++{
352.11498 ++	BoxRec box;
352.11499 ++
352.11500 ++	box.x1 = 0;
352.11501 ++	box.y1 = 0;
352.11502 ++	box.x2 = dst->drawable.width;
352.11503 ++	box.y2 = dst->drawable.height;
352.11504 ++
352.11505 ++	return sna_blt_fill_boxes(sna, GXclear,
352.11506 ++				  bo, dst->drawable.bitsPerPixel,
352.11507 ++				  0, &box, 1);
352.11508 ++}
352.11509 ++
352.11510 ++static bool
352.11511 ++gen9_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
352.11512 ++{
352.11513 ++	struct sna_composite_op tmp;
352.11514 ++	int16_t *v;
352.11515 ++
352.11516 ++	DBG(("%s: %dx%d\n",
352.11517 ++	     __FUNCTION__,
352.11518 ++	     dst->drawable.width,
352.11519 ++	     dst->drawable.height));
352.11520 ++
352.11521 ++	/* Prefer to use the BLT if already engaged */
352.11522 ++	if (sna->kgem.mode == KGEM_BLT &&
352.11523 ++	    gen9_render_clear_try_blt(sna, dst, bo))
352.11524 ++		return true;
352.11525 ++
352.11526 ++	/* Must use the BLT if we can't RENDER... */
352.11527 ++	if (too_large(dst->drawable.width, dst->drawable.height) ||
352.11528 ++	    unaligned(bo, dst->drawable.bitsPerPixel))
352.11529 ++		return gen9_render_clear_try_blt(sna, dst, bo);
352.11530 ++
352.11531 ++	tmp.dst.pixmap = dst;
352.11532 ++	tmp.dst.width  = dst->drawable.width;
352.11533 ++	tmp.dst.height = dst->drawable.height;
352.11534 ++	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
352.11535 ++	tmp.dst.bo = bo;
352.11536 ++	tmp.dst.x = tmp.dst.y = 0;
352.11537 ++
352.11538 ++	tmp.src.bo = sna_render_get_solid(sna, 0);
352.11539 ++	tmp.mask.bo = NULL;
352.11540 ++
352.11541 ++	tmp.floats_per_vertex = 2;
352.11542 ++	tmp.floats_per_rect = 6;
352.11543 ++	tmp.need_magic_ca_pass = false;
352.11544 ++
352.11545 ++	tmp.u.gen9.flags = FILL_FLAGS_NOBLEND;
352.11546 ++
352.11547 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
352.11548 ++	if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
352.11549 ++		kgem_submit(&sna->kgem);
352.11550 ++		if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
352.11551 ++			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11552 ++			return false;
352.11553 ++		}
352.11554 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11555 ++	}
352.11556 ++
352.11557 ++	gen9_align_vertex(sna, &tmp);
352.11558 ++	gen9_emit_fill_state(sna, &tmp);
352.11559 ++
352.11560 ++	gen9_get_rectangles(sna, &tmp, 1, gen9_emit_fill_state);
352.11561 ++
352.11562 ++	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
352.11563 ++	sna->render.vertex_used += 6;
352.11564 ++	assert(sna->render.vertex_used <= sna->render.vertex_size);
352.11565 ++
352.11566 ++	v[0] = dst->drawable.width;
352.11567 ++	v[5] = v[1] = dst->drawable.height;
352.11568 ++	v[8] = v[4] = 0;
352.11569 ++	v[9] = 0;
352.11570 ++
352.11571 ++	v[7] = v[2]  = v[3]  = 1;
352.11572 ++	v[6] = v[10] = v[11] = 0;
352.11573 ++
352.11574 ++	gen8_vertex_flush(sna);
352.11575 ++	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
352.11576 ++
352.11577 ++	return true;
352.11578 ++}
352.11579 ++
352.11580 ++#if !NO_VIDEO
352.11581 ++static uint32_t gen9_bind_video_source(struct sna *sna,
352.11582 ++				       struct kgem_bo *bo,
352.11583 ++				       uint32_t delta,
352.11584 ++				       int width,
352.11585 ++				       int height,
352.11586 ++				       int pitch,
352.11587 ++				       uint32_t format)
352.11588 ++{
352.11589 ++	uint32_t *ss;
352.11590 ++	int offset;
352.11591 ++
352.11592 ++	offset = sna->kgem.surface -= SURFACE_DW;
352.11593 ++	ss = sna->kgem.batch + offset;
352.11594 ++	ss[0] = (SURFACE_2D << SURFACE_TYPE_SHIFT |
352.11595 ++		 gen9_tiling_bits(bo->tiling) |
352.11596 ++		 format << SURFACE_FORMAT_SHIFT |
352.11597 ++		 SURFACE_VALIGN_4 | SURFACE_HALIGN_4);
352.11598 ++	ss[1] = 0;
352.11599 ++	ss[2] = ((width - 1)  << SURFACE_WIDTH_SHIFT |
352.11600 ++		 (height - 1) << SURFACE_HEIGHT_SHIFT);
352.11601 ++	ss[3] = (pitch - 1) << SURFACE_PITCH_SHIFT;
352.11602 ++	ss[4] = 0;
352.11603 ++	ss[5] = 0;
352.11604 ++	ss[6] = 0;
352.11605 ++	ss[7] = SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA);
352.11606 ++	*(uint64_t *)(ss+8) =
352.11607 ++		kgem_add_reloc64(&sna->kgem, offset + 8, bo,
352.11608 ++				 I915_GEM_DOMAIN_SAMPLER << 16,
352.11609 ++				 delta);
352.11610 ++	ss[10] = 0;
352.11611 ++	ss[11] = 0;
352.11612 ++	ss[12] = 0;
352.11613 ++	ss[13] = 0;
352.11614 ++	ss[14] = 0;
352.11615 ++	ss[15] = 0;
352.11616 ++
352.11617 ++	DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> sampler\n",
352.11618 ++	     offset, bo->handle, ss[1],
352.11619 ++	     format, width, height, bo->pitch, bo->tiling));
352.11620 ++
352.11621 ++	return offset * sizeof(uint32_t);
352.11622 ++}
352.11623 ++
352.11624 ++static void gen9_emit_video_state(struct sna *sna,
352.11625 ++				  const struct sna_composite_op *op)
352.11626 ++{
352.11627 ++	struct sna_video_frame *frame = op->priv;
352.11628 ++	uint32_t src_surf_format;
352.11629 ++	uint32_t src_surf_base[6];
352.11630 ++	int src_width[6];
352.11631 ++	int src_height[6];
352.11632 ++	int src_pitch[6];
352.11633 ++	uint32_t *binding_table;
352.11634 ++	uint16_t offset;
352.11635 ++	int n_src, n;
352.11636 ++
352.11637 ++	/* XXX VeBox, bicubic */
352.11638 ++
352.11639 ++	gen9_get_batch(sna, op);
352.11640 ++
352.11641 ++	src_surf_base[0] = 0;
352.11642 ++	src_surf_base[1] = 0;
352.11643 ++	src_surf_base[2] = frame->VBufOffset;
352.11644 ++	src_surf_base[3] = frame->VBufOffset;
352.11645 ++	src_surf_base[4] = frame->UBufOffset;
352.11646 ++	src_surf_base[5] = frame->UBufOffset;
352.11647 ++
352.11648 ++	if (is_planar_fourcc(frame->id)) {
352.11649 ++		src_surf_format = SURFACEFORMAT_R8_UNORM;
352.11650 ++		src_width[1]  = src_width[0]  = frame->width;
352.11651 ++		src_height[1] = src_height[0] = frame->height;
352.11652 ++		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
352.11653 ++		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
352.11654 ++			frame->width / 2;
352.11655 ++		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
352.11656 ++			frame->height / 2;
352.11657 ++		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
352.11658 ++			frame->pitch[0];
352.11659 ++		n_src = 6;
352.11660 ++	} else {
352.11661 ++		if (frame->id == FOURCC_RGB888)
352.11662 ++			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
352.11663 ++		else if (frame->id == FOURCC_UYVY)
352.11664 ++			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
352.11665 ++		else
352.11666 ++			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
352.11667 ++
352.11668 ++		src_width[0]  = frame->width;
352.11669 ++		src_height[0] = frame->height;
352.11670 ++		src_pitch[0]  = frame->pitch[0];
352.11671 ++		n_src = 1;
352.11672 ++	}
352.11673 ++
352.11674 ++	binding_table = gen9_composite_get_binding_table(sna, &offset);
352.11675 ++
352.11676 ++	binding_table[0] =
352.11677 ++		gen9_bind_bo(sna,
352.11678 ++			     op->dst.bo, op->dst.width, op->dst.height,
352.11679 ++			     gen9_get_dest_format(op->dst.format),
352.11680 ++			     true);
352.11681 ++	for (n = 0; n < n_src; n++) {
352.11682 ++		binding_table[1+n] =
352.11683 ++			gen9_bind_video_source(sna,
352.11684 ++					       frame->bo,
352.11685 ++					       src_surf_base[n],
352.11686 ++					       src_width[n],
352.11687 ++					       src_height[n],
352.11688 ++					       src_pitch[n],
352.11689 ++					       src_surf_format);
352.11690 ++	}
352.11691 ++
352.11692 ++	gen9_emit_state(sna, op, offset);
352.11693 ++}
352.11694 ++
352.11695 ++static unsigned select_video_kernel(const struct sna_video_frame *frame)
352.11696 ++{
352.11697 ++	switch (frame->id) {
352.11698 ++	case FOURCC_YV12:
352.11699 ++	case FOURCC_I420:
352.11700 ++	case FOURCC_XVMC:
352.11701 ++		return GEN9_WM_KERNEL_VIDEO_PLANAR;
352.11702 ++
352.11703 ++	case FOURCC_RGB888:
352.11704 ++	case FOURCC_RGB565:
352.11705 ++		return GEN9_WM_KERNEL_VIDEO_RGB;
352.11706 ++
352.11707 ++	default:
352.11708 ++		return GEN9_WM_KERNEL_VIDEO_PACKED;
352.11709 ++	}
352.11710 ++}
352.11711 ++
352.11712 ++static bool
352.11713 ++gen9_render_video(struct sna *sna,
352.11714 ++		  struct sna_video *video,
352.11715 ++		  struct sna_video_frame *frame,
352.11716 ++		  RegionPtr dstRegion,
352.11717 ++		  PixmapPtr pixmap)
352.11718 ++{
352.11719 ++	struct sna_composite_op tmp;
352.11720 ++	struct sna_pixmap *priv = sna_pixmap(pixmap);
352.11721 ++	int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
352.11722 ++	int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
352.11723 ++	int src_width = frame->src.x2 - frame->src.x1;
352.11724 ++	int src_height = frame->src.y2 - frame->src.y1;
352.11725 ++	float src_offset_x, src_offset_y;
352.11726 ++	float src_scale_x, src_scale_y;
352.11727 ++	unsigned filter;
352.11728 ++	const BoxRec *box;
352.11729 ++	int nbox;
352.11730 ++
352.11731 ++	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
352.11732 ++	     __FUNCTION__,
352.11733 ++	     src_width, src_height, dst_width, dst_height,
352.11734 ++	     region_num_rects(dstRegion),
352.11735 ++	     REGION_EXTENTS(NULL, dstRegion)->x1,
352.11736 ++	     REGION_EXTENTS(NULL, dstRegion)->y1,
352.11737 ++	     REGION_EXTENTS(NULL, dstRegion)->x2,
352.11738 ++	     REGION_EXTENTS(NULL, dstRegion)->y2));
352.11739 ++
352.11740 ++	assert(priv->gpu_bo);
352.11741 ++	assert(!too_large(pixmap->drawable.width, pixmap->drawable.height));
352.11742 ++	assert(!unaligned(priv->gpu_bo, pixmap->drawable.bitsPerPixel));
352.11743 ++
352.11744 ++	memset(&tmp, 0, sizeof(tmp));
352.11745 ++
352.11746 ++	tmp.dst.pixmap = pixmap;
352.11747 ++	tmp.dst.width  = pixmap->drawable.width;
352.11748 ++	tmp.dst.height = pixmap->drawable.height;
352.11749 ++	tmp.dst.format = sna_render_format_for_depth(pixmap->drawable.depth);
352.11750 ++	tmp.dst.bo = priv->gpu_bo;
352.11751 ++
352.11752 ++	tmp.src.bo = frame->bo;
352.11753 ++	tmp.mask.bo = NULL;
352.11754 ++
352.11755 ++	tmp.floats_per_vertex = 3;
352.11756 ++	tmp.floats_per_rect = 9;
352.11757 ++
352.11758 ++	DBG(("%s: scaling?=%d, planar?=%d [%x]\n",
352.11759 ++	     __FUNCTION__,
352.11760 ++	     src_width != dst_width || src_height != dst_height,
352.11761 ++	     is_planar_fourcc(frame->id), frame->id));
352.11762 ++
352.11763 ++	if (src_width == dst_width && src_height == dst_height)
352.11764 ++		filter = SAMPLER_FILTER_NEAREST;
352.11765 ++	else
352.11766 ++		filter = SAMPLER_FILTER_BILINEAR;
352.11767 ++
352.11768 ++	tmp.u.gen9.flags =
352.11769 ++		GEN9_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
352.11770 ++					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
352.11771 ++			       NO_BLEND,
352.11772 ++			       select_video_kernel(frame),
352.11773 ++			       2);
352.11774 ++	tmp.priv = frame;
352.11775 ++
352.11776 ++	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo);
352.11777 ++	if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL)) {
352.11778 ++		kgem_submit(&sna->kgem);
352.11779 ++		if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL))
352.11780 ++			return false;
352.11781 ++
352.11782 ++		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
352.11783 ++	}
352.11784 ++
352.11785 ++	gen9_align_vertex(sna, &tmp);
352.11786 ++	gen9_emit_video_state(sna, &tmp);
352.11787 ++
352.11788 ++	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
352.11789 ++	     __FUNCTION__,
352.11790 ++	     frame->src.x1, frame->src.y1,
352.11791 ++	     src_width, src_height,
352.11792 ++	     dst_width, dst_height,
352.11793 ++	     frame->width, frame->height));
352.11794 ++
352.11795 ++	src_scale_x = (float)src_width / dst_width / frame->width;
352.11796 ++	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
352.11797 ++
352.11798 ++	src_scale_y = (float)src_height / dst_height / frame->height;
352.11799 ++	src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
352.11800 ++
352.11801 ++	DBG(("%s: scale=(%f, %f), offset=(%f, %f)\n",
352.11802 ++	     __FUNCTION__,
352.11803 ++	     src_scale_x, src_scale_y,
352.11804 ++	     src_offset_x, src_offset_y));
352.11805 ++
352.11806 ++	box = region_rects(dstRegion);
352.11807 ++	nbox = region_num_rects(dstRegion);
352.11808 ++	while (nbox--) {
352.11809 ++		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
352.11810 ++		     __FUNCTION__,
352.11811 ++		     box->x1, box->y1,
352.11812 ++		     box->x2, box->y2,
352.11813 ++		     box->x1 * src_scale_x + src_offset_x,
352.11814 ++		     box->y1 * src_scale_y + src_offset_y,
352.11815 ++		     box->x2 * src_scale_x + src_offset_x,
352.11816 ++		     box->y2 * src_scale_y + src_offset_y));
352.11817 ++
352.11818 ++		gen9_get_rectangles(sna, &tmp, 1, gen9_emit_video_state);
352.11819 ++
352.11820 ++		OUT_VERTEX(box->x2, box->y2);
352.11821 ++		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
352.11822 ++		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.11823 ++
352.11824 ++		OUT_VERTEX(box->x1, box->y2);
352.11825 ++		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.11826 ++		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
352.11827 ++
352.11828 ++		OUT_VERTEX(box->x1, box->y1);
352.11829 ++		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
352.11830 ++		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
352.11831 ++
352.11832 ++		box++;
352.11833 ++	}
352.11834 ++	gen8_vertex_flush(sna);
352.11835 ++
352.11836 ++	if (!DAMAGE_IS_ALL(priv->gpu_damage))
352.11837 ++		sna_damage_add(&priv->gpu_damage, dstRegion);
352.11838 ++
352.11839 ++	return true;
352.11840 ++}
352.11841 ++#endif
352.11842 ++
352.11843 ++static void gen9_render_flush(struct sna *sna)
352.11844 ++{
352.11845 ++	gen8_vertex_close(sna);
352.11846 ++
352.11847 ++	assert(sna->render.vb_id == 0);
352.11848 ++	assert(sna->render.vertex_offset == 0);
352.11849 ++}
352.11850 ++
352.11851 ++static void gen9_render_reset(struct sna *sna)
352.11852 ++{
352.11853 ++	sna->render_state.gen9.emit_flush = false;
352.11854 ++	sna->render_state.gen9.needs_invariant = true;
352.11855 ++	sna->render_state.gen9.ve_id = 3 << 2;
352.11856 ++	sna->render_state.gen9.ve_dirty = false;
352.11857 ++	sna->render_state.gen9.last_primitive = -1;
352.11858 ++
352.11859 ++	sna->render_state.gen9.num_sf_outputs = 0;
352.11860 ++	sna->render_state.gen9.samplers = -1;
352.11861 ++	sna->render_state.gen9.blend = -1;
352.11862 ++	sna->render_state.gen9.kernel = -1;
352.11863 ++	sna->render_state.gen9.drawrect_offset = -1;
352.11864 ++	sna->render_state.gen9.drawrect_limit = -1;
352.11865 ++	sna->render_state.gen9.surface_table = 0;
352.11866 ++
352.11867 ++	if (sna->render.vbo && !kgem_bo_can_map(&sna->kgem, sna->render.vbo)) {
352.11868 ++		DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
352.11869 ++		discard_vbo(sna);
352.11870 ++	}
352.11871 ++
352.11872 ++	sna->render.vertex_offset = 0;
352.11873 ++	sna->render.nvertex_reloc = 0;
352.11874 ++	sna->render.vb_id = 0;
352.11875 ++}
352.11876 ++
352.11877 ++static void gen9_render_fini(struct sna *sna)
352.11878 ++{
352.11879 ++	kgem_bo_destroy(&sna->kgem, sna->render_state.gen9.general_bo);
352.11880 ++}
352.11881 ++
352.11882 ++static bool gen9_render_setup(struct sna *sna)
352.11883 ++{
352.11884 ++	struct gen9_render_state *state = &sna->render_state.gen9;
352.11885 ++	struct sna_static_stream general;
352.11886 ++	struct gen9_sampler_state *ss;
352.11887 ++	int i, j, k, l, m;
352.11888 ++	uint32_t devid;
352.11889 ++
352.11890 ++	devid = intel_get_device_id(sna->dev);
352.11891 ++	if (devid & 0xf)
352.11892 ++		state->gt = GEN9_GT_BIAS + ((devid >> 4) & 0xf) + 1;
352.11893 ++	DBG(("%s: gt=%d\n", __FUNCTION__, state->gt));
352.11894 ++
352.11895 ++	state->info = &min_gt_info;
352.11896 ++	if (is_skl(sna))
352.11897 ++		state->info = &skl_gt_info;
352.11898 ++	if (is_bxt(sna))
352.11899 ++		state->info = &bxt_gt_info;
352.11900 ++	if (is_kbl(sna))
352.11901 ++		state->info = &kbl_gt_info;
352.11902 ++	if (is_glk(sna))
352.11903 ++		state->info = &glk_gt_info;
352.11904 ++
352.11905 ++	sna_static_stream_init(&general);
352.11906 ++
352.11907 ++	/* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
352.11908 ++	 * dumps, you know it points to zero.
352.11909 ++	 */
352.11910 ++	null_create(&general);
352.11911 ++
352.11912 ++	for (m = 0; m < ARRAY_SIZE(wm_kernels); m++) {
352.11913 ++		if (wm_kernels[m].size) {
352.11914 ++			state->wm_kernel[m][1] =
352.11915 ++				sna_static_stream_add(&general,
352.11916 ++						      wm_kernels[m].data,
352.11917 ++						      wm_kernels[m].size,
352.11918 ++						      64);
352.11919 ++		} else {
352.11920 ++			if (USE_8_PIXEL_DISPATCH) {
352.11921 ++				state->wm_kernel[m][0] =
352.11922 ++					sna_static_stream_compile_wm(sna, &general,
352.11923 ++								     wm_kernels[m].data, 8);
352.11924 ++			}
352.11925 ++
352.11926 ++			if (USE_16_PIXEL_DISPATCH) {
352.11927 ++				state->wm_kernel[m][1] =
352.11928 ++					sna_static_stream_compile_wm(sna, &general,
352.11929 ++								     wm_kernels[m].data, 16);
352.11930 ++			}
352.11931 ++
352.11932 ++			if (USE_32_PIXEL_DISPATCH) {
352.11933 ++				state->wm_kernel[m][2] =
352.11934 ++					sna_static_stream_compile_wm(sna, &general,
352.11935 ++								     wm_kernels[m].data, 32);
352.11936 ++			}
352.11937 ++		}
352.11938 ++		assert(state->wm_kernel[m][0]|state->wm_kernel[m][1]|state->wm_kernel[m][2]);
352.11939 ++	}
352.11940 ++
352.11941 ++	COMPILE_TIME_ASSERT(SAMPLER_OFFSET(FILTER_COUNT, EXTEND_COUNT, FILTER_COUNT, EXTEND_COUNT) <= 0x7ff);
352.11942 ++	ss = sna_static_stream_map(&general,
352.11943 ++				   2 * sizeof(*ss) *
352.11944 ++				   (2 +
352.11945 ++				    FILTER_COUNT * EXTEND_COUNT *
352.11946 ++				    FILTER_COUNT * EXTEND_COUNT),
352.11947 ++				   32);
352.11948 ++	state->wm_state = sna_static_stream_offsetof(&general, ss);
352.11949 ++	sampler_copy_init(ss); ss += 2;
352.11950 ++	sampler_fill_init(ss); ss += 2;
352.11951 ++	for (i = 0; i < FILTER_COUNT; i++) {
352.11952 ++		for (j = 0; j < EXTEND_COUNT; j++) {
352.11953 ++			for (k = 0; k < FILTER_COUNT; k++) {
352.11954 ++				for (l = 0; l < EXTEND_COUNT; l++) {
352.11955 ++					sampler_state_init(ss++, i, j);
352.11956 ++					sampler_state_init(ss++, k, l);
352.11957 ++				}
352.11958 ++			}
352.11959 ++		}
352.11960 ++	}
352.11961 ++
352.11962 ++	state->cc_blend = gen9_create_blend_state(&general);
352.11963 ++
352.11964 ++	state->general_bo = sna_static_stream_fini(sna, &general);
352.11965 ++	return state->general_bo != NULL;
352.11966 ++}
352.11967 ++
352.11968 ++const char *gen9_render_init(struct sna *sna, const char *backend)
352.11969 ++{
352.11970 ++	if (!gen9_render_setup(sna))
352.11971 ++		return backend;
352.11972 ++
352.11973 ++	sna->kgem.context_switch = gen6_render_context_switch;
352.11974 ++	sna->kgem.retire = gen6_render_retire;
352.11975 ++	sna->kgem.expire = gen4_render_expire;
352.11976 ++
352.11977 ++#if !NO_COMPOSITE
352.11978 ++	sna->render.composite = gen9_render_composite;
352.11979 ++	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
352.11980 ++#endif
352.11981 ++#if !NO_COMPOSITE_SPANS
352.11982 ++	sna->render.check_composite_spans = gen9_check_composite_spans;
352.11983 ++	sna->render.composite_spans = gen9_render_composite_spans;
352.11984 ++	sna->render.prefer_gpu |= PREFER_GPU_SPANS;
352.11985 ++#endif
352.11986 ++#if !NO_VIDEO
352.11987 ++	sna->render.video = gen9_render_video;
352.11988 ++#endif
352.11989 ++
352.11990 ++#if !NO_COPY_BOXES
352.11991 ++	sna->render.copy_boxes = gen9_render_copy_boxes;
352.11992 ++#endif
352.11993 ++#if !NO_COPY
352.11994 ++	sna->render.copy = gen9_render_copy;
352.11995 ++#endif
352.11996 ++
352.11997 ++#if !NO_FILL_BOXES
352.11998 ++	sna->render.fill_boxes = gen9_render_fill_boxes;
352.11999 ++#endif
352.12000 ++#if !NO_FILL
352.12001 ++	sna->render.fill = gen9_render_fill;
352.12002 ++#endif
352.12003 ++#if !NO_FILL_ONE
352.12004 ++	sna->render.fill_one = gen9_render_fill_one;
352.12005 ++#endif
352.12006 ++#if !NO_FILL_CLEAR
352.12007 ++	sna->render.clear = gen9_render_clear;
352.12008 ++#endif
352.12009 ++
352.12010 ++	sna->render.flush = gen9_render_flush;
352.12011 ++	sna->render.reset = gen9_render_reset;
352.12012 ++	sna->render.fini = gen9_render_fini;
352.12013 ++
352.12014 ++	sna->render.max_3d_size = GEN9_MAX_SIZE;
352.12015 ++	sna->render.max_3d_pitch = 1 << 18;
352.12016 ++	return sna->render_state.gen9.info->name;
352.12017 ++}
352.12018 +diff --git a/src/sna/gen9_render.h b/src/sna/gen9_render.h
352.12019 +new file mode 100644
352.12020 +index 00000000..e3cb3f93
352.12021 +--- /dev/null
352.12022 ++++ b/src/sna/gen9_render.h
352.12023 +@@ -0,0 +1,1130 @@
352.12024 ++#ifndef GEN9_RENDER_H
352.12025 ++#define GEN9_RENDER_H
352.12026 ++
352.12027 ++#define INTEL_MASK(high, low) (((1 << ((high) - (low) + 1)) - 1) << (low))
352.12028 ++
352.12029 ++#define GEN9_3D(pipeline,op,sub) \
352.12030 ++	((3 << 29) | ((pipeline) << 27) | ((op) << 24) | ((sub) << 16))
352.12031 ++
352.12032 ++#define GEN9_STATE_BASE_ADDRESS			GEN9_3D(0, 1, 1)
352.12033 ++# define BASE_ADDRESS_MODIFY			(1 << 0)
352.12034 ++
352.12035 ++#define GEN9_STATE_SIP				GEN9_3D(0, 1, 2)
352.12036 ++
352.12037 ++#define GEN9_3DSTATE_VF_STATISTICS		GEN9_3D(1, 0, 0xb)
352.12038 ++#define GEN9_PIPELINE_SELECT			GEN9_3D(1, 1, 4)
352.12039 ++# define PIPELINE_SELECT_3D		0
352.12040 ++# define PIPELINE_SELECT_MEDIA		1
352.12041 ++#define PIPELINE_SELECTION_MASK            (3 << 8)
352.12042 ++
352.12043 ++#define GEN9_MEDIA_STATE_POINTERS		GEN9_3D(2, 0, 0)
352.12044 ++#define GEN9_MEDIA_OBJECT			GEN9_3D(2, 1, 0)
352.12045 ++
352.12046 ++#define GEN9_3DSTATE_CLEAR_PARAMS               GEN9_3D(3, 0, 0x04)
352.12047 ++#define GEN9_3DSTATE_DEPTH_BUFFER               GEN9_3D(3, 0, 0x05)
352.12048 ++# define DEPTH_BUFFER_TYPE_SHIFT	29
352.12049 ++# define DEPTH_BUFFER_FORMAT_SHIFT	18
352.12050 ++
352.12051 ++#define GEN9_3DSTATE_STENCIL_BUFFER		GEN9_3D(3, 0, 0x06)
352.12052 ++#define GEN9_3DSTATE_HIER_DEPTH_BUFFER		GEN9_3D(3, 0, 0x07)
352.12053 ++#define GEN9_3DSTATE_VERTEX_BUFFERS		GEN9_3D(3, 0, 0x08)
352.12054 ++# define VB_INDEX_SHIFT			26
352.12055 ++# define VB_MODIFY_ENABLE		(1 << 14)
352.12056 ++#define GEN9_3DSTATE_VERTEX_ELEMENTS		GEN9_3D(3, 0, 0x09)
352.12057 ++# define VE_INDEX_SHIFT		26
352.12058 ++# define VE_VALID					(1 << 25)
352.12059 ++# define VE_FORMAT_SHIFT				16
352.12060 ++# define VE_OFFSET_SHIFT				0
352.12061 ++# define VE_COMPONENT_0_SHIFT			28
352.12062 ++# define VE_COMPONENT_1_SHIFT			24
352.12063 ++# define VE_COMPONENT_2_SHIFT			20
352.12064 ++# define VE_COMPONENT_3_SHIFT			16
352.12065 ++#define GEN9_3DSTATE_INDEX_BUFFER		GEN9_3D(3, 0, 0x0a)
352.12066 ++#define GEN9_3DSTATE_VF				GEN9_3D(3, 0, 0x0c)
352.12067 ++
352.12068 ++#define GEN9_3DSTATE_MULTISAMPLE		GEN9_3D(3, 0, 0x0d)
352.12069 ++/* DW1 */
352.12070 ++# define MULTISAMPLE_PIXEL_LOCATION_CENTER		(0 << 4)
352.12071 ++# define MULTISAMPLE_PIXEL_LOCATION_UPPER_LEFT	(1 << 4)
352.12072 ++# define MULTISAMPLE_NUMSAMPLES_1			(0 << 1)
352.12073 ++# define MULTISAMPLE_NUMSAMPLES_4			(2 << 1)
352.12074 ++# define MULTISAMPLE_NUMSAMPLES_8			(3 << 1)
352.12075 ++
352.12076 ++#define GEN9_3DSTATE_CC_STATE_POINTERS		GEN9_3D(3, 0, 0x0e)
352.12077 ++#define GEN9_3DSTATE_SCISSOR_STATE_POINTERS	GEN9_3D(3, 0, 0x0f)
352.12078 ++
352.12079 ++#define GEN9_3DSTATE_VS				GEN9_3D(3, 0, 0x10)
352.12080 ++#define GEN9_3DSTATE_GS				GEN9_3D(3, 0, 0x11)
352.12081 ++#define GEN9_3DSTATE_CLIP			GEN9_3D(3, 0, 0x12)
352.12082 ++#define GEN9_3DSTATE_SF				GEN9_3D(3, 0, 0x13)
352.12083 ++# define SF_TRI_PROVOKE_SHIFT		29
352.12084 ++# define SF_LINE_PROVOKE_SHIFT		27
352.12085 ++# define SF_FAN_PROVOKE_SHIFT		25
352.12086 ++
352.12087 ++#define GEN9_3DSTATE_WM				GEN9_3D(3, 0, 0x14)
352.12088 ++/* DW1 */
352.12089 ++# define WM_STATISTICS_ENABLE                              (1 << 31)
352.12090 ++# define WM_DEPTH_CLEAR                                    (1 << 30)
352.12091 ++# define WM_DEPTH_RESOLVE                                  (1 << 28)
352.12092 ++# define WM_HIERARCHICAL_DEPTH_RESOLVE                     (1 << 27)
352.12093 ++# define WM_KILL_ENABLE                                    (1 << 25)
352.12094 ++# define WM_POSITION_ZW_PIXEL                              (0 << 17)
352.12095 ++# define WM_POSITION_ZW_CENTROID                           (2 << 17)
352.12096 ++# define WM_POSITION_ZW_SAMPLE                             (3 << 17)
352.12097 ++# define WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC              (1 << 16)
352.12098 ++# define WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC            (1 << 15)
352.12099 ++# define WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC               (1 << 14)
352.12100 ++# define WM_PERSPECTIVE_SAMPLE_BARYCENTRIC                 (1 << 13)
352.12101 ++# define WM_PERSPECTIVE_CENTROID_BARYCENTRIC               (1 << 12)
352.12102 ++# define WM_PERSPECTIVE_PIXEL_BARYCENTRIC                  (1 << 11)
352.12103 ++# define WM_LINE_END_CAP_AA_WIDTH_0_5                      (0 << 8)
352.12104 ++# define WM_LINE_END_CAP_AA_WIDTH_1_0                      (1 << 8)
352.12105 ++# define WM_LINE_END_CAP_AA_WIDTH_2_0                      (2 << 8)
352.12106 ++# define WM_LINE_END_CAP_AA_WIDTH_4_0                      (3 << 8)
352.12107 ++# define WM_LINE_AA_WIDTH_0_5                              (0 << 6)
352.12108 ++# define WM_LINE_AA_WIDTH_1_0                              (1 << 6)
352.12109 ++# define WM_LINE_AA_WIDTH_2_0                              (2 << 6)
352.12110 ++# define WM_LINE_AA_WIDTH_4_0                              (3 << 6)
352.12111 ++# define WM_POLYGON_STIPPLE_ENABLE                         (1 << 4)
352.12112 ++# define WM_LINE_STIPPLE_ENABLE                            (1 << 3)
352.12113 ++# define WM_POINT_RASTRULE_UPPER_RIGHT                     (1 << 2)
352.12114 ++# define WM_MSRAST_OFF_PIXEL                               (0 << 0)
352.12115 ++# define WM_MSRAST_OFF_PATTERN                             (1 << 0)
352.12116 ++# define WM_MSRAST_ON_PIXEL                                (2 << 0)
352.12117 ++# define WM_MSRAST_ON_PATTERN                              (3 << 0)
352.12118 ++
352.12119 ++#define GEN9_3DSTATE_CONSTANT_VS		GEN9_3D(3, 0, 0x15)
352.12120 ++#define GEN9_3DSTATE_CONSTANT_GS		GEN9_3D(3, 0, 0x16)
352.12121 ++#define GEN9_3DSTATE_CONSTANT_PS		GEN9_3D(3, 0, 0x17)
352.12122 ++
352.12123 ++#define GEN9_3DSTATE_SAMPLE_MASK		GEN9_3D(3, 0, 0x18)
352.12124 ++
352.12125 ++#define GEN9_3DSTATE_CONSTANT_HS                GEN9_3D(3, 0, 0x19)
352.12126 ++#define GEN9_3DSTATE_CONSTANT_DS                GEN9_3D(3, 0, 0x1a)
352.12127 ++
352.12128 ++#define GEN9_3DSTATE_HS                         GEN9_3D(3, 0, 0x1b)
352.12129 ++#define GEN9_3DSTATE_TE                         GEN9_3D(3, 0, 0x1c)
352.12130 ++#define GEN9_3DSTATE_DS                         GEN9_3D(3, 0, 0x1d)
352.12131 ++#define GEN9_3DSTATE_STREAMOUT                  GEN9_3D(3, 0, 0x1e)
352.12132 ++
352.12133 ++#define GEN9_3DSTATE_SBE                        GEN9_3D(3, 0, 0x1f)
352.12134 ++/* DW1 */
352.12135 ++# define SBE_FORCE_VERTEX_URB_READ_LENGTH  (1<<29)
352.12136 ++# define SBE_FORCE_VERTEX_URB_READ_OFFSET  (1<<28)
352.12137 ++# define SBE_NUM_OUTPUTS_SHIFT             22
352.12138 ++# define SBE_SWIZZLE_ENABLE                (1 << 21)
352.12139 ++# define SBE_POINT_SPRITE_LOWERLEFT        (1 << 20)
352.12140 ++# define SBE_URB_ENTRY_READ_LENGTH_SHIFT   11
352.12141 ++# define SBE_URB_ENTRY_READ_OFFSET_SHIFT   5
352.12142 ++#define SBE_ACTIVE_COMPONENT_NONE          0
352.12143 ++#define SBE_ACTIVE_COMPONENT_XY            1 
352.12144 ++#define SBE_ACTIVE_COMPONENT_XYZ           2
352.12145 ++#define SBE_ACTIVE_COMPONENT_XYZW          3
352.12146 ++
352.12147 ++
352.12148 ++#define GEN9_3DSTATE_PS                                 GEN9_3D(3, 0, 0x20)
352.12149 ++/* DW1:DW2 kernel pointer */
352.12150 ++/* DW3 */
352.12151 ++# define PS_SPF_MODE                               (1 << 31)
352.12152 ++# define PS_VECTOR_MASK_ENABLE                     (1 << 30)
352.12153 ++# define PS_SAMPLER_COUNT_SHIFT                    27
352.12154 ++# define PS_BINDING_TABLE_ENTRY_COUNT_SHIFT        18
352.12155 ++# define PS_FLOATING_POINT_MODE_IEEE_754           (0 << 16)
352.12156 ++# define PS_FLOATING_POINT_MODE_ALT                (1 << 16)
352.12157 ++/* DW4:DW5: scratch space */
352.12158 ++/* DW6 */
352.12159 ++# define PS_MAX_THREADS_SHIFT                      23
352.12160 ++# define PS_MAX_THREADS                            (63 << PS_MAX_THREADS_SHIFT)
352.12161 ++# define PS_PUSH_CONSTANT_ENABLE                   (1 << 11)
352.12162 ++# define PS_RENDER_TARGET_CLEAR			   (1 << 8)
352.12163 ++# define PS_RENDER_TARGET_RESOLVE		   (1 << 6)
352.12164 ++# define PS_POSOFFSET_NONE                         (0 << 3)
352.12165 ++# define PS_POSOFFSET_CENTROID                     (2 << 3)
352.12166 ++# define PS_POSOFFSET_SAMPLE                       (3 << 3)
352.12167 ++# define PS_32_DISPATCH_ENABLE                     (1 << 2)
352.12168 ++# define PS_16_DISPATCH_ENABLE                     (1 << 1)
352.12169 ++# define PS_8_DISPATCH_ENABLE                      (1 << 0)
352.12170 ++/* DW7 */
352.12171 ++# define PS_DISPATCH_START_GRF_SHIFT_0             16
352.12172 ++# define PS_DISPATCH_START_GRF_SHIFT_1             8
352.12173 ++# define PS_DISPATCH_START_GRF_SHIFT_2             0
352.12174 ++/* DW8:D9: kernel 1 pointer */
352.12175 ++/* DW10:D11: kernel 2 pointer */
352.12176 ++
352.12177 ++#define GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP      GEN9_3D(3, 0, 0x21)
352.12178 ++#define GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_CC         GEN9_3D(3, 0, 0x23)
352.12179 ++
352.12180 ++#define GEN9_3DSTATE_BLEND_STATE_POINTERS               GEN9_3D(3, 0, 0x24)
352.12181 ++
352.12182 ++#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_VS          GEN9_3D(3, 0, 0x26)
352.12183 ++#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_HS          GEN9_3D(3, 0, 0x27)
352.12184 ++#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_DS          GEN9_3D(3, 0, 0x28)
352.12185 ++#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_GS          GEN9_3D(3, 0, 0x29)
352.12186 ++#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_PS          GEN9_3D(3, 0, 0x2a)
352.12187 ++
352.12188 ++#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_VS          GEN9_3D(3, 0, 0x2b)
352.12189 ++#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_HS          GEN9_3D(3, 0, 0x2c)
352.12190 ++#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_DS          GEN9_3D(3, 0, 0x2d)
352.12191 ++#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_GS          GEN9_3D(3, 0, 0x2e)
352.12192 ++#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_PS          GEN9_3D(3, 0, 0x2f)
352.12193 ++
352.12194 ++#define GEN9_3DSTATE_URB_VS                             GEN9_3D(3, 0, 0x30)
352.12195 ++#define GEN9_3DSTATE_URB_HS                             GEN9_3D(3, 0, 0x31)
352.12196 ++#define GEN9_3DSTATE_URB_DS                             GEN9_3D(3, 0, 0x32)
352.12197 ++#define GEN9_3DSTATE_URB_GS                             GEN9_3D(3, 0, 0x33)
352.12198 ++/* DW1 */
352.12199 ++# define URB_ENTRY_NUMBER_SHIFT            0
352.12200 ++# define URB_ENTRY_SIZE_SHIFT              16
352.12201 ++# define URB_STARTING_ADDRESS_SHIFT        25
352.12202 ++
352.12203 ++#define GEN9_3DSTATE_GATHER_CONSTANT_VS             GEN9_3D(3, 0, 0x34)
352.12204 ++#define GEN9_3DSTATE_GATHER_CONSTANT_GS             GEN9_3D(3, 0, 0x35)
352.12205 ++#define GEN9_3DSTATE_GATHER_CONSTANT_HS             GEN9_3D(3, 0, 0x36)
352.12206 ++#define GEN9_3DSTATE_GATHER_CONSTANT_DS             GEN9_3D(3, 0, 0x37)
352.12207 ++#define GEN9_3DSTATE_GATHER_CONSTANT_PS             GEN9_3D(3, 0, 0x38)
352.12208 ++
352.12209 ++#define GEN9_3DSTATE_DX9_CONSTANTF_VS             GEN9_3D(3, 0, 0x39)
352.12210 ++#define GEN9_3DSTATE_DX9_CONSTANTF_PS             GEN9_3D(3, 0, 0x3a)
352.12211 ++#define GEN9_3DSTATE_DX9_CONSTANTI_VS             GEN9_3D(3, 0, 0x3b)
352.12212 ++#define GEN9_3DSTATE_DX9_CONSTANTI_PS             GEN9_3D(3, 0, 0x3c)
352.12213 ++#define GEN9_3DSTATE_DX9_CONSTANTB_VS             GEN9_3D(3, 0, 0x3d)
352.12214 ++#define GEN9_3DSTATE_DX9_CONSTANTB_PS             GEN9_3D(3, 0, 0x3e)
352.12215 ++#define GEN9_3DSTATE_DX9_LOCAL_VALID_VS           GEN9_3D(3, 0, 0x3f)
352.12216 ++#define GEN9_3DSTATE_DX9_LOCAL_VALID_PS           GEN9_3D(3, 0, 0x40)
352.12217 ++#define GEN9_3DSTATE_DX9_GENERATE_ACTIVE_VS       GEN9_3D(3, 0, 0x41)
352.12218 ++#define GEN9_3DSTATE_DX9_GENERATE_ACTIVE_PS       GEN9_3D(3, 0, 0x42)
352.12219 ++
352.12220 ++#define GEN9_3DSTATE_BINDING_TABLE_EDIT_VS       GEN9_3D(3, 0, 0x43)
352.12221 ++#define GEN9_3DSTATE_BINDING_TABLE_EDIT_GS       GEN9_3D(3, 0, 0x44)
352.12222 ++#define GEN9_3DSTATE_BINDING_TABLE_EDIT_HS       GEN9_3D(3, 0, 0x45)
352.12223 ++#define GEN9_3DSTATE_BINDING_TABLE_EDIT_DS       GEN9_3D(3, 0, 0x46)
352.12224 ++#define GEN9_3DSTATE_BINDING_TABLE_EDIT_PS       GEN9_3D(3, 0, 0x47)
352.12225 ++
352.12226 ++#define GEN9_3DSTATE_VF_INSTANCING		GEN9_3D(3, 0, 0x49)
352.12227 ++#define GEN9_3DSTATE_VF_SGVS			GEN9_3D(3, 0, 0x4a)
352.12228 ++# define SGVS_ENABLE_INSTANCE_ID			(1 << 31)
352.12229 ++# define SGVS_INSTANCE_ID_COMPONENT_SHIFT		29
352.12230 ++# define SGVS_INSTANCE_ID_ELEMENT_OFFSET_SHIFT	16
352.12231 ++# define SGVS_ENABLE_VERTEX_ID			(1 << 15)
352.12232 ++# define SGVS_VERTEX_ID_COMPONENT_SHIFT            13
352.12233 ++# define SGVS_VERTEX_ID_ELEMENT_OFFSET_SHIFT	0
352.12234 ++#define GEN9_3DSTATE_VF_TOPOLOGY		GEN9_3D(3, 0, 0x4b)
352.12235 ++# define POINTLIST         0x01
352.12236 ++# define LINELIST          0x02
352.12237 ++# define LINESTRIP         0x03
352.12238 ++# define TRILIST           0x04
352.12239 ++# define TRISTRIP          0x05
352.12240 ++# define TRIFAN            0x06
352.12241 ++# define QUADLIST          0x07
352.12242 ++# define QUADSTRIP         0x08
352.12243 ++# define LINELIST_ADJ      0x09
352.12244 ++# define LINESTRIP_ADJ     0x0A
352.12245 ++# define TRILIST_ADJ       0x0B
352.12246 ++# define TRISTRIP_ADJ      0x0C
352.12247 ++# define TRISTRIP_REVERSE  0x0D
352.12248 ++# define POLYGON           0x0E
352.12249 ++# define RECTLIST          0x0F
352.12250 ++# define LINELOOP          0x10
352.12251 ++# define POINTLIST_BF      0x11
352.12252 ++# define LINESTRIP_CONT    0x12
352.12253 ++# define LINESTRIP_BF      0x13
352.12254 ++# define LINESTRIP_CONT_BF 0x14
352.12255 ++# define TRIFAN_NOSTIPPLE  0x15
352.12256 ++
352.12257 ++#define GEN9_3DSTATE_WM_CHROMAKEY		GEN9_3D(3, 0, 0x4c)
352.12258 ++
352.12259 ++#define GEN9_3DSTATE_PS_BLEND				GEN9_3D(3, 0, 0x4d)
352.12260 ++# define PS_BLEND_ALPHA_TO_COVERAGE_ENABLE		(1 << 31)
352.12261 ++# define PS_BLEND_HAS_WRITEABLE_RT			(1 << 30)
352.12262 ++# define PS_BLEND_COLOR_BLEND_ENABLE			(1 << 29)
352.12263 ++# define PS_BLEND_SRC_ALPHA_SHIFT			24
352.12264 ++# define PS_BLEND_DST_ALPHA_SHIFT			19
352.12265 ++# define PS_BLEND_SRC_SHIFT				14
352.12266 ++# define PS_BLEND_DST_SHIFT				9
352.12267 ++# define PS_BLEND_ALPHA_TEST_ENABLE			(1 << 8)
352.12268 ++# define PS_BLEND_INDEPENDENT_ALPHA_BLEND_ENABLE	(1 << 7)
352.12269 ++
352.12270 ++#define GEN9_3DSTATE_WM_DEPTH_STENCIL		GEN9_3D(3, 0, 0x4e)
352.12271 ++/* DW1 */
352.12272 ++# define WM_DS_STENCIL_TEST_MASK_MASK		INTEL_MASK(31, 24)
352.12273 ++# define WM_DS_STENCIL_TEST_MASK_SHIFT		24
352.12274 ++# define WM_DS_STENCIL_WRITE_MASK_MASK		INTEL_MASK(23, 16)
352.12275 ++# define WM_DS_STENCIL_WRITE_MASK_SHIFT		16
352.12276 ++# define WM_DS_BF_STENCIL_TEST_MASK_MASK		INTEL_MASK(15, 8)
352.12277 ++# define WM_DS_BF_STENCIL_TEST_MASK_SHIFT		8
352.12278 ++# define WM_DS_BF_STENCIL_WRITE_MASK_MASK		INTEL_MASK(7, 0)
352.12279 ++# define WM_DS_DEPTH_FUNC_SHIFT			5
352.12280 ++# define WM_DS_DOUBLE_SIDED_STENCIL_ENABLE		(1 << 4)
352.12281 ++# define WM_DS_STENCIL_TEST_ENABLE			(1 << 3)
352.12282 ++# define WM_DS_STENCIL_BUFFER_WRITE_ENABLE		(1 << 2)
352.12283 ++# define WM_DS_DEPTH_TEST_ENABLE			(1 << 1)
352.12284 ++# define WM_DS_DEPTH_BUFFER_WRITE_ENABLE		(1 << 0)
352.12285 ++/* DW2 */
352.12286 ++# define WM_DS_STENCIL_TEST_MASK_MASK		INTEL_MASK(31, 24)
352.12287 ++# define WM_DS_STENCIL_TEST_MASK_SHIFT		24
352.12288 ++# define WM_DS_STENCIL_WRITE_MASK_MASK		INTEL_MASK(23, 16)
352.12289 ++# define WM_DS_STENCIL_WRITE_MASK_SHIFT		16
352.12290 ++# define WM_DS_BF_STENCIL_TEST_MASK_MASK		INTEL_MASK(15, 8)
352.12291 ++# define WM_DS_BF_STENCIL_TEST_MASK_SHIFT		8
352.12292 ++# define WM_DS_BF_STENCIL_WRITE_MASK_MASK		INTEL_MASK(7, 0)
352.12293 ++# define WM_DS_BF_STENCIL_WRITE_MASK_SHIFT		0
352.12294 ++
352.12295 ++#define GEN9_3DSTATE_PS_EXTRA		GEN9_3D(3, 0, 0x4f)
352.12296 ++# define PSX_PIXEL_SHADER_VALID                    (1 << 31)
352.12297 ++# define PSX_PIXEL_SHADER_NO_RT_WRITE              (1 << 30)
352.12298 ++# define PSX_OMASK_TO_RENDER_TARGET                (1 << 29)
352.12299 ++# define PSX_KILL_ENABLE                           (1 << 28)
352.12300 ++# define PSX_PSCDEPTH_OFF                          (0 << 26)
352.12301 ++# define PSX_PSCDEPTH_ON                           (1 << 26)
352.12302 ++# define PSX_PSCDEPTH_ON_GE                        (2 << 26)
352.12303 ++# define PSX_PSCDEPTH_ON_LE                        (3 << 26)
352.12304 ++# define PSX_FORCE_COMPUTED_DEPTH                  (1 << 25)
352.12305 ++# define PSX_USES_SOURCE_DEPTH                     (1 << 24)
352.12306 ++# define PSX_USES_SOURCE_W                         (1 << 23)
352.12307 ++# define PSX_ATTRIBUTE_ENABLE                      (1 << 8)
352.12308 ++# define PSX_SHADER_DISABLES_ALPHA_TO_COVERAGE     (1 << 7)
352.12309 ++# define PSX_SHADER_IS_PER_SAMPLE                  (1 << 6)
352.12310 ++# define PSX_SHADER_HAS_UAV                        (1 << 2)
352.12311 ++# define PSX_SHADER_USES_INPUT_COVERAGE_MASK       (1 << 1)
352.12312 ++
352.12313 ++#define GEN9_3DSTATE_RASTER		GEN9_3D(3, 0, 0x50)
352.12314 ++/* DW1 */
352.12315 ++# define RASTER_FRONT_WINDING_CCW                  (1 << 21)
352.12316 ++# define RASTER_CULL_BOTH                          (0 << 16)
352.12317 ++# define RASTER_CULL_NONE                          (1 << 16)
352.12318 ++# define RASTER_CULL_FRONT                         (2 << 16)
352.12319 ++# define RASTER_CULL_BACK                          (3 << 16)
352.12320 ++# define RASTER_SMOOTH_POINT_ENABLE                (1 << 13)
352.12321 ++# define RASTER_LINE_AA_ENABLE                     (1 << 2)
352.12322 ++# define RASTER_VIEWPORT_Z_CLIP_TEST_ENABLE        (1 << 0)
352.12323 ++
352.12324 ++#define GEN9_3DSTATE_SBE_SWIZ		GEN9_3D(3, 0, 0x51)
352.12325 ++#define GEN9_3DSTATE_WM_HZ_OP		GEN9_3D(3, 0, 0x52)
352.12326 ++
352.12327 ++#define GEN9_3DSTATE_COMPONENT_PACKING          GEN6_3D(3, 0, 0x55)
352.12328 ++
352.12329 ++
352.12330 ++
352.12331 ++#define GEN9_3DSTATE_DRAWING_RECTANGLE		GEN9_3D(3, 1, 0x00)
352.12332 ++#define GEN9_3DSTATE_SAMPLER_PALETTE_LOAD	GEN9_3D(3, 1, 0x02)
352.12333 ++#define GEN9_3DSTATE_CHROMA_KEY			GEN9_3D(3, 1, 0x04)
352.12334 ++
352.12335 ++#define GEN9_3DSTATE_POLY_STIPPLE_OFFSET	GEN9_3D(3, 1, 0x06)
352.12336 ++#define GEN9_3DSTATE_POLY_STIPPLE_PATTERN	GEN9_3D(3, 1, 0x07)
352.12337 ++#define GEN9_3DSTATE_LINE_STIPPLE		GEN9_3D(3, 1, 0x08)
352.12338 ++#define GEN9_3DSTATE_AA_LINE_PARAMS		GEN9_3D(3, 1, 0x0a)
352.12339 ++#define GEN9_3DSTATE_SAMPLER_PALETTE_LOAD1	GEN9_3D(3, 1, 0x0c)
352.12340 ++#define GEN9_3DSTATE_MONOFILTER_SIZE		GEN9_3D(3, 1, 0x11)
352.12341 ++#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_VS	GEN9_3D(3, 1, 0x12)
352.12342 ++#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_HS	GEN9_3D(3, 1, 0x13)
352.12343 ++#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_DS	GEN9_3D(3, 1, 0x14)
352.12344 ++#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_GS	GEN9_3D(3, 1, 0x15)
352.12345 ++#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_PS	GEN9_3D(3, 1, 0x16)
352.12346 ++/* DW1 */
352.12347 ++# define PUSH_CONSTANT_BUFFER_OFFSET_SHIFT 16
352.12348 ++# define PUSH_CONSTANT_BUFFER_SIZE_SHIFT 0
352.12349 ++
352.12350 ++#define GEN9_3DSTATE_SO_DECL_LIST		GEN9_3D(3, 1, 0x17)
352.12351 ++#define GEN9_3DSTATE_SO_BUFFER			GEN9_3D(3, 1, 0x18)
352.12352 ++#define GEN9_3DSTATE_BINDING_TABLE_POOL_ALLOC	GEN9_3D(3, 1, 0x19)
352.12353 ++#define GEN9_3DSTATE_GATHER_BUFFER_POOL_ALLOC	GEN9_3D(3, 1, 0x1a)
352.12354 ++#define GEN9_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC	GEN9_3D(3, 1, 0x1b)
352.12355 ++#define GEN9_3DSTATE_SAMPLE_PATTERN		GEN9_3D(3, 1, 0x1c)
352.12356 ++
352.12357 ++
352.12358 ++/* for GEN9_PIPE_CONTROL */
352.12359 ++#define GEN9_PIPE_CONTROL		GEN9_3D(3, 2, 0)
352.12360 ++#define PIPE_CONTROL_CS_STALL      (1 << 20)
352.12361 ++#define PIPE_CONTROL_NOWRITE       (0 << 14)
352.12362 ++#define PIPE_CONTROL_WRITE_QWORD   (1 << 14)
352.12363 ++#define PIPE_CONTROL_WRITE_DEPTH   (2 << 14)
352.12364 ++#define PIPE_CONTROL_WRITE_TIME    (3 << 14)
352.12365 ++#define PIPE_CONTROL_DEPTH_STALL   (1 << 13)
352.12366 ++#define PIPE_CONTROL_WC_FLUSH      (1 << 12)
352.12367 ++#define PIPE_CONTROL_IS_FLUSH      (1 << 11)
352.12368 ++#define PIPE_CONTROL_TC_FLUSH      (1 << 10)
352.12369 ++#define PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
352.12370 ++#define PIPE_CONTROL_FLUSH         (1 << 7)
352.12371 ++#define PIPE_CONTROL_GLOBAL_GTT    (1 << 2)
352.12372 ++#define PIPE_CONTROL_LOCAL_PGTT    (0 << 2)
352.12373 ++#define PIPE_CONTROL_STALL_AT_SCOREBOARD   (1 << 1)
352.12374 ++#define PIPE_CONTROL_DEPTH_CACHE_FLUSH	(1 << 0)
352.12375 ++
352.12376 ++
352.12377 ++#define GEN9_3DPRIMITIVE			GEN9_3D(3, 3, 0)
352.12378 ++
352.12379 ++/* 3DPRIMITIVE bits */
352.12380 ++#define VERTEX_SEQUENTIAL (0 << 15)
352.12381 ++#define VERTEX_RANDOM	  (1 << 15)
352.12382 ++
352.12383 ++#define ANISORATIO_2     0
352.12384 ++#define ANISORATIO_4     1
352.12385 ++#define ANISORATIO_6     2
352.12386 ++#define ANISORATIO_8     3
352.12387 ++#define ANISORATIO_10    4
352.12388 ++#define ANISORATIO_12    5
352.12389 ++#define ANISORATIO_14    6
352.12390 ++#define ANISORATIO_16    7
352.12391 ++
352.12392 ++#define BLENDFACTOR_ONE                 0x1
352.12393 ++#define BLENDFACTOR_SRC_COLOR           0x2
352.12394 ++#define BLENDFACTOR_SRC_ALPHA           0x3
352.12395 ++#define BLENDFACTOR_DST_ALPHA           0x4
352.12396 ++#define BLENDFACTOR_DST_COLOR           0x5
352.12397 ++#define BLENDFACTOR_SRC_ALPHA_SATURATE  0x6
352.12398 ++#define BLENDFACTOR_CONST_COLOR         0x7
352.12399 ++#define BLENDFACTOR_CONST_ALPHA         0x8
352.12400 ++#define BLENDFACTOR_SRC1_COLOR          0x9
352.12401 ++#define BLENDFACTOR_SRC1_ALPHA          0x0A
352.12402 ++#define BLENDFACTOR_ZERO                0x11
352.12403 ++#define BLENDFACTOR_INV_SRC_COLOR       0x12
352.12404 ++#define BLENDFACTOR_INV_SRC_ALPHA       0x13
352.12405 ++#define BLENDFACTOR_INV_DST_ALPHA       0x14
352.12406 ++#define BLENDFACTOR_INV_DST_COLOR       0x15
352.12407 ++#define BLENDFACTOR_INV_CONST_COLOR     0x17
352.12408 ++#define BLENDFACTOR_INV_CONST_ALPHA     0x18
352.12409 ++#define BLENDFACTOR_INV_SRC1_COLOR      0x19
352.12410 ++#define BLENDFACTOR_INV_SRC1_ALPHA      0x1A
352.12411 ++
352.12412 ++#define BLENDFUNCTION_ADD               0
352.12413 ++#define BLENDFUNCTION_SUBTRACT          1
352.12414 ++#define BLENDFUNCTION_REVERSE_SUBTRACT  2
352.12415 ++#define GEN9_BLENDFUNCTION_MIN               3
352.12416 ++#define BLENDFUNCTION_MAX               4
352.12417 ++
352.12418 ++#define ALPHATEST_FORMAT_UNORM8         0
352.12419 ++#define ALPHATEST_FORMAT_FLOAT32        1
352.12420 ++
352.12421 ++#define CHROMAKEY_KILL_ON_ANY_MATCH  0
352.12422 ++#define CHROMAKEY_REPLACE_BLACK      1
352.12423 ++
352.12424 ++#define CLIP_API_OGL     0
352.12425 ++#define CLIP_API_DX      1
352.12426 ++
352.12427 ++#define CLIPMODE_NORMAL              0
352.12428 ++#define CLIPMODE_CLIP_ALL            1
352.12429 ++#define CLIPMODE_CLIP_NON_REJECTED   2
352.12430 ++#define CLIPMODE_REJECT_ALL          3
352.12431 ++#define CLIPMODE_ACCEPT_ALL          4
352.12432 ++
352.12433 ++#define CLIP_NDCSPACE     0
352.12434 ++#define CLIP_SCREENSPACE  1
352.12435 ++
352.12436 ++#define COMPAREFUNCTION_ALWAYS       0
352.12437 ++#define COMPAREFUNCTION_NEVER        1
352.12438 ++#define COMPAREFUNCTION_LESS         2
352.12439 ++#define COMPAREFUNCTION_EQUAL        3
352.12440 ++#define COMPAREFUNCTION_LEQUAL       4
352.12441 ++#define COMPAREFUNCTION_GREATER      5
352.12442 ++#define COMPAREFUNCTION_NOTEQUAL     6
352.12443 ++#define COMPAREFUNCTION_GEQUAL       7
352.12444 ++
352.12445 ++#define COVERAGE_PIXELS_HALF     0
352.12446 ++#define COVERAGE_PIXELS_1        1
352.12447 ++#define COVERAGE_PIXELS_2        2
352.12448 ++#define COVERAGE_PIXELS_4        3
352.12449 ++
352.12450 ++#define DEPTHFORMAT_D32_FLOAT_S8X24_UINT     0
352.12451 ++#define DEPTHFORMAT_D32_FLOAT                1
352.12452 ++#define DEPTHFORMAT_D24_UNORM_S8_UINT        2
352.12453 ++#define DEPTHFORMAT_D16_UNORM                5
352.12454 ++
352.12455 ++#define FLOATING_POINT_IEEE_754        0
352.12456 ++#define FLOATING_POINT_NON_IEEE_754    1
352.12457 ++
352.12458 ++#define INDEX_BYTE     0
352.12459 ++#define INDEX_WORD     1
352.12460 ++#define INDEX_DWORD    2
352.12461 ++
352.12462 ++#define LOGICOPFUNCTION_CLEAR            0
352.12463 ++#define LOGICOPFUNCTION_NOR              1
352.12464 ++#define LOGICOPFUNCTION_AND_INVERTED     2
352.12465 ++#define LOGICOPFUNCTION_COPY_INVERTED    3
352.12466 ++#define LOGICOPFUNCTION_AND_REVERSE      4
352.12467 ++#define LOGICOPFUNCTION_INVERT           5
352.12468 ++#define LOGICOPFUNCTION_XOR              6
352.12469 ++#define LOGICOPFUNCTION_NAND             7
352.12470 ++#define LOGICOPFUNCTION_AND              8
352.12471 ++#define LOGICOPFUNCTION_EQUIV            9
352.12472 ++#define LOGICOPFUNCTION_NOOP             10
352.12473 ++#define LOGICOPFUNCTION_OR_INVERTED      11
352.12474 ++#define LOGICOPFUNCTION_COPY             12
352.12475 ++#define LOGICOPFUNCTION_OR_REVERSE       13
352.12476 ++#define LOGICOPFUNCTION_OR               14
352.12477 ++#define LOGICOPFUNCTION_SET              15
352.12478 ++
352.12479 ++#define MAPFILTER_NEAREST	0x0
352.12480 ++#define MAPFILTER_LINEAR	0x1
352.12481 ++#define MAPFILTER_ANISOTROPIC	0x2
352.12482 ++#define MAPFILTER_FLEXIBLE 	0x3
352.12483 ++#define MAPFILTER_MONO 		0x6
352.12484 ++
352.12485 ++#define MIPFILTER_NONE        0
352.12486 ++#define MIPFILTER_NEAREST     1
352.12487 ++#define MIPFILTER_LINEAR      3
352.12488 ++
352.12489 ++#define POLYGON_FRONT_FACING     0
352.12490 ++#define POLYGON_BACK_FACING      1
352.12491 ++
352.12492 ++#define PREFILTER_ALWAYS     0x0
352.12493 ++#define PREFILTER_NEVER      0x1
352.12494 ++#define PREFILTER_LESS       0x2
352.12495 ++#define PREFILTER_EQUAL      0x3
352.12496 ++#define PREFILTER_LEQUAL     0x4
352.12497 ++#define PREFILTER_GREATER    0x5
352.12498 ++#define PREFILTER_NOTEQUAL   0x6
352.12499 ++#define PREFILTER_GEQUAL     0x7
352.12500 ++
352.12501 ++#define RASTRULE_UPPER_LEFT  0
352.12502 ++#define RASTRULE_UPPER_RIGHT 1
352.12503 ++
352.12504 ++#define STENCILOP_KEEP               0
352.12505 ++#define STENCILOP_ZERO               1
352.12506 ++#define STENCILOP_REPLACE            2
352.12507 ++#define STENCILOP_INCRSAT            3
352.12508 ++#define STENCILOP_DECRSAT            4
352.12509 ++#define STENCILOP_INCR               5
352.12510 ++#define STENCILOP_DECR               6
352.12511 ++#define STENCILOP_INVERT             7
352.12512 ++
352.12513 ++#define SURFACE_MIPMAPLAYOUT_BELOW   0
352.12514 ++#define SURFACE_MIPMAPLAYOUT_RIGHT   1
352.12515 ++
352.12516 ++#define SURFACEFORMAT_R32G32B32A32_FLOAT             0x000
352.12517 ++#define SURFACEFORMAT_R32G32B32A32_SINT              0x001
352.12518 ++#define SURFACEFORMAT_R32G32B32A32_UINT              0x002
352.12519 ++#define SURFACEFORMAT_R32G32B32A32_UNORM             0x003
352.12520 ++#define SURFACEFORMAT_R32G32B32A32_SNORM             0x004
352.12521 ++#define SURFACEFORMAT_R64G64_FLOAT                   0x005
352.12522 ++#define SURFACEFORMAT_R32G32B32X32_FLOAT             0x006
352.12523 ++#define SURFACEFORMAT_R32G32B32A32_SSCALED           0x007
352.12524 ++#define SURFACEFORMAT_R32G32B32A32_USCALED           0x008
352.12525 ++#define SURFACEFORMAT_R32G32B32_FLOAT                0x040
352.12526 ++#define SURFACEFORMAT_R32G32B32_SINT                 0x041
352.12527 ++#define SURFACEFORMAT_R32G32B32_UINT                 0x042
352.12528 ++#define SURFACEFORMAT_R32G32B32_UNORM                0x043
352.12529 ++#define SURFACEFORMAT_R32G32B32_SNORM                0x044
352.12530 ++#define SURFACEFORMAT_R32G32B32_SSCALED              0x045
352.12531 ++#define SURFACEFORMAT_R32G32B32_USCALED              0x046
352.12532 ++#define SURFACEFORMAT_R16G16B16A16_UNORM             0x080
352.12533 ++#define SURFACEFORMAT_R16G16B16A16_SNORM             0x081
352.12534 ++#define SURFACEFORMAT_R16G16B16A16_SINT              0x082
352.12535 ++#define SURFACEFORMAT_R16G16B16A16_UINT              0x083
352.12536 ++#define SURFACEFORMAT_R16G16B16A16_FLOAT             0x084
352.12537 ++#define SURFACEFORMAT_R32G32_FLOAT                   0x085
352.12538 ++#define SURFACEFORMAT_R32G32_SINT                    0x086
352.12539 ++#define SURFACEFORMAT_R32G32_UINT                    0x087
352.12540 ++#define SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS       0x088
352.12541 ++#define SURFACEFORMAT_X32_TYPELESS_G8X24_UINT        0x089
352.12542 ++#define SURFACEFORMAT_L32A32_FLOAT                   0x08A
352.12543 ++#define SURFACEFORMAT_R32G32_UNORM                   0x08B
352.12544 ++#define SURFACEFORMAT_R32G32_SNORM                   0x08C
352.12545 ++#define SURFACEFORMAT_R64_FLOAT                      0x08D
352.12546 ++#define SURFACEFORMAT_R16G16B16X16_UNORM             0x08E
352.12547 ++#define SURFACEFORMAT_R16G16B16X16_FLOAT             0x08F
352.12548 ++#define SURFACEFORMAT_A32X32_FLOAT                   0x090
352.12549 ++#define SURFACEFORMAT_L32X32_FLOAT                   0x091
352.12550 ++#define SURFACEFORMAT_I32X32_FLOAT                   0x092
352.12551 ++#define SURFACEFORMAT_R16G16B16A16_SSCALED           0x093
352.12552 ++#define SURFACEFORMAT_R16G16B16A16_USCALED           0x094
352.12553 ++#define SURFACEFORMAT_R32G32_SSCALED                 0x095
352.12554 ++#define SURFACEFORMAT_R32G32_USCALED                 0x096
352.12555 ++#define SURFACEFORMAT_B8G8R8A8_UNORM                 0x0C0
352.12556 ++#define SURFACEFORMAT_B8G8R8A8_UNORM_SRGB            0x0C1
352.12557 ++#define SURFACEFORMAT_R10G10B10A2_UNORM              0x0C2
352.12558 ++#define SURFACEFORMAT_R10G10B10A2_UNORM_SRGB         0x0C3
352.12559 ++#define SURFACEFORMAT_R10G10B10A2_UINT               0x0C4
352.12560 ++#define SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM       0x0C5
352.12561 ++#define SURFACEFORMAT_R8G8B8A8_UNORM                 0x0C7
352.12562 ++#define SURFACEFORMAT_R8G8B8A8_UNORM_SRGB            0x0C8
352.12563 ++#define SURFACEFORMAT_R8G8B8A8_SNORM                 0x0C9
352.12564 ++#define SURFACEFORMAT_R8G8B8A8_SINT                  0x0CA
352.12565 ++#define SURFACEFORMAT_R8G8B8A8_UINT                  0x0CB
352.12566 ++#define SURFACEFORMAT_R16G16_UNORM                   0x0CC
352.12567 ++#define SURFACEFORMAT_R16G16_SNORM                   0x0CD
352.12568 ++#define SURFACEFORMAT_R16G16_SINT                    0x0CE
352.12569 ++#define SURFACEFORMAT_R16G16_UINT                    0x0CF
352.12570 ++#define SURFACEFORMAT_R16G16_FLOAT                   0x0D0
352.12571 ++#define SURFACEFORMAT_B10G10R10A2_UNORM              0x0D1
352.12572 ++#define SURFACEFORMAT_B10G10R10A2_UNORM_SRGB         0x0D2
352.12573 ++#define SURFACEFORMAT_R11G11B10_FLOAT                0x0D3
352.12574 ++#define SURFACEFORMAT_R32_SINT                       0x0D6
352.12575 ++#define SURFACEFORMAT_R32_UINT                       0x0D7
352.12576 ++#define SURFACEFORMAT_R32_FLOAT                      0x0D8
352.12577 ++#define SURFACEFORMAT_R24_UNORM_X8_TYPELESS          0x0D9
352.12578 ++#define SURFACEFORMAT_X24_TYPELESS_G8_UINT           0x0DA
352.12579 ++#define SURFACEFORMAT_L16A16_UNORM                   0x0DF
352.12580 ++#define SURFACEFORMAT_I24X8_UNORM                    0x0E0
352.12581 ++#define SURFACEFORMAT_L24X8_UNORM                    0x0E1
352.12582 ++#define SURFACEFORMAT_A24X8_UNORM                    0x0E2
352.12583 ++#define SURFACEFORMAT_I32_FLOAT                      0x0E3
352.12584 ++#define SURFACEFORMAT_L32_FLOAT                      0x0E4
352.12585 ++#define SURFACEFORMAT_A32_FLOAT                      0x0E5
352.12586 ++#define SURFACEFORMAT_B8G8R8X8_UNORM                 0x0E9
352.12587 ++#define SURFACEFORMAT_B8G8R8X8_UNORM_SRGB            0x0EA
352.12588 ++#define SURFACEFORMAT_R8G8B8X8_UNORM                 0x0EB
352.12589 ++#define SURFACEFORMAT_R8G8B8X8_UNORM_SRGB            0x0EC
352.12590 ++#define SURFACEFORMAT_R9G9B9E5_SHAREDEXP             0x0ED
352.12591 ++#define SURFACEFORMAT_B10G10R10X2_UNORM              0x0EE
352.12592 ++#define SURFACEFORMAT_L16A16_FLOAT                   0x0F0
352.12593 ++#define SURFACEFORMAT_R32_UNORM                      0x0F1
352.12594 ++#define SURFACEFORMAT_R32_SNORM                      0x0F2
352.12595 ++#define SURFACEFORMAT_R10G10B10X2_USCALED            0x0F3
352.12596 ++#define SURFACEFORMAT_R8G8B8A8_SSCALED               0x0F4
352.12597 ++#define SURFACEFORMAT_R8G8B8A8_USCALED               0x0F5
352.12598 ++#define SURFACEFORMAT_R16G16_SSCALED                 0x0F6
352.12599 ++#define SURFACEFORMAT_R16G16_USCALED                 0x0F7
352.12600 ++#define SURFACEFORMAT_R32_SSCALED                    0x0F8
352.12601 ++#define SURFACEFORMAT_R32_USCALED                    0x0F9
352.12602 ++#define SURFACEFORMAT_B5G6R5_UNORM                   0x100
352.12603 ++#define SURFACEFORMAT_B5G6R5_UNORM_SRGB              0x101
352.12604 ++#define SURFACEFORMAT_B5G5R5A1_UNORM                 0x102
352.12605 ++#define SURFACEFORMAT_B5G5R5A1_UNORM_SRGB            0x103
352.12606 ++#define SURFACEFORMAT_B4G4R4A4_UNORM                 0x104
352.12607 ++#define SURFACEFORMAT_B4G4R4A4_UNORM_SRGB            0x105
352.12608 ++#define SURFACEFORMAT_R8G8_UNORM                     0x106
352.12609 ++#define SURFACEFORMAT_R8G8_SNORM                     0x107
352.12610 ++#define SURFACEFORMAT_R8G8_SINT                      0x108
352.12611 ++#define SURFACEFORMAT_R8G8_UINT                      0x109
352.12612 ++#define SURFACEFORMAT_R16_UNORM                      0x10A
352.12613 ++#define SURFACEFORMAT_R16_SNORM                      0x10B
352.12614 ++#define SURFACEFORMAT_R16_SINT                       0x10C
352.12615 ++#define SURFACEFORMAT_R16_UINT                       0x10D
352.12616 ++#define SURFACEFORMAT_R16_FLOAT                      0x10E
352.12617 ++#define SURFACEFORMAT_I16_UNORM                      0x111
352.12618 ++#define SURFACEFORMAT_L16_UNORM                      0x112
352.12619 ++#define SURFACEFORMAT_A16_UNORM                      0x113
352.12620 ++#define SURFACEFORMAT_L8A8_UNORM                     0x114
352.12621 ++#define SURFACEFORMAT_I16_FLOAT                      0x115
352.12622 ++#define SURFACEFORMAT_L16_FLOAT                      0x116
352.12623 ++#define SURFACEFORMAT_A16_FLOAT                      0x117
352.12624 ++#define SURFACEFORMAT_R5G5_SNORM_B6_UNORM            0x119
352.12625 ++#define SURFACEFORMAT_B5G5R5X1_UNORM                 0x11A
352.12626 ++#define SURFACEFORMAT_B5G5R5X1_UNORM_SRGB            0x11B
352.12627 ++#define SURFACEFORMAT_R8G8_SSCALED                   0x11C
352.12628 ++#define SURFACEFORMAT_R8G8_USCALED                   0x11D
352.12629 ++#define SURFACEFORMAT_R16_SSCALED                    0x11E
352.12630 ++#define SURFACEFORMAT_R16_USCALED                    0x11F
352.12631 ++#define SURFACEFORMAT_R8_UNORM                       0x140
352.12632 ++#define SURFACEFORMAT_R8_SNORM                       0x141
352.12633 ++#define SURFACEFORMAT_R8_SINT                        0x142
352.12634 ++#define SURFACEFORMAT_R8_UINT                        0x143
352.12635 ++#define SURFACEFORMAT_A8_UNORM                       0x144
352.12636 ++#define SURFACEFORMAT_I8_UNORM                       0x145
352.12637 ++#define SURFACEFORMAT_L8_UNORM                       0x146
352.12638 ++#define SURFACEFORMAT_P4A4_UNORM                     0x147
352.12639 ++#define SURFACEFORMAT_A4P4_UNORM                     0x148
352.12640 ++#define SURFACEFORMAT_R8_SSCALED                     0x149
352.12641 ++#define SURFACEFORMAT_R8_USCALED                     0x14A
352.12642 ++#define SURFACEFORMAT_R1_UINT                        0x181
352.12643 ++#define SURFACEFORMAT_YCRCB_NORMAL                   0x182
352.12644 ++#define SURFACEFORMAT_YCRCB_SWAPUVY                  0x183
352.12645 ++#define SURFACEFORMAT_BC1_UNORM                      0x186
352.12646 ++#define SURFACEFORMAT_BC2_UNORM                      0x187
352.12647 ++#define SURFACEFORMAT_BC3_UNORM                      0x188
352.12648 ++#define SURFACEFORMAT_BC4_UNORM                      0x189
352.12649 ++#define SURFACEFORMAT_BC5_UNORM                      0x18A
352.12650 ++#define SURFACEFORMAT_BC1_UNORM_SRGB                 0x18B
352.12651 ++#define SURFACEFORMAT_BC2_UNORM_SRGB                 0x18C
352.12652 ++#define SURFACEFORMAT_BC3_UNORM_SRGB                 0x18D
352.12653 ++#define SURFACEFORMAT_MONO8                          0x18E
352.12654 ++#define SURFACEFORMAT_YCRCB_SWAPUV                   0x18F
352.12655 ++#define SURFACEFORMAT_YCRCB_SWAPY                    0x190
352.12656 ++#define SURFACEFORMAT_DXT1_RGB                       0x191
352.12657 ++#define SURFACEFORMAT_FXT1                           0x192
352.12658 ++#define SURFACEFORMAT_R8G8B8_UNORM                   0x193
352.12659 ++#define SURFACEFORMAT_R8G8B8_SNORM                   0x194
352.12660 ++#define SURFACEFORMAT_R8G8B8_SSCALED                 0x195
352.12661 ++#define SURFACEFORMAT_R8G8B8_USCALED                 0x196
352.12662 ++#define SURFACEFORMAT_R64G64B64A64_FLOAT             0x197
352.12663 ++#define SURFACEFORMAT_R64G64B64_FLOAT                0x198
352.12664 ++#define SURFACEFORMAT_BC4_SNORM                      0x199
352.12665 ++#define SURFACEFORMAT_BC5_SNORM                      0x19A
352.12666 ++#define SURFACEFORMAT_R16G16B16_UNORM                0x19C
352.12667 ++#define SURFACEFORMAT_R16G16B16_SNORM                0x19D
352.12668 ++#define SURFACEFORMAT_R16G16B16_SSCALED              0x19E
352.12669 ++#define SURFACEFORMAT_R16G16B16_USCALED              0x19F
352.12670 ++
352.12671 ++#define SURFACE_1D      0
352.12672 ++#define SURFACE_2D      1
352.12673 ++#define SURFACE_3D      2
352.12674 ++#define SURFACE_CUBE    3
352.12675 ++#define SURFACE_BUFFER  4
352.12676 ++#define SURFACE_NULL    7
352.12677 ++
352.12678 ++#define TEXCOORDMODE_WRAP            0
352.12679 ++#define TEXCOORDMODE_MIRROR          1
352.12680 ++#define TEXCOORDMODE_CLAMP           2
352.12681 ++#define TEXCOORDMODE_CUBE            3
352.12682 ++#define TEXCOORDMODE_CLAMP_BORDER    4
352.12683 ++#define TEXCOORDMODE_MIRROR_ONCE     5
352.12684 ++
352.12685 ++#define THREAD_PRIORITY_NORMAL   0
352.12686 ++#define THREAD_PRIORITY_HIGH     1
352.12687 ++
352.12688 ++#define VERTEX_SUBPIXEL_PRECISION_8BITS  0
352.12689 ++#define VERTEX_SUBPIXEL_PRECISION_4BITS  1
352.12690 ++
352.12691 ++#define COMPONENT_NOSTORE      0
352.12692 ++#define COMPONENT_STORE_SRC    1
352.12693 ++#define COMPONENT_STORE_0      2
352.12694 ++#define COMPONENT_STORE_1_FLT  3
352.12695 ++#define COMPONENT_STORE_1_INT  4
352.12696 ++#define COMPONENT_STORE_VID    5
352.12697 ++#define COMPONENT_STORE_IID    6
352.12698 ++#define COMPONENT_STORE_PID    7
352.12699 ++
352.12700 ++/* Execution Unit (EU) defines
352.12701 ++ */
352.12702 ++
352.12703 ++#define GEN9_ALIGN_1   0
352.12704 ++#define GEN9_ALIGN_16  1
352.12705 ++
352.12706 ++#define GEN9_ADDRESS_DIRECT                        0
352.12707 ++#define GEN9_ADDRESS_REGISTER_INDIRECT_REGISTER    1
352.12708 ++
352.12709 ++#define GEN9_CHANNEL_X     0
352.12710 ++#define GEN9_CHANNEL_Y     1
352.12711 ++#define GEN9_CHANNEL_Z     2
352.12712 ++#define GEN9_CHANNEL_W     3
352.12713 ++
352.12714 ++#define GEN9_COMPRESSION_NONE          0
352.12715 ++#define GEN9_COMPRESSION_2NDHALF       1
352.12716 ++#define GEN9_COMPRESSION_COMPRESSED    2
352.12717 ++
352.12718 ++#define GEN9_CONDITIONAL_NONE  0
352.12719 ++#define GEN9_CONDITIONAL_Z     1
352.12720 ++#define GEN9_CONDITIONAL_NZ    2
352.12721 ++#define GEN9_CONDITIONAL_EQ    1	/* Z */
352.12722 ++#define GEN9_CONDITIONAL_NEQ   2	/* NZ */
352.12723 ++#define GEN9_CONDITIONAL_G     3
352.12724 ++#define GEN9_CONDITIONAL_GE    4
352.12725 ++#define GEN9_CONDITIONAL_L     5
352.12726 ++#define GEN9_CONDITIONAL_LE    6
352.12727 ++#define GEN9_CONDITIONAL_C     7
352.12728 ++#define GEN9_CONDITIONAL_O     8
352.12729 ++
352.12730 ++#define GEN9_DEBUG_NONE        0
352.12731 ++#define GEN9_DEBUG_BREAKPOINT  1
352.12732 ++
352.12733 ++#define GEN9_DEPENDENCY_NORMAL         0
352.12734 ++#define GEN9_DEPENDENCY_NOTCLEARED     1
352.12735 ++#define GEN9_DEPENDENCY_NOTCHECKED     2
352.12736 ++#define GEN9_DEPENDENCY_DISABLE        3
352.12737 ++
352.12738 ++#define GEN9_EXECUTE_1     0
352.12739 ++#define GEN9_EXECUTE_2     1
352.12740 ++#define GEN9_EXECUTE_4     2
352.12741 ++#define GEN9_EXECUTE_8     3
352.12742 ++#define GEN9_EXECUTE_16    4
352.12743 ++#define GEN9_EXECUTE_32    5
352.12744 ++
352.12745 ++#define GEN9_HORIZONTAL_STRIDE_0   0
352.12746 ++#define GEN9_HORIZONTAL_STRIDE_1   1
352.12747 ++#define GEN9_HORIZONTAL_STRIDE_2   2
352.12748 ++#define GEN9_HORIZONTAL_STRIDE_4   3
352.12749 ++
352.12750 ++#define GEN9_INSTRUCTION_NORMAL    0
352.12751 ++#define GEN9_INSTRUCTION_SATURATE  1
352.12752 ++
352.12753 ++#define GEN9_OPCODE_MOV        1
352.12754 ++#define GEN9_OPCODE_SEL        2
352.12755 ++#define GEN9_OPCODE_NOT        4
352.12756 ++#define GEN9_OPCODE_AND        5
352.12757 ++#define GEN9_OPCODE_OR         6
352.12758 ++#define GEN9_OPCODE_XOR        7
352.12759 ++#define GEN9_OPCODE_SHR        8
352.12760 ++#define GEN9_OPCODE_SHL        9
352.12761 ++#define GEN9_OPCODE_RSR        10
352.12762 ++#define GEN9_OPCODE_RSL        11
352.12763 ++#define GEN9_OPCODE_ASR        12
352.12764 ++#define GEN9_OPCODE_CMP        16
352.12765 ++#define GEN9_OPCODE_JMPI       32
352.12766 ++#define GEN9_OPCODE_IF         34
352.12767 ++#define GEN9_OPCODE_IFF        35
352.12768 ++#define GEN9_OPCODE_ELSE       36
352.12769 ++#define GEN9_OPCODE_ENDIF      37
352.12770 ++#define GEN9_OPCODE_DO         38
352.12771 ++#define GEN9_OPCODE_WHILE      39
352.12772 ++#define GEN9_OPCODE_BREAK      40
352.12773 ++#define GEN9_OPCODE_CONTINUE   41
352.12774 ++#define GEN9_OPCODE_HALT       42
352.12775 ++#define GEN9_OPCODE_MSAVE      44
352.12776 ++#define GEN9_OPCODE_MRESTORE   45
352.12777 ++#define GEN9_OPCODE_PUSH       46
352.12778 ++#define GEN9_OPCODE_POP        47
352.12779 ++#define GEN9_OPCODE_WAIT       48
352.12780 ++#define GEN9_OPCODE_SEND       49
352.12781 ++#define GEN9_OPCODE_ADD        64
352.12782 ++#define GEN9_OPCODE_MUL        65
352.12783 ++#define GEN9_OPCODE_AVG        66
352.12784 ++#define GEN9_OPCODE_FRC        67
352.12785 ++#define GEN9_OPCODE_RNDU       68
352.12786 ++#define GEN9_OPCODE_RNDD       69
352.12787 ++#define GEN9_OPCODE_RNDE       70
352.12788 ++#define GEN9_OPCODE_RNDZ       71
352.12789 ++#define GEN9_OPCODE_MAC        72
352.12790 ++#define GEN9_OPCODE_MACH       73
352.12791 ++#define GEN9_OPCODE_LZD        74
352.12792 ++#define GEN9_OPCODE_SAD2       80
352.12793 ++#define GEN9_OPCODE_SADA2      81
352.12794 ++#define GEN9_OPCODE_DP4        84
352.12795 ++#define GEN9_OPCODE_DPH        85
352.12796 ++#define GEN9_OPCODE_DP3        86
352.12797 ++#define GEN9_OPCODE_DP2        87
352.12798 ++#define GEN9_OPCODE_DPA2       88
352.12799 ++#define GEN9_OPCODE_LINE       89
352.12800 ++#define GEN9_OPCODE_NOP        126
352.12801 ++
352.12802 ++#define GEN9_PREDICATE_NONE             0
352.12803 ++#define GEN9_PREDICATE_NORMAL           1
352.12804 ++#define GEN9_PREDICATE_ALIGN1_ANYV             2
352.12805 ++#define GEN9_PREDICATE_ALIGN1_ALLV             3
352.12806 ++#define GEN9_PREDICATE_ALIGN1_ANY2H            4
352.12807 ++#define GEN9_PREDICATE_ALIGN1_ALL2H            5
352.12808 ++#define GEN9_PREDICATE_ALIGN1_ANY4H            6
352.12809 ++#define GEN9_PREDICATE_ALIGN1_ALL4H            7
352.12810 ++#define GEN9_PREDICATE_ALIGN1_ANY8H            8
352.12811 ++#define GEN9_PREDICATE_ALIGN1_ALL8H            9
352.12812 ++#define GEN9_PREDICATE_ALIGN1_ANY16H           10
352.12813 ++#define GEN9_PREDICATE_ALIGN1_ALL16H           11
352.12814 ++#define GEN9_PREDICATE_ALIGN16_REPLICATE_X     2
352.12815 ++#define GEN9_PREDICATE_ALIGN16_REPLICATE_Y     3
352.12816 ++#define GEN9_PREDICATE_ALIGN16_REPLICATE_Z     4
352.12817 ++#define GEN9_PREDICATE_ALIGN16_REPLICATE_W     5
352.12818 ++#define GEN9_PREDICATE_ALIGN16_ANY4H           6
352.12819 ++#define GEN9_PREDICATE_ALIGN16_ALL4H           7
352.12820 ++
352.12821 ++#define GEN9_ARCHITECTURE_REGISTER_FILE    0
352.12822 ++#define GEN9_GENERAL_REGISTER_FILE         1
352.12823 ++#define GEN9_MESSAGE_REGISTER_FILE         2
352.12824 ++#define GEN9_IMMEDIATE_VALUE               3
352.12825 ++
352.12826 ++#define GEN9_REGISTER_TYPE_UD  0
352.12827 ++#define GEN9_REGISTER_TYPE_D   1
352.12828 ++#define GEN9_REGISTER_TYPE_UW  2
352.12829 ++#define GEN9_REGISTER_TYPE_W   3
352.12830 ++#define GEN9_REGISTER_TYPE_UB  4
352.12831 ++#define GEN9_REGISTER_TYPE_B   5
352.12832 ++#define GEN9_REGISTER_TYPE_VF  5	/* packed float vector, immediates only? */
352.12833 ++#define GEN9_REGISTER_TYPE_HF  6
352.12834 ++#define GEN9_REGISTER_TYPE_V   6	/* packed int vector, immediates only, uword dest only */
352.12835 ++#define GEN9_REGISTER_TYPE_F   7
352.12836 ++
352.12837 ++#define GEN9_ARF_NULL                  0x00
352.12838 ++#define GEN9_ARF_ADDRESS               0x10
352.12839 ++#define GEN9_ARF_ACCUMULATOR           0x20
352.12840 ++#define GEN9_ARF_FLAG                  0x30
352.12841 ++#define GEN9_ARF_MASK                  0x40
352.12842 ++#define GEN9_ARF_MASK_STACK            0x50
352.12843 ++#define GEN9_ARF_MASK_STACK_DEPTH      0x60
352.12844 ++#define GEN9_ARF_STATE                 0x70
352.12845 ++#define GEN9_ARF_CONTROL               0x80
352.12846 ++#define GEN9_ARF_NOTIFICATION_COUNT    0x90
352.12847 ++#define GEN9_ARF_IP                    0xA0
352.12848 ++
352.12849 ++#define GEN9_AMASK   0
352.12850 ++#define GEN9_IMASK   1
352.12851 ++#define GEN9_LMASK   2
352.12852 ++#define GEN9_CMASK   3
352.12853 ++
352.12854 ++#define GEN9_THREAD_NORMAL     0
352.12855 ++#define GEN9_THREAD_ATOMIC     1
352.12856 ++#define GEN9_THREAD_SWITCH     2
352.12857 ++
352.12858 ++#define GEN9_VERTICAL_STRIDE_0                 0
352.12859 ++#define GEN9_VERTICAL_STRIDE_1                 1
352.12860 ++#define GEN9_VERTICAL_STRIDE_2                 2
352.12861 ++#define GEN9_VERTICAL_STRIDE_4                 3
352.12862 ++#define GEN9_VERTICAL_STRIDE_8                 4
352.12863 ++#define GEN9_VERTICAL_STRIDE_16                5
352.12864 ++#define GEN9_VERTICAL_STRIDE_32                6
352.12865 ++#define GEN9_VERTICAL_STRIDE_64                7
352.12866 ++#define GEN9_VERTICAL_STRIDE_128               8
352.12867 ++#define GEN9_VERTICAL_STRIDE_256               9
352.12868 ++#define GEN9_VERTICAL_STRIDE_ONE_DIMENSIONAL   0xF
352.12869 ++
352.12870 ++#define GEN9_WIDTH_1       0
352.12871 ++#define GEN9_WIDTH_2       1
352.12872 ++#define GEN9_WIDTH_4       2
352.12873 ++#define GEN9_WIDTH_8       3
352.12874 ++#define GEN9_WIDTH_16      4
352.12875 ++
352.12876 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_1K      0
352.12877 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_2K      1
352.12878 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_4K      2
352.12879 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_8K      3
352.12880 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_16K     4
352.12881 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_32K     5
352.12882 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_64K     6
352.12883 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_128K    7
352.12884 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_256K    8
352.12885 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_512K    9
352.12886 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_1M      10
352.12887 ++#define GEN9_STATELESS_BUFFER_BOUNDARY_2M      11
352.12888 ++
352.12889 ++#define GEN9_POLYGON_FACING_FRONT      0
352.12890 ++#define GEN9_POLYGON_FACING_BACK       1
352.12891 ++
352.12892 ++#define GEN9_MESSAGE_TARGET_NULL               0
352.12893 ++#define GEN9_MESSAGE_TARGET_MATH               1
352.12894 ++#define GEN9_MESSAGE_TARGET_SAMPLER            2
352.12895 ++#define GEN9_MESSAGE_TARGET_GATEWAY            3
352.12896 ++#define GEN9_MESSAGE_TARGET_DATAPORT_READ      4
352.12897 ++#define GEN9_MESSAGE_TARGET_DATAPORT_WRITE     5
352.12898 ++#define GEN9_MESSAGE_TARGET_URB                6
352.12899 ++#define GEN9_MESSAGE_TARGET_THREAD_SPAWNER     7
352.12900 ++
352.12901 ++#define GEN9_SAMPLER_RETURN_FORMAT_FLOAT32     0
352.12902 ++#define GEN9_SAMPLER_RETURN_FORMAT_UINT32      2
352.12903 ++#define GEN9_SAMPLER_RETURN_FORMAT_SINT32      3
352.12904 ++
352.12905 ++#define GEN9_SAMPLER_MESSAGE_SIMD8_SAMPLE              0
352.12906 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE             0
352.12907 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS        0
352.12908 ++#define GEN9_SAMPLER_MESSAGE_SIMD8_KILLPIX             1
352.12909 ++#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD        1
352.12910 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD         1
352.12911 ++#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS  2
352.12912 ++#define GEN9_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS    2
352.12913 ++#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE    0
352.12914 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE     2
352.12915 ++#define GEN9_SAMPLER_MESSAGE_SIMD4X2_RESINFO           2
352.12916 ++#define GEN9_SAMPLER_MESSAGE_SIMD8_RESINFO             2
352.12917 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_RESINFO            2
352.12918 ++#define GEN9_SAMPLER_MESSAGE_SIMD4X2_LD                3
352.12919 ++#define GEN9_SAMPLER_MESSAGE_SIMD8_LD                  3
352.12920 ++#define GEN9_SAMPLER_MESSAGE_SIMD16_LD                 3
352.12921 ++
352.12922 ++#define GEN9_DATAPORT_OWORD_BLOCK_1_OWORDLOW   0
352.12923 ++#define GEN9_DATAPORT_OWORD_BLOCK_1_OWORDHIGH  1
352.12924 ++#define GEN9_DATAPORT_OWORD_BLOCK_2_OWORDS     2
352.12925 ++#define GEN9_DATAPORT_OWORD_BLOCK_4_OWORDS     3
352.12926 ++#define GEN9_DATAPORT_OWORD_BLOCK_8_OWORDS     4
352.12927 ++
352.12928 ++#define GEN9_DATAPORT_OWORD_DUAL_BLOCK_1OWORD     0
352.12929 ++#define GEN9_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS    2
352.12930 ++
352.12931 ++#define GEN9_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS   2
352.12932 ++#define GEN9_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS  3
352.12933 ++
352.12934 ++#define GEN9_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ          0
352.12935 ++#define GEN9_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ     1
352.12936 ++#define GEN9_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ          2
352.12937 ++#define GEN9_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ      3
352.12938 ++
352.12939 ++#define GEN9_DATAPORT_READ_TARGET_DATA_CACHE      0
352.12940 ++#define GEN9_DATAPORT_READ_TARGET_RENDER_CACHE    1
352.12941 ++#define GEN9_DATAPORT_READ_TARGET_SAMPLER_CACHE   2
352.12942 ++
352.12943 ++#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE                0
352.12944 ++#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED     1
352.12945 ++#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01         2
352.12946 ++#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23         3
352.12947 ++#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01       4
352.12948 ++
352.12949 ++#define GEN9_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE                0
352.12950 ++#define GEN9_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE           1
352.12951 ++#define GEN9_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE                2
352.12952 ++#define GEN9_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE            3
352.12953 ++#define GEN9_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE              4
352.12954 ++#define GEN9_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE     5
352.12955 ++#define GEN9_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE               7
352.12956 ++
352.12957 ++#define GEN9_MATH_FUNCTION_INV                              1
352.12958 ++#define GEN9_MATH_FUNCTION_LOG                              2
352.12959 ++#define GEN9_MATH_FUNCTION_EXP                              3
352.12960 ++#define GEN9_MATH_FUNCTION_SQRT                             4
352.12961 ++#define GEN9_MATH_FUNCTION_RSQ                              5
352.12962 ++#define GEN9_MATH_FUNCTION_SIN                              6 /* was 7 */
352.12963 ++#define GEN9_MATH_FUNCTION_COS                              7 /* was 8 */
352.12964 ++#define GEN9_MATH_FUNCTION_SINCOS                           8 /* was 6 */
352.12965 ++#define GEN9_MATH_FUNCTION_TAN                              9
352.12966 ++#define GEN9_MATH_FUNCTION_POW                              10
352.12967 ++#define GEN9_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER   11
352.12968 ++#define GEN9_MATH_FUNCTION_INT_DIV_QUOTIENT                 12
352.12969 ++#define GEN9_MATH_FUNCTION_INT_DIV_REMAINDER                13
352.12970 ++
352.12971 ++#define GEN9_MATH_INTEGER_UNSIGNED     0
352.12972 ++#define GEN9_MATH_INTEGER_SIGNED       1
352.12973 ++
352.12974 ++#define GEN9_MATH_PRECISION_FULL        0
352.12975 ++#define GEN9_MATH_PRECISION_PARTIAL     1
352.12976 ++
352.12977 ++#define GEN9_MATH_SATURATE_NONE         0
352.12978 ++#define GEN9_MATH_SATURATE_SATURATE     1
352.12979 ++
352.12980 ++#define GEN9_MATH_DATA_VECTOR  0
352.12981 ++#define GEN9_MATH_DATA_SCALAR  1
352.12982 ++
352.12983 ++#define GEN9_URB_OPCODE_WRITE  0
352.12984 ++
352.12985 ++#define GEN9_URB_SWIZZLE_NONE          0
352.12986 ++#define GEN9_URB_SWIZZLE_INTERLEAVE    1
352.12987 ++#define GEN9_URB_SWIZZLE_TRANSPOSE     2
352.12988 ++
352.12989 ++#define GEN9_SCRATCH_SPACE_SIZE_1K     0
352.12990 ++#define GEN9_SCRATCH_SPACE_SIZE_2K     1
352.12991 ++#define GEN9_SCRATCH_SPACE_SIZE_4K     2
352.12992 ++#define GEN9_SCRATCH_SPACE_SIZE_8K     3
352.12993 ++#define GEN9_SCRATCH_SPACE_SIZE_16K    4
352.12994 ++#define GEN9_SCRATCH_SPACE_SIZE_32K    5
352.12995 ++#define GEN9_SCRATCH_SPACE_SIZE_64K    6
352.12996 ++#define GEN9_SCRATCH_SPACE_SIZE_128K   7
352.12997 ++#define GEN9_SCRATCH_SPACE_SIZE_256K   8
352.12998 ++#define GEN9_SCRATCH_SPACE_SIZE_512K   9
352.12999 ++#define GEN9_SCRATCH_SPACE_SIZE_1M     10
352.13000 ++#define GEN9_SCRATCH_SPACE_SIZE_2M     11
352.13001 ++
352.13002 ++struct gen9_blend_state {
352.13003 ++	struct {
352.13004 ++		/* 00 */ uint32_t pad:19;
352.13005 ++		/* 19 */ uint32_t y_dither_offset:2;
352.13006 ++		/* 21 */ uint32_t x_dither_offset:2;
352.13007 ++		/* 23 */ uint32_t color_dither_enable:1;
352.13008 ++		/* 24 */ uint32_t alpha_test_function:3;
352.13009 ++		/* 27 */ uint32_t alpha_test:1;
352.13010 ++		/* 28 */ uint32_t alpha_to_coverage_dither:1;
352.13011 ++		/* 29 */ uint32_t alpha_to_one:1;
352.13012 ++		/* 30 */ uint32_t ia_blend:1;
352.13013 ++		/* 31 */ uint32_t alpha_to_coverage:1;
352.13014 ++	} common;
352.13015 ++
352.13016 ++	struct {
352.13017 ++		/* 00 */ uint32_t write_disable_blue:1;
352.13018 ++		/* 01 */ uint32_t write_disable_green:1;
352.13019 ++		/* 02 */ uint32_t write_disable_red:1;
352.13020 ++		/* 03 */ uint32_t write_disable_alpha:1;
352.13021 ++		/* 04 */ uint32_t pad0:1;
352.13022 ++		/* 05 */ uint32_t alpha_blend_function:3;
352.13023 ++		/* 08 */ uint32_t dest_alpha_blend_factor:5;
352.13024 ++		/* 13 */ uint32_t source_alpha_blend_factor:5;
352.13025 ++		/* 18 */ uint32_t color_blend_function:3;
352.13026 ++		/* 21 */ uint32_t dest_blend_factor:5;
352.13027 ++		/* 26 */ uint32_t source_blend_factor:5;
352.13028 ++		/* 31 */ uint32_t color_blend:1;
352.13029 ++		/* 32 */ uint32_t post_blend_clamp:1;
352.13030 ++		/* 33 */ uint32_t pre_blend_clamp:1;
352.13031 ++		/* 34 */ uint32_t color_clamp_range:2;
352.13032 ++		/* 36 */ uint32_t pre_blend_source_only_clamp:1;
352.13033 ++		/* 37 */ uint32_t pad1:22;
352.13034 ++		/* 59 */ uint32_t logic_op_function:4;
352.13035 ++		/* 63 */ uint32_t logic_op:1;
352.13036 ++	} rt;
352.13037 ++};
352.13038 ++
352.13039 ++struct gen9_color_calc_state {
352.13040 ++	struct {
352.13041 ++		/* 00 */ uint32_t alpha_test_format:1;
352.13042 ++		/* 01 */ uint32_t pad0:14;
352.13043 ++		/* 15 */ uint32_t round_disable:1;
352.13044 ++		/* 16 */ uint32_t bf_stencil_ref:8;
352.13045 ++		/* 24 */ uint32_t stencil_ref:8;
352.13046 ++	} cc0;
352.13047 ++
352.13048 ++	union {
352.13049 ++		float alpha_ref_f;
352.13050 ++		struct {
352.13051 ++			uint32_t ui:8;
352.13052 ++			uint32_t pad0:24;
352.13053 ++		} alpha_ref_fi;
352.13054 ++	} cc1;
352.13055 ++
352.13056 ++	float constant_r;
352.13057 ++	float constant_g;
352.13058 ++	float constant_b;
352.13059 ++	float constant_a;
352.13060 ++};
352.13061 ++
352.13062 ++struct gen9_sampler_state {
352.13063 ++	struct {
352.13064 ++		/* 00 */ unsigned int aniso_algorithm:1;
352.13065 ++		/* 01 */ unsigned int lod_bias:13;
352.13066 ++		/* 14 */ unsigned int min_filter:3;
352.13067 ++		/* 17 */ unsigned int mag_filter:3;
352.13068 ++		/* 20 */ unsigned int mip_filter:2;
352.13069 ++		/* 22 */ unsigned int base_level:5;
352.13070 ++		/* 27 */ unsigned int lod_preclamp:2;
352.13071 ++		/* 29 */ unsigned int default_color_mode:1;
352.13072 ++		/* 30 */ unsigned int flexible_filter_clamp:1;
352.13073 ++		/* 31 */ unsigned int disable:1;
352.13074 ++	} ss0;
352.13075 ++
352.13076 ++	struct {
352.13077 ++		/* 00 */ unsigned int cube_control_mode:1;
352.13078 ++		/* 01 */ unsigned int shadow_function:3;
352.13079 ++		/* 04 */ unsigned int chroma_key_mode:1;
352.13080 ++		/* 05 */ unsigned int chroma_key_index:2;
352.13081 ++		/* 07 */ unsigned int chroma_key_enable:1;
352.13082 ++		/* 08 */ unsigned int max_lod:12;
352.13083 ++		/* 20 */ unsigned int min_lod:12;
352.13084 ++	} ss1;
352.13085 ++
352.13086 ++	struct {
352.13087 ++		unsigned int pad:6;
352.13088 ++		unsigned int default_color_pointer:26;
352.13089 ++	} ss2;
352.13090 ++
352.13091 ++	struct {
352.13092 ++		/* 00 */ unsigned int r_wrap_mode:3;
352.13093 ++		/* 03 */ unsigned int t_wrap_mode:3;
352.13094 ++		/* 06 */ unsigned int s_wrap_mode:3;
352.13095 ++		/* 09 */ unsigned int pad:1;
352.13096 ++		/* 10 */ unsigned int non_normalized_coord:1;
352.13097 ++		/* 11 */ unsigned int trilinear_quality:2;
352.13098 ++		/* 13 */ unsigned int address_round:6;
352.13099 ++		/* 19 */ unsigned int max_aniso:3;
352.13100 ++		/* 22 */ unsigned int pad0:2;
352.13101 ++		/* 24 */ unsigned int non_separable_filter:8;
352.13102 ++	} ss3;
352.13103 ++};
352.13104 ++
352.13105 ++/* Surface state DW0 */
352.13106 ++#define SURFACE_RC_READ_WRITE	(1 << 8)
352.13107 ++#define SURFACE_TILED		(1 << 13)
352.13108 ++#define SURFACE_TILED_Y		(1 << 12)
352.13109 ++#define SURFACE_FORMAT_SHIFT	18
352.13110 ++#define SURFACE_VALIGN_1	(0 << 16) /* reserved! */
352.13111 ++#define SURFACE_VALIGN_4	(1 << 16)
352.13112 ++#define SURFACE_VALIGN_8	(2 << 16)
352.13113 ++#define SURFACE_VALIGN_16	(3 << 16)
352.13114 ++#define SURFACE_HALIGN_1	(0 << 14) /* reserved! */
352.13115 ++#define SURFACE_HALIGN_4	(1 << 14)
352.13116 ++#define SURFACE_HALIGN_8	(2 << 14)
352.13117 ++#define SURFACE_HALIGN_16	(3 << 14)
352.13118 ++#define SURFACE_TYPE_SHIFT		29
352.13119 ++
352.13120 ++/* Surface state DW2 */
352.13121 ++#define SURFACE_HEIGHT_SHIFT        16
352.13122 ++#define SURFACE_WIDTH_SHIFT         0
352.13123 ++
352.13124 ++/* Surface state DW3 */
352.13125 ++#define SURFACE_DEPTH_SHIFT         21
352.13126 ++#define SURFACE_PITCH_SHIFT         0
352.13127 ++
352.13128 ++#define SWIZZLE_ZERO		0
352.13129 ++#define SWIZZLE_ONE		1
352.13130 ++#define SWIZZLE_RED		4
352.13131 ++#define SWIZZLE_GREEN		5
352.13132 ++#define SWIZZLE_BLUE		6
352.13133 ++#define SWIZZLE_ALPHA		7
352.13134 ++#define __SURFACE_SWIZZLE(r,g,b,a) \
352.13135 ++	((a) << 16 | (b) << 19 | (g) << 22 | (r) << 25)
352.13136 ++#define SURFACE_SWIZZLE(r,g,b,a) \
352.13137 ++	__SURFACE_SWIZZLE(SWIZZLE_##r, SWIZZLE_##g, SWIZZLE_##b, SWIZZLE_##a)
352.13138 ++
352.13139 ++typedef enum {
352.13140 ++	SAMPLER_FILTER_NEAREST = 0,
352.13141 ++	SAMPLER_FILTER_BILINEAR,
352.13142 ++	FILTER_COUNT
352.13143 ++} sampler_filter_t;
352.13144 ++
352.13145 ++typedef enum {
352.13146 ++	SAMPLER_EXTEND_NONE = 0,
352.13147 ++	SAMPLER_EXTEND_REPEAT,
352.13148 ++	SAMPLER_EXTEND_PAD,
352.13149 ++	SAMPLER_EXTEND_REFLECT,
352.13150 ++	EXTEND_COUNT
352.13151 ++} sampler_extend_t;
352.13152 ++
352.13153 ++#endif
352.13154 +diff --git a/src/sna/kgem.c b/src/sna/kgem.c
352.13155 +index 78ed5407..f0d171ac 100644
352.13156 +--- a/src/sna/kgem.c
352.13157 ++++ b/src/sna/kgem.c
352.13158 +@@ -84,6 +84,10 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
352.13159 + #define DBG_NO_HANDLE_LUT 0
352.13160 + #define DBG_NO_WT 0
352.13161 + #define DBG_NO_WC_MMAP 0
352.13162 ++#define DBG_NO_BLT_Y 0
352.13163 ++#define DBG_NO_SCANOUT_Y 0
352.13164 ++#define DBG_NO_DIRTYFB 0
352.13165 ++#define DBG_NO_DETILING 0
352.13166 + #define DBG_DUMP 0
352.13167 + #define DBG_NO_MALLOC_CACHE 0
352.13168 + 
352.13169 +@@ -96,11 +100,6 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
352.13170 + #define SHOW_BATCH_BEFORE 0
352.13171 + #define SHOW_BATCH_AFTER 0
352.13172 + 
352.13173 +-#if !USE_WC_MMAP
352.13174 +-#undef DBG_NO_WC_MMAP
352.13175 +-#define DBG_NO_WC_MMAP 1
352.13176 +-#endif
352.13177 +-
352.13178 + #if 0
352.13179 + #define ASSERT_IDLE(kgem__, handle__) assert(!__kgem_busy(kgem__, handle__))
352.13180 + #define ASSERT_MAYBE_IDLE(kgem__, handle__, expect__) assert(!(expect__) || !__kgem_busy(kgem__, handle__))
352.13181 +@@ -187,6 +186,15 @@ struct local_i915_gem_caching {
352.13182 + #define LOCAL_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_SET_CACHING, struct local_i915_gem_caching)
352.13183 + #define LOCAL_IOCTL_I915_GEM_GET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_GET_CACHING, struct local_i915_gem_caching)
352.13184 + 
352.13185 ++struct local_i915_gem_mmap {
352.13186 ++	uint32_t handle;
352.13187 ++	uint32_t pad;
352.13188 ++	uint64_t offset;
352.13189 ++	uint64_t size;
352.13190 ++	uint64_t addr_ptr;
352.13191 ++};
352.13192 ++#define LOCAL_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct local_i915_gem_mmap)
352.13193 ++
352.13194 + struct local_i915_gem_mmap2 {
352.13195 + 	uint32_t handle;
352.13196 + 	uint32_t pad;
352.13197 +@@ -216,6 +224,12 @@ static struct kgem_bo *__kgem_freed_bo;
352.13198 + static struct kgem_request *__kgem_freed_request;
352.13199 + static struct drm_i915_gem_exec_object2 _kgem_dummy_exec;
352.13200 + 
352.13201 ++static inline struct sna *__to_sna(struct kgem *kgem)
352.13202 ++{
352.13203 ++	/* minor layering violations */
352.13204 ++	return container_of(kgem, struct sna, kgem);
352.13205 ++}
352.13206 ++
352.13207 + static inline int bytes(struct kgem_bo *bo)
352.13208 + {
352.13209 + 	return __kgem_bo_size(bo);
352.13210 +@@ -224,25 +238,31 @@ static inline int bytes(struct kgem_bo *bo)
352.13211 + #define bucket(B) (B)->size.pages.bucket
352.13212 + #define num_pages(B) (B)->size.pages.count
352.13213 + 
352.13214 +-static int do_ioctl(int fd, unsigned long req, void *arg)
352.13215 ++static int __do_ioctl(int fd, unsigned long req, void *arg)
352.13216 + {
352.13217 +-	int err;
352.13218 +-
352.13219 +-restart:
352.13220 +-	if (ioctl(fd, req, arg) == 0)
352.13221 +-		return 0;
352.13222 ++	do {
352.13223 ++		int err;
352.13224 + 
352.13225 +-	err = errno;
352.13226 ++		switch ((err = errno)) {
352.13227 ++		case EAGAIN:
352.13228 ++			sched_yield();
352.13229 ++		case EINTR:
352.13230 ++			break;
352.13231 ++		default:
352.13232 ++			return -err;
352.13233 ++		}
352.13234 + 
352.13235 +-	if (err == EINTR)
352.13236 +-		goto restart;
352.13237 ++		if (likely(ioctl(fd, req, arg) == 0))
352.13238 ++			return 0;
352.13239 ++	} while (1);
352.13240 ++}
352.13241 + 
352.13242 +-	if (err == EAGAIN) {
352.13243 +-		sched_yield();
352.13244 +-		goto restart;
352.13245 +-	}
352.13246 ++inline static int do_ioctl(int fd, unsigned long req, void *arg)
352.13247 ++{
352.13248 ++	if (likely(ioctl(fd, req, arg) == 0))
352.13249 ++		return 0;
352.13250 + 
352.13251 +-	return -err;
352.13252 ++	return __do_ioctl(fd, req, arg);
352.13253 + }
352.13254 + 
352.13255 + #ifdef DEBUG_MEMORY
352.13256 +@@ -266,6 +286,9 @@ static void assert_tiling(struct kgem *kgem, struct kgem_bo *bo)
352.13257 + 
352.13258 + 	assert(bo);
352.13259 + 
352.13260 ++	if (!kgem->can_fence && kgem->gen >= 040 && bo->tiling)
352.13261 ++		return; /* lies */
352.13262 ++
352.13263 + 	VG_CLEAR(tiling);
352.13264 + 	tiling.handle = bo->handle;
352.13265 + 	tiling.tiling_mode = bo->tiling;
352.13266 +@@ -273,7 +296,7 @@ static void assert_tiling(struct kgem *kgem, struct kgem_bo *bo)
352.13267 + 	assert(tiling.tiling_mode == bo->tiling);
352.13268 + }
352.13269 + 
352.13270 +-static void assert_cacheing(struct kgem *kgem, struct kgem_bo *bo)
352.13271 ++static void assert_caching(struct kgem *kgem, struct kgem_bo *bo)
352.13272 + {
352.13273 + 	struct local_i915_gem_caching arg;
352.13274 + 	int expect = kgem->has_llc ? SNOOPED : UNCACHED;
352.13275 +@@ -294,24 +317,117 @@ static void assert_bo_retired(struct kgem_bo *bo)
352.13276 + 	assert(bo->refcnt);
352.13277 + 	assert(bo->rq == NULL);
352.13278 + 	assert(bo->exec == NULL);
352.13279 ++	assert(!bo->needs_flush);
352.13280 + 	assert(list_is_empty(&bo->request));
352.13281 + }
352.13282 + #else
352.13283 + #define assert_tiling(kgem, bo)
352.13284 +-#define assert_cacheing(kgem, bo)
352.13285 ++#define assert_caching(kgem, bo)
352.13286 + #define assert_bo_retired(bo)
352.13287 + #endif
352.13288 + 
352.13289 ++static int __find_debugfs(struct kgem *kgem)
352.13290 ++{
352.13291 ++	int i;
352.13292 ++
352.13293 ++	for (i = 0; i < DRM_MAX_MINOR; i++) {
352.13294 ++		char path[80];
352.13295 ++
352.13296 ++		sprintf(path, "/sys/kernel/debug/dri/%d/i915_wedged", i);
352.13297 ++		if (access(path, R_OK) == 0)
352.13298 ++			return i;
352.13299 ++
352.13300 ++		sprintf(path, "/debug/dri/%d/i915_wedged", i);
352.13301 ++		if (access(path, R_OK) == 0)
352.13302 ++			return i;
352.13303 ++	}
352.13304 ++
352.13305 ++	return -1;
352.13306 ++}
352.13307 ++
352.13308 ++static int kgem_get_minor(struct kgem *kgem)
352.13309 ++{
352.13310 ++	struct stat st;
352.13311 ++
352.13312 ++	if (fstat(kgem->fd, &st))
352.13313 ++		return __find_debugfs(kgem);
352.13314 ++
352.13315 ++	if (!S_ISCHR(st.st_mode))
352.13316 ++		return __find_debugfs(kgem);
352.13317 ++
352.13318 ++	return st.st_rdev & 0x63;
352.13319 ++}
352.13320 ++
352.13321 ++static bool find_hang_state(struct kgem *kgem, char *path, int maxlen)
352.13322 ++{
352.13323 ++	int minor = kgem_get_minor(kgem);
352.13324 ++
352.13325 ++	/* Search for our hang state in a few canonical locations.
352.13326 ++	 * In the unlikely event of having multiple devices, we
352.13327 ++	 * will need to check which minor actually corresponds to ours.
352.13328 ++	 */
352.13329 ++
352.13330 ++	snprintf(path, maxlen, "/sys/class/drm/card%d/error", minor);
352.13331 ++	if (access(path, R_OK) == 0)
352.13332 ++		return true;
352.13333 ++
352.13334 ++	snprintf(path, maxlen, "/sys/kernel/debug/dri/%d/i915_error_state", minor);
352.13335 ++	if (access(path, R_OK) == 0)
352.13336 ++		return true;
352.13337 ++
352.13338 ++	snprintf(path, maxlen, "/debug/dri/%d/i915_error_state", minor);
352.13339 ++	if (access(path, R_OK) == 0)
352.13340 ++		return true;
352.13341 ++
352.13342 ++	path[0] = '\0';
352.13343 ++	return false;
352.13344 ++}
352.13345 ++
352.13346 ++static bool has_error_state(struct kgem *kgem, char *path)
352.13347 ++{
352.13348 ++   bool ret = false;
352.13349 ++   char no;
352.13350 ++   int fd;
352.13351 ++
352.13352 ++   fd = open(path, O_RDONLY);
352.13353 ++   if (fd >= 0) {
352.13354 ++      ret = read(fd, &no, 1) == 1 && no != 'N';
352.13355 ++      close(fd);
352.13356 ++   }
352.13357 ++
352.13358 ++   return ret;
352.13359 ++}
352.13360 ++
352.13361 ++static int kgem_get_screen_index(struct kgem *kgem)
352.13362 ++{
352.13363 ++	return __to_sna(kgem)->scrn->scrnIndex;
352.13364 ++}
352.13365 ++
352.13366 + static void
352.13367 + __kgem_set_wedged(struct kgem *kgem)
352.13368 + {
352.13369 ++	static int once;
352.13370 ++	char path[256];
352.13371 ++
352.13372 ++	if (kgem->wedged)
352.13373 ++		return;
352.13374 ++
352.13375 ++	if (!once &&
352.13376 ++	    find_hang_state(kgem, path, sizeof(path)) &&
352.13377 ++            has_error_state(kgem, path)) {
352.13378 ++		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
352.13379 ++			   "When reporting this, please include %s and the full dmesg.\n",
352.13380 ++			   path);
352.13381 ++		once = 1;
352.13382 ++	}
352.13383 ++
352.13384 + 	kgem->wedged = true;
352.13385 +-	sna_render_mark_wedged(container_of(kgem, struct sna, kgem));
352.13386 ++	sna_render_mark_wedged(__to_sna(kgem));
352.13387 + }
352.13388 + 
352.13389 + static void kgem_sna_reset(struct kgem *kgem)
352.13390 + {
352.13391 +-	struct sna *sna = container_of(kgem, struct sna, kgem);
352.13392 ++	struct sna *sna = __to_sna(kgem);
352.13393 + 
352.13394 + 	sna->render.reset(sna);
352.13395 + 	sna->blt_state.fill_bo = 0;
352.13396 +@@ -319,7 +435,7 @@ static void kgem_sna_reset(struct kgem *kgem)
352.13397 + 
352.13398 + static void kgem_sna_flush(struct kgem *kgem)
352.13399 + {
352.13400 +-	struct sna *sna = container_of(kgem, struct sna, kgem);
352.13401 ++	struct sna *sna = __to_sna(kgem);
352.13402 + 
352.13403 + 	sna->render.flush(sna);
352.13404 + 
352.13405 +@@ -327,22 +443,53 @@ static void kgem_sna_flush(struct kgem *kgem)
352.13406 + 		sna_render_flush_solid(sna);
352.13407 + }
352.13408 + 
352.13409 +-static bool gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
352.13410 ++static bool kgem_bo_rmfb(struct kgem *kgem, struct kgem_bo *bo)
352.13411 ++{
352.13412 ++	if (bo->scanout && bo->delta) {
352.13413 ++		DBG(("%s: releasing fb=%d for handle=%d\n",
352.13414 ++		     __FUNCTION__, bo->delta, bo->handle));
352.13415 ++		/* XXX will leak if we are not DRM_MASTER. *shrug* */
352.13416 ++		do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
352.13417 ++		bo->delta = 0;
352.13418 ++		return true;
352.13419 ++	} else
352.13420 ++		return false;
352.13421 ++}
352.13422 ++
352.13423 ++static bool kgem_set_tiling(struct kgem *kgem, struct kgem_bo *bo,
352.13424 ++			    int tiling, int stride)
352.13425 + {
352.13426 + 	struct drm_i915_gem_set_tiling set_tiling;
352.13427 + 	int err;
352.13428 + 
352.13429 ++	if (tiling == bo->tiling) {
352.13430 ++		if (tiling == I915_TILING_NONE) {
352.13431 ++			bo->pitch = stride;
352.13432 ++			return true;
352.13433 ++		}
352.13434 ++		if (stride == bo->pitch)
352.13435 ++			return true;
352.13436 ++	}
352.13437 ++
352.13438 + 	if (DBG_NO_TILING)
352.13439 + 		return false;
352.13440 + 
352.13441 + 	VG_CLEAR(set_tiling);
352.13442 + restart:
352.13443 +-	set_tiling.handle = handle;
352.13444 ++	set_tiling.handle = bo->handle;
352.13445 + 	set_tiling.tiling_mode = tiling;
352.13446 +-	set_tiling.stride = stride;
352.13447 ++	set_tiling.stride = tiling ? stride : 0;
352.13448 + 
352.13449 +-	if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
352.13450 +-		return true;
352.13451 ++	if (ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0) {
352.13452 ++		bo->tiling = set_tiling.tiling_mode;
352.13453 ++		bo->pitch = set_tiling.tiling_mode ? set_tiling.stride : stride;
352.13454 ++		DBG(("%s: handle=%d, tiling=%d [%d], pitch=%d [%d]: %d\n",
352.13455 ++		     __FUNCTION__, bo->handle,
352.13456 ++		     bo->tiling, tiling,
352.13457 ++		     bo->pitch, stride,
352.13458 ++		     set_tiling.tiling_mode == tiling));
352.13459 ++		return set_tiling.tiling_mode == tiling;
352.13460 ++	}
352.13461 + 
352.13462 + 	err = errno;
352.13463 + 	if (err == EINTR)
352.13464 +@@ -353,6 +500,11 @@ restart:
352.13465 + 		goto restart;
352.13466 + 	}
352.13467 + 
352.13468 ++	if (err == EBUSY && kgem_bo_rmfb(kgem, bo))
352.13469 ++		goto restart;
352.13470 ++
352.13471 ++	ERR(("%s: failed to set-tiling(tiling=%d, pitch=%d) for handle=%d: %d\n",
352.13472 ++	     __FUNCTION__, tiling, stride, bo->handle, err));
352.13473 + 	return false;
352.13474 + }
352.13475 + 
352.13476 +@@ -437,10 +589,15 @@ static void *__kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
352.13477 + 	DBG(("%s(handle=%d, size=%d)\n", __FUNCTION__,
352.13478 + 	     bo->handle, bytes(bo)));
352.13479 + 
352.13480 ++	if (bo->tiling && !kgem->can_fence)
352.13481 ++		return NULL;
352.13482 ++
352.13483 + 	VG_CLEAR(gtt);
352.13484 + retry_gtt:
352.13485 + 	gtt.handle = bo->handle;
352.13486 + 	if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gtt))) {
352.13487 ++		DBG(("%s: failed %d, throttling/cleaning caches\n",
352.13488 ++		     __FUNCTION__, err));
352.13489 + 		assert(err != EINVAL);
352.13490 + 
352.13491 + 		(void)__kgem_throttle_retire(kgem, 0);
352.13492 +@@ -460,6 +617,8 @@ retry_mmap:
352.13493 + 		   kgem->fd, gtt.offset);
352.13494 + 	if (ptr == MAP_FAILED) {
352.13495 + 		err = errno;
352.13496 ++		DBG(("%s: failed %d, throttling/cleaning caches\n",
352.13497 ++		     __FUNCTION__, err));
352.13498 + 		assert(err != EINVAL);
352.13499 + 
352.13500 + 		if (__kgem_throttle_retire(kgem, 0))
352.13501 +@@ -498,6 +657,8 @@ retry_wc:
352.13502 + 	wc.size = bytes(bo);
352.13503 + 	wc.flags = I915_MMAP_WC;
352.13504 + 	if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP_v2, &wc))) {
352.13505 ++		DBG(("%s: failed %d, throttling/cleaning caches\n",
352.13506 ++		     __FUNCTION__, err));
352.13507 + 		assert(err != EINVAL);
352.13508 + 
352.13509 + 		if (__kgem_throttle_retire(kgem, 0))
352.13510 +@@ -519,16 +680,19 @@ retry_wc:
352.13511 + 
352.13512 + static void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
352.13513 + {
352.13514 +-	struct drm_i915_gem_mmap mmap_arg;
352.13515 ++	struct local_i915_gem_mmap arg;
352.13516 + 	int err;
352.13517 + 
352.13518 ++	VG_CLEAR(arg);
352.13519 ++	arg.offset = 0;
352.13520 ++
352.13521 + retry:
352.13522 +-	VG_CLEAR(mmap_arg);
352.13523 +-	mmap_arg.handle = bo->handle;
352.13524 +-	mmap_arg.offset = 0;
352.13525 +-	mmap_arg.size = bytes(bo);
352.13526 +-	if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))) {
352.13527 +-		assert(err != EINVAL);
352.13528 ++	arg.handle = bo->handle;
352.13529 ++	arg.size = bytes(bo);
352.13530 ++	if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP, &arg))) {
352.13531 ++		DBG(("%s: failed %d, throttling/cleaning caches\n",
352.13532 ++		     __FUNCTION__, err));
352.13533 ++		assert(err != -EINVAL || bo->prime);
352.13534 + 
352.13535 + 		if (__kgem_throttle_retire(kgem, 0))
352.13536 + 			goto retry;
352.13537 +@@ -536,15 +700,16 @@ retry:
352.13538 + 		if (kgem_cleanup_cache(kgem))
352.13539 + 			goto retry;
352.13540 + 
352.13541 +-		ERR(("%s: failed to mmap handle=%d, %d bytes, into CPU domain: %d\n",
352.13542 +-		     __FUNCTION__, bo->handle, bytes(bo), -err));
352.13543 ++		ERR(("%s: failed to mmap handle=%d (prime? %d), %d bytes, into CPU domain: %d\n",
352.13544 ++		     __FUNCTION__, bo->handle, bo->prime, bytes(bo), -err));
352.13545 ++		bo->purged = 1;
352.13546 + 		return NULL;
352.13547 + 	}
352.13548 + 
352.13549 +-	VG(VALGRIND_MAKE_MEM_DEFINED(mmap_arg.addr_ptr, bytes(bo)));
352.13550 ++	VG(VALGRIND_MAKE_MEM_DEFINED(arg.addr_ptr, bytes(bo)));
352.13551 + 
352.13552 + 	DBG(("%s: caching CPU vma for %d\n", __FUNCTION__, bo->handle));
352.13553 +-	return bo->map__cpu = (void *)(uintptr_t)mmap_arg.addr_ptr;
352.13554 ++	return bo->map__cpu = (void *)(uintptr_t)arg.addr_ptr;
352.13555 + }
352.13556 + 
352.13557 + static int gem_write(int fd, uint32_t handle,
352.13558 +@@ -634,16 +799,10 @@ static void kgem_bo_retire(struct kgem *kgem, struct kgem_bo *bo)
352.13559 + 	assert(bo->exec == NULL);
352.13560 + 	assert(list_is_empty(&bo->vma));
352.13561 + 
352.13562 +-	if (bo->rq) {
352.13563 +-		__kgem_bo_clear_busy(bo);
352.13564 +-		kgem_retire(kgem);
352.13565 +-		assert_bo_retired(bo);
352.13566 +-	} else {
352.13567 +-		assert(bo->exec == NULL);
352.13568 +-		assert(list_is_empty(&bo->request));
352.13569 +-		assert(!bo->needs_flush);
352.13570 +-		ASSERT_IDLE(kgem, bo->handle);
352.13571 +-	}
352.13572 ++	if (bo->rq)
352.13573 ++		__kgem_retire_requests_upto(kgem, bo);
352.13574 ++	ASSERT_IDLE(kgem, bo->handle);
352.13575 ++	assert_bo_retired(bo);
352.13576 + }
352.13577 + 
352.13578 + static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
352.13579 +@@ -655,10 +814,8 @@ static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
352.13580 + 	assert(list_is_empty(&bo->vma));
352.13581 + 
352.13582 + 	if (bo->rq) {
352.13583 +-		if (!__kgem_busy(kgem, bo->handle)) {
352.13584 +-			__kgem_bo_clear_busy(bo);
352.13585 +-			kgem_retire(kgem);
352.13586 +-		}
352.13587 ++		if (!__kgem_busy(kgem, bo->handle))
352.13588 ++			__kgem_retire_requests_upto(kgem, bo);
352.13589 + 	} else {
352.13590 + 		assert(!bo->needs_flush);
352.13591 + 		ASSERT_IDLE(kgem, bo->handle);
352.13592 +@@ -694,6 +851,8 @@ retry:
352.13593 + 	}
352.13594 + 
352.13595 + 	if ((err = gem_write(kgem->fd, bo->handle, 0, length, data))) {
352.13596 ++		DBG(("%s: failed %d, throttling/cleaning caches\n",
352.13597 ++		     __FUNCTION__, err));
352.13598 + 		assert(err != EINVAL);
352.13599 + 
352.13600 + 		(void)__kgem_throttle_retire(kgem, 0);
352.13601 +@@ -728,27 +887,21 @@ static uint32_t gem_create(int fd, int num_pages)
352.13602 + 	return create.handle;
352.13603 + }
352.13604 + 
352.13605 +-static bool
352.13606 ++static void
352.13607 + kgem_bo_set_purgeable(struct kgem *kgem, struct kgem_bo *bo)
352.13608 + {
352.13609 +-#if DBG_NO_MADV
352.13610 +-	return true;
352.13611 +-#else
352.13612 ++#if !DBG_NO_MADV
352.13613 + 	struct drm_i915_gem_madvise madv;
352.13614 + 
352.13615 + 	assert(bo->exec == NULL);
352.13616 +-	assert(!bo->purged);
352.13617 + 
352.13618 + 	VG_CLEAR(madv);
352.13619 + 	madv.handle = bo->handle;
352.13620 + 	madv.madv = I915_MADV_DONTNEED;
352.13621 + 	if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv) == 0) {
352.13622 +-		bo->purged = 1;
352.13623 +-		kgem->need_purge |= !madv.retained && bo->domain == DOMAIN_GPU;
352.13624 +-		return madv.retained;
352.13625 ++		bo->purged = true;
352.13626 ++		kgem->need_purge |= !madv.retained && bo->domain != DOMAIN_CPU;
352.13627 + 	}
352.13628 +-
352.13629 +-	return true;
352.13630 + #endif
352.13631 + }
352.13632 + 
352.13633 +@@ -788,7 +941,7 @@ kgem_bo_clear_purgeable(struct kgem *kgem, struct kgem_bo *bo)
352.13634 + 	madv.madv = I915_MADV_WILLNEED;
352.13635 + 	if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv) == 0) {
352.13636 + 		bo->purged = !madv.retained;
352.13637 +-		kgem->need_purge |= !madv.retained && bo->domain == DOMAIN_GPU;
352.13638 ++		kgem->need_purge |= !madv.retained && bo->domain != DOMAIN_CPU;
352.13639 + 		return madv.retained;
352.13640 + 	}
352.13641 + 
352.13642 +@@ -869,13 +1022,17 @@ static struct kgem_request *__kgem_request_alloc(struct kgem *kgem)
352.13643 + {
352.13644 + 	struct kgem_request *rq;
352.13645 + 
352.13646 +-	rq = __kgem_freed_request;
352.13647 +-	if (rq) {
352.13648 +-		__kgem_freed_request = *(struct kgem_request **)rq;
352.13649 ++	if (unlikely(kgem->wedged)) {
352.13650 ++		rq = &kgem->static_request;
352.13651 + 	} else {
352.13652 +-		rq = malloc(sizeof(*rq));
352.13653 +-		if (rq == NULL)
352.13654 +-			rq = &kgem->static_request;
352.13655 ++		rq = __kgem_freed_request;
352.13656 ++		if (rq) {
352.13657 ++			__kgem_freed_request = *(struct kgem_request **)rq;
352.13658 ++		} else {
352.13659 ++			rq = malloc(sizeof(*rq));
352.13660 ++			if (rq == NULL)
352.13661 ++				rq = &kgem->static_request;
352.13662 ++		}
352.13663 + 	}
352.13664 + 
352.13665 + 	list_init(&rq->buffers);
352.13666 +@@ -925,11 +1082,11 @@ total_ram_size(void)
352.13667 + #ifdef HAVE_STRUCT_SYSINFO_TOTALRAM
352.13668 + 	struct sysinfo info;
352.13669 + 	if (sysinfo(&info) == 0)
352.13670 +-		return info.totalram * info.mem_unit;
352.13671 ++		return (size_t)info.totalram * info.mem_unit;
352.13672 + #endif
352.13673 + 
352.13674 + #ifdef _SC_PHYS_PAGES
352.13675 +-	 return sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
352.13676 ++	 return (size_t)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
352.13677 + #endif
352.13678 + 
352.13679 + 	return 0;
352.13680 +@@ -1150,6 +1307,10 @@ static bool test_has_wc_mmap(struct kgem *kgem)
352.13681 + 	if (DBG_NO_WC_MMAP)
352.13682 + 		return false;
352.13683 + 
352.13684 ++	/* XXX See https://bugs.freedesktop.org/show_bug.cgi?id=90841 */
352.13685 ++	if (kgem->gen < 033)
352.13686 ++		return false;
352.13687 ++
352.13688 + 	if (gem_param(kgem, LOCAL_I915_PARAM_MMAP_VERSION) < 1)
352.13689 + 		return false;
352.13690 + 
352.13691 +@@ -1187,7 +1348,7 @@ static bool test_has_caching(struct kgem *kgem)
352.13692 + 
352.13693 + static bool test_has_userptr(struct kgem *kgem)
352.13694 + {
352.13695 +-	uint32_t handle;
352.13696 ++	struct local_i915_gem_userptr arg;
352.13697 + 	void *ptr;
352.13698 + 
352.13699 + 	if (DBG_NO_USERPTR)
352.13700 +@@ -1200,11 +1361,23 @@ static bool test_has_userptr(struct kgem *kgem)
352.13701 + 	if (posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE))
352.13702 + 		return false;
352.13703 + 
352.13704 +-	handle = gem_userptr(kgem->fd, ptr, PAGE_SIZE, false);
352.13705 +-	gem_close(kgem->fd, handle);
352.13706 +-	free(ptr);
352.13707 ++	VG_CLEAR(arg);
352.13708 ++	arg.user_ptr = (uintptr_t)ptr;
352.13709 ++	arg.user_size = PAGE_SIZE;
352.13710 ++	arg.flags = I915_USERPTR_UNSYNCHRONIZED;
352.13711 + 
352.13712 +-	return handle != 0;
352.13713 ++	if (DBG_NO_UNSYNCHRONIZED_USERPTR ||
352.13714 ++	    do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_USERPTR, &arg)) {
352.13715 ++		arg.flags &= ~I915_USERPTR_UNSYNCHRONIZED;
352.13716 ++		if (do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_USERPTR, &arg))
352.13717 ++			arg.handle = 0;
352.13718 ++		/* Leak the userptr bo to keep the mmu_notifier alive */
352.13719 ++	} else {
352.13720 ++		gem_close(kgem->fd, arg.handle);
352.13721 ++		free(ptr);
352.13722 ++	}
352.13723 ++
352.13724 ++	return arg.handle != 0;
352.13725 + }
352.13726 + 
352.13727 + static bool test_has_create2(struct kgem *kgem)
352.13728 +@@ -1227,67 +1400,187 @@ static bool test_has_create2(struct kgem *kgem)
352.13729 + #endif
352.13730 + }
352.13731 + 
352.13732 +-static bool test_has_secure_batches(struct kgem *kgem)
352.13733 ++static bool test_can_blt_y(struct kgem *kgem)
352.13734 + {
352.13735 +-	if (DBG_NO_SECURE_BATCHES)
352.13736 ++	struct drm_i915_gem_exec_object2 object;
352.13737 ++	uint32_t batch[] = {
352.13738 ++#define MI_LOAD_REGISTER_IMM (0x22<<23 | (3-2))
352.13739 ++#define BCS_SWCTRL 0x22200
352.13740 ++#define BCS_SRC_Y (1 << 0)
352.13741 ++#define BCS_DST_Y (1 << 1)
352.13742 ++		MI_LOAD_REGISTER_IMM,
352.13743 ++		BCS_SWCTRL,
352.13744 ++		(BCS_SRC_Y | BCS_DST_Y) << 16 | (BCS_SRC_Y | BCS_DST_Y),
352.13745 ++
352.13746 ++		MI_LOAD_REGISTER_IMM,
352.13747 ++		BCS_SWCTRL,
352.13748 ++		(BCS_SRC_Y | BCS_DST_Y) << 16,
352.13749 ++
352.13750 ++		MI_BATCH_BUFFER_END,
352.13751 ++		0,
352.13752 ++	};
352.13753 ++	int ret;
352.13754 ++
352.13755 ++	if (DBG_NO_BLT_Y)
352.13756 + 		return false;
352.13757 + 
352.13758 +-	return gem_param(kgem, LOCAL_I915_PARAM_HAS_SECURE_BATCHES) > 0;
352.13759 ++	if (kgem->gen < 060)
352.13760 ++		return false;
352.13761 ++
352.13762 ++	memset(&object, 0, sizeof(object));
352.13763 ++	object.handle = gem_create(kgem->fd, 1);
352.13764 ++
352.13765 ++	ret = gem_write(kgem->fd, object.handle, 0, sizeof(batch), batch);
352.13766 ++	if (ret == 0) {
352.13767 ++		struct drm_i915_gem_execbuffer2 execbuf;
352.13768 ++
352.13769 ++		memset(&execbuf, 0, sizeof(execbuf));
352.13770 ++		execbuf.buffers_ptr = (uintptr_t)&object;
352.13771 ++		execbuf.buffer_count = 1;
352.13772 ++		execbuf.flags = KGEM_BLT;
352.13773 ++
352.13774 ++		ret = do_ioctl(kgem->fd,
352.13775 ++			       DRM_IOCTL_I915_GEM_EXECBUFFER2,
352.13776 ++			       &execbuf);
352.13777 ++	}
352.13778 ++	gem_close(kgem->fd, object.handle);
352.13779 ++
352.13780 ++	return ret == 0;
352.13781 + }
352.13782 + 
352.13783 +-static bool test_has_pinned_batches(struct kgem *kgem)
352.13784 ++static bool gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
352.13785 + {
352.13786 +-	if (DBG_NO_PINNED_BATCHES)
352.13787 ++	struct drm_i915_gem_set_tiling set_tiling;
352.13788 ++
352.13789 ++	if (DBG_NO_TILING)
352.13790 + 		return false;
352.13791 + 
352.13792 +-	return gem_param(kgem, LOCAL_I915_PARAM_HAS_PINNED_BATCHES) > 0;
352.13793 ++	VG_CLEAR(set_tiling);
352.13794 ++	set_tiling.handle = handle;
352.13795 ++	set_tiling.tiling_mode = tiling;
352.13796 ++	set_tiling.stride = stride;
352.13797 ++
352.13798 ++	if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
352.13799 ++		return set_tiling.tiling_mode == tiling;
352.13800 ++
352.13801 ++	return false;
352.13802 + }
352.13803 + 
352.13804 +-static int kgem_get_screen_index(struct kgem *kgem)
352.13805 ++static bool test_can_scanout_y(struct kgem *kgem)
352.13806 + {
352.13807 +-	struct sna *sna = container_of(kgem, struct sna, kgem);
352.13808 +-	return sna->scrn->scrnIndex;
352.13809 ++	struct drm_mode_fb_cmd arg;
352.13810 ++	bool ret = false;
352.13811 ++
352.13812 ++	if (DBG_NO_SCANOUT_Y)
352.13813 ++		return false;
352.13814 ++
352.13815 ++	VG_CLEAR(arg);
352.13816 ++	arg.width = 32;
352.13817 ++	arg.height = 32;
352.13818 ++	arg.pitch = 4*32;
352.13819 ++	arg.bpp = 32;
352.13820 ++	arg.depth = 24;
352.13821 ++	arg.handle = gem_create(kgem->fd, 1);
352.13822 ++
352.13823 ++	if (gem_set_tiling(kgem->fd, arg.handle, I915_TILING_Y, arg.pitch))
352.13824 ++		ret = do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg) == 0;
352.13825 ++	if (!ret) {
352.13826 ++		struct local_mode_fb_cmd2 {
352.13827 ++			uint32_t fb_id;
352.13828 ++			uint32_t width, height;
352.13829 ++			uint32_t pixel_format;
352.13830 ++			uint32_t flags;
352.13831 ++
352.13832 ++			uint32_t handles[4];
352.13833 ++			uint32_t pitches[4];
352.13834 ++			uint32_t offsets[4];
352.13835 ++			uint64_t modifiers[4];
352.13836 ++		} f;
352.13837 ++#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
352.13838 ++		memset(&f, 0, sizeof(f));
352.13839 ++		f.width = arg.width;
352.13840 ++		f.height = arg.height;
352.13841 ++		f.handles[0] = arg.handle;
352.13842 ++		f.pitches[0] = arg.pitch;
352.13843 ++		f.modifiers[0] = (uint64_t)1 << 56 | 2; /* MOD_Y_TILED */
352.13844 ++		f.pixel_format = 'X' | 'R' << 8 | '2' << 16 | '4' << 24; /* XRGB8888 */
352.13845 ++		f.flags = 1 << 1; /* + modifier */
352.13846 ++		if (drmIoctl(kgem->fd, LOCAL_IOCTL_MODE_ADDFB2, &f) == 0) {
352.13847 ++			ret = true;
352.13848 ++			arg.fb_id = f.fb_id;
352.13849 ++		}
352.13850 ++	}
352.13851 ++	do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &arg.fb_id);
352.13852 ++	gem_close(kgem->fd, arg.handle);
352.13853 ++
352.13854 ++	return ret;
352.13855 + }
352.13856 + 
352.13857 +-static int __find_debugfs(struct kgem *kgem)
352.13858 ++static bool test_has_dirtyfb(struct kgem *kgem)
352.13859 + {
352.13860 +-	int i;
352.13861 ++	struct drm_mode_fb_cmd create;
352.13862 ++	bool ret = false;
352.13863 + 
352.13864 +-	for (i = 0; i < DRM_MAX_MINOR; i++) {
352.13865 +-		char path[80];
352.13866 ++	if (DBG_NO_DIRTYFB)
352.13867 ++		return false;
352.13868 + 
352.13869 +-		sprintf(path, "/sys/kernel/debug/dri/%d/i915_wedged", i);
352.13870 +-		if (access(path, R_OK) == 0)
352.13871 +-			return i;
352.13872 ++	VG_CLEAR(create);
352.13873 ++	create.width = 32;
352.13874 ++	create.height = 32;
352.13875 ++	create.pitch = 4*32;
352.13876 ++	create.bpp = 32;
352.13877 ++	create.depth = 32;
352.13878 ++	create.handle = gem_create(kgem->fd, 1);
352.13879 ++	if (create.handle == 0)
352.13880 ++		return false;
352.13881 + 
352.13882 +-		sprintf(path, "/debug/dri/%d/i915_wedged", i);
352.13883 +-		if (access(path, R_OK) == 0)
352.13884 +-			return i;
352.13885 ++	if (drmIoctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &create) == 0) {
352.13886 ++		struct drm_mode_fb_dirty_cmd dirty;
352.13887 ++
352.13888 ++		memset(&dirty, 0, sizeof(dirty));
352.13889 ++		dirty.fb_id = create.fb_id;
352.13890 ++		ret = drmIoctl(kgem->fd,
352.13891 ++			       DRM_IOCTL_MODE_DIRTYFB,
352.13892 ++			       &dirty) == 0;
352.13893 ++
352.13894 ++		/* XXX There may be multiple levels of DIRTYFB, depending on
352.13895 ++		 * whether the kernel thinks tracking dirty regions is
352.13896 ++		 * beneficial vs flagging the whole fb as dirty.
352.13897 ++		 */
352.13898 ++
352.13899 ++		drmIoctl(kgem->fd,
352.13900 ++			 DRM_IOCTL_MODE_RMFB,
352.13901 ++			 &create.fb_id);
352.13902 + 	}
352.13903 ++	gem_close(kgem->fd, create.handle);
352.13904 + 
352.13905 +-	return -1;
352.13906 ++	return ret;
352.13907 + }
352.13908 + 
352.13909 +-static int kgem_get_minor(struct kgem *kgem)
352.13910 ++static bool test_has_secure_batches(struct kgem *kgem)
352.13911 + {
352.13912 +-	struct stat st;
352.13913 ++	if (DBG_NO_SECURE_BATCHES)
352.13914 ++		return false;
352.13915 + 
352.13916 +-	if (fstat(kgem->fd, &st))
352.13917 +-		return __find_debugfs(kgem);
352.13918 ++	return gem_param(kgem, LOCAL_I915_PARAM_HAS_SECURE_BATCHES) > 0;
352.13919 ++}
352.13920 + 
352.13921 +-	if (!S_ISCHR(st.st_mode))
352.13922 +-		return __find_debugfs(kgem);
352.13923 ++static bool test_has_pinned_batches(struct kgem *kgem)
352.13924 ++{
352.13925 ++	if (DBG_NO_PINNED_BATCHES)
352.13926 ++		return false;
352.13927 + 
352.13928 +-	return st.st_rdev & 0x63;
352.13929 ++	return gem_param(kgem, LOCAL_I915_PARAM_HAS_PINNED_BATCHES) > 0;
352.13930 + }
352.13931 + 
352.13932 + static bool kgem_init_pinned_batches(struct kgem *kgem)
352.13933 + {
352.13934 + 	int count[2] = { 16, 4 };
352.13935 + 	int size[2] = { 1, 4 };
352.13936 ++	int ret = 0;
352.13937 + 	int n, i;
352.13938 + 
352.13939 +-	if (kgem->wedged)
352.13940 ++	if (unlikely(kgem->wedged))
352.13941 + 		return true;
352.13942 + 
352.13943 + 	for (n = 0; n < ARRAY_SIZE(count); n++) {
352.13944 +@@ -1311,7 +1604,8 @@ static bool kgem_init_pinned_batches(struct kgem *kgem)
352.13945 + 			}
352.13946 + 
352.13947 + 			pin.alignment = 0;
352.13948 +-			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_PIN, &pin)) {
352.13949 ++			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
352.13950 ++			if (ret) {
352.13951 + 				gem_close(kgem->fd, pin.handle);
352.13952 + 				free(bo);
352.13953 + 				goto err;
352.13954 +@@ -1333,6 +1627,16 @@ err:
352.13955 + 		}
352.13956 + 	}
352.13957 + 
352.13958 ++	/* If we fail to pin some memory for 830gm/845g, we need to disable
352.13959 ++	 * acceleration as otherwise the machine will eventually fail. However,
352.13960 ++	 * the kernel started arbitrarily rejecting PIN, so hope for the best
352.13961 ++	 * if the ioctl no longer works.
352.13962 ++	 */
352.13963 ++	if (ret != -ENODEV && kgem->gen == 020)
352.13964 ++		return false;
352.13965 ++
352.13966 ++	kgem->has_pinned_batches = false;
352.13967 ++
352.13968 + 	/* For simplicity populate the lists with a single unpinned bo */
352.13969 + 	for (n = 0; n < ARRAY_SIZE(count); n++) {
352.13970 + 		struct kgem_bo *bo;
352.13971 +@@ -1340,18 +1644,18 @@ err:
352.13972 + 
352.13973 + 		handle = gem_create(kgem->fd, size[n]);
352.13974 + 		if (handle == 0)
352.13975 +-			break;
352.13976 ++			return false;
352.13977 + 
352.13978 + 		bo = __kgem_bo_alloc(handle, size[n]);
352.13979 + 		if (bo == NULL) {
352.13980 + 			gem_close(kgem->fd, handle);
352.13981 +-			break;
352.13982 ++			return false;
352.13983 + 		}
352.13984 + 
352.13985 + 		debug_alloc__bo(kgem, bo);
352.13986 + 		list_add(&bo->list, &kgem->pinned_batches[n]);
352.13987 + 	}
352.13988 +-	return false;
352.13989 ++	return true;
352.13990 + }
352.13991 + 
352.13992 + static void kgem_init_swizzling(struct kgem *kgem)
352.13993 +@@ -1364,7 +1668,7 @@ static void kgem_init_swizzling(struct kgem *kgem)
352.13994 + 	} tiling;
352.13995 + #define LOCAL_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct local_i915_gem_get_tiling_v2)
352.13996 + 
352.13997 +-	VG_CLEAR(tiling);
352.13998 ++	memset(&tiling, 0, sizeof(tiling));
352.13999 + 	tiling.handle = gem_create(kgem->fd, 1);
352.14000 + 	if (!tiling.handle)
352.14001 + 		return;
352.14002 +@@ -1375,12 +1679,23 @@ static void kgem_init_swizzling(struct kgem *kgem)
352.14003 + 	if (do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_GET_TILING, &tiling))
352.14004 + 		goto out;
352.14005 + 
352.14006 +-	if (kgem->gen < 50 && tiling.phys_swizzle_mode != tiling.swizzle_mode)
352.14007 ++	DBG(("%s: swizzle_mode=%d, phys_swizzle_mode=%d\n",
352.14008 ++	     __FUNCTION__, tiling.swizzle_mode, tiling.phys_swizzle_mode));
352.14009 ++
352.14010 ++	kgem->can_fence =
352.14011 ++		!DBG_NO_TILING &&
352.14012 ++		tiling.swizzle_mode != I915_BIT_6_SWIZZLE_UNKNOWN;
352.14013 ++
352.14014 ++	if (kgem->gen < 050 && tiling.phys_swizzle_mode != tiling.swizzle_mode)
352.14015 + 		goto out;
352.14016 + 
352.14017 +-	choose_memcpy_tiled_x(kgem, tiling.swizzle_mode);
352.14018 ++	if (!DBG_NO_DETILING)
352.14019 ++		choose_memcpy_tiled_x(kgem,
352.14020 ++				      tiling.swizzle_mode,
352.14021 ++				      __to_sna(kgem)->cpu_features);
352.14022 + out:
352.14023 + 	gem_close(kgem->fd, tiling.handle);
352.14024 ++	DBG(("%s: can fence?=%d\n", __FUNCTION__, kgem->can_fence));
352.14025 + }
352.14026 + 
352.14027 + static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
352.14028 +@@ -1399,6 +1714,7 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
352.14029 + 	     bo->handle, (long long)bo->presumed_offset));
352.14030 + 	for (n = 0; n < kgem->nreloc__self; n++) {
352.14031 + 		int i = kgem->reloc__self[n];
352.14032 ++		uint64_t addr;
352.14033 + 
352.14034 + 		assert(kgem->reloc[i].target_handle == ~0U);
352.14035 + 		kgem->reloc[i].target_handle = bo->target_handle;
352.14036 +@@ -1412,13 +1728,17 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
352.14037 + 
352.14038 + 			kgem->reloc[i].delta -= shrink;
352.14039 + 		}
352.14040 +-		kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t)] =
352.14041 +-			kgem->reloc[i].delta + bo->presumed_offset;
352.14042 ++		addr = (int)kgem->reloc[i].delta + bo->presumed_offset;
352.14043 ++		kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t)] = addr;
352.14044 ++		if (kgem->gen >= 0100)
352.14045 ++			kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t) + 1] = addr >> 32;
352.14046 + 	}
352.14047 + 
352.14048 + 	if (n == 256) {
352.14049 + 		for (n = kgem->reloc__self[255]; n < kgem->nreloc; n++) {
352.14050 + 			if (kgem->reloc[n].target_handle == ~0U) {
352.14051 ++				uint64_t addr;
352.14052 ++
352.14053 + 				kgem->reloc[n].target_handle = bo->target_handle;
352.14054 + 				kgem->reloc[n].presumed_offset = bo->presumed_offset;
352.14055 + 
352.14056 +@@ -1429,8 +1749,11 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
352.14057 + 					     kgem->reloc[n].delta - shrink));
352.14058 + 					kgem->reloc[n].delta -= shrink;
352.14059 + 				}
352.14060 +-				kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t)] =
352.14061 +-					kgem->reloc[n].delta + bo->presumed_offset;
352.14062 ++
352.14063 ++				addr = (int)kgem->reloc[n].delta + bo->presumed_offset;
352.14064 ++				kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t)] = addr;
352.14065 ++				if (kgem->gen >= 0100)
352.14066 ++					kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t) + 1] = addr >> 32;
352.14067 + 			}
352.14068 + 		}
352.14069 + 	}
352.14070 +@@ -1444,6 +1767,44 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
352.14071 + 	}
352.14072 + }
352.14073 + 
352.14074 ++static int kgem_bo_wait(struct kgem *kgem, struct kgem_bo *bo)
352.14075 ++{
352.14076 ++	struct local_i915_gem_wait {
352.14077 ++		uint32_t handle;
352.14078 ++		uint32_t flags;
352.14079 ++		int64_t timeout;
352.14080 ++	} wait;
352.14081 ++#define LOCAL_I915_GEM_WAIT       0x2c
352.14082 ++#define LOCAL_IOCTL_I915_GEM_WAIT         DRM_IOWR(DRM_COMMAND_BASE + LOCAL_I915_GEM_WAIT, struct local_i915_gem_wait)
352.14083 ++	int ret;
352.14084 ++
352.14085 ++	DBG(("%s: waiting for handle=%d\n", __FUNCTION__, bo->handle));
352.14086 ++	if (bo->rq == NULL)
352.14087 ++		return 0;
352.14088 ++
352.14089 ++	VG_CLEAR(wait);
352.14090 ++	wait.handle = bo->handle;
352.14091 ++	wait.flags = 0;
352.14092 ++	wait.timeout = -1;
352.14093 ++	ret = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_WAIT, &wait);
352.14094 ++	if (ret) {
352.14095 ++		struct drm_i915_gem_set_domain set_domain;
352.14096 ++
352.14097 ++		VG_CLEAR(set_domain);
352.14098 ++		set_domain.handle = bo->handle;
352.14099 ++		set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.14100 ++		set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.14101 ++		ret = do_ioctl(kgem->fd,
352.14102 ++			       DRM_IOCTL_I915_GEM_SET_DOMAIN,
352.14103 ++			       &set_domain);
352.14104 ++	}
352.14105 ++
352.14106 ++	if (ret == 0)
352.14107 ++		__kgem_retire_requests_upto(kgem, bo);
352.14108 ++
352.14109 ++	return ret;
352.14110 ++}
352.14111 ++
352.14112 + static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
352.14113 + {
352.14114 + 	struct kgem_bo *last;
352.14115 +@@ -1464,20 +1825,41 @@ static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
352.14116 + 	if (!kgem->has_llc)
352.14117 + 		flags |= CREATE_UNCACHED;
352.14118 + 
352.14119 ++restart:
352.14120 + 	kgem->batch_bo = kgem_create_linear(kgem,
352.14121 + 					    sizeof(uint32_t)*kgem->batch_size,
352.14122 + 					    flags);
352.14123 + 	if (kgem->batch_bo)
352.14124 + 		kgem->batch = kgem_bo_map__cpu(kgem, kgem->batch_bo);
352.14125 + 	if (kgem->batch == NULL) {
352.14126 +-		DBG(("%s: unable to map batch bo, mallocing(size=%d)\n",
352.14127 +-		     __FUNCTION__,
352.14128 +-		     sizeof(uint32_t)*kgem->batch_size));
352.14129 ++		int ring = kgem->ring == KGEM_BLT;
352.14130 ++		assert(ring < ARRAY_SIZE(kgem->requests));
352.14131 ++
352.14132 + 		if (kgem->batch_bo) {
352.14133 + 			kgem_bo_destroy(kgem, kgem->batch_bo);
352.14134 + 			kgem->batch_bo = NULL;
352.14135 + 		}
352.14136 + 
352.14137 ++		if (!list_is_empty(&kgem->requests[ring])) {
352.14138 ++			struct kgem_request *rq;
352.14139 ++
352.14140 ++			rq = list_first_entry(&kgem->requests[ring],
352.14141 ++					      struct kgem_request, list);
352.14142 ++			assert(rq->ring == ring);
352.14143 ++			assert(rq->bo);
352.14144 ++			assert(RQ(rq->bo->rq) == rq);
352.14145 ++			if (kgem_bo_wait(kgem, rq->bo) == 0)
352.14146 ++				goto restart;
352.14147 ++		}
352.14148 ++
352.14149 ++		if (flags & CREATE_NO_THROTTLE) {
352.14150 ++			flags &= ~CREATE_NO_THROTTLE;
352.14151 ++			if (kgem_cleanup_cache(kgem))
352.14152 ++				goto restart;
352.14153 ++		}
352.14154 ++
352.14155 ++		DBG(("%s: unable to map batch bo, mallocing(size=%d)\n",
352.14156 ++		     __FUNCTION__, sizeof(uint32_t)*kgem->batch_size));
352.14157 + 		if (posix_memalign((void **)&kgem->batch, PAGE_SIZE,
352.14158 + 				   ALIGN(sizeof(uint32_t) * kgem->batch_size, PAGE_SIZE))) {
352.14159 + 			ERR(("%s: batch allocation failed, disabling acceleration\n", __FUNCTION__));
352.14160 +@@ -1495,18 +1877,79 @@ static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
352.14161 + 	return last;
352.14162 + }
352.14163 + 
352.14164 +-void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14165 ++static void
352.14166 ++no_retire(struct kgem *kgem)
352.14167 ++{
352.14168 ++	(void)kgem;
352.14169 ++}
352.14170 ++
352.14171 ++static void
352.14172 ++no_expire(struct kgem *kgem)
352.14173 ++{
352.14174 ++	(void)kgem;
352.14175 ++}
352.14176 ++
352.14177 ++static void
352.14178 ++no_context_switch(struct kgem *kgem, int new_mode)
352.14179 ++{
352.14180 ++	(void)kgem;
352.14181 ++	(void)new_mode;
352.14182 ++}
352.14183 ++
352.14184 ++static uint64_t get_gtt_size(int fd)
352.14185 + {
352.14186 + 	struct drm_i915_gem_get_aperture aperture;
352.14187 ++	struct local_i915_gem_context_param {
352.14188 ++		uint32_t context;
352.14189 ++		uint32_t size;
352.14190 ++		uint64_t param;
352.14191 ++#define LOCAL_CONTEXT_PARAM_BAN_PERIOD	0x1
352.14192 ++#define LOCAL_CONTEXT_PARAM_NO_ZEROMAP	0x2
352.14193 ++#define LOCAL_CONTEXT_PARAM_GTT_SIZE	0x3
352.14194 ++		uint64_t value;
352.14195 ++	} p;
352.14196 ++#define LOCAL_I915_GEM_CONTEXT_GETPARAM       0x34
352.14197 ++#define LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_CONTEXT_GETPARAM, struct local_i915_gem_context_param)
352.14198 ++
352.14199 ++	memset(&aperture, 0, sizeof(aperture));
352.14200 ++
352.14201 ++	memset(&p, 0, sizeof(p));
352.14202 ++	p.param = LOCAL_CONTEXT_PARAM_GTT_SIZE;
352.14203 ++	if (drmIoctl(fd, LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p) == 0)
352.14204 ++		aperture.aper_size = p.value;
352.14205 ++	if (aperture.aper_size == 0)
352.14206 ++		(void)drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
352.14207 ++	if (aperture.aper_size == 0)
352.14208 ++		aperture.aper_size = 64*1024*1024;
352.14209 ++
352.14210 ++	DBG(("%s: aperture size %lld, available now %lld\n",
352.14211 ++	     __FUNCTION__,
352.14212 ++	     (long long)aperture.aper_size,
352.14213 ++	     (long long)aperture.aper_available_size));
352.14214 ++
352.14215 ++	/* clamp aperture to uint32_t for simplicity */
352.14216 ++	if (aperture.aper_size > 0xc0000000)
352.14217 ++		aperture.aper_size = 0xc0000000;
352.14218 ++
352.14219 ++	return aperture.aper_size;
352.14220 ++}
352.14221 ++
352.14222 ++void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14223 ++{
352.14224 + 	size_t totalram;
352.14225 + 	unsigned half_gpu_max;
352.14226 + 	unsigned int i, j;
352.14227 ++	uint64_t gtt_size;
352.14228 + 
352.14229 + 	DBG(("%s: fd=%d, gen=%d\n", __FUNCTION__, fd, gen));
352.14230 + 
352.14231 + 	kgem->fd = fd;
352.14232 + 	kgem->gen = gen;
352.14233 + 
352.14234 ++	kgem->retire = no_retire;
352.14235 ++	kgem->expire = no_expire;
352.14236 ++	kgem->context_switch = no_context_switch;
352.14237 ++
352.14238 + 	list_init(&kgem->requests[0]);
352.14239 + 	list_init(&kgem->requests[1]);
352.14240 + 	list_init(&kgem->batch_buffers);
352.14241 +@@ -1586,10 +2029,21 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14242 + 	DBG(("%s: can blt to cpu? %d\n", __FUNCTION__,
352.14243 + 	     kgem->can_blt_cpu));
352.14244 + 
352.14245 ++	kgem->can_blt_y = test_can_blt_y(kgem);
352.14246 ++	DBG(("%s: can blit to Y-tiled surfaces? %d\n", __FUNCTION__,
352.14247 ++	     kgem->can_blt_y));
352.14248 ++
352.14249 + 	kgem->can_render_y = gen != 021 && (gen >> 3) != 4;
352.14250 + 	DBG(("%s: can render to Y-tiled surfaces? %d\n", __FUNCTION__,
352.14251 + 	     kgem->can_render_y));
352.14252 + 
352.14253 ++	kgem->can_scanout_y = test_can_scanout_y(kgem);
352.14254 ++	DBG(("%s: can scanout Y-tiled surfaces? %d\n", __FUNCTION__,
352.14255 ++	     kgem->can_scanout_y));
352.14256 ++
352.14257 ++	kgem->has_dirtyfb = test_has_dirtyfb(kgem);
352.14258 ++	DBG(("%s: has dirty fb? %d\n", __FUNCTION__, kgem->has_dirtyfb));
352.14259 ++
352.14260 + 	kgem->has_secure_batches = test_has_secure_batches(kgem);
352.14261 + 	DBG(("%s: can use privileged batchbuffers? %d\n", __FUNCTION__,
352.14262 + 	     kgem->has_secure_batches));
352.14263 +@@ -1620,7 +2074,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14264 + 	if (!kgem->has_relaxed_delta && kgem->batch_size > 4*1024)
352.14265 + 		kgem->batch_size = 4*1024;
352.14266 + 
352.14267 +-	if (!kgem_init_pinned_batches(kgem) && gen == 020) {
352.14268 ++	if (!kgem_init_pinned_batches(kgem)) {
352.14269 + 		xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
352.14270 + 			   "Unable to reserve memory for GPU, disabling acceleration.\n");
352.14271 + 		__kgem_set_wedged(kgem);
352.14272 +@@ -1640,35 +2094,24 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14273 + 	     !DBG_NO_CPU && (kgem->has_llc | kgem->has_userptr | kgem->has_caching),
352.14274 + 	     kgem->has_llc, kgem->has_caching, kgem->has_userptr));
352.14275 + 
352.14276 +-	VG_CLEAR(aperture);
352.14277 +-	aperture.aper_size = 0;
352.14278 +-	(void)do_ioctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
352.14279 +-	if (aperture.aper_size == 0)
352.14280 +-		aperture.aper_size = 64*1024*1024;
352.14281 +-
352.14282 +-	DBG(("%s: aperture size %lld, available now %lld\n",
352.14283 +-	     __FUNCTION__,
352.14284 +-	     (long long)aperture.aper_size,
352.14285 +-	     (long long)aperture.aper_available_size));
352.14286 +-
352.14287 +-	kgem->aperture_total = aperture.aper_size;
352.14288 +-	kgem->aperture_high = aperture.aper_size * 3/4;
352.14289 +-	kgem->aperture_low = aperture.aper_size * 1/3;
352.14290 ++	gtt_size = get_gtt_size(fd);
352.14291 ++	kgem->aperture_total = gtt_size;
352.14292 ++	kgem->aperture_high = gtt_size * 3/4;
352.14293 ++	kgem->aperture_low = gtt_size * 1/3;
352.14294 + 	if (gen < 033) {
352.14295 + 		/* Severe alignment penalties */
352.14296 + 		kgem->aperture_high /= 2;
352.14297 + 		kgem->aperture_low /= 2;
352.14298 + 	}
352.14299 +-	DBG(("%s: aperture low=%d [%d], high=%d [%d]\n", __FUNCTION__,
352.14300 ++	DBG(("%s: aperture low=%u [%u], high=%u [%u]\n", __FUNCTION__,
352.14301 + 	     kgem->aperture_low, kgem->aperture_low / (1024*1024),
352.14302 + 	     kgem->aperture_high, kgem->aperture_high / (1024*1024)));
352.14303 + 
352.14304 + 	kgem->aperture_mappable = 256 * 1024 * 1024;
352.14305 + 	if (dev != NULL)
352.14306 + 		kgem->aperture_mappable = agp_aperture_size(dev, gen);
352.14307 +-	if (kgem->aperture_mappable == 0 ||
352.14308 +-	    kgem->aperture_mappable > aperture.aper_size)
352.14309 +-		kgem->aperture_mappable = aperture.aper_size;
352.14310 ++	if (kgem->aperture_mappable == 0 || kgem->aperture_mappable > gtt_size)
352.14311 ++		kgem->aperture_mappable = gtt_size;
352.14312 + 	DBG(("%s: aperture mappable=%d [%d MiB]\n", __FUNCTION__,
352.14313 + 	     kgem->aperture_mappable, kgem->aperture_mappable / (1024*1024)));
352.14314 + 
352.14315 +@@ -1697,7 +2140,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14316 + 		     __FUNCTION__));
352.14317 + 		totalram = kgem->aperture_total;
352.14318 + 	}
352.14319 +-	DBG(("%s: total ram=%ld\n", __FUNCTION__, (long)totalram));
352.14320 ++	DBG(("%s: total ram=%lld\n", __FUNCTION__, (long long)totalram));
352.14321 + 	if (kgem->max_object_size > totalram / 2)
352.14322 + 		kgem->max_object_size = totalram / 2;
352.14323 + 	if (kgem->max_gpu_size > totalram / 4)
352.14324 +@@ -1749,11 +2192,11 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
352.14325 + 	if (DBG_NO_CPU)
352.14326 + 		kgem->max_cpu_size = 0;
352.14327 + 
352.14328 +-	DBG(("%s: maximum object size=%d\n",
352.14329 ++	DBG(("%s: maximum object size=%u\n",
352.14330 + 	     __FUNCTION__, kgem->max_object_size));
352.14331 +-	DBG(("%s: large object thresold=%d\n",
352.14332 ++	DBG(("%s: large object thresold=%u\n",
352.14333 + 	     __FUNCTION__, kgem->large_object_size));
352.14334 +-	DBG(("%s: max object sizes (gpu=%d, cpu=%d, tile upload=%d, copy=%d)\n",
352.14335 ++	DBG(("%s: max object sizes (gpu=%u, cpu=%u, tile upload=%u, copy=%u)\n",
352.14336 + 	     __FUNCTION__,
352.14337 + 	     kgem->max_gpu_size, kgem->max_cpu_size,
352.14338 + 	     kgem->max_upload_tile_size, kgem->max_copy_tile_size));
352.14339 +@@ -2043,8 +2486,34 @@ static void kgem_add_bo(struct kgem *kgem, struct kgem_bo *bo)
352.14340 + 	kgem->flush |= bo->flush;
352.14341 + }
352.14342 + 
352.14343 ++static void kgem_clear_swctrl(struct kgem *kgem)
352.14344 ++{
352.14345 ++	uint32_t *b;
352.14346 ++
352.14347 ++	if (kgem->bcs_state == 0)
352.14348 ++		return;
352.14349 ++
352.14350 ++	DBG(("%s: clearin SWCTRL LRI from %x\n",
352.14351 ++	     __FUNCTION__, kgem->bcs_state));
352.14352 ++
352.14353 ++	b = kgem->batch + kgem->nbatch;
352.14354 ++	kgem->nbatch += 7;
352.14355 ++
352.14356 ++	*b++ = MI_FLUSH_DW;
352.14357 ++	*b++ = 0;
352.14358 ++	*b++ = 0;
352.14359 ++	*b++ = 0;
352.14360 ++
352.14361 ++	*b++ = MI_LOAD_REGISTER_IMM;
352.14362 ++	*b++ = BCS_SWCTRL;
352.14363 ++	*b++ = (BCS_SRC_Y | BCS_DST_Y) << 16;
352.14364 ++
352.14365 ++	kgem->bcs_state = 0;
352.14366 ++}
352.14367 ++
352.14368 + static uint32_t kgem_end_batch(struct kgem *kgem)
352.14369 + {
352.14370 ++	kgem_clear_swctrl(kgem);
352.14371 + 	kgem->batch[kgem->nbatch++] = MI_BATCH_BUFFER_END;
352.14372 + 	if (kgem->nbatch & 1)
352.14373 + 		kgem->batch[kgem->nbatch++] = MI_NOOP;
352.14374 +@@ -2064,17 +2533,6 @@ static void kgem_bo_binding_free(struct kgem *kgem, struct kgem_bo *bo)
352.14375 + 	}
352.14376 + }
352.14377 + 
352.14378 +-static void kgem_bo_rmfb(struct kgem *kgem, struct kgem_bo *bo)
352.14379 +-{
352.14380 +-	if (bo->scanout && bo->delta) {
352.14381 +-		DBG(("%s: releasing fb=%d for handle=%d\n",
352.14382 +-		     __FUNCTION__, bo->delta, bo->handle));
352.14383 +-		/* XXX will leak if we are not DRM_MASTER. *shrug* */
352.14384 +-		do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
352.14385 +-		bo->delta = 0;
352.14386 +-	}
352.14387 +-}
352.14388 +-
352.14389 + static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
352.14390 + {
352.14391 + 	DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
352.14392 +@@ -2150,13 +2608,16 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem,
352.14393 + 	assert(!bo->snoop);
352.14394 + 	assert(!bo->flush);
352.14395 + 	assert(!bo->needs_flush);
352.14396 ++	assert(!bo->delta);
352.14397 + 	assert(list_is_empty(&bo->vma));
352.14398 + 	assert_tiling(kgem, bo);
352.14399 +-	assert_cacheing(kgem, bo);
352.14400 ++	assert_caching(kgem, bo);
352.14401 + 	ASSERT_IDLE(kgem, bo->handle);
352.14402 + 
352.14403 + 	if (bucket(bo) >= NUM_CACHE_BUCKETS) {
352.14404 + 		if (bo->map__gtt) {
352.14405 ++			DBG(("%s: relinquishing large GTT mapping for handle=%d\n",
352.14406 ++			     __FUNCTION__, bo->handle));
352.14407 + 			munmap(bo->map__gtt, bytes(bo));
352.14408 + 			bo->map__gtt = NULL;
352.14409 + 		}
352.14410 +@@ -2167,6 +2628,8 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem,
352.14411 + 		assert(list_is_empty(&bo->vma));
352.14412 + 		list_move(&bo->list, &kgem->inactive[bucket(bo)]);
352.14413 + 		if (bo->map__gtt && !kgem_bo_can_map(kgem, bo)) {
352.14414 ++			DBG(("%s: relinquishing old GTT mapping for handle=%d\n",
352.14415 ++			     __FUNCTION__, bo->handle));
352.14416 + 			munmap(bo->map__gtt, bytes(bo));
352.14417 + 			bo->map__gtt = NULL;
352.14418 + 		}
352.14419 +@@ -2191,6 +2654,10 @@ static struct kgem_bo *kgem_bo_replace_io(struct kgem_bo *bo)
352.14420 + 		return bo;
352.14421 + 
352.14422 + 	assert(!bo->snoop);
352.14423 ++	assert(!bo->purged);
352.14424 ++	assert(!bo->scanout);
352.14425 ++	assert(!bo->delta);
352.14426 ++
352.14427 + 	if (__kgem_freed_bo) {
352.14428 + 		base = __kgem_freed_bo;
352.14429 + 		__kgem_freed_bo = *(struct kgem_bo **)base;
352.14430 +@@ -2221,6 +2688,7 @@ inline static void kgem_bo_remove_from_inactive(struct kgem *kgem,
352.14431 + 	list_del(&bo->list);
352.14432 + 	assert(bo->rq == NULL);
352.14433 + 	assert(bo->exec == NULL);
352.14434 ++	assert(!bo->purged);
352.14435 + 	if (!list_is_empty(&bo->vma)) {
352.14436 + 		assert(bo->map__gtt || bo->map__wc || bo->map__cpu);
352.14437 + 		list_del(&bo->vma);
352.14438 +@@ -2305,7 +2773,6 @@ static void kgem_bo_move_to_scanout(struct kgem *kgem, struct kgem_bo *bo)
352.14439 + 		list_move(&bo->list, &kgem->scanout);
352.14440 + 
352.14441 + 	kgem->need_expire = true;
352.14442 +-
352.14443 + }
352.14444 + 
352.14445 + static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
352.14446 +@@ -2316,6 +2783,8 @@ static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
352.14447 + 	assert(!bo->needs_flush);
352.14448 + 	assert(bo->refcnt == 0);
352.14449 + 	assert(bo->exec == NULL);
352.14450 ++	assert(!bo->purged);
352.14451 ++	assert(!bo->delta);
352.14452 + 
352.14453 + 	if (DBG_NO_SNOOP_CACHE) {
352.14454 + 		kgem_bo_free(kgem, bo);
352.14455 +@@ -2351,8 +2820,7 @@ static bool kgem_bo_move_to_cache(struct kgem *kgem, struct kgem_bo *bo)
352.14456 + 		kgem_bo_move_to_snoop(kgem, bo);
352.14457 + 	} else if (bo->scanout) {
352.14458 + 		kgem_bo_move_to_scanout(kgem, bo);
352.14459 +-	} else if ((bo = kgem_bo_replace_io(bo))->reusable &&
352.14460 +-		   kgem_bo_set_purgeable(kgem, bo)) {
352.14461 ++	} else if ((bo = kgem_bo_replace_io(bo))->reusable) {
352.14462 + 		kgem_bo_move_to_inactive(kgem, bo);
352.14463 + 		retired = true;
352.14464 + 	} else
352.14465 +@@ -2429,7 +2897,7 @@ void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo)
352.14466 + 	DBG(("%s: only handle in batch, discarding last operations for handle=%d\n",
352.14467 + 	     __FUNCTION__, bo->handle));
352.14468 + 
352.14469 +-	assert(bo->exec == &kgem->exec[0]);
352.14470 ++	assert(bo->exec == &_kgem_dummy_exec || bo->exec == &kgem->exec[0]);
352.14471 + 	assert(kgem->exec[0].handle == bo->handle);
352.14472 + 	assert(RQ(bo->rq) == kgem->next_request);
352.14473 + 
352.14474 +@@ -2457,16 +2925,23 @@ void kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b)
352.14475 + 
352.14476 + 	if (a == NULL || b == NULL)
352.14477 + 		return;
352.14478 ++	assert(a != b);
352.14479 + 	if (a->exec == NULL || b->exec == NULL)
352.14480 + 		return;
352.14481 + 
352.14482 +-	DBG(("%s: only handles in batch, discarding last operations for handle=%d and handle=%d\n",
352.14483 +-	     __FUNCTION__, a->handle, b->handle));
352.14484 ++	DBG(("%s: only handles in batch, discarding last operations for handle=%d (index=%d) and handle=%d (index=%d)\n",
352.14485 ++	     __FUNCTION__,
352.14486 ++	     a->handle, a->proxy ? -1 : a->exec - kgem->exec,
352.14487 ++	     b->handle, b->proxy ? -1 : b->exec - kgem->exec));
352.14488 + 
352.14489 +-	assert(a->exec == &kgem->exec[0] || a->exec == &kgem->exec[1]);
352.14490 ++	assert(a->exec == &_kgem_dummy_exec ||
352.14491 ++	       a->exec == &kgem->exec[0] ||
352.14492 ++	       a->exec == &kgem->exec[1]);
352.14493 + 	assert(a->handle == kgem->exec[0].handle || a->handle == kgem->exec[1].handle);
352.14494 + 	assert(RQ(a->rq) == kgem->next_request);
352.14495 +-	assert(b->exec == &kgem->exec[0] || b->exec == &kgem->exec[1]);
352.14496 ++	assert(b->exec == &_kgem_dummy_exec ||
352.14497 ++	       b->exec == &kgem->exec[0] ||
352.14498 ++	       b->exec == &kgem->exec[1]);
352.14499 + 	assert(b->handle == kgem->exec[0].handle || b->handle == kgem->exec[1].handle);
352.14500 + 	assert(RQ(b->rq) == kgem->next_request);
352.14501 + 
352.14502 +@@ -2487,6 +2962,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
352.14503 + 	DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
352.14504 + 
352.14505 + 	assert(list_is_empty(&bo->list));
352.14506 ++	assert(list_is_empty(&bo->vma));
352.14507 + 	assert(bo->refcnt == 0);
352.14508 + 	assert(bo->proxy == NULL);
352.14509 + 	assert(bo->active_scanout == 0);
352.14510 +@@ -2532,7 +3008,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
352.14511 + 	assert(bo->snoop == false);
352.14512 + 	assert(bo->io == false);
352.14513 + 	assert(bo->scanout == false);
352.14514 +-	assert_cacheing(kgem, bo);
352.14515 ++	assert_caching(kgem, bo);
352.14516 + 
352.14517 + 	kgem_bo_undo(kgem, bo);
352.14518 + 	assert(bo->refcnt == 0);
352.14519 +@@ -2556,9 +3032,6 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
352.14520 + 	assert(list_is_empty(&bo->request));
352.14521 + 
352.14522 + 	if (bo->map__cpu == NULL || bucket(bo) >= NUM_CACHE_BUCKETS) {
352.14523 +-		if (!kgem_bo_set_purgeable(kgem, bo))
352.14524 +-			goto destroy;
352.14525 +-
352.14526 + 		if (!kgem->has_llc && bo->domain == DOMAIN_CPU)
352.14527 + 			goto destroy;
352.14528 + 
352.14529 +@@ -2647,7 +3120,7 @@ static bool kgem_retire__flushing(struct kgem *kgem)
352.14530 + 		int count = 0;
352.14531 + 		list_for_each_entry(bo, &kgem->flushing, request)
352.14532 + 			count++;
352.14533 +-		DBG(("%s: %d bo on flushing list\n", __FUNCTION__, count));
352.14534 ++		DBG(("%s: %d bo on flushing list, retired? %d\n", __FUNCTION__, count, retired));
352.14535 + 	}
352.14536 + #endif
352.14537 + 
352.14538 +@@ -2656,6 +3129,34 @@ static bool kgem_retire__flushing(struct kgem *kgem)
352.14539 + 	return retired;
352.14540 + }
352.14541 + 
352.14542 ++static bool __kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
352.14543 ++{
352.14544 ++	struct drm_i915_gem_busy busy;
352.14545 ++
352.14546 ++	if (!bo->needs_flush)
352.14547 ++		return false;
352.14548 ++
352.14549 ++	bo->needs_flush = false;
352.14550 ++
352.14551 ++	VG_CLEAR(busy);
352.14552 ++	busy.handle = bo->handle;
352.14553 ++	busy.busy = !kgem->wedged;
352.14554 ++	(void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
352.14555 ++	DBG(("%s: handle=%d, busy=%d, wedged=%d\n",
352.14556 ++	     __FUNCTION__, bo->handle, busy.busy, kgem->wedged));
352.14557 ++
352.14558 ++	if (busy.busy == 0)
352.14559 ++		return false;
352.14560 ++
352.14561 ++	DBG(("%s: moving %d to flushing\n",
352.14562 ++	     __FUNCTION__, bo->handle));
352.14563 ++	list_add(&bo->request, &kgem->flushing);
352.14564 ++	bo->rq = MAKE_REQUEST(kgem, !!(busy.busy & ~0x1ffff));
352.14565 ++	bo->needs_flush = busy.busy & 0xffff;
352.14566 ++	kgem->need_retire = true;
352.14567 ++	return true;
352.14568 ++}
352.14569 ++
352.14570 + static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
352.14571 + {
352.14572 + 	bool retired = false;
352.14573 +@@ -2663,6 +3164,8 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
352.14574 + 	DBG(("%s: request %d complete\n",
352.14575 + 	     __FUNCTION__, rq->bo->handle));
352.14576 + 	assert(RQ(rq->bo->rq) == rq);
352.14577 ++	assert(rq != (struct kgem_request *)kgem);
352.14578 ++	assert(rq != &kgem->static_request);
352.14579 + 
352.14580 + 	if (rq == kgem->fence[rq->ring])
352.14581 + 		kgem->fence[rq->ring] = NULL;
352.14582 +@@ -2680,19 +3183,14 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
352.14583 + 
352.14584 + 		list_del(&bo->request);
352.14585 + 
352.14586 +-		if (bo->needs_flush)
352.14587 +-			bo->needs_flush = __kgem_busy(kgem, bo->handle);
352.14588 +-		if (bo->needs_flush) {
352.14589 +-			DBG(("%s: moving %d to flushing\n",
352.14590 ++		if (unlikely(__kgem_bo_flush(kgem, bo))) {
352.14591 ++			assert(bo != rq->bo);
352.14592 ++			DBG(("%s: movied %d to flushing\n",
352.14593 + 			     __FUNCTION__, bo->handle));
352.14594 +-			list_add(&bo->request, &kgem->flushing);
352.14595 +-			bo->rq = MAKE_REQUEST(kgem, RQ_RING(bo->rq));
352.14596 +-			kgem->need_retire = true;
352.14597 + 			continue;
352.14598 + 		}
352.14599 + 
352.14600 + 		bo->domain = DOMAIN_NONE;
352.14601 +-		bo->gtt_dirty = false;
352.14602 + 		bo->rq = NULL;
352.14603 + 		if (bo->refcnt)
352.14604 + 			continue;
352.14605 +@@ -2706,14 +3204,8 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
352.14606 + 	assert(rq->bo->refcnt > 0);
352.14607 + 
352.14608 + 	if (--rq->bo->refcnt == 0) {
352.14609 +-		if (kgem_bo_set_purgeable(kgem, rq->bo)) {
352.14610 +-			kgem_bo_move_to_inactive(kgem, rq->bo);
352.14611 +-			retired = true;
352.14612 +-		} else {
352.14613 +-			DBG(("%s: closing %d\n",
352.14614 +-			     __FUNCTION__, rq->bo->handle));
352.14615 +-			kgem_bo_free(kgem, rq->bo);
352.14616 +-		}
352.14617 ++		kgem_bo_move_to_inactive(kgem, rq->bo);
352.14618 ++		retired = true;
352.14619 + 	}
352.14620 + 
352.14621 + 	__kgem_request_free(rq);
352.14622 +@@ -2724,13 +3216,18 @@ static bool kgem_retire__requests_ring(struct kgem *kgem, int ring)
352.14623 + {
352.14624 + 	bool retired = false;
352.14625 + 
352.14626 ++	assert(ring < ARRAY_SIZE(kgem->requests));
352.14627 + 	while (!list_is_empty(&kgem->requests[ring])) {
352.14628 + 		struct kgem_request *rq;
352.14629 + 
352.14630 ++		DBG(("%s: retiring ring %d\n", __FUNCTION__, ring));
352.14631 ++
352.14632 + 		rq = list_first_entry(&kgem->requests[ring],
352.14633 + 				      struct kgem_request,
352.14634 + 				      list);
352.14635 + 		assert(rq->ring == ring);
352.14636 ++		assert(rq->bo);
352.14637 ++		assert(RQ(rq->bo->rq) == rq);
352.14638 + 		if (__kgem_busy(kgem, rq->bo->handle))
352.14639 + 			break;
352.14640 + 
352.14641 +@@ -2751,8 +3248,8 @@ static bool kgem_retire__requests_ring(struct kgem *kgem, int ring)
352.14642 + 					      struct kgem_request,
352.14643 + 					      list)->bo;
352.14644 + 
352.14645 +-		DBG(("%s: ring=%d, %d outstanding requests, oldest=%d\n",
352.14646 +-		     __FUNCTION__, ring, count, bo ? bo->handle : 0));
352.14647 ++		DBG(("%s: ring=%d, %d outstanding requests, oldest=%d, retired? %d\n",
352.14648 ++		     __FUNCTION__, ring, count, bo ? bo->handle : 0, retired));
352.14649 + 	}
352.14650 + #endif
352.14651 + 
352.14652 +@@ -2824,6 +3321,8 @@ bool __kgem_ring_is_idle(struct kgem *kgem, int ring)
352.14653 + 	rq = list_last_entry(&kgem->requests[ring],
352.14654 + 			     struct kgem_request, list);
352.14655 + 	assert(rq->ring == ring);
352.14656 ++	assert(rq->bo);
352.14657 ++	assert(RQ(rq->bo->rq) == rq);
352.14658 + 	if (__kgem_busy(kgem, rq->bo->handle)) {
352.14659 + 		DBG(("%s: last requests handle=%d still busy\n",
352.14660 + 		     __FUNCTION__, rq->bo->handle));
352.14661 +@@ -2845,23 +3344,30 @@ bool __kgem_ring_is_idle(struct kgem *kgem, int ring)
352.14662 + 	return true;
352.14663 + }
352.14664 + 
352.14665 +-void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
352.14666 ++bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
352.14667 + {
352.14668 +-	struct kgem_request *rq = bo->rq, *tmp;
352.14669 +-	struct list *requests = &kgem->requests[RQ_RING(rq) == I915_EXEC_BLT];
352.14670 ++	struct kgem_request * const rq = RQ(bo->rq), *tmp;
352.14671 ++	struct list *requests = &kgem->requests[rq->ring];
352.14672 ++
352.14673 ++	DBG(("%s(handle=%d, ring=%d)\n", __FUNCTION__, bo->handle, rq->ring));
352.14674 + 
352.14675 +-	rq = RQ(rq);
352.14676 + 	assert(rq != &kgem->static_request);
352.14677 + 	if (rq == (struct kgem_request *)kgem) {
352.14678 + 		__kgem_bo_clear_busy(bo);
352.14679 +-		return;
352.14680 ++		return false;
352.14681 + 	}
352.14682 + 
352.14683 ++	assert(rq->ring < ARRAY_SIZE(kgem->requests));
352.14684 + 	do {
352.14685 + 		tmp = list_first_entry(requests, struct kgem_request, list);
352.14686 + 		assert(tmp->ring == rq->ring);
352.14687 + 		__kgem_retire_rq(kgem, tmp);
352.14688 + 	} while (tmp != rq);
352.14689 ++
352.14690 ++	assert(bo->needs_flush || bo->rq == NULL);
352.14691 ++	assert(bo->needs_flush || list_is_empty(&bo->request));
352.14692 ++	assert(bo->needs_flush || bo->domain == DOMAIN_NONE);
352.14693 ++	return bo->rq;
352.14694 + }
352.14695 + 
352.14696 + #if 0
352.14697 +@@ -2932,6 +3438,7 @@ static void kgem_commit(struct kgem *kgem)
352.14698 + 		bo->binding.offset = 0;
352.14699 + 		bo->domain = DOMAIN_GPU;
352.14700 + 		bo->gpu_dirty = false;
352.14701 ++		bo->gtt_dirty = false;
352.14702 + 
352.14703 + 		if (bo->proxy) {
352.14704 + 			/* proxies are not used for domain tracking */
352.14705 +@@ -2955,6 +3462,23 @@ static void kgem_commit(struct kgem *kgem)
352.14706 + 			kgem_throttle(kgem);
352.14707 + 		}
352.14708 + 
352.14709 ++		while (!list_is_empty(&rq->buffers)) {
352.14710 ++			bo = list_first_entry(&rq->buffers,
352.14711 ++					      struct kgem_bo,
352.14712 ++					      request);
352.14713 ++
352.14714 ++			assert(RQ(bo->rq) == rq);
352.14715 ++			assert(bo->exec == NULL);
352.14716 ++			assert(bo->domain == DOMAIN_GPU);
352.14717 ++
352.14718 ++			list_del(&bo->request);
352.14719 ++			bo->domain = DOMAIN_NONE;
352.14720 ++			bo->rq = NULL;
352.14721 ++
352.14722 ++			if (bo->refcnt == 0)
352.14723 ++				_kgem_bo_destroy(kgem, bo);
352.14724 ++		}
352.14725 ++
352.14726 + 		kgem_retire(kgem);
352.14727 + 		assert(list_is_empty(&rq->buffers));
352.14728 + 
352.14729 +@@ -2964,7 +3488,9 @@ static void kgem_commit(struct kgem *kgem)
352.14730 + 		gem_close(kgem->fd, rq->bo->handle);
352.14731 + 		kgem_cleanup_cache(kgem);
352.14732 + 	} else {
352.14733 ++		assert(rq != (struct kgem_request *)kgem);
352.14734 + 		assert(rq->ring < ARRAY_SIZE(kgem->requests));
352.14735 ++		assert(rq->bo);
352.14736 + 		list_add_tail(&rq->list, &kgem->requests[rq->ring]);
352.14737 + 		kgem->need_throttle = kgem->need_retire = 1;
352.14738 + 
352.14739 +@@ -2988,8 +3514,10 @@ static void kgem_close_inactive(struct kgem *kgem)
352.14740 + {
352.14741 + 	unsigned int i;
352.14742 + 
352.14743 +-	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++)
352.14744 ++	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) {
352.14745 + 		kgem_close_list(kgem, &kgem->inactive[i]);
352.14746 ++		assert(list_is_empty(&kgem->inactive[i]));
352.14747 ++	}
352.14748 + }
352.14749 + 
352.14750 + static void kgem_finish_buffers(struct kgem *kgem)
352.14751 +@@ -3079,10 +3607,13 @@ static void kgem_finish_buffers(struct kgem *kgem)
352.14752 + 						kgem->has_handle_lut ? bo->base.target_handle : shrink->handle;
352.14753 + 					for (n = 0; n < kgem->nreloc; n++) {
352.14754 + 						if (kgem->reloc[n].target_handle == bo->base.target_handle) {
352.14755 ++							uint64_t addr = (int)kgem->reloc[n].delta + shrink->presumed_offset;
352.14756 ++							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] = addr;
352.14757 ++							if (kgem->gen >= 0100)
352.14758 ++								kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0]) + 1] = addr >> 32;
352.14759 ++
352.14760 + 							kgem->reloc[n].target_handle = shrink->target_handle;
352.14761 + 							kgem->reloc[n].presumed_offset = shrink->presumed_offset;
352.14762 +-							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] =
352.14763 +-								kgem->reloc[n].delta + shrink->presumed_offset;
352.14764 + 						}
352.14765 + 					}
352.14766 + 
352.14767 +@@ -3124,10 +3655,13 @@ static void kgem_finish_buffers(struct kgem *kgem)
352.14768 + 						kgem->has_handle_lut ? bo->base.target_handle : shrink->handle;
352.14769 + 					for (n = 0; n < kgem->nreloc; n++) {
352.14770 + 						if (kgem->reloc[n].target_handle == bo->base.target_handle) {
352.14771 ++							uint64_t addr = (int)kgem->reloc[n].delta + shrink->presumed_offset;
352.14772 ++							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] = addr;
352.14773 ++							if (kgem->gen >= 0100)
352.14774 ++								kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0]) + 1] = addr >> 32;
352.14775 ++
352.14776 + 							kgem->reloc[n].target_handle = shrink->target_handle;
352.14777 + 							kgem->reloc[n].presumed_offset = shrink->presumed_offset;
352.14778 +-							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] =
352.14779 +-								kgem->reloc[n].delta + shrink->presumed_offset;
352.14780 + 						}
352.14781 + 					}
352.14782 + 
352.14783 +@@ -3195,6 +3729,9 @@ static void kgem_cleanup(struct kgem *kgem)
352.14784 + 					kgem_bo_free(kgem, bo);
352.14785 + 			}
352.14786 + 
352.14787 ++			if (--rq->bo->refcnt == 0)
352.14788 ++				kgem_bo_free(kgem, rq->bo);
352.14789 ++
352.14790 + 			__kgem_request_free(rq);
352.14791 + 		}
352.14792 + 	}
352.14793 +@@ -3210,7 +3747,9 @@ kgem_batch_write(struct kgem *kgem,
352.14794 + 	char *ptr;
352.14795 + 	int ret;
352.14796 + 
352.14797 +-	ASSERT_IDLE(kgem, bo->handle);
352.14798 ++	assert(bo->exec == NULL);
352.14799 ++	assert(bo->rq == NULL);
352.14800 ++	assert(!__kgem_busy(kgem, bo->handle));
352.14801 + 
352.14802 + #if DBG_NO_EXEC
352.14803 + 	{
352.14804 +@@ -3371,55 +3910,54 @@ static int compact_batch_surface(struct kgem *kgem, int *shrink)
352.14805 + 	return size * sizeof(uint32_t);
352.14806 + }
352.14807 + 
352.14808 ++static struct kgem_bo *first_available(struct kgem *kgem, struct list *list)
352.14809 ++{
352.14810 ++	struct kgem_bo *bo;
352.14811 ++
352.14812 ++	list_for_each_entry(bo, list, list) {
352.14813 ++		assert(bo->refcnt > 0);
352.14814 ++
352.14815 ++		if (bo->rq) {
352.14816 ++			assert(RQ(bo->rq)->bo == bo);
352.14817 ++			if (__kgem_busy(kgem, bo->handle))
352.14818 ++				break;
352.14819 ++
352.14820 ++			__kgem_retire_rq(kgem, RQ(bo->rq));
352.14821 ++			assert(bo->rq == NULL);
352.14822 ++		}
352.14823 ++
352.14824 ++		if (bo->refcnt > 1)
352.14825 ++			continue;
352.14826 ++
352.14827 ++		list_move_tail(&bo->list, list);
352.14828 ++		return kgem_bo_reference(bo);
352.14829 ++	}
352.14830 ++
352.14831 ++	return NULL;
352.14832 ++}
352.14833 ++
352.14834 + static struct kgem_bo *
352.14835 + kgem_create_batch(struct kgem *kgem)
352.14836 + {
352.14837 +-#if !DBG_NO_SHRINK_BATCHES
352.14838 +-	struct drm_i915_gem_set_domain set_domain;
352.14839 + 	struct kgem_bo *bo;
352.14840 +-	int shrink = 0;
352.14841 +-	int size;
352.14842 ++	int size, shrink = 0;
352.14843 + 
352.14844 ++#if !DBG_NO_SHRINK_BATCHES
352.14845 + 	if (kgem->surface != kgem->batch_size)
352.14846 + 		size = compact_batch_surface(kgem, &shrink);
352.14847 + 	else
352.14848 + 		size = kgem->nbatch * sizeof(uint32_t);
352.14849 + 
352.14850 + 	if (size <= 4096) {
352.14851 +-		bo = list_first_entry(&kgem->pinned_batches[0],
352.14852 +-				      struct kgem_bo,
352.14853 +-				      list);
352.14854 +-		if (!bo->rq) {
352.14855 +-out_4096:
352.14856 +-			assert(bo->refcnt > 0);
352.14857 +-			list_move_tail(&bo->list, &kgem->pinned_batches[0]);
352.14858 +-			bo = kgem_bo_reference(bo);
352.14859 ++		bo = first_available(kgem, &kgem->pinned_batches[0]);
352.14860 ++		if (bo)
352.14861 + 			goto write;
352.14862 +-		}
352.14863 +-
352.14864 +-		if (!__kgem_busy(kgem, bo->handle)) {
352.14865 +-			assert(RQ(bo->rq)->bo == bo);
352.14866 +-			__kgem_retire_rq(kgem, RQ(bo->rq));
352.14867 +-			goto out_4096;
352.14868 +-		}
352.14869 + 	}
352.14870 + 
352.14871 +-	if (size <= 16384) {
352.14872 +-		bo = list_first_entry(&kgem->pinned_batches[1],
352.14873 +-				      struct kgem_bo,
352.14874 +-				      list);
352.14875 +-		if (!bo->rq) {
352.14876 +-out_16384:
352.14877 +-			assert(bo->refcnt > 0);
352.14878 +-			list_move_tail(&bo->list, &kgem->pinned_batches[1]);
352.14879 +-			bo = kgem_bo_reference(bo);
352.14880 +-			goto write;
352.14881 +-		}
352.14882 +-
352.14883 +-		if (!__kgem_busy(kgem, bo->handle)) {
352.14884 +-			__kgem_retire_rq(kgem, RQ(bo->rq));
352.14885 +-			goto out_16384;
352.14886 +-		}
352.14887 ++	if (size <= 16384) {
352.14888 ++		bo = first_available(kgem, &kgem->pinned_batches[1]);
352.14889 ++		if (bo)
352.14890 ++			goto write;
352.14891 + 	}
352.14892 + 
352.14893 + 	if (kgem->gen == 020) {
352.14894 +@@ -3443,16 +3981,8 @@ out_16384:
352.14895 + 			list_move_tail(&bo->list, &kgem->pinned_batches[size > 4096]);
352.14896 + 
352.14897 + 			DBG(("%s: syncing due to busy batches\n", __FUNCTION__));
352.14898 +-
352.14899 +-			VG_CLEAR(set_domain);
352.14900 +-			set_domain.handle = bo->handle;
352.14901 +-			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.14902 +-			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.14903 +-			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
352.14904 +-				DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
352.14905 +-				kgem_throttle(kgem);
352.14906 ++			if (kgem_bo_wait(kgem, bo))
352.14907 + 				return NULL;
352.14908 +-			}
352.14909 + 
352.14910 + 			kgem_retire(kgem);
352.14911 + 			assert(bo->rq == NULL);
352.14912 +@@ -3460,9 +3990,14 @@ out_16384:
352.14913 + 			goto write;
352.14914 + 		}
352.14915 + 	}
352.14916 ++#else
352.14917 ++	if (kgem->surface != kgem->batch_size)
352.14918 ++		size = kgem->batch_size * sizeof(uint32_t);
352.14919 ++	else
352.14920 ++		size = kgem->nbatch * sizeof(uint32_t);
352.14921 ++#endif
352.14922 + 
352.14923 +-	bo = NULL;
352.14924 +-	if (!kgem->has_llc) {
352.14925 ++	if (!kgem->batch_bo || !kgem->has_llc) {
352.14926 + 		bo = kgem_create_linear(kgem, size, CREATE_NO_THROTTLE);
352.14927 + 		if (bo) {
352.14928 + write:
352.14929 +@@ -3471,14 +4006,11 @@ write:
352.14930 + 				kgem_bo_destroy(kgem, bo);
352.14931 + 				return NULL;
352.14932 + 			}
352.14933 ++			return bo;
352.14934 + 		}
352.14935 + 	}
352.14936 +-	if (bo == NULL)
352.14937 +-		bo = kgem_new_batch(kgem);
352.14938 +-	return bo;
352.14939 +-#else
352.14940 ++
352.14941 + 	return kgem_new_batch(kgem);
352.14942 +-#endif
352.14943 + }
352.14944 + 
352.14945 + #if !NDEBUG
352.14946 +@@ -3530,7 +4062,7 @@ static void dump_fence_regs(struct kgem *kgem)
352.14947 + 
352.14948 + static int do_execbuf(struct kgem *kgem, struct drm_i915_gem_execbuffer2 *execbuf)
352.14949 + {
352.14950 +-	int ret, err;
352.14951 ++	int ret;
352.14952 + 
352.14953 + retry:
352.14954 + 	ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
352.14955 +@@ -3547,26 +4079,25 @@ retry:
352.14956 + 
352.14957 + 	/* last gasp */
352.14958 + 	ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
352.14959 +-	if (ret == 0)
352.14960 +-		return 0;
352.14961 ++	if (ret != -ENOSPC)
352.14962 ++		return ret;
352.14963 ++
352.14964 ++	/* One final trick up our sleeve for when we run out of space.
352.14965 ++	 * We turn everything off to free up our pinned framebuffers,
352.14966 ++	 * sprites and cursors, and try just one more time.
352.14967 ++	 */
352.14968 + 
352.14969 + 	xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
352.14970 + 		   "Failed to submit rendering commands, trying again with outputs disabled.\n");
352.14971 + 
352.14972 +-	/* One last trick up our sleeve for when we run out of space.
352.14973 +-	 * We turn everything off to free up our pinned framebuffers,
352.14974 +-	 * sprites and cursors, and try one last time.
352.14975 +-	 */
352.14976 +-	err = errno;
352.14977 +-	if (sna_mode_disable(container_of(kgem, struct sna, kgem))) {
352.14978 ++	if (sna_mode_disable(__to_sna(kgem))) {
352.14979 + 		kgem_cleanup_cache(kgem);
352.14980 + 		ret = do_ioctl(kgem->fd,
352.14981 + 			       DRM_IOCTL_I915_GEM_EXECBUFFER2,
352.14982 + 			       execbuf);
352.14983 + 		DBG(("%s: last_gasp ret=%d\n", __FUNCTION__, ret));
352.14984 +-		sna_mode_enable(container_of(kgem, struct sna, kgem));
352.14985 ++		sna_mode_enable(__to_sna(kgem));
352.14986 + 	}
352.14987 +-	errno = err;
352.14988 + 
352.14989 + 	return ret;
352.14990 + }
352.14991 +@@ -3575,6 +4106,7 @@ void _kgem_submit(struct kgem *kgem)
352.14992 + {
352.14993 + 	struct kgem_request *rq;
352.14994 + 	uint32_t batch_end;
352.14995 ++	int i, ret;
352.14996 + 
352.14997 + 	assert(!DBG_NO_HW);
352.14998 + 	assert(!kgem->wedged);
352.14999 +@@ -3609,7 +4141,6 @@ void _kgem_submit(struct kgem *kgem)
352.15000 + 	rq->bo = kgem_create_batch(kgem);
352.15001 + 	if (rq->bo) {
352.15002 + 		struct drm_i915_gem_execbuffer2 execbuf;
352.15003 +-		int i, ret;
352.15004 + 
352.15005 + 		assert(!rq->bo->needs_flush);
352.15006 + 
352.15007 +@@ -3619,7 +4150,8 @@ void _kgem_submit(struct kgem *kgem)
352.15008 + 		kgem->exec[i].relocs_ptr = (uintptr_t)kgem->reloc;
352.15009 + 		kgem->exec[i].alignment = 0;
352.15010 + 		kgem->exec[i].offset = rq->bo->presumed_offset;
352.15011 +-		kgem->exec[i].flags = 0;
352.15012 ++		/* Make sure the kernel releases any fence, ignored if gen4+ */
352.15013 ++		kgem->exec[i].flags = EXEC_OBJECT_NEEDS_FENCE;
352.15014 + 		kgem->exec[i].rsvd1 = 0;
352.15015 + 		kgem->exec[i].rsvd2 = 0;
352.15016 + 
352.15017 +@@ -3631,7 +4163,8 @@ void _kgem_submit(struct kgem *kgem)
352.15018 + 		memset(&execbuf, 0, sizeof(execbuf));
352.15019 + 		execbuf.buffers_ptr = (uintptr_t)kgem->exec;
352.15020 + 		execbuf.buffer_count = kgem->nexec;
352.15021 +-		execbuf.batch_len = batch_end*sizeof(uint32_t);
352.15022 ++		if (kgem->gen < 030)
352.15023 ++			execbuf.batch_len = batch_end*sizeof(uint32_t);
352.15024 + 		execbuf.flags = kgem->ring | kgem->batch_flags;
352.15025 + 
352.15026 + 		if (DBG_DUMP) {
352.15027 +@@ -3645,91 +4178,98 @@ void _kgem_submit(struct kgem *kgem)
352.15028 + 		}
352.15029 + 
352.15030 + 		ret = do_execbuf(kgem, &execbuf);
352.15031 +-		if (DEBUG_SYNC && ret == 0) {
352.15032 +-			struct drm_i915_gem_set_domain set_domain;
352.15033 +-
352.15034 +-			VG_CLEAR(set_domain);
352.15035 +-			set_domain.handle = rq->bo->handle;
352.15036 +-			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.15037 +-			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.15038 ++	} else
352.15039 ++		ret = -ENOMEM;
352.15040 + 
352.15041 +-			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
352.15042 ++	if (ret < 0) {
352.15043 ++		kgem_throttle(kgem);
352.15044 ++		if (!kgem->wedged) {
352.15045 ++			xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
352.15046 ++				   "Failed to submit rendering commands (%s), disabling acceleration.\n",
352.15047 ++				   strerror(-ret));
352.15048 ++			__kgem_set_wedged(kgem);
352.15049 + 		}
352.15050 +-		if (ret < 0) {
352.15051 +-			kgem_throttle(kgem);
352.15052 +-			if (!kgem->wedged) {
352.15053 +-				xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
352.15054 +-					   "Failed to submit rendering commands, disabling acceleration.\n");
352.15055 +-				__kgem_set_wedged(kgem);
352.15056 +-			}
352.15057 + 
352.15058 + #if !NDEBUG
352.15059 +-			ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
352.15060 +-			       kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
352.15061 +-			       kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
352.15062 ++		ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
352.15063 ++		       kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
352.15064 ++		       kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
352.15065 + 
352.15066 +-			for (i = 0; i < kgem->nexec; i++) {
352.15067 +-				struct kgem_bo *bo, *found = NULL;
352.15068 ++		for (i = 0; i < kgem->nexec; i++) {
352.15069 ++			struct kgem_bo *bo, *found = NULL;
352.15070 + 
352.15071 +-				list_for_each_entry(bo, &kgem->next_request->buffers, request) {
352.15072 +-					if (bo->handle == kgem->exec[i].handle) {
352.15073 +-						found = bo;
352.15074 +-						break;
352.15075 +-					}
352.15076 ++			list_for_each_entry(bo, &kgem->next_request->buffers, request) {
352.15077 ++				if (bo->handle == kgem->exec[i].handle) {
352.15078 ++					found = bo;
352.15079 ++					break;
352.15080 + 				}
352.15081 +-				ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
352.15082 +-				       i,
352.15083 +-				       kgem->exec[i].handle,
352.15084 +-				       (int)kgem->exec[i].offset,
352.15085 +-				       found ? kgem_bo_size(found) : -1,
352.15086 +-				       found ? found->tiling : -1,
352.15087 +-				       (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
352.15088 +-				       found ? found->snoop : -1,
352.15089 +-				       found ? found->purged : -1);
352.15090 + 			}
352.15091 +-			for (i = 0; i < kgem->nreloc; i++) {
352.15092 +-				ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
352.15093 +-				       i,
352.15094 +-				       (int)kgem->reloc[i].offset,
352.15095 +-				       kgem->reloc[i].target_handle,
352.15096 +-				       kgem->reloc[i].delta,
352.15097 +-				       kgem->reloc[i].read_domains,
352.15098 +-				       kgem->reloc[i].write_domain,
352.15099 +-				       (int)kgem->reloc[i].presumed_offset);
352.15100 ++			ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
352.15101 ++			       i,
352.15102 ++			       kgem->exec[i].handle,
352.15103 ++			       (int)kgem->exec[i].offset,
352.15104 ++			       found ? kgem_bo_size(found) : -1,
352.15105 ++			       found ? found->tiling : -1,
352.15106 ++			       (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
352.15107 ++			       found ? found->snoop : -1,
352.15108 ++			       found ? found->purged : -1);
352.15109 ++		}
352.15110 ++		for (i = 0; i < kgem->nreloc; i++) {
352.15111 ++			ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
352.15112 ++			       i,
352.15113 ++			       (int)kgem->reloc[i].offset,
352.15114 ++			       kgem->reloc[i].target_handle,
352.15115 ++			       kgem->reloc[i].delta,
352.15116 ++			       kgem->reloc[i].read_domains,
352.15117 ++			       kgem->reloc[i].write_domain,
352.15118 ++			       (int)kgem->reloc[i].presumed_offset);
352.15119 ++		}
352.15120 ++
352.15121 ++		{
352.15122 ++			struct drm_i915_gem_get_aperture aperture;
352.15123 ++			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
352.15124 ++				ErrorF("Aperture size %lld, available %lld\n",
352.15125 ++				       (long long)aperture.aper_size,
352.15126 ++				       (long long)aperture.aper_available_size);
352.15127 ++		}
352.15128 ++
352.15129 ++		if (ret == -ENOSPC)
352.15130 ++			dump_gtt_info(kgem);
352.15131 ++		if (ret == -EDEADLK)
352.15132 ++			dump_fence_regs(kgem);
352.15133 ++
352.15134 ++		if (DEBUG_SYNC) {
352.15135 ++			int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
352.15136 ++			if (fd != -1) {
352.15137 ++				int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
352.15138 ++				assert(ignored == batch_end*sizeof(uint32_t));
352.15139 ++				close(fd);
352.15140 + 			}
352.15141 + 
352.15142 +-			{
352.15143 +-				struct drm_i915_gem_get_aperture aperture;
352.15144 +-				if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
352.15145 +-					ErrorF("Aperture size %lld, available %lld\n",
352.15146 +-					       (long long)aperture.aper_size,
352.15147 +-					       (long long)aperture.aper_available_size);
352.15148 +-			}
352.15149 ++			FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
352.15150 ++		}
352.15151 ++#endif
352.15152 ++	} else {
352.15153 ++		if (DEBUG_SYNC) {
352.15154 ++			struct drm_i915_gem_set_domain set_domain;
352.15155 + 
352.15156 +-			if (ret == -ENOSPC)
352.15157 +-				dump_gtt_info(kgem);
352.15158 +-			if (ret == -EDEADLK)
352.15159 +-				dump_fence_regs(kgem);
352.15160 +-
352.15161 +-			if (DEBUG_SYNC) {
352.15162 +-				int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
352.15163 +-				if (fd != -1) {
352.15164 +-					int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
352.15165 +-					assert(ignored == batch_end*sizeof(uint32_t));
352.15166 +-					close(fd);
352.15167 +-				}
352.15168 ++			VG_CLEAR(set_domain);
352.15169 ++			set_domain.handle = rq->bo->handle;
352.15170 ++			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.15171 ++			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.15172 + 
352.15173 +-				FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
352.15174 +-			}
352.15175 +-#endif
352.15176 ++			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
352.15177 + 		}
352.15178 +-	}
352.15179 ++
352.15180 + #if SHOW_BATCH_AFTER
352.15181 +-	if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t)) == 0)
352.15182 +-		__kgem_batch_debug(kgem, batch_end);
352.15183 ++		if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t)) == 0)
352.15184 ++			__kgem_batch_debug(kgem, batch_end);
352.15185 + #endif
352.15186 +-	kgem_commit(kgem);
352.15187 +-	if (kgem->wedged)
352.15188 ++
352.15189 ++		kgem_commit(kgem);
352.15190 ++	}
352.15191 ++
352.15192 ++	if (unlikely(kgem->wedged))
352.15193 + 		kgem_cleanup(kgem);
352.15194 + 
352.15195 + 	kgem_reset(kgem);
352.15196 +@@ -3737,49 +4277,14 @@ void _kgem_submit(struct kgem *kgem)
352.15197 + 	assert(kgem->next_request != NULL);
352.15198 + }
352.15199 + 
352.15200 +-static bool find_hang_state(struct kgem *kgem, char *path, int maxlen)
352.15201 +-{
352.15202 +-	int minor = kgem_get_minor(kgem);
352.15203 +-
352.15204 +-	/* Search for our hang state in a few canonical locations.
352.15205 +-	 * In the unlikely event of having multiple devices, we
352.15206 +-	 * will need to check which minor actually corresponds to ours.
352.15207 +-	 */
352.15208 +-
352.15209 +-	snprintf(path, maxlen, "/sys/class/drm/card%d/error", minor);
352.15210 +-	if (access(path, R_OK) == 0)
352.15211 +-		return true;
352.15212 +-
352.15213 +-	snprintf(path, maxlen, "/sys/kernel/debug/dri/%d/i915_error_state", minor);
352.15214 +-	if (access(path, R_OK) == 0)
352.15215 +-		return true;
352.15216 +-
352.15217 +-	snprintf(path, maxlen, "/debug/dri/%d/i915_error_state", minor);
352.15218 +-	if (access(path, R_OK) == 0)
352.15219 +-		return true;
352.15220 +-
352.15221 +-	path[0] = '\0';
352.15222 +-	return false;
352.15223 +-}
352.15224 +-
352.15225 + void kgem_throttle(struct kgem *kgem)
352.15226 + {
352.15227 +-	if (kgem->wedged)
352.15228 ++	if (unlikely(kgem->wedged))
352.15229 + 		return;
352.15230 + 
352.15231 + 	if (__kgem_throttle(kgem, true)) {
352.15232 +-		static int once;
352.15233 +-		char path[128];
352.15234 +-
352.15235 + 		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
352.15236 + 			   "Detected a hung GPU, disabling acceleration.\n");
352.15237 +-		if (!once && find_hang_state(kgem, path, sizeof(path))) {
352.15238 +-			xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
352.15239 +-				   "When reporting this, please include %s and the full dmesg.\n",
352.15240 +-				   path);
352.15241 +-			once = 1;
352.15242 +-		}
352.15243 +-
352.15244 + 		__kgem_set_wedged(kgem);
352.15245 + 		kgem->need_throttle = false;
352.15246 + 	}
352.15247 +@@ -3860,7 +4365,8 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15248 + 	bool idle;
352.15249 + 	unsigned int i;
352.15250 + 
352.15251 +-	time(&now);
352.15252 ++	if (!time(&now))
352.15253 ++		return false;
352.15254 + 
352.15255 + 	while (__kgem_freed_bo) {
352.15256 + 		bo = __kgem_freed_bo;
352.15257 +@@ -3875,7 +4381,7 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15258 + 	}
352.15259 + 
352.15260 + 	kgem_clean_large_cache(kgem);
352.15261 +-	if (container_of(kgem, struct sna, kgem)->scrn->vtSema)
352.15262 ++	if (__to_sna(kgem)->scrn->vtSema)
352.15263 + 		kgem_clean_scanout_cache(kgem);
352.15264 + 
352.15265 + 	expire = 0;
352.15266 +@@ -3885,6 +4391,7 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15267 + 			break;
352.15268 + 		}
352.15269 + 
352.15270 ++		assert(now);
352.15271 + 		bo->delta = now;
352.15272 + 	}
352.15273 + 	if (expire) {
352.15274 +@@ -3909,7 +4416,7 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15275 + #endif
352.15276 + 
352.15277 + 	kgem_retire(kgem);
352.15278 +-	if (kgem->wedged)
352.15279 ++	if (unlikely(kgem->wedged))
352.15280 + 		kgem_cleanup(kgem);
352.15281 + 
352.15282 + 	kgem->expire(kgem);
352.15283 +@@ -3930,6 +4437,8 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15284 + 				break;
352.15285 + 			}
352.15286 + 
352.15287 ++			assert(now);
352.15288 ++			kgem_bo_set_purgeable(kgem, bo);
352.15289 + 			bo->delta = now;
352.15290 + 		}
352.15291 + 	}
352.15292 +@@ -3960,16 +4469,11 @@ bool kgem_expire_cache(struct kgem *kgem)
352.15293 + 				count++;
352.15294 + 				size += bytes(bo);
352.15295 + 				kgem_bo_free(kgem, bo);
352.15296 +-				DBG(("%s: expiring %d\n",
352.15297 ++				DBG(("%s: expiring handle=%d\n",
352.15298 + 				     __FUNCTION__, bo->handle));
352.15299 + 			}
352.15300 + 		}
352.15301 +-		if (!list_is_empty(&preserve)) {
352.15302 +-			preserve.prev->next = kgem->inactive[i].next;
352.15303 +-			kgem->inactive[i].next->prev = preserve.prev;
352.15304 +-			kgem->inactive[i].next = preserve.next;
352.15305 +-			preserve.next->prev = &kgem->inactive[i];
352.15306 +-		}
352.15307 ++		list_splice_tail(&preserve, &kgem->inactive[i]);
352.15308 + 	}
352.15309 + 
352.15310 + #ifdef DEBUG_MEMORY
352.15311 +@@ -3998,31 +4502,30 @@ bool kgem_cleanup_cache(struct kgem *kgem)
352.15312 + 	unsigned int i;
352.15313 + 	int n;
352.15314 + 
352.15315 ++	DBG(("%s\n", __FUNCTION__));
352.15316 ++
352.15317 + 	/* sync to the most recent request */
352.15318 + 	for (n = 0; n < ARRAY_SIZE(kgem->requests); n++) {
352.15319 + 		if (!list_is_empty(&kgem->requests[n])) {
352.15320 + 			struct kgem_request *rq;
352.15321 +-			struct drm_i915_gem_set_domain set_domain;
352.15322 + 
352.15323 +-			rq = list_first_entry(&kgem->requests[n],
352.15324 +-					      struct kgem_request,
352.15325 +-					      list);
352.15326 ++			rq = list_last_entry(&kgem->requests[n],
352.15327 ++					     struct kgem_request,
352.15328 ++					     list);
352.15329 + 
352.15330 + 			DBG(("%s: sync on cleanup\n", __FUNCTION__));
352.15331 +-
352.15332 +-			VG_CLEAR(set_domain);
352.15333 +-			set_domain.handle = rq->bo->handle;
352.15334 +-			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.15335 +-			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.15336 +-			(void)do_ioctl(kgem->fd,
352.15337 +-				       DRM_IOCTL_I915_GEM_SET_DOMAIN,
352.15338 +-				       &set_domain);
352.15339 ++			assert(rq->ring == n);
352.15340 ++			assert(rq->bo);
352.15341 ++			assert(RQ(rq->bo->rq) == rq);
352.15342 ++			kgem_bo_wait(kgem, rq->bo);
352.15343 + 		}
352.15344 ++		assert(list_is_empty(&kgem->requests[n]));
352.15345 + 	}
352.15346 + 
352.15347 + 	kgem_retire(kgem);
352.15348 + 	kgem_cleanup(kgem);
352.15349 + 
352.15350 ++	DBG(("%s: need_expire?=%d\n", __FUNCTION__, kgem->need_expire));
352.15351 + 	if (!kgem->need_expire)
352.15352 + 		return false;
352.15353 + 
352.15354 +@@ -4049,6 +4552,8 @@ bool kgem_cleanup_cache(struct kgem *kgem)
352.15355 + 
352.15356 + 	kgem->need_purge = false;
352.15357 + 	kgem->need_expire = false;
352.15358 ++
352.15359 ++	DBG(("%s: complete\n", __FUNCTION__));
352.15360 + 	return true;
352.15361 + }
352.15362 + 
352.15363 +@@ -4079,16 +4584,15 @@ retry_large:
352.15364 + 				goto discard;
352.15365 + 
352.15366 + 			if (bo->tiling != I915_TILING_NONE) {
352.15367 +-				if (use_active)
352.15368 ++				if (use_active && kgem->gen < 040)
352.15369 + 					goto discard;
352.15370 + 
352.15371 +-				if (!gem_set_tiling(kgem->fd, bo->handle,
352.15372 ++				if (!kgem_set_tiling(kgem, bo,
352.15373 + 						    I915_TILING_NONE, 0))
352.15374 + 					goto discard;
352.15375 +-
352.15376 +-				bo->tiling = I915_TILING_NONE;
352.15377 +-				bo->pitch = 0;
352.15378 + 			}
352.15379 ++			assert(bo->tiling == I915_TILING_NONE);
352.15380 ++			bo->pitch = 0;
352.15381 + 
352.15382 + 			if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo))
352.15383 + 				goto discard;
352.15384 +@@ -4169,17 +4673,17 @@ discard:
352.15385 + 				break;
352.15386 + 			}
352.15387 + 
352.15388 +-			if (I915_TILING_NONE != bo->tiling &&
352.15389 +-			    !gem_set_tiling(kgem->fd, bo->handle,
352.15390 +-					    I915_TILING_NONE, 0))
352.15391 +-				continue;
352.15392 ++			if (!kgem_set_tiling(kgem, bo, I915_TILING_NONE, 0)) {
352.15393 ++				kgem_bo_free(kgem, bo);
352.15394 ++				break;
352.15395 ++			}
352.15396 + 
352.15397 + 			kgem_bo_remove_from_inactive(kgem, bo);
352.15398 + 			assert(list_is_empty(&bo->vma));
352.15399 + 			assert(list_is_empty(&bo->list));
352.15400 + 
352.15401 +-			bo->tiling = I915_TILING_NONE;
352.15402 +-			bo->pitch = 0;
352.15403 ++			assert(bo->tiling == I915_TILING_NONE);
352.15404 ++			assert(bo->pitch == 0);
352.15405 + 			bo->delta = 0;
352.15406 + 			DBG(("  %s: found handle=%d (num_pages=%d) in linear vma cache\n",
352.15407 + 			     __FUNCTION__, bo->handle, num_pages(bo)));
352.15408 +@@ -4225,13 +4729,13 @@ discard:
352.15409 + 			if (first)
352.15410 + 				continue;
352.15411 + 
352.15412 +-			if (!gem_set_tiling(kgem->fd, bo->handle,
352.15413 +-					    I915_TILING_NONE, 0))
352.15414 +-				continue;
352.15415 +-
352.15416 +-			bo->tiling = I915_TILING_NONE;
352.15417 +-			bo->pitch = 0;
352.15418 ++			if (!kgem_set_tiling(kgem, bo, I915_TILING_NONE, 0)) {
352.15419 ++				kgem_bo_free(kgem, bo);
352.15420 ++				break;
352.15421 ++			}
352.15422 + 		}
352.15423 ++		assert(bo->tiling == I915_TILING_NONE);
352.15424 ++		bo->pitch = 0;
352.15425 + 
352.15426 + 		if (bo->map__gtt || bo->map__wc || bo->map__cpu) {
352.15427 + 			if (flags & (CREATE_CPU_MAP | CREATE_GTT_MAP)) {
352.15428 +@@ -4269,7 +4773,7 @@ discard:
352.15429 + 			kgem_bo_remove_from_inactive(kgem, bo);
352.15430 + 
352.15431 + 		assert(bo->tiling == I915_TILING_NONE);
352.15432 +-		bo->pitch = 0;
352.15433 ++		assert(bo->pitch == 0);
352.15434 + 		bo->delta = 0;
352.15435 + 		DBG(("  %s: found handle=%d (num_pages=%d) in linear %s cache\n",
352.15436 + 		     __FUNCTION__, bo->handle, num_pages(bo),
352.15437 +@@ -4340,9 +4844,9 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
352.15438 + 
352.15439 + 	bo->unique_id = kgem_get_unique_id(kgem);
352.15440 + 	bo->tiling = tiling.tiling_mode;
352.15441 +-	bo->reusable = false;
352.15442 + 	bo->prime = true;
352.15443 +-	bo->purged = true; /* no coherency guarantees */
352.15444 ++	bo->reusable = false;
352.15445 ++	kgem_bo_unclean(kgem, bo);
352.15446 + 
352.15447 + 	debug_alloc__bo(kgem, bo);
352.15448 + 	return bo;
352.15449 +@@ -4448,6 +4952,8 @@ int kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo)
352.15450 + #if defined(DRM_IOCTL_PRIME_HANDLE_TO_FD) && defined(O_CLOEXEC)
352.15451 + 	struct drm_prime_handle args;
352.15452 + 
352.15453 ++	assert(kgem_bo_is_fenced(kgem, bo));
352.15454 ++
352.15455 + 	VG_CLEAR(args);
352.15456 + 	args.handle = bo->handle;
352.15457 + 	args.flags = O_CLOEXEC;
352.15458 +@@ -4479,6 +4985,8 @@ struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags)
352.15459 + 	if ((flags & CREATE_UNCACHED) == 0) {
352.15460 + 		bo = search_linear_cache(kgem, size, CREATE_INACTIVE | flags);
352.15461 + 		if (bo) {
352.15462 ++			assert(!bo->purged);
352.15463 ++			assert(!bo->delta);
352.15464 + 			assert(bo->domain != DOMAIN_GPU);
352.15465 + 			ASSERT_IDLE(kgem, bo->handle);
352.15466 + 			bo->refcnt = 1;
352.15467 +@@ -4760,8 +5268,7 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
352.15468 + 				   struct kgem_bo *bo,
352.15469 + 				   int width, int height)
352.15470 + {
352.15471 +-	ScrnInfoPtr scrn =
352.15472 +-		container_of(kgem, struct sna, kgem)->scrn;
352.15473 ++	ScrnInfoPtr scrn = __to_sna(kgem)->scrn;
352.15474 + 	struct drm_mode_fb_cmd arg;
352.15475 + 
352.15476 + 	assert(bo->proxy == NULL);
352.15477 +@@ -4809,6 +5316,48 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
352.15478 + 	}
352.15479 + }
352.15480 + 
352.15481 ++static bool tiling_changed(struct kgem_bo *bo, int tiling, int pitch)
352.15482 ++{
352.15483 ++	if (tiling != bo->tiling)
352.15484 ++		return true;
352.15485 ++
352.15486 ++	return tiling != I915_TILING_NONE && pitch != bo->pitch;
352.15487 ++}
352.15488 ++
352.15489 ++static void set_gpu_tiling(struct kgem *kgem,
352.15490 ++			   struct kgem_bo *bo,
352.15491 ++			   int tiling, int pitch)
352.15492 ++{
352.15493 ++	DBG(("%s: handle=%d, tiling=%d, pitch=%d\n",
352.15494 ++	     __FUNCTION__, bo->handle, tiling, pitch));
352.15495 ++
352.15496 ++	if (tiling_changed(bo, tiling, pitch) && bo->map__gtt) {
352.15497 ++		if (!list_is_empty(&bo->vma)) {
352.15498 ++			list_del(&bo->vma);
352.15499 ++			kgem->vma[0].count--;
352.15500 ++		}
352.15501 ++		munmap(bo->map__gtt, bytes(bo));
352.15502 ++		bo->map__gtt = NULL;
352.15503 ++	}
352.15504 ++
352.15505 ++	bo->tiling = tiling;
352.15506 ++	bo->pitch = pitch;
352.15507 ++}
352.15508 ++
352.15509 ++bool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo)
352.15510 ++{
352.15511 ++	struct drm_i915_gem_get_tiling tiling;
352.15512 ++
352.15513 ++	assert(kgem);
352.15514 ++	assert(bo);
352.15515 ++
352.15516 ++	VG_CLEAR(tiling);
352.15517 ++	tiling.handle = bo->handle;
352.15518 ++	tiling.tiling_mode = bo->tiling;
352.15519 ++	(void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling);
352.15520 ++	return tiling.tiling_mode == bo->tiling; /* assume pitch is fine! */
352.15521 ++}
352.15522 ++
352.15523 + struct kgem_bo *kgem_create_2d(struct kgem *kgem,
352.15524 + 			       int width,
352.15525 + 			       int height,
352.15526 +@@ -4892,8 +5441,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
352.15527 + 			return last;
352.15528 + 		}
352.15529 + 
352.15530 +-		if (container_of(kgem, struct sna, kgem)->scrn->vtSema) {
352.15531 +-			ScrnInfoPtr scrn = container_of(kgem, struct sna, kgem)->scrn;
352.15532 ++		if (__to_sna(kgem)->scrn->vtSema) {
352.15533 ++			ScrnInfoPtr scrn = __to_sna(kgem)->scrn;
352.15534 + 
352.15535 + 			list_for_each_entry_reverse(bo, &kgem->scanout, list) {
352.15536 + 				struct drm_mode_fb_cmd arg;
352.15537 +@@ -4915,11 +5464,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
352.15538 + 						bo->delta = 0;
352.15539 + 					}
352.15540 + 
352.15541 +-					if (gem_set_tiling(kgem->fd, bo->handle,
352.15542 +-							   tiling, pitch)) {
352.15543 +-						bo->tiling = tiling;
352.15544 +-						bo->pitch = pitch;
352.15545 +-					} else {
352.15546 ++					if (!kgem_set_tiling(kgem, bo,
352.15547 ++							     tiling, pitch)) {
352.15548 + 						kgem_bo_free(kgem, bo);
352.15549 + 						break;
352.15550 + 					}
352.15551 +@@ -4950,6 +5496,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
352.15552 + 			}
352.15553 + 		}
352.15554 + 
352.15555 ++		if (flags & CREATE_CACHED)
352.15556 ++			return NULL;
352.15557 ++
352.15558 + 		bo = __kgem_bo_create_as_display(kgem, size, tiling, pitch);
352.15559 + 		if (bo)
352.15560 + 			return bo;
352.15561 +@@ -4987,14 +5536,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
352.15562 + 				if (num_pages(bo) < size)
352.15563 + 					continue;
352.15564 + 
352.15565 +-				if (bo->pitch != pitch || bo->tiling != tiling) {
352.15566 +-					if (!gem_set_tiling(kgem->fd, bo->handle,
352.15567 +-							    tiling, pitch))
352.15568 +-						continue;
352.15569 +-
352.15570 +-					bo->pitch = pitch;
352.15571 +-					bo->tiling = tiling;
352.15572 +-				}
352.15573 ++				if (!kgem_set_tiling(kgem, bo, tiling, pitch) &&
352.15574 ++				    !exact)
352.15575 ++					set_gpu_tiling(kgem, bo, tiling, pitch);
352.15576 + 			}
352.15577 + 
352.15578 + 			kgem_bo_remove_from_active(kgem, bo);
352.15579 +@@ -5020,14 +5564,11 @@ large_inactive:
352.15580 + 			if (size > num_pages(bo))
352.15581 + 				continue;
352.15582 + 
352.15583 +-			if (bo->tiling != tiling ||
352.15584 +-			    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
352.15585 +-				if (!gem_set_tiling(kgem->fd, bo->handle,
352.15586 +-						    tiling, pitch))
352.15587 ++			if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
352.15588 ++				if (kgem->gen >= 040 && !exact)
352.15589 ++					set_gpu_tiling(kgem, bo, tiling, pitch);
352.15590 ++				else
352.15591 + 					continue;
352.15592 +-
352.15593 +-				bo->tiling = tiling;
352.15594 +-				bo->pitch = pitch;
352.15595 + 			}
352.15596 + 
352.15597 + 			if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
352.15598 +@@ -5039,7 +5580,6 @@ large_inactive:
352.15599 + 
352.15600 + 			assert(bo->domain != DOMAIN_GPU);
352.15601 + 			bo->unique_id = kgem_get_unique_id(kgem);
352.15602 +-			bo->pitch = pitch;
352.15603 + 			bo->delta = 0;
352.15604 + 			DBG(("  1:from large inactive: pitch=%d, tiling=%d, handle=%d, id=%d\n",
352.15605 + 			     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
352.15606 +@@ -5088,14 +5628,13 @@ large_inactive:
352.15607 + 				if (bo->tiling != tiling ||
352.15608 + 				    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
352.15609 + 					if (bo->map__gtt ||
352.15610 +-					    !gem_set_tiling(kgem->fd, bo->handle,
352.15611 +-							    tiling, pitch)) {
352.15612 ++					    !kgem_set_tiling(kgem, bo,
352.15613 ++							     tiling, pitch)) {
352.15614 + 						DBG(("inactive GTT vma with wrong tiling: %d < %d\n",
352.15615 + 						     bo->tiling, tiling));
352.15616 +-						continue;
352.15617 ++						kgem_bo_free(kgem, bo);
352.15618 ++						break;
352.15619 + 					}
352.15620 +-					bo->tiling = tiling;
352.15621 +-					bo->pitch = pitch;
352.15622 + 				}
352.15623 + 
352.15624 + 				if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
352.15625 +@@ -5103,8 +5642,11 @@ large_inactive:
352.15626 + 					break;
352.15627 + 				}
352.15628 + 
352.15629 ++				if (tiling == I915_TILING_NONE)
352.15630 ++					bo->pitch = pitch;
352.15631 ++
352.15632 + 				assert(bo->tiling == tiling);
352.15633 +-				bo->pitch = pitch;
352.15634 ++				assert(bo->pitch >= pitch);
352.15635 + 				bo->delta = 0;
352.15636 + 				bo->unique_id = kgem_get_unique_id(kgem);
352.15637 + 
352.15638 +@@ -5170,15 +5712,12 @@ search_active:
352.15639 + 				if (num_pages(bo) < size)
352.15640 + 					continue;
352.15641 + 
352.15642 +-				if (bo->pitch != pitch) {
352.15643 +-					if (!gem_set_tiling(kgem->fd,
352.15644 +-							    bo->handle,
352.15645 +-							    tiling, pitch))
352.15646 +-						continue;
352.15647 +-
352.15648 +-					bo->pitch = pitch;
352.15649 +-				}
352.15650 ++				if (!kgem_set_tiling(kgem, bo, tiling, pitch) &&
352.15651 ++				    !exact)
352.15652 ++					set_gpu_tiling(kgem, bo, tiling, pitch);
352.15653 + 			}
352.15654 ++			assert(bo->tiling == tiling);
352.15655 ++			assert(bo->pitch >= pitch);
352.15656 + 
352.15657 + 			kgem_bo_remove_from_active(kgem, bo);
352.15658 + 
352.15659 +@@ -5233,19 +5772,21 @@ search_active:
352.15660 + 				if (num_pages(bo) < size)
352.15661 + 					continue;
352.15662 + 
352.15663 +-				if (bo->tiling != tiling ||
352.15664 +-				    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
352.15665 +-					if (!gem_set_tiling(kgem->fd,
352.15666 +-							    bo->handle,
352.15667 +-							    tiling, pitch))
352.15668 +-						continue;
352.15669 ++				if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
352.15670 ++					if (kgem->gen >= 040 && !exact) {
352.15671 ++						set_gpu_tiling(kgem, bo,
352.15672 ++							       tiling, pitch);
352.15673 ++					} else {
352.15674 ++						kgem_bo_free(kgem, bo);
352.15675 ++						break;
352.15676 ++					}
352.15677 + 				}
352.15678 ++				assert(bo->tiling == tiling);
352.15679 ++				assert(bo->pitch >= pitch);
352.15680 + 
352.15681 + 				kgem_bo_remove_from_active(kgem, bo);
352.15682 + 
352.15683 + 				bo->unique_id = kgem_get_unique_id(kgem);
352.15684 +-				bo->pitch = pitch;
352.15685 +-				bo->tiling = tiling;
352.15686 + 				bo->delta = 0;
352.15687 + 				DBG(("  1:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
352.15688 + 				     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
352.15689 +@@ -5323,11 +5864,13 @@ search_inactive:
352.15690 + 			continue;
352.15691 + 		}
352.15692 + 
352.15693 +-		if (bo->tiling != tiling ||
352.15694 +-		    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
352.15695 +-			if (!gem_set_tiling(kgem->fd, bo->handle,
352.15696 +-					    tiling, pitch))
352.15697 +-				continue;
352.15698 ++		if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
352.15699 ++			if (kgem->gen >= 040 && !exact) {
352.15700 ++				set_gpu_tiling(kgem, bo, tiling, pitch);
352.15701 ++			} else {
352.15702 ++				kgem_bo_free(kgem, bo);
352.15703 ++				break;
352.15704 ++			}
352.15705 + 		}
352.15706 + 
352.15707 + 		if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
352.15708 +@@ -5338,9 +5881,8 @@ search_inactive:
352.15709 + 		kgem_bo_remove_from_inactive(kgem, bo);
352.15710 + 		assert(list_is_empty(&bo->list));
352.15711 + 		assert(list_is_empty(&bo->vma));
352.15712 +-
352.15713 +-		bo->pitch = pitch;
352.15714 +-		bo->tiling = tiling;
352.15715 ++		assert(bo->tiling == tiling);
352.15716 ++		assert(bo->pitch >= pitch);
352.15717 + 
352.15718 + 		bo->delta = 0;
352.15719 + 		bo->unique_id = kgem_get_unique_id(kgem);
352.15720 +@@ -5388,14 +5930,17 @@ search_inactive:
352.15721 + 			kgem_bo_remove_from_active(kgem, bo);
352.15722 + 			__kgem_bo_clear_busy(bo);
352.15723 + 
352.15724 +-			if (tiling != I915_TILING_NONE && bo->pitch != pitch) {
352.15725 +-				if (!gem_set_tiling(kgem->fd, bo->handle, tiling, pitch)) {
352.15726 ++			if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
352.15727 ++				if (kgem->gen >= 040 && !exact) {
352.15728 ++					set_gpu_tiling(kgem, bo, tiling, pitch);
352.15729 ++				} else {
352.15730 + 					kgem_bo_free(kgem, bo);
352.15731 + 					goto no_retire;
352.15732 + 				}
352.15733 + 			}
352.15734 ++			assert(bo->tiling == tiling);
352.15735 ++			assert(bo->pitch >= pitch);
352.15736 + 
352.15737 +-			bo->pitch = pitch;
352.15738 + 			bo->unique_id = kgem_get_unique_id(kgem);
352.15739 + 			bo->delta = 0;
352.15740 + 			DBG(("  2:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
352.15741 +@@ -5440,18 +5985,21 @@ create:
352.15742 + 	}
352.15743 + 
352.15744 + 	bo->unique_id = kgem_get_unique_id(kgem);
352.15745 +-	if (tiling == I915_TILING_NONE ||
352.15746 +-	    gem_set_tiling(kgem->fd, handle, tiling, pitch)) {
352.15747 +-		bo->tiling = tiling;
352.15748 +-		bo->pitch = pitch;
352.15749 ++	if (kgem_set_tiling(kgem, bo, tiling, pitch)) {
352.15750 + 		if (flags & CREATE_SCANOUT)
352.15751 + 			__kgem_bo_make_scanout(kgem, bo, width, height);
352.15752 + 	} else {
352.15753 +-		if (flags & CREATE_EXACT) {
352.15754 +-			DBG(("%s: failed to set exact tiling (gem_set_tiling)\n", __FUNCTION__));
352.15755 +-			gem_close(kgem->fd, handle);
352.15756 +-			free(bo);
352.15757 +-			return NULL;
352.15758 ++		if (kgem->gen >= 040) {
352.15759 ++			assert(!kgem->can_fence);
352.15760 ++			bo->tiling = tiling;
352.15761 ++			bo->pitch = pitch;
352.15762 ++		} else {
352.15763 ++			if (flags & CREATE_EXACT) {
352.15764 ++				DBG(("%s: failed to set exact tiling (gem_set_tiling)\n", __FUNCTION__));
352.15765 ++				gem_close(kgem->fd, handle);
352.15766 ++				free(bo);
352.15767 ++				return NULL;
352.15768 ++			}
352.15769 + 		}
352.15770 + 	}
352.15771 + 
352.15772 +@@ -5608,7 +6156,7 @@ static void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo)
352.15773 + 
352.15774 + void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
352.15775 + {
352.15776 +-	if (!bo->needs_flush)
352.15777 ++	if (!bo->needs_flush && !bo->gtt_dirty)
352.15778 + 		return;
352.15779 + 
352.15780 + 	kgem_bo_submit(kgem, bo);
352.15781 +@@ -5621,18 +6169,24 @@ void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
352.15782 + 	if (bo->rq)
352.15783 + 		__kgem_flush(kgem, bo);
352.15784 + 
352.15785 ++	if (bo->scanout && kgem->needs_dirtyfb) {
352.15786 ++		struct drm_mode_fb_dirty_cmd cmd;
352.15787 ++		memset(&cmd, 0, sizeof(cmd));
352.15788 ++		cmd.fb_id = bo->delta;
352.15789 ++		(void)drmIoctl(kgem->fd, DRM_IOCTL_MODE_DIRTYFB, &cmd);
352.15790 ++	}
352.15791 ++
352.15792 + 	/* Whatever actually happens, we can regard the GTT write domain
352.15793 + 	 * as being flushed.
352.15794 + 	 */
352.15795 +-	bo->gtt_dirty = false;
352.15796 +-	bo->needs_flush = false;
352.15797 +-	bo->domain = DOMAIN_NONE;
352.15798 ++	__kgem_bo_clear_dirty(bo);
352.15799 + }
352.15800 + 
352.15801 + inline static bool nearly_idle(struct kgem *kgem)
352.15802 + {
352.15803 + 	int ring = kgem->ring == KGEM_BLT;
352.15804 + 
352.15805 ++	assert(ring < ARRAY_SIZE(kgem->requests));
352.15806 + 	if (list_is_singular(&kgem->requests[ring]))
352.15807 + 		return true;
352.15808 + 
352.15809 +@@ -5720,7 +6274,7 @@ static inline bool kgem_flush(struct kgem *kgem, bool flush)
352.15810 + 	if (kgem->nreloc == 0)
352.15811 + 		return true;
352.15812 + 
352.15813 +-	if (container_of(kgem, struct sna, kgem)->flags & SNA_POWERSAVE)
352.15814 ++	if (__to_sna(kgem)->flags & SNA_POWERSAVE)
352.15815 + 		return true;
352.15816 + 
352.15817 + 	if (kgem->flush == flush && kgem->aperture < kgem->aperture_low)
352.15818 +@@ -5982,6 +6536,55 @@ bool kgem_check_many_bo_fenced(struct kgem *kgem, ...)
352.15819 + 	return kgem_flush(kgem, flush);
352.15820 + }
352.15821 + 
352.15822 ++void __kgem_bcs_set_tiling(struct kgem *kgem,
352.15823 ++			   struct kgem_bo *src,
352.15824 ++			   struct kgem_bo *dst)
352.15825 ++{
352.15826 ++	uint32_t state, *b;
352.15827 ++
352.15828 ++	DBG(("%s: src handle=%d:tiling=%d, dst handle=%d:tiling=%d\n",
352.15829 ++	     __FUNCTION__,
352.15830 ++	     src ? src->handle : 0, src ? src->tiling : 0,
352.15831 ++	     dst ? dst->handle : 0, dst ? dst->tiling : 0));
352.15832 ++	assert(kgem->mode == KGEM_BLT);
352.15833 ++	assert(dst == NULL || kgem_bo_can_blt(kgem, dst));
352.15834 ++	assert(src == NULL || kgem_bo_can_blt(kgem, src));
352.15835 ++
352.15836 ++	state = 0;
352.15837 ++	if (dst && dst->tiling == I915_TILING_Y)
352.15838 ++		state |= BCS_DST_Y;
352.15839 ++	if (src && src->tiling == I915_TILING_Y)
352.15840 ++		state |= BCS_SRC_Y;
352.15841 ++
352.15842 ++	if (kgem->bcs_state == state)
352.15843 ++		return;
352.15844 ++
352.15845 ++	DBG(("%s: updating SWCTRL %x -> %x\n", __FUNCTION__,
352.15846 ++	     kgem->bcs_state, state));
352.15847 ++
352.15848 ++	/* Over-estimate space in case we need to re-emit the cmd packet */
352.15849 ++	if (!kgem_check_batch(kgem, 24)) {
352.15850 ++		_kgem_submit(kgem);
352.15851 ++		_kgem_set_mode(kgem, KGEM_BLT);
352.15852 ++		if (state == 0)
352.15853 ++			return;
352.15854 ++	}
352.15855 ++
352.15856 ++	b = kgem->batch + kgem->nbatch;
352.15857 ++	if (kgem->nbatch) {
352.15858 ++		*b++ = MI_FLUSH_DW;
352.15859 ++		*b++ = 0;
352.15860 ++		*b++ = 0;
352.15861 ++		*b++ = 0;
352.15862 ++	}
352.15863 ++	*b++ = MI_LOAD_REGISTER_IMM;
352.15864 ++	*b++ = BCS_SWCTRL;
352.15865 ++	*b++ = (BCS_SRC_Y | BCS_DST_Y) << 16 | state;
352.15866 ++	kgem->nbatch = b - kgem->batch;
352.15867 ++
352.15868 ++	kgem->bcs_state = state;
352.15869 ++}
352.15870 ++
352.15871 + uint32_t kgem_add_reloc(struct kgem *kgem,
352.15872 + 			uint32_t pos,
352.15873 + 			struct kgem_bo *bo,
352.15874 +@@ -6195,12 +6798,6 @@ static void kgem_trim_vma_cache(struct kgem *kgem, int type, int bucket)
352.15875 + 
352.15876 + 		list_del(&bo->vma);
352.15877 + 		kgem->vma[type].count--;
352.15878 +-
352.15879 +-		if (!bo->purged && !kgem_bo_set_purgeable(kgem, bo)) {
352.15880 +-			DBG(("%s: freeing unpurgeable old mapping\n",
352.15881 +-			     __FUNCTION__));
352.15882 +-			kgem_bo_free(kgem, bo);
352.15883 +-		}
352.15884 + 	}
352.15885 + }
352.15886 + 
352.15887 +@@ -6216,8 +6813,8 @@ static void *__kgem_bo_map__gtt_or_wc(struct kgem *kgem, struct kgem_bo *bo)
352.15888 + 	kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
352.15889 + 
352.15890 + 	if (bo->tiling || !kgem->has_wc_mmap) {
352.15891 +-		assert(num_pages(bo) <= kgem->aperture_mappable / 2);
352.15892 + 		assert(kgem->gen != 021 || bo->tiling != I915_TILING_Y);
352.15893 ++		warn_unless(num_pages(bo) <= kgem->aperture_mappable / 2);
352.15894 + 
352.15895 + 		ptr = bo->map__gtt;
352.15896 + 		if (ptr == NULL)
352.15897 +@@ -6291,6 +6888,7 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
352.15898 + 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
352.15899 + 			kgem_throttle(kgem);
352.15900 + 		}
352.15901 ++		bo->needs_flush = false;
352.15902 + 		kgem_bo_retire(kgem, bo);
352.15903 + 		bo->domain = DOMAIN_GTT;
352.15904 + 		bo->gtt_dirty = true;
352.15905 +@@ -6319,14 +6917,16 @@ void *kgem_bo_map__wc(struct kgem *kgem, struct kgem_bo *bo)
352.15906 + 	     bo->handle, (long)bo->presumed_offset, bo->tiling, bo->map__gtt, bo->map__cpu, bo->domain));
352.15907 + 
352.15908 + 	assert(bo->proxy == NULL);
352.15909 +-	assert(bo->exec == NULL);
352.15910 + 	assert(list_is_empty(&bo->list));
352.15911 + 	assert_tiling(kgem, bo);
352.15912 + 	assert(!bo->purged || bo->reusable);
352.15913 + 
352.15914 + 	if (bo->map__wc)
352.15915 + 		return bo->map__wc;
352.15916 ++	if (!kgem->has_wc_mmap)
352.15917 ++		return NULL;
352.15918 + 
352.15919 ++	kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
352.15920 + 	return __kgem_bo_map__wc(kgem, bo);
352.15921 + }
352.15922 + 
352.15923 +@@ -6373,6 +6973,8 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
352.15924 + {
352.15925 + 	struct drm_gem_flink flink;
352.15926 + 
352.15927 ++	assert(kgem_bo_is_fenced(kgem, bo));
352.15928 ++
352.15929 + 	VG_CLEAR(flink);
352.15930 + 	flink.handle = bo->handle;
352.15931 + 	if (do_ioctl(kgem->fd, DRM_IOCTL_GEM_FLINK, &flink))
352.15932 +@@ -6387,7 +6989,6 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
352.15933 + 	 * party, we track the lifetime accurately.
352.15934 + 	 */
352.15935 + 	bo->reusable = false;
352.15936 +-
352.15937 + 	kgem_bo_unclean(kgem, bo);
352.15938 + 
352.15939 + 	return flink.name;
352.15940 +@@ -6411,16 +7012,34 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
352.15941 + 	first_page = (uintptr_t)ptr;
352.15942 + 	last_page = first_page + size + PAGE_SIZE - 1;
352.15943 + 
352.15944 +-	first_page &= ~(PAGE_SIZE-1);
352.15945 +-	last_page &= ~(PAGE_SIZE-1);
352.15946 ++	first_page &= ~(uintptr_t)(PAGE_SIZE-1);
352.15947 ++	last_page &= ~(uintptr_t)(PAGE_SIZE-1);
352.15948 + 	assert(last_page > first_page);
352.15949 + 
352.15950 + 	handle = gem_userptr(kgem->fd,
352.15951 + 			     (void *)first_page, last_page-first_page,
352.15952 + 			     read_only);
352.15953 + 	if (handle == 0) {
352.15954 +-		DBG(("%s: import failed, errno=%d\n", __FUNCTION__, errno));
352.15955 +-		return NULL;
352.15956 ++		if (read_only && kgem->has_wc_mmap) {
352.15957 ++			struct drm_i915_gem_set_domain set_domain;
352.15958 ++
352.15959 ++			handle = gem_userptr(kgem->fd,
352.15960 ++					     (void *)first_page, last_page-first_page,
352.15961 ++					     false);
352.15962 ++
352.15963 ++			VG_CLEAR(set_domain);
352.15964 ++			set_domain.handle = handle;
352.15965 ++			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.15966 ++			set_domain.write_domain = 0;
352.15967 ++			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
352.15968 ++				gem_close(kgem->fd, handle);
352.15969 ++				handle = 0;
352.15970 ++			}
352.15971 ++		}
352.15972 ++		if (handle == 0) {
352.15973 ++			DBG(("%s: import failed, errno=%d\n", __FUNCTION__, errno));
352.15974 ++			return NULL;
352.15975 ++		}
352.15976 + 	}
352.15977 + 
352.15978 + 	bo = __kgem_bo_alloc(handle, (last_page - first_page) / PAGE_SIZE);
352.15979 +@@ -6483,8 +7102,10 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
352.15980 + 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
352.15981 + 			kgem_throttle(kgem);
352.15982 + 		}
352.15983 ++		bo->needs_flush = false;
352.15984 + 		kgem_bo_retire(kgem, bo);
352.15985 + 		bo->domain = DOMAIN_CPU;
352.15986 ++		bo->gtt_dirty = true;
352.15987 + 	}
352.15988 + }
352.15989 + 
352.15990 +@@ -6505,6 +7126,9 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
352.15991 + 	assert(bo->refcnt);
352.15992 + 	assert(!bo->purged);
352.15993 + 
352.15994 ++	if (bo->rq == NULL && (kgem->has_llc || bo->snoop) && !write)
352.15995 ++		return;
352.15996 ++
352.15997 + 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
352.15998 + 		struct drm_i915_gem_set_domain set_domain;
352.15999 + 
352.16000 +@@ -6522,9 +7146,11 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
352.16001 + 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
352.16002 + 			kgem_throttle(kgem);
352.16003 + 		}
352.16004 ++		bo->needs_flush = false;
352.16005 + 		if (write) {
352.16006 + 			kgem_bo_retire(kgem, bo);
352.16007 + 			bo->domain = DOMAIN_CPU;
352.16008 ++			bo->gtt_dirty = true;
352.16009 + 		} else {
352.16010 + 			if (bo->exec == NULL)
352.16011 + 				kgem_bo_maybe_retire(kgem, bo);
352.16012 +@@ -6539,6 +7165,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
352.16013 + 	assert(bo->refcnt);
352.16014 + 	assert(bo->proxy == NULL);
352.16015 + 	assert_tiling(kgem, bo);
352.16016 ++	assert(!bo->snoop);
352.16017 + 
352.16018 + 	kgem_bo_submit(kgem, bo);
352.16019 + 
352.16020 +@@ -6559,6 +7186,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
352.16021 + 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
352.16022 + 			kgem_throttle(kgem);
352.16023 + 		}
352.16024 ++		bo->needs_flush = false;
352.16025 + 		kgem_bo_retire(kgem, bo);
352.16026 + 		bo->domain = DOMAIN_GTT;
352.16027 + 		bo->gtt_dirty = true;
352.16028 +@@ -7485,6 +8113,7 @@ kgem_replace_bo(struct kgem *kgem,
352.16029 + 		}
352.16030 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.16031 + 	}
352.16032 ++	kgem_bcs_set_tiling(kgem, src, dst);
352.16033 + 
352.16034 + 	br00 = XY_SRC_COPY_BLT_CMD;
352.16035 + 	br13 = pitch;
352.16036 +@@ -7553,6 +8182,9 @@ bool kgem_bo_convert_to_gpu(struct kgem *kgem,
352.16037 + 	     __FUNCTION__, bo->handle, flags, __kgem_bo_is_busy(kgem, bo)));
352.16038 + 	assert(bo->tiling == I915_TILING_NONE);
352.16039 + 
352.16040 ++	if (flags & (__MOVE_PRIME | __MOVE_SCANOUT))
352.16041 ++		return false;
352.16042 ++
352.16043 + 	if (kgem->has_llc)
352.16044 + 		return true;
352.16045 + 
352.16046 +diff --git a/src/sna/kgem.h b/src/sna/kgem.h
352.16047 +index 2267bacf..08b4eb20 100644
352.16048 +--- a/src/sna/kgem.h
352.16049 ++++ b/src/sna/kgem.h
352.16050 +@@ -42,6 +42,7 @@ struct kgem_bo {
352.16051 + #define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3))
352.16052 + #define RQ_RING(rq) ((uintptr_t)(rq) & 3)
352.16053 + #define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT)
352.16054 ++#define RQ_IS_RENDER(rq) (RQ_RING(rq) == KGEM_RENDER)
352.16055 + #define MAKE_REQUEST(rq, ring) ((struct kgem_request *)((uintptr_t)(rq) | (ring)))
352.16056 + 
352.16057 + 	struct drm_i915_gem_exec_object2 *exec;
352.16058 +@@ -103,7 +104,7 @@ struct kgem_request {
352.16059 + 	struct list list;
352.16060 + 	struct kgem_bo *bo;
352.16061 + 	struct list buffers;
352.16062 +-	int ring;
352.16063 ++	unsigned ring;
352.16064 + };
352.16065 + 
352.16066 + enum {
352.16067 +@@ -112,6 +113,12 @@ enum {
352.16068 + 	NUM_MAP_TYPES,
352.16069 + };
352.16070 + 
352.16071 ++typedef void (*memcpy_box_func)(const void *src, void *dst, int bpp,
352.16072 ++				int32_t src_stride, int32_t dst_stride,
352.16073 ++				int16_t src_x, int16_t src_y,
352.16074 ++				int16_t dst_x, int16_t dst_y,
352.16075 ++				uint16_t width, uint16_t height);
352.16076 ++
352.16077 + struct kgem {
352.16078 + 	unsigned wedged;
352.16079 + 	int fd;
352.16080 +@@ -157,6 +164,8 @@ struct kgem {
352.16081 + 		int16_t count;
352.16082 + 	} vma[NUM_MAP_TYPES];
352.16083 + 
352.16084 ++	uint32_t bcs_state;
352.16085 ++
352.16086 + 	uint32_t batch_flags;
352.16087 + 	uint32_t batch_flags_base;
352.16088 + #define I915_EXEC_SECURE (1<<9)
352.16089 +@@ -186,9 +195,15 @@ struct kgem {
352.16090 + 	uint32_t has_no_reloc :1;
352.16091 + 	uint32_t has_handle_lut :1;
352.16092 + 	uint32_t has_wc_mmap :1;
352.16093 ++	uint32_t has_dirtyfb :1;
352.16094 + 
352.16095 ++	uint32_t can_fence :1;
352.16096 + 	uint32_t can_blt_cpu :1;
352.16097 ++	uint32_t can_blt_y :1;
352.16098 + 	uint32_t can_render_y :1;
352.16099 ++	uint32_t can_scanout_y :1;
352.16100 ++
352.16101 ++	uint32_t needs_dirtyfb :1;
352.16102 + 
352.16103 + 	uint16_t fence_max;
352.16104 + 	uint16_t half_cpu_cache_pages;
352.16105 +@@ -203,16 +218,9 @@ struct kgem {
352.16106 + 	void (*retire)(struct kgem *kgem);
352.16107 + 	void (*expire)(struct kgem *kgem);
352.16108 + 
352.16109 +-	void (*memcpy_to_tiled_x)(const void *src, void *dst, int bpp,
352.16110 +-				  int32_t src_stride, int32_t dst_stride,
352.16111 +-				  int16_t src_x, int16_t src_y,
352.16112 +-				  int16_t dst_x, int16_t dst_y,
352.16113 +-				  uint16_t width, uint16_t height);
352.16114 +-	void (*memcpy_from_tiled_x)(const void *src, void *dst, int bpp,
352.16115 +-				    int32_t src_stride, int32_t dst_stride,
352.16116 +-				    int16_t src_x, int16_t src_y,
352.16117 +-				    int16_t dst_x, int16_t dst_y,
352.16118 +-				    uint16_t width, uint16_t height);
352.16119 ++	memcpy_box_func memcpy_to_tiled_x;
352.16120 ++	memcpy_box_func memcpy_from_tiled_x;
352.16121 ++	memcpy_box_func memcpy_between_tiled_x;
352.16122 + 
352.16123 + 	struct kgem_bo *batch_bo;
352.16124 + 
352.16125 +@@ -230,7 +238,7 @@ struct kgem {
352.16126 + 
352.16127 + #define KGEM_MAX_DEFERRED_VBO 16
352.16128 + 
352.16129 +-#define KGEM_BATCH_RESERVED 1
352.16130 ++#define KGEM_BATCH_RESERVED 8 /* LRI(SWCTRL) + END */
352.16131 + #define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
352.16132 + #define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
352.16133 + 
352.16134 +@@ -317,6 +325,7 @@ bool kgem_bo_convert_to_gpu(struct kgem *kgem,
352.16135 + 			    struct kgem_bo *bo,
352.16136 + 			    unsigned flags);
352.16137 + 
352.16138 ++bool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo);
352.16139 + uint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format);
352.16140 + void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset);
352.16141 + 
352.16142 +@@ -342,6 +351,11 @@ static inline bool kgem_ring_is_idle(struct kgem *kgem, int ring)
352.16143 + {
352.16144 + 	ring = ring == KGEM_BLT;
352.16145 + 
352.16146 ++	if (kgem->needs_semaphore &&
352.16147 ++	    !list_is_empty(&kgem->requests[!ring]) &&
352.16148 ++	    !__kgem_ring_is_idle(kgem, !ring))
352.16149 ++		return false;
352.16150 ++
352.16151 + 	if (list_is_empty(&kgem->requests[ring]))
352.16152 + 		return true;
352.16153 + 
352.16154 +@@ -390,6 +404,7 @@ void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
352.16155 + static inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
352.16156 + {
352.16157 + 	assert(bo->refcnt);
352.16158 ++	assert(bo->refcnt > bo->active_scanout);
352.16159 + 	if (--bo->refcnt == 0)
352.16160 + 		_kgem_bo_destroy(kgem, bo);
352.16161 + }
352.16162 +@@ -400,13 +415,13 @@ static inline void kgem_set_mode(struct kgem *kgem,
352.16163 + 				 enum kgem_mode mode,
352.16164 + 				 struct kgem_bo *bo)
352.16165 + {
352.16166 +-	assert(!kgem->wedged);
352.16167 ++	warn_unless(!kgem->wedged);
352.16168 + 
352.16169 + #if DEBUG_FLUSH_BATCH
352.16170 + 	kgem_submit(kgem);
352.16171 + #endif
352.16172 + 
352.16173 +-	if (kgem->nreloc && bo->exec == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
352.16174 ++	if (kgem->nreloc && bo->rq == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
352.16175 + 		DBG(("%s: flushing before new bo\n", __FUNCTION__));
352.16176 + 		_kgem_submit(kgem);
352.16177 + 	}
352.16178 +@@ -422,7 +437,7 @@ static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode)
352.16179 + {
352.16180 + 	assert(kgem->mode == KGEM_NONE);
352.16181 + 	assert(kgem->nbatch == 0);
352.16182 +-	assert(!kgem->wedged);
352.16183 ++	warn_unless(!kgem->wedged);
352.16184 + 	kgem->context_switch(kgem, mode);
352.16185 + 	kgem->mode = mode;
352.16186 + }
352.16187 +@@ -566,7 +581,7 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
352.16188 + {
352.16189 + 	assert(bo->refcnt);
352.16190 + 
352.16191 +-	if (bo->tiling == I915_TILING_Y) {
352.16192 ++	if (bo->tiling == I915_TILING_Y && !kgem->can_blt_y) {
352.16193 + 		DBG(("%s: can not blt to handle=%d, tiling=Y\n",
352.16194 + 		     __FUNCTION__, bo->handle));
352.16195 + 		return false;
352.16196 +@@ -581,6 +596,22 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
352.16197 + 	return kgem_bo_blt_pitch_is_ok(kgem, bo);
352.16198 + }
352.16199 + 
352.16200 ++void __kgem_bcs_set_tiling(struct kgem *kgem,
352.16201 ++			   struct kgem_bo *src,
352.16202 ++			   struct kgem_bo *dst);
352.16203 ++
352.16204 ++inline static void kgem_bcs_set_tiling(struct kgem *kgem,
352.16205 ++				       struct kgem_bo *src,
352.16206 ++				       struct kgem_bo *dst)
352.16207 ++{
352.16208 ++	assert(kgem->mode == KGEM_BLT);
352.16209 ++
352.16210 ++	if (!kgem->can_blt_y)
352.16211 ++		return;
352.16212 ++
352.16213 ++	__kgem_bcs_set_tiling(kgem, src, dst);
352.16214 ++}
352.16215 ++
352.16216 + static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
352.16217 + {
352.16218 + 	assert(bo->refcnt);
352.16219 +@@ -607,17 +638,24 @@ static inline void kgem_bo_mark_busy(struct kgem *kgem, struct kgem_bo *bo, int
352.16220 + 	}
352.16221 + }
352.16222 + 
352.16223 +-inline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
352.16224 ++static inline void __kgem_bo_clear_dirty(struct kgem_bo *bo)
352.16225 + {
352.16226 + 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
352.16227 +-	bo->rq = NULL;
352.16228 +-	list_del(&bo->request);
352.16229 + 
352.16230 + 	bo->domain = DOMAIN_NONE;
352.16231 + 	bo->needs_flush = false;
352.16232 + 	bo->gtt_dirty = false;
352.16233 + }
352.16234 + 
352.16235 ++inline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
352.16236 ++{
352.16237 ++	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
352.16238 ++	bo->rq = NULL;
352.16239 ++	list_del(&bo->request);
352.16240 ++
352.16241 ++	__kgem_bo_clear_dirty(bo);
352.16242 ++}
352.16243 ++
352.16244 + static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
352.16245 + {
352.16246 + 	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
352.16247 +@@ -626,7 +664,7 @@ static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
352.16248 + 	return bo->rq;
352.16249 + }
352.16250 + 
352.16251 +-void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
352.16252 ++bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
352.16253 + static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
352.16254 + {
352.16255 + 	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
352.16256 +@@ -636,14 +674,13 @@ static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
352.16257 + 	if (bo->exec)
352.16258 + 		return true;
352.16259 + 
352.16260 +-	if (bo->rq && !__kgem_busy(kgem, bo->handle)) {
352.16261 +-		__kgem_retire_requests_upto(kgem, bo);
352.16262 +-		assert(list_is_empty(&bo->request));
352.16263 +-		assert(bo->rq == NULL);
352.16264 +-		assert(bo->domain == DOMAIN_NONE);
352.16265 +-	}
352.16266 ++	if (bo->rq == NULL)
352.16267 ++		return false;
352.16268 ++
352.16269 ++	if (__kgem_busy(kgem, bo->handle))
352.16270 ++		return true;
352.16271 + 
352.16272 +-	return kgem_bo_is_busy(bo);
352.16273 ++	return __kgem_retire_requests_upto(kgem, bo);
352.16274 + }
352.16275 + 
352.16276 + static inline bool kgem_bo_is_render(struct kgem_bo *bo)
352.16277 +@@ -651,7 +688,15 @@ static inline bool kgem_bo_is_render(struct kgem_bo *bo)
352.16278 + 	DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__,
352.16279 + 	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
352.16280 + 	assert(bo->refcnt);
352.16281 +-	return bo->rq && RQ_RING(bo->rq) == I915_EXEC_RENDER;
352.16282 ++	return bo->rq && RQ_RING(bo->rq) != KGEM_BLT;
352.16283 ++}
352.16284 ++
352.16285 ++static inline bool kgem_bo_is_blt(struct kgem_bo *bo)
352.16286 ++{
352.16287 ++	DBG(("%s: handle=%d, rq? %d\n", __FUNCTION__,
352.16288 ++	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
352.16289 ++	assert(bo->refcnt);
352.16290 ++	return RQ_RING(bo->rq) == KGEM_BLT;
352.16291 + }
352.16292 + 
352.16293 + static inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
352.16294 +@@ -852,6 +897,6 @@ memcpy_from_tiled_x(struct kgem *kgem,
352.16295 + 					 width, height);
352.16296 + }
352.16297 + 
352.16298 +-void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling);
352.16299 ++void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling, unsigned cpu);
352.16300 + 
352.16301 + #endif /* KGEM_H */
352.16302 +diff --git a/src/sna/kgem_debug_gen4.c b/src/sna/kgem_debug_gen4.c
352.16303 +index 9b80dc88..8e6e47b6 100644
352.16304 +--- a/src/sna/kgem_debug_gen4.c
352.16305 ++++ b/src/sna/kgem_debug_gen4.c
352.16306 +@@ -598,7 +598,7 @@ int kgem_gen4_decode_3d(struct kgem *kgem, uint32_t offset)
352.16307 + 		assert(len == 7);
352.16308 + 		kgem_debug_print(data, offset, 0,
352.16309 + 			  "3DSTATE_DEPTH_BUFFER\n");
352.16310 +-		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
352.16311 ++		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
352.16312 + 			  get_965_surfacetype(data[1] >> 29),
352.16313 + 			  get_965_depthformat((data[1] >> 18) & 0x7),
352.16314 + 			  (data[1] & 0x0001ffff) + 1,
352.16315 +diff --git a/src/sna/kgem_debug_gen5.c b/src/sna/kgem_debug_gen5.c
352.16316 +index 8b55dd91..f1b1275f 100644
352.16317 +--- a/src/sna/kgem_debug_gen5.c
352.16318 ++++ b/src/sna/kgem_debug_gen5.c
352.16319 +@@ -573,7 +573,7 @@ int kgem_gen5_decode_3d(struct kgem *kgem, uint32_t offset)
352.16320 + 		assert(len == 7);
352.16321 + 		kgem_debug_print(data, offset, 0,
352.16322 + 			  "3DSTATE_DEPTH_BUFFER\n");
352.16323 +-		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
352.16324 ++		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
352.16325 + 			  get_965_surfacetype(data[1] >> 29),
352.16326 + 			  get_965_depthformat((data[1] >> 18) & 0x7),
352.16327 + 			  (data[1] & 0x0001ffff) + 1,
352.16328 +diff --git a/src/sna/kgem_debug_gen6.c b/src/sna/kgem_debug_gen6.c
352.16329 +index 7ef55d38..579c5d54 100644
352.16330 +--- a/src/sna/kgem_debug_gen6.c
352.16331 ++++ b/src/sna/kgem_debug_gen6.c
352.16332 +@@ -985,7 +985,7 @@ int kgem_gen6_decode_3d(struct kgem *kgem, uint32_t offset)
352.16333 + 		assert(len == 7);
352.16334 + 		kgem_debug_print(data, offset, 0,
352.16335 + 			  "3DSTATE_DEPTH_BUFFER\n");
352.16336 +-		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
352.16337 ++		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
352.16338 + 			  get_965_surfacetype(data[1] >> 29),
352.16339 + 			  get_965_depthformat((data[1] >> 18) & 0x7),
352.16340 + 			  (data[1] & 0x0001ffff) + 1,
352.16341 +diff --git a/src/sna/sna.h b/src/sna/sna.h
352.16342 +index 18425e30..7861110a 100644
352.16343 +--- a/src/sna/sna.h
352.16344 ++++ b/src/sna/sna.h
352.16345 +@@ -154,6 +154,8 @@ struct sna_pixmap {
352.16346 + #define MAPPED_GTT 1
352.16347 + #define MAPPED_CPU 2
352.16348 + 	uint8_t flush :2;
352.16349 ++#define FLUSH_READ 1
352.16350 ++#define FLUSH_WRITE 2
352.16351 + 	uint8_t shm :1;
352.16352 + 	uint8_t clear :1;
352.16353 + 	uint8_t header :1;
352.16354 +@@ -179,18 +181,31 @@ static inline WindowPtr get_root_window(ScreenPtr screen)
352.16355 + #endif
352.16356 + }
352.16357 + 
352.16358 ++#if !NDEBUG
352.16359 ++static PixmapPtr check_pixmap(PixmapPtr pixmap)
352.16360 ++{
352.16361 ++	if (pixmap != NULL) {
352.16362 ++		assert(pixmap->refcnt >= 1);
352.16363 ++		assert(pixmap->devKind != 0xdeadbeef);
352.16364 ++	}
352.16365 ++	return pixmap;
352.16366 ++}
352.16367 ++#else
352.16368 ++#define check_pixmap(p) p
352.16369 ++#endif
352.16370 ++
352.16371 + static inline PixmapPtr get_window_pixmap(WindowPtr window)
352.16372 + {
352.16373 + 	assert(window);
352.16374 + 	assert(window->drawable.type != DRAWABLE_PIXMAP);
352.16375 +-	return fbGetWindowPixmap(window);
352.16376 ++	return check_pixmap(fbGetWindowPixmap(window));
352.16377 + }
352.16378 + 
352.16379 + static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
352.16380 + {
352.16381 + 	assert(drawable);
352.16382 + 	if (drawable->type == DRAWABLE_PIXMAP)
352.16383 +-		return (PixmapPtr)drawable;
352.16384 ++		return check_pixmap((PixmapPtr)drawable);
352.16385 + 	else
352.16386 + 		return get_window_pixmap((WindowPtr)drawable);
352.16387 + }
352.16388 +@@ -244,11 +259,12 @@ struct sna {
352.16389 + #define SNA_NO_VSYNC		0x40
352.16390 + #define SNA_TRIPLE_BUFFER	0x80
352.16391 + #define SNA_TEAR_FREE		0x100
352.16392 +-#define SNA_FORCE_SHADOW	0x200
352.16393 +-#define SNA_FLUSH_GTT		0x400
352.16394 ++#define SNA_WANT_TEAR_FREE	0x200
352.16395 ++#define SNA_FORCE_SHADOW	0x400
352.16396 ++#define SNA_FLUSH_GTT		0x800
352.16397 + #define SNA_PERFORMANCE		0x1000
352.16398 + #define SNA_POWERSAVE		0x2000
352.16399 +-#define SNA_REMOVE_OUTPUTS	0x4000
352.16400 ++#define SNA_NO_DPMS		0x4000
352.16401 + #define SNA_HAS_FLIP		0x10000
352.16402 + #define SNA_HAS_ASYNC_FLIP	0x20000
352.16403 + #define SNA_LINEAR_FB		0x40000
352.16404 +@@ -265,7 +281,13 @@ struct sna {
352.16405 + #define AVX 0x80
352.16406 + #define AVX2 0x100
352.16407 + 
352.16408 +-	unsigned watch_flush;
352.16409 ++	bool ignore_copy_area : 1;
352.16410 ++
352.16411 ++	unsigned watch_shm_flush;
352.16412 ++	unsigned watch_dri_flush;
352.16413 ++	unsigned damage_event;
352.16414 ++	bool needs_shm_flush;
352.16415 ++	bool needs_dri_flush;
352.16416 + 
352.16417 + 	struct timeval timer_tv;
352.16418 + 	uint32_t timer_expire[NUM_TIMERS];
352.16419 +@@ -284,9 +306,17 @@ struct sna {
352.16420 + 		struct kgem_bo *shadow;
352.16421 + 		unsigned front_active;
352.16422 + 		unsigned shadow_active;
352.16423 ++		unsigned rr_active;
352.16424 + 		unsigned flip_active;
352.16425 ++		unsigned hidden;
352.16426 ++		bool shadow_enabled;
352.16427 ++		bool shadow_wait;
352.16428 + 		bool dirty;
352.16429 + 
352.16430 ++		struct drm_event_vblank *shadow_events;
352.16431 ++		int shadow_nevent;
352.16432 ++		int shadow_size;
352.16433 ++
352.16434 + 		int max_crtc_width, max_crtc_height;
352.16435 + 		RegionRec shadow_region;
352.16436 + 		RegionRec shadow_cancel;
352.16437 +@@ -318,7 +348,8 @@ struct sna {
352.16438 + 		uint32_t fg, bg;
352.16439 + 		int size;
352.16440 + 
352.16441 +-		int active;
352.16442 ++		bool disable;
352.16443 ++		bool active;
352.16444 + 		int last_x;
352.16445 + 		int last_y;
352.16446 + 
352.16447 +@@ -331,8 +362,9 @@ struct sna {
352.16448 + 	} cursor;
352.16449 + 
352.16450 + 	struct sna_dri2 {
352.16451 +-		bool available;
352.16452 +-		bool open;
352.16453 ++		bool available : 1;
352.16454 ++		bool enable : 1;
352.16455 ++		bool open : 1;
352.16456 + 
352.16457 + #if HAVE_DRI2
352.16458 + 		void *flip_pending;
352.16459 +@@ -341,8 +373,11 @@ struct sna {
352.16460 + 	} dri2;
352.16461 + 
352.16462 + 	struct sna_dri3 {
352.16463 +-		bool available;
352.16464 +-		bool open;
352.16465 ++		bool available :1;
352.16466 ++		bool override : 1;
352.16467 ++		bool enable : 1;
352.16468 ++		bool open :1;
352.16469 ++
352.16470 + #if HAVE_DRI3
352.16471 + 		SyncScreenCreateFenceFunc create_fence;
352.16472 + 		struct list pixmaps;
352.16473 +@@ -353,6 +388,9 @@ struct sna {
352.16474 + 		bool available;
352.16475 + 		bool open;
352.16476 + #if HAVE_PRESENT
352.16477 ++		struct list vblank_queue;
352.16478 ++		uint64_t unflip;
352.16479 ++		void *freed_info;
352.16480 + #endif
352.16481 + 	} present;
352.16482 + 
352.16483 +@@ -364,8 +402,10 @@ struct sna {
352.16484 + 	EntityInfoPtr pEnt;
352.16485 + 	const struct intel_device_info *info;
352.16486 + 
352.16487 ++#if !HAVE_NOTIFY_FD
352.16488 + 	ScreenBlockHandlerProcPtr BlockHandler;
352.16489 + 	ScreenWakeupHandlerProcPtr WakeupHandler;
352.16490 ++#endif
352.16491 + 	CloseScreenProcPtr CloseScreen;
352.16492 + 
352.16493 + 	PicturePtr clear;
352.16494 +@@ -383,6 +423,7 @@ struct sna {
352.16495 + 		struct gen6_render_state gen6;
352.16496 + 		struct gen7_render_state gen7;
352.16497 + 		struct gen8_render_state gen8;
352.16498 ++		struct gen9_render_state gen9;
352.16499 + 	} render_state;
352.16500 + 
352.16501 + 	/* Broken-out options. */
352.16502 +@@ -420,7 +461,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
352.16503 + bool sna_mode_fake_init(struct sna *sna, int num_fake);
352.16504 + bool sna_mode_wants_tear_free(struct sna *sna);
352.16505 + void sna_mode_adjust_frame(struct sna *sna, int x, int y);
352.16506 +-extern void sna_mode_discover(struct sna *sna);
352.16507 ++extern void sna_mode_discover(struct sna *sna, bool tell);
352.16508 + extern void sna_mode_check(struct sna *sna);
352.16509 + extern bool sna_mode_disable(struct sna *sna);
352.16510 + extern void sna_mode_enable(struct sna *sna);
352.16511 +@@ -434,6 +475,7 @@ extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
352.16512 + extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
352.16513 + 					     const RegionRec *region);
352.16514 + extern void sna_mode_set_primary(struct sna *sna);
352.16515 ++extern bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id);
352.16516 + extern void sna_mode_close(struct sna *sna);
352.16517 + extern void sna_mode_fini(struct sna *sna);
352.16518 + 
352.16519 +@@ -444,6 +486,7 @@ extern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
352.16520 + typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
352.16521 + 				   void *data);
352.16522 + 
352.16523 ++extern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo);
352.16524 + extern int sna_page_flip(struct sna *sna,
352.16525 + 			 struct kgem_bo *bo,
352.16526 + 			 sna_flip_handler_t handler,
352.16527 +@@ -461,6 +504,11 @@ to_sna_from_screen(ScreenPtr screen)
352.16528 + 	return to_sna(xf86ScreenToScrn(screen));
352.16529 + }
352.16530 + 
352.16531 ++pure static inline ScreenPtr to_screen_from_sna(struct sna *sna)
352.16532 ++{
352.16533 ++	return xf86ScrnToScreen(sna->scrn);
352.16534 ++}
352.16535 ++
352.16536 + pure static inline struct sna *
352.16537 + to_sna_from_pixmap(PixmapPtr pixmap)
352.16538 + {
352.16539 +@@ -498,12 +546,11 @@ to_sna_from_kgem(struct kgem *kgem)
352.16540 + extern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
352.16541 + 				     const BoxRec *box,
352.16542 + 				     xf86CrtcPtr desired);
352.16543 ++extern xf86CrtcPtr sna_primary_crtc(struct sna *sna);
352.16544 + 
352.16545 + extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
352.16546 + 				  xf86CrtcPtr crtc, const BoxRec *clip);
352.16547 + 
352.16548 +-xf86CrtcPtr sna_mode_first_crtc(struct sna *sna);
352.16549 +-
352.16550 + const struct ust_msc {
352.16551 + 	uint64_t msc;
352.16552 + 	int tv_sec;
352.16553 +@@ -536,6 +583,11 @@ static inline uint64_t ust64(int tv_sec, int tv_usec)
352.16554 + 	return (uint64_t)tv_sec * 1000000 + tv_usec;
352.16555 + }
352.16556 + 
352.16557 ++static inline uint64_t swap_ust(const struct ust_msc *swap)
352.16558 ++{
352.16559 ++	return ust64(swap->tv_sec, swap->tv_usec);
352.16560 ++}
352.16561 ++
352.16562 + #if HAVE_DRI2
352.16563 + bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
352.16564 + void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
352.16565 +@@ -567,20 +619,59 @@ bool sna_present_open(struct sna *sna, ScreenPtr pScreen);
352.16566 + void sna_present_update(struct sna *sna);
352.16567 + void sna_present_close(struct sna *sna, ScreenPtr pScreen);
352.16568 + void sna_present_vblank_handler(struct drm_event_vblank *event);
352.16569 ++void sna_present_cancel_flip(struct sna *sna);
352.16570 + #else
352.16571 + static inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
352.16572 + static inline void sna_present_update(struct sna *sna) { }
352.16573 + static inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
352.16574 + static inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
352.16575 ++static inline void sna_present_cancel_flip(struct sna *sna) { }
352.16576 + #endif
352.16577 + 
352.16578 +-extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
352.16579 +-extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
352.16580 +-extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
352.16581 +-extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
352.16582 +-extern bool sna_crtc_is_on(xf86CrtcPtr crtc);
352.16583 ++extern unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc);
352.16584 ++extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_t rotation);
352.16585 ++extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx);
352.16586 + extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
352.16587 + 
352.16588 ++#define CRTC_VBLANK 0x3
352.16589 ++#define CRTC_ON 0x80000000
352.16590 ++
352.16591 ++uint32_t sna_crtc_id(xf86CrtcPtr crtc);
352.16592 ++
352.16593 ++static inline unsigned long *sna_crtc_flags(xf86CrtcPtr crtc)
352.16594 ++{
352.16595 ++	unsigned long *flags = crtc->driver_private;
352.16596 ++	assert(flags);
352.16597 ++	return flags;
352.16598 ++}
352.16599 ++
352.16600 ++static inline unsigned sna_crtc_pipe(xf86CrtcPtr crtc)
352.16601 ++{
352.16602 ++	return *sna_crtc_flags(crtc) >> 8 & 0xff;
352.16603 ++}
352.16604 ++
352.16605 ++static inline bool sna_crtc_is_on(xf86CrtcPtr crtc)
352.16606 ++{
352.16607 ++	return *sna_crtc_flags(crtc) & CRTC_ON;
352.16608 ++}
352.16609 ++
352.16610 ++static inline void sna_crtc_set_vblank(xf86CrtcPtr crtc)
352.16611 ++{
352.16612 ++	assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < 3);
352.16613 ++	++*sna_crtc_flags(crtc);
352.16614 ++}
352.16615 ++
352.16616 ++static inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc)
352.16617 ++{
352.16618 ++	assert(*sna_crtc_flags(crtc) & CRTC_VBLANK);
352.16619 ++	--*sna_crtc_flags(crtc);
352.16620 ++}
352.16621 ++
352.16622 ++static inline bool sna_crtc_has_vblank(xf86CrtcPtr crtc)
352.16623 ++{
352.16624 ++	return *sna_crtc_flags(crtc) & CRTC_VBLANK;
352.16625 ++}
352.16626 ++
352.16627 + CARD32 sna_format_for_depth(int depth);
352.16628 + CARD32 sna_render_format_for_depth(int depth);
352.16629 + 
352.16630 +@@ -998,15 +1089,14 @@ static inline uint32_t pixmap_size(PixmapPtr pixmap)
352.16631 + 
352.16632 + bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
352.16633 + void sna_accel_create(struct sna *sna);
352.16634 +-void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
352.16635 +-void sna_accel_wakeup_handler(struct sna *sna);
352.16636 +-void sna_accel_watch_flush(struct sna *sna, int enable);
352.16637 ++void sna_accel_block(struct sna *sna, struct timeval **tv);
352.16638 + void sna_accel_flush(struct sna *sna);
352.16639 + void sna_accel_enter(struct sna *sna);
352.16640 + void sna_accel_leave(struct sna *sna);
352.16641 + void sna_accel_close(struct sna *sna);
352.16642 + void sna_accel_free(struct sna *sna);
352.16643 + 
352.16644 ++void sna_watch_flush(struct sna *sna, int enable);
352.16645 + void sna_copy_fbcon(struct sna *sna);
352.16646 + 
352.16647 + bool sna_composite_create(struct sna *sna);
352.16648 +@@ -1127,6 +1217,16 @@ memcpy_blt(const void *src, void *dst, int bpp,
352.16649 + 	   uint16_t width, uint16_t height);
352.16650 + 
352.16651 + void
352.16652 ++affine_blt(const void *src, void *dst, int bpp,
352.16653 ++	   int16_t src_x, int16_t src_y,
352.16654 ++	   int16_t src_width, int16_t src_height,
352.16655 ++	   int32_t src_stride,
352.16656 ++	   int16_t dst_x, int16_t dst_y,
352.16657 ++	   uint16_t dst_width, uint16_t dst_height,
352.16658 ++	   int32_t dst_stride,
352.16659 ++	   const struct pixman_f_transform *t);
352.16660 ++
352.16661 ++void
352.16662 + memmove_box(const void *src, void *dst,
352.16663 + 	    int bpp, int32_t stride,
352.16664 + 	    const BoxRec *box,
352.16665 +@@ -1182,6 +1282,31 @@ box_intersect(BoxPtr a, const BoxRec *b)
352.16666 + 	return true;
352.16667 + }
352.16668 + 
352.16669 ++const BoxRec *
352.16670 ++__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y);
352.16671 ++inline static const BoxRec *
352.16672 ++find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
352.16673 ++{
352.16674 ++	/* Special case for incremental trapezoid clipping */
352.16675 ++	if (begin == end)
352.16676 ++		return end;
352.16677 ++
352.16678 ++	/* Quick test if scanline is within range of clip boxes */
352.16679 ++	if (begin->y2 > y) {
352.16680 ++		assert(end == begin + 1 ||
352.16681 ++		       __find_clip_box_for_y(begin, end, y) == begin);
352.16682 ++		return begin;
352.16683 ++	}
352.16684 ++	if (y >= end[-1].y2) {
352.16685 ++		assert(end == begin + 1 ||
352.16686 ++		       __find_clip_box_for_y(begin, end, y) == end);
352.16687 ++		return end;
352.16688 ++	}
352.16689 ++
352.16690 ++	/* Otherwise bisect to find the first box crossing y */
352.16691 ++	return __find_clip_box_for_y(begin, end, y);
352.16692 ++}
352.16693 ++
352.16694 + unsigned sna_cpu_detect(void);
352.16695 + char *sna_cpu_features_to_string(unsigned features, char *line);
352.16696 + 
352.16697 +@@ -1237,4 +1362,17 @@ static inline void sigtrap_put(void)
352.16698 + extern int getline(char **line, size_t *len, FILE *file);
352.16699 + #endif
352.16700 + 
352.16701 ++static inline void add_shm_flush(struct sna *sna, struct sna_pixmap *priv)
352.16702 ++{
352.16703 ++	if (!priv->shm)
352.16704 ++		return;
352.16705 ++
352.16706 ++	DBG(("%s: marking handle=%d for SHM flush\n",
352.16707 ++	     __FUNCTION__, priv->cpu_bo->handle));
352.16708 ++
352.16709 ++	assert(!priv->flush);
352.16710 ++	sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.16711 ++	sna->needs_shm_flush = true;
352.16712 ++}
352.16713 ++
352.16714 + #endif /* _SNA_H */
352.16715 +diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
352.16716 +index baf5f609..25a075cf 100644
352.16717 +--- a/src/sna/sna_accel.c
352.16718 ++++ b/src/sna/sna_accel.c
352.16719 +@@ -50,8 +50,11 @@
352.16720 + #endif
352.16721 + #include <shmint.h>
352.16722 + 
352.16723 ++#include <X11/extensions/damageproto.h>
352.16724 ++
352.16725 + #include <sys/time.h>
352.16726 + #include <sys/mman.h>
352.16727 ++#include <sys/ioctl.h>
352.16728 + #include <unistd.h>
352.16729 + 
352.16730 + #ifdef HAVE_VALGRIND
352.16731 +@@ -66,7 +69,8 @@
352.16732 + #define FORCE_FLUSH 0
352.16733 + #define FORCE_FULL_SYNC 0 /* https://bugs.freedesktop.org/show_bug.cgi?id=61628 */
352.16734 + 
352.16735 +-#define DEFAULT_TILING I915_TILING_X
352.16736 ++#define DEFAULT_PIXMAP_TILING I915_TILING_X
352.16737 ++#define DEFAULT_SCANOUT_TILING I915_TILING_X
352.16738 + 
352.16739 + #define USE_INPLACE 1
352.16740 + #define USE_SPANS 0 /* -1 force CPU, 1 force GPU */
352.16741 +@@ -115,6 +119,11 @@
352.16742 + #define RECTILINEAR	0x4
352.16743 + #define OVERWRITES	0x8
352.16744 + 
352.16745 ++#if XFONT2_CLIENT_FUNCS_VERSION >= 1
352.16746 ++#define AllocateFontPrivateIndex() xfont2_allocate_font_private_index()
352.16747 ++#define FontSetPrivate(font, idx, data) xfont2_font_set_private(font, idx, data)
352.16748 ++#endif
352.16749 ++
352.16750 + #if 0
352.16751 + static void __sna_fallback_flush(DrawablePtr d)
352.16752 + {
352.16753 +@@ -213,6 +222,7 @@ static GCOps sna_gc_ops__tmp;
352.16754 + static const GCFuncs sna_gc_funcs;
352.16755 + static const GCFuncs sna_gc_funcs__cpu;
352.16756 + 
352.16757 ++static void sna_shm_watch_flush(struct sna *sna, int enable);
352.16758 + static void
352.16759 + sna_poly_fill_rect__gpu(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect);
352.16760 + 
352.16761 +@@ -527,10 +537,10 @@ sna_pixmap_alloc_cpu(struct sna *sna,
352.16762 + 		DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__,
352.16763 + 		     pixmap->drawable.width, pixmap->drawable.height));
352.16764 + 
352.16765 +-		hint = 0;
352.16766 +-		if ((flags & MOVE_ASYNC_HINT) == 0 &&
352.16767 +-		    ((flags & MOVE_READ) == 0 || (priv->gpu_damage && !priv->clear && !sna->kgem.has_llc)))
352.16768 +-			hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
352.16769 ++		hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
352.16770 ++		if ((flags & MOVE_ASYNC_HINT) ||
352.16771 ++		    (priv->gpu_damage && !priv->clear && kgem_bo_is_busy(priv->gpu_bo) && sna->kgem.can_blt_cpu))
352.16772 ++			hint = 0;
352.16773 + 
352.16774 + 		priv->cpu_bo = kgem_create_cpu_2d(&sna->kgem,
352.16775 + 						  pixmap->drawable.width,
352.16776 +@@ -580,7 +590,7 @@ static void __sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
352.16777 + 		if (priv->cpu_bo->flush) {
352.16778 + 			assert(!priv->cpu_bo->reusable);
352.16779 + 			kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
352.16780 +-			sna_accel_watch_flush(sna, -1);
352.16781 ++			sna_shm_watch_flush(sna, -1);
352.16782 + 		}
352.16783 + 		kgem_bo_destroy(&sna->kgem, priv->cpu_bo);
352.16784 + 	} else if (!IS_STATIC_PTR(priv->ptr))
352.16785 +@@ -612,9 +622,9 @@ static bool sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv, bool a
352.16786 + 
352.16787 + static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
352.16788 + {
352.16789 +-#if DEFAULT_TILING == I915_TILING_NONE
352.16790 ++#if DEFAULT_PIXMAP_TILING == I915_TILING_NONE
352.16791 + 	return I915_TILING_NONE;
352.16792 +-#elif DEFAULT_TILING == I915_TILING_X
352.16793 ++#elif DEFAULT_PIXMAP_TILING == I915_TILING_X
352.16794 + 	return I915_TILING_X;
352.16795 + #else
352.16796 + 	/* Try to avoid hitting the Y-tiling GTT mapping bug on 855GM */
352.16797 +@@ -630,15 +640,6 @@ static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
352.16798 + 	     pixmap->drawable.height > sna->render.max_3d_size))
352.16799 + 		return I915_TILING_X;
352.16800 + 
352.16801 +-	if (sna_damage_is_all(&sna_pixmap(pixmap)->cpu_damage,
352.16802 +-			      pixmap->drawable.width,
352.16803 +-			      pixmap->drawable.height)) {
352.16804 +-		DBG(("%s: entire source is damaged, using Y-tiling\n",
352.16805 +-		     __FUNCTION__));
352.16806 +-		sna_damage_destroy(&sna_pixmap(priv)->gpu_damage);
352.16807 +-		return I915_TILING_Y;
352.16808 +-	}
352.16809 +-
352.16810 + 	return I915_TILING_Y;
352.16811 + #endif
352.16812 + }
352.16813 +@@ -666,6 +667,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
352.16814 + 	     __FUNCTION__, priv->gpu_bo->tiling, tiling,
352.16815 + 	     pixmap->drawable.width, pixmap->drawable.height));
352.16816 + 	assert(priv->gpu_damage == NULL || priv->gpu_bo);
352.16817 ++	assert(priv->gpu_bo->tiling != tiling);
352.16818 + 
352.16819 + 	if (priv->pinned) {
352.16820 + 		DBG(("%s: can't convert pinned bo\n", __FUNCTION__));
352.16821 +@@ -690,6 +692,12 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
352.16822 + 		return NULL;
352.16823 + 	}
352.16824 + 
352.16825 ++	if (bo->tiling == priv->gpu_bo->tiling) {
352.16826 ++		DBG(("%s: tiling request failed\n", __FUNCTION__));
352.16827 ++		kgem_bo_destroy(&sna->kgem, bo);
352.16828 ++		return NULL;
352.16829 ++	}
352.16830 ++
352.16831 + 	box.x1 = box.y1 = 0;
352.16832 + 	box.x2 = pixmap->drawable.width;
352.16833 + 	box.y2 = pixmap->drawable.height;
352.16834 +@@ -824,8 +832,8 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
352.16835 + 		datasize += adjust;
352.16836 + 	}
352.16837 + 
352.16838 +-	DBG(("%s: allocating pixmap %dx%d, depth=%d, size=%ld\n",
352.16839 +-	     __FUNCTION__, width, height, depth, (long)datasize));
352.16840 ++	DBG(("%s: allocating pixmap %dx%d, depth=%d/%d, size=%ld\n",
352.16841 ++	     __FUNCTION__, width, height, depth, bpp, (long)datasize));
352.16842 + 	pixmap = AllocatePixmap(screen, datasize);
352.16843 + 	if (!pixmap)
352.16844 + 		return NullPixmap;
352.16845 +@@ -878,7 +886,11 @@ __pop_freed_pixmap(struct sna *sna)
352.16846 + 	pixmap = sna->freed_pixmap;
352.16847 + 	sna->freed_pixmap = pixmap->devPrivate.ptr;
352.16848 + 
352.16849 ++	DBG(("%s: reusing freed pixmap=%ld header\n",
352.16850 ++	     __FUNCTION__, pixmap->drawable.serialNumber));
352.16851 ++
352.16852 + 	assert(pixmap->refcnt == 0);
352.16853 ++	assert(pixmap->devKind = 0xdeadbeef);
352.16854 + 	assert(sna_pixmap(pixmap));
352.16855 + 	assert(sna_pixmap(pixmap)->header);
352.16856 + 
352.16857 +@@ -990,7 +1002,7 @@ fallback:
352.16858 + 	}
352.16859 + 	priv->cpu_bo->pitch = pitch;
352.16860 + 	kgem_bo_mark_unreusable(priv->cpu_bo);
352.16861 +-	sna_accel_watch_flush(sna, 1);
352.16862 ++	sna_shm_watch_flush(sna, 1);
352.16863 + #ifdef DEBUG_MEMORY
352.16864 + 	sna->debug_memory.cpu_bo_allocs++;
352.16865 + 	sna->debug_memory.cpu_bo_bytes += kgem_bo_size(priv->cpu_bo);
352.16866 +@@ -1081,6 +1093,18 @@ sna_pixmap_create_scratch(ScreenPtr screen,
352.16867 + 	return pixmap;
352.16868 + }
352.16869 + 
352.16870 ++static unsigned small_copy(const RegionRec *region)
352.16871 ++{
352.16872 ++	if ((region->extents.x2 - region->extents.x1)*(region->extents.y2 - region->extents.y1) < 1024) {
352.16873 ++		DBG(("%s: region:%dx%d\n", __FUNCTION__,
352.16874 ++		     (region->extents.x2 - region->extents.x1),
352.16875 ++		     (region->extents.y2 - region->extents.y1)));
352.16876 ++		return COPY_SMALL;
352.16877 ++	}
352.16878 ++
352.16879 ++	return 0;
352.16880 ++}
352.16881 ++
352.16882 + #ifdef CREATE_PIXMAP_USAGE_SHARED
352.16883 + static Bool
352.16884 + sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
352.16885 +@@ -1124,7 +1148,7 @@ sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
352.16886 + 				    pixmap->drawable.height,
352.16887 + 				    pixmap->drawable.bitsPerPixel,
352.16888 + 				    I915_TILING_NONE,
352.16889 +-				    CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT);
352.16890 ++				    CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT);
352.16891 + 		if (bo == NULL) {
352.16892 + 			DBG(("%s: allocation failed\n", __FUNCTION__));
352.16893 + 			return FALSE;
352.16894 +@@ -1243,7 +1267,7 @@ sna_create_pixmap_shared(struct sna *sna, ScreenPtr screen,
352.16895 + 					      width, height,
352.16896 + 					      pixmap->drawable.bitsPerPixel,
352.16897 + 					      I915_TILING_NONE,
352.16898 +-					      CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT);
352.16899 ++					      CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT);
352.16900 + 		if (priv->gpu_bo == NULL) {
352.16901 + 			free(priv);
352.16902 + 			FreePixmap(pixmap);
352.16903 +@@ -1311,7 +1335,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
352.16904 + 
352.16905 + 	if (unlikely((sna->render.prefer_gpu & PREFER_GPU_RENDER) == 0))
352.16906 + 		flags &= ~KGEM_CAN_CREATE_GPU;
352.16907 +-	if (wedged(sna))
352.16908 ++	if (wedged(sna) && usage != SNA_CREATE_FB)
352.16909 + 		flags &= ~KGEM_CAN_CREATE_GTT;
352.16910 + 
352.16911 + 	DBG(("%s: usage=%d, flags=%x\n", __FUNCTION__, usage, flags));
352.16912 +@@ -1417,10 +1441,13 @@ static void __sna_free_pixmap(struct sna *sna,
352.16913 + 	__sna_pixmap_free_cpu(sna, priv);
352.16914 + 
352.16915 + 	if (priv->flush)
352.16916 +-		sna_accel_watch_flush(sna, -1);
352.16917 ++		sna_watch_flush(sna, -1);
352.16918 + 
352.16919 ++#if !NDEBUG
352.16920 ++	pixmap->devKind = 0xdeadbeef;
352.16921 ++#endif
352.16922 + 	if (priv->header) {
352.16923 +-		assert(pixmap->drawable.pScreen == sna->scrn->pScreen);
352.16924 ++		assert(pixmap->drawable.pScreen == to_screen_from_sna(sna));
352.16925 + 		assert(!priv->shm);
352.16926 + 		pixmap->devPrivate.ptr = sna->freed_pixmap;
352.16927 + 		sna->freed_pixmap = pixmap;
352.16928 +@@ -1485,7 +1512,7 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
352.16929 + 	if (priv->shm && kgem_bo_is_busy(priv->cpu_bo)) {
352.16930 + 		DBG(("%s: deferring release of active SHM pixmap=%ld\n",
352.16931 + 		     __FUNCTION__, pixmap->drawable.serialNumber));
352.16932 +-		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.16933 ++		add_shm_flush(sna, priv);
352.16934 + 		kgem_bo_submit(&sna->kgem, priv->cpu_bo); /* XXX ShmDetach */
352.16935 + 	} else
352.16936 + 		__sna_free_pixmap(sna, pixmap, priv);
352.16937 +@@ -1529,7 +1556,7 @@ static inline bool has_coherent_ptr(struct sna *sna, struct sna_pixmap *priv, un
352.16938 + 		if (!priv->cpu_bo)
352.16939 + 			return true;
352.16940 + 
352.16941 +-		assert(!priv->cpu_bo->needs_flush);
352.16942 ++		assert(!priv->cpu_bo->needs_flush || (flags & MOVE_WRITE) == 0);
352.16943 + 		assert(priv->pixmap->devKind == priv->cpu_bo->pitch);
352.16944 + 		return priv->pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu);
352.16945 + 	}
352.16946 +@@ -1557,6 +1584,11 @@ static inline bool has_coherent_ptr(struct sna *sna, struct sna_pixmap *priv, un
352.16947 + 		return true;
352.16948 + 	}
352.16949 + 
352.16950 ++	if (priv->pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__wc)) {
352.16951 ++		assert(priv->mapped == MAPPED_GTT);
352.16952 ++		return true;
352.16953 ++	}
352.16954 ++
352.16955 + 	return false;
352.16956 + }
352.16957 + 
352.16958 +@@ -1577,6 +1609,16 @@ static inline bool pixmap_inplace(struct sna *sna,
352.16959 + 		return false;
352.16960 + 
352.16961 + 	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) {
352.16962 ++		if (priv->clear) {
352.16963 ++			DBG(("%s: no, clear GPU bo is busy\n", __FUNCTION__));
352.16964 ++			return false;
352.16965 ++		}
352.16966 ++
352.16967 ++		if (flags & MOVE_ASYNC_HINT) {
352.16968 ++			DBG(("%s: no, async hint and GPU bo is busy\n", __FUNCTION__));
352.16969 ++			return false;
352.16970 ++		}
352.16971 ++
352.16972 + 		if ((flags & (MOVE_WRITE | MOVE_READ)) == (MOVE_WRITE | MOVE_READ)) {
352.16973 + 			DBG(("%s: no, GPU bo is busy\n", __FUNCTION__));
352.16974 + 			return false;
352.16975 +@@ -1624,7 +1666,7 @@ static bool sna_pixmap_alloc_gpu(struct sna *sna,
352.16976 + 	if (pixmap->usage_hint == SNA_CREATE_FB && (sna->flags & SNA_LINEAR_FB) == 0) {
352.16977 + 		flags |= CREATE_SCANOUT;
352.16978 + 		tiling = kgem_choose_tiling(&sna->kgem,
352.16979 +-					    -I915_TILING_X,
352.16980 ++					    -DEFAULT_SCANOUT_TILING,
352.16981 + 					    pixmap->drawable.width,
352.16982 + 					    pixmap->drawable.height,
352.16983 + 					    pixmap->drawable.bitsPerPixel);
352.16984 +@@ -1861,7 +1903,9 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
352.16985 + 	assert(priv->gpu_bo == cow->bo);
352.16986 + 	assert(cow->refcnt);
352.16987 + 
352.16988 +-	if (flags && (flags & MOVE_WRITE) == 0 && IS_COW_OWNER(priv->cow))
352.16989 ++	if (flags && /* flags == 0 => force decouple */
352.16990 ++	    (flags & MOVE_WRITE) == 0 &&
352.16991 ++	    (((flags & __MOVE_FORCE) == 0) || IS_COW_OWNER(priv->cow)))
352.16992 + 		return true;
352.16993 + 
352.16994 + 	if (!IS_COW_OWNER(priv->cow))
352.16995 +@@ -1933,7 +1977,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
352.16996 + 			box.y2 = pixmap->drawable.height;
352.16997 + 
352.16998 + 			if (flags & __MOVE_PRIME) {
352.16999 +-				create = CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT;
352.17000 ++				create = CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT;
352.17001 + 				tiling = I915_TILING_NONE;
352.17002 + 			} else {
352.17003 + 				create = 0;
352.17004 +@@ -2021,6 +2065,10 @@ sna_pixmap_make_cow(struct sna *sna,
352.17005 + 		     cow->bo->handle));
352.17006 + 
352.17007 + 		src_priv->cow = MAKE_COW_OWNER(cow);
352.17008 ++		if (src_priv->flush & FLUSH_WRITE) {
352.17009 ++			assert(!src_priv->shm);
352.17010 ++			sna_add_flush_pixmap(sna, src_priv, src_priv->gpu_bo);
352.17011 ++		}
352.17012 + 	}
352.17013 + 
352.17014 + 	if (cow == COW(dst_priv->cow)) {
352.17015 +@@ -2267,6 +2315,7 @@ skip_inplace_map:
352.17016 + 	    (flags & MOVE_WRITE ? (void *)priv->gpu_bo : (void *)priv->gpu_damage) && priv->cpu_damage == NULL &&
352.17017 + 	    priv->gpu_bo->tiling == I915_TILING_NONE &&
352.17018 + 	    (flags & MOVE_READ || kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, flags & MOVE_WRITE)) &&
352.17019 ++	    (!priv->clear || !kgem_bo_is_busy(priv->gpu_bo)) &&
352.17020 + 	    ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 ||
352.17021 + 	     (!priv->cow && !priv->move_to_gpu && !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)))) {
352.17022 + 		void *ptr;
352.17023 +@@ -2330,7 +2379,9 @@ skip_inplace_map:
352.17024 + 			     pixmap->devKind, pixmap->devKind * pixmap->drawable.height));
352.17025 + 
352.17026 + 			if (priv->cpu_bo) {
352.17027 ++				kgem_bo_undo(&sna->kgem, priv->cpu_bo);
352.17028 + 				if ((flags & MOVE_ASYNC_HINT || priv->cpu_bo->exec) &&
352.17029 ++				    sna->kgem.can_blt_cpu &&
352.17030 + 				    sna->render.fill_one(sna,
352.17031 + 							  pixmap, priv->cpu_bo, priv->clear_color,
352.17032 + 							  0, 0,
352.17033 +@@ -2344,21 +2395,26 @@ skip_inplace_map:
352.17034 + 				assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
352.17035 + 			}
352.17036 + 
352.17037 +-			assert(pixmap->devKind);
352.17038 +-			if (priv->clear_color == 0 ||
352.17039 +-			    pixmap->drawable.bitsPerPixel == 8 ||
352.17040 +-			    priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
352.17041 +-				memset(pixmap->devPrivate.ptr, priv->clear_color,
352.17042 +-				       (size_t)pixmap->devKind * pixmap->drawable.height);
352.17043 +-			} else {
352.17044 +-				pixman_fill(pixmap->devPrivate.ptr,
352.17045 +-					    pixmap->devKind/sizeof(uint32_t),
352.17046 +-					    pixmap->drawable.bitsPerPixel,
352.17047 +-					    0, 0,
352.17048 +-					    pixmap->drawable.width,
352.17049 +-					    pixmap->drawable.height,
352.17050 +-					    priv->clear_color);
352.17051 +-			}
352.17052 ++			if (sigtrap_get() == 0) {
352.17053 ++				assert(pixmap->devKind);
352.17054 ++				sigtrap_assert_active();
352.17055 ++				if (priv->clear_color == 0 ||
352.17056 ++				    pixmap->drawable.bitsPerPixel == 8 ||
352.17057 ++				    priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
352.17058 ++					memset(pixmap->devPrivate.ptr, priv->clear_color,
352.17059 ++					       (size_t)pixmap->devKind * pixmap->drawable.height);
352.17060 ++				} else {
352.17061 ++					pixman_fill(pixmap->devPrivate.ptr,
352.17062 ++						    pixmap->devKind/sizeof(uint32_t),
352.17063 ++						    pixmap->drawable.bitsPerPixel,
352.17064 ++						    0, 0,
352.17065 ++						    pixmap->drawable.width,
352.17066 ++						    pixmap->drawable.height,
352.17067 ++						    priv->clear_color);
352.17068 ++				}
352.17069 ++				sigtrap_put();
352.17070 ++			} else
352.17071 ++				return false;
352.17072 + 
352.17073 + clear_done:
352.17074 + 			sna_damage_all(&priv->cpu_damage, pixmap);
352.17075 +@@ -2414,6 +2470,10 @@ done:
352.17076 + 			DBG(("%s: discarding idle GPU bo\n", __FUNCTION__));
352.17077 + 			sna_pixmap_free_gpu(sna, priv);
352.17078 + 		}
352.17079 ++		if (priv->flush) {
352.17080 ++			assert(!priv->shm);
352.17081 ++			sna_add_flush_pixmap(sna, priv, priv->gpu_bo);
352.17082 ++		}
352.17083 + 		priv->source_count = SOURCE_BIAS;
352.17084 + 	}
352.17085 + 
352.17086 +@@ -2531,6 +2591,9 @@ static bool cpu_clear_boxes(struct sna *sna,
352.17087 + {
352.17088 + 	struct sna_fill_op fill;
352.17089 + 
352.17090 ++	if (!sna->kgem.can_blt_cpu)
352.17091 ++		return false;
352.17092 ++
352.17093 + 	if (!sna_fill_init_blt(&fill, sna,
352.17094 + 			       pixmap, priv->cpu_bo,
352.17095 + 			       GXcopy, priv->clear_color,
352.17096 +@@ -2659,6 +2722,10 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
352.17097 + 					}
352.17098 + 				}
352.17099 + 				sna_damage_add_to_pixmap(&priv->cpu_damage, region, pixmap);
352.17100 ++				if (priv->flush) {
352.17101 ++					assert(!priv->shm);
352.17102 ++					sna_add_flush_pixmap(sna, priv, priv->gpu_bo);
352.17103 ++				}
352.17104 + 
352.17105 + 				if (dx | dy)
352.17106 + 					RegionTranslate(region, -dx, -dy);
352.17107 +@@ -2904,17 +2971,22 @@ move_to_cpu:
352.17108 + 			assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
352.17109 + 		}
352.17110 + 
352.17111 +-		assert(pixmap->devKind);
352.17112 +-		do {
352.17113 +-			pixman_fill(pixmap->devPrivate.ptr,
352.17114 +-				    pixmap->devKind/sizeof(uint32_t),
352.17115 +-				    pixmap->drawable.bitsPerPixel,
352.17116 +-				    box->x1, box->y1,
352.17117 +-				    box->x2 - box->x1,
352.17118 +-				    box->y2 - box->y1,
352.17119 +-				    priv->clear_color);
352.17120 +-			box++;
352.17121 +-		} while (--n);
352.17122 ++		if (sigtrap_get() == 0) {
352.17123 ++			assert(pixmap->devKind);
352.17124 ++			sigtrap_assert_active();
352.17125 ++			do {
352.17126 ++				pixman_fill(pixmap->devPrivate.ptr,
352.17127 ++					    pixmap->devKind/sizeof(uint32_t),
352.17128 ++					    pixmap->drawable.bitsPerPixel,
352.17129 ++					    box->x1, box->y1,
352.17130 ++					    box->x2 - box->x1,
352.17131 ++					    box->y2 - box->y1,
352.17132 ++					    priv->clear_color);
352.17133 ++				box++;
352.17134 ++			} while (--n);
352.17135 ++			sigtrap_put();
352.17136 ++		} else
352.17137 ++			return false;
352.17138 + 
352.17139 + clear_done:
352.17140 + 		if (flags & MOVE_WRITE ||
352.17141 +@@ -3209,13 +3281,14 @@ __sna_pixmap_for_gpu(struct sna *sna, PixmapPtr pixmap, unsigned flags)
352.17142 + {
352.17143 + 	struct sna_pixmap *priv;
352.17144 + 
352.17145 ++	assert(flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE));
352.17146 + 	if ((flags & __MOVE_FORCE) == 0 && wedged(sna))
352.17147 + 		return NULL;
352.17148 + 
352.17149 + 	priv = sna_pixmap(pixmap);
352.17150 + 	if (priv == NULL) {
352.17151 + 		DBG(("%s: not attached\n", __FUNCTION__));
352.17152 +-		if ((flags & __MOVE_DRI) == 0)
352.17153 ++		if ((flags & (__MOVE_DRI | __MOVE_SCANOUT)) == 0)
352.17154 + 			return NULL;
352.17155 + 
352.17156 + 		if (pixmap->usage_hint == -1) {
352.17157 +@@ -3238,6 +3311,44 @@ __sna_pixmap_for_gpu(struct sna *sna, PixmapPtr pixmap, unsigned flags)
352.17158 + 	return priv;
352.17159 + }
352.17160 + 
352.17161 ++inline static void sna_pixmap_unclean(struct sna *sna,
352.17162 ++				      struct sna_pixmap *priv,
352.17163 ++				      unsigned flags)
352.17164 ++{
352.17165 ++	struct drm_i915_gem_busy busy;
352.17166 ++
352.17167 ++	assert(DAMAGE_IS_ALL(priv->gpu_damage));
352.17168 ++	assert(priv->gpu_bo);
352.17169 ++	assert(priv->gpu_bo->proxy == NULL);
352.17170 ++	assert_pixmap_map(priv->pixmap, priv);
352.17171 ++
352.17172 ++	sna_damage_destroy(&priv->cpu_damage);
352.17173 ++	list_del(&priv->flush_list);
352.17174 ++
352.17175 ++	if (flags & (__MOVE_DRI | __MOVE_SCANOUT))
352.17176 ++		return;
352.17177 ++
352.17178 ++	if (!priv->flush || priv->gpu_bo->exec)
352.17179 ++		return;
352.17180 ++
352.17181 ++	busy.handle = priv->gpu_bo->handle;
352.17182 ++	busy.busy = 0;
352.17183 ++	ioctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
352.17184 ++
352.17185 ++	DBG(("%s(pixmap=%ld): cleaning foreign bo handle=%u, busy=%x [ring=%d]\n",
352.17186 ++	     __FUNCTION__,
352.17187 ++	     priv->pixmap->drawable.serialNumber,
352.17188 ++	     busy.handle, busy.busy, !!(busy.busy & (0xfffe << 16))));
352.17189 ++
352.17190 ++	if (busy.busy) {
352.17191 ++		unsigned mode = KGEM_RENDER;
352.17192 ++		if (busy.busy & (0xfffe << 16))
352.17193 ++			mode = KGEM_BLT;
352.17194 ++		kgem_bo_mark_busy(&sna->kgem, priv->gpu_bo, mode);
352.17195 ++	} else
352.17196 ++		__kgem_bo_clear_busy(priv->gpu_bo);
352.17197 ++}
352.17198 ++
352.17199 + struct sna_pixmap *
352.17200 + sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags)
352.17201 + {
352.17202 +@@ -3287,12 +3398,14 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
352.17203 + 	if (priv->cow) {
352.17204 + 		unsigned cow = flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE);
352.17205 + 
352.17206 ++		assert(cow);
352.17207 ++
352.17208 + 		if ((flags & MOVE_READ) == 0) {
352.17209 + 			if (priv->gpu_damage) {
352.17210 + 				r.extents = *box;
352.17211 + 				r.data = NULL;
352.17212 + 				if (!region_subsumes_damage(&r, priv->gpu_damage))
352.17213 +-					cow |= MOVE_READ;
352.17214 ++					cow |= MOVE_READ | __MOVE_FORCE;
352.17215 + 			}
352.17216 + 		} else {
352.17217 + 			if (priv->cpu_damage) {
352.17218 +@@ -3303,22 +3416,18 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
352.17219 + 			}
352.17220 + 		}
352.17221 + 
352.17222 +-		if (cow) {
352.17223 +-			if (!sna_pixmap_undo_cow(sna, priv, cow))
352.17224 +-				return NULL;
352.17225 ++		if (!sna_pixmap_undo_cow(sna, priv, cow))
352.17226 ++			return NULL;
352.17227 + 
352.17228 +-			if (priv->gpu_bo == NULL)
352.17229 +-				sna_damage_destroy(&priv->gpu_damage);
352.17230 +-		}
352.17231 ++		if (priv->gpu_bo == NULL)
352.17232 ++			sna_damage_destroy(&priv->gpu_damage);
352.17233 + 	}
352.17234 + 
352.17235 + 	if (sna_damage_is_all(&priv->gpu_damage,
352.17236 + 			      pixmap->drawable.width,
352.17237 + 			      pixmap->drawable.height)) {
352.17238 +-		assert(priv->gpu_bo);
352.17239 +-		assert(priv->gpu_bo->proxy == NULL);
352.17240 +-		sna_damage_destroy(&priv->cpu_damage);
352.17241 +-		list_del(&priv->flush_list);
352.17242 ++		DBG(("%s: already all-damaged\n", __FUNCTION__));
352.17243 ++		sna_pixmap_unclean(sna, priv, flags);
352.17244 + 		goto done;
352.17245 + 	}
352.17246 + 
352.17247 +@@ -3360,10 +3469,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
352.17248 + 		return priv;
352.17249 + 	}
352.17250 + 
352.17251 +-	if (priv->shm) {
352.17252 +-		assert(!priv->flush);
352.17253 +-		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.17254 +-	}
352.17255 ++	add_shm_flush(sna, priv);
352.17256 + 
352.17257 + 	assert(priv->cpu_damage);
352.17258 + 	region_set(&r, box);
352.17259 +@@ -3527,7 +3633,8 @@ sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
352.17260 + 	}
352.17261 + 
352.17262 + 	if (priv->cow) {
352.17263 +-		unsigned cow = MOVE_WRITE | MOVE_READ;
352.17264 ++		unsigned cow = MOVE_WRITE | MOVE_READ | __MOVE_FORCE;
352.17265 ++		assert(cow);
352.17266 + 
352.17267 + 		if (flags & IGNORE_DAMAGE) {
352.17268 + 			if (priv->gpu_damage) {
352.17269 +@@ -3717,8 +3824,11 @@ create_gpu_bo:
352.17270 + 				else
352.17271 + 					move = MOVE_WRITE | MOVE_READ | MOVE_ASYNC_HINT;
352.17272 + 
352.17273 +-				if (sna_pixmap_move_to_gpu(pixmap, move))
352.17274 ++				if (sna_pixmap_move_to_gpu(pixmap, move)) {
352.17275 ++					sna_damage_all(&priv->gpu_damage,
352.17276 ++						       pixmap);
352.17277 + 					goto use_gpu_bo;
352.17278 ++				}
352.17279 + 			}
352.17280 + 
352.17281 + 			if (DAMAGE_IS_ALL(priv->gpu_damage) ||
352.17282 +@@ -3934,26 +4044,28 @@ prefer_gpu_bo:
352.17283 + 			goto move_to_gpu;
352.17284 + 		}
352.17285 + 
352.17286 +-		if ((priv->cpu_damage == NULL || flags & IGNORE_DAMAGE)) {
352.17287 +-			if (priv->gpu_bo && priv->gpu_bo->tiling) {
352.17288 +-				DBG(("%s: prefer to use GPU bo for rendering large pixmaps\n", __FUNCTION__));
352.17289 +-				goto prefer_gpu_bo;
352.17290 ++		if (!priv->shm) {
352.17291 ++			if ((priv->cpu_damage == NULL || flags & IGNORE_DAMAGE)) {
352.17292 ++				if (priv->gpu_bo && priv->gpu_bo->tiling) {
352.17293 ++					DBG(("%s: prefer to use GPU bo for rendering large pixmaps\n", __FUNCTION__));
352.17294 ++					goto prefer_gpu_bo;
352.17295 ++				}
352.17296 ++
352.17297 ++				if (priv->cpu_bo->pitch >= 4096) {
352.17298 ++					DBG(("%s: prefer to use GPU bo for rendering wide pixmaps\n", __FUNCTION__));
352.17299 ++					goto prefer_gpu_bo;
352.17300 ++				}
352.17301 + 			}
352.17302 + 
352.17303 +-			if (priv->cpu_bo->pitch >= 4096) {
352.17304 +-				DBG(("%s: prefer to use GPU bo for rendering wide pixmaps\n", __FUNCTION__));
352.17305 ++			if ((flags & IGNORE_DAMAGE) == 0 && priv->cpu_bo->snoop) {
352.17306 ++				DBG(("%s: prefer to use GPU bo for reading from snooped target bo\n", __FUNCTION__));
352.17307 + 				goto prefer_gpu_bo;
352.17308 + 			}
352.17309 +-		}
352.17310 +-
352.17311 +-		if ((flags & IGNORE_DAMAGE) == 0 && priv->cpu_bo->snoop) {
352.17312 +-			DBG(("%s: prefer to use GPU bo for reading from snooped target bo\n", __FUNCTION__));
352.17313 +-			goto prefer_gpu_bo;
352.17314 +-		}
352.17315 + 
352.17316 +-		if (!sna->kgem.can_blt_cpu) {
352.17317 +-			DBG(("%s: can't render to CPU bo, try to use GPU bo\n", __FUNCTION__));
352.17318 +-			goto prefer_gpu_bo;
352.17319 ++			if (!sna->kgem.can_blt_cpu) {
352.17320 ++				DBG(("%s: can't render to CPU bo, try to use GPU bo\n", __FUNCTION__));
352.17321 ++				goto prefer_gpu_bo;
352.17322 ++			}
352.17323 + 		}
352.17324 + 	}
352.17325 + 
352.17326 +@@ -3967,9 +4079,7 @@ prefer_gpu_bo:
352.17327 + 	}
352.17328 + 
352.17329 + 	if (priv->shm) {
352.17330 +-		assert(!priv->flush);
352.17331 +-		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.17332 +-
352.17333 ++		add_shm_flush(sna, priv);
352.17334 + 		/* As we may have flushed and retired,, recheck for busy bo */
352.17335 + 		if ((flags & FORCE_GPU) == 0 && !kgem_bo_is_busy(priv->cpu_bo))
352.17336 + 			return NULL;
352.17337 +@@ -4019,7 +4129,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
352.17338 + 	assert(width);
352.17339 + 	assert(height);
352.17340 + 
352.17341 +-	if (depth == 1)
352.17342 ++	if (depth < 8)
352.17343 + 		return create_pixmap(sna, screen, width, height, depth,
352.17344 + 				     CREATE_PIXMAP_USAGE_SCRATCH);
352.17345 + 
352.17346 +@@ -4121,27 +4231,21 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
352.17347 + 
352.17348 + 	if (priv->cow) {
352.17349 + 		unsigned cow = flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE);
352.17350 ++		assert(cow);
352.17351 + 		if (flags & MOVE_READ && priv->cpu_damage)
352.17352 + 			cow |= MOVE_WRITE;
352.17353 +-		if (cow) {
352.17354 +-			if (!sna_pixmap_undo_cow(sna, priv, cow))
352.17355 +-				return NULL;
352.17356 ++		if (!sna_pixmap_undo_cow(sna, priv, cow))
352.17357 ++			return NULL;
352.17358 + 
352.17359 +-			if (priv->gpu_bo == NULL)
352.17360 +-				sna_damage_destroy(&priv->gpu_damage);
352.17361 +-		}
352.17362 ++		if (priv->gpu_bo == NULL)
352.17363 ++			sna_damage_destroy(&priv->gpu_damage);
352.17364 + 	}
352.17365 + 
352.17366 + 	if (sna_damage_is_all(&priv->gpu_damage,
352.17367 + 			      pixmap->drawable.width,
352.17368 + 			      pixmap->drawable.height)) {
352.17369 + 		DBG(("%s: already all-damaged\n", __FUNCTION__));
352.17370 +-		assert(DAMAGE_IS_ALL(priv->gpu_damage));
352.17371 +-		assert(priv->gpu_bo);
352.17372 +-		assert(priv->gpu_bo->proxy == NULL);
352.17373 +-		assert_pixmap_map(pixmap, priv);
352.17374 +-		sna_damage_destroy(&priv->cpu_damage);
352.17375 +-		list_del(&priv->flush_list);
352.17376 ++		sna_pixmap_unclean(sna, priv, flags);
352.17377 + 		goto active;
352.17378 + 	}
352.17379 + 
352.17380 +@@ -4206,7 +4310,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
352.17381 + 				if (flags & MOVE_INPLACE_HINT || (priv->cpu_damage && priv->cpu_bo == NULL))
352.17382 + 					create = CREATE_GTT_MAP | CREATE_INACTIVE;
352.17383 + 				if (flags & __MOVE_PRIME)
352.17384 +-					create |= CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT;
352.17385 ++					create |= CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT;
352.17386 + 
352.17387 + 				sna_pixmap_alloc_gpu(sna, pixmap, priv, create);
352.17388 + 			}
352.17389 +@@ -4282,10 +4386,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
352.17390 + 		goto done;
352.17391 + 	}
352.17392 + 
352.17393 +-	if (priv->shm) {
352.17394 +-		assert(!priv->flush);
352.17395 +-		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.17396 +-	}
352.17397 ++	add_shm_flush(sna, priv);
352.17398 + 
352.17399 + 	n = sna_damage_get_boxes(priv->cpu_damage, &box);
352.17400 + 	assert(n);
352.17401 +@@ -4534,7 +4635,7 @@ static inline bool box32_trim_and_translate(Box32Rec *box, DrawablePtr d, GCPtr
352.17402 + 	return box32_clip(box, gc);
352.17403 + }
352.17404 + 
352.17405 +-static inline void box_add_pt(BoxPtr box, int16_t x, int16_t y)
352.17406 ++static inline void box_add_xy(BoxPtr box, int16_t x, int16_t y)
352.17407 + {
352.17408 + 	if (box->x1 > x)
352.17409 + 		box->x1 = x;
352.17410 +@@ -4547,6 +4648,11 @@ static inline void box_add_pt(BoxPtr box, int16_t x, int16_t y)
352.17411 + 		box->y2 = y;
352.17412 + }
352.17413 + 
352.17414 ++static inline void box_add_pt(BoxPtr box, const DDXPointRec *pt)
352.17415 ++{
352.17416 ++	box_add_xy(box, pt->x, pt->y);
352.17417 ++}
352.17418 ++
352.17419 + static inline bool box32_to_box16(const Box32Rec *b32, BoxRec *b16)
352.17420 + {
352.17421 + 	b16->x1 = b32->x1;
352.17422 +@@ -4864,6 +4970,7 @@ try_upload__inplace(PixmapPtr pixmap, RegionRec *region,
352.17423 + 	pixmap->devPrivate.ptr = dst;
352.17424 + 	pixmap->devKind = priv->gpu_bo->pitch;
352.17425 + 	priv->mapped = dst == MAP(priv->gpu_bo->map__cpu) ? MAPPED_CPU : MAPPED_GTT;
352.17426 ++	priv->cpu &= priv->mapped == MAPPED_CPU;
352.17427 + 	assert(has_coherent_ptr(sna, priv, MOVE_WRITE));
352.17428 + 
352.17429 + 	box = region_rects(region);
352.17430 +@@ -4923,8 +5030,7 @@ done:
352.17431 + 			sna_damage_all(&priv->gpu_damage, pixmap);
352.17432 + 		}
352.17433 + 
352.17434 +-		if (priv->shm)
352.17435 +-			sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.17436 ++		add_shm_flush(sna, priv);
352.17437 + 	}
352.17438 + 
352.17439 + 	assert(!priv->clear);
352.17440 +@@ -5172,6 +5278,16 @@ static inline uint8_t blt_depth(int depth)
352.17441 + 	}
352.17442 + }
352.17443 + 
352.17444 ++inline static void blt_done(struct sna *sna)
352.17445 ++{
352.17446 ++	sna->blt_state.fill_bo = 0;
352.17447 ++	if (sna->kgem.nbatch && __kgem_ring_empty(&sna->kgem)) {
352.17448 ++		DBG(("%s: flushing BLT operation on empty ring\n",
352.17449 ++		     __FUNCTION__));
352.17450 ++		_kgem_submit(&sna->kgem);
352.17451 ++	}
352.17452 ++}
352.17453 ++
352.17454 + static bool
352.17455 + sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17456 + 		     int x, int y, int w, int  h, char *bits)
352.17457 +@@ -5217,6 +5333,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17458 + 
352.17459 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.17460 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.17461 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.17462 + 
352.17463 + 	/* Region is pre-clipped and translated into pixmap space */
352.17464 + 	box = region_rects(region);
352.17465 +@@ -5238,6 +5355,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17466 + 				return false;
352.17467 + 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.17468 + 		}
352.17469 ++		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.17470 + 
352.17471 + 		upload = kgem_create_buffer(&sna->kgem,
352.17472 + 					    bstride*bh,
352.17473 +@@ -5331,7 +5449,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17474 + 		box++;
352.17475 + 	} while (--n);
352.17476 + 
352.17477 +-	sna->blt_state.fill_bo = 0;
352.17478 ++	blt_done(sna);
352.17479 + 	return true;
352.17480 + }
352.17481 + 
352.17482 +@@ -5381,6 +5499,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17483 + 
352.17484 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.17485 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.17486 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.17487 + 
352.17488 + 	skip = h * BitmapBytePad(w + left);
352.17489 + 	for (i = 1 << (gc->depth-1); i; i >>= 1, bits += skip) {
352.17490 +@@ -5408,6 +5527,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17491 + 					return false;
352.17492 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.17493 + 			}
352.17494 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.17495 + 
352.17496 + 			upload = kgem_create_buffer(&sna->kgem,
352.17497 + 						    bstride*bh,
352.17498 +@@ -5509,7 +5629,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
352.17499 + 		} while (--n);
352.17500 + 	}
352.17501 + 
352.17502 +-	sna->blt_state.fill_bo = 0;
352.17503 ++	blt_done(sna);
352.17504 + 	return true;
352.17505 + }
352.17506 + 
352.17507 +@@ -5837,7 +5957,7 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
352.17508 + 		if (!sna->render.copy_boxes(sna, alu,
352.17509 + 					    &pixmap->drawable, priv->gpu_bo, sx, sy,
352.17510 + 					    &pixmap->drawable, priv->gpu_bo, tx, ty,
352.17511 +-					    box, n, 0)) {
352.17512 ++					    box, n, small_copy(region))) {
352.17513 + 			DBG(("%s: fallback - accelerated copy boxes failed\n",
352.17514 + 			     __FUNCTION__));
352.17515 + 			goto fallback;
352.17516 +@@ -6098,6 +6218,9 @@ sna_copy_boxes__inplace(struct sna *sna, RegionPtr region, int alu,
352.17517 + 
352.17518 + 	kgem_bo_sync__cpu_full(&sna->kgem, src_priv->gpu_bo, FORCE_FULL_SYNC);
352.17519 + 
352.17520 ++	if (sigtrap_get())
352.17521 ++		return false;
352.17522 ++
352.17523 + 	box = region_rects(region);
352.17524 + 	n = region_num_rects(region);
352.17525 + 	if (src_priv->gpu_bo->tiling) {
352.17526 +@@ -6137,6 +6260,8 @@ sna_copy_boxes__inplace(struct sna *sna, RegionPtr region, int alu,
352.17527 + 		}
352.17528 + 	}
352.17529 + 
352.17530 ++	sigtrap_put();
352.17531 ++
352.17532 + 	return true;
352.17533 + 
352.17534 + upload_inplace:
352.17535 +@@ -6234,6 +6359,9 @@ upload_inplace:
352.17536 + 
352.17537 + 	assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
352.17538 + 
352.17539 ++	if (sigtrap_get())
352.17540 ++		return false;
352.17541 ++
352.17542 + 	box = region_rects(region);
352.17543 + 	n = region_num_rects(region);
352.17544 + 	if (dst_priv->gpu_bo->tiling) {
352.17545 +@@ -6265,15 +6393,19 @@ upload_inplace:
352.17546 + 		} while (--n);
352.17547 + 
352.17548 + 		if (!dst_priv->shm) {
352.17549 +-			assert(ptr == MAP(dst_priv->gpu_bo->map__cpu));
352.17550 + 			dst_pixmap->devPrivate.ptr = ptr;
352.17551 + 			dst_pixmap->devKind = dst_priv->gpu_bo->pitch;
352.17552 +-			dst_priv->mapped = MAPPED_CPU;
352.17553 ++			if (ptr == MAP(dst_priv->gpu_bo->map__cpu)) {
352.17554 ++				dst_priv->mapped = MAPPED_CPU;
352.17555 ++				dst_priv->cpu = true;
352.17556 ++			} else
352.17557 ++				dst_priv->mapped = MAPPED_GTT;
352.17558 + 			assert_pixmap_map(dst_pixmap, dst_priv);
352.17559 +-			dst_priv->cpu = true;
352.17560 + 		}
352.17561 + 	}
352.17562 + 
352.17563 ++	sigtrap_put();
352.17564 ++
352.17565 + 	return true;
352.17566 + }
352.17567 + 
352.17568 +@@ -6326,6 +6458,16 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
352.17569 + 
352.17570 + 	assert(region_num_rects(region));
352.17571 + 
352.17572 ++	if (src_priv &&
352.17573 ++	    src_priv->gpu_bo == NULL &&
352.17574 ++	    src_priv->cpu_bo == NULL &&
352.17575 ++	    src_priv->ptr == NULL) {
352.17576 ++		/* Rare but still happens, nothing to copy */
352.17577 ++		DBG(("%s: src pixmap=%ld is empty\n",
352.17578 ++		     __FUNCTION__, src_pixmap->drawable.serialNumber));
352.17579 ++		return;
352.17580 ++	}
352.17581 ++
352.17582 + 	if (src_pixmap == dst_pixmap)
352.17583 + 		return sna_self_copy_boxes(src, dst, gc,
352.17584 + 					   region, dx, dy,
352.17585 +@@ -6491,15 +6633,14 @@ discard_cow:
352.17586 + 					sna_damage_all(&dst_priv->gpu_damage, dst_pixmap);
352.17587 + 					sna_damage_destroy(&dst_priv->cpu_damage);
352.17588 + 					list_del(&dst_priv->flush_list);
352.17589 +-					if (dst_priv->shm)
352.17590 +-						sna_add_flush_pixmap(sna, dst_priv, dst_priv->cpu_bo);
352.17591 ++					add_shm_flush(sna, dst_priv);
352.17592 + 					return;
352.17593 + 				}
352.17594 + 			}
352.17595 + 			if (!sna->render.copy_boxes(sna, alu,
352.17596 + 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
352.17597 + 						    &dst_pixmap->drawable, bo, 0, 0,
352.17598 +-						    box, n, 0)) {
352.17599 ++						    box, n, small_copy(region))) {
352.17600 + 				DBG(("%s: fallback - accelerated copy boxes failed\n",
352.17601 + 				     __FUNCTION__));
352.17602 + 				goto fallback;
352.17603 +@@ -6536,7 +6677,7 @@ discard_cow:
352.17604 + 			if (!sna->render.copy_boxes(sna, alu,
352.17605 + 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
352.17606 + 						    &dst_pixmap->drawable, bo, 0, 0,
352.17607 +-						    box, n, 0)) {
352.17608 ++						    box, n, small_copy(region))) {
352.17609 + 				DBG(("%s: fallback - accelerated copy boxes failed\n",
352.17610 + 				     __FUNCTION__));
352.17611 + 				goto fallback;
352.17612 +@@ -6571,15 +6712,12 @@ discard_cow:
352.17613 + 			if (replaces && UNDO)
352.17614 + 				kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
352.17615 + 
352.17616 +-			if (src_priv->shm) {
352.17617 +-				assert(!src_priv->flush);
352.17618 +-				sna_add_flush_pixmap(sna, src_priv, src_priv->cpu_bo);
352.17619 +-			}
352.17620 ++			add_shm_flush(sna, src_priv);
352.17621 + 
352.17622 + 			if (!sna->render.copy_boxes(sna, alu,
352.17623 + 						    &src_pixmap->drawable, src_priv->cpu_bo, src_dx, src_dy,
352.17624 + 						    &dst_pixmap->drawable, bo, 0, 0,
352.17625 +-						    box, n, src_priv->shm ? COPY_LAST : 0)) {
352.17626 ++						    box, n, small_copy(region) | (src_priv->shm ? COPY_LAST : 0))) {
352.17627 + 				DBG(("%s: fallback - accelerated copy boxes failed\n",
352.17628 + 				     __FUNCTION__));
352.17629 + 				goto fallback;
352.17630 +@@ -6631,8 +6769,7 @@ discard_cow:
352.17631 + 				ok = sna->render.copy_boxes(sna, alu,
352.17632 + 							    &src_pixmap->drawable, src_bo, src_dx, src_dy,
352.17633 + 							    &dst_pixmap->drawable, bo, 0, 0,
352.17634 +-							    box, n, COPY_LAST);
352.17635 +-
352.17636 ++							    box, n, small_copy(region) |  COPY_LAST);
352.17637 + 				kgem_bo_sync__cpu(&sna->kgem, src_bo);
352.17638 + 				assert(src_bo->rq == NULL);
352.17639 + 				kgem_bo_destroy(&sna->kgem, src_bo);
352.17640 +@@ -6780,18 +6917,22 @@ fallback:
352.17641 + 				return;
352.17642 + 		}
352.17643 + 
352.17644 +-		assert(dst_pixmap->devPrivate.ptr);
352.17645 +-		assert(dst_pixmap->devKind);
352.17646 +-		do {
352.17647 +-			pixman_fill(dst_pixmap->devPrivate.ptr,
352.17648 +-				    dst_pixmap->devKind/sizeof(uint32_t),
352.17649 +-				    dst_pixmap->drawable.bitsPerPixel,
352.17650 +-				    box->x1, box->y1,
352.17651 +-				    box->x2 - box->x1,
352.17652 +-				    box->y2 - box->y1,
352.17653 +-				    src_priv->clear_color);
352.17654 +-			box++;
352.17655 +-		} while (--n);
352.17656 ++		if (sigtrap_get() == 0) {
352.17657 ++			assert(dst_pixmap->devPrivate.ptr);
352.17658 ++			assert(dst_pixmap->devKind);
352.17659 ++			sigtrap_assert_active();
352.17660 ++			do {
352.17661 ++				pixman_fill(dst_pixmap->devPrivate.ptr,
352.17662 ++					    dst_pixmap->devKind/sizeof(uint32_t),
352.17663 ++					    dst_pixmap->drawable.bitsPerPixel,
352.17664 ++					    box->x1, box->y1,
352.17665 ++					    box->x2 - box->x1,
352.17666 ++					    box->y2 - box->y1,
352.17667 ++					    src_priv->clear_color);
352.17668 ++				box++;
352.17669 ++			} while (--n);
352.17670 ++			sigtrap_put();
352.17671 ++		}
352.17672 + 	} else if (!sna_copy_boxes__inplace(sna, region, alu,
352.17673 + 					    src_pixmap, src_priv,
352.17674 + 					    src_dx, src_dy,
352.17675 +@@ -6848,36 +6989,39 @@ fallback:
352.17676 + 				((char *)src_pixmap->devPrivate.ptr +
352.17677 + 				 src_dy * src_stride + src_dx * bpp / 8);
352.17678 + 
352.17679 +-			do {
352.17680 +-				DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
352.17681 +-				     __FUNCTION__,
352.17682 +-				     box->x1, box->y1,
352.17683 +-				     box->x2 - box->x1,
352.17684 +-				     box->y2 - box->y1,
352.17685 +-				     src_dx, src_dy,
352.17686 +-				     src_stride, dst_stride));
352.17687 +-
352.17688 +-				assert(box->x1 >= 0);
352.17689 +-				assert(box->y1 >= 0);
352.17690 +-				assert(box->x2 <= dst_pixmap->drawable.width);
352.17691 +-				assert(box->y2 <= dst_pixmap->drawable.height);
352.17692 +-
352.17693 +-				assert(box->x1 + src_dx >= 0);
352.17694 +-				assert(box->y1 + src_dy >= 0);
352.17695 +-				assert(box->x2 + src_dx <= src_pixmap->drawable.width);
352.17696 +-				assert(box->y2 + src_dy <= src_pixmap->drawable.height);
352.17697 +-				assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
352.17698 +-				assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
352.17699 +-				assert(src_stride);
352.17700 +-				assert(dst_stride);
352.17701 +-				memcpy_blt(src_bits, dst_bits, bpp,
352.17702 +-					   src_stride, dst_stride,
352.17703 +-					   box->x1, box->y1,
352.17704 +-					   box->x1, box->y1,
352.17705 +-					   box->x2 - box->x1,
352.17706 +-					   box->y2 - box->y1);
352.17707 +-				box++;
352.17708 +-			} while (--n);
352.17709 ++			if (sigtrap_get() == 0) {
352.17710 ++				do {
352.17711 ++					DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
352.17712 ++					     __FUNCTION__,
352.17713 ++					     box->x1, box->y1,
352.17714 ++					     box->x2 - box->x1,
352.17715 ++					     box->y2 - box->y1,
352.17716 ++					     src_dx, src_dy,
352.17717 ++					     src_stride, dst_stride));
352.17718 ++
352.17719 ++					assert(box->x1 >= 0);
352.17720 ++					assert(box->y1 >= 0);
352.17721 ++					assert(box->x2 <= dst_pixmap->drawable.width);
352.17722 ++					assert(box->y2 <= dst_pixmap->drawable.height);
352.17723 ++
352.17724 ++					assert(box->x1 + src_dx >= 0);
352.17725 ++					assert(box->y1 + src_dy >= 0);
352.17726 ++					assert(box->x2 + src_dx <= src_pixmap->drawable.width);
352.17727 ++					assert(box->y2 + src_dy <= src_pixmap->drawable.height);
352.17728 ++					assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
352.17729 ++					assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
352.17730 ++					assert(src_stride);
352.17731 ++					assert(dst_stride);
352.17732 ++					memcpy_blt(src_bits, dst_bits, bpp,
352.17733 ++						   src_stride, dst_stride,
352.17734 ++						   box->x1, box->y1,
352.17735 ++						   box->x1, box->y1,
352.17736 ++						   box->x2 - box->x1,
352.17737 ++						   box->y2 - box->y1);
352.17738 ++					box++;
352.17739 ++				} while (--n);
352.17740 ++				sigtrap_put();
352.17741 ++			}
352.17742 + 		} else {
352.17743 + 			DBG(("%s: fallback -- miCopyRegion\n", __FUNCTION__));
352.17744 + 
352.17745 +@@ -6931,7 +7075,8 @@ sna_do_copy(DrawablePtr src, DrawablePtr dst, GCPtr gc,
352.17746 + 
352.17747 + 	/* Short cut for unmapped windows */
352.17748 + 	if (dst->type == DRAWABLE_WINDOW && !((WindowPtr)dst)->realized) {
352.17749 +-		DBG(("%s: unmapped\n", __FUNCTION__));
352.17750 ++		DBG(("%s: unmapped/unrealized dst (pixmap=%ld)\n",
352.17751 ++		     __FUNCTION__, get_window_pixmap((WindowPtr)dst)));
352.17752 + 		return NULL;
352.17753 + 	}
352.17754 + 
352.17755 +@@ -7115,19 +7260,28 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
352.17756 + 	if (gc->planemask == 0)
352.17757 + 		return NULL;
352.17758 + 
352.17759 +-	DBG(("%s: src=(%d, %d)x(%d, %d)+(%d, %d) -> dst=(%d, %d)+(%d, %d); alu=%d, pm=%lx, depth=%d\n",
352.17760 ++	if (sna->ignore_copy_area)
352.17761 ++		return NULL;
352.17762 ++
352.17763 ++	DBG(("%s: src=pixmap=%ld:(%d, %d)x(%d, %d)+(%d, %d) -> dst=pixmap=%ld:(%d, %d)+(%d, %d); alu=%d, pm=%lx, depth=%d\n",
352.17764 + 	     __FUNCTION__,
352.17765 ++	     get_drawable_pixmap(src)->drawable.serialNumber,
352.17766 + 	     src_x, src_y, width, height, src->x, src->y,
352.17767 ++	     get_drawable_pixmap(dst)->drawable.serialNumber,
352.17768 + 	     dst_x, dst_y, dst->x, dst->y,
352.17769 + 	     gc->alu, gc->planemask, gc->depth));
352.17770 + 
352.17771 + 	if (FORCE_FALLBACK || !ACCEL_COPY_AREA || wedged(sna) ||
352.17772 +-	    !PM_IS_SOLID(dst, gc->planemask) || gc->depth < 8)
352.17773 ++	    !PM_IS_SOLID(dst, gc->planemask) || gc->depth < 8) {
352.17774 ++		DBG(("%s: fallback copy\n", __FUNCTION__));
352.17775 + 		copy = sna_fallback_copy_boxes;
352.17776 +-	else if (src == dst)
352.17777 ++	} else if (src == dst) {
352.17778 ++		DBG(("%s: self copy\n", __FUNCTION__));
352.17779 + 		copy = sna_self_copy_boxes;
352.17780 +-	else
352.17781 ++	} else {
352.17782 ++		DBG(("%s: normal copy\n", __FUNCTION__));
352.17783 + 		copy = sna_copy_boxes;
352.17784 ++	}
352.17785 + 
352.17786 + 	return sna_do_copy(src, dst, gc,
352.17787 + 			   src_x, src_y,
352.17788 +@@ -7136,30 +7290,21 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
352.17789 + 			   copy, 0, NULL);
352.17790 + }
352.17791 + 
352.17792 +-static const BoxRec *
352.17793 +-find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
352.17794 ++const BoxRec *
352.17795 ++__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
352.17796 + {
352.17797 +-    const BoxRec *mid;
352.17798 +-
352.17799 +-    if (end == begin)
352.17800 +-	return end;
352.17801 +-
352.17802 +-    if (end - begin == 1) {
352.17803 ++	assert(end - begin > 1);
352.17804 ++	do {
352.17805 ++		const BoxRec *mid = begin + (end - begin) / 2;
352.17806 ++		if (mid->y2 > y)
352.17807 ++			end = mid;
352.17808 ++		else
352.17809 ++			begin = mid;
352.17810 ++	} while (end > begin + 1);
352.17811 + 	if (begin->y2 > y)
352.17812 +-	    return begin;
352.17813 ++		return begin;
352.17814 + 	else
352.17815 +-	    return end;
352.17816 +-    }
352.17817 +-
352.17818 +-    mid = begin + (end - begin) / 2;
352.17819 +-    if (mid->y2 > y)
352.17820 +-	/* If no box is found in [begin, mid], the function
352.17821 +-	 * will return @mid, which is then known to be the
352.17822 +-	 * correct answer.
352.17823 +-	 */
352.17824 +-	return find_clip_box_for_y(begin, mid, y);
352.17825 +-    else
352.17826 +-	return find_clip_box_for_y(mid, end, y);
352.17827 ++		return end;
352.17828 + }
352.17829 + 
352.17830 + struct sna_fill_spans {
352.17831 +@@ -8223,6 +8368,8 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
352.17832 + 	}
352.17833 + 	br13 |= blt_depth(drawable->depth) << 24;
352.17834 + 	br13 |= copy_ROP[gc->alu] << 16;
352.17835 ++	DBG(("%s: target-depth=%d, alu=%d, bg=%08x, fg=%08x\n",
352.17836 ++	     __FUNCTION__, drawable->depth, gc->alu, gc->bgPixel, gc->fgPixel));
352.17837 + 
352.17838 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, arg->bo);
352.17839 + 	assert(kgem_bo_can_blt(&sna->kgem, arg->bo));
352.17840 +@@ -8255,6 +8402,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
352.17841 + 					return; /* XXX fallback? */
352.17842 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.17843 + 			}
352.17844 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
352.17845 + 
352.17846 + 			assert(sna->kgem.mode == KGEM_BLT);
352.17847 + 			if (sna->kgem.gen >= 0100) {
352.17848 +@@ -8270,8 +8418,8 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
352.17849 + 							 I915_GEM_DOMAIN_RENDER |
352.17850 + 							 KGEM_RELOC_FENCED,
352.17851 + 							 0);
352.17852 +-				b[5] = gc->bgPixel;
352.17853 +-				b[6] = gc->fgPixel;
352.17854 ++				b[6] = gc->bgPixel;
352.17855 ++				b[7] = gc->fgPixel;
352.17856 + 
352.17857 + 				dst = (uint8_t *)&b[8];
352.17858 + 				sna->kgem.nbatch += 8 + src_stride;
352.17859 +@@ -8322,6 +8470,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
352.17860 + 					return; /* XXX fallback? */
352.17861 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.17862 + 			}
352.17863 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
352.17864 + 
352.17865 + 			upload = kgem_create_buffer(&sna->kgem,
352.17866 + 						    bstride*bh,
352.17867 +@@ -8408,7 +8557,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
352.17868 + 		sna_damage_add_to_pixmap(arg->damage, region, pixmap);
352.17869 + 	}
352.17870 + 	assert_pixmap_damage(pixmap);
352.17871 +-	sna->blt_state.fill_bo = 0;
352.17872 ++	blt_done(sna);
352.17873 + }
352.17874 + 
352.17875 + static void
352.17876 +@@ -8472,6 +8621,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
352.17877 + 				return; /* XXX fallback? */
352.17878 + 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.17879 + 		}
352.17880 ++		kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
352.17881 + 
352.17882 + 		upload = kgem_create_buffer(&sna->kgem,
352.17883 + 					    bstride*bh,
352.17884 +@@ -8588,6 +8738,8 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
352.17885 + 				}
352.17886 + 			}
352.17887 + 
352.17888 ++			kgem_bcs_set_tiling(&sna->kgem, upload, arg->bo);
352.17889 ++
352.17890 + 			assert(sna->kgem.mode == KGEM_BLT);
352.17891 + 			b = sna->kgem.batch + sna->kgem.nbatch;
352.17892 + 			if (sna->kgem.gen >= 0100) {
352.17893 +@@ -8641,7 +8793,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
352.17894 + 		sna_damage_add_to_pixmap(arg->damage, region, dst_pixmap);
352.17895 + 	}
352.17896 + 	assert_pixmap_damage(dst_pixmap);
352.17897 +-	sna->blt_state.fill_bo = 0;
352.17898 ++	blt_done(sna);
352.17899 + }
352.17900 + 
352.17901 + static RegionPtr
352.17902 +@@ -8895,36 +9047,11 @@ sna_poly_point_extents(DrawablePtr drawable, GCPtr gc,
352.17903 + 			last.x += pt->x;
352.17904 + 			last.y += pt->y;
352.17905 + 			pt++;
352.17906 +-			box_add_pt(&box, last.x, last.y);
352.17907 ++			box_add_xy(&box, last.x, last.y);
352.17908 + 		}
352.17909 + 	} else {
352.17910 +-		--n; ++pt;
352.17911 +-		while (n >= 8) {
352.17912 +-			box_add_pt(&box, pt[0].x, pt[0].y);
352.17913 +-			box_add_pt(&box, pt[1].x, pt[1].y);
352.17914 +-			box_add_pt(&box, pt[2].x, pt[2].y);
352.17915 +-			box_add_pt(&box, pt[3].x, pt[3].y);
352.17916 +-			box_add_pt(&box, pt[4].x, pt[4].y);
352.17917 +-			box_add_pt(&box, pt[5].x, pt[5].y);
352.17918 +-			box_add_pt(&box, pt[6].x, pt[6].y);
352.17919 +-			box_add_pt(&box, pt[7].x, pt[7].y);
352.17920 +-			pt += 8;
352.17921 +-			n -= 8;
352.17922 +-		}
352.17923 +-		if (n & 4) {
352.17924 +-			box_add_pt(&box, pt[0].x, pt[0].y);
352.17925 +-			box_add_pt(&box, pt[1].x, pt[1].y);
352.17926 +-			box_add_pt(&box, pt[2].x, pt[2].y);
352.17927 +-			box_add_pt(&box, pt[3].x, pt[3].y);
352.17928 +-			pt += 4;
352.17929 +-		}
352.17930 +-		if (n & 2) {
352.17931 +-			box_add_pt(&box, pt[0].x, pt[0].y);
352.17932 +-			box_add_pt(&box, pt[1].x, pt[1].y);
352.17933 +-			pt += 2;
352.17934 +-		}
352.17935 +-		if (n & 1)
352.17936 +-			box_add_pt(&box, pt[0].x, pt[0].y);
352.17937 ++		while (--n)
352.17938 ++			box_add_pt(&box, ++pt);
352.17939 + 	}
352.17940 + 	box.x2++;
352.17941 + 	box.y2++;
352.17942 +@@ -9636,7 +9763,7 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
352.17943 + 			y += pt->y;
352.17944 + 			if (blt)
352.17945 + 				blt &= pt->x == 0 || pt->y == 0;
352.17946 +-			box_add_pt(&box, x, y);
352.17947 ++			box_add_xy(&box, x, y);
352.17948 + 		}
352.17949 + 	} else {
352.17950 + 		int x = box.x1;
352.17951 +@@ -9648,7 +9775,7 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
352.17952 + 				x = pt->x;
352.17953 + 				y = pt->y;
352.17954 + 			}
352.17955 +-			box_add_pt(&box, pt->x, pt->y);
352.17956 ++			box_add_pt(&box, pt);
352.17957 + 		}
352.17958 + 	}
352.17959 + 	box.x2++;
352.17960 +@@ -10037,7 +10164,7 @@ out:
352.17961 + 	RegionUninit(&data.region);
352.17962 + }
352.17963 + 
352.17964 +-static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
352.17965 ++static inline bool box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
352.17966 + {
352.17967 + 	if (seg->x1 == seg->x2) {
352.17968 + 		if (seg->y1 > seg->y2) {
352.17969 +@@ -10051,6 +10178,9 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
352.17970 + 			if (gc->capStyle != CapNotLast)
352.17971 + 				b->y2++;
352.17972 + 		}
352.17973 ++		if (b->y1 >= b->y2)
352.17974 ++			return false;
352.17975 ++
352.17976 + 		b->x1 = seg->x1;
352.17977 + 		b->x2 = seg->x1 + 1;
352.17978 + 	} else {
352.17979 +@@ -10065,6 +10195,9 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
352.17980 + 			if (gc->capStyle != CapNotLast)
352.17981 + 				b->x2++;
352.17982 + 		}
352.17983 ++		if (b->x1 >= b->x2)
352.17984 ++			return false;
352.17985 ++
352.17986 + 		b->y1 = seg->y1;
352.17987 + 		b->y2 = seg->y1 + 1;
352.17988 + 	}
352.17989 +@@ -10073,6 +10206,7 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
352.17990 + 	     __FUNCTION__,
352.17991 + 	     seg->x1, seg->y1, seg->x2, seg->y2,
352.17992 + 	     b->x1, b->y1, b->x2, b->y2));
352.17993 ++	return true;
352.17994 + }
352.17995 + 
352.17996 + static bool
352.17997 +@@ -10107,12 +10241,13 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.17998 + 					nbox = ARRAY_SIZE(boxes);
352.17999 + 				n -= nbox;
352.18000 + 				do {
352.18001 +-					box_from_seg(b, seg++, gc);
352.18002 +-					if (b->y2 > b->y1 && b->x2 > b->x1) {
352.18003 ++					if (box_from_seg(b, seg++, gc)) {
352.18004 ++						assert(!box_empty(b));
352.18005 + 						b->x1 += dx;
352.18006 + 						b->x2 += dx;
352.18007 + 						b->y1 += dy;
352.18008 + 						b->y2 += dy;
352.18009 ++						assert(!box_empty(b));
352.18010 + 						b++;
352.18011 + 					}
352.18012 + 				} while (--nbox);
352.18013 +@@ -10131,7 +10266,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.18014 + 					nbox = ARRAY_SIZE(boxes);
352.18015 + 				n -= nbox;
352.18016 + 				do {
352.18017 +-					box_from_seg(b++, seg++, gc);
352.18018 ++					if (box_from_seg(b, seg++, gc)) {
352.18019 ++						assert(!box_empty(b));
352.18020 ++						b++;
352.18021 ++					}
352.18022 + 				} while (--nbox);
352.18023 + 
352.18024 + 				if (b != boxes) {
352.18025 +@@ -10156,7 +10294,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.18026 + 			do {
352.18027 + 				BoxRec box;
352.18028 + 
352.18029 +-				box_from_seg(&box, seg++, gc);
352.18030 ++				if (!box_from_seg(&box, seg++, gc))
352.18031 ++					continue;
352.18032 ++
352.18033 ++				assert(!box_empty(&box));
352.18034 + 				box.x1 += drawable->x;
352.18035 + 				box.x2 += drawable->x;
352.18036 + 				box.y1 += drawable->y;
352.18037 +@@ -10174,6 +10315,7 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.18038 + 						b->x2 += dx;
352.18039 + 						b->y1 += dy;
352.18040 + 						b->y2 += dy;
352.18041 ++						assert(!box_empty(b));
352.18042 + 						if (++b == last_box) {
352.18043 + 							fill.boxes(sna, &fill, boxes, last_box-boxes);
352.18044 + 							if (damage)
352.18045 +@@ -10185,7 +10327,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.18046 + 			} while (--n);
352.18047 + 		} else {
352.18048 + 			do {
352.18049 +-				box_from_seg(b, seg++, gc);
352.18050 ++				if (!box_from_seg(b, seg++, gc))
352.18051 ++					continue;
352.18052 ++
352.18053 ++				assert(!box_empty(b));
352.18054 + 				b->x1 += drawable->x;
352.18055 + 				b->x2 += drawable->x;
352.18056 + 				b->y1 += drawable->y;
352.18057 +@@ -10195,6 +10340,7 @@ sna_poly_segment_blt(DrawablePtr drawable,
352.18058 + 					b->x2 += dx;
352.18059 + 					b->y1 += dy;
352.18060 + 					b->y2 += dy;
352.18061 ++					assert(!box_empty(b));
352.18062 + 					if (++b == last_box) {
352.18063 + 						fill.boxes(sna, &fill, boxes, last_box-boxes);
352.18064 + 						if (damage)
352.18065 +@@ -10319,8 +10465,11 @@ sna_poly_zero_segment_blt(DrawablePtr drawable,
352.18066 + 				}
352.18067 + 				b->x2++;
352.18068 + 				b->y2++;
352.18069 +-				if (oc1 | oc2)
352.18070 +-					box_intersect(b, extents);
352.18071 ++
352.18072 ++				if ((oc1 | oc2) && !box_intersect(b, extents))
352.18073 ++					continue;
352.18074 ++
352.18075 ++				assert(!box_empty(b));
352.18076 + 				if (++b == last_box) {
352.18077 + 					ret = &&rectangle_continue;
352.18078 + 					goto *jump;
352.18079 +@@ -10383,6 +10532,7 @@ rectangle_continue:
352.18080 + 						     __FUNCTION__, x1, y1,
352.18081 + 						     b->x1, b->y1, b->x2, b->y2));
352.18082 + 
352.18083 ++						assert(!box_empty(b));
352.18084 + 						if (++b == last_box) {
352.18085 + 							ret = &&X_continue;
352.18086 + 							goto *jump;
352.18087 +@@ -10407,6 +10557,7 @@ X_continue:
352.18088 + 						b->x2 = x1 + 1;
352.18089 + 					b->y2 = b->y1 + 1;
352.18090 + 
352.18091 ++					assert(!box_empty(b));
352.18092 + 					if (++b == last_box) {
352.18093 + 						ret = &&X2_continue;
352.18094 + 						goto *jump;
352.18095 +@@ -10468,6 +10619,7 @@ X2_continue:
352.18096 + 							b->y2 = y1 + 1;
352.18097 + 						b->x2 = x1 + 1;
352.18098 + 
352.18099 ++						assert(!box_empty(b));
352.18100 + 						if (++b == last_box) {
352.18101 + 							ret = &&Y_continue;
352.18102 + 							goto *jump;
352.18103 +@@ -10491,6 +10643,7 @@ Y_continue:
352.18104 + 						b->y2 = y1 + 1;
352.18105 + 					b->x2 = x1 + 1;
352.18106 + 
352.18107 ++					assert(!box_empty(b));
352.18108 + 					if (++b == last_box) {
352.18109 + 						ret = &&Y2_continue;
352.18110 + 						goto *jump;
352.18111 +@@ -11785,14 +11938,29 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
352.18112 + 				if (nbox > ARRAY_SIZE(boxes))
352.18113 + 					nbox = ARRAY_SIZE(boxes);
352.18114 + 				n -= nbox;
352.18115 +-				do {
352.18116 ++				while (nbox >= 2) {
352.18117 ++					b[0].x1 = rect[0].x + dx;
352.18118 ++					b[0].y1 = rect[0].y + dy;
352.18119 ++					b[0].x2 = b[0].x1 + rect[0].width;
352.18120 ++					b[0].y2 = b[0].y1 + rect[0].height;
352.18121 ++
352.18122 ++					b[1].x1 = rect[1].x + dx;
352.18123 ++					b[1].y1 = rect[1].y + dy;
352.18124 ++					b[1].x2 = b[1].x1 + rect[1].width;
352.18125 ++					b[1].y2 = b[1].y1 + rect[1].height;
352.18126 ++
352.18127 ++					b += 2;
352.18128 ++					rect += 2;
352.18129 ++					nbox -= 2;
352.18130 ++				}
352.18131 ++				if (nbox) {
352.18132 + 					b->x1 = rect->x + dx;
352.18133 + 					b->y1 = rect->y + dy;
352.18134 + 					b->x2 = b->x1 + rect->width;
352.18135 + 					b->y2 = b->y1 + rect->height;
352.18136 + 					b++;
352.18137 + 					rect++;
352.18138 +-				} while (--nbox);
352.18139 ++				}
352.18140 + 				fill.boxes(sna, &fill, boxes, b-boxes);
352.18141 + 				b = boxes;
352.18142 + 			} while (n);
352.18143 +@@ -11802,14 +11970,29 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
352.18144 + 				if (nbox > ARRAY_SIZE(boxes))
352.18145 + 					nbox = ARRAY_SIZE(boxes);
352.18146 + 				n -= nbox;
352.18147 +-				do {
352.18148 ++				while (nbox >= 2) {
352.18149 ++					b[0].x1 = rect[0].x;
352.18150 ++					b[0].y1 = rect[0].y;
352.18151 ++					b[0].x2 = b[0].x1 + rect[0].width;
352.18152 ++					b[0].y2 = b[0].y1 + rect[0].height;
352.18153 ++
352.18154 ++					b[1].x1 = rect[1].x;
352.18155 ++					b[1].y1 = rect[1].y;
352.18156 ++					b[1].x2 = b[1].x1 + rect[1].width;
352.18157 ++					b[1].y2 = b[1].y1 + rect[1].height;
352.18158 ++
352.18159 ++					b += 2;
352.18160 ++					rect += 2;
352.18161 ++					nbox -= 2;
352.18162 ++				}
352.18163 ++				if (nbox) {
352.18164 + 					b->x1 = rect->x;
352.18165 + 					b->y1 = rect->y;
352.18166 + 					b->x2 = b->x1 + rect->width;
352.18167 + 					b->y2 = b->y1 + rect->height;
352.18168 + 					b++;
352.18169 + 					rect++;
352.18170 +-				} while (--nbox);
352.18171 ++				}
352.18172 + 				fill.boxes(sna, &fill, boxes, b-boxes);
352.18173 + 				b = boxes;
352.18174 + 			} while (n);
352.18175 +@@ -12192,6 +12375,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
352.18176 + 			return false;
352.18177 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18178 + 	}
352.18179 ++	kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
352.18180 + 
352.18181 + 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
352.18182 + 	assert(extents->x1 + dx >= 0);
352.18183 +@@ -12335,6 +12519,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
352.18184 + 
352.18185 + 			_kgem_submit(&sna->kgem);
352.18186 + 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18187 ++			kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
352.18188 + 		} while (1);
352.18189 + 	} else {
352.18190 + 		RegionRec clip;
352.18191 +@@ -12403,6 +12588,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
352.18192 + 					if (!kgem_check_batch(&sna->kgem, 3)) {
352.18193 + 						_kgem_submit(&sna->kgem);
352.18194 + 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18195 ++						kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
352.18196 + 
352.18197 + 						unwind_batch = sna->kgem.nbatch;
352.18198 + 						unwind_reloc = sna->kgem.nreloc;
352.18199 +@@ -12499,6 +12685,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
352.18200 + 							DBG(("%s: emitting split batch\n", __FUNCTION__));
352.18201 + 							_kgem_submit(&sna->kgem);
352.18202 + 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18203 ++							kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
352.18204 + 
352.18205 + 							unwind_batch = sna->kgem.nbatch;
352.18206 + 							unwind_reloc = sna->kgem.nreloc;
352.18207 +@@ -12572,7 +12759,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
352.18208 + 	}
352.18209 + done:
352.18210 + 	assert_pixmap_damage(pixmap);
352.18211 +-	sna->blt_state.fill_bo = 0;
352.18212 ++	blt_done(sna);
352.18213 + 	return true;
352.18214 + }
352.18215 + 
352.18216 +@@ -13128,6 +13315,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
352.18217 + 			return false;
352.18218 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18219 + 	}
352.18220 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18221 + 
352.18222 + 	if (!clipped) {
352.18223 + 		dx += drawable->x;
352.18224 +@@ -13240,6 +13428,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
352.18225 + 
352.18226 + 			_kgem_submit(&sna->kgem);
352.18227 + 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18228 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18229 + 		} while (1);
352.18230 + 	} else {
352.18231 + 		RegionRec clip;
352.18232 +@@ -13297,6 +13486,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
352.18233 + 					if (!kgem_check_batch(&sna->kgem, 3)) {
352.18234 + 						_kgem_submit(&sna->kgem);
352.18235 + 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18236 ++						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18237 + 
352.18238 + 						assert(sna->kgem.mode == KGEM_BLT);
352.18239 + 						b = sna->kgem.batch + sna->kgem.nbatch;
352.18240 +@@ -13369,6 +13559,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
352.18241 + 						if (!kgem_check_batch(&sna->kgem, 3)) {
352.18242 + 							_kgem_submit(&sna->kgem);
352.18243 + 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18244 ++							kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18245 + 
352.18246 + 							assert(sna->kgem.mode == KGEM_BLT);
352.18247 + 							b = sna->kgem.batch + sna->kgem.nbatch;
352.18248 +@@ -13419,7 +13610,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
352.18249 + 	}
352.18250 + 
352.18251 + 	assert_pixmap_damage(pixmap);
352.18252 +-	sna->blt_state.fill_bo = 0;
352.18253 ++	blt_done(sna);
352.18254 + 	return true;
352.18255 + }
352.18256 + 
352.18257 +@@ -13499,6 +13690,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18258 + 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
352.18259 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.18260 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.18261 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18262 + 
352.18263 + 	br00 = 3 << 20;
352.18264 + 	br13 = bo->pitch;
352.18265 +@@ -13543,6 +13735,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18266 + 						return false;
352.18267 + 					_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18268 + 				}
352.18269 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18270 + 
352.18271 + 				assert(sna->kgem.mode == KGEM_BLT);
352.18272 + 				b = sna->kgem.batch + sna->kgem.nbatch;
352.18273 +@@ -13606,6 +13799,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18274 + 						return false;
352.18275 + 					_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18276 + 				}
352.18277 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18278 + 
352.18279 + 				upload = kgem_create_buffer(&sna->kgem,
352.18280 + 							    bstride*bh,
352.18281 +@@ -13736,6 +13930,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18282 + 							return false;
352.18283 + 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18284 + 					}
352.18285 ++					kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18286 + 
352.18287 + 					assert(sna->kgem.mode == KGEM_BLT);
352.18288 + 					b = sna->kgem.batch + sna->kgem.nbatch;
352.18289 +@@ -13797,6 +13992,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18290 + 							return false;
352.18291 + 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18292 + 					}
352.18293 ++					kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18294 + 
352.18295 + 					upload = kgem_create_buffer(&sna->kgem,
352.18296 + 								    bstride*bh,
352.18297 +@@ -13927,6 +14123,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18298 + 								return false;
352.18299 + 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18300 + 						}
352.18301 ++						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18302 + 
352.18303 + 						assert(sna->kgem.mode == KGEM_BLT);
352.18304 + 						b = sna->kgem.batch + sna->kgem.nbatch;
352.18305 +@@ -13987,6 +14184,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18306 + 								return false;
352.18307 + 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18308 + 						}
352.18309 ++						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18310 + 
352.18311 + 						upload = kgem_create_buffer(&sna->kgem,
352.18312 + 									    bstride*bh,
352.18313 +@@ -14064,7 +14262,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
352.18314 + 		}
352.18315 + 	}
352.18316 + 
352.18317 +-	sna->blt_state.fill_bo = 0;
352.18318 ++	blt_done(sna);
352.18319 + 	return true;
352.18320 + }
352.18321 + 
352.18322 +@@ -14126,6 +14324,7 @@ sna_poly_fill_rect_stippled_n_box__imm(struct sna *sna,
352.18323 + 					return; /* XXX fallback? */
352.18324 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18325 + 			}
352.18326 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18327 + 
352.18328 + 			assert(sna->kgem.mode == KGEM_BLT);
352.18329 + 			b = sna->kgem.batch + sna->kgem.nbatch;
352.18330 +@@ -14251,6 +14450,7 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna,
352.18331 + 					return; /* XXX fallback? */
352.18332 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18333 + 			}
352.18334 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18335 + 
352.18336 + 			assert(sna->kgem.mode == KGEM_BLT);
352.18337 + 			b = sna->kgem.batch + sna->kgem.nbatch;
352.18338 +@@ -14414,6 +14614,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
352.18339 + 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
352.18340 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.18341 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.18342 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18343 + 
352.18344 + 	br00 = XY_MONO_SRC_COPY_IMM | 3 << 20;
352.18345 + 	br13 = bo->pitch;
352.18346 +@@ -14526,7 +14727,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
352.18347 + 	}
352.18348 + 
352.18349 + 	assert_pixmap_damage(pixmap);
352.18350 +-	sna->blt_state.fill_bo = 0;
352.18351 ++	blt_done(sna);
352.18352 + 	return true;
352.18353 + }
352.18354 + 
352.18355 +@@ -14559,6 +14760,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
352.18356 + 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
352.18357 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.18358 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.18359 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18360 + 
352.18361 + 	br00 = XY_MONO_SRC_COPY | 3 << 20;
352.18362 + 	br13 = bo->pitch;
352.18363 +@@ -14673,7 +14875,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
352.18364 + 	assert_pixmap_damage(pixmap);
352.18365 + 	if (tile)
352.18366 + 		kgem_bo_destroy(&sna->kgem, tile);
352.18367 +-	sna->blt_state.fill_bo = 0;
352.18368 ++	blt_done(sna);
352.18369 + 	return true;
352.18370 + }
352.18371 + 
352.18372 +@@ -15281,6 +15483,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
352.18373 + 		}
352.18374 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18375 + 	}
352.18376 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18377 + 
352.18378 + 	DBG(("%s: glyph clip box (%d, %d), (%d, %d)\n",
352.18379 + 	     __FUNCTION__,
352.18380 +@@ -15368,6 +15571,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
352.18381 + 			if (!kgem_check_batch(&sna->kgem, 3+len)) {
352.18382 + 				_kgem_submit(&sna->kgem);
352.18383 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18384 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18385 + 
352.18386 + 				DBG(("%s: new batch, glyph clip box (%d, %d), (%d, %d)\n",
352.18387 + 				     __FUNCTION__,
352.18388 +@@ -15479,7 +15683,7 @@ skip:
352.18389 + 	}
352.18390 + 
352.18391 + 	assert_pixmap_damage(pixmap);
352.18392 +-	sna->blt_state.fill_bo = 0;
352.18393 ++	blt_done(sna);
352.18394 + 	return true;
352.18395 + }
352.18396 + 
352.18397 +@@ -16002,6 +16206,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
352.18398 + 		}
352.18399 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18400 + 	}
352.18401 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18402 + 
352.18403 + 	unwind_batch = sna->kgem.nbatch;
352.18404 + 	unwind_reloc = sna->kgem.nreloc;
352.18405 +@@ -16111,6 +16316,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
352.18406 + 			if (!kgem_check_batch(&sna->kgem, 3+len)) {
352.18407 + 				_kgem_submit(&sna->kgem);
352.18408 + 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18409 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18410 + 
352.18411 + 				unwind_batch = sna->kgem.nbatch;
352.18412 + 				unwind_reloc = sna->kgem.nreloc;
352.18413 +@@ -16229,7 +16435,7 @@ skip:
352.18414 + 	}
352.18415 + 
352.18416 + 	assert_pixmap_damage(pixmap);
352.18417 +-	sna->blt_state.fill_bo = 0;
352.18418 ++	blt_done(sna);
352.18419 + 	return true;
352.18420 + }
352.18421 + 
352.18422 +@@ -16450,6 +16656,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
352.18423 + 
352.18424 + 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
352.18425 + 	assert(kgem_bo_can_blt(&sna->kgem, bo));
352.18426 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18427 + 
352.18428 + 	/* Region is pre-clipped and translated into pixmap space */
352.18429 + 	box = region_rects(region);
352.18430 +@@ -16471,6 +16678,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
352.18431 + 				return false;
352.18432 + 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.18433 + 		}
352.18434 ++		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.18435 + 
352.18436 + 		upload = kgem_create_buffer(&sna->kgem,
352.18437 + 					    bstride*bh,
352.18438 +@@ -16564,7 +16772,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
352.18439 + 		box++;
352.18440 + 	} while (--n);
352.18441 + 
352.18442 +-	sna->blt_state.fill_bo = 0;
352.18443 ++	blt_done(sna);
352.18444 + 	return true;
352.18445 + }
352.18446 + 
352.18447 +@@ -16754,7 +16962,9 @@ static int sna_create_gc(GCPtr gc)
352.18448 + 
352.18449 + 	gc->freeCompClip = 0;
352.18450 + 	gc->pCompositeClip = 0;
352.18451 ++#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,99,1,0)
352.18452 + 	gc->pRotatedPixmap = 0;
352.18453 ++#endif
352.18454 + 
352.18455 + 	fb_gc(gc)->bpp = bits_per_pixel(gc->depth);
352.18456 + 
352.18457 +@@ -16789,7 +16999,8 @@ sna_get_image__inplace(PixmapPtr pixmap,
352.18458 + 		break;
352.18459 + 	}
352.18460 + 
352.18461 +-	if (!kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC))
352.18462 ++	if ((flags & MOVE_INPLACE_HINT) == 0 &&
352.18463 ++	    !kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC))
352.18464 + 		return false;
352.18465 + 
352.18466 + 	if (idle && __kgem_bo_is_busy(&sna->kgem, priv->gpu_bo))
352.18467 +@@ -16801,11 +17012,19 @@ sna_get_image__inplace(PixmapPtr pixmap,
352.18468 + 	assert(sna_damage_contains_box(&priv->gpu_damage, &region->extents) == PIXMAN_REGION_IN);
352.18469 + 	assert(sna_damage_contains_box(&priv->cpu_damage, &region->extents) == PIXMAN_REGION_OUT);
352.18470 + 
352.18471 +-	src = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
352.18472 +-	if (src == NULL)
352.18473 +-		return false;
352.18474 ++	if (kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC)) {
352.18475 ++		src = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
352.18476 ++		if (src == NULL)
352.18477 ++			return false;
352.18478 + 
352.18479 +-	kgem_bo_sync__cpu_full(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC);
352.18480 ++		kgem_bo_sync__cpu_full(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC);
352.18481 ++	} else {
352.18482 ++		src = kgem_bo_map__wc(&sna->kgem, priv->gpu_bo);
352.18483 ++		if (src == NULL)
352.18484 ++			return false;
352.18485 ++
352.18486 ++		kgem_bo_sync__gtt(&sna->kgem, priv->gpu_bo);
352.18487 ++	}
352.18488 + 
352.18489 + 	if (sigtrap_get())
352.18490 + 		return false;
352.18491 +@@ -16833,12 +17052,11 @@ sna_get_image__inplace(PixmapPtr pixmap,
352.18492 + 			   region->extents.x2 - region->extents.x1,
352.18493 + 			   region->extents.y2 - region->extents.y1);
352.18494 + 		if (!priv->shm) {
352.18495 +-			assert(src == MAP(priv->gpu_bo->map__cpu));
352.18496 + 			pixmap->devPrivate.ptr = src;
352.18497 + 			pixmap->devKind = priv->gpu_bo->pitch;
352.18498 +-			priv->mapped = MAPPED_CPU;
352.18499 ++			priv->mapped = src == MAP(priv->gpu_bo->map__cpu) ? MAPPED_CPU : MAPPED_GTT;
352.18500 + 			assert_pixmap_map(pixmap, priv);
352.18501 +-			priv->cpu = true;
352.18502 ++			priv->cpu &= priv->mapped == MAPPED_CPU;
352.18503 + 		}
352.18504 + 	}
352.18505 + 
352.18506 +@@ -16930,7 +17148,7 @@ sna_get_image__fast(PixmapPtr pixmap,
352.18507 + 	if (priv == NULL || priv->gpu_damage == NULL)
352.18508 + 		return false;
352.18509 + 
352.18510 +-	if (priv->clear) {
352.18511 ++	if (priv->clear && sigtrap_get() == 0) {
352.18512 + 		int w = region->extents.x2 - region->extents.x1;
352.18513 + 		int h = region->extents.y2 - region->extents.y1;
352.18514 + 		int pitch = PixmapBytePad(w, pixmap->drawable.depth);
352.18515 +@@ -16939,6 +17157,7 @@ sna_get_image__fast(PixmapPtr pixmap,
352.18516 + 		     __FUNCTION__, priv->clear_color));
352.18517 + 		assert(DAMAGE_IS_ALL(priv->gpu_damage));
352.18518 + 		assert(priv->cpu_damage == NULL);
352.18519 ++		sigtrap_assert_active();
352.18520 + 
352.18521 + 		if (priv->clear_color == 0 ||
352.18522 + 		    pixmap->drawable.bitsPerPixel == 8 ||
352.18523 +@@ -16955,6 +17174,7 @@ sna_get_image__fast(PixmapPtr pixmap,
352.18524 + 				    priv->clear_color);
352.18525 + 		}
352.18526 + 
352.18527 ++		sigtrap_put();
352.18528 + 		return true;
352.18529 + 	}
352.18530 + 
352.18531 +@@ -17001,8 +17221,7 @@ sna_get_image(DrawablePtr drawable,
352.18532 + 	if (ACCEL_GET_IMAGE &&
352.18533 + 	    !FORCE_FALLBACK &&
352.18534 + 	    format == ZPixmap &&
352.18535 +-	    drawable->bitsPerPixel >= 8 &&
352.18536 +-	    PM_IS_SOLID(drawable, mask)) {
352.18537 ++	    drawable->bitsPerPixel >= 8) {
352.18538 + 		PixmapPtr pixmap = get_drawable_pixmap(drawable);
352.18539 + 		int16_t dx, dy;
352.18540 + 
352.18541 +@@ -17014,7 +17233,7 @@ sna_get_image(DrawablePtr drawable,
352.18542 + 		region.data = NULL;
352.18543 + 
352.18544 + 		if (sna_get_image__fast(pixmap, &region, dst, flags))
352.18545 +-			return;
352.18546 ++			goto apply_planemask;
352.18547 + 
352.18548 + 		if (!sna_drawable_move_region_to_cpu(&pixmap->drawable,
352.18549 + 						     &region, flags))
352.18550 +@@ -17032,6 +17251,16 @@ sna_get_image(DrawablePtr drawable,
352.18551 + 				   region.extents.x1, region.extents.y1, 0, 0, w, h);
352.18552 + 			sigtrap_put();
352.18553 + 		}
352.18554 ++
352.18555 ++apply_planemask:
352.18556 ++		if (!PM_IS_SOLID(drawable, mask)) {
352.18557 ++			FbStip pm = fbReplicatePixel(mask, drawable->bitsPerPixel);
352.18558 ++			FbStip *d = (FbStip *)dst;
352.18559 ++			int i, n = PixmapBytePad(w, drawable->depth) / sizeof(FbStip) * h;
352.18560 ++
352.18561 ++			for (i = 0; i < n; i++)
352.18562 ++				d[i] &= pm;
352.18563 ++		}
352.18564 + 	} else {
352.18565 + 		region.extents.x1 = x + drawable->x;
352.18566 + 		region.extents.y1 = y + drawable->y;
352.18567 +@@ -17162,17 +17391,19 @@ void sna_accel_flush(struct sna *sna)
352.18568 + 				__sna_free_pixmap(sna, priv->pixmap, priv);
352.18569 + 			}
352.18570 + 		} else {
352.18571 ++			unsigned hints;
352.18572 + 			DBG(("%s: flushing DRI pixmap=%ld\n", __FUNCTION__,
352.18573 + 			     priv->pixmap->drawable.serialNumber));
352.18574 + 			assert(priv->flush);
352.18575 +-			if (sna_pixmap_move_to_gpu(priv->pixmap,
352.18576 +-						   MOVE_READ | __MOVE_FORCE)) {
352.18577 +-				if (priv->flush & IS_CLIPPED) {
352.18578 ++			hints = MOVE_READ | __MOVE_FORCE;
352.18579 ++			if (priv->flush & FLUSH_WRITE)
352.18580 ++				hints |= MOVE_WRITE;
352.18581 ++			if (sna_pixmap_move_to_gpu(priv->pixmap, hints)) {
352.18582 ++				if (priv->flush & FLUSH_WRITE) {
352.18583 + 					kgem_bo_unclean(&sna->kgem, priv->gpu_bo);
352.18584 + 					sna_damage_all(&priv->gpu_damage, priv->pixmap);
352.18585 + 					assert(priv->cpu_damage == NULL);
352.18586 +-					priv->clear = false;
352.18587 +-					priv->cpu = false;
352.18588 ++					assert(priv->clear == false);
352.18589 + 				}
352.18590 + 			}
352.18591 + 		}
352.18592 +@@ -17184,10 +17415,46 @@ void sna_accel_flush(struct sna *sna)
352.18593 + }
352.18594 + 
352.18595 + static void
352.18596 +-sna_accel_flush_callback(CallbackListPtr *list,
352.18597 +-			 pointer user_data, pointer call_data)
352.18598 ++sna_shm_flush_callback(CallbackListPtr *list,
352.18599 ++		       pointer user_data, pointer call_data)
352.18600 + {
352.18601 +-	sna_accel_flush(user_data);
352.18602 ++	struct sna *sna = user_data;
352.18603 ++
352.18604 ++	if (!sna->needs_shm_flush)
352.18605 ++		return;
352.18606 ++
352.18607 ++	sna_accel_flush(sna);
352.18608 ++	sna->needs_shm_flush = false;
352.18609 ++}
352.18610 ++
352.18611 ++static void
352.18612 ++sna_flush_callback(CallbackListPtr *list, pointer user_data, pointer call_data)
352.18613 ++{
352.18614 ++	struct sna *sna = user_data;
352.18615 ++
352.18616 ++	if (!sna->needs_dri_flush)
352.18617 ++		return;
352.18618 ++
352.18619 ++	sna_accel_flush(sna);
352.18620 ++	sna->needs_dri_flush = false;
352.18621 ++}
352.18622 ++
352.18623 ++static void
352.18624 ++sna_event_callback(CallbackListPtr *list, pointer user_data, pointer call_data)
352.18625 ++{
352.18626 ++	EventInfoRec *eventinfo = call_data;
352.18627 ++	struct sna *sna = user_data;
352.18628 ++	int i;
352.18629 ++
352.18630 ++	if (sna->needs_dri_flush)
352.18631 ++		return;
352.18632 ++
352.18633 ++	for (i = 0; i < eventinfo->count; i++) {
352.18634 ++		if (eventinfo->events[i].u.u.type == sna->damage_event) {
352.18635 ++			sna->needs_dri_flush = true;
352.18636 ++			return;
352.18637 ++		}
352.18638 ++	}
352.18639 + }
352.18640 + 
352.18641 + static struct sna_pixmap *sna_accel_scanout(struct sna *sna)
352.18642 +@@ -17199,6 +17466,7 @@ static struct sna_pixmap *sna_accel_scanout(struct sna *sna)
352.18643 + 
352.18644 + 	assert(sna->vblank_interval);
352.18645 + 	assert(sna->front);
352.18646 ++	assert(!sna->mode.hidden);
352.18647 + 
352.18648 + 	priv = sna_pixmap(sna->front);
352.18649 + 	if (priv->gpu_bo == NULL)
352.18650 +@@ -17217,7 +17485,7 @@ static void sna_accel_disarm_timer(struct sna *sna, int id)
352.18651 + static bool has_offload_slaves(struct sna *sna)
352.18652 + {
352.18653 + #if HAS_PIXMAP_SHARING
352.18654 +-	ScreenPtr screen = sna->scrn->pScreen;
352.18655 ++	ScreenPtr screen = to_screen_from_sna(sna);
352.18656 + 	PixmapDirtyUpdatePtr dirty;
352.18657 + 
352.18658 + 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
352.18659 +@@ -17231,11 +17499,14 @@ static bool has_offload_slaves(struct sna *sna)
352.18660 + 
352.18661 + static bool has_shadow(struct sna *sna)
352.18662 + {
352.18663 +-	DamagePtr damage = sna->mode.shadow_damage;
352.18664 ++	DamagePtr damage;
352.18665 + 
352.18666 +-	if (damage == NULL)
352.18667 ++	if (!sna->mode.shadow_enabled)
352.18668 + 		return false;
352.18669 + 
352.18670 ++	damage = sna->mode.shadow_damage;
352.18671 ++	assert(damage);
352.18672 ++
352.18673 + 	DBG(("%s: has pending damage? %d, outstanding flips: %d\n",
352.18674 + 	     __FUNCTION__,
352.18675 + 	     RegionNotEmpty(DamageRegion(damage)),
352.18676 +@@ -17365,9 +17636,8 @@ static bool sna_accel_do_expire(struct sna *sna)
352.18677 + static void sna_accel_post_damage(struct sna *sna)
352.18678 + {
352.18679 + #if HAS_PIXMAP_SHARING
352.18680 +-	ScreenPtr screen = sna->scrn->pScreen;
352.18681 ++	ScreenPtr screen = to_screen_from_sna(sna);
352.18682 + 	PixmapDirtyUpdatePtr dirty;
352.18683 +-	bool flush = false;
352.18684 + 
352.18685 + 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
352.18686 + 		RegionRec region, *damage;
352.18687 +@@ -17376,8 +17646,6 @@ static void sna_accel_post_damage(struct sna *sna)
352.18688 + 		int16_t dx, dy;
352.18689 + 		int n;
352.18690 + 
352.18691 +-		assert(dirty->src == sna->front);
352.18692 +-
352.18693 + 		damage = DamageRegion(dirty->damage);
352.18694 + 		if (RegionNil(damage))
352.18695 + 			continue;
352.18696 +@@ -17477,7 +17745,14 @@ fallback:
352.18697 + 						    box, n, COPY_LAST))
352.18698 + 				goto fallback;
352.18699 + 
352.18700 +-			flush = true;
352.18701 ++			/* Before signalling the slave via ProcessPending,
352.18702 ++			 * ensure not only the batch is submitted as the
352.18703 ++			 * slave may be using the Damage callback to perform
352.18704 ++			 * its copy, but also that the memory must be coherent
352.18705 ++			 * - we need to treat it as uncached for the PCI slave
352.18706 ++			 * will bypass LLC.
352.18707 ++			 */
352.18708 ++			kgem_bo_sync__gtt(&sna->kgem, __sna_pixmap_get_bo(dst));
352.18709 + 		}
352.18710 + 
352.18711 + 		DamageRegionProcessPending(&dirty->slave_dst->drawable);
352.18712 +@@ -17485,8 +17760,6 @@ skip:
352.18713 + 		RegionUninit(&region);
352.18714 + 		DamageEmpty(dirty->damage);
352.18715 + 	}
352.18716 +-	if (flush)
352.18717 +-		kgem_submit(&sna->kgem);
352.18718 + #endif
352.18719 + }
352.18720 + 
352.18721 +@@ -17689,6 +17962,7 @@ sna_set_screen_pixmap(PixmapPtr pixmap)
352.18722 + static Bool
352.18723 + sna_create_window(WindowPtr win)
352.18724 + {
352.18725 ++	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
352.18726 + 	sna_set_window_pixmap(win, win->drawable.pScreen->devPrivate);
352.18727 + 	return TRUE;
352.18728 + }
352.18729 +@@ -17714,6 +17988,7 @@ sna_unmap_window(WindowPtr win)
352.18730 + static Bool
352.18731 + sna_destroy_window(WindowPtr win)
352.18732 + {
352.18733 ++	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
352.18734 + 	sna_video_destroy_window(win);
352.18735 + 	sna_dri2_destroy_window(win);
352.18736 + 	return TRUE;
352.18737 +@@ -17790,20 +18065,34 @@ static bool sna_option_accel_none(struct sna *sna)
352.18738 + 	if (wedged(sna))
352.18739 + 		return true;
352.18740 + 
352.18741 +-	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE))
352.18742 ++	if (!xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_ENABLE, TRUE))
352.18743 + 		return true;
352.18744 + 
352.18745 ++	if (sna->kgem.gen >= 0120)
352.18746 ++		return true;
352.18747 ++
352.18748 ++	if (!intel_option_cast_to_bool(sna->Options,
352.18749 ++				       OPTION_ACCEL_METHOD,
352.18750 ++				       !IS_DEFAULT_ACCEL_METHOD(NOACCEL)))
352.18751 ++		return false;
352.18752 ++
352.18753 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.18754 + 	s = xf86GetOptValString(sna->Options, OPTION_ACCEL_METHOD);
352.18755 + 	if (s == NULL)
352.18756 + 		return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
352.18757 + 
352.18758 + 	return strcasecmp(s, "none") == 0;
352.18759 ++#else
352.18760 ++	return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
352.18761 ++#endif
352.18762 + }
352.18763 + 
352.18764 + static bool sna_option_accel_blt(struct sna *sna)
352.18765 + {
352.18766 + 	const char *s;
352.18767 + 
352.18768 ++	assert(sna->kgem.gen < 0120);
352.18769 ++
352.18770 + 	s = xf86GetOptValString(sna->Options, OPTION_ACCEL_METHOD);
352.18771 + 	if (s == NULL)
352.18772 + 		return false;
352.18773 +@@ -17811,6 +18100,13 @@ static bool sna_option_accel_blt(struct sna *sna)
352.18774 + 	return strcasecmp(s, "blt") == 0;
352.18775 + }
352.18776 + 
352.18777 ++#if HAVE_NOTIFY_FD
352.18778 ++static void sna_accel_notify(int fd, int ready, void *data)
352.18779 ++{
352.18780 ++	sna_mode_wakeup(data);
352.18781 ++}
352.18782 ++#endif
352.18783 ++
352.18784 + bool sna_accel_init(ScreenPtr screen, struct sna *sna)
352.18785 + {
352.18786 + 	const char *backend;
352.18787 +@@ -17822,7 +18118,7 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
352.18788 + 	list_init(&sna->flush_pixmaps);
352.18789 + 	list_init(&sna->active_pixmaps);
352.18790 + 
352.18791 +-	AddGeneralSocket(sna->kgem.fd);
352.18792 ++	SetNotifyFd(sna->kgem.fd, sna_accel_notify, X_NOTIFY_READ, sna);
352.18793 + 
352.18794 + #ifdef DEBUG_MEMORY
352.18795 + 	sna->timer_expire[DEBUG_MEMORY_TIMER] = GetTimeInMillis()+ 10 * 1000;
352.18796 +@@ -17892,21 +18188,23 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
352.18797 + 		backend = "disabled";
352.18798 + 		sna->kgem.wedged = true;
352.18799 + 		sna_render_mark_wedged(sna);
352.18800 +-	} else if (sna_option_accel_blt(sna) || sna->info->gen >= 0110)
352.18801 ++	} else if (sna_option_accel_blt(sna))
352.18802 + 		(void)backend;
352.18803 +-	else if (sna->info->gen >= 0100)
352.18804 ++	else if (sna->kgem.gen >= 0110)
352.18805 ++		backend = gen9_render_init(sna, backend);
352.18806 ++	else if (sna->kgem.gen >= 0100)
352.18807 + 		backend = gen8_render_init(sna, backend);
352.18808 +-	else if (sna->info->gen >= 070)
352.18809 ++	else if (sna->kgem.gen >= 070)
352.18810 + 		backend = gen7_render_init(sna, backend);
352.18811 +-	else if (sna->info->gen >= 060)
352.18812 ++	else if (sna->kgem.gen >= 060)
352.18813 + 		backend = gen6_render_init(sna, backend);
352.18814 +-	else if (sna->info->gen >= 050)
352.18815 ++	else if (sna->kgem.gen >= 050)
352.18816 + 		backend = gen5_render_init(sna, backend);
352.18817 +-	else if (sna->info->gen >= 040)
352.18818 ++	else if (sna->kgem.gen >= 040)
352.18819 + 		backend = gen4_render_init(sna, backend);
352.18820 +-	else if (sna->info->gen >= 030)
352.18821 ++	else if (sna->kgem.gen >= 030)
352.18822 + 		backend = gen3_render_init(sna, backend);
352.18823 +-	else if (sna->info->gen >= 020)
352.18824 ++	else if (sna->kgem.gen >= 020)
352.18825 + 		backend = gen2_render_init(sna, backend);
352.18826 + 
352.18827 + 	DBG(("%s(backend=%s, prefer_gpu=%x)\n",
352.18828 +@@ -17924,8 +18222,14 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
352.18829 + 
352.18830 + void sna_accel_create(struct sna *sna)
352.18831 + {
352.18832 ++	ExtensionEntry *damage;
352.18833 ++
352.18834 + 	DBG(("%s\n", __FUNCTION__));
352.18835 + 
352.18836 ++	damage = CheckExtension("DAMAGE");
352.18837 ++	if (damage)
352.18838 ++		sna->damage_event = damage->eventBase + XDamageNotify;
352.18839 ++
352.18840 + 	if (!sna_glyphs_create(sna))
352.18841 + 		goto fail;
352.18842 + 
352.18843 +@@ -17943,27 +18247,59 @@ fail:
352.18844 + 	no_render_init(sna);
352.18845 + }
352.18846 + 
352.18847 +-void sna_accel_watch_flush(struct sna *sna, int enable)
352.18848 ++static void sna_shm_watch_flush(struct sna *sna, int enable)
352.18849 + {
352.18850 + 	DBG(("%s: enable=%d\n", __FUNCTION__, enable));
352.18851 + 	assert(enable);
352.18852 + 
352.18853 +-	if (sna->watch_flush == 0) {
352.18854 ++	if (sna->watch_shm_flush == 0) {
352.18855 ++		DBG(("%s: installing shm watchers\n", __FUNCTION__));
352.18856 ++		assert(enable > 0);
352.18857 ++
352.18858 ++		if (!AddCallback(&FlushCallback, sna_shm_flush_callback, sna))
352.18859 ++			return;
352.18860 ++
352.18861 ++		sna->watch_shm_flush++;
352.18862 ++	}
352.18863 ++
352.18864 ++	sna->watch_shm_flush += enable;
352.18865 ++}
352.18866 ++
352.18867 ++void sna_watch_flush(struct sna *sna, int enable)
352.18868 ++{
352.18869 ++	DBG(("%s: enable=%d\n", __FUNCTION__, enable));
352.18870 ++	assert(enable);
352.18871 ++
352.18872 ++	if (sna->watch_dri_flush == 0) {
352.18873 ++		int err = 0;
352.18874 ++
352.18875 + 		DBG(("%s: installing watchers\n", __FUNCTION__));
352.18876 + 		assert(enable > 0);
352.18877 +-		if (!AddCallback(&FlushCallback, sna_accel_flush_callback, sna)) {
352.18878 ++
352.18879 ++		if (!sna->damage_event)
352.18880 ++			return;
352.18881 ++
352.18882 ++		if (!AddCallback(&EventCallback, sna_event_callback, sna))
352.18883 ++			err = 1;
352.18884 ++
352.18885 ++		if (!AddCallback(&FlushCallback, sna_flush_callback, sna))
352.18886 ++			err = 1;
352.18887 ++
352.18888 ++		if (err) {
352.18889 + 			xf86DrvMsg(sna->scrn->scrnIndex, X_Error,
352.18890 + 				   "Failed to attach ourselves to the flush callbacks, expect missing synchronisation with DRI clients (e.g a compositor)\n");
352.18891 + 		}
352.18892 +-		sna->watch_flush++;
352.18893 ++
352.18894 ++		sna->watch_dri_flush++;
352.18895 + 	}
352.18896 + 
352.18897 +-	sna->watch_flush += enable;
352.18898 ++	sna->watch_dri_flush += enable;
352.18899 + }
352.18900 + 
352.18901 + void sna_accel_leave(struct sna *sna)
352.18902 + {
352.18903 + 	DBG(("%s\n", __FUNCTION__));
352.18904 ++	sna_scanout_flush(sna);
352.18905 + 
352.18906 + 	/* as root we always have permission to render */
352.18907 + 	if (geteuid() == 0)
352.18908 +@@ -17997,13 +18333,15 @@ void sna_accel_close(struct sna *sna)
352.18909 + 
352.18910 + 	sna_pixmap_expire(sna);
352.18911 + 
352.18912 +-	DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
352.18913 +-	RemoveGeneralSocket(sna->kgem.fd);
352.18914 ++	DeleteCallback(&FlushCallback, sna_shm_flush_callback, sna);
352.18915 ++	DeleteCallback(&FlushCallback, sna_flush_callback, sna);
352.18916 ++	DeleteCallback(&EventCallback, sna_event_callback, sna);
352.18917 ++	RemoveNotifyFd(sna->kgem.fd);
352.18918 + 
352.18919 + 	kgem_cleanup_cache(&sna->kgem);
352.18920 + }
352.18921 + 
352.18922 +-void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
352.18923 ++void sna_accel_block(struct sna *sna, struct timeval **tv)
352.18924 + {
352.18925 + 	sigtrap_assert_inactive();
352.18926 + 
352.18927 +@@ -18044,10 +18382,17 @@ restart:
352.18928 + 	if (sna_accel_do_debug_memory(sna))
352.18929 + 		sna_accel_debug_memory(sna);
352.18930 + 
352.18931 +-	if (sna->watch_flush == 1) {
352.18932 +-		DBG(("%s: removing watchers\n", __FUNCTION__));
352.18933 +-		DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
352.18934 +-		sna->watch_flush = 0;
352.18935 ++	if (sna->watch_shm_flush == 1) {
352.18936 ++		DBG(("%s: removing shm watchers\n", __FUNCTION__));
352.18937 ++		DeleteCallback(&FlushCallback, sna_shm_flush_callback, sna);
352.18938 ++		sna->watch_shm_flush = 0;
352.18939 ++	}
352.18940 ++
352.18941 ++	if (sna->watch_dri_flush == 1) {
352.18942 ++		DBG(("%s: removing dri watchers\n", __FUNCTION__));
352.18943 ++		DeleteCallback(&FlushCallback, sna_flush_callback, sna);
352.18944 ++		DeleteCallback(&EventCallback, sna_event_callback, sna);
352.18945 ++		sna->watch_dri_flush = 0;
352.18946 + 	}
352.18947 + 
352.18948 + 	if (sna->timer_active & 1) {
352.18949 +@@ -18083,22 +18428,6 @@ set_tv:
352.18950 + 	}
352.18951 + }
352.18952 + 
352.18953 +-void sna_accel_wakeup_handler(struct sna *sna)
352.18954 +-{
352.18955 +-	DBG(("%s: nbatch=%d, need_retire=%d, need_purge=%d\n", __FUNCTION__,
352.18956 +-	     sna->kgem.nbatch, sna->kgem.need_retire, sna->kgem.need_purge));
352.18957 +-
352.18958 +-	if (!sna->kgem.nbatch)
352.18959 +-		return;
352.18960 +-
352.18961 +-	if (kgem_is_idle(&sna->kgem)) {
352.18962 +-		DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
352.18963 +-		_kgem_submit(&sna->kgem);
352.18964 +-	}
352.18965 +-
352.18966 +-	sigtrap_assert_inactive();
352.18967 +-}
352.18968 +-
352.18969 + void sna_accel_free(struct sna *sna)
352.18970 + {
352.18971 + 	DBG(("%s\n", __FUNCTION__));
352.18972 +diff --git a/src/sna/sna_acpi.c b/src/sna/sna_acpi.c
352.18973 +index dcc0287b..643d04af 100644
352.18974 +--- a/src/sna/sna_acpi.c
352.18975 ++++ b/src/sna/sna_acpi.c
352.18976 +@@ -92,7 +92,7 @@ void _sna_acpi_wakeup(struct sna *sna)
352.18977 + 		DBG(("%s: error [%d], detaching from acpid\n", __FUNCTION__, n));
352.18978 + 
352.18979 + 		/* XXX reattach later? */
352.18980 +-		RemoveGeneralSocket(sna->acpi.fd);
352.18981 ++		RemoveNotifyFd(sna->acpi.fd);
352.18982 + 		sna_acpi_fini(sna);
352.18983 + 		return;
352.18984 + 	}
352.18985 +@@ -136,6 +136,13 @@ void _sna_acpi_wakeup(struct sna *sna)
352.18986 + 	} while (n);
352.18987 + }
352.18988 + 
352.18989 ++#if HAVE_NOTIFY_FD
352.18990 ++static void sna_acpi_notify(int fd, int read, void *data)
352.18991 ++{
352.18992 ++	_sna_acpi_wakeup(data);
352.18993 ++}
352.18994 ++#endif
352.18995 ++
352.18996 + static int read_power_state(const char *path)
352.18997 + {
352.18998 + 	DIR *dir;
352.18999 +@@ -200,7 +207,7 @@ void sna_acpi_init(struct sna *sna)
352.19000 + 
352.19001 + 	DBG(("%s: attaching to acpid\n", __FUNCTION__));
352.19002 + 
352.19003 +-	AddGeneralSocket(sna->acpi.fd);
352.19004 ++	SetNotifyFd(sna->acpi.fd, sna_acpi_notify, X_NOTIFY_READ, sna);
352.19005 + 	sna->acpi.remain = sizeof(sna->acpi.event) - 1;
352.19006 + 	sna->acpi.offset = 0;
352.19007 + 
352.19008 +diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
352.19009 +index de8f6ec3..ddd2586d 100644
352.19010 +--- a/src/sna/sna_blt.c
352.19011 ++++ b/src/sna/sna_blt.c
352.19012 +@@ -86,6 +86,11 @@ static const uint8_t fill_ROP[] = {
352.19013 + 	ROP_1
352.19014 + };
352.19015 + 
352.19016 ++static void sig_done(struct sna *sna, const struct sna_composite_op *op)
352.19017 ++{
352.19018 ++	sigtrap_put();
352.19019 ++}
352.19020 ++
352.19021 + static void nop_done(struct sna *sna, const struct sna_composite_op *op)
352.19022 + {
352.19023 + 	assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
352.19024 +@@ -129,7 +134,6 @@ static bool sna_blt_fill_init(struct sna *sna,
352.19025 + 	struct kgem *kgem = &sna->kgem;
352.19026 + 
352.19027 + 	assert(kgem_bo_can_blt (kgem, bo));
352.19028 +-	assert(bo->tiling != I915_TILING_Y);
352.19029 + 	blt->bo[0] = bo;
352.19030 + 
352.19031 + 	blt->br13 = bo->pitch;
352.19032 +@@ -183,6 +187,7 @@ static bool sna_blt_fill_init(struct sna *sna,
352.19033 + 				return false;
352.19034 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19035 + 		}
352.19036 ++		kgem_bcs_set_tiling(kgem, NULL, bo);
352.19037 + 
352.19038 + 		assert(sna->kgem.mode == KGEM_BLT);
352.19039 + 		b = kgem->batch + kgem->nbatch;
352.19040 +@@ -237,17 +242,13 @@ static bool sna_blt_fill_init(struct sna *sna,
352.19041 + 	return true;
352.19042 + }
352.19043 + 
352.19044 +-noinline static void sna_blt_fill_begin(struct sna *sna,
352.19045 +-					const struct sna_blt_state *blt)
352.19046 ++noinline static void __sna_blt_fill_begin(struct sna *sna,
352.19047 ++					  const struct sna_blt_state *blt)
352.19048 + {
352.19049 + 	struct kgem *kgem = &sna->kgem;
352.19050 + 	uint32_t *b;
352.19051 + 
352.19052 +-	if (kgem->nreloc) {
352.19053 +-		_kgem_submit(kgem);
352.19054 +-		_kgem_set_mode(kgem, KGEM_BLT);
352.19055 +-		assert(kgem->nbatch == 0);
352.19056 +-	}
352.19057 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, blt->bo[0]);
352.19058 + 
352.19059 + 	assert(kgem->mode == KGEM_BLT);
352.19060 + 	b = kgem->batch + kgem->nbatch;
352.19061 +@@ -293,6 +294,21 @@ noinline static void sna_blt_fill_begin(struct sna *sna,
352.19062 + 	}
352.19063 + }
352.19064 + 
352.19065 ++inline static void sna_blt_fill_begin(struct sna *sna,
352.19066 ++				      const struct sna_blt_state *blt)
352.19067 ++{
352.19068 ++	struct kgem *kgem = &sna->kgem;
352.19069 ++
352.19070 ++	if (kgem->nreloc) {
352.19071 ++		_kgem_submit(kgem);
352.19072 ++		_kgem_set_mode(kgem, KGEM_BLT);
352.19073 ++		kgem_bcs_set_tiling(kgem, NULL, blt->bo[0]);
352.19074 ++		assert(kgem->nbatch == 0);
352.19075 ++	}
352.19076 ++
352.19077 ++	__sna_blt_fill_begin(sna, blt);
352.19078 ++}
352.19079 ++
352.19080 + inline static void sna_blt_fill_one(struct sna *sna,
352.19081 + 				    const struct sna_blt_state *blt,
352.19082 + 				    int16_t x, int16_t y,
352.19083 +@@ -330,8 +346,8 @@ static bool sna_blt_copy_init(struct sna *sna,
352.19084 + {
352.19085 + 	struct kgem *kgem = &sna->kgem;
352.19086 + 
352.19087 +-	assert(kgem_bo_can_blt (kgem, src));
352.19088 +-	assert(kgem_bo_can_blt (kgem, dst));
352.19089 ++	assert(kgem_bo_can_blt(kgem, src));
352.19090 ++	assert(kgem_bo_can_blt(kgem, dst));
352.19091 + 
352.19092 + 	blt->bo[0] = src;
352.19093 + 	blt->bo[1] = dst;
352.19094 +@@ -370,6 +386,7 @@ static bool sna_blt_copy_init(struct sna *sna,
352.19095 + 			return false;
352.19096 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19097 + 	}
352.19098 ++	kgem_bcs_set_tiling(&sna->kgem, src, dst);
352.19099 + 
352.19100 + 	sna->blt_state.fill_bo = 0;
352.19101 + 	return true;
352.19102 +@@ -424,6 +441,7 @@ static bool sna_blt_alpha_fixup_init(struct sna *sna,
352.19103 + 			return false;
352.19104 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19105 + 	}
352.19106 ++	kgem_bcs_set_tiling(&sna->kgem, src, dst);
352.19107 + 
352.19108 + 	sna->blt_state.fill_bo = 0;
352.19109 + 	return true;
352.19110 +@@ -454,6 +472,7 @@ static void sna_blt_alpha_fixup_one(struct sna *sna,
352.19111 + 	    !kgem_check_reloc(kgem, 2)) {
352.19112 + 		_kgem_submit(kgem);
352.19113 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19114 ++		kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
352.19115 + 	}
352.19116 + 
352.19117 + 	assert(sna->kgem.mode == KGEM_BLT);
352.19118 +@@ -582,6 +601,7 @@ static void sna_blt_copy_one(struct sna *sna,
352.19119 + 	    !kgem_check_reloc(kgem, 2)) {
352.19120 + 		_kgem_submit(kgem);
352.19121 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19122 ++		kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
352.19123 + 	}
352.19124 + 
352.19125 + 	assert(sna->kgem.mode == KGEM_BLT);
352.19126 +@@ -912,8 +932,27 @@ sna_composite_mask_is_opaque(PicturePtr mask)
352.19127 + 		return is_solid(mask) && is_white(mask);
352.19128 + 	else if (!PICT_FORMAT_A(mask->format))
352.19129 + 		return true;
352.19130 +-	else
352.19131 +-		return is_solid(mask) && is_opaque_solid(mask);
352.19132 ++	else if (mask->pSourcePict) {
352.19133 ++		PictSolidFill *fill = (PictSolidFill *) mask->pSourcePict;
352.19134 ++		return (fill->color >> 24) == 0xff;
352.19135 ++	} else {
352.19136 ++		struct sna_pixmap *priv;
352.19137 ++		assert(mask->pDrawable);
352.19138 ++
352.19139 ++		if (mask->pDrawable->width  == 1 &&
352.19140 ++		    mask->pDrawable->height == 1 &&
352.19141 ++		    mask->repeat)
352.19142 ++			return pixel_is_opaque(get_pixel(mask), mask->format);
352.19143 ++
352.19144 ++		if (mask->transform)
352.19145 ++			return false;
352.19146 ++
352.19147 ++		priv = sna_pixmap_from_drawable(mask->pDrawable);
352.19148 ++		if (priv == NULL || !priv->clear)
352.19149 ++			return false;
352.19150 ++
352.19151 ++		return pixel_is_opaque(priv->clear_color, mask->format);
352.19152 ++	}
352.19153 + }
352.19154 + 
352.19155 + fastcall
352.19156 +@@ -971,6 +1010,7 @@ static void blt_composite_fill__cpu(struct sna *sna,
352.19157 + 
352.19158 + 	assert(op->dst.pixmap->devPrivate.ptr);
352.19159 + 	assert(op->dst.pixmap->devKind);
352.19160 ++	sigtrap_assert_active();
352.19161 + 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
352.19162 + 		    op->dst.pixmap->devKind / sizeof(uint32_t),
352.19163 + 		    op->dst.pixmap->drawable.bitsPerPixel,
352.19164 +@@ -990,6 +1030,7 @@ blt_composite_fill_box_no_offset__cpu(struct sna *sna,
352.19165 + 
352.19166 + 	assert(op->dst.pixmap->devPrivate.ptr);
352.19167 + 	assert(op->dst.pixmap->devKind);
352.19168 ++	sigtrap_assert_active();
352.19169 + 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
352.19170 + 		    op->dst.pixmap->devKind / sizeof(uint32_t),
352.19171 + 		    op->dst.pixmap->drawable.bitsPerPixel,
352.19172 +@@ -1010,6 +1051,7 @@ blt_composite_fill_boxes_no_offset__cpu(struct sna *sna,
352.19173 + 
352.19174 + 		assert(op->dst.pixmap->devPrivate.ptr);
352.19175 + 		assert(op->dst.pixmap->devKind);
352.19176 ++		sigtrap_assert_active();
352.19177 + 		pixman_fill(op->dst.pixmap->devPrivate.ptr,
352.19178 + 			    op->dst.pixmap->devKind / sizeof(uint32_t),
352.19179 + 			    op->dst.pixmap->drawable.bitsPerPixel,
352.19180 +@@ -1031,6 +1073,7 @@ blt_composite_fill_box__cpu(struct sna *sna,
352.19181 + 
352.19182 + 	assert(op->dst.pixmap->devPrivate.ptr);
352.19183 + 	assert(op->dst.pixmap->devKind);
352.19184 ++	sigtrap_assert_active();
352.19185 + 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
352.19186 + 		    op->dst.pixmap->devKind / sizeof(uint32_t),
352.19187 + 		    op->dst.pixmap->drawable.bitsPerPixel,
352.19188 +@@ -1052,6 +1095,7 @@ blt_composite_fill_boxes__cpu(struct sna *sna,
352.19189 + 
352.19190 + 		assert(op->dst.pixmap->devPrivate.ptr);
352.19191 + 		assert(op->dst.pixmap->devKind);
352.19192 ++		sigtrap_assert_active();
352.19193 + 		pixman_fill(op->dst.pixmap->devPrivate.ptr,
352.19194 + 			    op->dst.pixmap->devKind / sizeof(uint32_t),
352.19195 + 			    op->dst.pixmap->drawable.bitsPerPixel,
352.19196 +@@ -1159,12 +1203,15 @@ static inline void _sna_blt_maybe_clear(const struct sna_composite_op *op, const
352.19197 + 	    box->y2 - box->y1 >= op->dst.height) {
352.19198 + 		struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap);
352.19199 + 		if (op->dst.bo == priv->gpu_bo) {
352.19200 ++			sna_damage_all(&priv->gpu_damage, op->dst.pixmap);
352.19201 ++			sna_damage_destroy(&priv->cpu_damage);
352.19202 + 			priv->clear = true;
352.19203 + 			priv->clear_color = op->u.blt.pixel;
352.19204 + 			DBG(("%s: pixmap=%ld marking clear [%08x]\n",
352.19205 + 			     __FUNCTION__,
352.19206 + 			     op->dst.pixmap->drawable.serialNumber,
352.19207 + 			     op->u.blt.pixel));
352.19208 ++			((struct sna_composite_op *)op)->damage = NULL;
352.19209 + 		}
352.19210 + 	}
352.19211 + }
352.19212 +@@ -1404,6 +1451,7 @@ begin_blt(struct sna *sna,
352.19213 + 			return false;
352.19214 + 
352.19215 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.19216 ++		kgem_bcs_set_tiling(&sna->kgem, NULL, op->dst.bo);
352.19217 + 	}
352.19218 + 
352.19219 + 	return true;
352.19220 +@@ -1429,6 +1477,7 @@ prepare_blt_clear(struct sna *sna,
352.19221 + 	DBG(("%s\n", __FUNCTION__));
352.19222 + 
352.19223 + 	if (op->dst.bo == NULL) {
352.19224 ++		op->u.blt.pixel = 0;
352.19225 + 		op->blt   = blt_composite_fill__cpu;
352.19226 + 		if (op->dst.x|op->dst.y) {
352.19227 + 			op->box   = blt_composite_fill_box__cpu;
352.19228 +@@ -1439,9 +1488,8 @@ prepare_blt_clear(struct sna *sna,
352.19229 + 			op->boxes = blt_composite_fill_boxes_no_offset__cpu;
352.19230 + 			op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
352.19231 + 		}
352.19232 +-		op->done  = nop_done;
352.19233 +-		op->u.blt.pixel = 0;
352.19234 +-		return true;
352.19235 ++		op->done = sig_done;
352.19236 ++		return sigtrap_get() == 0;
352.19237 + 	}
352.19238 + 
352.19239 + 	op->blt = blt_composite_fill;
352.19240 +@@ -1484,8 +1532,8 @@ prepare_blt_fill(struct sna *sna,
352.19241 + 			op->boxes = blt_composite_fill_boxes_no_offset__cpu;
352.19242 + 			op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
352.19243 + 		}
352.19244 +-		op->done = nop_done;
352.19245 +-		return true;
352.19246 ++		op->done = sig_done;
352.19247 ++		return sigtrap_get() == 0;
352.19248 + 	}
352.19249 + 
352.19250 + 	op->blt = blt_composite_fill;
352.19251 +@@ -1668,6 +1716,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
352.19252 + 
352.19253 + 			_kgem_submit(kgem);
352.19254 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19255 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19256 + 		} while (1);
352.19257 + 	} else {
352.19258 + 		do {
352.19259 +@@ -1724,6 +1773,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
352.19260 + 
352.19261 + 			_kgem_submit(kgem);
352.19262 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19263 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19264 + 		} while (1);
352.19265 + 	}
352.19266 + 	sna_vertex_unlock(&sna->render);
352.19267 +@@ -1806,6 +1856,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
352.19268 + 
352.19269 + 			_kgem_submit(kgem);
352.19270 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19271 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19272 + 		} while (1);
352.19273 + 	} else {
352.19274 + 		do {
352.19275 +@@ -1864,6 +1915,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
352.19276 + 
352.19277 + 			_kgem_submit(kgem);
352.19278 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19279 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19280 + 		} while (1);
352.19281 + 	}
352.19282 + 	sna_vertex_unlock(&sna->render);
352.19283 +@@ -1973,6 +2025,7 @@ prepare_blt_copy(struct sna *sna,
352.19284 + 		}
352.19285 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.19286 + 	}
352.19287 ++	kgem_bcs_set_tiling(&sna->kgem, bo, op->dst.bo);
352.19288 + 
352.19289 + 	DBG(("%s\n", __FUNCTION__));
352.19290 + 
352.19291 +@@ -2396,6 +2449,9 @@ prepare_blt_put(struct sna *sna,
352.19292 + 			op->box   = blt_put_composite_box;
352.19293 + 			op->boxes = blt_put_composite_boxes;
352.19294 + 		}
352.19295 ++
352.19296 ++		op->done = nop_done;
352.19297 ++		return true;
352.19298 + 	} else {
352.19299 + 		if (alpha_fixup) {
352.19300 + 			op->u.blt.pixel = alpha_fixup;
352.19301 +@@ -2407,10 +2463,10 @@ prepare_blt_put(struct sna *sna,
352.19302 + 			op->box   = blt_put_composite_box__cpu;
352.19303 + 			op->boxes = blt_put_composite_boxes__cpu;
352.19304 + 		}
352.19305 +-	}
352.19306 +-	op->done = nop_done;
352.19307 + 
352.19308 +-	return true;
352.19309 ++		op->done = sig_done;
352.19310 ++		return sigtrap_get() == 0;
352.19311 ++	}
352.19312 + }
352.19313 + 
352.19314 + static bool
352.19315 +@@ -2544,6 +2600,7 @@ sna_blt_composite(struct sna *sna,
352.19316 + clear:
352.19317 + 		if (was_clear && sna_pixmap(tmp->dst.pixmap)->clear_color == 0) {
352.19318 + 			sna_pixmap(tmp->dst.pixmap)->clear = true;
352.19319 ++nop:
352.19320 + 			return prepare_blt_nop(sna, tmp);
352.19321 + 		}
352.19322 + 
352.19323 +@@ -2559,6 +2616,7 @@ clear:
352.19324 + 		}
352.19325 + 		tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
352.19326 + 						  &dst_box, &tmp->damage);
352.19327 ++		assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
352.19328 + 		if (tmp->dst.bo) {
352.19329 + 			if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
352.19330 + 				DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
352.19331 +@@ -2567,6 +2625,8 @@ clear:
352.19332 + 			}
352.19333 + 			if (hint & REPLACES)
352.19334 + 				kgem_bo_undo(&sna->kgem, tmp->dst.bo);
352.19335 ++			if (flags & COMPOSITE_UPLOAD)
352.19336 ++				return false;
352.19337 + 		} else {
352.19338 + 			RegionRec region;
352.19339 + 
352.19340 +@@ -2590,32 +2650,40 @@ clear:
352.19341 + 		}
352.19342 + 		if (op == PictOpOver && is_opaque_solid(src))
352.19343 + 			op = PictOpSrc;
352.19344 +-		if (op == PictOpAdd && is_white(src))
352.19345 ++		if (op == PictOpAdd &&
352.19346 ++		    PICT_FORMAT_RGB(src->format) == PICT_FORMAT_RGB(dst->format) &&
352.19347 ++		    is_white(src))
352.19348 + 			op = PictOpSrc;
352.19349 + 		if (was_clear && (op == PictOpAdd || op == PictOpOver)) {
352.19350 + 			if (sna_pixmap(tmp->dst.pixmap)->clear_color == 0)
352.19351 + 				op = PictOpSrc;
352.19352 + 			if (op == PictOpOver) {
352.19353 ++				unsigned dst_color = solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color);
352.19354 + 				color = over(get_solid_color(src, PICT_a8r8g8b8),
352.19355 +-					     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
352.19356 +-							   dst->format, PICT_a8r8g8b8));
352.19357 ++					     dst_color);
352.19358 + 				op = PictOpSrc;
352.19359 + 				DBG(("%s: precomputing solid OVER (%08x, %08x) -> %08x\n",
352.19360 + 				     __FUNCTION__, get_solid_color(src, PICT_a8r8g8b8),
352.19361 +-				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
352.19362 +-						   dst->format, PICT_a8r8g8b8),
352.19363 ++				     solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color),
352.19364 + 				     color));
352.19365 ++				if (color == dst_color)
352.19366 ++					goto nop;
352.19367 ++				else
352.19368 ++					goto fill;
352.19369 + 			}
352.19370 + 			if (op == PictOpAdd) {
352.19371 ++				unsigned dst_color = solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color);
352.19372 + 				color = add(get_solid_color(src, PICT_a8r8g8b8),
352.19373 +-					    color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
352.19374 +-							  dst->format, PICT_a8r8g8b8));
352.19375 ++					    dst_color);
352.19376 + 				op = PictOpSrc;
352.19377 + 				DBG(("%s: precomputing solid ADD (%08x, %08x) -> %08x\n",
352.19378 + 				     __FUNCTION__, get_solid_color(src, PICT_a8r8g8b8),
352.19379 +-				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
352.19380 +-						   dst->format, PICT_a8r8g8b8),
352.19381 ++				     solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color),
352.19382 + 				     color));
352.19383 ++				if (color == dst_color)
352.19384 ++					goto nop;
352.19385 ++				else
352.19386 ++					goto fill;
352.19387 + 			}
352.19388 + 		}
352.19389 + 		if (op == PictOpOutReverse && is_opaque_solid(src))
352.19390 +@@ -2649,6 +2717,7 @@ fill:
352.19391 + 		}
352.19392 + 		tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
352.19393 + 						  &dst_box, &tmp->damage);
352.19394 ++		assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
352.19395 + 		if (tmp->dst.bo) {
352.19396 + 			if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
352.19397 + 				DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
352.19398 +@@ -2657,6 +2726,8 @@ fill:
352.19399 + 			}
352.19400 + 			if (hint & REPLACES)
352.19401 + 				kgem_bo_undo(&sna->kgem, tmp->dst.bo);
352.19402 ++			if (flags & COMPOSITE_UPLOAD)
352.19403 ++				return false;
352.19404 + 		} else {
352.19405 + 			RegionRec region;
352.19406 + 
352.19407 +@@ -2720,8 +2791,8 @@ fill:
352.19408 + 	if (is_clear(src_pixmap)) {
352.19409 + 		if (src->repeat ||
352.19410 + 		    (x >= 0 && y >= 0 &&
352.19411 +-		     x + width  < src_pixmap->drawable.width &&
352.19412 +-		     y + height < src_pixmap->drawable.height)) {
352.19413 ++		     x + width  <= src_pixmap->drawable.width &&
352.19414 ++		     y + height <= src_pixmap->drawable.height)) {
352.19415 + 			color = color_convert(sna_pixmap(src_pixmap)->clear_color,
352.19416 + 					      src->format, tmp->dst.format);
352.19417 + 			goto fill;
352.19418 +@@ -2795,7 +2866,7 @@ fill:
352.19419 + 		if (src_pixmap->drawable.width  <= sna->render.max_3d_size &&
352.19420 + 		    src_pixmap->drawable.height <= sna->render.max_3d_size &&
352.19421 + 		    bo->pitch <= sna->render.max_3d_pitch &&
352.19422 +-		    (flags & COMPOSITE_FALLBACK) == 0)
352.19423 ++		    (flags & (COMPOSITE_UPLOAD | COMPOSITE_FALLBACK)) == 0)
352.19424 + 		{
352.19425 + 			return false;
352.19426 + 		}
352.19427 +@@ -2817,6 +2888,7 @@ fill:
352.19428 + 	}
352.19429 + 	tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
352.19430 + 					  &dst_box, &tmp->damage);
352.19431 ++	assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
352.19432 + 
352.19433 + 	if (tmp->dst.bo && hint & REPLACES) {
352.19434 + 		struct sna_pixmap *priv = sna_pixmap(tmp->dst.pixmap);
352.19435 +@@ -2846,7 +2918,7 @@ fallback:
352.19436 + 			DBG(("%s: fallback -- unaccelerated upload\n",
352.19437 + 			     __FUNCTION__));
352.19438 + 			goto fallback;
352.19439 +-		} else {
352.19440 ++		} else if ((flags & COMPOSITE_UPLOAD) == 0) {
352.19441 + 			ret = prepare_blt_copy(sna, tmp, bo, alpha_fixup);
352.19442 + 			if (!ret)
352.19443 + 				goto fallback;
352.19444 +@@ -3023,6 +3095,7 @@ sna_blt_composite__convert(struct sna *sna,
352.19445 + 		}
352.19446 + 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
352.19447 + 	}
352.19448 ++	kgem_bcs_set_tiling(&sna->kgem, tmp->src.bo, tmp->dst.bo);
352.19449 + 
352.19450 + 	if (alpha_fixup) {
352.19451 + 		tmp->blt   = blt_composite_copy_with_alpha;
352.19452 +@@ -3062,7 +3135,7 @@ static void sna_blt_fill_op_blt(struct sna *sna,
352.19453 + 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
352.19454 + 		const struct sna_blt_state *blt = &op->base.u.blt;
352.19455 + 
352.19456 +-		sna_blt_fill_begin(sna, blt);
352.19457 ++		__sna_blt_fill_begin(sna, blt);
352.19458 + 
352.19459 + 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
352.19460 + 		sna->blt_state.fill_pixel = blt->pixel;
352.19461 +@@ -3079,7 +3152,7 @@ fastcall static void sna_blt_fill_op_box(struct sna *sna,
352.19462 + 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
352.19463 + 		const struct sna_blt_state *blt = &op->base.u.blt;
352.19464 + 
352.19465 +-		sna_blt_fill_begin(sna, blt);
352.19466 ++		__sna_blt_fill_begin(sna, blt);
352.19467 + 
352.19468 + 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
352.19469 + 		sna->blt_state.fill_pixel = blt->pixel;
352.19470 +@@ -3097,7 +3170,7 @@ fastcall static void sna_blt_fill_op_boxes(struct sna *sna,
352.19471 + 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
352.19472 + 		const struct sna_blt_state *blt = &op->base.u.blt;
352.19473 + 
352.19474 +-		sna_blt_fill_begin(sna, blt);
352.19475 ++		__sna_blt_fill_begin(sna, blt);
352.19476 + 
352.19477 + 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
352.19478 + 		sna->blt_state.fill_pixel = blt->pixel;
352.19479 +@@ -3132,7 +3205,7 @@ fastcall static void sna_blt_fill_op_points(struct sna *sna,
352.19480 + 	DBG(("%s: %08x x %d\n", __FUNCTION__, blt->pixel, n));
352.19481 + 
352.19482 + 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
352.19483 +-		sna_blt_fill_begin(sna, blt);
352.19484 ++		__sna_blt_fill_begin(sna, blt);
352.19485 + 
352.19486 + 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
352.19487 + 		sna->blt_state.fill_pixel = blt->pixel;
352.19488 +@@ -3162,65 +3235,15 @@ fastcall static void sna_blt_fill_op_points(struct sna *sna,
352.19489 + 		assert(kgem->nbatch < kgem->surface);
352.19490 + 
352.19491 + 		if ((dx|dy) == 0) {
352.19492 +-			while (n_this_time >= 8) {
352.19493 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
352.19494 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
352.19495 +-				*((uint64_t *)b + 2) = pt_add(cmd, p+2, 0, 0);
352.19496 +-				*((uint64_t *)b + 3) = pt_add(cmd, p+3, 0, 0);
352.19497 +-				*((uint64_t *)b + 4) = pt_add(cmd, p+4, 0, 0);
352.19498 +-				*((uint64_t *)b + 5) = pt_add(cmd, p+5, 0, 0);
352.19499 +-				*((uint64_t *)b + 6) = pt_add(cmd, p+6, 0, 0);
352.19500 +-				*((uint64_t *)b + 7) = pt_add(cmd, p+7, 0, 0);
352.19501 +-				b += 16;
352.19502 +-				n_this_time -= 8;
352.19503 +-				p += 8;
352.19504 +-			}
352.19505 +-			if (n_this_time & 4) {
352.19506 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
352.19507 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
352.19508 +-				*((uint64_t *)b + 2) = pt_add(cmd, p+2, 0, 0);
352.19509 +-				*((uint64_t *)b + 3) = pt_add(cmd, p+3, 0, 0);
352.19510 +-				b += 8;
352.19511 +-				p += 4;
352.19512 +-			}
352.19513 +-			if (n_this_time & 2) {
352.19514 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
352.19515 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
352.19516 +-				b += 4;
352.19517 +-				p += 2;
352.19518 +-			}
352.19519 +-			if (n_this_time & 1)
352.19520 +-				*((uint64_t *)b + 0) = pt_add(cmd, p++, 0, 0);
352.19521 ++			do {
352.19522 ++				*(uint64_t *)b = pt_add(cmd, p++, 0, 0);
352.19523 ++				b += 2;
352.19524 ++			} while (--n_this_time);
352.19525 + 		} else {
352.19526 +-			while (n_this_time >= 8) {
352.19527 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
352.19528 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
352.19529 +-				*((uint64_t *)b + 2) = pt_add(cmd, p+2, dx, dy);
352.19530 +-				*((uint64_t *)b + 3) = pt_add(cmd, p+3, dx, dy);
352.19531 +-				*((uint64_t *)b + 4) = pt_add(cmd, p+4, dx, dy);
352.19532 +-				*((uint64_t *)b + 5) = pt_add(cmd, p+5, dx, dy);
352.19533 +-				*((uint64_t *)b + 6) = pt_add(cmd, p+6, dx, dy);
352.19534 +-				*((uint64_t *)b + 7) = pt_add(cmd, p+7, dx, dy);
352.19535 +-				b += 16;
352.19536 +-				n_this_time -= 8;
352.19537 +-				p += 8;
352.19538 +-			}
352.19539 +-			if (n_this_time & 4) {
352.19540 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
352.19541 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
352.19542 +-				*((uint64_t *)b + 2) = pt_add(cmd, p+2, dx, dy);
352.19543 +-				*((uint64_t *)b + 3) = pt_add(cmd, p+3, dx, dy);
352.19544 +-				b += 8;
352.19545 +-				p += 8;
352.19546 +-			}
352.19547 +-			if (n_this_time & 2) {
352.19548 +-				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
352.19549 +-				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
352.19550 +-				b += 4;
352.19551 +-				p += 2;
352.19552 +-			}
352.19553 +-			if (n_this_time & 1)
352.19554 +-				*((uint64_t *)b + 0) = pt_add(cmd, p++, dx, dy);
352.19555 ++			do {
352.19556 ++				*(uint64_t *)b = pt_add(cmd, p++, dx, dy);
352.19557 ++				b += 2;
352.19558 ++			} while (--n_this_time);
352.19559 + 		}
352.19560 + 
352.19561 + 		if (!n)
352.19562 +@@ -3414,6 +3437,7 @@ static bool sna_blt_fill_box(struct sna *sna, uint8_t alu,
352.19563 + 
352.19564 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19565 + 	}
352.19566 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.19567 + 
352.19568 + 	assert(kgem_check_batch(kgem, 6));
352.19569 + 	assert(kgem_check_reloc(kgem, 1));
352.19570 +@@ -3520,6 +3544,8 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
352.19571 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19572 + 		}
352.19573 + 
352.19574 ++		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.19575 ++
352.19576 + 		assert(sna->kgem.mode == KGEM_BLT);
352.19577 + 		b = kgem->batch + kgem->nbatch;
352.19578 + 		if (kgem->gen >= 0100) {
352.19579 +@@ -3608,6 +3634,7 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
352.19580 + 
352.19581 + 			_kgem_submit(kgem);
352.19582 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19583 ++			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
352.19584 + 
352.19585 + 			assert(sna->kgem.mode == KGEM_BLT);
352.19586 + 			b = kgem->batch + kgem->nbatch;
352.19587 +@@ -3754,6 +3781,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
352.19588 + 		}
352.19589 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.19590 + 	}
352.19591 ++	kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19592 + 
352.19593 + 	if ((dst_dx | dst_dy) == 0) {
352.19594 + 		if (kgem->gen >= 0100) {
352.19595 +@@ -3814,6 +3842,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
352.19596 + 
352.19597 + 				_kgem_submit(kgem);
352.19598 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.19599 ++				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19600 + 			} while (1);
352.19601 + 		} else {
352.19602 + 			uint64_t hdr = (uint64_t)br13 << 32 | cmd | 6;
352.19603 +@@ -3871,6 +3900,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
352.19604 + 
352.19605 + 				_kgem_submit(kgem);
352.19606 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.19607 ++				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19608 + 			} while (1);
352.19609 + 		}
352.19610 + 	} else {
352.19611 +@@ -3932,6 +3962,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
352.19612 + 
352.19613 + 				_kgem_submit(kgem);
352.19614 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.19615 ++				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19616 + 			} while (1);
352.19617 + 		} else {
352.19618 + 			cmd |= 6;
352.19619 +@@ -3989,6 +4020,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
352.19620 + 
352.19621 + 				_kgem_submit(kgem);
352.19622 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.19623 ++				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19624 + 			} while (1);
352.19625 + 		}
352.19626 + 	}
352.19627 +@@ -4095,6 +4127,7 @@ bool sna_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
352.19628 + 		    !kgem_check_reloc(kgem, 2)) {
352.19629 + 			_kgem_submit(kgem);
352.19630 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.19631 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
352.19632 + 		}
352.19633 + 
352.19634 + 		assert(sna->kgem.mode == KGEM_BLT);
352.19635 +@@ -4190,6 +4223,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
352.19636 + 		DBG(("%s: dst == src\n", __FUNCTION__));
352.19637 + 
352.19638 + 		if (src_bo->tiling == I915_TILING_Y &&
352.19639 ++		    !sna->kgem.can_blt_y &&
352.19640 + 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
352.19641 + 			struct kgem_bo *bo;
352.19642 + 
352.19643 +@@ -4237,6 +4271,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
352.19644 + 		}
352.19645 + 	} else {
352.19646 + 		if (src_bo->tiling == I915_TILING_Y &&
352.19647 ++		    !sna->kgem.can_blt_y &&
352.19648 + 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
352.19649 + 			DBG(("%s: src is y-tiled\n", __FUNCTION__));
352.19650 + 			if (src->type != DRAWABLE_PIXMAP)
352.19651 +@@ -4251,6 +4286,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
352.19652 + 		}
352.19653 + 
352.19654 + 		if (dst_bo->tiling == I915_TILING_Y &&
352.19655 ++		    !sna->kgem.can_blt_y &&
352.19656 + 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, dst_bo)) {
352.19657 + 			DBG(("%s: dst is y-tiled\n", __FUNCTION__));
352.19658 + 			if (dst->type != DRAWABLE_PIXMAP)
352.19659 +diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
352.19660 +index f01f020e..1da8c291 100644
352.19661 +--- a/src/sna/sna_composite.c
352.19662 ++++ b/src/sna/sna_composite.c
352.19663 +@@ -452,6 +452,8 @@ static void apply_damage(struct sna_composite_op *op, RegionPtr region)
352.19664 + 		op->damage = NULL;
352.19665 + 	} else
352.19666 + 		sna_damage_add(op->damage, region);
352.19667 ++
352.19668 ++	assert(!op->damage || !DAMAGE_IS_ALL(*op->damage));
352.19669 + }
352.19670 + 
352.19671 + static inline bool use_cpu(PixmapPtr pixmap, struct sna_pixmap *priv,
352.19672 +@@ -653,8 +655,9 @@ sna_composite(CARD8 op,
352.19673 + 	RegionRec region;
352.19674 + 	int dx, dy;
352.19675 + 
352.19676 +-	DBG(("%s(%d src=%ld+(%d, %d), mask=%ld+(%d, %d), dst=%ld+(%d, %d)+(%d, %d), size=(%d, %d)\n",
352.19677 +-	     __FUNCTION__, op,
352.19678 ++	DBG(("%s(pixmap=%ld, op=%d, src=%ld+(%d, %d), mask=%ld+(%d, %d), dst=%ld+(%d, %d)+(%d, %d), size=(%d, %d)\n",
352.19679 ++	     __FUNCTION__,
352.19680 ++	     pixmap->drawable.serialNumber, op,
352.19681 + 	     get_picture_id(src), src_x, src_y,
352.19682 + 	     get_picture_id(mask), mask_x, mask_y,
352.19683 + 	     get_picture_id(dst), dst_x, dst_y,
352.19684 +@@ -673,13 +676,6 @@ sna_composite(CARD8 op,
352.19685 + 			src = sna->clear;
352.19686 + 	}
352.19687 + 
352.19688 +-	if (mask && sna_composite_mask_is_opaque(mask)) {
352.19689 +-		DBG(("%s: removing opaque %smask\n",
352.19690 +-		     __FUNCTION__,
352.19691 +-		     mask->componentAlpha && PICT_FORMAT_RGB(mask->format) ? "CA " : ""));
352.19692 +-		mask = NULL;
352.19693 +-	}
352.19694 +-
352.19695 + 	if (!sna_compute_composite_region(&region,
352.19696 + 					  src, mask, dst,
352.19697 + 					  src_x,  src_y,
352.19698 +@@ -688,6 +684,13 @@ sna_composite(CARD8 op,
352.19699 + 					  width,  height))
352.19700 + 		return;
352.19701 + 
352.19702 ++	if (mask && sna_composite_mask_is_opaque(mask)) {
352.19703 ++		DBG(("%s: removing opaque %smask\n",
352.19704 ++		     __FUNCTION__,
352.19705 ++		     mask->componentAlpha && PICT_FORMAT_RGB(mask->format) ? "CA " : ""));
352.19706 ++		mask = NULL;
352.19707 ++	}
352.19708 ++
352.19709 + 	if (NO_COMPOSITE)
352.19710 + 		goto fallback;
352.19711 + 
352.19712 +@@ -756,6 +759,7 @@ sna_composite(CARD8 op,
352.19713 + 		DBG(("%s: fallback due unhandled composite op\n", __FUNCTION__));
352.19714 + 		goto fallback;
352.19715 + 	}
352.19716 ++	assert(!tmp.damage || !DAMAGE_IS_ALL(*tmp.damage));
352.19717 + 
352.19718 + 	if (region.data == NULL)
352.19719 + 		tmp.box(sna, &tmp, &region.extents);
352.19720 +@@ -797,8 +801,10 @@ sna_composite_rectangles(CARD8		 op,
352.19721 + 	int i, num_boxes;
352.19722 + 	unsigned hint;
352.19723 + 
352.19724 +-	DBG(("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n",
352.19725 +-	     __FUNCTION__, op,
352.19726 ++	DBG(("%s(pixmap=%ld, op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n",
352.19727 ++	     __FUNCTION__,
352.19728 ++	     get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber,
352.19729 ++	     op,
352.19730 + 	     (color->alpha >> 8 << 24) |
352.19731 + 	     (color->red   >> 8 << 16) |
352.19732 + 	     (color->green >> 8 << 8) |
352.19733 +@@ -814,38 +820,40 @@ sna_composite_rectangles(CARD8		 op,
352.19734 + 		return;
352.19735 + 	}
352.19736 + 
352.19737 +-	if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) {
352.19738 +-		switch (op) {
352.19739 +-		case PictOpOver:
352.19740 +-		case PictOpOutReverse:
352.19741 +-		case PictOpAdd:
352.19742 +-			return;
352.19743 +-		case  PictOpInReverse:
352.19744 +-		case  PictOpSrc:
352.19745 +-			op = PictOpClear;
352.19746 +-			break;
352.19747 +-		case  PictOpAtopReverse:
352.19748 +-			op = PictOpOut;
352.19749 +-			break;
352.19750 +-		case  PictOpXor:
352.19751 +-			op = PictOpOverReverse;
352.19752 +-			break;
352.19753 +-		}
352.19754 +-	}
352.19755 + 	if (color->alpha <= 0x00ff) {
352.19756 +-		switch (op) {
352.19757 +-		case PictOpOver:
352.19758 +-		case PictOpOutReverse:
352.19759 +-			return;
352.19760 +-		case  PictOpInReverse:
352.19761 +-			op = PictOpClear;
352.19762 +-			break;
352.19763 +-		case  PictOpAtopReverse:
352.19764 +-			op = PictOpOut;
352.19765 +-			break;
352.19766 +-		case  PictOpXor:
352.19767 +-			op = PictOpOverReverse;
352.19768 +-			break;
352.19769 ++		if (PICT_FORMAT_TYPE(dst->format) == PICT_TYPE_A ||
352.19770 ++		    (color->red|color->green|color->blue) <= 0x00ff) {
352.19771 ++			switch (op) {
352.19772 ++			case PictOpOver:
352.19773 ++			case PictOpOutReverse:
352.19774 ++			case PictOpAdd:
352.19775 ++				return;
352.19776 ++			case  PictOpInReverse:
352.19777 ++			case  PictOpSrc:
352.19778 ++				op = PictOpClear;
352.19779 ++				break;
352.19780 ++			case  PictOpAtopReverse:
352.19781 ++				op = PictOpOut;
352.19782 ++				break;
352.19783 ++			case  PictOpXor:
352.19784 ++				op = PictOpOverReverse;
352.19785 ++				break;
352.19786 ++			}
352.19787 ++		} else {
352.19788 ++			switch (op) {
352.19789 ++			case PictOpOver:
352.19790 ++			case PictOpOutReverse:
352.19791 ++				return;
352.19792 ++			case  PictOpInReverse:
352.19793 ++				op = PictOpClear;
352.19794 ++				break;
352.19795 ++			case  PictOpAtopReverse:
352.19796 ++				op = PictOpOut;
352.19797 ++				break;
352.19798 ++			case  PictOpXor:
352.19799 ++				op = PictOpOverReverse;
352.19800 ++				break;
352.19801 ++			}
352.19802 + 		}
352.19803 + 	} else if (color->alpha >= 0xff00) {
352.19804 + 		switch (op) {
352.19805 +@@ -863,11 +871,16 @@ sna_composite_rectangles(CARD8		 op,
352.19806 + 		case  PictOpXor:
352.19807 + 			op = PictOpOut;
352.19808 + 			break;
352.19809 ++		case PictOpAdd:
352.19810 ++			if (PICT_FORMAT_TYPE(dst->format) == PICT_TYPE_A ||
352.19811 ++			    (color->red&color->green&color->blue) >= 0xff00)
352.19812 ++				op = PictOpSrc;
352.19813 ++			break;
352.19814 + 		}
352.19815 + 	}
352.19816 + 
352.19817 + 	/* Avoid reducing overlapping translucent rectangles */
352.19818 +-	if (op == PictOpOver &&
352.19819 ++	if ((op == PictOpOver || op == PictOpAdd) &&
352.19820 + 	    num_rects == 1 &&
352.19821 + 	    sna_drawable_is_clear(dst->pDrawable))
352.19822 + 		op = PictOpSrc;
352.19823 +@@ -979,6 +992,9 @@ sna_composite_rectangles(CARD8		 op,
352.19824 + 			bool ok;
352.19825 + 
352.19826 + 			if (op == PictOpClear) {
352.19827 ++				if (priv->clear_color == 0)
352.19828 ++					goto done;
352.19829 ++
352.19830 + 				ok = sna_get_pixel_from_rgba(&pixel,
352.19831 + 							     0, 0, 0, 0,
352.19832 + 							     dst->format);
352.19833 +@@ -990,8 +1006,11 @@ sna_composite_rectangles(CARD8		 op,
352.19834 + 							     color->alpha,
352.19835 + 							     dst->format);
352.19836 + 			}
352.19837 +-			if (ok && priv->clear_color == pixel)
352.19838 ++			if (ok && priv->clear_color == pixel) {
352.19839 ++				DBG(("%s: matches current clear, skipping\n",
352.19840 ++				     __FUNCTION__));
352.19841 + 				goto done;
352.19842 ++			}
352.19843 + 		}
352.19844 + 
352.19845 + 		if (region.data == NULL) {
352.19846 +diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
352.19847 +index 272e83bc..d5c727ee 100644
352.19848 +--- a/src/sna/sna_damage.h
352.19849 ++++ b/src/sna/sna_damage.h
352.19850 +@@ -267,7 +267,7 @@ int _sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes);
352.19851 + static inline int
352.19852 + sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes)
352.19853 + {
352.19854 +-	assert(damage);
352.19855 ++	assert(DAMAGE_PTR(damage));
352.19856 + 
352.19857 + 	if (DAMAGE_IS_ALL(damage)) {
352.19858 + 		*boxes = &DAMAGE_PTR(damage)->extents;
352.19859 +@@ -322,7 +322,8 @@ static inline void sna_damage_destroy(struct sna_damage **damage)
352.19860 + 	if (*damage == NULL)
352.19861 + 		return;
352.19862 + 
352.19863 +-	__sna_damage_destroy(DAMAGE_PTR(*damage));
352.19864 ++	if (DAMAGE_PTR(*damage))
352.19865 ++		__sna_damage_destroy(DAMAGE_PTR(*damage));
352.19866 + 	*damage = NULL;
352.19867 + }
352.19868 + 
352.19869 +diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
352.19870 +index 4b218b70..9b77550e 100644
352.19871 +--- a/src/sna/sna_display.c
352.19872 ++++ b/src/sna/sna_display.c
352.19873 +@@ -39,6 +39,25 @@
352.19874 + #include <errno.h>
352.19875 + #include <poll.h>
352.19876 + #include <ctype.h>
352.19877 ++#include <dirent.h>
352.19878 ++
352.19879 ++#if HAVE_ALLOCA_H
352.19880 ++#include <alloca.h>
352.19881 ++#elif defined __GNUC__
352.19882 ++#define alloca __builtin_alloca
352.19883 ++#elif defined _AIX
352.19884 ++#define alloca __alloca
352.19885 ++#elif defined _MSC_VER
352.19886 ++#include <malloc.h>
352.19887 ++#define alloca _alloca
352.19888 ++#else
352.19889 ++void *alloca(size_t);
352.19890 ++#endif
352.19891 ++
352.19892 ++#define _PARSE_EDID_
352.19893 ++/* Jump through a few hoops in order to fixup EDIDs */
352.19894 ++#undef VERSION
352.19895 ++#undef REVISION
352.19896 + 
352.19897 + #include "sna.h"
352.19898 + #include "sna_reg.h"
352.19899 +@@ -72,6 +91,10 @@
352.19900 + #include <memcheck.h>
352.19901 + #endif
352.19902 + 
352.19903 ++#define FAIL_CURSOR_IOCTL 0
352.19904 ++
352.19905 ++#define COLDPLUG_DELAY_MS 2000
352.19906 ++
352.19907 + /* Minor discrepancy between 32-bit/64-bit ABI in old kernels */
352.19908 + union compat_mode_get_connector{
352.19909 + 	struct drm_mode_get_connector conn;
352.19910 +@@ -88,6 +111,8 @@ union compat_mode_get_connector{
352.19911 + #define DEFAULT_DPI 96
352.19912 + #endif
352.19913 + 
352.19914 ++#define OUTPUT_STATUS_CACHE_MS 15000
352.19915 ++
352.19916 + #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
352.19917 + 
352.19918 + #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
352.19919 +@@ -106,33 +131,87 @@ struct local_mode_obj_get_properties {
352.19920 + };
352.19921 + #define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee
352.19922 + 
352.19923 +-#if 0
352.19924 ++struct local_mode_set_plane {
352.19925 ++	uint32_t plane_id;
352.19926 ++	uint32_t crtc_id;
352.19927 ++	uint32_t fb_id; /* fb object contains surface format type */
352.19928 ++	uint32_t flags;
352.19929 ++
352.19930 ++	/* Signed dest location allows it to be partially off screen */
352.19931 ++	int32_t crtc_x, crtc_y;
352.19932 ++	uint32_t crtc_w, crtc_h;
352.19933 ++
352.19934 ++	/* Source values are 16.16 fixed point */
352.19935 ++	uint32_t src_x, src_y;
352.19936 ++	uint32_t src_h, src_w;
352.19937 ++};
352.19938 ++#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane)
352.19939 ++
352.19940 ++struct local_mode_get_plane {
352.19941 ++	uint32_t plane_id;
352.19942 ++
352.19943 ++	uint32_t crtc_id;
352.19944 ++	uint32_t fb_id;
352.19945 ++
352.19946 ++	uint32_t possible_crtcs;
352.19947 ++	uint32_t gamma_size;
352.19948 ++
352.19949 ++	uint32_t count_format_types;
352.19950 ++	uint64_t format_type_ptr;
352.19951 ++};
352.19952 ++#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane)
352.19953 ++
352.19954 ++struct local_mode_get_plane_res {
352.19955 ++	uint64_t plane_id_ptr;
352.19956 ++	uint64_t count_planes;
352.19957 ++};
352.19958 ++#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
352.19959 ++
352.19960 ++#if 1
352.19961 + #define __DBG DBG
352.19962 + #else
352.19963 + #define __DBG(x)
352.19964 + #endif
352.19965 + 
352.19966 ++#define DBG_NATIVE_ROTATION ~0 /* minimum RR_Rotate_0 */
352.19967 ++
352.19968 + extern XF86ConfigPtr xf86configptr;
352.19969 + 
352.19970 ++struct sna_cursor {
352.19971 ++	struct sna_cursor *next;
352.19972 ++	uint32_t *image;
352.19973 ++	bool transformed;
352.19974 ++	Rotation rotation;
352.19975 ++	int ref;
352.19976 ++	int size;
352.19977 ++	int last_width;
352.19978 ++	int last_height;
352.19979 ++	unsigned handle;
352.19980 ++	unsigned serial;
352.19981 ++	unsigned alloc;
352.19982 ++};
352.19983 ++
352.19984 + struct sna_crtc {
352.19985 ++	unsigned long flags;
352.19986 ++	uint32_t id;
352.19987 + 	xf86CrtcPtr base;
352.19988 + 	struct drm_mode_modeinfo kmode;
352.19989 +-	int dpms_mode;
352.19990 + 	PixmapPtr slave_pixmap;
352.19991 + 	DamagePtr slave_damage;
352.19992 +-	struct kgem_bo *bo, *shadow_bo, *client_bo;
352.19993 ++	struct kgem_bo *bo, *shadow_bo, *client_bo, *cache_bo;
352.19994 + 	struct sna_cursor *cursor;
352.19995 + 	unsigned int last_cursor_size;
352.19996 + 	uint32_t offset;
352.19997 + 	bool shadow;
352.19998 + 	bool fallback_shadow;
352.19999 + 	bool transform;
352.20000 ++	bool cursor_transform;
352.20001 ++	bool hwcursor;
352.20002 + 	bool flip_pending;
352.20003 +-	uint8_t id;
352.20004 +-	uint8_t pipe;
352.20005 + 
352.20006 +-	RegionRec client_damage; /* XXX overlap with shadow damage? */
352.20007 ++	struct pict_f_transform cursor_to_fb, fb_to_cursor;
352.20008 + 
352.20009 ++	RegionRec crtc_damage;
352.20010 + 	uint16_t shadow_bo_width, shadow_bo_height;
352.20011 + 
352.20012 + 	uint32_t rotation;
352.20013 +@@ -143,7 +222,9 @@ struct sna_crtc {
352.20014 + 			uint32_t supported;
352.20015 + 			uint32_t current;
352.20016 + 		} rotation;
352.20017 +-	} primary, sprite;
352.20018 ++		struct list link;
352.20019 ++	} primary;
352.20020 ++	struct list sprites;
352.20021 + 
352.20022 + 	uint32_t mode_serial, flip_serial;
352.20023 + 
352.20024 +@@ -173,21 +254,33 @@ struct sna_output {
352.20025 + 
352.20026 + 	unsigned int is_panel : 1;
352.20027 + 	unsigned int add_default_modes : 1;
352.20028 ++	int connector_type;
352.20029 ++	int connector_type_id;
352.20030 ++
352.20031 ++	uint32_t link_status_idx;
352.20032 + 
352.20033 + 	uint32_t edid_idx;
352.20034 + 	uint32_t edid_blob_id;
352.20035 + 	uint32_t edid_len;
352.20036 + 	void *edid_raw;
352.20037 ++	xf86MonPtr fake_edid_mon;
352.20038 ++	void *fake_edid_raw;
352.20039 + 
352.20040 + 	bool has_panel_limits;
352.20041 + 	int panel_hdisplay;
352.20042 + 	int panel_vdisplay;
352.20043 + 
352.20044 + 	uint32_t dpms_id;
352.20045 +-	int dpms_mode;
352.20046 ++	uint8_t dpms_mode;
352.20047 + 	struct backlight backlight;
352.20048 + 	int backlight_active_level;
352.20049 + 
352.20050 ++	uint32_t last_detect;
352.20051 ++	uint32_t status;
352.20052 ++	unsigned int hotplug_count;
352.20053 ++	bool update_properties;
352.20054 ++	bool reprobe;
352.20055 ++
352.20056 + 	int num_modes;
352.20057 + 	struct drm_mode_modeinfo *modes;
352.20058 + 
352.20059 +@@ -218,13 +311,91 @@ enum { /* XXX copied from hw/xfree86/modes/xf86Crtc.c */
352.20060 + 	OPTION_DEFAULT_MODES,
352.20061 + };
352.20062 + 
352.20063 ++static void __sna_output_dpms(xf86OutputPtr output, int dpms, int fixup);
352.20064 + static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
352.20065 ++static bool sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc,
352.20066 ++			  struct kgem_bo *bo, int x, int y);
352.20067 + 
352.20068 + static bool is_zaphod(ScrnInfoPtr scrn)
352.20069 + {
352.20070 + 	return xf86IsEntityShared(scrn->entityList[0]);
352.20071 + }
352.20072 + 
352.20073 ++static bool
352.20074 ++sna_zaphod_match(struct sna *sna, const char *output)
352.20075 ++{
352.20076 ++	const char *s, *colon;
352.20077 ++	char t[20];
352.20078 ++	unsigned int i = 0;
352.20079 ++
352.20080 ++	s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
352.20081 ++	if (s == NULL)
352.20082 ++		return false;
352.20083 ++
352.20084 ++	colon = strchr(s, ':');
352.20085 ++	if (colon) /* Skip over the ZaphodPipes */
352.20086 ++		s = colon + 1;
352.20087 ++
352.20088 ++	do {
352.20089 ++		/* match any outputs in a comma list, stopping at whitespace */
352.20090 ++		switch (*s) {
352.20091 ++		case '\0':
352.20092 ++			t[i] = '\0';
352.20093 ++			return strcmp(t, output) == 0;
352.20094 ++
352.20095 ++		case ',':
352.20096 ++			t[i] ='\0';
352.20097 ++			if (strcmp(t, output) == 0)
352.20098 ++				return TRUE;
352.20099 ++			i = 0;
352.20100 ++			break;
352.20101 ++
352.20102 ++		case ' ':
352.20103 ++		case '\t':
352.20104 ++		case '\n':
352.20105 ++		case '\r':
352.20106 ++			break;
352.20107 ++
352.20108 ++		default:
352.20109 ++			t[i++] = *s;
352.20110 ++			break;
352.20111 ++		}
352.20112 ++
352.20113 ++		s++;
352.20114 ++	} while (i < sizeof(t));
352.20115 ++
352.20116 ++	return false;
352.20117 ++}
352.20118 ++
352.20119 ++static unsigned
352.20120 ++get_zaphod_crtcs(struct sna *sna)
352.20121 ++{
352.20122 ++	const char *str, *colon;
352.20123 ++	unsigned crtcs = 0;
352.20124 ++
352.20125 ++	str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
352.20126 ++	if (str == NULL || (colon = strchr(str, ':')) == NULL) {
352.20127 ++		DBG(("%s: no zaphod pipes, using screen number: %x\n",
352.20128 ++		     __FUNCTION__,
352.20129 ++		     sna->scrn->confScreen->device->screen));
352.20130 ++		return 1 << sna->scrn->confScreen->device->screen;
352.20131 ++	}
352.20132 ++
352.20133 ++	DBG(("%s: ZaphodHeads='%s'\n", __FUNCTION__, str));
352.20134 ++	while (str < colon) {
352.20135 ++		char *end;
352.20136 ++		unsigned crtc = strtoul(str, &end, 0);
352.20137 ++		if (end == str)
352.20138 ++			break;
352.20139 ++		DBG(("%s: adding CRTC %d to zaphod pipes\n",
352.20140 ++		     __FUNCTION__, crtc));
352.20141 ++		crtcs |= 1 << crtc;
352.20142 ++		str = end + 1;
352.20143 ++	}
352.20144 ++	DBG(("%s: ZaphodPipes=%x\n", __FUNCTION__, crtcs));
352.20145 ++	return crtcs;
352.20146 ++}
352.20147 ++
352.20148 + inline static unsigned count_to_mask(int x)
352.20149 + {
352.20150 + 	return (1 << x) - 1;
352.20151 +@@ -247,6 +418,21 @@ static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
352.20152 + 	return crtc->driver_private;
352.20153 + }
352.20154 + 
352.20155 ++static inline unsigned __sna_crtc_pipe(struct sna_crtc *crtc)
352.20156 ++{
352.20157 ++	return crtc->flags >> 8 & 0xff;
352.20158 ++}
352.20159 ++
352.20160 ++static inline unsigned __sna_crtc_id(struct sna_crtc *crtc)
352.20161 ++{
352.20162 ++	return crtc->id;
352.20163 ++}
352.20164 ++
352.20165 ++uint32_t sna_crtc_id(xf86CrtcPtr crtc)
352.20166 ++{
352.20167 ++	return __sna_crtc_id(to_sna_crtc(crtc));
352.20168 ++}
352.20169 ++
352.20170 + static inline bool event_pending(int fd)
352.20171 + {
352.20172 + 	struct pollfd pfd;
352.20173 +@@ -268,29 +454,37 @@ static inline uint32_t fb_id(struct kgem_bo *bo)
352.20174 + 	return bo->delta;
352.20175 + }
352.20176 + 
352.20177 +-uint32_t sna_crtc_id(xf86CrtcPtr crtc)
352.20178 ++unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc)
352.20179 + {
352.20180 +-	if (to_sna_crtc(crtc) == NULL)
352.20181 +-		return 0;
352.20182 +-	return to_sna_crtc(crtc)->id;
352.20183 +-}
352.20184 ++	struct plane *sprite;
352.20185 ++	unsigned count;
352.20186 + 
352.20187 +-int sna_crtc_to_pipe(xf86CrtcPtr crtc)
352.20188 +-{
352.20189 +-	assert(to_sna_crtc(crtc));
352.20190 +-	return to_sna_crtc(crtc)->pipe;
352.20191 ++	count = 0;
352.20192 ++	list_for_each_entry(sprite, &to_sna_crtc(crtc)->sprites, link)
352.20193 ++		count++;
352.20194 ++
352.20195 ++	return count;
352.20196 + }
352.20197 + 
352.20198 +-uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
352.20199 ++static struct plane *lookup_sprite(struct sna_crtc *crtc, unsigned idx)
352.20200 + {
352.20201 +-	assert(to_sna_crtc(crtc));
352.20202 +-	return to_sna_crtc(crtc)->sprite.id;
352.20203 ++	struct plane *sprite;
352.20204 ++
352.20205 ++	list_for_each_entry(sprite, &crtc->sprites, link)
352.20206 ++		if (idx-- == 0)
352.20207 ++			return sprite;
352.20208 ++
352.20209 ++	return NULL;
352.20210 + }
352.20211 + 
352.20212 +-bool sna_crtc_is_on(xf86CrtcPtr crtc)
352.20213 ++uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx)
352.20214 + {
352.20215 ++	struct plane *sprite;
352.20216 ++
352.20217 + 	assert(to_sna_crtc(crtc));
352.20218 +-	return to_sna_crtc(crtc)->bo != NULL;
352.20219 ++
352.20220 ++	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
352.20221 ++	return sprite ? sprite->id : 0;
352.20222 + }
352.20223 + 
352.20224 + bool sna_crtc_is_transformed(xf86CrtcPtr crtc)
352.20225 +@@ -299,34 +493,48 @@ bool sna_crtc_is_transformed(xf86CrtcPtr crtc)
352.20226 + 	return to_sna_crtc(crtc)->transform;
352.20227 + }
352.20228 + 
352.20229 +-static inline uint64_t msc64(struct sna_crtc *sna_crtc, uint32_t seq)
352.20230 ++static inline bool msc64(struct sna_crtc *sna_crtc, uint32_t seq, uint64_t *msc)
352.20231 + {
352.20232 ++	bool record = true;
352.20233 + 	if (seq < sna_crtc->last_seq) {
352.20234 + 		if (sna_crtc->last_seq - seq > 0x40000000) {
352.20235 + 			sna_crtc->wrap_seq++;
352.20236 + 			DBG(("%s: pipe=%d wrapped; was %u, now %u, wraps=%u\n",
352.20237 +-			     __FUNCTION__, sna_crtc->pipe,
352.20238 ++			     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
352.20239 + 			     sna_crtc->last_seq, seq, sna_crtc->wrap_seq));
352.20240 +-		} else  {
352.20241 +-			ERR(("%s: pipe=%d msc went backwards; was %u, now %u\n",
352.20242 +-			     __FUNCTION__, sna_crtc->pipe, sna_crtc->last_seq, seq));
352.20243 +-			seq = sna_crtc->last_seq;
352.20244 ++		} else {
352.20245 ++			DBG(("%s: pipe=%d msc went backwards; was %u, now %u; ignoring for last_swap\n",
352.20246 ++			     __FUNCTION__, __sna_crtc_pipe(sna_crtc), sna_crtc->last_seq, seq));
352.20247 ++
352.20248 ++			record = false;
352.20249 + 		}
352.20250 + 	}
352.20251 +-	sna_crtc->last_seq = seq;
352.20252 +-	return (uint64_t)sna_crtc->wrap_seq << 32 | seq;
352.20253 ++	*msc = (uint64_t)sna_crtc->wrap_seq << 32 | seq;
352.20254 ++	return record;
352.20255 + }
352.20256 + 
352.20257 + uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
352.20258 + 			      int tv_sec, int tv_usec, unsigned seq)
352.20259 + {
352.20260 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.20261 ++	uint64_t msc;
352.20262 ++
352.20263 + 	assert(sna_crtc);
352.20264 +-	DBG(("%s: recording last swap on pipe=%d, frame %d, time %d.%06d\n",
352.20265 +-	     __FUNCTION__, sna_crtc->pipe, seq, tv_sec, tv_usec));
352.20266 +-	sna_crtc->swap.tv_sec = tv_sec;
352.20267 +-	sna_crtc->swap.tv_usec = tv_usec;
352.20268 +-	return sna_crtc->swap.msc = msc64(sna_crtc, seq);
352.20269 ++
352.20270 ++	if (msc64(sna_crtc, seq, &msc)) {
352.20271 ++		DBG(("%s: recording last swap on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
352.20272 ++		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
352.20273 ++		     tv_sec, tv_usec));
352.20274 ++		sna_crtc->swap.tv_sec = tv_sec;
352.20275 ++		sna_crtc->swap.tv_usec = tv_usec;
352.20276 ++		sna_crtc->swap.msc = msc;
352.20277 ++	} else {
352.20278 ++		DBG(("%s: swap event on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
352.20279 ++		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
352.20280 ++		     tv_sec, tv_usec));
352.20281 ++	}
352.20282 ++
352.20283 ++	return msc;
352.20284 + }
352.20285 + 
352.20286 + const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc)
352.20287 +@@ -342,15 +550,6 @@ const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc)
352.20288 + 	}
352.20289 + }
352.20290 + 
352.20291 +-xf86CrtcPtr sna_mode_first_crtc(struct sna *sna)
352.20292 +-{
352.20293 +-	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.20294 +-	if (sna->mode.num_real_crtc)
352.20295 +-		return config->crtc[0];
352.20296 +-	else
352.20297 +-		return NULL;
352.20298 +-}
352.20299 +-
352.20300 + #ifndef NDEBUG
352.20301 + static void gem_close(int fd, uint32_t handle);
352.20302 + static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
352.20303 +@@ -372,12 +571,24 @@ static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
352.20304 + #define assert_scanout(k, b, w, h)
352.20305 + #endif
352.20306 + 
352.20307 ++static void assert_crtc_fb(struct sna *sna, struct sna_crtc *crtc)
352.20308 ++{
352.20309 ++#ifndef NDEBUG
352.20310 ++	struct drm_mode_crtc mode = { .crtc_id = __sna_crtc_id(crtc) };
352.20311 ++	drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
352.20312 ++	assert(mode.fb_id == fb_id(crtc->bo));
352.20313 ++#endif
352.20314 ++}
352.20315 ++
352.20316 + static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
352.20317 + 		       int width, int height)
352.20318 + {
352.20319 + 	ScrnInfoPtr scrn = sna->scrn;
352.20320 + 	struct drm_mode_fb_cmd arg;
352.20321 + 
352.20322 ++	if (!kgem_bo_is_fenced(&sna->kgem, bo))
352.20323 ++		return 0;
352.20324 ++
352.20325 + 	assert(bo->refcnt);
352.20326 + 	assert(bo->proxy == NULL);
352.20327 + 	assert(!bo->snoop);
352.20328 +@@ -393,8 +604,9 @@ static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
352.20329 + 	DBG(("%s: create fb %dx%d@%d/%d\n",
352.20330 + 	     __FUNCTION__, width, height, scrn->depth, scrn->bitsPerPixel));
352.20331 + 
352.20332 +-	assert(bo->tiling != I915_TILING_Y);
352.20333 ++	assert(bo->tiling != I915_TILING_Y || sna->kgem.can_scanout_y);
352.20334 + 	assert((bo->pitch & 63) == 0);
352.20335 ++	assert(scrn->vtSema); /* must be master */
352.20336 + 
352.20337 + 	VG_CLEAR(arg);
352.20338 + 	arg.width = width;
352.20339 +@@ -404,21 +616,83 @@ static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
352.20340 + 	arg.depth = scrn->depth;
352.20341 + 	arg.handle = bo->handle;
352.20342 + 
352.20343 +-	assert(sna->scrn->vtSema); /* must be master */
352.20344 + 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
352.20345 +-		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352.20346 +-			   "%s: failed to add fb: %dx%d depth=%d, bpp=%d, pitch=%d: %d\n",
352.20347 +-			   __FUNCTION__, width, height,
352.20348 +-			   scrn->depth, scrn->bitsPerPixel, bo->pitch, errno);
352.20349 +-		return 0;
352.20350 ++		/* Try again with the fancy version */
352.20351 ++		struct local_mode_fb_cmd2 {
352.20352 ++			uint32_t fb_id;
352.20353 ++			uint32_t width, height;
352.20354 ++			uint32_t pixel_format;
352.20355 ++			uint32_t flags;
352.20356 ++
352.20357 ++			uint32_t handles[4];
352.20358 ++			uint32_t pitches[4]; /* pitch for each plane */
352.20359 ++			uint32_t offsets[4]; /* offset of each plane */
352.20360 ++			uint64_t modifiers[4];
352.20361 ++		} f;
352.20362 ++#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
352.20363 ++		memset(&f, 0, sizeof(f));
352.20364 ++		f.width = width;
352.20365 ++		f.height = height;
352.20366 ++		/* XXX interlaced */
352.20367 ++		f.flags = 1 << 1; /* +modifiers */
352.20368 ++		f.handles[0] = bo->handle;
352.20369 ++		f.pitches[0] = bo->pitch;
352.20370 ++
352.20371 ++		switch (bo->tiling) {
352.20372 ++		case I915_TILING_NONE:
352.20373 ++			break;
352.20374 ++		case I915_TILING_X:
352.20375 ++			/* I915_FORMAT_MOD_X_TILED */
352.20376 ++			f.modifiers[0] = (uint64_t)1 << 56 | 1;
352.20377 ++			break;
352.20378 ++		case I915_TILING_Y:
352.20379 ++			/* I915_FORMAT_MOD_X_TILED */
352.20380 ++			f.modifiers[0] = (uint64_t)1 << 56 | 2;
352.20381 ++			break;
352.20382 ++		}
352.20383 ++
352.20384 ++#define fourcc(a,b,c,d) ((a) | (b) << 8 | (c) << 16 | (d) << 24)
352.20385 ++		switch (scrn->depth) {
352.20386 ++		default:
352.20387 ++			ERR(("%s: unhandled screen format, depth=%d\n",
352.20388 ++			     __FUNCTION__, scrn->depth));
352.20389 ++			goto fail;
352.20390 ++		case 8:
352.20391 ++			f.pixel_format = fourcc('C', '8', ' ', ' ');
352.20392 ++			break;
352.20393 ++		case 15:
352.20394 ++			f.pixel_format = fourcc('X', 'R', '1', '5');
352.20395 ++			break;
352.20396 ++		case 16:
352.20397 ++			f.pixel_format = fourcc('R', 'G', '1', '6');
352.20398 ++			break;
352.20399 ++		case 24:
352.20400 ++			f.pixel_format = fourcc('X', 'R', '2', '4');
352.20401 ++			break;
352.20402 ++		case 30:
352.20403 ++			f.pixel_format = fourcc('X', 'R', '3', '0');
352.20404 ++			break;
352.20405 ++		}
352.20406 ++#undef fourcc
352.20407 ++
352.20408 ++		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_ADDFB2, &f)) {
352.20409 ++fail:
352.20410 ++			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352.20411 ++				   "%s: failed to add fb: %dx%d depth=%d, bpp=%d, pitch=%d: %d\n",
352.20412 ++				   __FUNCTION__, width, height,
352.20413 ++				   scrn->depth, scrn->bitsPerPixel, bo->pitch, errno);
352.20414 ++			return 0;
352.20415 ++		}
352.20416 ++
352.20417 ++		arg.fb_id = f.fb_id;
352.20418 + 	}
352.20419 + 	assert(arg.fb_id != 0);
352.20420 +-
352.20421 ++	bo->delta = arg.fb_id;
352.20422 + 	DBG(("%s: attached fb=%d to handle=%d\n",
352.20423 +-	     __FUNCTION__, arg.fb_id, arg.handle));
352.20424 ++	     __FUNCTION__, bo->delta, arg.handle));
352.20425 + 
352.20426 + 	bo->scanout = true;
352.20427 +-	return bo->delta = arg.fb_id;
352.20428 ++	return bo->delta;
352.20429 + }
352.20430 + 
352.20431 + static uint32_t gem_create(int fd, int size)
352.20432 +@@ -438,6 +712,7 @@ static uint32_t gem_create(int fd, int size)
352.20433 + static void *gem_mmap(int fd, int handle, int size)
352.20434 + {
352.20435 + 	struct drm_i915_gem_mmap_gtt mmap_arg;
352.20436 ++	struct drm_i915_gem_set_domain set_domain;
352.20437 + 	void *ptr;
352.20438 + 
352.20439 + 	VG_CLEAR(mmap_arg);
352.20440 +@@ -449,6 +724,15 @@ static void *gem_mmap(int fd, int handle, int size)
352.20441 + 	if (ptr == MAP_FAILED)
352.20442 + 		return NULL;
352.20443 + 
352.20444 ++	VG_CLEAR(set_domain);
352.20445 ++	set_domain.handle = handle;
352.20446 ++	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
352.20447 ++	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
352.20448 ++	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
352.20449 ++		munmap(ptr, size);
352.20450 ++		return NULL;
352.20451 ++	}
352.20452 ++
352.20453 + 	return ptr;
352.20454 + }
352.20455 + 
352.20456 +@@ -497,8 +781,6 @@ sna_backlight_uevent(int fd, void *closure)
352.20457 + 		if (sna_output->dpms_mode != DPMSModeOn)
352.20458 + 			continue;
352.20459 + 
352.20460 +-		assert(output->randr_output);
352.20461 +-
352.20462 + 		val = backlight_get(&sna_output->backlight);
352.20463 + 		if (val < 0)
352.20464 + 			continue;
352.20465 +@@ -523,6 +805,7 @@ sna_backlight_uevent(int fd, void *closure)
352.20466 + 					       TRUE, FALSE);
352.20467 + 		}
352.20468 + 	}
352.20469 ++	DBG(("%s: complete\n", __FUNCTION__));
352.20470 + }
352.20471 + 
352.20472 + static void sna_backlight_pre_init(struct sna *sna)
352.20473 +@@ -570,6 +853,7 @@ static void sna_backlight_drain_uevents(struct sna *sna)
352.20474 + 	if (sna->mode.backlight_monitor == NULL)
352.20475 + 		return;
352.20476 + 
352.20477 ++	DBG(("%s()\n", __FUNCTION__));
352.20478 + 	sna_backlight_uevent(udev_monitor_get_fd(sna->mode.backlight_monitor),
352.20479 + 			     sna);
352.20480 + }
352.20481 +@@ -632,9 +916,22 @@ sna_output_backlight_set(struct sna_output *sna_output, int level)
352.20482 + 	return ret;
352.20483 + }
352.20484 + 
352.20485 ++static bool
352.20486 ++has_native_backlight(struct sna_output *sna_output)
352.20487 ++{
352.20488 ++	return sna_output->backlight.type == BL_RAW;
352.20489 ++}
352.20490 ++
352.20491 + static void
352.20492 + sna_output_backlight_off(struct sna_output *sna_output)
352.20493 + {
352.20494 ++	/* Trust the kernel to turn the native backlight off. However, we
352.20495 ++	 * do explicitly turn the backlight back on (when we wake the output)
352.20496 ++	 * just in case a third party turns it off!
352.20497 ++	 */
352.20498 ++	if (has_native_backlight(sna_output))
352.20499 ++		return;
352.20500 ++
352.20501 + 	DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
352.20502 + 	backlight_off(&sna_output->backlight);
352.20503 + 	sna_output_backlight_set(sna_output, 0);
352.20504 +@@ -674,7 +971,7 @@ has_user_backlight_override(xf86OutputPtr output)
352.20505 + 	if (*str == '\0')
352.20506 + 		return (char *)str;
352.20507 + 
352.20508 +-	if (backlight_exists(str) == BL_NONE) {
352.20509 ++	if (!backlight_exists(str)) {
352.20510 + 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.20511 + 			   "Unrecognised backlight control interface '%s'\n",
352.20512 + 			   str);
352.20513 +@@ -684,6 +981,93 @@ has_user_backlight_override(xf86OutputPtr output)
352.20514 + 	return strdup(str);
352.20515 + }
352.20516 + 
352.20517 ++static int get_device_minor(int fd)
352.20518 ++{
352.20519 ++	struct stat st;
352.20520 ++
352.20521 ++	if (fstat(fd, &st) || !S_ISCHR(st.st_mode))
352.20522 ++		return -1;
352.20523 ++
352.20524 ++	return st.st_rdev & 0x63;
352.20525 ++}
352.20526 ++
352.20527 ++static const char * const sysfs_connector_types[] = {
352.20528 ++	/* DRM_MODE_CONNECTOR_Unknown */	"Unknown",
352.20529 ++	/* DRM_MODE_CONNECTOR_VGA */		"VGA",
352.20530 ++	/* DRM_MODE_CONNECTOR_DVII */		"DVI-I",
352.20531 ++	/* DRM_MODE_CONNECTOR_DVID */		"DVI-D",
352.20532 ++	/* DRM_MODE_CONNECTOR_DVIA */		"DVI-A",
352.20533 ++	/* DRM_MODE_CONNECTOR_Composite */	"Composite",
352.20534 ++	/* DRM_MODE_CONNECTOR_SVIDEO */		"SVIDEO",
352.20535 ++	/* DRM_MODE_CONNECTOR_LVDS */		"LVDS",
352.20536 ++	/* DRM_MODE_CONNECTOR_Component */	"Component",
352.20537 ++	/* DRM_MODE_CONNECTOR_9PinDIN */	"DIN",
352.20538 ++	/* DRM_MODE_CONNECTOR_DisplayPort */	"DP",
352.20539 ++	/* DRM_MODE_CONNECTOR_HDMIA */		"HDMI-A",
352.20540 ++	/* DRM_MODE_CONNECTOR_HDMIB */		"HDMI-B",
352.20541 ++	/* DRM_MODE_CONNECTOR_TV */		"TV",
352.20542 ++	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
352.20543 ++	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
352.20544 ++	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
352.20545 ++	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
352.20546 ++};
352.20547 ++
352.20548 ++static char *has_connector_backlight(xf86OutputPtr output)
352.20549 ++{
352.20550 ++	struct sna_output *sna_output = output->driver_private;
352.20551 ++	struct sna *sna = to_sna(output->scrn);
352.20552 ++	char path[1024];
352.20553 ++	DIR *dir;
352.20554 ++	struct dirent *de;
352.20555 ++	int minor, len;
352.20556 ++	char *str = NULL;
352.20557 ++
352.20558 ++	if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types))
352.20559 ++		return NULL;
352.20560 ++
352.20561 ++	minor = get_device_minor(sna->kgem.fd);
352.20562 ++	if (minor < 0)
352.20563 ++		return NULL;
352.20564 ++
352.20565 ++	len = snprintf(path, sizeof(path),
352.20566 ++		       "/sys/class/drm/card%d-%s-%d",
352.20567 ++		       minor,
352.20568 ++		       sysfs_connector_types[sna_output->connector_type],
352.20569 ++		       sna_output->connector_type_id);
352.20570 ++	DBG(("%s: lookup %s\n", __FUNCTION__, path));
352.20571 ++
352.20572 ++	dir = opendir(path);
352.20573 ++	if (dir == NULL)
352.20574 ++		return NULL;
352.20575 ++
352.20576 ++	while ((de = readdir(dir))) {
352.20577 ++		struct stat st;
352.20578 ++
352.20579 ++		if (*de->d_name == '.')
352.20580 ++			continue;
352.20581 ++
352.20582 ++		snprintf(path + len, sizeof(path) - len,
352.20583 ++			 "/%s", de->d_name);
352.20584 ++
352.20585 ++		if (stat(path, &st))
352.20586 ++			continue;
352.20587 ++
352.20588 ++		if (!S_ISDIR(st.st_mode))
352.20589 ++			continue;
352.20590 ++
352.20591 ++		DBG(("%s: testing %s as backlight\n",
352.20592 ++		     __FUNCTION__, de->d_name));
352.20593 ++
352.20594 ++		if (backlight_exists(de->d_name)) {
352.20595 ++			str = strdup(de->d_name); /* leak! */
352.20596 ++			break;
352.20597 ++		}
352.20598 ++	}
352.20599 ++
352.20600 ++	closedir(dir);
352.20601 ++	return str;
352.20602 ++}
352.20603 ++
352.20604 + static void
352.20605 + sna_output_backlight_init(xf86OutputPtr output)
352.20606 + {
352.20607 +@@ -696,11 +1080,20 @@ sna_output_backlight_init(xf86OutputPtr output)
352.20608 + 	return;
352.20609 + #endif
352.20610 + 
352.20611 +-	from = X_CONFIG;
352.20612 +-	best_iface = has_user_backlight_override(output);
352.20613 ++	if (sna_output->is_panel) {
352.20614 ++		from = X_CONFIG;
352.20615 ++		best_iface = has_user_backlight_override(output);
352.20616 ++		if (best_iface)
352.20617 ++			goto done;
352.20618 ++	}
352.20619 ++
352.20620 ++	best_iface = has_connector_backlight(output);
352.20621 + 	if (best_iface)
352.20622 + 		goto done;
352.20623 + 
352.20624 ++	if (!sna_output->is_panel)
352.20625 ++		return;
352.20626 ++
352.20627 + 	/* XXX detect right backlight for multi-GPU/panels */
352.20628 + 	from = X_PROBED;
352.20629 + 	pci = xf86GetPciInfoForEntity(to_sna(output->scrn)->pEnt->index);
352.20630 +@@ -728,6 +1121,38 @@ done:
352.20631 + 		   sna_output->backlight.iface, best_iface, output->name);
352.20632 + }
352.20633 + 
352.20634 ++#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(22, 0)
352.20635 ++static inline int sigio_block(void)
352.20636 ++{
352.20637 ++	return 0;
352.20638 ++}
352.20639 ++static inline void sigio_unblock(int was_blocked)
352.20640 ++{
352.20641 ++	(void)was_blocked;
352.20642 ++}
352.20643 ++#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
352.20644 ++static inline int sigio_block(void)
352.20645 ++{
352.20646 ++	OsBlockSIGIO();
352.20647 ++	return 0;
352.20648 ++}
352.20649 ++static inline void sigio_unblock(int was_blocked)
352.20650 ++{
352.20651 ++	OsReleaseSIGIO();
352.20652 ++	(void)was_blocked;
352.20653 ++}
352.20654 ++#else
352.20655 ++#include <xf86_OSproc.h>
352.20656 ++static inline int sigio_block(void)
352.20657 ++{
352.20658 ++	return xf86BlockSIGIO();
352.20659 ++}
352.20660 ++static inline void sigio_unblock(int was_blocked)
352.20661 ++{
352.20662 ++	xf86UnblockSIGIO(was_blocked);
352.20663 ++}
352.20664 ++#endif
352.20665 ++
352.20666 + static char *canonical_kmode_name(const struct drm_mode_modeinfo *kmode)
352.20667 + {
352.20668 + 	char tmp[32], *buf;
352.20669 +@@ -781,6 +1206,7 @@ mode_from_kmode(ScrnInfoPtr scrn,
352.20670 + 	mode->VTotal = kmode->vtotal;
352.20671 + 	mode->VScan = kmode->vscan;
352.20672 + 
352.20673 ++	mode->VRefresh = kmode->vrefresh;
352.20674 + 	mode->Flags = kmode->flags;
352.20675 + 	mode->name = get_kmode_name(kmode);
352.20676 + 
352.20677 +@@ -814,6 +1240,7 @@ mode_to_kmode(struct drm_mode_modeinfo *kmode, DisplayModePtr mode)
352.20678 + 	kmode->vtotal = mode->VTotal;
352.20679 + 	kmode->vscan = mode->VScan;
352.20680 + 
352.20681 ++	kmode->vrefresh = mode->VRefresh;
352.20682 + 	kmode->flags = mode->Flags;
352.20683 + 	if (mode->name)
352.20684 + 		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
352.20685 +@@ -824,11 +1251,12 @@ static void
352.20686 + sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
352.20687 + {
352.20688 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
352.20689 ++	/* All attached outputs are valid, so update our timestamps */
352.20690 ++	unsigned now = GetTimeInMillis();
352.20691 + 	int i;
352.20692 + 
352.20693 + 	assert(to_sna_crtc(crtc));
352.20694 +-	DBG(("%s(pipe=%d), currently? %d\n", __FUNCTION__,
352.20695 +-	     to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->dpms_mode));
352.20696 ++	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
352.20697 + 
352.20698 + 	/* DPMS handling by the kernel is inconsistent, so after setting a
352.20699 + 	 * mode on an output presume that we intend for it to be on, or that
352.20700 +@@ -843,10 +1271,11 @@ sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
352.20701 + 		if (output->crtc != crtc)
352.20702 + 			continue;
352.20703 + 
352.20704 +-		output->funcs->dpms(output, DPMSModeOn);
352.20705 ++		__sna_output_dpms(output, DPMSModeOn, false);
352.20706 ++		if (to_sna_output(output)->last_detect)
352.20707 ++			to_sna_output(output)->last_detect = now;
352.20708 + 	}
352.20709 + 
352.20710 +-	to_sna_crtc(crtc)->dpms_mode = DPMSModeOn;
352.20711 + #if XF86_CRTC_VERSION >= 3
352.20712 + 	crtc->active = TRUE;
352.20713 + #endif
352.20714 +@@ -859,8 +1288,7 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
352.20715 + 	int i;
352.20716 + 
352.20717 + 	assert(to_sna_crtc(crtc));
352.20718 +-	DBG(("%s(pipe=%d), currently? %d\n", __FUNCTION__,
352.20719 +-	     to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->dpms_mode));
352.20720 ++	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
352.20721 + 
352.20722 + 	/* DPMS handling by the kernel is inconsistent, so after setting a
352.20723 + 	 * mode on an output presume that we intend for it to be on, or that
352.20724 +@@ -875,35 +1303,47 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
352.20725 + 		if (output->crtc != crtc)
352.20726 + 			continue;
352.20727 + 
352.20728 +-		output->funcs->dpms(output, DPMSModeOff);
352.20729 ++		__sna_output_dpms(output, DPMSModeOff, false);
352.20730 + 	}
352.20731 +-
352.20732 +-	to_sna_crtc(crtc)->dpms_mode = DPMSModeOff;
352.20733 + }
352.20734 + 
352.20735 + static unsigned
352.20736 +-rotation_reduce(struct plane *p, unsigned rotation)
352.20737 ++rotation_reflect(unsigned rotation)
352.20738 + {
352.20739 +-	unsigned unsupported_rotations = rotation & ~p->rotation.supported;
352.20740 ++	unsigned other_bits;
352.20741 + 
352.20742 +-	if (unsupported_rotations == 0)
352.20743 +-		return rotation;
352.20744 ++	/* paranoia for future extensions */
352.20745 ++	other_bits = rotation & ~RR_Rotate_All;
352.20746 + 
352.20747 +-#define RR_Reflect_XY (RR_Reflect_X | RR_Reflect_Y)
352.20748 ++	/* flip the reflection to compensate for reflecting the rotation */
352.20749 ++	other_bits ^= RR_Reflect_X | RR_Reflect_Y;
352.20750 + 
352.20751 +-	if ((unsupported_rotations & RR_Reflect_XY) == RR_Reflect_XY &&
352.20752 +-	    p->rotation.supported& RR_Rotate_180) {
352.20753 +-		rotation &= ~RR_Reflect_XY;
352.20754 +-		rotation ^= RR_Rotate_180;
352.20755 +-	}
352.20756 ++	/* Reflect the screen by rotating the rotation bit,
352.20757 ++	 * which has to have at least RR_Rotate_0 set. This allows
352.20758 ++	 * us to reflect any of the rotation bits, not just 0.
352.20759 ++	 */
352.20760 ++	rotation &= RR_Rotate_All;
352.20761 ++	assert(rotation);
352.20762 ++	rotation <<= 2; /* RR_Rotate_0 -> RR_Rotate_180 etc */
352.20763 ++	rotation |= rotation >> 4; /* RR_Rotate_270' to RR_Rotate_90 */
352.20764 ++	rotation &= RR_Rotate_All;
352.20765 ++	assert(rotation);
352.20766 + 
352.20767 +-	if ((unsupported_rotations & RR_Rotate_180) &&
352.20768 +-	    (p->rotation.supported& RR_Reflect_XY) == RR_Reflect_XY) {
352.20769 +-		rotation ^= RR_Reflect_XY;
352.20770 +-		rotation &= ~RR_Rotate_180;
352.20771 ++	return rotation | other_bits;
352.20772 ++}
352.20773 ++
352.20774 ++static unsigned
352.20775 ++rotation_reduce(struct plane *p, unsigned rotation)
352.20776 ++{
352.20777 ++	/* If unsupported try exchanging rotation for a reflection */
352.20778 ++	if (rotation & ~p->rotation.supported) {
352.20779 ++		unsigned new_rotation = rotation_reflect(rotation);
352.20780 ++		if ((new_rotation & p->rotation.supported) == new_rotation)
352.20781 ++			rotation = new_rotation;
352.20782 + 	}
352.20783 + 
352.20784 +-#undef RR_Reflect_XY
352.20785 ++	/* Only one rotation bit should be set */
352.20786 ++	assert(is_power_of_two(rotation & RR_Rotate_All));
352.20787 + 
352.20788 + 	return rotation;
352.20789 + }
352.20790 +@@ -923,7 +1363,7 @@ rotation_set(struct sna *sna, struct plane *p, uint32_t desired)
352.20791 + 	if (desired == p->rotation.current)
352.20792 + 		return true;
352.20793 + 
352.20794 +-	if ((desired & p->rotation.supported) == 0) {
352.20795 ++	if ((desired & p->rotation.supported) != desired) {
352.20796 + 		errno = EINVAL;
352.20797 + 		return false;
352.20798 + 	}
352.20799 +@@ -956,20 +1396,105 @@ rotation_reset(struct plane *p)
352.20800 + 	p->rotation.current = 0;
352.20801 + }
352.20802 + 
352.20803 +-bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
352.20804 ++bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc,
352.20805 ++				  unsigned idx,
352.20806 ++				  uint32_t rotation)
352.20807 + {
352.20808 ++	struct plane *sprite;
352.20809 + 	assert(to_sna_crtc(crtc));
352.20810 ++
352.20811 ++	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
352.20812 ++	if (!sprite)
352.20813 ++		return false;
352.20814 ++
352.20815 + 	DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
352.20816 + 	     __FUNCTION__,
352.20817 +-	     to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite.id,
352.20818 +-	     rotation));
352.20819 ++	     sna_crtc_id(crtc), sna_crtc_pipe(crtc),
352.20820 ++	     sprite->id, rotation));
352.20821 + 
352.20822 +-	return rotation_set(to_sna(crtc->scrn),
352.20823 +-			    &to_sna_crtc(crtc)->sprite,
352.20824 +-			    rotation_reduce(&to_sna_crtc(crtc)->sprite, rotation));
352.20825 ++	return rotation_set(to_sna(crtc->scrn), sprite,
352.20826 ++			    rotation_reduce(sprite, rotation));
352.20827 + }
352.20828 + 
352.20829 +-static bool
352.20830 ++#if HAS_DEBUG_FULL
352.20831 ++#if !HAS_DEBUG_FULL
352.20832 ++#define LogF ErrorF
352.20833 ++#endif
352.20834 ++struct kmsg {
352.20835 ++	int fd;
352.20836 ++	int saved_loglevel;
352.20837 ++};
352.20838 ++
352.20839 ++static int kmsg_get_debug(void)
352.20840 ++{
352.20841 ++	FILE *file;
352.20842 ++	int v = -1;
352.20843 ++
352.20844 ++	file = fopen("/sys/module/drm/parameters/debug", "r");
352.20845 ++	if (file) {
352.20846 ++		fscanf(file, "%d", &v);
352.20847 ++		fclose(file);
352.20848 ++	}
352.20849 ++
352.20850 ++	return v;
352.20851 ++}
352.20852 ++
352.20853 ++static void kmsg_set_debug(int v)
352.20854 ++{
352.20855 ++	FILE *file;
352.20856 ++
352.20857 ++	file = fopen("/sys/module/drm/parameters/debug", "w");
352.20858 ++	if (file) {
352.20859 ++		fprintf(file, "%d\n", v);
352.20860 ++		fclose(file);
352.20861 ++	}
352.20862 ++}
352.20863 ++
352.20864 ++static void kmsg_open(struct kmsg *k)
352.20865 ++{
352.20866 ++	k->saved_loglevel = kmsg_get_debug();
352.20867 ++	if (k->saved_loglevel != -1)
352.20868 ++		kmsg_set_debug(0xff);
352.20869 ++
352.20870 ++	k->fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
352.20871 ++	if (k->fd != -1)
352.20872 ++		lseek(k->fd, 0, SEEK_END);
352.20873 ++}
352.20874 ++
352.20875 ++static void kmsg_close(struct kmsg *k, int dump)
352.20876 ++{
352.20877 ++	FILE *file;
352.20878 ++
352.20879 ++	file = NULL;
352.20880 ++	if (k->fd != -1 && dump)
352.20881 ++		file = fdopen(k->fd, "r");
352.20882 ++	if (file) {
352.20883 ++		size_t len = 0;
352.20884 ++		char *line = NULL;
352.20885 ++
352.20886 ++		while (getline(&line, &len, file) != -1) {
352.20887 ++			char *start = strchr(line, ';');
352.20888 ++			if (start)
352.20889 ++				LogF("KMSG: %s", start + 1);
352.20890 ++		}
352.20891 ++
352.20892 ++		free(line);
352.20893 ++		fclose(file);
352.20894 ++	}
352.20895 ++
352.20896 ++	if (k->fd != -1)
352.20897 ++		close(k->fd);
352.20898 ++
352.20899 ++	if (k->saved_loglevel != -1)
352.20900 ++		kmsg_set_debug(k->saved_loglevel);
352.20901 ++}
352.20902 ++#else
352.20903 ++struct kmsg { int unused; };
352.20904 ++static void kmsg_open(struct kmsg *k) {}
352.20905 ++static void kmsg_close(struct kmsg *k, int dump) {}
352.20906 ++#endif
352.20907 ++
352.20908 ++static int
352.20909 + sna_crtc_apply(xf86CrtcPtr crtc)
352.20910 + {
352.20911 + 	struct sna *sna = to_sna(crtc->scrn);
352.20912 +@@ -978,26 +1503,39 @@ sna_crtc_apply(xf86CrtcPtr crtc)
352.20913 + 	struct drm_mode_crtc arg;
352.20914 + 	uint32_t output_ids[32];
352.20915 + 	int output_count = 0;
352.20916 +-	int i;
352.20917 ++	int sigio, i;
352.20918 ++	struct kmsg kmsg;
352.20919 ++	int ret = EINVAL;
352.20920 + 
352.20921 +-	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->bo->handle));
352.20922 ++	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__,
352.20923 ++	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
352.20924 ++	     sna_crtc->bo->handle));
352.20925 + 	if (!sna_crtc->kmode.clock) {
352.20926 + 		ERR(("%s(CRTC:%d [pipe=%d]): attempted to set an invalid mode\n",
352.20927 +-		     __FUNCTION__, sna_crtc->id, sna_crtc->pipe));
352.20928 +-		return false;
352.20929 ++		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc)));
352.20930 ++		return EINVAL;
352.20931 + 	}
352.20932 + 
352.20933 ++	kmsg_open(&kmsg);
352.20934 ++	sigio = sigio_block();
352.20935 ++
352.20936 + 	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
352.20937 + 	sna_crtc_disable_cursor(sna, sna_crtc);
352.20938 + 
352.20939 + 	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
352.20940 ++		memset(&arg, 0, sizeof(arg));
352.20941 ++		arg.crtc_id = __sna_crtc_id(sna_crtc);
352.20942 ++		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
352.20943 ++	}
352.20944 ++
352.20945 ++	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
352.20946 + 		ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n",
352.20947 +-		     __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno));
352.20948 ++		     __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
352.20949 + 		sna_crtc->primary.rotation.supported &= ~sna_crtc->rotation;
352.20950 +-		return false;
352.20951 ++		goto unblock;
352.20952 + 	}
352.20953 + 	DBG(("%s: CRTC:%d [pipe=%d] primary rotation set to %x\n",
352.20954 +-	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->rotation));
352.20955 ++	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna_crtc->rotation));
352.20956 + 
352.20957 + 	for (i = 0; i < sna->mode.num_real_output; i++) {
352.20958 + 		xf86OutputPtr output = config->output[i];
352.20959 +@@ -1008,7 +1546,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
352.20960 + 		 * and we lose track of the user settings.
352.20961 + 		 */
352.20962 + 		if (output->crtc == NULL)
352.20963 +-			output->funcs->dpms(output, DPMSModeOff);
352.20964 ++			__sna_output_dpms(output, DPMSModeOff, false);
352.20965 + 
352.20966 + 		if (output->crtc != crtc)
352.20967 + 			continue;
352.20968 +@@ -1022,29 +1560,27 @@ sna_crtc_apply(xf86CrtcPtr crtc)
352.20969 + 
352.20970 + 		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
352.20971 + 		     __FUNCTION__, output->name, i, to_connector_id(output),
352.20972 +-		     sna_crtc->id, sna_crtc->pipe,
352.20973 ++		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
352.20974 + 		     (uint32_t)output->possible_crtcs,
352.20975 + 		     (uint32_t)output->possible_clones));
352.20976 + 
352.20977 +-		assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
352.20978 ++		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(sna_crtc)) ||
352.20979 + 		       is_zaphod(crtc->scrn));
352.20980 + 
352.20981 + 		output_ids[output_count] = to_connector_id(output);
352.20982 + 		if (++output_count == ARRAY_SIZE(output_ids)) {
352.20983 + 			DBG(("%s: too many outputs (%d) for me!\n",
352.20984 + 			     __FUNCTION__, output_count));
352.20985 +-			errno = EINVAL;
352.20986 +-			return false;
352.20987 ++			goto unblock;
352.20988 + 		}
352.20989 + 	}
352.20990 + 	if (output_count == 0) {
352.20991 + 		DBG(("%s: no outputs\n", __FUNCTION__));
352.20992 +-		errno = EINVAL;
352.20993 +-		return false;
352.20994 ++		goto unblock;
352.20995 + 	}
352.20996 + 
352.20997 + 	VG_CLEAR(arg);
352.20998 +-	arg.crtc_id = sna_crtc->id;
352.20999 ++	arg.crtc_id = __sna_crtc_id(sna_crtc);
352.21000 + 	arg.fb_id = fb_id(sna_crtc->bo);
352.21001 + 	if (sna_crtc->transform || sna_crtc->slave_pixmap) {
352.21002 + 		arg.x = 0;
352.21003 +@@ -1061,7 +1597,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
352.21004 + 	arg.mode_valid = 1;
352.21005 + 
352.21006 + 	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d%s%s update to %d outputs [%d...]\n",
352.21007 +-	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
352.21008 ++	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
352.21009 + 	     arg.mode.hdisplay,
352.21010 + 	     arg.mode.vdisplay,
352.21011 + 	     arg.x, arg.y,
352.21012 +@@ -1071,12 +1607,19 @@ sna_crtc_apply(xf86CrtcPtr crtc)
352.21013 + 	     sna_crtc->transform ? " [transformed]" : "",
352.21014 + 	     output_count, output_count ? output_ids[0] : 0));
352.21015 + 
352.21016 +-	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
352.21017 +-		return false;
352.21018 ++	ret = 0;
352.21019 ++	if (unlikely(drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))) {
352.21020 ++		ret = errno;
352.21021 ++		goto unblock;
352.21022 ++	}
352.21023 + 
352.21024 + 	sna_crtc->mode_serial++;
352.21025 + 	sna_crtc_force_outputs_on(crtc);
352.21026 +-	return true;
352.21027 ++
352.21028 ++unblock:
352.21029 ++	sigio_unblock(sigio);
352.21030 ++	kmsg_close(&kmsg, ret);
352.21031 ++	return ret;
352.21032 + }
352.21033 + 
352.21034 + static bool overlap(const BoxRec *a, const BoxRec *b)
352.21035 +@@ -1094,26 +1637,73 @@ static bool overlap(const BoxRec *a, const BoxRec *b)
352.21036 + 	return true;
352.21037 + }
352.21038 + 
352.21039 ++static void defer_event(struct sna *sna, struct drm_event *base)
352.21040 ++{
352.21041 ++	if (sna->mode.shadow_nevent == sna->mode.shadow_size) {
352.21042 ++		int size = sna->mode.shadow_size * 2;
352.21043 ++		void *ptr;
352.21044 ++
352.21045 ++		ptr = realloc(sna->mode.shadow_events,
352.21046 ++			      sizeof(struct drm_event_vblank)*size);
352.21047 ++		if (!ptr)
352.21048 ++			return;
352.21049 ++
352.21050 ++		sna->mode.shadow_events = ptr;
352.21051 ++		sna->mode.shadow_size = size;
352.21052 ++	}
352.21053 ++
352.21054 ++	memcpy(&sna->mode.shadow_events[sna->mode.shadow_nevent++],
352.21055 ++	       base, sizeof(struct drm_event_vblank));
352.21056 ++	DBG(("%s: deferring event count=%d\n",
352.21057 ++	     __func__, sna->mode.shadow_nevent));
352.21058 ++}
352.21059 ++
352.21060 ++static void flush_events(struct sna *sna)
352.21061 ++{
352.21062 ++	int n;
352.21063 ++
352.21064 ++	if (!sna->mode.shadow_nevent)
352.21065 ++		return;
352.21066 ++
352.21067 ++	DBG(("%s: flushing %d events=%d\n", __func__, sna->mode.shadow_nevent));
352.21068 ++
352.21069 ++	for (n = 0; n < sna->mode.shadow_nevent; n++) {
352.21070 ++		struct drm_event_vblank *vb = &sna->mode.shadow_events[n];
352.21071 ++
352.21072 ++		if ((uintptr_t)(vb->user_data) & 2)
352.21073 ++			sna_present_vblank_handler(vb);
352.21074 ++		else
352.21075 ++			sna_dri2_vblank_handler(vb);
352.21076 ++	}
352.21077 ++
352.21078 ++	sna->mode.shadow_nevent = 0;
352.21079 ++}
352.21080 ++
352.21081 ++
352.21082 + static bool wait_for_shadow(struct sna *sna,
352.21083 + 			    struct sna_pixmap *priv,
352.21084 + 			    unsigned flags)
352.21085 + {
352.21086 + 	PixmapPtr pixmap = priv->pixmap;
352.21087 +-	DamagePtr damage;
352.21088 + 	struct kgem_bo *bo, *tmp;
352.21089 + 	int flip_active;
352.21090 + 	bool ret = true;
352.21091 + 
352.21092 +-	DBG(("%s: flags=%x, flips=%d, handle=%d, shadow=%d\n",
352.21093 +-	     __FUNCTION__, flags, sna->mode.flip_active,
352.21094 ++	DBG(("%s: enabled? %d waiting? %d, flags=%x, flips=%d, pixmap=%ld [front?=%d], handle=%d, shadow=%d\n",
352.21095 ++	     __FUNCTION__, sna->mode.shadow_enabled, sna->mode.shadow_wait,
352.21096 ++	     flags, sna->mode.flip_active,
352.21097 ++	     pixmap->drawable.serialNumber, pixmap == sna->front,
352.21098 + 	     priv->gpu_bo->handle, sna->mode.shadow->handle));
352.21099 + 
352.21100 + 	assert(priv->move_to_gpu_data == sna);
352.21101 + 	assert(sna->mode.shadow != priv->gpu_bo);
352.21102 + 
352.21103 +-	if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_damage)
352.21104 ++	if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_enabled)
352.21105 + 		goto done;
352.21106 + 
352.21107 ++	assert(sna->mode.shadow_damage);
352.21108 ++	assert(!sna->mode.shadow_wait);
352.21109 ++
352.21110 + 	if ((flags & MOVE_WRITE) == 0) {
352.21111 + 		if ((flags & __MOVE_SCANOUT) == 0) {
352.21112 + 			struct sna_crtc *crtc;
352.21113 +@@ -1154,9 +1744,7 @@ static bool wait_for_shadow(struct sna *sna,
352.21114 + 	}
352.21115 + 
352.21116 + 	assert(sna->mode.shadow_active);
352.21117 +-
352.21118 +-	damage = sna->mode.shadow_damage;
352.21119 +-	sna->mode.shadow_damage = NULL;
352.21120 ++	sna->mode.shadow_wait = true;
352.21121 + 
352.21122 + 	flip_active = sna->mode.flip_active;
352.21123 + 	if (flip_active) {
352.21124 +@@ -1208,6 +1796,8 @@ static bool wait_for_shadow(struct sna *sna,
352.21125 + 			bo = sna->mode.shadow;
352.21126 + 		}
352.21127 + 	}
352.21128 ++	assert(sna->mode.shadow_wait);
352.21129 ++	sna->mode.shadow_wait = false;
352.21130 + 
352.21131 + 	if (bo->refcnt > 1) {
352.21132 + 		bo = kgem_create_2d(&sna->kgem,
352.21133 +@@ -1230,8 +1820,6 @@ static bool wait_for_shadow(struct sna *sna,
352.21134 + 			bo = sna->mode.shadow;
352.21135 + 	}
352.21136 + 
352.21137 +-	sna->mode.shadow_damage = damage;
352.21138 +-
352.21139 + 	RegionSubtract(&sna->mode.shadow_region,
352.21140 + 		       &sna->mode.shadow_region,
352.21141 + 		       &sna->mode.shadow_cancel);
352.21142 +@@ -1269,6 +1857,7 @@ static bool wait_for_shadow(struct sna *sna,
352.21143 + 			RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, &region);
352.21144 + 		}
352.21145 + 
352.21146 ++		crtc->client_bo->active_scanout--;
352.21147 + 		kgem_bo_destroy(&sna->kgem, crtc->client_bo);
352.21148 + 		crtc->client_bo = NULL;
352.21149 + 		list_del(&crtc->shadow_link);
352.21150 +@@ -1281,12 +1870,13 @@ static bool wait_for_shadow(struct sna *sna,
352.21151 + 		     sna->mode.shadow_region.extents.y1,
352.21152 + 		     sna->mode.shadow_region.extents.x2,
352.21153 + 		     sna->mode.shadow_region.extents.y2));
352.21154 +-		ret = sna->render.copy_boxes(sna, GXcopy,
352.21155 +-					     &pixmap->drawable, priv->gpu_bo, 0, 0,
352.21156 +-					     &pixmap->drawable, bo, 0, 0,
352.21157 +-					     region_rects(&sna->mode.shadow_region),
352.21158 +-					     region_num_rects(&sna->mode.shadow_region),
352.21159 +-					     0);
352.21160 ++		if (!sna->render.copy_boxes(sna, GXcopy,
352.21161 ++					    &pixmap->drawable, priv->gpu_bo, 0, 0,
352.21162 ++					    &pixmap->drawable, bo, 0, 0,
352.21163 ++					    region_rects(&sna->mode.shadow_region),
352.21164 ++					    region_num_rects(&sna->mode.shadow_region),
352.21165 ++					    0))
352.21166 ++			ERR(("%s: copy failed\n", __FUNCTION__));
352.21167 + 	}
352.21168 + 
352.21169 + 	if (priv->cow)
352.21170 +@@ -1295,11 +1885,13 @@ static bool wait_for_shadow(struct sna *sna,
352.21171 + 	sna_pixmap_unmap(pixmap, priv);
352.21172 + 
352.21173 + 	DBG(("%s: setting front pixmap to handle=%d\n", __FUNCTION__, bo->handle));
352.21174 ++	sna->mode.shadow->active_scanout--;
352.21175 + 	tmp = priv->gpu_bo;
352.21176 + 	priv->gpu_bo = bo;
352.21177 + 	if (bo != sna->mode.shadow)
352.21178 + 		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
352.21179 + 	sna->mode.shadow = tmp;
352.21180 ++	sna->mode.shadow->active_scanout++;
352.21181 + 
352.21182 + 	sna_dri2_pixmap_update_bo(sna, pixmap, bo);
352.21183 + 
352.21184 +@@ -1311,6 +1903,9 @@ done:
352.21185 + 	priv->move_to_gpu_data = NULL;
352.21186 + 	priv->move_to_gpu = NULL;
352.21187 + 
352.21188 ++	assert(!sna->mode.shadow_wait);
352.21189 ++	flush_events(sna);
352.21190 ++
352.21191 + 	return ret;
352.21192 + }
352.21193 + 
352.21194 +@@ -1358,22 +1953,43 @@ bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
352.21195 + 	return RegionNil(&sna->mode.shadow_region);
352.21196 + }
352.21197 + 
352.21198 ++static void sna_mode_damage(DamagePtr damage, RegionPtr region, void *closure)
352.21199 ++{
352.21200 ++	struct sna *sna = closure;
352.21201 ++
352.21202 ++	if (sna->mode.rr_active)
352.21203 ++		return;
352.21204 ++
352.21205 ++	/* Throw away the rectangles if the region grows too big */
352.21206 ++	region = DamageRegion(damage);
352.21207 ++	if (region->data) {
352.21208 ++		RegionRec dup;
352.21209 ++
352.21210 ++		dup = *region;
352.21211 ++		RegionUninit(&dup);
352.21212 ++
352.21213 ++		region->data = NULL;
352.21214 ++	}
352.21215 ++}
352.21216 ++
352.21217 + static bool sna_mode_enable_shadow(struct sna *sna)
352.21218 + {
352.21219 +-	ScreenPtr screen = sna->scrn->pScreen;
352.21220 ++	ScreenPtr screen = to_screen_from_sna(sna);
352.21221 + 
352.21222 + 	DBG(("%s\n", __FUNCTION__));
352.21223 + 	assert(sna->mode.shadow == NULL);
352.21224 + 	assert(sna->mode.shadow_damage == NULL);
352.21225 + 	assert(sna->mode.shadow_active == 0);
352.21226 ++	assert(!sna->mode.shadow_enabled);
352.21227 + 
352.21228 +-	sna->mode.shadow_damage = DamageCreate(NULL, NULL,
352.21229 +-					       DamageReportNone, TRUE,
352.21230 +-					       screen, screen);
352.21231 ++	sna->mode.shadow_damage = DamageCreate(sna_mode_damage, NULL,
352.21232 ++					       DamageReportRawRegion,
352.21233 ++					       TRUE, screen, sna);
352.21234 + 	if (!sna->mode.shadow_damage)
352.21235 + 		return false;
352.21236 + 
352.21237 + 	DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
352.21238 ++	sna->mode.shadow_enabled = true;
352.21239 + 	return true;
352.21240 + }
352.21241 + 
352.21242 +@@ -1381,8 +1997,10 @@ static void sna_mode_disable_shadow(struct sna *sna)
352.21243 + {
352.21244 + 	struct sna_pixmap *priv;
352.21245 + 
352.21246 +-	if (!sna->mode.shadow_damage)
352.21247 ++	if (!sna->mode.shadow_damage) {
352.21248 ++		assert(!sna->mode.shadow_enabled);
352.21249 + 		return;
352.21250 ++	}
352.21251 + 
352.21252 + 	DBG(("%s\n", __FUNCTION__));
352.21253 + 
352.21254 +@@ -1393,8 +2011,10 @@ static void sna_mode_disable_shadow(struct sna *sna)
352.21255 + 	DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
352.21256 + 	DamageDestroy(sna->mode.shadow_damage);
352.21257 + 	sna->mode.shadow_damage = NULL;
352.21258 ++	sna->mode.shadow_enabled = false;
352.21259 + 
352.21260 + 	if (sna->mode.shadow) {
352.21261 ++		sna->mode.shadow->active_scanout--;
352.21262 + 		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
352.21263 + 		sna->mode.shadow = NULL;
352.21264 + 	}
352.21265 +@@ -1413,7 +2033,7 @@ static void sna_crtc_slave_damage(DamagePtr damage, RegionPtr region, void *clos
352.21266 + 	     __FUNCTION__,
352.21267 + 	     region->extents.x1, region->extents.y1, region->extents.x2, region->extents.y2,
352.21268 + 	     region_num_rects(region),
352.21269 +-	     crtc->pipe, crtc->base->x, crtc->base->y));
352.21270 ++	     __sna_crtc_pipe(crtc), crtc->base->x, crtc->base->y));
352.21271 + 
352.21272 + 	assert(crtc->slave_damage == damage);
352.21273 + 	assert(sna->mode.shadow_damage);
352.21274 +@@ -1431,7 +2051,7 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
352.21275 + 		return true;
352.21276 + 	}
352.21277 + 
352.21278 +-	DBG(("%s: enabling for crtc %d\n", __FUNCTION__, crtc->id));
352.21279 ++	DBG(("%s: enabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
352.21280 + 
352.21281 + 	if (!sna->mode.shadow_active) {
352.21282 + 		if (!sna_mode_enable_shadow(sna))
352.21283 +@@ -1443,9 +2063,12 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
352.21284 + 	if (crtc->slave_pixmap) {
352.21285 + 		assert(crtc->slave_damage == NULL);
352.21286 + 
352.21287 ++		DBG(("%s: enabling PRIME slave tracking on CRTC %d [pipe=%d], pixmap=%ld\n",
352.21288 ++		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->slave_pixmap->drawable.serialNumber));
352.21289 + 		crtc->slave_damage = DamageCreate(sna_crtc_slave_damage, NULL,
352.21290 + 						  DamageReportRawRegion, TRUE,
352.21291 +-						  sna->scrn->pScreen, crtc);
352.21292 ++						  to_screen_from_sna(sna),
352.21293 ++						  crtc);
352.21294 + 		if (crtc->slave_damage == NULL) {
352.21295 + 			if (!--sna->mode.shadow_active)
352.21296 + 				sna_mode_disable_shadow(sna);
352.21297 +@@ -1465,6 +2088,9 @@ static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
352.21298 + 	if (crtc->client_bo == NULL)
352.21299 + 		return;
352.21300 + 
352.21301 ++	assert(crtc->client_bo->refcnt >= crtc->client_bo->active_scanout);
352.21302 ++	crtc->client_bo->active_scanout--;
352.21303 ++
352.21304 + 	if (!crtc->transform) {
352.21305 + 		DrawableRec tmp;
352.21306 + 
352.21307 +@@ -1489,7 +2115,7 @@ static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
352.21308 + 	if (!crtc->shadow)
352.21309 + 		return;
352.21310 + 
352.21311 +-	DBG(("%s: disabling for crtc %d\n", __FUNCTION__, crtc->id));
352.21312 ++	DBG(("%s: disabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
352.21313 + 	assert(sna->mode.shadow_active > 0);
352.21314 + 
352.21315 + 	if (crtc->slave_damage) {
352.21316 +@@ -1517,14 +2143,24 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
352.21317 + 	sna_crtc_disable_shadow(sna, sna_crtc);
352.21318 + 
352.21319 + 	if (sna_crtc->bo) {
352.21320 ++		DBG(("%s: releasing handle=%d from scanout, active=%d\n",
352.21321 ++		     __FUNCTION__,sna_crtc->bo->handle, sna_crtc->bo->active_scanout-1));
352.21322 ++		assert(sna_crtc->flags & CRTC_ON);
352.21323 + 		assert(sna_crtc->bo->active_scanout);
352.21324 + 		assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
352.21325 + 		sna_crtc->bo->active_scanout--;
352.21326 + 		kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
352.21327 + 		sna_crtc->bo = NULL;
352.21328 ++		sna_crtc->flags &= ~CRTC_ON;
352.21329 + 
352.21330 +-		assert(sna->mode.front_active);
352.21331 +-		sna->mode.front_active--;
352.21332 ++		if (sna->mode.hidden) {
352.21333 ++			sna->mode.hidden--;
352.21334 ++			assert(sna->mode.hidden);
352.21335 ++			assert(sna->mode.front_active == 0);
352.21336 ++		} else {
352.21337 ++			assert(sna->mode.front_active);
352.21338 ++			sna->mode.front_active--;
352.21339 ++		}
352.21340 + 		sna->mode.dirty = true;
352.21341 + 	}
352.21342 + 
352.21343 +@@ -1532,13 +2168,19 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
352.21344 + 		kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
352.21345 + 		sna_crtc->shadow_bo = NULL;
352.21346 + 	}
352.21347 +-	sna_crtc->transform = false;
352.21348 ++	if (sna_crtc->transform) {
352.21349 ++		assert(sna->mode.rr_active);
352.21350 ++		sna->mode.rr_active--;
352.21351 ++		sna_crtc->transform = false;
352.21352 ++	}
352.21353 + 
352.21354 ++	sna_crtc->cursor_transform = false;
352.21355 ++	sna_crtc->hwcursor = true;
352.21356 + 	assert(!sna_crtc->shadow);
352.21357 + }
352.21358 + 
352.21359 + static void
352.21360 +-sna_crtc_disable(xf86CrtcPtr crtc)
352.21361 ++sna_crtc_disable(xf86CrtcPtr crtc, bool force)
352.21362 + {
352.21363 + 	struct sna *sna = to_sna(crtc->scrn);
352.21364 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.21365 +@@ -1547,14 +2189,16 @@ sna_crtc_disable(xf86CrtcPtr crtc)
352.21366 + 	if (sna_crtc == NULL)
352.21367 + 		return;
352.21368 + 
352.21369 +-	DBG(("%s: disabling crtc [%d, pipe=%d]\n", __FUNCTION__,
352.21370 +-	     sna_crtc->id, sna_crtc->pipe));
352.21371 ++	if (!force && sna_crtc->bo == NULL)
352.21372 ++		return;
352.21373 ++
352.21374 ++	DBG(("%s: disabling crtc [%d, pipe=%d], force?=%d\n", __FUNCTION__,
352.21375 ++	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), force));
352.21376 + 
352.21377 + 	sna_crtc_force_outputs_off(crtc);
352.21378 +-	assert(sna_crtc->dpms_mode == DPMSModeOff);
352.21379 + 
352.21380 + 	memset(&arg, 0, sizeof(arg));
352.21381 +-	arg.crtc_id = sna_crtc->id;
352.21382 ++	arg.crtc_id = __sna_crtc_id(sna_crtc);
352.21383 + 	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
352.21384 + 
352.21385 + 	__sna_crtc_disable(sna, sna_crtc);
352.21386 +@@ -1574,19 +2218,19 @@ static void update_flush_interval(struct sna *sna)
352.21387 + 
352.21388 + 		if (!crtc->enabled) {
352.21389 + 			DBG(("%s: CRTC:%d (pipe %d) disabled\n",
352.21390 +-			     __FUNCTION__,i, to_sna_crtc(crtc)->pipe));
352.21391 ++			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
352.21392 + 			assert(to_sna_crtc(crtc)->bo == NULL);
352.21393 + 			continue;
352.21394 + 		}
352.21395 + 
352.21396 +-		if (to_sna_crtc(crtc)->dpms_mode != DPMSModeOn) {
352.21397 ++		if (to_sna_crtc(crtc)->bo == NULL) {
352.21398 + 			DBG(("%s: CRTC:%d (pipe %d) turned off\n",
352.21399 +-			     __FUNCTION__,i, to_sna_crtc(crtc)->pipe));
352.21400 ++			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
352.21401 + 			continue;
352.21402 + 		}
352.21403 + 
352.21404 + 		DBG(("%s: CRTC:%d (pipe %d) vrefresh=%f\n",
352.21405 +-		     __FUNCTION__, i, to_sna_crtc(crtc)->pipe,
352.21406 ++		     __FUNCTION__, i, sna_crtc_pipe(crtc),
352.21407 + 		     xf86ModeVRefresh(&crtc->mode)));
352.21408 + 		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(&crtc->mode));
352.21409 + 	}
352.21410 +@@ -1642,7 +2286,7 @@ void sna_copy_fbcon(struct sna *sna)
352.21411 + 	int dx, dy;
352.21412 + 	int i;
352.21413 + 
352.21414 +-	if (wedged(sna))
352.21415 ++	if (wedged(sna) || isGPU(sna->scrn))
352.21416 + 		return;
352.21417 + 
352.21418 + 	DBG(("%s\n", __FUNCTION__));
352.21419 +@@ -1662,7 +2306,7 @@ void sna_copy_fbcon(struct sna *sna)
352.21420 + 		assert(crtc != NULL);
352.21421 + 
352.21422 + 		VG_CLEAR(mode);
352.21423 +-		mode.crtc_id = crtc->id;
352.21424 ++		mode.crtc_id = __sna_crtc_id(crtc);
352.21425 + 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
352.21426 + 			continue;
352.21427 + 		if (!mode.fb_id)
352.21428 +@@ -1726,7 +2370,7 @@ void sna_copy_fbcon(struct sna *sna)
352.21429 + 	kgem_bo_destroy(&sna->kgem, bo);
352.21430 + 
352.21431 + #if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
352.21432 +-	sna->scrn->pScreen->canDoBGNoneRoot = ok;
352.21433 ++	to_screen_from_sna(sna)->canDoBGNoneRoot = ok;
352.21434 + #endif
352.21435 + }
352.21436 + 
352.21437 +@@ -1736,7 +2380,6 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
352.21438 + 	PictTransform crtc_to_fb;
352.21439 + 	struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
352.21440 + 	unsigned pitch_limit;
352.21441 +-	struct sna_pixmap *priv;
352.21442 + 	BoxRec b;
352.21443 + 
352.21444 + 	assert(sna->scrn->virtualX && sna->scrn->virtualY);
352.21445 +@@ -1765,27 +2408,31 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
352.21446 + 		return true;
352.21447 + 	}
352.21448 + 
352.21449 +-	priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
352.21450 +-	if (priv == NULL)
352.21451 +-		return true; /* maybe we can create a bo for the scanout? */
352.21452 +-
352.21453 +-	if (sna->kgem.gen == 071)
352.21454 +-		pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
352.21455 +-	else if ((sna->kgem.gen >> 3) > 4)
352.21456 +-		pitch_limit = 32 * 1024;
352.21457 +-	else if ((sna->kgem.gen >> 3) == 4)
352.21458 +-		pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
352.21459 +-	else if ((sna->kgem.gen >> 3) == 3)
352.21460 +-		pitch_limit = priv->gpu_bo->tiling ? 8 * 1024 : 16 * 1024;
352.21461 +-	else
352.21462 +-		pitch_limit = 8 * 1024;
352.21463 +-	DBG(("%s: gpu bo handle=%d tiling=%d pitch=%d, limit=%d\n", __FUNCTION__, priv->gpu_bo->handle, priv->gpu_bo->tiling, priv->gpu_bo->pitch, pitch_limit));
352.21464 +-	if (priv->gpu_bo->pitch > pitch_limit)
352.21465 +-		return true;
352.21466 ++	if (!isGPU(sna->scrn)) {
352.21467 ++		struct sna_pixmap *priv;
352.21468 + 
352.21469 +-	if (priv->gpu_bo->tiling && sna->flags & SNA_LINEAR_FB) {
352.21470 +-		DBG(("%s: gpu bo is tiled, need linear, forcing shadow\n", __FUNCTION__));
352.21471 +-		return true;
352.21472 ++		priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
352.21473 ++		if (priv == NULL)
352.21474 ++			return true; /* maybe we can create a bo for the scanout? */
352.21475 ++
352.21476 ++		if (sna->kgem.gen == 071)
352.21477 ++			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
352.21478 ++		else if ((sna->kgem.gen >> 3) > 4)
352.21479 ++			pitch_limit = 32 * 1024;
352.21480 ++		else if ((sna->kgem.gen >> 3) == 4)
352.21481 ++			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
352.21482 ++		else if ((sna->kgem.gen >> 3) == 3)
352.21483 ++			pitch_limit = priv->gpu_bo->tiling ? 8 * 1024 : 16 * 1024;
352.21484 ++		else
352.21485 ++			pitch_limit = 8 * 1024;
352.21486 ++		DBG(("%s: gpu bo handle=%d tiling=%d pitch=%d, limit=%d\n", __FUNCTION__, priv->gpu_bo->handle, priv->gpu_bo->tiling, priv->gpu_bo->pitch, pitch_limit));
352.21487 ++		if (priv->gpu_bo->pitch > pitch_limit)
352.21488 ++			return true;
352.21489 ++
352.21490 ++		if (priv->gpu_bo->tiling && sna->flags & SNA_LINEAR_FB) {
352.21491 ++			DBG(("%s: gpu bo is tiled, need linear, forcing shadow\n", __FUNCTION__));
352.21492 ++			return true;
352.21493 ++		}
352.21494 + 	}
352.21495 + 
352.21496 + 	transform = NULL;
352.21497 +@@ -1800,9 +2447,9 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
352.21498 + 		bool needs_transform = true;
352.21499 + 		unsigned rotation = rotation_reduce(&to_sna_crtc(crtc)->primary, crtc->rotation);
352.21500 + 		DBG(("%s: natively supported rotation? rotation=%x & supported=%x == %d\n",
352.21501 +-		     __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->primary.rotation.supported,
352.21502 +-		     !!(crtc->rotation & to_sna_crtc(crtc)->primary.rotation.supported)));
352.21503 +-		if (to_sna_crtc(crtc)->primary.rotation.supported & rotation)
352.21504 ++		     __FUNCTION__, rotation, to_sna_crtc(crtc)->primary.rotation.supported,
352.21505 ++		     rotation == (rotation & to_sna_crtc(crtc)->primary.rotation.supported)));
352.21506 ++		if ((to_sna_crtc(crtc)->primary.rotation.supported & rotation) == rotation)
352.21507 + 			needs_transform = RRTransformCompute(crtc->x, crtc->y,
352.21508 + 							     crtc->mode.HDisplay, crtc->mode.VDisplay,
352.21509 + 							     RR_Rotate_0, transform,
352.21510 +@@ -1839,6 +2486,7 @@ static void set_shadow(struct sna *sna, RegionPtr region)
352.21511 + 
352.21512 + 	assert(priv->gpu_bo);
352.21513 + 	assert(sna->mode.shadow);
352.21514 ++	assert(sna->mode.shadow->active_scanout);
352.21515 + 
352.21516 + 	DBG(("%s: waiting for region %dx[(%d, %d), (%d, %d)], front handle=%d, shadow handle=%d\n",
352.21517 + 	     __FUNCTION__,
352.21518 +@@ -1912,6 +2560,28 @@ get_scanout_bo(struct sna *sna, PixmapPtr pixmap)
352.21519 + 	return priv->gpu_bo;
352.21520 + }
352.21521 + 
352.21522 ++static void shadow_clear(struct sna *sna,
352.21523 ++			 PixmapPtr front, struct kgem_bo *bo,
352.21524 ++			 xf86CrtcPtr crtc)
352.21525 ++{
352.21526 ++	bool ok = false;
352.21527 ++	if (!wedged(sna))
352.21528 ++		ok = sna->render.fill_one(sna, front, bo, 0,
352.21529 ++					  0, 0, crtc->mode.HDisplay, crtc->mode.VDisplay,
352.21530 ++					  GXclear);
352.21531 ++	if (!ok) {
352.21532 ++		void *ptr = kgem_bo_map__gtt(&sna->kgem, bo);
352.21533 ++		if (ptr)
352.21534 ++			memset(ptr, 0, bo->pitch * crtc->mode.HDisplay);
352.21535 ++	}
352.21536 ++	sna->mode.shadow_dirty = true;
352.21537 ++}
352.21538 ++
352.21539 ++static bool rr_active(xf86CrtcPtr crtc)
352.21540 ++{
352.21541 ++	return crtc->transformPresent || crtc->rotation != RR_Rotate_0;
352.21542 ++}
352.21543 ++
352.21544 + static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
352.21545 + {
352.21546 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.21547 +@@ -1919,10 +2589,15 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
352.21548 + 	struct sna *sna = to_sna(scrn);
352.21549 + 	struct kgem_bo *bo;
352.21550 + 
352.21551 +-	sna_crtc->transform = false;
352.21552 ++	if (sna_crtc->transform) {
352.21553 ++		assert(sna->mode.rr_active);
352.21554 ++		sna_crtc->transform = false;
352.21555 ++		sna->mode.rr_active--;
352.21556 ++	}
352.21557 + 	sna_crtc->rotation = RR_Rotate_0;
352.21558 + 
352.21559 + 	if (use_shadow(sna, crtc)) {
352.21560 ++		PixmapPtr front;
352.21561 + 		unsigned long tiled_limit;
352.21562 + 		int tiling;
352.21563 + 
352.21564 +@@ -1949,6 +2624,10 @@ force_shadow:
352.21565 + 		}
352.21566 + 
352.21567 + 		tiling = I915_TILING_X;
352.21568 ++		if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270) &&
352.21569 ++		    sna->kgem.can_scanout_y)
352.21570 ++			tiling = I915_TILING_Y;
352.21571 ++
352.21572 + 		if (sna->kgem.gen == 071)
352.21573 + 			tiled_limit = 16 * 1024 * 8;
352.21574 + 		else if ((sna->kgem.gen >> 3) > 4)
352.21575 +@@ -1977,8 +2656,8 @@ force_shadow:
352.21576 + 			return NULL;
352.21577 + 		}
352.21578 + 
352.21579 +-		if (__sna_pixmap_get_bo(sna->front) && !crtc->transformPresent) {
352.21580 +-			DrawableRec tmp;
352.21581 ++		front = sna_crtc->slave_pixmap ?: sna->front;
352.21582 ++		if (__sna_pixmap_get_bo(front) && !rr_active(crtc)) {
352.21583 + 			BoxRec b;
352.21584 + 
352.21585 + 			b.x1 = crtc->x;
352.21586 +@@ -1986,28 +2665,48 @@ force_shadow:
352.21587 + 			b.x2 = crtc->x + crtc->mode.HDisplay;
352.21588 + 			b.y2 = crtc->y + crtc->mode.VDisplay;
352.21589 + 
352.21590 +-			DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d), handle=%d\n",
352.21591 +-			     __FUNCTION__,
352.21592 +-			     b.x1, b.y1,
352.21593 +-			     b.x2, b.y2,
352.21594 +-			     bo->handle));
352.21595 +-
352.21596 +-			tmp.width = crtc->mode.HDisplay;
352.21597 +-			tmp.height = crtc->mode.VDisplay;
352.21598 +-			tmp.depth = sna->front->drawable.depth;
352.21599 +-			tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
352.21600 +-
352.21601 +-			(void)sna->render.copy_boxes(sna, GXcopy,
352.21602 +-						     &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
352.21603 +-						     &tmp, bo, -b.x1, -b.y1,
352.21604 +-						     &b, 1, 0);
352.21605 +-		}
352.21606 ++			if (b.x1 < 0)
352.21607 ++				b.x1 = 0;
352.21608 ++			if (b.y1 < 0)
352.21609 ++				b.y1 = 0;
352.21610 ++			if (b.x2 > scrn->virtualX)
352.21611 ++				b.x2 = scrn->virtualX;
352.21612 ++			if (b.y2 > scrn->virtualY)
352.21613 ++				b.y2 = scrn->virtualY;
352.21614 ++			if (b.x2 - b.x1 < crtc->mode.HDisplay ||
352.21615 ++			    b.y2 - b.y1 < crtc->mode.VDisplay)
352.21616 ++				shadow_clear(sna, front, bo, crtc);
352.21617 ++
352.21618 ++			if (b.y2 > b.y1 && b.x2 > b.x1) {
352.21619 ++				DrawableRec tmp;
352.21620 ++
352.21621 ++				DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d) [fb=%dx%d], handle=%d\n",
352.21622 ++				     __FUNCTION__,
352.21623 ++				     b.x1, b.y1,
352.21624 ++				     b.x2-b.x1, b.y2-b.y1,
352.21625 ++				     scrn->virtualX, scrn->virtualY,
352.21626 ++				     bo->handle));
352.21627 ++
352.21628 ++				tmp.width = crtc->mode.HDisplay;
352.21629 ++				tmp.height = crtc->mode.VDisplay;
352.21630 ++				tmp.depth = front->drawable.depth;
352.21631 ++				tmp.bitsPerPixel = front->drawable.bitsPerPixel;
352.21632 ++
352.21633 ++				if (!sna->render.copy_boxes(sna, GXcopy,
352.21634 ++							     &front->drawable, __sna_pixmap_get_bo(front), 0, 0,
352.21635 ++							     &tmp, bo, -crtc->x, -crtc->y,
352.21636 ++							     &b, 1, COPY_LAST))
352.21637 ++					shadow_clear(sna, front, bo, crtc);
352.21638 ++			}
352.21639 ++		} else
352.21640 ++			shadow_clear(sna, front, bo, crtc);
352.21641 + 
352.21642 + 		sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
352.21643 + 		sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
352.21644 + 		sna_crtc->shadow_bo = bo;
352.21645 + out_shadow:
352.21646 + 		sna_crtc->transform = true;
352.21647 ++		sna->mode.rr_active++;
352.21648 + 		return kgem_bo_reference(bo);
352.21649 + 	} else {
352.21650 + 		if (sna_crtc->shadow_bo) {
352.21651 +@@ -2048,26 +2747,26 @@ out_shadow:
352.21652 + 		}
352.21653 + 
352.21654 + 		if (sna->flags & SNA_TEAR_FREE) {
352.21655 ++			RegionRec region;
352.21656 ++
352.21657 + 			assert(sna_crtc->slave_pixmap == NULL);
352.21658 + 
352.21659 + 			DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
352.21660 ++			region.extents.x1 = 0;
352.21661 ++			region.extents.y1 = 0;
352.21662 ++			region.extents.x2 = sna->scrn->virtualX;
352.21663 ++			region.extents.y2 = sna->scrn->virtualY;
352.21664 ++			region.data = NULL;
352.21665 ++
352.21666 + 			if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
352.21667 + 				DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
352.21668 + 				return NULL;
352.21669 + 			}
352.21670 + 
352.21671 +-			if (sna->mode.shadow == NULL && !wedged(sna)) {
352.21672 +-				RegionRec region;
352.21673 ++			if (sna->mode.shadow == NULL) {
352.21674 + 				struct kgem_bo *shadow;
352.21675 + 
352.21676 + 				DBG(("%s: creating TearFree shadow bo\n", __FUNCTION__));
352.21677 +-
352.21678 +-				region.extents.x1 = 0;
352.21679 +-				region.extents.y1 = 0;
352.21680 +-				region.extents.x2 = sna->scrn->virtualX;
352.21681 +-				region.extents.y2 = sna->scrn->virtualY;
352.21682 +-				region.data = NULL;
352.21683 +-
352.21684 + 				shadow = kgem_create_2d(&sna->kgem,
352.21685 + 							region.extents.x2,
352.21686 + 							region.extents.y2,
352.21687 +@@ -2093,9 +2792,12 @@ out_shadow:
352.21688 + 					goto force_shadow;
352.21689 + 				}
352.21690 + 
352.21691 ++				assert(__sna_pixmap_get_bo(sna->front) == NULL ||
352.21692 ++				       __sna_pixmap_get_bo(sna->front)->pitch == shadow->pitch);
352.21693 + 				sna->mode.shadow = shadow;
352.21694 +-				set_shadow(sna, &region);
352.21695 ++				sna->mode.shadow->active_scanout++;
352.21696 + 			}
352.21697 ++			set_shadow(sna, &region);
352.21698 + 
352.21699 + 			sna_crtc_disable_override(sna, sna_crtc);
352.21700 + 		} else
352.21701 +@@ -2107,6 +2809,37 @@ out_shadow:
352.21702 + 	}
352.21703 + }
352.21704 + 
352.21705 ++#define SCALING_EPSILON (1./256)
352.21706 ++
352.21707 ++static bool
352.21708 ++is_affine(const struct pixman_f_transform *t)
352.21709 ++{
352.21710 ++	return (fabs(t->m[2][0]) < SCALING_EPSILON &&
352.21711 ++		fabs(t->m[2][1]) < SCALING_EPSILON);
352.21712 ++}
352.21713 ++
352.21714 ++static double determinant(const struct pixman_f_transform *t)
352.21715 ++{
352.21716 ++	return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1];
352.21717 ++}
352.21718 ++
352.21719 ++static bool
352.21720 ++affine_is_pixel_exact(const struct pixman_f_transform *t)
352.21721 ++{
352.21722 ++	double det = t->m[2][2] * determinant(t);
352.21723 ++	if (fabs (det * det - 1.0) < SCALING_EPSILON) {
352.21724 ++		if (fabs(t->m[0][1]) < SCALING_EPSILON &&
352.21725 ++		    fabs(t->m[1][0]) < SCALING_EPSILON)
352.21726 ++			return true;
352.21727 ++
352.21728 ++		if (fabs(t->m[0][0]) < SCALING_EPSILON &&
352.21729 ++		    fabs(t->m[1][1]) < SCALING_EPSILON)
352.21730 ++			return true;
352.21731 ++	}
352.21732 ++
352.21733 ++	return false;
352.21734 ++}
352.21735 ++
352.21736 + static void sna_crtc_randr(xf86CrtcPtr crtc)
352.21737 + {
352.21738 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.21739 +@@ -2152,6 +2885,25 @@ static void sna_crtc_randr(xf86CrtcPtr crtc)
352.21740 + 	} else
352.21741 + 		crtc->transform_in_use = sna_crtc->rotation != RR_Rotate_0;
352.21742 + 
352.21743 ++	/* Recompute the cursor after a potential change in transform */
352.21744 ++	if (sna_crtc->cursor) {
352.21745 ++		assert(sna_crtc->cursor->ref > 0);
352.21746 ++		sna_crtc->cursor->ref--;
352.21747 ++		sna_crtc->cursor = NULL;
352.21748 ++	}
352.21749 ++
352.21750 ++	if (needs_transform) {
352.21751 ++		sna_crtc->hwcursor = is_affine(&f_fb_to_crtc);
352.21752 ++		sna_crtc->cursor_transform =
352.21753 ++			sna_crtc->hwcursor &&
352.21754 ++			!affine_is_pixel_exact(&f_fb_to_crtc);
352.21755 ++	} else {
352.21756 ++		sna_crtc->hwcursor = true;
352.21757 ++		sna_crtc->cursor_transform = false;
352.21758 ++	}
352.21759 ++	DBG(("%s: hwcursor?=%d, cursor_transform?=%d\n",
352.21760 ++	     __FUNCTION__, sna_crtc->hwcursor, sna_crtc->cursor_transform));
352.21761 ++
352.21762 + 	crtc->crtc_to_framebuffer = crtc_to_fb;
352.21763 + 	crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
352.21764 + 	crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
352.21765 +@@ -2184,7 +2936,7 @@ static void sna_crtc_randr(xf86CrtcPtr crtc)
352.21766 + static void
352.21767 + sna_crtc_damage(xf86CrtcPtr crtc)
352.21768 + {
352.21769 +-	ScreenPtr screen = crtc->scrn->pScreen;
352.21770 ++	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
352.21771 + 	struct sna *sna = to_sna(crtc->scrn);
352.21772 + 	RegionRec region, *damage;
352.21773 + 
352.21774 +@@ -2200,15 +2952,21 @@ sna_crtc_damage(xf86CrtcPtr crtc)
352.21775 + 	if (region.extents.y2 > screen->height)
352.21776 + 		region.extents.y2 = screen->height;
352.21777 + 
352.21778 ++	if (region.extents.x2 <= region.extents.x1 ||
352.21779 ++	    region.extents.y2 <= region.extents.y1) {
352.21780 ++		DBG(("%s: crtc not damaged, all-clipped\n", __FUNCTION__));
352.21781 ++		return;
352.21782 ++	}
352.21783 ++
352.21784 + 	DBG(("%s: marking crtc %d as completely damaged (%d, %d), (%d, %d)\n",
352.21785 +-	     __FUNCTION__, to_sna_crtc(crtc)->id,
352.21786 ++	     __FUNCTION__, sna_crtc_id(crtc),
352.21787 + 	     region.extents.x1, region.extents.y1,
352.21788 + 	     region.extents.x2, region.extents.y2));
352.21789 +-	to_sna_crtc(crtc)->client_damage = region;
352.21790 + 
352.21791 + 	assert(sna->mode.shadow_damage && sna->mode.shadow_active);
352.21792 + 	damage = DamageRegion(sna->mode.shadow_damage);
352.21793 + 	RegionUnion(damage, damage, &region);
352.21794 ++	to_sna_crtc(crtc)->crtc_damage = region;
352.21795 + 
352.21796 + 	DBG(("%s: damage now %dx[(%d, %d), (%d, %d)]\n",
352.21797 + 	     __FUNCTION__,
352.21798 +@@ -2260,6 +3018,21 @@ static const char *reflection_to_str(Rotation rotation)
352.21799 + 	}
352.21800 + }
352.21801 + 
352.21802 ++static void reprobe_connectors(xf86CrtcPtr crtc)
352.21803 ++{
352.21804 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
352.21805 ++	struct sna *sna = to_sna(crtc->scrn);
352.21806 ++	int i;
352.21807 ++
352.21808 ++	for (i = 0; i < sna->mode.num_real_output; i++) {
352.21809 ++		xf86OutputPtr output = config->output[i];
352.21810 ++		if (output->crtc == crtc)
352.21811 ++			to_sna_output(output)->reprobe = true;
352.21812 ++	}
352.21813 ++
352.21814 ++	sna_mode_discover(sna, true);
352.21815 ++}
352.21816 ++
352.21817 + static Bool
352.21818 + __sna_crtc_set_mode(xf86CrtcPtr crtc)
352.21819 + {
352.21820 +@@ -2268,11 +3041,19 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
352.21821 + 	struct kgem_bo *saved_bo, *bo;
352.21822 + 	uint32_t saved_offset;
352.21823 + 	bool saved_transform;
352.21824 ++	bool saved_hwcursor;
352.21825 ++	bool saved_cursor_transform;
352.21826 ++	int ret;
352.21827 + 
352.21828 +-	DBG(("%s\n", __FUNCTION__));
352.21829 ++	DBG(("%s: CRTC=%d, pipe=%d, hidden?=%d\n", __FUNCTION__,
352.21830 ++	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna->mode.hidden));
352.21831 ++	if (sna->mode.hidden)
352.21832 ++		return TRUE;
352.21833 + 
352.21834 + 	saved_bo = sna_crtc->bo;
352.21835 + 	saved_transform = sna_crtc->transform;
352.21836 ++	saved_cursor_transform = sna_crtc->cursor_transform;
352.21837 ++	saved_hwcursor = sna_crtc->hwcursor;
352.21838 + 	saved_offset = sna_crtc->offset;
352.21839 + 
352.21840 + 	sna_crtc->fallback_shadow = false;
352.21841 +@@ -2285,26 +3066,31 @@ retry: /* Attach per-crtc pixmap or direct */
352.21842 + 	}
352.21843 + 
352.21844 + 	/* Prevent recursion when enabling outputs during execbuffer */
352.21845 +-	if (bo->exec && RQ(bo->rq)->bo == NULL)
352.21846 ++	if (bo->exec && RQ(bo->rq)->bo == NULL) {
352.21847 + 		_kgem_submit(&sna->kgem);
352.21848 ++		__kgem_bo_clear_dirty(bo);
352.21849 ++	}
352.21850 + 
352.21851 + 	sna_crtc->bo = bo;
352.21852 +-	if (!sna_crtc_apply(crtc)) {
352.21853 +-		int err = errno;
352.21854 +-
352.21855 ++	ret = sna_crtc_apply(crtc);
352.21856 ++	if (ret) {
352.21857 + 		kgem_bo_destroy(&sna->kgem, bo);
352.21858 + 
352.21859 +-		if (!sna_crtc->shadow) {
352.21860 ++		if (!sna_crtc->fallback_shadow) {
352.21861 + 			sna_crtc->fallback_shadow = true;
352.21862 + 			goto retry;
352.21863 + 		}
352.21864 + 
352.21865 + 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
352.21866 +-			   "failed to set mode: %s [%d]\n", strerror(err), err);
352.21867 ++			   "failed to set mode: %s [%d]\n", strerror(ret), ret);
352.21868 + 		goto error;
352.21869 + 	}
352.21870 + 
352.21871 ++	sna_crtc->flags |= CRTC_ON;
352.21872 + 	bo->active_scanout++;
352.21873 ++	DBG(("%s: marking handle=%d as active=%d (removing %d from scanout, active=%d)\n",
352.21874 ++	     __FUNCTION__, bo->handle, bo->active_scanout,
352.21875 ++	     saved_bo ? saved_bo->handle : 0, saved_bo ? saved_bo->active_scanout - 1: -1));
352.21876 + 	if (saved_bo) {
352.21877 + 		assert(saved_bo->active_scanout);
352.21878 + 		assert(saved_bo->refcnt >= saved_bo->active_scanout);
352.21879 +@@ -2315,17 +3101,34 @@ retry: /* Attach per-crtc pixmap or direct */
352.21880 + 	sna_crtc_randr(crtc);
352.21881 + 	if (sna_crtc->transform)
352.21882 + 		sna_crtc_damage(crtc);
352.21883 ++	if (sna_crtc->cursor &&  /* Reload cursor if RandR maybe changed */
352.21884 ++	    (!sna_crtc->hwcursor ||
352.21885 ++	     saved_cursor_transform || sna_crtc->cursor_transform ||
352.21886 ++	     sna_crtc->cursor->rotation != crtc->rotation))
352.21887 ++		sna_crtc_disable_cursor(sna, sna_crtc);
352.21888 ++
352.21889 ++	assert(!sna->mode.hidden);
352.21890 + 	sna->mode.front_active += saved_bo == NULL;
352.21891 + 	sna->mode.dirty = true;
352.21892 +-	DBG(("%s: front_active=%d\n", __FUNCTION__, sna->mode.front_active));
352.21893 ++	DBG(("%s: handle=%d, scanout_active=%d, front_active=%d\n",
352.21894 ++	     __FUNCTION__, bo->handle, bo->active_scanout, sna->mode.front_active));
352.21895 + 
352.21896 + 	return TRUE;
352.21897 + 
352.21898 + error:
352.21899 + 	sna_crtc->offset = saved_offset;
352.21900 ++	if (sna_crtc->transform) {
352.21901 ++		assert(sna->mode.rr_active);
352.21902 ++		sna->mode.rr_active--;
352.21903 ++	}
352.21904 ++	if (saved_transform)
352.21905 ++		sna->mode.rr_active++;
352.21906 + 	sna_crtc->transform = saved_transform;
352.21907 ++	sna_crtc->cursor_transform = saved_cursor_transform;
352.21908 ++	sna_crtc->hwcursor = saved_hwcursor;
352.21909 + 	sna_crtc->bo = saved_bo;
352.21910 +-	sna_mode_discover(sna);
352.21911 ++
352.21912 ++	reprobe_connectors(crtc);
352.21913 + 	return FALSE;
352.21914 + }
352.21915 + 
352.21916 +@@ -2346,14 +3149,14 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
352.21917 + 	xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
352.21918 + 		   "switch to mode %dx%d@%.1f on %s using pipe %d, position (%d, %d), rotation %s, reflection %s\n",
352.21919 + 		   mode->HDisplay, mode->VDisplay, xf86ModeVRefresh(mode),
352.21920 +-		   outputs_for_crtc(crtc, outputs, sizeof(outputs)), sna_crtc->pipe,
352.21921 ++		   outputs_for_crtc(crtc, outputs, sizeof(outputs)), __sna_crtc_pipe(sna_crtc),
352.21922 + 		   x, y, rotation_to_str(rotation), reflection_to_str(rotation));
352.21923 + 
352.21924 + 	assert(mode->HDisplay <= sna->mode.max_crtc_width &&
352.21925 + 	       mode->VDisplay <= sna->mode.max_crtc_height);
352.21926 + 
352.21927 + #if HAS_GAMMA
352.21928 +-	drmModeCrtcSetGamma(sna->kgem.fd, sna_crtc->id,
352.21929 ++	drmModeCrtcSetGamma(sna->kgem.fd, __sna_crtc_id(sna_crtc),
352.21930 + 			    crtc->gamma_size,
352.21931 + 			    crtc->gamma_red,
352.21932 + 			    crtc->gamma_green,
352.21933 +@@ -2372,17 +3175,10 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
352.21934 + static void
352.21935 + sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
352.21936 + {
352.21937 +-	struct sna_crtc *priv = to_sna_crtc(crtc);
352.21938 +-
352.21939 + 	DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n",
352.21940 +-	     __FUNCTION__, priv->pipe, mode, mode == DPMSModeOn));
352.21941 +-	if (priv->dpms_mode == mode)
352.21942 +-		return;
352.21943 +-
352.21944 +-	assert(priv);
352.21945 +-	priv->dpms_mode = mode;
352.21946 ++	     __FUNCTION__, sna_crtc_pipe(crtc), mode, mode == DPMSModeOn));
352.21947 + 
352.21948 +-	if (mode == DPMSModeOn && crtc->enabled && priv->bo == NULL) {
352.21949 ++	if (mode == DPMSModeOn && crtc->enabled) {
352.21950 + 		if (__sna_crtc_set_mode(crtc))
352.21951 + 			update_flush_interval(to_sna(crtc->scrn));
352.21952 + 		else
352.21953 +@@ -2390,7 +3186,7 @@ sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
352.21954 + 	}
352.21955 + 
352.21956 + 	if (mode != DPMSModeOn)
352.21957 +-		sna_crtc_disable(crtc);
352.21958 ++		sna_crtc_disable(crtc, false);
352.21959 + }
352.21960 + 
352.21961 + void sna_mode_adjust_frame(struct sna *sna, int x, int y)
352.21962 +@@ -2426,7 +3222,7 @@ sna_crtc_gamma_set(xf86CrtcPtr crtc,
352.21963 + {
352.21964 + 	assert(to_sna_crtc(crtc));
352.21965 + 	drmModeCrtcSetGamma(to_sna(crtc->scrn)->kgem.fd,
352.21966 +-			    to_sna_crtc(crtc)->id,
352.21967 ++			    sna_crtc_id(crtc),
352.21968 + 			    size, red, green, blue);
352.21969 + }
352.21970 + 
352.21971 +@@ -2434,10 +3230,14 @@ static void
352.21972 + sna_crtc_destroy(xf86CrtcPtr crtc)
352.21973 + {
352.21974 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.21975 ++	struct plane *sprite, *sn;
352.21976 + 
352.21977 + 	if (sna_crtc == NULL)
352.21978 + 		return;
352.21979 + 
352.21980 ++	list_for_each_entry_safe(sprite, sn, &sna_crtc->sprites, link)
352.21981 ++		free(sprite);
352.21982 ++
352.21983 + 	free(sna_crtc);
352.21984 + 	crtc->driver_private = NULL;
352.21985 + }
352.21986 +@@ -2455,7 +3255,7 @@ sna_crtc_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr pixmap)
352.21987 + 		return TRUE;
352.21988 + 
352.21989 + 	DBG(("%s: CRTC:%d, pipe=%d setting scanout pixmap=%ld\n",
352.21990 +-	     __FUNCTION__, sna_crtc->id,  sna_crtc->pipe,
352.21991 ++	     __FUNCTION__, __sna_crtc_id(sna_crtc),  __sna_crtc_pipe(sna_crtc),
352.21992 + 	     pixmap ? pixmap->drawable.serialNumber : 0));
352.21993 + 
352.21994 + 	/* Disable first so that we can unregister the damage tracking */
352.21995 +@@ -2576,6 +3376,10 @@ static int plane_details(struct sna *sna, struct plane *p)
352.21996 + 		}
352.21997 + 	}
352.21998 + 
352.21999 ++	p->rotation.supported &= DBG_NATIVE_ROTATION;
352.22000 ++	if (!xf86ReturnOptValBool(sna->Options, OPTION_ROTATION, TRUE))
352.22001 ++		p->rotation.supported = RR_Rotate_0;
352.22002 ++
352.22003 + 	if (props != (uint32_t *)stack_props)
352.22004 + 		free(props);
352.22005 + 
352.22006 +@@ -2583,20 +3387,26 @@ static int plane_details(struct sna *sna, struct plane *p)
352.22007 + 	return type;
352.22008 + }
352.22009 + 
352.22010 ++static void add_sprite_plane(struct sna_crtc *crtc,
352.22011 ++			     struct plane *details)
352.22012 ++{
352.22013 ++	struct plane *sprite = malloc(sizeof(*sprite));
352.22014 ++	if (!sprite)
352.22015 ++		return;
352.22016 ++
352.22017 ++	memcpy(sprite, details, sizeof(*sprite));
352.22018 ++	list_add(&sprite->link, &crtc->sprites);
352.22019 ++}
352.22020 ++
352.22021 + static void
352.22022 + sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
352.22023 + {
352.22024 + #define LOCAL_IOCTL_SET_CAP	DRM_IOWR(0x0d, struct local_set_cap)
352.22025 +-#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
352.22026 +-#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane)
352.22027 + 	struct local_set_cap {
352.22028 + 		uint64_t name;
352.22029 + 		uint64_t value;
352.22030 + 	} cap;
352.22031 +-	struct local_mode_get_plane_res {
352.22032 +-		uint64_t plane_id_ptr;
352.22033 +-		uint64_t count_planes;
352.22034 +-	} r;
352.22035 ++	struct local_mode_get_plane_res r;
352.22036 + 	uint32_t stack_planes[32];
352.22037 + 	uint32_t *planes = stack_planes;
352.22038 + 	int i;
352.22039 +@@ -2629,18 +3439,7 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
352.22040 + 	VG(VALGRIND_MAKE_MEM_DEFINED(planes, sizeof(uint32_t)*r.count_planes));
352.22041 + 
352.22042 + 	for (i = 0; i < r.count_planes; i++) {
352.22043 +-		struct local_mode_get_plane {
352.22044 +-			uint32_t plane_id;
352.22045 +-
352.22046 +-			uint32_t crtc_id;
352.22047 +-			uint32_t fb_id;
352.22048 +-
352.22049 +-			uint32_t possible_crtcs;
352.22050 +-			uint32_t gamma_size;
352.22051 +-
352.22052 +-			uint32_t count_format_types;
352.22053 +-			uint64_t format_type_ptr;
352.22054 +-		} p;
352.22055 ++		struct local_mode_get_plane p;
352.22056 + 		struct plane details;
352.22057 + 
352.22058 + 		VG_CLEAR(p);
352.22059 +@@ -2649,11 +3448,11 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
352.22060 + 		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANE, &p))
352.22061 + 			continue;
352.22062 + 
352.22063 +-		if ((p.possible_crtcs & (1 << crtc->pipe)) == 0)
352.22064 ++		if ((p.possible_crtcs & (1 << __sna_crtc_pipe(crtc))) == 0)
352.22065 + 			continue;
352.22066 + 
352.22067 + 		DBG(("%s: plane %d is attached to our pipe=%d\n",
352.22068 +-		     __FUNCTION__, planes[i], crtc->pipe));
352.22069 ++		     __FUNCTION__, planes[i], __sna_crtc_pipe(crtc)));
352.22070 + 
352.22071 + 		details.id = p.plane_id;
352.22072 + 		details.rotation.prop = 0;
352.22073 +@@ -2672,8 +3471,7 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
352.22074 + 			break;
352.22075 + 
352.22076 + 		case DRM_PLANE_TYPE_OVERLAY:
352.22077 +-			if (crtc->sprite.id == 0)
352.22078 +-				crtc->sprite = details;
352.22079 ++			add_sprite_plane(crtc, &details);
352.22080 + 			break;
352.22081 + 		}
352.22082 + 	}
352.22083 +@@ -2688,7 +3486,6 @@ sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *crtc)
352.22084 + 	crtc->rotation = RR_Rotate_0;
352.22085 + 	crtc->primary.rotation.supported = RR_Rotate_0;
352.22086 + 	crtc->primary.rotation.current = RR_Rotate_0;
352.22087 +-	crtc->sprite.rotation = crtc->primary.rotation;
352.22088 + }
352.22089 + 
352.22090 + static void
352.22091 +@@ -2698,55 +3495,55 @@ sna_crtc_init__cursor(struct sna *sna, struct sna_crtc *crtc)
352.22092 + 
352.22093 + 	VG_CLEAR(arg);
352.22094 + 	arg.flags = DRM_MODE_CURSOR_BO;
352.22095 +-	arg.crtc_id = crtc->id;
352.22096 ++	arg.crtc_id = __sna_crtc_id(crtc);
352.22097 + 	arg.width = arg.height = 0;
352.22098 + 	arg.handle = 0;
352.22099 + 
352.22100 + 	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
352.22101 ++	crtc->hwcursor = true;
352.22102 + }
352.22103 + 
352.22104 + static bool
352.22105 +-sna_crtc_add(ScrnInfoPtr scrn, int id)
352.22106 ++sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
352.22107 + {
352.22108 + 	struct sna *sna = to_sna(scrn);
352.22109 + 	xf86CrtcPtr crtc;
352.22110 + 	struct sna_crtc *sna_crtc;
352.22111 + 	struct drm_i915_get_pipe_from_crtc_id get_pipe;
352.22112 + 
352.22113 +-	DBG(("%s(%d)\n", __FUNCTION__, id));
352.22114 ++	DBG(("%s(%d): is-zaphod? %d\n", __FUNCTION__, id, is_zaphod(scrn)));
352.22115 + 
352.22116 + 	sna_crtc = calloc(sizeof(struct sna_crtc), 1);
352.22117 + 	if (sna_crtc == NULL)
352.22118 + 		return false;
352.22119 + 
352.22120 + 	sna_crtc->id = id;
352.22121 +-	sna_crtc->dpms_mode = -1;
352.22122 + 
352.22123 + 	VG_CLEAR(get_pipe);
352.22124 + 	get_pipe.pipe = 0;
352.22125 +-	get_pipe.crtc_id = sna_crtc->id;
352.22126 ++	get_pipe.crtc_id = id;
352.22127 + 	if (drmIoctl(sna->kgem.fd,
352.22128 + 		     DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
352.22129 + 		     &get_pipe)) {
352.22130 + 		free(sna_crtc);
352.22131 + 		return false;
352.22132 + 	}
352.22133 +-	sna_crtc->pipe = get_pipe.pipe;
352.22134 ++	assert((unsigned)get_pipe.pipe < 256);
352.22135 ++	sna_crtc->flags |= get_pipe.pipe << 8;
352.22136 + 
352.22137 + 	if (is_zaphod(scrn) &&
352.22138 +-	    scrn->confScreen->device->screen != sna_crtc->pipe) {
352.22139 ++	    (get_zaphod_crtcs(sna) & (1 << get_pipe.pipe)) == 0) {
352.22140 + 		free(sna_crtc);
352.22141 + 		return true;
352.22142 + 	}
352.22143 + 
352.22144 ++	list_init(&sna_crtc->sprites);
352.22145 + 	sna_crtc_init__rotation(sna, sna_crtc);
352.22146 +-
352.22147 + 	sna_crtc_find_planes(sna, sna_crtc);
352.22148 + 
352.22149 +-	DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x, sprite id=%x: supported-rotations=%x, current-rotation=%x\n",
352.22150 +-	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
352.22151 +-	     sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current,
352.22152 +-	     sna_crtc->sprite.id, sna_crtc->sprite.rotation.supported, sna_crtc->sprite.rotation.current));
352.22153 ++	DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x\n",
352.22154 ++	     __FUNCTION__, id, get_pipe.pipe,
352.22155 ++	     sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current));
352.22156 + 
352.22157 + 	list_init(&sna_crtc->shadow_link);
352.22158 + 
352.22159 +@@ -2761,7 +3558,7 @@ sna_crtc_add(ScrnInfoPtr scrn, int id)
352.22160 + 	crtc->driver_private = sna_crtc;
352.22161 + 	sna_crtc->base = crtc;
352.22162 + 	DBG(("%s: attached crtc[%d] pipe=%d\n",
352.22163 +-	     __FUNCTION__, id, sna_crtc->pipe));
352.22164 ++	     __FUNCTION__, id, __sna_crtc_pipe(sna_crtc)));
352.22165 + 
352.22166 + 	return true;
352.22167 + }
352.22168 +@@ -2798,20 +3595,56 @@ find_property(struct sna *sna, struct sna_output *output, const char *name)
352.22169 + 	return -1;
352.22170 + }
352.22171 + 
352.22172 ++static void update_properties(struct sna *sna, struct sna_output *output)
352.22173 ++{
352.22174 ++	union compat_mode_get_connector compat_conn;
352.22175 ++	struct drm_mode_modeinfo dummy;
352.22176 ++
352.22177 ++	VG_CLEAR(compat_conn);
352.22178 ++
352.22179 ++	compat_conn.conn.connector_id = output->id;
352.22180 ++	compat_conn.conn.count_props = output->num_props;
352.22181 ++	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
352.22182 ++	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
352.22183 ++	compat_conn.conn.count_modes = 1; /* skip detect */
352.22184 ++	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
352.22185 ++	compat_conn.conn.count_encoders = 0;
352.22186 ++
352.22187 ++	(void)drmIoctl(sna->kgem.fd,
352.22188 ++		       DRM_IOCTL_MODE_GETCONNECTOR,
352.22189 ++		       &compat_conn.conn);
352.22190 ++
352.22191 ++	assert(compat_conn.conn.count_props == output->num_props);
352.22192 ++	output->update_properties = false;
352.22193 ++}
352.22194 ++
352.22195 + static xf86OutputStatus
352.22196 + sna_output_detect(xf86OutputPtr output)
352.22197 + {
352.22198 + 	struct sna *sna = to_sna(output->scrn);
352.22199 + 	struct sna_output *sna_output = output->driver_private;
352.22200 + 	union compat_mode_get_connector compat_conn;
352.22201 ++	uint32_t now;
352.22202 + 
352.22203 + 	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
352.22204 ++	sna_output->update_properties = false;
352.22205 + 
352.22206 + 	if (!sna_output->id) {
352.22207 + 		DBG(("%s(%s) hiding due to lost connection\n", __FUNCTION__, output->name));
352.22208 + 		return XF86OutputStatusDisconnected;
352.22209 + 	}
352.22210 + 
352.22211 ++	/* Cache detections for 15s or hotplug event  */
352.22212 ++	now = GetTimeInMillis();
352.22213 ++	if (sna_output->last_detect != 0 &&
352.22214 ++	    (int32_t)(now - sna_output->last_detect) <= OUTPUT_STATUS_CACHE_MS) {
352.22215 ++		DBG(("%s(%s) reporting cached status (since %dms): %d\n",
352.22216 ++		     __FUNCTION__, output->name, now - sna_output->last_detect,
352.22217 ++		     sna_output->status));
352.22218 ++		sna_output->update_properties = true;
352.22219 ++		return sna_output->status;
352.22220 ++	}
352.22221 ++
352.22222 + 	VG_CLEAR(compat_conn);
352.22223 + 	compat_conn.conn.connector_id = sna_output->id;
352.22224 + 	sna_output->num_modes = compat_conn.conn.count_modes = 0; /* reprobe */
352.22225 +@@ -2854,15 +3687,23 @@ sna_output_detect(xf86OutputPtr output)
352.22226 + 	DBG(("%s(%s): found %d modes, connection status=%d\n",
352.22227 + 	     __FUNCTION__, output->name, sna_output->num_modes, compat_conn.conn.connection));
352.22228 + 
352.22229 ++	sna_output->reprobe = false;
352.22230 ++	sna_output->last_detect = now;
352.22231 + 	switch (compat_conn.conn.connection) {
352.22232 + 	case DRM_MODE_CONNECTED:
352.22233 +-		return XF86OutputStatusConnected;
352.22234 ++		sna_output->status = XF86OutputStatusConnected;
352.22235 ++		output->mm_width = compat_conn.conn.mm_width;
352.22236 ++		output->mm_height = compat_conn.conn.mm_height;
352.22237 ++		break;
352.22238 + 	case DRM_MODE_DISCONNECTED:
352.22239 +-		return XF86OutputStatusDisconnected;
352.22240 ++		sna_output->status = XF86OutputStatusDisconnected;
352.22241 ++		break;
352.22242 + 	default:
352.22243 + 	case DRM_MODE_UNKNOWNCONNECTION:
352.22244 +-		return XF86OutputStatusUnknown;
352.22245 ++		sna_output->status = XF86OutputStatusUnknown;
352.22246 ++		break;
352.22247 + 	}
352.22248 ++	return sna_output->status;
352.22249 + }
352.22250 + 
352.22251 + static Bool
352.22252 +@@ -2895,6 +3736,27 @@ sna_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
352.22253 + 	return MODE_OK;
352.22254 + }
352.22255 + 
352.22256 ++static void sna_output_set_parsed_edid(xf86OutputPtr output, xf86MonPtr mon)
352.22257 ++{
352.22258 ++	unsigned conn_mm_width, conn_mm_height;
352.22259 ++
352.22260 ++	/* We set the output size based on values from the kernel */
352.22261 ++	conn_mm_width = output->mm_width;
352.22262 ++	conn_mm_height = output->mm_height;
352.22263 ++
352.22264 ++	xf86OutputSetEDID(output, mon);
352.22265 ++
352.22266 ++	if (output->mm_width != conn_mm_width || output->mm_height != conn_mm_height) {
352.22267 ++		DBG(("%s)%s): kernel and Xorg disagree over physical size: kernel=%dx%dmm, Xorg=%dx%dmm\n",
352.22268 ++		     __FUNCTION__, output->name,
352.22269 ++		     conn_mm_width, conn_mm_height,
352.22270 ++		     output->mm_width, output->mm_height));
352.22271 ++	}
352.22272 ++
352.22273 ++	output->mm_width = conn_mm_width;
352.22274 ++	output->mm_height = conn_mm_height;
352.22275 ++}
352.22276 ++
352.22277 + static void
352.22278 + sna_output_attach_edid(xf86OutputPtr output)
352.22279 + {
352.22280 +@@ -2907,6 +3769,13 @@ sna_output_attach_edid(xf86OutputPtr output)
352.22281 + 	if (sna_output->edid_idx == -1)
352.22282 + 		return;
352.22283 + 
352.22284 ++	/* Always refresh the blob as the kernel may randomly update the
352.22285 ++	 * id even if the contents of the blob doesn't change, and a
352.22286 ++	 * request for the stale id will return nothing.
352.22287 ++	 */
352.22288 ++	if (sna_output->update_properties)
352.22289 ++		update_properties(sna, sna_output);
352.22290 ++
352.22291 + 	raw = sna_output->edid_raw;
352.22292 + 	blob.length = sna_output->edid_len;
352.22293 + 
352.22294 +@@ -2917,8 +3786,12 @@ sna_output_attach_edid(xf86OutputPtr output)
352.22295 + 		old = NULL;
352.22296 + 
352.22297 + 	blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
352.22298 +-	DBG(("%s: attaching EDID id=%d, current=%d\n",
352.22299 +-	     __FUNCTION__, blob.blob_id, sna_output->edid_blob_id));
352.22300 ++	if (!blob.blob_id)
352.22301 ++		goto done;
352.22302 ++
352.22303 ++	DBG(("%s(%s): attaching EDID id=%d, current=%d\n",
352.22304 ++	     __FUNCTION__, output->name,
352.22305 ++	     blob.blob_id, sna_output->edid_blob_id));
352.22306 + 	if (blob.blob_id == sna_output->edid_blob_id && 0) { /* sigh */
352.22307 + 		if (output->MonInfo) {
352.22308 + 			/* XXX the property keeps on disappearing... */
352.22309 +@@ -2936,26 +3809,45 @@ sna_output_attach_edid(xf86OutputPtr output)
352.22310 + 	}
352.22311 + 
352.22312 + 	blob.data = (uintptr_t)raw;
352.22313 +-	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
352.22314 +-		goto done;
352.22315 ++	do {
352.22316 ++		while (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
352.22317 ++			update_properties(sna, sna_output);
352.22318 ++			if (blob.blob_id == sna_output->prop_values[sna_output->edid_idx]) {
352.22319 ++				DBG(("%s(%s): failed to read blob, reusing previous\n",
352.22320 ++				     __FUNCTION__, output->name));
352.22321 ++				goto done;
352.22322 ++			}
352.22323 ++			blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
352.22324 ++		}
352.22325 + 
352.22326 +-	DBG(("%s: retrieving blob id=%d, length=%d\n",
352.22327 +-	     __FUNCTION__, blob.blob_id, blob.length));
352.22328 ++		DBG(("%s(%s): retrieving blob id=%d, length=%d\n",
352.22329 ++		     __FUNCTION__, output->name, blob.blob_id, blob.length));
352.22330 + 
352.22331 +-	if (blob.length > sna_output->edid_len) {
352.22332 +-		raw = realloc(raw, blob.length);
352.22333 +-		if (raw == NULL)
352.22334 ++		if (blob.length < 128)
352.22335 + 			goto done;
352.22336 + 
352.22337 +-		VG(memset(raw, 0, blob.length));
352.22338 +-		blob.data = (uintptr_t)raw;
352.22339 +-		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
352.22340 +-			goto done;
352.22341 ++		if (blob.length > sna_output->edid_len) {
352.22342 ++			raw = realloc(raw, blob.length);
352.22343 ++			if (raw == NULL)
352.22344 ++				goto done;
352.22345 ++
352.22346 ++			VG(memset(raw, 0, blob.length));
352.22347 ++			blob.data = (uintptr_t)raw;
352.22348 ++		}
352.22349 ++	} while (blob.length != sna_output->edid_len &&
352.22350 ++		 drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob));
352.22351 ++
352.22352 ++	if (blob.length & 127) {
352.22353 ++		/* Truncated EDID! Make sure no one reads too far */
352.22354 ++		*SECTION(NO_EDID, (uint8_t*)raw) = blob.length/128 - 1;
352.22355 ++		blob.length &= -128;
352.22356 + 	}
352.22357 + 
352.22358 + 	if (old &&
352.22359 + 	    blob.length == sna_output->edid_len &&
352.22360 + 	    memcmp(old, raw, blob.length) == 0) {
352.22361 ++		DBG(("%s(%s): EDID + MonInfo is unchanged\n",
352.22362 ++		     __FUNCTION__, output->name));
352.22363 + 		assert(sna_output->edid_raw == raw);
352.22364 + 		sna_output->edid_blob_id = blob.blob_id;
352.22365 + 		RRChangeOutputProperty(output->randr_output,
352.22366 +@@ -2974,31 +3866,186 @@ skip_read:
352.22367 + 			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
352.22368 + 	}
352.22369 + 
352.22370 +-done:
352.22371 +-	xf86OutputSetEDID(output, mon);
352.22372 +-	if (raw) {
352.22373 +-		sna_output->edid_raw = raw;
352.22374 +-		sna_output->edid_len = blob.length;
352.22375 +-		sna_output->edid_blob_id = blob.blob_id;
352.22376 ++done:
352.22377 ++	sna_output_set_parsed_edid(output, mon);
352.22378 ++	if (raw) {
352.22379 ++		sna_output->edid_raw = raw;
352.22380 ++		sna_output->edid_len = blob.length;
352.22381 ++		sna_output->edid_blob_id = blob.blob_id;
352.22382 ++	}
352.22383 ++}
352.22384 ++
352.22385 ++static void
352.22386 ++sna_output_attach_tile(xf86OutputPtr output)
352.22387 ++{
352.22388 ++#if XF86_OUTPUT_VERSION >= 3
352.22389 ++	struct sna *sna = to_sna(output->scrn);
352.22390 ++	struct sna_output *sna_output = output->driver_private;
352.22391 ++	struct drm_mode_get_blob blob;
352.22392 ++	struct xf86CrtcTileInfo tile_info, *set = NULL;
352.22393 ++	char *tile;
352.22394 ++	int id;
352.22395 ++
352.22396 ++	id = find_property(sna, sna_output, "TILE");
352.22397 ++	DBG(("%s: found? TILE=%d\n", __FUNCTION__, id));
352.22398 ++	if (id == -1)
352.22399 ++		goto out;
352.22400 ++
352.22401 ++	if (sna_output->update_properties)
352.22402 ++		update_properties(sna, sna_output);
352.22403 ++
352.22404 ++	VG_CLEAR(blob);
352.22405 ++	blob.blob_id = sna_output->prop_values[id];
352.22406 ++	blob.length = 0;
352.22407 ++	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
352.22408 ++		goto out;
352.22409 ++
352.22410 ++	do {
352.22411 ++		id = blob.length;
352.22412 ++		tile = alloca(id + 1);
352.22413 ++		blob.data = (uintptr_t)tile;
352.22414 ++		VG(memset(tile, 0, id));
352.22415 ++		DBG(("%s: reading %d bytes for TILE blob\n", __FUNCTION__, id));
352.22416 ++		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
352.22417 ++			goto out;
352.22418 ++	} while (id != blob.length);
352.22419 ++
352.22420 ++	tile[blob.length] = '\0'; /* paranoia */
352.22421 ++	DBG(("%s: TILE='%s'\n", __FUNCTION__, tile));
352.22422 ++	if (xf86OutputParseKMSTile(tile, blob.length, &tile_info))
352.22423 ++		set = &tile_info;
352.22424 ++out:
352.22425 ++	xf86OutputSetTile(output, set);
352.22426 ++#endif
352.22427 ++}
352.22428 ++
352.22429 ++static bool duplicate_mode(DisplayModePtr modes, DisplayModePtr m)
352.22430 ++{
352.22431 ++	if (m == NULL)
352.22432 ++		return false;
352.22433 ++
352.22434 ++	while (modes) {
352.22435 ++		if (xf86ModesEqual(modes, m))
352.22436 ++			return true;
352.22437 ++
352.22438 ++		modes = modes->next;
352.22439 ++	}
352.22440 ++
352.22441 ++	return false;
352.22442 ++}
352.22443 ++
352.22444 ++static struct pixel_count {
352.22445 ++	int16_t width, height;
352.22446 ++} common_16_9[] = {
352.22447 ++	{ 640, 360 },
352.22448 ++	{ 720, 405 },
352.22449 ++	{ 864, 486 },
352.22450 ++	{ 960, 540 },
352.22451 ++	{ 1024, 576 },
352.22452 ++	{ 1280, 720 },
352.22453 ++	{ 1366, 768 },
352.22454 ++	{ 1600, 900 },
352.22455 ++	{ 1920, 1080 },
352.22456 ++	{ 2048, 1152 },
352.22457 ++	{ 2560, 1440 },
352.22458 ++	{ 2880, 1620 },
352.22459 ++	{ 3200, 1800 },
352.22460 ++	{ 3840, 2160 },
352.22461 ++	{ 4096, 2304 },
352.22462 ++	{ 5120, 2880 },
352.22463 ++	{ 7680, 4320 },
352.22464 ++	{ 15360, 8640 },
352.22465 ++}, common_16_10[] = {
352.22466 ++	{ 1280, 800 },
352.22467 ++	{ 1400, 900 },
352.22468 ++	{ 1680, 1050 },
352.22469 ++	{ 1920, 1200 },
352.22470 ++	{ 2560, 1600 },
352.22471 ++};
352.22472 ++
352.22473 ++static DisplayModePtr
352.22474 ++default_modes(DisplayModePtr preferred)
352.22475 ++{
352.22476 ++	DisplayModePtr modes;
352.22477 ++	int n;
352.22478 ++
352.22479 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0)
352.22480 ++	modes = xf86GetDefaultModes();
352.22481 ++#else
352.22482 ++	modes = xf86GetDefaultModes(0, 0);
352.22483 ++#endif
352.22484 ++
352.22485 ++	/* XXX O(n^2) mode list generation :( */
352.22486 ++
352.22487 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,901,0)
352.22488 ++	if (preferred) {
352.22489 ++		DisplayModePtr m;
352.22490 ++
352.22491 ++		/* Add a half-resolution mode useful for large panels */
352.22492 ++		m = xf86GTFMode(preferred->HDisplay/2,
352.22493 ++				preferred->VDisplay/2,
352.22494 ++				xf86ModeVRefresh(preferred),
352.22495 ++				FALSE, FALSE);
352.22496 ++		if (!duplicate_mode(modes, m))
352.22497 ++			modes = xf86ModesAdd(modes, m);
352.22498 ++		else
352.22499 ++			free(m);
352.22500 ++
352.22501 ++		if (preferred->VDisplay * 16 > preferred->HDisplay*9 - preferred->HDisplay/32 &&
352.22502 ++		    preferred->VDisplay * 16 < preferred->HDisplay*9 + preferred->HDisplay/32) {
352.22503 ++			DBG(("Adding 16:9 modes -- %d < %d > %d\n",
352.22504 ++			     preferred->HDisplay*9 - preferred->HDisplay/32,
352.22505 ++			     preferred->VDisplay * 16,
352.22506 ++			     preferred->HDisplay*9 + preferred->HDisplay/32));
352.22507 ++			for (n = 0; n < ARRAY_SIZE(common_16_9); n++) {
352.22508 ++				if (preferred->HDisplay <= common_16_9[n].width ||
352.22509 ++				    preferred->VDisplay <= common_16_9[n].height)
352.22510 ++					break;
352.22511 ++
352.22512 ++				m = xf86GTFMode(common_16_9[n].width,
352.22513 ++						common_16_9[n].height,
352.22514 ++						xf86ModeVRefresh(preferred),
352.22515 ++						FALSE, FALSE);
352.22516 ++				if (!duplicate_mode(modes, m))
352.22517 ++					modes = xf86ModesAdd(modes, m);
352.22518 ++				else
352.22519 ++					free(m);
352.22520 ++			}
352.22521 ++		}
352.22522 ++
352.22523 ++		if (preferred->VDisplay * 16 > preferred->HDisplay*10 - preferred->HDisplay/32 &&
352.22524 ++		    preferred->VDisplay * 16 < preferred->HDisplay*10 + preferred->HDisplay/32) {
352.22525 ++			DBG(("Adding 16:10 modes -- %d < %d > %d\n",
352.22526 ++			     preferred->HDisplay*10 - preferred->HDisplay/32,
352.22527 ++			     preferred->VDisplay * 16,
352.22528 ++			     preferred->HDisplay*10 + preferred->HDisplay/32));
352.22529 ++			for (n = 0; n < ARRAY_SIZE(common_16_10); n++) {
352.22530 ++				if (preferred->HDisplay <= common_16_10[n].width ||
352.22531 ++				    preferred->VDisplay <= common_16_10[n].height)
352.22532 ++					break;
352.22533 ++
352.22534 ++				m = xf86GTFMode(common_16_10[n].width,
352.22535 ++						common_16_10[n].height,
352.22536 ++						xf86ModeVRefresh(preferred),
352.22537 ++						FALSE, FALSE);
352.22538 ++				if (!duplicate_mode(modes, m))
352.22539 ++					modes = xf86ModesAdd(modes, m);
352.22540 ++				else
352.22541 ++					free(m);
352.22542 ++			}
352.22543 ++		}
352.22544 + 	}
352.22545 +-}
352.22546 +-
352.22547 +-static DisplayModePtr
352.22548 +-default_modes(void)
352.22549 +-{
352.22550 +-#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0)
352.22551 +-	return xf86GetDefaultModes();
352.22552 +-#else
352.22553 +-	return xf86GetDefaultModes(0, 0);
352.22554 + #endif
352.22555 ++
352.22556 ++	return modes;
352.22557 + }
352.22558 + 
352.22559 + static DisplayModePtr
352.22560 +-sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
352.22561 ++sna_output_add_default_modes(xf86OutputPtr output, DisplayModePtr modes)
352.22562 + {
352.22563 + 	xf86MonPtr mon = output->MonInfo;
352.22564 + 	DisplayModePtr i, m, preferred = NULL;
352.22565 +-	int max_x = 0, max_y = 0;
352.22566 ++	int max_x = 0, max_y = 0, max_clock = 0;
352.22567 + 	float max_vrefresh = 0.0;
352.22568 + 
352.22569 + 	if (mon && GTF_SUPPORTED(mon->features.msc))
352.22570 +@@ -3009,16 +4056,17 @@ sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
352.22571 + 			preferred = m;
352.22572 + 		max_x = max(max_x, m->HDisplay);
352.22573 + 		max_y = max(max_y, m->VDisplay);
352.22574 ++		max_clock = max(max_clock, m->Clock);
352.22575 + 		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
352.22576 + 	}
352.22577 +-
352.22578 +-	max_vrefresh = max(max_vrefresh, 60.0);
352.22579 + 	max_vrefresh *= (1 + SYNC_TOLERANCE);
352.22580 + 
352.22581 +-	m = default_modes();
352.22582 ++	m = default_modes(preferred);
352.22583 + 	xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
352.22584 + 
352.22585 + 	for (i = m; i; i = i->next) {
352.22586 ++		if (i->Clock > max_clock)
352.22587 ++			i->status = MODE_CLOCK_HIGH;
352.22588 + 		if (xf86ModeVRefresh(i) > max_vrefresh)
352.22589 + 			i->status = MODE_VSYNC;
352.22590 + 		if (preferred &&
352.22591 +@@ -3034,28 +4082,47 @@ sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
352.22592 + }
352.22593 + 
352.22594 + static DisplayModePtr
352.22595 ++sna_output_override_edid(xf86OutputPtr output)
352.22596 ++{
352.22597 ++	struct sna_output *sna_output = output->driver_private;
352.22598 ++
352.22599 ++	if (sna_output->fake_edid_mon == NULL)
352.22600 ++		return NULL;
352.22601 ++
352.22602 ++	xf86OutputSetEDID(output, sna_output->fake_edid_mon);
352.22603 ++	return xf86DDCGetModes(output->scrn->scrnIndex,
352.22604 ++			       sna_output->fake_edid_mon);
352.22605 ++}
352.22606 ++
352.22607 ++static DisplayModePtr
352.22608 + sna_output_get_modes(xf86OutputPtr output)
352.22609 + {
352.22610 + 	struct sna_output *sna_output = output->driver_private;
352.22611 +-	DisplayModePtr Modes = NULL, current = NULL;
352.22612 ++	DisplayModePtr Modes, current;
352.22613 + 	int i;
352.22614 + 
352.22615 + 	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
352.22616 + 	assert(sna_output->id);
352.22617 + 
352.22618 ++	Modes = sna_output_override_edid(output);
352.22619 ++	if (Modes)
352.22620 ++		return Modes;
352.22621 ++
352.22622 + 	sna_output_attach_edid(output);
352.22623 ++	sna_output_attach_tile(output);
352.22624 + 
352.22625 +-	if (output->crtc) {
352.22626 ++	current = NULL;
352.22627 ++	if (output->crtc && !sna_output->hotplug_count) {
352.22628 + 		struct drm_mode_crtc mode;
352.22629 + 
352.22630 + 		VG_CLEAR(mode);
352.22631 + 		assert(to_sna_crtc(output->crtc));
352.22632 +-		mode.crtc_id = to_sna_crtc(output->crtc)->id;
352.22633 ++		mode.crtc_id = sna_crtc_id(output->crtc);
352.22634 + 
352.22635 + 		if (drmIoctl(to_sna(output->scrn)->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode) == 0) {
352.22636 + 			DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
352.22637 +-			     to_sna_crtc(output->crtc)->id,
352.22638 +-			     to_sna_crtc(output->crtc)->pipe,
352.22639 ++			     sna_crtc_id(output->crtc),
352.22640 ++			     sna_crtc_pipe(output->crtc),
352.22641 + 			     mode.mode_valid && mode.mode.clock));
352.22642 + 
352.22643 + 			if (mode.mode_valid && mode.mode.clock) {
352.22644 +@@ -3117,7 +4184,7 @@ sna_output_get_modes(xf86OutputPtr output)
352.22645 + 	}
352.22646 + 
352.22647 + 	if (sna_output->add_default_modes)
352.22648 +-		Modes = sna_output_panel_edid(output, Modes);
352.22649 ++		Modes = sna_output_add_default_modes(output, Modes);
352.22650 + 
352.22651 + 	return Modes;
352.22652 + }
352.22653 +@@ -3132,6 +4199,8 @@ sna_output_destroy(xf86OutputPtr output)
352.22654 + 		return;
352.22655 + 
352.22656 + 	free(sna_output->edid_raw);
352.22657 ++	free(sna_output->fake_edid_raw);
352.22658 ++
352.22659 + 	for (i = 0; i < sna_output->num_props; i++) {
352.22660 + 		if (sna_output->props[i].kprop == NULL)
352.22661 + 			continue;
352.22662 +@@ -3155,7 +4224,7 @@ sna_output_destroy(xf86OutputPtr output)
352.22663 + }
352.22664 + 
352.22665 + static void
352.22666 +-sna_output_dpms(xf86OutputPtr output, int dpms)
352.22667 ++__sna_output_dpms(xf86OutputPtr output, int dpms, int fixup)
352.22668 + {
352.22669 + 	struct sna *sna = to_sna(output->scrn);
352.22670 + 	struct sna_output *sna_output = output->driver_private;
352.22671 +@@ -3182,8 +4251,9 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
352.22672 + 	if (sna_output->backlight.iface && dpms != DPMSModeOn) {
352.22673 + 		if (old_dpms == DPMSModeOn) {
352.22674 + 			sna_output->backlight_active_level = sna_output_backlight_get(output);
352.22675 +-			DBG(("%s: saving current backlight %d\n",
352.22676 +-			     __FUNCTION__, sna_output->backlight_active_level));
352.22677 ++			DBG(("%s(%s:%d): saving current backlight %d\n",
352.22678 ++			     __FUNCTION__, output->name, sna_output->id,
352.22679 ++			     sna_output->backlight_active_level));
352.22680 + 		}
352.22681 + 		sna_output->dpms_mode = dpms;
352.22682 + 		sna_output_backlight_off(sna_output);
352.22683 +@@ -3193,18 +4263,31 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
352.22684 + 	    drmModeConnectorSetProperty(sna->kgem.fd,
352.22685 + 					sna_output->id,
352.22686 + 					sna_output->dpms_id,
352.22687 +-					dpms))
352.22688 +-		dpms = old_dpms;
352.22689 ++					dpms)) {
352.22690 ++		DBG(("%s(%s:%d): failed to set DPMS to %d (fixup? %d)\n",
352.22691 ++		     __FUNCTION__, output->name, sna_output->id, dpms, fixup));
352.22692 ++		if (fixup && dpms != DPMSModeOn) {
352.22693 ++			sna_crtc_disable(output->crtc, false);
352.22694 ++			return;
352.22695 ++		}
352.22696 ++	}
352.22697 + 
352.22698 + 	if (sna_output->backlight.iface && dpms == DPMSModeOn) {
352.22699 +-		DBG(("%s: restoring previous backlight %d\n",
352.22700 +-		     __FUNCTION__, sna_output->backlight_active_level));
352.22701 ++		DBG(("%s(%d:%d: restoring previous backlight %d\n",
352.22702 ++		     __FUNCTION__, output->name, sna_output->id,
352.22703 ++		     sna_output->backlight_active_level));
352.22704 + 		sna_output_backlight_on(sna_output);
352.22705 + 	}
352.22706 + 
352.22707 + 	sna_output->dpms_mode = dpms;
352.22708 + }
352.22709 + 
352.22710 ++static void
352.22711 ++sna_output_dpms(xf86OutputPtr output, int dpms)
352.22712 ++{
352.22713 ++	__sna_output_dpms(output, dpms, true);
352.22714 ++}
352.22715 ++
352.22716 + static bool
352.22717 + sna_property_ignore(drmModePropertyPtr prop)
352.22718 + {
352.22719 +@@ -3239,14 +4322,14 @@ sna_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
352.22720 + 	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
352.22721 + 					TRUE, immutable, 2, atom_range);
352.22722 + 	if (err != 0)
352.22723 +-		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.22724 ++		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22725 + 			   "RRConfigureOutputProperty error, %d\n", err);
352.22726 + 
352.22727 + 	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
352.22728 + 				     32, PropModeReplace, 1, &value,
352.22729 + 				     FALSE, FALSE);
352.22730 + 	if (err != 0)
352.22731 +-		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.22732 ++		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22733 + 			   "RRChangeOutputProperty error, %d\n", err);
352.22734 + }
352.22735 + 
352.22736 +@@ -3303,7 +4386,7 @@ sna_output_create_resources(xf86OutputPtr output)
352.22737 + 							p->kprop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
352.22738 + 							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
352.22739 + 			if (err != 0) {
352.22740 +-				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.22741 ++				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22742 + 					   "RRConfigureOutputProperty error, %d\n", err);
352.22743 + 			}
352.22744 + 
352.22745 +@@ -3315,7 +4398,7 @@ sna_output_create_resources(xf86OutputPtr output)
352.22746 + 						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1],
352.22747 + 						     FALSE, FALSE);
352.22748 + 			if (err != 0) {
352.22749 +-				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.22750 ++				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22751 + 					   "RRChangeOutputProperty error, %d\n", err);
352.22752 + 			}
352.22753 + 		}
352.22754 +@@ -3385,18 +4468,19 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
352.22755 + 			if (value->type != XA_INTEGER || value->format != 32 ||
352.22756 + 			    value->size != 1)
352.22757 + 				return FALSE;
352.22758 +-			val = *(uint32_t *)value->data;
352.22759 + 
352.22760 ++			val = *(uint32_t *)value->data;
352.22761 + 			drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
352.22762 + 						    p->kprop->prop_id, (uint64_t)val);
352.22763 + 			return TRUE;
352.22764 + 		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
352.22765 +-			Atom	atom;
352.22766 +-			const char	*name;
352.22767 +-			int		j;
352.22768 ++			Atom atom;
352.22769 ++			const char *name;
352.22770 ++			int j;
352.22771 + 
352.22772 + 			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
352.22773 + 				return FALSE;
352.22774 ++
352.22775 + 			memcpy(&atom, value->data, 4);
352.22776 + 			name = NameForAtom(atom);
352.22777 + 			if (name == NULL)
352.22778 +@@ -3425,7 +4509,7 @@ static Bool
352.22779 + sna_output_get_property(xf86OutputPtr output, Atom property)
352.22780 + {
352.22781 + 	struct sna_output *sna_output = output->driver_private;
352.22782 +-	int err;
352.22783 ++	int err, i, j;
352.22784 + 
352.22785 + 	if (property == backlight_atom || property == backlight_deprecated_atom) {
352.22786 + 		INT32 val;
352.22787 +@@ -3449,7 +4533,7 @@ sna_output_get_property(xf86OutputPtr output, Atom property)
352.22788 + 					     XA_INTEGER, 32, PropModeReplace, 1, &val,
352.22789 + 					     FALSE, FALSE);
352.22790 + 		if (err != 0) {
352.22791 +-			xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.22792 ++			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22793 + 				   "RRChangeOutputProperty error, %d\n", err);
352.22794 + 			return FALSE;
352.22795 + 		}
352.22796 +@@ -3457,6 +4541,40 @@ sna_output_get_property(xf86OutputPtr output, Atom property)
352.22797 + 		return TRUE;
352.22798 + 	}
352.22799 + 
352.22800 ++	for (i = 0; i < sna_output->num_props; i++) {
352.22801 ++		struct sna_property *p = &sna_output->props[i];
352.22802 ++
352.22803 ++		if (p->atoms == NULL || p->atoms[0] != property)
352.22804 ++			continue;
352.22805 ++
352.22806 ++		if (sna_output->update_properties && output->scrn->vtSema)
352.22807 ++			update_properties(to_sna(output->scrn), sna_output);
352.22808 ++
352.22809 ++		err = 0;
352.22810 ++		if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
352.22811 ++			err = RRChangeOutputProperty(output->randr_output,
352.22812 ++						     property, XA_INTEGER, 32,
352.22813 ++						     PropModeReplace, 1,
352.22814 ++						     &sna_output->prop_values[i],
352.22815 ++						     FALSE, FALSE);
352.22816 ++		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
352.22817 ++			for (j = 0; j < p->kprop->count_enums; j++) {
352.22818 ++				if (p->kprop->enums[j].value == sna_output->prop_values[i])
352.22819 ++					break;
352.22820 ++			}
352.22821 ++			err = RRChangeOutputProperty(output->randr_output,
352.22822 ++						     property, XA_ATOM, 32,
352.22823 ++						     PropModeReplace, 1,
352.22824 ++						     &p->atoms[j+1],
352.22825 ++						     FALSE, FALSE);
352.22826 ++		}
352.22827 ++
352.22828 ++		if (err != 0)
352.22829 ++			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
352.22830 ++				   "RRChangeOutputProperty error, %d\n", err);
352.22831 ++		return TRUE;
352.22832 ++	}
352.22833 ++
352.22834 + 	return FALSE;
352.22835 + }
352.22836 + 
352.22837 +@@ -3500,47 +4618,11 @@ static const char * const output_names[] = {
352.22838 + 	/* DRM_MODE_CONNECTOR_TV */		"TV",
352.22839 + 	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
352.22840 + 	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
352.22841 +-	/* DRM_MODE_CONNECTOR_DSI */		"DSI"
352.22842 ++	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
352.22843 ++	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
352.22844 + };
352.22845 + 
352.22846 + static bool
352.22847 +-sna_zaphod_match(const char *s, const char *output)
352.22848 +-{
352.22849 +-	char t[20];
352.22850 +-	unsigned int i = 0;
352.22851 +-
352.22852 +-	do {
352.22853 +-		/* match any outputs in a comma list, stopping at whitespace */
352.22854 +-		switch (*s) {
352.22855 +-		case '\0':
352.22856 +-			t[i] = '\0';
352.22857 +-			return strcmp(t, output) == 0;
352.22858 +-
352.22859 +-		case ',':
352.22860 +-			t[i] ='\0';
352.22861 +-			if (strcmp(t, output) == 0)
352.22862 +-				return TRUE;
352.22863 +-			i = 0;
352.22864 +-			break;
352.22865 +-
352.22866 +-		case ' ':
352.22867 +-		case '\t':
352.22868 +-		case '\n':
352.22869 +-		case '\r':
352.22870 +-			break;
352.22871 +-
352.22872 +-		default:
352.22873 +-			t[i++] = *s;
352.22874 +-			break;
352.22875 +-		}
352.22876 +-
352.22877 +-		s++;
352.22878 +-	} while (i < sizeof(t));
352.22879 +-
352.22880 +-	return false;
352.22881 +-}
352.22882 +-
352.22883 +-static bool
352.22884 + output_ignored(ScrnInfoPtr scrn, const char *name)
352.22885 + {
352.22886 + 	char monitor_name[64];
352.22887 +@@ -3572,14 +4654,21 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
352.22888 + 	struct drm_mode_get_encoder enc;
352.22889 + 	uint32_t *ids = NULL;
352.22890 + 
352.22891 ++	DBG(("%s(%d): expected count=%d\n", __FUNCTION__, id, count));
352.22892 ++
352.22893 + 	VG_CLEAR(compat_conn);
352.22894 ++	VG_CLEAR(enc);
352.22895 + 	memset(out, 0, sizeof(*out));
352.22896 + 
352.22897 + 	do {
352.22898 +-		free(ids);
352.22899 +-		ids = malloc(sizeof(*ids) * count);
352.22900 +-		if (ids == 0)
352.22901 ++		uint32_t *nids;
352.22902 ++
352.22903 ++		nids = realloc(ids, sizeof(*ids) * count);
352.22904 ++		if (nids == NULL) {
352.22905 ++			free(ids);
352.22906 + 			return false;
352.22907 ++		}
352.22908 ++		ids = nids;
352.22909 + 
352.22910 + 		compat_conn.conn.connector_id = id;
352.22911 + 		compat_conn.conn.count_props = 0;
352.22912 +@@ -3593,12 +4682,14 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
352.22913 + 			compat_conn.conn.count_encoders = count = 0;
352.22914 + 		}
352.22915 + 
352.22916 ++		VG(VALGRIND_MAKE_MEM_DEFINED(ids, sizeof(uint32_t)*compat_conn.conn.count_encoders));
352.22917 + 		if (count == compat_conn.conn.count_encoders)
352.22918 + 			break;
352.22919 + 
352.22920 + 		count = compat_conn.conn.count_encoders;
352.22921 + 	} while (1);
352.22922 + 
352.22923 ++	DBG(("%s(%d): gathering %d encoders\n", __FUNCTION__, id, count));
352.22924 + 	for (count = 0; count < compat_conn.conn.count_encoders; count++) {
352.22925 + 		enc.encoder_id = ids[count];
352.22926 + 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
352.22927 +@@ -3606,6 +4697,8 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
352.22928 + 			count = 0;
352.22929 + 			break;
352.22930 + 		}
352.22931 ++		DBG(("%s(%d): encoder=%d, possible_crtcs=%x, possible_clones=%x\n",
352.22932 ++		     __FUNCTION__, id, enc.encoder_id, enc.possible_crtcs, enc.possible_clones));
352.22933 + 		out->possible_crtcs |= enc.possible_crtcs;
352.22934 + 		out->possible_clones |= enc.possible_clones;
352.22935 + 
352.22936 +@@ -3731,6 +4824,116 @@ static int name_from_path(struct sna *sna,
352.22937 + 	return 0;
352.22938 + }
352.22939 + 
352.22940 ++static char *fake_edid_name(xf86OutputPtr output)
352.22941 ++{
352.22942 ++	struct sna *sna = to_sna(output->scrn);
352.22943 ++	const char *str, *colon;
352.22944 ++
352.22945 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.22946 ++	str = xf86GetOptValString(sna->Options, OPTION_EDID);
352.22947 ++#else
352.22948 ++	str = NULL;
352.22949 ++#endif
352.22950 ++	if (str == NULL)
352.22951 ++		return NULL;
352.22952 ++
352.22953 ++	do {
352.22954 ++		colon = strchr(str, ':');
352.22955 ++		if (colon == NULL)
352.22956 ++			return NULL;
352.22957 ++
352.22958 ++		if (strncmp(str, output->name, colon-str) == 0 &&
352.22959 ++		    output->name[colon-str] == '\0') {
352.22960 ++			char *path;
352.22961 ++			int len;
352.22962 ++
352.22963 ++			str = colon + 1;
352.22964 ++			colon = strchr(str, ',');
352.22965 ++			if (colon)
352.22966 ++				len = colon - str;
352.22967 ++			else
352.22968 ++				len = strlen(str);
352.22969 ++
352.22970 ++			path = malloc(len + 1);
352.22971 ++			if (path == NULL)
352.22972 ++				return NULL;
352.22973 ++
352.22974 ++			memcpy(path, str, len);
352.22975 ++			path[len] = '\0';
352.22976 ++			return path;
352.22977 ++		}
352.22978 ++
352.22979 ++		str = strchr(colon + 1, ',');
352.22980 ++		if (str == NULL)
352.22981 ++			return NULL;
352.22982 ++
352.22983 ++		str++;
352.22984 ++	} while (1);
352.22985 ++}
352.22986 ++
352.22987 ++static void
352.22988 ++sna_output_load_fake_edid(xf86OutputPtr output)
352.22989 ++{
352.22990 ++	struct sna_output *sna_output = output->driver_private;
352.22991 ++	const char *filename;
352.22992 ++	FILE *file;
352.22993 ++	void *raw;
352.22994 ++	int size;
352.22995 ++	xf86MonPtr mon;
352.22996 ++
352.22997 ++	filename = fake_edid_name(output);
352.22998 ++	if (filename == NULL)
352.22999 ++		return;
352.23000 ++
352.23001 ++	file = fopen(filename, "rb");
352.23002 ++	if (file == NULL)
352.23003 ++		goto err;
352.23004 ++
352.23005 ++	fseek(file, 0, SEEK_END);
352.23006 ++	size = ftell(file);
352.23007 ++	if (size % 128) {
352.23008 ++		fclose(file);
352.23009 ++		goto err;
352.23010 ++	}
352.23011 ++
352.23012 ++	raw = malloc(size);
352.23013 ++	if (raw == NULL) {
352.23014 ++		fclose(file);
352.23015 ++		free(raw);
352.23016 ++		goto err;
352.23017 ++	}
352.23018 ++
352.23019 ++	fseek(file, 0, SEEK_SET);
352.23020 ++	if (fread(raw, size, 1, file) != 1) {
352.23021 ++		fclose(file);
352.23022 ++		free(raw);
352.23023 ++		goto err;
352.23024 ++	}
352.23025 ++	fclose(file);
352.23026 ++
352.23027 ++	mon = xf86InterpretEDID(output->scrn->scrnIndex, raw);
352.23028 ++	if (mon == NULL) {
352.23029 ++		free(raw);
352.23030 ++		goto err;
352.23031 ++	}
352.23032 ++
352.23033 ++	if (mon && size > 128)
352.23034 ++		mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
352.23035 ++
352.23036 ++	sna_output->fake_edid_mon = mon;
352.23037 ++	sna_output->fake_edid_raw = raw;
352.23038 ++
352.23039 ++	xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
352.23040 ++		   "Loading EDID from \"%s\" for output %s\n",
352.23041 ++		   filename, output->name);
352.23042 ++	return;
352.23043 ++
352.23044 ++err:
352.23045 ++	xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
352.23046 ++		   "Could not read EDID file \"%s\" for output %s\n",
352.23047 ++		   filename, output->name);
352.23048 ++}
352.23049 ++
352.23050 + static int
352.23051 + sna_output_add(struct sna *sna, unsigned id, unsigned serial)
352.23052 + {
352.23053 +@@ -3765,6 +4968,7 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
352.23054 + 		return -1;
352.23055 + 	}
352.23056 + 	assert(compat_conn.conn.connector_id == id);
352.23057 ++	DBG(("%s(%d): has %d associated encoders\n", __FUNCTION__, id, compat_conn.conn.count_encoders));
352.23058 + 
352.23059 + 	if (compat_conn.conn.connector_type < ARRAY_SIZE(output_names))
352.23060 + 		output_name = output_names[compat_conn.conn.connector_type];
352.23061 +@@ -3813,34 +5017,43 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
352.23062 + 	}
352.23063 + 
352.23064 + 	if (is_zaphod(scrn)) {
352.23065 +-		const char *str;
352.23066 ++		unsigned zaphod_crtcs;
352.23067 + 
352.23068 +-		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
352.23069 +-		if (str && !sna_zaphod_match(str, name)) {
352.23070 +-			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
352.23071 ++		if (!sna_zaphod_match(sna, name)) {
352.23072 ++			DBG(("%s: zaphod mismatch, want %s, have %s\n",
352.23073 ++			     __FUNCTION__,
352.23074 ++			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
352.23075 ++			     name));
352.23076 + 			return 0;
352.23077 + 		}
352.23078 + 
352.23079 +-		if ((possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
352.23080 +-			if (str) {
352.23081 +-				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352.23082 +-					   "%s is an invalid output for screen (pipe) %d\n",
352.23083 +-					   name, scrn->confScreen->device->screen);
352.23084 +-				return -1;
352.23085 +-			} else
352.23086 +-				return 0;
352.23087 ++		zaphod_crtcs = get_zaphod_crtcs(sna);
352.23088 ++		possible_crtcs &= zaphod_crtcs;
352.23089 ++		if (possible_crtcs == 0) {
352.23090 ++			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352.23091 ++				   "%s is an invalid output for screen %d\n",
352.23092 ++				   name, scrn->confScreen->device->screen);
352.23093 ++			return -1;
352.23094 + 		}
352.23095 + 
352.23096 +-		possible_crtcs = 1;
352.23097 ++		possible_crtcs >>= ffs(zaphod_crtcs) - 1;
352.23098 + 	}
352.23099 + 
352.23100 + 	sna_output = calloc(sizeof(struct sna_output), 1);
352.23101 + 	if (!sna_output)
352.23102 + 		return -1;
352.23103 + 
352.23104 ++	sna_output->connector_type = compat_conn.conn.connector_type;
352.23105 ++	sna_output->connector_type_id = compat_conn.conn.connector_type_id;
352.23106 + 	sna_output->num_props = compat_conn.conn.count_props;
352.23107 + 	sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props);
352.23108 + 	sna_output->prop_values = malloc(sizeof(uint64_t)*compat_conn.conn.count_props);
352.23109 ++	if (sna_output->prop_ids == NULL || sna_output->prop_values == NULL) {
352.23110 ++		free(sna_output->prop_ids);
352.23111 ++		free(sna_output->prop_values);
352.23112 ++		free(sna_output);
352.23113 ++		return -1;
352.23114 ++	}
352.23115 + 
352.23116 + 	compat_conn.conn.count_encoders = 0;
352.23117 + 
352.23118 +@@ -3865,16 +5078,16 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
352.23119 + 	/* Construct name from topology, and recheck if output is acceptable */
352.23120 + 	path = name_from_path(sna, sna_output, name);
352.23121 + 	if (path) {
352.23122 +-		const char *str;
352.23123 +-
352.23124 + 		if (output_ignored(scrn, name)) {
352.23125 + 			len = 0;
352.23126 + 			goto skip;
352.23127 + 		}
352.23128 + 
352.23129 +-		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
352.23130 +-		if (str && !sna_zaphod_match(str, name)) {
352.23131 +-			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
352.23132 ++		if (is_zaphod(scrn) && !sna_zaphod_match(sna, name)) {
352.23133 ++			DBG(("%s: zaphod mismatch, want %s, have %s\n",
352.23134 ++			     __FUNCTION__,
352.23135 ++			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
352.23136 ++			     name));
352.23137 + 			len = 0;
352.23138 + 			goto skip;
352.23139 + 		}
352.23140 +@@ -3889,7 +5102,6 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
352.23141 + 			if (strcmp(output->name, name) == 0) {
352.23142 + 				assert(output->scrn == scrn);
352.23143 + 				assert(output->funcs == &sna_output_funcs);
352.23144 +-				assert(to_sna_output(output)->id == 0);
352.23145 + 				sna_output_destroy(output);
352.23146 + 				goto reset;
352.23147 + 			}
352.23148 +@@ -3935,6 +5147,8 @@ reset:
352.23149 + 	sna_output->id = compat_conn.conn.connector_id;
352.23150 + 	sna_output->is_panel = is_panel(compat_conn.conn.connector_type);
352.23151 + 	sna_output->edid_idx = find_property(sna, sna_output, "EDID");
352.23152 ++	sna_output->link_status_idx =
352.23153 ++		find_property(sna, sna_output, "link-status");
352.23154 + 	if (find_property(sna, sna_output, "scaling mode") != -1)
352.23155 + 		sna_output->add_default_modes =
352.23156 + 			xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
352.23157 +@@ -3945,10 +5159,8 @@ reset:
352.23158 + 		sna_output->dpms_mode = sna_output->prop_values[i];
352.23159 + 		DBG(("%s: found 'DPMS' (idx=%d, id=%d), initial value=%d\n",
352.23160 + 		     __FUNCTION__, i, sna_output->dpms_id, sna_output->dpms_mode));
352.23161 +-	} else {
352.23162 +-		sna_output->dpms_id = -1;
352.23163 ++	} else
352.23164 + 		sna_output->dpms_mode = DPMSModeOff;
352.23165 +-	}
352.23166 + 
352.23167 + 	sna_output->possible_encoders = possible_encoders;
352.23168 + 	sna_output->attached_encoders = attached_encoders;
352.23169 +@@ -3963,12 +5175,13 @@ reset:
352.23170 + 	sna_output->base = output;
352.23171 + 
352.23172 + 	backlight_init(&sna_output->backlight);
352.23173 +-	if (sna_output->is_panel)
352.23174 +-		sna_output_backlight_init(output);
352.23175 ++	sna_output_backlight_init(output);
352.23176 + 
352.23177 + 	output->possible_crtcs = possible_crtcs & count_to_mask(sna->mode.num_real_crtc);
352.23178 + 	output->interlaceAllowed = TRUE;
352.23179 + 
352.23180 ++	sna_output_load_fake_edid(output);
352.23181 ++
352.23182 + 	if (serial) {
352.23183 + 		if (output->randr_output == NULL) {
352.23184 + 			output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), name, len, output);
352.23185 +@@ -3976,6 +5189,7 @@ reset:
352.23186 + 				goto cleanup;
352.23187 + 		}
352.23188 + 
352.23189 ++		RROutputChanged(output->randr_output, TRUE);
352.23190 + 		sna_output_create_resources(output);
352.23191 + 		RRPostPendingProperties(output->randr_output);
352.23192 + 
352.23193 +@@ -4009,38 +5223,6 @@ skip:
352.23194 + 	return len;
352.23195 + }
352.23196 + 
352.23197 +-static void sna_output_del(xf86OutputPtr output)
352.23198 +-{
352.23199 +-	ScrnInfoPtr scrn = output->scrn;
352.23200 +-	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
352.23201 +-	int i;
352.23202 +-
352.23203 +-	DBG(("%s(%s)\n", __FUNCTION__, output->name));
352.23204 +-	assert(to_sna_output(output));
352.23205 +-
352.23206 +-	RROutputDestroy(output->randr_output);
352.23207 +-	sna_output_destroy(output);
352.23208 +-
352.23209 +-	while (output->probed_modes)
352.23210 +-		xf86DeleteMode(&output->probed_modes, output->probed_modes);
352.23211 +-
352.23212 +-	free(output);
352.23213 +-
352.23214 +-	for (i = 0; i < config->num_output; i++)
352.23215 +-		if (config->output[i] == output)
352.23216 +-			break;
352.23217 +-	assert(i < to_sna(scrn)->mode.num_real_output);
352.23218 +-	DBG(("%s: removing output #%d of %d\n",
352.23219 +-	     __FUNCTION__, i, to_sna(scrn)->mode.num_real_output));
352.23220 +-
352.23221 +-	for (; i < config->num_output; i++) {
352.23222 +-		config->output[i] = config->output[i+1];
352.23223 +-		config->output[i]->possible_clones >>= 1;
352.23224 +-	}
352.23225 +-	config->num_output--;
352.23226 +-	to_sna(scrn)->mode.num_real_output--;
352.23227 +-}
352.23228 +-
352.23229 + static int output_rank(const void *A, const void *B)
352.23230 + {
352.23231 + 	const xf86OutputPtr *a = A;
352.23232 +@@ -4058,6 +5240,7 @@ static void sort_config_outputs(struct sna *sna)
352.23233 + {
352.23234 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.23235 + 	qsort(config->output, sna->mode.num_real_output, sizeof(*config->output), output_rank);
352.23236 ++	config->compat_output = 0; /* make sure it is a sane value */
352.23237 + 	sna_mode_compute_possible_outputs(sna);
352.23238 + }
352.23239 + 
352.23240 +@@ -4080,11 +5263,15 @@ static bool disable_unused_crtc(struct sna *sna)
352.23241 + 	bool update = false;
352.23242 + 	int o, c;
352.23243 + 
352.23244 ++	DBG(("%s\n", __FUNCTION__));
352.23245 ++
352.23246 + 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.23247 + 		xf86CrtcPtr crtc = config->crtc[c];
352.23248 + 
352.23249 +-		if (!crtc->enabled)
352.23250 ++		if (!crtc->enabled) {
352.23251 ++			sna_crtc_disable(crtc, false);
352.23252 + 			continue;
352.23253 ++		}
352.23254 + 
352.23255 + 		for (o = 0; o < sna->mode.num_real_output; o++) {
352.23256 + 			xf86OutputPtr output = config->output[o];
352.23257 +@@ -4094,7 +5281,7 @@ static bool disable_unused_crtc(struct sna *sna)
352.23258 + 
352.23259 + 		if (o == sna->mode.num_real_output) {
352.23260 + 			DBG(("%s: CRTC:%d was enabled with no outputs\n",
352.23261 +-			     __FUNCTION__, to_sna_crtc(crtc)->id));
352.23262 ++			     __FUNCTION__, sna_crtc_id(crtc)));
352.23263 + 			crtc->enabled = false;
352.23264 + 			update = true;
352.23265 + 		}
352.23266 +@@ -4108,17 +5295,145 @@ static bool disable_unused_crtc(struct sna *sna)
352.23267 + 	return update;
352.23268 + }
352.23269 + 
352.23270 +-void sna_mode_discover(struct sna *sna)
352.23271 ++bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id)
352.23272 ++{
352.23273 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.23274 ++	int i;
352.23275 ++
352.23276 ++	for (i = 0; i < sna->mode.num_real_output; i++) {
352.23277 ++		struct sna_output *output = to_sna_output(config->output[i]);
352.23278 ++		if (output->id == id) {
352.23279 ++			output->reprobe = true;
352.23280 ++			return true;
352.23281 ++		}
352.23282 ++	}
352.23283 ++
352.23284 ++	return false;
352.23285 ++}
352.23286 ++
352.23287 ++static bool
352.23288 ++output_retrain_link(struct sna *sna, struct sna_output *output)
352.23289 ++{
352.23290 ++	struct sna_crtc *crtc = to_sna_crtc(output->base->crtc);
352.23291 ++	int crtc_x = crtc->offset & 0xffff;
352.23292 ++	int crtc_y = crtc->offset >> 16;
352.23293 ++
352.23294 ++	return sna_crtc_flip(sna, crtc, crtc->bo, crtc_x, crtc_y);
352.23295 ++}
352.23296 ++
352.23297 ++static bool
352.23298 ++output_check_link(struct sna *sna, struct sna_output *output)
352.23299 ++{
352.23300 ++	uint64_t link_status;
352.23301 ++
352.23302 ++	if (!output->base->crtc)
352.23303 ++		return true;
352.23304 ++
352.23305 ++	if (output->link_status_idx == -1)
352.23306 ++		return true;
352.23307 ++
352.23308 ++#define LINK_STATUS_GOOD 0
352.23309 ++	link_status = output->prop_values[output->link_status_idx];
352.23310 ++	DBG(("%s: link_status=%d\n", __FUNCTION__, link_status));
352.23311 ++	if (link_status == LINK_STATUS_GOOD)
352.23312 ++		return true;
352.23313 ++
352.23314 ++	/* Perform a modeset as required for "link-status" = BAD */
352.23315 ++	if (!output_retrain_link(sna, output))
352.23316 ++		return false;
352.23317 ++
352.23318 ++	/* Query the "link-status" again to confirm the modeset */
352.23319 ++	update_properties(sna, output);
352.23320 ++
352.23321 ++	link_status = output->prop_values[output->link_status_idx];
352.23322 ++	DBG(("%s: link_status=%d after modeset\n", __FUNCTION__, link_status));
352.23323 ++	return link_status == LINK_STATUS_GOOD;
352.23324 ++}
352.23325 ++
352.23326 ++static bool
352.23327 ++output_check_status(struct sna *sna, struct sna_output *output)
352.23328 ++{
352.23329 ++	union compat_mode_get_connector compat_conn;
352.23330 ++	struct drm_mode_modeinfo dummy;
352.23331 ++	struct drm_mode_get_blob blob;
352.23332 ++	xf86OutputStatus status;
352.23333 ++	char *edid;
352.23334 ++
352.23335 ++	VG_CLEAR(compat_conn);
352.23336 ++
352.23337 ++	compat_conn.conn.connection = -1;
352.23338 ++	compat_conn.conn.connector_id = output->id;
352.23339 ++	compat_conn.conn.count_modes = 1; /* skip detect */
352.23340 ++	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
352.23341 ++	compat_conn.conn.count_encoders = 0;
352.23342 ++	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
352.23343 ++	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
352.23344 ++	compat_conn.conn.count_props = output->num_props;
352.23345 ++
352.23346 ++	if (drmIoctl(sna->kgem.fd,
352.23347 ++		     DRM_IOCTL_MODE_GETCONNECTOR,
352.23348 ++		     &compat_conn.conn) == 0)
352.23349 ++		output->update_properties = false;
352.23350 ++
352.23351 ++	if (!output_check_link(sna, output))
352.23352 ++		return false;
352.23353 ++
352.23354 ++	if (output->reprobe)
352.23355 ++		return false;
352.23356 ++
352.23357 ++	switch (compat_conn.conn.connection) {
352.23358 ++	case DRM_MODE_CONNECTED:
352.23359 ++		status = XF86OutputStatusConnected;
352.23360 ++		break;
352.23361 ++	case DRM_MODE_DISCONNECTED:
352.23362 ++		status = XF86OutputStatusDisconnected;
352.23363 ++		break;
352.23364 ++	default:
352.23365 ++	case DRM_MODE_UNKNOWNCONNECTION:
352.23366 ++		status = XF86OutputStatusUnknown;
352.23367 ++		break;
352.23368 ++	}
352.23369 ++	if (output->status != status)
352.23370 ++		return false;
352.23371 ++
352.23372 ++	if (status != XF86OutputStatusConnected)
352.23373 ++		return true;
352.23374 ++
352.23375 ++	if (output->num_modes != compat_conn.conn.count_modes)
352.23376 ++		return false;
352.23377 ++
352.23378 ++	if (output->edid_len == 0)
352.23379 ++		return false;
352.23380 ++
352.23381 ++	edid = alloca(output->edid_len);
352.23382 ++
352.23383 ++	VG_CLEAR(blob);
352.23384 ++	blob.blob_id = output->prop_values[output->edid_idx];
352.23385 ++	blob.length = output->edid_len;
352.23386 ++	blob.data = (uintptr_t)edid;
352.23387 ++	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
352.23388 ++		return false;
352.23389 ++
352.23390 ++	if (blob.length != output->edid_len)
352.23391 ++		return false;
352.23392 ++
352.23393 ++	return memcmp(edid, output->edid_raw, output->edid_len) == 0;
352.23394 ++}
352.23395 ++
352.23396 ++void sna_mode_discover(struct sna *sna, bool tell)
352.23397 + {
352.23398 + 	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
352.23399 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.23400 ++	bool force = sna->flags & SNA_REPROBE;
352.23401 + 	struct drm_mode_card_res res;
352.23402 +-	uint32_t connectors[32];
352.23403 ++	uint32_t connectors[32], now;
352.23404 + 	unsigned changed = 0;
352.23405 + 	unsigned serial;
352.23406 + 	int i, j;
352.23407 + 
352.23408 + 	DBG(("%s()\n", __FUNCTION__));
352.23409 ++	sna->flags &= ~SNA_REPROBE;
352.23410 ++
352.23411 + 	VG_CLEAR(connectors);
352.23412 + 
352.23413 + 	memset(&res, 0, sizeof(res));
352.23414 +@@ -4128,10 +5443,11 @@ void sna_mode_discover(struct sna *sna)
352.23415 + 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
352.23416 + 		return;
352.23417 + 
352.23418 +-	DBG(("%s: now %d (was %d) connectors\n", __FUNCTION__,
352.23419 +-	     res.count_connectors, sna->mode.num_real_output));
352.23420 ++	DBG(("%s: now %d (was %d) connectors, %d encoders, %d crtc\n", __FUNCTION__,
352.23421 ++	     res.count_connectors, sna->mode.num_real_output,
352.23422 ++	     res.count_encoders, res.count_crtcs));
352.23423 + 	if (res.count_connectors > 32)
352.23424 +-		return;
352.23425 ++		res.count_connectors = 32;
352.23426 + 
352.23427 + 	assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn));
352.23428 + 	assert(sna->mode.max_crtc_width  == res.max_width);
352.23429 +@@ -4142,6 +5458,11 @@ void sna_mode_discover(struct sna *sna)
352.23430 + 	if (serial == 0)
352.23431 + 		serial = ++sna->mode.serial;
352.23432 + 
352.23433 ++	if (force) {
352.23434 ++		changed = 4;
352.23435 ++		now = 0;
352.23436 ++	} else
352.23437 ++		now = GetTimeInMillis();
352.23438 + 	for (i = 0; i < res.count_connectors; i++) {
352.23439 + 		DBG(("%s: connector[%d] = %d\n", __FUNCTION__, i, connectors[i]));
352.23440 + 		for (j = 0; j < sna->mode.num_real_output; j++) {
352.23441 +@@ -4161,32 +5482,42 @@ void sna_mode_discover(struct sna *sna)
352.23442 + 
352.23443 + 	for (i = 0; i < sna->mode.num_real_output; i++) {
352.23444 + 		xf86OutputPtr output = config->output[i];
352.23445 ++		struct sna_output *sna_output = to_sna_output(output);
352.23446 + 
352.23447 +-		if (to_sna_output(output)->id == 0)
352.23448 ++		if (sna_output->id == 0)
352.23449 + 			continue;
352.23450 + 
352.23451 +-		if (to_sna_output(output)->serial == serial)
352.23452 ++		if (sna_output->serial == serial) {
352.23453 ++			if (output_check_status(sna, sna_output)) {
352.23454 ++				DBG(("%s: output %s (id=%d), retained state\n",
352.23455 ++				     __FUNCTION__, output->name, sna_output->id));
352.23456 ++				sna_output->last_detect = now;
352.23457 ++			} else {
352.23458 ++				DBG(("%s: output %s (id=%d), changed state, reprobing\n",
352.23459 ++				     __FUNCTION__, output->name, sna_output->id));
352.23460 ++				sna_output->hotplug_count++;
352.23461 ++				sna_output->last_detect = 0;
352.23462 ++				changed |= 4;
352.23463 ++			}
352.23464 + 			continue;
352.23465 ++		}
352.23466 + 
352.23467 + 		DBG(("%s: removing output %s (id=%d), serial=%u [now %u]\n",
352.23468 +-		     __FUNCTION__, output->name, to_sna_output(output)->id,
352.23469 +-		    to_sna_output(output)->serial, serial));
352.23470 ++		     __FUNCTION__, output->name, sna_output->id,
352.23471 ++		    sna_output->serial, serial));
352.23472 + 
352.23473 + 		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
352.23474 +-			   "%s output %s\n",
352.23475 +-			   sna->flags & SNA_REMOVE_OUTPUTS ? "Removed" : "Disabled",
352.23476 ++			   "Disabled output %s\n",
352.23477 + 			   output->name);
352.23478 +-		if (sna->flags & SNA_REMOVE_OUTPUTS) {
352.23479 +-			sna_output_del(output);
352.23480 +-			i--;
352.23481 +-		} else {
352.23482 +-			to_sna_output(output)->id = 0;
352.23483 +-			output->crtc = NULL;
352.23484 +-		}
352.23485 ++		sna_output->id = 0;
352.23486 ++		sna_output->last_detect = 0;
352.23487 ++		output->crtc = NULL;
352.23488 ++		RROutputChanged(output->randr_output, TRUE);
352.23489 + 		changed |= 2;
352.23490 + 	}
352.23491 + 
352.23492 +-	if (changed) {
352.23493 ++	/* Have the list of available outputs been updated? */
352.23494 ++	if (changed & 3) {
352.23495 + 		DBG(("%s: outputs changed, broadcasting\n", __FUNCTION__));
352.23496 + 
352.23497 + 		sna_mode_set_primary(sna);
352.23498 +@@ -4200,6 +5531,51 @@ void sna_mode_discover(struct sna *sna)
352.23499 + 
352.23500 + 		xf86RandR12TellChanged(screen);
352.23501 + 	}
352.23502 ++
352.23503 ++	/* If anything has changed, refresh the RandR information.
352.23504 ++	 * Note this could recurse once from udevless RRGetInfo() probes,
352.23505 ++	 * but only once.
352.23506 ++	 */
352.23507 ++	if (changed && tell)
352.23508 ++		RRGetInfo(screen, TRUE);
352.23509 ++}
352.23510 ++
352.23511 ++/* Since we only probe the current mode on startup, we may not have the full
352.23512 ++ * list of modes available until the user explicitly requests them. Fake a
352.23513 ++ * hotplug event after a second after starting to fill in any missing modes.
352.23514 ++ */
352.23515 ++static CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data)
352.23516 ++{
352.23517 ++	struct sna *sna = data;
352.23518 ++	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
352.23519 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.23520 ++	bool reprobe = false;
352.23521 ++	int i;
352.23522 ++
352.23523 ++	DBG(("%s()\n", __FUNCTION__));
352.23524 ++
352.23525 ++	for (i = 0; i < sna->mode.num_real_output; i++) {
352.23526 ++		xf86OutputPtr output = config->output[i];
352.23527 ++		struct sna_output *sna_output = to_sna_output(output);
352.23528 ++
352.23529 ++		if (sna_output->id == 0)
352.23530 ++			continue;
352.23531 ++		if (sna_output->last_detect)
352.23532 ++			continue;
352.23533 ++		if (output->status == XF86OutputStatusDisconnected)
352.23534 ++			continue;
352.23535 ++
352.23536 ++		DBG(("%s: output %s connected, needs reprobe\n",
352.23537 ++		     __FUNCTION__, output->name));
352.23538 ++		reprobe = true;
352.23539 ++	}
352.23540 ++
352.23541 ++	if (reprobe) {
352.23542 ++		RRGetInfo(screen, TRUE);
352.23543 ++		RRTellChanged(screen);
352.23544 ++	}
352.23545 ++	free(timer);
352.23546 ++	return 0;
352.23547 + }
352.23548 + 
352.23549 + static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
352.23550 +@@ -4208,7 +5584,7 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
352.23551 + 
352.23552 + 	DBG(("%s\n", __FUNCTION__));
352.23553 + 
352.23554 +-	if (wedged(sna))
352.23555 ++	if (wedged(sna) || isGPU(sna->scrn))
352.23556 + 		return;
352.23557 + 
352.23558 + 	old_priv = sna_pixmap_force_to_gpu(old, MOVE_READ);
352.23559 +@@ -4220,12 +5596,19 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
352.23560 + 		return;
352.23561 + 
352.23562 + 	if (old_priv->clear) {
352.23563 +-		(void)sna->render.fill_one(sna, new, new_priv->gpu_bo,
352.23564 +-					   old_priv->clear_color,
352.23565 +-					   0, 0,
352.23566 +-					   new->drawable.width,
352.23567 +-					   new->drawable.height,
352.23568 +-					   GXcopy);
352.23569 ++		bool ok = false;
352.23570 ++		if (!wedged(sna))
352.23571 ++			ok = sna->render.fill_one(sna, new, new_priv->gpu_bo,
352.23572 ++						  old_priv->clear_color,
352.23573 ++						  0, 0,
352.23574 ++						  new->drawable.width,
352.23575 ++						  new->drawable.height,
352.23576 ++						  GXcopy);
352.23577 ++		if (!ok) {
352.23578 ++			void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
352.23579 ++			if (ptr)
352.23580 ++				memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
352.23581 ++		}
352.23582 + 		new_priv->clear = true;
352.23583 + 		new_priv->clear_color = old_priv->clear_color;
352.23584 + 	} else {
352.23585 +@@ -4281,11 +5664,18 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
352.23586 + 			     __FUNCTION__, box.x2, box.y2, sx, sy, dx, dy));
352.23587 + 
352.23588 + 			if (box.x2 != new->drawable.width || box.y2 != new->drawable.height) {
352.23589 +-				(void)sna->render.fill_one(sna, new, new_priv->gpu_bo, 0,
352.23590 +-							   0, 0,
352.23591 +-							   new->drawable.width,
352.23592 +-							   new->drawable.height,
352.23593 +-							   GXclear);
352.23594 ++				bool ok = false;
352.23595 ++				if (!wedged(sna))
352.23596 ++					ok = sna->render.fill_one(sna, new, new_priv->gpu_bo, 0,
352.23597 ++								  0, 0,
352.23598 ++								  new->drawable.width,
352.23599 ++								  new->drawable.height,
352.23600 ++								  GXclear);
352.23601 ++				if (!ok) {
352.23602 ++					void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
352.23603 ++					if (ptr)
352.23604 ++						memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
352.23605 ++				}
352.23606 + 			}
352.23607 + 			(void)sna->render.copy_boxes(sna, GXcopy,
352.23608 + 						     &old->drawable, old_priv->gpu_bo, sx, sy,
352.23609 +@@ -4302,7 +5692,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.23610 + {
352.23611 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
352.23612 + 	struct sna *sna = to_sna(scrn);
352.23613 +-	ScreenPtr screen = scrn->pScreen;
352.23614 ++	ScreenPtr screen = xf86ScrnToScreen(scrn);
352.23615 + 	PixmapPtr new_front;
352.23616 + 	int i;
352.23617 + 
352.23618 +@@ -4337,9 +5727,20 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.23619 + 	for (i = 0; i < sna->mode.num_real_crtc; i++)
352.23620 + 		sna_crtc_disable_shadow(sna, to_sna_crtc(config->crtc[i]));
352.23621 + 	assert(sna->mode.shadow_active == 0);
352.23622 ++	assert(!sna->mode.shadow_enabled);
352.23623 + 	assert(sna->mode.shadow_damage == NULL);
352.23624 + 	assert(sna->mode.shadow == NULL);
352.23625 + 
352.23626 ++	/* Flush pending shadow updates */
352.23627 ++	if (sna->mode.flip_active) {
352.23628 ++		DBG(("%s: waiting for %d outstanding TearFree flips\n",
352.23629 ++		     __FUNCTION__, sna->mode.flip_active));
352.23630 ++		while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
352.23631 ++			sna_mode_wakeup(sna);
352.23632 ++	}
352.23633 ++
352.23634 ++	/* Cancel a pending [un]flip (as the pixmaps no longer match) */
352.23635 ++	sna_present_cancel_flip(sna);
352.23636 + 	copy_front(sna, sna->front, new_front);
352.23637 + 
352.23638 + 	screen->SetScreenPixmap(new_front);
352.23639 +@@ -4351,14 +5752,6 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.23640 + 	scrn->virtualY = height;
352.23641 + 	scrn->displayWidth = width;
352.23642 + 
352.23643 +-	/* Flush pending shadow updates */
352.23644 +-	if (sna->mode.flip_active) {
352.23645 +-		DBG(("%s: waiting for %d outstanding TearFree flips\n",
352.23646 +-		     __FUNCTION__, sna->mode.flip_active));
352.23647 +-		while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
352.23648 +-			sna_mode_wakeup(sna);
352.23649 +-	}
352.23650 +-
352.23651 + 	/* Only update the CRTCs if we are in control */
352.23652 + 	if (!scrn->vtSema)
352.23653 + 		return TRUE;
352.23654 +@@ -4371,7 +5764,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.23655 + 			continue;
352.23656 + 
352.23657 + 		if (!__sna_crtc_set_mode(crtc))
352.23658 +-			sna_crtc_disable(crtc);
352.23659 ++			sna_crtc_disable(crtc, false);
352.23660 + 	}
352.23661 + 
352.23662 + 	sna_mode_wakeup(sna);
352.23663 +@@ -4381,19 +5774,6 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.23664 + }
352.23665 + 
352.23666 + /* cursor handling */
352.23667 +-struct sna_cursor {
352.23668 +-	struct sna_cursor *next;
352.23669 +-	uint32_t *image;
352.23670 +-	Rotation rotation;
352.23671 +-	int ref;
352.23672 +-	int size;
352.23673 +-	int last_width;
352.23674 +-	int last_height;
352.23675 +-	unsigned handle;
352.23676 +-	unsigned serial;
352.23677 +-	unsigned alloc;
352.23678 +-};
352.23679 +-
352.23680 + static void
352.23681 + rotate_coord(Rotation rotation, int size,
352.23682 + 	     int x_dst, int y_dst,
352.23683 +@@ -4429,36 +5809,6 @@ rotate_coord(Rotation rotation, int size,
352.23684 + 	*y_src = y_dst;
352.23685 + }
352.23686 + 
352.23687 +-static void
352.23688 +-rotate_coord_back(Rotation rotation, int size, int *x, int *y)
352.23689 +-{
352.23690 +-	int t;
352.23691 +-
352.23692 +-	if (rotation & RR_Reflect_X)
352.23693 +-		*x = size - *x - 1;
352.23694 +-	if (rotation & RR_Reflect_Y)
352.23695 +-		*y = size - *y - 1;
352.23696 +-
352.23697 +-	switch (rotation & 0xf) {
352.23698 +-	case RR_Rotate_0:
352.23699 +-		break;
352.23700 +-	case RR_Rotate_90:
352.23701 +-		t = *x;
352.23702 +-		*x = *y;
352.23703 +-		*y = size - t - 1;
352.23704 +-		break;
352.23705 +-	case RR_Rotate_180:
352.23706 +-		*x = size - *x - 1;
352.23707 +-		*y = size - *y - 1;
352.23708 +-		break;
352.23709 +-	case RR_Rotate_270:
352.23710 +-		t = *x;
352.23711 +-		*x = size - *y - 1;
352.23712 +-		*y = t;
352.23713 +-		break;
352.23714 +-	}
352.23715 +-}
352.23716 +-
352.23717 + static struct sna_cursor *__sna_create_cursor(struct sna *sna, int size)
352.23718 + {
352.23719 + 	struct sna_cursor *c;
352.23720 +@@ -4519,6 +5869,17 @@ static uint32_t *get_cursor_argb(CursorPtr c)
352.23721 + #endif
352.23722 + }
352.23723 + 
352.23724 ++static int __cursor_size(int width, int height)
352.23725 ++{
352.23726 ++	int i, size;
352.23727 ++
352.23728 ++	i = MAX(width, height);
352.23729 ++	for (size = 64; size < i; size <<= 1)
352.23730 ++		;
352.23731 ++
352.23732 ++	return size;
352.23733 ++}
352.23734 ++
352.23735 + static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23736 + {
352.23737 + 	struct sna_cursor *cursor;
352.23738 +@@ -4526,6 +5887,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23739 + 	const uint32_t *argb;
352.23740 + 	uint32_t *image;
352.23741 + 	int width, height, pitch, size, x, y;
352.23742 ++	bool transformed;
352.23743 + 	Rotation rotation;
352.23744 + 
352.23745 + 	assert(sna->cursor.ref);
352.23746 +@@ -4537,8 +5899,8 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23747 + 	       cursor ? cursor->serial : 0,
352.23748 + 	       sna->cursor.serial));
352.23749 + 	if (cursor && cursor->serial == sna->cursor.serial) {
352.23750 +-		assert(cursor->size == sna->cursor.size);
352.23751 +-		assert(cursor->rotation == crtc->transform_in_use ? crtc->rotation : RR_Rotate_0);
352.23752 ++		assert(cursor->size == sna->cursor.size || cursor->transformed);
352.23753 ++		assert(cursor->rotation == (!to_sna_crtc(crtc)->cursor_transform && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0);
352.23754 + 		assert(cursor->ref);
352.23755 + 		return cursor;
352.23756 + 	}
352.23757 +@@ -4550,22 +5912,81 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23758 + 	       sna->cursor.serial,
352.23759 + 	       get_cursor_argb(sna->cursor.ref) != NULL));
352.23760 + 
352.23761 +-	rotation = crtc->transform_in_use ? crtc->rotation : RR_Rotate_0;
352.23762 ++	transformed = to_sna_crtc(crtc)->cursor_transform;
352.23763 ++	rotation = (!transformed && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0;
352.23764 ++
352.23765 ++	if (transformed) {
352.23766 ++		struct pixman_box16 box;
352.23767 ++
352.23768 ++		box.x1 = box.y1 = 0;
352.23769 ++		box.x2 = sna->cursor.ref->bits->width;
352.23770 ++		box.y2 = sna->cursor.ref->bits->height;
352.23771 + 
352.23772 +-	if (sna->cursor.use_gtt) { /* Don't allow phys cursor sharing */
352.23773 ++		pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer, &box);
352.23774 ++		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
352.23775 ++		__DBG(("%s: transformed cursor %dx%d -> %dx%d\n",
352.23776 ++		       __FUNCTION__ ,
352.23777 ++		       sna->cursor.ref->bits->width,
352.23778 ++		       sna->cursor.ref->bits->height,
352.23779 ++		       box.x2 - box.x1, box.y2 - box.y1));
352.23780 ++	} else
352.23781 ++		size = sna->cursor.size;
352.23782 ++
352.23783 ++	if (crtc->transform_in_use) {
352.23784 ++		RRTransformPtr T = NULL;
352.23785 ++		struct pixman_vector v;
352.23786 ++
352.23787 ++		if (crtc->transformPresent) {
352.23788 ++			T = &crtc->transform;
352.23789 ++
352.23790 ++			/* Cancel any translation from this affine
352.23791 ++			 * transformation. We just want to rotate and scale
352.23792 ++			 * the cursor image.
352.23793 ++			 */
352.23794 ++			v.vector[0] = 0;
352.23795 ++			v.vector[1] = 0;
352.23796 ++			v.vector[2] = pixman_fixed_1;
352.23797 ++			pixman_transform_point(&crtc->transform.transform, &v);
352.23798 ++		}
352.23799 ++
352.23800 ++		RRTransformCompute(0, 0, size, size, crtc->rotation, T, NULL,
352.23801 ++				   &to_sna_crtc(crtc)->cursor_to_fb,
352.23802 ++				   &to_sna_crtc(crtc)->fb_to_cursor);
352.23803 ++		if (T)
352.23804 ++			pixman_f_transform_translate(
352.23805 ++					&to_sna_crtc(crtc)->cursor_to_fb,
352.23806 ++					&to_sna_crtc(crtc)->fb_to_cursor,
352.23807 ++					-pixman_fixed_to_double(v.vector[0]),
352.23808 ++					-pixman_fixed_to_double(v.vector[1]));
352.23809 ++
352.23810 ++		__DBG(("%s: cursor_to_fb [%f %f %f, %f %f %f, %f %f %f]\n",
352.23811 ++		       __FUNCTION__,
352.23812 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[0][0],
352.23813 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[0][1],
352.23814 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[0][2],
352.23815 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[1][0],
352.23816 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[1][1],
352.23817 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[1][2],
352.23818 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[2][0],
352.23819 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[2][1],
352.23820 ++		       to_sna_crtc(crtc)->cursor_to_fb.m[2][2]));
352.23821 ++	}
352.23822 ++
352.23823 ++	/* Don't allow phys cursor sharing */
352.23824 ++	if (sna->cursor.use_gtt && !transformed) {
352.23825 + 		for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) {
352.23826 +-			if (cursor->serial == sna->cursor.serial && cursor->rotation == rotation) {
352.23827 ++			if (cursor->serial == sna->cursor.serial &&
352.23828 ++			    cursor->rotation == rotation &&
352.23829 ++			    !cursor->transformed) {
352.23830 + 				__DBG(("%s: reusing handle=%d, serial=%d, rotation=%d, size=%d\n",
352.23831 + 				       __FUNCTION__, cursor->handle, cursor->serial, cursor->rotation, cursor->size));
352.23832 + 				assert(cursor->size == sna->cursor.size);
352.23833 + 				return cursor;
352.23834 + 			}
352.23835 + 		}
352.23836 +-
352.23837 +-		cursor = to_sna_crtc(crtc)->cursor;
352.23838 + 	}
352.23839 + 
352.23840 +-	size = sna->cursor.size;
352.23841 ++	cursor = to_sna_crtc(crtc)->cursor;
352.23842 + 	if (cursor && cursor->alloc < 4*size*size)
352.23843 + 		cursor = NULL;
352.23844 + 
352.23845 +@@ -4577,7 +5998,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23846 + 		}
352.23847 + 	}
352.23848 + 
352.23849 +-	width = sna->cursor.ref->bits->width;
352.23850 ++	width  = sna->cursor.ref->bits->width;
352.23851 + 	height = sna->cursor.ref->bits->height;
352.23852 + 	source = sna->cursor.ref->bits->source;
352.23853 + 	mask = sna->cursor.ref->bits->mask;
352.23854 +@@ -4585,7 +6006,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23855 + 	pitch = BitmapBytePad(width);
352.23856 + 
352.23857 + 	image = cursor->image;
352.23858 +-	if (image == NULL) {
352.23859 ++	if (image == NULL || transformed) {
352.23860 + 		image = sna->cursor.scratch;
352.23861 + 		cursor->last_width = cursor->last_height = size;
352.23862 + 	}
352.23863 +@@ -4616,6 +6037,21 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23864 + 				mask += pitch;
352.23865 + 				source += pitch;
352.23866 + 			}
352.23867 ++			if (transformed) {
352.23868 ++				__DBG(("%s: Applying affine BLT to bitmap\n", __FUNCTION__));
352.23869 ++				affine_blt(image, cursor->image, 32,
352.23870 ++					   0, 0, width, height, size * 4,
352.23871 ++					   0, 0, size, size, size * 4,
352.23872 ++					   &to_sna_crtc(crtc)->cursor_to_fb);
352.23873 ++				image = cursor->image;
352.23874 ++			}
352.23875 ++		} else if (transformed) {
352.23876 ++			__DBG(("%s: Applying affine BLT to ARGB\n", __FUNCTION__));
352.23877 ++			affine_blt(argb, cursor->image, 32,
352.23878 ++				   0, 0, width, height, width * 4,
352.23879 ++				   0, 0, size, size, size * 4,
352.23880 ++				   &to_sna_crtc(crtc)->cursor_to_fb);
352.23881 ++			image = cursor->image;
352.23882 + 		} else
352.23883 + 			memcpy_blt(argb, image, 32,
352.23884 + 				   width * 4, size * 4,
352.23885 +@@ -4662,9 +6098,16 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
352.23886 + 
352.23887 + 	cursor->size = size;
352.23888 + 	cursor->rotation = rotation;
352.23889 ++	cursor->transformed = transformed;
352.23890 + 	cursor->serial = sna->cursor.serial;
352.23891 +-	cursor->last_width = width;
352.23892 +-	cursor->last_height = height;
352.23893 ++	if (transformed) {
352.23894 ++		/* mark the transformed rectangle as dirty, not input */
352.23895 ++		cursor->last_width = size;
352.23896 ++		cursor->last_height = size;
352.23897 ++	} else {
352.23898 ++		cursor->last_width = width;
352.23899 ++		cursor->last_height = height;
352.23900 ++	}
352.23901 + 	return cursor;
352.23902 + }
352.23903 + 
352.23904 +@@ -4674,40 +6117,55 @@ sna_realize_cursor(xf86CursorInfoPtr info, CursorPtr cursor)
352.23905 + 	return NULL;
352.23906 + }
352.23907 + 
352.23908 +-#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
352.23909 +-static inline int sigio_block(void)
352.23910 +-{
352.23911 +-	OsBlockSIGIO();
352.23912 +-	return 0;
352.23913 +-}
352.23914 +-static inline void sigio_unblock(int was_blocked)
352.23915 ++static void enable_fb_access(ScrnInfoPtr scrn, int state)
352.23916 + {
352.23917 +-	OsReleaseSIGIO();
352.23918 +-	(void)was_blocked;
352.23919 +-}
352.23920 ++	scrn->EnableDisableFBAccess(
352.23921 ++#ifdef XF86_HAS_SCRN_CONV
352.23922 ++				    scrn,
352.23923 + #else
352.23924 +-#include <xf86_OSproc.h>
352.23925 +-static inline int sigio_block(void)
352.23926 ++				    scrn->scrnIndex,
352.23927 ++#endif
352.23928 ++				    state);
352.23929 ++}
352.23930 ++
352.23931 ++
352.23932 ++static void __restore_swcursor(ScrnInfoPtr scrn)
352.23933 + {
352.23934 +-	return xf86BlockSIGIO();
352.23935 ++	DBG(("%s: attempting to restore SW cursor\n", __FUNCTION__));
352.23936 ++	enable_fb_access(scrn, FALSE);
352.23937 ++	enable_fb_access(scrn, TRUE);
352.23938 ++
352.23939 ++	RemoveBlockAndWakeupHandlers((void *)__restore_swcursor,
352.23940 ++				     (void *)NoopDDA,
352.23941 ++				     scrn);
352.23942 + }
352.23943 +-static inline void sigio_unblock(int was_blocked)
352.23944 ++
352.23945 ++static void restore_swcursor(struct sna *sna)
352.23946 + {
352.23947 +-	xf86UnblockSIGIO(was_blocked);
352.23948 ++	sna->cursor.info->HideCursor(sna->scrn);
352.23949 ++
352.23950 ++	/* XXX Force the cursor to be restored (avoiding recursion) */
352.23951 ++	FreeCursor(sna->cursor.ref, None);
352.23952 ++	sna->cursor.ref = NULL;
352.23953 ++
352.23954 ++	RegisterBlockAndWakeupHandlers((void *)__restore_swcursor,
352.23955 ++				       (void *)NoopDDA,
352.23956 ++				       sna->scrn);
352.23957 + }
352.23958 +-#endif
352.23959 + 
352.23960 + static void
352.23961 + sna_show_cursors(ScrnInfoPtr scrn)
352.23962 + {
352.23963 + 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
352.23964 + 	struct sna *sna = to_sna(scrn);
352.23965 ++	struct kmsg kmsg;
352.23966 + 	int sigio, c;
352.23967 + 
352.23968 + 	DBG(("%s: cursor?=%d\n", __FUNCTION__, sna->cursor.ref != NULL));
352.23969 + 	if (sna->cursor.ref == NULL)
352.23970 + 		return;
352.23971 + 
352.23972 ++	kmsg_open(&kmsg);
352.23973 + 	sigio = sigio_block();
352.23974 + 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.23975 + 		xf86CrtcPtr crtc = xf86_config->crtc[c];
352.23976 +@@ -4721,7 +6179,7 @@ sna_show_cursors(ScrnInfoPtr scrn)
352.23977 + 
352.23978 + 		if (!crtc->cursor_in_range) {
352.23979 + 			DBG(("%s: skipping cursor outside CRTC (pipe=%d)\n",
352.23980 +-			     __FUNCTION__, sna_crtc->pipe));
352.23981 ++			     __FUNCTION__, sna_crtc_pipe(crtc)));
352.23982 + 			continue;
352.23983 + 		}
352.23984 + 
352.23985 +@@ -4729,20 +6187,21 @@ sna_show_cursors(ScrnInfoPtr scrn)
352.23986 + 		if (cursor == NULL ||
352.23987 + 		    (sna_crtc->cursor == cursor && sna_crtc->last_cursor_size == cursor->size)) {
352.23988 + 			DBG(("%s: skipping cursor already show on CRTC (pipe=%d)\n",
352.23989 +-			     __FUNCTION__, sna_crtc->pipe));
352.23990 ++			     __FUNCTION__, sna_crtc_pipe(crtc)));
352.23991 + 			continue;
352.23992 + 		}
352.23993 + 
352.23994 + 		DBG(("%s: CRTC pipe=%d, handle->%d\n", __FUNCTION__,
352.23995 +-		     sna_crtc->pipe, cursor->handle));
352.23996 ++		     sna_crtc_pipe(crtc), cursor->handle));
352.23997 + 
352.23998 + 		VG_CLEAR(arg);
352.23999 + 		arg.flags = DRM_MODE_CURSOR_BO;
352.24000 +-		arg.crtc_id = sna_crtc->id;
352.24001 ++		arg.crtc_id = __sna_crtc_id(sna_crtc);
352.24002 + 		arg.width = arg.height = cursor->size;
352.24003 + 		arg.handle = cursor->handle;
352.24004 + 
352.24005 +-		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
352.24006 ++		if (!FAIL_CURSOR_IOCTL &&
352.24007 ++		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
352.24008 + 			if (sna_crtc->cursor) {
352.24009 + 				assert(sna_crtc->cursor->ref > 0);
352.24010 + 				sna_crtc->cursor->ref--;
352.24011 +@@ -4750,10 +6209,18 @@ sna_show_cursors(ScrnInfoPtr scrn)
352.24012 + 			cursor->ref++;
352.24013 + 			sna_crtc->cursor = cursor;
352.24014 + 			sna_crtc->last_cursor_size = cursor->size;
352.24015 ++		} else {
352.24016 ++			ERR(("%s: failed to show cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
352.24017 ++			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
352.24018 ++			sna->cursor.disable = true;
352.24019 + 		}
352.24020 + 	}
352.24021 + 	sigio_unblock(sigio);
352.24022 + 	sna->cursor.active = true;
352.24023 ++	kmsg_close(&kmsg, sna->cursor.disable);
352.24024 ++
352.24025 ++	if (unlikely(sna->cursor.disable))
352.24026 ++		restore_swcursor(sna);
352.24027 + }
352.24028 + 
352.24029 + static void
352.24030 +@@ -4789,24 +6256,45 @@ static void
352.24031 + sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc)
352.24032 + {
352.24033 + 	struct drm_mode_cursor arg;
352.24034 ++	int sigio;
352.24035 + 
352.24036 + 	if (!crtc->cursor)
352.24037 + 		return;
352.24038 + 
352.24039 +-	DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, crtc->id, crtc->cursor->handle));
352.24040 +-	assert(crtc->cursor->ref);
352.24041 ++	sigio = sigio_block();
352.24042 ++	if (crtc->cursor) {
352.24043 ++		DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), crtc->cursor->handle));
352.24044 ++		assert(crtc->cursor->ref > 0);
352.24045 ++		crtc->cursor->ref--;
352.24046 ++		crtc->cursor = NULL;
352.24047 ++		crtc->last_cursor_size = 0;
352.24048 + 
352.24049 +-	VG_CLEAR(arg);
352.24050 +-	arg.flags = DRM_MODE_CURSOR_BO;
352.24051 +-	arg.crtc_id = crtc->id;
352.24052 +-	arg.width = arg.height = 0;
352.24053 +-	arg.handle = 0;
352.24054 ++		VG_CLEAR(arg);
352.24055 ++		arg.flags = DRM_MODE_CURSOR_BO;
352.24056 ++		arg.crtc_id = __sna_crtc_id(crtc);
352.24057 ++		arg.width = arg.height = 0;
352.24058 ++		arg.handle = 0;
352.24059 + 
352.24060 +-	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
352.24061 +-	assert(crtc->cursor->ref > 0);
352.24062 +-	crtc->cursor->ref--;
352.24063 +-	crtc->cursor = NULL;
352.24064 +-	crtc->last_cursor_size = 0;
352.24065 ++		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
352.24066 ++	}
352.24067 ++	sigio_unblock(sigio);
352.24068 ++}
352.24069 ++
352.24070 ++static void
352.24071 ++sna_disable_cursors(ScrnInfoPtr scrn)
352.24072 ++{
352.24073 ++	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
352.24074 ++	struct sna *sna = to_sna(scrn);
352.24075 ++	int sigio, c;
352.24076 ++
352.24077 ++	DBG(("%s\n", __FUNCTION__));
352.24078 ++
352.24079 ++	sigio = sigio_block();
352.24080 ++	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.24081 ++		assert(to_sna_crtc(xf86_config->crtc[c]));
352.24082 ++		sna_crtc_disable_cursor(sna, to_sna_crtc(xf86_config->crtc[c]));
352.24083 ++	}
352.24084 ++	sigio_unblock(sigio);
352.24085 + }
352.24086 + 
352.24087 + static void
352.24088 +@@ -4852,6 +6340,7 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
352.24089 + {
352.24090 + 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
352.24091 + 	struct sna *sna = to_sna(scrn);
352.24092 ++	struct kmsg kmsg;
352.24093 + 	int sigio, c;
352.24094 + 
352.24095 + 	__DBG(("%s(%d, %d), cursor? %d\n", __FUNCTION__,
352.24096 +@@ -4859,6 +6348,7 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
352.24097 + 	if (sna->cursor.ref == NULL)
352.24098 + 		return;
352.24099 + 
352.24100 ++	kmsg_open(&kmsg);
352.24101 + 	sigio = sigio_block();
352.24102 + 	sna->cursor.last_x = x;
352.24103 + 	sna->cursor.last_y = y;
352.24104 +@@ -4876,27 +6366,37 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
352.24105 + 
352.24106 + 		VG_CLEAR(arg);
352.24107 + 		arg.flags = 0;
352.24108 +-		arg.crtc_id = sna_crtc->id;
352.24109 ++		arg.crtc_id = __sna_crtc_id(sna_crtc);
352.24110 + 		arg.handle = 0;
352.24111 + 
352.24112 + 		if (sna_crtc->bo == NULL)
352.24113 + 			goto disable;
352.24114 + 
352.24115 ++		cursor = __sna_get_cursor(sna, crtc);
352.24116 ++		if (cursor == NULL)
352.24117 ++			cursor = sna_crtc->cursor;
352.24118 ++		if (cursor == NULL) {
352.24119 ++			__DBG(("%s: failed to grab cursor, disabling\n", __FUNCTION__));
352.24120 ++			goto disable;
352.24121 ++		}
352.24122 ++
352.24123 + 		if (crtc->transform_in_use) {
352.24124 + 			int xhot = sna->cursor.ref->bits->xhot;
352.24125 + 			int yhot = sna->cursor.ref->bits->yhot;
352.24126 +-			struct pict_f_vector v;
352.24127 ++			struct pict_f_vector v, hot;
352.24128 + 
352.24129 +-			v.v[0] = (x + xhot) + 0.5;
352.24130 +-			v.v[1] = (y + yhot) + 0.5;
352.24131 +-			v.v[2] = 1;
352.24132 ++			v.v[0] = x + xhot + .5;
352.24133 ++			v.v[1] = y + yhot + .5;
352.24134 ++			v.v[2] = 1.;
352.24135 + 			pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &v);
352.24136 + 
352.24137 +-			rotate_coord_back(crtc->rotation, sna->cursor.size, &xhot, &yhot);
352.24138 ++			hot.v[0] = xhot;
352.24139 ++			hot.v[1] = yhot;
352.24140 ++			hot.v[2] = 1.;
352.24141 ++			pixman_f_transform_point(&sna_crtc->fb_to_cursor, &hot);
352.24142 + 
352.24143 +-			/* cursor will have 0.5 added to it already so floor is sufficent */
352.24144 +-			arg.x = floor(v.v[0]) - xhot;
352.24145 +-			arg.y = floor(v.v[1]) - yhot;
352.24146 ++			arg.x = floor(v.v[0] - hot.v[0]);
352.24147 ++			arg.y = floor(v.v[1] - hot.v[1]);
352.24148 + 		} else {
352.24149 + 			arg.x = x - crtc->x;
352.24150 + 			arg.y = y - crtc->y;
352.24151 +@@ -4904,15 +6404,6 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
352.24152 + 
352.24153 + 		if (arg.x < crtc->mode.HDisplay && arg.x > -sna->cursor.size &&
352.24154 + 		    arg.y < crtc->mode.VDisplay && arg.y > -sna->cursor.size) {
352.24155 +-			cursor = __sna_get_cursor(sna, crtc);
352.24156 +-			if (cursor == NULL)
352.24157 +-				cursor = sna_crtc->cursor;
352.24158 +-			if (cursor == NULL) {
352.24159 +-				__DBG(("%s: failed to grab cursor, disabling\n",
352.24160 +-				       __FUNCTION__));
352.24161 +-				goto disable;
352.24162 +-			}
352.24163 +-
352.24164 + 			if (sna_crtc->cursor != cursor || sna_crtc->last_cursor_size != cursor->size) {
352.24165 + 				arg.flags |= DRM_MODE_CURSOR_BO;
352.24166 + 				arg.handle = cursor->handle;
352.24167 +@@ -4932,10 +6423,13 @@ disable:
352.24168 + 		}
352.24169 + 
352.24170 + 		__DBG(("%s: CRTC:%d (%d, %d), handle=%d, flags=%x (old cursor handle=%d), move? %d, update handle? %d\n",
352.24171 +-		       __FUNCTION__, sna_crtc->id, arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0,
352.24172 ++		       __FUNCTION__, __sna_crtc_id(sna_crtc), arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0,
352.24173 + 		       arg.flags & DRM_MODE_CURSOR_MOVE, arg.flags & DRM_MODE_CURSOR_BO));
352.24174 + 
352.24175 +-		if (arg.flags &&
352.24176 ++		if (arg.flags == 0)
352.24177 ++			continue;
352.24178 ++
352.24179 ++		if (!FAIL_CURSOR_IOCTL &&
352.24180 + 		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
352.24181 + 			if (arg.flags & DRM_MODE_CURSOR_BO) {
352.24182 + 				if (sna_crtc->cursor) {
352.24183 +@@ -4949,9 +6443,21 @@ disable:
352.24184 + 				} else
352.24185 + 					sna_crtc->last_cursor_size = 0;
352.24186 + 			}
352.24187 ++		} else {
352.24188 ++			ERR(("%s: failed to update cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
352.24189 ++			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
352.24190 ++			/* XXX How to force switch back to SW cursor?
352.24191 ++			 * Right now we just want until the next cursor image
352.24192 ++			 * change, which is fairly frequent.
352.24193 ++			 */
352.24194 ++			sna->cursor.disable = true;
352.24195 + 		}
352.24196 + 	}
352.24197 + 	sigio_unblock(sigio);
352.24198 ++	kmsg_close(&kmsg, sna->cursor.disable);
352.24199 ++
352.24200 ++	if (unlikely(sna->cursor.disable))
352.24201 ++		restore_swcursor(sna);
352.24202 + }
352.24203 + 
352.24204 + #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2)
352.24205 +@@ -4978,17 +6484,6 @@ sna_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
352.24206 + {
352.24207 + }
352.24208 + 
352.24209 +-static int __cursor_size(CursorPtr cursor)
352.24210 +-{
352.24211 +-	int i, size;
352.24212 +-
352.24213 +-	i = MAX(cursor->bits->width, cursor->bits->height);
352.24214 +-	for (size = 64; size < i; size <<= 1)
352.24215 +-		;
352.24216 +-
352.24217 +-	return size;
352.24218 +-}
352.24219 +-
352.24220 + static bool
352.24221 + sna_cursor_preallocate(struct sna *sna)
352.24222 + {
352.24223 +@@ -5006,6 +6501,50 @@ sna_cursor_preallocate(struct sna *sna)
352.24224 + 	return true;
352.24225 + }
352.24226 + 
352.24227 ++static bool
352.24228 ++transformable_cursor(struct sna *sna, CursorPtr cursor)
352.24229 ++{
352.24230 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24231 ++	int i;
352.24232 ++
352.24233 ++	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24234 ++		xf86CrtcPtr crtc = config->crtc[i];
352.24235 ++		struct pixman_box16 box;
352.24236 ++		int size;
352.24237 ++
352.24238 ++		if (!to_sna_crtc(crtc)->hwcursor) {
352.24239 ++			DBG(("%s: hwcursor disabled on CRTC:%d [pipe=%d]\n",
352.24240 ++			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc)));
352.24241 ++			return false;
352.24242 ++		}
352.24243 ++
352.24244 ++		if (!sna->cursor.use_gtt || !sna->cursor.scratch) {
352.24245 ++			DBG(("%s: unable to use GTT curosor access [%d] or no scratch [%d]\n",
352.24246 ++			     __FUNCTION__, sna->cursor.use_gtt, sna->cursor.scratch));
352.24247 ++			return false;
352.24248 ++		}
352.24249 ++
352.24250 ++		box.x1 = box.y1 = 0;
352.24251 ++		box.x2 = cursor->bits->width;
352.24252 ++		box.y2 = cursor->bits->height;
352.24253 ++
352.24254 ++		if (!pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer,
352.24255 ++					       &box)) {
352.24256 ++			DBG(("%s: unable to transform bounds\n", __FUNCTION__));
352.24257 ++			return false;
352.24258 ++		}
352.24259 ++
352.24260 ++		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
352.24261 ++		if (size > sna->cursor.max_size) {
352.24262 ++			DBG(("%s: transformed cursor size=%d too large, max=%d\n",
352.24263 ++			     __FUNCTION__, size, sna->cursor.max_size));
352.24264 ++			return false;
352.24265 ++		}
352.24266 ++	}
352.24267 ++
352.24268 ++	return true;
352.24269 ++}
352.24270 ++
352.24271 + static Bool
352.24272 + sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
352.24273 + {
352.24274 +@@ -5014,6 +6553,9 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
352.24275 + 	DBG(("%s (%dx%d)?\n", __FUNCTION__,
352.24276 + 	     cursor->bits->width, cursor->bits->height));
352.24277 + 
352.24278 ++	if (sna->cursor.disable)
352.24279 ++		return FALSE;
352.24280 ++
352.24281 + 	/* cursors are invariant */
352.24282 + 	if (cursor == sna->cursor.ref)
352.24283 + 		return TRUE;
352.24284 +@@ -5023,12 +6565,24 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
352.24285 + 		sna->cursor.ref = NULL;
352.24286 + 	}
352.24287 + 
352.24288 +-	sna->cursor.size = __cursor_size(cursor);
352.24289 +-	if (sna->cursor.size > sna->cursor.max_size)
352.24290 ++	sna->cursor.size =
352.24291 ++		__cursor_size(cursor->bits->width, cursor->bits->height);
352.24292 ++	if (sna->cursor.size > sna->cursor.max_size) {
352.24293 ++		DBG(("%s: cursor size=%d too large, max %d: using sw cursor\n",
352.24294 ++		     __FUNCTION__, sna->cursor.size, sna->cursor.max_size));
352.24295 + 		return FALSE;
352.24296 ++	}
352.24297 ++
352.24298 ++	if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) {
352.24299 ++		DBG(("%s: RandR active [%d] and non-transformable cursor: using sw cursor\n",
352.24300 ++		     __FUNCTION__, sna->mode.rr_active));
352.24301 ++		return FALSE;
352.24302 ++	}
352.24303 + 
352.24304 +-	if (!sna_cursor_preallocate(sna))
352.24305 ++	if (!sna_cursor_preallocate(sna)) {
352.24306 ++		DBG(("%s: cursor preallocation failed: using sw cursor\n", __FUNCTION__));
352.24307 + 		return FALSE;
352.24308 ++	}
352.24309 + 
352.24310 + 	sna->cursor.ref = cursor;
352.24311 + 	cursor->refcnt++;
352.24312 +@@ -5056,8 +6610,12 @@ sna_cursor_pre_init(struct sna *sna)
352.24313 + 		return;
352.24314 + 
352.24315 + #define LOCAL_IOCTL_GET_CAP	DRM_IOWR(0x0c, struct local_get_cap)
352.24316 +-#define DRM_CAP_CURSOR_WIDTH	8
352.24317 +-#define DRM_CAP_CURSOR_HEIGHT	9
352.24318 ++#ifndef DRM_CAP_CURSOR_WIDTH
352.24319 ++#define DRM_CAP_CURSOR_WIDTH	0x8
352.24320 ++#endif
352.24321 ++#ifndef DRM_CAP_CURSOR_HEIGHT
352.24322 ++#define DRM_CAP_CURSOR_HEIGHT	0x9
352.24323 ++#endif
352.24324 + 
352.24325 + #define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
352.24326 + 
352.24327 +@@ -5087,11 +6645,9 @@ sna_cursor_pre_init(struct sna *sna)
352.24328 + 	DBG(("%s: cursor updates use_gtt?=%d\n",
352.24329 + 	     __FUNCTION__, sna->cursor.use_gtt));
352.24330 + 
352.24331 +-	if (!sna->cursor.use_gtt) {
352.24332 +-		sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4);
352.24333 +-		if (!sna->cursor.scratch)
352.24334 +-			sna->cursor.max_size = 0;
352.24335 +-	}
352.24336 ++	sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4);
352.24337 ++	if (!sna->cursor.scratch && !sna->cursor.use_gtt)
352.24338 ++		sna->cursor.max_size = 0;
352.24339 + 
352.24340 + 	sna->cursor.num_stash = -sna->mode.num_real_crtc;
352.24341 + 
352.24342 +@@ -5193,7 +6749,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
352.24343 + 	int output_count = 0;
352.24344 + 	int i;
352.24345 + 
352.24346 +-	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, crtc->id, crtc->pipe, bo->handle));
352.24347 ++	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), bo->handle));
352.24348 + 
352.24349 + 	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
352.24350 + 	assert(crtc->bo);
352.24351 +@@ -5207,11 +6763,11 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
352.24352 + 
352.24353 + 		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
352.24354 + 		     __FUNCTION__, output->name, i, to_connector_id(output),
352.24355 +-		     crtc->id, crtc->pipe,
352.24356 ++		     __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
352.24357 + 		     (uint32_t)output->possible_crtcs,
352.24358 + 		     (uint32_t)output->possible_clones));
352.24359 + 
352.24360 +-		assert(output->possible_crtcs & (1 << crtc->pipe) ||
352.24361 ++		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(crtc)) ||
352.24362 + 		       is_zaphod(sna->scrn));
352.24363 + 
352.24364 + 		output_ids[output_count] = to_connector_id(output);
352.24365 +@@ -5221,7 +6777,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
352.24366 + 	assert(output_count);
352.24367 + 
352.24368 + 	VG_CLEAR(arg);
352.24369 +-	arg.crtc_id = crtc->id;
352.24370 ++	arg.crtc_id = __sna_crtc_id(crtc);
352.24371 + 	arg.fb_id = fb_id(bo);
352.24372 + 	assert(arg.fb_id);
352.24373 + 	arg.x = x;
352.24374 +@@ -5231,20 +6787,74 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
352.24375 + 	arg.mode = crtc->kmode;
352.24376 + 	arg.mode_valid = 1;
352.24377 + 
352.24378 +-	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d across %d outputs [%d...]\n",
352.24379 +-	     __FUNCTION__, crtc->id, crtc->pipe,
352.24380 +-	     arg.mode.hdisplay,
352.24381 +-	     arg.mode.vdisplay,
352.24382 +-	     arg.x, arg.y,
352.24383 +-	     arg.mode.clock,
352.24384 +-	     arg.fb_id,
352.24385 +-	     output_count, output_count ? output_ids[0] : 0));
352.24386 ++	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d across %d outputs [%d...]\n",
352.24387 ++	     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
352.24388 ++	     arg.mode.hdisplay,
352.24389 ++	     arg.mode.vdisplay,
352.24390 ++	     arg.x, arg.y,
352.24391 ++	     arg.mode.clock,
352.24392 ++	     arg.fb_id,
352.24393 ++	     output_count, output_count ? output_ids[0] : 0));
352.24394 ++
352.24395 ++	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
352.24396 ++		return false;
352.24397 ++
352.24398 ++	crtc->offset = y << 16 | x;
352.24399 ++	__kgem_bo_clear_dirty(bo);
352.24400 ++	return true;
352.24401 ++}
352.24402 ++
352.24403 ++static void sna_mode_restore(struct sna *sna)
352.24404 ++{
352.24405 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24406 ++	int error = 0;
352.24407 ++	int i;
352.24408 ++
352.24409 ++	assert(!sna->mode.hidden);
352.24410 ++
352.24411 ++	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24412 ++		xf86CrtcPtr crtc = config->crtc[i];
352.24413 ++
352.24414 ++		assert(to_sna_crtc(crtc) != NULL);
352.24415 ++		if (to_sna_crtc(crtc)->bo == NULL)
352.24416 ++			continue;
352.24417 ++
352.24418 ++		assert(crtc->enabled);
352.24419 ++		if (!__sna_crtc_set_mode(crtc)) {
352.24420 ++			sna_crtc_disable(crtc, false);
352.24421 ++			error++;
352.24422 ++		}
352.24423 ++	}
352.24424 ++	sna_mode_wakeup(sna);
352.24425 ++	while (sna->mode.flip_active && sna_mode_wakeup(sna))
352.24426 ++		;
352.24427 ++	update_flush_interval(sna);
352.24428 ++	sna_cursors_reload(sna);
352.24429 ++	sna->mode.dirty = false;
352.24430 ++
352.24431 ++	if (error)
352.24432 ++		xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.24433 ++			   "Failed to restore display configuration\n");
352.24434 ++}
352.24435 ++
352.24436 ++bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo)
352.24437 ++{
352.24438 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24439 ++	int i;
352.24440 ++
352.24441 ++	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24442 ++		struct sna_crtc *crtc = config->crtc[i]->driver_private;
352.24443 ++
352.24444 ++		if (crtc->bo == NULL)
352.24445 ++			continue;
352.24446 + 
352.24447 +-	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
352.24448 +-		return false;
352.24449 ++		if (crtc->bo == bo)
352.24450 ++			continue;
352.24451 + 
352.24452 +-	crtc->offset = y << 16 | x;
352.24453 +-	return true;
352.24454 ++		return true;
352.24455 ++	}
352.24456 ++
352.24457 ++	return false;
352.24458 + }
352.24459 + 
352.24460 + int
352.24461 +@@ -5256,6 +6866,7 @@ sna_page_flip(struct sna *sna,
352.24462 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24463 + 	const int width = sna->scrn->virtualX;
352.24464 + 	const int height = sna->scrn->virtualY;
352.24465 ++	int sigio;
352.24466 + 	int count = 0;
352.24467 + 	int i;
352.24468 + 
352.24469 +@@ -5263,23 +6874,26 @@ sna_page_flip(struct sna *sna,
352.24470 + 	assert(bo->refcnt);
352.24471 + 
352.24472 + 	assert((sna->flags & SNA_IS_HOSTED) == 0);
352.24473 +-	assert((sna->flags & SNA_TEAR_FREE) == 0);
352.24474 + 	assert(sna->mode.flip_active == 0);
352.24475 + 	assert(sna->mode.front_active);
352.24476 ++	assert(!sna->mode.hidden);
352.24477 + 	assert(sna->scrn->vtSema);
352.24478 + 
352.24479 + 	if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0)
352.24480 + 		return 0;
352.24481 + 
352.24482 + 	kgem_bo_submit(&sna->kgem, bo);
352.24483 ++	__kgem_bo_clear_dirty(bo);
352.24484 + 
352.24485 ++	sigio = sigio_block();
352.24486 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24487 + 		struct sna_crtc *crtc = config->crtc[i]->driver_private;
352.24488 + 		struct drm_mode_crtc_page_flip arg;
352.24489 + 		uint32_t crtc_offset;
352.24490 ++		int fixup;
352.24491 + 
352.24492 + 		DBG(("%s: crtc %d id=%d, pipe=%d active? %d\n",
352.24493 +-		     __FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo != NULL));
352.24494 ++		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo != NULL));
352.24495 + 		if (crtc->bo == NULL)
352.24496 + 			continue;
352.24497 + 		assert(!crtc->transform);
352.24498 +@@ -5288,13 +6902,18 @@ sna_page_flip(struct sna *sna,
352.24499 + 		assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
352.24500 + 		assert(crtc->flip_bo == NULL);
352.24501 + 
352.24502 +-		arg.crtc_id = crtc->id;
352.24503 ++		assert_crtc_fb(sna, crtc);
352.24504 ++		if (data == NULL && crtc->bo == bo)
352.24505 ++			goto next_crtc;
352.24506 ++
352.24507 ++		arg.crtc_id = __sna_crtc_id(crtc);
352.24508 + 		arg.fb_id = get_fb(sna, bo, width, height);
352.24509 + 		if (arg.fb_id == 0) {
352.24510 + 			assert(count == 0);
352.24511 +-			return 0;
352.24512 ++			break;
352.24513 + 		}
352.24514 + 
352.24515 ++		fixup = 0;
352.24516 + 		crtc_offset = crtc->base->y << 16 | crtc->base->x;
352.24517 + 
352.24518 + 		if (bo->pitch != crtc->bo->pitch || crtc_offset != crtc->offset) {
352.24519 +@@ -5303,7 +6922,12 @@ sna_page_flip(struct sna *sna,
352.24520 + 			     bo->pitch, crtc->bo->pitch,
352.24521 + 			     crtc_offset, crtc->offset));
352.24522 + fixup_flip:
352.24523 ++			fixup = 1;
352.24524 + 			if (crtc->bo != bo && sna_crtc_flip(sna, crtc, bo, crtc->base->x, crtc->base->y)) {
352.24525 ++update_scanout:
352.24526 ++				DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
352.24527 ++				     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout,
352.24528 ++				     bo->handle, bo->active_scanout));
352.24529 + 				assert(crtc->bo->active_scanout);
352.24530 + 				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
352.24531 + 				crtc->bo->active_scanout--;
352.24532 +@@ -5321,15 +6945,8 @@ fixup_flip:
352.24533 + 					goto next_crtc;
352.24534 + 
352.24535 + 				/* queue a flip in order to send the event */
352.24536 +-			} else {
352.24537 +-				if (count && !xf86SetDesiredModes(sna->scrn)) {
352.24538 +-					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.24539 +-						   "failed to restore display configuration\n");
352.24540 +-					for (; i < sna->mode.num_real_crtc; i++)
352.24541 +-						sna_crtc_disable(config->crtc[i]);
352.24542 +-				}
352.24543 +-				return 0;
352.24544 +-			}
352.24545 ++			} else
352.24546 ++				goto error;
352.24547 + 		}
352.24548 + 
352.24549 + 		/* Only the reference crtc will finally deliver its page flip
352.24550 +@@ -5346,7 +6963,7 @@ fixup_flip:
352.24551 + 
352.24552 + retry_flip:
352.24553 + 		DBG(("%s: crtc %d id=%d, pipe=%d  --> fb %d\n",
352.24554 +-		     __FUNCTION__, i, crtc->id, crtc->pipe, arg.fb_id));
352.24555 ++		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), arg.fb_id));
352.24556 + 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
352.24557 + 			ERR(("%s: pageflip failed with err=%d\n", __FUNCTION__, errno));
352.24558 + 
352.24559 +@@ -5354,7 +6971,7 @@ retry_flip:
352.24560 + 				struct drm_mode_crtc mode;
352.24561 + 
352.24562 + 				memset(&mode, 0, sizeof(mode));
352.24563 +-				mode.crtc_id = crtc->id;
352.24564 ++				mode.crtc_id = __sna_crtc_id(crtc);
352.24565 + 				drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
352.24566 + 
352.24567 + 				DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=%d\n",
352.24568 +@@ -5366,7 +6983,7 @@ retry_flip:
352.24569 + 					goto fixup_flip;
352.24570 + 
352.24571 + 				if (count == 0)
352.24572 +-					return 0;
352.24573 ++					break;
352.24574 + 
352.24575 + 				DBG(("%s: throttling on busy flip / waiting for kernel to catch up\n", __FUNCTION__));
352.24576 + 				drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_THROTTLE, 0);
352.24577 +@@ -5375,15 +6992,25 @@ retry_flip:
352.24578 + 				goto retry_flip;
352.24579 + 			}
352.24580 + 
352.24581 ++			if (!fixup)
352.24582 ++				goto fixup_flip;
352.24583 ++
352.24584 ++error:
352.24585 + 			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.24586 +-				   "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
352.24587 +-				   crtc->id, crtc->pipe, data ? "synchronous": "asynchronous");
352.24588 ++					"page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
352.24589 ++					__sna_crtc_id(crtc), __sna_crtc_pipe(crtc), data ? "synchronous": "asynchronous");
352.24590 ++
352.24591 ++			if (count || crtc->bo == bo)
352.24592 ++				sna_mode_restore(sna);
352.24593 ++
352.24594 + 			sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
352.24595 +-			goto fixup_flip;
352.24596 ++			count = 0;
352.24597 ++			break;
352.24598 + 		}
352.24599 + 
352.24600 + 		if (data) {
352.24601 + 			assert(crtc->flip_bo == NULL);
352.24602 ++			assert(handler);
352.24603 + 			crtc->flip_handler = handler;
352.24604 + 			crtc->flip_data = data;
352.24605 + 			crtc->flip_bo = kgem_bo_reference(bo);
352.24606 +@@ -5391,11 +7018,15 @@ retry_flip:
352.24607 + 			crtc->flip_serial = crtc->mode_serial;
352.24608 + 			crtc->flip_pending = true;
352.24609 + 			sna->mode.flip_active++;
352.24610 +-		}
352.24611 + 
352.24612 ++			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
352.24613 ++			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
352.24614 ++		} else
352.24615 ++			goto update_scanout;
352.24616 + next_crtc:
352.24617 + 		count++;
352.24618 + 	}
352.24619 ++	sigio_unblock(sigio);
352.24620 + 
352.24621 + 	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
352.24622 + 	return count;
352.24623 +@@ -5471,7 +7102,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
352.24624 + 
352.24625 + 		assert(sna_crtc);
352.24626 + 
352.24627 +-		lut.crtc_id = sna_crtc->id;
352.24628 ++		lut.crtc_id = __sna_crtc_id(sna_crtc);
352.24629 + 		lut.gamma_size = 256;
352.24630 + 		lut.red = (uintptr_t)(gamma);
352.24631 + 		lut.green = (uintptr_t)(gamma + 256);
352.24632 +@@ -5485,7 +7116,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
352.24633 + 		}
352.24634 + 
352.24635 + 		DBG(("%s: CRTC:%d, pipe=%d: gamma set?=%d\n",
352.24636 +-		     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
352.24637 ++		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
352.24638 + 		     gamma_set));
352.24639 + 		if (!gamma_set) {
352.24640 + 			int i;
352.24641 +@@ -5502,6 +7133,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
352.24642 + 			crtc->gamma_red = gamma;
352.24643 + 			crtc->gamma_green = gamma + 256;
352.24644 + 			crtc->gamma_blue = gamma + 2*256;
352.24645 ++			crtc->gamma_size = 256;
352.24646 + 		}
352.24647 + 	}
352.24648 + }
352.24649 +@@ -5528,6 +7160,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24650 + {
352.24651 + 	ScrnInfoPtr scrn = sna->scrn;
352.24652 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
352.24653 ++	int crtc_active, crtc_enabled;
352.24654 + 	int width, height;
352.24655 + 	int i, j;
352.24656 + 
352.24657 +@@ -5565,6 +7198,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24658 + 	}
352.24659 + 
352.24660 + 	/* Copy the existing modes on each CRTCs */
352.24661 ++	crtc_active = crtc_enabled = 0;
352.24662 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24663 + 		xf86CrtcPtr crtc = config->crtc[i];
352.24664 + 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.24665 +@@ -5577,12 +7211,12 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24666 + 
352.24667 + 		/* Retrieve the current mode */
352.24668 + 		VG_CLEAR(mode);
352.24669 +-		mode.crtc_id = sna_crtc->id;
352.24670 ++		mode.crtc_id = __sna_crtc_id(sna_crtc);
352.24671 + 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
352.24672 + 			continue;
352.24673 + 
352.24674 + 		DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
352.24675 +-		     sna_crtc->id, sna_crtc->pipe,
352.24676 ++		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
352.24677 + 		     mode.mode_valid && mode.mode.clock));
352.24678 + 
352.24679 + 		if (!mode.mode_valid || mode.mode.clock == 0)
352.24680 +@@ -5593,6 +7227,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24681 + 		crtc->desiredX = mode.x;
352.24682 + 		crtc->desiredY = mode.y;
352.24683 + 		crtc->desiredTransformPresent = FALSE;
352.24684 ++		crtc_active++;
352.24685 + 	}
352.24686 + 
352.24687 + 	/* Reconstruct outputs pointing to active CRTC */
352.24688 +@@ -5604,6 +7239,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24689 + 
352.24690 + 		crtc_id = (uintptr_t)output->crtc;
352.24691 + 		output->crtc = NULL;
352.24692 ++		output->status = XF86OutputStatusUnknown;
352.24693 + 		if (sna->flags & SNA_IS_SLAVED)
352.24694 + 			continue;
352.24695 + 
352.24696 +@@ -5623,7 +7259,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24697 + 			xf86CrtcPtr crtc = config->crtc[j];
352.24698 + 
352.24699 + 			assert(to_sna_crtc(crtc));
352.24700 +-			if (to_sna_crtc(crtc)->id != crtc_id)
352.24701 ++			if (sna_crtc_id(crtc) != crtc_id)
352.24702 + 				continue;
352.24703 + 
352.24704 + 			if (crtc->desiredMode.status == MODE_OK) {
352.24705 +@@ -5641,18 +7277,30 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24706 + 					   "Output %s using initial mode %s on pipe %d\n",
352.24707 + 					   output->name,
352.24708 + 					   crtc->desiredMode.name,
352.24709 +-					   to_sna_crtc(crtc)->pipe);
352.24710 ++					   sna_crtc_pipe(crtc));
352.24711 + 
352.24712 + 				output->crtc = crtc;
352.24713 ++				output->status = XF86OutputStatusConnected;
352.24714 + 				crtc->enabled = TRUE;
352.24715 ++				crtc_enabled++;
352.24716 ++
352.24717 ++				output_set_gamma(output, crtc);
352.24718 ++
352.24719 ++				if (output->conf_monitor) {
352.24720 ++					output->mm_width = output->conf_monitor->mon_width;
352.24721 ++					output->mm_height = output->conf_monitor->mon_height;
352.24722 ++				}
352.24723 ++
352.24724 ++#if 0
352.24725 ++				sna_output_attach_edid(output);
352.24726 ++				sna_output_attach_tile(output);
352.24727 ++#endif
352.24728 + 
352.24729 + 				if (output->mm_width == 0 || output->mm_height == 0) {
352.24730 + 					output->mm_height = (crtc->desiredMode.VDisplay * 254) / (10*DEFAULT_DPI);
352.24731 + 					output->mm_width = (crtc->desiredMode.HDisplay * 254) / (10*DEFAULT_DPI);
352.24732 + 				}
352.24733 + 
352.24734 +-				output_set_gamma(output, crtc);
352.24735 +-
352.24736 + 				M = calloc(1, sizeof(DisplayModeRec));
352.24737 + 				if (M) {
352.24738 + 					*M = crtc->desiredMode;
352.24739 +@@ -5673,6 +7321,12 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24740 + 		}
352.24741 + 	}
352.24742 + 
352.24743 ++	if (crtc_active != crtc_enabled) {
352.24744 ++		DBG(("%s: only enabled %d out of %d active CRTC, forcing a reconfigure\n",
352.24745 ++		     __FUNCTION__, crtc_enabled, crtc_active));
352.24746 ++		return false;
352.24747 ++	}
352.24748 ++
352.24749 + 	width = height = 0;
352.24750 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24751 + 		xf86CrtcPtr crtc = config->crtc[i];
352.24752 +@@ -5707,8 +7361,8 @@ static bool sna_probe_initial_configuration(struct sna *sna)
352.24753 + 			if (sna_output->num_modes == 0)
352.24754 + 				continue;
352.24755 + 
352.24756 +-			width = sna_output->modes[0].hdisplay;
352.24757 +-			height= sna_output->modes[0].vdisplay;
352.24758 ++			width  = sna_output->modes[0].hdisplay;
352.24759 ++			height = sna_output->modes[0].vdisplay;
352.24760 + 
352.24761 + 			DBG(("%s: panel '%s' is %dx%d\n",
352.24762 + 			     __FUNCTION__, output->name, width, height));
352.24763 +@@ -5788,7 +7442,7 @@ probe_capabilities(struct sna *sna)
352.24764 + 	sna->flags &= ~(SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP);
352.24765 + 	if (has_flip(sna))
352.24766 + 		sna->flags |= SNA_HAS_FLIP;
352.24767 +-	if (has_flip__async(sna))
352.24768 ++	if (has_flip__async(sna) && (sna->flags & SNA_TEAR_FREE) == 0)
352.24769 + 		sna->flags |= SNA_HAS_ASYNC_FLIP;
352.24770 + 	DBG(("%s: page flips? %s, async? %s\n", __FUNCTION__,
352.24771 + 	     sna->flags & SNA_HAS_FLIP ? "enabled" : "disabled",
352.24772 +@@ -5813,12 +7467,25 @@ sna_crtc_config_notify(ScreenPtr screen)
352.24773 + 		return;
352.24774 + 	}
352.24775 + 
352.24776 ++	/* Flush any events completed by the modeset */
352.24777 ++	sna_mode_wakeup(sna);
352.24778 ++
352.24779 + 	update_flush_interval(sna);
352.24780 ++	sna->cursor.disable = false; /* Reset HW cursor until the next fail */
352.24781 + 	sna_cursors_reload(sna);
352.24782 + 
352.24783 + 	probe_capabilities(sna);
352.24784 + 	sna_present_update(sna);
352.24785 + 
352.24786 ++	/* Allow TearFree to come back on when everything is off */
352.24787 ++	if (!sna->mode.front_active && sna->flags & SNA_WANT_TEAR_FREE) {
352.24788 ++		if ((sna->flags & SNA_TEAR_FREE) == 0)
352.24789 ++			DBG(("%s: enable TearFree next modeset\n",
352.24790 ++			     __FUNCTION__));
352.24791 ++
352.24792 ++		sna->flags |= SNA_TEAR_FREE;
352.24793 ++	}
352.24794 ++
352.24795 + 	sna->mode.dirty = false;
352.24796 + }
352.24797 + 
352.24798 +@@ -5840,6 +7507,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
352.24799 + 	}
352.24800 + 
352.24801 + 	probe_capabilities(sna);
352.24802 ++	sna->mode.hidden = 1;
352.24803 + 
352.24804 + 	if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake))
352.24805 + 		num_fake = 1;
352.24806 +@@ -5855,6 +7523,9 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
352.24807 + 	if (res) {
352.24808 + 		xf86CrtcConfigPtr xf86_config;
352.24809 + 
352.24810 ++		DBG(("%s: found %d CRTC, %d encoders, %d connectors\n",
352.24811 ++		     __FUNCTION__, res->count_crtcs, res->count_encoders, res->count_connectors));
352.24812 ++
352.24813 + 		assert(res->count_crtcs);
352.24814 + 		assert(res->count_connectors);
352.24815 + 
352.24816 +@@ -5862,6 +7533,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
352.24817 + 
352.24818 + 		xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
352.24819 + 		xf86_config->xf86_crtc_notify = sna_crtc_config_notify;
352.24820 ++		xf86_config->compat_output = 0;
352.24821 + 
352.24822 + 		for (i = 0; i < res->count_crtcs; i++)
352.24823 + 			if (!sna_crtc_add(scrn, res->crtcs[i]))
352.24824 +@@ -5900,6 +7572,11 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
352.24825 + 	if (!sna_mode_fake_init(sna, num_fake))
352.24826 + 		return false;
352.24827 + 
352.24828 ++	sna->mode.shadow_size = 256;
352.24829 ++	sna->mode.shadow_events = malloc(sna->mode.shadow_size * sizeof(struct drm_event_vblank));
352.24830 ++	if (!sna->mode.shadow_events)
352.24831 ++		return false;
352.24832 ++
352.24833 + 	if (!sna_probe_initial_configuration(sna)) {
352.24834 + 		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
352.24835 + 
352.24836 +@@ -5912,6 +7589,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
352.24837 + 		}
352.24838 + 	}
352.24839 + 	sort_config_outputs(sna);
352.24840 ++	TimerSet(NULL, 0, COLDPLUG_DELAY_MS, sna_mode_coldplug, sna);
352.24841 + 
352.24842 + 	sna_setup_provider(scrn);
352.24843 + 	return scrn->modes != NULL;
352.24844 +@@ -5921,18 +7599,58 @@ bool
352.24845 + sna_mode_wants_tear_free(struct sna *sna)
352.24846 + {
352.24847 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24848 ++	bool found = false;
352.24849 ++	FILE *file;
352.24850 + 	int i;
352.24851 + 
352.24852 ++	file = fopen("/sys/module/i915/parameters/enable_fbc", "r");
352.24853 ++	if (file) {
352.24854 ++		int fbc_enabled = 0;
352.24855 ++		int value;
352.24856 ++
352.24857 ++		if (fscanf(file, "%d", &value) == 1)
352.24858 ++			fbc_enabled = value > 0;
352.24859 ++		fclose(file);
352.24860 ++
352.24861 ++		DBG(("%s: module parameter 'enable_fbc' enabled? %d\n",
352.24862 ++		     __FUNCTION__, fbc_enabled));
352.24863 ++
352.24864 ++		if (fbc_enabled)
352.24865 ++			return true;
352.24866 ++	}
352.24867 ++
352.24868 + 	for (i = 0; i < sna->mode.num_real_output; i++) {
352.24869 + 		struct sna_output *output = to_sna_output(config->output[i]);
352.24870 + 		int id = find_property(sna, output, "Panel Self-Refresh");
352.24871 +-		if (id !=-1 && output->prop_values[id] != -1) {
352.24872 ++		if (id == -1)
352.24873 ++			continue;
352.24874 ++
352.24875 ++		found = true;
352.24876 ++		if (output->prop_values[id] != -1) {
352.24877 + 			DBG(("%s: Panel Self-Refresh detected on %s\n",
352.24878 + 			     __FUNCTION__, config->output[i]->name));
352.24879 + 			return true;
352.24880 + 		}
352.24881 + 	}
352.24882 + 
352.24883 ++	if (!found) {
352.24884 ++		file = fopen("/sys/module/i915/parameters/enable_psr", "r");
352.24885 ++		if (file) {
352.24886 ++			int psr_enabled = 0;
352.24887 ++			int value;
352.24888 ++
352.24889 ++			if (fscanf(file, "%d", &value) == 1)
352.24890 ++				psr_enabled = value > 0;
352.24891 ++			fclose(file);
352.24892 ++
352.24893 ++			DBG(("%s: module parameter 'enable_psr' enabled? %d\n",
352.24894 ++			     __FUNCTION__, psr_enabled));
352.24895 ++
352.24896 ++			if (psr_enabled)
352.24897 ++				return true;
352.24898 ++		}
352.24899 ++	}
352.24900 ++
352.24901 + 	return false;
352.24902 + }
352.24903 + 
352.24904 +@@ -5955,7 +7673,7 @@ sna_mode_set_primary(struct sna *sna)
352.24905 + 
352.24906 + 		DBG(("%s: setting PrimaryOutput %s\n", __FUNCTION__, output->name));
352.24907 + 		rr->primaryOutput = output->randr_output;
352.24908 +-		RROutputChanged(rr->primaryOutput, 0);
352.24909 ++		RROutputChanged(rr->primaryOutput, FALSE);
352.24910 + 		rr->layoutChanged = TRUE;
352.24911 + 		break;
352.24912 + 	}
352.24913 +@@ -5974,12 +7692,9 @@ sna_mode_disable(struct sna *sna)
352.24914 + 	if (!sna->scrn->vtSema)
352.24915 + 		return false;
352.24916 + 
352.24917 +-	/* XXX we will cause previously hidden cursors to be reshown, but
352.24918 +-	 * this should be a rare fixup case for severe fragmentation.
352.24919 +-	 */
352.24920 +-	sna_hide_cursors(sna->scrn);
352.24921 ++	sna_disable_cursors(sna->scrn);
352.24922 + 	for (i = 0; i < sna->mode.num_real_crtc; i++)
352.24923 +-		sna_crtc_disable(config->crtc[i]);
352.24924 ++		sna_crtc_disable(config->crtc[i], false);
352.24925 + 	assert(sna->mode.front_active == 0);
352.24926 + 
352.24927 + 	sna_mode_wakeup(sna);
352.24928 +@@ -6001,6 +7716,11 @@ sna_mode_enable(struct sna *sna)
352.24929 + 	if (!sna->scrn->vtSema)
352.24930 + 		return;
352.24931 + 
352.24932 ++	if (sna->mode.hidden) {
352.24933 ++		DBG(("%s: hidden outputs\n", __FUNCTION__));
352.24934 ++		return;
352.24935 ++	}
352.24936 ++
352.24937 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.24938 + 		xf86CrtcPtr crtc = config->crtc[i];
352.24939 + 
352.24940 +@@ -6016,13 +7736,30 @@ sna_mode_enable(struct sna *sna)
352.24941 + 	}
352.24942 + 
352.24943 + 	update_flush_interval(sna);
352.24944 +-	sna_show_cursors(sna->scrn);
352.24945 ++	sna_cursors_reload(sna);
352.24946 + 	sna->mode.dirty = false;
352.24947 + }
352.24948 + 
352.24949 ++static void sna_randr_close(struct sna *sna)
352.24950 ++{
352.24951 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24952 ++	int n;
352.24953 ++
352.24954 ++	/* The RR structs are freed early during CloseScreen as they
352.24955 ++	 * are tracked as Resources. However, we may be tempted to
352.24956 ++	 * access them during shutdown so decouple them now.
352.24957 ++	 */
352.24958 ++	  for (n = 0; n < config->num_output; n++)
352.24959 ++		  config->output[n]->randr_output = NULL;
352.24960 ++
352.24961 ++	  for (n = 0; n < config->num_crtc; n++)
352.24962 ++		  config->crtc[n]->randr_crtc = NULL;
352.24963 ++}
352.24964 ++
352.24965 + void
352.24966 + sna_mode_close(struct sna *sna)
352.24967 + {
352.24968 ++	sna_randr_close(sna);
352.24969 + 	sna_mode_wakeup(sna);
352.24970 + 
352.24971 + 	if (sna->flags & SNA_IS_HOSTED)
352.24972 +@@ -6077,15 +7814,22 @@ xf86CrtcPtr
352.24973 + sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
352.24974 + {
352.24975 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.24976 +-	xf86CrtcPtr best_crtc;
352.24977 +-	int best_coverage, c;
352.24978 ++	xf86CrtcPtr best_crtc = NULL;
352.24979 ++	int best_coverage = -1, c;
352.24980 + 
352.24981 + 	if (sna->flags & SNA_IS_HOSTED)
352.24982 + 		return NULL;
352.24983 + 
352.24984 + 	/* If we do not own the VT, we do not own the CRTC either */
352.24985 +-	if (!sna->scrn->vtSema)
352.24986 ++	if (!sna->scrn->vtSema) {
352.24987 ++		DBG(("%s: none, VT switched\n", __FUNCTION__));
352.24988 ++		return NULL;
352.24989 ++	}
352.24990 ++
352.24991 ++	if (sna->mode.hidden) {
352.24992 ++		DBG(("%s: none, hidden outputs\n", __FUNCTION__));
352.24993 + 		return NULL;
352.24994 ++	}
352.24995 + 
352.24996 + 	DBG(("%s for box=(%d, %d), (%d, %d)\n",
352.24997 + 	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
352.24998 +@@ -6107,10 +7851,10 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
352.24999 + 			     cover_box.x2, cover_box.y2));
352.25000 + 			return desired;
352.25001 + 		}
352.25002 ++		best_crtc = desired;
352.25003 ++		best_coverage = 0;
352.25004 + 	}
352.25005 + 
352.25006 +-	best_crtc = NULL;
352.25007 +-	best_coverage = 0;
352.25008 + 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.25009 + 		xf86CrtcPtr crtc = config->crtc[c];
352.25010 + 		BoxRec cover_box;
352.25011 +@@ -6156,6 +7900,38 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
352.25012 + 	return best_crtc;
352.25013 + }
352.25014 + 
352.25015 ++static xf86CrtcPtr first_active_crtc(struct sna *sna)
352.25016 ++{
352.25017 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.25018 ++	int n;
352.25019 ++
352.25020 ++	for (n = 0; n < sna->mode.num_real_crtc; n++) {
352.25021 ++		xf86CrtcPtr crtc = config->crtc[n];
352.25022 ++		if (to_sna_crtc(crtc)->bo)
352.25023 ++			return crtc;
352.25024 ++	}
352.25025 ++
352.25026 ++	/* No active, use the first as a placeholder */
352.25027 ++	if (sna->mode.num_real_crtc)
352.25028 ++		return config->crtc[0];
352.25029 ++
352.25030 ++	return NULL;
352.25031 ++}
352.25032 ++
352.25033 ++xf86CrtcPtr sna_primary_crtc(struct sna *sna)
352.25034 ++{
352.25035 ++	rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
352.25036 ++	if (rr && rr->primaryOutput) {
352.25037 ++		xf86OutputPtr output = rr->primaryOutput->devPrivate;
352.25038 ++		if (output->crtc &&
352.25039 ++		    output->scrn == sna->scrn &&
352.25040 ++		    to_sna_crtc(output->crtc))
352.25041 ++			return output->crtc;
352.25042 ++	}
352.25043 ++
352.25044 ++	return first_active_crtc(sna);
352.25045 ++}
352.25046 ++
352.25047 + #define MI_LOAD_REGISTER_IMM			(0x22<<23)
352.25048 + 
352.25049 + static bool sna_emit_wait_for_scanline_hsw(struct sna *sna,
352.25050 +@@ -6433,7 +8209,7 @@ sna_wait_for_scanline(struct sna *sna,
352.25051 + 		y2 /= 2;
352.25052 + 	}
352.25053 + 
352.25054 +-	pipe = sna_crtc_to_pipe(crtc);
352.25055 ++	pipe = sna_crtc_pipe(crtc);
352.25056 + 	DBG(("%s: pipe=%d, y1=%d, y2=%d, full_height?=%d\n",
352.25057 + 	     __FUNCTION__, pipe, y1, y2, full_height));
352.25058 + 
352.25059 +@@ -6457,19 +8233,101 @@ sna_wait_for_scanline(struct sna *sna,
352.25060 + 	return ret;
352.25061 + }
352.25062 + 
352.25063 ++static bool sna_mode_shutdown_crtc(xf86CrtcPtr crtc)
352.25064 ++{
352.25065 ++	struct sna *sna = to_sna(crtc->scrn);
352.25066 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
352.25067 ++	bool disabled = false;
352.25068 ++	int o;
352.25069 ++
352.25070 ++	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
352.25071 ++		   "%s: invalid state found on pipe %d, disabling CRTC:%d\n",
352.25072 ++		   __FUNCTION__,
352.25073 ++		   __sna_crtc_pipe(to_sna_crtc(crtc)),
352.25074 ++		   __sna_crtc_id(to_sna_crtc(crtc)));
352.25075 ++	sna_crtc_disable(crtc, true);
352.25076 ++#if XF86_CRTC_VERSION >= 3
352.25077 ++	crtc->active = FALSE;
352.25078 ++#endif
352.25079 ++	if (crtc->enabled) {
352.25080 ++		crtc->enabled = FALSE;
352.25081 ++		disabled = true;
352.25082 ++	}
352.25083 ++
352.25084 ++	for (o = 0; o < sna->mode.num_real_output; o++) {
352.25085 ++		xf86OutputPtr output = config->output[o];
352.25086 ++
352.25087 ++		if (output->crtc != crtc)
352.25088 ++			continue;
352.25089 ++
352.25090 ++		output->funcs->dpms(output, DPMSModeOff);
352.25091 ++		output->crtc = NULL;
352.25092 ++	}
352.25093 ++
352.25094 ++	return disabled;
352.25095 ++}
352.25096 ++
352.25097 ++static bool
352.25098 ++sna_mode_disable_secondary_planes(struct sna *sna)
352.25099 ++{
352.25100 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.25101 ++	bool disabled = false;
352.25102 ++	int c;
352.25103 ++
352.25104 ++	/* Disable all secondary planes on our CRTCs, just in case
352.25105 ++	 * other userspace left garbage in them.
352.25106 ++	 */
352.25107 ++	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.25108 ++		xf86CrtcPtr crtc = config->crtc[c];
352.25109 ++		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.25110 ++		struct plane *plane;
352.25111 ++
352.25112 ++		list_for_each_entry(plane, &sna_crtc->sprites, link) {
352.25113 ++			struct local_mode_get_plane p;
352.25114 ++			struct local_mode_set_plane s;
352.25115 ++
352.25116 ++			VG_CLEAR(p);
352.25117 ++			p.plane_id = plane->id;
352.25118 ++			p.count_format_types = 0;
352.25119 ++			if (drmIoctl(sna->kgem.fd,
352.25120 ++				     LOCAL_IOCTL_MODE_GETPLANE,
352.25121 ++				     &p))
352.25122 ++				continue;
352.25123 ++
352.25124 ++			if (p.fb_id == 0 || p.crtc_id == 0)
352.25125 ++				continue;
352.25126 ++
352.25127 ++			memset(&s, 0, sizeof(s));
352.25128 ++			s.plane_id = p.plane_id;
352.25129 ++			s.crtc_id = p.crtc_id;
352.25130 ++			if (drmIoctl(sna->kgem.fd,
352.25131 ++				     LOCAL_IOCTL_MODE_SETPLANE,
352.25132 ++				     &s))
352.25133 ++				disabled |= sna_mode_shutdown_crtc(crtc);
352.25134 ++		}
352.25135 ++	}
352.25136 ++
352.25137 ++	return disabled;
352.25138 ++}
352.25139 ++
352.25140 + void sna_mode_check(struct sna *sna)
352.25141 + {
352.25142 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.25143 +-	int i;
352.25144 ++	bool disabled;
352.25145 ++	int c, o;
352.25146 + 
352.25147 + 	if (sna->flags & SNA_IS_HOSTED)
352.25148 + 		return;
352.25149 + 
352.25150 +-	DBG(("%s\n", __FUNCTION__));
352.25151 ++	DBG(("%s: hidden?=%d\n", __FUNCTION__, sna->mode.hidden));
352.25152 ++	if (sna->mode.hidden)
352.25153 ++		return;
352.25154 ++
352.25155 ++	disabled = sna_mode_disable_secondary_planes(sna);
352.25156 + 
352.25157 + 	/* Validate CRTC attachments and force consistency upon the kernel */
352.25158 +-	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.25159 +-		xf86CrtcPtr crtc = config->crtc[i];
352.25160 ++	for (c = 0; c < sna->mode.num_real_crtc; c++) {
352.25161 ++		xf86CrtcPtr crtc = config->crtc[c];
352.25162 + 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.25163 + 		struct drm_mode_crtc mode;
352.25164 + 		uint32_t expected[2];
352.25165 +@@ -6483,7 +8341,7 @@ void sna_mode_check(struct sna *sna)
352.25166 + 		expected[1] = sna_crtc->flip_bo ? fb_id(sna_crtc->flip_bo) : -1;
352.25167 + 
352.25168 + 		VG_CLEAR(mode);
352.25169 +-		mode.crtc_id = sna_crtc->id;
352.25170 ++		mode.crtc_id = __sna_crtc_id(sna_crtc);
352.25171 + 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
352.25172 + 			continue;
352.25173 + 
352.25174 +@@ -6492,16 +8350,12 @@ void sna_mode_check(struct sna *sna)
352.25175 + 		     mode.crtc_id, mode.mode_valid,
352.25176 + 		     mode.fb_id, expected[0], expected[1]));
352.25177 + 
352.25178 +-		if (mode.fb_id != expected[0] && mode.fb_id != expected[1]) {
352.25179 +-			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
352.25180 +-				   "%s: invalid state found on pipe %d, disabling CRTC:%d\n",
352.25181 +-				   __FUNCTION__, sna_crtc->pipe, sna_crtc->id);
352.25182 +-			sna_crtc_disable(crtc);
352.25183 +-		}
352.25184 ++		if (mode.fb_id != expected[0] && mode.fb_id != expected[1])
352.25185 ++			disabled |= sna_mode_shutdown_crtc(crtc);
352.25186 + 	}
352.25187 + 
352.25188 +-	for (i = 0; i < config->num_output; i++) {
352.25189 +-		xf86OutputPtr output = config->output[i];
352.25190 ++	for (o = 0; o < config->num_output; o++) {
352.25191 ++		xf86OutputPtr output = config->output[o];
352.25192 + 		struct sna_output *sna_output;
352.25193 + 
352.25194 + 		if (output->crtc)
352.25195 +@@ -6515,26 +8369,16 @@ void sna_mode_check(struct sna *sna)
352.25196 + 	}
352.25197 + 
352.25198 + 	update_flush_interval(sna);
352.25199 ++
352.25200 ++	if (disabled)
352.25201 ++		xf86RandR12TellChanged(xf86ScrnToScreen(sna->scrn));
352.25202 + }
352.25203 + 
352.25204 + static bool
352.25205 + sna_crtc_hide_planes(struct sna *sna, struct sna_crtc *crtc)
352.25206 + {
352.25207 +-#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane)
352.25208 +-	struct local_mode_set_plane {
352.25209 +-		uint32_t plane_id;
352.25210 +-		uint32_t crtc_id;
352.25211 +-		uint32_t fb_id; /* fb object contains surface format type */
352.25212 +-		uint32_t flags;
352.25213 +-
352.25214 +-		/* Signed dest location allows it to be partially off screen */
352.25215 +-		int32_t crtc_x, crtc_y;
352.25216 +-		uint32_t crtc_w, crtc_h;
352.25217 +-
352.25218 +-		/* Source values are 16.16 fixed point */
352.25219 +-		uint32_t src_x, src_y;
352.25220 +-		uint32_t src_h, src_w;
352.25221 +-	} s;
352.25222 ++	struct local_mode_set_plane s;
352.25223 ++	struct plane *plane;
352.25224 + 
352.25225 + 	if (crtc->primary.id == 0)
352.25226 + 		return false;
352.25227 +@@ -6544,8 +8388,10 @@ sna_crtc_hide_planes(struct sna *sna, struct sna_crtc *crtc)
352.25228 + 	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
352.25229 + 		return false;
352.25230 + 
352.25231 +-	s.plane_id = crtc->sprite.id;
352.25232 +-	(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
352.25233 ++	list_for_each_entry(plane, &crtc->sprites, link) {
352.25234 ++		s.plane_id = plane->id;
352.25235 ++		(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
352.25236 ++	}
352.25237 + 
352.25238 + 	__sna_crtc_disable(sna, crtc);
352.25239 + 	return true;
352.25240 +@@ -6561,21 +8407,22 @@ void sna_mode_reset(struct sna *sna)
352.25241 + 
352.25242 + 	DBG(("%s\n", __FUNCTION__));
352.25243 + 
352.25244 +-	sna_hide_cursors(sna->scrn);
352.25245 ++	sna_disable_cursors(sna->scrn);
352.25246 + 	for (i = 0; i < sna->mode.num_real_crtc; i++)
352.25247 + 		if (!sna_crtc_hide_planes(sna, to_sna_crtc(config->crtc[i])))
352.25248 +-			sna_crtc_disable(config->crtc[i]);
352.25249 ++			sna_crtc_disable(config->crtc[i], true);
352.25250 + 	assert(sna->mode.front_active == 0);
352.25251 + 
352.25252 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.25253 + 		struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]);
352.25254 ++		struct plane *plane;
352.25255 + 
352.25256 + 		assert(sna_crtc != NULL);
352.25257 +-		sna_crtc->dpms_mode = -1;
352.25258 + 
352.25259 + 		/* Force the rotation property to be reset on next use */
352.25260 + 		rotation_reset(&sna_crtc->primary);
352.25261 +-		rotation_reset(&sna_crtc->sprite);
352.25262 ++		list_for_each_entry(plane, &sna_crtc->sprites, link)
352.25263 ++			rotation_reset(plane);
352.25264 + 	}
352.25265 + 
352.25266 + 	/* VT switching, likely to be fbcon so make the backlight usable */
352.25267 +@@ -6641,9 +8488,10 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25268 + {
352.25269 + 	int16_t sx, sy;
352.25270 + 	struct sna *sna = to_sna(crtc->scrn);
352.25271 +-	ScreenPtr screen = sna->scrn->pScreen;
352.25272 ++	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
352.25273 + 	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
352.25274 + 	PictFormatPtr format;
352.25275 ++	PictTransform T;
352.25276 + 	PicturePtr src, dst;
352.25277 + 	PixmapPtr pixmap;
352.25278 + 	int depth, error;
352.25279 +@@ -6664,6 +8512,14 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25280 + 	     __FUNCTION__, format->format, depth, draw->bitsPerPixel,
352.25281 + 	     bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
352.25282 + 
352.25283 ++	if (sx | sy)
352.25284 ++		RegionTranslate(region, sx, sy);
352.25285 ++	error = !sna_drawable_move_region_to_cpu(draw, region, MOVE_READ);
352.25286 ++	if (sx | sy)
352.25287 ++		RegionTranslate(region, -sx, -sy);
352.25288 ++	if (error)
352.25289 ++		return;
352.25290 ++
352.25291 + 	ptr = kgem_bo_map__gtt(&sna->kgem, bo);
352.25292 + 	if (ptr == NULL)
352.25293 + 		return;
352.25294 +@@ -6683,9 +8539,37 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25295 + 	if (!src)
352.25296 + 		goto free_pixmap;
352.25297 + 
352.25298 +-	error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);
352.25299 +-	if (error)
352.25300 +-		goto free_src;
352.25301 ++	pixman_transform_init_translate(&T, sx << 16, sy << 16);
352.25302 ++	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
352.25303 ++	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
352.25304 ++#define f2d(x) (((double)(x))/65536.)
352.25305 ++		DBG(("%s: transform=[[%f %f %f], [%f %f %f], [%f %f %f]] (raw [[%x %x %x], [%x %x %x], [%x %x %x]])\n",
352.25306 ++		     __FUNCTION__,
352.25307 ++		     f2d(T.matrix[0][0]),
352.25308 ++		     f2d(T.matrix[0][1]),
352.25309 ++		     f2d(T.matrix[0][2]),
352.25310 ++		     f2d(T.matrix[1][0]),
352.25311 ++		     f2d(T.matrix[1][1]),
352.25312 ++		     f2d(T.matrix[1][2]),
352.25313 ++		     f2d(T.matrix[2][0]),
352.25314 ++		     f2d(T.matrix[2][1]),
352.25315 ++		     f2d(T.matrix[2][2]),
352.25316 ++		     T.matrix[0][0],
352.25317 ++		     T.matrix[0][1],
352.25318 ++		     T.matrix[0][2],
352.25319 ++		     T.matrix[1][0],
352.25320 ++		     T.matrix[1][1],
352.25321 ++		     T.matrix[1][2],
352.25322 ++		     T.matrix[2][0],
352.25323 ++		     T.matrix[2][1],
352.25324 ++		     T.matrix[2][2]));
352.25325 ++#undef f2d
352.25326 ++
352.25327 ++		error = SetPictureTransform(src, &T);
352.25328 ++		if (error)
352.25329 ++			goto free_src;
352.25330 ++		sx = sy = 0;
352.25331 ++	}
352.25332 + 
352.25333 + 	if (crtc->filter && crtc->transform_in_use)
352.25334 + 		SetPicturePictFilter(src, crtc->filter,
352.25335 +@@ -6733,10 +8617,11 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25336 + {
352.25337 + 	int16_t sx, sy;
352.25338 + 	struct sna *sna = to_sna(crtc->scrn);
352.25339 +-	ScreenPtr screen = crtc->scrn->pScreen;
352.25340 ++	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
352.25341 + 	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
352.25342 + 	struct sna_composite_op tmp;
352.25343 + 	PictFormatPtr format;
352.25344 ++	PictTransform T;
352.25345 + 	PicturePtr src, dst;
352.25346 + 	PixmapPtr pixmap;
352.25347 + 	const BoxRec *b;
352.25348 +@@ -6777,9 +8662,14 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25349 + 	if (!src)
352.25350 + 		goto free_pixmap;
352.25351 + 
352.25352 +-	error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);
352.25353 +-	if (error)
352.25354 +-		goto free_src;
352.25355 ++	pixman_transform_init_translate(&T, sx << 16, sy << 16);
352.25356 ++	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
352.25357 ++	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
352.25358 ++		error = SetPictureTransform(src, &T);
352.25359 ++		if (error)
352.25360 ++			goto free_src;
352.25361 ++		sx = sy = 0;
352.25362 ++	}
352.25363 + 
352.25364 + 	if (crtc->filter && crtc->transform_in_use)
352.25365 + 		SetPicturePictFilter(src, crtc->filter,
352.25366 +@@ -6793,36 +8683,38 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
352.25367 + 	ValidatePicture(src);
352.25368 + 	ValidatePicture(dst);
352.25369 + 
352.25370 +-	if (!sna->render.composite(sna,
352.25371 +-				   PictOpSrc, src, NULL, dst,
352.25372 +-				   sx, sy,
352.25373 +-				   0, 0,
352.25374 +-				   0, 0,
352.25375 +-				   crtc->mode.HDisplay, crtc->mode.VDisplay,
352.25376 +-				   COMPOSITE_PARTIAL, memset(&tmp, 0, sizeof(tmp)))) {
352.25377 +-		DBG(("%s: unsupported operation!\n", __FUNCTION__));
352.25378 +-		sna_crtc_redisplay__fallback(crtc, region, bo);
352.25379 +-		goto free_dst;
352.25380 +-	}
352.25381 +-
352.25382 ++	/* Composite each box individually as if we are dealing with a rotation
352.25383 ++	 * on a large display, we may have to perform intermediate copies. We
352.25384 ++	 * can then minimise the overdraw by looking at individual boxes rather
352.25385 ++	 * than the bbox.
352.25386 ++	 */
352.25387 + 	n = region_num_rects(region);
352.25388 + 	b = region_rects(region);
352.25389 + 	do {
352.25390 +-		BoxRec box;
352.25391 +-
352.25392 +-		box = *b++;
352.25393 ++		BoxRec box = *b;
352.25394 + 		transformed_box(&box, crtc);
352.25395 + 
352.25396 + 		DBG(("%s: (%d, %d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
352.25397 + 		     __FUNCTION__,
352.25398 +-		     b[-1].x1, b[-1].y1, b[-1].x2-b[-1].x1, b[-1].y2-b[-1].y1,
352.25399 ++		     b->x1, b->y1, b->x2-b->x1, b->y2-b->y1,
352.25400 + 		     box.x1, box.y1, box.x2, box.y2));
352.25401 + 
352.25402 +-		tmp.box(sna, &tmp, &box);
352.25403 +-	} while (--n);
352.25404 +-	tmp.done(sna, &tmp);
352.25405 ++		if (!sna->render.composite(sna,
352.25406 ++					   PictOpSrc, src, NULL, dst,
352.25407 ++					   sx + box.x1, sy + box.y1,
352.25408 ++					   0, 0,
352.25409 ++					   box.x1, box.y1,
352.25410 ++					   box.x2 - box.x1, box.y2 - box.y1,
352.25411 ++					   0, memset(&tmp, 0, sizeof(tmp)))) {
352.25412 ++			DBG(("%s: unsupported operation!\n", __FUNCTION__));
352.25413 ++			sna_crtc_redisplay__fallback(crtc, region, bo);
352.25414 ++			break;
352.25415 ++		} else {
352.25416 ++			tmp.box(sna, &tmp, &box);
352.25417 ++			tmp.done(sna, &tmp);
352.25418 ++		}
352.25419 ++	} while (b++, --n);
352.25420 + 
352.25421 +-free_dst:
352.25422 + 	FreePicture(dst, None);
352.25423 + free_src:
352.25424 + 	FreePicture(src, None);
352.25425 +@@ -6839,7 +8731,7 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
352.25426 + 	struct sna_pixmap *priv = sna_pixmap((PixmapPtr)draw);
352.25427 + 
352.25428 + 	DBG(("%s: crtc %d [pipe=%d], damage (%d, %d), (%d, %d) x %d\n",
352.25429 +-	     __FUNCTION__, to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe,
352.25430 ++	     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc),
352.25431 + 	     region->extents.x1, region->extents.y1,
352.25432 + 	     region->extents.x2, region->extents.y2,
352.25433 + 	     region_num_rects(region)));
352.25434 +@@ -6898,7 +8790,10 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
352.25435 + static void shadow_flip_handler(struct drm_event_vblank *e,
352.25436 + 				void *data)
352.25437 + {
352.25438 +-	sna_mode_redisplay(data);
352.25439 ++	struct sna *sna = data;
352.25440 ++
352.25441 ++	if (!sna->mode.shadow_wait)
352.25442 ++		sna_mode_redisplay(sna);
352.25443 + }
352.25444 + 
352.25445 + void sna_shadow_set_crtc(struct sna *sna,
352.25446 +@@ -6908,18 +8803,23 @@ void sna_shadow_set_crtc(struct sna *sna,
352.25447 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.25448 + 	struct sna_pixmap *priv;
352.25449 + 
352.25450 ++	assert(sna_crtc);
352.25451 + 	DBG(("%s: setting shadow override for CRTC:%d to handle=%d\n",
352.25452 +-	     __FUNCTION__, sna_crtc->id, bo->handle));
352.25453 ++	     __FUNCTION__, __sna_crtc_id(sna_crtc), bo->handle));
352.25454 + 
352.25455 + 	assert(sna->flags & SNA_TEAR_FREE);
352.25456 +-	assert(sna_crtc);
352.25457 + 	assert(!sna_crtc->transform);
352.25458 + 
352.25459 + 	if (sna_crtc->client_bo != bo) {
352.25460 +-		if (sna_crtc->client_bo)
352.25461 ++		if (sna_crtc->client_bo) {
352.25462 ++			assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
352.25463 ++			sna_crtc->client_bo->active_scanout--;
352.25464 + 			kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
352.25465 ++		}
352.25466 + 
352.25467 + 		sna_crtc->client_bo = kgem_bo_reference(bo);
352.25468 ++		sna_crtc->client_bo->active_scanout++;
352.25469 ++		assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
352.25470 + 		sna_crtc_damage(crtc);
352.25471 + 	}
352.25472 + 
352.25473 +@@ -6969,11 +8869,13 @@ void sna_shadow_unset_crtc(struct sna *sna,
352.25474 + 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.25475 + 
352.25476 + 	DBG(("%s: clearin shadow override for CRTC:%d\n",
352.25477 +-	     __FUNCTION__, sna_crtc->id));
352.25478 ++	     __FUNCTION__, __sna_crtc_id(sna_crtc)));
352.25479 + 
352.25480 + 	if (sna_crtc->client_bo == NULL)
352.25481 + 		return;
352.25482 + 
352.25483 ++	assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
352.25484 ++	sna_crtc->client_bo->active_scanout--;
352.25485 + 	kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
352.25486 + 	sna_crtc->client_bo = NULL;
352.25487 + 	list_del(&sna_crtc->shadow_link);
352.25488 +@@ -6982,15 +8884,57 @@ void sna_shadow_unset_crtc(struct sna *sna,
352.25489 + 	sna_crtc_damage(crtc);
352.25490 + }
352.25491 + 
352.25492 ++static bool move_crtc_to_gpu(struct sna *sna)
352.25493 ++{
352.25494 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.25495 ++	int i;
352.25496 ++
352.25497 ++	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.25498 ++		struct sna_crtc *crtc = to_sna_crtc(config->crtc[i]);
352.25499 ++		unsigned hint;
352.25500 ++
352.25501 ++		assert(crtc);
352.25502 ++
352.25503 ++		if (crtc->bo == NULL)
352.25504 ++			continue;
352.25505 ++
352.25506 ++		if (crtc->slave_pixmap)
352.25507 ++			continue;
352.25508 ++
352.25509 ++		if (crtc->client_bo)
352.25510 ++			continue;
352.25511 ++
352.25512 ++		if (crtc->shadow_bo)
352.25513 ++			continue;
352.25514 ++
352.25515 ++		hint = MOVE_READ | MOVE_ASYNC_HINT | __MOVE_SCANOUT;
352.25516 ++		if (sna->flags & SNA_TEAR_FREE)
352.25517 ++			hint |= __MOVE_FORCE;
352.25518 ++
352.25519 ++		DBG(("%s: CRTC %d [pipe=%d] requires frontbuffer\n",
352.25520 ++		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc)));
352.25521 ++		return sna_pixmap_move_to_gpu(sna->front, hint);
352.25522 ++	}
352.25523 ++
352.25524 ++	return true;
352.25525 ++}
352.25526 ++
352.25527 + void sna_mode_redisplay(struct sna *sna)
352.25528 + {
352.25529 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.25530 + 	RegionPtr region;
352.25531 + 	int i;
352.25532 + 
352.25533 +-	if (!sna->mode.shadow_damage)
352.25534 ++	if (sna->mode.hidden) {
352.25535 ++		DBG(("%s: hidden outputs, skipping\n", __FUNCTION__));
352.25536 ++		return;
352.25537 ++	}
352.25538 ++
352.25539 ++	if (!sna->mode.shadow_enabled)
352.25540 + 		return;
352.25541 + 
352.25542 ++	assert(sna->mode.shadow_damage);
352.25543 ++
352.25544 + 	DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",
352.25545 + 	     __FUNCTION__,
352.25546 + 	     !RegionNil(DamageRegion(sna->mode.shadow_damage)),
352.25547 +@@ -7012,21 +8956,23 @@ void sna_mode_redisplay(struct sna *sna)
352.25548 + 	     region->extents.x2, region->extents.y2));
352.25549 + 
352.25550 + 	if (sna->mode.flip_active) {
352.25551 +-		DamagePtr damage;
352.25552 +-
352.25553 +-		damage = sna->mode.shadow_damage;
352.25554 +-		sna->mode.shadow_damage = NULL;
352.25555 ++		DBG(("%s: checking for %d outstanding flip completions\n",
352.25556 ++		     __FUNCTION__, sna->mode.flip_active));
352.25557 + 
352.25558 ++		sna->mode.dirty = true;
352.25559 + 		while (sna->mode.flip_active && sna_mode_wakeup(sna))
352.25560 + 			;
352.25561 ++		sna->mode.dirty = false;
352.25562 + 
352.25563 +-		sna->mode.shadow_damage = damage;
352.25564 ++		DBG(("%s: now %d outstanding flip completions (enabled? %d)\n",
352.25565 ++		     __FUNCTION__,
352.25566 ++		     sna->mode.flip_active,
352.25567 ++		     sna->mode.shadow_enabled));
352.25568 ++		if (sna->mode.flip_active || !sna->mode.shadow_enabled)
352.25569 ++			return;
352.25570 + 	}
352.25571 + 
352.25572 +-	if (sna->mode.flip_active)
352.25573 +-		return;
352.25574 +-
352.25575 +-	if (wedged(sna) || !sna_pixmap_move_to_gpu(sna->front, MOVE_READ | MOVE_ASYNC_HINT | __MOVE_SCANOUT)) {
352.25576 ++	if (!move_crtc_to_gpu(sna)) {
352.25577 + 		DBG(("%s: forcing scanout update using the CPU\n", __FUNCTION__));
352.25578 + 		if (!sna_pixmap_move_to_cpu(sna->front, MOVE_READ))
352.25579 + 			return;
352.25580 +@@ -7047,90 +8993,14 @@ void sna_mode_redisplay(struct sna *sna)
352.25581 + 			damage.data = NULL;
352.25582 + 			RegionIntersect(&damage, &damage, region);
352.25583 + 			if (!box_empty(&damage.extents)) {
352.25584 +-				struct kgem_bo *bo = NULL;
352.25585 +-
352.25586 + 				DBG(("%s: fallback intersects pipe=%d [(%d, %d), (%d, %d)]\n",
352.25587 +-				     __FUNCTION__, sna_crtc->pipe,
352.25588 ++				     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
352.25589 + 				     damage.extents.x1, damage.extents.y1,
352.25590 + 				     damage.extents.x2, damage.extents.y2));
352.25591 + 
352.25592 +-				if (sna->flags & SNA_TEAR_FREE) {
352.25593 +-					RegionRec new_damage;
352.25594 +-
352.25595 +-					RegionNull(&new_damage);
352.25596 +-					RegionCopy(&new_damage, &damage);
352.25597 +-
352.25598 +-					bo = sna_crtc->client_bo;
352.25599 +-					if (bo == NULL) {
352.25600 +-						damage.extents = crtc->bounds;
352.25601 +-						damage.data = NULL;
352.25602 +-						bo = kgem_create_2d(&sna->kgem,
352.25603 +-								crtc->mode.HDisplay,
352.25604 +-								crtc->mode.VDisplay,
352.25605 +-								crtc->scrn->bitsPerPixel,
352.25606 +-								sna_crtc->bo->tiling,
352.25607 +-								CREATE_SCANOUT);
352.25608 +-					} else
352.25609 +-						RegionUnion(&damage, &damage, &sna_crtc->client_damage);
352.25610 +-
352.25611 +-					DBG(("%s: TearFree fallback, shadow handle=%d, crtc handle=%d\n", __FUNCTION__, bo->handle, sna_crtc->bo->handle));
352.25612 +-
352.25613 +-					sna_crtc->client_damage = new_damage;
352.25614 +-				}
352.25615 +-
352.25616 +-				if (bo == NULL)
352.25617 +-					bo = sna_crtc->bo;
352.25618 +-				sna_crtc_redisplay__fallback(crtc, &damage, bo);
352.25619 +-
352.25620 +-				if (bo != sna_crtc->bo) {
352.25621 +-					struct drm_mode_crtc_page_flip arg;
352.25622 +-
352.25623 +-					arg.crtc_id = sna_crtc->id;
352.25624 +-					arg.fb_id = get_fb(sna, bo,
352.25625 +-							   crtc->mode.HDisplay,
352.25626 +-							   crtc->mode.VDisplay);
352.25627 +-
352.25628 +-					arg.user_data = (uintptr_t)sna_crtc;
352.25629 +-					arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
352.25630 +-					arg.reserved = 0;
352.25631 +-
352.25632 +-					if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
352.25633 +-						if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
352.25634 +-							assert(sna_crtc->bo->active_scanout);
352.25635 +-							assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
352.25636 +-							sna_crtc->bo->active_scanout--;
352.25637 +-							kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
352.25638 +-
352.25639 +-							sna_crtc->bo = bo;
352.25640 +-							sna_crtc->bo->active_scanout++;
352.25641 +-							sna_crtc->client_bo = NULL;
352.25642 +-						} else {
352.25643 +-							DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
352.25644 +-							     __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
352.25645 +-							xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.25646 +-								   "Page flipping failed, disabling TearFree\n");
352.25647 +-							sna->flags &= ~SNA_TEAR_FREE;
352.25648 +-
352.25649 +-							damage.extents = crtc->bounds;
352.25650 +-							damage.data = NULL;
352.25651 +-							sna_crtc_redisplay__fallback(crtc, &damage, sna_crtc->bo);
352.25652 +-
352.25653 +-							kgem_bo_destroy(&sna->kgem, bo);
352.25654 +-							sna_crtc->client_bo = NULL;
352.25655 +-						}
352.25656 +-					} else {
352.25657 +-						sna->mode.flip_active++;
352.25658 +-
352.25659 +-						assert(sna_crtc->flip_bo == NULL);
352.25660 +-						sna_crtc->flip_handler = shadow_flip_handler;
352.25661 +-						sna_crtc->flip_data = sna;
352.25662 +-						sna_crtc->flip_bo = bo;
352.25663 +-						sna_crtc->flip_bo->active_scanout++;
352.25664 +-						sna_crtc->flip_serial = sna_crtc->mode_serial;
352.25665 +-
352.25666 +-						sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
352.25667 +-					}
352.25668 +-				}
352.25669 ++				sna_crtc_redisplay__fallback(crtc,
352.25670 ++							     &damage,
352.25671 ++							     sna_crtc->bo);
352.25672 + 			}
352.25673 + 			RegionUninit(&damage);
352.25674 + 
352.25675 +@@ -7171,6 +9041,7 @@ void sna_mode_redisplay(struct sna *sna)
352.25676 + 		xf86CrtcPtr crtc = config->crtc[i];
352.25677 + 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
352.25678 + 		RegionRec damage;
352.25679 ++		int sigio;
352.25680 + 
352.25681 + 		assert(sna_crtc != NULL);
352.25682 + 		DBG(("%s: crtc[%d] transformed? %d\n",
352.25683 +@@ -7192,30 +9063,38 @@ void sna_mode_redisplay(struct sna *sna)
352.25684 + 		     region_num_rects(&damage),
352.25685 + 		     damage.extents.x1, damage.extents.y1,
352.25686 + 		     damage.extents.x2, damage.extents.y2));
352.25687 ++		sigio = sigio_block();
352.25688 + 		if (!box_empty(&damage.extents)) {
352.25689 + 			if (sna->flags & SNA_TEAR_FREE) {
352.25690 ++				RegionRec new_damage;
352.25691 + 				struct drm_mode_crtc_page_flip arg;
352.25692 + 				struct kgem_bo *bo;
352.25693 + 
352.25694 +-				RegionUninit(&damage);
352.25695 +-				damage.extents = crtc->bounds;
352.25696 +-				damage.data = NULL;
352.25697 ++				RegionNull(&new_damage);
352.25698 ++				RegionCopy(&new_damage, &damage);
352.25699 + 
352.25700 +-				bo = sna_crtc->client_bo;
352.25701 +-				if (bo == NULL)
352.25702 ++				bo = sna_crtc->cache_bo;
352.25703 ++				if (bo == NULL) {
352.25704 ++					damage.extents = crtc->bounds;
352.25705 ++					damage.data = NULL;
352.25706 + 					bo = kgem_create_2d(&sna->kgem,
352.25707 + 							    crtc->mode.HDisplay,
352.25708 + 							    crtc->mode.VDisplay,
352.25709 + 							    crtc->scrn->bitsPerPixel,
352.25710 + 							    sna_crtc->bo->tiling,
352.25711 + 							    CREATE_SCANOUT);
352.25712 +-				if (bo == NULL)
352.25713 +-					goto disable1;
352.25714 ++					if (bo == NULL)
352.25715 ++						continue;
352.25716 ++				} else
352.25717 ++					RegionUnion(&damage, &damage, &sna_crtc->crtc_damage);
352.25718 ++				sna_crtc->crtc_damage = new_damage;
352.25719 + 
352.25720 + 				sna_crtc_redisplay(crtc, &damage, bo);
352.25721 + 				kgem_bo_submit(&sna->kgem, bo);
352.25722 ++				__kgem_bo_clear_dirty(bo);
352.25723 + 
352.25724 +-				arg.crtc_id = sna_crtc->id;
352.25725 ++				assert_crtc_fb(sna, sna_crtc);
352.25726 ++				arg.crtc_id = __sna_crtc_id(sna_crtc);
352.25727 + 				arg.fb_id = get_fb(sna, bo,
352.25728 + 						   crtc->mode.HDisplay,
352.25729 + 						   crtc->mode.VDisplay);
352.25730 +@@ -7228,6 +9107,9 @@ void sna_mode_redisplay(struct sna *sna)
352.25731 + 
352.25732 + 				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
352.25733 + 					if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
352.25734 ++						DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
352.25735 ++						     __FUNCTION__, sna_crtc->bo->handle, sna_crtc->bo->active_scanout - 1,
352.25736 ++						     bo->handle, bo->active_scanout));
352.25737 + 						assert(sna_crtc->bo->active_scanout);
352.25738 + 						assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
352.25739 + 						sna_crtc->bo->active_scanout--;
352.25740 +@@ -7235,13 +9117,12 @@ void sna_mode_redisplay(struct sna *sna)
352.25741 + 
352.25742 + 						sna_crtc->bo = kgem_bo_reference(bo);
352.25743 + 						sna_crtc->bo->active_scanout++;
352.25744 +-						sna_crtc->client_bo = kgem_bo_reference(bo);
352.25745 + 					} else {
352.25746 + 						BoxRec box;
352.25747 + 						DrawableRec tmp;
352.25748 + 
352.25749 + 						DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
352.25750 +-						     __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
352.25751 ++						     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
352.25752 + 						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.25753 + 							   "Page flipping failed, disabling TearFree\n");
352.25754 + 						sna->flags &= ~SNA_TEAR_FREE;
352.25755 +@@ -7260,13 +9141,13 @@ disable1:
352.25756 + 									    &box, 1, COPY_LAST)) {
352.25757 + 							xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
352.25758 + 								   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
352.25759 +-								   __FUNCTION__, sna_crtc->id, sna_crtc->pipe);
352.25760 +-							sna_crtc_disable(crtc);
352.25761 ++								   __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc));
352.25762 ++							sna_crtc_disable(crtc, false);
352.25763 + 						}
352.25764 +-
352.25765 +-						kgem_bo_destroy(&sna->kgem, bo);
352.25766 +-						sna_crtc->client_bo = NULL;
352.25767 + 					}
352.25768 ++
352.25769 ++					kgem_bo_destroy(&sna->kgem, bo);
352.25770 ++					sna_crtc->cache_bo = NULL;
352.25771 + 					continue;
352.25772 + 				}
352.25773 + 				sna->mode.flip_active++;
352.25774 +@@ -7279,13 +9160,20 @@ disable1:
352.25775 + 				sna_crtc->flip_serial = sna_crtc->mode_serial;
352.25776 + 				sna_crtc->flip_pending = true;
352.25777 + 
352.25778 +-				sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
352.25779 ++				if (sna_crtc->bo != sna->mode.shadow) {
352.25780 ++					assert_scanout(&sna->kgem, sna_crtc->bo,
352.25781 ++						       crtc->mode.HDisplay, crtc->mode.VDisplay);
352.25782 ++					sna_crtc->cache_bo = kgem_bo_reference(sna_crtc->bo);
352.25783 ++				}
352.25784 ++				DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
352.25785 ++				     __FUNCTION__, __sna_crtc_id(sna_crtc), sna_crtc->flip_bo->handle, sna_crtc->flip_bo->active_scanout, sna_crtc->flip_serial));
352.25786 + 			} else {
352.25787 + 				sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
352.25788 + 				kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
352.25789 + 			}
352.25790 + 		}
352.25791 + 		RegionUninit(&damage);
352.25792 ++		sigio_unblock(sigio);
352.25793 + 
352.25794 + 		if (sna_crtc->slave_damage)
352.25795 + 			DamageEmpty(sna_crtc->slave_damage);
352.25796 +@@ -7296,6 +9184,7 @@ disable1:
352.25797 + 		struct kgem_bo *old = sna->mode.shadow;
352.25798 + 		struct drm_mode_crtc_page_flip arg;
352.25799 + 		uint32_t fb = 0;
352.25800 ++		int sigio;
352.25801 + 
352.25802 + 		DBG(("%s: flipping TearFree outputs, current scanout handle=%d [active?=%d], new handle=%d [active=%d]\n",
352.25803 + 		     __FUNCTION__, old->handle, old->active_scanout, new->handle, new->active_scanout));
352.25804 +@@ -7307,7 +9196,9 @@ disable1:
352.25805 + 		arg.reserved = 0;
352.25806 + 
352.25807 + 		kgem_bo_submit(&sna->kgem, new);
352.25808 ++		__kgem_bo_clear_dirty(new);
352.25809 + 
352.25810 ++		sigio = sigio_block();
352.25811 + 		for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.25812 + 			struct sna_crtc *crtc = config->crtc[i]->driver_private;
352.25813 + 			struct kgem_bo *flip_bo;
352.25814 +@@ -7315,20 +9206,20 @@ disable1:
352.25815 + 
352.25816 + 			assert(crtc != NULL);
352.25817 + 			DBG(("%s: crtc %d [%d, pipe=%d] active? %d, transformed? %d\n",
352.25818 +-			     __FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo ? crtc->bo->handle : 0, crtc->transform));
352.25819 ++			     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo ? crtc->bo->handle : 0, crtc->transform));
352.25820 + 			if (crtc->bo == NULL || crtc->transform)
352.25821 + 				continue;
352.25822 + 
352.25823 + 			assert(config->crtc[i]->enabled);
352.25824 +-			assert(crtc->dpms_mode <= DPMSModeOn);
352.25825 + 			assert(crtc->flip_bo == NULL);
352.25826 ++			assert_crtc_fb(sna, crtc);
352.25827 + 
352.25828 +-			arg.crtc_id = crtc->id;
352.25829 ++			arg.crtc_id = __sna_crtc_id(crtc);
352.25830 + 			arg.user_data = (uintptr_t)crtc;
352.25831 + 
352.25832 + 			if (crtc->client_bo) {
352.25833 + 				DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
352.25834 +-				     __FUNCTION__, crtc->id, crtc->pipe, crtc->client_bo->handle));
352.25835 ++				     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->client_bo->handle));
352.25836 + 				arg.fb_id = get_fb(sna, crtc->client_bo,
352.25837 + 						   crtc->base->mode.HDisplay,
352.25838 + 						   crtc->base->mode.VDisplay);
352.25839 +@@ -7356,6 +9247,7 @@ fixup_shadow:
352.25840 + 						}
352.25841 + 					}
352.25842 + 
352.25843 ++					sigio_unblock(sigio);
352.25844 + 					return;
352.25845 + 				}
352.25846 + 
352.25847 +@@ -7365,8 +9257,12 @@ fixup_shadow:
352.25848 + 				y = crtc->base->y;
352.25849 + 			}
352.25850 + 
352.25851 +-			if (crtc->bo == flip_bo)
352.25852 ++			if (crtc->bo == flip_bo) {
352.25853 ++				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
352.25854 ++				DBG(("%s: flip handle=%d is already on the CRTC\n",
352.25855 ++				     __FUNCTION__, flip_bo->handle));
352.25856 + 				continue;
352.25857 ++			}
352.25858 + 
352.25859 + 			if (flip_bo->pitch != crtc->bo->pitch || (y << 16 | x)  != crtc->offset) {
352.25860 + 				DBG(("%s: changing pitch (new %d =?= old %d) or offset (new %x =?= old %x)\n",
352.25861 +@@ -7375,6 +9271,9 @@ fixup_shadow:
352.25862 + 				     y << 16 | x, crtc->offset));
352.25863 + fixup_flip:
352.25864 + 				if (sna_crtc_flip(sna, crtc, flip_bo, x, y)) {
352.25865 ++					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
352.25866 ++					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout-1,
352.25867 ++					     flip_bo->handle, flip_bo->active_scanout));
352.25868 + 					assert(flip_bo != crtc->bo);
352.25869 + 					assert(crtc->bo->active_scanout);
352.25870 + 					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
352.25871 +@@ -7389,9 +9288,11 @@ fixup_flip:
352.25872 + 					crtc->bo = kgem_bo_reference(flip_bo);
352.25873 + 					crtc->bo->active_scanout++;
352.25874 + 				} else {
352.25875 +-					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.25876 +-						   "Failed to prepare CRTC for page flipping, disabling TearFree\n");
352.25877 +-					sna->flags &= ~SNA_TEAR_FREE;
352.25878 ++					if (sna->flags & SNA_TEAR_FREE) {
352.25879 ++						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.25880 ++								"Failed to prepare CRTC for page flipping, disabling TearFree\n");
352.25881 ++						sna->flags &= ~SNA_TEAR_FREE;
352.25882 ++					}
352.25883 + 
352.25884 + 					if (sna->mode.flip_active == 0) {
352.25885 + 						DBG(("%s: abandoning flip attempt\n", __FUNCTION__));
352.25886 +@@ -7400,15 +9301,15 @@ fixup_flip:
352.25887 + 
352.25888 + 					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
352.25889 + 						   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
352.25890 +-						   __FUNCTION__, crtc->id, crtc->pipe);
352.25891 +-					sna_crtc_disable(crtc->base);
352.25892 ++						   __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc));
352.25893 ++					sna_crtc_disable(crtc->base, false);
352.25894 + 				}
352.25895 + 				continue;
352.25896 + 			}
352.25897 + 
352.25898 + 			if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
352.25899 + 				ERR(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
352.25900 +-				     __FUNCTION__, arg.fb_id, i, crtc->id, crtc->pipe, errno));
352.25901 ++				     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), errno));
352.25902 + 				goto fixup_flip;
352.25903 + 			}
352.25904 + 			sna->mode.flip_active++;
352.25905 +@@ -7421,6 +9322,9 @@ fixup_flip:
352.25906 + 			crtc->flip_serial = crtc->mode_serial;
352.25907 + 			crtc->flip_pending = true;
352.25908 + 
352.25909 ++			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
352.25910 ++			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
352.25911 ++
352.25912 + 			{
352.25913 + 				struct drm_i915_gem_busy busy = { flip_bo->handle };
352.25914 + 				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy) == 0) {
352.25915 +@@ -7435,6 +9339,7 @@ fixup_flip:
352.25916 + 				}
352.25917 + 			}
352.25918 + 		}
352.25919 ++		sigio_unblock(sigio);
352.25920 + 
352.25921 + 		DBG(("%s: flipped %d outputs, shadow active? %d\n",
352.25922 + 		     __FUNCTION__,
352.25923 +@@ -7486,7 +9391,9 @@ again:
352.25924 + 		struct drm_event *e = (struct drm_event *)&buffer[i];
352.25925 + 		switch (e->type) {
352.25926 + 		case DRM_EVENT_VBLANK:
352.25927 +-			if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
352.25928 ++			if (sna->mode.shadow_wait)
352.25929 ++				defer_event(sna, e);
352.25930 ++			else if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
352.25931 + 				sna_present_vblank_handler((struct drm_event_vblank *)e);
352.25932 + 			else
352.25933 + 				sna_dri2_vblank_handler((struct drm_event_vblank *)e);
352.25934 +@@ -7495,13 +9402,19 @@ again:
352.25935 + 			{
352.25936 + 				struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
352.25937 + 				struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
352.25938 ++				uint64_t msc;
352.25939 + 
352.25940 + 				/* Beware Zaphod! */
352.25941 + 				sna = to_sna(crtc->base->scrn);
352.25942 + 
352.25943 +-				crtc->swap.tv_sec = vbl->tv_sec;
352.25944 +-				crtc->swap.tv_usec = vbl->tv_usec;
352.25945 +-				crtc->swap.msc = msc64(crtc, vbl->sequence);
352.25946 ++				if (msc64(crtc, vbl->sequence, &msc)) {
352.25947 ++					DBG(("%s: recording last swap on pipe=%d, frame %d [%08llx], time %d.%06d\n",
352.25948 ++					     __FUNCTION__, __sna_crtc_pipe(crtc), vbl->sequence, (long long)msc, vbl->tv_sec, vbl->tv_usec));
352.25949 ++					crtc->swap.tv_sec = vbl->tv_sec;
352.25950 ++					crtc->swap.tv_usec = vbl->tv_usec;
352.25951 ++					crtc->swap.msc = msc;
352.25952 ++				}
352.25953 ++				assert(crtc->flip_pending);
352.25954 + 				crtc->flip_pending = false;
352.25955 + 
352.25956 + 				assert(crtc->flip_bo);
352.25957 +@@ -7509,10 +9422,12 @@ again:
352.25958 + 				assert(crtc->flip_bo->refcnt >= crtc->flip_bo->active_scanout);
352.25959 + 
352.25960 + 				if (crtc->flip_serial == crtc->mode_serial) {
352.25961 +-					DBG(("%s: removing handle=%d from scanout, installing handle=%d\n",
352.25962 +-					     __FUNCTION__, crtc->bo->handle, crtc->flip_bo->handle));
352.25963 ++					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
352.25964 ++					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout - 1,
352.25965 ++					     crtc->flip_bo->handle, crtc->flip_bo->active_scanout));
352.25966 + 					assert(crtc->bo->active_scanout);
352.25967 + 					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
352.25968 ++
352.25969 + 					crtc->bo->active_scanout--;
352.25970 + 					kgem_bo_destroy(&sna->kgem, crtc->bo);
352.25971 + 
352.25972 +@@ -7523,6 +9438,8 @@ again:
352.25973 + 
352.25974 + 					crtc->bo = crtc->flip_bo;
352.25975 + 					crtc->flip_bo = NULL;
352.25976 ++
352.25977 ++					assert_crtc_fb(sna, crtc);
352.25978 + 				} else {
352.25979 + 					crtc->flip_bo->active_scanout--;
352.25980 + 					kgem_bo_destroy(&sna->kgem, crtc->flip_bo);
352.25981 +@@ -7531,8 +9448,10 @@ again:
352.25982 + 
352.25983 + 				DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna->mode.flip_active));
352.25984 + 				assert(sna->mode.flip_active);
352.25985 +-				if (--sna->mode.flip_active == 0)
352.25986 ++				if (--sna->mode.flip_active == 0) {
352.25987 ++					assert(crtc->flip_handler);
352.25988 + 					crtc->flip_handler(vbl, crtc->flip_data);
352.25989 ++				}
352.25990 + 			}
352.25991 + 			break;
352.25992 + 		default:
352.25993 +diff --git a/src/sna/sna_display_fake.c b/src/sna/sna_display_fake.c
352.25994 +index 4d74c38d..fa26bda1 100644
352.25995 +--- a/src/sna/sna_display_fake.c
352.25996 ++++ b/src/sna/sna_display_fake.c
352.25997 +@@ -96,12 +96,6 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
352.25998 + }
352.25999 + 
352.26000 + static void
352.26001 +-sna_crtc_gamma_set(xf86CrtcPtr crtc,
352.26002 +-		       CARD16 *red, CARD16 *green, CARD16 *blue, int size)
352.26003 +-{
352.26004 +-}
352.26005 +-
352.26006 +-static void
352.26007 + sna_crtc_destroy(xf86CrtcPtr crtc)
352.26008 + {
352.26009 + }
352.26010 +@@ -109,7 +103,6 @@ sna_crtc_destroy(xf86CrtcPtr crtc)
352.26011 + static const xf86CrtcFuncsRec sna_crtc_funcs = {
352.26012 + 	.dpms = sna_crtc_dpms,
352.26013 + 	.set_mode_major = sna_crtc_set_mode_major,
352.26014 +-	.gamma_set = sna_crtc_gamma_set,
352.26015 + 	.destroy = sna_crtc_destroy,
352.26016 + };
352.26017 + 
352.26018 +@@ -192,7 +185,7 @@ static const xf86OutputFuncsRec sna_output_funcs = {
352.26019 + static Bool
352.26020 + sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
352.26021 + {
352.26022 +-	ScreenPtr screen = scrn->pScreen;
352.26023 ++	ScreenPtr screen = xf86ScrnToScreen(scrn);
352.26024 + 	PixmapPtr new_front;
352.26025 + 
352.26026 + 	DBG(("%s (%d, %d) -> (%d, %d)\n", __FUNCTION__,
352.26027 +@@ -262,6 +255,7 @@ static bool add_fake_output(struct sna *sna, bool late)
352.26028 + 	output->mm_height = 0;
352.26029 + 	output->interlaceAllowed = FALSE;
352.26030 + 	output->subpixel_order = SubPixelNone;
352.26031 ++	output->status = XF86OutputStatusDisconnected;
352.26032 + 
352.26033 + 	output->possible_crtcs = ~((1 << sna->mode.num_real_crtc) - 1);
352.26034 + 	output->possible_clones = ~((1 << sna->mode.num_real_output) - 1);
352.26035 +@@ -297,6 +291,8 @@ static bool add_fake_output(struct sna *sna, bool late)
352.26036 + 
352.26037 + 		RRCrtcSetRotations(crtc->randr_crtc,
352.26038 + 				   RR_Rotate_All | RR_Reflect_All);
352.26039 ++		if (!RRCrtcGammaSetSize(crtc->randr_crtc, 256))
352.26040 ++			goto err;
352.26041 + 	}
352.26042 + 
352.26043 + 	sna->mode.num_fake++;
352.26044 +@@ -312,13 +308,16 @@ err:
352.26045 + 			continue;
352.26046 + 
352.26047 + 		xf86OutputDestroy(output);
352.26048 ++		i--;
352.26049 + 	}
352.26050 + 
352.26051 + 	for (i = 0; i < xf86_config->num_crtc; i++) {
352.26052 + 		crtc = xf86_config->crtc[i];
352.26053 + 		if (crtc->driver_private)
352.26054 + 			continue;
352.26055 ++
352.26056 + 		xf86CrtcDestroy(crtc);
352.26057 ++		i--;
352.26058 + 	}
352.26059 + 	sna->mode.num_fake = -1;
352.26060 + 	return false;
352.26061 +diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
352.26062 +index e5c4d53e..d89525cc 100644
352.26063 +--- a/src/sna/sna_dri2.c
352.26064 ++++ b/src/sna/sna_dri2.c
352.26065 +@@ -82,12 +82,23 @@ get_private(void *buffer)
352.26066 + 	return (struct sna_dri2_private *)((DRI2Buffer2Ptr)buffer+1);
352.26067 + }
352.26068 + 
352.26069 ++pure static inline DRI2BufferPtr sna_pixmap_get_buffer(PixmapPtr pixmap)
352.26070 ++{
352.26071 ++	assert(pixmap->refcnt);
352.26072 ++	return ((void **)__get_private(pixmap, sna_pixmap_key))[2];
352.26073 ++}
352.26074 ++
352.26075 ++static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr)
352.26076 ++{
352.26077 ++	assert(pixmap->refcnt);
352.26078 ++	((void **)__get_private(pixmap, sna_pixmap_key))[2] = ptr;
352.26079 ++}
352.26080 ++
352.26081 + #if DRI2INFOREC_VERSION >= 4
352.26082 + enum event_type {
352.26083 + 	WAITMSC = 0,
352.26084 + 	SWAP,
352.26085 +-	SWAP_WAIT,
352.26086 +-	SWAP_THROTTLE,
352.26087 ++	SWAP_COMPLETE,
352.26088 + 	FLIP,
352.26089 + 	FLIP_THROTTLE,
352.26090 + 	FLIP_COMPLETE,
352.26091 +@@ -98,6 +109,7 @@ struct dri_bo {
352.26092 + 	struct list link;
352.26093 + 	struct kgem_bo *bo;
352.26094 + 	uint32_t name;
352.26095 ++	unsigned flags;
352.26096 + };
352.26097 + 
352.26098 + struct sna_dri2_event {
352.26099 +@@ -108,6 +120,8 @@ struct sna_dri2_event {
352.26100 + 	xf86CrtcPtr crtc;
352.26101 + 	int pipe;
352.26102 + 	bool queued;
352.26103 ++	bool sync;
352.26104 ++	bool chained;
352.26105 + 
352.26106 + 	/* for swaps & flips only */
352.26107 + 	DRI2SwapEventPtr event_complete;
352.26108 +@@ -116,35 +130,146 @@ struct sna_dri2_event {
352.26109 + 	DRI2BufferPtr back;
352.26110 + 	struct kgem_bo *bo;
352.26111 + 
352.26112 ++	struct copy {
352.26113 ++		struct kgem_bo *bo;
352.26114 ++		unsigned flags;
352.26115 ++		uint32_t name;
352.26116 ++		uint32_t size;
352.26117 ++	} pending;
352.26118 ++
352.26119 + 	struct sna_dri2_event *chain;
352.26120 + 
352.26121 +-	struct list cache;
352.26122 + 	struct list link;
352.26123 + 
352.26124 +-	int mode;
352.26125 ++	int flip_continue;
352.26126 ++	int keepalive;
352.26127 ++	int signal;
352.26128 + };
352.26129 + 
352.26130 ++#if DRI2INFOREC_VERSION < 10
352.26131 ++#undef USE_ASYNC_SWAP
352.26132 ++#endif
352.26133 ++
352.26134 ++#if USE_ASYNC_SWAP
352.26135 ++#define KEEPALIVE 8 /* wait ~100ms before discarding swap caches */
352.26136 ++#define APPLY_DAMAGE 0
352.26137 ++#else
352.26138 ++#define USE_ASYNC_SWAP 0
352.26139 ++#define KEEPALIVE 1
352.26140 ++#define APPLY_DAMAGE 1
352.26141 ++#endif
352.26142 ++
352.26143 + static void sna_dri2_flip_event(struct sna_dri2_event *flip);
352.26144 ++inline static DRI2BufferPtr dri2_window_get_front(WindowPtr win);
352.26145 ++
352.26146 ++static struct kgem_bo *
352.26147 ++__sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.26148 ++		      DRI2BufferPtr src, DRI2BufferPtr dst,
352.26149 ++		      unsigned flags);
352.26150 ++
352.26151 ++inline static void
352.26152 ++__sna_dri2_copy_event(struct sna_dri2_event *info, unsigned flags)
352.26153 ++{
352.26154 ++	DBG(("%s: flags = %x\n", __FUNCTION__, flags));
352.26155 ++	assert(info->front != info->back);
352.26156 ++	info->bo = __sna_dri2_copy_region(info->sna, info->draw, NULL,
352.26157 ++					  info->back, info->front,
352.26158 ++					  flags);
352.26159 ++	info->front->flags = info->back->flags;
352.26160 ++}
352.26161 ++
352.26162 ++static int front_pitch(DrawablePtr draw)
352.26163 ++{
352.26164 ++	DRI2BufferPtr buffer;
352.26165 ++
352.26166 ++	buffer = NULL;
352.26167 ++	if (draw->type != DRAWABLE_PIXMAP)
352.26168 ++		buffer = dri2_window_get_front((WindowPtr)draw);
352.26169 ++	if (buffer == NULL)
352.26170 ++		buffer = sna_pixmap_get_buffer(get_drawable_pixmap(draw));
352.26171 ++
352.26172 ++	return buffer ? buffer->pitch : 0;
352.26173 ++}
352.26174 ++
352.26175 ++struct dri2_window {
352.26176 ++	DRI2BufferPtr front;
352.26177 ++	struct sna_dri2_event *chain;
352.26178 ++	xf86CrtcPtr crtc;
352.26179 ++	int64_t msc_delta;
352.26180 ++	struct list cache;
352.26181 ++	uint32_t cache_size;
352.26182 ++	int scanout;
352.26183 ++};
352.26184 ++
352.26185 ++static struct dri2_window *dri2_window(WindowPtr win)
352.26186 ++{
352.26187 ++	assert(win->drawable.type != DRAWABLE_PIXMAP);
352.26188 ++	return ((void **)__get_private(win, sna_window_key))[1];
352.26189 ++}
352.26190 ++
352.26191 ++static bool use_scanout(struct sna *sna,
352.26192 ++			DrawablePtr draw,
352.26193 ++			struct dri2_window *priv)
352.26194 ++{
352.26195 ++	if (priv->front)
352.26196 ++		return true;
352.26197 ++
352.26198 ++	if (priv->scanout < 0)
352.26199 ++		priv->scanout =
352.26200 ++			(sna->flags & (SNA_LINEAR_FB | SNA_NO_WAIT | SNA_NO_FLIP)) == 0 &&
352.26201 ++			draw->width  == sna->front->drawable.width &&
352.26202 ++			draw->height == sna->front->drawable.height &&
352.26203 ++			draw->bitsPerPixel == sna->front->drawable.bitsPerPixel;
352.26204 ++
352.26205 ++	return priv->scanout;
352.26206 ++}
352.26207 + 
352.26208 + static void
352.26209 + sna_dri2_get_back(struct sna *sna,
352.26210 + 		  DrawablePtr draw,
352.26211 +-		  DRI2BufferPtr back,
352.26212 +-		  struct sna_dri2_event *info)
352.26213 ++		  DRI2BufferPtr back)
352.26214 + {
352.26215 ++	struct dri2_window *priv = dri2_window((WindowPtr)draw);
352.26216 ++	uint32_t size;
352.26217 + 	struct kgem_bo *bo;
352.26218 ++	struct dri_bo *c;
352.26219 + 	uint32_t name;
352.26220 ++	int flags;
352.26221 + 	bool reuse;
352.26222 + 
352.26223 +-	DBG(("%s: draw size=%dx%d, buffer size=%dx%d\n",
352.26224 ++	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, active?=%d, pitch=%d, front pitch=%d\n",
352.26225 + 	     __FUNCTION__, draw->width, draw->height,
352.26226 +-	     get_private(back)->size & 0xffff, get_private(back)->size >> 16));
352.26227 +-	reuse = (draw->height << 16 | draw->width) == get_private(back)->size;
352.26228 ++	     get_private(back)->bo->handle,
352.26229 ++	     get_private(back)->size & 0xffff, get_private(back)->size >> 16,
352.26230 ++	     get_private(back)->bo->scanout,
352.26231 ++	     get_private(back)->bo->active_scanout,
352.26232 ++	     back->pitch, front_pitch(draw)));
352.26233 ++	assert(priv);
352.26234 ++
352.26235 ++	size = draw->height << 16 | draw->width;
352.26236 ++	if (size != priv->cache_size) {
352.26237 ++		while (!list_is_empty(&priv->cache)) {
352.26238 ++			c = list_first_entry(&priv->cache, struct dri_bo, link);
352.26239 ++			list_del(&c->link);
352.26240 ++
352.26241 ++			DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
352.26242 ++			assert(c->bo);
352.26243 ++			kgem_bo_destroy(&sna->kgem, c->bo);
352.26244 ++
352.26245 ++			free(c);
352.26246 ++		}
352.26247 ++		priv->cache_size = size;
352.26248 ++	}
352.26249 ++
352.26250 ++	reuse = size == get_private(back)->size;
352.26251 ++	if (reuse)
352.26252 ++		reuse = get_private(back)->bo->scanout == use_scanout(sna, draw, priv);
352.26253 ++	DBG(("%s: reuse backbuffer? %d\n", __FUNCTION__, reuse));
352.26254 + 	if (reuse) {
352.26255 + 		bo = get_private(back)->bo;
352.26256 + 		assert(bo->refcnt);
352.26257 +-		DBG(("%s: back buffer handle=%d, scanout?=%d, refcnt=%d\n",
352.26258 +-					__FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
352.26259 ++		DBG(("%s: back buffer handle=%d, active?=%d, refcnt=%d\n",
352.26260 ++		     __FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
352.26261 + 		if (bo->active_scanout == 0) {
352.26262 + 			DBG(("%s: reuse unattached back\n", __FUNCTION__));
352.26263 + 			get_private(back)->stale = false;
352.26264 +@@ -153,24 +278,37 @@ sna_dri2_get_back(struct sna *sna,
352.26265 + 	}
352.26266 + 
352.26267 + 	bo = NULL;
352.26268 +-	if (info) {
352.26269 +-		struct dri_bo *c;
352.26270 +-		list_for_each_entry(c, &info->cache, link) {
352.26271 +-			if (c->bo && c->bo->scanout == 0) {
352.26272 +-				bo = c->bo;
352.26273 +-				name = c->name;
352.26274 +-				DBG(("%s: reuse cache handle=%d\n", __FUNCTION__, bo->handle));
352.26275 +-				list_move_tail(&c->link, &info->cache);
352.26276 +-				c->bo = NULL;
352.26277 ++	list_for_each_entry(c, &priv->cache, link) {
352.26278 ++		DBG(("%s: cache: handle=%d, active=%d\n",
352.26279 ++		     __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
352.26280 ++		assert(c->bo);
352.26281 ++		if (c->bo->active_scanout == 0) {
352.26282 ++			_list_del(&c->link);
352.26283 ++			if (c->bo == NULL) {
352.26284 ++				free(c);
352.26285 ++				goto out;
352.26286 + 			}
352.26287 ++			bo = c->bo;
352.26288 ++			name = c->name;
352.26289 ++			flags = c->flags;
352.26290 ++			DBG(("%s: reuse cache handle=%d, name=%d, flags=%d\n", __FUNCTION__, bo->handle, name, flags));
352.26291 ++			c->bo = NULL;
352.26292 ++			break;
352.26293 + 		}
352.26294 + 	}
352.26295 + 	if (bo == NULL) {
352.26296 + 		DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
352.26297 ++		flags = CREATE_EXACT;
352.26298 ++
352.26299 ++		if (use_scanout(sna, draw, priv)) {
352.26300 ++			DBG(("%s: requesting scanout compatible back\n", __FUNCTION__));
352.26301 ++			flags |= CREATE_SCANOUT;
352.26302 ++		}
352.26303 ++
352.26304 + 		bo = kgem_create_2d(&sna->kgem,
352.26305 + 				    draw->width, draw->height, draw->bitsPerPixel,
352.26306 + 				    get_private(back)->bo->tiling,
352.26307 +-				    get_private(back)->bo->scanout ? CREATE_SCANOUT : 0);
352.26308 ++				    flags);
352.26309 + 		if (bo == NULL)
352.26310 + 			return;
352.26311 + 
352.26312 +@@ -179,30 +317,42 @@ sna_dri2_get_back(struct sna *sna,
352.26313 + 			kgem_bo_destroy(&sna->kgem, bo);
352.26314 + 			return;
352.26315 + 		}
352.26316 ++
352.26317 ++		flags = 0;
352.26318 ++		if (USE_ASYNC_SWAP && back->flags) {
352.26319 ++			BoxRec box;
352.26320 ++
352.26321 ++			box.x1 = 0;
352.26322 ++			box.y1 = 0;
352.26323 ++			box.x2 = draw->width;
352.26324 ++			box.y2 = draw->height;
352.26325 ++
352.26326 ++			DBG(("%s: filling new buffer with old back\n", __FUNCTION__));
352.26327 ++			if (sna->render.copy_boxes(sna, GXcopy,
352.26328 ++						   draw, get_private(back)->bo, 0, 0,
352.26329 ++						   draw, bo, 0, 0,
352.26330 ++						   &box, 1, COPY_LAST | COPY_DRI))
352.26331 ++				flags = back->flags;
352.26332 ++		}
352.26333 + 	}
352.26334 + 	assert(bo->active_scanout == 0);
352.26335 + 
352.26336 +-	if (info && reuse) {
352.26337 +-		bool found = false;
352.26338 +-		struct dri_bo *c;
352.26339 +-
352.26340 +-		list_for_each_entry_reverse(c, &info->cache, link) {
352.26341 +-			if (c->bo == NULL) {
352.26342 +-				found = true;
352.26343 +-				_list_del(&c->link);
352.26344 +-				break;
352.26345 +-			}
352.26346 +-		}
352.26347 +-		if (!found)
352.26348 ++	if (reuse && get_private(back)->bo->refcnt == 1 + get_private(back)->bo->active_scanout) {
352.26349 ++		if (&c->link == &priv->cache)
352.26350 + 			c = malloc(sizeof(*c));
352.26351 + 		if (c != NULL) {
352.26352 + 			c->bo = ref(get_private(back)->bo);
352.26353 + 			c->name = back->name;
352.26354 +-			list_add(&c->link, &info->cache);
352.26355 +-			DBG(("%s: cacheing handle=%d (name=%d)\n", __FUNCTION__, c->bo->handle, c->name));
352.26356 ++			c->flags = back->flags;
352.26357 ++			list_add(&c->link, &priv->cache);
352.26358 ++			DBG(("%s: caching handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, c->bo->handle, c->name, c->flags, c->bo->active_scanout));
352.26359 + 		}
352.26360 ++	} else {
352.26361 ++		if (&c->link != &priv->cache)
352.26362 ++			free(c);
352.26363 + 	}
352.26364 + 
352.26365 ++	assert(bo->active_scanout == 0);
352.26366 + 	assert(bo != get_private(back)->bo);
352.26367 + 	kgem_bo_destroy(&sna->kgem, get_private(back)->bo);
352.26368 + 
352.26369 +@@ -210,21 +360,13 @@ sna_dri2_get_back(struct sna *sna,
352.26370 + 	get_private(back)->size = draw->height << 16 | draw->width;
352.26371 + 	back->pitch = bo->pitch;
352.26372 + 	back->name = name;
352.26373 ++	back->flags = flags;
352.26374 + 
352.26375 +-	get_private(back)->stale = false;
352.26376 +-}
352.26377 +-
352.26378 +-struct dri2_window {
352.26379 +-	DRI2BufferPtr front;
352.26380 +-	struct sna_dri2_event *chain;
352.26381 +-	xf86CrtcPtr crtc;
352.26382 +-	int64_t msc_delta;
352.26383 +-};
352.26384 ++	assert(back->pitch);
352.26385 ++	assert(back->name);
352.26386 + 
352.26387 +-static struct dri2_window *dri2_window(WindowPtr win)
352.26388 +-{
352.26389 +-	assert(win->drawable.type != DRAWABLE_PIXMAP);
352.26390 +-	return ((void **)__get_private(win, sna_window_key))[1];
352.26391 ++out:
352.26392 ++	get_private(back)->stale = false;
352.26393 + }
352.26394 + 
352.26395 + static struct sna_dri2_event *
352.26396 +@@ -232,21 +374,25 @@ dri2_chain(DrawablePtr d)
352.26397 + {
352.26398 + 	struct dri2_window *priv = dri2_window((WindowPtr)d);
352.26399 + 	assert(priv != NULL);
352.26400 ++	assert(priv->chain == NULL || priv->chain->chained);
352.26401 + 	return priv->chain;
352.26402 + }
352.26403 + inline static DRI2BufferPtr dri2_window_get_front(WindowPtr win)
352.26404 + {
352.26405 + 	struct dri2_window *priv = dri2_window(win);
352.26406 ++	assert(priv->front == NULL || get_private(priv->front)->bo->active_scanout);
352.26407 + 	return priv ? priv->front : NULL;
352.26408 + }
352.26409 + #else
352.26410 + inline static void *dri2_window_get_front(WindowPtr win) { return NULL; }
352.26411 ++#define APPLY_DAMAGE 1
352.26412 + #endif
352.26413 + 
352.26414 + #if DRI2INFOREC_VERSION < 6
352.26415 + 
352.26416 + #define xorg_can_triple_buffer() 0
352.26417 + #define swap_limit(d, l) false
352.26418 ++#define mark_stale(b)
352.26419 + 
352.26420 + #else
352.26421 + 
352.26422 +@@ -273,6 +419,8 @@ mark_stale(DRI2BufferPtr back)
352.26423 + 	 * stale frame. (This is mostly useful for tracking down
352.26424 + 	 * driver bugs!)
352.26425 + 	 */
352.26426 ++	DBG(("%s(handle=%d) => %d\n", __FUNCTION__,
352.26427 ++	     get_private(back)->bo->handle, xorg_can_triple_buffer()));
352.26428 + 	get_private(back)->stale = xorg_can_triple_buffer();
352.26429 + }
352.26430 + 
352.26431 +@@ -286,21 +434,29 @@ sna_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit)
352.26432 + static void
352.26433 + sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
352.26434 + {
352.26435 ++	struct sna *sna = to_sna_from_drawable(draw);
352.26436 ++
352.26437 + 	DBG(("%s: reusing buffer pixmap=%ld, attachment=%d, handle=%d, name=%d\n",
352.26438 + 	     __FUNCTION__, get_drawable_pixmap(draw)->drawable.serialNumber,
352.26439 + 	     buffer->attachment, get_private(buffer)->bo->handle, buffer->name));
352.26440 + 	assert(get_private(buffer)->refcnt);
352.26441 +-	assert(get_private(buffer)->bo->refcnt > get_private(buffer)->bo->active_scanout);
352.26442 ++	assert(get_private(buffer)->bo->refcnt >= get_private(buffer)->bo->active_scanout);
352.26443 ++	assert(kgem_bo_flink(&sna->kgem, get_private(buffer)->bo) == buffer->name);
352.26444 + 
352.26445 + 	if (buffer->attachment == DRI2BufferBackLeft &&
352.26446 + 	    draw->type != DRAWABLE_PIXMAP) {
352.26447 +-		DBG(("%s: replacing back buffer\n", __FUNCTION__));
352.26448 +-		sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer, dri2_chain(draw));
352.26449 ++		DBG(("%s: replacing back buffer on window %ld\n", __FUNCTION__, draw->id));
352.26450 ++		sna_dri2_get_back(sna, draw, buffer);
352.26451 + 
352.26452 +-		assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
352.26453 + 		assert(get_private(buffer)->bo->refcnt);
352.26454 + 		assert(get_private(buffer)->bo->active_scanout == 0);
352.26455 ++		assert(kgem_bo_flink(&sna->kgem, get_private(buffer)->bo) == buffer->name);
352.26456 ++		DBG(("%s: reusing back buffer handle=%d, name=%d, pitch=%d, age=%d\n",
352.26457 ++		     __FUNCTION__, get_private(buffer)->bo->handle,
352.26458 ++		     buffer->name, buffer->pitch, buffer->flags));
352.26459 + 	}
352.26460 ++
352.26461 ++	kgem_bo_submit(&sna->kgem, get_private(buffer)->bo);
352.26462 + }
352.26463 + 
352.26464 + static bool swap_limit(DrawablePtr draw, int limit)
352.26465 +@@ -314,11 +470,6 @@ static bool swap_limit(DrawablePtr draw, int limit)
352.26466 + }
352.26467 + #endif
352.26468 + 
352.26469 +-#if DRI2INFOREC_VERSION < 10
352.26470 +-#undef USE_ASYNC_SWAP
352.26471 +-#define USE_ASYNC_SWAP 0
352.26472 +-#endif
352.26473 +-
352.26474 + #define COLOR_PREFER_TILING_Y 0
352.26475 + 
352.26476 + /* Prefer to enable TILING_Y if this buffer will never be a
352.26477 +@@ -328,6 +479,9 @@ static uint32_t color_tiling(struct sna *sna, DrawablePtr draw)
352.26478 + {
352.26479 + 	uint32_t tiling;
352.26480 + 
352.26481 ++	if (!sna->kgem.can_fence)
352.26482 ++		return I915_TILING_NONE;
352.26483 ++
352.26484 + 	if (COLOR_PREFER_TILING_Y &&
352.26485 + 	    (draw->width  != sna->front->drawable.width ||
352.26486 + 	     draw->height != sna->front->drawable.height))
352.26487 +@@ -355,7 +509,6 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
352.26488 + 					  PixmapPtr pixmap)
352.26489 + {
352.26490 + 	struct sna_pixmap *priv;
352.26491 +-	int tiling;
352.26492 + 
352.26493 + 	DBG(("%s: attaching DRI client to pixmap=%ld\n",
352.26494 + 	     __FUNCTION__, pixmap->drawable.serialNumber));
352.26495 +@@ -373,31 +526,29 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
352.26496 + 		return NULL;
352.26497 + 	}
352.26498 + 
352.26499 +-	assert(priv->flush == false);
352.26500 ++	assert(priv->flush == false || priv->pinned & PIN_DRI3);
352.26501 ++	assert(priv->gpu_bo->flush == false || priv->pinned & PIN_DRI3);
352.26502 + 	assert(priv->cpu_damage == NULL);
352.26503 + 	assert(priv->gpu_bo);
352.26504 + 	assert(priv->gpu_bo->proxy == NULL);
352.26505 +-	assert(priv->gpu_bo->flush == false);
352.26506 +-
352.26507 +-	tiling = color_tiling(sna, &pixmap->drawable);
352.26508 +-	if (tiling < 0)
352.26509 +-		tiling = -tiling;
352.26510 +-	if (priv->gpu_bo->tiling != tiling)
352.26511 +-		sna_pixmap_change_tiling(pixmap, tiling);
352.26512 + 
352.26513 +-	return priv->gpu_bo;
352.26514 +-}
352.26515 ++	if (!kgem_bo_is_fenced(&sna->kgem, priv->gpu_bo)) {
352.26516 ++		if (priv->gpu_bo->tiling &&
352.26517 ++		    !sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
352.26518 ++			DBG(("%s: failed to discard tiling (%d) for DRI2 protocol\n", __FUNCTION__, priv->gpu_bo->tiling));
352.26519 ++			return NULL;
352.26520 ++		}
352.26521 ++	} else {
352.26522 ++		int tiling = color_tiling(sna, &pixmap->drawable);
352.26523 ++		if (tiling < 0)
352.26524 ++			tiling = -tiling;
352.26525 ++		if (priv->gpu_bo->tiling < tiling && !priv->gpu_bo->scanout)
352.26526 ++			sna_pixmap_change_tiling(pixmap, tiling);
352.26527 ++	}
352.26528 + 
352.26529 +-pure static inline void *sna_pixmap_get_buffer(PixmapPtr pixmap)
352.26530 +-{
352.26531 +-	assert(pixmap->refcnt);
352.26532 +-	return ((void **)__get_private(pixmap, sna_pixmap_key))[2];
352.26533 +-}
352.26534 ++	priv->gpu_bo->active_scanout++;
352.26535 + 
352.26536 +-static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr)
352.26537 +-{
352.26538 +-	assert(pixmap->refcnt);
352.26539 +-	((void **)__get_private(pixmap, sna_pixmap_key))[2] = ptr;
352.26540 ++	return priv->gpu_bo;
352.26541 + }
352.26542 + 
352.26543 + void
352.26544 +@@ -422,13 +573,18 @@ sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo)
352.26545 + 	if (private->bo == bo)
352.26546 + 		return;
352.26547 + 
352.26548 ++	assert(private->bo->active_scanout > 0);
352.26549 ++	private->bo->active_scanout--;
352.26550 ++
352.26551 + 	DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, private->bo->handle));
352.26552 + 	private->bo->flush = false;
352.26553 + 	kgem_bo_destroy(&sna->kgem, private->bo);
352.26554 + 
352.26555 ++
352.26556 + 	buffer->name = kgem_bo_flink(&sna->kgem, bo);
352.26557 + 	buffer->pitch = bo->pitch;
352.26558 + 	private->bo = ref(bo);
352.26559 ++	bo->active_scanout++;
352.26560 + 
352.26561 + 	DBG(("%s: adding flush hint to handle=%d\n", __FUNCTION__, bo->handle));
352.26562 + 	bo->flush = true;
352.26563 +@@ -449,9 +605,9 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26564 + 	struct sna_dri2_private *private;
352.26565 + 	PixmapPtr pixmap;
352.26566 + 	struct kgem_bo *bo;
352.26567 +-	unsigned flags = 0;
352.26568 ++	unsigned bpp = format ?: draw->bitsPerPixel;
352.26569 ++	unsigned flags = CREATE_EXACT;
352.26570 + 	uint32_t size;
352.26571 +-	int bpp;
352.26572 + 
352.26573 + 	DBG(("%s pixmap=%ld, (attachment=%d, format=%d, drawable=%dx%d), window?=%d\n",
352.26574 + 	     __FUNCTION__,
352.26575 +@@ -468,11 +624,11 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26576 + 		if (draw->type != DRAWABLE_PIXMAP)
352.26577 + 			buffer = dri2_window_get_front((WindowPtr)draw);
352.26578 + 		if (buffer == NULL)
352.26579 +-			buffer = sna_pixmap_get_buffer(pixmap);
352.26580 ++			buffer = (DRI2Buffer2Ptr)sna_pixmap_get_buffer(pixmap);
352.26581 + 		if (buffer) {
352.26582 + 			private = get_private(buffer);
352.26583 + 
352.26584 +-			DBG(("%s: reusing front buffer attachment, win=%lu %dx%d, pixmap=%ld [%ld] %dx%d, handle=%d, name=%d\n",
352.26585 ++			DBG(("%s: reusing front buffer attachment, win=%lu %dx%d, pixmap=%ld [%ld] %dx%d, handle=%d, name=%d, active_scanout=%d\n",
352.26586 + 			     __FUNCTION__,
352.26587 + 			     draw->type != DRAWABLE_PIXMAP ? (long)draw->id : (long)0,
352.26588 + 			     draw->width, draw->height,
352.26589 +@@ -480,12 +636,22 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26590 + 			     private->pixmap->drawable.serialNumber,
352.26591 + 			     pixmap->drawable.width,
352.26592 + 			     pixmap->drawable.height,
352.26593 +-			     private->bo->handle, buffer->name));
352.26594 ++			     private->bo->handle, buffer->name,
352.26595 ++			     private->bo->active_scanout));
352.26596 + 
352.26597 ++			assert(buffer->attachment == DRI2BufferFrontLeft);
352.26598 + 			assert(private->pixmap == pixmap);
352.26599 + 			assert(sna_pixmap(pixmap)->flush);
352.26600 + 			assert(sna_pixmap(pixmap)->pinned & PIN_DRI2);
352.26601 + 			assert(kgem_bo_flink(&sna->kgem, private->bo) == buffer->name);
352.26602 ++			assert(private->bo->pitch == buffer->pitch);
352.26603 ++			assert(private->bo->active_scanout);
352.26604 ++
352.26605 ++			sna_pixmap_move_to_gpu(pixmap,
352.26606 ++					       MOVE_READ |
352.26607 ++					       __MOVE_FORCE |
352.26608 ++					       __MOVE_DRI);
352.26609 ++			kgem_bo_submit(&sna->kgem, private->bo);
352.26610 + 
352.26611 + 			private->refcnt++;
352.26612 + 			return buffer;
352.26613 +@@ -498,7 +664,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26614 + 		assert(sna_pixmap(pixmap) != NULL);
352.26615 + 
352.26616 + 		bo = ref(bo);
352.26617 +-		bpp = pixmap->drawable.bitsPerPixel;
352.26618 + 		if (pixmap == sna->front && !(sna->flags & SNA_LINEAR_FB))
352.26619 + 			flags |= CREATE_SCANOUT;
352.26620 + 		DBG(("%s: attaching to front buffer %dx%d [%p:%d], scanout? %d\n",
352.26621 +@@ -506,6 +671,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26622 + 		     pixmap->drawable.width, pixmap->drawable.height,
352.26623 + 		     pixmap, pixmap->refcnt, flags & CREATE_SCANOUT));
352.26624 + 		size = (uint32_t)pixmap->drawable.height << 16 | pixmap->drawable.width;
352.26625 ++		bpp = pixmap->drawable.bitsPerPixel;
352.26626 + 		break;
352.26627 + 
352.26628 + 	case DRI2BufferBackLeft:
352.26629 +@@ -514,6 +680,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26630 + 				flags |= CREATE_SCANOUT;
352.26631 + 			if (draw->width  == sna->front->drawable.width &&
352.26632 + 			    draw->height == sna->front->drawable.height &&
352.26633 ++			    draw->bitsPerPixel == bpp &&
352.26634 + 			    (sna->flags & (SNA_LINEAR_FB | SNA_NO_WAIT | SNA_NO_FLIP)) == 0)
352.26635 + 				flags |= CREATE_SCANOUT;
352.26636 + 		}
352.26637 +@@ -521,7 +688,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26638 + 	case DRI2BufferFrontRight:
352.26639 + 	case DRI2BufferFakeFrontLeft:
352.26640 + 	case DRI2BufferFakeFrontRight:
352.26641 +-		bpp = draw->bitsPerPixel;
352.26642 + 		DBG(("%s: creating back buffer %dx%d, suitable for scanout? %d\n",
352.26643 + 		     __FUNCTION__,
352.26644 + 		     draw->width, draw->height,
352.26645 +@@ -530,7 +696,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26646 + 		bo = kgem_create_2d(&sna->kgem,
352.26647 + 				    draw->width,
352.26648 + 				    draw->height,
352.26649 +-				    draw->bitsPerPixel,
352.26650 ++				    bpp,
352.26651 + 				    color_tiling(sna, draw),
352.26652 + 				    flags);
352.26653 + 		break;
352.26654 +@@ -558,7 +724,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26655 + 		 * not understand W tiling and the GTT is incapable of
352.26656 + 		 * W fencing.
352.26657 + 		 */
352.26658 +-		bpp = format ? format : draw->bitsPerPixel;
352.26659 + 		bpp *= 2;
352.26660 + 		bo = kgem_create_2d(&sna->kgem,
352.26661 + 				    ALIGN(draw->width, 64),
352.26662 +@@ -570,7 +735,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26663 + 	case DRI2BufferDepthStencil:
352.26664 + 	case DRI2BufferHiz:
352.26665 + 	case DRI2BufferAccum:
352.26666 +-		bpp = format ? format : draw->bitsPerPixel,
352.26667 + 		bo = kgem_create_2d(&sna->kgem,
352.26668 + 				    draw->width, draw->height, bpp,
352.26669 + 				    other_tiling(sna, draw),
352.26670 +@@ -614,7 +778,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26671 + 		pixmap->refcnt++;
352.26672 + 
352.26673 + 		priv = sna_pixmap(pixmap);
352.26674 +-		assert(priv->flush == false);
352.26675 ++		assert(priv->flush == false || priv->pinned & PIN_DRI3);
352.26676 + 		assert((priv->pinned & PIN_DRI2) == 0);
352.26677 + 
352.26678 + 		/* Don't allow this named buffer to be replaced */
352.26679 +@@ -630,17 +794,17 @@ sna_dri2_create_buffer(DrawablePtr draw,
352.26680 + 		if (priv->gpu_bo->exec)
352.26681 + 			sna->kgem.flush = 1;
352.26682 + 
352.26683 +-		priv->flush |= 1;
352.26684 ++		priv->flush |= FLUSH_READ;
352.26685 + 		if (draw->type == DRAWABLE_PIXMAP) {
352.26686 + 			/* DRI2 renders directly into GLXPixmaps, treat as hostile */
352.26687 + 			kgem_bo_unclean(&sna->kgem, priv->gpu_bo);
352.26688 + 			sna_damage_all(&priv->gpu_damage, pixmap);
352.26689 + 			priv->clear = false;
352.26690 + 			priv->cpu = false;
352.26691 +-			priv->flush |= 2;
352.26692 ++			priv->flush |= FLUSH_WRITE;
352.26693 + 		}
352.26694 + 
352.26695 +-		sna_accel_watch_flush(sna, 1);
352.26696 ++		sna_watch_flush(sna, 1);
352.26697 + 	}
352.26698 + 
352.26699 + 	return buffer;
352.26700 +@@ -651,16 +815,80 @@ err:
352.26701 + 	return NULL;
352.26702 + }
352.26703 + 
352.26704 +-static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
352.26705 ++static void
352.26706 ++sna_dri2_cache_bo(struct sna *sna,
352.26707 ++		  DrawablePtr draw,
352.26708 ++		  struct kgem_bo *bo,
352.26709 ++		  uint32_t name,
352.26710 ++		  uint32_t size,
352.26711 ++		  uint32_t flags)
352.26712 ++{
352.26713 ++	struct dri_bo *c;
352.26714 ++
352.26715 ++	DBG(("%s(handle=%d, name=%d)\n", __FUNCTION__, bo->handle, name));
352.26716 ++
352.26717 ++	if (draw == NULL) {
352.26718 ++		DBG(("%s: no draw, releasing handle=%d\n",
352.26719 ++		     __FUNCTION__, bo->handle));
352.26720 ++		goto err;
352.26721 ++	}
352.26722 ++
352.26723 ++	if (draw->type == DRAWABLE_PIXMAP) {
352.26724 ++		DBG(("%s: not a window, releasing handle=%d\n",
352.26725 ++		     __FUNCTION__, bo->handle));
352.26726 ++		goto err;
352.26727 ++	}
352.26728 ++
352.26729 ++	if (bo->refcnt > 1 + bo->active_scanout) {
352.26730 ++		DBG(("%s: multiple references [%d], releasing handle\n",
352.26731 ++		     __FUNCTION__, bo->refcnt, bo->handle));
352.26732 ++		goto err;
352.26733 ++	}
352.26734 ++
352.26735 ++	if ((draw->height << 16 | draw->width) != size) {
352.26736 ++		DBG(("%s: wrong size [%dx%d], releasing handle\n",
352.26737 ++		     __FUNCTION__,
352.26738 ++		     size & 0xffff, size >> 16,
352.26739 ++		     bo->handle));
352.26740 ++		goto err;
352.26741 ++	}
352.26742 ++
352.26743 ++	if (bo->scanout && front_pitch(draw) != bo->pitch) {
352.26744 ++		DBG(("%s: scanout with pitch change [%d != %d], releasing handle\n",
352.26745 ++		     __FUNCTION__, bo->pitch, front_pitch(draw), bo->handle));
352.26746 ++		goto err;
352.26747 ++	}
352.26748 ++
352.26749 ++	c = malloc(sizeof(*c));
352.26750 ++	if (!c)
352.26751 ++		goto err;
352.26752 ++
352.26753 ++	DBG(("%s: caching handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, bo->handle, name, flags, bo->active_scanout));
352.26754 ++
352.26755 ++	c->bo = bo;
352.26756 ++	c->name = name;
352.26757 ++	c->flags = flags;
352.26758 ++	list_add(&c->link, &dri2_window((WindowPtr)draw)->cache);
352.26759 ++	return;
352.26760 ++
352.26761 ++err:
352.26762 ++	kgem_bo_destroy(&sna->kgem, bo);
352.26763 ++}
352.26764 ++
352.26765 ++static void _sna_dri2_destroy_buffer(struct sna *sna,
352.26766 ++				     DrawablePtr draw,
352.26767 ++				     DRI2Buffer2Ptr buffer)
352.26768 + {
352.26769 + 	struct sna_dri2_private *private = get_private(buffer);
352.26770 + 
352.26771 + 	if (buffer == NULL)
352.26772 + 		return;
352.26773 + 
352.26774 +-	DBG(("%s: %p [handle=%d] -- refcnt=%d, pixmap=%ld\n",
352.26775 ++	DBG(("%s: %p [handle=%d] -- refcnt=%d, draw=%ld, pixmap=%ld, proxy?=%d\n",
352.26776 + 	     __FUNCTION__, buffer, private->bo->handle, private->refcnt,
352.26777 +-	     private->pixmap ? private->pixmap->drawable.serialNumber : 0));
352.26778 ++	     draw ? draw->id : 0,
352.26779 ++	     private->pixmap ? private->pixmap->drawable.serialNumber : 0,
352.26780 ++	     private->proxy != NULL));
352.26781 + 	assert(private->refcnt > 0);
352.26782 + 	if (--private->refcnt)
352.26783 + 		return;
352.26784 +@@ -669,7 +897,10 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
352.26785 + 
352.26786 + 	if (private->proxy) {
352.26787 + 		DBG(("%s: destroying proxy\n", __FUNCTION__));
352.26788 +-		_sna_dri2_destroy_buffer(sna, private->proxy);
352.26789 ++		assert(private->bo->active_scanout > 0);
352.26790 ++		private->bo->active_scanout--;
352.26791 ++
352.26792 ++		_sna_dri2_destroy_buffer(sna, draw, private->proxy);
352.26793 + 		private->pixmap = NULL;
352.26794 + 	}
352.26795 + 
352.26796 +@@ -683,6 +914,11 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
352.26797 + 		assert(priv->pinned & PIN_DRI2);
352.26798 + 		assert(priv->flush);
352.26799 + 
352.26800 ++		DBG(("%s: removing active_scanout=%d from pixmap handle=%d\n",
352.26801 ++		     __FUNCTION__, priv->gpu_bo->active_scanout, priv->gpu_bo->handle));
352.26802 ++		assert(priv->gpu_bo->active_scanout > 0);
352.26803 ++		priv->gpu_bo->active_scanout--;
352.26804 ++
352.26805 + 		/* Undo the DRI markings on this pixmap */
352.26806 + 		DBG(("%s: releasing last DRI pixmap=%ld, scanout?=%d\n",
352.26807 + 		     __FUNCTION__,
352.26808 +@@ -692,28 +928,34 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
352.26809 + 		list_del(&priv->flush_list);
352.26810 + 
352.26811 + 		DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, private->bo->handle));
352.26812 +-		priv->gpu_bo->flush = false;
352.26813 + 		priv->pinned &= ~PIN_DRI2;
352.26814 + 
352.26815 +-		priv->flush = false;
352.26816 +-		sna_accel_watch_flush(sna, -1);
352.26817 ++		if ((priv->pinned & PIN_DRI3) == 0) {
352.26818 ++			priv->gpu_bo->flush = false;
352.26819 ++			priv->flush = false;
352.26820 ++		}
352.26821 ++		sna_watch_flush(sna, -1);
352.26822 + 
352.26823 + 		sna_pixmap_set_buffer(pixmap, NULL);
352.26824 + 		pixmap->drawable.pScreen->DestroyPixmap(pixmap);
352.26825 + 	}
352.26826 +-	assert(private->bo->flush == false);
352.26827 + 
352.26828 +-	kgem_bo_destroy(&sna->kgem, private->bo);
352.26829 ++	sna_dri2_cache_bo(sna, draw,
352.26830 ++			  private->bo,
352.26831 ++			  buffer->name,
352.26832 ++			  private->size,
352.26833 ++			  buffer->flags);
352.26834 + 	free(buffer);
352.26835 + }
352.26836 + 
352.26837 + static void sna_dri2_destroy_buffer(DrawablePtr draw, DRI2Buffer2Ptr buffer)
352.26838 + {
352.26839 +-	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), buffer);
352.26840 ++	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), draw, buffer);
352.26841 + }
352.26842 + 
352.26843 + static DRI2BufferPtr sna_dri2_reference_buffer(DRI2BufferPtr buffer)
352.26844 + {
352.26845 ++	assert(get_private(buffer)->refcnt > 0);
352.26846 + 	get_private(buffer)->refcnt++;
352.26847 + 	return buffer;
352.26848 + }
352.26849 +@@ -746,10 +988,9 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
352.26850 + {
352.26851 + 	struct sna *sna = to_sna_from_pixmap(pixmap);
352.26852 + 	struct sna_pixmap *priv = sna_pixmap(pixmap);
352.26853 +-	RegionRec region;
352.26854 + 
352.26855 +-	DBG(("%s: pixmap=%ld, handle=%d\n",
352.26856 +-	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle));
352.26857 ++	DBG(("%s: pixmap=%ld, handle=%d (old handle=%d)\n",
352.26858 ++	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle, priv->gpu_bo->handle));
352.26859 + 
352.26860 + 	assert(pixmap->drawable.width * pixmap->drawable.bitsPerPixel <= 8*bo->pitch);
352.26861 + 	assert(pixmap->drawable.height * bo->pitch <= kgem_bo_size(bo));
352.26862 +@@ -758,21 +999,34 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
352.26863 + 	assert((priv->pinned & (PIN_PRIME | PIN_DRI3)) == 0);
352.26864 + 	assert(priv->flush);
352.26865 + 
352.26866 +-	/* Post damage on the new front buffer so that listeners, such
352.26867 +-	 * as DisplayLink know take a copy and shove it over the USB,
352.26868 +-	 * also for software cursors and the like.
352.26869 +-	 */
352.26870 +-	region.extents.x1 = region.extents.y1 = 0;
352.26871 +-	region.extents.x2 = pixmap->drawable.width;
352.26872 +-	region.extents.y2 = pixmap->drawable.height;
352.26873 +-	region.data = NULL;
352.26874 +-	DamageRegionAppend(&pixmap->drawable, &region);
352.26875 ++	if (APPLY_DAMAGE) {
352.26876 ++		RegionRec region;
352.26877 ++
352.26878 ++		/* Post damage on the new front buffer so that listeners, such
352.26879 ++		 * as DisplayLink know take a copy and shove it over the USB,
352.26880 ++		 * also for software cursors and the like.
352.26881 ++		 */
352.26882 ++		region.extents.x1 = region.extents.y1 = 0;
352.26883 ++		region.extents.x2 = pixmap->drawable.width;
352.26884 ++		region.extents.y2 = pixmap->drawable.height;
352.26885 ++		region.data = NULL;
352.26886 ++
352.26887 ++		/*
352.26888 ++		 * Eeek, beware the sw cursor copying to the old bo
352.26889 ++		 * causing recursion and mayhem.
352.26890 ++		 */
352.26891 ++		DBG(("%s: marking whole pixmap as damaged\n", __FUNCTION__));
352.26892 ++		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
352.26893 ++		DamageRegionAppend(&pixmap->drawable, &region);
352.26894 ++	}
352.26895 + 
352.26896 + 	damage(pixmap, priv, NULL);
352.26897 + 
352.26898 + 	assert(bo->refcnt);
352.26899 +-	if (priv->move_to_gpu)
352.26900 ++	if (priv->move_to_gpu) {
352.26901 ++		DBG(("%s: applying final/discard move-to-gpu\n", __FUNCTION__));
352.26902 + 		priv->move_to_gpu(sna, priv, 0);
352.26903 ++	}
352.26904 + 	if (priv->gpu_bo != bo) {
352.26905 + 		DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, priv->gpu_bo->handle));
352.26906 + 		priv->gpu_bo->flush = false;
352.26907 +@@ -792,8 +1046,27 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
352.26908 + 		bo->domain = DOMAIN_NONE;
352.26909 + 	assert(bo->flush);
352.26910 + 
352.26911 +-	DamageRegionProcessPending(&pixmap->drawable);
352.26912 ++	if (APPLY_DAMAGE) {
352.26913 ++		sna->ignore_copy_area = false;
352.26914 ++		DamageRegionProcessPending(&pixmap->drawable);
352.26915 ++	}
352.26916 ++}
352.26917 ++
352.26918 ++#if defined(__GNUC__)
352.26919 ++#define popcount(x) __builtin_popcount(x)
352.26920 ++#else
352.26921 ++static int popcount(unsigned int x)
352.26922 ++{
352.26923 ++	int count = 0;
352.26924 ++
352.26925 ++	while (x) {
352.26926 ++		count += x&1;
352.26927 ++		x >>= 1;
352.26928 ++	}
352.26929 ++
352.26930 ++	return count;
352.26931 + }
352.26932 ++#endif
352.26933 + 
352.26934 + static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kgem_bo *src, bool sync)
352.26935 + {
352.26936 +@@ -823,6 +1096,12 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
352.26937 + 		return;
352.26938 + 	}
352.26939 + 
352.26940 ++	if (sna->render_state.gt < 2 && sna->kgem.has_semaphores) {
352.26941 ++		DBG(("%s: small GT [%d], not forcing selection\n",
352.26942 ++		     __FUNCTION__, sna->render_state.gt));
352.26943 ++		return;
352.26944 ++	}
352.26945 ++
352.26946 + 	VG_CLEAR(busy);
352.26947 + 	busy.handle = src->handle;
352.26948 + 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy))
352.26949 +@@ -860,9 +1139,11 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
352.26950 + 	 * the cost of the query.
352.26951 + 	 */
352.26952 + 	mode = KGEM_RENDER;
352.26953 +-	if (busy.busy & (0xfffe << 16))
352.26954 ++	if ((busy.busy & 0xffff) == I915_EXEC_BLT)
352.26955 + 		mode = KGEM_BLT;
352.26956 +-	kgem_bo_mark_busy(&sna->kgem, busy.handle == src->handle ? src : dst, mode);
352.26957 ++	kgem_bo_mark_busy(&sna->kgem,
352.26958 ++			  busy.handle == src->handle ? src : dst,
352.26959 ++			  mode);
352.26960 + 	_kgem_set_mode(&sna->kgem, mode);
352.26961 + }
352.26962 + 
352.26963 +@@ -871,10 +1152,13 @@ static bool is_front(int attachment)
352.26964 + 	return attachment == DRI2BufferFrontLeft;
352.26965 + }
352.26966 + 
352.26967 ++#define DRI2_SYNC 0x1
352.26968 ++#define DRI2_DAMAGE 0x2
352.26969 ++#define DRI2_BO 0x4
352.26970 + static struct kgem_bo *
352.26971 + __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.26972 + 		      DRI2BufferPtr src, DRI2BufferPtr dst,
352.26973 +-		      bool sync)
352.26974 ++		      unsigned flags)
352.26975 + {
352.26976 + 	PixmapPtr pixmap = get_drawable_pixmap(draw);
352.26977 + 	DrawableRec scratch, *src_draw = &pixmap->drawable, *dst_draw = &pixmap->drawable;
352.26978 +@@ -886,7 +1170,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.26979 + 	struct kgem_bo *dst_bo;
352.26980 + 	const BoxRec *boxes;
352.26981 + 	int16_t dx, dy, sx, sy;
352.26982 +-	unsigned flags;
352.26983 ++	unsigned hint;
352.26984 + 	int n;
352.26985 + 
352.26986 + 	/* To hide a stale DRI2Buffer, one may choose to substitute
352.26987 +@@ -962,8 +1246,9 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.26988 + 			}
352.26989 + 		}
352.26990 + 	} else
352.26991 +-		sync = false;
352.26992 ++		flags &= ~DRI2_SYNC;
352.26993 + 
352.26994 ++	scratch.pScreen = draw->pScreen;
352.26995 + 	scratch.x = scratch.y = 0;
352.26996 + 	scratch.width = scratch.height = 0;
352.26997 + 	scratch.depth = draw->depth;
352.26998 +@@ -971,6 +1256,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.26999 + 
352.27000 + 	src_bo = src_priv->bo;
352.27001 + 	assert(src_bo->refcnt);
352.27002 ++	kgem_bo_unclean(&sna->kgem, src_bo);
352.27003 + 	if (is_front(src->attachment)) {
352.27004 + 		struct sna_pixmap *priv;
352.27005 + 
352.27006 +@@ -987,11 +1273,12 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27007 + 		scratch.height = src_priv->size >> 16;
352.27008 + 		src_draw = &scratch;
352.27009 + 
352.27010 +-		DBG(("%s: source size %dx%d, region size %dx%d\n",
352.27011 ++		DBG(("%s: source size %dx%d, region size %dx%d, src offset %dx%d\n",
352.27012 + 		     __FUNCTION__,
352.27013 + 		     scratch.width, scratch.height,
352.27014 + 		     clip.extents.x2 - clip.extents.x1,
352.27015 +-		     clip.extents.y2 - clip.extents.y1));
352.27016 ++		     clip.extents.y2 - clip.extents.y1,
352.27017 ++		     -sx, -sy));
352.27018 + 
352.27019 + 		source.extents.x1 = -sx;
352.27020 + 		source.extents.y1 = -sy;
352.27021 +@@ -1002,6 +1289,10 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27022 + 		assert(region == NULL || region == &clip);
352.27023 + 		pixman_region_intersect(&clip, &clip, &source);
352.27024 + 
352.27025 ++		if (!pixman_region_not_empty(&clip)) {
352.27026 ++			DBG(("%s: region doesn't overlap pixmap\n", __FUNCTION__));
352.27027 ++			return NULL;
352.27028 ++		}
352.27029 + 	}
352.27030 + 
352.27031 + 	dst_bo = dst_priv->bo;
352.27032 +@@ -1013,12 +1304,12 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27033 + 		/* Preserve the CRTC shadow overrides */
352.27034 + 		sna_shadow_steal_crtcs(sna, &shadow);
352.27035 + 
352.27036 +-		flags = MOVE_WRITE | __MOVE_FORCE;
352.27037 ++		hint = MOVE_WRITE | __MOVE_FORCE;
352.27038 + 		if (clip.data)
352.27039 +-			flags |= MOVE_READ;
352.27040 ++			hint |= MOVE_READ;
352.27041 + 
352.27042 + 		assert(region == NULL || region == &clip);
352.27043 +-		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, flags);
352.27044 ++		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, hint);
352.27045 + 		if (priv) {
352.27046 + 			damage(pixmap, priv, region);
352.27047 + 			dst_bo = priv->gpu_bo;
352.27048 +@@ -1050,20 +1341,20 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27049 + 		assert(region == NULL || region == &clip);
352.27050 + 		pixman_region_intersect(&clip, &clip, &target);
352.27051 + 
352.27052 +-		sync = false;
352.27053 ++		flags &= ~DRI2_SYNC;
352.27054 + 	}
352.27055 + 
352.27056 + 	if (!wedged(sna)) {
352.27057 + 		xf86CrtcPtr crtc;
352.27058 + 
352.27059 + 		crtc = NULL;
352.27060 +-		if (sync && sna_pixmap_is_scanout(sna, pixmap))
352.27061 ++		if (flags & DRI2_SYNC && sna_pixmap_is_scanout(sna, pixmap))
352.27062 + 			crtc = sna_covering_crtc(sna, &clip.extents, NULL);
352.27063 + 		sna_dri2_select_mode(sna, dst_bo, src_bo, crtc != NULL);
352.27064 + 
352.27065 +-		sync = (crtc != NULL&&
352.27066 +-			sna_wait_for_scanline(sna, pixmap, crtc,
352.27067 +-					      &clip.extents));
352.27068 ++		if (crtc == NULL ||
352.27069 ++		    !sna_wait_for_scanline(sna, pixmap, crtc, &clip.extents))
352.27070 ++			flags &= ~DRI2_SYNC;
352.27071 + 	}
352.27072 + 
352.27073 + 	if (region) {
352.27074 +@@ -1075,8 +1366,11 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27075 + 		boxes = &clip.extents;
352.27076 + 		n = 1;
352.27077 + 	}
352.27078 +-	DamageRegionAppend(&pixmap->drawable, region);
352.27079 +-
352.27080 ++	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
352.27081 ++		DBG(("%s: marking region as damaged\n", __FUNCTION__));
352.27082 ++		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
352.27083 ++		DamageRegionAppend(&pixmap->drawable, region);
352.27084 ++	}
352.27085 + 
352.27086 + 	DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
352.27087 + 	     __FUNCTION__,
352.27088 +@@ -1084,29 +1378,36 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
352.27089 + 	     boxes[0].x2, boxes[0].y2,
352.27090 + 	     n, sx, sy, dx, dy));
352.27091 + 
352.27092 +-	flags = COPY_LAST;
352.27093 +-	if (sync)
352.27094 +-		flags |= COPY_SYNC;
352.27095 ++	hint = COPY_LAST | COPY_DRI;
352.27096 ++	if (flags & DRI2_SYNC)
352.27097 ++		hint |= COPY_SYNC;
352.27098 + 	if (!sna->render.copy_boxes(sna, GXcopy,
352.27099 + 				    src_draw, src_bo, sx, sy,
352.27100 + 				    dst_draw, dst_bo, dx, dy,
352.27101 +-				    boxes, n, flags))
352.27102 ++				    boxes, n, hint))
352.27103 + 		memcpy_copy_boxes(sna, GXcopy,
352.27104 + 				  src_draw, src_bo, sx, sy,
352.27105 + 				  dst_draw, dst_bo, dx, dy,
352.27106 +-				  boxes, n, flags);
352.27107 +-
352.27108 +-	DBG(("%s: flushing? %d\n", __FUNCTION__, sync));
352.27109 +-	if (sync) { /* STAT! */
352.27110 +-		struct kgem_request *rq = sna->kgem.next_request;
352.27111 +-		kgem_submit(&sna->kgem);
352.27112 +-		if (rq->bo) {
352.27113 +-			bo = ref(rq->bo);
352.27114 +-			DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle));
352.27115 ++				  boxes, n, hint);
352.27116 ++
352.27117 ++	sna->needs_dri_flush = true;
352.27118 ++	if (flags & (DRI2_SYNC | DRI2_BO)) { /* STAT! */
352.27119 ++		struct kgem_request *rq = RQ(dst_bo->rq);
352.27120 ++		if (rq && rq != (void *)&sna->kgem) {
352.27121 ++			if (rq->bo == NULL)
352.27122 ++				kgem_submit(&sna->kgem);
352.27123 ++			if (rq->bo) { /* Becareful in case the gpu is wedged */
352.27124 ++				bo = ref(rq->bo);
352.27125 ++				DBG(("%s: recording sync fence handle=%d\n",
352.27126 ++				     __FUNCTION__, bo->handle));
352.27127 ++			}
352.27128 + 		}
352.27129 + 	}
352.27130 + 
352.27131 +-	DamageRegionProcessPending(&pixmap->drawable);
352.27132 ++	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
352.27133 ++		sna->ignore_copy_area = false;
352.27134 ++		DamageRegionProcessPending(&pixmap->drawable);
352.27135 ++	}
352.27136 + 
352.27137 + 	if (clip.data)
352.27138 + 		pixman_region_fini(&clip);
352.27139 +@@ -1142,6 +1443,8 @@ sna_dri2_copy_region(DrawablePtr draw,
352.27140 + 	assert(get_private(src)->refcnt);
352.27141 + 	assert(get_private(dst)->refcnt);
352.27142 + 
352.27143 ++	assert(get_private(src)->bo != get_private(dst)->bo);
352.27144 ++
352.27145 + 	assert(get_private(src)->bo->refcnt);
352.27146 + 	assert(get_private(dst)->bo->refcnt);
352.27147 + 
352.27148 +@@ -1151,7 +1454,7 @@ sna_dri2_copy_region(DrawablePtr draw,
352.27149 + 	     region->extents.x2, region->extents.y2,
352.27150 + 	     region_num_rects(region)));
352.27151 + 
352.27152 +-	__sna_dri2_copy_region(sna, draw, region, src, dst, false);
352.27153 ++	__sna_dri2_copy_region(sna, draw, region, src, dst, DRI2_DAMAGE);
352.27154 + }
352.27155 + 
352.27156 + inline static uint32_t pipe_select(int pipe)
352.27157 +@@ -1161,6 +1464,7 @@ inline static uint32_t pipe_select(int pipe)
352.27158 + 	 * we can safely ignore the capability check - if we have more
352.27159 + 	 * than two pipes, we can assume that they are fully supported.
352.27160 + 	 */
352.27161 ++	assert(pipe < _DRM_VBLANK_HIGH_CRTC_MASK);
352.27162 + 	if (pipe > 1)
352.27163 + 		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
352.27164 + 	else if (pipe > 0)
352.27165 +@@ -1169,15 +1473,53 @@ inline static uint32_t pipe_select(int pipe)
352.27166 + 		return 0;
352.27167 + }
352.27168 + 
352.27169 +-static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, int pipe)
352.27170 ++static inline bool sna_next_vblank(struct sna_dri2_event *info)
352.27171 + {
352.27172 +-	DBG(("%s(pipe=%d, waiting until seq=%u%s)\n",
352.27173 +-	     __FUNCTION__, pipe, vbl->request.sequence,
352.27174 +-	     vbl->request.type & DRM_VBLANK_RELATIVE ? " [relative]" : ""));
352.27175 +-	assert(pipe != -1);
352.27176 ++	union drm_wait_vblank vbl;
352.27177 + 
352.27178 +-	vbl->request.type |= pipe_select(pipe);
352.27179 +-	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
352.27180 ++	DBG(("%s(pipe=%d, waiting until next vblank)\n",
352.27181 ++	     __FUNCTION__, info->pipe));
352.27182 ++	assert(info->pipe != -1);
352.27183 ++
352.27184 ++	VG_CLEAR(vbl);
352.27185 ++	vbl.request.type =
352.27186 ++		DRM_VBLANK_RELATIVE |
352.27187 ++		DRM_VBLANK_EVENT |
352.27188 ++		pipe_select(info->pipe);
352.27189 ++	vbl.request.sequence = 1;
352.27190 ++	vbl.request.signal = (uintptr_t)info;
352.27191 ++
352.27192 ++	assert(!info->queued);
352.27193 ++	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
352.27194 ++		return false;
352.27195 ++
352.27196 ++	info->queued = true;
352.27197 ++	return true;
352.27198 ++}
352.27199 ++
352.27200 ++static inline bool sna_wait_vblank(struct sna_dri2_event *info,
352.27201 ++				   unsigned seq)
352.27202 ++{
352.27203 ++	union drm_wait_vblank vbl;
352.27204 ++
352.27205 ++	DBG(("%s(pipe=%d, waiting until vblank %u)\n",
352.27206 ++	     __FUNCTION__, info->pipe, seq));
352.27207 ++	assert(info->pipe != -1);
352.27208 ++
352.27209 ++	VG_CLEAR(vbl);
352.27210 ++	vbl.request.type =
352.27211 ++		DRM_VBLANK_ABSOLUTE |
352.27212 ++		DRM_VBLANK_EVENT |
352.27213 ++		pipe_select(info->pipe);
352.27214 ++	vbl.request.sequence = seq;
352.27215 ++	vbl.request.signal = (uintptr_t)info;
352.27216 ++
352.27217 ++	assert(!info->queued);
352.27218 ++	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
352.27219 ++		return false;
352.27220 ++
352.27221 ++	info->queued = true;
352.27222 ++	return true;
352.27223 + }
352.27224 + 
352.27225 + #if DRI2INFOREC_VERSION >= 4
352.27226 +@@ -1195,6 +1537,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
352.27227 + {
352.27228 + 	struct dri2_window *priv;
352.27229 + 
352.27230 ++	assert(draw);
352.27231 + 	if (draw->type != DRAWABLE_WINDOW)
352.27232 + 		return msc;
352.27233 + 
352.27234 +@@ -1206,6 +1549,9 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
352.27235 + 			priv->crtc = crtc;
352.27236 + 			priv->msc_delta = 0;
352.27237 + 			priv->chain = NULL;
352.27238 ++			priv->scanout = -1;
352.27239 ++			priv->cache_size = 0;
352.27240 ++			list_init(&priv->cache);
352.27241 + 			dri2_window_attach((WindowPtr)draw, priv);
352.27242 + 		}
352.27243 + 	} else {
352.27244 +@@ -1214,8 +1560,8 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
352.27245 + 			const struct ust_msc *this = sna_crtc_last_swap(crtc);
352.27246 + 			DBG(("%s: Window transferring from pipe=%d [msc=%llu] to pipe=%d [msc=%llu], delta now %lld\n",
352.27247 + 			     __FUNCTION__,
352.27248 +-			     sna_crtc_to_pipe(priv->crtc), (long long)last->msc,
352.27249 +-			     sna_crtc_to_pipe(crtc), (long long)this->msc,
352.27250 ++			     sna_crtc_pipe(priv->crtc), (long long)last->msc,
352.27251 ++			     sna_crtc_pipe(crtc), (long long)this->msc,
352.27252 + 			     (long long)(priv->msc_delta + this->msc - last->msc)));
352.27253 + 			priv->msc_delta += this->msc - last->msc;
352.27254 + 			priv->crtc = crtc;
352.27255 +@@ -1248,57 +1594,119 @@ sna_dri2_get_crtc(DrawablePtr draw)
352.27256 + 				 NULL);
352.27257 + }
352.27258 + 
352.27259 +-static void
352.27260 +-sna_dri2_remove_event(WindowPtr win, struct sna_dri2_event *info)
352.27261 ++static void frame_swap_complete(struct sna_dri2_event *frame, int type)
352.27262 + {
352.27263 +-	struct dri2_window *priv;
352.27264 +-	struct sna_dri2_event *chain;
352.27265 +-
352.27266 +-	assert(win->drawable.type == DRAWABLE_WINDOW);
352.27267 +-	DBG(("%s: remove[%p] from window %ld, active? %d\n",
352.27268 +-	     __FUNCTION__, info, (long)win->drawable.id, info->draw != NULL));
352.27269 ++	const struct ust_msc *swap;
352.27270 + 
352.27271 +-	priv = dri2_window(win);
352.27272 +-	assert(priv);
352.27273 +-	assert(priv->chain != NULL);
352.27274 ++	assert(frame->signal);
352.27275 ++	frame->signal = false;
352.27276 + 
352.27277 +-	if (priv->chain == info) {
352.27278 +-		priv->chain = info->chain;
352.27279 ++	if (frame->client == NULL) {
352.27280 ++		DBG(("%s: client already gone\n", __FUNCTION__));
352.27281 + 		return;
352.27282 + 	}
352.27283 + 
352.27284 +-	chain = priv->chain;
352.27285 +-	while (chain->chain != info)
352.27286 +-		chain = chain->chain;
352.27287 +-	assert(chain != info);
352.27288 +-	assert(info->chain != chain);
352.27289 +-	chain->chain = info->chain;
352.27290 ++	assert(frame->draw);
352.27291 ++
352.27292 ++	swap = sna_crtc_last_swap(frame->crtc);
352.27293 ++	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc=%lld], tv=%d.%06d\n",
352.27294 ++	     __FUNCTION__, type, (long)frame->draw->id, frame->pipe,
352.27295 ++	     (long long)swap->msc,
352.27296 ++	     (long long)draw_current_msc(frame->draw, frame->crtc, swap->msc),
352.27297 ++	     swap->tv_sec, swap->tv_usec));
352.27298 ++
352.27299 ++	DRI2SwapComplete(frame->client, frame->draw,
352.27300 ++			 draw_current_msc(frame->draw, frame->crtc, swap->msc),
352.27301 ++			 swap->tv_sec, swap->tv_usec,
352.27302 ++			 type, frame->event_complete, frame->event_data);
352.27303 + }
352.27304 + 
352.27305 +-static void
352.27306 +-sna_dri2_event_free(struct sna_dri2_event *info)
352.27307 ++static void fake_swap_complete(struct sna *sna, ClientPtr client,
352.27308 ++			       DrawablePtr draw, xf86CrtcPtr crtc,
352.27309 ++			       int type, DRI2SwapEventPtr func, void *data)
352.27310 + {
352.27311 +-	DrawablePtr draw = info->draw;
352.27312 ++	const struct ust_msc *swap;
352.27313 + 
352.27314 +-	DBG(("%s(draw?=%d)\n", __FUNCTION__, draw != NULL));
352.27315 +-	if (draw && draw->type == DRAWABLE_WINDOW)
352.27316 +-		sna_dri2_remove_event((WindowPtr)draw, info);
352.27317 ++	assert(draw);
352.27318 + 
352.27319 +-	_sna_dri2_destroy_buffer(info->sna, info->front);
352.27320 +-	_sna_dri2_destroy_buffer(info->sna, info->back);
352.27321 ++	if (crtc == NULL)
352.27322 ++		crtc = sna_primary_crtc(sna);
352.27323 + 
352.27324 +-	while (!list_is_empty(&info->cache)) {
352.27325 +-		struct dri_bo *c;
352.27326 ++	swap = sna_crtc_last_swap(crtc);
352.27327 ++	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n",
352.27328 ++	     __FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_pipe(crtc) : -1,
352.27329 ++	     (long long)swap->msc,
352.27330 ++	     (long long)draw_current_msc(draw, crtc, swap->msc),
352.27331 ++	     swap->tv_sec, swap->tv_usec));
352.27332 + 
352.27333 +-		c = list_first_entry(&info->cache, struct dri_bo, link);
352.27334 +-		list_del(&c->link);
352.27335 ++	DRI2SwapComplete(client, draw,
352.27336 ++			 draw_current_msc(draw, crtc, swap->msc),
352.27337 ++			 swap->tv_sec, swap->tv_usec,
352.27338 ++			 type, func, data);
352.27339 ++}
352.27340 + 
352.27341 +-		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
352.27342 +-		if (c->bo)
352.27343 +-			kgem_bo_destroy(&info->sna->kgem, c->bo);
352.27344 ++static void
352.27345 ++sna_dri2_remove_event(struct sna_dri2_event *info)
352.27346 ++{
352.27347 ++	WindowPtr win = (WindowPtr)info->draw;
352.27348 ++	struct dri2_window *priv;
352.27349 + 
352.27350 +-		free(c);
352.27351 ++	assert(win->drawable.type == DRAWABLE_WINDOW);
352.27352 ++	DBG(("%s: remove[%p] from window %ld, active? %d\n",
352.27353 ++	     __FUNCTION__, info, (long)win->drawable.id, info->draw != NULL));
352.27354 ++	assert(!info->signal);
352.27355 ++
352.27356 ++	priv = dri2_window(win);
352.27357 ++	assert(priv);
352.27358 ++	assert(priv->chain != NULL);
352.27359 ++	assert(info->chained);
352.27360 ++	info->chained = false;
352.27361 ++
352.27362 ++	if (priv->chain != info) {
352.27363 ++		struct sna_dri2_event *chain = priv->chain;
352.27364 ++		while (chain->chain != info) {
352.27365 ++			assert(chain->chained);
352.27366 ++			chain = chain->chain;
352.27367 ++		}
352.27368 ++		assert(chain != info);
352.27369 ++		assert(info->chain != chain);
352.27370 ++		chain->chain = info->chain;
352.27371 ++		return;
352.27372 ++	}
352.27373 ++
352.27374 ++	priv->chain = info->chain;
352.27375 ++	if (priv->chain == NULL) {
352.27376 ++		struct dri_bo *c, *tmp;
352.27377 ++
352.27378 ++		c = list_entry(priv->cache.next->next, struct dri_bo, link);
352.27379 ++		list_for_each_entry_safe_from(c, tmp, &priv->cache, link) {
352.27380 ++			list_del(&c->link);
352.27381 ++
352.27382 ++			DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
352.27383 ++			assert(c->bo);
352.27384 ++			kgem_bo_destroy(&info->sna->kgem, c->bo);
352.27385 ++			free(c);
352.27386 ++		}
352.27387 + 	}
352.27388 ++}
352.27389 ++
352.27390 ++static void
352.27391 ++sna_dri2_event_free(struct sna_dri2_event *info)
352.27392 ++{
352.27393 ++	DBG(("%s(draw?=%d)\n", __FUNCTION__, info->draw != NULL));
352.27394 ++	assert(!info->queued);
352.27395 ++	assert(!info->signal);
352.27396 ++	assert(info->pending.bo == NULL);
352.27397 ++
352.27398 ++	if (info->sna->dri2.flip_pending == info)
352.27399 ++		info->sna->dri2.flip_pending = NULL;
352.27400 ++	assert(info->sna->dri2.flip_pending != info);
352.27401 ++	if (info->chained)
352.27402 ++		sna_dri2_remove_event(info);
352.27403 ++
352.27404 ++	assert((info->front == NULL && info->back == NULL) || info->front != info->back);
352.27405 ++	_sna_dri2_destroy_buffer(info->sna, info->draw, info->front);
352.27406 ++	_sna_dri2_destroy_buffer(info->sna, info->draw, info->back);
352.27407 + 
352.27408 + 	if (info->bo) {
352.27409 + 		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
352.27410 +@@ -1331,15 +1739,26 @@ sna_dri2_client_gone(CallbackListPtr *list, void *closure, void *data)
352.27411 + 
352.27412 + 		event = list_first_entry(&priv->events, struct sna_dri2_event, link);
352.27413 + 		assert(event->client == client);
352.27414 ++		list_del(&event->link);
352.27415 ++		event->signal = false;
352.27416 + 
352.27417 +-		if (event->queued) {
352.27418 +-			if (event->draw)
352.27419 +-				sna_dri2_remove_event((WindowPtr)event->draw,
352.27420 +-						      event);
352.27421 +-			event->client = NULL;
352.27422 +-			event->draw = NULL;
352.27423 +-			list_del(&event->link);
352.27424 +-		} else
352.27425 ++		if (event->pending.bo) {
352.27426 ++			assert(event->pending.bo->active_scanout > 0);
352.27427 ++			event->pending.bo->active_scanout--;
352.27428 ++
352.27429 ++			kgem_bo_destroy(&sna->kgem, event->pending.bo);
352.27430 ++			event->pending.bo = NULL;
352.27431 ++		}
352.27432 ++
352.27433 ++		if (event->chained)
352.27434 ++			sna_dri2_remove_event(event);
352.27435 ++
352.27436 ++		event->client = NULL;
352.27437 ++		event->draw = NULL;
352.27438 ++		event->keepalive = 1;
352.27439 ++		assert(!event->signal);
352.27440 ++
352.27441 ++		if (!event->queued)
352.27442 + 			sna_dri2_event_free(event);
352.27443 + 	}
352.27444 + 
352.27445 +@@ -1365,11 +1784,15 @@ static bool add_event_to_client(struct sna_dri2_event *info, struct sna *sna, Cl
352.27446 + }
352.27447 + 
352.27448 + static struct sna_dri2_event *
352.27449 +-sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
352.27450 ++sna_dri2_add_event(struct sna *sna,
352.27451 ++		   DrawablePtr draw,
352.27452 ++		   ClientPtr client,
352.27453 ++		   xf86CrtcPtr crtc)
352.27454 + {
352.27455 + 	struct dri2_window *priv;
352.27456 + 	struct sna_dri2_event *info, *chain;
352.27457 + 
352.27458 ++	assert(draw != NULL);
352.27459 + 	assert(draw->type == DRAWABLE_WINDOW);
352.27460 + 	DBG(("%s: adding event to window %ld)\n",
352.27461 + 	     __FUNCTION__, (long)draw->id));
352.27462 +@@ -1382,11 +1805,11 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
352.27463 + 	if (info == NULL)
352.27464 + 		return NULL;
352.27465 + 
352.27466 +-	list_init(&info->cache);
352.27467 + 	info->sna = sna;
352.27468 + 	info->draw = draw;
352.27469 +-	info->crtc = priv->crtc;
352.27470 +-	info->pipe = sna_crtc_to_pipe(priv->crtc);
352.27471 ++	info->crtc = crtc;
352.27472 ++	info->pipe = sna_crtc_pipe(crtc);
352.27473 ++	info->keepalive = 1;
352.27474 + 
352.27475 + 	if (!add_event_to_client(info, sna, client)) {
352.27476 + 		free(info);
352.27477 +@@ -1394,6 +1817,7 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
352.27478 + 	}
352.27479 + 
352.27480 + 	assert(priv->chain != info);
352.27481 ++	info->chained = true;
352.27482 + 
352.27483 + 	if (priv->chain == NULL) {
352.27484 + 		priv->chain = info;
352.27485 +@@ -1409,6 +1833,66 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
352.27486 + 	return info;
352.27487 + }
352.27488 + 
352.27489 ++static void decouple_window(WindowPtr win,
352.27490 ++			    struct dri2_window *priv,
352.27491 ++			    struct sna *sna,
352.27492 ++			    bool signal)
352.27493 ++{
352.27494 ++	if (priv->front) {
352.27495 ++		DBG(("%s: decouple private front\n", __FUNCTION__));
352.27496 ++		assert(priv->crtc);
352.27497 ++		sna_shadow_unset_crtc(sna, priv->crtc);
352.27498 ++
352.27499 ++		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
352.27500 ++		priv->front = NULL;
352.27501 ++	}
352.27502 ++
352.27503 ++	if (priv->chain) {
352.27504 ++		struct sna_dri2_event *info, *chain;
352.27505 ++
352.27506 ++		DBG(("%s: freeing chain\n", __FUNCTION__));
352.27507 ++
352.27508 ++		chain = priv->chain;
352.27509 ++		while ((info = chain)) {
352.27510 ++			DBG(("%s: freeing event, pending signal? %d, pending swap? handle=%d\n",
352.27511 ++			     __FUNCTION__, info->signal,
352.27512 ++			     info->pending.bo ? info->pending.bo->handle : 0));
352.27513 ++			assert(info->draw == &win->drawable);
352.27514 ++
352.27515 ++			if (info->pending.bo) {
352.27516 ++				if (signal) {
352.27517 ++					bool was_signalling = info->signal;
352.27518 ++					info->signal = true;
352.27519 ++					frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
352.27520 ++					info->signal = was_signalling;
352.27521 ++				}
352.27522 ++				assert(info->pending.bo->active_scanout > 0);
352.27523 ++				info->pending.bo->active_scanout--;
352.27524 ++
352.27525 ++				kgem_bo_destroy(&sna->kgem, info->pending.bo);
352.27526 ++				info->pending.bo = NULL;
352.27527 ++			}
352.27528 ++
352.27529 ++			if (info->signal && signal)
352.27530 ++				frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
352.27531 ++			info->signal = false;
352.27532 ++			info->draw = NULL;
352.27533 ++			info->keepalive = 1;
352.27534 ++			assert(!info->signal);
352.27535 ++			list_del(&info->link);
352.27536 ++
352.27537 ++			chain = info->chain;
352.27538 ++			info->chain = NULL;
352.27539 ++			info->chained = false;
352.27540 ++
352.27541 ++			if (!info->queued)
352.27542 ++				sna_dri2_event_free(info);
352.27543 ++		}
352.27544 ++
352.27545 ++		priv->chain = NULL;
352.27546 ++	}
352.27547 ++}
352.27548 ++
352.27549 + void sna_dri2_decouple_window(WindowPtr win)
352.27550 + {
352.27551 + 	struct dri2_window *priv;
352.27552 +@@ -1418,50 +1902,34 @@ void sna_dri2_decouple_window(WindowPtr win)
352.27553 + 		return;
352.27554 + 
352.27555 + 	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
352.27556 ++	decouple_window(win, priv, to_sna_from_drawable(&win->drawable), true);
352.27557 + 
352.27558 +-	if (priv->front) {
352.27559 +-		struct sna *sna = to_sna_from_drawable(&win->drawable);
352.27560 +-		assert(priv->crtc);
352.27561 +-		sna_shadow_unset_crtc(sna, priv->crtc);
352.27562 +-		_sna_dri2_destroy_buffer(sna, priv->front);
352.27563 +-		priv->front = NULL;
352.27564 +-	}
352.27565 ++	priv->scanout = -1;
352.27566 + }
352.27567 + 
352.27568 + void sna_dri2_destroy_window(WindowPtr win)
352.27569 + {
352.27570 + 	struct dri2_window *priv;
352.27571 ++	struct sna *sna;
352.27572 + 
352.27573 + 	priv = dri2_window(win);
352.27574 + 	if (priv == NULL)
352.27575 + 		return;
352.27576 + 
352.27577 + 	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
352.27578 ++	sna = to_sna_from_drawable(&win->drawable);
352.27579 ++	decouple_window(win, priv, sna, false);
352.27580 + 
352.27581 +-	if (priv->front) {
352.27582 +-		struct sna *sna = to_sna_from_drawable(&win->drawable);
352.27583 +-		assert(priv->crtc);
352.27584 +-		sna_shadow_unset_crtc(sna, priv->crtc);
352.27585 +-		_sna_dri2_destroy_buffer(sna, priv->front);
352.27586 +-	}
352.27587 +-
352.27588 +-	if (priv->chain) {
352.27589 +-		struct sna_dri2_event *info, *chain;
352.27590 +-
352.27591 +-		DBG(("%s: freeing chain\n", __FUNCTION__));
352.27592 +-
352.27593 +-		chain = priv->chain;
352.27594 +-		while ((info = chain)) {
352.27595 +-			info->draw = NULL;
352.27596 +-			info->client = NULL;
352.27597 +-			list_del(&info->link);
352.27598 ++	while (!list_is_empty(&priv->cache)) {
352.27599 ++		struct dri_bo *c;
352.27600 + 
352.27601 +-			chain = info->chain;
352.27602 +-			info->chain = NULL;
352.27603 ++		c = list_first_entry(&priv->cache, struct dri_bo, link);
352.27604 ++		list_del(&c->link);
352.27605 + 
352.27606 +-			if (!info->queued)
352.27607 +-				sna_dri2_event_free(info);
352.27608 +-		}
352.27609 ++		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
352.27610 ++		assert(c->bo);
352.27611 ++		kgem_bo_destroy(&sna->kgem, c->bo);
352.27612 ++		free(c);
352.27613 + 	}
352.27614 + 
352.27615 + 	free(priv);
352.27616 +@@ -1479,19 +1947,30 @@ sna_dri2_flip(struct sna_dri2_event *info)
352.27617 + {
352.27618 + 	struct kgem_bo *bo = get_private(info->back)->bo;
352.27619 + 	struct kgem_bo *tmp_bo;
352.27620 +-	uint32_t tmp_name;
352.27621 ++	uint32_t tmp_name, tmp_flags;
352.27622 + 	int tmp_pitch;
352.27623 + 
352.27624 + 	DBG(("%s(type=%d)\n", __FUNCTION__, info->type));
352.27625 + 
352.27626 + 	assert(sna_pixmap_get_buffer(info->sna->front) == info->front);
352.27627 + 	assert(get_drawable_pixmap(info->draw)->drawable.height * bo->pitch <= kgem_bo_size(bo));
352.27628 ++	assert(get_private(info->front)->size == get_private(info->back)->size);
352.27629 + 	assert(bo->refcnt);
352.27630 + 
352.27631 ++	if (info->sna->mode.flip_active) {
352.27632 ++		DBG(("%s: %d flips still active, aborting\n",
352.27633 ++		     __FUNCTION__, info->sna->mode.flip_active));
352.27634 ++		return false;
352.27635 ++	}
352.27636 ++
352.27637 ++	assert(!info->queued);
352.27638 + 	if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler,
352.27639 + 			   info->type == FLIP_ASYNC ? NULL : info))
352.27640 + 		return false;
352.27641 + 
352.27642 ++	DBG(("%s: queued flip=%p\n", __FUNCTION__, info->type == FLIP_ASYNC ? NULL : info));
352.27643 ++	assert(info->signal || info->type != FLIP_THROTTLE);
352.27644 ++
352.27645 + 	assert(info->sna->dri2.flip_pending == NULL ||
352.27646 + 	       info->sna->dri2.flip_pending == info);
352.27647 + 	if (info->type != FLIP_ASYNC)
352.27648 +@@ -1505,13 +1984,21 @@ sna_dri2_flip(struct sna_dri2_event *info)
352.27649 + 	tmp_bo = get_private(info->front)->bo;
352.27650 + 	tmp_name = info->front->name;
352.27651 + 	tmp_pitch = info->front->pitch;
352.27652 ++	tmp_flags = info->front->flags;
352.27653 ++
352.27654 ++	assert(tmp_bo->active_scanout > 0);
352.27655 ++	tmp_bo->active_scanout--;
352.27656 + 
352.27657 + 	set_bo(info->sna->front, bo);
352.27658 + 
352.27659 ++	info->front->flags = info->back->flags;
352.27660 + 	info->front->name = info->back->name;
352.27661 + 	info->front->pitch = info->back->pitch;
352.27662 + 	get_private(info->front)->bo = bo;
352.27663 ++	bo->active_scanout++;
352.27664 ++	assert(bo->active_scanout <= bo->refcnt);
352.27665 + 
352.27666 ++	info->back->flags = tmp_flags;
352.27667 + 	info->back->name = tmp_name;
352.27668 + 	info->back->pitch = tmp_pitch;
352.27669 + 	get_private(info->back)->bo = tmp_bo;
352.27670 +@@ -1521,6 +2008,7 @@ sna_dri2_flip(struct sna_dri2_event *info)
352.27671 + 	assert(get_private(info->back)->bo->refcnt);
352.27672 + 	assert(get_private(info->front)->bo != get_private(info->back)->bo);
352.27673 + 
352.27674 ++	info->keepalive = KEEPALIVE;
352.27675 + 	info->queued = true;
352.27676 + 	return true;
352.27677 + }
352.27678 +@@ -1549,15 +2037,16 @@ can_flip(struct sna * sna,
352.27679 + 	}
352.27680 + 
352.27681 + 	assert(sna->scrn->vtSema);
352.27682 ++	assert(!sna->mode.hidden);
352.27683 + 
352.27684 + 	if ((sna->flags & (SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP)) == 0) {
352.27685 + 		DBG(("%s: no, pageflips disabled\n", __FUNCTION__));
352.27686 + 		return false;
352.27687 + 	}
352.27688 + 
352.27689 +-	if (front->format != back->format) {
352.27690 ++	if (front->cpp != back->cpp) {
352.27691 + 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
352.27692 +-		     __FUNCTION__, front->format, back->format));
352.27693 ++		     __FUNCTION__, front->cpp, back->cpp));
352.27694 + 		return false;
352.27695 + 	}
352.27696 + 
352.27697 +@@ -1567,7 +2056,7 @@ can_flip(struct sna * sna,
352.27698 + 	}
352.27699 + 
352.27700 + 	if (!sna_crtc_is_on(crtc)) {
352.27701 +-		DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_to_pipe(crtc)));
352.27702 ++		DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_pipe(crtc)));
352.27703 + 		return false;
352.27704 + 	}
352.27705 + 
352.27706 +@@ -1581,7 +2070,7 @@ can_flip(struct sna * sna,
352.27707 + 	if (sna_pixmap_get_buffer(pixmap) != front) {
352.27708 + 		DBG(("%s: no, DRI2 drawable is no longer attached (old name=%d, new name=%d) to pixmap=%ld\n",
352.27709 + 		     __FUNCTION__, front->name,
352.27710 +-		     sna_pixmap_get_buffer(pixmap) ? ((DRI2BufferPtr)sna_pixmap_get_buffer(pixmap))->name : 0,
352.27711 ++		     sna_pixmap_get_buffer(pixmap) ? sna_pixmap_get_buffer(pixmap)->name : 0,
352.27712 + 		     pixmap->drawable.serialNumber));
352.27713 + 		return false;
352.27714 + 	}
352.27715 +@@ -1661,7 +2150,6 @@ can_flip(struct sna * sna,
352.27716 + 	}
352.27717 + 
352.27718 + 	DBG(("%s: yes, pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber));
352.27719 +-	assert(dri2_window(win)->front == NULL);
352.27720 + 	return true;
352.27721 + }
352.27722 + 
352.27723 +@@ -1680,9 +2168,9 @@ can_xchg(struct sna *sna,
352.27724 + 	if (draw->type == DRAWABLE_PIXMAP)
352.27725 + 		return false;
352.27726 + 
352.27727 +-	if (front->format != back->format) {
352.27728 ++	if (front->cpp != back->cpp) {
352.27729 + 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
352.27730 +-		     __FUNCTION__, front->format, back->format));
352.27731 ++		     __FUNCTION__, front->cpp, back->cpp));
352.27732 + 		return false;
352.27733 + 	}
352.27734 + 
352.27735 +@@ -1714,6 +2202,8 @@ can_xchg(struct sna *sna,
352.27736 + 		return false;
352.27737 + 	}
352.27738 + 
352.27739 ++	DBG(("%s: back size=%x, front size=%x\n",
352.27740 ++	     __FUNCTION__, get_private(back)->size, get_private(front)->size));
352.27741 + 	if (get_private(back)->size != get_private(front)->size) {
352.27742 + 		DBG(("%s: no, back buffer %dx%d does not match front buffer %dx%d\n",
352.27743 + 		     __FUNCTION__,
352.27744 +@@ -1766,9 +2256,9 @@ overlaps_other_crtc(struct sna *sna, xf86CrtcPtr desired)
352.27745 + static bool
352.27746 + can_xchg_crtc(struct sna *sna,
352.27747 + 	      DrawablePtr draw,
352.27748 ++	      xf86CrtcPtr crtc,
352.27749 + 	      DRI2BufferPtr front,
352.27750 +-	      DRI2BufferPtr back,
352.27751 +-	      xf86CrtcPtr crtc)
352.27752 ++	      DRI2BufferPtr back)
352.27753 + {
352.27754 + 	WindowPtr win = (WindowPtr)draw;
352.27755 + 	PixmapPtr pixmap;
352.27756 +@@ -1785,9 +2275,9 @@ can_xchg_crtc(struct sna *sna,
352.27757 + 	if (draw->type == DRAWABLE_PIXMAP)
352.27758 + 		return false;
352.27759 + 
352.27760 +-	if (front->format != back->format) {
352.27761 ++	if (front->cpp != back->cpp) {
352.27762 + 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
352.27763 +-		     __FUNCTION__, front->format, back->format));
352.27764 ++		     __FUNCTION__, front->cpp, back->cpp));
352.27765 + 		return false;
352.27766 + 	}
352.27767 + 
352.27768 +@@ -1866,20 +2356,21 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
352.27769 + 
352.27770 + 	back_bo = get_private(back)->bo;
352.27771 + 	front_bo = get_private(front)->bo;
352.27772 +-	assert(front_bo != back_bo);
352.27773 + 
352.27774 +-	DBG(("%s: win=%ld, exchange front=%d/%d and back=%d/%d, pixmap=%ld %dx%d\n",
352.27775 ++	DBG(("%s: win=%ld, exchange front=%d/%d,ref=%d and back=%d/%d,ref=%d, pixmap=%ld %dx%d\n",
352.27776 + 	     __FUNCTION__, win->drawable.id,
352.27777 +-	     front_bo->handle, front->name,
352.27778 +-	     back_bo->handle, back->name,
352.27779 ++	     front_bo->handle, front->name, get_private(front)->refcnt,
352.27780 ++	     back_bo->handle, back->name, get_private(back)->refcnt,
352.27781 + 	     pixmap->drawable.serialNumber,
352.27782 + 	     pixmap->drawable.width,
352.27783 + 	     pixmap->drawable.height));
352.27784 + 
352.27785 +-	DBG(("%s: back_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
352.27786 +-	     __FUNCTION__, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
352.27787 +-	DBG(("%s: front_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
352.27788 +-	     __FUNCTION__, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
352.27789 ++	DBG(("%s: back_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
352.27790 ++	     __FUNCTION__, back_bo->handle, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
352.27791 ++	DBG(("%s: front_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
352.27792 ++	     __FUNCTION__, front_bo->handle, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
352.27793 ++
352.27794 ++	assert(front_bo != back_bo);
352.27795 + 	assert(front_bo->refcnt);
352.27796 + 	assert(back_bo->refcnt);
352.27797 + 
352.27798 +@@ -1894,6 +2385,11 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
352.27799 + 	get_private(back)->bo = front_bo;
352.27800 + 	mark_stale(back);
352.27801 + 
352.27802 ++	assert(front_bo->active_scanout > 0);
352.27803 ++	front_bo->active_scanout--;
352.27804 ++	back_bo->active_scanout++;
352.27805 ++	assert(back_bo->active_scanout <= back_bo->refcnt);
352.27806 ++
352.27807 + 	tmp = front->name;
352.27808 + 	front->name = back->name;
352.27809 + 	back->name = tmp;
352.27810 +@@ -1902,17 +2398,23 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
352.27811 + 	front->pitch = back->pitch;
352.27812 + 	back->pitch = tmp;
352.27813 + 
352.27814 ++	tmp = front->flags;
352.27815 ++	front->flags = back->flags;
352.27816 ++	back->flags = tmp;
352.27817 ++
352.27818 + 	assert(front_bo->refcnt);
352.27819 + 	assert(back_bo->refcnt);
352.27820 + 
352.27821 ++	assert(front_bo->pitch == get_private(front)->bo->pitch);
352.27822 ++	assert(back_bo->pitch == get_private(back)->bo->pitch);
352.27823 ++
352.27824 + 	assert(get_private(front)->bo == sna_pixmap(pixmap)->gpu_bo);
352.27825 + }
352.27826 + 
352.27827 + static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc, DRI2BufferPtr front, DRI2BufferPtr back)
352.27828 + {
352.27829 + 	WindowPtr win = (WindowPtr)draw;
352.27830 +-	DRI2Buffer2Ptr tmp;
352.27831 +-	struct kgem_bo *bo;
352.27832 ++	struct dri2_window *priv = dri2_window(win);
352.27833 + 
352.27834 + 	DBG(("%s: exchange front=%d/%d and back=%d/%d, win id=%lu, pixmap=%ld %dx%d\n",
352.27835 + 	     __FUNCTION__,
352.27836 +@@ -1922,162 +2424,130 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
352.27837 + 	     get_window_pixmap(win)->drawable.serialNumber,
352.27838 + 	     get_window_pixmap(win)->drawable.width,
352.27839 + 	     get_window_pixmap(win)->drawable.height));
352.27840 ++	assert(can_xchg_crtc(sna, draw, crtc, front, back));
352.27841 + 
352.27842 +-	DamageRegionAppend(&win->drawable, &win->clipList);
352.27843 ++	if (APPLY_DAMAGE) {
352.27844 ++		DBG(("%s: marking drawable as damaged\n", __FUNCTION__));
352.27845 ++		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
352.27846 ++		DamageRegionAppend(&win->drawable, &win->clipList);
352.27847 ++	}
352.27848 + 	sna_shadow_set_crtc(sna, crtc, get_private(back)->bo);
352.27849 +-	DamageRegionProcessPending(&win->drawable);
352.27850 ++	if (APPLY_DAMAGE) {
352.27851 ++		sna->ignore_copy_area = false;
352.27852 ++		DamageRegionProcessPending(&win->drawable);
352.27853 ++	}
352.27854 + 
352.27855 +-	assert(dri2_window(win)->front == NULL);
352.27856 ++	if (priv->front == NULL) {
352.27857 ++		DRI2Buffer2Ptr tmp;
352.27858 + 
352.27859 +-	tmp = calloc(1, sizeof(*tmp) + sizeof(struct sna_dri2_private));
352.27860 +-	if (tmp == NULL) {
352.27861 +-		back->attachment = -1;
352.27862 +-		if (get_private(back)->proxy == NULL) {
352.27863 +-			get_private(back)->pixmap = get_window_pixmap(win);
352.27864 +-			get_private(back)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(back)->pixmap));
352.27865 ++		tmp = calloc(1, sizeof(*tmp) + sizeof(struct sna_dri2_private));
352.27866 ++		if (tmp == NULL) {
352.27867 ++			sna_shadow_unset_crtc(sna, crtc);
352.27868 ++			return;
352.27869 + 		}
352.27870 +-		dri2_window(win)->front = sna_dri2_reference_buffer(back);
352.27871 +-		return;
352.27872 +-	}
352.27873 + 
352.27874 +-	*tmp = *back;
352.27875 +-	tmp->attachment = DRI2BufferFrontLeft;
352.27876 +-	tmp->driverPrivate = tmp + 1;
352.27877 +-	get_private(tmp)->refcnt = 1;
352.27878 +-	get_private(tmp)->bo = get_private(back)->bo;
352.27879 +-	get_private(tmp)->size = get_private(back)->size;
352.27880 +-	get_private(tmp)->pixmap = get_window_pixmap(win);
352.27881 +-	get_private(tmp)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(tmp)->pixmap));
352.27882 +-	dri2_window(win)->front = tmp;
352.27883 +-
352.27884 +-	DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
352.27885 +-	back->name = 0;
352.27886 +-	bo = kgem_create_2d(&sna->kgem,
352.27887 +-			    draw->width, draw->height, draw->bitsPerPixel,
352.27888 +-			    get_private(back)->bo->tiling,
352.27889 +-			    CREATE_SCANOUT);
352.27890 +-	if (bo != NULL) {
352.27891 +-		get_private(back)->bo = bo;
352.27892 +-		back->pitch = bo->pitch;
352.27893 +-		back->name = kgem_bo_flink(&sna->kgem, bo);
352.27894 +-	}
352.27895 +-	if (back->name == 0) {
352.27896 +-		if (bo != NULL)
352.27897 +-			kgem_bo_destroy(&sna->kgem, bo);
352.27898 +-		get_private(back)->bo = NULL;
352.27899 +-		back->attachment = -1;
352.27900 ++		tmp->attachment = DRI2BufferFrontLeft;
352.27901 ++		tmp->driverPrivate = tmp + 1;
352.27902 ++		tmp->cpp = back->cpp;
352.27903 ++		tmp->format = back->format;
352.27904 ++
352.27905 ++		get_private(tmp)->refcnt = 1;
352.27906 ++		get_private(tmp)->bo = kgem_create_2d(&sna->kgem,
352.27907 ++						      draw->width, draw->height, draw->bitsPerPixel,
352.27908 ++						      get_private(back)->bo->tiling,
352.27909 ++						      CREATE_SCANOUT | CREATE_EXACT);
352.27910 ++		if (get_private(tmp)->bo != NULL) {
352.27911 ++			tmp->pitch = get_private(tmp)->bo->pitch;
352.27912 ++			tmp->name = kgem_bo_flink(&sna->kgem, get_private(tmp)->bo);
352.27913 ++		}
352.27914 ++		if (tmp->name == 0) {
352.27915 ++			if (get_private(tmp)->bo != NULL)
352.27916 ++				kgem_bo_destroy(&sna->kgem, get_private(tmp)->bo);
352.27917 ++			sna_shadow_unset_crtc(sna, crtc);
352.27918 ++			return;
352.27919 ++		}
352.27920 ++		get_private(tmp)->size = get_private(back)->size;
352.27921 ++		get_private(tmp)->pixmap = get_private(front)->pixmap;
352.27922 ++		get_private(tmp)->proxy = sna_dri2_reference_buffer(front);
352.27923 ++		get_private(tmp)->bo->active_scanout++;
352.27924 ++
352.27925 ++		priv->front = front = tmp;
352.27926 + 	}
352.27927 +-}
352.27928 ++	assert(front == priv->front);
352.27929 + 
352.27930 +-static void frame_swap_complete(struct sna_dri2_event *frame, int type)
352.27931 +-{
352.27932 +-	const struct ust_msc *swap;
352.27933 ++	{
352.27934 ++		struct kgem_bo *front_bo = get_private(front)->bo;
352.27935 ++		struct kgem_bo *back_bo = get_private(back)->bo;
352.27936 ++		unsigned tmp;
352.27937 + 
352.27938 +-	if (frame->draw == NULL)
352.27939 +-		return;
352.27940 ++		assert(front_bo->refcnt);
352.27941 ++		assert(back_bo->refcnt);
352.27942 + 
352.27943 +-	assert(frame->client);
352.27944 ++		get_private(back)->bo = front_bo;
352.27945 ++		get_private(front)->bo = back_bo;
352.27946 ++		mark_stale(back);
352.27947 + 
352.27948 +-	swap = sna_crtc_last_swap(frame->crtc);
352.27949 +-	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc=%lld], tv=%d.%06d\n",
352.27950 +-	     __FUNCTION__, type, (long)frame->draw, frame->pipe,
352.27951 +-	     (long long)swap->msc,
352.27952 +-	     (long long)draw_current_msc(frame->draw, frame->crtc, swap->msc),
352.27953 +-	     swap->tv_sec, swap->tv_usec));
352.27954 ++		assert(front_bo->active_scanout > 0);
352.27955 ++		front_bo->active_scanout--;
352.27956 ++		back_bo->active_scanout++;
352.27957 ++		assert(back_bo->active_scanout <= back_bo->refcnt);
352.27958 + 
352.27959 +-	DRI2SwapComplete(frame->client, frame->draw,
352.27960 +-			 draw_current_msc(frame->draw, frame->crtc, swap->msc),
352.27961 +-			 swap->tv_sec, swap->tv_usec,
352.27962 +-			 type, frame->event_complete, frame->event_data);
352.27963 +-}
352.27964 ++		tmp = front->name;
352.27965 ++		front->name = back->name;
352.27966 ++		back->name = tmp;
352.27967 + 
352.27968 +-static void fake_swap_complete(struct sna *sna, ClientPtr client,
352.27969 +-			       DrawablePtr draw, xf86CrtcPtr crtc,
352.27970 +-			       int type, DRI2SwapEventPtr func, void *data)
352.27971 +-{
352.27972 +-	const struct ust_msc *swap;
352.27973 +-
352.27974 +-	swap = sna_crtc_last_swap(crtc);
352.27975 +-	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n",
352.27976 +-	     __FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_to_pipe(crtc) : -1,
352.27977 +-	     (long long)swap->msc,
352.27978 +-	     (long long)draw_current_msc(draw, crtc, swap->msc),
352.27979 +-	     swap->tv_sec, swap->tv_usec));
352.27980 ++		tmp = front->pitch;
352.27981 ++		front->pitch = back->pitch;
352.27982 ++		back->pitch = tmp;
352.27983 + 
352.27984 +-	DRI2SwapComplete(client, draw,
352.27985 +-			 draw_current_msc(draw, crtc, swap->msc),
352.27986 +-			 swap->tv_sec, swap->tv_usec,
352.27987 +-			 type, func, data);
352.27988 ++		tmp = front->flags;
352.27989 ++		front->flags = back->flags;
352.27990 ++		back->flags = tmp;
352.27991 ++	}
352.27992 + }
352.27993 + 
352.27994 + static void chain_swap(struct sna_dri2_event *chain)
352.27995 + {
352.27996 +-	union drm_wait_vblank vbl;
352.27997 ++	DBG(("%s: draw=%ld, queued?=%d, type=%d\n",
352.27998 ++	     __FUNCTION__, (long)chain->draw->id, chain->queued, chain->type));
352.27999 ++
352.28000 ++	if (chain->queued) /* too early! */
352.28001 ++		return;
352.28002 + 
352.28003 + 	if (chain->draw == NULL) {
352.28004 + 		sna_dri2_event_free(chain);
352.28005 + 		return;
352.28006 + 	}
352.28007 + 
352.28008 +-	if (chain->queued) /* too early! */
352.28009 +-		return;
352.28010 +-
352.28011 + 	assert(chain == dri2_chain(chain->draw));
352.28012 +-	DBG(("%s: chaining draw=%ld, type=%d\n",
352.28013 +-	     __FUNCTION__, (long)chain->draw->id, chain->type));
352.28014 +-	chain->queued = true;
352.28015 ++	assert(chain->signal);
352.28016 + 
352.28017 + 	switch (chain->type) {
352.28018 +-	case SWAP_THROTTLE:
352.28019 ++	case SWAP_COMPLETE:
352.28020 + 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
352.28021 +-		if (chain->sna->mode.shadow &&
352.28022 +-		    !chain->sna->mode.shadow_damage) {
352.28023 +-			/* recursed from wait_for_shadow(), simply requeue */
352.28024 +-			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
352.28025 +-			VG_CLEAR(vbl);
352.28026 +-			vbl.request.type =
352.28027 +-				DRM_VBLANK_RELATIVE |
352.28028 +-				DRM_VBLANK_EVENT;
352.28029 +-			vbl.request.sequence = 1;
352.28030 +-			vbl.request.signal = (uintptr_t)chain;
352.28031 +-
352.28032 +-			if (!sna_wait_vblank(chain->sna, &vbl, chain->pipe))
352.28033 +-				return;
352.28034 +-
352.28035 +-			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
352.28036 +-		}
352.28037 +-
352.28038 + 		if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
352.28039 + 			sna_dri2_xchg(chain->draw, chain->front, chain->back);
352.28040 +-		} else if (can_xchg_crtc(chain->sna, chain->draw, chain->front, chain->back, chain->crtc)) {
352.28041 +-			sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc, chain->front, chain->back);
352.28042 ++		} else if (can_xchg_crtc(chain->sna, chain->draw, chain->crtc,
352.28043 ++					 chain->front, chain->back)) {
352.28044 ++			sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc,
352.28045 ++					   chain->front, chain->back);
352.28046 + 		} else {
352.28047 +-			assert(chain->queued);
352.28048 +-			chain->bo = __sna_dri2_copy_region(chain->sna, chain->draw, NULL,
352.28049 +-							   chain->back, chain->front,
352.28050 +-							   true);
352.28051 ++			__sna_dri2_copy_event(chain, chain->sync | DRI2_BO);
352.28052 + 		}
352.28053 ++		assert(get_private(chain->back)->bo != get_private(chain->front)->bo);
352.28054 + 	case SWAP:
352.28055 + 		break;
352.28056 + 	default:
352.28057 + 		return;
352.28058 + 	}
352.28059 + 
352.28060 +-	VG_CLEAR(vbl);
352.28061 +-	vbl.request.type =
352.28062 +-		DRM_VBLANK_RELATIVE |
352.28063 +-		DRM_VBLANK_EVENT;
352.28064 +-	vbl.request.sequence = 1;
352.28065 +-	vbl.request.signal = (uintptr_t)chain;
352.28066 +-	if (sna_wait_vblank(chain->sna, &vbl, chain->pipe)) {
352.28067 ++	if ((chain->type == SWAP_COMPLETE &&
352.28068 ++	     !swap_limit(chain->draw, 2 + !chain->sync) &&
352.28069 ++	     !chain->sync) ||
352.28070 ++	    !sna_next_vblank(chain)) {
352.28071 + 		DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
352.28072 + 		frame_swap_complete(chain, DRI2_BLIT_COMPLETE);
352.28073 + 		sna_dri2_event_free(chain);
352.28074 +-	} else {
352.28075 +-		if (chain->type == SWAP_THROTTLE && !swap_limit(chain->draw, 2)) {
352.28076 +-			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28077 +-			frame_swap_complete(chain, DRI2_BLIT_COMPLETE);
352.28078 +-		}
352.28079 + 	}
352.28080 + }
352.28081 + 
352.28082 +@@ -2086,40 +2556,27 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
352.28083 + 	if (bo == NULL)
352.28084 + 		return false;
352.28085 + 
352.28086 +-	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
352.28087 +-	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
352.28088 +-	assert(bo->refcnt);
352.28089 +-
352.28090 +-	if (bo->exec)
352.28091 +-		return true;
352.28092 +-
352.28093 +-	if (bo->rq == NULL)
352.28094 +-		return false;
352.28095 +-
352.28096 +-	return __kgem_busy(kgem, bo->handle);
352.28097 ++	return __kgem_bo_is_busy(kgem, bo);
352.28098 + }
352.28099 + 
352.28100 +-static bool sna_dri2_blit_complete(struct sna *sna,
352.28101 +-				   struct sna_dri2_event *info)
352.28102 ++static bool sna_dri2_blit_complete(struct sna_dri2_event *info)
352.28103 + {
352.28104 +-	if (rq_is_busy(&sna->kgem, info->bo)) {
352.28105 +-		union drm_wait_vblank vbl;
352.28106 ++	if (!info->bo)
352.28107 ++		return true;
352.28108 + 
352.28109 ++	if (__kgem_bo_is_busy(&info->sna->kgem, info->bo)) {
352.28110 + 		DBG(("%s: vsync'ed blit is still busy, postponing\n",
352.28111 + 		     __FUNCTION__));
352.28112 +-
352.28113 +-		VG_CLEAR(vbl);
352.28114 +-		vbl.request.type =
352.28115 +-			DRM_VBLANK_RELATIVE |
352.28116 +-			DRM_VBLANK_EVENT;
352.28117 +-		vbl.request.sequence = 1;
352.28118 +-		vbl.request.signal = (uintptr_t)info;
352.28119 +-		assert(info->queued);
352.28120 +-		if (!sna_wait_vblank(sna, &vbl, info->pipe))
352.28121 ++		if (sna_next_vblank(info))
352.28122 + 			return false;
352.28123 ++
352.28124 ++		kgem_bo_sync__gtt(&info->sna->kgem, info->bo);
352.28125 + 	}
352.28126 + 
352.28127 + 	DBG(("%s: blit finished\n", __FUNCTION__));
352.28128 ++	kgem_bo_destroy(&info->sna->kgem, info->bo);
352.28129 ++	info->bo = NULL;
352.28130 ++
352.28131 + 	return true;
352.28132 + }
352.28133 + 
352.28134 +@@ -2128,11 +2585,12 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
352.28135 + 	struct sna_dri2_event *info = (void *)(uintptr_t)event->user_data;
352.28136 + 	struct sna *sna = info->sna;
352.28137 + 	DrawablePtr draw;
352.28138 +-	union drm_wait_vblank vbl;
352.28139 + 	uint64_t msc;
352.28140 + 
352.28141 +-	DBG(("%s(type=%d, sequence=%d)\n", __FUNCTION__, info->type, event->sequence));
352.28142 ++	DBG(("%s(type=%d, sequence=%d, draw=%ld)\n", __FUNCTION__, info->type, event->sequence, info->draw ? info->draw->serialNumber : 0));
352.28143 + 	assert(info->queued);
352.28144 ++	info->queued = false;
352.28145 ++
352.28146 + 	msc = sna_crtc_record_event(info->crtc, event);
352.28147 + 
352.28148 + 	draw = info->draw;
352.28149 +@@ -2141,68 +2599,120 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
352.28150 + 		goto done;
352.28151 + 	}
352.28152 + 
352.28153 ++	assert((info->front == NULL && info->back == NULL) || info->front != info->back);
352.28154 + 	switch (info->type) {
352.28155 + 	case FLIP:
352.28156 + 		/* If we can still flip... */
352.28157 ++		assert(info->signal);
352.28158 + 		if (can_flip(sna, draw, info->front, info->back, info->crtc) &&
352.28159 + 		    sna_dri2_flip(info))
352.28160 + 			return;
352.28161 + 
352.28162 + 		/* else fall through to blit */
352.28163 + 	case SWAP:
352.28164 +-		assert(info->queued);
352.28165 +-		if (sna->mode.shadow && !sna->mode.shadow_damage) {
352.28166 +-			/* recursed from wait_for_shadow(), simply requeue */
352.28167 +-			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
352.28168 +-
352.28169 +-		} else if (can_xchg(info->sna, draw, info->front, info->back)) {
352.28170 ++		assert(info->signal);
352.28171 ++		if (can_xchg(info->sna, draw, info->front, info->back)) {
352.28172 + 			sna_dri2_xchg(draw, info->front, info->back);
352.28173 +-			info->type = SWAP_WAIT;
352.28174 +-		} else if (can_xchg_crtc(sna, draw, info->front, info->back, info->crtc)) {
352.28175 +-			sna_dri2_xchg_crtc(sna, draw, info->crtc, info->front, info->back);
352.28176 +-			info->type = SWAP_WAIT;
352.28177 ++			info->type = SWAP_COMPLETE;
352.28178 ++		} else if (can_xchg_crtc(sna, draw, info->crtc,
352.28179 ++					 info->front, info->back)) {
352.28180 ++			sna_dri2_xchg_crtc(sna, draw, info->crtc,
352.28181 ++					   info->front, info->back);
352.28182 ++			info->type = SWAP_COMPLETE;
352.28183 + 		}  else {
352.28184 +-			assert(info->queued);
352.28185 +-			info->bo = __sna_dri2_copy_region(sna, draw, NULL,
352.28186 +-							  info->back, info->front, true);
352.28187 +-			info->type = SWAP_WAIT;
352.28188 ++			__sna_dri2_copy_event(info, DRI2_BO | DRI2_SYNC);
352.28189 ++			info->type = SWAP_COMPLETE;
352.28190 + 		}
352.28191 + 
352.28192 +-		VG_CLEAR(vbl);
352.28193 +-		vbl.request.type =
352.28194 +-			DRM_VBLANK_RELATIVE |
352.28195 +-			DRM_VBLANK_EVENT;
352.28196 +-		vbl.request.sequence = 1;
352.28197 +-		vbl.request.signal = (uintptr_t)info;
352.28198 +-
352.28199 +-		assert(info->queued);
352.28200 +-		if (!sna_wait_vblank(sna, &vbl, info->pipe))
352.28201 ++		if (sna_next_vblank(info))
352.28202 + 			return;
352.28203 + 
352.28204 + 		DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
352.28205 ++		assert(info->pending.bo == NULL);
352.28206 ++		assert(info->keepalive == 1);
352.28207 + 		/* fall through to SwapComplete */
352.28208 +-	case SWAP_WAIT:
352.28209 +-		if (!sna_dri2_blit_complete(sna, info))
352.28210 +-			return;
352.28211 +-
352.28212 +-		DBG(("%s: swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
352.28213 +-		     event->sequence, event->tv_sec, event->tv_usec));
352.28214 +-		frame_swap_complete(info, DRI2_BLIT_COMPLETE);
352.28215 +-		break;
352.28216 +-
352.28217 +-	case SWAP_THROTTLE:
352.28218 ++	case SWAP_COMPLETE:
352.28219 + 		DBG(("%s: %d complete, frame=%d tv=%d.%06d\n",
352.28220 + 		     __FUNCTION__, info->type,
352.28221 + 		     event->sequence, event->tv_sec, event->tv_usec));
352.28222 + 
352.28223 +-		if (xorg_can_triple_buffer()) {
352.28224 +-			if (!sna_dri2_blit_complete(sna, info))
352.28225 ++		if (info->signal) {
352.28226 ++			if (!sna_dri2_blit_complete(info))
352.28227 + 				return;
352.28228 + 
352.28229 + 			DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
352.28230 + 			     event->sequence, event->tv_sec, event->tv_usec));
352.28231 + 			frame_swap_complete(info, DRI2_BLIT_COMPLETE);
352.28232 + 		}
352.28233 ++
352.28234 ++		if (info->pending.bo) {
352.28235 ++			struct copy current_back;
352.28236 ++
352.28237 ++			DBG(("%s: swapping back handle=%d [name=%d, active=%d] for pending handle=%d [name=%d, active=%d], front handle=%d [name=%d, active=%d]\n",
352.28238 ++			     __FUNCTION__,
352.28239 ++			     get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
352.28240 ++			     info->pending.bo->handle, info->pending.name, info->pending.bo->active_scanout,
352.28241 ++			     get_private(info->front)->bo->handle, info->front->name, get_private(info->front)->bo->active_scanout));
352.28242 ++
352.28243 ++			assert(info->pending.bo->active_scanout > 0);
352.28244 ++			info->pending.bo->active_scanout--;
352.28245 ++
352.28246 ++			current_back.bo = get_private(info->back)->bo;
352.28247 ++			current_back.size = get_private(info->back)->size;
352.28248 ++			current_back.name = info->back->name;
352.28249 ++			current_back.flags = info->back->flags;
352.28250 ++
352.28251 ++			get_private(info->back)->bo = info->pending.bo;
352.28252 ++			get_private(info->back)->size = info->pending.size;
352.28253 ++			info->back->name = info->pending.name;
352.28254 ++			info->back->pitch = info->pending.bo->pitch;
352.28255 ++			info->back->flags = info->pending.flags;
352.28256 ++			info->pending.bo = NULL;
352.28257 ++
352.28258 ++			assert(get_private(info->back)->bo != get_private(info->front)->bo);
352.28259 ++
352.28260 ++			if (can_xchg(info->sna, info->draw, info->front, info->back))
352.28261 ++				sna_dri2_xchg(info->draw, info->front, info->back);
352.28262 ++			else if (can_xchg_crtc(info->sna, info->draw, info->crtc,
352.28263 ++						 info->front, info->back))
352.28264 ++				sna_dri2_xchg_crtc(info->sna, info->draw, info->crtc,
352.28265 ++						   info->front, info->back);
352.28266 ++			else
352.28267 ++				__sna_dri2_copy_event(info, info->sync | DRI2_BO);
352.28268 ++
352.28269 ++			sna_dri2_cache_bo(info->sna, info->draw,
352.28270 ++					  get_private(info->back)->bo,
352.28271 ++					  info->back->name,
352.28272 ++					  get_private(info->back)->size,
352.28273 ++					  info->back->flags);
352.28274 ++
352.28275 ++			get_private(info->back)->bo = current_back.bo;
352.28276 ++			get_private(info->back)->size = current_back.size;
352.28277 ++			info->back->name = current_back.name;
352.28278 ++			info->back->pitch = current_back.bo->pitch;
352.28279 ++			info->back->flags = current_back.flags;
352.28280 ++
352.28281 ++			DBG(("%s: restored current back handle=%d [name=%d, active=%d], active=%d], front handle=%d [name=%d, active=%d]\n",
352.28282 ++			     __FUNCTION__,
352.28283 ++			     get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
352.28284 ++			     get_private(info->front)->bo->handle, info->front->name, get_private(info->front)->bo->active_scanout));
352.28285 ++
352.28286 ++			assert(info->draw);
352.28287 ++			assert(!info->signal);
352.28288 ++			info->keepalive++;
352.28289 ++			info->signal = true;
352.28290 ++		}
352.28291 ++
352.28292 ++		if (--info->keepalive) {
352.28293 ++			if (sna_next_vblank(info))
352.28294 ++				return;
352.28295 ++
352.28296 ++			if (info->signal) {
352.28297 ++				DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
352.28298 ++				     event->sequence, event->tv_sec, event->tv_usec));
352.28299 ++				frame_swap_complete(info, DRI2_BLIT_COMPLETE);
352.28300 ++			}
352.28301 ++		}
352.28302 + 		break;
352.28303 + 
352.28304 + 	case WAITMSC:
352.28305 +@@ -2218,11 +2728,11 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
352.28306 + 	}
352.28307 + 
352.28308 + 	if (info->chain) {
352.28309 ++		DBG(("%s: continuing chain\n", __FUNCTION__));
352.28310 + 		assert(info->chain != info);
352.28311 + 		assert(info->draw == draw);
352.28312 +-		sna_dri2_remove_event((WindowPtr)draw, info);
352.28313 ++		sna_dri2_remove_event(info);
352.28314 + 		chain_swap(info->chain);
352.28315 +-		info->draw = NULL;
352.28316 + 	}
352.28317 + 
352.28318 + done:
352.28319 +@@ -2230,101 +2740,148 @@ done:
352.28320 + 	DBG(("%s complete\n", __FUNCTION__));
352.28321 + }
352.28322 + 
352.28323 +-static bool
352.28324 ++static void
352.28325 + sna_dri2_immediate_blit(struct sna *sna,
352.28326 + 			struct sna_dri2_event *info,
352.28327 +-			bool sync, bool event)
352.28328 ++			bool sync)
352.28329 + {
352.28330 +-	DrawablePtr draw = info->draw;
352.28331 +-	bool ret = false;
352.28332 ++	struct sna_dri2_event *chain = dri2_chain(info->draw);
352.28333 + 
352.28334 + 	if (sna->flags & SNA_NO_WAIT)
352.28335 + 		sync = false;
352.28336 + 
352.28337 +-	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, send-event? %d\n",
352.28338 +-	     __FUNCTION__, sync, dri2_chain(draw) != info,
352.28339 +-	     event));
352.28340 ++	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, pipe %d\n",
352.28341 ++	     __FUNCTION__, sync, chain != info, info->pipe));
352.28342 ++	assert(chain);
352.28343 + 
352.28344 +-	info->type = SWAP_THROTTLE;
352.28345 +-	if (!sync || dri2_chain(draw) == info) {
352.28346 +-		DBG(("%s: no pending blit, starting chain\n",
352.28347 +-		     __FUNCTION__));
352.28348 ++	info->type = SWAP_COMPLETE;
352.28349 ++	info->sync = sync;
352.28350 ++	info->keepalive = KEEPALIVE;
352.28351 + 
352.28352 +-		info->queued = true;
352.28353 +-		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
352.28354 +-						  info->back,
352.28355 +-						  info->front,
352.28356 +-						  sync);
352.28357 +-		if (event) {
352.28358 +-			if (sync) {
352.28359 +-				union drm_wait_vblank vbl;
352.28360 +-
352.28361 +-				VG_CLEAR(vbl);
352.28362 +-				vbl.request.type =
352.28363 +-					DRM_VBLANK_RELATIVE |
352.28364 +-					DRM_VBLANK_EVENT;
352.28365 +-				vbl.request.sequence = 1;
352.28366 +-				vbl.request.signal = (uintptr_t)info;
352.28367 +-				ret = !sna_wait_vblank(sna, &vbl, info->pipe);
352.28368 +-				if (ret)
352.28369 +-					event = !swap_limit(draw, 2);
352.28370 +-			}
352.28371 +-			if (event) {
352.28372 +-				DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28373 +-				frame_swap_complete(info, DRI2_BLIT_COMPLETE);
352.28374 +-			}
352.28375 ++	if (chain == info) {
352.28376 ++		DBG(("%s: no pending blit, starting chain\n", __FUNCTION__));
352.28377 ++
352.28378 ++		assert(info->front != info->back);
352.28379 ++		if (can_xchg(info->sna, info->draw, info->front, info->back)) {
352.28380 ++			sna_dri2_xchg(info->draw, info->front, info->back);
352.28381 ++		} else if (can_xchg_crtc(info->sna, info->draw, info->crtc,
352.28382 ++					 info->front, info->back)) {
352.28383 ++			sna_dri2_xchg_crtc(info->sna, info->draw, info->crtc,
352.28384 ++					   info->front, info->back);
352.28385 ++		} else
352.28386 ++			__sna_dri2_copy_event(info, sync | DRI2_BO);
352.28387 ++
352.28388 ++		assert(info->signal);
352.28389 ++
352.28390 ++		if ((!swap_limit(info->draw, 2 + !sync) && !sync) ||
352.28391 ++		    !sna_next_vblank(info)) {
352.28392 ++			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28393 ++			frame_swap_complete(info, DRI2_BLIT_COMPLETE);
352.28394 ++			sna_dri2_event_free(info);
352.28395 ++		}
352.28396 ++		return;
352.28397 ++	}
352.28398 ++
352.28399 ++	DBG(("%s: current event front=%d [name=%d, active?=%d], back=%d [name=%d, active?=%d]\n", __FUNCTION__,
352.28400 ++	     get_private(chain->front)->bo->handle, chain->front->name, get_private(chain->front)->bo->active_scanout,
352.28401 ++	     get_private(chain->back)->bo->handle, chain->back->name, get_private(chain->back)->bo->active_scanout));
352.28402 ++
352.28403 ++	if (chain->type == SWAP_COMPLETE && chain->front == info->front) {
352.28404 ++		assert(chain->draw == info->draw);
352.28405 ++		assert(chain->client == info->client);
352.28406 ++		assert(chain->event_complete == info->event_complete);
352.28407 ++		assert(chain->event_data == info->event_data);
352.28408 ++		assert(chain->queued);
352.28409 ++
352.28410 ++		if ((!sync || !chain->sync) && chain->pending.bo) {
352.28411 ++			bool signal = chain->signal;
352.28412 ++
352.28413 ++			DBG(("%s: swap elision, unblocking client\n", __FUNCTION__));
352.28414 ++			assert(chain->draw);
352.28415 ++			chain->signal = true;
352.28416 ++			frame_swap_complete(chain, DRI2_EXCHANGE_COMPLETE);
352.28417 ++			chain->signal = signal;
352.28418 ++
352.28419 ++			assert(chain->pending.bo->active_scanout > 0);
352.28420 ++			chain->pending.bo->active_scanout--;
352.28421 ++
352.28422 ++			sna_dri2_cache_bo(chain->sna, chain->draw,
352.28423 ++					  chain->pending.bo,
352.28424 ++					  chain->pending.name,
352.28425 ++					  chain->pending.size,
352.28426 ++					  chain->pending.flags);
352.28427 ++			chain->pending.bo = NULL;
352.28428 ++		}
352.28429 ++
352.28430 ++		if (chain->pending.bo == NULL && swap_limit(info->draw, 2 + !sync)) {
352.28431 ++			DBG(("%s: setting handle=%d as pending blit (current event front=%d, back=%d)\n", __FUNCTION__,
352.28432 ++			     get_private(info->back)->bo->handle,
352.28433 ++			     get_private(chain->front)->bo->handle,
352.28434 ++			     get_private(chain->back)->bo->handle));
352.28435 ++			chain->pending.bo = ref(get_private(info->back)->bo);
352.28436 ++			chain->pending.size = get_private(info->back)->size;
352.28437 ++			chain->pending.name = info->back->name;
352.28438 ++			chain->pending.flags = info->back->flags;
352.28439 ++			chain->sync = sync;
352.28440 ++			info->signal = false; /* transfer signal to pending */
352.28441 ++
352.28442 ++			/* Prevent us from handing it back on next GetBuffers */
352.28443 ++			chain->pending.bo->active_scanout++;
352.28444 ++
352.28445 ++			sna_dri2_event_free(info);
352.28446 ++			return;
352.28447 + 		}
352.28448 +-	} else {
352.28449 +-		DBG(("%s: pending blit, chained\n", __FUNCTION__));
352.28450 +-		ret = true;
352.28451 + 	}
352.28452 + 
352.28453 +-	DBG(("%s: continue? %d\n", __FUNCTION__, ret));
352.28454 +-	return ret;
352.28455 ++	DBG(("%s: pending blit, chained\n", __FUNCTION__));
352.28456 + }
352.28457 + 
352.28458 + static bool
352.28459 + sna_dri2_flip_continue(struct sna_dri2_event *info)
352.28460 + {
352.28461 +-	DBG(("%s(mode=%d)\n", __FUNCTION__, info->mode));
352.28462 ++	struct kgem_bo *bo = get_private(info->front)->bo;
352.28463 + 
352.28464 +-	if (info->mode > 0){
352.28465 +-		struct kgem_bo *bo = get_private(info->front)->bo;
352.28466 ++	DBG(("%s(mode=%d)\n", __FUNCTION__, info->flip_continue));
352.28467 ++	assert(info->flip_continue > 0);
352.28468 ++	info->type = info->flip_continue;
352.28469 ++	info->flip_continue = 0;
352.28470 + 
352.28471 +-		info->type = info->mode;
352.28472 ++	assert(!info->signal);
352.28473 ++	info->signal = info->type == FLIP_THROTTLE && info->draw;
352.28474 + 
352.28475 +-		if (bo != sna_pixmap(info->sna->front)->gpu_bo)
352.28476 +-			return false;
352.28477 ++	if (info->sna->mode.front_active == 0)
352.28478 ++		return false;
352.28479 + 
352.28480 +-		if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
352.28481 +-			return false;
352.28482 ++	if (bo != sna_pixmap(info->sna->front)->gpu_bo)
352.28483 ++		return false;
352.28484 + 
352.28485 +-		assert(info->sna->dri2.flip_pending == NULL ||
352.28486 +-		       info->sna->dri2.flip_pending == info);
352.28487 +-		info->sna->dri2.flip_pending = info;
352.28488 +-		assert(info->queued);
352.28489 +-	} else {
352.28490 +-		info->type = -info->mode;
352.28491 ++	assert(!info->queued);
352.28492 ++	if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
352.28493 ++		return false;
352.28494 + 
352.28495 +-		if (!info->draw)
352.28496 +-			return false;
352.28497 ++	DBG(("%s: queued flip=%p\n", __FUNCTION__, info));
352.28498 ++	assert(info->sna->dri2.flip_pending == NULL ||
352.28499 ++	       info->sna->dri2.flip_pending == info);
352.28500 ++	info->sna->dri2.flip_pending = info;
352.28501 ++	info->queued = true;
352.28502 + 
352.28503 +-		if (!can_flip(info->sna, info->draw, info->front, info->back, info->crtc))
352.28504 +-			return false;
352.28505 ++	return true;
352.28506 ++}
352.28507 + 
352.28508 +-		assert(sna_pixmap_get_buffer(get_drawable_pixmap(info->draw)) == info->front);
352.28509 +-		if (!sna_dri2_flip(info))
352.28510 +-			return false;
352.28511 ++static bool
352.28512 ++sna_dri2_flip_keepalive(struct sna_dri2_event *info)
352.28513 ++{
352.28514 ++	DBG(("%s(keepalive?=%d)\n", __FUNCTION__, info->keepalive-1));
352.28515 ++	assert(info->keepalive > 0);
352.28516 ++	if (!--info->keepalive)
352.28517 ++		return false;
352.28518 + 
352.28519 +-		if (!xorg_can_triple_buffer()) {
352.28520 +-			sna_dri2_get_back(info->sna, info->draw, info->back, info);
352.28521 +-			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28522 +-			frame_swap_complete(info, DRI2_FLIP_COMPLETE);
352.28523 +-		}
352.28524 +-	}
352.28525 ++	if (info->draw == NULL)
352.28526 ++		return false;
352.28527 + 
352.28528 +-	info->mode = 0;
352.28529 +-	return true;
352.28530 ++	DBG(("%s: marking next flip as complete\n", __FUNCTION__));
352.28531 ++	info->flip_continue = FLIP_COMPLETE;
352.28532 ++	return sna_dri2_flip_continue(info);
352.28533 + }
352.28534 + 
352.28535 + static void chain_flip(struct sna *sna)
352.28536 +@@ -2332,8 +2889,8 @@ static void chain_flip(struct sna *sna)
352.28537 + 	struct sna_dri2_event *chain = sna->dri2.flip_pending;
352.28538 + 
352.28539 + 	assert(chain->type == FLIP);
352.28540 +-	DBG(("%s: chaining type=%d, cancelled?=%d\n",
352.28541 +-	     __FUNCTION__, chain->type, chain->draw == NULL));
352.28542 ++	DBG(("%s: chaining type=%d, cancelled?=%d window=%ld\n",
352.28543 ++	     __FUNCTION__, chain->type, chain->draw == NULL, chain->draw ? chain->draw->id : 0));
352.28544 + 
352.28545 + 	sna->dri2.flip_pending = NULL;
352.28546 + 	if (chain->draw == NULL) {
352.28547 +@@ -2343,31 +2900,18 @@ static void chain_flip(struct sna *sna)
352.28548 + 
352.28549 + 	assert(chain == dri2_chain(chain->draw));
352.28550 + 	assert(!chain->queued);
352.28551 +-	chain->queued = true;
352.28552 + 
352.28553 + 	if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
352.28554 + 	    sna_dri2_flip(chain)) {
352.28555 + 		DBG(("%s: performing chained flip\n", __FUNCTION__));
352.28556 + 	} else {
352.28557 + 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
352.28558 +-		chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
352.28559 +-						  chain->back, chain->front,
352.28560 +-						  true);
352.28561 ++		__sna_dri2_copy_event(chain, DRI2_SYNC);
352.28562 + 
352.28563 + 		if (xorg_can_triple_buffer()) {
352.28564 +-			union drm_wait_vblank vbl;
352.28565 +-
352.28566 +-			VG_CLEAR(vbl);
352.28567 +-
352.28568 +-			chain->type = SWAP_WAIT;
352.28569 +-			vbl.request.type =
352.28570 +-				DRM_VBLANK_RELATIVE |
352.28571 +-				DRM_VBLANK_EVENT;
352.28572 +-			vbl.request.sequence = 1;
352.28573 +-			vbl.request.signal = (uintptr_t)chain;
352.28574 +-
352.28575 +-			assert(chain->queued);
352.28576 +-			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
352.28577 ++			chain->type = SWAP_COMPLETE;
352.28578 ++			assert(chain->signal);
352.28579 ++			if (sna_next_vblank(chain))
352.28580 + 				return;
352.28581 + 		}
352.28582 + 
352.28583 +@@ -2381,8 +2925,10 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
352.28584 + {
352.28585 + 	struct sna *sna = flip->sna;
352.28586 + 
352.28587 +-	DBG(("%s(pipe=%d, event=%d)\n", __FUNCTION__, flip->pipe, flip->type));
352.28588 +-	assert(flip->queued);
352.28589 ++	DBG(("%s flip=%p (pipe=%d, event=%d, queued?=%d)\n", __FUNCTION__, flip, flip->pipe, flip->type, flip->queued));
352.28590 ++	if (!flip->queued) /* pageflip died whilst being queued */
352.28591 ++		return;
352.28592 ++	flip->queued = false;
352.28593 + 
352.28594 + 	if (sna->dri2.flip_pending == flip)
352.28595 + 		sna->dri2.flip_pending = NULL;
352.28596 +@@ -2390,8 +2936,10 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
352.28597 + 	/* We assume our flips arrive in order, so we don't check the frame */
352.28598 + 	switch (flip->type) {
352.28599 + 	case FLIP:
352.28600 +-		DBG(("%s: swap complete, unblocking client\n", __FUNCTION__));
352.28601 +-		frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
352.28602 ++		if (flip->signal) {
352.28603 ++			DBG(("%s: swap complete, unblocking client\n", __FUNCTION__));
352.28604 ++			frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
352.28605 ++		}
352.28606 + 		sna_dri2_event_free(flip);
352.28607 + 
352.28608 + 		if (sna->dri2.flip_pending)
352.28609 +@@ -2399,27 +2947,35 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
352.28610 + 		break;
352.28611 + 
352.28612 + 	case FLIP_THROTTLE:
352.28613 +-		DBG(("%s: triple buffer swap complete, unblocking client\n", __FUNCTION__));
352.28614 +-		frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
352.28615 ++		if (flip->signal) {
352.28616 ++			DBG(("%s: triple buffer swap complete, unblocking client\n", __FUNCTION__));
352.28617 ++			frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
352.28618 ++		}
352.28619 + 	case FLIP_COMPLETE:
352.28620 ++		assert(!flip->signal);
352.28621 + 		if (sna->dri2.flip_pending) {
352.28622 ++			DBG(("%s: pending flip\n", __FUNCTION__));
352.28623 + 			sna_dri2_event_free(flip);
352.28624 + 			chain_flip(sna);
352.28625 +-		} else if (!flip->mode) {
352.28626 ++		} else if (!flip->flip_continue) {
352.28627 + 			DBG(("%s: flip chain complete\n", __FUNCTION__));
352.28628 ++			if (!sna_dri2_flip_keepalive(flip)) {
352.28629 ++				if (flip->chain) {
352.28630 ++					sna_dri2_remove_event(flip);
352.28631 ++					chain_swap(flip->chain);
352.28632 ++				}
352.28633 + 
352.28634 +-			if (flip->chain) {
352.28635 +-				sna_dri2_remove_event((WindowPtr)flip->draw,
352.28636 +-						      flip);
352.28637 +-				chain_swap(flip->chain);
352.28638 +-				flip->draw = NULL;
352.28639 ++				sna_dri2_event_free(flip);
352.28640 + 			}
352.28641 +-
352.28642 +-			sna_dri2_event_free(flip);
352.28643 + 		} else if (!sna_dri2_flip_continue(flip)) {
352.28644 + 			DBG(("%s: no longer able to flip\n", __FUNCTION__));
352.28645 +-			if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->mode < 0))
352.28646 +-				sna_dri2_event_free(flip);
352.28647 ++			if (flip->draw != NULL)
352.28648 ++				__sna_dri2_copy_event(flip, 0);
352.28649 ++			if (flip->signal) {
352.28650 ++				DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28651 ++				frame_swap_complete(flip, DRI2_BLIT_COMPLETE);
352.28652 ++			}
352.28653 ++			sna_dri2_event_free(flip);
352.28654 + 		}
352.28655 + 		break;
352.28656 + 
352.28657 +@@ -2433,17 +2989,27 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
352.28658 + 	}
352.28659 + }
352.28660 + 
352.28661 ++static int
352.28662 ++sna_query_vblank(struct sna *sna, xf86CrtcPtr crtc, union drm_wait_vblank *vbl)
352.28663 ++{
352.28664 ++	VG_CLEAR(*vbl);
352.28665 ++	vbl->request.type =
352.28666 ++		_DRM_VBLANK_RELATIVE | pipe_select(sna_crtc_pipe(crtc));
352.28667 ++	vbl->request.sequence = 0;
352.28668 ++
352.28669 ++	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
352.28670 ++}
352.28671 ++
352.28672 + static uint64_t
352.28673 + get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
352.28674 + {
352.28675 + 	union drm_wait_vblank vbl;
352.28676 +-	uint64_t ret = -1;
352.28677 ++	uint64_t ret;
352.28678 + 
352.28679 +-	VG_CLEAR(vbl);
352.28680 +-	vbl.request.type = _DRM_VBLANK_RELATIVE;
352.28681 +-	vbl.request.sequence = 0;
352.28682 +-	if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
352.28683 ++	if (sna_query_vblank(sna, crtc, &vbl) == 0)
352.28684 + 		ret = sna_crtc_record_vblank(crtc, &vbl);
352.28685 ++	else
352.28686 ++		ret = sna_crtc_last_swap(crtc)->msc;
352.28687 + 
352.28688 + 	return draw_current_msc(draw, crtc, ret);
352.28689 + }
352.28690 +@@ -2494,12 +3060,18 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async)
352.28691 + }
352.28692 + 
352.28693 + static bool immediate_swap(struct sna *sna,
352.28694 +-			   uint64_t target_msc,
352.28695 +-			   uint64_t divisor,
352.28696 + 			   DrawablePtr draw,
352.28697 + 			   xf86CrtcPtr crtc,
352.28698 ++			   uint64_t *target_msc,
352.28699 ++			   uint64_t divisor,
352.28700 ++			   uint64_t remainder,
352.28701 + 			   uint64_t *current_msc)
352.28702 + {
352.28703 ++	/*
352.28704 ++	 * If divisor is zero, or current_msc is smaller than target_msc
352.28705 ++	 * we just need to make sure target_msc passes before initiating
352.28706 ++	 * the swap.
352.28707 ++	 */
352.28708 + 	if (divisor == 0) {
352.28709 + 		*current_msc = -1;
352.28710 + 
352.28711 +@@ -2508,72 +3080,97 @@ static bool immediate_swap(struct sna *sna,
352.28712 + 			return true;
352.28713 + 		}
352.28714 + 
352.28715 +-		if (target_msc)
352.28716 ++		if (*target_msc)
352.28717 + 			*current_msc = get_current_msc(sna, draw, crtc);
352.28718 + 
352.28719 + 		DBG(("%s: current_msc=%ld, target_msc=%ld -- %s\n",
352.28720 +-		     __FUNCTION__, (long)*current_msc, (long)target_msc,
352.28721 +-		     (*current_msc >= target_msc - 1) ? "yes" : "no"));
352.28722 +-		return *current_msc >= target_msc - 1;
352.28723 ++		     __FUNCTION__, (long)*current_msc, (long)*target_msc,
352.28724 ++		     (*current_msc >= *target_msc - 1) ? "yes" : "no"));
352.28725 ++		return *current_msc >= *target_msc - 1;
352.28726 + 	}
352.28727 + 
352.28728 + 	DBG(("%s: explicit waits requests, divisor=%ld\n",
352.28729 + 	     __FUNCTION__, (long)divisor));
352.28730 + 	*current_msc = get_current_msc(sna, draw, crtc);
352.28731 +-	return false;
352.28732 ++	if (*current_msc >= *target_msc) {
352.28733 ++		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
352.28734 ++		     __FUNCTION__,
352.28735 ++		     (long long)*current_msc,
352.28736 ++		     (long long)*target_msc,
352.28737 ++		     (long long)divisor,
352.28738 ++		     (long long)remainder));
352.28739 ++
352.28740 ++		*target_msc = *current_msc + remainder - *current_msc % divisor;
352.28741 ++		if (*target_msc <= *current_msc)
352.28742 ++			*target_msc += divisor;
352.28743 ++	}
352.28744 ++
352.28745 ++	DBG(("%s: target_msc=%lld, current_msc=%lld, immediate?=%d\n",
352.28746 ++	     __FUNCTION__, (long long)*target_msc, (long long)*current_msc,
352.28747 ++	     *current_msc >= *target_msc - 1));
352.28748 ++	return *current_msc >= *target_msc - 1;
352.28749 + }
352.28750 + 
352.28751 + static bool
352.28752 + sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
352.28753 + 		       DRI2BufferPtr front, DRI2BufferPtr back,
352.28754 +-		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
352.28755 ++		       bool immediate, CARD64 *target_msc, CARD64 current_msc,
352.28756 + 		       DRI2SwapEventPtr func, void *data)
352.28757 + {
352.28758 + 	struct sna *sna = to_sna_from_drawable(draw);
352.28759 + 	struct sna_dri2_event *info;
352.28760 +-	uint64_t current_msc;
352.28761 +-
352.28762 +-	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
352.28763 +-		int type;
352.28764 + 
352.28765 ++	if (immediate) {
352.28766 ++		bool signal = false;
352.28767 + 		info = sna->dri2.flip_pending;
352.28768 + 		DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d, continuation? %d\n",
352.28769 +-		     __FUNCTION__, sna_crtc_to_pipe(crtc),
352.28770 +-		     info != NULL, info ? info->mode : 0,
352.28771 ++		     __FUNCTION__, sna_crtc_pipe(crtc),
352.28772 ++		     info != NULL, info ? info->flip_continue : 0,
352.28773 + 		     info && info->draw == draw));
352.28774 + 
352.28775 + 		if (info && info->draw == draw) {
352.28776 + 			assert(info->type != FLIP);
352.28777 +-			assert(info->front == front);
352.28778 ++			assert(info->queued);
352.28779 ++			assert(info->front != info->back);
352.28780 ++			if (info->front != front) {
352.28781 ++				assert(info->front != NULL);
352.28782 ++				_sna_dri2_destroy_buffer(sna, draw, info->front);
352.28783 ++				info->front = sna_dri2_reference_buffer(front);
352.28784 ++			}
352.28785 + 			if (info->back != back) {
352.28786 +-				_sna_dri2_destroy_buffer(sna, info->back);
352.28787 ++				assert(info->back != NULL);
352.28788 ++				_sna_dri2_destroy_buffer(sna, draw, info->back);
352.28789 + 				info->back = sna_dri2_reference_buffer(back);
352.28790 + 			}
352.28791 +-			if (info->mode || current_msc >= *target_msc) {
352.28792 +-				DBG(("%s: executing xchg of pending flip\n",
352.28793 +-				     __FUNCTION__));
352.28794 +-				sna_dri2_xchg(draw, front, back);
352.28795 +-				info->mode = type = FLIP_COMPLETE;
352.28796 +-				goto new_back;
352.28797 +-			} else {
352.28798 ++			assert(info->front != info->back);
352.28799 ++			DBG(("%s: executing xchg of pending flip: flip_continue=%d, keepalive=%d, chain?=%d\n", __FUNCTION__, info->flip_continue, info->keepalive, current_msc < *target_msc));
352.28800 ++			sna_dri2_xchg(draw, front, back);
352.28801 ++			info->keepalive = KEEPALIVE;
352.28802 ++			if (xorg_can_triple_buffer() &&
352.28803 ++			    current_msc < *target_msc) {
352.28804 + 				DBG(("%s: chaining flip\n", __FUNCTION__));
352.28805 +-				type = FLIP_THROTTLE;
352.28806 +-				if (xorg_can_triple_buffer())
352.28807 +-					info->mode = -type;
352.28808 +-				else
352.28809 +-					info->mode = -FLIP_COMPLETE;
352.28810 ++				info->flip_continue = FLIP_THROTTLE;
352.28811 + 				goto out;
352.28812 ++			} else {
352.28813 ++				info->flip_continue = FLIP_COMPLETE;
352.28814 ++				signal = info->signal;
352.28815 ++				assert(info->draw);
352.28816 ++				info->signal = true;
352.28817 ++				goto new_back;
352.28818 + 			}
352.28819 + 		}
352.28820 + 
352.28821 +-		info = sna_dri2_add_event(sna, draw, client);
352.28822 ++		info = sna_dri2_add_event(sna, draw, client, crtc);
352.28823 + 		if (info == NULL)
352.28824 + 			return false;
352.28825 + 
352.28826 + 		assert(info->crtc == crtc);
352.28827 + 		info->event_complete = func;
352.28828 + 		info->event_data = data;
352.28829 ++		assert(info->draw);
352.28830 ++		info->signal = true;
352.28831 + 
352.28832 ++		assert(front != back);
352.28833 + 		info->front = sna_dri2_reference_buffer(front);
352.28834 + 		info->back = sna_dri2_reference_buffer(back);
352.28835 + 
352.28836 +@@ -2584,26 +3181,33 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
352.28837 + 			 */
352.28838 + 			DBG(("%s: queueing flip after pending completion\n",
352.28839 + 			     __FUNCTION__));
352.28840 +-			info->type = type = FLIP;
352.28841 ++			info->type = FLIP;
352.28842 + 			sna->dri2.flip_pending = info;
352.28843 +-			assert(info->queued);
352.28844 + 			current_msc++;
352.28845 ++		} else if (sna->mode.flip_active) {
352.28846 ++			DBG(("%s: %d outstanding flips from old client, queueing\n",
352.28847 ++			     __FUNCTION__, sna->mode.flip_active));
352.28848 ++			goto queue;
352.28849 + 		} else {
352.28850 +-			info->type = type = use_triple_buffer(sna, client, *target_msc == 0);
352.28851 ++			info->type = use_triple_buffer(sna, client, *target_msc == 0);
352.28852 + 			if (!sna_dri2_flip(info)) {
352.28853 + 				DBG(("%s: flip failed, falling back\n", __FUNCTION__));
352.28854 ++				info->signal = false;
352.28855 + 				sna_dri2_event_free(info);
352.28856 + 				return false;
352.28857 + 			}
352.28858 ++			assert(get_private(info->front)->bo->active_scanout);
352.28859 + 		}
352.28860 + 
352.28861 +-		swap_limit(draw, 1 + (type == FLIP_THROTTLE));
352.28862 +-		if (type >= FLIP_COMPLETE) {
352.28863 ++		swap_limit(draw, 1 + (info->type == FLIP_THROTTLE));
352.28864 ++		if (info->type >= FLIP_COMPLETE) {
352.28865 + new_back:
352.28866 + 			if (!xorg_can_triple_buffer())
352.28867 +-				sna_dri2_get_back(sna, draw, back, info);
352.28868 ++				sna_dri2_get_back(sna, draw, back);
352.28869 + 			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
352.28870 + 			frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
352.28871 ++			assert(info->draw);
352.28872 ++			info->signal = signal;
352.28873 + 			if (info->type == FLIP_ASYNC)
352.28874 + 				sna_dri2_event_free(info);
352.28875 + 		}
352.28876 +@@ -2613,57 +3217,34 @@ out:
352.28877 + 		return true;
352.28878 + 	}
352.28879 + 
352.28880 +-	info = sna_dri2_add_event(sna, draw, client);
352.28881 ++queue:
352.28882 ++	if (KEEPALIVE > 1 && sna->dri2.flip_pending) {
352.28883 ++		info = sna->dri2.flip_pending;
352.28884 ++		info->keepalive = 1;
352.28885 ++	}
352.28886 ++
352.28887 ++	info = sna_dri2_add_event(sna, draw, client, crtc);
352.28888 + 	if (info == NULL)
352.28889 + 		return false;
352.28890 + 
352.28891 + 	assert(info->crtc == crtc);
352.28892 + 	info->event_complete = func;
352.28893 + 	info->event_data = data;
352.28894 ++	assert(info->draw);
352.28895 ++	info->signal = true;
352.28896 + 	info->type = FLIP;
352.28897 + 
352.28898 ++	assert(front != back);
352.28899 + 	info->front = sna_dri2_reference_buffer(front);
352.28900 + 	info->back = sna_dri2_reference_buffer(back);
352.28901 + 
352.28902 +-	/*
352.28903 +-	 * If divisor is zero, or current_msc is smaller than target_msc
352.28904 +-	 * we just need to make sure target_msc passes before initiating
352.28905 +-	 * the swap.
352.28906 +-	 */
352.28907 +-	if (divisor && current_msc >= *target_msc) {
352.28908 +-		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
352.28909 +-		     __FUNCTION__,
352.28910 +-		     (long long)current_msc,
352.28911 +-		     (long long)*target_msc,
352.28912 +-		     (long long)divisor,
352.28913 +-		     (long long)remainder));
352.28914 +-
352.28915 +-		*target_msc = current_msc + remainder - current_msc % divisor;
352.28916 +-		if (*target_msc <= current_msc)
352.28917 +-			*target_msc += divisor;
352.28918 +-	}
352.28919 +-
352.28920 +-	if (*target_msc <= current_msc + 1) {
352.28921 +-		if (!sna_dri2_flip(info)) {
352.28922 +-			sna_dri2_event_free(info);
352.28923 +-			return false;
352.28924 +-		}
352.28925 ++	if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) {
352.28926 + 		*target_msc = current_msc + 1;
352.28927 + 	} else {
352.28928 +-		union drm_wait_vblank vbl;
352.28929 +-
352.28930 +-		VG_CLEAR(vbl);
352.28931 +-
352.28932 +-		vbl.request.type =
352.28933 +-			DRM_VBLANK_ABSOLUTE |
352.28934 +-			DRM_VBLANK_EVENT;
352.28935 +-
352.28936 + 		/* Account for 1 frame extra pageflip delay */
352.28937 +-		vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
352.28938 +-		vbl.request.signal = (uintptr_t)info;
352.28939 +-
352.28940 +-		info->queued = true;
352.28941 +-		if (sna_wait_vblank(sna, &vbl, info->pipe)) {
352.28942 ++		if (!sna_wait_vblank(info,
352.28943 ++				     draw_target_seq(draw, *target_msc - 1))) {
352.28944 ++			info->signal = false;
352.28945 + 			sna_dri2_event_free(info);
352.28946 + 			return false;
352.28947 + 		}
352.28948 +@@ -2674,128 +3255,6 @@ out:
352.28949 + 	return true;
352.28950 + }
352.28951 + 
352.28952 +-static bool
352.28953 +-sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
352.28954 +-		       DRI2BufferPtr front, DRI2BufferPtr back,
352.28955 +-		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
352.28956 +-		       DRI2SwapEventPtr func, void *data)
352.28957 +-{
352.28958 +-	struct sna *sna = to_sna_from_drawable(draw);
352.28959 +-	uint64_t current_msc;
352.28960 +-	bool sync, event;
352.28961 +-
352.28962 +-	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
352.28963 +-		return false;
352.28964 +-
352.28965 +-	sync = current_msc < *target_msc;
352.28966 +-	event = dri2_chain(draw) == NULL;
352.28967 +-	if (!sync || event) {
352.28968 +-		DBG(("%s: performing immediate xchg on pipe %d\n",
352.28969 +-		     __FUNCTION__, sna_crtc_to_pipe(crtc)));
352.28970 +-		sna_dri2_xchg(draw, front, back);
352.28971 +-	}
352.28972 +-	if (sync) {
352.28973 +-		struct sna_dri2_event *info;
352.28974 +-
352.28975 +-		info = sna_dri2_add_event(sna, draw, client);
352.28976 +-		if (!info)
352.28977 +-			goto complete;
352.28978 +-
352.28979 +-		info->event_complete = func;
352.28980 +-		info->event_data = data;
352.28981 +-
352.28982 +-		info->front = sna_dri2_reference_buffer(front);
352.28983 +-		info->back = sna_dri2_reference_buffer(back);
352.28984 +-		info->type = SWAP_THROTTLE;
352.28985 +-
352.28986 +-		if (event) {
352.28987 +-			union drm_wait_vblank vbl;
352.28988 +-
352.28989 +-			VG_CLEAR(vbl);
352.28990 +-			vbl.request.type =
352.28991 +-				DRM_VBLANK_RELATIVE |
352.28992 +-				DRM_VBLANK_EVENT;
352.28993 +-			vbl.request.sequence = 1;
352.28994 +-			vbl.request.signal = (uintptr_t)info;
352.28995 +-
352.28996 +-			info->queued = true;
352.28997 +-			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
352.28998 +-				sna_dri2_event_free(info);
352.28999 +-				goto complete;
352.29000 +-			}
352.29001 +-
352.29002 +-			swap_limit(draw, 2);
352.29003 +-		}
352.29004 +-	} else {
352.29005 +-complete:
352.29006 +-		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
352.29007 +-	}
352.29008 +-
352.29009 +-	*target_msc = current_msc + 1;
352.29010 +-	return true;
352.29011 +-}
352.29012 +-
352.29013 +-static bool
352.29014 +-sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
352.29015 +-			    DRI2BufferPtr front, DRI2BufferPtr back,
352.29016 +-			    CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
352.29017 +-			    DRI2SwapEventPtr func, void *data)
352.29018 +-{
352.29019 +-	struct sna *sna = to_sna_from_drawable(draw);
352.29020 +-	uint64_t current_msc;
352.29021 +-	bool sync, event;
352.29022 +-
352.29023 +-	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
352.29024 +-		return false;
352.29025 +-
352.29026 +-	sync = current_msc < *target_msc;
352.29027 +-	event = dri2_chain(draw) == NULL;
352.29028 +-	if (!sync || event) {
352.29029 +-		DBG(("%s: performing immediate xchg only on pipe %d\n",
352.29030 +-		     __FUNCTION__, sna_crtc_to_pipe(crtc)));
352.29031 +-		sna_dri2_xchg_crtc(sna, draw, crtc, front, back);
352.29032 +-	}
352.29033 +-	if (sync) {
352.29034 +-		struct sna_dri2_event *info;
352.29035 +-
352.29036 +-		info = sna_dri2_add_event(sna, draw, client);
352.29037 +-		if (!info)
352.29038 +-			goto complete;
352.29039 +-
352.29040 +-		info->event_complete = func;
352.29041 +-		info->event_data = data;
352.29042 +-
352.29043 +-		info->front = sna_dri2_reference_buffer(front);
352.29044 +-		info->back = sna_dri2_reference_buffer(back);
352.29045 +-		info->type = SWAP_THROTTLE;
352.29046 +-
352.29047 +-		if (event) {
352.29048 +-			union drm_wait_vblank vbl;
352.29049 +-
352.29050 +-			VG_CLEAR(vbl);
352.29051 +-			vbl.request.type =
352.29052 +-				DRM_VBLANK_RELATIVE |
352.29053 +-				DRM_VBLANK_EVENT;
352.29054 +-			vbl.request.sequence = 1;
352.29055 +-			vbl.request.signal = (uintptr_t)info;
352.29056 +-
352.29057 +-			info->queued = true;
352.29058 +-			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
352.29059 +-				sna_dri2_event_free(info);
352.29060 +-				goto complete;
352.29061 +-			}
352.29062 +-
352.29063 +-			swap_limit(draw, 2);
352.29064 +-		}
352.29065 +-	} else {
352.29066 +-complete:
352.29067 +-		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
352.29068 +-	}
352.29069 +-
352.29070 +-	*target_msc = current_msc + 1;
352.29071 +-	return true;
352.29072 +-}
352.29073 +-
352.29074 + static bool has_pending_events(struct sna *sna)
352.29075 + {
352.29076 + 	struct pollfd pfd;
352.29077 +@@ -2830,11 +3289,11 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.29078 + 		       CARD64 remainder, DRI2SwapEventPtr func, void *data)
352.29079 + {
352.29080 + 	struct sna *sna = to_sna_from_drawable(draw);
352.29081 +-	union drm_wait_vblank vbl;
352.29082 + 	xf86CrtcPtr crtc = NULL;
352.29083 + 	struct sna_dri2_event *info = NULL;
352.29084 + 	int type = DRI2_EXCHANGE_COMPLETE;
352.29085 + 	CARD64 current_msc;
352.29086 ++	bool immediate;
352.29087 + 
352.29088 + 	DBG(("%s: draw=%lu %dx%d, pixmap=%ld %dx%d, back=%u (refs=%d/%d, flush=%d) , front=%u (refs=%d/%d, flush=%d)\n",
352.29089 + 	     __FUNCTION__,
352.29090 +@@ -2860,6 +3319,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.29091 + 	assert(get_private(front)->refcnt);
352.29092 + 	assert(get_private(back)->refcnt);
352.29093 + 
352.29094 ++	assert(get_private(back)->bo != get_private(front)->bo);
352.29095 + 	assert(get_private(front)->bo->refcnt);
352.29096 + 	assert(get_private(back)->bo->refcnt);
352.29097 + 
352.29098 +@@ -2876,17 +3336,17 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.29099 + 		goto skip;
352.29100 + 	}
352.29101 + 
352.29102 +-	assert(sna_pixmap_from_drawable(draw)->flush);
352.29103 +-
352.29104 + 	if (draw->type != DRAWABLE_PIXMAP) {
352.29105 + 		WindowPtr win = (WindowPtr)draw;
352.29106 + 		struct dri2_window *priv = dri2_window(win);
352.29107 ++
352.29108 + 		if (priv->front) {
352.29109 +-			assert(front == priv->front);
352.29110 +-			assert(get_private(priv->front)->refcnt > 1);
352.29111 +-			get_private(priv->front)->refcnt--;
352.29112 +-			priv->front = NULL;
352.29113 ++			front = priv->front;
352.29114 ++			assert(front->attachment == DRI2BufferFrontLeft);
352.29115 ++			assert(get_private(front)->refcnt);
352.29116 ++			assert(get_private(front)->pixmap == get_drawable_pixmap(draw));
352.29117 + 		}
352.29118 ++
352.29119 + 		if (win->clipList.extents.x2 <= win->clipList.extents.x1 ||
352.29120 + 		    win->clipList.extents.y2 <= win->clipList.extents.y1) {
352.29121 + 			DBG(("%s: window clipped (%d, %d), (%d, %d)\n",
352.29122 +@@ -2899,6 +3359,10 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.29123 + 		}
352.29124 + 	}
352.29125 + 
352.29126 ++	DBG(("%s: using front handle=%d, active_scanout?=%d, flush?=%d\n", __FUNCTION__, get_private(front)->bo->handle, get_private(front)->bo->active_scanout, sna_pixmap_from_drawable(draw)->flush));
352.29127 ++	assert(get_private(front)->bo->active_scanout);
352.29128 ++	assert(sna_pixmap_from_drawable(draw)->flush);
352.29129 ++
352.29130 + 	/* Drawable not displayed... just complete the swap */
352.29131 + 	if ((sna->flags & SNA_NO_WAIT) == 0)
352.29132 + 		crtc = sna_dri2_get_crtc(draw);
352.29133 +@@ -2914,109 +3378,112 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.29134 + 		sna_mode_wakeup(sna);
352.29135 + 	}
352.29136 + 
352.29137 +-	if (can_xchg(sna, draw, front, back) &&
352.29138 +-	    sna_dri2_schedule_xchg(client, draw, crtc, front, back,
352.29139 ++	immediate = immediate_swap(sna, draw, crtc,
352.29140 + 				   target_msc, divisor, remainder,
352.29141 +-				   func, data))
352.29142 +-		return TRUE;
352.29143 +-
352.29144 +-	if (can_xchg_crtc(sna, draw, front, back, crtc) &&
352.29145 +-	    sna_dri2_schedule_xchg_crtc(client, draw, crtc, front, back,
352.29146 +-					target_msc, divisor, remainder,
352.29147 +-					func, data))
352.29148 +-		return TRUE;
352.29149 ++				   &current_msc);
352.29150 + 
352.29151 + 	if (can_flip(sna, draw, front, back, crtc) &&
352.29152 + 	    sna_dri2_schedule_flip(client, draw, crtc, front, back,
352.29153 +-				  target_msc, divisor, remainder,
352.29154 ++				  immediate, target_msc, current_msc,
352.29155 + 				  func, data))
352.29156 + 		return TRUE;
352.29157 + 
352.29158 +-	VG_CLEAR(vbl);
352.29159 +-
352.29160 +-	info = sna_dri2_add_event(sna, draw, client);
352.29161 ++	info = sna_dri2_add_event(sna, draw, client, crtc);
352.29162 + 	if (!info)
352.29163 + 		goto blit;
352.29164 + 
352.29165 + 	assert(info->crtc == crtc);
352.29166 + 	info->event_complete = func;
352.29167 + 	info->event_data = data;
352.29168 ++	assert(info->draw);
352.29169 ++	info->signal = true;
352.29170 + 
352.29171 ++	assert(front != back);
352.29172 + 	info->front = sna_dri2_reference_buffer(front);
352.29173 + 	info->back = sna_dri2_reference_buffer(back);
352.29174 + 
352.29175 +-	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
352.29176 ++	if (immediate) {
352.29177 + 		bool sync = current_msc < *target_msc;
352.29178 +-		if (!sna_dri2_immediate_blit(sna, info, sync, true))
352.29179 +-			sna_dri2_event_free(info);
352.29180 ++		sna_dri2_immediate_blit(sna, info, sync);
352.29181 + 		*target_msc = current_msc + sync;
352.29182 ++		DBG(("%s: reported target_msc=%llu\n",
352.29183 ++		     __FUNCTION__, *target_msc));
352.29184 + 		return TRUE;
352.29185 + 	}
352.29186 + 
352.29187 +-	vbl.request.type =
352.29188 +-		DRM_VBLANK_ABSOLUTE |
352.29189 +-		DRM_VBLANK_EVENT;
352.29190 +-	vbl.request.signal = (uintptr_t)info;
352.29191 +-
352.29192 +-	/*
352.29193 +-	 * If divisor is zero, or current_msc is smaller than target_msc
352.29194 +-	 * we just need to make sure target_msc passes before initiating
352.29195 +-	 * the swap.
352.29196 +-	 */
352.29197 + 	info->type = SWAP;
352.29198 +-	info->queued = true;
352.29199 +-	if (divisor && current_msc >= *target_msc) {
352.29200 +-		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
352.29201 +-		     __FUNCTION__,
352.29202 +-		     (long long)current_msc,
352.29203 +-		     (long long)*target_msc,
352.29204 +-		     (long long)divisor,
352.29205 +-		     (long long)remainder));
352.29206 +-
352.29207 +-		*target_msc = current_msc + remainder - current_msc % divisor;
352.29208 +-		if (*target_msc <= current_msc)
352.29209 +-			*target_msc += divisor;
352.29210 +-	}
352.29211 +-	vbl.request.sequence = draw_target_seq(draw, *target_msc - 1);
352.29212 + 	if (*target_msc <= current_msc + 1) {
352.29213 + 		DBG(("%s: performing blit before queueing\n", __FUNCTION__));
352.29214 +-		assert(info->queued);
352.29215 +-		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
352.29216 +-						  back, front,
352.29217 +-						  true);
352.29218 +-		info->type = SWAP_WAIT;
352.29219 +-
352.29220 +-		vbl.request.type =
352.29221 +-			DRM_VBLANK_RELATIVE |
352.29222 +-			DRM_VBLANK_EVENT;
352.29223 +-		vbl.request.sequence = 1;
352.29224 ++		__sna_dri2_copy_event(info, DRI2_SYNC);
352.29225 ++		info->type = SWAP_COMPLETE;
352.29226 ++		if (!sna_next_vblank(info))
352.29227 ++			goto fake;
352.29228 ++
352.29229 ++		DBG(("%s: reported target_msc=%llu\n",
352.29230 ++		     __FUNCTION__, *target_msc));
352.29231 + 		*target_msc = current_msc + 1;
352.29232 +-	}
352.29233 ++		swap_limit(draw, 2);
352.29234 ++	} else {
352.29235 ++		if (!sna_wait_vblank(info,
352.29236 ++				     draw_target_seq(draw, *target_msc - 1)))
352.29237 ++			goto blit;
352.29238 + 
352.29239 +-	assert(info->queued);
352.29240 +-	if (sna_wait_vblank(sna, &vbl, info->pipe))
352.29241 +-		goto blit;
352.29242 ++		DBG(("%s: reported target_msc=%llu (in)\n",
352.29243 ++		     __FUNCTION__, *target_msc));
352.29244 ++		swap_limit(draw, 1);
352.29245 ++	}
352.29246 + 
352.29247 +-	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
352.29248 +-	swap_limit(draw, 1 + (info->type == SWAP_WAIT));
352.29249 + 	return TRUE;
352.29250 + 
352.29251 + blit:
352.29252 + 	DBG(("%s -- blit\n", __FUNCTION__));
352.29253 +-	if (info)
352.29254 +-		sna_dri2_event_free(info);
352.29255 + 	if (can_xchg(sna, draw, front, back)) {
352.29256 + 		sna_dri2_xchg(draw, front, back);
352.29257 + 	} else {
352.29258 +-		__sna_dri2_copy_region(sna, draw, NULL, back, front, false);
352.29259 ++		__sna_dri2_copy_region(sna, draw, NULL, back, front, 0);
352.29260 ++		front->flags = back->flags;
352.29261 + 		type = DRI2_BLIT_COMPLETE;
352.29262 + 	}
352.29263 ++	if (draw->type == DRAWABLE_PIXMAP)
352.29264 ++		goto fake;
352.29265 + skip:
352.29266 + 	DBG(("%s: unable to show frame, unblocking client\n", __FUNCTION__));
352.29267 +-	if (crtc == NULL)
352.29268 +-		crtc = sna_mode_first_crtc(sna);
352.29269 +-	fake_swap_complete(sna, client, draw, crtc, type, func, data);
352.29270 +-	*target_msc = 0; /* offscreen, so zero out target vblank count */
352.29271 ++	if (crtc == NULL && (sna->flags & SNA_NO_WAIT) == 0)
352.29272 ++		crtc = sna_primary_crtc(sna);
352.29273 ++	if (crtc && sna_crtc_is_on(crtc)) {
352.29274 ++		if (info == NULL)
352.29275 ++			info = sna_dri2_add_event(sna, draw, client, crtc);
352.29276 ++		if (info != dri2_chain(draw))
352.29277 ++			goto fake;
352.29278 ++
352.29279 ++		assert(info->crtc == crtc);
352.29280 ++
352.29281 ++		info->type = SWAP_COMPLETE;
352.29282 ++		info->event_complete = func;
352.29283 ++		info->event_data = data;
352.29284 ++		assert(info->draw);
352.29285 ++		info->signal = true;
352.29286 ++
352.29287 ++		if (info->front == NULL)
352.29288 ++			info->front = sna_dri2_reference_buffer(front);
352.29289 ++		if (info->back == NULL)
352.29290 ++			info->back = sna_dri2_reference_buffer(back);
352.29291 ++
352.29292 ++		if (!sna_next_vblank(info))
352.29293 ++			goto fake;
352.29294 ++
352.29295 ++		swap_limit(draw, 1);
352.29296 ++	} else {
352.29297 ++fake:
352.29298 ++		/* XXX Use a Timer to throttle the client? */
352.29299 ++		fake_swap_complete(sna, client, draw, crtc, type, func, data);
352.29300 ++		if (info) {
352.29301 ++			assert(info->draw);
352.29302 ++			info->signal = false;
352.29303 ++			sna_dri2_event_free(info);
352.29304 ++		}
352.29305 ++	}
352.29306 ++	DBG(("%s: reported target_msc=%llu (in)\n", __FUNCTION__, *target_msc));
352.29307 + 	return TRUE;
352.29308 + }
352.29309 + 
352.29310 +@@ -3030,27 +3497,25 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
352.29311 + 	struct sna *sna = to_sna_from_drawable(draw);
352.29312 + 	xf86CrtcPtr crtc = sna_dri2_get_crtc(draw);
352.29313 + 	const struct ust_msc *swap;
352.29314 ++	union drm_wait_vblank vbl;
352.29315 + 
352.29316 + 	DBG(("%s(draw=%ld, pipe=%d)\n", __FUNCTION__, draw->id,
352.29317 +-	     crtc ? sna_crtc_to_pipe(crtc) : -1));
352.29318 ++	     crtc ? sna_crtc_pipe(crtc) : -1));
352.29319 + 
352.29320 +-	if (crtc != NULL) {
352.29321 +-		union drm_wait_vblank vbl;
352.29322 ++	/* Drawable not displayed, make up a *monotonic* value */
352.29323 ++	if (crtc == NULL)
352.29324 ++		crtc = sna_primary_crtc(sna);
352.29325 ++	if (crtc == NULL)
352.29326 ++		return FALSE;
352.29327 + 
352.29328 +-		VG_CLEAR(vbl);
352.29329 +-		vbl.request.type = _DRM_VBLANK_RELATIVE;
352.29330 +-		vbl.request.sequence = 0;
352.29331 +-		if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
352.29332 +-			sna_crtc_record_vblank(crtc, &vbl);
352.29333 +-	} else
352.29334 +-		/* Drawable not displayed, make up a *monotonic* value */
352.29335 +-		crtc = sna_mode_first_crtc(sna);
352.29336 ++	if (sna_query_vblank(sna, crtc, &vbl) == 0)
352.29337 ++		sna_crtc_record_vblank(crtc, &vbl);
352.29338 + 
352.29339 + 	swap = sna_crtc_last_swap(crtc);
352.29340 + 	*msc = draw_current_msc(draw, crtc, swap->msc);
352.29341 + 	*ust = ust64(swap->tv_sec, swap->tv_usec);
352.29342 +-	DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
352.29343 +-	     (long long)*msc, (long long)*ust));
352.29344 ++	DBG(("%s: msc=%llu [raw=%llu], ust=%llu\n", __FUNCTION__,
352.29345 ++	     (long long)*msc, swap->msc, (long long)*ust));
352.29346 + 	return TRUE;
352.29347 + }
352.29348 + 
352.29349 +@@ -3068,32 +3533,22 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
352.29350 + 	struct sna_dri2_event *info = NULL;
352.29351 + 	xf86CrtcPtr crtc;
352.29352 + 	CARD64 current_msc;
352.29353 +-	union drm_wait_vblank vbl;
352.29354 + 	const struct ust_msc *swap;
352.29355 +-	int pipe;
352.29356 + 
352.29357 + 	crtc = sna_dri2_get_crtc(draw);
352.29358 + 	DBG(("%s(pipe=%d, target_msc=%llu, divisor=%llu, rem=%llu)\n",
352.29359 +-	     __FUNCTION__, crtc ? sna_crtc_to_pipe(crtc) : -1,
352.29360 ++	     __FUNCTION__, crtc ? sna_crtc_pipe(crtc) : -1,
352.29361 + 	     (long long)target_msc,
352.29362 + 	     (long long)divisor,
352.29363 + 	     (long long)remainder));
352.29364 + 
352.29365 + 	/* Drawable not visible, return immediately */
352.29366 + 	if (crtc == NULL)
352.29367 +-		goto out_complete;
352.29368 +-
352.29369 +-	pipe = sna_crtc_to_pipe(crtc);
352.29370 +-
352.29371 +-	VG_CLEAR(vbl);
352.29372 +-
352.29373 +-	/* Get current count */
352.29374 +-	vbl.request.type = _DRM_VBLANK_RELATIVE;
352.29375 +-	vbl.request.sequence = 0;
352.29376 +-	if (sna_wait_vblank(sna, &vbl, pipe))
352.29377 +-		goto out_complete;
352.29378 ++		crtc = sna_primary_crtc(sna);
352.29379 ++	if (crtc == NULL)
352.29380 ++		return FALSE;
352.29381 + 
352.29382 +-	current_msc = draw_current_msc(draw, crtc, sna_crtc_record_vblank(crtc, &vbl));
352.29383 ++	current_msc = get_current_msc(sna, draw, crtc);
352.29384 + 
352.29385 + 	/* If target_msc already reached or passed, set it to
352.29386 + 	 * current_msc to ensure we return a reasonable value back
352.29387 +@@ -3104,15 +3559,13 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
352.29388 + 	if (divisor == 0 && current_msc >= target_msc)
352.29389 + 		goto out_complete;
352.29390 + 
352.29391 +-	info = sna_dri2_add_event(sna, draw, client);
352.29392 ++	info = sna_dri2_add_event(sna, draw, client, crtc);
352.29393 + 	if (!info)
352.29394 + 		goto out_complete;
352.29395 + 
352.29396 + 	assert(info->crtc == crtc);
352.29397 + 	info->type = WAITMSC;
352.29398 + 
352.29399 +-	vbl.request.signal = (uintptr_t)info;
352.29400 +-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
352.29401 + 	/*
352.29402 + 	 * If divisor is zero, or current_msc is smaller than target_msc,
352.29403 + 	 * we just need to make sure target_msc passes before waking up the
352.29404 +@@ -3129,10 +3582,8 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
352.29405 + 		if (target_msc <= current_msc)
352.29406 + 			target_msc += divisor;
352.29407 + 	}
352.29408 +-	vbl.request.sequence = draw_target_seq(draw, target_msc);
352.29409 + 
352.29410 +-	info->queued = true;
352.29411 +-	if (sna_wait_vblank(sna, &vbl, pipe))
352.29412 ++	if (!sna_wait_vblank(info, draw_target_seq(draw, target_msc)))
352.29413 + 		goto out_free_info;
352.29414 + 
352.29415 + 	DRI2BlockClient(client, draw);
352.29416 +@@ -3141,8 +3592,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
352.29417 + out_free_info:
352.29418 + 	sna_dri2_event_free(info);
352.29419 + out_complete:
352.29420 +-	if (crtc == NULL)
352.29421 +-		crtc = sna_mode_first_crtc(sna);
352.29422 + 	swap = sna_crtc_last_swap(crtc);
352.29423 + 	DRI2WaitMSCComplete(client, draw,
352.29424 + 			    draw_current_msc(draw, crtc, swap->msc),
352.29425 +@@ -3231,9 +3680,18 @@ static bool is_level(const char **str)
352.29426 + 	return false;
352.29427 + }
352.29428 + 
352.29429 ++static const char *options_get_dri(struct sna *sna)
352.29430 ++{
352.29431 ++#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.29432 ++	return xf86GetOptValString(sna->Options, OPTION_DRI);
352.29433 ++#else
352.29434 ++	return NULL;
352.29435 ++#endif
352.29436 ++}
352.29437 ++
352.29438 + static const char *dri_driver_name(struct sna *sna)
352.29439 + {
352.29440 +-	const char *s = xf86GetOptValString(sna->Options, OPTION_DRI);
352.29441 ++	const char *s = options_get_dri(sna);
352.29442 + 
352.29443 + 	if (is_level(&s)) {
352.29444 + 		if (sna->kgem.gen < 030)
352.29445 +@@ -3259,7 +3717,7 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
352.29446 + 
352.29447 + 	if (wedged(sna)) {
352.29448 + 		xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
352.29449 +-			   "loading DRI2 whilst the GPU is wedged.\n");
352.29450 ++			   "loading DRI2 whilst acceleration is disabled.\n");
352.29451 + 	}
352.29452 + 
352.29453 + 	if (xf86LoaderCheckSymbol("DRI2Version"))
352.29454 +@@ -3274,7 +3732,7 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
352.29455 + 	memset(&info, '\0', sizeof(info));
352.29456 + 	info.fd = sna->kgem.fd;
352.29457 + 	info.driverName = dri_driver_name(sna);
352.29458 +-	info.deviceName = intel_get_client_name(sna->dev);
352.29459 ++	info.deviceName = intel_get_master_name(sna->dev);
352.29460 + 
352.29461 + 	DBG(("%s: loading dri driver '%s' [gen=%d] for device '%s'\n",
352.29462 + 	     __FUNCTION__, info.driverName, sna->kgem.gen, info.deviceName));
352.29463 +@@ -3299,11 +3757,12 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
352.29464 + 	info.numDrivers = 2;
352.29465 + 	info.driverNames = driverNames;
352.29466 + 	driverNames[0] = info.driverName;
352.29467 +-	driverNames[1] = info.driverName;
352.29468 ++	driverNames[1] = "va_gl";
352.29469 + #endif
352.29470 + 
352.29471 + #if DRI2INFOREC_VERSION >= 6
352.29472 + 	if (xorg_can_triple_buffer()) {
352.29473 ++		DBG(("%s: enabling Xorg triple buffering\n", __FUNCTION__));
352.29474 + 		info.version = 6;
352.29475 + 		info.SwapLimitValidate = sna_dri2_swap_limit_validate;
352.29476 + 		info.ReuseBufferNotify = sna_dri2_reuse_buffer;
352.29477 +@@ -3311,8 +3770,10 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
352.29478 + #endif
352.29479 + 
352.29480 + #if USE_ASYNC_SWAP
352.29481 ++	DBG(("%s: enabled async swap and buffer age\n", __FUNCTION__));
352.29482 + 	info.version = 10;
352.29483 + 	info.scheduleSwap0 = 1;
352.29484 ++	info.bufferAge = 1;
352.29485 + #endif
352.29486 + 
352.29487 + 	return DRI2ScreenInit(screen, &info);
352.29488 +diff --git a/src/sna/sna_dri3.c b/src/sna/sna_dri3.c
352.29489 +index f586e242..ce4970ae 100644
352.29490 +--- a/src/sna/sna_dri3.c
352.29491 ++++ b/src/sna/sna_dri3.c
352.29492 +@@ -55,11 +55,14 @@ static inline void mark_dri3_pixmap(struct sna *sna, struct sna_pixmap *priv, st
352.29493 + 	if (bo->exec)
352.29494 + 		sna->kgem.flush = 1;
352.29495 + 	if (bo == priv->gpu_bo)
352.29496 +-		priv->flush |= 3;
352.29497 ++		priv->flush |= FLUSH_READ | FLUSH_WRITE;
352.29498 + 	else
352.29499 + 		priv->shm = true;
352.29500 + 
352.29501 +-	sna_accel_watch_flush(sna, 1);
352.29502 ++	sna_watch_flush(sna, 1);
352.29503 ++
352.29504 ++	kgem_bo_submit(&sna->kgem, bo);
352.29505 ++	kgem_bo_unclean(&sna->kgem, bo);
352.29506 + }
352.29507 + 
352.29508 + static void sna_sync_flush(struct sna *sna, struct sna_pixmap *priv)
352.29509 +@@ -270,6 +273,8 @@ static PixmapPtr sna_dri3_pixmap_from_fd(ScreenPtr screen,
352.29510 + 		priv->ptr = MAKE_STATIC_PTR(pixmap->devPrivate.ptr);
352.29511 + 	} else {
352.29512 + 		assert(priv->gpu_bo == bo);
352.29513 ++		priv->create = kgem_can_create_2d(&sna->kgem,
352.29514 ++						  width, height, depth);
352.29515 + 		priv->pinned |= PIN_DRI3;
352.29516 + 	}
352.29517 + 	list_add(&priv->cow_list, &sna->dri3.pixmaps);
352.29518 +@@ -325,6 +330,15 @@ static int sna_dri3_fd_from_pixmap(ScreenPtr screen,
352.29519 + 		return -1;
352.29520 + 	}
352.29521 + 
352.29522 ++	if (bo->tiling && !sna->kgem.can_fence) {
352.29523 ++		if (!sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
352.29524 ++			DBG(("%s: unable to discard GPU tiling (%d) for DRI3 protocol\n",
352.29525 ++			     __FUNCTION__, bo->tiling));
352.29526 ++			return -1;
352.29527 ++		}
352.29528 ++		bo = priv->gpu_bo;
352.29529 ++	}
352.29530 ++
352.29531 + 	fd = kgem_bo_export_to_prime(&sna->kgem, bo);
352.29532 + 	if (fd == -1) {
352.29533 + 		DBG(("%s: exporting handle=%d to fd failed\n", __FUNCTION__, bo->handle));
352.29534 +diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
352.29535 +index 8a3599c7..1b4015de 100644
352.29536 +--- a/src/sna/sna_driver.c
352.29537 ++++ b/src/sna/sna_driver.c
352.29538 +@@ -57,6 +57,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
352.29539 + #include <mi.h>
352.29540 + #include <micmap.h>
352.29541 + 
352.29542 ++#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
352.29543 ++#include <X11/extensions/dpmsconst.h>
352.29544 ++#else
352.29545 ++#define DPMSModeOn 0
352.29546 ++#define DPMSModeOff 3
352.29547 ++#endif
352.29548 ++
352.29549 + #include <sys/ioctl.h>
352.29550 + #include <sys/fcntl.h>
352.29551 + #include <sys/poll.h>
352.29552 +@@ -69,6 +76,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
352.29553 + 
352.29554 + #if HAVE_DOT_GIT
352.29555 + #include "git_version.h"
352.29556 ++#else
352.29557 ++#define git_version "not compiled from git"
352.29558 + #endif
352.29559 + 
352.29560 + #ifdef TEARFREE
352.29561 +@@ -185,12 +194,12 @@ sna_set_fallback_mode(ScrnInfoPtr scrn)
352.29562 + 
352.29563 + 	xf86DisableUnusedFunctions(scrn);
352.29564 + #ifdef RANDR_12_INTERFACE
352.29565 +-	if (get_root_window(scrn->pScreen))
352.29566 +-		xf86RandR12TellChanged(scrn->pScreen);
352.29567 ++	if (get_root_window(xf86ScrnToScreen(scrn)))
352.29568 ++		xf86RandR12TellChanged(xf86ScrnToScreen(scrn));
352.29569 + #endif
352.29570 + }
352.29571 + 
352.29572 +-static Bool sna_set_desired_mode(struct sna *sna)
352.29573 ++static void sna_set_desired_mode(struct sna *sna)
352.29574 + {
352.29575 + 	ScrnInfoPtr scrn = sna->scrn;
352.29576 + 
352.29577 +@@ -203,7 +212,6 @@ static Bool sna_set_desired_mode(struct sna *sna)
352.29578 + 	}
352.29579 + 
352.29580 + 	sna_mode_check(sna);
352.29581 +-	return TRUE;
352.29582 + }
352.29583 + 
352.29584 + /**
352.29585 +@@ -222,7 +230,7 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
352.29586 + 	     screen->width, screen->height, screen->rootDepth));
352.29587 + 
352.29588 + 	assert(sna->scrn == xf86ScreenToScrn(screen));
352.29589 +-	assert(sna->scrn->pScreen == screen);
352.29590 ++	assert(to_screen_from_sna(sna) == screen);
352.29591 + 
352.29592 + 	/* free the data used during miInitScreen */
352.29593 + 	free(screen->devPrivate);
352.29594 +@@ -273,33 +281,89 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
352.29595 + 		if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0)
352.29596 + 			sna_copy_fbcon(sna);
352.29597 + 
352.29598 +-		(void)sna_set_desired_mode(sna);
352.29599 ++		sna_set_desired_mode(sna);
352.29600 + 	}
352.29601 + 
352.29602 + 	return TRUE;
352.29603 + }
352.29604 + 
352.29605 +-static Bool sna_save_screen(ScreenPtr screen, int mode)
352.29606 ++static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
352.29607 + {
352.29608 +-	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
352.29609 ++	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
352.29610 ++	struct sna *sna = to_sna(scrn);
352.29611 ++	bool changed = false;
352.29612 ++	int i;
352.29613 + 
352.29614 +-	DBG(("%s(mode=%d)\n", __FUNCTION__, mode));
352.29615 ++	DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n",
352.29616 ++	     __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn));
352.29617 + 	if (!scrn->vtSema)
352.29618 +-		return FALSE;
352.29619 ++		return;
352.29620 + 
352.29621 +-	xf86SaveScreen(screen, mode);
352.29622 +-	sna_crtc_config_notify(screen);
352.29623 +-	return TRUE;
352.29624 ++	/* Opencoded version of xf86DPMSSet().
352.29625 ++	 *
352.29626 ++	 * The principle difference is to skip calling crtc->dpms() when
352.29627 ++	 * turning off the display. This (on recent enough kernels at
352.29628 ++	 * least) should be equivalent in power consumption, but require
352.29629 ++	 * less work (hence quicker and less likely to fail) when switching
352.29630 ++	 * back on.
352.29631 ++	 */
352.29632 ++	if (mode != DPMSModeOn) {
352.29633 ++		if (sna->mode.hidden == 0 && !(sna->flags & SNA_NO_DPMS)) {
352.29634 ++			DBG(("%s: hiding %d outputs\n",
352.29635 ++			     __FUNCTION__, config->num_output));
352.29636 ++			for (i = 0; i < config->num_output; i++) {
352.29637 ++				xf86OutputPtr output = config->output[i];
352.29638 ++				if (output->crtc != NULL)
352.29639 ++					output->funcs->dpms(output, mode);
352.29640 ++			}
352.29641 ++			sna->mode.hidden = sna->mode.front_active + 1;
352.29642 ++			sna->mode.front_active = 0;
352.29643 ++			changed = true;
352.29644 ++		}
352.29645 ++	} else {
352.29646 ++		/* Re-enable CRTC that have been forced off via other means */
352.29647 ++		if (sna->mode.hidden != 0) {
352.29648 ++			DBG(("%s: unhiding %d crtc, %d outputs\n",
352.29649 ++			     __FUNCTION__, config->num_crtc, config->num_output));
352.29650 ++			sna->mode.front_active = sna->mode.hidden - 1;
352.29651 ++			sna->mode.hidden = 0;
352.29652 ++			for (i = 0; i < config->num_crtc; i++) {
352.29653 ++				xf86CrtcPtr crtc = config->crtc[i];
352.29654 ++				if (crtc->enabled)
352.29655 ++					crtc->funcs->dpms(crtc, mode);
352.29656 ++			}
352.29657 ++
352.29658 ++			for (i = 0; i < config->num_output; i++) {
352.29659 ++				xf86OutputPtr output = config->output[i];
352.29660 ++				if (output->crtc != NULL)
352.29661 ++					output->funcs->dpms(output, mode);
352.29662 ++			}
352.29663 ++			changed = true;
352.29664 ++		}
352.29665 ++	}
352.29666 ++
352.29667 ++	DBG(("%s: hiding outputs? %d, front active? %d, changed? %d\n",
352.29668 ++	     __FUNCTION__, sna->mode.hidden, sna->mode.front_active, changed));
352.29669 ++
352.29670 ++	if (changed)
352.29671 ++		sna_crtc_config_notify(xf86ScrnToScreen(scrn));
352.29672 + }
352.29673 + 
352.29674 +-static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
352.29675 ++static Bool sna_save_screen(ScreenPtr screen, int mode)
352.29676 + {
352.29677 +-	DBG(("%s(mode=%d, flags=%d)\n", __FUNCTION__, mode));
352.29678 +-	if (!scrn->vtSema)
352.29679 +-		return;
352.29680 ++	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
352.29681 ++
352.29682 ++	DBG(("%s(mode=%d [unblank=%d])\n",
352.29683 ++	     __FUNCTION__, mode, xf86IsUnblank(mode)));
352.29684 + 
352.29685 +-	xf86DPMSSet(scrn, mode, flags);
352.29686 +-	sna_crtc_config_notify(xf86ScrnToScreen(scrn));
352.29687 ++	/* We have to unroll xf86SaveScreen() here as it is called
352.29688 ++	 * by DPMSSet() nullifying our special handling crtc->dpms()
352.29689 ++	 * in sna_dpms_set().
352.29690 ++	 */
352.29691 ++	sna_dpms_set(scrn,
352.29692 ++		     xf86IsUnblank(mode) ? DPMSModeOn : DPMSModeOff,
352.29693 ++		     0);
352.29694 ++	return TRUE;
352.29695 + }
352.29696 + 
352.29697 + static void sna_selftest(void)
352.29698 +@@ -330,107 +394,6 @@ static void sna_setup_capabilities(ScrnInfoPtr scrn, int fd)
352.29699 + #endif
352.29700 + }
352.29701 + 
352.29702 +-static int
352.29703 +-namecmp(const char *s1, const char *s2)
352.29704 +-{
352.29705 +-	char c1, c2;
352.29706 +-
352.29707 +-	if (!s1 || *s1 == 0) {
352.29708 +-		if (!s2 || *s2 == 0)
352.29709 +-			return 0;
352.29710 +-		else
352.29711 +-			return 1;
352.29712 +-	}
352.29713 +-
352.29714 +-	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.29715 +-		s1++;
352.29716 +-
352.29717 +-	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.29718 +-		s2++;
352.29719 +-
352.29720 +-	c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.29721 +-	c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.29722 +-	while (c1 == c2) {
352.29723 +-		if (c1 == '\0')
352.29724 +-			return 0;
352.29725 +-
352.29726 +-		s1++;
352.29727 +-		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.29728 +-			s1++;
352.29729 +-
352.29730 +-		s2++;
352.29731 +-		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.29732 +-			s2++;
352.29733 +-
352.29734 +-		c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.29735 +-		c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.29736 +-	}
352.29737 +-
352.29738 +-	return c1 - c2;
352.29739 +-}
352.29740 +-
352.29741 +-static Bool sna_option_cast_to_bool(struct sna *sna, int id, Bool val)
352.29742 +-{
352.29743 +-	const char *str = xf86GetOptValString(sna->Options, id);
352.29744 +-
352.29745 +-	if (str == NULL)
352.29746 +-		return val;
352.29747 +-
352.29748 +-	if (*str == '\0')
352.29749 +-		return TRUE;
352.29750 +-
352.29751 +-	if (namecmp(str, "1") == 0)
352.29752 +-		return TRUE;
352.29753 +-	if (namecmp(str, "on") == 0)
352.29754 +-		return TRUE;
352.29755 +-	if (namecmp(str, "true") == 0)
352.29756 +-		return TRUE;
352.29757 +-	if (namecmp(str, "yes") == 0)
352.29758 +-		return TRUE;
352.29759 +-
352.29760 +-	if (namecmp(str, "0") == 0)
352.29761 +-		return FALSE;
352.29762 +-	if (namecmp(str, "off") == 0)
352.29763 +-		return FALSE;
352.29764 +-	if (namecmp(str, "false") == 0)
352.29765 +-		return FALSE;
352.29766 +-	if (namecmp(str, "no") == 0)
352.29767 +-		return FALSE;
352.29768 +-
352.29769 +-	return val;
352.29770 +-}
352.29771 +-
352.29772 +-static unsigned sna_option_cast_to_unsigned(struct sna *sna, int id, unsigned val)
352.29773 +-{
352.29774 +-	const char *str = xf86GetOptValString(sna->Options, id);
352.29775 +-	unsigned v;
352.29776 +-
352.29777 +-	if (str == NULL || *str == '\0')
352.29778 +-		return val;
352.29779 +-
352.29780 +-	if (namecmp(str, "on") == 0)
352.29781 +-		return val;
352.29782 +-	if (namecmp(str, "true") == 0)
352.29783 +-		return val;
352.29784 +-	if (namecmp(str, "yes") == 0)
352.29785 +-		return val;
352.29786 +-
352.29787 +-	if (namecmp(str, "0") == 0)
352.29788 +-		return 0;
352.29789 +-	if (namecmp(str, "off") == 0)
352.29790 +-		return 0;
352.29791 +-	if (namecmp(str, "false") == 0)
352.29792 +-		return 0;
352.29793 +-	if (namecmp(str, "no") == 0)
352.29794 +-		return 0;
352.29795 +-
352.29796 +-	v = atoi(str);
352.29797 +-	if (v)
352.29798 +-		return v;
352.29799 +-
352.29800 +-	return val;
352.29801 +-}
352.29802 +-
352.29803 + static Bool fb_supports_depth(int fd, int depth)
352.29804 + {
352.29805 + 	struct drm_i915_gem_create create;
352.29806 +@@ -470,16 +433,24 @@ static void setup_dri(struct sna *sna)
352.29807 + 	unsigned level;
352.29808 + 
352.29809 + 	sna->dri2.available = false;
352.29810 ++	sna->dri2.enable = false;
352.29811 + 	sna->dri3.available = false;
352.29812 ++	sna->dri3.enable = false;
352.29813 ++	sna->dri3.override = false;
352.29814 + 
352.29815 +-	level = sna_option_cast_to_unsigned(sna, OPTION_DRI, ~0);
352.29816 ++	level = intel_option_cast_to_unsigned(sna->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
352.29817 + #if HAVE_DRI3
352.29818 +-	if (level >= 3)
352.29819 +-		sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
352.29820 ++	sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
352.29821 ++	sna->dri3.override =
352.29822 ++		!sna->dri3.available ||
352.29823 ++		xf86IsOptionSet(sna->Options, OPTION_DRI);
352.29824 ++	if (level >= 3 && sna->kgem.gen >= 040)
352.29825 ++		sna->dri3.enable = sna->dri3.available;
352.29826 + #endif
352.29827 + #if HAVE_DRI2
352.29828 ++	sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
352.29829 + 	if (level >= 2)
352.29830 +-		sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
352.29831 ++		sna->dri2.enable = sna->dri2.available;
352.29832 + #endif
352.29833 + }
352.29834 + 
352.29835 +@@ -498,13 +469,13 @@ static bool enable_tear_free(struct sna *sna)
352.29836 + 	return ENABLE_TEAR_FREE;
352.29837 + }
352.29838 + 
352.29839 +-static void setup_tear_free(struct sna *sna)
352.29840 ++static bool setup_tear_free(struct sna *sna)
352.29841 + {
352.29842 + 	MessageType from;
352.29843 + 	Bool enable;
352.29844 + 
352.29845 + 	if (sna->flags & SNA_LINEAR_FB)
352.29846 +-		return;
352.29847 ++		return false;
352.29848 + 
352.29849 + 	if ((sna->flags & SNA_HAS_FLIP) == 0) {
352.29850 + 		from = X_PROBED;
352.29851 +@@ -518,11 +489,12 @@ static void setup_tear_free(struct sna *sna)
352.29852 + 		from = X_CONFIG;
352.29853 + 
352.29854 + 	if (enable)
352.29855 +-		sna->flags |= SNA_TEAR_FREE;
352.29856 ++		sna->flags |= SNA_WANT_TEAR_FREE | SNA_TEAR_FREE;
352.29857 + 
352.29858 + done:
352.29859 + 	xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n",
352.29860 + 		   sna->flags & SNA_TEAR_FREE ? "en" : "dis");
352.29861 ++	return sna->flags & SNA_TEAR_FREE;
352.29862 + }
352.29863 + 
352.29864 + /**
352.29865 +@@ -612,8 +584,10 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
352.29866 + 	}
352.29867 + 
352.29868 + 	intel_detect_chipset(scrn, sna->dev);
352.29869 +-	xf86DrvMsg(scrn->scrnIndex, X_PROBED, "CPU: %s\n",
352.29870 +-		   sna_cpu_features_to_string(sna->cpu_features, buf));
352.29871 ++	xf86DrvMsg(scrn->scrnIndex, X_PROBED,
352.29872 ++		   "CPU: %s; using a maximum of %d threads\n",
352.29873 ++		   sna_cpu_features_to_string(sna->cpu_features, buf),
352.29874 ++		   sna_use_threads(64*1024, 64*1024, 1));
352.29875 + 
352.29876 + 	if (!xf86SetDepthBpp(scrn, 24, 0, 0,
352.29877 + 			     Support32bppFb |
352.29878 +@@ -651,18 +625,11 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
352.29879 + 	kgem_init(&sna->kgem, fd,
352.29880 + 		  xf86GetPciInfoForEntity(pEnt->index),
352.29881 + 		  sna->info->gen);
352.29882 +-	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) ||
352.29883 +-	    !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) {
352.29884 +-		xf86DrvMsg(sna->scrn->scrnIndex, X_CONFIG,
352.29885 +-			   "Disabling hardware acceleration.\n");
352.29886 +-		sna->kgem.wedged = true;
352.29887 +-	}
352.29888 + 
352.29889 + 	if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
352.29890 + 		sna->flags |= SNA_LINEAR_FB;
352.29891 +-
352.29892 +-	if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE))
352.29893 +-		sna->flags |= SNA_REMOVE_OUTPUTS;
352.29894 ++	if (!sna->kgem.can_fence)
352.29895 ++		sna->flags |= SNA_LINEAR_FB;
352.29896 + 
352.29897 + 	if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
352.29898 + 		sna->flags |= SNA_NO_WAIT;
352.29899 +@@ -695,7 +662,8 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
352.29900 + 	}
352.29901 + 	scrn->currentMode = scrn->modes;
352.29902 + 
352.29903 +-	setup_tear_free(sna);
352.29904 ++	if (!setup_tear_free(sna) && sna_mode_wants_tear_free(sna))
352.29905 ++		sna->kgem.needs_dirtyfb = sna->kgem.has_dirtyfb;
352.29906 + 
352.29907 + 	xf86SetGamma(scrn, zeros);
352.29908 + 	xf86SetDpi(scrn, 0, 0);
352.29909 +@@ -721,11 +689,13 @@ cleanup:
352.29910 + 	return FALSE;
352.29911 + }
352.29912 + 
352.29913 ++#if !HAVE_NOTIFY_FD
352.29914 + static bool has_shadow(struct sna *sna)
352.29915 + {
352.29916 +-	if (!sna->mode.shadow_damage)
352.29917 ++	if (!sna->mode.shadow_enabled)
352.29918 + 		return false;
352.29919 + 
352.29920 ++	assert(sna->mode.shadow_damage);
352.29921 + 	if (RegionNil(DamageRegion(sna->mode.shadow_damage)))
352.29922 + 		return false;
352.29923 + 
352.29924 +@@ -748,7 +718,7 @@ sna_block_handler(BLOCKHANDLER_ARGS_DECL)
352.29925 + 	sna->BlockHandler(BLOCKHANDLER_ARGS);
352.29926 + 
352.29927 + 	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna))
352.29928 +-		sna_accel_block_handler(sna, tv);
352.29929 ++		sna_accel_block(sna, tv);
352.29930 + }
352.29931 + 
352.29932 + static void
352.29933 +@@ -770,52 +740,102 @@ sna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
352.29934 + 
352.29935 + 	sna->WakeupHandler(WAKEUPHANDLER_ARGS);
352.29936 + 
352.29937 +-	sna_accel_wakeup_handler(sna);
352.29938 +-
352.29939 + 	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) {
352.29940 + 		sna_mode_wakeup(sna);
352.29941 + 		/* Clear the flag so that subsequent ZaphodHeads don't block  */
352.29942 + 		FD_CLR(sna->kgem.fd, (fd_set*)read_mask);
352.29943 + 	}
352.29944 + }
352.29945 ++#else
352.29946 ++static void
352.29947 ++sna_block_handler(void *data, void *_timeout)
352.29948 ++{
352.29949 ++	struct sna *sna = data;
352.29950 ++	int *timeout = _timeout;
352.29951 ++	struct timeval tv, *tvp;
352.29952 ++
352.29953 ++	DBG(("%s (timeout=%d)\n", __FUNCTION__, *timeout));
352.29954 ++	if (*timeout == 0)
352.29955 ++		return;
352.29956 ++
352.29957 ++	if (*timeout < 0) {
352.29958 ++		tvp = NULL;
352.29959 ++	} else {
352.29960 ++		tv.tv_sec = *timeout / 1000;
352.29961 ++		tv.tv_usec = (*timeout % 1000) * 1000;
352.29962 ++		tvp = &tv;
352.29963 ++	}
352.29964 ++
352.29965 ++	sna_accel_block(sna, &tvp);
352.29966 ++	if (tvp)
352.29967 ++		*timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
352.29968 ++}
352.29969 ++#endif
352.29970 + 
352.29971 + #if HAVE_UDEV
352.29972 ++#include <sys/stat.h>
352.29973 ++
352.29974 + static void
352.29975 + sna_handle_uevents(int fd, void *closure)
352.29976 + {
352.29977 + 	struct sna *sna = closure;
352.29978 +-	struct udev_device *dev;
352.29979 +-	const char *str;
352.29980 + 	struct stat s;
352.29981 +-	dev_t udev_devnum;
352.29982 ++	struct pollfd pfd;
352.29983 ++	bool hotplug = false;
352.29984 + 
352.29985 + 	DBG(("%s\n", __FUNCTION__));
352.29986 + 
352.29987 +-	dev = udev_monitor_receive_device(sna->uevent_monitor);
352.29988 +-	if (!dev)
352.29989 +-		return;
352.29990 ++	pfd.fd = udev_monitor_get_fd(sna->uevent_monitor);
352.29991 ++	pfd.events = POLLIN;
352.29992 ++
352.29993 ++	if (fstat(sna->kgem.fd, &s))
352.29994 ++		memset(&s, 0, sizeof(s));
352.29995 ++
352.29996 ++	while (poll(&pfd, 1, 0) > 0) {
352.29997 ++		struct udev_device *dev;
352.29998 ++		dev_t devnum;
352.29999 ++
352.30000 ++		dev = udev_monitor_receive_device(sna->uevent_monitor);
352.30001 ++		if (dev == NULL)
352.30002 ++			break;
352.30003 ++
352.30004 ++		devnum = udev_device_get_devnum(dev);
352.30005 ++		if (memcmp(&s.st_rdev, &devnum, sizeof(dev_t)) == 0) {
352.30006 ++			const char *str;
352.30007 ++
352.30008 ++			str = udev_device_get_property_value(dev, "HOTPLUG");
352.30009 ++			if (str && atoi(str) == 1) {
352.30010 ++				str = udev_device_get_property_value(dev, "CONNECTOR");
352.30011 ++				if (str) {
352.30012 ++					hotplug |= sna_mode_find_hotplug_connector(sna, atoi(str));
352.30013 ++				} else {
352.30014 ++					sna->flags |= SNA_REPROBE;
352.30015 ++					hotplug = true;
352.30016 ++				}
352.30017 ++			}
352.30018 ++		}
352.30019 + 
352.30020 +-	udev_devnum = udev_device_get_devnum(dev);
352.30021 +-	if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) {
352.30022 + 		udev_device_unref(dev);
352.30023 +-		return;
352.30024 + 	}
352.30025 + 
352.30026 +-	str = udev_device_get_property_value(dev, "HOTPLUG");
352.30027 +-	if (str && atoi(str) == 1) {
352.30028 +-		ScrnInfoPtr scrn = sna->scrn;
352.30029 +-
352.30030 +-		DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema));
352.30031 ++	if (hotplug) {
352.30032 ++		DBG(("%s: hotplug event (vtSema?=%d)\n",
352.30033 ++		     __FUNCTION__, sna->scrn->vtSema));
352.30034 + 
352.30035 +-		if (scrn->vtSema) {
352.30036 +-			sna_mode_discover(sna);
352.30037 +-			sna_mode_check(sna);
352.30038 +-			RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
352.30039 +-		} else
352.30040 ++		if (sna->scrn->vtSema)
352.30041 ++			sna_mode_discover(sna, true);
352.30042 ++		else
352.30043 + 			sna->flags |= SNA_REPROBE;
352.30044 + 	}
352.30045 ++}
352.30046 + 
352.30047 +-	udev_device_unref(dev);
352.30048 ++static bool has_randr(void)
352.30049 ++{
352.30050 ++#if HAS_DIXREGISTERPRIVATEKEY
352.30051 ++	return dixPrivateKeyRegistered(rrPrivKey);
352.30052 ++#else
352.30053 ++	return *rrPrivKey;
352.30054 ++#endif
352.30055 + }
352.30056 + 
352.30057 + static void
352.30058 +@@ -833,7 +853,7 @@ sna_uevent_init(struct sna *sna)
352.30059 + 	/* RandR will be disabled if Xinerama is active, and so generating
352.30060 + 	 * RR hotplug events is then verboten.
352.30061 + 	 */
352.30062 +-	if (!dixPrivateKeyRegistered(rrPrivKey))
352.30063 ++	if (!has_randr())
352.30064 + 		goto out;
352.30065 + 
352.30066 + 	u = NULL;
352.30067 +@@ -861,7 +881,8 @@ sna_uevent_init(struct sna *sna)
352.30068 + 
352.30069 + 	sna->uevent_monitor = mon;
352.30070 + out:
352.30071 +-	xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n",
352.30072 ++	xf86DrvMsg(sna->scrn->scrnIndex, from,
352.30073 ++		   "Display hotplug detection %s\n",
352.30074 + 		   sna->uevent_monitor ? "enabled" : "disabled");
352.30075 + 	return;
352.30076 + 
352.30077 +@@ -874,17 +895,10 @@ err_dev:
352.30078 + 
352.30079 + static bool sna_uevent_poll(struct sna *sna)
352.30080 + {
352.30081 +-	struct pollfd pfd;
352.30082 +-
352.30083 + 	if (sna->uevent_monitor == NULL)
352.30084 + 		return false;
352.30085 + 
352.30086 +-	pfd.fd = udev_monitor_get_fd(sna->uevent_monitor);
352.30087 +-	pfd.events = POLLIN;
352.30088 +-
352.30089 +-	while (poll(&pfd, 1, 0) > 0)
352.30090 +-		sna_handle_uevents(pfd.fd, sna);
352.30091 +-
352.30092 ++	sna_handle_uevents(udev_monitor_get_fd(sna->uevent_monitor), sna);
352.30093 + 	return true;
352.30094 + }
352.30095 + 
352.30096 +@@ -918,8 +932,10 @@ sna_randr_getinfo(ScreenPtr screen, Rotation *rotations)
352.30097 + {
352.30098 + 	struct sna *sna = to_sna_from_screen(screen);
352.30099 + 
352.30100 ++	DBG(("%s()\n", __FUNCTION__));
352.30101 ++
352.30102 + 	if (!sna_uevent_poll(sna))
352.30103 +-		sna_mode_discover(sna);
352.30104 ++		sna_mode_discover(sna, false);
352.30105 + 
352.30106 + 	return sna->mode.rrGetInfo(screen, rotations);
352.30107 + }
352.30108 +@@ -931,8 +947,8 @@ static void sna_leave_vt(VT_FUNC_ARGS_DECL)
352.30109 + 
352.30110 + 	DBG(("%s\n", __FUNCTION__));
352.30111 + 
352.30112 +-	sna_accel_leave(sna);
352.30113 + 	sna_mode_reset(sna);
352.30114 ++	sna_accel_leave(sna);
352.30115 + 
352.30116 + 	if (intel_put_master(sna->dev))
352.30117 + 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
352.30118 +@@ -948,6 +964,12 @@ static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
352.30119 + 
352.30120 + 	/* XXX Note that we will leak kernel resources if !vtSema */
352.30121 + 
352.30122 ++#if HAVE_NOTIFY_FD
352.30123 ++	RemoveBlockAndWakeupHandlers(sna_block_handler,
352.30124 ++				     (ServerWakeupHandlerProcPtr)NoopDDA,
352.30125 ++				     sna);
352.30126 ++#endif
352.30127 ++
352.30128 + 	sna_uevent_fini(sna);
352.30129 + 	sna_mode_close(sna);
352.30130 + 
352.30131 +@@ -1047,12 +1069,13 @@ static void sna_dri_init(struct sna *sna, ScreenPtr screen)
352.30132 + {
352.30133 + 	char str[128] = "";
352.30134 + 
352.30135 +-	if (sna->dri2.available)
352.30136 ++	if (sna->dri2.enable)
352.30137 + 		sna->dri2.open = sna_dri2_open(sna, screen);
352.30138 + 	if (sna->dri2.open)
352.30139 + 		strcat(str, "DRI2 ");
352.30140 + 
352.30141 +-	if (sna->dri3.available)
352.30142 ++	/* Load DRI3 in case DRI2 doesn't work, e.g. vgaarb */
352.30143 ++	if (sna->dri3.enable || (!sna->dri2.open && !sna->dri3.override))
352.30144 + 		sna->dri3.open = sna_dri3_open(sna, screen);
352.30145 + 	if (sna->dri3.open)
352.30146 + 		strcat(str, "DRI3 ");
352.30147 +@@ -1098,7 +1121,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
352.30148 + 	DBG(("%s\n", __FUNCTION__));
352.30149 + 
352.30150 + 	assert(sna->scrn == scrn);
352.30151 +-	assert(scrn->pScreen == NULL); /* set afterwards */
352.30152 ++	assert(to_screen_from_sna(sna) == NULL || /* set afterwards */
352.30153 ++	       to_screen_from_sna(sna) == screen);
352.30154 + 
352.30155 + 	assert(sna->freed_pixmap == NULL);
352.30156 + 
352.30157 +@@ -1166,11 +1190,17 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
352.30158 + 	 * later memory should be bound when allocating, e.g rotate_mem */
352.30159 + 	scrn->vtSema = TRUE;
352.30160 + 
352.30161 ++#if !HAVE_NOTIFY_FD
352.30162 + 	sna->BlockHandler = screen->BlockHandler;
352.30163 + 	screen->BlockHandler = sna_block_handler;
352.30164 + 
352.30165 + 	sna->WakeupHandler = screen->WakeupHandler;
352.30166 + 	screen->WakeupHandler = sna_wakeup_handler;
352.30167 ++#else
352.30168 ++	RegisterBlockAndWakeupHandlers(sna_block_handler,
352.30169 ++				       (ServerWakeupHandlerProcPtr)NoopDDA,
352.30170 ++				       sna);
352.30171 ++#endif
352.30172 + 
352.30173 + 	screen->SaveScreen = sna_save_screen;
352.30174 + 	screen->CreateScreenResources = sna_create_screen_resources;
352.30175 +@@ -1190,6 +1220,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
352.30176 + 				 CMAP_PALETTED_TRUECOLOR))
352.30177 + 		return FALSE;
352.30178 + 
352.30179 ++	if (!xf86CheckBoolOption(scrn->options, "dpms", TRUE))
352.30180 ++		sna->flags |= SNA_NO_DPMS;
352.30181 + 	xf86DPMSInit(screen, sna_dpms_set, 0);
352.30182 + 
352.30183 + 	sna_uevent_init(sna);
352.30184 +@@ -1244,20 +1276,15 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
352.30185 + 	if (intel_get_master(sna->dev))
352.30186 + 		return FALSE;
352.30187 + 
352.30188 ++	sna_accel_enter(sna);
352.30189 ++
352.30190 + 	if (sna->flags & SNA_REPROBE) {
352.30191 +-		DBG(("%s: reporting deferred hotplug event\n",
352.30192 +-		     __FUNCTION__));
352.30193 +-		sna_mode_discover(sna);
352.30194 +-		RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
352.30195 +-		sna->flags &= ~SNA_REPROBE;
352.30196 ++		DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__));
352.30197 ++		sna_mode_discover(sna, true);
352.30198 + 	}
352.30199 + 
352.30200 +-	if (!sna_set_desired_mode(sna)) {
352.30201 +-		intel_put_master(sna->dev);
352.30202 +-		return FALSE;
352.30203 +-	}
352.30204 ++	sna_set_desired_mode(sna);
352.30205 + 
352.30206 +-	sna_accel_enter(sna);
352.30207 + 	return TRUE;
352.30208 + }
352.30209 + 
352.30210 +@@ -1379,6 +1406,9 @@ static void describe_sna(ScrnInfoPtr scrn)
352.30211 + 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
352.30212 + 		   "SNA compiled: %s\n", BUILDER_DESCRIPTION);
352.30213 + #endif
352.30214 ++#if HAS_DEBUG_FULL
352.30215 ++	ErrorF("SNA compiled with full debug logging; expect to run slowly\n");
352.30216 ++#endif
352.30217 + #if !NDEBUG
352.30218 + 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
352.30219 + 		   "SNA compiled with assertions enabled\n");
352.30220 +@@ -1400,6 +1430,7 @@ static void describe_sna(ScrnInfoPtr scrn)
352.30221 + 		   "SNA compiled for use with valgrind\n");
352.30222 + 	VALGRIND_PRINTF("SNA compiled for use with valgrind\n");
352.30223 + #endif
352.30224 ++	DBG(("xf86-video-intel version: %s\n", git_version));
352.30225 + 	DBG(("pixman version: %s\n", pixman_version_string()));
352.30226 + }
352.30227 + 
352.30228 +diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
352.30229 +index a5dfb06b..6ee40336 100644
352.30230 +--- a/src/sna/sna_glyphs.c
352.30231 ++++ b/src/sna/sna_glyphs.c
352.30232 +@@ -74,7 +74,7 @@
352.30233 + #define NO_GLYPHS_VIA_MASK 0
352.30234 + #define FORCE_SMALL_MASK 0 /* -1 = never, 1 = always */
352.30235 + #define NO_GLYPHS_SLOW 0
352.30236 +-#define NO_DISCARD_MASK 0
352.30237 ++#define DISCARD_MASK 0 /* -1 = never, 1 = always */
352.30238 + 
352.30239 + #define CACHE_PICTURE_SIZE 1024
352.30240 + #define GLYPH_MIN_SIZE 8
352.30241 +@@ -185,7 +185,7 @@ void sna_glyphs_close(struct sna *sna)
352.30242 +  */
352.30243 + bool sna_glyphs_create(struct sna *sna)
352.30244 + {
352.30245 +-	ScreenPtr screen = sna->scrn->pScreen;
352.30246 ++	ScreenPtr screen = to_screen_from_sna(sna);
352.30247 + 	pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
352.30248 + 	unsigned int formats[] = {
352.30249 + 		PIXMAN_a8,
352.30250 +@@ -1094,6 +1094,9 @@ sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
352.30251 + 
352.30252 + static inline bool use_small_mask(struct sna *sna, int16_t width, int16_t height, int depth)
352.30253 + {
352.30254 ++	if (depth < 8)
352.30255 ++		return true;
352.30256 ++
352.30257 + 	if (FORCE_SMALL_MASK)
352.30258 + 		return FORCE_SMALL_MASK > 0;
352.30259 + 
352.30260 +@@ -1156,12 +1159,6 @@ glyphs_via_mask(struct sna *sna,
352.30261 + 	src_x += box.x1 - list->xOff;
352.30262 + 	src_y += box.y1 - list->yOff;
352.30263 + 
352.30264 +-	if (format->depth < 8) {
352.30265 +-		format = PictureMatchFormat(screen, 8, PICT_a8);
352.30266 +-		if (!format)
352.30267 +-			return false;
352.30268 +-	}
352.30269 +-
352.30270 + 	component_alpha = NeedsComponent(format->format);
352.30271 + 	if (use_small_mask(sna, width, height, format->depth)) {
352.30272 + 		pixman_image_t *mask_image;
352.30273 +@@ -1179,7 +1176,7 @@ use_small_mask:
352.30274 + 			return false;
352.30275 + 
352.30276 + 		mask_image =
352.30277 +-			pixman_image_create_bits(format->depth << 24 | format->format,
352.30278 ++			pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
352.30279 + 						 width, height,
352.30280 + 						 pixmap->devPrivate.ptr,
352.30281 + 						 pixmap->devKind);
352.30282 +@@ -1386,10 +1383,11 @@ next_image:
352.30283 + 					DBG(("%s: atlas format=%08x, mask format=%08x\n",
352.30284 + 					     __FUNCTION__,
352.30285 + 					     (int)p->atlas->format,
352.30286 +-					     (int)(format->depth << 24 | format->format)));
352.30287 ++					     (int)mask->format));
352.30288 + 
352.30289 + 					memset(&tmp, 0, sizeof(tmp));
352.30290 +-					if (p->atlas->format == (format->depth << 24 | format->format)) {
352.30291 ++					if (p->atlas->format == mask->format ||
352.30292 ++					    alphaless(p->atlas->format) == mask->format) {
352.30293 + 						ok = sna->render.composite(sna, PictOpAdd,
352.30294 + 									   p->atlas, NULL, mask,
352.30295 + 									   0, 0, 0, 0, 0, 0,
352.30296 +@@ -1561,6 +1559,9 @@ skip_glyph:
352.30297 + 		}
352.30298 + 	}
352.30299 + 
352.30300 ++	assert(format);
352.30301 ++	DBG(("%s: format=%08d, depth=%d\n",
352.30302 ++	     __FUNCTION__, format->format, format->depth));
352.30303 + out:
352.30304 + 	if (list_extents != stack_extents)
352.30305 + 		free(list_extents);
352.30306 +@@ -1573,24 +1574,34 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
352.30307 + 	PictFormatPtr g;
352.30308 + 	uint32_t color;
352.30309 + 
352.30310 +-	if (NO_DISCARD_MASK)
352.30311 +-		return false;
352.30312 ++	if (DISCARD_MASK)
352.30313 ++		return DISCARD_MASK > 0;
352.30314 + 
352.30315 + 	DBG(("%s: nlist=%d, mask=%08x, depth %d, op=%d (bounded? %d)\n",
352.30316 + 	     __FUNCTION__, nlist,
352.30317 + 	     mask ? (unsigned)mask->format : 0, mask ? mask->depth : 0,
352.30318 + 	     op, op_is_bounded(op)));
352.30319 + 
352.30320 +-	if (nlist == 1 && list->len == 1)
352.30321 +-		return true;
352.30322 ++	if (nlist == 1 && list->len == 1) {
352.30323 ++		if (mask == list->format)
352.30324 ++			return true;
352.30325 ++
352.30326 ++		g = list->format;
352.30327 ++		goto skip;
352.30328 ++	}
352.30329 + 
352.30330 +-	if (!op_is_bounded(op))
352.30331 ++	if (!op_is_bounded(op)) {
352.30332 ++		DBG(("%s: unbounded op, not discarding\n", __FUNCTION__));
352.30333 + 		return false;
352.30334 ++	}
352.30335 + 
352.30336 + 	/* No glyphs overlap and we are not performing a mask conversion. */
352.30337 + 	g = glyphs_format(nlist, list, glyphs);
352.30338 +-	if (mask == g)
352.30339 ++	if (mask == g) {
352.30340 ++		DBG(("%s: mask matches glyphs format, no conversion, so discard mask\n",
352.30341 ++		     __FUNCTION__));
352.30342 + 		return true;
352.30343 ++	}
352.30344 + 
352.30345 + 	DBG(("%s: preferred mask format %08x, depth %d\n",
352.30346 + 	     __FUNCTION__, g ? (unsigned)g->format : 0,  g ? g->depth : 0));
352.30347 +@@ -1605,18 +1616,41 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
352.30348 + 
352.30349 + 			list++;
352.30350 + 		}
352.30351 ++
352.30352 ++		if (!sna_picture_is_solid(src, &color))
352.30353 ++			return false;
352.30354 ++
352.30355 ++		return color >> 24 == 0xff;
352.30356 + 	} else {
352.30357 +-		if (PICT_FORMAT_A(mask->format) >= PICT_FORMAT_A(g->format))
352.30358 ++skip:
352.30359 ++		if (mask->format == g->format)
352.30360 + 			return true;
352.30361 + 
352.30362 +-		if (g->depth != 1)
352.30363 +-			return false;
352.30364 +-	}
352.30365 ++		if (mask->format == alphaless(g->format))
352.30366 ++			return true;
352.30367 ++
352.30368 ++		if (PICT_FORMAT_TYPE(g->format) == PICT_TYPE_A &&
352.30369 ++		    PICT_FORMAT_TYPE(mask->format) != PICT_TYPE_A)
352.30370 ++			return true;
352.30371 + 
352.30372 +-	if (!sna_picture_is_solid(src, &color))
352.30373 + 		return false;
352.30374 ++	}
352.30375 ++}
352.30376 + 
352.30377 +-	return color >> 24 == 0xff;
352.30378 ++static uint32_t pixman_format(PictFormatPtr short_format)
352.30379 ++{
352.30380 ++	uint32_t bpp;
352.30381 ++
352.30382 ++	bpp = short_format->depth;
352.30383 ++	if (bpp <= 1)
352.30384 ++		bpp = 1;
352.30385 ++	else if (bpp <= 8)
352.30386 ++		bpp = 8;
352.30387 ++	else if (bpp <= 16)
352.30388 ++		bpp = 16;
352.30389 ++	else
352.30390 ++		bpp = 32;
352.30391 ++	return bpp << 24 | short_format->format;
352.30392 + }
352.30393 + 
352.30394 + static void
352.30395 +@@ -1756,7 +1790,7 @@ next:
352.30396 + 		if (sigtrap_get() == 0) {
352.30397 + 			if (mask_format) {
352.30398 + 				pixman_composite_glyphs(op, src_image, dst_image,
352.30399 +-							mask_format->format | (mask_format->depth << 24),
352.30400 ++							pixman_format(mask_format),
352.30401 + 							src_x + src_dx + region.extents.x1 - dst_x,
352.30402 + 							src_y + src_dy + region.extents.y1 - dst_y,
352.30403 + 							region.extents.x1, region.extents.y1,
352.30404 +@@ -1815,10 +1849,10 @@ out:
352.30405 + 			     x, y,
352.30406 + 			     mask_format->depth,
352.30407 + 			     (long)mask_format->format,
352.30408 +-			     (long)(mask_format->depth << 24 | mask_format->format),
352.30409 ++			     (long)pixman_format(mask_format),
352.30410 + 			     NeedsComponent(mask_format->format)));
352.30411 + 			mask_image =
352.30412 +-				pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
352.30413 ++				pixman_image_create_bits(pixman_format(mask_format),
352.30414 + 							 region.extents.x2 - region.extents.x1,
352.30415 + 							 region.extents.y2 - region.extents.y1,
352.30416 + 							 NULL, 0);
352.30417 +@@ -2086,12 +2120,6 @@ glyphs_via_image(struct sna *sna,
352.30418 + 	src_x += box.x1 - list->xOff;
352.30419 + 	src_y += box.y1 - list->yOff;
352.30420 + 
352.30421 +-	if (format->depth < 8) {
352.30422 +-		format = PictureMatchFormat(screen, 8, PICT_a8);
352.30423 +-		if (!format)
352.30424 +-			return false;
352.30425 +-	}
352.30426 +-
352.30427 + 	DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
352.30428 + 	     __FUNCTION__, (unsigned long)format->format,
352.30429 + 	     format->depth, (uint32_t)width*height*format->depth));
352.30430 +@@ -2104,7 +2132,7 @@ glyphs_via_image(struct sna *sna,
352.30431 + 		return false;
352.30432 + 
352.30433 + 	mask_image =
352.30434 +-		pixman_image_create_bits(format->depth << 24 | format->format,
352.30435 ++		pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
352.30436 + 					 width, height,
352.30437 + 					 pixmap->devPrivate.ptr,
352.30438 + 					 pixmap->devKind);
352.30439 +diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
352.30440 +index d6aa1294..d32bd583 100644
352.30441 +--- a/src/sna/sna_io.c
352.30442 ++++ b/src/sna/sna_io.c
352.30443 +@@ -105,8 +105,10 @@ read_boxes_inplace__cpu(struct kgem *kgem,
352.30444 + 	if (!download_inplace__cpu(kgem, dst, bo, box, n))
352.30445 + 		return false;
352.30446 + 
352.30447 ++	if (bo->tiling == I915_TILING_Y)
352.30448 ++		return false;
352.30449 ++
352.30450 + 	assert(kgem_bo_can_map__cpu(kgem, bo, false));
352.30451 +-	assert(bo->tiling != I915_TILING_Y);
352.30452 + 
352.30453 + 	src = kgem_bo_map__cpu(kgem, bo);
352.30454 + 	if (src == NULL)
352.30455 +@@ -281,6 +283,9 @@ fallback:
352.30456 + 		if (box[n].y2 > extents.y2)
352.30457 + 			extents.y2 = box[n].y2;
352.30458 + 	}
352.30459 ++	if (!can_blt && sna->render.max_3d_size == 0)
352.30460 ++		goto fallback;
352.30461 ++
352.30462 + 	if (kgem_bo_can_map(kgem, src_bo)) {
352.30463 + 		/* Is it worth detiling? */
352.30464 + 		if ((extents.y2 - extents.y1 - 1) * src_bo->pitch < 4096)
352.30465 +@@ -477,6 +482,7 @@ fallback:
352.30466 + 			goto fallback;
352.30467 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.30468 + 	}
352.30469 ++	kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
352.30470 + 
352.30471 + 	tmp_nbox = nbox;
352.30472 + 	tmp_box = box;
352.30473 +@@ -539,6 +545,7 @@ fallback:
352.30474 + 				break;
352.30475 + 
352.30476 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.30477 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
352.30478 + 			tmp_box += nbox_this_time;
352.30479 + 		} while (1);
352.30480 + 	} else {
352.30481 +@@ -597,6 +604,7 @@ fallback:
352.30482 + 				break;
352.30483 + 
352.30484 + 			_kgem_set_mode(kgem, KGEM_BLT);
352.30485 ++			kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
352.30486 + 			tmp_box += nbox_this_time;
352.30487 + 		} while (1);
352.30488 + 	}
352.30489 +@@ -666,8 +674,10 @@ write_boxes_inplace__tiled(struct kgem *kgem,
352.30490 + {
352.30491 + 	uint8_t *dst;
352.30492 + 
352.30493 ++	if (bo->tiling == I915_TILING_Y)
352.30494 ++		return false;
352.30495 ++
352.30496 + 	assert(kgem->has_wc_mmap || kgem_bo_can_map__cpu(kgem, bo, true));
352.30497 +-	assert(bo->tiling != I915_TILING_Y);
352.30498 + 
352.30499 + 	if (kgem_bo_can_map__cpu(kgem, bo, true)) {
352.30500 + 		dst = kgem_bo_map__cpu(kgem, bo);
352.30501 +@@ -778,6 +788,15 @@ static bool __upload_inplace(struct kgem *kgem,
352.30502 + 	if (FORCE_INPLACE)
352.30503 + 		return FORCE_INPLACE > 0;
352.30504 + 
352.30505 ++	if (bo->exec)
352.30506 ++		return false;
352.30507 ++
352.30508 ++	if (bo->flush)
352.30509 ++		return true;
352.30510 ++
352.30511 ++	if (kgem_bo_can_map__cpu(kgem, bo, true))
352.30512 ++		return true;
352.30513 ++
352.30514 + 	/* If we are writing through the GTT, check first if we might be
352.30515 + 	 * able to almagamate a series of small writes into a single
352.30516 + 	 * operation.
352.30517 +@@ -849,6 +868,8 @@ bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
352.30518 + 		if (box[n].y2 > extents.y2)
352.30519 + 			extents.y2 = box[n].y2;
352.30520 + 	}
352.30521 ++	if (!can_blt && sna->render.max_3d_size == 0)
352.30522 ++		goto fallback;
352.30523 + 
352.30524 + 	/* Try to avoid switching rings... */
352.30525 + 	if (!can_blt || kgem->ring == KGEM_RENDER ||
352.30526 +@@ -1038,6 +1059,7 @@ tile:
352.30527 + 			goto fallback;
352.30528 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.30529 + 	}
352.30530 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30531 + 
352.30532 + 	if (kgem->gen >= 0100) {
352.30533 + 		cmd |= 8;
352.30534 +@@ -1129,6 +1151,7 @@ tile:
352.30535 + 			if (nbox) {
352.30536 + 				_kgem_submit(kgem);
352.30537 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.30538 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30539 + 			}
352.30540 + 
352.30541 + 			kgem_bo_destroy(kgem, src_bo);
352.30542 +@@ -1224,6 +1247,7 @@ tile:
352.30543 + 			if (nbox) {
352.30544 + 				_kgem_submit(kgem);
352.30545 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.30546 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30547 + 			}
352.30548 + 
352.30549 + 			kgem_bo_destroy(kgem, src_bo);
352.30550 +@@ -1541,6 +1565,7 @@ tile:
352.30551 + 			goto fallback;
352.30552 + 		_kgem_set_mode(kgem, KGEM_BLT);
352.30553 + 	}
352.30554 ++	kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30555 + 
352.30556 + 	if (sna->kgem.gen >= 0100) {
352.30557 + 		cmd |= 8;
352.30558 +@@ -1636,6 +1661,7 @@ tile:
352.30559 + 			if (nbox) {
352.30560 + 				_kgem_submit(kgem);
352.30561 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.30562 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30563 + 			}
352.30564 + 
352.30565 + 			kgem_bo_destroy(kgem, src_bo);
352.30566 +@@ -1732,6 +1758,7 @@ tile:
352.30567 + 			if (nbox) {
352.30568 + 				_kgem_submit(kgem);
352.30569 + 				_kgem_set_mode(kgem, KGEM_BLT);
352.30570 ++				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
352.30571 + 			}
352.30572 + 
352.30573 + 			kgem_bo_destroy(kgem, src_bo);
352.30574 +diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
352.30575 +index 6dd6fe88..2796d972 100644
352.30576 +--- a/src/sna/sna_present.c
352.30577 ++++ b/src/sna/sna_present.c
352.30578 +@@ -27,6 +27,7 @@
352.30579 + #include <sys/types.h>
352.30580 + #include <fcntl.h>
352.30581 + #include <unistd.h>
352.30582 ++#include <sys/poll.h>
352.30583 + #include <errno.h>
352.30584 + #include <xf86drm.h>
352.30585 + 
352.30586 +@@ -38,21 +39,73 @@
352.30587 + static present_screen_info_rec present_info;
352.30588 + 
352.30589 + struct sna_present_event {
352.30590 +-	uint64_t event_id;
352.30591 + 	xf86CrtcPtr crtc;
352.30592 ++	struct sna *sna;
352.30593 ++	struct list link;
352.30594 ++	uint64_t *event_id;
352.30595 ++	uint64_t target_msc;
352.30596 ++	int n_event_id;
352.30597 ++	bool queued;
352.30598 + };
352.30599 + 
352.30600 ++static void sna_present_unflip(ScreenPtr screen, uint64_t event_id);
352.30601 ++static bool sna_present_queue(struct sna_present_event *info,
352.30602 ++			      uint64_t last_msc);
352.30603 ++
352.30604 + static inline struct sna_present_event *
352.30605 + to_present_event(uintptr_t  data)
352.30606 + {
352.30607 + 	return (struct sna_present_event *)(data & ~3);
352.30608 + }
352.30609 + 
352.30610 ++static struct sna_present_event *info_alloc(struct sna *sna)
352.30611 ++{
352.30612 ++	struct sna_present_event *info;
352.30613 ++
352.30614 ++	info = sna->present.freed_info;
352.30615 ++	if (info) {
352.30616 ++		sna->present.freed_info = NULL;
352.30617 ++		return info;
352.30618 ++	}
352.30619 ++
352.30620 ++	return malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
352.30621 ++}
352.30622 ++
352.30623 ++static void info_free(struct sna_present_event *info)
352.30624 ++{
352.30625 ++	struct sna *sna = info->sna;
352.30626 ++
352.30627 ++	if (sna->present.freed_info)
352.30628 ++		free(sna->present.freed_info);
352.30629 ++
352.30630 ++	sna->present.freed_info = info;
352.30631 ++}
352.30632 ++
352.30633 ++static inline bool msc_before(uint64_t msc, uint64_t target)
352.30634 ++{
352.30635 ++	return (int64_t)(msc - target) < 0;
352.30636 ++}
352.30637 ++
352.30638 + #define MARK_PRESENT(x) ((void *)((uintptr_t)(x) | 2))
352.30639 + 
352.30640 +-static int pipe_from_crtc(RRCrtcPtr crtc)
352.30641 ++static inline xf86CrtcPtr unmask_crtc(xf86CrtcPtr crtc)
352.30642 ++{
352.30643 ++	return (xf86CrtcPtr)((uintptr_t)crtc & ~1);
352.30644 ++}
352.30645 ++
352.30646 ++static inline xf86CrtcPtr mark_crtc(xf86CrtcPtr crtc)
352.30647 ++{
352.30648 ++	return (xf86CrtcPtr)((uintptr_t)crtc | 1);
352.30649 ++}
352.30650 ++
352.30651 ++static inline bool has_vblank(xf86CrtcPtr crtc)
352.30652 ++{
352.30653 ++	return (uintptr_t)crtc & 1;
352.30654 ++}
352.30655 ++
352.30656 ++static inline int pipe_from_crtc(RRCrtcPtr crtc)
352.30657 + {
352.30658 +-	return crtc ? sna_crtc_to_pipe(crtc->devPrivate) : -1;
352.30659 ++	return crtc ? sna_crtc_pipe(crtc->devPrivate) : -1;
352.30660 + }
352.30661 + 
352.30662 + static uint32_t pipe_select(int pipe)
352.30663 +@@ -74,6 +127,215 @@ static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, i
352.30664 + 	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
352.30665 + }
352.30666 + 
352.30667 ++static uint64_t gettime_ust64(void)
352.30668 ++{
352.30669 ++	struct timespec tv;
352.30670 ++
352.30671 ++	if (clock_gettime(CLOCK_MONOTONIC, &tv))
352.30672 ++		return GetTimeInMicros();
352.30673 ++
352.30674 ++	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
352.30675 ++}
352.30676 ++
352.30677 ++static void vblank_complete(struct sna_present_event *info,
352.30678 ++			    uint64_t ust, uint64_t msc)
352.30679 ++{
352.30680 ++	int n;
352.30681 ++
352.30682 ++	if (msc_before(msc, info->target_msc)) {
352.30683 ++		DBG(("%s: event=%d too early, now %lld, expected %lld\n",
352.30684 ++		     __FUNCTION__,
352.30685 ++		     info->event_id[0],
352.30686 ++		     (long long)msc, (long long)info->target_msc));
352.30687 ++		if (sna_present_queue(info, msc))
352.30688 ++			return;
352.30689 ++	}
352.30690 ++
352.30691 ++	DBG(("%s: %d events complete\n", __FUNCTION__, info->n_event_id));
352.30692 ++	for (n = 0; n < info->n_event_id; n++) {
352.30693 ++		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete%s\n", __FUNCTION__,
352.30694 ++		     sna_crtc_pipe(info->crtc),
352.30695 ++		     (int)(ust / 1000000), (int)(ust % 1000000),
352.30696 ++		     (long long)msc, (long long)info->target_msc,
352.30697 ++		     (long long)info->event_id[n],
352.30698 ++		     info->target_msc && msc == (uint32_t)info->target_msc ? "" : ": MISS"));
352.30699 ++		present_event_notify(info->event_id[n], ust, msc);
352.30700 ++	}
352.30701 ++	if (info->n_event_id > 1)
352.30702 ++		free(info->event_id);
352.30703 ++	list_del(&info->link);
352.30704 ++	info_free(info);
352.30705 ++}
352.30706 ++
352.30707 ++static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target)
352.30708 ++{
352.30709 ++	const DisplayModeRec *mode = &crtc->desiredMode;
352.30710 ++	const struct ust_msc *swap = sna_crtc_last_swap(crtc);
352.30711 ++	int64_t delay, subframe;
352.30712 ++
352.30713 ++	assert(mode->Clock);
352.30714 ++
352.30715 ++	delay = target - swap->msc;
352.30716 ++	assert(delay >= 0);
352.30717 ++	if (delay > 1) { /* try to use the hw vblank for the last frame */
352.30718 ++		delay--;
352.30719 ++		subframe = 0;
352.30720 ++	} else {
352.30721 ++		subframe = gettime_ust64() - swap_ust(swap);
352.30722 ++		subframe += 500;
352.30723 ++		subframe /= 1000;
352.30724 ++	}
352.30725 ++	delay *= mode->VTotal * mode->HTotal / mode->Clock;
352.30726 ++	if (subframe < delay)
352.30727 ++		delay -= subframe;
352.30728 ++	else
352.30729 ++		delay = 0;
352.30730 ++
352.30731 ++	DBG(("%s: sleep %d frames, %llu ms\n", __FUNCTION__,
352.30732 ++	     (int)(target - swap->msc), (long long)delay));
352.30733 ++	assert(delay >= 0);
352.30734 ++	return MIN(delay, INT32_MAX);
352.30735 ++}
352.30736 ++
352.30737 ++static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
352.30738 ++{
352.30739 ++	struct sna_present_event *info = data;
352.30740 ++	union drm_wait_vblank vbl;
352.30741 ++	uint64_t msc, ust;
352.30742 ++
352.30743 ++	DBG(("%s(event=%lldx%d, now=%d)\n", __FUNCTION__, (long long)info->event_id[0], info->n_event_id, now));
352.30744 ++
352.30745 ++	VG_CLEAR(vbl);
352.30746 ++	vbl.request.type = DRM_VBLANK_RELATIVE;
352.30747 ++	vbl.request.sequence = 0;
352.30748 ++	if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
352.30749 ++		ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
352.30750 ++		msc = sna_crtc_record_vblank(info->crtc, &vbl);
352.30751 ++		DBG(("%s: event=%lld, target msc=%lld, now %lld\n",
352.30752 ++		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)msc));
352.30753 ++		if (msc_before(msc, info->target_msc)) {
352.30754 ++			int delta = info->target_msc - msc;
352.30755 ++			uint32_t delay;
352.30756 ++
352.30757 ++			DBG(("%s: too early, requeuing delta=%d\n", __FUNCTION__, delta));
352.30758 ++			assert(info->target_msc - msc < 1ull<<31);
352.30759 ++			if (delta <= 2) {
352.30760 ++				vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
352.30761 ++				vbl.request.sequence = info->target_msc;
352.30762 ++				vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
352.30763 ++				if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
352.30764 ++					DBG(("%s: scheduled new vblank event for %lld\n", __FUNCTION__, (long long)info->target_msc));
352.30765 ++					info->queued = true;
352.30766 ++					if (delta == 1) {
352.30767 ++						sna_crtc_set_vblank(info->crtc);
352.30768 ++						info->crtc = mark_crtc(info->crtc);
352.30769 ++					}
352.30770 ++					free(timer);
352.30771 ++					return 0;
352.30772 ++				}
352.30773 ++			}
352.30774 ++
352.30775 ++			delay = msc_to_delay(info->crtc, info->target_msc);
352.30776 ++			if (delay) {
352.30777 ++				DBG(("%s: requeueing timer for %dms delay\n", __FUNCTION__, delay));
352.30778 ++				return delay;
352.30779 ++			}
352.30780 ++
352.30781 ++			/* As a last resort use a blocking wait.
352.30782 ++			 * Less than a millisecond for (hopefully) a rare case.
352.30783 ++			 */
352.30784 ++			DBG(("%s: blocking wait!\n", __FUNCTION__));
352.30785 ++			vbl.request.type = DRM_VBLANK_ABSOLUTE;
352.30786 ++			vbl.request.sequence = info->target_msc;
352.30787 ++			if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
352.30788 ++				ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
352.30789 ++				msc = sna_crtc_record_vblank(info->crtc, &vbl);
352.30790 ++			} else {
352.30791 ++				DBG(("%s: blocking wait failed, fudging\n",
352.30792 ++				     __FUNCTION__));
352.30793 ++				goto fixup;
352.30794 ++			}
352.30795 ++		}
352.30796 ++	} else {
352.30797 ++fixup:
352.30798 ++		ust = gettime_ust64();
352.30799 ++		msc = info->target_msc;
352.30800 ++		DBG(("%s: event=%lld, CRTC OFF, target msc=%lld, was %lld (off)\n",
352.30801 ++		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)sna_crtc_last_swap(info->crtc)->msc));
352.30802 ++	}
352.30803 ++
352.30804 ++	vblank_complete(info, ust, msc);
352.30805 ++	free(timer);
352.30806 ++	return 0;
352.30807 ++}
352.30808 ++
352.30809 ++static bool sna_fake_vblank(struct sna_present_event *info)
352.30810 ++{
352.30811 ++	const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
352.30812 ++	uint32_t delay;
352.30813 ++
352.30814 ++	if (msc_before(swap->msc, info->target_msc))
352.30815 ++		delay = msc_to_delay(info->crtc, info->target_msc);
352.30816 ++	else
352.30817 ++		delay = 0;
352.30818 ++
352.30819 ++	DBG(("%s(event=%lldx%d, target_msc=%lld, msc=%lld, delay=%ums)\n",
352.30820 ++	     __FUNCTION__, (long long)info->event_id[0], info->n_event_id,
352.30821 ++	     (long long)info->target_msc, (long long)swap->msc, delay));
352.30822 ++	if (delay == 0) {
352.30823 ++		uint64_t ust, msc;
352.30824 ++
352.30825 ++		if (msc_before(swap->msc, info->target_msc)) {
352.30826 ++			/* Fixup and pretend it completed immediately */
352.30827 ++			msc = info->target_msc;
352.30828 ++			ust = gettime_ust64();
352.30829 ++		} else {
352.30830 ++			msc = swap->msc;
352.30831 ++			ust = swap_ust(swap);
352.30832 ++		}
352.30833 ++
352.30834 ++		vblank_complete(info, ust, msc);
352.30835 ++		return true;
352.30836 ++	}
352.30837 ++
352.30838 ++	return TimerSet(NULL, 0, delay, sna_fake_vblank_handler, info);
352.30839 ++}
352.30840 ++
352.30841 ++static bool sna_present_queue(struct sna_present_event *info,
352.30842 ++			      uint64_t last_msc)
352.30843 ++{
352.30844 ++	union drm_wait_vblank vbl;
352.30845 ++	int delta = info->target_msc - last_msc;
352.30846 ++
352.30847 ++	DBG(("%s: target msc=%llu, seq=%u (last_msc=%llu), delta=%d\n",
352.30848 ++	     __FUNCTION__,
352.30849 ++	     (long long)info->target_msc,
352.30850 ++	     (unsigned)info->target_msc,
352.30851 ++	     (long long)last_msc,
352.30852 ++	     delta));
352.30853 ++	assert(info->target_msc - last_msc < 1ull<<31);
352.30854 ++	assert(delta >= 0);
352.30855 ++
352.30856 ++	VG_CLEAR(vbl);
352.30857 ++	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
352.30858 ++	vbl.request.sequence = info->target_msc;
352.30859 ++	vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
352.30860 ++	if (delta > 2 ||
352.30861 ++	    sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc))) {
352.30862 ++		DBG(("%s: vblank enqueue failed, faking delta=%d\n", __FUNCTION__, delta));
352.30863 ++		if (!sna_fake_vblank(info))
352.30864 ++			return false;
352.30865 ++	} else {
352.30866 ++		info->queued = true;
352.30867 ++		if (delta == 1) {
352.30868 ++			sna_crtc_set_vblank(info->crtc);
352.30869 ++			info->crtc = mark_crtc(info->crtc);
352.30870 ++		}
352.30871 ++	}
352.30872 ++
352.30873 ++	return true;
352.30874 ++}
352.30875 ++
352.30876 + static RRCrtcPtr
352.30877 + sna_present_get_crtc(WindowPtr window)
352.30878 + {
352.30879 +@@ -81,7 +343,10 @@ sna_present_get_crtc(WindowPtr window)
352.30880 + 	BoxRec box;
352.30881 + 	xf86CrtcPtr crtc;
352.30882 + 
352.30883 +-	DBG(("%s\n", __FUNCTION__));
352.30884 ++	DBG(("%s: window=%ld (pixmap=%ld), box=(%d, %d)x(%d, %d)\n",
352.30885 ++	     __FUNCTION__, window->drawable.id, get_window_pixmap(window)->drawable.serialNumber,
352.30886 ++	     window->drawable.x, window->drawable.y,
352.30887 ++	     window->drawable.width, window->drawable.height));
352.30888 + 
352.30889 + 	box.x1 = window->drawable.x;
352.30890 + 	box.y1 = window->drawable.y;
352.30891 +@@ -99,26 +364,59 @@ static int
352.30892 + sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
352.30893 + {
352.30894 + 	struct sna *sna = to_sna_from_screen(crtc->pScreen);
352.30895 +-	int pipe = pipe_from_crtc(crtc);
352.30896 + 	union drm_wait_vblank vbl;
352.30897 + 
352.30898 +-	DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
352.30899 ++	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc->devPrivate)));
352.30900 ++	if (sna_crtc_has_vblank(crtc->devPrivate)) {
352.30901 ++		DBG(("%s: vblank active, reusing last swap msc/ust\n",
352.30902 ++		     __FUNCTION__));
352.30903 ++		goto last;
352.30904 ++	}
352.30905 + 
352.30906 + 	VG_CLEAR(vbl);
352.30907 + 	vbl.request.type = DRM_VBLANK_RELATIVE;
352.30908 + 	vbl.request.sequence = 0;
352.30909 +-	if (sna_wait_vblank(sna, &vbl, pipe) == 0) {
352.30910 ++	if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc->devPrivate)) == 0) {
352.30911 ++		struct sna_present_event *info;
352.30912 ++
352.30913 + 		*ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
352.30914 + 		*msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl);
352.30915 ++
352.30916 ++		info = info_alloc(sna);
352.30917 ++		if (info) {
352.30918 ++			info->crtc = crtc->devPrivate;
352.30919 ++			info->sna = sna;
352.30920 ++			info->target_msc = *msc + 1;
352.30921 ++			info->event_id = (uint64_t *)(info + 1);
352.30922 ++			info->n_event_id = 0;
352.30923 ++
352.30924 ++			vbl.request.type =
352.30925 ++				DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
352.30926 ++			vbl.request.sequence = info->target_msc;
352.30927 ++			vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
352.30928 ++
352.30929 ++			if (sna_wait_vblank(info->sna, &vbl,
352.30930 ++					    sna_crtc_pipe(info->crtc)) == 0) {
352.30931 ++				list_add(&info->link,
352.30932 ++					 &sna->present.vblank_queue);
352.30933 ++				info->queued = true;
352.30934 ++				sna_crtc_set_vblank(info->crtc);
352.30935 ++				info->crtc = mark_crtc(info->crtc);
352.30936 ++			} else
352.30937 ++				info_free(info);
352.30938 ++		}
352.30939 + 	} else {
352.30940 +-		const struct ust_msc *swap = sna_crtc_last_swap(crtc->devPrivate);
352.30941 +-		*ust = ust64(swap->tv_sec, swap->tv_usec);
352.30942 ++		const struct ust_msc *swap;
352.30943 ++last:
352.30944 ++		swap = sna_crtc_last_swap(crtc->devPrivate);
352.30945 ++		*ust = swap_ust(swap);
352.30946 + 		*msc = swap->msc;
352.30947 + 	}
352.30948 + 
352.30949 +-	DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld\n", __FUNCTION__, pipe,
352.30950 ++	DBG(("%s: pipe=%d, tv=%d.%06d seq=%d msc=%lld\n", __FUNCTION__,
352.30951 ++	     sna_crtc_pipe(crtc->devPrivate),
352.30952 + 	     (int)(*ust / 1000000), (int)(*ust % 1000000),
352.30953 +-	     (long long)*msc));
352.30954 ++	     vbl.reply.sequence, (long long)*msc));
352.30955 + 
352.30956 + 	return Success;
352.30957 + }
352.30958 +@@ -127,43 +425,106 @@ void
352.30959 + sna_present_vblank_handler(struct drm_event_vblank *event)
352.30960 + {
352.30961 + 	struct sna_present_event *info = to_present_event(event->user_data);
352.30962 ++	uint64_t msc;
352.30963 + 
352.30964 +-	DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
352.30965 +-	     sna_crtc_to_pipe(info->crtc),
352.30966 +-	     event->tv_sec, event->tv_usec, event->sequence,
352.30967 +-	     (long long)info->event_id));
352.30968 +-	present_event_notify(info->event_id,
352.30969 +-			     ust64(event->tv_sec, event->tv_usec),
352.30970 +-			     sna_crtc_record_event(info->crtc, event));
352.30971 +-	free(info);
352.30972 ++	if (!info->queued) {
352.30973 ++		DBG(("%s: arrived unexpectedly early (not queued)\n", __FUNCTION__));
352.30974 ++		assert(!has_vblank(info->crtc));
352.30975 ++		return;
352.30976 ++	}
352.30977 ++
352.30978 ++	if (has_vblank(info->crtc)) {
352.30979 ++		DBG(("%s: clearing immediate flag\n", __FUNCTION__));
352.30980 ++		info->crtc = unmask_crtc(info->crtc);
352.30981 ++		sna_crtc_clear_vblank(info->crtc);
352.30982 ++	}
352.30983 ++
352.30984 ++	msc = sna_crtc_record_event(info->crtc, event);
352.30985 ++
352.30986 ++	if (info->sna->mode.shadow_wait) {
352.30987 ++		DBG(("%s: recursed from TearFree\n", __FUNCTION__));
352.30988 ++		if (TimerSet(NULL, 0, 1, sna_fake_vblank_handler, info))
352.30989 ++			return;
352.30990 ++	}
352.30991 ++
352.30992 ++	vblank_complete(info, ust64(event->tv_sec, event->tv_usec), msc);
352.30993 + }
352.30994 + 
352.30995 + static int
352.30996 + sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
352.30997 + {
352.30998 + 	struct sna *sna = to_sna_from_screen(crtc->pScreen);
352.30999 +-	struct sna_present_event *event;
352.31000 +-	union drm_wait_vblank vbl;
352.31001 +-
352.31002 +-	DBG(("%s(pipe=%d, event=%lld, msc=%lld)\n",
352.31003 +-	     __FUNCTION__, pipe_from_crtc(crtc),
352.31004 +-	     (long long)event_id, (long long)msc));
352.31005 ++	struct sna_present_event *info, *tmp;
352.31006 ++	const struct ust_msc *swap;
352.31007 + 
352.31008 +-	event = malloc(sizeof(struct sna_present_event));
352.31009 +-	if (event == NULL)
352.31010 ++	if (!sna_crtc_is_on(crtc->devPrivate))
352.31011 + 		return BadAlloc;
352.31012 + 
352.31013 +-	event->event_id = event_id;
352.31014 +-	event->crtc = crtc->devPrivate;
352.31015 ++	swap = sna_crtc_last_swap(crtc->devPrivate);
352.31016 ++	DBG(("%s(pipe=%d, event=%lld, msc=%lld, last swap=%lld)\n",
352.31017 ++	     __FUNCTION__, sna_crtc_pipe(crtc->devPrivate),
352.31018 ++	     (long long)event_id, (long long)msc, (long long)swap->msc));
352.31019 + 
352.31020 +-	VG_CLEAR(vbl);
352.31021 +-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
352.31022 +-	vbl.request.sequence = msc;
352.31023 +-	vbl.request.signal = (uintptr_t)MARK_PRESENT(event);
352.31024 +-	if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(event->crtc))) {
352.31025 +-		DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
352.31026 +-		free(event);
352.31027 +-		return BadMatch;
352.31028 ++	if (warn_unless((int64_t)(msc - swap->msc) >= 0)) {
352.31029 ++		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
352.31030 ++		     sna_crtc_pipe(crtc->devPrivate),
352.31031 ++		     swap->tv_sec, swap->tv_usec,
352.31032 ++		     (long long)swap->msc, (long long)msc,
352.31033 ++		     (long long)event_id));
352.31034 ++		present_event_notify(event_id, swap_ust(swap), swap->msc);
352.31035 ++		return Success;
352.31036 ++	}
352.31037 ++	if (warn_unless(msc - swap->msc < 1ull<<31))
352.31038 ++		return BadValue;
352.31039 ++
352.31040 ++	list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
352.31041 ++		if (tmp->target_msc == msc &&
352.31042 ++		    unmask_crtc(tmp->crtc) == crtc->devPrivate) {
352.31043 ++			uint64_t *events = tmp->event_id;
352.31044 ++
352.31045 ++			if (tmp->n_event_id &&
352.31046 ++			    is_power_of_two(tmp->n_event_id)) {
352.31047 ++				events = malloc(2*sizeof(uint64_t)*tmp->n_event_id);
352.31048 ++				if (events == NULL)
352.31049 ++					return BadAlloc;
352.31050 ++
352.31051 ++				memcpy(events,
352.31052 ++				       tmp->event_id,
352.31053 ++				       tmp->n_event_id*sizeof(uint64_t));
352.31054 ++				if (tmp->n_event_id != 1)
352.31055 ++					free(tmp->event_id);
352.31056 ++				tmp->event_id = events;
352.31057 ++			}
352.31058 ++
352.31059 ++			DBG(("%s: appending event=%lld to vblank %lld x %d\n",
352.31060 ++			     __FUNCTION__, (long long)event_id, (long long)msc, tmp->n_event_id+1));
352.31061 ++			events[tmp->n_event_id++] = event_id;
352.31062 ++			return Success;
352.31063 ++		}
352.31064 ++		if ((int64_t)(tmp->target_msc - msc) > 0) {
352.31065 ++			DBG(("%s: previous target_msc=%lld invalid for coalescing\n",
352.31066 ++			     __FUNCTION__, (long long)tmp->target_msc));
352.31067 ++			break;
352.31068 ++		}
352.31069 ++	}
352.31070 ++
352.31071 ++	info = info_alloc(sna);
352.31072 ++	if (info == NULL)
352.31073 ++		return BadAlloc;
352.31074 ++
352.31075 ++	info->crtc = crtc->devPrivate;
352.31076 ++	info->sna = sna;
352.31077 ++	info->target_msc = msc;
352.31078 ++	info->event_id = (uint64_t *)(info + 1);
352.31079 ++	info->event_id[0] = event_id;
352.31080 ++	info->n_event_id = 1;
352.31081 ++	list_add_tail(&info->link, &tmp->link);
352.31082 ++	info->queued = false;
352.31083 ++
352.31084 ++	if (!sna_present_queue(info, swap->msc)) {
352.31085 ++		list_del(&info->link);
352.31086 ++		info_free(info);
352.31087 ++		return BadAlloc;
352.31088 + 	}
352.31089 + 
352.31090 + 	return Success;
352.31091 +@@ -180,14 +541,6 @@ sna_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
352.31092 + static void
352.31093 + sna_present_flush(WindowPtr window)
352.31094 + {
352.31095 +-	PixmapPtr pixmap = get_window_pixmap(window);
352.31096 +-	struct sna_pixmap *priv;
352.31097 +-
352.31098 +-	DBG(("%s(pixmap=%ld)\n", __FUNCTION__, pixmap->drawable.serialNumber));
352.31099 +-
352.31100 +-	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | MOVE_ASYNC_HINT | __MOVE_FORCE);
352.31101 +-	if (priv && priv->gpu_bo)
352.31102 +-		kgem_scanout_flush(&to_sna_from_pixmap(pixmap)->kgem, priv->gpu_bo);
352.31103 + }
352.31104 + 
352.31105 + static bool
352.31106 +@@ -201,8 +554,13 @@ check_flip__crtc(struct sna *sna,
352.31107 + 
352.31108 + 	assert(sna->scrn->vtSema);
352.31109 + 
352.31110 +-	if (sna->mode.shadow_active) {
352.31111 +-		DBG(("%s: shadow buffer active\n", __FUNCTION__));
352.31112 ++	if (!sna->mode.front_active) {
352.31113 ++		DBG(("%s: DPMS off, no flips\n", __FUNCTION__));
352.31114 ++		return FALSE;
352.31115 ++	}
352.31116 ++
352.31117 ++	if (sna->mode.rr_active) {
352.31118 ++		DBG(("%s: RandR transformation active\n", __FUNCTION__));
352.31119 + 		return false;
352.31120 + 	}
352.31121 + 
352.31122 +@@ -224,6 +582,11 @@ sna_present_check_flip(RRCrtcPtr crtc,
352.31123 + 	     pixmap->drawable.serialNumber,
352.31124 + 	     sync_flip));
352.31125 + 
352.31126 ++	if (!sna->scrn->vtSema) {
352.31127 ++		DBG(("%s: VT switched away, no flips\n", __FUNCTION__));
352.31128 ++		return FALSE;
352.31129 ++	}
352.31130 ++
352.31131 + 	if (sna->flags & SNA_NO_FLIP) {
352.31132 + 		DBG(("%s: flips not suported\n", __FUNCTION__));
352.31133 + 		return FALSE;
352.31134 +@@ -231,7 +594,7 @@ sna_present_check_flip(RRCrtcPtr crtc,
352.31135 + 
352.31136 + 	if (sync_flip) {
352.31137 + 		if ((sna->flags & SNA_HAS_FLIP) == 0) {
352.31138 +-			DBG(("%s: async flips not suported\n", __FUNCTION__));
352.31139 ++			DBG(("%s: sync flips not suported\n", __FUNCTION__));
352.31140 + 			return FALSE;
352.31141 + 		}
352.31142 + 	} else {
352.31143 +@@ -257,24 +620,39 @@ sna_present_check_flip(RRCrtcPtr crtc,
352.31144 + 		return FALSE;
352.31145 + 	}
352.31146 + 
352.31147 +-	return TRUE;
352.31148 +-}
352.31149 +-
352.31150 +-static uint64_t gettime_ust64(void)
352.31151 +-{
352.31152 +-	struct timespec tv;
352.31153 ++	if (flip->pinned) {
352.31154 ++		assert(flip->gpu_bo);
352.31155 ++		if (sna->flags & SNA_LINEAR_FB) {
352.31156 ++			if (flip->gpu_bo->tiling != I915_TILING_NONE) {
352.31157 ++				DBG(("%s: pined bo, tilng=%d needs NONE\n",
352.31158 ++				     __FUNCTION__, flip->gpu_bo->tiling));
352.31159 ++				return FALSE;
352.31160 ++			}
352.31161 ++		} else {
352.31162 ++			if (!sna->kgem.can_scanout_y &&
352.31163 ++			    flip->gpu_bo->tiling == I915_TILING_Y) {
352.31164 ++				DBG(("%s: pined bo, tilng=%d and can't scanout Y\n",
352.31165 ++				     __FUNCTION__, flip->gpu_bo->tiling));
352.31166 ++				return FALSE;
352.31167 ++			}
352.31168 ++		}
352.31169 + 
352.31170 +-	if (clock_gettime(CLOCK_MONOTONIC, &tv))
352.31171 +-		return 0;
352.31172 ++		if (flip->gpu_bo->pitch & 63) {
352.31173 ++			DBG(("%s: pined bo, bad pitch=%d\n",
352.31174 ++			     __FUNCTION__, flip->gpu_bo->pitch));
352.31175 ++			return FALSE;
352.31176 ++		}
352.31177 ++	}
352.31178 + 
352.31179 +-	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
352.31180 ++	return TRUE;
352.31181 + }
352.31182 + 
352.31183 + static Bool
352.31184 +-page_flip__async(RRCrtcPtr crtc,
352.31185 +-		 uint64_t event_id,
352.31186 +-		 uint64_t target_msc,
352.31187 +-		 struct kgem_bo *bo)
352.31188 ++flip__async(struct sna *sna,
352.31189 ++	    RRCrtcPtr crtc,
352.31190 ++	    uint64_t event_id,
352.31191 ++	    uint64_t target_msc,
352.31192 ++	    struct kgem_bo *bo)
352.31193 + {
352.31194 + 	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
352.31195 + 	     __FUNCTION__,
352.31196 +@@ -282,17 +660,17 @@ page_flip__async(RRCrtcPtr crtc,
352.31197 + 	     (long long)event_id,
352.31198 + 	     bo->handle));
352.31199 + 
352.31200 +-	if (!sna_page_flip(to_sna_from_screen(crtc->pScreen), bo, NULL, NULL)) {
352.31201 ++	if (!sna_page_flip(sna, bo, NULL, NULL)) {
352.31202 + 		DBG(("%s: async pageflip failed\n", __FUNCTION__));
352.31203 + 		present_info.capabilities &= ~PresentCapabilityAsync;
352.31204 + 		return FALSE;
352.31205 + 	}
352.31206 + 
352.31207 +-	DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
352.31208 ++	DBG(("%s: pipe=%d tv=%ld.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
352.31209 + 	     pipe_from_crtc(crtc),
352.31210 +-	     gettime_ust64() / 1000000, gettime_ust64() % 1000000,
352.31211 +-	     sna_crtc_last_swap(crtc->devPrivate)->msc,
352.31212 +-	     (long long)event_id));
352.31213 ++	     (long)(gettime_ust64() / 1000000), (int)(gettime_ust64() % 1000000),
352.31214 ++	     crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL,
352.31215 ++	     (long long)target_msc, (long long)event_id));
352.31216 + 	present_event_notify(event_id, gettime_ust64(), target_msc);
352.31217 + 	return TRUE;
352.31218 + }
352.31219 +@@ -303,7 +681,12 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
352.31220 + 	struct sna_present_event *info = data;
352.31221 + 	struct ust_msc swap;
352.31222 + 
352.31223 +-	DBG(("%s(sequence=%d)\n", __FUNCTION__, event->sequence));
352.31224 ++	DBG(("%s(sequence=%d): event=%lld\n", __FUNCTION__, event->sequence, (long long)info->event_id[0]));
352.31225 ++	assert(info->n_event_id == 1);
352.31226 ++	if (!info->queued) {
352.31227 ++		DBG(("%s: arrived unexpectedly early (not queued)\n", __FUNCTION__));
352.31228 ++		return;
352.31229 ++	}
352.31230 + 
352.31231 + 	if (info->crtc == NULL) {
352.31232 + 		swap.tv_sec = event->tv_sec;
352.31233 +@@ -312,22 +695,33 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
352.31234 + 	} else
352.31235 + 		swap = *sna_crtc_last_swap(info->crtc);
352.31236 + 
352.31237 +-	DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
352.31238 +-	     info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
352.31239 ++	DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld (target %lld), event=%lld complete%s\n", __FUNCTION__,
352.31240 ++	     info->crtc ? sna_crtc_pipe(info->crtc) : -1,
352.31241 + 	     swap.tv_sec, swap.tv_usec, (long long)swap.msc,
352.31242 +-	     (long long)info->event_id));
352.31243 +-	present_event_notify(info->event_id, ust64(swap.tv_sec, swap.tv_usec), swap.msc);
352.31244 +-	free(info);
352.31245 ++	     (long long)info->target_msc,
352.31246 ++	     (long long)info->event_id[0],
352.31247 ++	     info->target_msc && info->target_msc == swap.msc ? "" : ": MISS"));
352.31248 ++	present_event_notify(info->event_id[0], swap_ust(&swap), swap.msc);
352.31249 ++	if (info->crtc)
352.31250 ++		sna_crtc_clear_vblank(info->crtc);
352.31251 ++
352.31252 ++	if (info->sna->present.unflip) {
352.31253 ++		DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, (long long)info->sna->present.unflip));
352.31254 ++		sna_present_unflip(xf86ScrnToScreen(info->sna->scrn),
352.31255 ++				   info->sna->present.unflip);
352.31256 ++		info->sna->present.unflip = 0;
352.31257 ++	}
352.31258 ++	info_free(info);
352.31259 + }
352.31260 + 
352.31261 + static Bool
352.31262 +-page_flip(ScreenPtr screen,
352.31263 +-	  RRCrtcPtr crtc,
352.31264 +-	  uint64_t event_id,
352.31265 +-	  struct kgem_bo *bo)
352.31266 ++flip(struct sna *sna,
352.31267 ++     RRCrtcPtr crtc,
352.31268 ++     uint64_t event_id,
352.31269 ++     uint64_t target_msc,
352.31270 ++     struct kgem_bo *bo)
352.31271 + {
352.31272 +-	struct sna *sna = to_sna_from_screen(screen);
352.31273 +-	struct sna_present_event *event;
352.31274 ++	struct sna_present_event *info;
352.31275 + 
352.31276 + 	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
352.31277 + 	     __FUNCTION__,
352.31278 +@@ -335,18 +729,27 @@ page_flip(ScreenPtr screen,
352.31279 + 	     (long long)event_id,
352.31280 + 	     bo->handle));
352.31281 + 
352.31282 +-	event = malloc(sizeof(struct sna_present_event));
352.31283 +-	if (event == NULL)
352.31284 ++	info = info_alloc(sna);
352.31285 ++	if (info == NULL)
352.31286 + 		return FALSE;
352.31287 + 
352.31288 +-	event->event_id = event_id;
352.31289 +-	event->crtc = crtc ? crtc->devPrivate : NULL;
352.31290 +-	if (!sna_page_flip(sna, bo, present_flip_handler, event)) {
352.31291 ++	info->crtc = crtc ? crtc->devPrivate : NULL;
352.31292 ++	info->sna = sna;
352.31293 ++	info->event_id = (uint64_t *)(info + 1);
352.31294 ++	info->event_id[0] = event_id;
352.31295 ++	info->n_event_id = 1;
352.31296 ++	info->target_msc = target_msc;
352.31297 ++	info->queued = false;
352.31298 ++
352.31299 ++	if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
352.31300 + 		DBG(("%s: pageflip failed\n", __FUNCTION__));
352.31301 +-		free(event);
352.31302 ++		info_free(info);
352.31303 + 		return FALSE;
352.31304 + 	}
352.31305 + 
352.31306 ++	info->queued = true;
352.31307 ++	if (info->crtc)
352.31308 ++		sna_crtc_set_vblank(info->crtc);
352.31309 + 	return TRUE;
352.31310 + }
352.31311 + 
352.31312 +@@ -358,12 +761,48 @@ get_flip_bo(PixmapPtr pixmap)
352.31313 + 
352.31314 + 	DBG(("%s(pixmap=%ld)\n", __FUNCTION__, pixmap->drawable.serialNumber));
352.31315 + 
352.31316 +-	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_FORCE);
352.31317 ++	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT | __MOVE_FORCE);
352.31318 + 	if (priv == NULL) {
352.31319 + 		DBG(("%s: cannot force pixmap to the GPU\n", __FUNCTION__));
352.31320 + 		return NULL;
352.31321 + 	}
352.31322 + 
352.31323 ++	if (priv->gpu_bo->scanout)
352.31324 ++		return priv->gpu_bo;
352.31325 ++
352.31326 ++	if (sna->kgem.has_llc && !wedged(sna) && !priv->pinned) {
352.31327 ++		struct kgem_bo *bo;
352.31328 ++		uint32_t tiling;
352.31329 ++
352.31330 ++		tiling = I915_TILING_NONE;
352.31331 ++		if ((sna->flags & SNA_LINEAR_FB) == 0)
352.31332 ++			tiling = I915_TILING_X;
352.31333 ++
352.31334 ++		bo = kgem_create_2d(&sna->kgem,
352.31335 ++				    pixmap->drawable.width,
352.31336 ++				    pixmap->drawable.height,
352.31337 ++				    pixmap->drawable.bitsPerPixel,
352.31338 ++				    tiling, CREATE_SCANOUT | CREATE_CACHED);
352.31339 ++		if (bo) {
352.31340 ++			BoxRec box;
352.31341 ++
352.31342 ++			box.x1 = box.y1 = 0;
352.31343 ++			box.x2 = pixmap->drawable.width;
352.31344 ++			box.y2 = pixmap->drawable.height;
352.31345 ++
352.31346 ++			if (sna->render.copy_boxes(sna, GXcopy,
352.31347 ++						   &pixmap->drawable, priv->gpu_bo, 0, 0,
352.31348 ++						   &pixmap->drawable, bo, 0, 0,
352.31349 ++						   &box, 1, 0)) {
352.31350 ++				sna_pixmap_unmap(pixmap, priv);
352.31351 ++				kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
352.31352 ++
352.31353 ++				priv->gpu_bo = bo;
352.31354 ++			} else
352.31355 ++				kgem_bo_destroy(&sna->kgem, bo);
352.31356 ++		}
352.31357 ++	}
352.31358 ++
352.31359 + 	if (sna->flags & SNA_LINEAR_FB &&
352.31360 + 	    priv->gpu_bo->tiling &&
352.31361 + 	    !sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
352.31362 +@@ -372,12 +811,17 @@ get_flip_bo(PixmapPtr pixmap)
352.31363 + 	}
352.31364 + 
352.31365 + 	if (priv->gpu_bo->tiling == I915_TILING_Y &&
352.31366 ++	    !sna->kgem.can_scanout_y &&
352.31367 + 	    !sna_pixmap_change_tiling(pixmap, I915_TILING_X)) {
352.31368 + 		DBG(("%s: invalid Y-tiling, cannot convert\n", __FUNCTION__));
352.31369 + 		return NULL;
352.31370 + 	}
352.31371 + 
352.31372 +-	priv->pinned |= PIN_SCANOUT;
352.31373 ++	if (priv->gpu_bo->pitch & 63) {
352.31374 ++		DBG(("%s: invalid pitch, no conversion\n", __FUNCTION__));
352.31375 ++		return NULL;
352.31376 ++	}
352.31377 ++
352.31378 + 	return priv->gpu_bo;
352.31379 + }
352.31380 + 
352.31381 +@@ -388,6 +832,7 @@ sna_present_flip(RRCrtcPtr crtc,
352.31382 + 		 PixmapPtr pixmap,
352.31383 + 		 Bool sync_flip)
352.31384 + {
352.31385 ++	struct sna *sna = to_sna_from_pixmap(pixmap);
352.31386 + 	struct kgem_bo *bo;
352.31387 + 
352.31388 + 	DBG(("%s(pipe=%d, event=%lld, msc=%lld, pixmap=%ld, sync?=%d)\n",
352.31389 +@@ -397,11 +842,32 @@ sna_present_flip(RRCrtcPtr crtc,
352.31390 + 	     (long long)target_msc,
352.31391 + 	     pixmap->drawable.serialNumber, sync_flip));
352.31392 + 
352.31393 +-	if (!check_flip__crtc(to_sna_from_pixmap(pixmap), crtc)) {
352.31394 ++	if (!check_flip__crtc(sna, crtc)) {
352.31395 + 		DBG(("%s: flip invalid for CRTC\n", __FUNCTION__));
352.31396 + 		return FALSE;
352.31397 + 	}
352.31398 + 
352.31399 ++	assert(sna->present.unflip == 0);
352.31400 ++
352.31401 ++	if (sna->flags & SNA_TEAR_FREE) {
352.31402 ++		DBG(("%s: disabling TearFree (was %s) in favour of Present flips\n",
352.31403 ++		     __FUNCTION__, sna->mode.shadow_enabled ? "enabled" : "disabled"));
352.31404 ++		sna->mode.shadow_enabled = false;
352.31405 ++	}
352.31406 ++	assert(!sna->mode.shadow_enabled);
352.31407 ++
352.31408 ++	if (sna->mode.flip_active) {
352.31409 ++		struct pollfd pfd;
352.31410 ++
352.31411 ++		DBG(("%s: flips still pending, stalling\n", __FUNCTION__));
352.31412 ++		pfd.fd = sna->kgem.fd;
352.31413 ++		pfd.events = POLLIN;
352.31414 ++		while (poll(&pfd, 1, 0) == 1)
352.31415 ++			sna_mode_wakeup(sna);
352.31416 ++		if (sna->mode.flip_active)
352.31417 ++			return FALSE;
352.31418 ++	}
352.31419 ++
352.31420 + 	bo = get_flip_bo(pixmap);
352.31421 + 	if (bo == NULL) {
352.31422 + 		DBG(("%s: flip invalid bo\n", __FUNCTION__));
352.31423 +@@ -409,9 +875,9 @@ sna_present_flip(RRCrtcPtr crtc,
352.31424 + 	}
352.31425 + 
352.31426 + 	if (sync_flip)
352.31427 +-		return page_flip(crtc->pScreen, crtc, event_id, bo);
352.31428 ++		return flip(sna, crtc, event_id, target_msc, bo);
352.31429 + 	else
352.31430 +-		return page_flip__async(crtc, event_id, target_msc, bo);
352.31431 ++		return flip__async(sna, crtc, event_id, target_msc, bo);
352.31432 + }
352.31433 + 
352.31434 + static void
352.31435 +@@ -421,29 +887,70 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id)
352.31436 + 	struct kgem_bo *bo;
352.31437 + 
352.31438 + 	DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id));
352.31439 +-	if (sna->mode.front_active == 0 || sna->mode.shadow_active) {
352.31440 ++	if (sna->mode.front_active == 0 || sna->mode.rr_active) {
352.31441 + 		const struct ust_msc *swap;
352.31442 + 
352.31443 + 		DBG(("%s: no CRTC active, perform no-op flip\n", __FUNCTION__));
352.31444 + 
352.31445 + notify:
352.31446 +-		swap = sna_crtc_last_swap(sna_mode_first_crtc(sna));
352.31447 +-		DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
352.31448 ++		swap = sna_crtc_last_swap(sna_primary_crtc(sna));
352.31449 ++		DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld, event=%lld complete\n", __FUNCTION__,
352.31450 + 		     -1,
352.31451 + 		     swap->tv_sec, swap->tv_usec, (long long)swap->msc,
352.31452 + 		     (long long)event_id));
352.31453 +-		present_event_notify(event_id,
352.31454 +-				     ust64(swap->tv_sec, swap->tv_usec),
352.31455 +-				     swap->msc);
352.31456 ++		present_event_notify(event_id, swap_ust(swap), swap->msc);
352.31457 ++		return;
352.31458 ++	}
352.31459 ++
352.31460 ++	assert(!sna->mode.shadow_enabled);
352.31461 ++	if (sna->mode.flip_active) {
352.31462 ++		DBG(("%s: %d outstanding flips, queueing unflip\n", __FUNCTION__, sna->mode.flip_active));
352.31463 ++		assert(sna->present.unflip == 0);
352.31464 ++		sna->present.unflip = event_id;
352.31465 + 		return;
352.31466 + 	}
352.31467 + 
352.31468 ++	if (sna->flags & SNA_TEAR_FREE) {
352.31469 ++		DBG(("%s: %s TearFree after Present flips\n",
352.31470 ++		     __FUNCTION__, sna->mode.shadow_damage != NULL ? "enabling" : "disabling"));
352.31471 ++		sna->mode.shadow_enabled = sna->mode.shadow_damage != NULL;
352.31472 ++	}
352.31473 ++
352.31474 + 	bo = get_flip_bo(screen->GetScreenPixmap(screen));
352.31475 +-	if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) {
352.31476 ++	if (bo == NULL) {
352.31477 ++reset_mode:
352.31478 + 		DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__));
352.31479 + 		xf86SetDesiredModes(sna->scrn);
352.31480 + 		goto notify;
352.31481 + 	}
352.31482 ++
352.31483 ++	/* Are we unflipping after a failure that left our ScreenP in place? */
352.31484 ++	if (!sna_needs_page_flip(sna, bo))
352.31485 ++		goto notify;
352.31486 ++
352.31487 ++	assert(sna_pixmap(screen->GetScreenPixmap(screen))->pinned & PIN_SCANOUT);
352.31488 ++
352.31489 ++	if (sna->flags & SNA_HAS_ASYNC_FLIP) {
352.31490 ++		DBG(("%s: trying async flip restore\n", __FUNCTION__));
352.31491 ++		if (flip__async(sna, NULL, event_id, 0, bo))
352.31492 ++			return;
352.31493 ++	}
352.31494 ++
352.31495 ++	if (!flip(sna, NULL, event_id, 0, bo))
352.31496 ++		goto reset_mode;
352.31497 ++}
352.31498 ++
352.31499 ++void sna_present_cancel_flip(struct sna *sna)
352.31500 ++{
352.31501 ++	if (sna->present.unflip) {
352.31502 ++		const struct ust_msc *swap;
352.31503 ++
352.31504 ++		swap = sna_crtc_last_swap(sna_primary_crtc(sna));
352.31505 ++		present_event_notify(sna->present.unflip,
352.31506 ++				     swap_ust(swap), swap->msc);
352.31507 ++
352.31508 ++		sna->present.unflip = 0;
352.31509 ++	}
352.31510 + }
352.31511 + 
352.31512 + static present_screen_info_rec present_info = {
352.31513 +@@ -463,10 +970,13 @@ static present_screen_info_rec present_info = {
352.31514 + 
352.31515 + bool sna_present_open(struct sna *sna, ScreenPtr screen)
352.31516 + {
352.31517 ++	DBG(("%s(num_crtc=%d)\n", __FUNCTION__, sna->mode.num_real_crtc));
352.31518 ++
352.31519 + 	if (sna->mode.num_real_crtc == 0)
352.31520 + 		return false;
352.31521 + 
352.31522 + 	sna_present_update(sna);
352.31523 ++	list_init(&sna->present.vblank_queue);
352.31524 + 
352.31525 + 	return present_screen_init(screen, &present_info);
352.31526 + }
352.31527 +diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
352.31528 +index 3fbb9ecb..3e935d57 100644
352.31529 +--- a/src/sna/sna_render.c
352.31530 ++++ b/src/sna/sna_render.c
352.31531 +@@ -54,7 +54,7 @@ sna_format_for_depth(int depth)
352.31532 + {
352.31533 + 	switch (depth) {
352.31534 + 	case 1: return PICT_a1;
352.31535 +-	case 4: return PICT_a4;
352.31536 ++	case 4: return PICT_x4a4;
352.31537 + 	case 8: return PICT_a8;
352.31538 + 	case 15: return PICT_x1r5g5b5;
352.31539 + 	case 16: return PICT_r5g6b5;
352.31540 +@@ -272,18 +272,6 @@ no_render_context_switch(struct kgem *kgem,
352.31541 + }
352.31542 + 
352.31543 + static void
352.31544 +-no_render_retire(struct kgem *kgem)
352.31545 +-{
352.31546 +-	(void)kgem;
352.31547 +-}
352.31548 +-
352.31549 +-static void
352.31550 +-no_render_expire(struct kgem *kgem)
352.31551 +-{
352.31552 +-	(void)kgem;
352.31553 +-}
352.31554 +-
352.31555 +-static void
352.31556 + no_render_fini(struct sna *sna)
352.31557 + {
352.31558 + 	(void)sna;
352.31559 +@@ -316,8 +304,6 @@ const char *no_render_init(struct sna *sna)
352.31560 + 	render->fini = no_render_fini;
352.31561 + 
352.31562 + 	sna->kgem.context_switch = no_render_context_switch;
352.31563 +-	sna->kgem.retire = no_render_retire;
352.31564 +-	sna->kgem.expire = no_render_expire;
352.31565 + 	if (sna->kgem.has_blt)
352.31566 + 		sna->kgem.ring = KGEM_BLT;
352.31567 + 
352.31568 +@@ -407,10 +393,7 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box, bool blt)
352.31569 + 		}
352.31570 + 	}
352.31571 + 
352.31572 +-	if (priv->shm) {
352.31573 +-		assert(!priv->flush);
352.31574 +-		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.31575 +-	}
352.31576 ++	add_shm_flush(sna, priv);
352.31577 + 
352.31578 + 	DBG(("%s for box=(%d, %d), (%d, %d)\n",
352.31579 + 	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
352.31580 +@@ -567,6 +550,7 @@ static struct kgem_bo *upload(struct sna *sna,
352.31581 + 			assert(priv->gpu_damage == NULL);
352.31582 + 			assert(priv->gpu_bo == NULL);
352.31583 + 			assert(bo->proxy != NULL);
352.31584 ++			sna_damage_all(&priv->cpu_damage, pixmap);
352.31585 + 			kgem_proxy_bo_attach(bo, &priv->gpu_bo);
352.31586 + 		}
352.31587 + 	}
352.31588 +@@ -627,10 +611,7 @@ sna_render_pixmap_bo(struct sna *sna,
352.31589 + 		    !priv->cpu_bo->snoop && priv->cpu_bo->pitch < 4096) {
352.31590 + 			DBG(("%s: CPU all damaged\n", __FUNCTION__));
352.31591 + 			channel->bo = priv->cpu_bo;
352.31592 +-			if (priv->shm) {
352.31593 +-				assert(!priv->flush);
352.31594 +-				sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
352.31595 +-			}
352.31596 ++			add_shm_flush(sna, priv);
352.31597 + 			goto done;
352.31598 + 		}
352.31599 + 	}
352.31600 +@@ -1275,6 +1256,7 @@ sna_render_picture_extract(struct sna *sna,
352.31601 + 			assert(priv->gpu_damage == NULL);
352.31602 + 			assert(priv->gpu_bo == NULL);
352.31603 + 			assert(bo->proxy != NULL);
352.31604 ++			sna_damage_all(&priv->cpu_damage, pixmap);
352.31605 + 			kgem_proxy_bo_attach(bo, &priv->gpu_bo);
352.31606 + 		}
352.31607 + 	}
352.31608 +@@ -1338,6 +1320,8 @@ sna_render_picture_convolve(struct sna *sna,
352.31609 + 	 */
352.31610 + 	DBG(("%s: origin=(%d,%d) kernel=%dx%d, size=%dx%d\n",
352.31611 + 	     __FUNCTION__, x_off, y_off, cw, ch, w, h));
352.31612 ++	if (cw*ch > 32) /* too much loss of precision from quantization! */
352.31613 ++		return -1;
352.31614 + 
352.31615 + 	assert(picture->pDrawable);
352.31616 + 	assert(picture->filter == PictFilterConvolution);
352.31617 +@@ -1388,9 +1372,9 @@ sna_render_picture_convolve(struct sna *sna,
352.31618 + 			alpha = CreateSolidPicture(0, &color, &error);
352.31619 + 			if (alpha) {
352.31620 + 				sna_composite(PictOpAdd, picture, alpha, tmp,
352.31621 +-					      x, y,
352.31622 ++					      x-(x_off+i), y-(y_off+j),
352.31623 ++					      0, 0,
352.31624 + 					      0, 0,
352.31625 +-					      x_off+i, y_off+j,
352.31626 + 					      w, h);
352.31627 + 				FreePicture(alpha, 0);
352.31628 + 			}
352.31629 +@@ -2183,11 +2167,11 @@ copy_overlap(struct sna *sna, uint8_t alu,
352.31630 + 	ret = (sna->render.copy_boxes(sna, GXcopy,
352.31631 + 				      draw, bo, src_dx, src_dy,
352.31632 + 				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
352.31633 +-				      box, n , 0) &&
352.31634 ++				      box, n, 0) &&
352.31635 + 	       sna->render.copy_boxes(sna, alu,
352.31636 + 				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
352.31637 + 				      draw, bo, dst_dx, dst_dy,
352.31638 +-				      box, n , 0));
352.31639 ++				      box, n, 0));
352.31640 + 
352.31641 + 	screen->DestroyPixmap(tmp);
352.31642 + 	return ret;
352.31643 +@@ -2308,16 +2292,22 @@ static bool can_copy_cpu(struct sna *sna,
352.31644 + 			 struct kgem_bo *src,
352.31645 + 			 struct kgem_bo *dst)
352.31646 + {
352.31647 +-	if (src->tiling != dst->tiling)
352.31648 +-		return false;
352.31649 ++	DBG(("%s: tiling=%d:%d, pitch=%d:%d, can_map=%d:%d[%d]\n",
352.31650 ++	     __FUNCTION__,
352.31651 ++	     src->tiling, dst->tiling,
352.31652 ++	     src->pitch, dst->pitch,
352.31653 ++	     kgem_bo_can_map__cpu(&sna->kgem, src, false),
352.31654 ++	     kgem_bo_can_map__cpu(&sna->kgem, dst, true),
352.31655 ++	     sna->kgem.has_wc_mmap));
352.31656 + 
352.31657 +-	if (src->pitch != dst->pitch)
352.31658 ++	if (src->tiling != dst->tiling)
352.31659 + 		return false;
352.31660 + 
352.31661 + 	if (!kgem_bo_can_map__cpu(&sna->kgem, src, false))
352.31662 + 		return false;
352.31663 + 
352.31664 +-	if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true))
352.31665 ++	if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true) &&
352.31666 ++	    !sna->kgem.has_wc_mmap)
352.31667 + 		return false;
352.31668 + 
352.31669 + 	DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle));
352.31670 +@@ -2330,31 +2320,62 @@ memcpy_copy_boxes(struct sna *sna, uint8_t op,
352.31671 + 		  const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy,
352.31672 + 		  const BoxRec *box, int n, unsigned flags)
352.31673 + {
352.31674 ++	memcpy_box_func detile = NULL;
352.31675 + 	void *dst, *src;
352.31676 +-	bool clipped;
352.31677 + 
352.31678 + 	if (op != GXcopy)
352.31679 + 		return false;
352.31680 + 
352.31681 +-	clipped = (n > 1 ||
352.31682 +-		   box->x1 + dx > 0 ||
352.31683 +-		   box->y1 + dy > 0 ||
352.31684 +-		   box->x2 + dx < dst_draw->width ||
352.31685 +-		   box->y2 + dy < dst_draw->height);
352.31686 ++	if (src_draw->depth != dst_draw->depth)
352.31687 ++		return false;
352.31688 + 
352.31689 + 	dst = src = NULL;
352.31690 +-	if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) {
352.31691 +-		dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
352.31692 ++	if (can_copy_cpu(sna, src_bo, dst_bo)) {
352.31693 ++		if (src_bo->pitch != dst_bo->pitch ||
352.31694 ++		    dx != sx || dy != sy || n > 1 ||
352.31695 ++		    box->x1 + dx > 0 ||
352.31696 ++		    box->y1 + dy > 0 ||
352.31697 ++		    box->x2 + dx < dst_draw->width ||
352.31698 ++		    box->y2 + dy < dst_draw->height) {
352.31699 ++			if (dx != sx) /* not implemented in memcpy yet */
352.31700 ++				goto use_gtt;
352.31701 ++
352.31702 ++			switch (dst_bo->tiling) {
352.31703 ++			default:
352.31704 ++			case I915_TILING_Y:
352.31705 ++				goto use_gtt;
352.31706 ++
352.31707 ++			case I915_TILING_X:
352.31708 ++				detile = sna->kgem.memcpy_between_tiled_x;
352.31709 ++				if (detile == NULL)
352.31710 ++					goto use_gtt;
352.31711 ++				break;
352.31712 ++
352.31713 ++			case I915_TILING_NONE:
352.31714 ++				break;
352.31715 ++			}
352.31716 ++		}
352.31717 ++
352.31718 ++		if (kgem_bo_can_map__cpu(&sna->kgem, dst_bo, true))
352.31719 ++			dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
352.31720 ++		else
352.31721 ++			dst = kgem_bo_map__wc(&sna->kgem, dst_bo);
352.31722 + 		src = kgem_bo_map__cpu(&sna->kgem, src_bo);
352.31723 + 	}
352.31724 + 
352.31725 + 	if (dst == NULL || src == NULL) {
352.31726 ++use_gtt:
352.31727 + 		dst = kgem_bo_map__gtt(&sna->kgem, dst_bo);
352.31728 + 		src = kgem_bo_map__gtt(&sna->kgem, src_bo);
352.31729 + 		if (dst == NULL || src == NULL)
352.31730 + 			return false;
352.31731 ++
352.31732 ++		detile = NULL;
352.31733 + 	} else {
352.31734 +-		kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
352.31735 ++		if (dst == dst_bo->map__wc)
352.31736 ++			kgem_bo_sync__gtt(&sna->kgem, dst_bo);
352.31737 ++		else
352.31738 ++			kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
352.31739 + 		kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false);
352.31740 + 	}
352.31741 + 
352.31742 +@@ -2362,7 +2383,16 @@ memcpy_copy_boxes(struct sna *sna, uint8_t op,
352.31743 + 	     __FUNCTION__, sx, sy, dx, dy, n));
352.31744 + 
352.31745 + 	if (sigtrap_get() == 0) {
352.31746 +-		do {
352.31747 ++		if (detile) {
352.31748 ++			do {
352.31749 ++				detile(src, dst, dst_draw->bitsPerPixel,
352.31750 ++				       src_bo->pitch, dst_bo->pitch,
352.31751 ++				       box->x1 + sx, box->y1 + sy,
352.31752 ++				       box->x1 + dx, box->y1 + dy,
352.31753 ++				       box->x2 - box->x1, box->y2 - box->y1);
352.31754 ++				box++;
352.31755 ++			} while (--n);
352.31756 ++		} else do {
352.31757 + 			memcpy_blt(src, dst, dst_draw->bitsPerPixel,
352.31758 + 				   src_bo->pitch, dst_bo->pitch,
352.31759 + 				   box->x1 + sx, box->y1 + sy,
352.31760 +@@ -2380,4 +2410,5 @@ void
352.31761 + sna_render_mark_wedged(struct sna *sna)
352.31762 + {
352.31763 + 	sna->render.copy_boxes = memcpy_copy_boxes;
352.31764 ++	sna->render.prefer_gpu = 0;
352.31765 + }
352.31766 +diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
352.31767 +index 6e1fa480..4ba345a7 100644
352.31768 +--- a/src/sna/sna_render.h
352.31769 ++++ b/src/sna/sna_render.h
352.31770 +@@ -148,6 +148,10 @@ struct sna_composite_op {
352.31771 + 		struct {
352.31772 + 			uint32_t flags;
352.31773 + 		} gen8;
352.31774 ++
352.31775 ++		struct {
352.31776 ++			uint32_t flags;
352.31777 ++		} gen9;
352.31778 + 	} u;
352.31779 + 
352.31780 + 	void *priv;
352.31781 +@@ -238,8 +242,9 @@ struct sna_render {
352.31782 + 			  int16_t w, int16_t h,
352.31783 + 			  unsigned flags,
352.31784 + 			  struct sna_composite_op *tmp);
352.31785 +-#define COMPOSITE_PARTIAL 0x1
352.31786 +-#define COMPOSITE_FALLBACK 0x80000000
352.31787 ++#define COMPOSITE_PARTIAL	0x1
352.31788 ++#define COMPOSITE_UPLOAD	0x40000000
352.31789 ++#define COMPOSITE_FALLBACK	0x80000000
352.31790 + 
352.31791 + 	bool (*check_composite_spans)(struct sna *sna, uint8_t op,
352.31792 + 				      PicturePtr dst, PicturePtr src,
352.31793 +@@ -286,6 +291,8 @@ struct sna_render {
352.31794 + #define COPY_LAST 0x1
352.31795 + #define COPY_SYNC 0x2
352.31796 + #define COPY_NO_OVERLAP 0x4
352.31797 ++#define COPY_SMALL 0x8
352.31798 ++#define COPY_DRI 0x10
352.31799 + 
352.31800 + 	bool (*copy)(struct sna *sna, uint8_t alu,
352.31801 + 		     PixmapPtr src, struct kgem_bo *src_bo,
352.31802 +@@ -481,6 +488,7 @@ enum {
352.31803 + 
352.31804 + 	GEN7_WM_KERNEL_VIDEO_PLANAR,
352.31805 + 	GEN7_WM_KERNEL_VIDEO_PACKED,
352.31806 ++	GEN7_WM_KERNEL_VIDEO_RGB,
352.31807 + 	GEN7_WM_KERNEL_COUNT
352.31808 + };
352.31809 + 
352.31810 +@@ -533,12 +541,13 @@ enum {
352.31811 + 
352.31812 + 	GEN8_WM_KERNEL_VIDEO_PLANAR,
352.31813 + 	GEN8_WM_KERNEL_VIDEO_PACKED,
352.31814 ++	GEN8_WM_KERNEL_VIDEO_RGB,
352.31815 + 	GEN8_WM_KERNEL_COUNT
352.31816 + };
352.31817 + 
352.31818 + struct gen8_render_state {
352.31819 + 	unsigned gt;
352.31820 +-
352.31821 ++	const struct gt_info *info;
352.31822 + 	struct kgem_bo *general_bo;
352.31823 + 
352.31824 + 	uint32_t vs_state;
352.31825 +@@ -565,6 +574,58 @@ struct gen8_render_state {
352.31826 + 	bool emit_flush;
352.31827 + };
352.31828 + 
352.31829 ++enum {
352.31830 ++	GEN9_WM_KERNEL_NOMASK = 0,
352.31831 ++	GEN9_WM_KERNEL_NOMASK_P,
352.31832 ++
352.31833 ++	GEN9_WM_KERNEL_MASK,
352.31834 ++	GEN9_WM_KERNEL_MASK_P,
352.31835 ++
352.31836 ++	GEN9_WM_KERNEL_MASKCA,
352.31837 ++	GEN9_WM_KERNEL_MASKCA_P,
352.31838 ++
352.31839 ++	GEN9_WM_KERNEL_MASKSA,
352.31840 ++	GEN9_WM_KERNEL_MASKSA_P,
352.31841 ++
352.31842 ++	GEN9_WM_KERNEL_OPACITY,
352.31843 ++	GEN9_WM_KERNEL_OPACITY_P,
352.31844 ++
352.31845 ++	GEN9_WM_KERNEL_VIDEO_PLANAR,
352.31846 ++	GEN9_WM_KERNEL_VIDEO_PACKED,
352.31847 ++	GEN9_WM_KERNEL_VIDEO_RGB,
352.31848 ++	GEN9_WM_KERNEL_COUNT
352.31849 ++};
352.31850 ++
352.31851 ++struct gen9_render_state {
352.31852 ++	unsigned gt;
352.31853 ++	const struct gt_info *info;
352.31854 ++	struct kgem_bo *general_bo;
352.31855 ++
352.31856 ++	uint32_t vs_state;
352.31857 ++	uint32_t sf_state;
352.31858 ++	uint32_t sf_mask_state;
352.31859 ++	uint32_t wm_state;
352.31860 ++	uint32_t wm_kernel[GEN9_WM_KERNEL_COUNT][3];
352.31861 ++
352.31862 ++	uint32_t cc_blend;
352.31863 ++
352.31864 ++	uint32_t drawrect_offset;
352.31865 ++	uint32_t drawrect_limit;
352.31866 ++	uint32_t blend;
352.31867 ++	uint32_t samplers;
352.31868 ++	uint32_t kernel;
352.31869 ++
352.31870 ++	uint16_t num_sf_outputs;
352.31871 ++	uint16_t ve_id;
352.31872 ++	uint16_t last_primitive;
352.31873 ++	int16_t floats_per_vertex;
352.31874 ++	uint16_t surface_table;
352.31875 ++
352.31876 ++	bool needs_invariant;
352.31877 ++	bool emit_flush;
352.31878 ++	bool ve_dirty;
352.31879 ++};
352.31880 ++
352.31881 + struct sna_static_stream {
352.31882 + 	uint32_t size, used;
352.31883 + 	uint8_t *data;
352.31884 +@@ -620,6 +681,7 @@ const char *gen5_render_init(struct sna *sna, const char *backend);
352.31885 + const char *gen6_render_init(struct sna *sna, const char *backend);
352.31886 + const char *gen7_render_init(struct sna *sna, const char *backend);
352.31887 + const char *gen8_render_init(struct sna *sna, const char *backend);
352.31888 ++const char *gen9_render_init(struct sna *sna, const char *backend);
352.31889 + 
352.31890 + void sna_render_mark_wedged(struct sna *sna);
352.31891 + 
352.31892 +diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
352.31893 +index 10fbbfe2..e162e37f 100644
352.31894 +--- a/src/sna/sna_render_inline.h
352.31895 ++++ b/src/sna/sna_render_inline.h
352.31896 +@@ -304,6 +304,12 @@ color_convert(uint32_t pixel,
352.31897 + 	return pixel;
352.31898 + }
352.31899 + 
352.31900 ++inline static uint32_t
352.31901 ++solid_color(uint32_t format, uint32_t pixel)
352.31902 ++{
352.31903 ++	return color_convert(pixel, format, PICT_a8r8g8b8);
352.31904 ++}
352.31905 ++
352.31906 + inline static bool dst_use_gpu(PixmapPtr pixmap)
352.31907 + {
352.31908 + 	struct sna_pixmap *priv = sna_pixmap(pixmap);
352.31909 +diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c
352.31910 +index 308efc0a..8e2627f7 100644
352.31911 +--- a/src/sna/sna_tiling.c
352.31912 ++++ b/src/sna/sna_tiling.c
352.31913 +@@ -369,8 +369,7 @@ sna_tiling_composite_spans_boxes(struct sna *sna,
352.31914 + 				 const BoxRec *box, int nbox, float opacity)
352.31915 + {
352.31916 + 	while (nbox--)
352.31917 +-		sna_tiling_composite_spans_box(sna, op->base.priv, box++, opacity);
352.31918 +-	(void)sna;
352.31919 ++		sna_tiling_composite_spans_box(sna, op, box++, opacity);
352.31920 + }
352.31921 + 
352.31922 + fastcall static void
352.31923 +@@ -581,6 +580,7 @@ sna_tiling_composite_spans(uint32_t op,
352.31924 + 	tile->rects = tile->rects_embedded;
352.31925 + 	tile->rect_count = 0;
352.31926 + 	tile->rect_size = ARRAY_SIZE(tile->rects_embedded);
352.31927 ++	COMPILE_TIME_ASSERT(sizeof(tile->rects_embedded[0]) >= sizeof(struct sna_tile_span));
352.31928 + 
352.31929 + 	tmp->box   = sna_tiling_composite_spans_box;
352.31930 + 	tmp->boxes = sna_tiling_composite_spans_boxes;
352.31931 +diff --git a/src/sna/sna_trapezoids_boxes.c b/src/sna/sna_trapezoids_boxes.c
352.31932 +index 9900e3f0..bbf83759 100644
352.31933 +--- a/src/sna/sna_trapezoids_boxes.c
352.31934 ++++ b/src/sna/sna_trapezoids_boxes.c
352.31935 +@@ -198,7 +198,7 @@ composite_aligned_boxes(struct sna *sna,
352.31936 + 	if (op == PictOpClear && sna->clear)
352.31937 + 		src = sna->clear;
352.31938 + 
352.31939 +-	DBG(("%s: clipped extents (%d, %d), (%d, %d);  now offset by (%d, %d), orgin (%d, %d)\n",
352.31940 ++	DBG(("%s: clipped extents (%d, %d), (%d, %d);  now offset by (%d, %d), origin (%d, %d)\n",
352.31941 + 	     __FUNCTION__,
352.31942 + 	     clip.extents.x1, clip.extents.y1,
352.31943 + 	     clip.extents.x2, clip.extents.y2,
352.31944 +@@ -592,6 +592,8 @@ lerp32_opacity(PixmapPtr scratch,
352.31945 + 	uint32_t *ptr;
352.31946 + 	int stride, i;
352.31947 + 
352.31948 ++	sigtrap_assert_active();
352.31949 ++
352.31950 + 	ptr = (uint32_t*)((uint8_t *)scratch->devPrivate.ptr + scratch->devKind * y);
352.31951 + 	ptr += x;
352.31952 + 	stride = scratch->devKind / 4;
352.31953 +diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
352.31954 +index 37def2f9..8bc7c8a8 100644
352.31955 +--- a/src/sna/sna_trapezoids_imprecise.c
352.31956 ++++ b/src/sna/sna_trapezoids_imprecise.c
352.31957 +@@ -962,6 +962,16 @@ tor_add_trapezoid(struct tor *tor,
352.31958 + 		  const xTrapezoid *t,
352.31959 + 		  int dx, int dy)
352.31960 + {
352.31961 ++	if (!xTrapezoidValid(t)) {
352.31962 ++		__DBG(("%s: skipping invalid trapezoid: top=%d, bottom=%d, left=(%d, %d), (%d, %d), right=(%d, %d), (%d, %d)\n",
352.31963 ++		       __FUNCTION__,
352.31964 ++		       t->top, t->bottom,
352.31965 ++		       t->left.p1.x, t->left.p1.y,
352.31966 ++		       t->left.p2.x, t->left.p2.y,
352.31967 ++		       t->right.p1.x, t->right.p1.y,
352.31968 ++		       t->right.p2.x, t->right.p2.y));
352.31969 ++		return;
352.31970 ++	}
352.31971 + 	polygon_add_edge(tor->polygon, t, &t->left, 1, dx, dy);
352.31972 + 	polygon_add_edge(tor->polygon, t, &t->right, -1, dx, dy);
352.31973 + }
352.31974 +@@ -1687,31 +1697,27 @@ struct span_thread {
352.31975 + #define SPAN_THREAD_MAX_BOXES (8192/sizeof(struct sna_opacity_box))
352.31976 + struct span_thread_boxes {
352.31977 + 	const struct sna_composite_spans_op *op;
352.31978 ++	const BoxRec *clip_start, *clip_end;
352.31979 + 	int num_boxes;
352.31980 + 	struct sna_opacity_box boxes[SPAN_THREAD_MAX_BOXES];
352.31981 + };
352.31982 + 
352.31983 +-static void span_thread_add_boxes(struct sna *sna, void *data,
352.31984 +-				  const BoxRec *box, int count, float alpha)
352.31985 ++static void span_thread_add_box(struct sna *sna, void *data,
352.31986 ++				const BoxRec *box, float alpha)
352.31987 + {
352.31988 + 	struct span_thread_boxes *b = data;
352.31989 + 
352.31990 +-	__DBG(("%s: adding %d boxes with alpha=%f\n",
352.31991 +-	       __FUNCTION__, count, alpha));
352.31992 ++	__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
352.31993 + 
352.31994 +-	assert(count > 0 && count <= SPAN_THREAD_MAX_BOXES);
352.31995 +-	if (unlikely(b->num_boxes + count > SPAN_THREAD_MAX_BOXES)) {
352.31996 +-		DBG(("%s: flushing %d boxes, adding %d\n", __FUNCTION__, b->num_boxes, count));
352.31997 +-		assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
352.31998 ++	if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
352.31999 ++		DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
352.32000 + 		b->op->thread_boxes(sna, b->op, b->boxes, b->num_boxes);
352.32001 + 		b->num_boxes = 0;
352.32002 + 	}
352.32003 + 
352.32004 +-	do {
352.32005 +-		b->boxes[b->num_boxes].box = *box++;
352.32006 +-		b->boxes[b->num_boxes].alpha = alpha;
352.32007 +-		b->num_boxes++;
352.32008 +-	} while (--count);
352.32009 ++	b->boxes[b->num_boxes].box = *box++;
352.32010 ++	b->boxes[b->num_boxes].alpha = alpha;
352.32011 ++	b->num_boxes++;
352.32012 + 	assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
352.32013 + }
352.32014 + 
352.32015 +@@ -1722,8 +1728,22 @@ span_thread_box(struct sna *sna,
352.32016 + 		const BoxRec *box,
352.32017 + 		int coverage)
352.32018 + {
352.32019 ++	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
352.32020 ++
352.32021 + 	__DBG(("%s: %d -> %d @ %d\n", __FUNCTION__, box->x1, box->x2, coverage));
352.32022 +-	span_thread_add_boxes(sna, op, box, 1, AREA_TO_ALPHA(coverage));
352.32023 ++	if (b->num_boxes) {
352.32024 ++		struct sna_opacity_box *bb = &b->boxes[b->num_boxes-1];
352.32025 ++		if (bb->box.x1 == box->x1 &&
352.32026 ++		    bb->box.x2 == box->x2 &&
352.32027 ++		    bb->box.y2 == box->y1 &&
352.32028 ++		    bb->alpha == AREA_TO_ALPHA(coverage)) {
352.32029 ++			bb->box.y2 = box->y2;
352.32030 ++			__DBG(("%s: contracted double row: %d -> %d\n", __func__, bb->box.y1, bb->box.y2));
352.32031 ++			return;
352.32032 ++		}
352.32033 ++	}
352.32034 ++
352.32035 ++	span_thread_add_box(sna, op, box, AREA_TO_ALPHA(coverage));
352.32036 + }
352.32037 + 
352.32038 + static void
352.32039 +@@ -1733,20 +1753,28 @@ span_thread_clipped_box(struct sna *sna,
352.32040 + 			const BoxRec *box,
352.32041 + 			int coverage)
352.32042 + {
352.32043 +-	pixman_region16_t region;
352.32044 ++	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
352.32045 ++	const BoxRec *c;
352.32046 + 
352.32047 + 	__DBG(("%s: %d -> %d @ %f\n", __FUNCTION__, box->x1, box->x2,
352.32048 + 	       AREA_TO_ALPHA(coverage)));
352.32049 + 
352.32050 +-	pixman_region_init_rects(&region, box, 1);
352.32051 +-	RegionIntersect(&region, &region, clip);
352.32052 +-	if (region_num_rects(&region)) {
352.32053 +-		span_thread_add_boxes(sna, op,
352.32054 +-				      region_rects(&region),
352.32055 +-				      region_num_rects(&region),
352.32056 +-				      AREA_TO_ALPHA(coverage));
352.32057 ++	b->clip_start =
352.32058 ++		find_clip_box_for_y(b->clip_start, b->clip_end, box->y1);
352.32059 ++
352.32060 ++	c = b->clip_start;
352.32061 ++	while (c != b->clip_end) {
352.32062 ++		BoxRec clipped;
352.32063 ++
352.32064 ++		if (box->y2 <= c->y1)
352.32065 ++			break;
352.32066 ++
352.32067 ++		clipped = *box;
352.32068 ++		if (!box_intersect(&clipped, c++))
352.32069 ++			continue;
352.32070 ++
352.32071 ++		span_thread_add_box(sna, op, &clipped, AREA_TO_ALPHA(coverage));
352.32072 + 	}
352.32073 +-	pixman_region_fini(&region);
352.32074 + }
352.32075 + 
352.32076 + static span_func_t
352.32077 +@@ -1777,6 +1805,16 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
352.32078 + 	return span;
352.32079 + }
352.32080 + 
352.32081 ++inline static void
352.32082 ++span_thread_boxes_init(struct span_thread_boxes *boxes,
352.32083 ++		       const struct sna_composite_spans_op *op,
352.32084 ++		       const RegionRec *clip)
352.32085 ++{
352.32086 ++	boxes->op = op;
352.32087 ++	region_get_boxes(clip, &boxes->clip_start, &boxes->clip_end);
352.32088 ++	boxes->num_boxes = 0;
352.32089 ++}
352.32090 ++
352.32091 + static void
352.32092 + span_thread(void *arg)
352.32093 + {
352.32094 +@@ -1789,8 +1827,7 @@ span_thread(void *arg)
352.32095 + 	if (!tor_init(&tor, &thread->extents, 2*thread->ntrap))
352.32096 + 		return;
352.32097 + 
352.32098 +-	boxes.op = thread->op;
352.32099 +-	boxes.num_boxes = 0;
352.32100 ++	span_thread_boxes_init(&boxes, thread->op, thread->clip);
352.32101 + 
352.32102 + 	y1 = thread->extents.y1 - thread->draw_y;
352.32103 + 	y2 = thread->extents.y2 - thread->draw_y;
352.32104 +@@ -2190,6 +2227,52 @@ static void _tor_blt_src(struct inplace *in, const BoxRec *box, uint8_t v)
352.32105 + 	} while (--h);
352.32106 + }
352.32107 + 
352.32108 ++struct clipped_span {
352.32109 ++	span_func_t span;
352.32110 ++	const BoxRec *clip_start, *clip_end;
352.32111 ++};
352.32112 ++
352.32113 ++static void
352.32114 ++tor_blt_clipped(struct sna *sna,
352.32115 ++		struct sna_composite_spans_op *op,
352.32116 ++		pixman_region16_t *clip,
352.32117 ++		const BoxRec *box,
352.32118 ++		int coverage)
352.32119 ++{
352.32120 ++	struct clipped_span *cs = (struct clipped_span *)clip;
352.32121 ++	const BoxRec *c;
352.32122 ++
352.32123 ++	cs->clip_start =
352.32124 ++		find_clip_box_for_y(cs->clip_start, cs->clip_end, box->y1);
352.32125 ++
352.32126 ++	c = cs->clip_start;
352.32127 ++	while (c != cs->clip_end) {
352.32128 ++		BoxRec clipped;
352.32129 ++
352.32130 ++		if (box->y2 <= c->y1)
352.32131 ++			break;
352.32132 ++
352.32133 ++		clipped = *box;
352.32134 ++		if (!box_intersect(&clipped, c++))
352.32135 ++			continue;
352.32136 ++
352.32137 ++		cs->span(sna, op, NULL, &clipped, coverage);
352.32138 ++	}
352.32139 ++}
352.32140 ++
352.32141 ++inline static span_func_t
352.32142 ++clipped_span(struct clipped_span *cs,
352.32143 ++	     span_func_t span,
352.32144 ++	     const RegionRec *clip)
352.32145 ++{
352.32146 ++	if (clip->data) {
352.32147 ++		cs->span = span;
352.32148 ++		region_get_boxes(clip, &cs->clip_start, &cs->clip_end);
352.32149 ++		span = tor_blt_clipped;
352.32150 ++	}
352.32151 ++	return span;
352.32152 ++}
352.32153 ++
352.32154 + static void
352.32155 + tor_blt_src(struct sna *sna,
352.32156 + 	    struct sna_composite_spans_op *op,
352.32157 +@@ -2203,25 +2286,6 @@ tor_blt_src(struct sna *sna,
352.32158 + }
352.32159 + 
352.32160 + static void
352.32161 +-tor_blt_src_clipped(struct sna *sna,
352.32162 +-		    struct sna_composite_spans_op *op,
352.32163 +-		    pixman_region16_t *clip,
352.32164 +-		    const BoxRec *box,
352.32165 +-		    int coverage)
352.32166 +-{
352.32167 +-	pixman_region16_t region;
352.32168 +-	int n;
352.32169 +-
352.32170 +-	pixman_region_init_rects(&region, box, 1);
352.32171 +-	RegionIntersect(&region, &region, clip);
352.32172 +-	n = region_num_rects(&region);
352.32173 +-	box = region_rects(&region);
352.32174 +-	while (n--)
352.32175 +-		tor_blt_src(sna, op, NULL, box++, coverage);
352.32176 +-	pixman_region_fini(&region);
352.32177 +-}
352.32178 +-
352.32179 +-static void
352.32180 + tor_blt_in(struct sna *sna,
352.32181 + 	   struct sna_composite_spans_op *op,
352.32182 + 	   pixman_region16_t *clip,
352.32183 +@@ -2253,25 +2317,6 @@ tor_blt_in(struct sna *sna,
352.32184 + }
352.32185 + 
352.32186 + static void
352.32187 +-tor_blt_in_clipped(struct sna *sna,
352.32188 +-		   struct sna_composite_spans_op *op,
352.32189 +-		   pixman_region16_t *clip,
352.32190 +-		   const BoxRec *box,
352.32191 +-		   int coverage)
352.32192 +-{
352.32193 +-	pixman_region16_t region;
352.32194 +-	int n;
352.32195 +-
352.32196 +-	pixman_region_init_rects(&region, box, 1);
352.32197 +-	RegionIntersect(&region, &region, clip);
352.32198 +-	n = region_num_rects(&region);
352.32199 +-	box = region_rects(&region);
352.32200 +-	while (n--)
352.32201 +-		tor_blt_in(sna, op, NULL, box++, coverage);
352.32202 +-	pixman_region_fini(&region);
352.32203 +-}
352.32204 +-
352.32205 +-static void
352.32206 + tor_blt_add(struct sna *sna,
352.32207 + 	    struct sna_composite_spans_op *op,
352.32208 + 	    pixman_region16_t *clip,
352.32209 +@@ -2310,25 +2355,6 @@ tor_blt_add(struct sna *sna,
352.32210 + }
352.32211 + 
352.32212 + static void
352.32213 +-tor_blt_add_clipped(struct sna *sna,
352.32214 +-		    struct sna_composite_spans_op *op,
352.32215 +-		    pixman_region16_t *clip,
352.32216 +-		    const BoxRec *box,
352.32217 +-		    int coverage)
352.32218 +-{
352.32219 +-	pixman_region16_t region;
352.32220 +-	int n;
352.32221 +-
352.32222 +-	pixman_region_init_rects(&region, box, 1);
352.32223 +-	RegionIntersect(&region, &region, clip);
352.32224 +-	n = region_num_rects(&region);
352.32225 +-	box = region_rects(&region);
352.32226 +-	while (n--)
352.32227 +-		tor_blt_add(sna, op, NULL, box++, coverage);
352.32228 +-	pixman_region_fini(&region);
352.32229 +-}
352.32230 +-
352.32231 +-static void
352.32232 + tor_blt_lerp32(struct sna *sna,
352.32233 + 	       struct sna_composite_spans_op *op,
352.32234 + 	       pixman_region16_t *clip,
352.32235 +@@ -2343,6 +2369,7 @@ tor_blt_lerp32(struct sna *sna,
352.32236 + 	if (coverage == 0)
352.32237 + 		return;
352.32238 + 
352.32239 ++	sigtrap_assert_active();
352.32240 + 	ptr += box->y1 * stride + box->x1;
352.32241 + 
352.32242 + 	h = box->y2 - box->y1;
352.32243 +@@ -2383,25 +2410,6 @@ tor_blt_lerp32(struct sna *sna,
352.32244 + 	}
352.32245 + }
352.32246 + 
352.32247 +-static void
352.32248 +-tor_blt_lerp32_clipped(struct sna *sna,
352.32249 +-		       struct sna_composite_spans_op *op,
352.32250 +-		       pixman_region16_t *clip,
352.32251 +-		       const BoxRec *box,
352.32252 +-		       int coverage)
352.32253 +-{
352.32254 +-	pixman_region16_t region;
352.32255 +-	int n;
352.32256 +-
352.32257 +-	pixman_region_init_rects(&region, box, 1);
352.32258 +-	RegionIntersect(&region, &region, clip);
352.32259 +-	n = region_num_rects(&region);
352.32260 +-	box = region_rects(&region);
352.32261 +-	while (n--)
352.32262 +-		tor_blt_lerp32(sna, op, NULL, box++, coverage);
352.32263 +-	pixman_region_fini(&region);
352.32264 +-}
352.32265 +-
352.32266 + struct pixman_inplace {
352.32267 + 	pixman_image_t *image, *source, *mask;
352.32268 + 	uint32_t color;
352.32269 +@@ -2431,24 +2439,6 @@ pixmask_span_solid(struct sna *sna,
352.32270 + 			       pi->dx + box->x1, pi->dy + box->y1,
352.32271 + 			       box->x2 - box->x1, box->y2 - box->y1);
352.32272 + }
352.32273 +-static void
352.32274 +-pixmask_span_solid__clipped(struct sna *sna,
352.32275 +-			    struct sna_composite_spans_op *op,
352.32276 +-			    pixman_region16_t *clip,
352.32277 +-			    const BoxRec *box,
352.32278 +-			    int coverage)
352.32279 +-{
352.32280 +-	pixman_region16_t region;
352.32281 +-	int n;
352.32282 +-
352.32283 +-	pixman_region_init_rects(&region, box, 1);
352.32284 +-	RegionIntersect(&region, &region, clip);
352.32285 +-	n = region_num_rects(&region);
352.32286 +-	box = region_rects(&region);
352.32287 +-	while (n--)
352.32288 +-		pixmask_span_solid(sna, op, NULL, box++, coverage);
352.32289 +-	pixman_region_fini(&region);
352.32290 +-}
352.32291 + 
352.32292 + static void
352.32293 + pixmask_span(struct sna *sna,
352.32294 +@@ -2471,24 +2461,6 @@ pixmask_span(struct sna *sna,
352.32295 + 			       pi->dx + box->x1, pi->dy + box->y1,
352.32296 + 			       box->x2 - box->x1, box->y2 - box->y1);
352.32297 + }
352.32298 +-static void
352.32299 +-pixmask_span__clipped(struct sna *sna,
352.32300 +-		      struct sna_composite_spans_op *op,
352.32301 +-		      pixman_region16_t *clip,
352.32302 +-		      const BoxRec *box,
352.32303 +-		      int coverage)
352.32304 +-{
352.32305 +-	pixman_region16_t region;
352.32306 +-	int n;
352.32307 +-
352.32308 +-	pixman_region_init_rects(&region, box, 1);
352.32309 +-	RegionIntersect(&region, &region, clip);
352.32310 +-	n = region_num_rects(&region);
352.32311 +-	box = region_rects(&region);
352.32312 +-	while (n--)
352.32313 +-		pixmask_span(sna, op, NULL, box++, coverage);
352.32314 +-	pixman_region_fini(&region);
352.32315 +-}
352.32316 + 
352.32317 + struct inplace_x8r8g8b8_thread {
352.32318 + 	xTrapezoid *traps;
352.32319 +@@ -2507,6 +2479,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.32320 + 	struct inplace_x8r8g8b8_thread *thread = arg;
352.32321 + 	struct tor tor;
352.32322 + 	span_func_t span;
352.32323 ++	struct clipped_span clipped;
352.32324 + 	RegionPtr clip;
352.32325 + 	int y1, y2, n;
352.32326 + 
352.32327 +@@ -2537,12 +2510,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.32328 + 		inplace.stride = pixmap->devKind;
352.32329 + 		inplace.color = thread->color;
352.32330 + 
352.32331 +-		if (clip->data)
352.32332 +-			span = tor_blt_lerp32_clipped;
352.32333 +-		else
352.32334 +-			span = tor_blt_lerp32;
352.32335 ++		span = clipped_span(&clipped, tor_blt_lerp32, clip);
352.32336 + 
352.32337 +-		tor_render(NULL, &tor, (void*)&inplace, clip, span, false);
352.32338 ++		tor_render(NULL, &tor,
352.32339 ++			   (void*)&inplace, (void*)&clipped,
352.32340 ++			   span, false);
352.32341 + 	} else if (thread->is_solid) {
352.32342 + 		struct pixman_inplace pi;
352.32343 + 
352.32344 +@@ -2555,12 +2527,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.32345 + 						     1, 1, pi.bits, 0);
352.32346 + 		pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
352.32347 + 
352.32348 +-		if (clip->data)
352.32349 +-			span = pixmask_span_solid__clipped;
352.32350 +-		else
352.32351 +-			span = pixmask_span_solid;
352.32352 ++		span = clipped_span(&clipped, pixmask_span_solid, clip);
352.32353 + 
352.32354 +-		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
352.32355 ++		tor_render(NULL, &tor,
352.32356 ++			   (void*)&pi, (void *)&clipped,
352.32357 ++			   span, false);
352.32358 + 
352.32359 + 		pixman_image_unref(pi.source);
352.32360 + 		pixman_image_unref(pi.image);
352.32361 +@@ -2579,12 +2550,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.32362 + 		pi.bits = pixman_image_get_data(pi.mask);
352.32363 + 		pi.op = thread->op;
352.32364 + 
352.32365 +-		if (clip->data)
352.32366 +-			span = pixmask_span__clipped;
352.32367 +-		else
352.32368 +-			span = pixmask_span;
352.32369 ++		span = clipped_span(&clipped, pixmask_span, clip);
352.32370 + 
352.32371 +-		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
352.32372 ++		tor_render(NULL, &tor,
352.32373 ++			   (void*)&pi, (void *)&clipped,
352.32374 ++			   span, false);
352.32375 + 
352.32376 + 		pixman_image_unref(pi.mask);
352.32377 + 		pixman_image_unref(pi.source);
352.32378 +@@ -2698,6 +2668,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.32379 + 	if (num_threads == 1) {
352.32380 + 		struct tor tor;
352.32381 + 		span_func_t span;
352.32382 ++		struct clipped_span clipped;
352.32383 + 
352.32384 + 		if (!tor_init(&tor, &region.extents, 2*ntrap))
352.32385 + 			return true;
352.32386 +@@ -2723,17 +2694,15 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.32387 + 			inplace.stride = pixmap->devKind;
352.32388 + 			inplace.color = color;
352.32389 + 
352.32390 +-			if (dst->pCompositeClip->data)
352.32391 +-				span = tor_blt_lerp32_clipped;
352.32392 +-			else
352.32393 +-				span = tor_blt_lerp32;
352.32394 ++			span = clipped_span(&clipped, tor_blt_lerp32, dst->pCompositeClip);
352.32395 + 
352.32396 + 			DBG(("%s: render inplace op=%d, color=%08x\n",
352.32397 + 			     __FUNCTION__, op, color));
352.32398 + 
352.32399 + 			if (sigtrap_get() == 0) {
352.32400 +-				tor_render(NULL, &tor, (void*)&inplace,
352.32401 +-					   dst->pCompositeClip, span, false);
352.32402 ++				tor_render(NULL, &tor,
352.32403 ++					   (void*)&inplace, (void*)&clipped,
352.32404 ++					   span, false);
352.32405 + 				sigtrap_put();
352.32406 + 			}
352.32407 + 		} else if (is_solid) {
352.32408 +@@ -2748,15 +2717,12 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.32409 + 							     1, 1, pi.bits, 0);
352.32410 + 			pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
352.32411 + 
352.32412 +-			if (dst->pCompositeClip->data)
352.32413 +-				span = pixmask_span_solid__clipped;
352.32414 +-			else
352.32415 +-				span = pixmask_span_solid;
352.32416 ++			span = clipped_span(&clipped, pixmask_span_solid, dst->pCompositeClip);
352.32417 + 
352.32418 + 			if (sigtrap_get() == 0) {
352.32419 +-				tor_render(NULL, &tor, (void*)&pi,
352.32420 +-					   dst->pCompositeClip, span,
352.32421 +-					   false);
352.32422 ++				tor_render(NULL, &tor,
352.32423 ++					   (void*)&pi, (void*)&clipped,
352.32424 ++					   span, false);
352.32425 + 				sigtrap_put();
352.32426 + 			}
352.32427 + 
352.32428 +@@ -2777,15 +2743,12 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.32429 + 			pi.bits = pixman_image_get_data(pi.mask);
352.32430 + 			pi.op = op;
352.32431 + 
352.32432 +-			if (dst->pCompositeClip->data)
352.32433 +-				span = pixmask_span__clipped;
352.32434 +-			else
352.32435 +-				span = pixmask_span;
352.32436 ++			span = clipped_span(&clipped, pixmask_span, dst->pCompositeClip);
352.32437 + 
352.32438 + 			if (sigtrap_get() == 0) {
352.32439 +-				tor_render(NULL, &tor, (void*)&pi,
352.32440 +-					   dst->pCompositeClip, span,
352.32441 +-					   false);
352.32442 ++				tor_render(NULL, &tor,
352.32443 ++					   (void*)&pi, (void*)&clipped,
352.32444 ++					   span, false);
352.32445 + 				sigtrap_put();
352.32446 + 			}
352.32447 + 
352.32448 +@@ -2847,9 +2810,9 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.32449 + 
352.32450 + struct inplace_thread {
352.32451 + 	xTrapezoid *traps;
352.32452 +-	RegionPtr clip;
352.32453 + 	span_func_t span;
352.32454 + 	struct inplace inplace;
352.32455 ++	struct clipped_span clipped;
352.32456 + 	BoxRec extents;
352.32457 + 	int dx, dy;
352.32458 + 	int draw_x, draw_y;
352.32459 +@@ -2874,8 +2837,9 @@ static void inplace_thread(void *arg)
352.32460 + 		tor_add_trapezoid(&tor, &thread->traps[n], thread->dx, thread->dy);
352.32461 + 	}
352.32462 + 
352.32463 +-	tor_render(NULL, &tor, (void*)&thread->inplace,
352.32464 +-		   thread->clip, thread->span, thread->unbounded);
352.32465 ++	tor_render(NULL, &tor,
352.32466 ++		   (void*)&thread->inplace, (void*)&thread->clipped,
352.32467 ++		   thread->span, thread->unbounded);
352.32468 + 
352.32469 + 	tor_fini(&tor);
352.32470 + }
352.32471 +@@ -2889,6 +2853,7 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
352.32472 + 				 bool fallback)
352.32473 + {
352.32474 + 	struct inplace inplace;
352.32475 ++	struct clipped_span clipped;
352.32476 + 	span_func_t span;
352.32477 + 	PixmapPtr pixmap;
352.32478 + 	struct sna_pixmap *priv;
352.32479 +@@ -3005,21 +2970,12 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
352.32480 + 	     region.extents.x2, region.extents.y2));
352.32481 + 
352.32482 + 	if (op == PictOpSrc) {
352.32483 +-		if (dst->pCompositeClip->data)
352.32484 +-			span = tor_blt_src_clipped;
352.32485 +-		else
352.32486 +-			span = tor_blt_src;
352.32487 ++		span = tor_blt_src;
352.32488 + 	} else if (op == PictOpIn) {
352.32489 +-		if (dst->pCompositeClip->data)
352.32490 +-			span = tor_blt_in_clipped;
352.32491 +-		else
352.32492 +-			span = tor_blt_in;
352.32493 ++		span = tor_blt_in;
352.32494 + 	} else {
352.32495 + 		assert(op == PictOpAdd);
352.32496 +-		if (dst->pCompositeClip->data)
352.32497 +-			span = tor_blt_add_clipped;
352.32498 +-		else
352.32499 +-			span = tor_blt_add;
352.32500 ++		span = tor_blt_add;
352.32501 + 	}
352.32502 + 
352.32503 + 	DBG(("%s: move-to-cpu\n", __FUNCTION__));
352.32504 +@@ -3037,6 +2993,8 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
352.32505 + 	inplace.stride = pixmap->devKind;
352.32506 + 	inplace.opacity = color >> 24;
352.32507 + 
352.32508 ++	span = clipped_span(&clipped, span, dst->pCompositeClip);
352.32509 ++
352.32510 + 	num_threads = 1;
352.32511 + 	if ((flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
352.32512 + 		num_threads = sna_use_threads(region.extents.x2 - region.extents.x1,
352.32513 +@@ -3057,8 +3015,9 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
352.32514 + 		}
352.32515 + 
352.32516 + 		if (sigtrap_get() == 0) {
352.32517 +-			tor_render(NULL, &tor, (void*)&inplace,
352.32518 +-				   dst->pCompositeClip, span, unbounded);
352.32519 ++			tor_render(NULL, &tor,
352.32520 ++				   (void*)&inplace, (void *)&clipped,
352.32521 ++				   span, unbounded);
352.32522 + 			sigtrap_put();
352.32523 + 		}
352.32524 + 
352.32525 +@@ -3075,8 +3034,8 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
352.32526 + 		threads[0].traps = traps;
352.32527 + 		threads[0].ntrap = ntrap;
352.32528 + 		threads[0].inplace = inplace;
352.32529 ++		threads[0].clipped = clipped;
352.32530 + 		threads[0].extents = region.extents;
352.32531 +-		threads[0].clip = dst->pCompositeClip;
352.32532 + 		threads[0].span = span;
352.32533 + 		threads[0].unbounded = unbounded;
352.32534 + 		threads[0].dx = dx;
352.32535 +@@ -3707,8 +3666,7 @@ tristrip_thread(void *arg)
352.32536 + 	if (!tor_init(&tor, &thread->extents, 2*thread->count))
352.32537 + 		return;
352.32538 + 
352.32539 +-	boxes.op = thread->op;
352.32540 +-	boxes.num_boxes = 0;
352.32541 ++	span_thread_boxes_init(&boxes, thread->op, thread->clip);
352.32542 + 
352.32543 + 	cw = 0; ccw = 1;
352.32544 + 	polygon_add_line(tor.polygon,
352.32545 +@@ -3874,7 +3832,7 @@ imprecise_tristrip_span_converter(struct sna *sna,
352.32546 + 				break;
352.32547 + 		} while (1);
352.32548 + 		polygon_add_line(tor.polygon,
352.32549 +-				 &points[cw], &points[2+ccw],
352.32550 ++				 &points[cw], &points[ccw],
352.32551 + 				 dx, dy);
352.32552 + 		assert(tor.polygon->num_edges <= 2*count);
352.32553 + 
352.32554 +diff --git a/src/sna/sna_trapezoids_mono.c b/src/sna/sna_trapezoids_mono.c
352.32555 +index 808703a9..07a7867d 100644
352.32556 +--- a/src/sna/sna_trapezoids_mono.c
352.32557 ++++ b/src/sna/sna_trapezoids_mono.c
352.32558 +@@ -72,13 +72,14 @@ struct mono {
352.32559 + 	struct sna *sna;
352.32560 + 	struct sna_composite_op op;
352.32561 + 	pixman_region16_t clip;
352.32562 ++	const BoxRec *clip_start, *clip_end;
352.32563 + 
352.32564 + 	fastcall void (*span)(struct mono *, int, int, BoxPtr);
352.32565 + 
352.32566 + 	struct mono_polygon polygon;
352.32567 + };
352.32568 + 
352.32569 +-#define I(x) pixman_fixed_to_int ((x) + pixman_fixed_1_minus_e/2)
352.32570 ++#define I(x) pixman_fixed_to_int((x) + pixman_fixed_1_minus_e/2)
352.32571 + 
352.32572 + static struct quorem
352.32573 + floored_muldivrem(int32_t x, int32_t a, int32_t b)
352.32574 +@@ -249,22 +250,22 @@ mono_add_line(struct mono *mono,
352.32575 + 
352.32576 + 		e->dxdy = floored_muldivrem(dx, pixman_fixed_1, dy);
352.32577 + 
352.32578 +-		e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1_minus_e/2 - p1->y,
352.32579 ++		e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1/2 - p1->y,
352.32580 + 					 dx, dy);
352.32581 + 		e->x.quo += p1->x;
352.32582 + 		e->x.rem -= dy;
352.32583 + 
352.32584 + 		e->dy = dy;
352.32585 +-
352.32586 +-		__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
352.32587 +-		       __FUNCTION__,
352.32588 +-		       I(e->x.quo), e->x.quo, e->x.rem, e->dy,
352.32589 +-		       e->dxdy.quo, e->dxdy.rem, e->dy));
352.32590 + 	}
352.32591 + 	e->x.quo += dst_x*pixman_fixed_1;
352.32592 ++	__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
352.32593 ++	       __FUNCTION__,
352.32594 ++	       I(e->x.quo), e->x.quo, e->x.rem, e->dy,
352.32595 ++	       e->dxdy.quo, e->dxdy.rem, e->dy));
352.32596 + 
352.32597 + 	{
352.32598 + 		struct mono_edge **ptail = &polygon->y_buckets[ytop - mono->clip.extents.y1];
352.32599 ++		assert(ytop - mono->clip.extents.y1 < mono->clip.extents.y2 - mono->clip.extents.y1);
352.32600 + 		if (*ptail)
352.32601 + 			(*ptail)->prev = e;
352.32602 + 		e->next = *ptail;
352.32603 +@@ -368,6 +369,10 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
352.32604 + 		    e->x.rem == n->x.rem &&
352.32605 + 		    e->dxdy.quo == n->dxdy.quo &&
352.32606 + 		    e->dxdy.rem == n->dxdy.rem) {
352.32607 ++			assert(e->dy == n->dy);
352.32608 ++			__DBG(("%s: discarding cancellation pair (%d.%d) + (%d.%d)\n",
352.32609 ++			       __FUNCTION__, e->x.quo, e->x.rem, e->dxdy.quo, e->dxdy.rem));
352.32610 ++
352.32611 + 			if (e->prev)
352.32612 + 				e->prev->next = n->next;
352.32613 + 			else
352.32614 +@@ -378,8 +383,11 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
352.32615 + 				break;
352.32616 + 
352.32617 + 			e = n->next;
352.32618 +-		} else
352.32619 ++		} else {
352.32620 ++			__DBG(("%s: adding edge (%d.%d) + (%d.%d)/%d, height=%d\n",
352.32621 ++			       __FUNCTION__, n->x.quo, n->x.rem, n->dxdy.quo, n->dxdy.rem, n->dy, n->height_left));
352.32622 + 			e = n;
352.32623 ++		}
352.32624 + 	}
352.32625 + 
352.32626 + 	return edges;
352.32627 +@@ -474,6 +482,34 @@ mono_span__fast(struct mono *c, int x1, int x2, BoxPtr box)
352.32628 + 	c->op.box(c->sna, &c->op, box);
352.32629 + }
352.32630 + 
352.32631 ++fastcall static void
352.32632 ++mono_span__clipped(struct mono *c, int x1, int x2, BoxPtr box)
352.32633 ++{
352.32634 ++	const BoxRec *b;
352.32635 ++
352.32636 ++	__DBG(("%s [%d, %d]\n", __FUNCTION__, x1, x2));
352.32637 ++
352.32638 ++	c->clip_start =
352.32639 ++		find_clip_box_for_y(c->clip_start, c->clip_end, box->y1);
352.32640 ++
352.32641 ++	b = c->clip_start;
352.32642 ++	while (b != c->clip_end) {
352.32643 ++		BoxRec clipped;
352.32644 ++
352.32645 ++		if (box->y2 <= b->y1)
352.32646 ++			break;
352.32647 ++
352.32648 ++		clipped.x1 = x1;
352.32649 ++		clipped.x2 = x2;
352.32650 ++		clipped.y1 = box->y1;
352.32651 ++		clipped.y2 = box->y2;
352.32652 ++		if (!box_intersect(&clipped, b++))
352.32653 ++			continue;
352.32654 ++
352.32655 ++		c->op.box(c->sna, &c->op, &clipped);
352.32656 ++	}
352.32657 ++}
352.32658 ++
352.32659 + struct mono_span_thread_boxes {
352.32660 + 	const struct sna_composite_op *op;
352.32661 + #define MONO_SPAN_MAX_BOXES (8192/sizeof(BoxRec))
352.32662 +@@ -482,40 +518,45 @@ struct mono_span_thread_boxes {
352.32663 + };
352.32664 + 
352.32665 + inline static void
352.32666 +-thread_mono_span_add_boxes(struct mono *c, const BoxRec *box, int count)
352.32667 ++thread_mono_span_add_box(struct mono *c, const BoxRec *box)
352.32668 + {
352.32669 + 	struct mono_span_thread_boxes *b = c->op.priv;
352.32670 + 
352.32671 +-	assert(count > 0 && count <= MONO_SPAN_MAX_BOXES);
352.32672 +-	if (unlikely(b->num_boxes + count > MONO_SPAN_MAX_BOXES)) {
352.32673 ++	if (unlikely(b->num_boxes == MONO_SPAN_MAX_BOXES)) {
352.32674 + 		b->op->thread_boxes(c->sna, b->op, b->boxes, b->num_boxes);
352.32675 + 		b->num_boxes = 0;
352.32676 + 	}
352.32677 + 
352.32678 +-	memcpy(b->boxes + b->num_boxes, box, count*sizeof(BoxRec));
352.32679 +-	b->num_boxes += count;
352.32680 ++	b->boxes[b->num_boxes++] = *box;
352.32681 + 	assert(b->num_boxes <= MONO_SPAN_MAX_BOXES);
352.32682 + }
352.32683 + 
352.32684 + fastcall static void
352.32685 + thread_mono_span_clipped(struct mono *c, int x1, int x2, BoxPtr box)
352.32686 + {
352.32687 +-	pixman_region16_t region;
352.32688 ++	const BoxRec *b;
352.32689 + 
352.32690 + 	__DBG(("%s [%d, %d]\n", __FUNCTION__, x1, x2));
352.32691 + 
352.32692 +-	box->x1 = x1;
352.32693 +-	box->x2 = x2;
352.32694 ++	c->clip_start =
352.32695 ++		find_clip_box_for_y(c->clip_start, c->clip_end, box->y1);
352.32696 + 
352.32697 +-	assert(c->clip.data);
352.32698 ++	b = c->clip_start;
352.32699 ++	while (b != c->clip_end) {
352.32700 ++		BoxRec clipped;
352.32701 ++
352.32702 ++		if (box->y2 <= b->y1)
352.32703 ++			break;
352.32704 ++
352.32705 ++		clipped.x1 = x1;
352.32706 ++		clipped.x2 = x2;
352.32707 ++		clipped.y1 = box->y1;
352.32708 ++		clipped.y2 = box->y2;
352.32709 ++		if (!box_intersect(&clipped, b++))
352.32710 ++			continue;
352.32711 + 
352.32712 +-	pixman_region_init_rects(&region, box, 1);
352.32713 +-	RegionIntersect(&region, &region, &c->clip);
352.32714 +-	if (region_num_rects(&region))
352.32715 +-		thread_mono_span_add_boxes(c,
352.32716 +-					   region_rects(&region),
352.32717 +-					   region_num_rects(&region));
352.32718 +-	pixman_region_fini(&region);
352.32719 ++		thread_mono_span_add_box(c, &clipped);
352.32720 ++	}
352.32721 + }
352.32722 + 
352.32723 + fastcall static void
352.32724 +@@ -525,7 +566,7 @@ thread_mono_span(struct mono *c, int x1, int x2, BoxPtr box)
352.32725 + 
352.32726 + 	box->x1 = x1;
352.32727 + 	box->x2 = x2;
352.32728 +-	thread_mono_span_add_boxes(c, box, 1);
352.32729 ++	thread_mono_span_add_box(c, box);
352.32730 + }
352.32731 + 
352.32732 + inline static void
352.32733 +@@ -537,6 +578,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
352.32734 + 	int winding = 0;
352.32735 + 	BoxRec box;
352.32736 + 
352.32737 ++	__DBG(("%s: y=%d, h=%d\n", __FUNCTION__, y, h));
352.32738 ++
352.32739 + 	DBG_MONO_EDGES(edge);
352.32740 + 	VALIDATE_MONO_EDGES(&c->head);
352.32741 + 
352.32742 +@@ -547,6 +590,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
352.32743 + 		struct mono_edge *next = edge->next;
352.32744 + 		int16_t xend = I(edge->x.quo);
352.32745 + 
352.32746 ++		__DBG(("%s: adding edge dir=%d [winding=%d], x=%d [%d]\n",
352.32747 ++		       __FUNCTION__, edge->dir, winding + edge->dir, xend, edge->x.quo));
352.32748 + 		if (--edge->height_left) {
352.32749 + 			if (edge->dy) {
352.32750 + 				edge->x.quo += edge->dxdy.quo;
352.32751 +@@ -555,6 +600,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
352.32752 + 					++edge->x.quo;
352.32753 + 					edge->x.rem -= edge->dy;
352.32754 + 				}
352.32755 ++				__DBG(("%s: stepped edge (%d.%d) + (%d.%d)/%d, height=%d, prev_x=%d\n",
352.32756 ++				       __FUNCTION__, edge->x.quo, edge->x.rem, edge->dxdy.quo, edge->dxdy.rem, edge->dy, edge->height_left, edge->x.quo));
352.32757 + 			}
352.32758 + 
352.32759 + 			if (edge->x.quo < prev_x) {
352.32760 +@@ -578,17 +625,22 @@ mono_row(struct mono *c, int16_t y, int16_t h)
352.32761 + 		winding += edge->dir;
352.32762 + 		if (winding == 0) {
352.32763 + 			assert(I(next->x.quo) >= xend);
352.32764 +-			if (I(next->x.quo) > xend + 1) {
352.32765 ++			if (I(next->x.quo) > xend) {
352.32766 ++				__DBG(("%s: end span: %d\n", __FUNCTION__, xend));
352.32767 + 				if (xstart < c->clip.extents.x1)
352.32768 + 					xstart = c->clip.extents.x1;
352.32769 + 				if (xend > c->clip.extents.x2)
352.32770 + 					xend = c->clip.extents.x2;
352.32771 +-				if (xend > xstart)
352.32772 ++				if (xend > xstart) {
352.32773 ++					__DBG(("%s: emit span [%d, %d]\n", __FUNCTION__, xstart, xend));
352.32774 + 					c->span(c, xstart, xend, &box);
352.32775 ++				}
352.32776 + 				xstart = INT16_MIN;
352.32777 + 			}
352.32778 +-		} else if (xstart == INT16_MIN)
352.32779 ++		} else if (xstart == INT16_MIN) {
352.32780 ++			__DBG(("%s: starting new span: %d\n", __FUNCTION__, xend));
352.32781 + 			xstart = xend;
352.32782 ++		}
352.32783 + 
352.32784 + 		edge = next;
352.32785 + 	}
352.32786 +@@ -650,9 +702,14 @@ mono_render(struct mono *mono)
352.32787 + 	for (i = 0; i < h; i = j) {
352.32788 + 		j = i + 1;
352.32789 + 
352.32790 ++		__DBG(("%s: row=%d, new edges? %d\n", __FUNCTION__,
352.32791 ++		       i, polygon->y_buckets[i] != NULL));
352.32792 ++
352.32793 + 		if (polygon->y_buckets[i])
352.32794 + 			mono_merge_edges(mono, polygon->y_buckets[i]);
352.32795 + 
352.32796 ++		__DBG(("%s: row=%d, vertical? %d\n", __FUNCTION__,
352.32797 ++		       i, mono->is_vertical));
352.32798 + 		if (mono->is_vertical) {
352.32799 + 			struct mono_edge *e = mono->head.next;
352.32800 + 			int min_height = h - i;
352.32801 +@@ -667,6 +724,7 @@ mono_render(struct mono *mono)
352.32802 + 				j++;
352.32803 + 			if (j != i + 1)
352.32804 + 				mono_step_edges(mono, j - (i + 1));
352.32805 ++			__DBG(("%s: %d vertical rows\n", __FUNCTION__, j-i));
352.32806 + 		}
352.32807 + 
352.32808 + 		mono_row(mono, i, j-i);
352.32809 +@@ -717,6 +775,7 @@ mono_span_thread(void *arg)
352.32810 + 		if (RegionNil(&mono.clip))
352.32811 + 			return;
352.32812 + 	}
352.32813 ++	region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
352.32814 + 
352.32815 + 	boxes.op = thread->op;
352.32816 + 	boxes.num_boxes = 0;
352.32817 +@@ -891,9 +950,12 @@ mono_trapezoids_span_converter(struct sna *sna,
352.32818 + 
352.32819 + 	if (mono.clip.data == NULL && mono.op.damage == NULL)
352.32820 + 		mono.span = mono_span__fast;
352.32821 ++	else if (mono.clip.data != NULL && mono.op.damage == NULL)
352.32822 ++		mono.span = mono_span__clipped;
352.32823 + 	else
352.32824 + 		mono.span = mono_span;
352.32825 + 
352.32826 ++	region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
352.32827 + 	mono_render(&mono);
352.32828 + 	mono.op.done(mono.sna, &mono.op);
352.32829 + 	mono_fini(&mono);
352.32830 +@@ -939,6 +1001,7 @@ mono_trapezoids_span_converter(struct sna *sna,
352.32831 + 					       mono.clip.extents.x2 - mono.clip.extents.x1,
352.32832 + 					       mono.clip.extents.y2 - mono.clip.extents.y1,
352.32833 + 					       COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
352.32834 ++			region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
352.32835 + 			mono_render(&mono);
352.32836 + 			mono.op.done(mono.sna, &mono.op);
352.32837 + 		}
352.32838 +@@ -974,6 +1037,7 @@ mono_inplace_fill_box(struct sna *sna,
352.32839 + 	     box->x2 - box->x1,
352.32840 + 	     box->y2 - box->y1,
352.32841 + 	     fill->color));
352.32842 ++	sigtrap_assert_active();
352.32843 + 	pixman_fill(fill->data, fill->stride, fill->bpp,
352.32844 + 		    box->x1, box->y1,
352.32845 + 		    box->x2 - box->x1,
352.32846 +@@ -995,6 +1059,7 @@ mono_inplace_fill_boxes(struct sna *sna,
352.32847 + 		     box->x2 - box->x1,
352.32848 + 		     box->y2 - box->y1,
352.32849 + 		     fill->color));
352.32850 ++		sigtrap_assert_active();
352.32851 + 		pixman_fill(fill->data, fill->stride, fill->bpp,
352.32852 + 			    box->x1, box->y1,
352.32853 + 			    box->x2 - box->x1,
352.32854 +@@ -1382,10 +1447,13 @@ mono_triangles_span_converter(struct sna *sna,
352.32855 + 		mono_render(&mono);
352.32856 + 		mono.op.done(mono.sna, &mono.op);
352.32857 + 	}
352.32858 ++	mono_fini(&mono);
352.32859 + 
352.32860 + 	if (!was_clear && !operator_is_bounded(op)) {
352.32861 + 		xPointFixed p1, p2;
352.32862 + 
352.32863 ++		DBG(("%s: performing unbounded clear\n", __FUNCTION__));
352.32864 ++
352.32865 + 		if (!mono_init(&mono, 2+3*count))
352.32866 + 			return false;
352.32867 + 
352.32868 +@@ -1431,7 +1499,6 @@ mono_triangles_span_converter(struct sna *sna,
352.32869 + 		mono_fini(&mono);
352.32870 + 	}
352.32871 + 
352.32872 +-	mono_fini(&mono);
352.32873 + 	REGION_UNINIT(NULL, &mono.clip);
352.32874 + 	return true;
352.32875 + }
352.32876 +diff --git a/src/sna/sna_trapezoids_precise.c b/src/sna/sna_trapezoids_precise.c
352.32877 +index 9187ab48..242b4acb 100644
352.32878 +--- a/src/sna/sna_trapezoids_precise.c
352.32879 ++++ b/src/sna/sna_trapezoids_precise.c
352.32880 +@@ -1023,6 +1023,16 @@ tor_init(struct tor *converter, const BoxRec *box, int num_edges)
352.32881 + static void
352.32882 + tor_add_trapezoid(struct tor *tor, const xTrapezoid *t, int dx, int dy)
352.32883 + {
352.32884 ++	if (!xTrapezoidValid(t)) {
352.32885 ++		__DBG(("%s: skipping invalid trapezoid: top=%d, bottom=%d, left=(%d, %d), (%d, %d), right=(%d, %d), (%d, %d)\n",
352.32886 ++		       __FUNCTION__,
352.32887 ++		       t->top, t->bottom,
352.32888 ++		       t->left.p1.x, t->left.p1.y,
352.32889 ++		       t->left.p2.x, t->left.p2.y,
352.32890 ++		       t->right.p1.x, t->right.p1.y,
352.32891 ++		       t->right.p2.x, t->right.p2.y));
352.32892 ++		return;
352.32893 ++	}
352.32894 + 	polygon_add_edge(tor->polygon, t, &t->left, 1, dx, dy);
352.32895 + 	polygon_add_edge(tor->polygon, t, &t->right, -1, dx, dy);
352.32896 + }
352.32897 +@@ -1635,31 +1645,27 @@ struct span_thread {
352.32898 + #define SPAN_THREAD_MAX_BOXES (8192/sizeof(struct sna_opacity_box))
352.32899 + struct span_thread_boxes {
352.32900 + 	const struct sna_composite_spans_op *op;
352.32901 ++	const BoxRec *clip_start, *clip_end;
352.32902 + 	int num_boxes;
352.32903 + 	struct sna_opacity_box boxes[SPAN_THREAD_MAX_BOXES];
352.32904 + };
352.32905 + 
352.32906 +-static void span_thread_add_boxes(struct sna *sna, void *data,
352.32907 +-				  const BoxRec *box, int count, float alpha)
352.32908 ++static void span_thread_add_box(struct sna *sna, void *data,
352.32909 ++				const BoxRec *box, float alpha)
352.32910 + {
352.32911 + 	struct span_thread_boxes *b = data;
352.32912 + 
352.32913 +-	__DBG(("%s: adding %d boxes with alpha=%f\n",
352.32914 +-	       __FUNCTION__, count, alpha));
352.32915 ++	__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
352.32916 + 
352.32917 +-	assert(count > 0 && count <= SPAN_THREAD_MAX_BOXES);
352.32918 +-	if (unlikely(b->num_boxes + count > SPAN_THREAD_MAX_BOXES)) {
352.32919 +-		DBG(("%s: flushing %d boxes, adding %d\n", __FUNCTION__, b->num_boxes, count));
352.32920 +-		assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
352.32921 ++	if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
352.32922 ++		DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
352.32923 + 		b->op->thread_boxes(sna, b->op, b->boxes, b->num_boxes);
352.32924 + 		b->num_boxes = 0;
352.32925 + 	}
352.32926 + 
352.32927 +-	do {
352.32928 +-		b->boxes[b->num_boxes].box = *box++;
352.32929 +-		b->boxes[b->num_boxes].alpha = alpha;
352.32930 +-		b->num_boxes++;
352.32931 +-	} while (--count);
352.32932 ++	b->boxes[b->num_boxes].box = *box++;
352.32933 ++	b->boxes[b->num_boxes].alpha = alpha;
352.32934 ++	b->num_boxes++;
352.32935 + 	assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
352.32936 + }
352.32937 + 
352.32938 +@@ -1670,8 +1676,22 @@ span_thread_box(struct sna *sna,
352.32939 + 		const BoxRec *box,
352.32940 + 		int coverage)
352.32941 + {
352.32942 ++	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
352.32943 ++
352.32944 + 	__DBG(("%s: %d -> %d @ %d\n", __FUNCTION__, box->x1, box->x2, coverage));
352.32945 +-	span_thread_add_boxes(sna, op, box, 1, AREA_TO_FLOAT(coverage));
352.32946 ++	if (b->num_boxes) {
352.32947 ++		struct sna_opacity_box *bb = &b->boxes[b->num_boxes-1];
352.32948 ++		if (bb->box.x1 == box->x1 &&
352.32949 ++		    bb->box.x2 == box->x2 &&
352.32950 ++		    bb->box.y2 == box->y1 &&
352.32951 ++		    bb->alpha == AREA_TO_FLOAT(coverage)) {
352.32952 ++			bb->box.y2 = box->y2;
352.32953 ++			__DBG(("%s: contracted double row: %d -> %d\n", __func__, bb->box.y1, bb->box.y2));
352.32954 ++			return;
352.32955 ++		}
352.32956 ++	}
352.32957 ++
352.32958 ++	span_thread_add_box(sna, op, box, AREA_TO_FLOAT(coverage));
352.32959 + }
352.32960 + 
352.32961 + static void
352.32962 +@@ -1681,20 +1701,28 @@ span_thread_clipped_box(struct sna *sna,
352.32963 + 			const BoxRec *box,
352.32964 + 			int coverage)
352.32965 + {
352.32966 +-	pixman_region16_t region;
352.32967 ++	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
352.32968 ++	const BoxRec *c;
352.32969 + 
352.32970 + 	__DBG(("%s: %d -> %d @ %f\n", __FUNCTION__, box->x1, box->x2,
352.32971 + 	       AREA_TO_FLOAT(coverage)));
352.32972 + 
352.32973 +-	pixman_region_init_rects(&region, box, 1);
352.32974 +-	RegionIntersect(&region, &region, clip);
352.32975 +-	if (region_num_rects(&region)) {
352.32976 +-		span_thread_add_boxes(sna, op,
352.32977 +-				      region_rects(&region),
352.32978 +-				      region_num_rects(&region),
352.32979 +-				      AREA_TO_FLOAT(coverage));
352.32980 ++	b->clip_start =
352.32981 ++		find_clip_box_for_y(b->clip_start, b->clip_end, box->y1);
352.32982 ++
352.32983 ++	c = b->clip_start;
352.32984 ++	while (c != b->clip_end) {
352.32985 ++		BoxRec clipped;
352.32986 ++
352.32987 ++		if (box->y2 <= c->y1)
352.32988 ++			break;
352.32989 ++
352.32990 ++		clipped = *box;
352.32991 ++		if (!box_intersect(&clipped, c++))
352.32992 ++			continue;
352.32993 ++
352.32994 ++		span_thread_add_box(sna, op, &clipped, AREA_TO_FLOAT(coverage));
352.32995 + 	}
352.32996 +-	pixman_region_fini(&region);
352.32997 + }
352.32998 + 
352.32999 + static span_func_t
352.33000 +@@ -1712,7 +1740,7 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
352.33001 + 
352.33002 + 	assert(!is_mono(dst, maskFormat));
352.33003 + 	assert(tmp->thread_boxes);
352.33004 +-	DBG(("%s: clipped? %d\n", __FUNCTION__, clip->data != NULL));
352.33005 ++	DBG(("%s: clipped? %d x %d\n", __FUNCTION__, clip->data != NULL, region_num_rects(clip)));
352.33006 + 	if (clip->data)
352.33007 + 		span = span_thread_clipped_box;
352.33008 + 	else
352.33009 +@@ -1721,6 +1749,17 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
352.33010 + 	return span;
352.33011 + }
352.33012 + 
352.33013 ++inline static void
352.33014 ++span_thread_boxes_init(struct span_thread_boxes *boxes,
352.33015 ++		       const struct sna_composite_spans_op *op,
352.33016 ++		       const RegionRec *clip)
352.33017 ++{
352.33018 ++	boxes->op = op;
352.33019 ++	boxes->clip_start = region_rects(clip);
352.33020 ++	boxes->clip_end = boxes->clip_start + region_num_rects(clip);
352.33021 ++	boxes->num_boxes = 0;
352.33022 ++}
352.33023 ++
352.33024 + static void
352.33025 + span_thread(void *arg)
352.33026 + {
352.33027 +@@ -1733,8 +1772,7 @@ span_thread(void *arg)
352.33028 + 	if (!tor_init(&tor, &thread->extents, 2*thread->ntrap))
352.33029 + 		return;
352.33030 + 
352.33031 +-	boxes.op = thread->op;
352.33032 +-	boxes.num_boxes = 0;
352.33033 ++	span_thread_boxes_init(&boxes, thread->op, thread->clip);
352.33034 + 
352.33035 + 	y1 = thread->extents.y1 - thread->draw_y;
352.33036 + 	y2 = thread->extents.y2 - thread->draw_y;
352.33037 +@@ -2183,6 +2221,52 @@ static force_inline uint8_t coverage_opacity(int coverage, uint8_t opacity)
352.33038 + 	return opacity == 255 ? coverage : mul_8_8(coverage, opacity);
352.33039 + }
352.33040 + 
352.33041 ++struct clipped_span {
352.33042 ++	span_func_t span;
352.33043 ++	const BoxRec *clip_start, *clip_end;
352.33044 ++};
352.33045 ++
352.33046 ++static void
352.33047 ++tor_blt_clipped(struct sna *sna,
352.33048 ++		struct sna_composite_spans_op *op,
352.33049 ++		pixman_region16_t *clip,
352.33050 ++		const BoxRec *box,
352.33051 ++		int coverage)
352.33052 ++{
352.33053 ++	struct clipped_span *cs = (struct clipped_span *)clip;
352.33054 ++	const BoxRec *c;
352.33055 ++
352.33056 ++	cs->clip_start =
352.33057 ++		find_clip_box_for_y(cs->clip_start, cs->clip_end, box->y1);
352.33058 ++
352.33059 ++	c = cs->clip_start;
352.33060 ++	while (c != cs->clip_end) {
352.33061 ++		BoxRec clipped;
352.33062 ++
352.33063 ++		if (box->y2 <= c->y1)
352.33064 ++			break;
352.33065 ++
352.33066 ++		clipped = *box;
352.33067 ++		if (!box_intersect(&clipped, c++))
352.33068 ++			continue;
352.33069 ++
352.33070 ++		cs->span(sna, op, NULL, &clipped, coverage);
352.33071 ++	}
352.33072 ++}
352.33073 ++
352.33074 ++inline static span_func_t
352.33075 ++clipped_span(struct clipped_span *cs,
352.33076 ++	     span_func_t span,
352.33077 ++	     const RegionRec *clip)
352.33078 ++{
352.33079 ++	if (clip->data) {
352.33080 ++		cs->span = span;
352.33081 ++		region_get_boxes(clip, &cs->clip_start, &cs->clip_end);
352.33082 ++		span = tor_blt_clipped;
352.33083 ++	}
352.33084 ++	return span;
352.33085 ++}
352.33086 ++
352.33087 + static void _tor_blt_src(struct inplace *in, const BoxRec *box, uint8_t v)
352.33088 + {
352.33089 + 	uint8_t *ptr = in->ptr;
352.33090 +@@ -2218,25 +2302,6 @@ tor_blt_src(struct sna *sna,
352.33091 + }
352.33092 + 
352.33093 + static void
352.33094 +-tor_blt_src_clipped(struct sna *sna,
352.33095 +-		    struct sna_composite_spans_op *op,
352.33096 +-		    pixman_region16_t *clip,
352.33097 +-		    const BoxRec *box,
352.33098 +-		    int coverage)
352.33099 +-{
352.33100 +-	pixman_region16_t region;
352.33101 +-	int n;
352.33102 +-
352.33103 +-	pixman_region_init_rects(&region, box, 1);
352.33104 +-	RegionIntersect(&region, &region, clip);
352.33105 +-	n = region_num_rects(&region);
352.33106 +-	box = region_rects(&region);
352.33107 +-	while (n--)
352.33108 +-		tor_blt_src(sna, op, NULL, box++, coverage);
352.33109 +-	pixman_region_fini(&region);
352.33110 +-}
352.33111 +-
352.33112 +-static void
352.33113 + tor_blt_in(struct sna *sna,
352.33114 + 	   struct sna_composite_spans_op *op,
352.33115 + 	   pixman_region16_t *clip,
352.33116 +@@ -2268,25 +2333,6 @@ tor_blt_in(struct sna *sna,
352.33117 + }
352.33118 + 
352.33119 + static void
352.33120 +-tor_blt_in_clipped(struct sna *sna,
352.33121 +-		   struct sna_composite_spans_op *op,
352.33122 +-		   pixman_region16_t *clip,
352.33123 +-		   const BoxRec *box,
352.33124 +-		   int coverage)
352.33125 +-{
352.33126 +-	pixman_region16_t region;
352.33127 +-	int n;
352.33128 +-
352.33129 +-	pixman_region_init_rects(&region, box, 1);
352.33130 +-	RegionIntersect(&region, &region, clip);
352.33131 +-	n = region_num_rects(&region);
352.33132 +-	box = region_rects(&region);
352.33133 +-	while (n--)
352.33134 +-		tor_blt_in(sna, op, NULL, box++, coverage);
352.33135 +-	pixman_region_fini(&region);
352.33136 +-}
352.33137 +-
352.33138 +-static void
352.33139 + tor_blt_add(struct sna *sna,
352.33140 + 	    struct sna_composite_spans_op *op,
352.33141 + 	    pixman_region16_t *clip,
352.33142 +@@ -2325,25 +2371,6 @@ tor_blt_add(struct sna *sna,
352.33143 + }
352.33144 + 
352.33145 + static void
352.33146 +-tor_blt_add_clipped(struct sna *sna,
352.33147 +-		    struct sna_composite_spans_op *op,
352.33148 +-		    pixman_region16_t *clip,
352.33149 +-		    const BoxRec *box,
352.33150 +-		    int coverage)
352.33151 +-{
352.33152 +-	pixman_region16_t region;
352.33153 +-	int n;
352.33154 +-
352.33155 +-	pixman_region_init_rects(&region, box, 1);
352.33156 +-	RegionIntersect(&region, &region, clip);
352.33157 +-	n = region_num_rects(&region);
352.33158 +-	box = region_rects(&region);
352.33159 +-	while (n--)
352.33160 +-		tor_blt_add(sna, op, NULL, box++, coverage);
352.33161 +-	pixman_region_fini(&region);
352.33162 +-}
352.33163 +-
352.33164 +-static void
352.33165 + tor_blt_lerp32(struct sna *sna,
352.33166 + 	       struct sna_composite_spans_op *op,
352.33167 + 	       pixman_region16_t *clip,
352.33168 +@@ -2358,6 +2385,7 @@ tor_blt_lerp32(struct sna *sna,
352.33169 + 	if (coverage == 0)
352.33170 + 		return;
352.33171 + 
352.33172 ++	sigtrap_assert_active();
352.33173 + 	ptr += box->y1 * stride + box->x1;
352.33174 + 
352.33175 + 	h = box->y2 - box->y1;
352.33176 +@@ -2396,25 +2424,6 @@ tor_blt_lerp32(struct sna *sna,
352.33177 + 	}
352.33178 + }
352.33179 + 
352.33180 +-static void
352.33181 +-tor_blt_lerp32_clipped(struct sna *sna,
352.33182 +-		       struct sna_composite_spans_op *op,
352.33183 +-		       pixman_region16_t *clip,
352.33184 +-		       const BoxRec *box,
352.33185 +-		       int coverage)
352.33186 +-{
352.33187 +-	pixman_region16_t region;
352.33188 +-	int n;
352.33189 +-
352.33190 +-	pixman_region_init_rects(&region, box, 1);
352.33191 +-	RegionIntersect(&region, &region, clip);
352.33192 +-	n = region_num_rects(&region);
352.33193 +-	box = region_rects(&region);
352.33194 +-	while (n--)
352.33195 +-		tor_blt_lerp32(sna, op, NULL, box++, coverage);
352.33196 +-	pixman_region_fini(&region);
352.33197 +-}
352.33198 +-
352.33199 + struct pixman_inplace {
352.33200 + 	pixman_image_t *image, *source, *mask;
352.33201 + 	uint32_t color;
352.33202 +@@ -2442,24 +2451,6 @@ pixmask_span_solid(struct sna *sna,
352.33203 + 			       pi->dx + box->x1, pi->dy + box->y1,
352.33204 + 			       box->x2 - box->x1, box->y2 - box->y1);
352.33205 + }
352.33206 +-static void
352.33207 +-pixmask_span_solid__clipped(struct sna *sna,
352.33208 +-			    struct sna_composite_spans_op *op,
352.33209 +-			    pixman_region16_t *clip,
352.33210 +-			    const BoxRec *box,
352.33211 +-			    int coverage)
352.33212 +-{
352.33213 +-	pixman_region16_t region;
352.33214 +-	int n;
352.33215 +-
352.33216 +-	pixman_region_init_rects(&region, box, 1);
352.33217 +-	RegionIntersect(&region, &region, clip);
352.33218 +-	n = region_num_rects(&region);
352.33219 +-	box = region_rects(&region);
352.33220 +-	while (n--)
352.33221 +-		pixmask_span_solid(sna, op, NULL, box++, coverage);
352.33222 +-	pixman_region_fini(&region);
352.33223 +-}
352.33224 + 
352.33225 + static void
352.33226 + pixmask_span(struct sna *sna,
352.33227 +@@ -2480,24 +2471,6 @@ pixmask_span(struct sna *sna,
352.33228 + 			       pi->dx + box->x1, pi->dy + box->y1,
352.33229 + 			       box->x2 - box->x1, box->y2 - box->y1);
352.33230 + }
352.33231 +-static void
352.33232 +-pixmask_span__clipped(struct sna *sna,
352.33233 +-		      struct sna_composite_spans_op *op,
352.33234 +-		      pixman_region16_t *clip,
352.33235 +-		      const BoxRec *box,
352.33236 +-		      int coverage)
352.33237 +-{
352.33238 +-	pixman_region16_t region;
352.33239 +-	int n;
352.33240 +-
352.33241 +-	pixman_region_init_rects(&region, box, 1);
352.33242 +-	RegionIntersect(&region, &region, clip);
352.33243 +-	n = region_num_rects(&region);
352.33244 +-	box = region_rects(&region);
352.33245 +-	while (n--)
352.33246 +-		pixmask_span(sna, op, NULL, box++, coverage);
352.33247 +-	pixman_region_fini(&region);
352.33248 +-}
352.33249 + 
352.33250 + struct inplace_x8r8g8b8_thread {
352.33251 + 	xTrapezoid *traps;
352.33252 +@@ -2516,6 +2489,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.33253 + 	struct inplace_x8r8g8b8_thread *thread = arg;
352.33254 + 	struct tor tor;
352.33255 + 	span_func_t span;
352.33256 ++	struct clipped_span clipped;
352.33257 + 	RegionPtr clip;
352.33258 + 	int y1, y2, n;
352.33259 + 
352.33260 +@@ -2546,12 +2520,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.33261 + 		inplace.stride = pixmap->devKind;
352.33262 + 		inplace.color = thread->color;
352.33263 + 
352.33264 +-		if (clip->data)
352.33265 +-			span = tor_blt_lerp32_clipped;
352.33266 +-		else
352.33267 +-			span = tor_blt_lerp32;
352.33268 ++		span = clipped_span(&clipped, tor_blt_lerp32, clip);
352.33269 + 
352.33270 +-		tor_render(NULL, &tor, (void*)&inplace, clip, span, false);
352.33271 ++		tor_render(NULL, &tor,
352.33272 ++			   (void*)&inplace, (void *)&clipped,
352.33273 ++			   span, false);
352.33274 + 	} else if (thread->is_solid) {
352.33275 + 		struct pixman_inplace pi;
352.33276 + 
352.33277 +@@ -2564,10 +2537,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.33278 + 						     1, 1, pi.bits, 0);
352.33279 + 		pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
352.33280 + 
352.33281 +-		if (clip->data)
352.33282 +-			span = pixmask_span_solid__clipped;
352.33283 +-		else
352.33284 +-			span = pixmask_span_solid;
352.33285 ++		span = clipped_span(&clipped, pixmask_span_solid, clip);
352.33286 + 
352.33287 + 		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
352.33288 + 
352.33289 +@@ -2588,12 +2558,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
352.33290 + 		pi.bits = pixman_image_get_data(pi.mask);
352.33291 + 		pi.op = thread->op;
352.33292 + 
352.33293 +-		if (clip->data)
352.33294 +-			span = pixmask_span__clipped;
352.33295 +-		else
352.33296 +-			span = pixmask_span;
352.33297 ++		span = clipped_span(&clipped, pixmask_span, clip);
352.33298 + 
352.33299 +-		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
352.33300 ++		tor_render(NULL, &tor,
352.33301 ++			   (void*)&pi, (void *)&clipped,
352.33302 ++			   span, false);
352.33303 + 
352.33304 + 		pixman_image_unref(pi.mask);
352.33305 + 		pixman_image_unref(pi.source);
352.33306 +@@ -2712,6 +2681,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.33307 + 	if (num_threads == 1) {
352.33308 + 		struct tor tor;
352.33309 + 		span_func_t span;
352.33310 ++		struct clipped_span clipped;
352.33311 + 
352.33312 + 		if (!tor_init(&tor, &region.extents, 2*ntrap))
352.33313 + 			return true;
352.33314 +@@ -2737,17 +2707,14 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.33315 + 			inplace.stride = pixmap->devKind;
352.33316 + 			inplace.color = color;
352.33317 + 
352.33318 +-			if (dst->pCompositeClip->data)
352.33319 +-				span = tor_blt_lerp32_clipped;
352.33320 +-			else
352.33321 +-				span = tor_blt_lerp32;
352.33322 +-
352.33323 ++			span = clipped_span(&clipped, tor_blt_lerp32, dst->pCompositeClip);
352.33324 + 			DBG(("%s: render inplace op=%d, color=%08x\n",
352.33325 + 			     __FUNCTION__, op, color));
352.33326 + 
352.33327 + 			if (sigtrap_get() == 0) {
352.33328 +-				tor_render(NULL, &tor, (void*)&inplace,
352.33329 +-					   dst->pCompositeClip, span, false);
352.33330 ++				tor_render(NULL, &tor,
352.33331 ++					   (void*)&inplace, (void*)&clipped,
352.33332 ++					   span, false);
352.33333 + 				sigtrap_put();
352.33334 + 			}
352.33335 + 		} else if (is_solid) {
352.33336 +@@ -2762,15 +2729,11 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.33337 + 							     1, 1, pi.bits, 0);
352.33338 + 			pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
352.33339 + 
352.33340 +-			if (dst->pCompositeClip->data)
352.33341 +-				span = pixmask_span_solid__clipped;
352.33342 +-			else
352.33343 +-				span = pixmask_span_solid;
352.33344 +-
352.33345 ++			span = clipped_span(&clipped, pixmask_span_solid, dst->pCompositeClip);
352.33346 + 			if (sigtrap_get() == 0) {
352.33347 +-				tor_render(NULL, &tor, (void*)&pi,
352.33348 +-					   dst->pCompositeClip, span,
352.33349 +-					   false);
352.33350 ++				tor_render(NULL, &tor,
352.33351 ++					   (void*)&pi, (void*)&clipped,
352.33352 ++					    span, false);
352.33353 + 				sigtrap_put();
352.33354 + 			}
352.33355 + 
352.33356 +@@ -2791,15 +2754,11 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.33357 + 			pi.bits = pixman_image_get_data(pi.mask);
352.33358 + 			pi.op = op;
352.33359 + 
352.33360 +-			if (dst->pCompositeClip->data)
352.33361 +-				span = pixmask_span__clipped;
352.33362 +-			else
352.33363 +-				span = pixmask_span;
352.33364 +-
352.33365 ++			span = clipped_span(&clipped, pixmask_span, dst->pCompositeClip);
352.33366 + 			if (sigtrap_get() == 0) {
352.33367 +-				tor_render(NULL, &tor, (void*)&pi,
352.33368 +-					   dst->pCompositeClip, span,
352.33369 +-					   false);
352.33370 ++				tor_render(NULL, &tor,
352.33371 ++					   (void*)&pi, (void *)&clipped,
352.33372 ++					   span, false);
352.33373 + 				sigtrap_put();
352.33374 + 			}
352.33375 + 
352.33376 +@@ -2861,9 +2820,9 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
352.33377 + 
352.33378 + struct inplace_thread {
352.33379 + 	xTrapezoid *traps;
352.33380 +-	RegionPtr clip;
352.33381 + 	span_func_t span;
352.33382 + 	struct inplace inplace;
352.33383 ++	struct clipped_span clipped;
352.33384 + 	BoxRec extents;
352.33385 + 	int dx, dy;
352.33386 + 	int draw_x, draw_y;
352.33387 +@@ -2888,8 +2847,9 @@ static void inplace_thread(void *arg)
352.33388 + 		tor_add_trapezoid(&tor, &thread->traps[n], thread->dx, thread->dy);
352.33389 + 	}
352.33390 + 
352.33391 +-	tor_render(NULL, &tor, (void*)&thread->inplace,
352.33392 +-		   thread->clip, thread->span, thread->unbounded);
352.33393 ++	tor_render(NULL, &tor, 
352.33394 ++		   (void*)&thread->inplace, (void*)&thread->clipped,
352.33395 ++		   thread->span, thread->unbounded);
352.33396 + 
352.33397 + 	tor_fini(&tor);
352.33398 + }
352.33399 +@@ -2903,6 +2863,7 @@ precise_trapezoid_span_inplace(struct sna *sna,
352.33400 + 			       bool fallback)
352.33401 + {
352.33402 + 	struct inplace inplace;
352.33403 ++	struct clipped_span clipped;
352.33404 + 	span_func_t span;
352.33405 + 	PixmapPtr pixmap;
352.33406 + 	struct sna_pixmap *priv;
352.33407 +@@ -3020,21 +2981,12 @@ precise_trapezoid_span_inplace(struct sna *sna,
352.33408 + 	     dst->pCompositeClip->data != NULL));
352.33409 + 
352.33410 + 	if (op == PictOpSrc) {
352.33411 +-		if (dst->pCompositeClip->data)
352.33412 +-			span = tor_blt_src_clipped;
352.33413 +-		else
352.33414 +-			span = tor_blt_src;
352.33415 ++		span = tor_blt_src;
352.33416 + 	} else if (op == PictOpIn) {
352.33417 +-		if (dst->pCompositeClip->data)
352.33418 +-			span = tor_blt_in_clipped;
352.33419 +-		else
352.33420 +-			span = tor_blt_in;
352.33421 ++		span = tor_blt_in;
352.33422 + 	} else {
352.33423 + 		assert(op == PictOpAdd);
352.33424 +-		if (dst->pCompositeClip->data)
352.33425 +-			span = tor_blt_add_clipped;
352.33426 +-		else
352.33427 +-			span = tor_blt_add;
352.33428 ++		span = tor_blt_add;
352.33429 + 	}
352.33430 + 
352.33431 + 	DBG(("%s: move-to-cpu(dst)\n", __FUNCTION__));
352.33432 +@@ -3052,6 +3004,8 @@ precise_trapezoid_span_inplace(struct sna *sna,
352.33433 + 	inplace.stride = pixmap->devKind;
352.33434 + 	inplace.opacity = color >> 24;
352.33435 + 
352.33436 ++	span = clipped_span(&clipped, span, dst->pCompositeClip);
352.33437 ++
352.33438 + 	num_threads = 1;
352.33439 + 	if (!NO_GPU_THREADS &&
352.33440 + 	    (flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
352.33441 +@@ -3074,8 +3028,9 @@ precise_trapezoid_span_inplace(struct sna *sna,
352.33442 + 		}
352.33443 + 
352.33444 + 		if (sigtrap_get() == 0) {
352.33445 +-			tor_render(NULL, &tor, (void*)&inplace,
352.33446 +-				   dst->pCompositeClip, span, unbounded);
352.33447 ++			tor_render(NULL, &tor,
352.33448 ++				   (void*)&inplace, (void *)&clipped,
352.33449 ++				   span, unbounded);
352.33450 + 			sigtrap_put();
352.33451 + 		}
352.33452 + 
352.33453 +@@ -3093,7 +3048,7 @@ precise_trapezoid_span_inplace(struct sna *sna,
352.33454 + 		threads[0].ntrap = ntrap;
352.33455 + 		threads[0].inplace = inplace;
352.33456 + 		threads[0].extents = region.extents;
352.33457 +-		threads[0].clip = dst->pCompositeClip;
352.33458 ++		threads[0].clipped = clipped;
352.33459 + 		threads[0].span = span;
352.33460 + 		threads[0].unbounded = unbounded;
352.33461 + 		threads[0].dx = dx;
352.33462 +@@ -3316,8 +3271,7 @@ tristrip_thread(void *arg)
352.33463 + 	if (!tor_init(&tor, &thread->extents, 2*thread->count))
352.33464 + 		return;
352.33465 + 
352.33466 +-	boxes.op = thread->op;
352.33467 +-	boxes.num_boxes = 0;
352.33468 ++	span_thread_boxes_init(&boxes, thread->op, thread->clip);
352.33469 + 
352.33470 + 	cw = 0; ccw = 1;
352.33471 + 	polygon_add_line(tor.polygon,
352.33472 +diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c
352.33473 +index ed0e7b31..e2b11c31 100644
352.33474 +--- a/src/sna/sna_video.c
352.33475 ++++ b/src/sna/sna_video.c
352.33476 +@@ -591,6 +591,72 @@ use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */
352.33477 + 	return true;
352.33478 + }
352.33479 + 
352.33480 ++void sna_video_fill_colorkey(struct sna_video *video,
352.33481 ++			     const RegionRec *clip)
352.33482 ++{
352.33483 ++	struct sna *sna = video->sna;
352.33484 ++	PixmapPtr front = sna->front;
352.33485 ++	struct kgem_bo *bo = __sna_pixmap_get_bo(front);
352.33486 ++	uint8_t *dst, *tmp;
352.33487 ++	int w, width;
352.33488 ++
352.33489 ++	if (video->AlwaysOnTop || RegionEqual(&video->clip, (RegionPtr)clip))
352.33490 ++		return;
352.33491 ++
352.33492 ++	assert(bo);
352.33493 ++	if (!wedged(sna) &&
352.33494 ++	    sna_blt_fill_boxes(sna, GXcopy, bo,
352.33495 ++			       front->drawable.bitsPerPixel,
352.33496 ++			       video->color_key,
352.33497 ++			       region_rects(clip),
352.33498 ++			       region_num_rects(clip))) {
352.33499 ++		RegionCopy(&video->clip, (RegionPtr)clip);
352.33500 ++		return;
352.33501 ++	}
352.33502 ++
352.33503 ++	dst = kgem_bo_map__gtt(&sna->kgem, bo);
352.33504 ++	if (dst == NULL)
352.33505 ++		return;
352.33506 ++
352.33507 ++	w = front->drawable.bitsPerPixel/8;
352.33508 ++	width = (clip->extents.x2 - clip->extents.x1) * w;
352.33509 ++	tmp = malloc(width);
352.33510 ++	if (tmp == NULL)
352.33511 ++		return;
352.33512 ++
352.33513 ++	memcpy(tmp, &video->color_key, w);
352.33514 ++	while (2 * w < width) {
352.33515 ++		memcpy(tmp + w, tmp, w);
352.33516 ++		w *= 2;
352.33517 ++	}
352.33518 ++	if (w < width)
352.33519 ++		memcpy(tmp + w, tmp, width - w);
352.33520 ++
352.33521 ++	if (sigtrap_get() == 0) {
352.33522 ++		const BoxRec *box = region_rects(clip);
352.33523 ++		int n = region_num_rects(clip);
352.33524 ++
352.33525 ++		w = front->drawable.bitsPerPixel/8;
352.33526 ++		do {
352.33527 ++			int y = box->y1;
352.33528 ++			uint8_t *row = dst + y*bo->pitch + w*box->x1;
352.33529 ++
352.33530 ++			width = (box->x2 - box->x1) * w;
352.33531 ++			while (y < box->y2) {
352.33532 ++				memcpy(row, tmp, width);
352.33533 ++				row += bo->pitch;
352.33534 ++				y++;
352.33535 ++			}
352.33536 ++			box++;
352.33537 ++		} while (--n);
352.33538 ++		sigtrap_put();
352.33539 ++
352.33540 ++		RegionCopy(&video->clip, (RegionPtr)clip);
352.33541 ++	}
352.33542 ++
352.33543 ++	free(tmp);
352.33544 ++}
352.33545 ++
352.33546 + XvAdaptorPtr sna_xv_adaptor_alloc(struct sna *sna)
352.33547 + {
352.33548 + 	XvAdaptorPtr new_adaptors;
352.33549 +diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h
352.33550 +index f21605fc..39cb725f 100644
352.33551 +--- a/src/sna/sna_video.h
352.33552 ++++ b/src/sna/sna_video.h
352.33553 +@@ -72,6 +72,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
352.33554 + struct sna_video {
352.33555 + 	struct sna *sna;
352.33556 + 
352.33557 ++	int idx; /* XXX expose struct plane instead? */
352.33558 ++
352.33559 + 	int brightness;
352.33560 + 	int contrast;
352.33561 + 	int saturation;
352.33562 +@@ -193,6 +195,9 @@ bool
352.33563 + sna_video_copy_data(struct sna_video *video,
352.33564 + 		    struct sna_video_frame *frame,
352.33565 + 		    const uint8_t *buf);
352.33566 ++void
352.33567 ++sna_video_fill_colorkey(struct sna_video *video,
352.33568 ++			const RegionRec *clip);
352.33569 + 
352.33570 + void sna_video_buffer_fini(struct sna_video *video);
352.33571 + 
352.33572 +@@ -210,4 +215,26 @@ sna_window_set_port(WindowPtr window, XvPortPtr port)
352.33573 + 	((void **)__get_private(window, sna_window_key))[2] = port;
352.33574 + }
352.33575 + 
352.33576 ++static inline int offset_and_clip(int x, int dx)
352.33577 ++{
352.33578 ++	x += dx;
352.33579 ++	if (x <= 0)
352.33580 ++		return 0;
352.33581 ++	if (x >= MAXSHORT)
352.33582 ++		return MAXSHORT;
352.33583 ++	return x;
352.33584 ++}
352.33585 ++
352.33586 ++static inline void init_video_region(RegionRec *region,
352.33587 ++				     DrawablePtr draw,
352.33588 ++				     int drw_x, int drw_y,
352.33589 ++				     int drw_w, int drw_h)
352.33590 ++{
352.33591 ++	region->extents.x1 = offset_and_clip(draw->x, drw_x);
352.33592 ++	region->extents.y1 = offset_and_clip(draw->y, drw_y);
352.33593 ++	region->extents.x2 = offset_and_clip(draw->x, drw_x + drw_w);
352.33594 ++	region->extents.y2 = offset_and_clip(draw->y, drw_y + drw_h);
352.33595 ++	region->data = NULL;
352.33596 ++}
352.33597 ++
352.33598 + #endif /* SNA_VIDEO_H */
352.33599 +diff --git a/src/sna/sna_video_overlay.c b/src/sna/sna_video_overlay.c
352.33600 +index ac81f1a0..9bc5ce40 100644
352.33601 +--- a/src/sna/sna_video_overlay.c
352.33602 ++++ b/src/sna/sna_video_overlay.c
352.33603 +@@ -130,7 +130,7 @@ static int sna_video_overlay_stop(ddStopVideo_ARGS)
352.33604 + 
352.33605 + 	DBG(("%s()\n", __FUNCTION__));
352.33606 + 
352.33607 +-	REGION_EMPTY(scrn->pScreen, &video->clip);
352.33608 ++	REGION_EMPTY(to_screen_from_sna(sna), &video->clip);
352.33609 + 
352.33610 + 	request.flags = 0;
352.33611 + 	(void)drmIoctl(sna->kgem.fd,
352.33612 +@@ -474,15 +474,13 @@ sna_video_overlay_put_image(ddPutImage_ARGS)
352.33613 + 	if (src_h >= (drw_h * 8))
352.33614 + 		drw_h = src_h / 7;
352.33615 + 
352.33616 +-	clip.extents.x1 = draw->x + drw_x;
352.33617 +-	clip.extents.y1 = draw->y + drw_y;
352.33618 +-	clip.extents.x2 = clip.extents.x1 + drw_w;
352.33619 +-	clip.extents.y2 = clip.extents.y1 + drw_h;
352.33620 +-	clip.data = NULL;
352.33621 ++	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
352.33622 + 
352.33623 + 	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
352.33624 +-	if (!video->AlwaysOnTop)
352.33625 ++	if (!video->AlwaysOnTop) {
352.33626 ++		ValidateGC(draw, gc);
352.33627 + 		RegionIntersect(&clip, &clip, gc->pCompositeClip);
352.33628 ++	}
352.33629 + 	if (box_empty(&clip.extents))
352.33630 + 		goto invisible;
352.33631 + 
352.33632 +@@ -551,15 +549,7 @@ sna_video_overlay_put_image(ddPutImage_ARGS)
352.33633 + 	ret = Success;
352.33634 + 	if (sna_video_overlay_show
352.33635 + 	    (sna, video, &frame, crtc, &dstBox, src_w, src_h, drw_w, drw_h)) {
352.33636 +-		//xf86XVFillKeyHelperDrawable(draw, video->color_key, &clip);
352.33637 +-		if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
352.33638 +-		    sna_blt_fill_boxes(sna, GXcopy,
352.33639 +-				       __sna_pixmap_get_bo(sna->front),
352.33640 +-				       sna->front->drawable.bitsPerPixel,
352.33641 +-				       video->color_key,
352.33642 +-				       region_rects(&clip),
352.33643 +-				       region_num_rects(&clip)))
352.33644 +-			RegionCopy(&video->clip, &clip);
352.33645 ++		sna_video_fill_colorkey(video, &clip);
352.33646 + 		sna_window_set_port((WindowPtr)draw, port);
352.33647 + 	} else {
352.33648 + 		DBG(("%s: failed to show video frame\n", __FUNCTION__));
352.33649 +diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
352.33650 +index 92230f97..69bfdfd2 100644
352.33651 +--- a/src/sna/sna_video_sprite.c
352.33652 ++++ b/src/sna/sna_video_sprite.c
352.33653 +@@ -47,6 +47,8 @@
352.33654 + #define DRM_FORMAT_YUYV         fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
352.33655 + #define DRM_FORMAT_UYVY         fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
352.33656 + 
352.33657 ++#define has_hw_scaling(sna) ((sna)->kgem.gen < 071)
352.33658 ++
352.33659 + #define LOCAL_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct local_mode_set_plane)
352.33660 + struct local_mode_set_plane {
352.33661 + 	uint32_t plane_id;
352.33662 +@@ -81,19 +83,17 @@ static int sna_video_sprite_stop(ddStopVideo_ARGS)
352.33663 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(video->sna->scrn);
352.33664 + 	int i;
352.33665 + 
352.33666 +-	for (i = 0; i < config->num_crtc; i++) {
352.33667 ++	for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
352.33668 + 		xf86CrtcPtr crtc = config->crtc[i];
352.33669 + 		int pipe;
352.33670 + 
352.33671 +-		if (sna_crtc_id(crtc) == 0)
352.33672 +-			break;
352.33673 +-
352.33674 +-		pipe = sna_crtc_to_pipe(crtc);
352.33675 ++		pipe = sna_crtc_pipe(crtc);
352.33676 ++		assert(pipe < ARRAY_SIZE(video->bo));
352.33677 + 		if (video->bo[pipe] == NULL)
352.33678 + 			continue;
352.33679 + 
352.33680 + 		memset(&s, 0, sizeof(s));
352.33681 +-		s.plane_id = sna_crtc_to_sprite(crtc);
352.33682 ++		s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
352.33683 + 		if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
352.33684 + 			xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
352.33685 + 				   "failed to disable plane\n");
352.33686 +@@ -153,7 +153,7 @@ static int sna_video_sprite_best_size(ddQueryBestSize_ARGS)
352.33687 + 	struct sna_video *video = port->devPriv.ptr;
352.33688 + 	struct sna *sna = video->sna;
352.33689 + 
352.33690 +-	if (sna->kgem.gen >= 075) {
352.33691 ++	if (!has_hw_scaling(sna) && !sna->render.video) {
352.33692 + 		*p_w = vid_w;
352.33693 + 		*p_h = vid_h;
352.33694 + 	} else {
352.33695 +@@ -221,12 +221,12 @@ sna_video_sprite_show(struct sna *sna,
352.33696 + 		      BoxPtr dstBox)
352.33697 + {
352.33698 + 	struct local_mode_set_plane s;
352.33699 +-	int pipe = sna_crtc_to_pipe(crtc);
352.33700 ++	int pipe = sna_crtc_pipe(crtc);
352.33701 + 
352.33702 + 	/* XXX handle video spanning multiple CRTC */
352.33703 + 
352.33704 + 	VG_CLEAR(s);
352.33705 +-	s.plane_id = sna_crtc_to_sprite(crtc);
352.33706 ++	s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
352.33707 + 
352.33708 + #define DRM_I915_SET_SPRITE_COLORKEY 0x2b
352.33709 + #define LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct local_intel_sprite_colorkey)
352.33710 +@@ -263,9 +263,6 @@ sna_video_sprite_show(struct sna *sna,
352.33711 + 		video->color_key_changed &= ~(1 << pipe);
352.33712 + 	}
352.33713 + 
352.33714 +-	if (video->bo[pipe] == frame->bo)
352.33715 +-		return true;
352.33716 +-
352.33717 + 	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
352.33718 + 	if (frame->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
352.33719 + 		int tmp = frame->width;
352.33720 +@@ -283,15 +280,30 @@ sna_video_sprite_show(struct sna *sna,
352.33721 + 			uint32_t handles[4];
352.33722 + 			uint32_t pitches[4]; /* pitch for each plane */
352.33723 + 			uint32_t offsets[4]; /* offset of each plane */
352.33724 ++			uint64_t modifiers[4];
352.33725 + 		} f;
352.33726 + 		bool purged = true;
352.33727 + 
352.33728 + 		memset(&f, 0, sizeof(f));
352.33729 + 		f.width = frame->width;
352.33730 + 		f.height = frame->height;
352.33731 ++		f.flags = 1 << 1; /* +modifiers */
352.33732 + 		f.handles[0] = frame->bo->handle;
352.33733 + 		f.pitches[0] = frame->pitch[0];
352.33734 + 
352.33735 ++		switch (frame->bo->tiling) {
352.33736 ++		case I915_TILING_NONE:
352.33737 ++			break;
352.33738 ++		case I915_TILING_X:
352.33739 ++			/* I915_FORMAT_MOD_X_TILED */
352.33740 ++			f.modifiers[0] = (uint64_t)1 << 56 | 1;
352.33741 ++			break;
352.33742 ++		case I915_TILING_Y:
352.33743 ++			/* I915_FORMAT_MOD_X_TILED */
352.33744 ++			f.modifiers[0] = (uint64_t)1 << 56 | 2;
352.33745 ++			break;
352.33746 ++		}
352.33747 ++
352.33748 + 		switch (frame->id) {
352.33749 + 		case FOURCC_RGB565:
352.33750 + 			f.pixel_format = DRM_FORMAT_RGB565;
352.33751 +@@ -360,7 +372,7 @@ sna_video_sprite_show(struct sna *sna,
352.33752 + 		return false;
352.33753 + 	}
352.33754 + 
352.33755 +-	frame->bo->domain = DOMAIN_NONE;
352.33756 ++	__kgem_bo_clear_dirty(frame->bo);
352.33757 + 
352.33758 + 	if (video->bo[pipe])
352.33759 + 		kgem_bo_destroy(&sna->kgem, video->bo[pipe]);
352.33760 +@@ -374,17 +386,17 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
352.33761 + 	struct sna *sna = video->sna;
352.33762 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.33763 + 	RegionRec clip;
352.33764 ++	BoxRec draw_extents;
352.33765 + 	int ret, i;
352.33766 + 
352.33767 +-	clip.extents.x1 = draw->x + drw_x;
352.33768 +-	clip.extents.y1 = draw->y + drw_y;
352.33769 +-	clip.extents.x2 = clip.extents.x1 + drw_w;
352.33770 +-	clip.extents.y2 = clip.extents.y1 + drw_h;
352.33771 +-	clip.data = NULL;
352.33772 ++	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
352.33773 ++	draw_extents = clip.extents;
352.33774 + 
352.33775 + 	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
352.33776 +-	if (!video->AlwaysOnTop)
352.33777 ++	if (!video->AlwaysOnTop) {
352.33778 ++		ValidateGC(draw, gc);
352.33779 + 		RegionIntersect(&clip, &clip, gc->pCompositeClip);
352.33780 ++	}
352.33781 + 
352.33782 + 	DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n",
352.33783 + 	     __FUNCTION__,
352.33784 +@@ -402,19 +414,17 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
352.33785 + 		goto err;
352.33786 + 	}
352.33787 + 
352.33788 +-	for (i = 0; i < config->num_crtc; i++) {
352.33789 ++	for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
352.33790 + 		xf86CrtcPtr crtc = config->crtc[i];
352.33791 + 		struct sna_video_frame frame;
352.33792 ++		BoxRec dst = draw_extents;
352.33793 + 		int pipe;
352.33794 + 		INT32 x1, x2, y1, y2;
352.33795 +-		BoxRec dst;
352.33796 + 		RegionRec reg;
352.33797 + 		Rotation rotation;
352.33798 ++		bool cache_bo;
352.33799 + 
352.33800 +-		if (sna_crtc_id(crtc) == 0)
352.33801 +-			break;
352.33802 +-
352.33803 +-		pipe = sna_crtc_to_pipe(crtc);
352.33804 ++		pipe = sna_crtc_pipe(crtc);
352.33805 + 
352.33806 + 		sna_video_frame_init(video, format->id, width, height, &frame);
352.33807 + 
352.33808 +@@ -423,10 +433,11 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
352.33809 + 		RegionIntersect(&reg, &reg, &clip);
352.33810 + 		if (RegionNil(&reg)) {
352.33811 + off:
352.33812 ++			assert(pipe < ARRAY_SIZE(video->bo));
352.33813 + 			if (video->bo[pipe]) {
352.33814 + 				struct local_mode_set_plane s;
352.33815 + 				memset(&s, 0, sizeof(s));
352.33816 +-				s.plane_id = sna_crtc_to_sprite(crtc);
352.33817 ++				s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
352.33818 + 				if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
352.33819 + 					xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
352.33820 + 						   "failed to disable plane\n");
352.33821 +@@ -440,8 +451,6 @@ off:
352.33822 + 		y1 = src_y;
352.33823 + 		y2 = src_y + src_h;
352.33824 + 
352.33825 +-		dst = clip.extents;
352.33826 +-
352.33827 + 		ret = xf86XVClipVideoHelper(&dst, &x1, &x2, &y1, &y2,
352.33828 + 					    &reg, frame.width, frame.height);
352.33829 + 		RegionUninit(&reg);
352.33830 +@@ -465,8 +474,8 @@ off:
352.33831 + 
352.33832 + 		/* if sprite can't handle rotation natively, store it for the copy func */
352.33833 + 		rotation = RR_Rotate_0;
352.33834 +-		if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) {
352.33835 +-			sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0);
352.33836 ++		if (!sna_crtc_set_sprite_rotation(crtc, video->idx, crtc->rotation)) {
352.33837 ++			sna_crtc_set_sprite_rotation(crtc, video->idx, RR_Rotate_0);
352.33838 + 			rotation = crtc->rotation;
352.33839 + 		}
352.33840 + 		sna_video_frame_set_rotation(video, &frame, rotation);
352.33841 +@@ -496,6 +505,8 @@ off:
352.33842 + 			frame.image.y1 = 0;
352.33843 + 			frame.image.x2 = frame.width;
352.33844 + 			frame.image.y2 = frame.height;
352.33845 ++
352.33846 ++			cache_bo = false;
352.33847 + 		} else {
352.33848 + 			frame.bo = sna_video_buffer(video, &frame);
352.33849 + 			if (frame.bo == NULL) {
352.33850 +@@ -509,6 +520,60 @@ off:
352.33851 + 				ret = BadAlloc;
352.33852 + 				goto err;
352.33853 + 			}
352.33854 ++
352.33855 ++			cache_bo = true;
352.33856 ++		}
352.33857 ++
352.33858 ++		if (!has_hw_scaling(sna) && sna->render.video &&
352.33859 ++		    !((frame.src.x2 - frame.src.x1) == (dst.x2 - dst.x1) &&
352.33860 ++		      (frame.src.y2 - frame.src.y1) == (dst.y2 - dst.y1))) {
352.33861 ++			ScreenPtr screen = to_screen_from_sna(sna);
352.33862 ++			PixmapPtr scaled;
352.33863 ++			RegionRec r;
352.33864 ++
352.33865 ++			r.extents.x1 = r.extents.y1 = 0;
352.33866 ++			r.extents.x2 = dst.x2 - dst.x1;
352.33867 ++			r.extents.y2 = dst.y2 - dst.y1;
352.33868 ++			r.data = NULL;
352.33869 ++
352.33870 ++			DBG(("%s: scaling from (%d, %d) to (%d, %d)\n",
352.33871 ++			     __FUNCTION__,
352.33872 ++			     frame.src.x2 - frame.src.x1,
352.33873 ++			     frame.src.y2 - frame.src.y1,
352.33874 ++			     r.extents.x2, r.extents.y2));
352.33875 ++
352.33876 ++			scaled = screen->CreatePixmap(screen,
352.33877 ++						      r.extents.x2,
352.33878 ++						      r.extents.y2,
352.33879 ++						      24,
352.33880 ++						      CREATE_PIXMAP_USAGE_SCRATCH);
352.33881 ++			if (scaled == NULL) {
352.33882 ++				ret = BadAlloc;
352.33883 ++				goto err;
352.33884 ++			}
352.33885 ++
352.33886 ++			if (!sna->render.video(sna, video, &frame, &r, scaled)) {
352.33887 ++				screen->DestroyPixmap(scaled);
352.33888 ++				ret = BadAlloc;
352.33889 ++				goto err;
352.33890 ++			}
352.33891 ++
352.33892 ++			if (cache_bo)
352.33893 ++				sna_video_buffer_fini(video);
352.33894 ++			else
352.33895 ++				kgem_bo_destroy(&sna->kgem, frame.bo);
352.33896 ++
352.33897 ++			frame.bo = kgem_bo_reference(__sna_pixmap_get_bo(scaled));
352.33898 ++			kgem_bo_submit(&sna->kgem, frame.bo);
352.33899 ++
352.33900 ++			frame.id = FOURCC_RGB888;
352.33901 ++			frame.src = frame.image = r.extents;
352.33902 ++			frame.width = frame.image.x2;
352.33903 ++			frame.height = frame.image.y2;
352.33904 ++			frame.pitch[0] = frame.bo->pitch;
352.33905 ++
352.33906 ++			screen->DestroyPixmap(scaled);
352.33907 ++			cache_bo = false;
352.33908 + 		}
352.33909 + 
352.33910 + 		ret = Success;
352.33911 +@@ -517,24 +582,16 @@ off:
352.33912 + 			ret = BadAlloc;
352.33913 + 		}
352.33914 + 
352.33915 +-		frame.bo->domain = DOMAIN_NONE;
352.33916 +-		if (xvmc_passthrough(format->id))
352.33917 +-			kgem_bo_destroy(&sna->kgem, frame.bo);
352.33918 +-		else
352.33919 ++		if (cache_bo)
352.33920 + 			sna_video_buffer_fini(video);
352.33921 ++		else
352.33922 ++			kgem_bo_destroy(&sna->kgem, frame.bo);
352.33923 + 
352.33924 + 		if (ret != Success)
352.33925 + 			goto err;
352.33926 + 	}
352.33927 + 
352.33928 +-	if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
352.33929 +-	    sna_blt_fill_boxes(sna, GXcopy,
352.33930 +-			       __sna_pixmap_get_bo(sna->front),
352.33931 +-			       sna->front->drawable.bitsPerPixel,
352.33932 +-			       video->color_key,
352.33933 +-			       region_rects(&clip),
352.33934 +-			       region_num_rects(&clip)))
352.33935 +-		RegionCopy(&video->clip, &clip);
352.33936 ++	sna_video_fill_colorkey(video, &clip);
352.33937 + 	sna_window_set_port((WindowPtr)draw, port);
352.33938 + 
352.33939 + 	return Success;
352.33940 +@@ -606,25 +663,28 @@ static int sna_video_sprite_color_key(struct sna *sna)
352.33941 + 	return color_key & ((1 << scrn->depth) - 1);
352.33942 + }
352.33943 + 
352.33944 +-static bool sna_video_has_sprites(struct sna *sna)
352.33945 ++static int sna_video_has_sprites(struct sna *sna)
352.33946 + {
352.33947 + 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
352.33948 ++	unsigned min;
352.33949 + 	int i;
352.33950 + 
352.33951 + 	DBG(("%s: num_crtc=%d\n", __FUNCTION__, sna->mode.num_real_crtc));
352.33952 + 
352.33953 + 	if (sna->mode.num_real_crtc == 0)
352.33954 +-		return false;
352.33955 ++		return 0;
352.33956 + 
352.33957 ++	min = -1;
352.33958 + 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
352.33959 +-		if (!sna_crtc_to_sprite(config->crtc[i])) {
352.33960 +-			DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(config->crtc[i])));
352.33961 +-			return false;
352.33962 +-		}
352.33963 ++		unsigned count =  sna_crtc_count_sprites(config->crtc[i]);
352.33964 ++		DBG(("%s: %d sprites found on pipe %d\n", __FUNCTION__,
352.33965 ++		     count, sna_crtc_pipe(config->crtc[i])));
352.33966 ++		if (count < min)
352.33967 ++			min = count;
352.33968 + 	}
352.33969 + 
352.33970 +-	DBG(("%s: yes\n", __FUNCTION__));
352.33971 +-	return true;
352.33972 ++	DBG(("%s: min=%d\n", __FUNCTION__, min));
352.33973 ++	return min;
352.33974 + }
352.33975 + 
352.33976 + void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
352.33977 +@@ -632,16 +692,18 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
352.33978 + 	XvAdaptorPtr adaptor;
352.33979 + 	struct sna_video *video;
352.33980 + 	XvPortPtr port;
352.33981 ++	int count, i;
352.33982 + 
352.33983 +-	if (!sna_video_has_sprites(sna))
352.33984 ++	count = sna_video_has_sprites(sna);
352.33985 ++	if (!count)
352.33986 + 		return;
352.33987 + 
352.33988 + 	adaptor = sna_xv_adaptor_alloc(sna);
352.33989 + 	if (!adaptor)
352.33990 + 		return;
352.33991 + 
352.33992 +-	video = calloc(1, sizeof(*video));
352.33993 +-	port = calloc(1, sizeof(*port));
352.33994 ++	video = calloc(count, sizeof(*video));
352.33995 ++	port = calloc(count, sizeof(*port));
352.33996 + 	if (video == NULL || port == NULL) {
352.33997 + 		free(video);
352.33998 + 		free(port);
352.33999 +@@ -686,36 +748,43 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
352.34000 + 	adaptor->ddPutImage = sna_video_sprite_put_image;
352.34001 + 	adaptor->ddQueryImageAttributes = sna_video_sprite_query;
352.34002 + 
352.34003 +-	adaptor->nPorts = 1;
352.34004 ++	adaptor->nPorts = count;
352.34005 + 	adaptor->pPorts = port;
352.34006 + 
352.34007 +-	adaptor->base_id = port->id = FakeClientID(0);
352.34008 +-	AddResource(port->id, XvGetRTPort(), port);
352.34009 +-	port->pAdaptor = adaptor;
352.34010 +-	port->pNotify =  NULL;
352.34011 +-	port->pDraw =  NULL;
352.34012 +-	port->client =  NULL;
352.34013 +-	port->grab.client =  NULL;
352.34014 +-	port->time = currentTime;
352.34015 +-	port->devPriv.ptr = video;
352.34016 +-
352.34017 +-	video->sna = sna;
352.34018 +-	video->alignment = 64;
352.34019 +-	video->color_key = sna_video_sprite_color_key(sna);
352.34020 +-	video->color_key_changed = ~0;
352.34021 +-	video->has_color_key = true;
352.34022 +-	video->brightness = -19;	/* (255/219) * -16 */
352.34023 +-	video->contrast = 75;	/* 255/219 * 64 */
352.34024 +-	video->saturation = 146;	/* 128/112 * 128 */
352.34025 +-	video->desired_crtc = NULL;
352.34026 +-	video->gamma5 = 0xc0c0c0;
352.34027 +-	video->gamma4 = 0x808080;
352.34028 +-	video->gamma3 = 0x404040;
352.34029 +-	video->gamma2 = 0x202020;
352.34030 +-	video->gamma1 = 0x101010;
352.34031 +-	video->gamma0 = 0x080808;
352.34032 +-	RegionNull(&video->clip);
352.34033 +-	video->SyncToVblank = 1;
352.34034 ++	for (i = 0; i < count; i++) {
352.34035 ++		port->id = FakeClientID(0);
352.34036 ++		AddResource(port->id, XvGetRTPort(), port);
352.34037 ++		port->pAdaptor = adaptor;
352.34038 ++		port->pNotify =  NULL;
352.34039 ++		port->pDraw =  NULL;
352.34040 ++		port->client =  NULL;
352.34041 ++		port->grab.client =  NULL;
352.34042 ++		port->time = currentTime;
352.34043 ++		port->devPriv.ptr = video;
352.34044 ++
352.34045 ++		video->sna = sna;
352.34046 ++		video->idx = i;
352.34047 ++		video->alignment = 64;
352.34048 ++		video->color_key = sna_video_sprite_color_key(sna);
352.34049 ++		video->color_key_changed = ~0;
352.34050 ++		video->has_color_key = true;
352.34051 ++		video->brightness = -19;	/* (255/219) * -16 */
352.34052 ++		video->contrast = 75;	/* 255/219 * 64 */
352.34053 ++		video->saturation = 146;	/* 128/112 * 128 */
352.34054 ++		video->desired_crtc = NULL;
352.34055 ++		video->gamma5 = 0xc0c0c0;
352.34056 ++		video->gamma4 = 0x808080;
352.34057 ++		video->gamma3 = 0x404040;
352.34058 ++		video->gamma2 = 0x202020;
352.34059 ++		video->gamma1 = 0x101010;
352.34060 ++		video->gamma0 = 0x080808;
352.34061 ++		RegionNull(&video->clip);
352.34062 ++		video->SyncToVblank = 1;
352.34063 ++
352.34064 ++		port++;
352.34065 ++		video++;
352.34066 ++	}
352.34067 ++	adaptor->base_id = adaptor->pPorts[0].id;
352.34068 + 
352.34069 + 	xvColorKey = MAKE_ATOM("XV_COLORKEY");
352.34070 + 	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");
352.34071 +diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
352.34072 +index 95011939..3cce5cf1 100644
352.34073 +--- a/src/sna/sna_video_textured.c
352.34074 ++++ b/src/sna/sna_video_textured.c
352.34075 +@@ -48,7 +48,12 @@ static const XvAttributeRec Attributes[] = {
352.34076 + 	//{XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"},
352.34077 + };
352.34078 + 
352.34079 +-static const XvImageRec Images[] = {
352.34080 ++static const XvImageRec gen2_Images[] = {
352.34081 ++	XVIMAGE_YUY2,
352.34082 ++	XVIMAGE_UYVY,
352.34083 ++};
352.34084 ++
352.34085 ++static const XvImageRec gen3_Images[] = {
352.34086 + 	XVIMAGE_YUY2,
352.34087 + 	XVIMAGE_YV12,
352.34088 + 	XVIMAGE_I420,
352.34089 +@@ -149,15 +154,16 @@ sna_video_textured_put_image(ddPutImage_ARGS)
352.34090 + 	BoxRec dstBox;
352.34091 + 	RegionRec clip;
352.34092 + 	xf86CrtcPtr crtc;
352.34093 ++	int16_t dx, dy;
352.34094 + 	bool flush = false;
352.34095 + 	bool ret;
352.34096 + 
352.34097 +-	clip.extents.x1 = draw->x + drw_x;
352.34098 +-	clip.extents.y1 = draw->y + drw_y;
352.34099 +-	clip.extents.x2 = clip.extents.x1 + drw_w;
352.34100 +-	clip.extents.y2 = clip.extents.y1 + drw_h;
352.34101 +-	clip.data = NULL;
352.34102 ++	if (wedged(sna))
352.34103 ++		return BadAlloc;
352.34104 + 
352.34105 ++	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
352.34106 ++
352.34107 ++	ValidateGC(draw, gc);
352.34108 + 	RegionIntersect(&clip, &clip, gc->pCompositeClip);
352.34109 + 	if (!RegionNotEmpty(&clip))
352.34110 + 		return Success;
352.34111 +@@ -181,6 +187,9 @@ sna_video_textured_put_image(ddPutImage_ARGS)
352.34112 + 				   &clip))
352.34113 + 		return Success;
352.34114 + 
352.34115 ++	if (get_drawable_deltas(draw, pixmap, &dx, &dy))
352.34116 ++		RegionTranslate(&clip, dx, dy);
352.34117 ++
352.34118 + 	flags = MOVE_WRITE | __MOVE_FORCE;
352.34119 + 	if (clip.data)
352.34120 + 		flags |= MOVE_READ;
352.34121 +@@ -234,7 +243,7 @@ sna_video_textured_put_image(ddPutImage_ARGS)
352.34122 + 		DBG(("%s: failed to render video\n", __FUNCTION__));
352.34123 + 		ret = BadAlloc;
352.34124 + 	} else
352.34125 +-		DamageDamageRegion(draw, &clip);
352.34126 ++		DamageDamageRegion(&pixmap->drawable, &clip);
352.34127 + 
352.34128 + 	kgem_bo_destroy(&sna->kgem, frame.bo);
352.34129 + 
352.34130 +@@ -316,7 +325,7 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
352.34131 + 
352.34132 + 	if (!sna->render.video) {
352.34133 + 		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
352.34134 +-			   "Textured video not supported on this hardware\n");
352.34135 ++			   "Textured video not supported on this hardware or backend\n");
352.34136 + 		return;
352.34137 + 	}
352.34138 + 
352.34139 +@@ -362,8 +371,13 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
352.34140 + 						 ARRAY_SIZE(Formats));
352.34141 + 	adaptor->nAttributes = ARRAY_SIZE(Attributes);
352.34142 + 	adaptor->pAttributes = (XvAttributeRec *)Attributes;
352.34143 +-	adaptor->nImages = ARRAY_SIZE(Images);
352.34144 +-	adaptor->pImages = (XvImageRec *)Images;
352.34145 ++	if (sna->kgem.gen < 030) {
352.34146 ++		adaptor->nImages = ARRAY_SIZE(gen2_Images);
352.34147 ++		adaptor->pImages = (XvImageRec *)gen2_Images;
352.34148 ++	} else {
352.34149 ++		adaptor->nImages = ARRAY_SIZE(gen3_Images);
352.34150 ++		adaptor->pImages = (XvImageRec *)gen3_Images;
352.34151 ++	}
352.34152 + #if XORG_XV_VERSION < 2
352.34153 + 	adaptor->ddAllocatePort = sna_xv_alloc_port;
352.34154 + 	adaptor->ddFreePort = sna_xv_free_port;
352.34155 +diff --git a/src/sna/xassert.h b/src/sna/xassert.h
352.34156 +index 1bcfd080..e648e4bc 100644
352.34157 +--- a/src/sna/xassert.h
352.34158 ++++ b/src/sna/xassert.h
352.34159 +@@ -43,6 +43,28 @@
352.34160 + 	xorg_backtrace(); \
352.34161 + 	FatalError("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
352.34162 + } while (0)
352.34163 ++
352.34164 ++#define warn_unless(E) \
352.34165 ++({ \
352.34166 ++	bool fail = !(E); \
352.34167 ++	if (unlikely(fail)) { \
352.34168 ++		static int __warn_once__; \
352.34169 ++		if (!__warn_once__) { \
352.34170 ++			xorg_backtrace(); \
352.34171 ++			ErrorF("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
352.34172 ++			__warn_once__ = 1; \
352.34173 ++		} \
352.34174 ++	} \
352.34175 ++	unlikely(fail); \
352.34176 ++})
352.34177 ++
352.34178 ++#define dbg(EXPR) EXPR
352.34179 ++
352.34180 ++#else
352.34181 ++
352.34182 ++#define warn_unless(E) ({ bool fail = !(E); unlikely(fail); })
352.34183 ++#define dbg(EXPR)
352.34184 ++
352.34185 + #endif
352.34186 + 
352.34187 + #endif /* __XASSERT_H__ */
352.34188 +diff --git a/src/uxa/i830_reg.h b/src/uxa/i830_reg.h
352.34189 +index d8306bcd..ba39d82c 100644
352.34190 +--- a/src/uxa/i830_reg.h
352.34191 ++++ b/src/uxa/i830_reg.h
352.34192 +@@ -65,6 +65,12 @@
352.34193 + #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA	(0)
352.34194 + #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB	(0x1<<20)
352.34195 + 
352.34196 ++#define MI_LOAD_REGISTER_IMM		(0x22<<23 | (3-2))
352.34197 ++
352.34198 ++#define BCS_SWCTRL                      0x22200
352.34199 ++# define BCS_SWCTRL_SRC_Y               (1 << 0)
352.34200 ++# define BCS_SWCTRL_DST_Y               (1 << 1)
352.34201 ++
352.34202 + /* BLT commands */
352.34203 + #define COLOR_BLT_CMD		((2<<29)|(0x40<<22)|(0x3))
352.34204 + #define COLOR_BLT_WRITE_ALPHA	(1<<21)
352.34205 +diff --git a/src/uxa/i965_video.c b/src/uxa/i965_video.c
352.34206 +index 68e6fd38..438ab909 100644
352.34207 +--- a/src/uxa/i965_video.c
352.34208 ++++ b/src/uxa/i965_video.c
352.34209 +@@ -37,7 +37,6 @@
352.34210 + #include "fourcc.h"
352.34211 + 
352.34212 + #include "intel.h"
352.34213 +-#include "intel_xvmc.h"
352.34214 + #include "intel_uxa.h"
352.34215 + #include "i830_reg.h"
352.34216 + #include "i965_reg.h"
352.34217 +diff --git a/src/uxa/intel.h b/src/uxa/intel.h
352.34218 +index 1b7e5339..a5e77af4 100644
352.34219 +--- a/src/uxa/intel.h
352.34220 ++++ b/src/uxa/intel.h
352.34221 +@@ -121,7 +121,6 @@ typedef struct intel_screen_private {
352.34222 + 
352.34223 + 	void *modes;
352.34224 + 	drm_intel_bo *front_buffer, *back_buffer;
352.34225 +-	unsigned int back_name;
352.34226 + 	long front_pitch, front_tiling;
352.34227 + 
352.34228 + 	dri_bufmgr *bufmgr;
352.34229 +@@ -169,6 +168,7 @@ typedef struct intel_screen_private {
352.34230 + 	const struct intel_device_info *info;
352.34231 + 
352.34232 + 	unsigned int BR[20];
352.34233 ++	unsigned int BR_tiling[2];
352.34234 + 
352.34235 + 	CloseScreenProcPtr CloseScreen;
352.34236 + 
352.34237 +@@ -196,7 +196,9 @@ typedef struct intel_screen_private {
352.34238 + 
352.34239 + 	int colorKey;
352.34240 + 	XF86VideoAdaptorPtr adaptor;
352.34241 ++#if !HAVE_NOTIFY_FD
352.34242 + 	ScreenBlockHandlerProcPtr BlockHandler;
352.34243 ++#endif
352.34244 + 	Bool overlayOn;
352.34245 + 
352.34246 + 	struct {
352.34247 +@@ -285,8 +287,6 @@ typedef struct intel_screen_private {
352.34248 + 	Bool has_kernel_flush;
352.34249 + 	Bool needs_flush;
352.34250 + 
352.34251 +-	struct _DRI2FrameEvent *pending_flip[MAX_PIPES];
352.34252 +-
352.34253 + 	/* Broken-out options. */
352.34254 + 	OptionInfoPtr Options;
352.34255 + 
352.34256 +@@ -368,6 +368,7 @@ typedef void (*intel_drm_abort_proc)(ScrnInfoPtr scrn,
352.34257 + 
352.34258 + extern uint32_t intel_drm_queue_alloc(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data, intel_drm_handler_proc handler, intel_drm_abort_proc abort);
352.34259 + extern void intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data);
352.34260 ++extern void intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq);
352.34261 + 
352.34262 + extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
352.34263 + extern int intel_crtc_id(xf86CrtcPtr crtc);
352.34264 +@@ -408,7 +409,6 @@ typedef struct _DRI2FrameEvent {
352.34265 + 	ClientPtr client;
352.34266 + 	enum DRI2FrameEventType type;
352.34267 + 	int frame;
352.34268 +-	int pipe;
352.34269 + 
352.34270 + 	struct list drawable_resource, client_resource;
352.34271 + 
352.34272 +@@ -418,7 +418,12 @@ typedef struct _DRI2FrameEvent {
352.34273 + 	DRI2BufferPtr front;
352.34274 + 	DRI2BufferPtr back;
352.34275 + 
352.34276 +-	struct _DRI2FrameEvent *chain;
352.34277 ++	/* current scanout for triple buffer */
352.34278 ++	int old_width;
352.34279 ++	int old_height;
352.34280 ++	int old_pitch;
352.34281 ++	int old_tiling;
352.34282 ++	dri_bo *old_buffer;
352.34283 + } DRI2FrameEventRec, *DRI2FrameEventPtr;
352.34284 + 
352.34285 + extern Bool intel_do_pageflip(intel_screen_private *intel,
352.34286 +@@ -456,10 +461,6 @@ extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
352.34287 + 
352.34288 + Bool I830DRI2ScreenInit(ScreenPtr pScreen);
352.34289 + void I830DRI2CloseScreen(ScreenPtr pScreen);
352.34290 +-void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
352.34291 +-			       unsigned int tv_usec, DRI2FrameEventPtr flip_info);
352.34292 +-void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
352.34293 +-			      unsigned int tv_usec, DRI2FrameEventPtr flip_info);
352.34294 + 
352.34295 + /* intel_dri3.c */
352.34296 + Bool intel_dri3_screen_init(ScreenPtr screen);
352.34297 +diff --git a/src/uxa/intel_batchbuffer.c b/src/uxa/intel_batchbuffer.c
352.34298 +index a29e4434..114c6026 100644
352.34299 +--- a/src/uxa/intel_batchbuffer.c
352.34300 ++++ b/src/uxa/intel_batchbuffer.c
352.34301 +@@ -245,6 +245,17 @@ void intel_batch_submit(ScrnInfoPtr scrn)
352.34302 + 	if (intel->batch_used == 0)
352.34303 + 		return;
352.34304 + 
352.34305 ++	if (intel->current_batch == I915_EXEC_BLT &&
352.34306 ++	    INTEL_INFO(intel)->gen >= 060) {
352.34307 ++		OUT_BATCH(MI_FLUSH_DW);
352.34308 ++		OUT_BATCH(0);
352.34309 ++		OUT_BATCH(0);
352.34310 ++		OUT_BATCH(0);
352.34311 ++		OUT_BATCH(MI_LOAD_REGISTER_IMM);
352.34312 ++		OUT_BATCH(BCS_SWCTRL);
352.34313 ++		OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16);
352.34314 ++	}
352.34315 ++
352.34316 + 	/* Mark the end of the batchbuffer. */
352.34317 + 	OUT_BATCH(MI_BATCH_BUFFER_END);
352.34318 + 	/* Emit a padding dword if we aren't going to be quad-word aligned. */
352.34319 +diff --git a/src/uxa/intel_batchbuffer.h b/src/uxa/intel_batchbuffer.h
352.34320 +index e5fb8d08..e71ffd19 100644
352.34321 +--- a/src/uxa/intel_batchbuffer.h
352.34322 ++++ b/src/uxa/intel_batchbuffer.h
352.34323 +@@ -30,7 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
352.34324 + #ifndef _INTEL_BATCHBUFFER_H
352.34325 + #define _INTEL_BATCHBUFFER_H
352.34326 + 
352.34327 +-#define BATCH_RESERVED		16
352.34328 ++#define BATCH_RESERVED		64
352.34329 + 
352.34330 + 
352.34331 + void intel_batch_init(ScrnInfoPtr scrn);
352.34332 +@@ -202,6 +202,23 @@ do {									\
352.34333 + 
352.34334 + #define BEGIN_BATCH(n)	__BEGIN_BATCH(n,RENDER_BATCH)
352.34335 + #define BEGIN_BATCH_BLT(n)	__BEGIN_BATCH(n,BLT_BATCH)
352.34336 ++#define BEGIN_BATCH_BLT_TILED(n) \
352.34337 ++do { \
352.34338 ++	if (INTEL_INFO(intel)->gen < 060) { \
352.34339 ++		__BEGIN_BATCH(n, BLT_BATCH); \
352.34340 ++	} else { \
352.34341 ++		__BEGIN_BATCH(n+7, BLT_BATCH); \
352.34342 ++		OUT_BATCH(MI_FLUSH_DW); \
352.34343 ++		OUT_BATCH(0); \
352.34344 ++		OUT_BATCH(0); \
352.34345 ++		OUT_BATCH(0); \
352.34346 ++		OUT_BATCH(MI_LOAD_REGISTER_IMM); \
352.34347 ++		OUT_BATCH(BCS_SWCTRL); \
352.34348 ++		OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16 | \
352.34349 ++			  ((intel->BR_tiling[0] == I915_TILING_Y) ? BCS_SWCTRL_DST_Y : 0) | \
352.34350 ++			  ((intel->BR_tiling[1] == I915_TILING_Y) ? BCS_SWCTRL_SRC_Y : 0)); \
352.34351 ++	} \
352.34352 ++} while (0)
352.34353 + 
352.34354 + #define ADVANCE_BATCH() do {						\
352.34355 + 	if (intel->batch_emitting == 0)					\
352.34356 +diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
352.34357 +index 7b4d4e0c..809cda1d 100644
352.34358 +--- a/src/uxa/intel_display.c
352.34359 ++++ b/src/uxa/intel_display.c
352.34360 +@@ -89,11 +89,11 @@ struct intel_mode {
352.34361 + 	struct list outputs;
352.34362 + 	struct list crtcs;
352.34363 + 
352.34364 +-	void *pageflip_data;
352.34365 +-	intel_pageflip_handler_proc pageflip_handler;
352.34366 +-	intel_pageflip_abort_proc pageflip_abort;
352.34367 +-
352.34368 +-	Bool delete_dp_12_displays;
352.34369 ++	struct {
352.34370 ++		intel_pageflip_handler_proc handler;
352.34371 ++		intel_pageflip_abort_proc abort;
352.34372 ++		void *data;
352.34373 ++	} pageflip;
352.34374 + };
352.34375 + 
352.34376 + struct intel_pageflip {
352.34377 +@@ -114,7 +114,6 @@ struct intel_crtc {
352.34378 + 	struct list link;
352.34379 + 	PixmapPtr scanout_pixmap;
352.34380 + 	uint32_t scanout_fb_id;
352.34381 +-	int32_t vblank_offset;
352.34382 + 	uint32_t msc_prev;
352.34383 + 	uint64_t msc_high;
352.34384 + };
352.34385 +@@ -193,7 +192,7 @@ intel_output_backlight_init(xf86OutputPtr output)
352.34386 + 
352.34387 + 	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
352.34388 + 	if (str != NULL) {
352.34389 +-		if (backlight_exists(str) != BL_NONE) {
352.34390 ++		if (backlight_exists(str)) {
352.34391 + 			intel_output->backlight_active_level =
352.34392 + 				backlight_open(&intel_output->backlight,
352.34393 + 					       strdup(str));
352.34394 +@@ -689,9 +688,11 @@ intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
352.34395 + 	}
352.34396 + 
352.34397 + 	bo = intel_get_pixmap_bo(ppix);
352.34398 +-	if (intel->front_buffer) {
352.34399 +-		ErrorF("have front buffer\n");
352.34400 +-	}
352.34401 ++	if (!bo)
352.34402 ++		return FALSE;
352.34403 ++
352.34404 ++	if (intel->front_buffer)
352.34405 ++		return FALSE;
352.34406 + 
352.34407 + 	drm_intel_bo_disable_reuse(bo);
352.34408 + 
352.34409 +@@ -867,6 +868,48 @@ intel_output_attach_edid(xf86OutputPtr output)
352.34410 + 	xf86OutputSetEDID(output, mon);
352.34411 + }
352.34412 + 
352.34413 ++static void
352.34414 ++intel_output_attach_tile(xf86OutputPtr output)
352.34415 ++{
352.34416 ++#if XF86_OUTPUT_VERSION >= 3
352.34417 ++	struct intel_output *intel_output = output->driver_private;
352.34418 ++	drmModeConnectorPtr koutput = intel_output->mode_output;
352.34419 ++	struct intel_mode *mode = intel_output->mode;
352.34420 ++	drmModePropertyBlobPtr blob = NULL;
352.34421 ++	struct xf86CrtcTileInfo tile_info, *set = NULL;
352.34422 ++	int i;
352.34423 ++
352.34424 ++	for (i = 0; koutput && i < koutput->count_props; i++) {
352.34425 ++		drmModePropertyPtr props;
352.34426 ++
352.34427 ++		props = drmModeGetProperty(mode->fd, koutput->props[i]);
352.34428 ++		if (!props)
352.34429 ++			continue;
352.34430 ++
352.34431 ++		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
352.34432 ++			drmModeFreeProperty(props);
352.34433 ++			continue;
352.34434 ++		}
352.34435 ++
352.34436 ++		if (!strcmp(props->name, "TILE")) {
352.34437 ++			blob = drmModeGetPropertyBlob(mode->fd,
352.34438 ++						      koutput->prop_values[i]);
352.34439 ++		}
352.34440 ++		drmModeFreeProperty(props);
352.34441 ++	}
352.34442 ++
352.34443 ++	if (blob) {
352.34444 ++		if (xf86OutputParseKMSTile(blob->data,
352.34445 ++					   blob->length,
352.34446 ++					   &tile_info))
352.34447 ++			set = &tile_info;
352.34448 ++		drmModeFreePropertyBlob(blob);
352.34449 ++	}
352.34450 ++
352.34451 ++	xf86OutputSetTile(output, set);
352.34452 ++#endif
352.34453 ++}
352.34454 ++
352.34455 + static DisplayModePtr
352.34456 + intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
352.34457 + {
352.34458 +@@ -922,6 +965,7 @@ intel_output_get_modes(xf86OutputPtr output)
352.34459 + 	int i;
352.34460 + 
352.34461 + 	intel_output_attach_edid(output);
352.34462 ++	intel_output_attach_tile(output);
352.34463 + 
352.34464 + 	if (!koutput)
352.34465 + 		return Modes;
352.34466 +@@ -1492,6 +1536,7 @@ intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_
352.34467 + 			intel_output = output->driver_private;
352.34468 + 			intel_output->output_id = mode_res->connectors[num];
352.34469 + 			intel_output->mode_output = koutput;
352.34470 ++			RROutputChanged(output->randr_output, TRUE);
352.34471 + 			return;
352.34472 + 		}
352.34473 + 	}
352.34474 +@@ -1650,9 +1695,6 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data);
352.34475 + static void
352.34476 + intel_pageflip_complete(struct intel_mode *mode);
352.34477 + 
352.34478 +-static void
352.34479 +-intel_drm_abort_seq (ScrnInfoPtr scrn, uint32_t seq);
352.34480 +-
352.34481 + Bool
352.34482 + intel_do_pageflip(intel_screen_private *intel,
352.34483 + 		  dri_bo *new_front,
352.34484 +@@ -1671,23 +1713,30 @@ intel_do_pageflip(intel_screen_private *intel,
352.34485 + 	uint32_t new_fb_id;
352.34486 + 	uint32_t flags;
352.34487 + 	uint32_t seq;
352.34488 ++	int err = 0;
352.34489 + 	int i;
352.34490 + 
352.34491 + 	/*
352.34492 ++	 * We only have a single length queue in the kernel, so any
352.34493 ++	 * attempts to schedule a second flip before processing the first
352.34494 ++	 * is a bug. Punt it back to the caller.
352.34495 ++	 */
352.34496 ++	if (mode->flip_count)
352.34497 ++		return FALSE;
352.34498 ++
352.34499 ++	/*
352.34500 + 	 * Create a new handle for the back buffer
352.34501 + 	 */
352.34502 + 	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
352.34503 + 			 scrn->depth, scrn->bitsPerPixel, pitch,
352.34504 +-			 new_front->handle, &new_fb_id))
352.34505 ++			 new_front->handle, &new_fb_id)) {
352.34506 ++		err = errno;
352.34507 + 		goto error_out;
352.34508 ++	}
352.34509 + 
352.34510 + 	drm_intel_bo_disable_reuse(new_front);
352.34511 +         intel_flush(intel);
352.34512 + 
352.34513 +-	mode->pageflip_data = pageflip_data;
352.34514 +-	mode->pageflip_handler = pageflip_handler;
352.34515 +-	mode->pageflip_abort = pageflip_abort;
352.34516 +-
352.34517 + 	/*
352.34518 + 	 * Queue flips on all enabled CRTCs
352.34519 + 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
352.34520 +@@ -1699,6 +1748,7 @@ intel_do_pageflip(intel_screen_private *intel,
352.34521 + 	 */
352.34522 + 	mode->fe_msc = 0;
352.34523 + 	mode->fe_usec = 0;
352.34524 ++	memset(&mode->pageflip, 0, sizeof(mode->pageflip));
352.34525 + 
352.34526 + 	flags = DRM_MODE_PAGE_FLIP_EVENT;
352.34527 + 	if (async)
352.34528 +@@ -1711,8 +1761,7 @@ intel_do_pageflip(intel_screen_private *intel,
352.34529 + 
352.34530 + 		flip = calloc(1, sizeof(struct intel_pageflip));
352.34531 + 		if (flip == NULL) {
352.34532 +-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
352.34533 +-				   "flip queue: carrier alloc failed.\n");
352.34534 ++			err = errno;
352.34535 + 			goto error_undo;
352.34536 + 		}
352.34537 + 
352.34538 +@@ -1724,33 +1773,30 @@ intel_do_pageflip(intel_screen_private *intel,
352.34539 + 
352.34540 + 		seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
352.34541 + 		if (!seq) {
352.34542 ++			err = errno;
352.34543 + 			free(flip);
352.34544 + 			goto error_undo;
352.34545 + 		}
352.34546 + 
352.34547 +-again:
352.34548 ++		mode->flip_count++;
352.34549 ++
352.34550 + 		if (drmModePageFlip(mode->fd,
352.34551 + 				    crtc_id(crtc),
352.34552 + 				    new_fb_id,
352.34553 + 				    flags, (void *)(uintptr_t)seq)) {
352.34554 +-			if (intel_mode_read_drm_events(intel)) {
352.34555 +-				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
352.34556 +-					   "flip queue retry\n");
352.34557 +-				goto again;
352.34558 +-			}
352.34559 +-			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
352.34560 +-				   "flip queue failed: %s\n", strerror(errno));
352.34561 +-			if (seq)
352.34562 +-				intel_drm_abort_seq(scrn, seq);
352.34563 +-			free(flip);
352.34564 ++			err = errno;
352.34565 ++			intel_drm_abort_seq(scrn, seq);
352.34566 + 			goto error_undo;
352.34567 + 		}
352.34568 +-		mode->flip_count++;
352.34569 + 	}
352.34570 + 
352.34571 + 	mode->old_fb_id = mode->fb_id;
352.34572 + 	mode->fb_id = new_fb_id;
352.34573 + 
352.34574 ++	mode->pageflip.data = pageflip_data;
352.34575 ++	mode->pageflip.handler = pageflip_handler;
352.34576 ++	mode->pageflip.abort = pageflip_abort;
352.34577 ++
352.34578 + 	if (!mode->flip_count)
352.34579 + 		intel_pageflip_complete(mode);
352.34580 + 
352.34581 +@@ -1765,7 +1811,7 @@ error_undo:
352.34582 + 
352.34583 + error_out:
352.34584 + 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
352.34585 +-		   strerror(errno));
352.34586 ++		   strerror(err));
352.34587 + 
352.34588 + 	mode->flip_count = 0;
352.34589 + 	return FALSE;
352.34590 +@@ -1839,7 +1885,7 @@ intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), v
352.34591 + /*
352.34592 +  * Abort by drm queue sequence number
352.34593 +  */
352.34594 +-static void
352.34595 ++void
352.34596 + intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
352.34597 + {
352.34598 + 	struct intel_drm_queue *q;
352.34599 +@@ -1911,7 +1957,6 @@ intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
352.34600 + {
352.34601 + 	struct intel_crtc *intel_crtc = crtc->driver_private;
352.34602 + 
352.34603 +-        sequence += intel_crtc->vblank_offset;
352.34604 +         if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000)
352.34605 +                 intel_crtc->msc_high += 0x100000000L;
352.34606 +         intel_crtc->msc_prev = sequence;
352.34607 +@@ -1935,37 +1980,10 @@ intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64
352.34608 +         return 0;
352.34609 + }
352.34610 + 
352.34611 +-/*
352.34612 +- * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number,
352.34613 +- * removing the high 32 bits and subtracting out the vblank_offset term.
352.34614 +- *
352.34615 +- * This also updates the vblank_offset when it notices that the value should
352.34616 +- * change.
352.34617 +- */
352.34618 +-
352.34619 +-#define MAX_VBLANK_OFFSET       1000
352.34620 +-
352.34621 + uint32_t
352.34622 + intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
352.34623 + {
352.34624 +-	struct intel_crtc *intel_crtc = crtc->driver_private;
352.34625 +-        uint64_t msc, ust;
352.34626 +-
352.34627 +-	if (intel_get_crtc_msc_ust(scrn, crtc, &msc, &ust) == 0) {
352.34628 +-		int64_t diff = expect - msc;
352.34629 +-
352.34630 +-		/* We're way off here, assume that the kernel has lost its mind
352.34631 +-		 * and smack the vblank back to something sensible
352.34632 +-		 */
352.34633 +-		if (diff < -MAX_VBLANK_OFFSET || diff > MAX_VBLANK_OFFSET) {
352.34634 +-			intel_crtc->vblank_offset += (int32_t) diff;
352.34635 +-			if (intel_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
352.34636 +-			    intel_crtc->vblank_offset < MAX_VBLANK_OFFSET)
352.34637 +-				intel_crtc->vblank_offset = 0;
352.34638 +-		}
352.34639 +-	}
352.34640 +-
352.34641 +-        return (uint32_t) (expect - intel_crtc->vblank_offset);
352.34642 ++        return (uint32_t)expect;
352.34643 + }
352.34644 + 
352.34645 + /*
352.34646 +@@ -1998,14 +2016,13 @@ intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *use
352.34647 + static void
352.34648 + intel_pageflip_complete(struct intel_mode *mode)
352.34649 + {
352.34650 +-	/* Release framebuffer */
352.34651 +-	drmModeRmFB(mode->fd, mode->old_fb_id);
352.34652 +-
352.34653 +-	if (!mode->pageflip_handler)
352.34654 ++	if (!mode->pageflip.handler)
352.34655 + 		return;
352.34656 + 
352.34657 +-	mode->pageflip_handler(mode->fe_msc, mode->fe_usec,
352.34658 +-			       mode->pageflip_data);
352.34659 ++	/* Release framebuffer */
352.34660 ++	drmModeRmFB(mode->fd, mode->old_fb_id);
352.34661 ++	mode->pageflip.handler(mode->fe_msc, mode->fe_usec,
352.34662 ++			       mode->pageflip.data);
352.34663 + }
352.34664 + 
352.34665 + /*
352.34666 +@@ -2045,6 +2062,7 @@ intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
352.34667 + 
352.34668 + 	if (!mode)
352.34669 + 		return;
352.34670 ++
352.34671 + 	intel_pageflip_complete(mode);
352.34672 + }
352.34673 + 
352.34674 +@@ -2060,18 +2078,18 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
352.34675 + 	if (!mode)
352.34676 + 		return;
352.34677 + 
352.34678 +-	/* Release framebuffer */
352.34679 +-	drmModeRmFB(mode->fd, mode->old_fb_id);
352.34680 +-
352.34681 +-	if (!mode->pageflip_abort)
352.34682 ++	if (!mode->pageflip.abort)
352.34683 + 		return;
352.34684 + 
352.34685 +-	mode->pageflip_abort(mode->pageflip_data);
352.34686 ++	/* Release framebuffer */
352.34687 ++	drmModeRmFB(mode->fd, mode->old_fb_id);
352.34688 ++	mode->pageflip.abort(mode->pageflip.data);
352.34689 + }
352.34690 + 
352.34691 + /*
352.34692 +  * Check for pending DRM events and process them.
352.34693 +  */
352.34694 ++#if !HAVE_NOTIFY_FD
352.34695 + static void
352.34696 + drm_wakeup_handler(pointer data, int err, pointer p)
352.34697 + {
352.34698 +@@ -2086,6 +2104,14 @@ drm_wakeup_handler(pointer data, int err, pointer p)
352.34699 + 	if (FD_ISSET(mode->fd, read_mask))
352.34700 + 		drmHandleEvent(mode->fd, &mode->event_context);
352.34701 + }
352.34702 ++#else
352.34703 ++static void
352.34704 ++drm_notify_fd(int fd, int ready, void *data)
352.34705 ++{
352.34706 ++	struct intel_mode *mode = data;
352.34707 ++	drmHandleEvent(mode->fd, &mode->event_context);
352.34708 ++}
352.34709 ++#endif
352.34710 + 
352.34711 + /*
352.34712 +  * If there are any available, read drm_events
352.34713 +@@ -2231,10 +2257,6 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
352.34714 + 		intel->use_pageflipping = TRUE;
352.34715 + 	}
352.34716 + 
352.34717 +-	if (xf86ReturnOptValBool(intel->Options, OPTION_DELETE_DP12, FALSE)) {
352.34718 +-		mode->delete_dp_12_displays = TRUE;
352.34719 +-	}
352.34720 +-
352.34721 + 	intel->modes = mode;
352.34722 + 	drmModeFreeResources(mode_res);
352.34723 + 	return TRUE;
352.34724 +@@ -2250,9 +2272,11 @@ intel_mode_init(struct intel_screen_private *intel)
352.34725 + 	 * registration within ScreenInit and not PreInit.
352.34726 + 	 */
352.34727 + 	mode->flip_count = 0;
352.34728 +-	AddGeneralSocket(mode->fd);
352.34729 ++	SetNotifyFd(mode->fd, drm_notify_fd, X_NOTIFY_READ, mode);
352.34730 ++#if !HAVE_NOTIFY_FD
352.34731 + 	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
352.34732 + 				       drm_wakeup_handler, mode);
352.34733 ++#endif
352.34734 + }
352.34735 + 
352.34736 + void
352.34737 +@@ -2276,9 +2300,11 @@ intel_mode_close(intel_screen_private *intel)
352.34738 + 
352.34739 +         intel_drm_abort_scrn(intel->scrn);
352.34740 + 
352.34741 ++#if !HAVE_NOTIFY_FD
352.34742 + 	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
352.34743 + 				     drm_wakeup_handler, mode);
352.34744 +-	RemoveGeneralSocket(mode->fd);
352.34745 ++#endif
352.34746 ++	RemoveNotifyFd(mode->fd);
352.34747 + }
352.34748 + 
352.34749 + void
352.34750 +@@ -2498,12 +2524,11 @@ intel_mode_hotplug(struct intel_screen_private *intel)
352.34751 + 	int i, j;
352.34752 + 	Bool found;
352.34753 + 	Bool changed = FALSE;
352.34754 +-	struct intel_mode *mode = intel->modes;
352.34755 ++
352.34756 + 	mode_res = drmModeGetResources(intel->drmSubFD);
352.34757 + 	if (!mode_res)
352.34758 + 		goto out;
352.34759 + 
352.34760 +-restart_destroy:
352.34761 + 	for (i = 0; i < config->num_output; i++) {
352.34762 + 		xf86OutputPtr output = config->output[i];
352.34763 + 		struct intel_output *intel_output;
352.34764 +@@ -2522,13 +2547,9 @@ restart_destroy:
352.34765 + 		drmModeFreeConnector(intel_output->mode_output);
352.34766 + 		intel_output->mode_output = NULL;
352.34767 + 		intel_output->output_id = -1;
352.34768 ++		RROutputChanged(output->randr_output, TRUE);
352.34769 + 
352.34770 + 		changed = TRUE;
352.34771 +-		if (mode->delete_dp_12_displays) {
352.34772 +-			RROutputDestroy(output->randr_output);
352.34773 +-			xf86OutputDestroy(output);
352.34774 +-			goto restart_destroy;
352.34775 +-		}
352.34776 + 	}
352.34777 + 
352.34778 + 	/* find new output ids we don't have outputs for */
352.34779 +@@ -2552,10 +2573,8 @@ restart_destroy:
352.34780 + 		intel_output_init(scrn, intel->modes, mode_res, i, 1);
352.34781 + 	}
352.34782 + 
352.34783 +-	if (changed) {
352.34784 +-		RRSetChanged(xf86ScrnToScreen(scrn));
352.34785 ++	if (changed)
352.34786 + 		RRTellChanged(xf86ScrnToScreen(scrn));
352.34787 +-	}
352.34788 + 
352.34789 + 	drmModeFreeResources(mode_res);
352.34790 + out:
352.34791 +diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
352.34792 +index f61c6210..524826d2 100644
352.34793 +--- a/src/uxa/intel_dri.c
352.34794 ++++ b/src/uxa/intel_dri.c
352.34795 +@@ -81,6 +81,47 @@ static DevPrivateKeyRec i830_client_key;
352.34796 + static int i830_client_key;
352.34797 + #endif
352.34798 + 
352.34799 ++static void I830DRI2FlipEventHandler(unsigned int frame,
352.34800 ++				     unsigned int tv_sec,
352.34801 ++				     unsigned int tv_usec,
352.34802 ++				     DRI2FrameEventPtr flip_info);
352.34803 ++
352.34804 ++static void I830DRI2FrameEventHandler(unsigned int frame,
352.34805 ++				      unsigned int tv_sec,
352.34806 ++				      unsigned int tv_usec,
352.34807 ++				      DRI2FrameEventPtr swap_info);
352.34808 ++
352.34809 ++static void
352.34810 ++i830_dri2_del_frame_event(DRI2FrameEventPtr info);
352.34811 ++
352.34812 ++static uint32_t pipe_select(int pipe)
352.34813 ++{
352.34814 ++	if (pipe > 1)
352.34815 ++		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
352.34816 ++	else if (pipe > 0)
352.34817 ++		return DRM_VBLANK_SECONDARY;
352.34818 ++	else
352.34819 ++		return 0;
352.34820 ++}
352.34821 ++
352.34822 ++static void
352.34823 ++intel_dri2_vblank_handler(ScrnInfoPtr scrn,
352.34824 ++                          xf86CrtcPtr crtc,
352.34825 ++                          uint64_t msc,
352.34826 ++                          uint64_t usec,
352.34827 ++                          void *data)
352.34828 ++{
352.34829 ++        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, data);
352.34830 ++}
352.34831 ++
352.34832 ++static void
352.34833 ++intel_dri2_vblank_abort(ScrnInfoPtr scrn,
352.34834 ++                        xf86CrtcPtr crtc,
352.34835 ++                        void *data)
352.34836 ++{
352.34837 ++        i830_dri2_del_frame_event(data);
352.34838 ++}
352.34839 ++
352.34840 + static uint32_t pixmap_flink(PixmapPtr pixmap)
352.34841 + {
352.34842 + 	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
352.34843 +@@ -135,9 +176,6 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
352.34844 + 		pixmap = NULL;
352.34845 + 		if (attachments[i] == DRI2BufferFrontLeft) {
352.34846 + 			pixmap = get_front_buffer(drawable);
352.34847 +-
352.34848 +-			if (pixmap == NULL)
352.34849 +-				drawable = &(get_drawable_pixmap(drawable)->drawable);
352.34850 + 		} else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) {
352.34851 + 			pixmap = pDepthPixmap;
352.34852 + 			pixmap->refcnt++;
352.34853 +@@ -246,11 +284,8 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
352.34854 + 	}
352.34855 + 
352.34856 + 	pixmap = NULL;
352.34857 +-	if (attachment == DRI2BufferFrontLeft) {
352.34858 ++	if (attachment == DRI2BufferFrontLeft)
352.34859 + 		pixmap = get_front_buffer(drawable);
352.34860 +-		if (pixmap == NULL)
352.34861 +-			drawable = &(get_drawable_pixmap(drawable)->drawable);
352.34862 +-	}
352.34863 + 
352.34864 + 	if (pixmap == NULL) {
352.34865 + 		unsigned int hint = INTEL_CREATE_PIXMAP_DRI2;
352.34866 +@@ -673,6 +708,20 @@ i830_dri2_del_frame_event(DRI2FrameEventPtr info)
352.34867 + 	if (info->back)
352.34868 + 		I830DRI2DestroyBuffer(NULL, info->back);
352.34869 + 
352.34870 ++	if (info->old_buffer) {
352.34871 ++		/* Check that the old buffer still matches the front buffer
352.34872 ++		 * in case a mode change occurred before we woke up.
352.34873 ++		 */
352.34874 ++		if (info->intel->back_buffer == NULL &&
352.34875 ++		    info->old_width  == info->intel->scrn->virtualX &&
352.34876 ++		    info->old_height == info->intel->scrn->virtualY &&
352.34877 ++		    info->old_pitch  == info->intel->front_pitch &&
352.34878 ++		    info->old_tiling == info->intel->front_tiling)
352.34879 ++			info->intel->back_buffer = info->old_buffer;
352.34880 ++		else
352.34881 ++			dri_bo_unreference(info->old_buffer);
352.34882 ++	}
352.34883 ++
352.34884 + 	free(info);
352.34885 + }
352.34886 + 
352.34887 +@@ -708,16 +757,14 @@ static void
352.34888 + I830DRI2ExchangeBuffers(struct intel_screen_private *intel, DRI2BufferPtr front, DRI2BufferPtr back)
352.34889 + {
352.34890 + 	I830DRI2BufferPrivatePtr front_priv, back_priv;
352.34891 +-	int tmp;
352.34892 + 	struct intel_uxa_pixmap *new_front;
352.34893 + 
352.34894 + 	front_priv = front->driverPrivate;
352.34895 + 	back_priv = back->driverPrivate;
352.34896 + 
352.34897 + 	/* Swap BO names so DRI works */
352.34898 +-	tmp = front->name;
352.34899 + 	front->name = back->name;
352.34900 +-	back->name = tmp;
352.34901 ++	back->name = pixmap_flink(front_priv->pixmap);
352.34902 + 
352.34903 + 	/* Swap pixmap bos */
352.34904 + 	new_front = intel_exchange_pixmap_buffers(intel,
352.34905 +@@ -753,87 +800,30 @@ I830DRI2FlipAbort(void *pageflip_data)
352.34906 +         i830_dri2_del_frame_event(info);
352.34907 + }
352.34908 + 
352.34909 +-/*
352.34910 +- * Our internal swap routine takes care of actually exchanging, blitting, or
352.34911 +- * flipping buffers as necessary.
352.34912 +- */
352.34913 + static Bool
352.34914 +-I830DRI2ScheduleFlip(struct intel_screen_private *intel,
352.34915 +-		     DrawablePtr draw,
352.34916 +-		     DRI2FrameEventPtr info)
352.34917 ++allocate_back_buffer(struct intel_screen_private *intel)
352.34918 + {
352.34919 +-	I830DRI2BufferPrivatePtr priv = info->back->driverPrivate;
352.34920 +-	drm_intel_bo *new_back, *old_back;
352.34921 +-	int tmp_name;
352.34922 +-
352.34923 +-	if (!intel->use_triple_buffer) {
352.34924 +-		info->type = DRI2_SWAP;
352.34925 +-		if (!intel_do_pageflip(intel,
352.34926 +-				       get_pixmap_bo(priv),
352.34927 +-				       info->pipe, FALSE, info,
352.34928 +-                                       I830DRI2FlipComplete,
352.34929 +-                                       I830DRI2FlipAbort))
352.34930 +-			return FALSE;
352.34931 +-
352.34932 +-		I830DRI2ExchangeBuffers(intel, info->front, info->back);
352.34933 +-		return TRUE;
352.34934 +-	}
352.34935 ++	drm_intel_bo *bo;
352.34936 ++	int pitch;
352.34937 ++	uint32_t tiling;
352.34938 + 
352.34939 +-	if (intel->pending_flip[info->pipe]) {
352.34940 +-		assert(intel->pending_flip[info->pipe]->chain == NULL);
352.34941 +-		intel->pending_flip[info->pipe]->chain = info;
352.34942 ++	if (intel->back_buffer)
352.34943 + 		return TRUE;
352.34944 +-	}
352.34945 + 
352.34946 +-	if (intel->back_buffer == NULL) {
352.34947 +-		new_back = drm_intel_bo_alloc(intel->bufmgr, "front buffer",
352.34948 +-					      intel->front_buffer->size, 0);
352.34949 +-		if (new_back == NULL)
352.34950 +-			return FALSE;
352.34951 +-
352.34952 +-		if (intel->front_tiling != I915_TILING_NONE) {
352.34953 +-			uint32_t tiling = intel->front_tiling;
352.34954 +-			drm_intel_bo_set_tiling(new_back, &tiling, intel->front_pitch);
352.34955 +-			if (tiling != intel->front_tiling) {
352.34956 +-				drm_intel_bo_unreference(new_back);
352.34957 +-				return FALSE;
352.34958 +-			}
352.34959 +-		}
352.34960 +-
352.34961 +-		drm_intel_bo_disable_reuse(new_back);
352.34962 +-		dri_bo_flink(new_back, &intel->back_name);
352.34963 +-	} else {
352.34964 +-		new_back = intel->back_buffer;
352.34965 +-		intel->back_buffer = NULL;
352.34966 +-	}
352.34967 ++	bo = intel_allocate_framebuffer(intel->scrn,
352.34968 ++					intel->scrn->virtualX,
352.34969 ++					intel->scrn->virtualY,
352.34970 ++					intel->cpp,
352.34971 ++					&pitch, &tiling);
352.34972 ++	if (bo == NULL)
352.34973 ++		return FALSE;
352.34974 + 
352.34975 +-	old_back = get_pixmap_bo(priv);
352.34976 +-	if (!intel_do_pageflip(intel, old_back, info->pipe, FALSE, info, I830DRI2FlipComplete, I830DRI2FlipAbort)) {
352.34977 +-		intel->back_buffer = new_back;
352.34978 ++	if (pitch != intel->front_pitch || tiling != intel->front_tiling) {
352.34979 ++		drm_intel_bo_unreference(bo);
352.34980 + 		return FALSE;
352.34981 + 	}
352.34982 +-	info->type = DRI2_SWAP_CHAIN;
352.34983 +-	intel->pending_flip[info->pipe] = info;
352.34984 +-
352.34985 +-	priv = info->front->driverPrivate;
352.34986 +-
352.34987 +-	/* Exchange the current front-buffer with the fresh bo */
352.34988 +-
352.34989 +-	intel->back_buffer = intel->front_buffer;
352.34990 +-	drm_intel_bo_reference(intel->back_buffer);
352.34991 +-	intel_set_pixmap_bo(priv->pixmap, new_back);
352.34992 +-	drm_intel_bo_unreference(new_back);
352.34993 +-
352.34994 +-	tmp_name = info->front->name;
352.34995 +-	info->front->name = intel->back_name;
352.34996 +-	intel->back_name = tmp_name;
352.34997 + 
352.34998 +-	/* Then flip DRI2 pointers and update the screen pixmap */
352.34999 +-	I830DRI2ExchangeBuffers(intel, info->front, info->back);
352.35000 +-	DRI2SwapComplete(info->client, draw, 0, 0, 0,
352.35001 +-			 DRI2_EXCHANGE_COMPLETE,
352.35002 +-			 info->event_complete,
352.35003 +-			 info->event_data);
352.35004 ++	intel->back_buffer = bo;
352.35005 + 	return TRUE;
352.35006 + }
352.35007 + 
352.35008 +@@ -889,8 +879,88 @@ can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
352.35009 + 	return TRUE;
352.35010 + }
352.35011 + 
352.35012 +-void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
352.35013 +-			       unsigned int tv_usec, DRI2FrameEventPtr swap_info)
352.35014 ++static Bool
352.35015 ++queue_flip(struct intel_screen_private *intel,
352.35016 ++	   DrawablePtr draw,
352.35017 ++	   DRI2FrameEventPtr info)
352.35018 ++{
352.35019 ++	xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
352.35020 ++	I830DRI2BufferPrivatePtr priv = info->back->driverPrivate;
352.35021 ++	drm_intel_bo *old_back = get_pixmap_bo(priv);
352.35022 ++
352.35023 ++	if (crtc == NULL)
352.35024 ++		return FALSE;
352.35025 ++
352.35026 ++	if (!can_exchange(draw, info->front, info->back))
352.35027 ++		return FALSE;
352.35028 ++
352.35029 ++	if (!intel_do_pageflip(intel, old_back,
352.35030 ++			       intel_crtc_to_pipe(crtc),
352.35031 ++			       FALSE, info,
352.35032 ++			       I830DRI2FlipComplete, I830DRI2FlipAbort))
352.35033 ++		return FALSE;
352.35034 ++
352.35035 ++#if DRI2INFOREC_VERSION >= 6
352.35036 ++	if (intel->use_triple_buffer && allocate_back_buffer(intel)) {
352.35037 ++		info->old_width  = intel->scrn->virtualX;
352.35038 ++		info->old_height = intel->scrn->virtualY;
352.35039 ++		info->old_pitch  = intel->front_pitch;
352.35040 ++		info->old_tiling = intel->front_tiling;
352.35041 ++		info->old_buffer = intel->front_buffer;
352.35042 ++		dri_bo_reference(info->old_buffer);
352.35043 ++
352.35044 ++		priv = info->front->driverPrivate;
352.35045 ++		intel_set_pixmap_bo(priv->pixmap, intel->back_buffer);
352.35046 ++
352.35047 ++		dri_bo_unreference(intel->back_buffer);
352.35048 ++		intel->back_buffer = NULL;
352.35049 ++
352.35050 ++		DRI2SwapLimit(draw, 2);
352.35051 ++	} else
352.35052 ++		DRI2SwapLimit(draw, 1);
352.35053 ++#endif
352.35054 ++
352.35055 ++	/* Then flip DRI2 pointers and update the screen pixmap */
352.35056 ++	I830DRI2ExchangeBuffers(intel, info->front, info->back);
352.35057 ++	return TRUE;
352.35058 ++}
352.35059 ++
352.35060 ++static Bool
352.35061 ++queue_swap(struct intel_screen_private *intel,
352.35062 ++	   DrawablePtr draw,
352.35063 ++	   DRI2FrameEventPtr info)
352.35064 ++{
352.35065 ++	xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
352.35066 ++	drmVBlank vbl;
352.35067 ++
352.35068 ++	if (crtc == NULL)
352.35069 ++		return FALSE;
352.35070 ++
352.35071 ++	vbl.request.type =
352.35072 ++		DRM_VBLANK_RELATIVE |
352.35073 ++		DRM_VBLANK_EVENT |
352.35074 ++		pipe_select(intel_crtc_to_pipe(crtc));
352.35075 ++	vbl.request.sequence = 1;
352.35076 ++	vbl.request.signal =
352.35077 ++		intel_drm_queue_alloc(intel->scrn, crtc, info,
352.35078 ++				      intel_dri2_vblank_handler,
352.35079 ++				      intel_dri2_vblank_abort);
352.35080 ++	if (vbl.request.signal == 0)
352.35081 ++		return FALSE;
352.35082 ++
352.35083 ++	info->type = DRI2_SWAP;
352.35084 ++	if (drmWaitVBlank(intel->drmSubFD, &vbl)) {
352.35085 ++		intel_drm_abort_seq(intel->scrn, vbl.request.signal);
352.35086 ++		return FALSE;
352.35087 ++	}
352.35088 ++
352.35089 ++	return TRUE;
352.35090 ++}
352.35091 ++
352.35092 ++static void I830DRI2FrameEventHandler(unsigned int frame,
352.35093 ++				      unsigned int tv_sec,
352.35094 ++				      unsigned int tv_usec,
352.35095 ++				      DRI2FrameEventPtr swap_info)
352.35096 + {
352.35097 + 	intel_screen_private *intel = swap_info->intel;
352.35098 + 	DrawablePtr drawable;
352.35099 +@@ -906,24 +976,22 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
352.35100 + 		return;
352.35101 + 	}
352.35102 + 
352.35103 +-
352.35104 + 	switch (swap_info->type) {
352.35105 + 	case DRI2_FLIP:
352.35106 + 		/* If we can still flip... */
352.35107 +-		if (can_exchange(drawable, swap_info->front, swap_info->back) &&
352.35108 +-		    I830DRI2ScheduleFlip(intel, drawable, swap_info))
352.35109 +-			return;
352.35110 +-
352.35111 +-		/* else fall through to exchange/blit */
352.35112 +-	case DRI2_SWAP: {
352.35113 +-		I830DRI2FallbackBlitSwap(drawable,
352.35114 +-					 swap_info->front, swap_info->back);
352.35115 +-		DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
352.35116 +-				 DRI2_BLIT_COMPLETE,
352.35117 +-				 swap_info->client ? swap_info->event_complete : NULL,
352.35118 +-				 swap_info->event_data);
352.35119 +-		break;
352.35120 +-	}
352.35121 ++		if (!queue_flip(intel, drawable, swap_info) &&
352.35122 ++		    !queue_swap(intel, drawable, swap_info)) {
352.35123 ++		case DRI2_SWAP:
352.35124 ++			I830DRI2FallbackBlitSwap(drawable,
352.35125 ++						 swap_info->front, swap_info->back);
352.35126 ++			DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
352.35127 ++					 DRI2_BLIT_COMPLETE,
352.35128 ++					 swap_info->client ? swap_info->event_complete : NULL,
352.35129 ++					 swap_info->event_data);
352.35130 ++			break;
352.35131 ++		}
352.35132 ++		return;
352.35133 ++
352.35134 + 	case DRI2_WAITMSC:
352.35135 + 		if (swap_info->client)
352.35136 + 			DRI2WaitMSCComplete(swap_info->client, drawable,
352.35137 +@@ -939,12 +1007,13 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
352.35138 + 	i830_dri2_del_frame_event(swap_info);
352.35139 + }
352.35140 + 
352.35141 +-void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
352.35142 +-			      unsigned int tv_usec, DRI2FrameEventPtr flip_info)
352.35143 ++static void I830DRI2FlipEventHandler(unsigned int frame,
352.35144 ++				     unsigned int tv_sec,
352.35145 ++				     unsigned int tv_usec,
352.35146 ++				     DRI2FrameEventPtr flip_info)
352.35147 + {
352.35148 + 	struct intel_screen_private *intel = flip_info->intel;
352.35149 + 	DrawablePtr drawable;
352.35150 +-	DRI2FrameEventPtr chain;
352.35151 + 
352.35152 + 	drawable = NULL;
352.35153 + 	if (flip_info->drawable_id)
352.35154 +@@ -954,6 +1023,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
352.35155 + 
352.35156 + 	/* We assume our flips arrive in order, so we don't check the frame */
352.35157 + 	switch (flip_info->type) {
352.35158 ++	case DRI2_FLIP:
352.35159 + 	case DRI2_SWAP:
352.35160 + 		if (!drawable)
352.35161 + 			break;
352.35162 +@@ -984,35 +1054,6 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
352.35163 + 				 flip_info->event_data);
352.35164 + 		break;
352.35165 + 
352.35166 +-	case DRI2_SWAP_CHAIN:
352.35167 +-		assert(intel->pending_flip[flip_info->pipe] == flip_info);
352.35168 +-		intel->pending_flip[flip_info->pipe] = NULL;
352.35169 +-
352.35170 +-		chain = flip_info->chain;
352.35171 +-		if (chain) {
352.35172 +-			DrawablePtr chain_drawable = NULL;
352.35173 +-			if (chain->drawable_id)
352.35174 +-				 dixLookupDrawable(&chain_drawable,
352.35175 +-						   chain->drawable_id,
352.35176 +-						   serverClient,
352.35177 +-						   M_ANY, DixWriteAccess);
352.35178 +-			if (chain_drawable == NULL) {
352.35179 +-				i830_dri2_del_frame_event(chain);
352.35180 +-			} else if (!can_exchange(chain_drawable, chain->front, chain->back) ||
352.35181 +-				   !I830DRI2ScheduleFlip(intel, chain_drawable, chain)) {
352.35182 +-				I830DRI2FallbackBlitSwap(chain_drawable,
352.35183 +-							 chain->front,
352.35184 +-							 chain->back);
352.35185 +-
352.35186 +-				DRI2SwapComplete(chain->client, chain_drawable, frame, tv_sec, tv_usec,
352.35187 +-						 DRI2_BLIT_COMPLETE,
352.35188 +-						 chain->client ? chain->event_complete : NULL,
352.35189 +-						 chain->event_data);
352.35190 +-				i830_dri2_del_frame_event(chain);
352.35191 +-			}
352.35192 +-		}
352.35193 +-		break;
352.35194 +-
352.35195 + 	default:
352.35196 + 		xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
352.35197 + 			   "%s: unknown vblank event received\n", __func__);
352.35198 +@@ -1023,38 +1064,6 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
352.35199 + 	i830_dri2_del_frame_event(flip_info);
352.35200 + }
352.35201 + 
352.35202 +-static uint32_t pipe_select(int pipe)
352.35203 +-{
352.35204 +-	if (pipe > 1)
352.35205 +-		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
352.35206 +-	else if (pipe > 0)
352.35207 +-		return DRM_VBLANK_SECONDARY;
352.35208 +-	else
352.35209 +-		return 0;
352.35210 +-}
352.35211 +-
352.35212 +-static void
352.35213 +-intel_dri2_vblank_handler(ScrnInfoPtr scrn,
352.35214 +-                          xf86CrtcPtr crtc,
352.35215 +-                          uint64_t msc,
352.35216 +-                          uint64_t usec,
352.35217 +-                          void *data)
352.35218 +-{
352.35219 +-        DRI2FrameEventPtr swap_info = data;
352.35220 +-
352.35221 +-        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, swap_info);
352.35222 +-}
352.35223 +-
352.35224 +-static void
352.35225 +-intel_dri2_vblank_abort(ScrnInfoPtr scrn,
352.35226 +-                        xf86CrtcPtr crtc,
352.35227 +-                        void *data)
352.35228 +-{
352.35229 +-        DRI2FrameEventPtr swap_info = data;
352.35230 +-
352.35231 +-        i830_dri2_del_frame_event(swap_info);
352.35232 +-}
352.35233 +-
352.35234 + /*
352.35235 +  * ScheduleSwap is responsible for requesting a DRM vblank event for the
352.35236 +  * appropriate frame.
352.35237 +@@ -1089,7 +1098,6 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35238 +         int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1;
352.35239 +         int flip = 0;
352.35240 + 	DRI2FrameEventPtr swap_info = NULL;
352.35241 +-	enum DRI2FrameEventType swap_type = DRI2_SWAP;
352.35242 + 	uint64_t current_msc, current_ust;
352.35243 +         uint64_t request_msc;
352.35244 +         uint32_t seq;
352.35245 +@@ -1109,7 +1117,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35246 + 	swap_info->event_data = data;
352.35247 + 	swap_info->front = front;
352.35248 + 	swap_info->back = back;
352.35249 +-	swap_info->pipe = pipe;
352.35250 ++	swap_info->type = DRI2_SWAP;
352.35251 + 
352.35252 + 	if (!i830_dri2_add_frame_event(swap_info)) {
352.35253 + 	    free(swap_info);
352.35254 +@@ -1124,20 +1132,27 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35255 + 	if (ret)
352.35256 + 	    goto blit_fallback;
352.35257 + 
352.35258 +-	/* Flips need to be submitted one frame before */
352.35259 ++	/*
352.35260 ++	 * If we can, schedule the flip directly from here rather
352.35261 ++	 * than waiting for an event from the kernel for the current
352.35262 ++	 * (or a past) MSC.
352.35263 ++	 */
352.35264 ++	if (divisor == 0 &&
352.35265 ++	    current_msc >= *target_msc &&
352.35266 ++	    queue_flip(intel, draw, swap_info))
352.35267 ++		return TRUE;
352.35268 ++
352.35269 + 	if (can_exchange(draw, front, back)) {
352.35270 +-	    swap_type = DRI2_FLIP;
352.35271 +-	    flip = 1;
352.35272 ++		swap_info->type = DRI2_FLIP;
352.35273 ++		/* Flips need to be submitted one frame before */
352.35274 ++		if (*target_msc > 0)
352.35275 ++			--*target_msc;
352.35276 ++		flip = 1;
352.35277 + 	}
352.35278 + 
352.35279 +-	swap_info->type = swap_type;
352.35280 +-
352.35281 +-	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
352.35282 +-	 * Do it early, so handling of different timing constraints
352.35283 +-	 * for divisor, remainder and msc vs. target_msc works.
352.35284 +-	 */
352.35285 +-	if (*target_msc > 0)
352.35286 +-		*target_msc -= flip;
352.35287 ++#if DRI2INFOREC_VERSION >= 6
352.35288 ++	DRI2SwapLimit(draw, 1);
352.35289 ++#endif
352.35290 + 
352.35291 + 	/*
352.35292 + 	 * If divisor is zero, or current_msc is smaller than target_msc
352.35293 +@@ -1145,15 +1160,6 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35294 + 	 * the swap.
352.35295 + 	 */
352.35296 + 	if (divisor == 0 || current_msc < *target_msc) {
352.35297 +-		/*
352.35298 +-		 * If we can, schedule the flip directly from here rather
352.35299 +-		 * than waiting for an event from the kernel for the current
352.35300 +-		 * (or a past) MSC.
352.35301 +-		 */
352.35302 +-		if (flip && divisor == 0 && current_msc >= *target_msc &&
352.35303 +-		    I830DRI2ScheduleFlip(intel, draw, swap_info))
352.35304 +-			return TRUE;
352.35305 +-
352.35306 + 		vbl.request.type =
352.35307 + 			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
352.35308 + 
352.35309 +@@ -1168,7 +1174,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35310 + 		 * current_msc to ensure we return a reasonable value back
352.35311 + 		 * to the caller. This makes swap_interval logic more robust.
352.35312 + 		 */
352.35313 +-		if (current_msc >= *target_msc)
352.35314 ++		if (current_msc > *target_msc)
352.35315 + 			*target_msc = current_msc;
352.35316 + 
352.35317 +                 seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
352.35318 +@@ -1183,6 +1189,8 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
352.35319 + 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
352.35320 + 				   "divisor 0 get vblank counter failed: %s\n",
352.35321 + 				   strerror(errno));
352.35322 ++			intel_drm_abort_seq(intel->scrn, seq);
352.35323 ++			swap_info = NULL;
352.35324 + 			goto blit_fallback;
352.35325 + 		}
352.35326 + 
352.35327 +@@ -1332,7 +1340,6 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
352.35328 + 
352.35329 + 	if (!i830_dri2_add_frame_event(wait_info)) {
352.35330 + 	    free(wait_info);
352.35331 +-	    wait_info = NULL;
352.35332 + 	    goto out_complete;
352.35333 + 	}
352.35334 + 
352.35335 +@@ -1374,7 +1381,8 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
352.35336 + 					   strerror(errno));
352.35337 + 				limit--;
352.35338 + 			}
352.35339 +-			goto out_free;
352.35340 ++			intel_drm_abort_seq(intel->scrn, seq);
352.35341 ++			goto out_complete;
352.35342 + 		}
352.35343 + 
352.35344 + 		wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
352.35345 +@@ -1417,7 +1425,8 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
352.35346 + 				   strerror(errno));
352.35347 + 			limit--;
352.35348 + 		}
352.35349 +-		goto out_free;
352.35350 ++		intel_drm_abort_seq(intel->scrn, seq);
352.35351 ++		goto out_complete;
352.35352 + 	}
352.35353 + 
352.35354 + 	wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
352.35355 +@@ -1440,13 +1449,92 @@ static int has_i830_dri(void)
352.35356 + 	return access(DRI_DRIVER_PATH "/i830_dri.so", R_OK) == 0;
352.35357 + }
352.35358 + 
352.35359 +-static const char *dri_driver_name(intel_screen_private *intel)
352.35360 ++static int
352.35361 ++namecmp(const char *s1, const char *s2)
352.35362 ++{
352.35363 ++	char c1, c2;
352.35364 ++
352.35365 ++	if (!s1 || *s1 == 0) {
352.35366 ++		if (!s2 || *s2 == 0)
352.35367 ++			return 0;
352.35368 ++		else
352.35369 ++			return 1;
352.35370 ++	}
352.35371 ++
352.35372 ++	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.35373 ++		s1++;
352.35374 ++
352.35375 ++	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.35376 ++		s2++;
352.35377 ++
352.35378 ++	c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.35379 ++	c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.35380 ++	while (c1 == c2) {
352.35381 ++		if (c1 == '\0')
352.35382 ++			return 0;
352.35383 ++
352.35384 ++		s1++;
352.35385 ++		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
352.35386 ++			s1++;
352.35387 ++
352.35388 ++		s2++;
352.35389 ++		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
352.35390 ++			s2++;
352.35391 ++
352.35392 ++		c1 = isupper(*s1) ? tolower(*s1) : *s1;
352.35393 ++		c2 = isupper(*s2) ? tolower(*s2) : *s2;
352.35394 ++	}
352.35395 ++
352.35396 ++	return c1 - c2;
352.35397 ++}
352.35398 ++
352.35399 ++static Bool is_level(const char **str)
352.35400 ++{
352.35401 ++	const char *s = *str;
352.35402 ++	char *end;
352.35403 ++	unsigned val;
352.35404 ++
352.35405 ++	if (s == NULL || *s == '\0')
352.35406 ++		return TRUE;
352.35407 ++
352.35408 ++	if (namecmp(s, "on") == 0)
352.35409 ++		return TRUE;
352.35410 ++	if (namecmp(s, "true") == 0)
352.35411 ++		return TRUE;
352.35412 ++	if (namecmp(s, "yes") == 0)
352.35413 ++		return TRUE;
352.35414 ++
352.35415 ++	if (namecmp(s, "0") == 0)
352.35416 ++		return TRUE;
352.35417 ++	if (namecmp(s, "off") == 0)
352.35418 ++		return TRUE;
352.35419 ++	if (namecmp(s, "false") == 0)
352.35420 ++		return TRUE;
352.35421 ++	if (namecmp(s, "no") == 0)
352.35422 ++		return TRUE;
352.35423 ++
352.35424 ++	val = strtoul(s, &end, 0);
352.35425 ++	if (val && *end == '\0')
352.35426 ++		return TRUE;
352.35427 ++	if (val && *end == ':')
352.35428 ++		*str = end + 1;
352.35429 ++	return FALSE;
352.35430 ++}
352.35431 ++
352.35432 ++static const char *options_get_dri(intel_screen_private *intel)
352.35433 + {
352.35434 + #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.35435 +-	const char *s = xf86GetOptValString(intel->Options, OPTION_DRI);
352.35436 +-	Bool dummy;
352.35437 ++	return xf86GetOptValString(intel->Options, OPTION_DRI);
352.35438 ++#else
352.35439 ++	return NULL;
352.35440 ++#endif
352.35441 ++}
352.35442 + 
352.35443 +-	if (s == NULL || xf86getBoolValue(&dummy, s)) {
352.35444 ++static const char *dri_driver_name(intel_screen_private *intel)
352.35445 ++{
352.35446 ++	const char *s = options_get_dri(intel);
352.35447 ++
352.35448 ++	if (is_level(&s)) {
352.35449 + 		if (INTEL_INFO(intel)->gen < 030)
352.35450 + 			return has_i830_dri() ? "i830" : "i915";
352.35451 + 		else if (INTEL_INFO(intel)->gen < 040)
352.35452 +@@ -1456,14 +1544,6 @@ static const char *dri_driver_name(intel_screen_private *intel)
352.35453 + 	}
352.35454 + 
352.35455 + 	return s;
352.35456 +-#else
352.35457 +-	if (INTEL_INFO(intel)->gen < 030)
352.35458 +-		return has_i830_dri() ? "i830" : "i915";
352.35459 +-	else if (INTEL_INFO(intel)->gen < 040)
352.35460 +-		return "i915";
352.35461 +-	else
352.35462 +-		return "i965";
352.35463 +-#endif
352.35464 + }
352.35465 + 
352.35466 + Bool I830DRI2ScreenInit(ScreenPtr screen)
352.35467 +@@ -1544,7 +1624,7 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
352.35468 + 	info.numDrivers = 2;
352.35469 + 	info.driverNames = driverNames;
352.35470 + 	driverNames[0] = info.driverName;
352.35471 +-	driverNames[1] = info.driverName;
352.35472 ++	driverNames[1] = "va_gl";
352.35473 + #endif
352.35474 + 
352.35475 + 	return DRI2ScreenInit(screen, &info);
352.35476 +diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
352.35477 +index 2793da5d..3703c412 100644
352.35478 +--- a/src/uxa/intel_driver.c
352.35479 ++++ b/src/uxa/intel_driver.c
352.35480 +@@ -237,24 +237,17 @@ static Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
352.35481 + 	return TRUE;
352.35482 + }
352.35483 + 
352.35484 +-static Bool intel_option_cast_string_to_bool(intel_screen_private *intel,
352.35485 +-					     int id, Bool val)
352.35486 +-{
352.35487 +-#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
352.35488 +-	xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id));
352.35489 +-	return val;
352.35490 +-#else
352.35491 +-	return val;
352.35492 +-#endif
352.35493 +-}
352.35494 +-
352.35495 + static void intel_check_dri_option(ScrnInfoPtr scrn)
352.35496 + {
352.35497 + 	intel_screen_private *intel = intel_get_screen_private(scrn);
352.35498 ++	unsigned level;
352.35499 + 
352.35500 + 	intel->dri2 = intel->dri3 = DRI_NONE;
352.35501 +-	if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE))
352.35502 +-		intel->dri2 = intel->dri3 = DRI_DISABLED;
352.35503 ++	level = intel_option_cast_to_unsigned(intel->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
352.35504 ++	if (level < 3 || INTEL_INFO(intel)->gen < 040)
352.35505 ++		intel->dri3 = DRI_DISABLED;
352.35506 ++	if (level < 2)
352.35507 ++		intel->dri2 = DRI_DISABLED;
352.35508 + 
352.35509 + 	if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) {
352.35510 + 		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
352.35511 +@@ -371,8 +364,8 @@ static Bool can_accelerate_blt(struct intel_screen_private *intel)
352.35512 + 	if (INTEL_INFO(intel)->gen == -1)
352.35513 + 		return FALSE;
352.35514 + 
352.35515 +-	if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) ||
352.35516 +-	    !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) {
352.35517 ++	if (!xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_ENABLE, TRUE) ||
352.35518 ++	    !intel_option_cast_to_bool(intel->Options, OPTION_ACCEL_METHOD, TRUE)) {
352.35519 + 		xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG,
352.35520 + 			   "Disabling hardware acceleration.\n");
352.35521 + 		return FALSE;
352.35522 +@@ -659,8 +652,9 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
352.35523 + }
352.35524 + 
352.35525 + static void
352.35526 +-intel_dirty_update(ScreenPtr screen)
352.35527 ++intel_dirty_update(intel_screen_private *intel)
352.35528 + {
352.35529 ++	ScreenPtr screen = xf86ScrnToScreen(intel->scrn);
352.35530 + 	RegionPtr region;
352.35531 + 	PixmapDirtyUpdatePtr ent;
352.35532 + 
352.35533 +@@ -677,6 +671,7 @@ intel_dirty_update(ScreenPtr screen)
352.35534 + }
352.35535 + #endif
352.35536 + 
352.35537 ++#if !HAVE_NOTIFY_FD
352.35538 + static void
352.35539 + I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
352.35540 + {
352.35541 +@@ -694,9 +689,22 @@ I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
352.35542 + 	intel_uxa_block_handler(intel);
352.35543 + 	intel_video_block_handler(intel);
352.35544 + #ifdef INTEL_PIXMAP_SHARING
352.35545 +-	intel_dirty_update(screen);
352.35546 ++	intel_dirty_update(intel);
352.35547 + #endif
352.35548 + }
352.35549 ++#else
352.35550 ++static void
352.35551 ++I830BlockHandler(void *data, void *timeout)
352.35552 ++{
352.35553 ++	intel_screen_private *intel = data;
352.35554 ++
352.35555 ++	intel_uxa_block_handler(intel);
352.35556 ++	intel_video_block_handler(intel);
352.35557 ++#ifdef INTEL_PIXMAP_SHARING
352.35558 ++	intel_dirty_update(intel);
352.35559 ++#endif
352.35560 ++}
352.35561 ++#endif
352.35562 + 
352.35563 + static Bool
352.35564 + intel_init_initial_framebuffer(ScrnInfoPtr scrn)
352.35565 +@@ -735,6 +743,8 @@ intel_flush_callback(CallbackListPtr *list,
352.35566 + }
352.35567 + 
352.35568 + #if HAVE_UDEV
352.35569 ++#include <sys/stat.h>
352.35570 ++
352.35571 + static void
352.35572 + I830HandleUEvents(int fd, void *closure)
352.35573 + {
352.35574 +@@ -771,6 +781,15 @@ I830HandleUEvents(int fd, void *closure)
352.35575 + 	udev_device_unref(dev);
352.35576 + }
352.35577 + 
352.35578 ++static int has_randr(void)
352.35579 ++{
352.35580 ++#if HAS_DIXREGISTERPRIVATEKEY
352.35581 ++	return dixPrivateKeyRegistered(rrPrivKey);
352.35582 ++#else
352.35583 ++	return *rrPrivKey;
352.35584 ++#endif
352.35585 ++}
352.35586 ++
352.35587 + static void
352.35588 + I830UeventInit(ScrnInfoPtr scrn)
352.35589 + {
352.35590 +@@ -780,6 +799,10 @@ I830UeventInit(ScrnInfoPtr scrn)
352.35591 + 	Bool hotplug;
352.35592 + 	MessageType from = X_CONFIG;
352.35593 + 
352.35594 ++	/* Without RR, nothing we can do here */
352.35595 ++	if (!has_randr())
352.35596 ++		return;
352.35597 ++
352.35598 + 	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
352.35599 + 		from = X_DEFAULT;
352.35600 + 		hotplug = TRUE;
352.35601 +@@ -939,8 +962,14 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
352.35602 + 			   "Hardware cursor initialization failed\n");
352.35603 + 	}
352.35604 + 
352.35605 ++#if !HAVE_NOTIFY_FD
352.35606 + 	intel->BlockHandler = screen->BlockHandler;
352.35607 + 	screen->BlockHandler = I830BlockHandler;
352.35608 ++#else
352.35609 ++	RegisterBlockAndWakeupHandlers(I830BlockHandler,
352.35610 ++				       (ServerWakeupHandlerProcPtr)NoopDDA,
352.35611 ++				       intel);
352.35612 ++#endif
352.35613 + 
352.35614 + #ifdef INTEL_PIXMAP_SHARING
352.35615 + 	screen->StartPixmapTracking = PixmapStartDirtyTracking;
352.35616 +@@ -1164,8 +1193,6 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
352.35617 + 
352.35618 + 	intel_sync_close(screen);
352.35619 + 
352.35620 +-	xf86GARTCloseScreen(scrn->scrnIndex);
352.35621 +-
352.35622 + 	scrn->vtSema = FALSE;
352.35623 + 	return TRUE;
352.35624 + }
352.35625 +diff --git a/src/uxa/intel_hwmc.c b/src/uxa/intel_hwmc.c
352.35626 +index 829cb8e0..78540600 100644
352.35627 +--- a/src/uxa/intel_hwmc.c
352.35628 ++++ b/src/uxa/intel_hwmc.c
352.35629 +@@ -193,7 +193,7 @@ Bool intel_xvmc_adaptor_init(ScreenPtr pScreen)
352.35630 + 	intel_screen_private *intel = intel_get_screen_private(scrn);
352.35631 + 	struct pci_device *pci;
352.35632 + 	static XF86MCAdaptorRec *pAdapt;
352.35633 +-	char *name;
352.35634 ++	const char *name;
352.35635 + 	char buf[64];
352.35636 + 
352.35637 + 	if (!intel->XvMCEnabled)
352.35638 +diff --git a/src/uxa/intel_memory.c b/src/uxa/intel_memory.c
352.35639 +index 0c6cf30c..b2d7a367 100644
352.35640 +--- a/src/uxa/intel_memory.c
352.35641 ++++ b/src/uxa/intel_memory.c
352.35642 +@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
352.35643 +  * This is the video memory allocator.  Our memory allocation is different from
352.35644 +  * other graphics chips, where you have a fixed amount of graphics memory
352.35645 +  * available that you want to put to the best use.  Instead, we have almost no
352.35646 +- * memory pre-allocated, and we have to choose an appropriate amount of sytem
352.35647 ++ * memory pre-allocated, and we have to choose an appropriate amount of system
352.35648 +  * memory to use.
352.35649 +  *
352.35650 +  * The allocations we might do:
352.35651 +diff --git a/src/uxa/intel_present.c b/src/uxa/intel_present.c
352.35652 +index d20043f3..ac028edd 100644
352.35653 +--- a/src/uxa/intel_present.c
352.35654 ++++ b/src/uxa/intel_present.c
352.35655 +@@ -244,6 +244,7 @@ intel_present_check_flip(RRCrtcPtr              crtc,
352.35656 + 	ScrnInfoPtr             scrn = xf86ScreenToScrn(screen);
352.35657 + 	intel_screen_private    *intel = intel_get_screen_private(scrn);
352.35658 +         dri_bo                  *bo;
352.35659 ++	uint32_t		tiling, swizzle;
352.35660 + 
352.35661 + 	if (!scrn->vtSema)
352.35662 + 		return FALSE;
352.35663 +@@ -266,6 +267,12 @@ intel_present_check_flip(RRCrtcPtr              crtc,
352.35664 +         if (!bo)
352.35665 +                 return FALSE;
352.35666 + 
352.35667 ++	if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle))
352.35668 ++		return FALSE;
352.35669 ++
352.35670 ++	if (tiling == I915_TILING_Y)
352.35671 ++		return FALSE;
352.35672 ++
352.35673 + 	return TRUE;
352.35674 + }
352.35675 + 
352.35676 +@@ -343,29 +350,33 @@ intel_present_unflip(ScreenPtr screen, uint64_t event_id)
352.35677 + {
352.35678 + 	ScrnInfoPtr                             scrn = xf86ScreenToScrn(screen);
352.35679 + 	intel_screen_private                    *intel = intel_get_screen_private(scrn);
352.35680 +-	struct intel_present_vblank_event       *event;
352.35681 + 	PixmapPtr                               pixmap = screen->GetScreenPixmap(screen);
352.35682 ++	struct intel_present_vblank_event       *event = NULL;
352.35683 + 	dri_bo                                  *bo;
352.35684 +-	Bool                                    ret;
352.35685 + 
352.35686 + 	if (!intel_present_check_flip(NULL, screen->root, pixmap, true))
352.35687 +-		return;
352.35688 ++		goto fail;
352.35689 + 
352.35690 + 	bo = intel_get_pixmap_bo(pixmap);
352.35691 + 	if (!bo)
352.35692 +-		return;
352.35693 ++		goto fail;
352.35694 + 
352.35695 + 	event = calloc(1, sizeof(struct intel_present_vblank_event));
352.35696 + 	if (!event)
352.35697 +-		return;
352.35698 ++		goto fail;
352.35699 + 
352.35700 + 	event->event_id = event_id;
352.35701 + 
352.35702 +-	ret = intel_do_pageflip(intel, bo, -1, FALSE, event, intel_present_flip_event, intel_present_flip_abort);
352.35703 +-	if (!ret) {
352.35704 +-		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352.35705 +-			   "present unflip failed\n");
352.35706 +-	}
352.35707 ++	if (!intel_do_pageflip(intel, bo, -1, FALSE, event,
352.35708 ++			       intel_present_flip_event,
352.35709 ++			       intel_present_flip_abort))
352.35710 ++		goto fail;
352.35711 ++
352.35712 ++	return;
352.35713 ++fail:
352.35714 ++	xf86SetDesiredModes(scrn);
352.35715 ++	present_event_notify(event_id, 0, 0);
352.35716 ++	free(event);
352.35717 + }
352.35718 + 
352.35719 + static present_screen_info_rec intel_present_screen_info = {
352.35720 +diff --git a/src/uxa/intel_uxa.c b/src/uxa/intel_uxa.c
352.35721 +index 590ff5d1..ec32a723 100644
352.35722 +--- a/src/uxa/intel_uxa.c
352.35723 ++++ b/src/uxa/intel_uxa.c
352.35724 +@@ -176,6 +176,24 @@ intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask)
352.35725 + 	return TRUE;
352.35726 + }
352.35727 + 
352.35728 ++static Bool
352.35729 ++intel_uxa_check_bo_tiling(intel_screen_private *intel,
352.35730 ++			  PixmapPtr pixmap,
352.35731 ++			  unsigned *tiling_out)
352.35732 ++{
352.35733 ++	struct intel_uxa_pixmap *priv;
352.35734 ++
352.35735 ++	priv = intel_uxa_get_pixmap_private(pixmap);
352.35736 ++	if (!priv)
352.35737 ++		return FALSE;
352.35738 ++
352.35739 ++	if (priv->tiling == I915_TILING_Y && INTEL_INFO(intel)->gen < 060)
352.35740 ++		return FALSE;
352.35741 ++
352.35742 ++	*tiling_out = priv->tiling;
352.35743 ++	return TRUE;
352.35744 ++}
352.35745 ++
352.35746 + /**
352.35747 +  * Sets up hardware state for a series of solid fills.
352.35748 +  */
352.35749 +@@ -189,6 +207,9 @@ intel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
352.35750 + 		intel_uxa_get_pixmap_bo(pixmap),
352.35751 + 	};
352.35752 + 
352.35753 ++	if (!intel_uxa_check_bo_tiling(intel, pixmap, &intel->BR_tiling[0]))
352.35754 ++		return FALSE;
352.35755 ++
352.35756 + 	if (!intel_uxa_check_pitch_2d(pixmap))
352.35757 + 		return FALSE;
352.35758 + 
352.35759 +@@ -236,7 +257,7 @@ static void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
352.35760 + 
352.35761 + 	{
352.35762 + 		int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6;
352.35763 +-		BEGIN_BATCH_BLT(len);
352.35764 ++		BEGIN_BATCH_BLT_TILED(len);
352.35765 + 
352.35766 + 		cmd = XY_COLOR_BLT_CMD | (len - 2);
352.35767 + 
352.35768 +@@ -310,6 +331,10 @@ intel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
352.35769 + 		intel_uxa_get_pixmap_bo(dest),
352.35770 + 	};
352.35771 + 
352.35772 ++	if (!intel_uxa_check_bo_tiling(intel, dest, &intel->BR_tiling[0]) ||
352.35773 ++	    !intel_uxa_check_bo_tiling(intel, source, &intel->BR_tiling[1]))
352.35774 ++		return FALSE;
352.35775 ++
352.35776 + 	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
352.35777 + 		return FALSE;
352.35778 + 
352.35779 +@@ -375,7 +400,7 @@ intel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
352.35780 + 
352.35781 + 	{
352.35782 + 		int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8;
352.35783 +-		BEGIN_BATCH_BLT(len);
352.35784 ++		BEGIN_BATCH_BLT_TILED(len);
352.35785 + 
352.35786 + 		cmd = XY_SRC_COPY_BLT_CMD | (len - 2);
352.35787 + 
352.35788 +@@ -1068,7 +1093,7 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
352.35789 + 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
352.35790 + 	PixmapPtr pixmap;
352.35791 + 	intel_screen_private *intel = intel_get_screen_private(scrn);
352.35792 +-	dri_bo *bo = intel->front_buffer;
352.35793 ++	dri_bo *bo = intel->front_buffer, *old_bo;
352.35794 + 	int old_width, old_height, old_pitch;
352.35795 + 
352.35796 + 	if (!uxa_resources_init(screen))
352.35797 +@@ -1081,6 +1106,7 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
352.35798 + 	old_width = pixmap->drawable.width;
352.35799 + 	old_height = pixmap->drawable.height;
352.35800 + 	old_pitch = pixmap->devKind;
352.35801 ++	old_bo = intel_uxa_get_pixmap_bo(pixmap);
352.35802 + 
352.35803 + 	if (!screen->ModifyPixmapHeader(pixmap,
352.35804 + 					scrn->virtualX,
352.35805 +@@ -1102,6 +1128,9 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
352.35806 + err:
352.35807 + 	screen->ModifyPixmapHeader(pixmap,
352.35808 + 				   old_width, old_height, -1, -1, old_pitch, NULL);
352.35809 ++	if (old_bo)
352.35810 ++		intel_uxa_set_pixmap_bo(pixmap, old_bo);
352.35811 ++
352.35812 + 	return FALSE;
352.35813 + }
352.35814 + 
352.35815 +diff --git a/test/Makefile.am b/test/Makefile.am
352.35816 +index 66ed8ebb..12b5d5d8 100644
352.35817 +--- a/test/Makefile.am
352.35818 ++++ b/test/Makefile.am
352.35819 +@@ -5,6 +5,7 @@ stress_TESTS = \
352.35820 + 	basic-rectangle \
352.35821 + 	basic-string \
352.35822 + 	basic-copyarea \
352.35823 ++	basic-copyplane \
352.35824 + 	basic-copyarea-size \
352.35825 + 	basic-putimage \
352.35826 + 	basic-lines \
352.35827 +@@ -12,8 +13,10 @@ stress_TESTS = \
352.35828 + 	DrawSegments \
352.35829 + 	cursor-test \
352.35830 + 	render-fill \
352.35831 ++	render-glyphs \
352.35832 + 	render-trapezoid \
352.35833 + 	render-trapezoid-image \
352.35834 ++	render-triangle \
352.35835 + 	render-fill-copy \
352.35836 + 	render-composite-solid \
352.35837 + 	render-composite-solid-mask \
352.35838 +@@ -25,9 +28,16 @@ stress_TESTS = \
352.35839 + 	shm-test \
352.35840 + 	$(NULL)
352.35841 + 
352.35842 ++if X11_VM
352.35843 ++stress_TESTS += \
352.35844 ++	xvidmode \
352.35845 ++	$(NULL)
352.35846 ++endif
352.35847 ++
352.35848 + if DRI2
352.35849 + stress_TESTS += \
352.35850 + 	dri2-race \
352.35851 ++	dri2-speed \
352.35852 + 	dri2-swap \
352.35853 + 	dri2-test \
352.35854 + 	$(NULL)
352.35855 +@@ -36,8 +46,11 @@ endif
352.35856 + if X11_DRI3
352.35857 + stress_TESTS += \
352.35858 + 	dri3-test \
352.35859 ++	present-race \
352.35860 ++	present-speed \
352.35861 + 	present-test \
352.35862 + 	$(NULL)
352.35863 ++present_speed_CFLAGS = ${AM_CFLAGS} -pthread
352.35864 + endif
352.35865 + check_PROGRAMS = $(stress_TESTS)
352.35866 + 
352.35867 +diff --git a/test/basic-copyplane.c b/test/basic-copyplane.c
352.35868 +new file mode 100644
352.35869 +index 00000000..f049b82b
352.35870 +--- /dev/null
352.35871 ++++ b/test/basic-copyplane.c
352.35872 +@@ -0,0 +1,99 @@
352.35873 ++#include <stdint.h>
352.35874 ++#include <stdio.h>
352.35875 ++#include <stdlib.h>
352.35876 ++
352.35877 ++#include <X11/Xutil.h> /* for XDestroyImage */
352.35878 ++#include <pixman.h> /* for pixman blt functions */
352.35879 ++
352.35880 ++#include "test.h"
352.35881 ++
352.35882 ++static uint8_t clock_bits[] = {0x3C, 0x5E, 0xEF, 0xF7, 0x87, 0xFF, 0x7E, 0x3C};
352.35883 ++
352.35884 ++/* https://bugs.freedesktop.org/show_bug.cgi?id=91499 */
352.35885 ++static void draw_clock(struct test_display *t, Drawable d,
352.35886 ++		       uint8_t alu, int x, int y, uint32_t fg, uint32_t bg)
352.35887 ++{
352.35888 ++	Pixmap pixmap;
352.35889 ++	XGCValues val;
352.35890 ++	GC gc;
352.35891 ++
352.35892 ++	val.graphics_exposures = 0;
352.35893 ++	val.function = alu;
352.35894 ++	val.foreground = fg;
352.35895 ++	val.background = fg;
352.35896 ++
352.35897 ++	gc = XCreateGC(t->dpy, d,
352.35898 ++		       GCGraphicsExposures | GCForeground | GCBackground | GCFunction,
352.35899 ++		       &val);
352.35900 ++	pixmap = XCreateBitmapFromData(t->dpy, d, (char *)clock_bits, 8, 8);
352.35901 ++
352.35902 ++	XCopyPlane(t->dpy, pixmap, d, gc, 0, 0, 8, 8, x, y, 1);
352.35903 ++
352.35904 ++	XFreePixmap(t->dpy, pixmap);
352.35905 ++	XFreeGC(t->dpy, gc);
352.35906 ++}
352.35907 ++
352.35908 ++static void clear(struct test_display *dpy, struct test_target *tt)
352.35909 ++{
352.35910 ++	XRenderColor render_color = {0};
352.35911 ++	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
352.35912 ++			     0, 0, tt->width, tt->height);
352.35913 ++}
352.35914 ++
352.35915 ++static void clock_tests(struct test *t, int reps, int sets, enum target target)
352.35916 ++{
352.35917 ++	struct test_target out, ref;
352.35918 ++	int r, s;
352.35919 ++
352.35920 ++	printf("Testing clock (%s): ", test_target_name(target));
352.35921 ++	fflush(stdout);
352.35922 ++
352.35923 ++	test_target_create_render(&t->out, target, &out);
352.35924 ++	clear(&t->out, &out);
352.35925 ++
352.35926 ++	test_target_create_render(&t->ref, target, &ref);
352.35927 ++	clear(&t->ref, &ref);
352.35928 ++
352.35929 ++	for (s = 0; s < sets; s++) {
352.35930 ++		for (r = 0; r < reps; r++) {
352.35931 ++			int x = rand() % (out.width - 8);
352.35932 ++			int y = rand() % (out.height - 8);
352.35933 ++			uint8_t alu = rand() % (GXset + 1);
352.35934 ++			uint32_t bg = rand();
352.35935 ++			uint32_t fg = rand();
352.35936 ++
352.35937 ++			draw_clock(&t->out, out.draw, alu, x, y, fg, bg);
352.35938 ++			draw_clock(&t->ref, ref.draw, alu, x, y, fg, bg);
352.35939 ++		}
352.35940 ++
352.35941 ++		test_compare(t,
352.35942 ++			     out.draw, out.format,
352.35943 ++			     ref.draw, ref.format,
352.35944 ++			     0, 0, out.width, out.height,
352.35945 ++			     "");
352.35946 ++	}
352.35947 ++
352.35948 ++	printf("passed [%d iterations x %d]\n", reps, sets);
352.35949 ++
352.35950 ++	test_target_destroy_render(&t->out, &out);
352.35951 ++	test_target_destroy_render(&t->ref, &ref);
352.35952 ++}
352.35953 ++
352.35954 ++int main(int argc, char **argv)
352.35955 ++{
352.35956 ++	struct test test;
352.35957 ++	int i;
352.35958 ++
352.35959 ++	test_init(&test, argc, argv);
352.35960 ++
352.35961 ++	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
352.35962 ++		int reps = REPS(i), sets = SETS(i);
352.35963 ++		enum target t;
352.35964 ++
352.35965 ++		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
352.35966 ++			clock_tests(&test, reps, sets, t);
352.35967 ++		}
352.35968 ++	}
352.35969 ++
352.35970 ++	return 0;
352.35971 ++}
352.35972 +diff --git a/test/dri2-race.c b/test/dri2-race.c
352.35973 +index 8862c84c..ece624f6 100644
352.35974 +--- a/test/dri2-race.c
352.35975 ++++ b/test/dri2-race.c
352.35976 +@@ -5,6 +5,11 @@
352.35977 + #include <X11/Xlib.h>
352.35978 + #include <X11/Xutil.h>
352.35979 + #include <X11/extensions/Xfixes.h>
352.35980 ++#include <X11/extensions/Xcomposite.h>
352.35981 ++#include <X11/Xlib-xcb.h>
352.35982 ++#include <xcb/xcb.h>
352.35983 ++#include <xcb/xcbext.h>
352.35984 ++#include <xcb/dri2.h>
352.35985 + #include <unistd.h>
352.35986 + #include <fcntl.h>
352.35987 + #include <string.h>
352.35988 +@@ -12,11 +17,49 @@
352.35989 + 
352.35990 + #include <xf86drm.h>
352.35991 + #include <drm.h>
352.35992 ++#include <setjmp.h>
352.35993 + 
352.35994 + #include "dri2.h"
352.35995 + 
352.35996 + #define COUNT 60
352.35997 + 
352.35998 ++#define N_DIVISORS 3
352.35999 ++static const int divisors[N_DIVISORS] = { 0, 1, 16 };
352.36000 ++
352.36001 ++static jmp_buf error_handler[4];
352.36002 ++static int have_error_handler;
352.36003 ++
352.36004 ++#define error_get() \
352.36005 ++	setjmp(error_handler[have_error_handler++])
352.36006 ++
352.36007 ++#define error_put() \
352.36008 ++	have_error_handler--
352.36009 ++
352.36010 ++static int (*saved_io_error)(Display *dpy);
352.36011 ++
352.36012 ++static int io_error(Display *dpy)
352.36013 ++{
352.36014 ++	if (have_error_handler)
352.36015 ++		longjmp(error_handler[--have_error_handler], 0);
352.36016 ++
352.36017 ++	return saved_io_error(dpy);
352.36018 ++}
352.36019 ++
352.36020 ++static int x_error(Display *dpy, XErrorEvent *e)
352.36021 ++{
352.36022 ++	return Success;
352.36023 ++}
352.36024 ++
352.36025 ++static uint32_t upper_32_bits(uint64_t val)
352.36026 ++{
352.36027 ++	return val >> 32;
352.36028 ++}
352.36029 ++
352.36030 ++static uint32_t lower_32_bits(uint64_t val)
352.36031 ++{
352.36032 ++	return val & 0xffffffff;
352.36033 ++}
352.36034 ++
352.36035 + static int dri2_open(Display *dpy)
352.36036 + {
352.36037 + 	drm_auth_t auth;
352.36038 +@@ -41,45 +84,701 @@ static int dri2_open(Display *dpy)
352.36039 + 	return fd;
352.36040 + }
352.36041 + 
352.36042 +-static void run(Display *dpy, int width, int height,
352.36043 +-		unsigned int *attachments, int nattachments,
352.36044 +-		const char *name)
352.36045 ++static void swap_buffers(Display *dpy, Window win, int divisor,
352.36046 ++			 unsigned int *attachments, int nattachments)
352.36047 ++{
352.36048 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.36049 ++	unsigned int seq[2];
352.36050 ++
352.36051 ++	seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
352.36052 ++						 0, 0, 0, divisor, 0, 0).sequence;
352.36053 ++
352.36054 ++
352.36055 ++	seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
352.36056 ++						nattachments, nattachments,
352.36057 ++						attachments).sequence;
352.36058 ++
352.36059 ++	xcb_flush(c);
352.36060 ++	xcb_discard_reply(c, seq[0]);
352.36061 ++	xcb_discard_reply(c, seq[1]);
352.36062 ++}
352.36063 ++
352.36064 ++#define COMPOSITE 1
352.36065 ++
352.36066 ++static int has_composite(Display *dpy)
352.36067 ++{
352.36068 ++	Display *dummy = NULL;
352.36069 ++	int event, error;
352.36070 ++	int major = -1, minor = -1;
352.36071 ++
352.36072 ++	if (dpy == NULL)
352.36073 ++		dummy = dpy = XOpenDisplay(NULL);
352.36074 ++
352.36075 ++	if (XCompositeQueryExtension(dpy, &event, &error))
352.36076 ++		XCompositeQueryVersion(dpy, &major, &minor);
352.36077 ++
352.36078 ++	if (dummy)
352.36079 ++		XCloseDisplay(dummy);
352.36080 ++
352.36081 ++	return major > 0 || minor >= 4;
352.36082 ++}
352.36083 ++
352.36084 ++static void race_window(Display *dpy, int width, int height,
352.36085 ++			unsigned int *attachments, int nattachments,
352.36086 ++			unsigned flags, const char *name)
352.36087 + {
352.36088 + 	Window win;
352.36089 + 	XSetWindowAttributes attr;
352.36090 +-	int count, loop;
352.36091 ++	int count, loop, n;
352.36092 + 	DRI2Buffer *buffers;
352.36093 + 
352.36094 ++	if (flags & COMPOSITE && !has_composite(dpy))
352.36095 ++		return;
352.36096 ++
352.36097 ++	printf("%s(%s)\n", __func__, name);
352.36098 ++
352.36099 + 	/* Be nasty and install a fullscreen window on top so that we
352.36100 + 	 * can guarantee we do not get clipped by children.
352.36101 + 	 */
352.36102 + 	attr.override_redirect = 1;
352.36103 +-	loop = 100;
352.36104 +-	do {
352.36105 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36106 ++		loop = 256 >> ffs(divisors[n]);
352.36107 ++		printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop);
352.36108 ++		fflush(stdout);
352.36109 ++		do {
352.36110 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36111 ++					0, 0, width, height, 0,
352.36112 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36113 ++					InputOutput,
352.36114 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36115 ++					CWOverrideRedirect, &attr);
352.36116 ++			if (flags & COMPOSITE)
352.36117 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36118 ++			XMapWindow(dpy, win);
352.36119 ++
352.36120 ++			DRI2CreateDrawable(dpy, win);
352.36121 ++
352.36122 ++			buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.36123 ++					attachments, nattachments, &count);
352.36124 ++			if (count != nattachments)
352.36125 ++				return;
352.36126 ++
352.36127 ++			free(buffers);
352.36128 ++			for (count = 0; count < loop; count++)
352.36129 ++				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
352.36130 ++			XDestroyWindow(dpy, win);
352.36131 ++			printf("."); fflush(stdout);
352.36132 ++		} while (--loop);
352.36133 ++		printf("*\n");
352.36134 ++	}
352.36135 ++
352.36136 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36137 ++		loop = 256 >> ffs(divisors[n]);
352.36138 ++		printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop);
352.36139 ++		fflush(stdout);
352.36140 ++		do {
352.36141 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36142 ++					0, 0, width, height, 0,
352.36143 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36144 ++					InputOutput,
352.36145 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36146 ++					CWOverrideRedirect, &attr);
352.36147 ++			if (flags & COMPOSITE)
352.36148 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36149 ++			XMapWindow(dpy, win);
352.36150 ++
352.36151 ++			DRI2CreateDrawable(dpy, win);
352.36152 ++
352.36153 ++			buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.36154 ++					attachments, nattachments, &count);
352.36155 ++			if (count != nattachments)
352.36156 ++				return;
352.36157 ++
352.36158 ++			free(buffers);
352.36159 ++			for (count = 0; count < loop; count++)
352.36160 ++				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
352.36161 ++			XDestroyWindow(dpy, win);
352.36162 ++			printf("."); fflush(stdout);
352.36163 ++		} while (--loop);
352.36164 ++		printf("*\n");
352.36165 ++	}
352.36166 ++
352.36167 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36168 ++		loop = 256 >> ffs(divisors[n]);
352.36169 ++		printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop);
352.36170 ++		fflush(stdout);
352.36171 ++		do {
352.36172 ++			uint64_t ignore, msc;
352.36173 ++			xcb_connection_t *c = XGetXCBConnection(dpy);
352.36174 ++
352.36175 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36176 ++					0, 0, width, height, 0,
352.36177 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36178 ++					InputOutput,
352.36179 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36180 ++					CWOverrideRedirect, &attr);
352.36181 ++			if (flags & COMPOSITE)
352.36182 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36183 ++			XMapWindow(dpy, win);
352.36184 ++
352.36185 ++			DRI2CreateDrawable(dpy, win);
352.36186 ++			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
352.36187 ++			msc++;
352.36188 ++			for (count = 0; count < loop; count++) {
352.36189 ++				xcb_discard_reply(c,
352.36190 ++						xcb_dri2_wait_msc(c, win,
352.36191 ++							upper_32_bits(msc),
352.36192 ++							lower_32_bits(msc),
352.36193 ++							0, 0, 0, 0).sequence);
352.36194 ++				msc += divisors[n];
352.36195 ++			}
352.36196 ++			XFlush(dpy);
352.36197 ++			XDestroyWindow(dpy, win);
352.36198 ++			printf("."); fflush(stdout);
352.36199 ++		} while (--loop);
352.36200 ++		printf("*\n");
352.36201 ++	}
352.36202 ++
352.36203 ++	XSync(dpy, 1);
352.36204 ++	sleep(2);
352.36205 ++	XSync(dpy, 1);
352.36206 ++}
352.36207 ++
352.36208 ++static int rand_size(int max)
352.36209 ++{
352.36210 ++	return 1 + (rand() % (max - 1));
352.36211 ++}
352.36212 ++
352.36213 ++static void race_resize(Display *dpy, int width, int height,
352.36214 ++			unsigned int *attachments, int nattachments,
352.36215 ++			unsigned flags, const char *name)
352.36216 ++{
352.36217 ++	Window win;
352.36218 ++	XSetWindowAttributes attr;
352.36219 ++	int count, loop, n;
352.36220 ++	DRI2Buffer *buffers;
352.36221 ++
352.36222 ++	if (flags & COMPOSITE && !has_composite(dpy))
352.36223 ++		return;
352.36224 ++
352.36225 ++	printf("%s(%s)\n", __func__, name);
352.36226 ++
352.36227 ++	attr.override_redirect = 1;
352.36228 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36229 ++		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36230 ++				    0, 0, width, height, 0,
352.36231 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36232 ++				    InputOutput,
352.36233 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36234 ++				    CWOverrideRedirect, &attr);
352.36235 ++		if (flags & COMPOSITE)
352.36236 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36237 ++		XMapWindow(dpy, win);
352.36238 ++
352.36239 ++		DRI2CreateDrawable(dpy, win);
352.36240 ++
352.36241 ++		loop = 256 >> ffs(divisors[n]);
352.36242 ++		printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop);
352.36243 ++		fflush(stdout);
352.36244 ++		do {
352.36245 ++			int w, h;
352.36246 ++
352.36247 ++			buffers = DRI2GetBuffers(dpy, win, &w, &h,
352.36248 ++					attachments, nattachments, &count);
352.36249 ++			if (count != nattachments)
352.36250 ++				return;
352.36251 ++
352.36252 ++			free(buffers);
352.36253 ++			for (count = 0; count < loop; count++)
352.36254 ++				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
352.36255 ++			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
352.36256 ++			printf("."); fflush(stdout);
352.36257 ++		} while (--loop);
352.36258 ++		XDestroyWindow(dpy, win);
352.36259 ++		XSync(dpy, True);
352.36260 ++		printf("*\n");
352.36261 ++	}
352.36262 ++
352.36263 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36264 + 		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36265 + 				    0, 0, width, height, 0,
352.36266 + 				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36267 + 				    InputOutput,
352.36268 + 				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36269 + 				    CWOverrideRedirect, &attr);
352.36270 ++		if (flags & COMPOSITE)
352.36271 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36272 + 		XMapWindow(dpy, win);
352.36273 + 
352.36274 + 		DRI2CreateDrawable(dpy, win);
352.36275 + 
352.36276 +-		buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.36277 +-					 attachments, nattachments, &count);
352.36278 +-		if (count != nattachments)
352.36279 +-			return;
352.36280 ++		loop = 256 >> ffs(divisors[n]);
352.36281 ++		printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop);
352.36282 ++		fflush(stdout);
352.36283 ++		do {
352.36284 ++			int w, h;
352.36285 ++
352.36286 ++			buffers = DRI2GetBuffers(dpy, win, &w, &h,
352.36287 ++					attachments, nattachments, &count);
352.36288 ++			if (count != nattachments)
352.36289 ++				return;
352.36290 + 
352.36291 +-		free(buffers);
352.36292 +-		for (count = 0; count < loop; count++)
352.36293 +-			DRI2SwapBuffers(dpy, win, 0, 0, 0);
352.36294 ++			free(buffers);
352.36295 ++			for (count = 0; count < loop; count++)
352.36296 ++				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
352.36297 ++			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
352.36298 ++			printf("."); fflush(stdout);
352.36299 ++		} while (--loop);
352.36300 + 		XDestroyWindow(dpy, win);
352.36301 +-	} while (--loop);
352.36302 ++		XSync(dpy, True);
352.36303 ++		printf("*\n");
352.36304 ++	}
352.36305 ++
352.36306 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36307 ++		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36308 ++				    0, 0, width, height, 0,
352.36309 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36310 ++				    InputOutput,
352.36311 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36312 ++				    CWOverrideRedirect, &attr);
352.36313 ++		if (flags & COMPOSITE)
352.36314 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36315 ++		XMapWindow(dpy, win);
352.36316 ++
352.36317 ++		DRI2CreateDrawable(dpy, win);
352.36318 ++
352.36319 ++		loop = 256 >> ffs(divisors[n]);
352.36320 ++		printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop);
352.36321 ++		fflush(stdout);
352.36322 ++		do {
352.36323 ++			uint64_t ignore, msc;
352.36324 ++			xcb_connection_t *c = XGetXCBConnection(dpy);
352.36325 ++
352.36326 ++			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
352.36327 ++			msc++;
352.36328 ++			for (count = 0; count < loop; count++) {
352.36329 ++				xcb_discard_reply(c,
352.36330 ++						xcb_dri2_wait_msc(c, win,
352.36331 ++							upper_32_bits(msc),
352.36332 ++							lower_32_bits(msc),
352.36333 ++							0, 0, 0, 0).sequence);
352.36334 ++				msc += divisors[n];
352.36335 ++			}
352.36336 ++			XFlush(dpy);
352.36337 ++			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
352.36338 ++			printf("."); fflush(stdout);
352.36339 ++		} while (--loop);
352.36340 ++		XDestroyWindow(dpy, win);
352.36341 ++		XSync(dpy, True);
352.36342 ++		printf("*\n");
352.36343 ++	}
352.36344 ++
352.36345 ++	XSync(dpy, 1);
352.36346 ++	sleep(2);
352.36347 ++	XSync(dpy, 1);
352.36348 ++}
352.36349 ++
352.36350 ++static void race_manager(Display *dpy, int width, int height,
352.36351 ++			 unsigned int *attachments, int nattachments,
352.36352 ++			 unsigned flags, const char *name)
352.36353 ++{
352.36354 ++	Display *mgr = XOpenDisplay(NULL);
352.36355 ++	Window win;
352.36356 ++	XSetWindowAttributes attr;
352.36357 ++	int count, loop, n;
352.36358 ++	DRI2Buffer *buffers;
352.36359 ++
352.36360 ++	if (flags & COMPOSITE && !has_composite(dpy))
352.36361 ++		return;
352.36362 ++
352.36363 ++	printf("%s(%s)\n", __func__, name);
352.36364 ++
352.36365 ++	/* Be nasty and install a fullscreen window on top so that we
352.36366 ++	 * can guarantee we do not get clipped by children.
352.36367 ++	 */
352.36368 ++	attr.override_redirect = 1;
352.36369 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36370 ++		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
352.36371 ++		fflush(stdout);
352.36372 ++		loop = 256 >> ffs(divisors[n]);
352.36373 ++		do {
352.36374 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36375 ++					0, 0, width, height, 0,
352.36376 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36377 ++					InputOutput,
352.36378 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36379 ++					CWOverrideRedirect, &attr);
352.36380 ++			if (flags & COMPOSITE)
352.36381 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36382 ++			XMapWindow(dpy, win);
352.36383 ++
352.36384 ++			DRI2CreateDrawable(dpy, win);
352.36385 ++
352.36386 ++			buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.36387 ++					attachments, nattachments, &count);
352.36388 ++			if (count != nattachments)
352.36389 ++				return;
352.36390 ++
352.36391 ++			free(buffers);
352.36392 ++			for (count = 0; count < loop; count++)
352.36393 ++				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
352.36394 ++			XFlush(dpy);
352.36395 ++			XDestroyWindow(mgr, win);
352.36396 ++			XFlush(mgr);
352.36397 ++			printf("."); fflush(stdout);
352.36398 ++		} while (--loop);
352.36399 ++		printf("*\n");
352.36400 ++	}
352.36401 ++
352.36402 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36403 ++		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
352.36404 ++		fflush(stdout);
352.36405 ++		loop = 256 >> ffs(divisors[n]);
352.36406 ++		do {
352.36407 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36408 ++					0, 0, width, height, 0,
352.36409 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36410 ++					InputOutput,
352.36411 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36412 ++					CWOverrideRedirect, &attr);
352.36413 ++			if (flags & COMPOSITE)
352.36414 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36415 ++			XMapWindow(dpy, win);
352.36416 ++
352.36417 ++			DRI2CreateDrawable(dpy, win);
352.36418 ++
352.36419 ++			buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.36420 ++					attachments, nattachments, &count);
352.36421 ++			if (count != nattachments)
352.36422 ++				return;
352.36423 ++
352.36424 ++			free(buffers);
352.36425 ++			for (count = 0; count < loop; count++)
352.36426 ++				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
352.36427 ++			XFlush(dpy);
352.36428 ++			XDestroyWindow(mgr, win);
352.36429 ++			XFlush(mgr);
352.36430 ++			printf("."); fflush(stdout);
352.36431 ++		} while (--loop);
352.36432 ++		printf("*\n");
352.36433 ++	}
352.36434 ++
352.36435 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36436 ++		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
352.36437 ++		fflush(stdout);
352.36438 ++		loop = 256 >> ffs(divisors[n]);
352.36439 ++		do {
352.36440 ++			uint64_t ignore, msc;
352.36441 ++			xcb_connection_t *c = XGetXCBConnection(dpy);
352.36442 ++
352.36443 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36444 ++					0, 0, width, height, 0,
352.36445 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36446 ++					InputOutput,
352.36447 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36448 ++					CWOverrideRedirect, &attr);
352.36449 ++			if (flags & COMPOSITE)
352.36450 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36451 ++			XMapWindow(dpy, win);
352.36452 ++
352.36453 ++			DRI2CreateDrawable(dpy, win);
352.36454 ++			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
352.36455 ++			msc++;
352.36456 ++			for (count = 0; count < loop; count++) {
352.36457 ++				xcb_discard_reply(c,
352.36458 ++						xcb_dri2_wait_msc(c, win,
352.36459 ++							upper_32_bits(msc),
352.36460 ++							lower_32_bits(msc),
352.36461 ++							0, 0, 0, 0).sequence);
352.36462 ++				msc += divisors[n];
352.36463 ++			}
352.36464 ++			XFlush(dpy);
352.36465 ++			XDestroyWindow(mgr, win);
352.36466 ++			XFlush(mgr);
352.36467 ++			printf("."); fflush(stdout);
352.36468 ++		} while (--loop);
352.36469 ++		printf("*\n");
352.36470 ++	}
352.36471 + 
352.36472 + 	XSync(dpy, 1);
352.36473 ++	XSync(mgr, 1);
352.36474 + 	sleep(2);
352.36475 + 	XSync(dpy, 1);
352.36476 ++	XSync(mgr, 1);
352.36477 ++
352.36478 ++	XCloseDisplay(mgr);
352.36479 ++}
352.36480 ++
352.36481 ++static void race_close(int width, int height,
352.36482 ++		       unsigned int *attachments, int nattachments,
352.36483 ++		       unsigned flags, const char *name)
352.36484 ++{
352.36485 ++	XSetWindowAttributes attr;
352.36486 ++	int count, loop, n;
352.36487 ++
352.36488 ++	if (flags & COMPOSITE && !has_composite(NULL))
352.36489 ++		return;
352.36490 ++
352.36491 ++	printf("%s(%s)\n", __func__, name);
352.36492 ++
352.36493 ++	/* Be nasty and install a fullscreen window on top so that we
352.36494 ++	 * can guarantee we do not get clipped by children.
352.36495 ++	 */
352.36496 ++	attr.override_redirect = 1;
352.36497 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36498 ++		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
352.36499 ++		fflush(stdout);
352.36500 ++		loop = 256 >> ffs(divisors[n]);
352.36501 ++		do {
352.36502 ++			Display *dpy = XOpenDisplay(NULL);
352.36503 ++			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36504 ++					0, 0, width, height, 0,
352.36505 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36506 ++					InputOutput,
352.36507 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36508 ++					CWOverrideRedirect, &attr);
352.36509 ++			if (flags & COMPOSITE)
352.36510 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36511 ++			XMapWindow(dpy, win);
352.36512 ++
352.36513 ++			DRI2CreateDrawable(dpy, win);
352.36514 ++			free(DRI2GetBuffers(dpy, win, &width, &height,
352.36515 ++						attachments, nattachments, &count));
352.36516 ++			if (count != nattachments)
352.36517 ++				return;
352.36518 ++
352.36519 ++			for (count = 0; count < loop; count++)
352.36520 ++				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
352.36521 ++			XCloseDisplay(dpy);
352.36522 ++			printf("."); fflush(stdout);
352.36523 ++		} while (--loop);
352.36524 ++		printf("*\n");
352.36525 ++	}
352.36526 ++
352.36527 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36528 ++		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
352.36529 ++		fflush(stdout);
352.36530 ++		loop = 256 >> ffs(divisors[n]);
352.36531 ++		do {
352.36532 ++			Display *dpy = XOpenDisplay(NULL);
352.36533 ++			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36534 ++					0, 0, width, height, 0,
352.36535 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36536 ++					InputOutput,
352.36537 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36538 ++					CWOverrideRedirect, &attr);
352.36539 ++			if (flags & COMPOSITE)
352.36540 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36541 ++			XMapWindow(dpy, win);
352.36542 ++
352.36543 ++			DRI2CreateDrawable(dpy, win);
352.36544 ++			free(DRI2GetBuffers(dpy, win, &width, &height,
352.36545 ++						attachments, nattachments, &count));
352.36546 ++			if (count != nattachments)
352.36547 ++				return;
352.36548 ++
352.36549 ++			for (count = 0; count < loop; count++)
352.36550 ++				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
352.36551 ++			XCloseDisplay(dpy);
352.36552 ++			printf("."); fflush(stdout);
352.36553 ++		} while (--loop);
352.36554 ++		printf("*\n");
352.36555 ++	}
352.36556 ++
352.36557 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36558 ++		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
352.36559 ++		fflush(stdout);
352.36560 ++		loop = 256 >> ffs(divisors[n]);
352.36561 ++		do {
352.36562 ++			uint64_t ignore, msc;
352.36563 ++			Display *dpy = XOpenDisplay(NULL);
352.36564 ++			xcb_connection_t *c = XGetXCBConnection(dpy);
352.36565 ++			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36566 ++					0, 0, width, height, 0,
352.36567 ++					DefaultDepth(dpy, DefaultScreen(dpy)),
352.36568 ++					InputOutput,
352.36569 ++					DefaultVisual(dpy, DefaultScreen(dpy)),
352.36570 ++					CWOverrideRedirect, &attr);
352.36571 ++			if (flags & COMPOSITE)
352.36572 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36573 ++			XMapWindow(dpy, win);
352.36574 ++
352.36575 ++			DRI2CreateDrawable(dpy, win);
352.36576 ++			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
352.36577 ++			msc++;
352.36578 ++			for (count = 0; count < loop; count++) {
352.36579 ++				xcb_discard_reply(c,
352.36580 ++						xcb_dri2_wait_msc(c, win,
352.36581 ++							upper_32_bits(msc),
352.36582 ++							lower_32_bits(msc),
352.36583 ++							0, 0, 0, 0).sequence);
352.36584 ++				msc += divisors[n];
352.36585 ++			}
352.36586 ++			XFlush(dpy);
352.36587 ++			XCloseDisplay(dpy);
352.36588 ++			printf("."); fflush(stdout);
352.36589 ++		} while (--loop);
352.36590 ++		printf("*\n");
352.36591 ++	}
352.36592 ++}
352.36593 ++
352.36594 ++static void race_client(int width, int height,
352.36595 ++			unsigned int *attachments, int nattachments,
352.36596 ++			unsigned flags, const char *name)
352.36597 ++{
352.36598 ++	Display *mgr = XOpenDisplay(NULL);
352.36599 ++	XSetWindowAttributes attr;
352.36600 ++	int count, loop, n;
352.36601 ++
352.36602 ++	if (flags & COMPOSITE && !has_composite(NULL))
352.36603 ++		return;
352.36604 ++
352.36605 ++	printf("%s(%s)\n", __func__, name);
352.36606 ++
352.36607 ++	/* Be nasty and install a fullscreen window on top so that we
352.36608 ++	 * can guarantee we do not get clipped by children.
352.36609 ++	 */
352.36610 ++	attr.override_redirect = 1;
352.36611 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36612 ++		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
352.36613 ++		fflush(stdout);
352.36614 ++		loop = 256 >> ffs(divisors[n]);
352.36615 ++		do {
352.36616 ++			Display *dpy = XOpenDisplay(NULL);
352.36617 ++			Window win;
352.36618 ++
352.36619 ++			if (error_get()) {
352.36620 ++				XCloseDisplay(dpy);
352.36621 ++				printf("+"); fflush(stdout);
352.36622 ++				continue;
352.36623 ++			}
352.36624 ++
352.36625 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36626 ++					    0, 0, width, height, 0,
352.36627 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36628 ++					    InputOutput,
352.36629 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36630 ++					    CWOverrideRedirect, &attr);
352.36631 ++			if (flags & COMPOSITE)
352.36632 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36633 ++			XMapWindow(dpy, win);
352.36634 ++
352.36635 ++			DRI2CreateDrawable(dpy, win);
352.36636 ++			free(DRI2GetBuffers(dpy, win, &width, &height,
352.36637 ++					    attachments, nattachments, &count));
352.36638 ++			if (count == nattachments) {
352.36639 ++				for (count = 0; count < loop; count++)
352.36640 ++					DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
352.36641 ++			}
352.36642 ++
352.36643 ++			XFlush(dpy);
352.36644 ++			XKillClient(mgr, win);
352.36645 ++			XFlush(mgr);
352.36646 ++
352.36647 ++			XCloseDisplay(dpy);
352.36648 ++			printf("."); fflush(stdout);
352.36649 ++
352.36650 ++			error_put();
352.36651 ++		} while (--loop);
352.36652 ++		printf("*\n");
352.36653 ++	}
352.36654 ++
352.36655 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36656 ++		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
352.36657 ++		fflush(stdout);
352.36658 ++		loop = 256 >> ffs(divisors[n]);
352.36659 ++		do {
352.36660 ++			Display *dpy = XOpenDisplay(NULL);
352.36661 ++			Window win;
352.36662 ++
352.36663 ++			if (error_get()) {
352.36664 ++				XCloseDisplay(dpy);
352.36665 ++				printf("+"); fflush(stdout);
352.36666 ++				continue;
352.36667 ++			}
352.36668 ++
352.36669 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36670 ++					    0, 0, width, height, 0,
352.36671 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36672 ++					    InputOutput,
352.36673 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36674 ++					    CWOverrideRedirect, &attr);
352.36675 ++			if (flags & COMPOSITE)
352.36676 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36677 ++			XMapWindow(dpy, win);
352.36678 ++
352.36679 ++			DRI2CreateDrawable(dpy, win);
352.36680 ++			free(DRI2GetBuffers(dpy, win, &width, &height,
352.36681 ++					    attachments, nattachments, &count));
352.36682 ++			if (count == nattachments) {
352.36683 ++				for (count = 0; count < loop; count++)
352.36684 ++					swap_buffers(dpy, win, divisors[n], attachments, nattachments);
352.36685 ++			}
352.36686 ++
352.36687 ++			XFlush(dpy);
352.36688 ++			XKillClient(mgr, win);
352.36689 ++			XFlush(mgr);
352.36690 ++
352.36691 ++			XCloseDisplay(dpy);
352.36692 ++			printf("."); fflush(stdout);
352.36693 ++
352.36694 ++			error_put();
352.36695 ++		} while (--loop);
352.36696 ++		printf("*\n");
352.36697 ++	}
352.36698 ++
352.36699 ++	for (n = 0; n < N_DIVISORS; n++) {
352.36700 ++		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
352.36701 ++		fflush(stdout);
352.36702 ++		loop = 256 >> ffs(divisors[n]);
352.36703 ++		do {
352.36704 ++			Display *dpy = XOpenDisplay(NULL);
352.36705 ++			uint64_t ignore, msc;
352.36706 ++			xcb_connection_t *c;
352.36707 ++			Window win;
352.36708 ++
352.36709 ++			if (error_get()) {
352.36710 ++				XCloseDisplay(dpy);
352.36711 ++				printf("+"); fflush(stdout);
352.36712 ++				continue;
352.36713 ++			}
352.36714 ++
352.36715 ++			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.36716 ++					    0, 0, width, height, 0,
352.36717 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.36718 ++					    InputOutput,
352.36719 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.36720 ++					    CWOverrideRedirect, &attr);
352.36721 ++			if (flags & COMPOSITE)
352.36722 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.36723 ++			XMapWindow(dpy, win);
352.36724 ++
352.36725 ++			DRI2CreateDrawable(dpy, win);
352.36726 ++			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
352.36727 ++			c = XGetXCBConnection(dpy);
352.36728 ++			msc++;
352.36729 ++			for (count = 0; count < loop; count++) {
352.36730 ++				xcb_discard_reply(c,
352.36731 ++						  xcb_dri2_wait_msc(c, win,
352.36732 ++								    upper_32_bits(msc),
352.36733 ++								    lower_32_bits(msc),
352.36734 ++								    0, 0, 0, 0).sequence);
352.36735 ++				msc += divisors[n];
352.36736 ++			}
352.36737 ++
352.36738 ++			XFlush(dpy);
352.36739 ++			XKillClient(mgr, win);
352.36740 ++			XFlush(mgr);
352.36741 ++
352.36742 ++			XCloseDisplay(dpy);
352.36743 ++			printf("."); fflush(stdout);
352.36744 ++
352.36745 ++			error_put();
352.36746 ++		} while (--loop);
352.36747 ++		printf("*\n");
352.36748 ++	}
352.36749 ++
352.36750 ++	XCloseDisplay(mgr);
352.36751 + }
352.36752 + 
352.36753 + int main(void)
352.36754 +@@ -91,7 +790,10 @@ int main(void)
352.36755 + 		DRI2BufferFrontLeft,
352.36756 + 	};
352.36757 + 
352.36758 +-	dpy = XOpenDisplay (NULL);
352.36759 ++	saved_io_error = XSetIOErrorHandler(io_error);
352.36760 ++	XSetErrorHandler(x_error);
352.36761 ++
352.36762 ++	dpy = XOpenDisplay(NULL);
352.36763 + 	if (dpy == NULL)
352.36764 + 		return 77;
352.36765 + 
352.36766 +@@ -101,13 +803,52 @@ int main(void)
352.36767 + 
352.36768 + 	width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
352.36769 + 	height = HeightOfScreen(DefaultScreenOfDisplay(dpy));
352.36770 +-	run(dpy, width, height, attachments, 1, "fullscreen");
352.36771 +-	run(dpy, width, height, attachments, 2, "fullscreen (with front)");
352.36772 ++	race_window(dpy, width, height, attachments, 1, 0, "fullscreen");
352.36773 ++	race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen");
352.36774 ++	race_window(dpy, width, height, attachments, 2, 0, "fullscreen (with front)");
352.36775 ++	race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
352.36776 ++
352.36777 ++	race_resize(dpy, width, height, attachments, 1, 0, "");
352.36778 ++	race_resize(dpy, width, height, attachments, 1, COMPOSITE, "composite");
352.36779 ++	race_resize(dpy, width, height, attachments, 2, 0, "with front");
352.36780 ++	race_resize(dpy, width, height, attachments, 2, COMPOSITE, "composite with front");
352.36781 ++
352.36782 ++	race_manager(dpy, width, height, attachments, 1, 0, "fullscreen");
352.36783 ++	race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen");
352.36784 ++	race_manager(dpy, width, height, attachments, 2, 0, "fullscreen (with front)");
352.36785 ++	race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
352.36786 ++
352.36787 ++	race_close(width, height, attachments, 1, 0, "fullscreen");
352.36788 ++	race_close(width, height, attachments, 1, COMPOSITE, "composite fullscreen");
352.36789 ++	race_close(width, height, attachments, 2, 0, "fullscreen (with front)");
352.36790 ++	race_close(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
352.36791 ++
352.36792 ++	race_client(width, height, attachments, 1, 0, "fullscreen");
352.36793 ++	race_client(width, height, attachments, 1, COMPOSITE, "composite fullscreen");
352.36794 ++	race_client(width, height, attachments, 2, 0, "fullscreen (with front)");
352.36795 ++	race_client(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
352.36796 + 
352.36797 + 	width /= 2;
352.36798 + 	height /= 2;
352.36799 +-	run(dpy, width, height, attachments, 1, "windowed");
352.36800 +-	run(dpy, width, height, attachments, 2, "windowed (with front)");
352.36801 ++	race_window(dpy, width, height, attachments, 1, 0, "windowed");
352.36802 ++	race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed");
352.36803 ++	race_window(dpy, width, height, attachments, 2, 0, "windowed (with front)");
352.36804 ++	race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
352.36805 ++
352.36806 ++	race_manager(dpy, width, height, attachments, 1, 0, "windowed");
352.36807 ++	race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed");
352.36808 ++	race_manager(dpy, width, height, attachments, 2, 0, "windowed (with front)");
352.36809 ++	race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
352.36810 ++
352.36811 ++	race_close(width, height, attachments, 1, 0, "windowed");
352.36812 ++	race_close(width, height, attachments, 1, COMPOSITE, "composite windowed");
352.36813 ++	race_close(width, height, attachments, 2, 0, "windowed (with front)");
352.36814 ++	race_close(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
352.36815 ++
352.36816 ++	race_client(width, height, attachments, 1, 0, "windowed");
352.36817 ++	race_client(width, height, attachments, 1, COMPOSITE, "composite windowed");
352.36818 ++	race_client(width, height, attachments, 2, 0, "windowed (with front)");
352.36819 ++	race_client(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
352.36820 + 
352.36821 + 	return 0;
352.36822 + }
352.36823 +diff --git a/test/dri2-speed.c b/test/dri2-speed.c
352.36824 +new file mode 100644
352.36825 +index 00000000..87b9d0b6
352.36826 +--- /dev/null
352.36827 ++++ b/test/dri2-speed.c
352.36828 +@@ -0,0 +1,342 @@
352.36829 ++/*
352.36830 ++ * Copyright (c) 2015 Intel Corporation
352.36831 ++ *
352.36832 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.36833 ++ * copy of this software and associated documentation files (the "Software"),
352.36834 ++ * to deal in the Software without restriction, including without limitation
352.36835 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.36836 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.36837 ++ * Software is furnished to do so, subject to the following conditions:
352.36838 ++ *
352.36839 ++ * The above copyright notice and this permission notice (including the next
352.36840 ++ * paragraph) shall be included in all copies or substantial portions of the
352.36841 ++ * Software.
352.36842 ++ *
352.36843 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.36844 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.36845 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.36846 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.36847 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
352.36848 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
352.36849 ++ * SOFTWARE.
352.36850 ++ *
352.36851 ++ */
352.36852 ++
352.36853 ++#ifdef HAVE_CONFIG_H
352.36854 ++#include "config.h"
352.36855 ++#endif
352.36856 ++
352.36857 ++#include <X11/Xlib.h>
352.36858 ++#include <X11/Xatom.h>
352.36859 ++#include <X11/Xlib-xcb.h>
352.36860 ++#include <X11/Xutil.h>
352.36861 ++#include <X11/Xlibint.h>
352.36862 ++#include <X11/extensions/dpms.h>
352.36863 ++#include <X11/extensions/randr.h>
352.36864 ++#include <X11/extensions/Xcomposite.h>
352.36865 ++#include <X11/extensions/Xdamage.h>
352.36866 ++#include <X11/extensions/Xrandr.h>
352.36867 ++#include <xcb/xcb.h>
352.36868 ++#include <xcb/dri2.h>
352.36869 ++#include <xf86drm.h>
352.36870 ++
352.36871 ++#include <stdio.h>
352.36872 ++#include <string.h>
352.36873 ++#include <fcntl.h>
352.36874 ++#include <unistd.h>
352.36875 ++#include <assert.h>
352.36876 ++#include <errno.h>
352.36877 ++#include <setjmp.h>
352.36878 ++#include <signal.h>
352.36879 ++
352.36880 ++#include "dri2.h"
352.36881 ++
352.36882 ++static int _x_error_occurred;
352.36883 ++
352.36884 ++static int
352.36885 ++_check_error_handler(Display     *display,
352.36886 ++		     XErrorEvent *event)
352.36887 ++{
352.36888 ++	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
352.36889 ++	       DisplayString(display),
352.36890 ++	       event->serial,
352.36891 ++	       event->error_code,
352.36892 ++	       event->request_code,
352.36893 ++	       event->minor_code);
352.36894 ++	_x_error_occurred++;
352.36895 ++	return False; /* ignored */
352.36896 ++}
352.36897 ++
352.36898 ++static double elapsed(const struct timespec *start,
352.36899 ++		      const struct timespec *end)
352.36900 ++{
352.36901 ++	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
352.36902 ++}
352.36903 ++
352.36904 ++static void run(Display *dpy, Window win, const char *name)
352.36905 ++{
352.36906 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.36907 ++	struct timespec start, end;
352.36908 ++	int n, completed = 0;
352.36909 ++
352.36910 ++	_x_error_occurred = 0;
352.36911 ++
352.36912 ++	clock_gettime(CLOCK_MONOTONIC, &start);
352.36913 ++	do {
352.36914 ++		for (n = 0; n < 1000; n++) {
352.36915 ++			unsigned int attachments[] = { DRI2BufferBackLeft };
352.36916 ++			unsigned int seq[2];
352.36917 ++
352.36918 ++			seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
352.36919 ++								 0, 0, 0, 0, 0, 0).sequence;
352.36920 ++
352.36921 ++
352.36922 ++			seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
352.36923 ++								1, 1, attachments).sequence;
352.36924 ++
352.36925 ++			xcb_flush(c);
352.36926 ++			xcb_discard_reply(c, seq[0]);
352.36927 ++			xcb_discard_reply(c, seq[1]);
352.36928 ++			completed++;
352.36929 ++		}
352.36930 ++		clock_gettime(CLOCK_MONOTONIC, &end);
352.36931 ++	} while (end.tv_sec < start.tv_sec + 10);
352.36932 ++
352.36933 ++	XSync(dpy, True);
352.36934 ++	if (_x_error_occurred)
352.36935 ++		abort();
352.36936 ++
352.36937 ++	printf("%s: Completed %d swaps in %.1fs, %.3fus each (%.1f FPS)\n",
352.36938 ++	       name, completed, elapsed(&start, &end) / 1000000,
352.36939 ++	       elapsed(&start, &end) / completed,
352.36940 ++	       completed / (elapsed(&start, &end) / 1000000));
352.36941 ++}
352.36942 ++
352.36943 ++static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
352.36944 ++{
352.36945 ++	XRRScreenResources *res;
352.36946 ++
352.36947 ++	res = XRRGetScreenResourcesCurrent(dpy, window);
352.36948 ++	if (res == NULL)
352.36949 ++		res = XRRGetScreenResources(dpy, window);
352.36950 ++
352.36951 ++	return res;
352.36952 ++}
352.36953 ++
352.36954 ++static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
352.36955 ++{
352.36956 ++	int i;
352.36957 ++
352.36958 ++	for (i = 0; i < res->nmode; i++) {
352.36959 ++		if (res->modes[i].id == id)
352.36960 ++			return &res->modes[i];
352.36961 ++	}
352.36962 ++
352.36963 ++	return NULL;
352.36964 ++}
352.36965 ++
352.36966 ++static int dri2_open(Display *dpy)
352.36967 ++{
352.36968 ++	drm_auth_t auth;
352.36969 ++	char *driver, *device;
352.36970 ++	int fd;
352.36971 ++
352.36972 ++	if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
352.36973 ++		return -1;
352.36974 ++
352.36975 ++	printf ("Connecting to %s driver on %s\n", driver, device);
352.36976 ++
352.36977 ++	fd = open(device, O_RDWR);
352.36978 ++	if (fd < 0)
352.36979 ++		return -1;
352.36980 ++
352.36981 ++	if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
352.36982 ++		return -1;
352.36983 ++
352.36984 ++	if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
352.36985 ++		return -1;
352.36986 ++
352.36987 ++	return fd;
352.36988 ++}
352.36989 ++
352.36990 ++static void fullscreen(Display *dpy, Window win)
352.36991 ++{
352.36992 ++	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
352.36993 ++	XChangeProperty(dpy, win,
352.36994 ++			XInternAtom(dpy, "_NET_WM_STATE", False),
352.36995 ++			XA_ATOM, 32, PropModeReplace,
352.36996 ++			(unsigned char *)&atom, 1);
352.36997 ++}
352.36998 ++
352.36999 ++static int has_composite(Display *dpy)
352.37000 ++{
352.37001 ++	int event, error;
352.37002 ++	int major, minor;
352.37003 ++
352.37004 ++	if (!XDamageQueryExtension (dpy, &event, &error))
352.37005 ++		return 0;
352.37006 ++
352.37007 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
352.37008 ++		return 0;
352.37009 ++
352.37010 ++	XCompositeQueryVersion(dpy, &major, &minor);
352.37011 ++
352.37012 ++	return major > 0 || minor >= 4;
352.37013 ++}
352.37014 ++
352.37015 ++int main(void)
352.37016 ++{
352.37017 ++	Display *dpy;
352.37018 ++	Window root, win;
352.37019 ++	XRRScreenResources *res;
352.37020 ++	XRRCrtcInfo **original_crtc;
352.37021 ++	XSetWindowAttributes attr;
352.37022 ++	int i, j, fd;
352.37023 ++
352.37024 ++	attr.override_redirect = 1;
352.37025 ++
352.37026 ++	dpy = XOpenDisplay(NULL);
352.37027 ++	if (dpy == NULL)
352.37028 ++		return 77;
352.37029 ++
352.37030 ++	fd = dri2_open(dpy);
352.37031 ++	if (fd < 0)
352.37032 ++		return 77;
352.37033 ++
352.37034 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.37035 ++		DPMSDisable(dpy);
352.37036 ++
352.37037 ++	root = DefaultRootWindow(dpy);
352.37038 ++
352.37039 ++	signal(SIGALRM, SIG_IGN);
352.37040 ++	XSetErrorHandler(_check_error_handler);
352.37041 ++
352.37042 ++	res = NULL;
352.37043 ++	if (XRRQueryVersion(dpy, &i, &i))
352.37044 ++		res = _XRRGetScreenResourcesCurrent(dpy, root);
352.37045 ++	if (res == NULL)
352.37046 ++		return 77;
352.37047 ++
352.37048 ++	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
352.37049 ++	for (i = 0; i < res->ncrtc; i++)
352.37050 ++		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
352.37051 ++
352.37052 ++	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
352.37053 ++	for (i = 0; i < res->ncrtc; i++)
352.37054 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.37055 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
352.37056 ++
352.37057 ++	DRI2CreateDrawable(dpy, root);
352.37058 ++	DRI2SwapInterval(dpy, root, 0);
352.37059 ++	run(dpy, root, "off");
352.37060 ++	XSync(dpy, True);
352.37061 ++
352.37062 ++	for (i = 0; i < res->noutput; i++) {
352.37063 ++		XRROutputInfo *output;
352.37064 ++		XRRModeInfo *mode;
352.37065 ++
352.37066 ++		output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
352.37067 ++		if (output == NULL)
352.37068 ++			continue;
352.37069 ++
352.37070 ++		mode = NULL;
352.37071 ++		if (res->nmode)
352.37072 ++			mode = lookup_mode(res, output->modes[0]);
352.37073 ++
352.37074 ++		for (j = 0; mode && j < 2*output->ncrtc; j++) {
352.37075 ++			int c = j;
352.37076 ++			if (c >= output->ncrtc)
352.37077 ++				c = 2*output->ncrtc - j - 1;
352.37078 ++
352.37079 ++			printf("[%d, %d] -- OUTPUT:%ld, CRTC:%ld: %dx%d\n",
352.37080 ++			       i, c, (long)res->outputs[i], (long)output->crtcs[c],
352.37081 ++			       mode->width, mode->height);
352.37082 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
352.37083 ++					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
352.37084 ++
352.37085 ++			run(dpy, root, "root");
352.37086 ++			XSync(dpy, True);
352.37087 ++
352.37088 ++			win = XCreateWindow(dpy, root,
352.37089 ++					    0, 0, mode->width, mode->height, 0,
352.37090 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37091 ++					    InputOutput,
352.37092 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37093 ++					    CWOverrideRedirect, &attr);
352.37094 ++			DRI2CreateDrawable(dpy, win);
352.37095 ++			DRI2SwapInterval(dpy, win, 0);
352.37096 ++			fullscreen(dpy, win);
352.37097 ++			XMapWindow(dpy, win);
352.37098 ++			run(dpy, win, "fullscreen");
352.37099 ++			XDestroyWindow(dpy, win);
352.37100 ++			XSync(dpy, True);
352.37101 ++
352.37102 ++			win = XCreateWindow(dpy, root,
352.37103 ++					    0, 0, mode->width, mode->height, 0,
352.37104 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37105 ++					    InputOutput,
352.37106 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37107 ++					    CWOverrideRedirect, &attr);
352.37108 ++			DRI2CreateDrawable(dpy, win);
352.37109 ++			DRI2SwapInterval(dpy, win, 0);
352.37110 ++			XMapWindow(dpy, win);
352.37111 ++			run(dpy, win, "windowed");
352.37112 ++			XDestroyWindow(dpy, win);
352.37113 ++			XSync(dpy, True);
352.37114 ++
352.37115 ++			if (has_composite(dpy)) {
352.37116 ++				Damage damage;
352.37117 ++
352.37118 ++				_x_error_occurred = 0;
352.37119 ++				win = XCreateWindow(dpy, root,
352.37120 ++						    0, 0, mode->width, mode->height, 0,
352.37121 ++						    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37122 ++						    InputOutput,
352.37123 ++						    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37124 ++						    CWOverrideRedirect, &attr);
352.37125 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.37126 ++				damage = XDamageCreate(dpy, win, XDamageReportRawRectangles);
352.37127 ++				DRI2CreateDrawable(dpy, win);
352.37128 ++				DRI2SwapInterval(dpy, win, 0);
352.37129 ++				XMapWindow(dpy, win);
352.37130 ++				XSync(dpy, True);
352.37131 ++				if (!_x_error_occurred)
352.37132 ++					run(dpy, win, "composited");
352.37133 ++				XDamageDestroy(dpy, damage);
352.37134 ++				XDestroyWindow(dpy, win);
352.37135 ++				XSync(dpy, True);
352.37136 ++			}
352.37137 ++
352.37138 ++			win = XCreateWindow(dpy, root,
352.37139 ++					    0, 0, mode->width/2, mode->height/2, 0,
352.37140 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37141 ++					    InputOutput,
352.37142 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37143 ++					    CWOverrideRedirect, &attr);
352.37144 ++			DRI2CreateDrawable(dpy, win);
352.37145 ++			DRI2SwapInterval(dpy, win, 0);
352.37146 ++			XMapWindow(dpy, win);
352.37147 ++			run(dpy, win, "half");
352.37148 ++			XDestroyWindow(dpy, win);
352.37149 ++			XSync(dpy, True);
352.37150 ++
352.37151 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
352.37152 ++					 0, 0, None, RR_Rotate_0, NULL, 0);
352.37153 ++		}
352.37154 ++
352.37155 ++		XRRFreeOutputInfo(output);
352.37156 ++	}
352.37157 ++
352.37158 ++	for (i = 0; i < res->ncrtc; i++)
352.37159 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.37160 ++				 original_crtc[i]->x,
352.37161 ++				 original_crtc[i]->y,
352.37162 ++				 original_crtc[i]->mode,
352.37163 ++				 original_crtc[i]->rotation,
352.37164 ++				 original_crtc[i]->outputs,
352.37165 ++				 original_crtc[i]->noutput);
352.37166 ++
352.37167 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.37168 ++		DPMSEnable(dpy);
352.37169 ++	return 0;
352.37170 ++}
352.37171 +diff --git a/test/dri2-test.c b/test/dri2-test.c
352.37172 +index dd4179f3..bdf01f38 100644
352.37173 +--- a/test/dri2-test.c
352.37174 ++++ b/test/dri2-test.c
352.37175 +@@ -6,6 +6,10 @@
352.37176 + #include <X11/Xutil.h>
352.37177 + #include <X11/extensions/Xfixes.h>
352.37178 + #include <X11/extensions/Xrandr.h>
352.37179 ++#include <X11/Xlib-xcb.h>
352.37180 ++#include <xcb/xcb.h>
352.37181 ++#include <xcb/xcbext.h>
352.37182 ++#include <xcb/dri2.h>
352.37183 + #include <unistd.h>
352.37184 + #include <fcntl.h>
352.37185 + #include <string.h>
352.37186 +@@ -18,6 +22,8 @@
352.37187 + 
352.37188 + #define COUNT 60
352.37189 + 
352.37190 ++static int prime[] = { 0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29, 31, 37, 41, 43, 47, 51, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 };
352.37191 ++
352.37192 + static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
352.37193 + {
352.37194 + 	XRRScreenResources *res;
352.37195 +@@ -101,16 +107,41 @@ static uint64_t check_msc(Display *dpy, Window win, uint64_t last_msc)
352.37196 + 	return current_msc;
352.37197 + }
352.37198 + 
352.37199 ++static void wait_next_vblank(Display *dpy, Window win)
352.37200 ++{
352.37201 ++	uint64_t msc, ust, sbc;
352.37202 ++	DRI2WaitMSC(dpy, win, 0, 1, 0, &ust, &msc, &sbc);
352.37203 ++}
352.37204 ++
352.37205 ++static void swap_buffers(xcb_connection_t *c, Window win,
352.37206 ++		unsigned int *attachments, int nattachments)
352.37207 ++{
352.37208 ++	unsigned int seq[2];
352.37209 ++
352.37210 ++	seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
352.37211 ++						 0, 0, 0, 0, 0, 0).sequence;
352.37212 ++
352.37213 ++
352.37214 ++	seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
352.37215 ++						nattachments, nattachments,
352.37216 ++						attachments).sequence;
352.37217 ++
352.37218 ++	xcb_flush(c);
352.37219 ++	xcb_discard_reply(c, seq[0]);
352.37220 ++	xcb_discard_reply(c, seq[1]);
352.37221 ++}
352.37222 ++
352.37223 + static void run(Display *dpy, int width, int height,
352.37224 + 		unsigned int *attachments, int nattachments,
352.37225 + 		const char *name)
352.37226 + {
352.37227 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37228 + 	Window win;
352.37229 + 	XSetWindowAttributes attr;
352.37230 +-	int count;
352.37231 + 	DRI2Buffer *buffers;
352.37232 + 	struct timespec start, end;
352.37233 +-	uint64_t msc;
352.37234 ++	uint64_t start_msc, end_msc;
352.37235 ++	int modulus, remainder, count;
352.37236 + 
352.37237 + 	/* Be nasty and install a fullscreen window on top so that we
352.37238 + 	 * can guarantee we do not get clipped by children.
352.37239 +@@ -125,42 +156,99 @@ static void run(Display *dpy, int width, int height,
352.37240 + 	XMapWindow(dpy, win);
352.37241 + 
352.37242 + 	DRI2CreateDrawable(dpy, win);
352.37243 +-	msc = check_msc(dpy, win, 0);
352.37244 ++	DRI2SwapInterval(dpy, win, 1);
352.37245 ++	start_msc = check_msc(dpy, win, 0);
352.37246 + 
352.37247 + 	buffers = DRI2GetBuffers(dpy, win, &width, &height,
352.37248 + 				 attachments, nattachments, &count);
352.37249 + 	if (count != nattachments)
352.37250 + 		return;
352.37251 + 
352.37252 +-	msc = check_msc(dpy, win, msc);
352.37253 ++	swap_buffers(c, win, attachments, nattachments);
352.37254 ++	start_msc = check_msc(dpy, win, start_msc);
352.37255 + 	clock_gettime(CLOCK_MONOTONIC, &start);
352.37256 + 	for (count = 0; count < COUNT; count++)
352.37257 +-		DRI2SwapBuffers(dpy, win, 0, 0, 0);
352.37258 +-	msc = check_msc(dpy, win, msc);
352.37259 ++		swap_buffers(c, win, attachments, nattachments);
352.37260 ++	end_msc = check_msc(dpy, win, start_msc);
352.37261 + 	clock_gettime(CLOCK_MONOTONIC, &end);
352.37262 +-	printf("%d %s (%dx%d) swaps in %fs.\n",
352.37263 +-	       count, name, width, height, elapsed(&start, &end));
352.37264 ++	printf("%d [%ld] %s (%dx%d) swaps in %fs.\n",
352.37265 ++	       count, (long)(end_msc - start_msc),
352.37266 ++	       name, width, height, elapsed(&start, &end));
352.37267 + 
352.37268 +-	msc = check_msc(dpy, win, msc);
352.37269 ++	swap_buffers(c, win, attachments, nattachments);
352.37270 ++	start_msc = check_msc(dpy, win, end_msc);
352.37271 + 	clock_gettime(CLOCK_MONOTONIC, &start);
352.37272 + 	for (count = 0; count < COUNT; count++)
352.37273 + 		dri2_copy_swap(dpy, win, width, height, nattachments == 2);
352.37274 +-	msc = check_msc(dpy, win, msc);
352.37275 ++	end_msc = check_msc(dpy, win, start_msc);
352.37276 + 	clock_gettime(CLOCK_MONOTONIC, &end);
352.37277 + 
352.37278 +-	printf("%d %s (%dx%d) blits in %fs.\n",
352.37279 +-	       count, name, width, height, elapsed(&start, &end));
352.37280 ++	printf("%d [%ld] %s (%dx%d) blits in %fs.\n",
352.37281 ++	       count, (long)(end_msc - start_msc),
352.37282 ++	       name, width, height, elapsed(&start, &end));
352.37283 + 
352.37284 + 	DRI2SwapInterval(dpy, win, 0);
352.37285 ++	wait_next_vblank(dpy, win);
352.37286 ++
352.37287 ++	swap_buffers(c, win, attachments, nattachments);
352.37288 ++	start_msc = check_msc(dpy, win, end_msc);
352.37289 ++	clock_gettime(CLOCK_MONOTONIC, &start);
352.37290 ++	for (count = 0; count < COUNT; count++)
352.37291 ++		swap_buffers(c, win, attachments, nattachments);
352.37292 ++	end_msc = check_msc(dpy, win, start_msc);
352.37293 ++	clock_gettime(CLOCK_MONOTONIC, &end);
352.37294 ++	printf("%d [%ld] %s (%dx%d) vblank=0 swaps in %fs.\n",
352.37295 ++	       count, (long)(end_msc - start_msc),
352.37296 ++	       name, width, height, elapsed(&start, &end));
352.37297 + 
352.37298 +-	msc = check_msc(dpy, win, msc);
352.37299 ++	start_msc = check_msc(dpy, win, end_msc);
352.37300 + 	clock_gettime(CLOCK_MONOTONIC, &start);
352.37301 + 	for (count = 0; count < COUNT; count++)
352.37302 +-		DRI2SwapBuffers(dpy, win, 0, 0, 0);
352.37303 +-	msc = check_msc(dpy, win, msc);
352.37304 ++		wait_next_vblank(dpy, win);
352.37305 ++	end_msc = check_msc(dpy, win, start_msc);
352.37306 + 	clock_gettime(CLOCK_MONOTONIC, &end);
352.37307 +-	printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n",
352.37308 +-	       count, name, width, height, elapsed(&start, &end));
352.37309 ++	printf("%d [%ld] %s waits in %fs.\n",
352.37310 ++	       count, (long)(end_msc - start_msc),
352.37311 ++	       name, elapsed(&start, &end));
352.37312 ++
352.37313 ++	printf("Testing past & future waits\n");
352.37314 ++	for (modulus = 1; modulus <= 128; modulus <<= 1) {
352.37315 ++		for (count = 0;  prime[count] < modulus; count++) {
352.37316 ++			uint64_t msc, ust, sbc;
352.37317 ++			uint64_t target;
352.37318 ++
352.37319 ++			remainder = prime[count];
352.37320 ++
352.37321 ++			DRI2WaitMSC(dpy, win, 0, 1, 0, &ust, &msc, &sbc);
352.37322 ++
352.37323 ++			target = msc + modulus + 1;
352.37324 ++			target &= -modulus;
352.37325 ++			target += remainder;
352.37326 ++
352.37327 ++			DRI2WaitMSC(dpy, win, target, modulus, remainder,
352.37328 ++				    &ust, &msc, &sbc);
352.37329 ++			if (msc != target) {
352.37330 ++				printf("Missed future MSC (%d, %d): expected=%lld, found=%lld\n",
352.37331 ++				       modulus, remainder,
352.37332 ++				       (long long)target, (long long)msc);
352.37333 ++			}
352.37334 ++
352.37335 ++			target = msc;
352.37336 ++			target &= -modulus;
352.37337 ++			target += remainder;
352.37338 ++			if (target <= msc)
352.37339 ++				target += modulus;
352.37340 ++
352.37341 ++			DRI2WaitMSC(dpy, win, msc, modulus, remainder,
352.37342 ++				    &ust, &msc, &sbc);
352.37343 ++
352.37344 ++			if (msc != target) {
352.37345 ++				printf("Missed past MSC (%d, %d): expected=%lld, found=%lld\n",
352.37346 ++				       modulus, remainder,
352.37347 ++				       (long long)target, (long long)msc);
352.37348 ++			}
352.37349 ++		}
352.37350 ++	}
352.37351 + 
352.37352 + 	XDestroyWindow(dpy, win);
352.37353 + 	free(buffers);
352.37354 +diff --git a/test/dri3-test.c b/test/dri3-test.c
352.37355 +index c66da313..78e105a8 100644
352.37356 +--- a/test/dri3-test.c
352.37357 ++++ b/test/dri3-test.c
352.37358 +@@ -93,14 +93,9 @@ static const struct pci_id_match ids[] = {
352.37359 + 	INTEL_IVB_D_IDS(070),
352.37360 + 	INTEL_IVB_M_IDS(070),
352.37361 + 
352.37362 +-	INTEL_HSW_D_IDS(075),
352.37363 +-	INTEL_HSW_M_IDS(075),
352.37364 +-
352.37365 +-	INTEL_VLV_D_IDS(071),
352.37366 +-	INTEL_VLV_M_IDS(071),
352.37367 +-
352.37368 +-	INTEL_BDW_D_IDS(0100),
352.37369 +-	INTEL_BDW_M_IDS(0100),
352.37370 ++	INTEL_HSW_IDS(075),
352.37371 ++	INTEL_VLV_IDS(071),
352.37372 ++	INTEL_BDW_IDS(0100),
352.37373 + };
352.37374 + 
352.37375 + static int i915_gen(int device)
352.37376 +@@ -1020,6 +1015,67 @@ fail:
352.37377 + 	return 1;
352.37378 + }
352.37379 + 
352.37380 ++static int gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
352.37381 ++{
352.37382 ++	struct drm_i915_gem_set_tiling set_tiling;
352.37383 ++
352.37384 ++	set_tiling.handle = handle;
352.37385 ++	set_tiling.tiling_mode = tiling;
352.37386 ++	set_tiling.stride = stride;
352.37387 ++
352.37388 ++	return drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0;
352.37389 ++}
352.37390 ++
352.37391 ++static int test_tiling(Display *dpy, int device)
352.37392 ++{
352.37393 ++	Window root = RootWindow(dpy, DefaultScreen(dpy));
352.37394 ++	const int tiling[] = { I915_TILING_NONE, I915_TILING_X, I915_TILING_Y };
352.37395 ++	int line = -1;
352.37396 ++	int t;
352.37397 ++
352.37398 ++	_x_error_occurred = 0;
352.37399 ++
352.37400 ++	for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) {
352.37401 ++		uint32_t src;
352.37402 ++		int src_fd;
352.37403 ++		Pixmap src_pix;
352.37404 ++
352.37405 ++		src = gem_create(device, 4*4096);
352.37406 ++		if (!src) {
352.37407 ++			line = __LINE__;
352.37408 ++			goto fail;
352.37409 ++		}
352.37410 ++
352.37411 ++		gem_set_tiling(device, src, tiling[t], 512);
352.37412 ++
352.37413 ++		src_fd = gem_export(device, src);
352.37414 ++		if (src_fd < 0) {
352.37415 ++			line = __LINE__;
352.37416 ++			goto fail;
352.37417 ++		}
352.37418 ++
352.37419 ++		src_pix = dri3_create_pixmap(dpy, root,
352.37420 ++					     128, 32, 32,
352.37421 ++					     src_fd, 32, 512, 4*4096);
352.37422 ++		XSync(dpy, True);
352.37423 ++		if (_x_error_occurred) {
352.37424 ++			line = __LINE__;
352.37425 ++			goto fail;
352.37426 ++		}
352.37427 ++		XFreePixmap(dpy, src_pix);
352.37428 ++		_x_error_occurred = 0;
352.37429 ++
352.37430 ++		close(src_fd);
352.37431 ++		gem_close(device, src);
352.37432 ++	}
352.37433 ++
352.37434 ++	return 0;
352.37435 ++
352.37436 ++fail:
352.37437 ++	printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line);
352.37438 ++	return 1;
352.37439 ++}
352.37440 ++
352.37441 + static int
352.37442 + _check_error_handler(Display     *display,
352.37443 + 		     XErrorEvent *event)
352.37444 +@@ -1060,6 +1116,7 @@ int main(void)
352.37445 + 
352.37446 + 	error += test_bad_size(dpy, device);
352.37447 + 	error += test_bad_pitch(dpy, device);
352.37448 ++	error += test_tiling(dpy, device);
352.37449 + 
352.37450 + 	error += test_shm(dpy, device, 400, 300);
352.37451 + 	error += test_shm(dpy, device, 300, 400);
352.37452 +diff --git a/test/dri3.c b/test/dri3.c
352.37453 +index 45f3285c..e5644629 100644
352.37454 +--- a/test/dri3.c
352.37455 ++++ b/test/dri3.c
352.37456 +@@ -29,6 +29,7 @@
352.37457 + #include <xcb/dri3.h>
352.37458 + #include <xcb/sync.h>
352.37459 + #include <unistd.h>
352.37460 ++#include <stdlib.h>
352.37461 + 
352.37462 + #include "dri3.h"
352.37463 + 
352.37464 +@@ -109,12 +110,45 @@ void dri3_fence_free(Display *dpy, struct dri3_fence *fence)
352.37465 + 	xcb_sync_destroy_fence(c, fence->xid);
352.37466 + }
352.37467 + 
352.37468 ++static void dri3_query_version(xcb_connection_t *c, int *major, int *minor)
352.37469 ++{
352.37470 ++	xcb_dri3_query_version_reply_t *reply;
352.37471 ++
352.37472 ++	reply = xcb_dri3_query_version_reply(c,
352.37473 ++					     xcb_dri3_query_version(c,
352.37474 ++								    XCB_DRI3_MAJOR_VERSION,
352.37475 ++								    XCB_DRI3_MINOR_VERSION),
352.37476 ++					     NULL);
352.37477 ++	if (reply != NULL) {
352.37478 ++		*major = reply->major_version;
352.37479 ++		*minor = reply->minor_version;
352.37480 ++		free(reply);
352.37481 ++	}
352.37482 ++}
352.37483 ++
352.37484 ++static int dri3_exists(xcb_connection_t *c)
352.37485 ++{
352.37486 ++	const xcb_query_extension_reply_t *ext;
352.37487 ++	int major, minor;
352.37488 ++
352.37489 ++	major = minor = -1;
352.37490 ++
352.37491 ++	ext = xcb_get_extension_data(c, &xcb_dri3_id);
352.37492 ++	if (ext != NULL && ext->present)
352.37493 ++		dri3_query_version(c, &major, &minor);
352.37494 ++
352.37495 ++	return major >= 0;
352.37496 ++}
352.37497 ++
352.37498 + int dri3_open__full(Display *dpy, Window root, unsigned provider)
352.37499 + {
352.37500 + 	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37501 + 	xcb_dri3_open_cookie_t cookie;
352.37502 + 	xcb_dri3_open_reply_t *reply;
352.37503 + 
352.37504 ++	if (!dri3_exists(c))
352.37505 ++		return -1;
352.37506 ++
352.37507 + 	cookie = xcb_dri3_open(c, root, provider);
352.37508 + 	reply = xcb_dri3_open_reply(c, cookie, NULL);
352.37509 + 
352.37510 +diff --git a/test/present-race.c b/test/present-race.c
352.37511 +new file mode 100644
352.37512 +index 00000000..b2b6aa2b
352.37513 +--- /dev/null
352.37514 ++++ b/test/present-race.c
352.37515 +@@ -0,0 +1,484 @@
352.37516 ++/*
352.37517 ++ * Copyright (c) 2014 Intel Corporation
352.37518 ++ *
352.37519 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.37520 ++ * copy of this software and associated documentation files (the "Software"),
352.37521 ++ * to deal in the Software without restriction, including without limitation
352.37522 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.37523 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.37524 ++ * Software is furnished to do so, subject to the following conditions:
352.37525 ++ *
352.37526 ++ * The above copyright notice and this permission notice (including the next
352.37527 ++ * paragraph) shall be included in all copies or substantial portions of the
352.37528 ++ * Software.
352.37529 ++ *
352.37530 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.37531 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.37532 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.37533 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.37534 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
352.37535 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
352.37536 ++ * SOFTWARE.
352.37537 ++ *
352.37538 ++ */
352.37539 ++
352.37540 ++#ifdef HAVE_CONFIG_H
352.37541 ++#include "config.h"
352.37542 ++#endif
352.37543 ++
352.37544 ++#include <X11/Xlib.h>
352.37545 ++#include <X11/Xlib-xcb.h>
352.37546 ++#include <X11/xshmfence.h>
352.37547 ++#include <X11/Xutil.h>
352.37548 ++#include <X11/Xlibint.h>
352.37549 ++#include <X11/extensions/dpms.h>
352.37550 ++#include <X11/extensions/randr.h>
352.37551 ++#include <X11/extensions/Xcomposite.h>
352.37552 ++#include <X11/extensions/Xrandr.h>
352.37553 ++#include <X11/extensions/Xrender.h>
352.37554 ++#include <X11/extensions/XShm.h>
352.37555 ++#if HAVE_X11_EXTENSIONS_SHMPROTO_H
352.37556 ++#include <X11/extensions/shmproto.h>
352.37557 ++#elif HAVE_X11_EXTENSIONS_SHMSTR_H
352.37558 ++#include <X11/extensions/shmstr.h>
352.37559 ++#else
352.37560 ++#error Failed to find the right header for X11 MIT-SHM protocol definitions
352.37561 ++#endif
352.37562 ++#include <xcb/xcb.h>
352.37563 ++#include <xcb/present.h>
352.37564 ++#include <xcb/xfixes.h>
352.37565 ++#include <xcb/dri3.h>
352.37566 ++#include <xf86drm.h>
352.37567 ++#include <i915_drm.h>
352.37568 ++
352.37569 ++#include <stdio.h>
352.37570 ++#include <string.h>
352.37571 ++#include <fcntl.h>
352.37572 ++#include <unistd.h>
352.37573 ++#include <assert.h>
352.37574 ++#include <errno.h>
352.37575 ++#include <setjmp.h>
352.37576 ++#include <signal.h>
352.37577 ++
352.37578 ++#include <sys/mman.h>
352.37579 ++#include <sys/ipc.h>
352.37580 ++#include <sys/shm.h>
352.37581 ++#include <pciaccess.h>
352.37582 ++
352.37583 ++#include "dri3.h"
352.37584 ++
352.37585 ++static int _x_error_occurred;
352.37586 ++static uint32_t stamp;
352.37587 ++
352.37588 ++static int
352.37589 ++_check_error_handler(Display     *display,
352.37590 ++		     XErrorEvent *event)
352.37591 ++{
352.37592 ++	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
352.37593 ++	       DisplayString(display),
352.37594 ++	       event->serial,
352.37595 ++	       event->error_code,
352.37596 ++	       event->request_code,
352.37597 ++	       event->minor_code);
352.37598 ++	_x_error_occurred++;
352.37599 ++	return False; /* ignored */
352.37600 ++}
352.37601 ++
352.37602 ++static int has_composite(Display *dpy)
352.37603 ++{
352.37604 ++	int event, error;
352.37605 ++	int major, minor;
352.37606 ++
352.37607 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
352.37608 ++		return 0;
352.37609 ++
352.37610 ++	XCompositeQueryVersion(dpy, &major, &minor);
352.37611 ++
352.37612 ++	return major > 0 || minor >= 4;
352.37613 ++}
352.37614 ++
352.37615 ++static void *setup_msc(Display *dpy, Window win)
352.37616 ++{
352.37617 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37618 ++	xcb_void_cookie_t cookie;
352.37619 ++	uint32_t id = xcb_generate_id(c);
352.37620 ++	xcb_generic_error_t *error;
352.37621 ++	void *q;
352.37622 ++
352.37623 ++	cookie = xcb_present_select_input_checked(c, id, win, XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
352.37624 ++	q = xcb_register_for_special_xge(c, &xcb_present_id, id, &stamp);
352.37625 ++
352.37626 ++	error = xcb_request_check(c, cookie);
352.37627 ++	assert(error == NULL);
352.37628 ++
352.37629 ++	return q;
352.37630 ++}
352.37631 ++
352.37632 ++static void teardown_msc(Display *dpy, void *q)
352.37633 ++{
352.37634 ++	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
352.37635 ++}
352.37636 ++
352.37637 ++static uint64_t wait_vblank(Display *dpy, Window win)
352.37638 ++{
352.37639 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37640 ++	static uint32_t serial = 1;
352.37641 ++	uint64_t msc = 0;
352.37642 ++	int complete = 0;
352.37643 ++	void *q;
352.37644 ++
352.37645 ++	if (win == 0)
352.37646 ++		win = DefaultRootWindow(dpy);
352.37647 ++
352.37648 ++	q = setup_msc(dpy, win);
352.37649 ++
352.37650 ++	xcb_present_notify_msc(c, win, serial ^ 0xdeadbeef, 0, 1, 0);
352.37651 ++	xcb_flush(c);
352.37652 ++
352.37653 ++	do {
352.37654 ++		xcb_present_complete_notify_event_t *ce;
352.37655 ++		xcb_generic_event_t *ev;
352.37656 ++
352.37657 ++		ev = xcb_wait_for_special_event(c, q);
352.37658 ++		if (ev == NULL)
352.37659 ++			break;
352.37660 ++
352.37661 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.37662 ++		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
352.37663 ++		    ce->serial == (serial ^ 0xdeadbeef)) {
352.37664 ++			msc = ce->msc;
352.37665 ++			complete = 1;
352.37666 ++		}
352.37667 ++		free(ev);
352.37668 ++	} while (!complete);
352.37669 ++
352.37670 ++	if (++serial == 0)
352.37671 ++		serial = 1;
352.37672 ++
352.37673 ++	teardown_msc(dpy, q);
352.37674 ++
352.37675 ++	return msc;
352.37676 ++}
352.37677 ++
352.37678 ++static int test_basic(Display *dpy, int dummy)
352.37679 ++{
352.37680 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37681 ++	XSetWindowAttributes attr;
352.37682 ++	Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
352.37683 ++	Pixmap pixmap;
352.37684 ++	struct dri3_fence fence;
352.37685 ++	Window root, win;
352.37686 ++	unsigned int width, height;
352.37687 ++	unsigned border, depth;
352.37688 ++	int x, y, ret = 1;
352.37689 ++	const char *phase;
352.37690 ++	uint64_t msc;
352.37691 ++
352.37692 ++	root = DefaultRootWindow(dpy);
352.37693 ++	XGetGeometry(dpy, root,
352.37694 ++		     &win, &x, &y,
352.37695 ++		     &width, &height, &border, &depth);
352.37696 ++
352.37697 ++	_x_error_occurred = 0;
352.37698 ++	attr.override_redirect = 1;
352.37699 ++	switch (dummy) {
352.37700 ++	case 0:
352.37701 ++		win = root;
352.37702 ++		phase = "root";
352.37703 ++		break;
352.37704 ++	case 1:
352.37705 ++		win = XCreateWindow(dpy, root,
352.37706 ++				    0, 0, width, height, 0, depth,
352.37707 ++				    InputOutput, visual,
352.37708 ++				    CWOverrideRedirect, &attr);
352.37709 ++		phase = "fullscreen";
352.37710 ++		break;
352.37711 ++	case 2:
352.37712 ++		width /= 2;
352.37713 ++		height /= 2;
352.37714 ++		win = XCreateWindow(dpy, root,
352.37715 ++				    0, 0, width, height, 0, depth,
352.37716 ++				    InputOutput, visual,
352.37717 ++				    CWOverrideRedirect, &attr);
352.37718 ++		phase = "window";
352.37719 ++		break;
352.37720 ++	case 3:
352.37721 ++		if (!has_composite(dpy))
352.37722 ++			return 0;
352.37723 ++
352.37724 ++		win = XCreateWindow(dpy, root,
352.37725 ++				    0, 0, width, height, 0,
352.37726 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37727 ++				    InputOutput,
352.37728 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37729 ++				    CWOverrideRedirect, &attr);
352.37730 ++		XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.37731 ++		phase = "composite";
352.37732 ++		break;
352.37733 ++
352.37734 ++	default:
352.37735 ++		phase = "broken";
352.37736 ++		win = root;
352.37737 ++		abort();
352.37738 ++		break;
352.37739 ++	}
352.37740 ++
352.37741 ++	XMapWindow(dpy, win);
352.37742 ++	XSync(dpy, True);
352.37743 ++	if (_x_error_occurred)
352.37744 ++		return 1;
352.37745 ++
352.37746 ++	if (dri3_create_fence(dpy, win, &fence))
352.37747 ++		return 0;
352.37748 ++
352.37749 ++	printf("%s: Testing basic flip: %dx%d\n", phase, width, height);
352.37750 ++	fflush(stdout);
352.37751 ++	_x_error_occurred = 0;
352.37752 ++
352.37753 ++	xshmfence_reset(fence.addr);
352.37754 ++	msc = wait_vblank(dpy, win);
352.37755 ++
352.37756 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.37757 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.37758 ++			   0, /* valid */
352.37759 ++			   0, /* update */
352.37760 ++			   0, /* x_off */
352.37761 ++			   0, /* y_off */
352.37762 ++			   None,
352.37763 ++			   None, /* wait fence */
352.37764 ++			   fence.xid,
352.37765 ++			   XCB_PRESENT_OPTION_NONE,
352.37766 ++			   (msc + 64) & -64, /* target msc */
352.37767 ++			   64, /* divisor */
352.37768 ++			   32, /* remainder */
352.37769 ++			   0, NULL);
352.37770 ++	XFreePixmap(dpy, pixmap);
352.37771 ++
352.37772 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.37773 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.37774 ++			   0, /* valid */
352.37775 ++			   0, /* update */
352.37776 ++			   0, /* x_off */
352.37777 ++			   0, /* y_off */
352.37778 ++			   None,
352.37779 ++			   None, /* wait fence */
352.37780 ++			   None, /* sync fence */
352.37781 ++			   XCB_PRESENT_OPTION_NONE,
352.37782 ++			   (msc + 64) & -64, /* target msc */
352.37783 ++			   64, /* divisor */
352.37784 ++			   48, /* remainder */
352.37785 ++			   0, NULL);
352.37786 ++	XFreePixmap(dpy, pixmap);
352.37787 ++	XDestroyWindow(dpy, win);
352.37788 ++	XFlush(dpy);
352.37789 ++
352.37790 ++	ret = !!xshmfence_await(fence.addr);
352.37791 ++	dri3_fence_free(dpy, &fence);
352.37792 ++
352.37793 ++	XSync(dpy, True);
352.37794 ++	ret += !!_x_error_occurred;
352.37795 ++
352.37796 ++	return ret;
352.37797 ++}
352.37798 ++
352.37799 ++static int test_race(Display *dpy, int dummy)
352.37800 ++{
352.37801 ++	Display *mgr = XOpenDisplay(NULL);
352.37802 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37803 ++	XSetWindowAttributes attr;
352.37804 ++	Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
352.37805 ++	Pixmap pixmap;
352.37806 ++	struct dri3_fence fence;
352.37807 ++	Window root, win;
352.37808 ++	unsigned int width, height;
352.37809 ++	unsigned border, depth;
352.37810 ++	int x, y, ret = 1;
352.37811 ++	const char *phase;
352.37812 ++	uint64_t msc;
352.37813 ++
352.37814 ++	root = DefaultRootWindow(dpy);
352.37815 ++	XGetGeometry(dpy, root,
352.37816 ++		     &win, &x, &y,
352.37817 ++		     &width, &height, &border, &depth);
352.37818 ++
352.37819 ++	_x_error_occurred = 0;
352.37820 ++	attr.override_redirect = 1;
352.37821 ++	switch (dummy) {
352.37822 ++	case 0:
352.37823 ++		win = root;
352.37824 ++		phase = "root";
352.37825 ++		break;
352.37826 ++	case 1:
352.37827 ++		win = XCreateWindow(dpy, root,
352.37828 ++				    0, 0, width, height, 0, depth,
352.37829 ++				    InputOutput, visual,
352.37830 ++				    CWOverrideRedirect, &attr);
352.37831 ++		phase = "fullscreen";
352.37832 ++		break;
352.37833 ++	case 2:
352.37834 ++		width /= 2;
352.37835 ++		height /= 2;
352.37836 ++		win = XCreateWindow(dpy, root,
352.37837 ++				    0, 0, width, height, 0, depth,
352.37838 ++				    InputOutput, visual,
352.37839 ++				    CWOverrideRedirect, &attr);
352.37840 ++		phase = "window";
352.37841 ++		break;
352.37842 ++	case 3:
352.37843 ++		if (!has_composite(dpy))
352.37844 ++			return 0;
352.37845 ++
352.37846 ++		win = XCreateWindow(dpy, root,
352.37847 ++				    0, 0, width, height, 0,
352.37848 ++				    DefaultDepth(dpy, DefaultScreen(dpy)),
352.37849 ++				    InputOutput,
352.37850 ++				    DefaultVisual(dpy, DefaultScreen(dpy)),
352.37851 ++				    CWOverrideRedirect, &attr);
352.37852 ++		XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.37853 ++		phase = "composite";
352.37854 ++		break;
352.37855 ++
352.37856 ++	default:
352.37857 ++		phase = "broken";
352.37858 ++		win = root;
352.37859 ++		abort();
352.37860 ++		break;
352.37861 ++	}
352.37862 ++
352.37863 ++	XMapWindow(dpy, win);
352.37864 ++	XSync(dpy, True);
352.37865 ++	if (_x_error_occurred)
352.37866 ++		return 1;
352.37867 ++
352.37868 ++	if (dri3_create_fence(dpy, win, &fence))
352.37869 ++		return 0;
352.37870 ++
352.37871 ++	printf("%s: Testing race with manager: %dx%d\n", phase, width, height);
352.37872 ++	fflush(stdout);
352.37873 ++	_x_error_occurred = 0;
352.37874 ++
352.37875 ++	xshmfence_reset(fence.addr);
352.37876 ++	msc = wait_vblank(dpy, win);
352.37877 ++
352.37878 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.37879 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.37880 ++			   0, /* valid */
352.37881 ++			   0, /* update */
352.37882 ++			   0, /* x_off */
352.37883 ++			   0, /* y_off */
352.37884 ++			   None,
352.37885 ++			   None, /* wait fence */
352.37886 ++			   fence.xid,
352.37887 ++			   XCB_PRESENT_OPTION_NONE,
352.37888 ++			   (msc + 64) & -64, /* target msc */
352.37889 ++			   64, /* divisor */
352.37890 ++			   32, /* remainder */
352.37891 ++			   0, NULL);
352.37892 ++	XFreePixmap(dpy, pixmap);
352.37893 ++
352.37894 ++	XFlush(dpy);
352.37895 ++	XDestroyWindow(mgr, win);
352.37896 ++	XFlush(mgr);
352.37897 ++
352.37898 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.37899 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.37900 ++			   0, /* valid */
352.37901 ++			   0, /* update */
352.37902 ++			   0, /* x_off */
352.37903 ++			   0, /* y_off */
352.37904 ++			   None,
352.37905 ++			   None, /* wait fence */
352.37906 ++			   None, /* sync fence */
352.37907 ++			   XCB_PRESENT_OPTION_NONE,
352.37908 ++			   (msc + 64) & -64, /* target msc */
352.37909 ++			   64, /* divisor */
352.37910 ++			   48, /* remainder */
352.37911 ++			   0, NULL);
352.37912 ++	XFreePixmap(dpy, pixmap);
352.37913 ++	XFlush(dpy);
352.37914 ++
352.37915 ++	ret = !!xshmfence_await(fence.addr);
352.37916 ++	dri3_fence_free(dpy, &fence);
352.37917 ++
352.37918 ++	XSync(dpy, True);
352.37919 ++	ret += !!_x_error_occurred;
352.37920 ++
352.37921 ++	XCloseDisplay(mgr);
352.37922 ++
352.37923 ++	return ret;
352.37924 ++}
352.37925 ++
352.37926 ++static int has_present(Display *dpy)
352.37927 ++{
352.37928 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.37929 ++	xcb_generic_error_t *error = NULL;
352.37930 ++	void *reply;
352.37931 ++
352.37932 ++	reply = xcb_xfixes_query_version_reply(c,
352.37933 ++					       xcb_xfixes_query_version(c,
352.37934 ++									XCB_XFIXES_MAJOR_VERSION,
352.37935 ++									XCB_XFIXES_MINOR_VERSION),
352.37936 ++					       &error);
352.37937 ++	free(reply);
352.37938 ++	free(error);
352.37939 ++	if (reply == NULL) {
352.37940 ++		fprintf(stderr, "XFixes not supported on %s\n", DisplayString(dpy));
352.37941 ++		return 0;
352.37942 ++	}
352.37943 ++
352.37944 ++	reply = xcb_dri3_query_version_reply(c,
352.37945 ++					     xcb_dri3_query_version(c,
352.37946 ++								    XCB_DRI3_MAJOR_VERSION,
352.37947 ++								    XCB_DRI3_MINOR_VERSION),
352.37948 ++					     &error);
352.37949 ++	free(reply);
352.37950 ++	free(error);
352.37951 ++	if (reply == NULL) {
352.37952 ++		fprintf(stderr, "DRI3 not supported on %s\n", DisplayString(dpy));
352.37953 ++		return 0;
352.37954 ++	}
352.37955 ++
352.37956 ++	reply = xcb_present_query_version_reply(c,
352.37957 ++						xcb_present_query_version(c,
352.37958 ++									  XCB_PRESENT_MAJOR_VERSION,
352.37959 ++									  XCB_PRESENT_MINOR_VERSION),
352.37960 ++						&error);
352.37961 ++
352.37962 ++	free(reply);
352.37963 ++	free(error);
352.37964 ++	if (reply == NULL) {
352.37965 ++		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
352.37966 ++		return 0;
352.37967 ++	}
352.37968 ++
352.37969 ++	return 1;
352.37970 ++}
352.37971 ++
352.37972 ++int main(void)
352.37973 ++{
352.37974 ++	Display *dpy;
352.37975 ++	int dummy;
352.37976 ++	int error = 0;
352.37977 ++
352.37978 ++	dpy = XOpenDisplay(NULL);
352.37979 ++	if (dpy == NULL)
352.37980 ++		return 77;
352.37981 ++
352.37982 ++	if (!has_present(dpy))
352.37983 ++		return 77;
352.37984 ++
352.37985 ++	if (DPMSQueryExtension(dpy, &dummy, &dummy))
352.37986 ++		DPMSDisable(dpy);
352.37987 ++
352.37988 ++	signal(SIGALRM, SIG_IGN);
352.37989 ++	XSetErrorHandler(_check_error_handler);
352.37990 ++
352.37991 ++	for (dummy = 0; dummy <= 3; dummy++) {
352.37992 ++		error += test_basic(dpy, dummy);
352.37993 ++		error += test_race(dpy, dummy);
352.37994 ++	}
352.37995 ++
352.37996 ++	if (DPMSQueryExtension(dpy, &dummy, &dummy))
352.37997 ++		DPMSEnable(dpy);
352.37998 ++	return !!error;
352.37999 ++}
352.38000 +diff --git a/test/present-speed.c b/test/present-speed.c
352.38001 +new file mode 100644
352.38002 +index 00000000..eccde931
352.38003 +--- /dev/null
352.38004 ++++ b/test/present-speed.c
352.38005 +@@ -0,0 +1,1015 @@
352.38006 ++/*
352.38007 ++ * Copyright (c) 2015 Intel Corporation
352.38008 ++ *
352.38009 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.38010 ++ * copy of this software and associated documentation files (the "Software"),
352.38011 ++ * to deal in the Software without restriction, including without limitation
352.38012 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.38013 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.38014 ++ * Software is furnished to do so, subject to the following conditions:
352.38015 ++ *
352.38016 ++ * The above copyright notice and this permission notice (including the next
352.38017 ++ * paragraph) shall be included in all copies or substantial portions of the
352.38018 ++ * Software.
352.38019 ++ *
352.38020 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.38021 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.38022 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.38023 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.38024 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
352.38025 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
352.38026 ++ * SOFTWARE.
352.38027 ++ *
352.38028 ++ */
352.38029 ++
352.38030 ++#ifdef HAVE_CONFIG_H
352.38031 ++#include "config.h"
352.38032 ++#endif
352.38033 ++
352.38034 ++#include <X11/Xlib.h>
352.38035 ++#include <X11/Xatom.h>
352.38036 ++#include <X11/Xlib-xcb.h>
352.38037 ++#include <X11/xshmfence.h>
352.38038 ++#include <X11/Xutil.h>
352.38039 ++#include <X11/Xlibint.h>
352.38040 ++#include <X11/extensions/Xcomposite.h>
352.38041 ++#include <X11/extensions/Xdamage.h>
352.38042 ++#include <X11/extensions/dpms.h>
352.38043 ++#include <X11/extensions/randr.h>
352.38044 ++#include <X11/extensions/Xrandr.h>
352.38045 ++#include <xcb/xcb.h>
352.38046 ++#include <xcb/present.h>
352.38047 ++#include <xcb/dri3.h>
352.38048 ++#include <xcb/xfixes.h>
352.38049 ++#include <xf86drm.h>
352.38050 ++#include <i915_drm.h>
352.38051 ++
352.38052 ++#include <stdio.h>
352.38053 ++#include <string.h>
352.38054 ++#include <fcntl.h>
352.38055 ++#include <unistd.h>
352.38056 ++#include <assert.h>
352.38057 ++#include <errno.h>
352.38058 ++#include <setjmp.h>
352.38059 ++#include <signal.h>
352.38060 ++#include <sys/wait.h>
352.38061 ++
352.38062 ++#include "dri3.h"
352.38063 ++
352.38064 ++static int _x_error_occurred;
352.38065 ++static uint32_t stamp;
352.38066 ++
352.38067 ++struct list {
352.38068 ++    struct list *next, *prev;
352.38069 ++};
352.38070 ++
352.38071 ++static void
352.38072 ++list_init(struct list *list)
352.38073 ++{
352.38074 ++    list->next = list->prev = list;
352.38075 ++}
352.38076 ++
352.38077 ++static inline void
352.38078 ++__list_add(struct list *entry,
352.38079 ++	    struct list *prev,
352.38080 ++	    struct list *next)
352.38081 ++{
352.38082 ++    next->prev = entry;
352.38083 ++    entry->next = next;
352.38084 ++    entry->prev = prev;
352.38085 ++    prev->next = entry;
352.38086 ++}
352.38087 ++
352.38088 ++static inline void
352.38089 ++list_add(struct list *entry, struct list *head)
352.38090 ++{
352.38091 ++    __list_add(entry, head, head->next);
352.38092 ++}
352.38093 ++
352.38094 ++static inline void
352.38095 ++__list_del(struct list *prev, struct list *next)
352.38096 ++{
352.38097 ++	next->prev = prev;
352.38098 ++	prev->next = next;
352.38099 ++}
352.38100 ++
352.38101 ++static inline void
352.38102 ++_list_del(struct list *entry)
352.38103 ++{
352.38104 ++    __list_del(entry->prev, entry->next);
352.38105 ++}
352.38106 ++
352.38107 ++static inline void
352.38108 ++list_move(struct list *list, struct list *head)
352.38109 ++{
352.38110 ++	if (list->prev != head) {
352.38111 ++		_list_del(list);
352.38112 ++		list_add(list, head);
352.38113 ++	}
352.38114 ++}
352.38115 ++
352.38116 ++#define __container_of(ptr, sample, member)				\
352.38117 ++    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
352.38118 ++
352.38119 ++#define list_for_each_entry(pos, head, member)				\
352.38120 ++    for (pos = __container_of((head)->next, pos, member);		\
352.38121 ++	 &pos->member != (head);					\
352.38122 ++	 pos = __container_of(pos->member.next, pos, member))
352.38123 ++
352.38124 ++static int
352.38125 ++_check_error_handler(Display     *display,
352.38126 ++		     XErrorEvent *event)
352.38127 ++{
352.38128 ++	if (_x_error_occurred < 0)
352.38129 ++		return True;
352.38130 ++
352.38131 ++	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
352.38132 ++	       DisplayString(display),
352.38133 ++	       event->serial,
352.38134 ++	       event->error_code,
352.38135 ++	       event->request_code,
352.38136 ++	       event->minor_code);
352.38137 ++	_x_error_occurred++;
352.38138 ++	return False; /* ignored */
352.38139 ++}
352.38140 ++
352.38141 ++static double elapsed(const struct timespec *start,
352.38142 ++		      const struct timespec *end)
352.38143 ++{
352.38144 ++	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
352.38145 ++}
352.38146 ++
352.38147 ++struct buffer {
352.38148 ++	struct list link;
352.38149 ++	Pixmap pixmap;
352.38150 ++	struct dri3_fence fence;
352.38151 ++	int fd;
352.38152 ++	int busy;
352.38153 ++	int id;
352.38154 ++};
352.38155 ++
352.38156 ++#define DRI3 1
352.38157 ++#define NOCOPY 2
352.38158 ++#define ASYNC 4
352.38159 ++static void run(Display *dpy, Window win, const char *name, unsigned options)
352.38160 ++{
352.38161 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.38162 ++	struct timespec start, end;
352.38163 ++#define N_BACK 8
352.38164 ++	char test_name[128];
352.38165 ++	struct buffer buffer[N_BACK];
352.38166 ++	struct list mru;
352.38167 ++	Window root;
352.38168 ++	unsigned int width, height;
352.38169 ++	unsigned border, depth;
352.38170 ++	unsigned present_flags = 0;
352.38171 ++	xcb_xfixes_region_t update = 0;
352.38172 ++	int completed = 0;
352.38173 ++	int queued = 0;
352.38174 ++	uint32_t eid = 0;
352.38175 ++	void *Q = NULL;
352.38176 ++	int i, n;
352.38177 ++
352.38178 ++	list_init(&mru);
352.38179 ++
352.38180 ++	XGetGeometry(dpy, win,
352.38181 ++		     &root, &i, &n, &width, &height, &border, &depth);
352.38182 ++
352.38183 ++	_x_error_occurred = 0;
352.38184 ++
352.38185 ++	for (n = 0; n < N_BACK; n++) {
352.38186 ++		buffer[n].pixmap = xcb_generate_id(c);
352.38187 ++		xcb_create_pixmap(c, depth, buffer[n].pixmap, win,
352.38188 ++				  width, height);
352.38189 ++		buffer[n].fence.xid = 0;
352.38190 ++		buffer[n].fd = -1;
352.38191 ++		buffer[n].id = n;
352.38192 ++		if (options & DRI3) {
352.38193 ++			xcb_dri3_buffer_from_pixmap_reply_t *reply;
352.38194 ++			int *fds;
352.38195 ++
352.38196 ++			if (dri3_create_fence(dpy, win, &buffer[n].fence))
352.38197 ++				return;
352.38198 ++
352.38199 ++			reply = xcb_dri3_buffer_from_pixmap_reply (c,
352.38200 ++								   xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
352.38201 ++								   NULL);
352.38202 ++			if (reply == NULL)
352.38203 ++				return;
352.38204 ++
352.38205 ++			fds = xcb_dri3_buffer_from_pixmap_reply_fds (c, reply);
352.38206 ++			buffer[n].fd = fds[0];
352.38207 ++			free(reply);
352.38208 ++
352.38209 ++			/* start idle */
352.38210 ++			xshmfence_trigger(buffer[n].fence.addr);
352.38211 ++		}
352.38212 ++		buffer[n].busy = 0;
352.38213 ++		list_add(&buffer[n].link, &mru);
352.38214 ++	}
352.38215 ++	if (options & ASYNC)
352.38216 ++		present_flags |= XCB_PRESENT_OPTION_ASYNC;
352.38217 ++	if (options & NOCOPY) {
352.38218 ++		update = xcb_generate_id(c);
352.38219 ++		xcb_xfixes_create_region(c, update, 0, NULL);
352.38220 ++		present_flags |= XCB_PRESENT_OPTION_COPY;
352.38221 ++	}
352.38222 ++
352.38223 ++	if (!(options & DRI3)) {
352.38224 ++		eid = xcb_generate_id(c);
352.38225 ++		xcb_present_select_input(c, eid, win,
352.38226 ++					 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
352.38227 ++					 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
352.38228 ++		Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
352.38229 ++	}
352.38230 ++
352.38231 ++	clock_gettime(CLOCK_MONOTONIC, &start);
352.38232 ++	do {
352.38233 ++		for (n = 0; n < 1000; n++) {
352.38234 ++			struct buffer *tmp, *b = NULL;
352.38235 ++retry:
352.38236 ++			list_for_each_entry(tmp, &mru, link) {
352.38237 ++				if (tmp->fence.xid)
352.38238 ++					tmp->busy = !xshmfence_query(tmp->fence.addr);
352.38239 ++				if (!tmp->busy) {
352.38240 ++					b = tmp;
352.38241 ++					break;
352.38242 ++				}
352.38243 ++			}
352.38244 ++			if (options & DRI3) {
352.38245 ++				if (b == NULL)
352.38246 ++					goto retry;
352.38247 ++
352.38248 ++				xshmfence_reset(b->fence.addr);
352.38249 ++				queued--;
352.38250 ++				completed++;
352.38251 ++			} else while (b == NULL) {
352.38252 ++				xcb_present_generic_event_t *ev;
352.38253 ++
352.38254 ++				ev = (xcb_present_generic_event_t *)
352.38255 ++					xcb_wait_for_special_event(c, Q);
352.38256 ++				if (ev == NULL)
352.38257 ++					abort();
352.38258 ++
352.38259 ++				do {
352.38260 ++					switch (ev->evtype) {
352.38261 ++					case XCB_PRESENT_COMPLETE_NOTIFY:
352.38262 ++						completed++;
352.38263 ++						queued--;
352.38264 ++						break;
352.38265 ++
352.38266 ++					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
352.38267 ++						{
352.38268 ++							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
352.38269 ++							assert(ie->serial < N_BACK);
352.38270 ++							buffer[ie->serial].busy = 0;
352.38271 ++							if (b == NULL)
352.38272 ++								b = &buffer[ie->serial];
352.38273 ++							break;
352.38274 ++						}
352.38275 ++					}
352.38276 ++					free(ev);
352.38277 ++				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
352.38278 ++			}
352.38279 ++
352.38280 ++			b->busy = (options & NOCOPY) == 0;
352.38281 ++			xcb_present_pixmap(c, win, b->pixmap, b->id,
352.38282 ++					   0, /* valid */
352.38283 ++					   update, /* update */
352.38284 ++					   0, /* x_off */
352.38285 ++					   0, /* y_off */
352.38286 ++					   None,
352.38287 ++					   None, /* wait fence */
352.38288 ++					   b->fence.xid,
352.38289 ++					   present_flags,
352.38290 ++					   0, /* target msc */
352.38291 ++					   0, /* divisor */
352.38292 ++					   0, /* remainder */
352.38293 ++					   0, NULL);
352.38294 ++			list_move(&b->link, &mru);
352.38295 ++			queued++;
352.38296 ++			xcb_flush(c);
352.38297 ++		}
352.38298 ++		clock_gettime(CLOCK_MONOTONIC, &end);
352.38299 ++	} while (end.tv_sec < start.tv_sec + 10);
352.38300 ++
352.38301 ++	if (options & DRI3) {
352.38302 ++		struct buffer *b;
352.38303 ++		XID pixmap;
352.38304 ++
352.38305 ++		pixmap = xcb_generate_id(c);
352.38306 ++		xcb_create_pixmap(c, depth, pixmap, win, width, height);
352.38307 ++		xcb_present_pixmap(c, win, pixmap, 0xdeadbeef,
352.38308 ++				   0, /* valid */
352.38309 ++				   None, /* update */
352.38310 ++				   0, /* x_off */
352.38311 ++				   0, /* y_off */
352.38312 ++				   None,
352.38313 ++				   None, /* wait fence */
352.38314 ++				   None,
352.38315 ++				   0,
352.38316 ++				   0, /* target msc */
352.38317 ++				   0, /* divisor */
352.38318 ++				   0, /* remainder */
352.38319 ++				   0, NULL);
352.38320 ++		xcb_flush(c);
352.38321 ++
352.38322 ++		list_for_each_entry(b, &mru, link)
352.38323 ++			xshmfence_await(b->fence.addr);
352.38324 ++
352.38325 ++		xcb_free_pixmap(c, pixmap);
352.38326 ++		completed += queued;
352.38327 ++	} else while (queued) {
352.38328 ++		xcb_present_generic_event_t *ev;
352.38329 ++
352.38330 ++		ev = (xcb_present_generic_event_t *)
352.38331 ++			xcb_wait_for_special_event(c, Q);
352.38332 ++		if (ev == NULL)
352.38333 ++			abort();
352.38334 ++
352.38335 ++		do {
352.38336 ++			switch (ev->evtype) {
352.38337 ++			case XCB_PRESENT_COMPLETE_NOTIFY:
352.38338 ++				completed++;
352.38339 ++				queued--;
352.38340 ++				break;
352.38341 ++
352.38342 ++			case XCB_PRESENT_EVENT_IDLE_NOTIFY:
352.38343 ++				break;
352.38344 ++			}
352.38345 ++			free(ev);
352.38346 ++		} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
352.38347 ++	}
352.38348 ++	clock_gettime(CLOCK_MONOTONIC, &end);
352.38349 ++
352.38350 ++	if (update)
352.38351 ++		xcb_xfixes_destroy_region(c, update);
352.38352 ++	for (n = 0; n < N_BACK; n++) {
352.38353 ++		if (buffer[n].fence.xid)
352.38354 ++			dri3_fence_free(dpy, &buffer[n].fence);
352.38355 ++		if (buffer[n].fd != -1)
352.38356 ++			close(buffer[n].fd);
352.38357 ++		xcb_free_pixmap(c, buffer[n].pixmap);
352.38358 ++	}
352.38359 ++
352.38360 ++	if (Q) {
352.38361 ++		xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
352.38362 ++		XSync(dpy, True);
352.38363 ++		xcb_unregister_for_special_event(c, Q);
352.38364 ++	}
352.38365 ++
352.38366 ++	test_name[0] = '\0';
352.38367 ++	if (options) {
352.38368 ++		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
352.38369 ++			 options & NOCOPY ? " no-copy" : "",
352.38370 ++			 options & DRI3 ? " dri3" : "",
352.38371 ++			 options & ASYNC ? " async" : "");
352.38372 ++	}
352.38373 ++	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
352.38374 ++	       name, test_name,
352.38375 ++	       completed, elapsed(&start, &end) / 1000000,
352.38376 ++	       elapsed(&start, &end) / completed,
352.38377 ++	       completed / (elapsed(&start, &end) / 1000000));
352.38378 ++}
352.38379 ++
352.38380 ++struct perpixel {
352.38381 ++	Window win;
352.38382 ++	struct buffer buffer[N_BACK];
352.38383 ++	struct list mru;
352.38384 ++	uint32_t eid;
352.38385 ++	void *Q;
352.38386 ++	int queued;
352.38387 ++};
352.38388 ++
352.38389 ++static void perpixel(Display *dpy,
352.38390 ++		     int max_width, int max_height, unsigned options)
352.38391 ++{
352.38392 ++	//const int sz = max_width * max_height;
352.38393 ++	const int sz = 1048;
352.38394 ++	struct perpixel *pp;
352.38395 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.38396 ++	struct timespec start, end;
352.38397 ++	char test_name[128];
352.38398 ++	unsigned present_flags = 0;
352.38399 ++	xcb_xfixes_region_t update = 0;
352.38400 ++	int completed = 0;
352.38401 ++	int i, n;
352.38402 ++
352.38403 ++	pp = calloc(sz, sizeof(*pp));
352.38404 ++	if (!pp)
352.38405 ++		return;
352.38406 ++
352.38407 ++	for (i = 0; i < sz; i++) {
352.38408 ++		XSetWindowAttributes attr = { .override_redirect = 1 };
352.38409 ++		int depth = DefaultDepth(dpy, DefaultScreen(dpy));
352.38410 ++		pp[i].win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.38411 ++					  i % max_width, i / max_width, 1, 1, 0, depth,
352.38412 ++					  InputOutput,
352.38413 ++					  DefaultVisual(dpy, DefaultScreen(dpy)),
352.38414 ++					  CWOverrideRedirect, &attr);
352.38415 ++		XMapWindow(dpy, pp[i].win);
352.38416 ++		list_init(&pp[i].mru);
352.38417 ++		for (n = 0; n < N_BACK; n++) {
352.38418 ++			pp[i].buffer[n].pixmap = xcb_generate_id(c);
352.38419 ++			xcb_create_pixmap(c, depth, pp[i].buffer[n].pixmap,
352.38420 ++					  pp[i].win, 1, 1);
352.38421 ++			pp[i].buffer[n].fence.xid = 0;
352.38422 ++			pp[i].buffer[n].fd = -1;
352.38423 ++			pp[i].buffer[n].id = n;
352.38424 ++			if (options & DRI3) {
352.38425 ++				xcb_dri3_buffer_from_pixmap_reply_t *reply;
352.38426 ++				int *fds;
352.38427 ++
352.38428 ++				if (dri3_create_fence(dpy, pp[i].win, &pp[i].buffer[n].fence))
352.38429 ++					return;
352.38430 ++
352.38431 ++				reply = xcb_dri3_buffer_from_pixmap_reply(c,
352.38432 ++									  xcb_dri3_buffer_from_pixmap(c, pp[i].buffer[n].pixmap),
352.38433 ++									  NULL);
352.38434 ++				if (reply == NULL)
352.38435 ++					return;
352.38436 ++
352.38437 ++				fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, reply);
352.38438 ++				pp[i].buffer[n].fd = fds[0];
352.38439 ++				free(reply);
352.38440 ++
352.38441 ++				/* start idle */
352.38442 ++				xshmfence_trigger(pp[i].buffer[n].fence.addr);
352.38443 ++			}
352.38444 ++			pp[i].buffer[n].busy = 0;
352.38445 ++			list_add(&pp[i].buffer[n].link, &pp[i].mru);
352.38446 ++		}
352.38447 ++
352.38448 ++		if (!(options & DRI3)) {
352.38449 ++			pp[i].eid = xcb_generate_id(c);
352.38450 ++			xcb_present_select_input(c, pp[i].eid, pp[i].win,
352.38451 ++						 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
352.38452 ++						 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
352.38453 ++			pp[i].Q = xcb_register_for_special_xge(c, &xcb_present_id, pp[i].eid, &stamp);
352.38454 ++		}
352.38455 ++		pp[i].queued = 0;
352.38456 ++	}
352.38457 ++
352.38458 ++	XSync(dpy, True);
352.38459 ++	_x_error_occurred = 0;
352.38460 ++
352.38461 ++	if (options & ASYNC)
352.38462 ++		present_flags |= XCB_PRESENT_OPTION_ASYNC;
352.38463 ++	if (options & NOCOPY) {
352.38464 ++		update = xcb_generate_id(c);
352.38465 ++		xcb_xfixes_create_region(c, update, 0, NULL);
352.38466 ++		present_flags |= XCB_PRESENT_OPTION_COPY;
352.38467 ++	}
352.38468 ++
352.38469 ++	clock_gettime(CLOCK_MONOTONIC, &start);
352.38470 ++	do {
352.38471 ++		for (i = 0; i < sz; i++) {
352.38472 ++			struct buffer *tmp, *b = NULL;
352.38473 ++retry:
352.38474 ++			list_for_each_entry(tmp, &pp[i].mru, link) {
352.38475 ++				if (tmp->fence.xid)
352.38476 ++					tmp->busy = !xshmfence_query(tmp->fence.addr);
352.38477 ++				if (!tmp->busy) {
352.38478 ++					b = tmp;
352.38479 ++					break;
352.38480 ++				}
352.38481 ++			}
352.38482 ++			if (options & DRI3) {
352.38483 ++				if (b == NULL)
352.38484 ++					goto retry;
352.38485 ++
352.38486 ++				xshmfence_reset(b->fence.addr);
352.38487 ++				pp[i].queued--;
352.38488 ++				completed++;
352.38489 ++			} else while (b == NULL) {
352.38490 ++				xcb_present_generic_event_t *ev;
352.38491 ++
352.38492 ++				ev = (xcb_present_generic_event_t *)
352.38493 ++					xcb_wait_for_special_event(c, pp[i].Q);
352.38494 ++				if (ev == NULL)
352.38495 ++					abort();
352.38496 ++
352.38497 ++				do {
352.38498 ++					switch (ev->evtype) {
352.38499 ++					case XCB_PRESENT_COMPLETE_NOTIFY:
352.38500 ++						completed++;
352.38501 ++						pp[i].queued--;
352.38502 ++						break;
352.38503 ++
352.38504 ++					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
352.38505 ++						{
352.38506 ++							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
352.38507 ++							assert(ie->serial < N_BACK);
352.38508 ++							pp[i].buffer[ie->serial].busy = 0;
352.38509 ++							if (b == NULL)
352.38510 ++								b = &pp[i].buffer[ie->serial];
352.38511 ++							break;
352.38512 ++						}
352.38513 ++					}
352.38514 ++					free(ev);
352.38515 ++				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
352.38516 ++			}
352.38517 ++
352.38518 ++			b->busy = (options & NOCOPY) == 0;
352.38519 ++			xcb_present_pixmap(c, pp[i].win, b->pixmap, b->id,
352.38520 ++					   0, /* valid */
352.38521 ++					   update, /* update */
352.38522 ++					   0, /* x_off */
352.38523 ++					   0, /* y_off */
352.38524 ++					   None,
352.38525 ++					   None, /* wait fence */
352.38526 ++					   b->fence.xid,
352.38527 ++					   present_flags,
352.38528 ++					   0, /* target msc */
352.38529 ++					   0, /* divisor */
352.38530 ++					   0, /* remainder */
352.38531 ++					   0, NULL);
352.38532 ++			list_move(&b->link, &pp[i].mru);
352.38533 ++			pp[i].queued++;
352.38534 ++		}
352.38535 ++		xcb_flush(c);
352.38536 ++		clock_gettime(CLOCK_MONOTONIC, &end);
352.38537 ++	} while (end.tv_sec < start.tv_sec + 10);
352.38538 ++
352.38539 ++	for (i = 0; i < sz; i++) {
352.38540 ++		if (options & DRI3) {
352.38541 ++			int depth = DefaultDepth(dpy, DefaultScreen(dpy));
352.38542 ++			struct buffer *b;
352.38543 ++			XID pixmap;
352.38544 ++
352.38545 ++			pixmap = xcb_generate_id(c);
352.38546 ++			xcb_create_pixmap(c, depth, pixmap, pp[i].win, 1, 1);
352.38547 ++			xcb_present_pixmap(c, pp[i].win, pixmap, 0xdeadbeef,
352.38548 ++					   0, /* valid */
352.38549 ++					   None, /* update */
352.38550 ++					   0, /* x_off */
352.38551 ++					   0, /* y_off */
352.38552 ++					   None,
352.38553 ++					   None, /* wait fence */
352.38554 ++					   None,
352.38555 ++					   0,
352.38556 ++					   0, /* target msc */
352.38557 ++					   0, /* divisor */
352.38558 ++					   0, /* remainder */
352.38559 ++					   0, NULL);
352.38560 ++			xcb_flush(c);
352.38561 ++
352.38562 ++			list_for_each_entry(b, &pp[i].mru, link)
352.38563 ++				xshmfence_await(b->fence.addr);
352.38564 ++
352.38565 ++			xcb_free_pixmap(c, pixmap);
352.38566 ++			completed += pp[i].queued;
352.38567 ++		} else while (pp[i].queued) {
352.38568 ++			xcb_present_generic_event_t *ev;
352.38569 ++
352.38570 ++			ev = (xcb_present_generic_event_t *)
352.38571 ++				xcb_wait_for_special_event(c, pp[i].Q);
352.38572 ++			if (ev == NULL)
352.38573 ++				abort();
352.38574 ++
352.38575 ++			do {
352.38576 ++				switch (ev->evtype) {
352.38577 ++				case XCB_PRESENT_COMPLETE_NOTIFY:
352.38578 ++					completed++;
352.38579 ++					pp[i].queued--;
352.38580 ++					break;
352.38581 ++
352.38582 ++				case XCB_PRESENT_EVENT_IDLE_NOTIFY:
352.38583 ++					break;
352.38584 ++				}
352.38585 ++				free(ev);
352.38586 ++			} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
352.38587 ++		}
352.38588 ++	}
352.38589 ++	clock_gettime(CLOCK_MONOTONIC, &end);
352.38590 ++
352.38591 ++	if (update)
352.38592 ++		xcb_xfixes_destroy_region(c, update);
352.38593 ++
352.38594 ++	for (i = 0; i < sz; i++) {
352.38595 ++		for (n = 0; n < N_BACK; n++) {
352.38596 ++			if (pp[i].buffer[n].fence.xid)
352.38597 ++				dri3_fence_free(dpy, &pp[i].buffer[n].fence);
352.38598 ++			if (pp[i].buffer[n].fd != -1)
352.38599 ++				close(pp[i].buffer[n].fd);
352.38600 ++			xcb_free_pixmap(c, pp[i].buffer[n].pixmap);
352.38601 ++		}
352.38602 ++
352.38603 ++		if (pp[i].Q) {
352.38604 ++			xcb_discard_reply(c, xcb_present_select_input_checked(c, pp[i].eid, pp[i].win, 0).sequence);
352.38605 ++			XSync(dpy, True);
352.38606 ++			xcb_unregister_for_special_event(c, pp[i].Q);
352.38607 ++		}
352.38608 ++
352.38609 ++		XDestroyWindow(dpy, pp[i].win);
352.38610 ++	}
352.38611 ++	free(pp);
352.38612 ++
352.38613 ++	test_name[0] = '\0';
352.38614 ++	if (options) {
352.38615 ++		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
352.38616 ++			 options & NOCOPY ? " no-copy" : "",
352.38617 ++			 options & DRI3 ? " dri3" : "",
352.38618 ++			 options & ASYNC ? " async" : "");
352.38619 ++	}
352.38620 ++	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
352.38621 ++	       __func__, test_name,
352.38622 ++	       completed, elapsed(&start, &end) / 1000000,
352.38623 ++	       elapsed(&start, &end) / completed,
352.38624 ++	       completed / (elapsed(&start, &end) / 1000000));
352.38625 ++}
352.38626 ++
352.38627 ++static int isqrt(int x)
352.38628 ++{
352.38629 ++	int i;
352.38630 ++
352.38631 ++	for (i = 2; i*i < x; i++)
352.38632 ++		;
352.38633 ++	return i;
352.38634 ++}
352.38635 ++
352.38636 ++struct sibling {
352.38637 ++	pthread_t thread;
352.38638 ++	Display *dpy;
352.38639 ++	int x, y;
352.38640 ++	int width, height;
352.38641 ++	unsigned options;
352.38642 ++};
352.38643 ++
352.38644 ++static void *sibling(void *arg)
352.38645 ++{
352.38646 ++	struct sibling *s = arg;
352.38647 ++	XSetWindowAttributes attr = { .override_redirect = 1 };
352.38648 ++	Window win = XCreateWindow(s->dpy, DefaultRootWindow(s->dpy),
352.38649 ++				   s->x, s->y, s->width, s->height, 0,
352.38650 ++				   DefaultDepth(s->dpy, DefaultScreen(s->dpy)),
352.38651 ++				   InputOutput,
352.38652 ++				   DefaultVisual(s->dpy, DefaultScreen(s->dpy)),
352.38653 ++				   CWOverrideRedirect, &attr);
352.38654 ++	XMapWindow(s->dpy, win);
352.38655 ++	run(s->dpy, win, "sibling", s->options);
352.38656 ++	return NULL;
352.38657 ++}
352.38658 ++
352.38659 ++static void siblings(Display *dpy,
352.38660 ++		     int max_width, int max_height, int ncpus, unsigned options)
352.38661 ++{
352.38662 ++	int sq_ncpus = isqrt(ncpus);
352.38663 ++	int width = max_width / sq_ncpus;
352.38664 ++	int height = max_height/ sq_ncpus;
352.38665 ++	struct sibling s[ncpus];
352.38666 ++	int child;
352.38667 ++
352.38668 ++	if (ncpus <= 1)
352.38669 ++		return;
352.38670 ++
352.38671 ++	for (child = 0; child < ncpus; child++) {
352.38672 ++		s[child].dpy = dpy;
352.38673 ++		s[child].x = (child % sq_ncpus) * width;
352.38674 ++		s[child].y = (child / sq_ncpus) * height;
352.38675 ++		s[child].width = width;
352.38676 ++		s[child].height = height;
352.38677 ++		s[child].options = options;
352.38678 ++		pthread_create(&s[child].thread, NULL, sibling, &s[child]);
352.38679 ++	}
352.38680 ++
352.38681 ++	for (child = 0; child < ncpus; child++)
352.38682 ++		pthread_join(s[child].thread, NULL);
352.38683 ++}
352.38684 ++
352.38685 ++static void cousins(int max_width, int max_height, int ncpus, unsigned options)
352.38686 ++{
352.38687 ++	int sq_ncpus = isqrt(ncpus);
352.38688 ++	int width = max_width / sq_ncpus;
352.38689 ++	int height = max_height/ sq_ncpus;
352.38690 ++	int child;
352.38691 ++
352.38692 ++	if (ncpus <= 1)
352.38693 ++		return;
352.38694 ++
352.38695 ++	for (child = 0; child < ncpus; child++) {
352.38696 ++		for (; fork() == 0; exit(0)) {
352.38697 ++			int x = (child % sq_ncpus) * width;
352.38698 ++			int y = (child / sq_ncpus) * height;
352.38699 ++			XSetWindowAttributes attr = { .override_redirect = 1 };
352.38700 ++			Display *dpy = XOpenDisplay(NULL);
352.38701 ++			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
352.38702 ++						   x, y, width, height, 0,
352.38703 ++						   DefaultDepth(dpy, DefaultScreen(dpy)),
352.38704 ++						   InputOutput,
352.38705 ++						   DefaultVisual(dpy, DefaultScreen(dpy)),
352.38706 ++						   CWOverrideRedirect, &attr);
352.38707 ++			XMapWindow(dpy, win);
352.38708 ++			run(dpy, win, "cousin", options);
352.38709 ++		}
352.38710 ++	}
352.38711 ++
352.38712 ++	while (child) {
352.38713 ++		int status = -1;
352.38714 ++		pid_t pid = wait(&status);
352.38715 ++		if (pid == -1)
352.38716 ++			continue;
352.38717 ++		child--;
352.38718 ++	}
352.38719 ++}
352.38720 ++
352.38721 ++static int has_present(Display *dpy)
352.38722 ++{
352.38723 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.38724 ++	xcb_generic_error_t *error = NULL;
352.38725 ++	void *reply;
352.38726 ++
352.38727 ++	reply = xcb_present_query_version_reply(c,
352.38728 ++						xcb_present_query_version(c,
352.38729 ++									  XCB_PRESENT_MAJOR_VERSION,
352.38730 ++									  XCB_PRESENT_MINOR_VERSION),
352.38731 ++						&error);
352.38732 ++
352.38733 ++	free(reply);
352.38734 ++	free(error);
352.38735 ++	if (reply == NULL) {
352.38736 ++		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
352.38737 ++		return 0;
352.38738 ++	}
352.38739 ++
352.38740 ++	return 1;
352.38741 ++}
352.38742 ++
352.38743 ++static int has_composite(Display *dpy)
352.38744 ++{
352.38745 ++	int event, error;
352.38746 ++	int major, minor;
352.38747 ++
352.38748 ++	if (!XDamageQueryExtension (dpy, &event, &error))
352.38749 ++		return 0;
352.38750 ++
352.38751 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
352.38752 ++		return 0;
352.38753 ++
352.38754 ++	XCompositeQueryVersion(dpy, &major, &minor);
352.38755 ++
352.38756 ++	return major > 0 || minor >= 4;
352.38757 ++}
352.38758 ++
352.38759 ++static int dri3_query_version(Display *dpy, int *major, int *minor)
352.38760 ++{
352.38761 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.38762 ++	xcb_dri3_query_version_reply_t *reply;
352.38763 ++	xcb_generic_error_t *error;
352.38764 ++
352.38765 ++	*major = *minor = -1;
352.38766 ++
352.38767 ++	reply = xcb_dri3_query_version_reply(c,
352.38768 ++					     xcb_dri3_query_version(c,
352.38769 ++								    XCB_DRI3_MAJOR_VERSION,
352.38770 ++								    XCB_DRI3_MINOR_VERSION),
352.38771 ++					     &error);
352.38772 ++	free(error);
352.38773 ++	if (reply == NULL)
352.38774 ++		return -1;
352.38775 ++
352.38776 ++	*major = reply->major_version;
352.38777 ++	*minor = reply->minor_version;
352.38778 ++	free(reply);
352.38779 ++
352.38780 ++	return 0;
352.38781 ++}
352.38782 ++
352.38783 ++static int has_dri3(Display *dpy)
352.38784 ++{
352.38785 ++	const xcb_query_extension_reply_t *ext;
352.38786 ++	int major, minor;
352.38787 ++
352.38788 ++	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
352.38789 ++	if (ext == NULL || !ext->present)
352.38790 ++		return 0;
352.38791 ++
352.38792 ++	if (dri3_query_version(dpy, &major, &minor) < 0)
352.38793 ++		return 0;
352.38794 ++
352.38795 ++	return major >= 0;
352.38796 ++}
352.38797 ++
352.38798 ++static int has_xfixes(Display *dpy)
352.38799 ++{
352.38800 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.38801 ++	const xcb_query_extension_reply_t *ext;
352.38802 ++	void *reply;
352.38803 ++
352.38804 ++	ext = xcb_get_extension_data(c, &xcb_xfixes_id);
352.38805 ++	if (ext == NULL || !ext->present)
352.38806 ++		return 0;
352.38807 ++
352.38808 ++	reply = xcb_xfixes_query_version_reply(c,
352.38809 ++					       xcb_xfixes_query_version(c,
352.38810 ++									XCB_XFIXES_MAJOR_VERSION,
352.38811 ++									XCB_XFIXES_MINOR_VERSION),
352.38812 ++					       NULL);
352.38813 ++	free(reply);
352.38814 ++
352.38815 ++	return reply != NULL;
352.38816 ++}
352.38817 ++
352.38818 ++static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
352.38819 ++{
352.38820 ++	XRRScreenResources *res;
352.38821 ++
352.38822 ++	res = XRRGetScreenResourcesCurrent(dpy, window);
352.38823 ++	if (res == NULL)
352.38824 ++		res = XRRGetScreenResources(dpy, window);
352.38825 ++
352.38826 ++	return res;
352.38827 ++}
352.38828 ++
352.38829 ++static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
352.38830 ++{
352.38831 ++	int i;
352.38832 ++
352.38833 ++	for (i = 0; i < res->nmode; i++) {
352.38834 ++		if (res->modes[i].id == id)
352.38835 ++			return &res->modes[i];
352.38836 ++	}
352.38837 ++
352.38838 ++	return NULL;
352.38839 ++}
352.38840 ++
352.38841 ++static void fullscreen(Display *dpy, Window win)
352.38842 ++{
352.38843 ++	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
352.38844 ++	XChangeProperty(dpy, win,
352.38845 ++			XInternAtom(dpy, "_NET_WM_STATE", False),
352.38846 ++			XA_ATOM, 32, PropModeReplace,
352.38847 ++			(unsigned char *)&atom, 1);
352.38848 ++}
352.38849 ++
352.38850 ++static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
352.38851 ++{
352.38852 ++	Window root = DefaultRootWindow(dpy);
352.38853 ++	Window win;
352.38854 ++	XSetWindowAttributes attr;
352.38855 ++	int i, j;
352.38856 ++
352.38857 ++	attr.override_redirect = 1;
352.38858 ++
352.38859 ++	run(dpy, root, "off", options);
352.38860 ++	XSync(dpy, True);
352.38861 ++
352.38862 ++	for (i = 0; i < res->noutput; i++) {
352.38863 ++		XRROutputInfo *output;
352.38864 ++		XRRModeInfo *mode;
352.38865 ++
352.38866 ++		output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
352.38867 ++		if (output == NULL)
352.38868 ++			continue;
352.38869 ++
352.38870 ++		mode = NULL;
352.38871 ++		if (res->nmode)
352.38872 ++			mode = lookup_mode(res, output->modes[0]);
352.38873 ++
352.38874 ++		for (j = 0; mode && j < 2*output->ncrtc; j++) {
352.38875 ++			int c = j;
352.38876 ++			if (c >= output->ncrtc)
352.38877 ++				c = 2*output->ncrtc - j - 1;
352.38878 ++
352.38879 ++			printf("[%d, %d] -- OUTPUT:%ld, CRTC:%ld: %dx%d\n",
352.38880 ++			       i, c, (long)res->outputs[i], (long)output->crtcs[c],
352.38881 ++			       mode->width, mode->height);
352.38882 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
352.38883 ++					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
352.38884 ++
352.38885 ++			run(dpy, root, "root", options);
352.38886 ++			XSync(dpy, True);
352.38887 ++
352.38888 ++			win = XCreateWindow(dpy, root,
352.38889 ++					    0, 0, mode->width, mode->height, 0,
352.38890 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.38891 ++					    InputOutput,
352.38892 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.38893 ++					    CWOverrideRedirect, &attr);
352.38894 ++			fullscreen(dpy, win);
352.38895 ++			XMapWindow(dpy, win);
352.38896 ++			run(dpy, win, "fullscreen", options);
352.38897 ++			XDestroyWindow(dpy, win);
352.38898 ++			XSync(dpy, True);
352.38899 ++
352.38900 ++			win = XCreateWindow(dpy, root,
352.38901 ++					    0, 0, mode->width, mode->height, 0,
352.38902 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.38903 ++					    InputOutput,
352.38904 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.38905 ++					    CWOverrideRedirect, &attr);
352.38906 ++			XMapWindow(dpy, win);
352.38907 ++			run(dpy, win, "windowed", options);
352.38908 ++			XDestroyWindow(dpy, win);
352.38909 ++			XSync(dpy, True);
352.38910 ++
352.38911 ++			if (has_composite(dpy)) {
352.38912 ++				Damage damage;
352.38913 ++
352.38914 ++				_x_error_occurred = 0;
352.38915 ++				win = XCreateWindow(dpy, root,
352.38916 ++						    0, 0, mode->width, mode->height, 0,
352.38917 ++						    DefaultDepth(dpy, DefaultScreen(dpy)),
352.38918 ++						    InputOutput,
352.38919 ++						    DefaultVisual(dpy, DefaultScreen(dpy)),
352.38920 ++						    CWOverrideRedirect, &attr);
352.38921 ++				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.38922 ++				damage = XDamageCreate(dpy, win, XDamageReportNonEmpty);
352.38923 ++				XMapWindow(dpy, win);
352.38924 ++				XSync(dpy, True);
352.38925 ++				if (!_x_error_occurred)
352.38926 ++					run(dpy, win, "composited", options);
352.38927 ++				XDamageDestroy(dpy, damage);
352.38928 ++				XDestroyWindow(dpy, win);
352.38929 ++				XSync(dpy, True);
352.38930 ++			}
352.38931 ++
352.38932 ++			win = XCreateWindow(dpy, root,
352.38933 ++					    0, 0, mode->width/2, mode->height/2, 0,
352.38934 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.38935 ++					    InputOutput,
352.38936 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.38937 ++					    CWOverrideRedirect, &attr);
352.38938 ++			XMapWindow(dpy, win);
352.38939 ++			run(dpy, win, "half", options);
352.38940 ++			XDestroyWindow(dpy, win);
352.38941 ++			XSync(dpy, True);
352.38942 ++
352.38943 ++			perpixel(dpy, mode->width, mode->height, options);
352.38944 ++
352.38945 ++			siblings(dpy, mode->width, mode->height,
352.38946 ++				 sysconf(_SC_NPROCESSORS_ONLN),
352.38947 ++				 options);
352.38948 ++
352.38949 ++			cousins(mode->width, mode->height,
352.38950 ++				sysconf(_SC_NPROCESSORS_ONLN),
352.38951 ++				options);
352.38952 ++
352.38953 ++			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
352.38954 ++					 0, 0, None, RR_Rotate_0, NULL, 0);
352.38955 ++		}
352.38956 ++
352.38957 ++		XRRFreeOutputInfo(output);
352.38958 ++	}
352.38959 ++
352.38960 ++}
352.38961 ++
352.38962 ++int main(void)
352.38963 ++{
352.38964 ++	Display *dpy;
352.38965 ++	XRRScreenResources *res;
352.38966 ++	XRRCrtcInfo **original_crtc;
352.38967 ++	int i;
352.38968 ++
352.38969 ++	XInitThreads();
352.38970 ++
352.38971 ++	dpy = XOpenDisplay(NULL);
352.38972 ++	if (dpy == NULL)
352.38973 ++		return 77;
352.38974 ++
352.38975 ++	if (!has_present(dpy))
352.38976 ++		return 77;
352.38977 ++
352.38978 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.38979 ++		DPMSDisable(dpy);
352.38980 ++
352.38981 ++	signal(SIGALRM, SIG_IGN);
352.38982 ++	XSetErrorHandler(_check_error_handler);
352.38983 ++
352.38984 ++	res = NULL;
352.38985 ++	if (XRRQueryVersion(dpy, &i, &i))
352.38986 ++		res = _XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
352.38987 ++	if (res == NULL)
352.38988 ++		return 77;
352.38989 ++
352.38990 ++	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
352.38991 ++	for (i = 0; i < res->ncrtc; i++)
352.38992 ++		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
352.38993 ++
352.38994 ++	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
352.38995 ++	for (i = 0; i < res->ncrtc; i++)
352.38996 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.38997 ++				 0, 0, None, RR_Rotate_0, NULL, 0);
352.38998 ++
352.38999 ++	loop(dpy, res, 0);
352.39000 ++	loop(dpy, res, ASYNC);
352.39001 ++	if (has_xfixes(dpy))
352.39002 ++		loop(dpy, res, NOCOPY);
352.39003 ++	if (has_dri3(dpy)) {
352.39004 ++		loop(dpy, res, DRI3);
352.39005 ++		loop(dpy, res, DRI3 | ASYNC);
352.39006 ++	}
352.39007 ++
352.39008 ++	for (i = 0; i < res->ncrtc; i++)
352.39009 ++		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
352.39010 ++				 original_crtc[i]->x,
352.39011 ++				 original_crtc[i]->y,
352.39012 ++				 original_crtc[i]->mode,
352.39013 ++				 original_crtc[i]->rotation,
352.39014 ++				 original_crtc[i]->outputs,
352.39015 ++				 original_crtc[i]->noutput);
352.39016 ++
352.39017 ++	if (DPMSQueryExtension(dpy, &i, &i))
352.39018 ++		DPMSEnable(dpy);
352.39019 ++	return 0;
352.39020 ++}
352.39021 +diff --git a/test/present-test.c b/test/present-test.c
352.39022 +index 6b562eb0..5a12a24f 100644
352.39023 +--- a/test/present-test.c
352.39024 ++++ b/test/present-test.c
352.39025 +@@ -31,7 +31,9 @@
352.39026 + #include <X11/xshmfence.h>
352.39027 + #include <X11/Xutil.h>
352.39028 + #include <X11/Xlibint.h>
352.39029 ++#include <X11/extensions/dpms.h>
352.39030 + #include <X11/extensions/randr.h>
352.39031 ++#include <X11/extensions/Xcomposite.h>
352.39032 + #include <X11/extensions/Xrandr.h>
352.39033 + #include <X11/extensions/Xrender.h>
352.39034 + #include <X11/extensions/XShm.h>
352.39035 +@@ -44,6 +46,8 @@
352.39036 + #endif
352.39037 + #include <xcb/xcb.h>
352.39038 + #include <xcb/present.h>
352.39039 ++#include <xcb/xfixes.h>
352.39040 ++#include <xcb/dri3.h>
352.39041 + #include <xf86drm.h>
352.39042 + #include <i915_drm.h>
352.39043 + 
352.39044 +@@ -134,12 +138,14 @@ static void *setup_msc(Display *dpy,  Window win)
352.39045 + 	return q;
352.39046 + }
352.39047 + 
352.39048 +-static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
352.39049 ++static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc, uint64_t *ust)
352.39050 + {
352.39051 + 	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39052 ++	static uint32_t serial = 1;
352.39053 + 	uint64_t msc = 0;
352.39054 ++	int complete = 0;
352.39055 + 
352.39056 +-	xcb_present_notify_msc(c, win, 0, 0, 0, 0);
352.39057 ++	xcb_present_notify_msc(c, win, serial ^ 0xcc00ffee, 0, 0, 0);
352.39058 + 	xcb_flush(c);
352.39059 + 
352.39060 + 	do {
352.39061 +@@ -151,82 +157,1268 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
352.39062 + 			break;
352.39063 + 
352.39064 + 		ce = (xcb_present_complete_notify_event_t *)ev;
352.39065 +-		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
352.39066 ++		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
352.39067 ++		    ce->serial == (serial ^ 0xcc00ffee)) {
352.39068 ++			msc = ce->msc;
352.39069 ++			if (ust)
352.39070 ++				*ust = ce->ust;
352.39071 ++			complete = 1;
352.39072 ++		}
352.39073 ++		free(ev);
352.39074 ++	} while (!complete);
352.39075 ++
352.39076 ++	if ((int64_t)(msc - last_msc) < 0) {
352.39077 ++		printf("Invalid MSC: was %llu, now %llu\n",
352.39078 ++		       (long long)last_msc, (long long)msc);
352.39079 ++	}
352.39080 ++
352.39081 ++	if (++serial == 0)
352.39082 ++		serial = 1;
352.39083 ++
352.39084 ++	return msc;
352.39085 ++}
352.39086 ++
352.39087 ++static uint64_t wait_vblank(Display *dpy, Window win, void *q)
352.39088 ++{
352.39089 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39090 ++	static uint32_t serial = 1;
352.39091 ++	uint64_t msc = 0;
352.39092 ++	int complete = 0;
352.39093 ++
352.39094 ++	xcb_present_notify_msc(c, win, serial ^ 0xdeadbeef, 0, 1, 0);
352.39095 ++	xcb_flush(c);
352.39096 ++
352.39097 ++	do {
352.39098 ++		xcb_present_complete_notify_event_t *ce;
352.39099 ++		xcb_generic_event_t *ev;
352.39100 ++
352.39101 ++		ev = xcb_wait_for_special_event(c, q);
352.39102 ++		if (ev == NULL)
352.39103 ++			break;
352.39104 ++
352.39105 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39106 ++		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
352.39107 ++		    ce->serial == (serial ^ 0xdeadbeef)) {
352.39108 + 			msc = ce->msc;
352.39109 ++			complete = 1;
352.39110 ++		}
352.39111 ++		free(ev);
352.39112 ++	} while (!complete);
352.39113 ++
352.39114 ++	if (++serial == 0)
352.39115 ++		serial = 1;
352.39116 ++
352.39117 ++	return msc;
352.39118 ++}
352.39119 ++
352.39120 ++static uint64_t msc_interval(Display *dpy, Window win, void *q)
352.39121 ++{
352.39122 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39123 ++	uint64_t msc, ust;
352.39124 ++	int complete = 0;
352.39125 ++
352.39126 ++	msc = check_msc(dpy, win, q, 0, NULL);
352.39127 ++
352.39128 ++	xcb_present_notify_msc(c, win, 0xc0ffee00, msc, 0, 0);
352.39129 ++	xcb_present_notify_msc(c, win, 0xc0ffee01, msc + 10, 0, 0);
352.39130 ++	xcb_flush(c);
352.39131 ++
352.39132 ++	ust = msc = 0;
352.39133 ++	do {
352.39134 ++		xcb_present_complete_notify_event_t *ce;
352.39135 ++		xcb_generic_event_t *ev;
352.39136 ++
352.39137 ++		ev = xcb_wait_for_special_event(c, q);
352.39138 ++		if (ev == NULL)
352.39139 ++			break;
352.39140 ++
352.39141 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39142 ++		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
352.39143 ++		    ce->serial == 0xc0ffee00) {
352.39144 ++			msc -= ce->msc;
352.39145 ++			ust -= ce->ust;
352.39146 ++			complete++;
352.39147 ++		}
352.39148 ++		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
352.39149 ++		    ce->serial == 0xc0ffee01) {
352.39150 ++			msc += ce->msc;
352.39151 ++			ust += ce->ust;
352.39152 ++			complete++;
352.39153 ++		}
352.39154 ++		free(ev);
352.39155 ++	} while (complete != 2);
352.39156 ++
352.39157 ++	printf("10 frame interval: msc=%lld, ust=%lld\n",
352.39158 ++	       (long long)msc, (long long)ust);
352.39159 ++	XSync(dpy, True);
352.39160 ++	if (msc == 0)
352.39161 ++		return 0;
352.39162 ++
352.39163 ++	return (ust + msc/2) / msc;
352.39164 ++}
352.39165 ++
352.39166 ++static void teardown_msc(Display *dpy, void *q)
352.39167 ++{
352.39168 ++	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
352.39169 ++}
352.39170 ++
352.39171 ++static int test_whole(Display *dpy, Window win, const char *phase)
352.39172 ++{
352.39173 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39174 ++	Pixmap pixmap;
352.39175 ++	struct dri3_fence fence;
352.39176 ++	Window root;
352.39177 ++	unsigned int width, height;
352.39178 ++	unsigned border, depth;
352.39179 ++	int x, y, ret = 1;
352.39180 ++
352.39181 ++	XGetGeometry(dpy, win,
352.39182 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39183 ++
352.39184 ++	if (dri3_create_fence(dpy, win, &fence))
352.39185 ++		return 0;
352.39186 ++
352.39187 ++	printf("%s: Testing simple flip: %dx%d\n", phase, width, height);
352.39188 ++	_x_error_occurred = 0;
352.39189 ++
352.39190 ++	xshmfence_reset(fence.addr);
352.39191 ++
352.39192 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39193 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.39194 ++			   0, /* valid */
352.39195 ++			   0, /* update */
352.39196 ++			   0, /* x_off */
352.39197 ++			   0, /* y_off */
352.39198 ++			   None,
352.39199 ++			   None, /* wait fence */
352.39200 ++			   fence.xid,
352.39201 ++			   XCB_PRESENT_OPTION_NONE,
352.39202 ++			   0, /* target msc */
352.39203 ++			   0, /* divisor */
352.39204 ++			   0, /* remainder */
352.39205 ++			   0, NULL);
352.39206 ++	XFreePixmap(dpy, pixmap);
352.39207 ++
352.39208 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39209 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.39210 ++			   0, /* valid */
352.39211 ++			   0, /* update */
352.39212 ++			   0, /* x_off */
352.39213 ++			   0, /* y_off */
352.39214 ++			   None,
352.39215 ++			   None, /* wait fence */
352.39216 ++			   None, /* sync fence */
352.39217 ++			   XCB_PRESENT_OPTION_NONE,
352.39218 ++			   0, /* target msc */
352.39219 ++			   0, /* divisor */
352.39220 ++			   0, /* remainder */
352.39221 ++			   0, NULL);
352.39222 ++	XFreePixmap(dpy, pixmap);
352.39223 ++	XFlush(dpy);
352.39224 ++
352.39225 ++	ret = !!xshmfence_await(fence.addr);
352.39226 ++	dri3_fence_free(dpy, &fence);
352.39227 ++
352.39228 ++	XSync(dpy, True);
352.39229 ++	ret += !!_x_error_occurred;
352.39230 ++
352.39231 ++	return ret;
352.39232 ++}
352.39233 ++
352.39234 ++static uint64_t flush_flips(Display *dpy, Window win, Pixmap pixmap, void *Q, uint64_t *ust)
352.39235 ++{
352.39236 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39237 ++	uint64_t msc;
352.39238 ++	int complete;
352.39239 ++
352.39240 ++	msc = check_msc(dpy, win, Q, 0, NULL);
352.39241 ++	xcb_present_pixmap(c, win, pixmap,
352.39242 ++			   0xdeadbeef, /* serial */
352.39243 ++			   0, /* valid */
352.39244 ++			   0, /* update */
352.39245 ++			   0, /* x_off */
352.39246 ++			   0, /* y_off */
352.39247 ++			   None,
352.39248 ++			   None, /* wait fence */
352.39249 ++			   None,
352.39250 ++			   XCB_PRESENT_OPTION_NONE,
352.39251 ++			   msc + 60, /* target msc */
352.39252 ++			   0, /* divisor */
352.39253 ++			   0, /* remainder */
352.39254 ++			   0, NULL);
352.39255 ++	xcb_flush(c);
352.39256 ++	complete = 0;
352.39257 ++	do {
352.39258 ++		xcb_present_complete_notify_event_t *ce;
352.39259 ++		xcb_generic_event_t *ev;
352.39260 ++
352.39261 ++		ev = xcb_wait_for_special_event(c, Q);
352.39262 ++		if (ev == NULL)
352.39263 ++			break;
352.39264 ++
352.39265 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39266 ++		complete = (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP &&
352.39267 ++			    ce->serial == 0xdeadbeef);
352.39268 ++		free(ev);
352.39269 ++	} while (!complete);
352.39270 ++	XSync(dpy, True);
352.39271 ++
352.39272 ++	return check_msc(dpy, win, Q, msc, ust);
352.39273 ++}
352.39274 ++
352.39275 ++static int test_double(Display *dpy, Window win, const char *phase, void *Q)
352.39276 ++{
352.39277 ++#define COUNT (15*60)
352.39278 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39279 ++	Pixmap pixmap;
352.39280 ++	Window root;
352.39281 ++	unsigned int width, height;
352.39282 ++	unsigned border, depth;
352.39283 ++	int x, y, n, ret;
352.39284 ++	struct {
352.39285 ++		uint64_t msc, ust;
352.39286 ++	} frame[COUNT+1];
352.39287 ++	int offset = 0;
352.39288 ++
352.39289 ++	XGetGeometry(dpy, win,
352.39290 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39291 ++
352.39292 ++	printf("%s: Testing flip double buffering: %dx%d\n", phase, width, height);
352.39293 ++	_x_error_occurred = 0;
352.39294 ++
352.39295 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39296 ++	flush_flips(dpy, win, pixmap, Q, NULL);
352.39297 ++	for (n = 0; n <= COUNT; n++) {
352.39298 ++		int complete;
352.39299 ++
352.39300 ++		xcb_present_pixmap(c, win, pixmap, n,
352.39301 ++				   0, /* valid */
352.39302 ++				   0, /* update */
352.39303 ++				   0, /* x_off */
352.39304 ++				   0, /* y_off */
352.39305 ++				   None,
352.39306 ++				   None, /* wait fence */
352.39307 ++				   None,
352.39308 ++				   XCB_PRESENT_OPTION_NONE,
352.39309 ++				   0, /* target msc */
352.39310 ++				   0, /* divisor */
352.39311 ++				   0, /* remainder */
352.39312 ++				   0, NULL);
352.39313 ++		xcb_flush(c);
352.39314 ++
352.39315 ++		complete = 0;
352.39316 ++		do {
352.39317 ++			xcb_present_complete_notify_event_t *ce;
352.39318 ++			xcb_generic_event_t *ev;
352.39319 ++
352.39320 ++			ev = xcb_wait_for_special_event(c, Q);
352.39321 ++			if (ev == NULL)
352.39322 ++				break;
352.39323 ++
352.39324 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.39325 ++			if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP &&
352.39326 ++			    ce->serial == n) {
352.39327 ++				frame[n].msc = ce->msc;
352.39328 ++				frame[n].ust = ce->ust;
352.39329 ++				complete = 1;
352.39330 ++			}
352.39331 ++			free(ev);
352.39332 ++		} while (!complete);
352.39333 ++	}
352.39334 ++	XFreePixmap(dpy, pixmap);
352.39335 ++
352.39336 ++	XSync(dpy, True);
352.39337 ++	ret = !!_x_error_occurred;
352.39338 ++
352.39339 ++	if (frame[COUNT].msc - frame[0].msc != COUNT) {
352.39340 ++		printf("Expected %d frames interval, %d elapsed instead\n",
352.39341 ++		       COUNT, (int)(frame[COUNT].msc - frame[0].msc));
352.39342 ++		for (n = 0; n <= COUNT; n++) {
352.39343 ++			if (frame[n].msc - frame[0].msc != n + offset) {
352.39344 ++				printf("frame[%d]: msc=%03lld, ust=%lld\n", n,
352.39345 ++				       (long long)(frame[n].msc - frame[0].msc),
352.39346 ++				       (long long)(frame[n].ust - frame[0].ust));
352.39347 ++				offset = frame[n].msc - frame[0].msc - n;
352.39348 ++				ret++;
352.39349 ++			}
352.39350 ++		}
352.39351 ++	}
352.39352 ++
352.39353 ++	return ret;
352.39354 ++}
352.39355 ++
352.39356 ++static int test_future(Display *dpy, Window win, const char *phase, void *Q)
352.39357 ++{
352.39358 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39359 ++	Pixmap pixmap;
352.39360 ++	struct dri3_fence fence;
352.39361 ++	Window root;
352.39362 ++	unsigned int width, height;
352.39363 ++	unsigned border, depth;
352.39364 ++	int x, y, ret = 0, n;
352.39365 ++	uint64_t msc, ust;
352.39366 ++	int complete, count;
352.39367 ++	int early = 0, late = 0;
352.39368 ++	int earliest = 0, latest = 0;
352.39369 ++	uint64_t interval;
352.39370 ++
352.39371 ++	XGetGeometry(dpy, win,
352.39372 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39373 ++
352.39374 ++	if (dri3_create_fence(dpy, win, &fence))
352.39375 ++		return 0;
352.39376 ++
352.39377 ++	printf("%s: Testing flips into the future: %dx%d\n", phase, width, height);
352.39378 ++	_x_error_occurred = 0;
352.39379 ++
352.39380 ++	interval = msc_interval(dpy, win, Q);
352.39381 ++	if (interval == 0) {
352.39382 ++		printf("Zero delay between frames\n");
352.39383 ++		return 1;
352.39384 ++	}
352.39385 ++
352.39386 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39387 ++	msc = flush_flips(dpy, win, pixmap, Q, &ust);
352.39388 ++	for (n = 1; n <= 10; n++)
352.39389 ++		xcb_present_pixmap(c, win, pixmap,
352.39390 ++				   n, /* serial */
352.39391 ++				   0, /* valid */
352.39392 ++				   0, /* update */
352.39393 ++				   0, /* x_off */
352.39394 ++				   0, /* y_off */
352.39395 ++				   None,
352.39396 ++				   None, /* wait fence */
352.39397 ++				   None,
352.39398 ++				   XCB_PRESENT_OPTION_NONE,
352.39399 ++				   msc + 60 + n*15*60, /* target msc */
352.39400 ++				   0, /* divisor */
352.39401 ++				   0, /* remainder */
352.39402 ++				   0, NULL);
352.39403 ++	xcb_present_pixmap(c, win, pixmap,
352.39404 ++			   0xdeadbeef, /* serial */
352.39405 ++			   0, /* valid */
352.39406 ++			   0, /* update */
352.39407 ++			   0, /* x_off */
352.39408 ++			   0, /* y_off */
352.39409 ++			   None,
352.39410 ++			   None, /* wait fence */
352.39411 ++			   None,
352.39412 ++			   XCB_PRESENT_OPTION_NONE,
352.39413 ++			   msc + 60 + n*15*60, /* target msc */
352.39414 ++			   0, /* divisor */
352.39415 ++			   0, /* remainder */
352.39416 ++			   0, NULL);
352.39417 ++	xcb_flush(c);
352.39418 ++
352.39419 ++	complete = 0;
352.39420 ++	count = 0;
352.39421 ++	do {
352.39422 ++		xcb_present_complete_notify_event_t *ce;
352.39423 ++		xcb_generic_event_t *ev;
352.39424 ++
352.39425 ++		ev = xcb_wait_for_special_event(c, Q);
352.39426 ++		if (ev == NULL)
352.39427 ++			break;
352.39428 ++
352.39429 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39430 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
352.39431 ++
352.39432 ++		if (ce->serial == 0xdeadbeef) {
352.39433 ++			int64_t time;
352.39434 ++
352.39435 ++			time = ce->ust - (ust + (60 + 15*60*n) * interval);
352.39436 ++			if (time < -(int64_t)interval) {
352.39437 ++				fprintf(stderr,
352.39438 ++					"\tflips completed too early by %lldms\n",
352.39439 ++					(long long)(-time / 1000));
352.39440 ++			} else if (time > (int64_t)interval) {
352.39441 ++				fprintf(stderr,
352.39442 ++					"\tflips completed too late by %lldms\n",
352.39443 ++					(long long)(time / 1000));
352.39444 ++			}
352.39445 ++			complete = 1;
352.39446 ++		} else {
352.39447 ++			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
352.39448 ++			if (diff < 0) {
352.39449 ++				if (-diff > earliest) {
352.39450 ++					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
352.39451 ++					earliest = -diff;
352.39452 ++				}
352.39453 ++				early++;
352.39454 ++				ret++;
352.39455 ++			} else if (diff > 0) {
352.39456 ++				if (diff > latest) {
352.39457 ++					fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
352.39458 ++					latest = diff;
352.39459 ++				}
352.39460 ++				late++;
352.39461 ++				ret++;
352.39462 ++			}
352.39463 ++			count++;
352.39464 ++		}
352.39465 ++		free(ev);
352.39466 ++	} while (!complete);
352.39467 ++
352.39468 ++	if (early)
352.39469 ++		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
352.39470 ++	if (late)
352.39471 ++		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
352.39472 ++
352.39473 ++	if (count != 10) {
352.39474 ++		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", 10 - count);
352.39475 ++		ret++;
352.39476 ++
352.39477 ++		do {
352.39478 ++			xcb_present_complete_notify_event_t *ce;
352.39479 ++			xcb_generic_event_t *ev;
352.39480 ++
352.39481 ++			ev = xcb_wait_for_special_event(c, Q);
352.39482 ++			if (ev == NULL)
352.39483 ++				break;
352.39484 ++
352.39485 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.39486 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
352.39487 ++			free(ev);
352.39488 ++		} while (++count != 10);
352.39489 ++	}
352.39490 ++
352.39491 ++	ret += !!_x_error_occurred;
352.39492 ++
352.39493 ++	return ret;
352.39494 ++}
352.39495 ++
352.39496 ++static int test_exhaustion(Display *dpy, Window win, const char *phase, void *Q)
352.39497 ++{
352.39498 ++#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
352.39499 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39500 ++	Pixmap pixmap;
352.39501 ++	struct dri3_fence fence[2];
352.39502 ++	Window root;
352.39503 ++	xcb_xfixes_region_t region;
352.39504 ++	unsigned int width, height;
352.39505 ++	unsigned border, depth;
352.39506 ++	int x, y, ret = 0, n;
352.39507 ++	uint64_t target, final;
352.39508 ++
352.39509 ++	XGetGeometry(dpy, win,
352.39510 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39511 ++
352.39512 ++	if (dri3_create_fence(dpy, win, &fence[0]) ||
352.39513 ++	    dri3_create_fence(dpy, win, &fence[1]))
352.39514 ++		return 0;
352.39515 ++
352.39516 ++	printf("%s: Testing flips with long vblank queues: %dx%d\n", phase, width, height);
352.39517 ++	_x_error_occurred = 0;
352.39518 ++
352.39519 ++	region = xcb_generate_id(c);
352.39520 ++	xcb_xfixes_create_region(c, region, 0, NULL);
352.39521 ++
352.39522 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39523 ++	xshmfence_reset(fence[0].addr);
352.39524 ++	xshmfence_reset(fence[1].addr);
352.39525 ++	target = check_msc(dpy, win, Q, 0, NULL);
352.39526 ++	for (n = N_VBLANKS; n--; )
352.39527 ++		xcb_present_pixmap(c, win, pixmap, 0,
352.39528 ++				   0, /* valid */
352.39529 ++				   region, /* update */
352.39530 ++				   0, /* x_off */
352.39531 ++				   0, /* y_off */
352.39532 ++				   None,
352.39533 ++				   None, /* wait fence */
352.39534 ++				   None,
352.39535 ++				   XCB_PRESENT_OPTION_NONE,
352.39536 ++				   target + N_VBLANKS, /* target msc */
352.39537 ++				   1, /* divisor */
352.39538 ++				   0, /* remainder */
352.39539 ++				   0, NULL);
352.39540 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.39541 ++			   region, /* valid */
352.39542 ++			   region, /* update */
352.39543 ++			   0, /* x_off */
352.39544 ++			   0, /* y_off */
352.39545 ++			   None,
352.39546 ++			   None, /* wait fence */
352.39547 ++			   fence[0].xid,
352.39548 ++			   XCB_PRESENT_OPTION_NONE,
352.39549 ++			   target, /* target msc */
352.39550 ++			   0, /* divisor */
352.39551 ++			   0, /* remainder */
352.39552 ++			   0, NULL);
352.39553 ++	for (n = 1; n < N_VBLANKS; n++)
352.39554 ++		xcb_present_pixmap(c, win, pixmap, 0,
352.39555 ++				   region, /* valid */
352.39556 ++				   region, /* update */
352.39557 ++				   0, /* x_off */
352.39558 ++				   0, /* y_off */
352.39559 ++				   None,
352.39560 ++				   None, /* wait fence */
352.39561 ++				   None,
352.39562 ++				   XCB_PRESENT_OPTION_NONE,
352.39563 ++				   target + n, /* target msc */
352.39564 ++				   0, /* divisor */
352.39565 ++				   0, /* remainder */
352.39566 ++				   0, NULL);
352.39567 ++	xcb_present_pixmap(c, win, pixmap, 0,
352.39568 ++			   region, /* valid */
352.39569 ++			   region, /* update */
352.39570 ++			   0, /* x_off */
352.39571 ++			   0, /* y_off */
352.39572 ++			   None,
352.39573 ++			   None, /* wait fence */
352.39574 ++			   fence[1].xid,
352.39575 ++			   XCB_PRESENT_OPTION_NONE,
352.39576 ++			   target + N_VBLANKS, /* target msc */
352.39577 ++			   0, /* divisor */
352.39578 ++			   0, /* remainder */
352.39579 ++			   0, NULL);
352.39580 ++	xcb_flush(c);
352.39581 ++
352.39582 ++	ret += !!xshmfence_await(fence[0].addr);
352.39583 ++	final = check_msc(dpy, win, Q, 0, NULL);
352.39584 ++	if (final < target) {
352.39585 ++		printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
352.39586 ++		       (long long)final, (long long)target);
352.39587 ++		ret++;
352.39588 ++	} else if (final > target + 1) {
352.39589 ++		printf("\tFirst flip too late, MSC was %llu, expected %llu\n",
352.39590 ++		       (long long)final, (long long)target);
352.39591 ++		ret++;
352.39592 ++	}
352.39593 ++
352.39594 ++	ret += !!xshmfence_await(fence[1].addr);
352.39595 ++	final = check_msc(dpy, win, Q, 0, NULL);
352.39596 ++	if (final < target + N_VBLANKS) {
352.39597 ++		printf("\tLast flip too early, MSC was %llu, expected %llu\n",
352.39598 ++		       (long long)final, (long long)(target + N_VBLANKS));
352.39599 ++		ret++;
352.39600 ++	} else if (final > target + N_VBLANKS + 1) {
352.39601 ++		printf("\tLast flip too late, MSC was %llu, expected %llu\n",
352.39602 ++		       (long long)final, (long long)(target + N_VBLANKS));
352.39603 ++		ret++;
352.39604 ++	}
352.39605 ++
352.39606 ++	flush_flips(dpy, win, pixmap, Q, NULL);
352.39607 ++
352.39608 ++	XFreePixmap(dpy, pixmap);
352.39609 ++	xcb_xfixes_destroy_region(c, region);
352.39610 ++	dri3_fence_free(dpy, &fence[1]);
352.39611 ++	dri3_fence_free(dpy, &fence[0]);
352.39612 ++
352.39613 ++	XSync(dpy, True);
352.39614 ++	ret += !!_x_error_occurred;
352.39615 ++
352.39616 ++	return ret;
352.39617 ++#undef N_VBLANKS
352.39618 ++}
352.39619 ++
352.39620 ++static int test_accuracy(Display *dpy, Window win, const char *phase, void *Q)
352.39621 ++{
352.39622 ++#define N_VBLANKS (60 * 120) /* ~2 minutes */
352.39623 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39624 ++	Pixmap pixmap;
352.39625 ++	Window root;
352.39626 ++	unsigned int width, height;
352.39627 ++	unsigned border, depth;
352.39628 ++	int x, y, ret = 0, n;
352.39629 ++	uint64_t target;
352.39630 ++	int early = 0, late = 0;
352.39631 ++	int earliest = 0, latest = 0;
352.39632 ++	int complete, count;
352.39633 ++
352.39634 ++	XGetGeometry(dpy, win,
352.39635 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39636 ++
352.39637 ++	printf("%s: Testing flip accuracy: %dx%d\n", phase, width, height);
352.39638 ++	_x_error_occurred = 0;
352.39639 ++
352.39640 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39641 ++	target = flush_flips(dpy, win, pixmap, Q, NULL);
352.39642 ++	for (n = 0; n <= N_VBLANKS; n++)
352.39643 ++		xcb_present_pixmap(c, win, pixmap,
352.39644 ++				   n, /* serial */
352.39645 ++				   0, /* valid */
352.39646 ++				   0, /* update */
352.39647 ++				   0, /* x_off */
352.39648 ++				   0, /* y_off */
352.39649 ++				   None,
352.39650 ++				   None, /* wait fence */
352.39651 ++				   None,
352.39652 ++				   XCB_PRESENT_OPTION_NONE,
352.39653 ++				   target + 60 + n, /* target msc */
352.39654 ++				   0, /* divisor */
352.39655 ++				   0, /* remainder */
352.39656 ++				   0, NULL);
352.39657 ++	xcb_present_pixmap(c, win, pixmap,
352.39658 ++			   0xdeadbeef, /* serial */
352.39659 ++			   0, /* valid */
352.39660 ++			   0, /* update */
352.39661 ++			   0, /* x_off */
352.39662 ++			   0, /* y_off */
352.39663 ++			   None,
352.39664 ++			   None, /* wait fence */
352.39665 ++			   None,
352.39666 ++			   XCB_PRESENT_OPTION_NONE,
352.39667 ++			   target + 60 + n, /* target msc */
352.39668 ++			   0, /* divisor */
352.39669 ++			   0, /* remainder */
352.39670 ++			   0, NULL);
352.39671 ++	xcb_flush(c);
352.39672 ++
352.39673 ++	complete = 0;
352.39674 ++	count = 0;
352.39675 ++	do {
352.39676 ++		xcb_present_complete_notify_event_t *ce;
352.39677 ++		xcb_generic_event_t *ev;
352.39678 ++
352.39679 ++		ev = xcb_wait_for_special_event(c, Q);
352.39680 ++		if (ev == NULL)
352.39681 ++			break;
352.39682 ++
352.39683 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39684 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
352.39685 ++
352.39686 ++		if (ce->serial != 0xdeadbeef) {
352.39687 ++			int diff = (int64_t)(ce->msc - (target + ce->serial + 60));
352.39688 ++			if (diff < 0) {
352.39689 ++				if (-diff > earliest) {
352.39690 ++					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
352.39691 ++					earliest = -diff;
352.39692 ++				}
352.39693 ++				early++;
352.39694 ++				ret++;
352.39695 ++			} else if (diff > 0) {
352.39696 ++				if (diff > latest) {
352.39697 ++					fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
352.39698 ++					latest = diff;
352.39699 ++				}
352.39700 ++				late++;
352.39701 ++				ret++;
352.39702 ++			}
352.39703 ++			count++;
352.39704 ++		} else
352.39705 ++			complete = 1;
352.39706 + 		free(ev);
352.39707 +-	} while (msc == 0);
352.39708 ++	} while (!complete);
352.39709 ++
352.39710 ++	if (early)
352.39711 ++		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
352.39712 ++	if (late)
352.39713 ++		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
352.39714 ++
352.39715 ++	if (count != N_VBLANKS+1) {
352.39716 ++		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", N_VBLANKS+1 - count);
352.39717 ++		ret++;
352.39718 ++		do {
352.39719 ++			xcb_present_complete_notify_event_t *ce;
352.39720 ++			xcb_generic_event_t *ev;
352.39721 ++
352.39722 ++			ev = xcb_wait_for_special_event(c, Q);
352.39723 ++			if (ev == NULL)
352.39724 ++				break;
352.39725 ++
352.39726 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.39727 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
352.39728 ++			free(ev);
352.39729 ++		} while (++count != N_VBLANKS+1);
352.39730 ++	}
352.39731 ++
352.39732 ++	XFreePixmap(dpy, pixmap);
352.39733 ++
352.39734 ++	XSync(dpy, True);
352.39735 ++	ret += !!_x_error_occurred;
352.39736 ++
352.39737 ++	return ret;
352.39738 ++#undef N_VBLANKS
352.39739 ++}
352.39740 ++
352.39741 ++static int test_modulus(Display *dpy, Window win, const char *phase, void *Q)
352.39742 ++{
352.39743 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39744 ++	Pixmap pixmap;
352.39745 ++	Window root;
352.39746 ++	unsigned int width, height;
352.39747 ++	unsigned border, depth;
352.39748 ++	xcb_xfixes_region_t region;
352.39749 ++	int x, y, ret = 0;
352.39750 ++	uint64_t target;
352.39751 ++	int early = 0, late = 0;
352.39752 ++	int earliest = 0, latest = 0;
352.39753 ++	int complete, expect, count;
352.39754 ++
352.39755 ++	XGetGeometry(dpy, win,
352.39756 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.39757 ++
352.39758 ++	printf("%s: Testing flip modulus: %dx%d\n", phase, width, height);
352.39759 ++	_x_error_occurred = 0;
352.39760 ++
352.39761 ++	region = xcb_generate_id(c);
352.39762 ++	xcb_xfixes_create_region(c, region, 0, NULL);
352.39763 ++
352.39764 ++	pixmap = XCreatePixmap(dpy, win, width, height, depth);
352.39765 ++	target = flush_flips(dpy, win, pixmap, Q, NULL);
352.39766 ++	expect = 0;
352.39767 ++	for (x = 1; x <= 7; x++) {
352.39768 ++		for (y = 0; y < x; y++) {
352.39769 ++			xcb_present_pixmap(c, win, pixmap,
352.39770 ++					   y << 16 | x, /* serial */
352.39771 ++					   region, /* valid */
352.39772 ++					   region, /* update */
352.39773 ++					   0, /* x_off */
352.39774 ++					   0, /* y_off */
352.39775 ++					   None,
352.39776 ++					   None, /* wait fence */
352.39777 ++					   None,
352.39778 ++					   XCB_PRESENT_OPTION_NONE,
352.39779 ++					   0, /* target msc */
352.39780 ++					   x, /* divisor */
352.39781 ++					   y, /* remainder */
352.39782 ++					   0, NULL);
352.39783 ++			expect++;
352.39784 ++		}
352.39785 ++	}
352.39786 ++	xcb_present_pixmap(c, win, pixmap,
352.39787 ++			   0xdeadbeef, /* serial */
352.39788 ++			   0, /* valid */
352.39789 ++			   0, /* update */
352.39790 ++			   0, /* x_off */
352.39791 ++			   0, /* y_off */
352.39792 ++			   None,
352.39793 ++			   None, /* wait fence */
352.39794 ++			   None,
352.39795 ++			   XCB_PRESENT_OPTION_NONE,
352.39796 ++			   target + 2*x, /* target msc */
352.39797 ++			   0, /* divisor */
352.39798 ++			   0, /* remainder */
352.39799 ++			   0, NULL);
352.39800 ++	xcb_flush(c);
352.39801 ++
352.39802 ++	complete = 0;
352.39803 ++	count = 0;
352.39804 ++	do {
352.39805 ++		xcb_present_complete_notify_event_t *ce;
352.39806 ++		xcb_generic_event_t *ev;
352.39807 ++
352.39808 ++		ev = xcb_wait_for_special_event(c, Q);
352.39809 ++		if (ev == NULL)
352.39810 ++			break;
352.39811 ++
352.39812 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39813 ++		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
352.39814 ++			break;
352.39815 ++
352.39816 ++		assert(ce->serial);
352.39817 ++		if (ce->serial != 0xdeadbeef) {
352.39818 ++			uint64_t msc;
352.39819 ++			int diff;
352.39820 ++
352.39821 ++			x = ce->serial & 0xffff;
352.39822 ++			y = ce->serial >> 16;
352.39823 ++
352.39824 ++			msc = target;
352.39825 ++			msc -= target % x;
352.39826 ++			msc += y;
352.39827 ++			if (msc <= target)
352.39828 ++				msc += x;
352.39829 ++
352.39830 ++			diff = (int64_t)(ce->msc - msc);
352.39831 ++			if (diff < 0) {
352.39832 ++				if (-diff > earliest) {
352.39833 ++					fprintf(stderr, "\tframe (%d, %d) displayed early by %d frames\n", y, x, -diff);
352.39834 ++					earliest = -diff;
352.39835 ++				}
352.39836 ++				early++;
352.39837 ++				ret++;
352.39838 ++			} else if (diff > 0) {
352.39839 ++				if (diff > latest) {
352.39840 ++					fprintf(stderr, "\tframe (%d, %d) displayed late by %d frames\n", y, x, diff);
352.39841 ++					latest = diff;
352.39842 ++				}
352.39843 ++				late++;
352.39844 ++				ret++;
352.39845 ++			}
352.39846 ++			count++;
352.39847 ++		} else
352.39848 ++			complete = 1;
352.39849 ++		free(ev);
352.39850 ++	} while (!complete);
352.39851 ++
352.39852 ++	if (early)
352.39853 ++		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
352.39854 ++	if (late)
352.39855 ++		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
352.39856 ++
352.39857 ++	if (count != expect) {
352.39858 ++		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", expect - count);
352.39859 ++		ret++;
352.39860 ++		do {
352.39861 ++			xcb_present_complete_notify_event_t *ce;
352.39862 ++			xcb_generic_event_t *ev;
352.39863 ++
352.39864 ++			ev = xcb_wait_for_special_event(c, Q);
352.39865 ++			if (ev == NULL)
352.39866 ++				break;
352.39867 ++
352.39868 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.39869 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.39870 ++			free(ev);
352.39871 ++		} while (++count != expect);
352.39872 ++	}
352.39873 ++
352.39874 ++	XFreePixmap(dpy, pixmap);
352.39875 ++	xcb_xfixes_destroy_region(c, region);
352.39876 ++
352.39877 ++	XSync(dpy, True);
352.39878 ++	ret += !!_x_error_occurred;
352.39879 ++
352.39880 ++	return ret;
352.39881 ++}
352.39882 ++
352.39883 ++static int test_future_msc(Display *dpy, void *Q)
352.39884 ++{
352.39885 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.39886 ++	Window root = DefaultRootWindow(dpy);
352.39887 ++	int ret = 0, n;
352.39888 ++	uint64_t msc, ust;
352.39889 ++	int complete, count;
352.39890 ++	int early = 0, late = 0;
352.39891 ++	int earliest = 0, latest = 0;
352.39892 ++	uint64_t interval;
352.39893 ++
352.39894 ++	printf("Testing notifies into the future\n");
352.39895 ++	_x_error_occurred = 0;
352.39896 ++
352.39897 ++	interval = msc_interval(dpy, root, Q);
352.39898 ++	if (interval == 0) {
352.39899 ++		printf("Zero delay between frames\n");
352.39900 ++		return 1;
352.39901 ++	}
352.39902 ++	msc = check_msc(dpy, root, Q, 0, &ust);
352.39903 ++	printf("Initial msc=%llx, interval between frames %lldus\n",
352.39904 ++	       (long long)msc, (long long)interval);
352.39905 ++
352.39906 ++	for (n = 1; n <= 10; n++)
352.39907 ++		xcb_present_notify_msc(c, root, n, msc + 60 + n*15*60, 0, 0);
352.39908 ++	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n*15*60, 0, 0);
352.39909 ++	xcb_flush(c);
352.39910 ++
352.39911 ++	complete = 0;
352.39912 ++	count = 0;
352.39913 ++	do {
352.39914 ++		xcb_present_complete_notify_event_t *ce;
352.39915 ++		xcb_generic_event_t *ev;
352.39916 ++
352.39917 ++		ev = xcb_wait_for_special_event(c, Q);
352.39918 ++		if (ev == NULL)
352.39919 ++			break;
352.39920 ++
352.39921 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.39922 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.39923 ++
352.39924 ++		if (ce->serial == 0xdeadbeef) {
352.39925 ++			int64_t time, tolerance;
352.39926 ++
352.39927 ++			tolerance = 60 + 15*60*n/10;
352.39928 ++			if (tolerance < interval)
352.39929 ++				tolerance = interval;
352.39930 ++
352.39931 ++			time = ce->ust - (ust + (60 + 15*60*n) * interval);
352.39932 ++			if (time < -(int64_t)tolerance) {
352.39933 ++				fprintf(stderr,
352.39934 ++					"\tnotifies completed too early by %lldms, tolerance %lldus\n",
352.39935 ++					(long long)(-time / 1000), (long long)tolerance);
352.39936 ++			} else if (time > (int64_t)tolerance) {
352.39937 ++				fprintf(stderr,
352.39938 ++					"\tnotifies completed too late by %lldms, tolerance %lldus\n",
352.39939 ++					(long long)(time / 1000), (long long)tolerance);
352.39940 ++			}
352.39941 ++			complete = 1;
352.39942 ++		} else {
352.39943 ++			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
352.39944 ++
352.39945 ++			if (ce->serial != count + 1) {
352.39946 ++				fprintf(stderr, "vblank received out of order! expected %d, received %d\n",
352.39947 ++					count + 1, (int)ce->serial);
352.39948 ++				ret++;
352.39949 ++			}
352.39950 ++			count++;
352.39951 ++
352.39952 ++			if (diff < 0) {
352.39953 ++				if (-diff > earliest) {
352.39954 ++					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
352.39955 ++					earliest = -diff;
352.39956 ++				}
352.39957 ++				early++;
352.39958 ++				ret++;
352.39959 ++			} else if (diff > 0) {
352.39960 ++				if (diff > latest) {
352.39961 ++					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
352.39962 ++					latest = diff;
352.39963 ++				}
352.39964 ++				late++;
352.39965 ++				ret++;
352.39966 ++			}
352.39967 ++		}
352.39968 ++		free(ev);
352.39969 ++	} while (!complete);
352.39970 ++
352.39971 ++	if (early)
352.39972 ++		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
352.39973 ++	if (late)
352.39974 ++		printf("\t%d notifies too late (worst %d)!\n", late, latest);
352.39975 ++
352.39976 ++	if (count != 10) {
352.39977 ++		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", 10 - count);
352.39978 ++		ret++;
352.39979 ++		do {
352.39980 ++			xcb_present_complete_notify_event_t *ce;
352.39981 ++			xcb_generic_event_t *ev;
352.39982 ++
352.39983 ++			ev = xcb_wait_for_special_event(c, Q);
352.39984 ++			if (ev == NULL)
352.39985 ++				break;
352.39986 ++
352.39987 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.39988 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.39989 ++			free(ev);
352.39990 ++		} while (++count != 10);
352.39991 ++	}
352.39992 ++
352.39993 ++	XSync(dpy, True);
352.39994 ++	ret += !!_x_error_occurred;
352.39995 ++
352.39996 ++	return ret;
352.39997 ++}
352.39998 ++
352.39999 ++static int test_wrap_msc(Display *dpy)
352.40000 ++{
352.40001 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.40002 ++	Window root, win;
352.40003 ++	int x, y;
352.40004 ++	unsigned int width, height;
352.40005 ++	unsigned border, depth;
352.40006 ++	XSetWindowAttributes attr;
352.40007 ++	int ret = 0, n;
352.40008 ++	uint64_t msc, ust;
352.40009 ++	int complete;
352.40010 ++	uint64_t interval;
352.40011 ++	void *Q;
352.40012 ++
352.40013 ++	XGetGeometry(dpy, DefaultRootWindow(dpy),
352.40014 ++		     &root, &x, &y, &width, &height, &border, &depth);
352.40015 ++
352.40016 ++	attr.override_redirect = 1;
352.40017 ++	win = XCreateWindow(dpy, root,
352.40018 ++			    0, 0, width, height, 0, depth,
352.40019 ++			    InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
352.40020 ++			    CWOverrideRedirect, &attr);
352.40021 ++	XMapWindow(dpy, win);
352.40022 ++	XSync(dpy, True);
352.40023 ++	if (_x_error_occurred)
352.40024 ++		return 1;
352.40025 + 
352.40026 +-	if (msc < last_msc) {
352.40027 +-		printf("Invalid MSC: was %llu, now %llu\n",
352.40028 +-		       (long long)last_msc, (long long)msc);
352.40029 ++	printf("Testing wraparound notifies\n");
352.40030 ++	_x_error_occurred = 0;
352.40031 ++
352.40032 ++	Q = setup_msc(dpy, win);
352.40033 ++	interval = msc_interval(dpy, win, Q);
352.40034 ++	if (interval == 0) {
352.40035 ++		printf("Zero delay between frames\n");
352.40036 ++		return 1;
352.40037 + 	}
352.40038 ++	msc = check_msc(dpy, win, Q, 0, &ust);
352.40039 ++	printf("Initial msc=%llx, interval between frames %lldus\n",
352.40040 ++	       (long long)msc, (long long)interval);
352.40041 ++
352.40042 ++	for (n = 1; n <= 10; n++)
352.40043 ++		xcb_present_notify_msc(c, win, n,
352.40044 ++				       msc + ((long long)n<<32) + n,
352.40045 ++				       0, 0);
352.40046 ++	for (n = 1; n <= 10; n++)
352.40047 ++		xcb_present_notify_msc(c, win, -n,
352.40048 ++				       0, (long long)n << 32, 0);
352.40049 ++	xcb_present_notify_msc(c, win, 0xdeadbeef, msc + 60*10, 0, 0);
352.40050 ++	xcb_flush(c);
352.40051 + 
352.40052 +-	return msc;
352.40053 ++	complete = 0;
352.40054 ++	do {
352.40055 ++		xcb_present_complete_notify_event_t *ce;
352.40056 ++		xcb_generic_event_t *ev;
352.40057 ++
352.40058 ++		ev = xcb_wait_for_special_event(c, Q);
352.40059 ++		if (ev == NULL)
352.40060 ++			break;
352.40061 ++
352.40062 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.40063 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40064 ++
352.40065 ++		if (ce->serial == 0xdeadbeef) {
352.40066 ++			complete = 1;
352.40067 ++		} else {
352.40068 ++			fprintf(stderr,
352.40069 ++				"\tnotify %d recieved at +%llu\n",
352.40070 ++				ce->serial, ce->msc - msc);
352.40071 ++			ret++;
352.40072 ++		}
352.40073 ++		free(ev);
352.40074 ++	} while (!complete);
352.40075 ++
352.40076 ++	teardown_msc(dpy, Q);
352.40077 ++	XDestroyWindow(dpy, win);
352.40078 ++	XSync(dpy, True);
352.40079 ++
352.40080 ++	return ret;
352.40081 + }
352.40082 + 
352.40083 +-static void teardown_msc(Display *dpy, void *q)
352.40084 ++static int test_exhaustion_msc(Display *dpy, void *Q)
352.40085 + {
352.40086 +-	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
352.40087 ++#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
352.40088 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.40089 ++	Window root = DefaultRootWindow(dpy);
352.40090 ++	int ret = 0, n, complete;
352.40091 ++	int earliest = 0, early = 0;
352.40092 ++	int latest = 0, late = 0;
352.40093 ++	uint64_t msc;
352.40094 ++
352.40095 ++	printf("Testing notifies with long queues\n");
352.40096 ++	_x_error_occurred = 0;
352.40097 ++
352.40098 ++	msc = check_msc(dpy, root, Q, 0, NULL);
352.40099 ++	for (n = N_VBLANKS; n--; )
352.40100 ++		xcb_present_notify_msc(c, root, N_VBLANKS, msc + N_VBLANKS, 0, 0);
352.40101 ++	for (n = 1; n <= N_VBLANKS ; n++)
352.40102 ++		xcb_present_notify_msc(c, root, n, msc + n, 0, 0);
352.40103 ++	xcb_flush(c);
352.40104 ++
352.40105 ++	complete = 2*N_VBLANKS;
352.40106 ++	do {
352.40107 ++		xcb_present_complete_notify_event_t *ce;
352.40108 ++		xcb_generic_event_t *ev;
352.40109 ++		int diff;
352.40110 ++
352.40111 ++		ev = xcb_wait_for_special_event(c, Q);
352.40112 ++		if (ev == NULL)
352.40113 ++			break;
352.40114 ++
352.40115 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.40116 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40117 ++
352.40118 ++		diff = (int64_t)(ce->msc - msc - ce->serial);
352.40119 ++		if (diff < 0) {
352.40120 ++			if (-diff > earliest) {
352.40121 ++				fprintf(stderr, "\tnotify %d early by %d msc\n",(int)ce->serial, -diff);
352.40122 ++				earliest = -diff;
352.40123 ++			}
352.40124 ++			early++;
352.40125 ++			ret++;
352.40126 ++		} else if (diff > 0) {
352.40127 ++			if (diff > latest) {
352.40128 ++				fprintf(stderr, "\tnotify %d late by %d msc\n", (int)ce->serial, diff);
352.40129 ++				latest = diff;
352.40130 ++			}
352.40131 ++			late++;
352.40132 ++			ret++;
352.40133 ++		}
352.40134 ++		free(ev);
352.40135 ++	} while (--complete);
352.40136 ++
352.40137 ++	if (early)
352.40138 ++		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
352.40139 ++	if (late)
352.40140 ++		printf("\t%d notifies too late (worst %d)!\n", late, latest);
352.40141 ++
352.40142 ++	XSync(dpy, True);
352.40143 ++	ret += !!_x_error_occurred;
352.40144 ++
352.40145 ++	return ret;
352.40146 ++#undef N_VBLANKS
352.40147 + }
352.40148 +-static int test_whole(Display *dpy)
352.40149 ++
352.40150 ++static int test_accuracy_msc(Display *dpy, void *Q)
352.40151 + {
352.40152 +-	Pixmap pixmap;
352.40153 +-	struct dri3_fence fence;
352.40154 +-	Window root;
352.40155 +-	unsigned int width, height;
352.40156 +-	unsigned border, depth;
352.40157 +-	int x, y, ret = 1;
352.40158 ++#define N_VBLANKS (60 * 120) /* ~2 minutes */
352.40159 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.40160 ++	Window root = DefaultRootWindow(dpy);
352.40161 ++	int ret = 0, n;
352.40162 ++	uint64_t msc;
352.40163 ++	int early = 0, late = 0;
352.40164 ++	int earliest = 0, latest = 0;
352.40165 ++	int complete, count;
352.40166 + 
352.40167 +-	XGetGeometry(dpy, DefaultRootWindow(dpy),
352.40168 +-		     &root, &x, &y, &width, &height, &border, &depth);
352.40169 ++	printf("Testing notify accuracy\n");
352.40170 ++	_x_error_occurred = 0;
352.40171 + 
352.40172 +-	if (dri3_create_fence(dpy, root, &fence))
352.40173 +-		return 0;
352.40174 ++	msc = check_msc(dpy, root, Q, 0, NULL);
352.40175 ++	for (n = 0; n <= N_VBLANKS; n++)
352.40176 ++		xcb_present_notify_msc(c, root, n, msc + 60 + n, 0, 0);
352.40177 ++	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n, 0, 0);
352.40178 ++	xcb_flush(c);
352.40179 ++
352.40180 ++	complete = 0;
352.40181 ++	count = 0;
352.40182 ++	do {
352.40183 ++		xcb_present_complete_notify_event_t *ce;
352.40184 ++		xcb_generic_event_t *ev;
352.40185 ++
352.40186 ++		ev = xcb_wait_for_special_event(c, Q);
352.40187 ++		if (ev == NULL)
352.40188 ++			break;
352.40189 ++
352.40190 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.40191 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40192 ++
352.40193 ++		if (ce->serial != 0xdeadbeef) {
352.40194 ++			int diff = (int64_t)(ce->msc - (msc + ce->serial + 60));
352.40195 ++			if (diff < 0) {
352.40196 ++				if (-diff > earliest) {
352.40197 ++					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
352.40198 ++					earliest = -diff;
352.40199 ++				}
352.40200 ++				early++;
352.40201 ++				ret++;
352.40202 ++			} else if (diff > 0) {
352.40203 ++				if (diff > latest) {
352.40204 ++					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
352.40205 ++					latest = diff;
352.40206 ++				}
352.40207 ++				late++;
352.40208 ++				ret++;
352.40209 ++			}
352.40210 ++			count++;
352.40211 ++		} else
352.40212 ++			complete = 1;
352.40213 ++		free(ev);
352.40214 ++	} while (!complete);
352.40215 ++
352.40216 ++	if (early)
352.40217 ++		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
352.40218 ++	if (late)
352.40219 ++		printf("\t%d notifies too late (worst %d)!\n", late, latest);
352.40220 ++
352.40221 ++	if (count != N_VBLANKS+1) {
352.40222 ++		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", N_VBLANKS+1 - count);
352.40223 ++		ret++;
352.40224 ++		do {
352.40225 ++			xcb_present_complete_notify_event_t *ce;
352.40226 ++			xcb_generic_event_t *ev;
352.40227 ++
352.40228 ++			ev = xcb_wait_for_special_event(c, Q);
352.40229 ++			if (ev == NULL)
352.40230 ++				break;
352.40231 ++
352.40232 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.40233 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40234 ++			free(ev);
352.40235 ++		} while (++count != N_VBLANKS+1);
352.40236 ++	}
352.40237 ++
352.40238 ++	XSync(dpy, True);
352.40239 ++	ret += !!_x_error_occurred;
352.40240 ++
352.40241 ++	return ret;
352.40242 ++#undef N_VBLANKS
352.40243 ++}
352.40244 + 
352.40245 +-	printf("Testing whole screen flip: %dx%d\n", width, height);
352.40246 ++static int test_modulus_msc(Display *dpy, void *Q)
352.40247 ++{
352.40248 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.40249 ++	Window root = DefaultRootWindow(dpy);
352.40250 ++	xcb_present_complete_notify_event_t *ce;
352.40251 ++	xcb_generic_event_t *ev;
352.40252 ++	int x, y, ret = 0;
352.40253 ++	uint64_t target;
352.40254 ++	int early = 0, late = 0;
352.40255 ++	int earliest = 0, latest = 0;
352.40256 ++	int complete, count, expect;
352.40257 ++
352.40258 ++	printf("Testing notify modulus\n");
352.40259 + 	_x_error_occurred = 0;
352.40260 + 
352.40261 +-	xshmfence_reset(fence.addr);
352.40262 ++	target = wait_vblank(dpy, root, Q);
352.40263 + 
352.40264 +-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
352.40265 +-	xcb_present_pixmap(XGetXCBConnection(dpy),
352.40266 +-			   root, pixmap,
352.40267 +-			   0, /* sbc */
352.40268 +-			   0, /* valid */
352.40269 +-			   0, /* update */
352.40270 +-			   0, /* x_off */
352.40271 +-			   0, /* y_off */
352.40272 +-			   None,
352.40273 +-			   None, /* wait fence */
352.40274 +-			   fence.xid,
352.40275 +-			   XCB_PRESENT_OPTION_NONE,
352.40276 +-			   0, /* target msc */
352.40277 +-			   0, /* divisor */
352.40278 +-			   0, /* remainder */
352.40279 +-			   0, NULL);
352.40280 +-	XFreePixmap(dpy, pixmap);
352.40281 ++	expect = 0;
352.40282 ++	xcb_present_notify_msc(c, root, 0, 0, 0, 0);
352.40283 ++	for (x = 1; x <= 19; x++) {
352.40284 ++		for (y = 0; y < x; y++) {
352.40285 ++			xcb_present_notify_msc(c, root, y << 16 | x, 0, x, y);
352.40286 ++			expect++;
352.40287 ++		}
352.40288 ++	}
352.40289 ++	xcb_present_notify_msc(c, root, 0xdeadbeef, target + 2*x, 0, 0);
352.40290 ++	xcb_flush(c);
352.40291 + 
352.40292 +-	pixmap = XCreatePixmap(dpy, root, width, height, depth);
352.40293 +-	xcb_present_pixmap(XGetXCBConnection(dpy),
352.40294 +-			   root, pixmap,
352.40295 +-			   0, /* sbc */
352.40296 +-			   0, /* valid */
352.40297 +-			   0, /* update */
352.40298 +-			   0, /* x_off */
352.40299 +-			   0, /* y_off */
352.40300 +-			   None,
352.40301 +-			   None, /* wait fence */
352.40302 +-			   None, /* sync fence */
352.40303 +-			   XCB_PRESENT_OPTION_NONE,
352.40304 +-			   0, /* target msc */
352.40305 +-			   0, /* divisor */
352.40306 +-			   0, /* remainder */
352.40307 +-			   0, NULL);
352.40308 +-	XFreePixmap(dpy, pixmap);
352.40309 +-	XFlush(dpy);
352.40310 ++	ev = xcb_wait_for_special_event(c, Q);
352.40311 ++	if (ev) {
352.40312 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.40313 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40314 ++		assert(ce->serial == 0);
352.40315 ++		assert(target == ce->msc);
352.40316 ++		target = ce->msc;
352.40317 ++	}
352.40318 + 
352.40319 +-	ret = !!xshmfence_await(fence.addr);
352.40320 +-	dri3_fence_free(dpy, &fence);
352.40321 ++	complete = 0;
352.40322 ++	count = 0;
352.40323 ++	do {
352.40324 ++		ev = xcb_wait_for_special_event(c, Q);
352.40325 ++		if (ev == NULL)
352.40326 ++			break;
352.40327 ++
352.40328 ++		ce = (xcb_present_complete_notify_event_t *)ev;
352.40329 ++		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40330 ++
352.40331 ++		assert(ce->serial);
352.40332 ++		if (ce->serial != 0xdeadbeef) {
352.40333 ++			uint64_t msc;
352.40334 ++			int diff;
352.40335 ++
352.40336 ++			x = ce->serial & 0xffff;
352.40337 ++			y = ce->serial >> 16;
352.40338 ++
352.40339 ++			msc = target;
352.40340 ++			msc -= target % x;
352.40341 ++			msc += y;
352.40342 ++			if (msc <= target)
352.40343 ++				msc += x;
352.40344 ++
352.40345 ++			diff = (int64_t)(ce->msc - msc);
352.40346 ++			if (diff < 0) {
352.40347 ++				if (-diff > earliest) {
352.40348 ++					fprintf(stderr, "\tnotify (%d, %d) early by %d msc (target %lld, reported %lld)\n", y, x, -diff, (long long)msc, (long long)ce->msc);
352.40349 ++					earliest = -diff;
352.40350 ++				}
352.40351 ++				early++;
352.40352 ++				ret++;
352.40353 ++			} else if (diff > 0) {
352.40354 ++				if (diff > latest) {
352.40355 ++					fprintf(stderr, "\tnotify (%d, %d) late by %d msc (target %lld, reported %lld)\n", y, x, diff, (long long)msc, (long long)ce->msc);
352.40356 ++					latest = diff;
352.40357 ++				}
352.40358 ++				late++;
352.40359 ++				ret++;
352.40360 ++			}
352.40361 ++			count++;
352.40362 ++		} else
352.40363 ++			complete = 1;
352.40364 ++		free(ev);
352.40365 ++	} while (!complete);
352.40366 ++
352.40367 ++	if (early)
352.40368 ++		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
352.40369 ++	if (late)
352.40370 ++		printf("\t%d notifies too late (worst %d)!\n", late, latest);
352.40371 ++
352.40372 ++	if (count != expect) {
352.40373 ++		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", expect - count);
352.40374 ++		ret++;
352.40375 ++		do {
352.40376 ++			ev = xcb_wait_for_special_event(c, Q);
352.40377 ++			if (ev == NULL)
352.40378 ++				break;
352.40379 ++
352.40380 ++			ce = (xcb_present_complete_notify_event_t *)ev;
352.40381 ++			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
352.40382 ++			free(ev);
352.40383 ++		} while (++count != expect);
352.40384 ++	}
352.40385 + 
352.40386 + 	XSync(dpy, True);
352.40387 + 	ret += !!_x_error_occurred;
352.40388 +@@ -279,8 +1471,6 @@ static int for_each_crtc(Display *dpy,
352.40389 + 	for (i = 0; i < res->ncrtc; i++)
352.40390 + 		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
352.40391 + 
352.40392 +-	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
352.40393 +-
352.40394 + 	for (i = 0; i < res->noutput; i++) {
352.40395 + 		XRROutputInfo *output;
352.40396 + 		XRRModeInfo *mode;
352.40397 +@@ -322,7 +1512,7 @@ static int for_each_crtc(Display *dpy,
352.40398 + 	free(original_crtc);
352.40399 + 	XRRFreeScreenResources(res);
352.40400 + 
352.40401 +-	return j;
352.40402 ++	return err;
352.40403 + }
352.40404 + 
352.40405 + struct test_crtc {
352.40406 +@@ -335,6 +1525,7 @@ struct test_crtc {
352.40407 + 	uint64_t msc;
352.40408 + };
352.40409 + #define SYNC 0x1
352.40410 ++#define FUTURE 0x2
352.40411 + 
352.40412 + static int __test_crtc(Display *dpy, RRCrtc crtc,
352.40413 + 		       int width, int height,
352.40414 +@@ -344,7 +1535,7 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
352.40415 + 	Pixmap pixmap;
352.40416 + 	int err = 0;
352.40417 + 
352.40418 +-	test->msc = check_msc(dpy, test->win, test->queue, test->msc);
352.40419 ++	test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
352.40420 + 
352.40421 + 	if (test->flags & SYNC)
352.40422 + 		xshmfence_reset(test->fence.addr);
352.40423 +@@ -361,16 +1552,14 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
352.40424 + 			   None, /* wait fence */
352.40425 + 			   test->flags & SYNC ? test->fence.xid : None,
352.40426 + 			   XCB_PRESENT_OPTION_NONE,
352.40427 +-			   0, /* target msc */
352.40428 ++			   test->msc, /* target msc */
352.40429 + 			   1, /* divisor */
352.40430 + 			   0, /* remainder */
352.40431 + 			   0, NULL);
352.40432 +-	XFreePixmap(dpy, pixmap);
352.40433 +-
352.40434 + 	if (test->flags & SYNC) {
352.40435 +-		pixmap = XCreatePixmap(dpy, test->win, width, height, test->depth);
352.40436 ++		Pixmap tmp = XCreatePixmap(dpy, test->win, width, height, test->depth);
352.40437 + 		xcb_present_pixmap(XGetXCBConnection(dpy),
352.40438 +-				   test->win, pixmap,
352.40439 ++				   test->win, tmp,
352.40440 + 				   1, /* sbc */
352.40441 + 				   0, /* valid */
352.40442 + 				   0, /* update */
352.40443 +@@ -380,16 +1569,17 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
352.40444 + 				   None, /* wait fence */
352.40445 + 				   None, /* sync fence */
352.40446 + 				   XCB_PRESENT_OPTION_NONE,
352.40447 +-				   1, /* target msc */
352.40448 ++				   test->msc + (test->flags & FUTURE ? 5 * 16 : 1), /* target msc */
352.40449 + 				   1, /* divisor */
352.40450 + 				   0, /* remainder */
352.40451 + 				   0, NULL);
352.40452 +-		XFreePixmap(dpy, pixmap);
352.40453 ++		XFreePixmap(dpy, tmp);
352.40454 + 		XFlush(dpy);
352.40455 + 		err += !!xshmfence_await(test->fence.addr);
352.40456 + 	}
352.40457 ++	XFreePixmap(dpy, pixmap);
352.40458 + 
352.40459 +-	test->msc = check_msc(dpy, test->win, test->queue, test->msc);
352.40460 ++	test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
352.40461 + 	return err;
352.40462 + }
352.40463 + 
352.40464 +@@ -410,15 +1600,23 @@ static int test_crtc(Display *dpy, void *queue, uint64_t last_msc)
352.40465 + 
352.40466 + 	printf("Testing each crtc, without waiting for each flip\n");
352.40467 + 	test.flags = 0;
352.40468 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40469 + 	err += for_each_crtc(dpy, __test_crtc, &test);
352.40470 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40471 + 
352.40472 + 	printf("Testing each crtc, waiting for flips to complete\n");
352.40473 + 	test.flags = SYNC;
352.40474 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40475 + 	err += for_each_crtc(dpy, __test_crtc, &test);
352.40476 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40477 + 
352.40478 +-	test.msc = check_msc(dpy, test.win, test.queue, test.msc);
352.40479 +-	dri3_fence_free(dpy, &test.fence);
352.40480 ++	printf("Testing each crtc, with future flips\n");
352.40481 ++	test.flags = FUTURE | SYNC;
352.40482 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40483 ++	err += for_each_crtc(dpy, __test_crtc, &test);
352.40484 ++	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
352.40485 + 
352.40486 ++	dri3_fence_free(dpy, &test.fence);
352.40487 + 	XSync(dpy, True);
352.40488 + 	err += !!_x_error_occurred;
352.40489 + 
352.40490 +@@ -536,6 +1734,31 @@ static int gem_set_caching(int fd, uint32_t handle, int caching)
352.40491 + 	return drmIoctl(fd, LOCAL_IOCTL_I915_GEM_SET_CACHING, &arg) == 0;
352.40492 + }
352.40493 + 
352.40494 ++static int gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
352.40495 ++{
352.40496 ++	struct drm_i915_gem_set_tiling set_tiling;
352.40497 ++	int err;
352.40498 ++
352.40499 ++restart:
352.40500 ++	set_tiling.handle = handle;
352.40501 ++	set_tiling.tiling_mode = tiling;
352.40502 ++	set_tiling.stride = stride;
352.40503 ++
352.40504 ++	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
352.40505 ++		return 1;
352.40506 ++
352.40507 ++	err = errno;
352.40508 ++	if (err == EINTR)
352.40509 ++		goto restart;
352.40510 ++
352.40511 ++	if (err == EAGAIN) {
352.40512 ++		sched_yield();
352.40513 ++		goto restart;
352.40514 ++	}
352.40515 ++
352.40516 ++	return 0;
352.40517 ++}
352.40518 ++
352.40519 + static int gem_export(int fd, uint32_t handle)
352.40520 + {
352.40521 + 	struct drm_prime_handle args;
352.40522 +@@ -557,6 +1780,126 @@ static void gem_close(int fd, uint32_t handle)
352.40523 + 	(void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
352.40524 + }
352.40525 + 
352.40526 ++static int test_dri3_tiling(Display *dpy)
352.40527 ++{
352.40528 ++	Window win = DefaultRootWindow(dpy);
352.40529 ++	const int tiling[] = { I915_TILING_NONE, I915_TILING_X, I915_TILING_Y };
352.40530 ++	Window root;
352.40531 ++	unsigned int width, height;
352.40532 ++	unsigned border, depth, bpp;
352.40533 ++	unsigned stride, size;
352.40534 ++	void *Q;
352.40535 ++	int x, y;
352.40536 ++	int device;
352.40537 ++	int line = -1;
352.40538 ++	int t;
352.40539 ++
352.40540 ++	device = dri3_open(dpy);
352.40541 ++	if (device < 0)
352.40542 ++		return 0;
352.40543 ++
352.40544 ++	if (!is_intel(device))
352.40545 ++		return 0;
352.40546 ++
352.40547 ++	printf("Opened Intel DRI3 device\n");
352.40548 ++
352.40549 ++	XGetGeometry(dpy, win, &root, &x, &y,
352.40550 ++		     &width, &height, &border, &depth);
352.40551 ++
352.40552 ++	switch (depth) {
352.40553 ++	case 8: bpp = 8; break;
352.40554 ++	case 15: case 16: bpp = 16; break;
352.40555 ++	case 24: case 32: bpp = 32; break;
352.40556 ++	default: return 0;
352.40557 ++	}
352.40558 ++
352.40559 ++	stride = ALIGN(width * bpp/8, 512);
352.40560 ++	size = PAGE_ALIGN(stride * ALIGN(height, 32));
352.40561 ++	printf("Creating DRI3 %dx%d (source stride=%d, size=%d) for GTT\n",
352.40562 ++	       width, height, stride, size);
352.40563 ++
352.40564 ++	_x_error_occurred = 0;
352.40565 ++	Q = setup_msc(dpy, root);
352.40566 ++
352.40567 ++	for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) {
352.40568 ++		uint64_t msc;
352.40569 ++		uint32_t src;
352.40570 ++		int src_fd;
352.40571 ++		Pixmap src_pix;
352.40572 ++
352.40573 ++		src = gem_create(device, size);
352.40574 ++		if (!src) {
352.40575 ++			line = __LINE__;
352.40576 ++			goto fail;
352.40577 ++		}
352.40578 ++
352.40579 ++		gem_set_tiling(device, src, tiling[t], stride);
352.40580 ++
352.40581 ++		src_fd = gem_export(device, src);
352.40582 ++		if (src_fd < 0) {
352.40583 ++			line = __LINE__;
352.40584 ++			goto fail;
352.40585 ++		}
352.40586 ++
352.40587 ++		src_pix = dri3_create_pixmap(dpy, root,
352.40588 ++					     width, height, depth,
352.40589 ++					     src_fd, bpp, stride, size);
352.40590 ++
352.40591 ++		msc = wait_vblank(dpy, root, Q);
352.40592 ++
352.40593 ++		xcb_present_pixmap(XGetXCBConnection(dpy),
352.40594 ++				   win, src_pix,
352.40595 ++				   0, /* sbc */
352.40596 ++				   0, /* valid */
352.40597 ++				   0, /* update */
352.40598 ++				   0, /* x_off */
352.40599 ++				   0, /* y_off */
352.40600 ++				   None,
352.40601 ++				   None, /* wait fence */
352.40602 ++				   None,
352.40603 ++				   XCB_PRESENT_OPTION_NONE,
352.40604 ++				   msc + 2, /* target msc */
352.40605 ++				   1, /* divisor */
352.40606 ++				   0, /* remainder */
352.40607 ++				   0, NULL);
352.40608 ++
352.40609 ++		xcb_present_pixmap(XGetXCBConnection(dpy),
352.40610 ++				   win, src_pix,
352.40611 ++				   0, /* sbc */
352.40612 ++				   0, /* valid */
352.40613 ++				   0, /* update */
352.40614 ++				   0, /* x_off */
352.40615 ++				   0, /* y_off */
352.40616 ++				   None,
352.40617 ++				   None, /* wait fence */
352.40618 ++				   None,
352.40619 ++				   XCB_PRESENT_OPTION_NONE,
352.40620 ++				   msc + 3, /* target msc */
352.40621 ++				   1, /* divisor */
352.40622 ++				   0, /* remainder */
352.40623 ++				   0, NULL);
352.40624 ++
352.40625 ++		XSync(dpy, True);
352.40626 ++		if (_x_error_occurred) {
352.40627 ++			line = __LINE__;
352.40628 ++			goto fail;
352.40629 ++		}
352.40630 ++		XFreePixmap(dpy, src_pix);
352.40631 ++		_x_error_occurred = 0;
352.40632 ++
352.40633 ++		close(src_fd);
352.40634 ++		gem_close(device, src);
352.40635 ++	}
352.40636 ++
352.40637 ++	teardown_msc(dpy, Q);
352.40638 ++	return 0;
352.40639 ++
352.40640 ++fail:
352.40641 ++	printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line);
352.40642 ++	teardown_msc(dpy, Q);
352.40643 ++	return 1;
352.40644 ++}
352.40645 ++
352.40646 + static int test_dri3(Display *dpy)
352.40647 + {
352.40648 + 	Window win = DefaultRootWindow(dpy);
352.40649 +@@ -670,8 +2013,32 @@ fail:
352.40650 + static int has_present(Display *dpy)
352.40651 + {
352.40652 + 	xcb_connection_t *c = XGetXCBConnection(dpy);
352.40653 +-	xcb_present_query_version_reply_t *reply;
352.40654 + 	xcb_generic_error_t *error = NULL;
352.40655 ++	void *reply;
352.40656 ++
352.40657 ++	reply = xcb_xfixes_query_version_reply(c,
352.40658 ++					       xcb_xfixes_query_version(c,
352.40659 ++									XCB_XFIXES_MAJOR_VERSION,
352.40660 ++									XCB_XFIXES_MINOR_VERSION),
352.40661 ++					       &error);
352.40662 ++	free(reply);
352.40663 ++	free(error);
352.40664 ++	if (reply == NULL) {
352.40665 ++		fprintf(stderr, "XFixes not supported on %s\n", DisplayString(dpy));
352.40666 ++		return 0;
352.40667 ++	}
352.40668 ++
352.40669 ++	reply = xcb_dri3_query_version_reply(c,
352.40670 ++					     xcb_dri3_query_version(c,
352.40671 ++								    XCB_DRI3_MAJOR_VERSION,
352.40672 ++								    XCB_DRI3_MINOR_VERSION),
352.40673 ++					     &error);
352.40674 ++	free(reply);
352.40675 ++	free(error);
352.40676 ++	if (reply == NULL) {
352.40677 ++		fprintf(stderr, "DRI3 not supported on %s\n", DisplayString(dpy));
352.40678 ++		return 0;
352.40679 ++	}
352.40680 + 
352.40681 + 	reply = xcb_present_query_version_reply(c,
352.40682 + 						xcb_present_query_version(c,
352.40683 +@@ -681,14 +2048,32 @@ static int has_present(Display *dpy)
352.40684 + 
352.40685 + 	free(reply);
352.40686 + 	free(error);
352.40687 ++	if (reply == NULL) {
352.40688 ++		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
352.40689 ++		return 0;
352.40690 ++	}
352.40691 ++
352.40692 ++	return 1;
352.40693 ++}
352.40694 ++
352.40695 ++static int has_composite(Display *dpy)
352.40696 ++{
352.40697 ++	int event, error;
352.40698 ++	int major, minor;
352.40699 ++
352.40700 ++	if (!XCompositeQueryExtension(dpy, &event, &error))
352.40701 ++		return 0;
352.40702 ++
352.40703 ++	XCompositeQueryVersion(dpy, &major, &minor);
352.40704 + 
352.40705 +-	return reply != NULL;
352.40706 ++	return major > 0 || minor >= 4;
352.40707 + }
352.40708 + 
352.40709 + int main(void)
352.40710 + {
352.40711 + 	Display *dpy;
352.40712 + 	Window root;
352.40713 ++	int dummy;
352.40714 + 	int error = 0;
352.40715 + 	uint64_t last_msc;
352.40716 + 	void *queue;
352.40717 +@@ -700,27 +2085,135 @@ int main(void)
352.40718 + 	if (!has_present(dpy))
352.40719 + 		return 77;
352.40720 + 
352.40721 ++	if (DPMSQueryExtension(dpy, &dummy, &dummy))
352.40722 ++		DPMSDisable(dpy);
352.40723 ++
352.40724 + 	root = DefaultRootWindow(dpy);
352.40725 + 
352.40726 + 	signal(SIGALRM, SIG_IGN);
352.40727 + 	XSetErrorHandler(_check_error_handler);
352.40728 + 
352.40729 + 	queue = setup_msc(dpy, root);
352.40730 +-	last_msc = check_msc(dpy, root, queue, 0);
352.40731 ++	last_msc = check_msc(dpy, root, queue, 0, NULL);
352.40732 ++
352.40733 ++	error += test_future_msc(dpy, queue);
352.40734 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40735 ++
352.40736 ++	error += test_wrap_msc(dpy);
352.40737 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40738 ++
352.40739 ++	error += test_accuracy_msc(dpy, queue);
352.40740 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40741 ++
352.40742 ++	error += test_modulus_msc(dpy, queue);
352.40743 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40744 ++
352.40745 ++	error += test_exhaustion_msc(dpy, queue);
352.40746 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40747 ++
352.40748 ++	for (dummy = 0; dummy <= 3; dummy++) {
352.40749 ++		Window win;
352.40750 ++		uint64_t msc = 0;
352.40751 ++		XSetWindowAttributes attr;
352.40752 ++		Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
352.40753 ++		unsigned int width, height;
352.40754 ++		unsigned border, depth;
352.40755 ++		const char *phase;
352.40756 ++		int x, y;
352.40757 ++		void *Q;
352.40758 ++
352.40759 ++		attr.override_redirect = 1;
352.40760 ++
352.40761 ++		XGetGeometry(dpy, root, &win, &x, &y,
352.40762 ++			     &width, &height, &border, &depth);
352.40763 ++
352.40764 ++		_x_error_occurred = 0;
352.40765 ++		switch (dummy) {
352.40766 ++		case 0:
352.40767 ++			win = root;
352.40768 ++			phase = "root";
352.40769 ++			break;
352.40770 ++		case 1:
352.40771 ++			win = XCreateWindow(dpy, root,
352.40772 ++					    0, 0, width, height, 0, depth,
352.40773 ++					    InputOutput, visual,
352.40774 ++					    CWOverrideRedirect, &attr);
352.40775 ++			phase = "fullscreen";
352.40776 ++			break;
352.40777 ++		case 2:
352.40778 ++			win = XCreateWindow(dpy, root,
352.40779 ++					    0, 0, width/2, height/2, 0, depth,
352.40780 ++					    InputOutput, visual,
352.40781 ++					    CWOverrideRedirect, &attr);
352.40782 ++			phase = "window";
352.40783 ++			break;
352.40784 ++		case 3:
352.40785 ++			if (!has_composite(dpy))
352.40786 ++				continue;
352.40787 ++
352.40788 ++			win = XCreateWindow(dpy, root,
352.40789 ++					    0, 0, width, height, 0,
352.40790 ++					    DefaultDepth(dpy, DefaultScreen(dpy)),
352.40791 ++					    InputOutput,
352.40792 ++					    DefaultVisual(dpy, DefaultScreen(dpy)),
352.40793 ++					    CWOverrideRedirect, &attr);
352.40794 ++			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
352.40795 ++			phase = "composite";
352.40796 ++			break;
352.40797 ++
352.40798 ++		default:
352.40799 ++			phase = "broken";
352.40800 ++			win = root;
352.40801 ++			abort();
352.40802 ++			break;
352.40803 ++		}
352.40804 ++
352.40805 ++		XMapWindow(dpy, win);
352.40806 ++		XSync(dpy, True);
352.40807 ++		if (_x_error_occurred)
352.40808 ++			continue;
352.40809 ++
352.40810 ++		Q = setup_msc(dpy, win);
352.40811 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40812 + 
352.40813 +-	error += test_whole(dpy);
352.40814 +-	last_msc = check_msc(dpy, root, queue, last_msc);
352.40815 ++		error += test_whole(dpy, win, phase);
352.40816 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40817 ++
352.40818 ++		error += test_double(dpy, win, phase, Q);
352.40819 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40820 ++
352.40821 ++		error += test_future(dpy, win, phase, Q);
352.40822 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40823 ++
352.40824 ++		error += test_accuracy(dpy, win, phase, Q);
352.40825 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40826 ++
352.40827 ++		error += test_modulus(dpy, win, phase, Q);
352.40828 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40829 ++
352.40830 ++		error += test_exhaustion(dpy, win, phase, Q);
352.40831 ++		msc = check_msc(dpy, win, Q, msc, NULL);
352.40832 ++
352.40833 ++		teardown_msc(dpy, Q);
352.40834 ++		if (win != root)
352.40835 ++			XDestroyWindow(dpy, win);
352.40836 ++	}
352.40837 + 
352.40838 + 	error += test_crtc(dpy, queue, last_msc);
352.40839 +-	last_msc = check_msc(dpy, root, queue, last_msc);
352.40840 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40841 + 
352.40842 + 	error += test_shm(dpy);
352.40843 +-	last_msc = check_msc(dpy, root, queue, last_msc);
352.40844 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40845 + 
352.40846 + 	error += test_dri3(dpy);
352.40847 +-	last_msc = check_msc(dpy, root, queue, last_msc);
352.40848 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40849 ++
352.40850 ++	error += test_dri3_tiling(dpy);
352.40851 ++	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
352.40852 + 
352.40853 + 	teardown_msc(dpy, queue);
352.40854 + 
352.40855 ++	if (DPMSQueryExtension(dpy, &dummy, &dummy))
352.40856 ++		DPMSEnable(dpy);
352.40857 + 	return !!error;
352.40858 + }
352.40859 +diff --git a/test/render-glyphs.c b/test/render-glyphs.c
352.40860 +new file mode 100644
352.40861 +index 00000000..8822e36a
352.40862 +--- /dev/null
352.40863 ++++ b/test/render-glyphs.c
352.40864 +@@ -0,0 +1,441 @@
352.40865 ++#include <stdint.h>
352.40866 ++#include <stdio.h>
352.40867 ++#include <stdlib.h>
352.40868 ++#include <stdbool.h>
352.40869 ++#include <stdarg.h>
352.40870 ++#include <string.h>
352.40871 ++
352.40872 ++#include <X11/Xutil.h> /* for XDestroyImage */
352.40873 ++#include <pixman.h> /* for pixman blt functions */
352.40874 ++
352.40875 ++#include "test.h"
352.40876 ++
352.40877 ++static const XRenderColor colors[] = {
352.40878 ++	/* red, green, blue, alpha */
352.40879 ++	{ 0 },
352.40880 ++	{ 0, 0, 0, 0xffff },
352.40881 ++	{ 0xffff, 0, 0, 0xffff },
352.40882 ++	{ 0, 0xffff, 0, 0xffff },
352.40883 ++	{ 0, 0, 0xffff, 0xffff },
352.40884 ++	{ 0xffff, 0xffff, 0xffff, 0xffff },
352.40885 ++};
352.40886 ++
352.40887 ++static struct clip {
352.40888 ++	void *func;
352.40889 ++} clips[] = {
352.40890 ++	{ NULL },
352.40891 ++};
352.40892 ++
352.40893 ++static int _x_error_occurred;
352.40894 ++
352.40895 ++static int
352.40896 ++_check_error_handler(Display     *display,
352.40897 ++		     XErrorEvent *event)
352.40898 ++{
352.40899 ++	_x_error_occurred = 1;
352.40900 ++	return False; /* ignored */
352.40901 ++}
352.40902 ++
352.40903 ++static void clear(struct test_display *dpy,
352.40904 ++		  struct test_target *tt,
352.40905 ++		  const XRenderColor *c)
352.40906 ++{
352.40907 ++	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, c,
352.40908 ++			     0, 0, tt->width, tt->height);
352.40909 ++}
352.40910 ++
352.40911 ++static bool check_op(struct test_display *dpy, int op, struct test_target *tt)
352.40912 ++{
352.40913 ++	XRenderColor render_color = {0};
352.40914 ++
352.40915 ++	XSync(dpy->dpy, True);
352.40916 ++	_x_error_occurred = 0;
352.40917 ++
352.40918 ++	XRenderFillRectangle(dpy->dpy, op,
352.40919 ++			     tt->picture, &render_color,
352.40920 ++			     0, 0, 0, 0);
352.40921 ++
352.40922 ++	XSync(dpy->dpy, True);
352.40923 ++	return _x_error_occurred == 0;
352.40924 ++}
352.40925 ++
352.40926 ++struct glyph_iter {
352.40927 ++	enum {
352.40928 ++		GLYPHS, OP, DST, SRC, MASK, CLIP,
352.40929 ++	} stage;
352.40930 ++
352.40931 ++	int glyph_format;
352.40932 ++	int op;
352.40933 ++	int dst_color;
352.40934 ++	int src_color;
352.40935 ++	int mask_format;
352.40936 ++	int clip;
352.40937 ++
352.40938 ++	struct {
352.40939 ++		struct test_display *dpy;
352.40940 ++		struct test_target tt;
352.40941 ++		GlyphSet glyphset;
352.40942 ++		Picture src;
352.40943 ++		XRenderPictFormat *mask_format;
352.40944 ++	} ref, out;
352.40945 ++};
352.40946 ++
352.40947 ++static void glyph_iter_init(struct glyph_iter *gi,
352.40948 ++			    struct test *t, enum target target)
352.40949 ++{
352.40950 ++	memset(gi, 0, sizeof(*gi));
352.40951 ++
352.40952 ++	gi->out.dpy = &t->out;
352.40953 ++	test_target_create_render(&t->out, target, &gi->out.tt);
352.40954 ++
352.40955 ++	gi->ref.dpy = &t->ref;
352.40956 ++	test_target_create_render(&t->ref, target, &gi->ref.tt);
352.40957 ++
352.40958 ++	gi->stage = GLYPHS;
352.40959 ++	gi->glyph_format = -1;
352.40960 ++	gi->op = -1;
352.40961 ++	gi->dst_color = -1;
352.40962 ++	gi->src_color = -1;
352.40963 ++	gi->mask_format = -1;
352.40964 ++	gi->clip = -1;
352.40965 ++}
352.40966 ++
352.40967 ++static void render_clear(char *image, int image_size, int bpp)
352.40968 ++{
352.40969 ++	memset(image, 0, image_size);
352.40970 ++}
352.40971 ++
352.40972 ++static void render_black(char *image, int image_size, int bpp)
352.40973 ++{
352.40974 ++	if (bpp == 4) {
352.40975 ++		uint32_t *p = (uint32_t *)image;
352.40976 ++		image_size /= 4;
352.40977 ++		while (image_size--)
352.40978 ++			*p++ = 0x000000ff;
352.40979 ++	} else
352.40980 ++		memset(image, 0x55, image_size);
352.40981 ++}
352.40982 ++
352.40983 ++static void render_green(char *image, int image_size, int bpp)
352.40984 ++{
352.40985 ++	if (bpp == 4) {
352.40986 ++		uint32_t *p = (uint32_t *)image;
352.40987 ++		image_size /= 4;
352.40988 ++		while (image_size--)
352.40989 ++			*p++ = 0xffff0000;
352.40990 ++	} else
352.40991 ++		memset(image, 0xaa, image_size);
352.40992 ++}
352.40993 ++
352.40994 ++static void render_white(char *image, int image_size, int bpp)
352.40995 ++{
352.40996 ++	memset(image, 0xff, image_size);
352.40997 ++}
352.40998 ++
352.40999 ++static GlyphSet create_glyphs(Display *dpy, int format_id)
352.41000 ++{
352.41001 ++#define N_GLYPHS 4
352.41002 ++	XRenderPictFormat *format;
352.41003 ++	XGlyphInfo glyph = { 8, 8, 0, 0, 8, 0 };
352.41004 ++	char image[4*8*8];
352.41005 ++	GlyphSet glyphset;
352.41006 ++	Glyph gid;
352.41007 ++	int image_size;
352.41008 ++	int bpp;
352.41009 ++	int n;
352.41010 ++
352.41011 ++	format = XRenderFindStandardFormat(dpy, format_id);
352.41012 ++	if (format == NULL)
352.41013 ++		return 0;
352.41014 ++
352.41015 ++	switch (format_id) {
352.41016 ++	case PictStandardARGB32:
352.41017 ++	case PictStandardRGB24:
352.41018 ++		image_size = 4 * 8 * 8;
352.41019 ++		bpp = 4;
352.41020 ++		break;
352.41021 ++	case PictStandardA8:
352.41022 ++	case PictStandardA4:
352.41023 ++		image_size = 8 * 8;
352.41024 ++		bpp = 1;
352.41025 ++		break;
352.41026 ++	case PictStandardA1:
352.41027 ++		image_size = 8;
352.41028 ++		bpp = 0;
352.41029 ++		break;
352.41030 ++	default:
352.41031 ++		return 0;
352.41032 ++	}
352.41033 ++
352.41034 ++	glyphset = XRenderCreateGlyphSet(dpy, format);
352.41035 ++	for (n = 0; n < N_GLYPHS; n++) {
352.41036 ++		gid = n;
352.41037 ++
352.41038 ++		switch (n) {
352.41039 ++		case 0: render_clear(image, image_size, bpp); break;
352.41040 ++		case 1: render_black(image, image_size, bpp); break;
352.41041 ++		case 2: render_green(image, image_size, bpp); break;
352.41042 ++		case 3: render_white(image, image_size, bpp); break;
352.41043 ++		}
352.41044 ++
352.41045 ++		XRenderAddGlyphs(dpy, glyphset,
352.41046 ++				 &gid, &glyph, 1, image, image_size);
352.41047 ++	}
352.41048 ++
352.41049 ++	return glyphset;
352.41050 ++}
352.41051 ++
352.41052 ++static const char *glyph_name(int n)
352.41053 ++{
352.41054 ++	switch (n) {
352.41055 ++	case 0: return "clear";
352.41056 ++	case 1: return "black";
352.41057 ++	case 2: return "green";
352.41058 ++	case 3: return "white";
352.41059 ++	default: return "unknown";
352.41060 ++	}
352.41061 ++}
352.41062 ++
352.41063 ++static bool glyph_iter_next(struct glyph_iter *gi)
352.41064 ++{
352.41065 ++restart:
352.41066 ++	if (gi->stage == GLYPHS) {
352.41067 ++		if (++gi->glyph_format == PictStandardNUM)
352.41068 ++			return false;
352.41069 ++
352.41070 ++		if (gi->out.glyphset)
352.41071 ++			XRenderFreeGlyphSet(gi->out.dpy->dpy,
352.41072 ++					    gi->out.glyphset);
352.41073 ++		gi->out.glyphset = create_glyphs(gi->out.dpy->dpy,
352.41074 ++					       gi->glyph_format);
352.41075 ++
352.41076 ++		if (gi->ref.glyphset)
352.41077 ++			XRenderFreeGlyphSet(gi->ref.dpy->dpy,
352.41078 ++					    gi->ref.glyphset);
352.41079 ++		gi->ref.glyphset = create_glyphs(gi->ref.dpy->dpy,
352.41080 ++					       gi->glyph_format);
352.41081 ++
352.41082 ++		gi->stage++;
352.41083 ++	}
352.41084 ++
352.41085 ++	if (gi->stage == OP) {
352.41086 ++		do {
352.41087 ++			if (++gi->op == 255)
352.41088 ++				goto reset_op;
352.41089 ++		} while (!check_op(gi->out.dpy, gi->op, &gi->out.tt) ||
352.41090 ++			 !check_op(gi->ref.dpy, gi->op, &gi->ref.tt));
352.41091 ++
352.41092 ++		gi->stage++;
352.41093 ++	}
352.41094 ++
352.41095 ++	if (gi->stage == DST) {
352.41096 ++		if (++gi->dst_color == ARRAY_SIZE(colors))
352.41097 ++			goto reset_dst;
352.41098 ++
352.41099 ++		gi->stage++;
352.41100 ++	}
352.41101 ++
352.41102 ++	if (gi->stage == SRC) {
352.41103 ++		if (++gi->src_color == ARRAY_SIZE(colors))
352.41104 ++			goto reset_src;
352.41105 ++
352.41106 ++		if (gi->ref.src)
352.41107 ++			XRenderFreePicture(gi->ref.dpy->dpy, gi->ref.src);
352.41108 ++		gi->ref.src = XRenderCreateSolidFill(gi->ref.dpy->dpy,
352.41109 ++						     &colors[gi->src_color]);
352.41110 ++
352.41111 ++		if (gi->out.src)
352.41112 ++			XRenderFreePicture(gi->out.dpy->dpy, gi->out.src);
352.41113 ++		gi->out.src = XRenderCreateSolidFill(gi->out.dpy->dpy,
352.41114 ++						     &colors[gi->src_color]);
352.41115 ++
352.41116 ++		gi->stage++;
352.41117 ++	}
352.41118 ++
352.41119 ++	if (gi->stage == MASK) {
352.41120 ++		if (++gi->mask_format > PictStandardNUM)
352.41121 ++			goto reset_mask;
352.41122 ++
352.41123 ++		if (gi->mask_format == PictStandardRGB24)
352.41124 ++			gi->mask_format++;
352.41125 ++
352.41126 ++		if (gi->mask_format < PictStandardNUM) {
352.41127 ++			gi->out.mask_format = XRenderFindStandardFormat(gi->out.dpy->dpy,
352.41128 ++									gi->mask_format);
352.41129 ++			gi->ref.mask_format = XRenderFindStandardFormat(gi->ref.dpy->dpy,
352.41130 ++									gi->mask_format);
352.41131 ++		} else {
352.41132 ++			gi->out.mask_format = NULL;
352.41133 ++			gi->ref.mask_format = NULL;
352.41134 ++		}
352.41135 ++
352.41136 ++		gi->stage++;
352.41137 ++	}
352.41138 ++
352.41139 ++	if (gi->stage == CLIP) {
352.41140 ++		if (++gi->clip == ARRAY_SIZE(clips))
352.41141 ++			goto reset_clip;
352.41142 ++
352.41143 ++		gi->stage++;
352.41144 ++	}
352.41145 ++
352.41146 ++	gi->stage--;
352.41147 ++	return true;
352.41148 ++
352.41149 ++reset_op:
352.41150 ++	gi->op = -1;
352.41151 ++reset_dst:
352.41152 ++	gi->dst_color = -1;
352.41153 ++reset_src:
352.41154 ++	gi->src_color = -1;
352.41155 ++reset_mask:
352.41156 ++	gi->mask_format = -1;
352.41157 ++reset_clip:
352.41158 ++	gi->clip = -1;
352.41159 ++	gi->stage--;
352.41160 ++	goto restart;
352.41161 ++}
352.41162 ++
352.41163 ++static void glyph_iter_fini(struct glyph_iter *gi)
352.41164 ++{
352.41165 ++	if (gi->out.glyphset)
352.41166 ++		XRenderFreeGlyphSet (gi->out.dpy->dpy, gi->out.glyphset);
352.41167 ++	if (gi->ref.glyphset)
352.41168 ++		XRenderFreeGlyphSet (gi->ref.dpy->dpy, gi->ref.glyphset);
352.41169 ++
352.41170 ++	test_target_destroy_render(gi->out.dpy, &gi->out.tt);
352.41171 ++	test_target_destroy_render(gi->ref.dpy, &gi->ref.tt);
352.41172 ++}
352.41173 ++
352.41174 ++static const char *stdformat_to_str(int id)
352.41175 ++{
352.41176 ++	switch (id) {
352.41177 ++	case PictStandardARGB32: return "ARGB32";
352.41178 ++	case PictStandardRGB24: return "RGB24";
352.41179 ++	case PictStandardA8: return "A8";
352.41180 ++	case PictStandardA4: return "A4";
352.41181 ++	case PictStandardA1: return "A1";
352.41182 ++	default: return "none";
352.41183 ++	}
352.41184 ++}
352.41185 ++
352.41186 ++static char *glyph_iter_to_string(struct glyph_iter *gi,
352.41187 ++				  const char *format,
352.41188 ++				  ...)
352.41189 ++{
352.41190 ++	static char buf[100];
352.41191 ++	va_list ap;
352.41192 ++	int len;
352.41193 ++
352.41194 ++	len = sprintf(buf, "glyphs=%s, op=%d, dst=%08x, src=%08x, mask=%s",
352.41195 ++		      stdformat_to_str(gi->glyph_format), gi->op,
352.41196 ++		      xrender_color(&colors[gi->dst_color]),
352.41197 ++		      xrender_color(&colors[gi->src_color]),
352.41198 ++		      stdformat_to_str(gi->mask_format));
352.41199 ++
352.41200 ++	if (format) {
352.41201 ++		buf[len++] = ' ';
352.41202 ++		va_start(ap, format);
352.41203 ++		vsprintf(buf+len, format, ap);
352.41204 ++		va_end(ap);
352.41205 ++	}
352.41206 ++
352.41207 ++	return buf;
352.41208 ++}
352.41209 ++
352.41210 ++static void single(struct test *t, enum target target)
352.41211 ++{
352.41212 ++	struct glyph_iter gi;
352.41213 ++	int n;
352.41214 ++
352.41215 ++	printf("Testing single glyph (%s): ", test_target_name(target));
352.41216 ++	fflush(stdout);
352.41217 ++
352.41218 ++	glyph_iter_init(&gi, t, target);
352.41219 ++	while (glyph_iter_next(&gi)) {
352.41220 ++		XGlyphElt8 elt;
352.41221 ++		char id[N_GLYPHS];
352.41222 ++
352.41223 ++		for (n = 0; n < N_GLYPHS; n++) {
352.41224 ++			id[n] = n;
352.41225 ++
352.41226 ++			elt.chars = &id[n];
352.41227 ++			elt.nchars = 1;
352.41228 ++			elt.xOff = 0;
352.41229 ++			elt.yOff = 0;
352.41230 ++
352.41231 ++			clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
352.41232 ++			elt.glyphset = gi.out.glyphset;
352.41233 ++			XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
352.41234 ++					       gi.out.src,
352.41235 ++					       gi.out.tt.picture,
352.41236 ++					       gi.out.mask_format,
352.41237 ++					       0, 0,
352.41238 ++					       0, 8,
352.41239 ++					       &elt, 1);
352.41240 ++
352.41241 ++			clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
352.41242 ++			elt.glyphset = gi.ref.glyphset;
352.41243 ++			XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
352.41244 ++					       gi.ref.src,
352.41245 ++					       gi.ref.tt.picture,
352.41246 ++					       gi.ref.mask_format,
352.41247 ++					       0, 0,
352.41248 ++					       0, 8,
352.41249 ++					       &elt, 1);
352.41250 ++			test_compare(t,
352.41251 ++				     gi.out.tt.draw, gi.out.tt.format,
352.41252 ++				     gi.ref.tt.draw, gi.ref.tt.format,
352.41253 ++				     0, 0, gi.out.tt.width, gi.out.tt.height,
352.41254 ++				     glyph_iter_to_string(&gi,
352.41255 ++							  "glyph=%s",
352.41256 ++							  glyph_name(n)));
352.41257 ++		}
352.41258 ++
352.41259 ++		elt.chars = &id[0];
352.41260 ++		elt.nchars = n;
352.41261 ++		clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
352.41262 ++		elt.glyphset = gi.out.glyphset;
352.41263 ++		XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
352.41264 ++				       gi.out.src,
352.41265 ++				       gi.out.tt.picture,
352.41266 ++				       gi.out.mask_format,
352.41267 ++				       0, 0,
352.41268 ++				       0, 8,
352.41269 ++				       &elt, 1);
352.41270 ++
352.41271 ++		clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
352.41272 ++		elt.glyphset = gi.ref.glyphset;
352.41273 ++		XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
352.41274 ++				       gi.ref.src,
352.41275 ++				       gi.ref.tt.picture,
352.41276 ++				       gi.ref.mask_format,
352.41277 ++				       0, 0,
352.41278 ++				       0, 8,
352.41279 ++				       &elt, 1);
352.41280 ++		test_compare(t,
352.41281 ++			     gi.out.tt.draw, gi.out.tt.format,
352.41282 ++			     gi.ref.tt.draw, gi.ref.tt.format,
352.41283 ++			     0, 0, gi.out.tt.width, gi.out.tt.height,
352.41284 ++			     glyph_iter_to_string(&gi, "all"));
352.41285 ++	}
352.41286 ++	glyph_iter_fini(&gi);
352.41287 ++}
352.41288 ++
352.41289 ++int main(int argc, char **argv)
352.41290 ++{
352.41291 ++	struct test test;
352.41292 ++	int t;
352.41293 ++
352.41294 ++	test_init(&test, argc, argv);
352.41295 ++	XSetErrorHandler(_check_error_handler);
352.41296 ++
352.41297 ++	for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
352.41298 ++		single(&test, t);
352.41299 ++		//overlapping(&test, t);
352.41300 ++		//gap(&test, t);
352.41301 ++		//mixed(&test, t);
352.41302 ++	}
352.41303 ++
352.41304 ++	return 0;
352.41305 ++}
352.41306 +diff --git a/test/render-trapezoid.c b/test/render-trapezoid.c
352.41307 +index cd990143..f15a78e3 100644
352.41308 +--- a/test/render-trapezoid.c
352.41309 ++++ b/test/render-trapezoid.c
352.41310 +@@ -403,16 +403,141 @@ static void trap_tests(struct test *t,
352.41311 + 	free(traps);
352.41312 + }
352.41313 + 
352.41314 ++enum edge {
352.41315 ++	EDGE_SHARP = PolyEdgeSharp,
352.41316 ++	EDGE_SMOOTH,
352.41317 ++};
352.41318 ++
352.41319 ++static const char *edge_name(enum edge edge)
352.41320 ++{
352.41321 ++	switch (edge) {
352.41322 ++	default:
352.41323 ++	case EDGE_SHARP: return "sharp";
352.41324 ++	case EDGE_SMOOTH: return "smooth";
352.41325 ++	}
352.41326 ++}
352.41327 ++
352.41328 ++static void set_edge(Display *dpy, Picture p, enum edge edge)
352.41329 ++{
352.41330 ++	XRenderPictureAttributes a;
352.41331 ++
352.41332 ++	a.poly_edge = edge;
352.41333 ++	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
352.41334 ++}
352.41335 ++
352.41336 ++static void edge_test(struct test *t,
352.41337 ++		      enum mask mask,
352.41338 ++		      enum edge edge,
352.41339 ++		      enum target target)
352.41340 ++{
352.41341 ++	struct test_target out, ref;
352.41342 ++	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
352.41343 ++	Picture src_ref, src_out;
352.41344 ++	XTrapezoid trap;
352.41345 ++	int left_or_right, p;
352.41346 ++
352.41347 ++	test_target_create_render(&t->out, target, &out);
352.41348 ++	set_edge(t->out.dpy, out.picture, edge);
352.41349 ++	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
352.41350 ++
352.41351 ++	test_target_create_render(&t->ref, target, &ref);
352.41352 ++	set_edge(t->ref.dpy, ref.picture, edge);
352.41353 ++	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
352.41354 ++
352.41355 ++	printf("Testing edges (with mask %s and %s edges) (%s): ",
352.41356 ++	       mask_name(mask),
352.41357 ++	       edge_name(edge),
352.41358 ++	       test_target_name(target));
352.41359 ++	fflush(stdout);
352.41360 ++
352.41361 ++	for (left_or_right = 0; left_or_right <= 1; left_or_right++) {
352.41362 ++		for (p = -64; p <= out.width + 64; p++) {
352.41363 ++			char buf[80];
352.41364 ++
352.41365 ++			if (left_or_right) {
352.41366 ++				trap.left.p1.x = 0;
352.41367 ++				trap.left.p1.y = 0;
352.41368 ++				trap.left.p2.x = 0;
352.41369 ++				trap.left.p2.y = out.height << 16;
352.41370 ++
352.41371 ++				trap.right.p1.x = p << 16;
352.41372 ++				trap.right.p1.y = 0;
352.41373 ++				trap.right.p2.x = out.width << 16;
352.41374 ++				trap.right.p2.y = out.height << 16;
352.41375 ++			} else {
352.41376 ++				trap.right.p1.x = out.width << 16;
352.41377 ++				trap.right.p1.y = 0;
352.41378 ++				trap.right.p2.x = out.width << 16;
352.41379 ++				trap.right.p2.y = out.height << 16;
352.41380 ++
352.41381 ++				trap.left.p1.x = 0;
352.41382 ++				trap.left.p1.y = 0;
352.41383 ++				trap.left.p2.x = p << 16;
352.41384 ++				trap.left.p2.y = out.height << 16;
352.41385 ++			}
352.41386 ++
352.41387 ++			trap.top = 0;
352.41388 ++			trap.bottom = out.height << 16;
352.41389 ++
352.41390 ++			sprintf(buf,
352.41391 ++				"trap=((%d, %d), (%d, %d)), ((%d, %d), (%d, %d))\n",
352.41392 ++				trap.left.p1.x >> 16, trap.left.p1.y >> 16,
352.41393 ++				trap.left.p2.x >> 16, trap.left.p2.y >> 16,
352.41394 ++				trap.right.p1.x >> 16, trap.right.p1.y >> 16,
352.41395 ++				trap.right.p2.x >> 16, trap.right.p2.y >> 16);
352.41396 ++
352.41397 ++			clear(&t->out, &out);
352.41398 ++			XRenderCompositeTrapezoids(t->out.dpy,
352.41399 ++						   PictOpSrc,
352.41400 ++						   src_out,
352.41401 ++						   out.picture,
352.41402 ++						   mask_format(t->out.dpy, mask),
352.41403 ++						   0, 0,
352.41404 ++						   &trap, 1);
352.41405 ++
352.41406 ++			clear(&t->ref, &ref);
352.41407 ++			XRenderCompositeTrapezoids(t->ref.dpy,
352.41408 ++						   PictOpSrc,
352.41409 ++						   src_ref,
352.41410 ++						   ref.picture,
352.41411 ++						   mask_format(t->ref.dpy, mask),
352.41412 ++						   0, 0,
352.41413 ++						   &trap, 1);
352.41414 ++
352.41415 ++			test_compare(t,
352.41416 ++				     out.draw, out.format,
352.41417 ++				     ref.draw, ref.format,
352.41418 ++				     0, 0, out.width, out.height,
352.41419 ++				     buf);
352.41420 ++		}
352.41421 ++	}
352.41422 ++
352.41423 ++	XRenderFreePicture(t->out.dpy, src_out);
352.41424 ++	test_target_destroy_render(&t->out, &out);
352.41425 ++
352.41426 ++	XRenderFreePicture(t->ref.dpy, src_ref);
352.41427 ++	test_target_destroy_render(&t->ref, &ref);
352.41428 ++
352.41429 ++	printf("pass\n");
352.41430 ++}
352.41431 ++
352.41432 + int main(int argc, char **argv)
352.41433 + {
352.41434 + 	struct test test;
352.41435 + 	int i, dx, dy;
352.41436 + 	enum target target;
352.41437 + 	enum mask mask;
352.41438 ++	enum edge edge;
352.41439 + 	enum trapezoid trapezoid;
352.41440 + 
352.41441 + 	test_init(&test, argc, argv);
352.41442 + 
352.41443 ++	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
352.41444 ++		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
352.41445 ++			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
352.41446 ++				edge_test(&test, mask, edge, target);
352.41447 ++	}
352.41448 ++
352.41449 + 	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
352.41450 + 		int reps = REPS(i), sets = SETS(i);
352.41451 + 
352.41452 +diff --git a/test/render-triangle.c b/test/render-triangle.c
352.41453 +new file mode 100644
352.41454 +index 00000000..165834ce
352.41455 +--- /dev/null
352.41456 ++++ b/test/render-triangle.c
352.41457 +@@ -0,0 +1,180 @@
352.41458 ++#include <stdint.h>
352.41459 ++#include <stdio.h>
352.41460 ++#include <stdlib.h>
352.41461 ++
352.41462 ++#include "test.h"
352.41463 ++
352.41464 ++enum edge {
352.41465 ++	EDGE_SHARP = PolyEdgeSharp,
352.41466 ++	EDGE_SMOOTH,
352.41467 ++};
352.41468 ++
352.41469 ++static void set_edge(Display *dpy, Picture p, enum edge edge)
352.41470 ++{
352.41471 ++	XRenderPictureAttributes a;
352.41472 ++
352.41473 ++	a.poly_edge = edge;
352.41474 ++	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
352.41475 ++}
352.41476 ++
352.41477 ++static XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
352.41478 ++{
352.41479 ++	switch (mask) {
352.41480 ++	default:
352.41481 ++	case MASK_NONE: return NULL;
352.41482 ++	case MASK_A1: return XRenderFindStandardFormat(dpy, PictStandardA1);
352.41483 ++	case MASK_A8: return XRenderFindStandardFormat(dpy, PictStandardA8);
352.41484 ++	}
352.41485 ++}
352.41486 ++
352.41487 ++static const char *mask_name(enum mask mask)
352.41488 ++{
352.41489 ++	switch (mask) {
352.41490 ++	default:
352.41491 ++	case MASK_NONE: return "none";
352.41492 ++	case MASK_A1: return "a1";
352.41493 ++	case MASK_A8: return "a8";
352.41494 ++	}
352.41495 ++}
352.41496 ++
352.41497 ++static const char *edge_name(enum edge edge)
352.41498 ++{
352.41499 ++	switch (edge) {
352.41500 ++	default:
352.41501 ++	case EDGE_SHARP: return "sharp";
352.41502 ++	case EDGE_SMOOTH: return "smooth";
352.41503 ++	}
352.41504 ++}
352.41505 ++
352.41506 ++static void clear(struct test_display *dpy, struct test_target *tt)
352.41507 ++{
352.41508 ++	XRenderColor render_color = {0};
352.41509 ++	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
352.41510 ++			     0, 0, tt->width, tt->height);
352.41511 ++}
352.41512 ++
352.41513 ++static void step_to_point(int step, int width, int height, XPointFixed *p)
352.41514 ++{
352.41515 ++	do {
352.41516 ++		p->x = (step - 64) << 16;
352.41517 ++		p->y = -64 << 16;
352.41518 ++
352.41519 ++		step -= width - 128;
352.41520 ++		if (step <= 0)
352.41521 ++			return;
352.41522 ++
352.41523 ++		p->x = (width + 64) << 16;
352.41524 ++		p->y = (step - 64) << 16;
352.41525 ++		step -= height - 128;
352.41526 ++
352.41527 ++		if (step <= 0)
352.41528 ++			return;
352.41529 ++
352.41530 ++		p->x = (width + 64 - step) << 16;
352.41531 ++		p->y = (height + 64) << 16;
352.41532 ++		step -= width - 128;
352.41533 ++
352.41534 ++		if (step <= 0)
352.41535 ++			return;
352.41536 ++
352.41537 ++		p->x = -64 << 16;
352.41538 ++		p->y = (height + 64 - step) << 16;
352.41539 ++		step -= height - 128;
352.41540 ++	} while (step > 0);
352.41541 ++}
352.41542 ++
352.41543 ++static void edge_test(struct test *t,
352.41544 ++		      enum mask mask,
352.41545 ++		      enum edge edge,
352.41546 ++		      enum target target)
352.41547 ++{
352.41548 ++	struct test_target out, ref;
352.41549 ++	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
352.41550 ++	Picture src_ref, src_out;
352.41551 ++	XTriangle tri;
352.41552 ++	unsigned step, max;
352.41553 ++
352.41554 ++	test_target_create_render(&t->out, target, &out);
352.41555 ++	set_edge(t->out.dpy, out.picture, edge);
352.41556 ++	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
352.41557 ++
352.41558 ++	test_target_create_render(&t->ref, target, &ref);
352.41559 ++	set_edge(t->ref.dpy, ref.picture, edge);
352.41560 ++	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
352.41561 ++
352.41562 ++	printf("Testing edges (with mask %s and %s edges) (%s): ",
352.41563 ++	       mask_name(mask),
352.41564 ++	       edge_name(edge),
352.41565 ++	       test_target_name(target));
352.41566 ++	fflush(stdout);
352.41567 ++
352.41568 ++	max = 2*(out.width + 128 + out.height+128);
352.41569 ++	step = 0;
352.41570 ++	for (step = 0; step <= max; step++) {
352.41571 ++		char buf[80];
352.41572 ++
352.41573 ++		step_to_point(step, out.width, out.height, &tri.p1);
352.41574 ++		step_to_point(step + out.width + 128,
352.41575 ++			      out.width, out.height,
352.41576 ++			      &tri.p2);
352.41577 ++		step_to_point(step + out.height + 128 + 2*(out.width + 128),
352.41578 ++			      out.width, out.height,
352.41579 ++			      &tri.p3);
352.41580 ++
352.41581 ++		sprintf(buf,
352.41582 ++			"tri=((%d, %d), (%d, %d), (%d, %d))\n",
352.41583 ++			tri.p1.x >> 16, tri.p1.y >> 16,
352.41584 ++			tri.p2.x >> 16, tri.p2.y >> 16,
352.41585 ++			tri.p3.x >> 16, tri.p3.y >> 16);
352.41586 ++
352.41587 ++		clear(&t->out, &out);
352.41588 ++		XRenderCompositeTriangles(t->out.dpy,
352.41589 ++					  PictOpSrc,
352.41590 ++					  src_out,
352.41591 ++					  out.picture,
352.41592 ++					  mask_format(t->out.dpy, mask),
352.41593 ++					  0, 0,
352.41594 ++					  &tri, 1);
352.41595 ++
352.41596 ++		clear(&t->ref, &ref);
352.41597 ++		XRenderCompositeTriangles(t->ref.dpy,
352.41598 ++					  PictOpSrc,
352.41599 ++					  src_ref,
352.41600 ++					  ref.picture,
352.41601 ++					  mask_format(t->ref.dpy, mask),
352.41602 ++					  0, 0,
352.41603 ++					  &tri, 1);
352.41604 ++
352.41605 ++		test_compare(t,
352.41606 ++			     out.draw, out.format,
352.41607 ++			     ref.draw, ref.format,
352.41608 ++			     0, 0, out.width, out.height,
352.41609 ++			     buf);
352.41610 ++	}
352.41611 ++
352.41612 ++	XRenderFreePicture(t->out.dpy, src_out);
352.41613 ++	test_target_destroy_render(&t->out, &out);
352.41614 ++
352.41615 ++	XRenderFreePicture(t->ref.dpy, src_ref);
352.41616 ++	test_target_destroy_render(&t->ref, &ref);
352.41617 ++
352.41618 ++	printf("pass\n");
352.41619 ++}
352.41620 ++
352.41621 ++int main(int argc, char **argv)
352.41622 ++{
352.41623 ++	struct test test;
352.41624 ++	enum target target;
352.41625 ++	enum mask mask;
352.41626 ++	enum edge edge;
352.41627 ++
352.41628 ++	test_init(&test, argc, argv);
352.41629 ++
352.41630 ++	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
352.41631 ++		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
352.41632 ++			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
352.41633 ++				edge_test(&test, mask, edge, target);
352.41634 ++	}
352.41635 ++
352.41636 ++	return 0;
352.41637 ++}
352.41638 +diff --git a/test/test.h b/test/test.h
352.41639 +index a3ef979d..9eec1cf9 100644
352.41640 +--- a/test/test.h
352.41641 ++++ b/test/test.h
352.41642 +@@ -107,6 +107,15 @@ static inline uint32_t color(uint8_t red, uint8_t green, uint8_t blue, uint8_t a
352.41643 + 	return alpha << 24 | ra >> 8 << 16 | ga >> 8 << 8 | ba >> 8;
352.41644 + }
352.41645 + 
352.41646 ++static inline uint32_t xrender_color(const XRenderColor *c)
352.41647 ++{
352.41648 ++	uint32_t ra = c->red * c->alpha;
352.41649 ++	uint32_t ga = c->green * c->alpha;
352.41650 ++	uint32_t ba = c->blue * c->alpha;
352.41651 ++
352.41652 ++	return c->alpha >> 8 << 24 | ra >> 24 << 16 | ga >> 24 << 8 | ba >> 24;
352.41653 ++}
352.41654 ++
352.41655 + void test_timer_start(struct test_display *t, struct timespec *tv);
352.41656 + double test_timer_stop(struct test_display *t, struct timespec *tv);
352.41657 + 
352.41658 +diff --git a/test/test_image.c b/test/test_image.c
352.41659 +index d15a8af8..1c076990 100644
352.41660 +--- a/test/test_image.c
352.41661 ++++ b/test/test_image.c
352.41662 +@@ -197,13 +197,10 @@ void test_compare(struct test *t,
352.41663 + 		  const char *info)
352.41664 + {
352.41665 + 	XImage out_image, ref_image;
352.41666 +-	Pixmap tmp;
352.41667 +-	char *out, *ref;
352.41668 ++	uint32_t *out, *ref;
352.41669 + 	char buf[600];
352.41670 + 	uint32_t mask;
352.41671 + 	int i, j;
352.41672 +-	XGCValues gcv;
352.41673 +-	GC gc;
352.41674 + 
352.41675 + 	if (w * h * 4 > t->out.max_shm_size)
352.41676 + 		return test_compare_fallback(t,
352.41677 +@@ -214,37 +211,24 @@ void test_compare(struct test *t,
352.41678 + 	test_init_image(&out_image, &t->out.shm, out_format, w, h);
352.41679 + 	test_init_image(&ref_image, &t->ref.shm, ref_format, w, h);
352.41680 + 
352.41681 +-	gcv.graphics_exposures = 0;
352.41682 +-
352.41683 + 	die_unless(out_image.depth == ref_image.depth);
352.41684 + 	die_unless(out_image.bits_per_pixel == ref_image.bits_per_pixel);
352.41685 + 	die_unless(out_image.bits_per_pixel == 32);
352.41686 + 
352.41687 +-	mask = depth_mask(out_image.depth);
352.41688 ++	XShmGetImage(t->out.dpy, out_draw, &out_image, x, y, AllPlanes);
352.41689 ++	out = (uint32_t *)out_image.data;
352.41690 + 
352.41691 +-	tmp = XCreatePixmap(t->out.dpy, out_draw, w, h, out_image.depth);
352.41692 +-	gc = XCreateGC(t->out.dpy, tmp, GCGraphicsExposures, &gcv);
352.41693 +-	XCopyArea(t->out.dpy, out_draw, tmp, gc, x, y, w, h, 0, 0);
352.41694 +-	XShmGetImage(t->out.dpy, tmp, &out_image, 0, 0, AllPlanes);
352.41695 +-	XFreeGC(t->out.dpy, gc);
352.41696 +-	XFreePixmap(t->out.dpy, tmp);
352.41697 +-	out = out_image.data;
352.41698 +-
352.41699 +-	tmp = XCreatePixmap(t->ref.dpy, ref_draw, w, h, ref_image.depth);
352.41700 +-	gc = XCreateGC(t->ref.dpy, tmp, GCGraphicsExposures, &gcv);
352.41701 +-	XCopyArea(t->ref.dpy, ref_draw, tmp, gc, x, y, w, h, 0, 0);
352.41702 +-	XShmGetImage(t->ref.dpy, tmp, &ref_image, 0, 0, AllPlanes);
352.41703 +-	XFreeGC(t->ref.dpy, gc);
352.41704 +-	XFreePixmap(t->ref.dpy, tmp);
352.41705 +-	ref = ref_image.data;
352.41706 ++	XShmGetImage(t->ref.dpy, ref_draw, &ref_image, x, y, AllPlanes);
352.41707 ++	ref = (uint32_t *)ref_image.data;
352.41708 + 
352.41709 + 	/* Start with an exact comparison. However, one quicky desires
352.41710 + 	 * a fuzzy comparator to hide hardware inaccuracies...
352.41711 + 	 */
352.41712 ++	mask = depth_mask(out_image.depth);
352.41713 + 	for (j = 0; j < h; j++) {
352.41714 + 		for (i = 0; i < w; i++) {
352.41715 +-			uint32_t a = ((uint32_t *)out)[i] & mask;
352.41716 +-			uint32_t b = ((uint32_t *)ref)[i] & mask;
352.41717 ++			uint32_t a = out[i] & mask;
352.41718 ++			uint32_t b = ref[i] & mask;
352.41719 + 			if (a != b && pixel_difference(a, b) > MAX_DELTA) {
352.41720 + 				show_pixels(buf,
352.41721 + 					    &out_image, &ref_image,
352.41722 +@@ -255,8 +239,8 @@ void test_compare(struct test *t,
352.41723 + 				    x,i, y,j, a, b, pixel_difference(a, b), buf, info);
352.41724 + 			}
352.41725 + 		}
352.41726 +-		out += out_image.bytes_per_line;
352.41727 +-		ref += ref_image.bytes_per_line;
352.41728 ++		out = (uint32_t *)((char *)out + out_image.bytes_per_line);
352.41729 ++		ref = (uint32_t *)((char *)ref + ref_image.bytes_per_line);
352.41730 + 	}
352.41731 + }
352.41732 + 
352.41733 +diff --git a/test/xvidmode.c b/test/xvidmode.c
352.41734 +new file mode 100644
352.41735 +index 00000000..5cde8286
352.41736 +--- /dev/null
352.41737 ++++ b/test/xvidmode.c
352.41738 +@@ -0,0 +1,54 @@
352.41739 ++#include <stdlib.h>
352.41740 ++#include <stdio.h>
352.41741 ++#include <string.h>
352.41742 ++#include <X11/Xlib.h>
352.41743 ++#include <X11/extensions/xf86vmode.h>
352.41744 ++
352.41745 ++int main(void)
352.41746 ++{
352.41747 ++	Display *dpy;
352.41748 ++	XF86VidModeModeLine current;
352.41749 ++	XF86VidModeModeInfo **modes;
352.41750 ++	int num_modes, i;
352.41751 ++	int saved_mode = -1;
352.41752 ++	int dotclock;
352.41753 ++
352.41754 ++	dpy = XOpenDisplay(NULL);
352.41755 ++	if (dpy == NULL)
352.41756 ++		dpy = XOpenDisplay(":0");
352.41757 ++
352.41758 ++	XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &dotclock, &current);
352.41759 ++	XF86VidModeGetAllModeLines(dpy, XDefaultScreen(dpy),
352.41760 ++				   &num_modes, &modes);
352.41761 ++	for (i = 0; i < num_modes; i++) {
352.41762 ++		int this;
352.41763 ++
352.41764 ++		this = (current.hdisplay == modes[i]->hdisplay &&
352.41765 ++			current.vdisplay == modes[i]->vdisplay &&
352.41766 ++			dotclock == modes[i]->dotclock);
352.41767 ++		if (this && saved_mode == -1)
352.41768 ++			saved_mode = i;
352.41769 ++
352.41770 ++		printf("[%d] %dx%d%s\n",
352.41771 ++		       i,
352.41772 ++		       modes[i]->hdisplay,
352.41773 ++		       modes[i]->vdisplay,
352.41774 ++		       this ? "*" : "");
352.41775 ++	}
352.41776 ++
352.41777 ++	for (i = 0; i < num_modes; i++) {
352.41778 ++		printf("Switching to mode %dx%d\n",
352.41779 ++		       modes[i]->hdisplay,
352.41780 ++		       modes[i]->vdisplay);
352.41781 ++		XF86VidModeSwitchToMode(dpy, XDefaultScreen(dpy), modes[i]);
352.41782 ++		XSync(dpy, True);
352.41783 ++	}
352.41784 ++
352.41785 ++	if (saved_mode != -1) {
352.41786 ++		XF86VidModeSwitchToMode(dpy, XDefaultScreen(dpy),
352.41787 ++					modes[saved_mode]);
352.41788 ++		XFlush(dpy);
352.41789 ++	}
352.41790 ++
352.41791 ++	return 0;
352.41792 ++}
352.41793 +diff --git a/tools/Makefile.am b/tools/Makefile.am
352.41794 +index b5de2c96..92df266b 100644
352.41795 +--- a/tools/Makefile.am
352.41796 ++++ b/tools/Makefile.am
352.41797 +@@ -26,13 +26,30 @@ AM_CFLAGS = \
352.41798 + drivermandir = $(DRIVER_MAN_DIR)
352.41799 + policydir = $(datarootdir)/polkit-1/actions
352.41800 + 
352.41801 ++bin_PROGRAMS =
352.41802 ++noinst_PROGRAMS =
352.41803 ++libexec_PROGRAMS =
352.41804 ++
352.41805 + if BUILD_TOOLS
352.41806 +-bin_PROGRAMS = intel-virtual-output
352.41807 ++bin_PROGRAMS += intel-virtual-output
352.41808 + driverman_DATA = intel-virtual-output.$(DRIVER_MAN_SUFFIX)
352.41809 + endif
352.41810 + 
352.41811 ++if BUILD_TOOL_CURSOR
352.41812 ++noinst_PROGRAMS += cursor
352.41813 ++cursor_CFLAGS = $(TOOL_CURSOR_CFLAGS)
352.41814 ++cursor_LDADD = $(TOOL_CURSOR_LIBS)
352.41815 ++endif
352.41816 ++
352.41817 ++if X11_DRI3
352.41818 ++noinst_PROGRAMS += dri3info
352.41819 ++dri3info_SOURCES = dri3info.c
352.41820 ++dri3info_CFLAGS = $(X11_DRI3_CFLAGS) $(DRI_CFLAGS)
352.41821 ++dri3info_LDADD = $(X11_DRI3_LIBS) $(DRI_LIBS)
352.41822 ++endif
352.41823 ++
352.41824 + if BUILD_BACKLIGHT_HELPER
352.41825 +-libexec_PROGRAMS = xf86-video-intel-backlight-helper
352.41826 ++libexec_PROGRAMS += xf86-video-intel-backlight-helper
352.41827 + nodist_policy_DATA = org.x.xf86-video-intel.backlight-helper.policy
352.41828 + 
352.41829 + backlight_helper = $(libexecdir)/xf86-video-intel-backlight-helper
352.41830 +diff --git a/tools/backlight_helper.c b/tools/backlight_helper.c
352.41831 +index 8b2667dc..aadb8fac 100644
352.41832 +--- a/tools/backlight_helper.c
352.41833 ++++ b/tools/backlight_helper.c
352.41834 +@@ -1,3 +1,7 @@
352.41835 ++#ifdef HAVE_CONFIG_H
352.41836 ++#include "config.h"
352.41837 ++#endif
352.41838 ++
352.41839 + #include <stdio.h>
352.41840 + #include <string.h>
352.41841 + #include <stdarg.h>
352.41842 +@@ -9,6 +13,12 @@
352.41843 + #include <sys/types.h>
352.41844 + #include <sys/stat.h>
352.41845 + 
352.41846 ++#if MAJOR_IN_MKDEV
352.41847 ++#include <sys/mkdev.h>
352.41848 ++#elif MAJOR_IN_SYSMACROS
352.41849 ++#include <sys/sysmacros.h>
352.41850 ++#endif
352.41851 ++
352.41852 + #define DBG 0
352.41853 + 
352.41854 + #if defined(__GNUC__) && (__GNUC__ > 3)
352.41855 +diff --git a/tools/cursor.c b/tools/cursor.c
352.41856 +new file mode 100644
352.41857 +index 00000000..6a2438ad
352.41858 +--- /dev/null
352.41859 ++++ b/tools/cursor.c
352.41860 +@@ -0,0 +1,127 @@
352.41861 ++/*
352.41862 ++ * Copyright © 2015 Intel Corporation
352.41863 ++ *
352.41864 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.41865 ++ * copy of this software and associated documentation files (the "Software"),
352.41866 ++ * to deal in the Software without restriction, including without limitation
352.41867 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.41868 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.41869 ++ * Software is furnished to do so, subject to the following conditions:
352.41870 ++ *
352.41871 ++ * The above copyright notice and this permission notice (including the next
352.41872 ++ * paragraph) shall be included in all copies or substantial portions of the
352.41873 ++ * Software.
352.41874 ++ *
352.41875 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.41876 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.41877 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.41878 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.41879 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
352.41880 ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
352.41881 ++ * IN THE SOFTWARE.
352.41882 ++ *
352.41883 ++ */
352.41884 ++
352.41885 ++#ifdef HAVE_CONFIG_H
352.41886 ++#include "config.h"
352.41887 ++#endif
352.41888 ++
352.41889 ++#include <X11/Xlib.h>
352.41890 ++#include <X11/extensions/Xfixes.h>
352.41891 ++
352.41892 ++#include <stdint.h>
352.41893 ++#include <stdio.h>
352.41894 ++#include <stdlib.h>
352.41895 ++#include <png.h>
352.41896 ++
352.41897 ++int main(int argc, char **argv)
352.41898 ++{
352.41899 ++	Display *dpy;
352.41900 ++	XFixesCursorImage *cur;
352.41901 ++	unsigned long *src; /* XXX deep sigh */
352.41902 ++	unsigned x, y;
352.41903 ++	png_struct *png;
352.41904 ++	png_info *info;
352.41905 ++	png_byte **rows;
352.41906 ++	FILE *file;
352.41907 ++
352.41908 ++	dpy = XOpenDisplay(NULL);
352.41909 ++	if (dpy == NULL)
352.41910 ++		return 1;
352.41911 ++
352.41912 ++	if (!XFixesQueryExtension(dpy, (int *)&x, (int *)&y))
352.41913 ++		return 1;
352.41914 ++
352.41915 ++	cur = XFixesGetCursorImage(dpy);
352.41916 ++	if (cur == NULL)
352.41917 ++		return 1;
352.41918 ++
352.41919 ++	printf("Cursor on display '%s': %dx%d, (hotspot %dx%d)\n",
352.41920 ++	       DisplayString(dpy),
352.41921 ++	       cur->width, cur->height,
352.41922 ++	       cur->xhot, cur->yhot);
352.41923 ++
352.41924 ++	if (1) {
352.41925 ++		int x, y;
352.41926 ++
352.41927 ++		src = cur->pixels;
352.41928 ++		for (y = 0; y < cur->height; y++) {
352.41929 ++			for (x = 0; x < cur->width; x++) {
352.41930 ++				if (x == cur->xhot && y == cur->yhot)
352.41931 ++					printf("+");
352.41932 ++				else
352.41933 ++					printf("%c", *src ? *src >> 24 >= 127 ? 'x' : '.' : ' ');
352.41934 ++				src++;
352.41935 ++			}
352.41936 ++			printf("\n");
352.41937 ++		}
352.41938 ++	}
352.41939 ++
352.41940 ++	file = fopen("cursor.png", "wb");
352.41941 ++	if (file == NULL)
352.41942 ++		return 2;
352.41943 ++
352.41944 ++	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
352.41945 ++	info = png_create_info_struct(png);
352.41946 ++	png_init_io(png, file);
352.41947 ++	png_set_IHDR(png, info,
352.41948 ++		     cur->width, cur->height, 8,
352.41949 ++		     PNG_COLOR_TYPE_RGB_ALPHA,
352.41950 ++		     PNG_INTERLACE_NONE,
352.41951 ++		     PNG_COMPRESSION_TYPE_DEFAULT,
352.41952 ++		     PNG_FILTER_TYPE_DEFAULT);
352.41953 ++	png_write_info(png, info);
352.41954 ++
352.41955 ++	src = cur->pixels;
352.41956 ++	rows = malloc(cur->height*sizeof(png_byte*));
352.41957 ++	if (rows == NULL)
352.41958 ++		return 3;
352.41959 ++
352.41960 ++	for (y = 0; y < cur->height; y++) {
352.41961 ++		rows[y] = malloc(cur->width * 4);
352.41962 ++		for (x = 0; x < cur->width; x++) {
352.41963 ++			uint32_t p = *src++;
352.41964 ++			uint8_t r = p >> 0;
352.41965 ++			uint8_t g = p >> 8;
352.41966 ++			uint8_t b = p >> 16;
352.41967 ++			uint8_t a = p >> 24;
352.41968 ++
352.41969 ++			if (a > 0x00 && a < 0xff) {
352.41970 ++				r = (r * 0xff + a /2) / a;
352.41971 ++				g = (g * 0xff + a /2) / a;
352.41972 ++				b = (b * 0xff + a /2) / a;
352.41973 ++			}
352.41974 ++
352.41975 ++			rows[y][4*x + 0] = b;
352.41976 ++			rows[y][4*x + 1] = g;
352.41977 ++			rows[y][4*x + 2] = r;
352.41978 ++			rows[y][4*x + 3] = a;
352.41979 ++		}
352.41980 ++	}
352.41981 ++
352.41982 ++	png_write_image(png, rows);
352.41983 ++	png_write_end(png, NULL);
352.41984 ++	fclose(file);
352.41985 ++
352.41986 ++	return 0;
352.41987 ++}
352.41988 +diff --git a/tools/dri3info.c b/tools/dri3info.c
352.41989 +new file mode 100644
352.41990 +index 00000000..0c33fc5a
352.41991 +--- /dev/null
352.41992 ++++ b/tools/dri3info.c
352.41993 +@@ -0,0 +1,329 @@
352.41994 ++/*
352.41995 ++ * Copyright (c) 2015 Intel Corporation
352.41996 ++ *
352.41997 ++ * Permission is hereby granted, free of charge, to any person obtaining a
352.41998 ++ * copy of this software and associated documentation files (the "Software"),
352.41999 ++ * to deal in the Software without restriction, including without limitation
352.42000 ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
352.42001 ++ * and/or sell copies of the Software, and to permit persons to whom the
352.42002 ++ * Software is furnished to do so, subject to the following conditions:
352.42003 ++ *
352.42004 ++ * The above copyright notice and this permission notice (including the next
352.42005 ++ * paragraph) shall be included in all copies or substantial portions of the
352.42006 ++ * Software.
352.42007 ++ *
352.42008 ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
352.42009 ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
352.42010 ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
352.42011 ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
352.42012 ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
352.42013 ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
352.42014 ++ * SOFTWARE.
352.42015 ++ *
352.42016 ++ * To compile standalone: gcc -o dri3info dri3info.c `pkg-config --cflags --libs xcb-dri3 x11-xcb xrandr xxf86vm libdrm`
352.42017 ++ */
352.42018 ++
352.42019 ++#include <X11/Xlib.h>
352.42020 ++#include <X11/Xlib-xcb.h>
352.42021 ++#include <xcb/xcb.h>
352.42022 ++#include <xcb/dri3.h>
352.42023 ++#include <unistd.h>
352.42024 ++#include <stdio.h>
352.42025 ++#include <stdlib.h>
352.42026 ++#include <stdint.h>
352.42027 ++#include <string.h>
352.42028 ++#include <sys/stat.h>
352.42029 ++#include <drm.h>
352.42030 ++#include <xf86drm.h>
352.42031 ++
352.42032 ++#include <X11/extensions/Xrandr.h>
352.42033 ++#include <X11/extensions/xf86vmode.h>
352.42034 ++
352.42035 ++static int dri3_query_version(Display *dpy, int *major, int *minor)
352.42036 ++{
352.42037 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.42038 ++	xcb_dri3_query_version_reply_t *reply;
352.42039 ++	xcb_generic_error_t *error;
352.42040 ++
352.42041 ++	*major = *minor = -1;
352.42042 ++
352.42043 ++	reply = xcb_dri3_query_version_reply(c,
352.42044 ++					     xcb_dri3_query_version(c,
352.42045 ++								    XCB_DRI3_MAJOR_VERSION,
352.42046 ++								    XCB_DRI3_MINOR_VERSION),
352.42047 ++					     &error);
352.42048 ++	free(error);
352.42049 ++	if (reply == NULL)
352.42050 ++		return -1;
352.42051 ++
352.42052 ++	*major = reply->major_version;
352.42053 ++	*minor = reply->minor_version;
352.42054 ++	free(reply);
352.42055 ++
352.42056 ++	return 0;
352.42057 ++}
352.42058 ++
352.42059 ++static int dri3_exists(Display *dpy)
352.42060 ++{
352.42061 ++	const xcb_query_extension_reply_t *ext;
352.42062 ++	int major, minor;
352.42063 ++
352.42064 ++	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
352.42065 ++	if (ext == NULL || !ext->present)
352.42066 ++		return 0;
352.42067 ++
352.42068 ++	if (dri3_query_version(dpy, &major, &minor) < 0)
352.42069 ++		return 0;
352.42070 ++
352.42071 ++	return major >= 0;
352.42072 ++}
352.42073 ++
352.42074 ++static int dri3_open(Display *dpy)
352.42075 ++{
352.42076 ++	xcb_connection_t *c = XGetXCBConnection(dpy);
352.42077 ++	xcb_dri3_open_cookie_t cookie;
352.42078 ++	xcb_dri3_open_reply_t *reply;
352.42079 ++
352.42080 ++	if (!dri3_exists(dpy))
352.42081 ++		return -1;
352.42082 ++
352.42083 ++	cookie = xcb_dri3_open(c, RootWindow(dpy, DefaultScreen(dpy)), None);
352.42084 ++	reply = xcb_dri3_open_reply(c, cookie, NULL);
352.42085 ++
352.42086 ++	if (!reply)
352.42087 ++		return -1;
352.42088 ++
352.42089 ++	if (reply->nfd != 1)
352.42090 ++		return -1;
352.42091 ++
352.42092 ++	return xcb_dri3_open_reply_fds(c, reply)[0];
352.42093 ++}
352.42094 ++
352.42095 ++static void get_device_path(int fd, char *buf, int len)
352.42096 ++{
352.42097 ++	struct stat remote, local;
352.42098 ++	int i;
352.42099 ++
352.42100 ++	if (fstat(fd, &remote))
352.42101 ++		goto out;
352.42102 ++
352.42103 ++	for (i = 0; i < 16; i++) {
352.42104 ++		snprintf(buf, len, "/dev/dri/card%d", i);
352.42105 ++		if (stat(buf, &local))
352.42106 ++			continue;
352.42107 ++
352.42108 ++		if (local.st_mode == remote.st_mode &&
352.42109 ++		    local.st_rdev == remote.st_rdev)
352.42110 ++			return;
352.42111 ++
352.42112 ++		snprintf(buf, len, "/dev/dri/renderD%d", i + 128);
352.42113 ++		if (stat(buf, &local))
352.42114 ++			continue;
352.42115 ++
352.42116 ++		if (local.st_mode == remote.st_mode &&
352.42117 ++		    local.st_rdev == remote.st_rdev)
352.42118 ++			return;
352.42119 ++	}
352.42120 ++
352.42121 ++out:
352.42122 ++	strncpy(buf, "unknown path", len);
352.42123 ++}
352.42124 ++
352.42125 ++static void get_driver_name(int fd, char *name, int len)
352.42126 ++{
352.42127 ++	drm_version_t version;
352.42128 ++
352.42129 ++	memset(name, 0, len);
352.42130 ++	memset(&version, 0, sizeof(version));
352.42131 ++	version.name_len = len;
352.42132 ++	version.name = name;
352.42133 ++
352.42134 ++	(void)drmIoctl(fd, DRM_IOCTL_VERSION, &version);
352.42135 ++}
352.42136 ++
352.42137 ++static int compute_refresh_rate_from_mode(long n, long d, unsigned flags,
352.42138 ++					   int32_t *numerator,
352.42139 ++					   int32_t *denominator)
352.42140 ++{
352.42141 ++	int i;
352.42142 ++
352.42143 ++	/* The mode flags are only defined privately to the Xserver (in xf86str.h)
352.42144 ++	 * but they at least bit compatible between VidMode, RandR and DRM.
352.42145 ++	 */
352.42146 ++# define V_INTERLACE 0x010
352.42147 ++# define V_DBLSCAN   0x020
352.42148 ++
352.42149 ++	if (flags & V_INTERLACE)
352.42150 ++		n *= 2;
352.42151 ++	else if (flags & V_DBLSCAN)
352.42152 ++		d *= 2;
352.42153 ++
352.42154 ++	/* The OML_sync_control spec requires that if the refresh rate is a
352.42155 ++	 * whole number, that the returned numerator be equal to the refresh
352.42156 ++	 * rate and the denominator be 1.
352.42157 ++	 */
352.42158 ++
352.42159 ++	if (n % d == 0) {
352.42160 ++		n /= d;
352.42161 ++		d = 1;
352.42162 ++	}
352.42163 ++	else {
352.42164 ++		static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
352.42165 ++
352.42166 ++		/* This is a poor man's way to reduce a fraction.  It's far from
352.42167 ++		 * perfect, but it will work well enough for this situation.
352.42168 ++		 */
352.42169 ++
352.42170 ++		for (i = 0; f[i] != 0; i++) {
352.42171 ++			while (n % f[i] == 0 && d % f[i] == 0) {
352.42172 ++				d /= f[i];
352.42173 ++				n /= f[i];
352.42174 ++			}
352.42175 ++		}
352.42176 ++	}
352.42177 ++
352.42178 ++	*numerator = n;
352.42179 ++	*denominator = d;
352.42180 ++	return 1;
352.42181 ++}
352.42182 ++
352.42183 ++static int RRGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
352.42184 ++{
352.42185 ++	int ret = 0;
352.42186 ++	Window root = RootWindow(dpy, DefaultScreen(dpy));
352.42187 ++	XRRScreenResources *res;
352.42188 ++	int rr_event, rr_error;
352.42189 ++	RROutput primary;
352.42190 ++	RRMode mode = 0;
352.42191 ++	int n;
352.42192 ++
352.42193 ++	if (!XRRQueryExtension(dpy, &rr_event, &rr_error))
352.42194 ++		return ret;
352.42195 ++
352.42196 ++	res = XRRGetScreenResourcesCurrent(dpy, root);
352.42197 ++	if (res == NULL)
352.42198 ++		return ret;
352.42199 ++
352.42200 ++	/* Use the primary output if specified, otherwise
352.42201 ++	 * use the mode on the first enabled crtc.
352.42202 ++	 */
352.42203 ++	primary = XRRGetOutputPrimary(dpy, root);
352.42204 ++	if (primary) {
352.42205 ++		XRROutputInfo *output;
352.42206 ++
352.42207 ++		output = XRRGetOutputInfo(dpy, res, primary);
352.42208 ++		if (output != NULL) {
352.42209 ++			if (output->crtc) {
352.42210 ++				XRRCrtcInfo *crtc;
352.42211 ++
352.42212 ++				crtc = XRRGetCrtcInfo(dpy, res, output->crtc);
352.42213 ++				if (crtc) {
352.42214 ++					mode = crtc->mode;
352.42215 ++					XRRFreeCrtcInfo(crtc);
352.42216 ++				}
352.42217 ++			}
352.42218 ++			XRRFreeOutputInfo(output);
352.42219 ++		}
352.42220 ++	}
352.42221 ++
352.42222 ++	for (n = 0; mode == 0 && n < res->ncrtc; n++) {
352.42223 ++		XRRCrtcInfo *crtc;
352.42224 ++
352.42225 ++		crtc = XRRGetCrtcInfo(dpy, res, res->crtcs[n]);
352.42226 ++		if (crtc) {
352.42227 ++			mode = crtc->mode;
352.42228 ++			XRRFreeCrtcInfo(crtc);
352.42229 ++		}
352.42230 ++	}
352.42231 ++
352.42232 ++	for (n = 0; n < res->nmode; n++) {
352.42233 ++		if (res->modes[n].id == mode) {
352.42234 ++			ret = compute_refresh_rate_from_mode(res->modes[n].dotClock,
352.42235 ++							     res->modes[n].hTotal*res->modes[n].vTotal,
352.42236 ++							     res->modes[n].modeFlags,
352.42237 ++							     numerator, denominator);
352.42238 ++			break;
352.42239 ++		}
352.42240 ++	}
352.42241 ++
352.42242 ++	XRRFreeScreenResources(res);
352.42243 ++	return ret;
352.42244 ++}
352.42245 ++
352.42246 ++static int VMGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
352.42247 ++{
352.42248 ++	XF86VidModeModeLine mode_line;
352.42249 ++	int dot_clock;
352.42250 ++	int i;
352.42251 ++
352.42252 ++	if (XF86VidModeQueryVersion(dpy, &i, &i) &&
352.42253 ++	    XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &dot_clock, &mode_line))
352.42254 ++		return compute_refresh_rate_from_mode(dot_clock * 1000,
352.42255 ++						      mode_line.vtotal * mode_line.htotal,
352.42256 ++						      mode_line.flags,
352.42257 ++						      numerator, denominator);
352.42258 ++
352.42259 ++	return 0;
352.42260 ++}
352.42261 ++
352.42262 ++static int get_refresh_rate(Display *dpy,
352.42263 ++			     int32_t *numerator,
352.42264 ++			     int32_t *denominator)
352.42265 ++{
352.42266 ++	if (RRGetMscRate(dpy, numerator, denominator))
352.42267 ++		return 1;
352.42268 ++
352.42269 ++	if (VMGetMscRate(dpy, numerator, denominator))
352.42270 ++		return 1;
352.42271 ++
352.42272 ++	return 0;
352.42273 ++}
352.42274 ++
352.42275 ++static void info(const char *dpyname)
352.42276 ++{
352.42277 ++	Display *dpy;
352.42278 ++	int device;
352.42279 ++	int32_t numerator, denominator;
352.42280 ++
352.42281 ++	dpy = XOpenDisplay(dpyname);
352.42282 ++	if (dpy == NULL) {
352.42283 ++		printf("Unable to connect to display '%s'\n",
352.42284 ++		       dpyname ?: getenv("DISPLAY") ?: "unset");
352.42285 ++		return;
352.42286 ++	}
352.42287 ++
352.42288 ++	printf("Display '%s'\n", DisplayString(dpy));
352.42289 ++	device = dri3_open(dpy);
352.42290 ++	if (device < 0) {
352.42291 ++		printf("\tUnable to connect to DRI3\n");
352.42292 ++	} else {
352.42293 ++		char device_path[1024];
352.42294 ++		char driver_name[1024];
352.42295 ++
352.42296 ++		get_device_path(device, device_path, sizeof(device_path));
352.42297 ++		get_driver_name(device, driver_name, sizeof(driver_name));
352.42298 ++
352.42299 ++		printf("Connected to DRI3, using fd %d which matches %s, driver %s\n",
352.42300 ++		       device, device_path, driver_name);
352.42301 ++		close(device);
352.42302 ++	}
352.42303 ++
352.42304 ++	if (get_refresh_rate(dpy, &numerator, &denominator))
352.42305 ++		printf("\tPrimary refresh rate: %d/%d (%.1fHz)\n",
352.42306 ++		       numerator, denominator, numerator/(float)denominator);
352.42307 ++
352.42308 ++	XCloseDisplay(dpy);
352.42309 ++}
352.42310 ++
352.42311 ++int main(int argc, char **argv)
352.42312 ++{
352.42313 ++	int i;
352.42314 ++
352.42315 ++	if (argc > 1) {
352.42316 ++		for (i = 1; i < argc; i++)
352.42317 ++			info(argv[i]);
352.42318 ++	} else
352.42319 ++		info(NULL);
352.42320 ++
352.42321 ++	return 0;
352.42322 ++}
352.42323 +diff --git a/tools/virtual.c b/tools/virtual.c
352.42324 +index 8e2b4a22..fc8db2b9 100644
352.42325 +--- a/tools/virtual.c
352.42326 ++++ b/tools/virtual.c
352.42327 +@@ -31,6 +31,7 @@
352.42328 + 
352.42329 + #include <X11/Xlibint.h>
352.42330 + #include <X11/extensions/record.h>
352.42331 ++#include <X11/extensions/scrnsaver.h>
352.42332 + #include <X11/extensions/XShm.h>
352.42333 + #if HAVE_X11_EXTENSIONS_SHMPROTO_H
352.42334 + #include <X11/extensions/shmproto.h>
352.42335 +@@ -79,13 +80,15 @@ static int verbose;
352.42336 + #define DRAW 0x8
352.42337 + #define DAMAGE 0x10
352.42338 + #define CURSOR 0x20
352.42339 +-#define POLL 0x40
352.42340 ++#define SCREEN 0x40
352.42341 ++#define POLL 0x80
352.42342 + 
352.42343 + struct display {
352.42344 + 	Display *dpy;
352.42345 + 	struct clone *clone;
352.42346 + 	struct context *ctx;
352.42347 + 
352.42348 ++	int saver_event, saver_error, saver_active;
352.42349 + 	int damage_event, damage_error;
352.42350 + 	int xfixes_event, xfixes_error;
352.42351 + 	int rr_event, rr_error, rr_active;
352.42352 +@@ -98,6 +101,7 @@ struct display {
352.42353 + 	int width;
352.42354 + 	int height;
352.42355 + 	int depth;
352.42356 ++	int active;
352.42357 + 
352.42358 + 	XRenderPictFormat *root_format;
352.42359 + 	XRenderPictFormat *rgb16_format;
352.42360 +@@ -111,7 +115,7 @@ struct display {
352.42361 + 	Cursor invisible_cursor;
352.42362 + 	Cursor visible_cursor;
352.42363 + 
352.42364 +-	XcursorImage cursor_image;
352.42365 ++	XcursorImage cursor_image; /* first only */
352.42366 + 	int cursor_serial;
352.42367 + 	int cursor_x;
352.42368 + 	int cursor_y;
352.42369 +@@ -123,6 +127,13 @@ struct display {
352.42370 + 	int send;
352.42371 + 	int skip_clone;
352.42372 + 	int skip_frame;
352.42373 ++
352.42374 ++	struct {
352.42375 ++		int timeout;
352.42376 ++		int interval;
352.42377 ++		int prefer_blank;
352.42378 ++		int allow_exp;
352.42379 ++	} saver;
352.42380 + };
352.42381 + 
352.42382 + struct output {
352.42383 +@@ -145,6 +156,7 @@ struct output {
352.42384 + 	XRenderPictFormat *use_render;
352.42385 + 
352.42386 + 	int x, y;
352.42387 ++	int width, height;
352.42388 + 	XRRModeInfo mode;
352.42389 + 	Rotation rotation;
352.42390 + };
352.42391 +@@ -218,6 +230,13 @@ static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Wi
352.42392 + static int _x_error_occurred;
352.42393 + 
352.42394 + static int
352.42395 ++_io_error_handler(Display *display)
352.42396 ++{
352.42397 ++	fprintf(stderr, "XIO error on display %s\n", DisplayString(display));
352.42398 ++	abort();
352.42399 ++}
352.42400 ++
352.42401 ++static int
352.42402 + _check_error_handler(Display     *display,
352.42403 + 		     XErrorEvent *event)
352.42404 + {
352.42405 +@@ -243,6 +262,10 @@ can_use_shm(Display *dpy,
352.42406 + 	XExtCodes *codes;
352.42407 + 	int major, minor, has_shm, has_pixmap;
352.42408 + 
352.42409 ++	*shm_event = 0;
352.42410 ++	*shm_opcode = 0;
352.42411 ++	*shm_pixmap = 0;
352.42412 ++
352.42413 + 	if (!XShmQueryExtension(dpy))
352.42414 + 		return 0;
352.42415 + 
352.42416 +@@ -320,6 +343,7 @@ can_use_shm(Display *dpy,
352.42417 + #include <X11/Xlib-xcb.h>
352.42418 + #include <X11/xshmfence.h>
352.42419 + #include <xcb/xcb.h>
352.42420 ++#include <xcb/xcbext.h>
352.42421 + #include <xcb/dri3.h>
352.42422 + #include <xcb/sync.h>
352.42423 + static Pixmap dri3_create_pixmap(Display *dpy,
352.42424 +@@ -357,6 +381,7 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
352.42425 + {
352.42426 + 	xcb_connection_t *c = XGetXCBConnection(dpy);
352.42427 + 	xcb_dri3_query_version_reply_t *reply;
352.42428 ++	xcb_generic_error_t *error;
352.42429 + 
352.42430 + 	*major = *minor = -1;
352.42431 + 
352.42432 +@@ -364,7 +389,8 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
352.42433 + 					     xcb_dri3_query_version(c,
352.42434 + 								    XCB_DRI3_MAJOR_VERSION,
352.42435 + 								    XCB_DRI3_MINOR_VERSION),
352.42436 +-					     NULL);
352.42437 ++					     &error);
352.42438 ++	free(error);
352.42439 + 	if (reply == NULL)
352.42440 + 		return -1;
352.42441 + 
352.42442 +@@ -377,8 +403,13 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
352.42443 + 
352.42444 + static int dri3_exists(Display *dpy)
352.42445 + {
352.42446 ++	const xcb_query_extension_reply_t *ext;
352.42447 + 	int major, minor;
352.42448 + 
352.42449 ++	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
352.42450 ++	if (ext == NULL || !ext->present)
352.42451 ++		return 0;
352.42452 ++
352.42453 + 	if (dri3_query_version(dpy, &major, &minor) < 0)
352.42454 + 		return 0;
352.42455 + 
352.42456 +@@ -809,6 +840,10 @@ static int clone_update_modes__fixed(struct clone *clone)
352.42457 + 	RRMode id;
352.42458 + 	int i, j, ret = ENOENT;
352.42459 + 
352.42460 ++	DBG(X11, ("%s-%s cloning modes fixed %dx%d\n",
352.42461 ++	     DisplayString(clone->dst.dpy), clone->dst.name,
352.42462 ++	     clone->dst.width, clone->dst.height));
352.42463 ++
352.42464 + 	assert(clone->src.rr_output);
352.42465 + 
352.42466 + 	res = _XRRGetScreenResourcesCurrent(clone->src.dpy, clone->src.window);
352.42467 +@@ -837,8 +872,8 @@ static int clone_update_modes__fixed(struct clone *clone)
352.42468 + 
352.42469 + 	/* Create matching mode for the real output on the virtual */
352.42470 + 	memset(&mode, 0, sizeof(mode));
352.42471 +-	mode.width = clone->width;
352.42472 +-	mode.height = clone->height;
352.42473 ++	mode.width = clone->dst.width;
352.42474 ++	mode.height = clone->dst.height;
352.42475 + 	mode.nameLength = sprintf(mode_name, "FAKE-%dx%d", mode.width, mode.height);
352.42476 + 	mode.name = mode_name;
352.42477 + 
352.42478 +@@ -942,6 +977,35 @@ out:
352.42479 + 	return rr_output;
352.42480 + }
352.42481 + 
352.42482 ++static int check_virtual(struct display *display)
352.42483 ++{
352.42484 ++	XRRScreenResources *res;
352.42485 ++	int found = -ENOENT;
352.42486 ++	int i;
352.42487 ++
352.42488 ++	res = _XRRGetScreenResourcesCurrent(display->dpy, display->root);
352.42489 ++	if (res == NULL)
352.42490 ++		return -ENOMEM;
352.42491 ++
352.42492 ++	for (i = 0; found == -ENOENT && i < res->noutput; i++) {
352.42493 ++		XRROutputInfo *output;
352.42494 ++
352.42495 ++		output = XRRGetOutputInfo(display->dpy, res, res->outputs[i]);
352.42496 ++		if (output == NULL)
352.42497 ++			continue;
352.42498 ++
352.42499 ++		if (strcmp(output->name, "VIRTUAL1") == 0)
352.42500 ++			found = 0;
352.42501 ++
352.42502 ++		XRRFreeOutputInfo(output);
352.42503 ++	}
352.42504 ++	XRRFreeScreenResources(res);
352.42505 ++
352.42506 ++	DBG(XRR, ("%s(%s): has VIRTUAL1? %d\n",
352.42507 ++		  __func__, DisplayString(display->dpy), found));
352.42508 ++	return found;
352.42509 ++}
352.42510 ++
352.42511 + static int stride_for_depth(int width, int depth)
352.42512 + {
352.42513 + 	if (depth == 24)
352.42514 +@@ -1082,20 +1146,20 @@ static int clone_init_xfer(struct clone *clone)
352.42515 + 		width = 0;
352.42516 + 		height = 0;
352.42517 + 	} else if (clone->dri3.xid) {
352.42518 +-		width = clone->dst.display->width;
352.42519 +-		height = clone->dst.display->height;
352.42520 ++		width = clone->dst.width;
352.42521 ++		height = clone->dst.height;
352.42522 + 	} else {
352.42523 + 		width = mode_width(&clone->src.mode, clone->src.rotation);
352.42524 + 		height = mode_height(&clone->src.mode, clone->src.rotation);
352.42525 + 	}
352.42526 + 
352.42527 ++	DBG(DRAW, ("%s-%s create xfer, %dx%d (currently %dx%d)\n",
352.42528 ++	     DisplayString(clone->dst.dpy), clone->dst.name,
352.42529 ++	     width, height, clone->width, clone->height));
352.42530 ++
352.42531 + 	if (width == clone->width && height == clone->height)
352.42532 + 		return 0;
352.42533 + 
352.42534 +-	DBG(DRAW, ("%s-%s create xfer, %dx%d\n",
352.42535 +-	     DisplayString(clone->dst.dpy), clone->dst.name,
352.42536 +-	     width, height));
352.42537 +-
352.42538 + 	if (clone->shm.shmaddr) {
352.42539 + 		if (clone->src.use_shm)
352.42540 + 			XShmDetach(clone->src.dpy, &clone->src.shm);
352.42541 +@@ -1225,6 +1289,56 @@ static void clone_update(struct clone *clone)
352.42542 + 	clone->rr_update = 0;
352.42543 + }
352.42544 + 
352.42545 ++static void screensaver_save(struct display *display)
352.42546 ++{
352.42547 ++	display->saver_active =
352.42548 ++		XScreenSaverQueryExtension(display->dpy,
352.42549 ++					   &display->saver_event,
352.42550 ++					   &display->saver_error);
352.42551 ++	DBG(SCREEN,
352.42552 ++	    ("%s screen saver active? %d [event=%d, error=%d]\n",
352.42553 ++	     DisplayString(display->dpy),
352.42554 ++	     display->saver_active,
352.42555 ++	     display->saver_event,
352.42556 ++	     display->saver_error));
352.42557 ++
352.42558 ++	XGetScreenSaver(display->dpy,
352.42559 ++			&display->saver.timeout,
352.42560 ++			&display->saver.interval,
352.42561 ++			&display->saver.prefer_blank,
352.42562 ++			&display->saver.allow_exp);
352.42563 ++
352.42564 ++	DBG(SCREEN,
352.42565 ++	    ("%s saving screen saver defaults: timeout=%d interval=%d prefer_blank=%d allow_exp=%d\n",
352.42566 ++	     DisplayString(display->dpy),
352.42567 ++	     display->saver.timeout,
352.42568 ++	     display->saver.interval,
352.42569 ++	     display->saver.prefer_blank,
352.42570 ++	     display->saver.allow_exp));
352.42571 ++}
352.42572 ++
352.42573 ++static void screensaver_disable(struct display *display)
352.42574 ++{
352.42575 ++	DBG(SCREEN,
352.42576 ++	    ("%s disabling screen saver\n", DisplayString(display->dpy)));
352.42577 ++
352.42578 ++	XSetScreenSaver(display->dpy, 0, 0, DefaultBlanking, DefaultExposures);
352.42579 ++	display_mark_flush(display);
352.42580 ++}
352.42581 ++
352.42582 ++static void screensaver_restore(struct display *display)
352.42583 ++{
352.42584 ++	DBG(SCREEN,
352.42585 ++	    ("%s restoring screen saver\n", DisplayString(display->dpy)));
352.42586 ++
352.42587 ++	XSetScreenSaver(display->dpy,
352.42588 ++			display->saver.timeout,
352.42589 ++			display->saver.interval,
352.42590 ++			display->saver.prefer_blank,
352.42591 ++			display->saver.allow_exp);
352.42592 ++	display_mark_flush(display);
352.42593 ++}
352.42594 ++
352.42595 + static int context_update(struct context *ctx)
352.42596 + {
352.42597 + 	Display *dpy = ctx->display->dpy;
352.42598 +@@ -1325,8 +1439,19 @@ static int context_update(struct context *ctx)
352.42599 + 		struct clone *clone;
352.42600 + 		int x1, x2, y1, y2;
352.42601 + 
352.42602 +-		if (display->rr_active == 0)
352.42603 ++		if (display->rr_active == 0) {
352.42604 ++			for (clone = display->clone; clone; clone = clone->next) {
352.42605 ++				struct output *output = &clone->src;
352.42606 ++				if (output->mode.id) {
352.42607 ++					clone->dst.mode.id = -1;
352.42608 ++					clone->dst.rr_crtc = -1;
352.42609 ++				} else {
352.42610 ++					clone->dst.mode.id = 0;
352.42611 ++					clone->dst.rr_crtc = 0;
352.42612 ++				}
352.42613 ++			}
352.42614 + 			continue;
352.42615 ++		}
352.42616 + 
352.42617 + 		x1 = y1 = INT_MAX;
352.42618 + 		x2 = y2 = INT_MIN;
352.42619 +@@ -1570,6 +1695,13 @@ ungrab:
352.42620 + 		XUngrabServer(display->dpy);
352.42621 + 	}
352.42622 + 
352.42623 ++	for (n = 1; n < ctx->ndisplay; n++) {
352.42624 ++		struct display *display = &ctx->display[n];
352.42625 ++
352.42626 ++		display->active = 0;
352.42627 ++		screensaver_restore(display);
352.42628 ++	}
352.42629 ++
352.42630 + 	ctx->active = NULL;
352.42631 + 	for (n = 0; n < ctx->nclone; n++) {
352.42632 + 		struct clone *clone = &ctx->clones[n];
352.42633 +@@ -1580,7 +1712,10 @@ ungrab:
352.42634 + 			continue;
352.42635 + 
352.42636 + 		DBG(XRR, ("%s-%s: added to active list\n",
352.42637 +-		     DisplayString(clone->dst.display->dpy), clone->dst.name));
352.42638 ++			  DisplayString(clone->dst.display->dpy), clone->dst.name));
352.42639 ++
352.42640 ++		if (clone->dst.display->active++ == 0)
352.42641 ++			screensaver_disable(clone->dst.display);
352.42642 + 
352.42643 + 		clone->active = ctx->active;
352.42644 + 		ctx->active = clone;
352.42645 +@@ -1599,14 +1734,17 @@ static Cursor display_load_invisible_cursor(struct display *display)
352.42646 + 
352.42647 + static Cursor display_get_visible_cursor(struct display *display)
352.42648 + {
352.42649 +-	if (display->cursor_serial != display->cursor_image.size) {
352.42650 +-		DBG(CURSOR, ("%s updating cursor\n", DisplayString(display->dpy)));
352.42651 ++	struct display *first = display->ctx->display;
352.42652 ++
352.42653 ++	if (display->cursor_serial != first->cursor_serial) {
352.42654 ++		DBG(CURSOR, ("%s updating cursor %dx%d, serial %d\n",
352.42655 ++		    DisplayString(display->dpy), first->cursor_image.width, first->cursor_image.height, first->cursor_serial));
352.42656 + 
352.42657 + 		if (display->visible_cursor)
352.42658 + 			XFreeCursor(display->dpy, display->visible_cursor);
352.42659 + 
352.42660 +-		display->visible_cursor = XcursorImageLoadCursor(display->dpy, &display->cursor_image);
352.42661 +-		display->cursor_serial = display->cursor_image.size;
352.42662 ++		display->visible_cursor = XcursorImageLoadCursor(display->dpy, &first->cursor_image);
352.42663 ++		display->cursor_serial = first->cursor_serial;
352.42664 + 	}
352.42665 + 
352.42666 + 	return display->visible_cursor;
352.42667 +@@ -1629,7 +1767,7 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
352.42668 + 	display->cursor_image.height = cur->height;
352.42669 + 	display->cursor_image.xhot = cur->xhot;
352.42670 + 	display->cursor_image.yhot = cur->yhot;
352.42671 +-	display->cursor_image.size++;
352.42672 ++	display->cursor_serial++;
352.42673 + 
352.42674 + 	n = cur->width*cur->height;
352.42675 + 	src = cur->pixels;
352.42676 +@@ -1637,11 +1775,24 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
352.42677 + 	while (n--)
352.42678 + 		*dst++ = *src++;
352.42679 + 
352.42680 +-	DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
352.42681 +-	display->cursor_moved++;
352.42682 +-	if (display->cursor != display->invisible_cursor) {
352.42683 +-		display->cursor_visible++;
352.42684 +-		context_enable_timer(display->ctx);
352.42685 ++	if (verbose & CURSOR) {
352.42686 ++		int x, y;
352.42687 ++
352.42688 ++		printf("%s cursor image %dx%d, serial %d:\n",
352.42689 ++		       DisplayString(display->dpy),
352.42690 ++		       cur->width, cur->height,
352.42691 ++		       display->cursor_serial);
352.42692 ++		dst = display->cursor_image.pixels;
352.42693 ++		for (y = 0; y < cur->height; y++) {
352.42694 ++			for (x = 0; x < cur->width; x++) {
352.42695 ++				if (x == cur->xhot && y == cur->yhot)
352.42696 ++					printf("+");
352.42697 ++				else
352.42698 ++					printf("%c", *dst ? *dst >> 24 >= 127 ? 'x' : '.' : ' ');
352.42699 ++				dst++;
352.42700 ++			}
352.42701 ++			printf("\n");
352.42702 ++		}
352.42703 + 	}
352.42704 + }
352.42705 + 
352.42706 +@@ -1685,6 +1836,8 @@ static void display_flush_cursor(struct display *display)
352.42707 + 	if (cursor == None)
352.42708 + 		cursor = display->invisible_cursor;
352.42709 + 	if (cursor != display->cursor) {
352.42710 ++		DBG(CURSOR, ("%s setting cursor shape %lx\n",
352.42711 ++		    DisplayString(display->dpy), (long)cursor));
352.42712 + 		XDefineCursor(display->dpy, display->root, cursor);
352.42713 + 		display->cursor = cursor;
352.42714 + 	}
352.42715 +@@ -1762,6 +1915,8 @@ static void get_src(struct clone *c, const XRectangle *clip)
352.42716 + 	c->image.obdata = (char *)&c->src.shm;
352.42717 + 
352.42718 + 	if (c->src.use_render) {
352.42719 ++		DBG(DRAW, ("%s-%s get_src via XRender\n",
352.42720 ++			   DisplayString(c->dst.dpy), c->dst.name));
352.42721 + 		XRenderComposite(c->src.dpy, PictOpSrc,
352.42722 + 				 c->src.win_picture, 0, c->src.pix_picture,
352.42723 + 				 clip->x, clip->y,
352.42724 +@@ -1782,16 +1937,22 @@ static void get_src(struct clone *c, const XRectangle *clip)
352.42725 + 				     &c->image, 0, 0);
352.42726 + 		}
352.42727 + 	} else if (c->src.pixmap) {
352.42728 ++		DBG(DRAW, ("%s-%s get_src XCopyArea (SHM/DRI3)\n",
352.42729 ++			   DisplayString(c->dst.dpy), c->dst.name));
352.42730 + 		XCopyArea(c->src.dpy, c->src.window, c->src.pixmap, c->src.gc,
352.42731 + 			  clip->x, clip->y,
352.42732 + 			  clip->width, clip->height,
352.42733 + 			  0, 0);
352.42734 + 		XSync(c->src.dpy, False);
352.42735 + 	} else if (c->src.use_shm) {
352.42736 ++		DBG(DRAW, ("%s-%s get_src XShmGetImage\n",
352.42737 ++			   DisplayString(c->dst.dpy), c->dst.name));
352.42738 + 		ximage_prepare(&c->image, clip->width, clip->height);
352.42739 + 		XShmGetImage(c->src.dpy, c->src.window, &c->image,
352.42740 + 			     clip->x, clip->y, AllPlanes);
352.42741 + 	} else {
352.42742 ++		DBG(DRAW, ("%s-%s get_src XGetSubImage (slow)\n",
352.42743 ++			   DisplayString(c->dst.dpy), c->dst.name));
352.42744 + 		ximage_prepare(&c->image, c->width, c->height);
352.42745 + 		XGetSubImage(c->src.dpy, c->src.window,
352.42746 + 			     clip->x, clip->y, clip->width, clip->height,
352.42747 +@@ -1838,7 +1999,7 @@ static void put_dst(struct clone *c, const XRectangle *clip)
352.42748 + 				 clip->width, clip->height);
352.42749 + 		c->dst.display->send |= c->dst.use_shm;
352.42750 + 	} else if (c->dst.pixmap) {
352.42751 +-		DBG(DRAW, ("%s-%s using SHM pixmap\n",
352.42752 ++		DBG(DRAW, ("%s-%s using SHM or DRI3 pixmap\n",
352.42753 + 		     DisplayString(c->dst.dpy), c->dst.name));
352.42754 + 		c->dst.serial = NextRequest(c->dst.dpy);
352.42755 + 		XCopyArea(c->dst.dpy, c->dst.pixmap, c->dst.window, c->dst.gc,
352.42756 +@@ -1870,6 +2031,9 @@ static int clone_paint(struct clone *c)
352.42757 + {
352.42758 + 	XRectangle clip;
352.42759 + 
352.42760 ++	if (c->width == 0 || c->height == 0)
352.42761 ++		return 0;
352.42762 ++
352.42763 + 	DBG(DRAW, ("%s-%s paint clone, damaged (%d, %d), (%d, %d) [(%d, %d), (%d,  %d)]\n",
352.42764 + 	     DisplayString(c->dst.dpy), c->dst.name,
352.42765 + 	     c->damaged.x1, c->damaged.y1,
352.42766 +@@ -1944,6 +2108,10 @@ static int clone_paint(struct clone *c)
352.42767 + 		clip.height = c->damaged.y2 - c->damaged.y1;
352.42768 + 		get_src(c, &clip);
352.42769 + 
352.42770 ++		DBG(DRAW, ("%s-%s target offset %dx%d\n",
352.42771 ++			   DisplayString(c->dst.dpy), c->dst.name,
352.42772 ++			   c->dst.x - c->src.x, c->dst.y - c->src.y));
352.42773 ++
352.42774 + 		clip.x += c->dst.x - c->src.x;
352.42775 + 		clip.y += c->dst.y - c->src.y;
352.42776 + 		put_dst(c, &clip);
352.42777 +@@ -1969,8 +2137,9 @@ static void clone_damage(struct clone *c, const XRectangle *rec)
352.42778 + 	if ((v = (int)rec->y + rec->height) > c->damaged.y2)
352.42779 + 		c->damaged.y2 = v;
352.42780 + 
352.42781 +-	DBG(DAMAGE, ("%s-%s damaged: (%d, %d), (%d, %d)\n",
352.42782 ++	DBG(DAMAGE, ("%s-%s damaged: +(%d,%d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
352.42783 + 	     DisplayString(c->dst.display->dpy), c->dst.name,
352.42784 ++	     rec->x, rec->y, rec->width, rec->height,
352.42785 + 	     c->damaged.x1, c->damaged.y1,
352.42786 + 	     c->damaged.x2, c->damaged.y2));
352.42787 + }
352.42788 +@@ -2252,6 +2421,8 @@ static int clone_init_depth(struct clone *clone)
352.42789 + 	if (ret)
352.42790 + 		return ret;
352.42791 + 
352.42792 ++	clone->depth = depth;
352.42793 ++
352.42794 + 	DBG(X11, ("%s-%s using depth %d, requires xrender for src? %d, for dst? %d\n",
352.42795 + 	     DisplayString(clone->dst.dpy), clone->dst.name,
352.42796 + 	     clone->depth,
352.42797 +@@ -2312,6 +2483,8 @@ static int add_display(struct context *ctx, Display *dpy)
352.42798 + 	display->depth = DefaultDepth(dpy, DefaultScreen(dpy));
352.42799 + 	display->visual = DefaultVisual(dpy, DefaultScreen(dpy));
352.42800 + 
352.42801 ++	XSelectInput(dpy, display->root, ExposureMask);
352.42802 ++
352.42803 + 	display->has_shm = can_use_shm(dpy, display->root,
352.42804 + 				       &display->shm_event,
352.42805 + 				       &display->shm_opcode,
352.42806 +@@ -2323,6 +2496,8 @@ static int add_display(struct context *ctx, Display *dpy)
352.42807 + 	     display->shm_opcode,
352.42808 + 	     display->has_shm_pixmap));
352.42809 + 
352.42810 ++	screensaver_save(display);
352.42811 ++
352.42812 + 	display->rr_active = XRRQueryExtension(dpy, &display->rr_event, &display->rr_error);
352.42813 + 	DBG(X11, ("%s: randr_active?=%d, event=%d, error=%d\n",
352.42814 + 	     DisplayString(dpy),
352.42815 +@@ -2592,6 +2767,11 @@ static int last_display_add_clones__randr(struct context *ctx)
352.42816 + 			return ret;
352.42817 + 		}
352.42818 + 
352.42819 ++		clone->dst.x = 0;
352.42820 ++		clone->dst.y = 0;
352.42821 ++		clone->dst.width = display->width;
352.42822 ++		clone->dst.height = display->height;
352.42823 ++
352.42824 + 		ret = clone_update_modes__randr(clone);
352.42825 + 		if (ret) {
352.42826 + 			fprintf(stderr, "Failed to clone output \"%s\" from display \"%s\"\n",
352.42827 +@@ -2668,8 +2848,8 @@ static int last_display_add_clones__xinerama(struct context *ctx)
352.42828 + 		}
352.42829 + 
352.42830 + 		/* Replace the modes on the local VIRTUAL output with the remote Screen */
352.42831 +-		clone->width = xi[n].width;
352.42832 +-		clone->height = xi[n].height;
352.42833 ++		clone->dst.width = xi[n].width;
352.42834 ++		clone->dst.height = xi[n].height;
352.42835 + 		clone->dst.x = xi[n].x_org;
352.42836 + 		clone->dst.y = xi[n].y_org;
352.42837 + 		clone->dst.rr_crtc = -1;
352.42838 +@@ -2698,64 +2878,67 @@ static int last_display_add_clones__display(struct context *ctx)
352.42839 + 	Display *dpy = display->dpy;
352.42840 + 	struct clone *clone;
352.42841 + 	Screen *scr;
352.42842 ++	int count, s;
352.42843 + 	char buf[80];
352.42844 + 	int ret;
352.42845 + 	RROutput id;
352.42846 + 
352.42847 ++	count = ScreenCount(dpy);
352.42848 ++	DBG(X11, ("%s(%s) - %d screens\n", __func__, DisplayString(dpy), count));
352.42849 ++	for (s = 0; s < count; s++) {
352.42850 ++		clone = add_clone(ctx);
352.42851 ++		if (clone == NULL)
352.42852 ++			return -ENOMEM;
352.42853 + 
352.42854 +-	DBG(X11, ("%s(%s)\n", __func__, DisplayString(dpy)));
352.42855 +-	clone = add_clone(ctx);
352.42856 +-	if (clone == NULL)
352.42857 +-		return -ENOMEM;
352.42858 ++		clone->depth = 24;
352.42859 ++		clone->next = display->clone;
352.42860 ++		display->clone = clone;
352.42861 + 
352.42862 +-	clone->depth = 24;
352.42863 +-	clone->next = display->clone;
352.42864 +-	display->clone = clone;
352.42865 ++		id = claim_virtual(ctx->display, buf, ctx->nclone);
352.42866 ++		if (id == 0) {
352.42867 ++			fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
352.42868 ++				buf, DisplayString(dpy));
352.42869 ++		}
352.42870 ++		ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
352.42871 ++		if (ret) {
352.42872 ++			fprintf(stderr, "Failed to add display \"%s\"\n",
352.42873 ++				DisplayString(ctx->display->dpy));
352.42874 ++			return ret;
352.42875 ++		}
352.42876 + 
352.42877 +-	id = claim_virtual(ctx->display, buf, ctx->nclone);
352.42878 +-	if (id == 0) {
352.42879 +-		fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
352.42880 +-			buf, DisplayString(dpy));
352.42881 +-	}
352.42882 +-	ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
352.42883 +-	if (ret) {
352.42884 +-		fprintf(stderr, "Failed to add display \"%s\"\n",
352.42885 +-			DisplayString(ctx->display->dpy));
352.42886 +-		return ret;
352.42887 +-	}
352.42888 ++		sprintf(buf, "SCREEN%d", s);
352.42889 ++		ret = clone_output_init(clone, &clone->dst, display, buf, 0);
352.42890 ++		if (ret) {
352.42891 ++			fprintf(stderr, "Failed to add display \"%s\"\n",
352.42892 ++				DisplayString(dpy));
352.42893 ++			return ret;
352.42894 ++		}
352.42895 + 
352.42896 +-	sprintf(buf, "WHOLE");
352.42897 +-	ret = clone_output_init(clone, &clone->dst, display, buf, 0);
352.42898 +-	if (ret) {
352.42899 +-		fprintf(stderr, "Failed to add display \"%s\"\n",
352.42900 +-			DisplayString(dpy));
352.42901 +-		return ret;
352.42902 +-	}
352.42903 ++		ret = clone_init_depth(clone);
352.42904 ++		if (ret) {
352.42905 ++			fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
352.42906 ++				DisplayString(dpy));
352.42907 ++			return ret;
352.42908 ++		}
352.42909 + 
352.42910 +-	ret = clone_init_depth(clone);
352.42911 +-	if (ret) {
352.42912 +-		fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
352.42913 +-			DisplayString(dpy));
352.42914 +-		return ret;
352.42915 +-	}
352.42916 ++		/* Replace the modes on the local VIRTUAL output with the remote Screen */
352.42917 ++		scr = ScreenOfDisplay(dpy, s);
352.42918 ++		clone->dst.width = scr->width;
352.42919 ++		clone->dst.height = scr->height;
352.42920 ++		clone->dst.x = 0;
352.42921 ++		clone->dst.y = 0;
352.42922 ++		clone->dst.rr_crtc = -1;
352.42923 ++		ret = clone_update_modes__fixed(clone);
352.42924 ++		if (ret) {
352.42925 ++			fprintf(stderr, "Failed to clone display \"%s\"\n",
352.42926 ++				DisplayString(dpy));
352.42927 ++			return ret;
352.42928 ++		}
352.42929 + 
352.42930 +-	/* Replace the modes on the local VIRTUAL output with the remote Screen */
352.42931 +-	scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
352.42932 +-	clone->width = scr->width;
352.42933 +-	clone->height = scr->height;
352.42934 +-	clone->dst.x = 0;
352.42935 +-	clone->dst.y = 0;
352.42936 +-	clone->dst.rr_crtc = -1;
352.42937 +-	ret = clone_update_modes__fixed(clone);
352.42938 +-	if (ret) {
352.42939 +-		fprintf(stderr, "Failed to clone display \"%s\"\n",
352.42940 +-			DisplayString(dpy));
352.42941 +-		return ret;
352.42942 ++		clone->active = ctx->active;
352.42943 ++		ctx->active = clone;
352.42944 + 	}
352.42945 + 
352.42946 +-	clone->active = ctx->active;
352.42947 +-	ctx->active = clone;
352.42948 +-
352.42949 + 	return 0;
352.42950 + }
352.42951 + 
352.42952 +@@ -3168,6 +3351,33 @@ static void context_cleanup(struct context *ctx)
352.42953 + 	XCloseDisplay(dpy);
352.42954 + }
352.42955 + 
352.42956 ++static void update_cursor_image(struct context *ctx)
352.42957 ++{
352.42958 ++	XFixesCursorImage *cur;
352.42959 ++	int i;
352.42960 ++
352.42961 ++	DBG(CURSOR, ("%s cursor changed\n",
352.42962 ++		     DisplayString(ctx->display->dpy)));
352.42963 ++
352.42964 ++	cur = XFixesGetCursorImage(ctx->display->dpy);
352.42965 ++	if (cur == NULL)
352.42966 ++		return;
352.42967 ++
352.42968 ++	display_load_visible_cursor(&ctx->display[0], cur);
352.42969 ++	for (i = 1; i < ctx->ndisplay; i++) {
352.42970 ++		struct display *display = &ctx->display[i];
352.42971 ++
352.42972 ++		DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
352.42973 ++		display->cursor_moved++;
352.42974 ++		if (display->cursor != display->invisible_cursor) {
352.42975 ++			display->cursor_visible++;
352.42976 ++			context_enable_timer(display->ctx);
352.42977 ++		}
352.42978 ++	}
352.42979 ++
352.42980 ++	XFree(cur);
352.42981 ++}
352.42982 ++
352.42983 + static int done;
352.42984 + 
352.42985 + static void signal_handler(int sig)
352.42986 +@@ -3182,6 +3392,7 @@ int main(int argc, char **argv)
352.42987 + 	uint64_t count;
352.42988 + 	int daemonize = 1, bumblebee = 0, siblings = 0, singleton = 1;
352.42989 + 	int i, ret, open, fail;
352.42990 ++	int idle;
352.42991 + 
352.42992 + 	signal(SIGPIPE, SIG_IGN);
352.42993 + 
352.42994 +@@ -3228,6 +3439,7 @@ int main(int argc, char **argv)
352.42995 + 		return -ret;
352.42996 + 
352.42997 + 	XSetErrorHandler(_check_error_handler);
352.42998 ++	XSetIOErrorHandler(_io_error_handler);
352.42999 + 
352.43000 + 	ret = add_fd(&ctx, display_open(&ctx, src_name));
352.43001 + 	if (ret) {
352.43002 +@@ -3237,6 +3449,13 @@ int main(int argc, char **argv)
352.43003 + 		goto out;
352.43004 + 	}
352.43005 + 
352.43006 ++	ret = check_virtual(ctx.display);
352.43007 ++	if (ret) {
352.43008 ++		fprintf(stderr, "No VIRTUAL outputs on \"%s\".\n",
352.43009 ++			DisplayString(ctx.display->dpy));
352.43010 ++		goto out;
352.43011 ++	}
352.43012 ++
352.43013 + 	if (singleton) {
352.43014 + 		XSelectInput(ctx.display->dpy, ctx.display->root, PropertyChangeMask);
352.43015 + 		if (first_display_has_singleton(&ctx)) {
352.43016 +@@ -3291,6 +3510,11 @@ int main(int argc, char **argv)
352.43017 + 	if (ret)
352.43018 + 		goto out;
352.43019 + 
352.43020 ++	if (ctx.display->saver_active)
352.43021 ++		XScreenSaverSelectInput(ctx.display->dpy,
352.43022 ++					ctx.display->root,
352.43023 ++					ScreenSaverNotifyMask);
352.43024 ++
352.43025 + 	if ((ctx.display->rr_event | ctx.display->rr_error) == 0) {
352.43026 + 		fprintf(stderr, "RandR extension not supported by %s\n", DisplayString(ctx.display->dpy));
352.43027 + 		ret = EINVAL;
352.43028 +@@ -3348,25 +3572,60 @@ int main(int argc, char **argv)
352.43029 + 	signal(SIGTERM, signal_handler);
352.43030 + 
352.43031 + 	ctx.command_continuation = 0;
352.43032 ++	update_cursor_image(&ctx);
352.43033 ++
352.43034 ++	idle = 0;
352.43035 + 	while (!done) {
352.43036 + 		XEvent e;
352.43037 + 		int reconfigure = 0;
352.43038 + 		int rr_update = 0;
352.43039 + 
352.43040 +-		DBG(POLL, ("polling - enable timer? %d, nfd=%d, ndisplay=%d\n", ctx.timer_active, ctx.nfd, ctx.ndisplay));
352.43041 +-		ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
352.43042 +-		if (ret <= 0)
352.43043 +-			break;
352.43044 ++		if (idle) {
352.43045 ++			DBG(POLL, ("polling - enable timer? %d, nfd=%d, ndisplay=%d\n", ctx.timer_active, ctx.nfd, ctx.ndisplay));
352.43046 ++			ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
352.43047 ++			if (ret <= 0)
352.43048 ++				break;
352.43049 ++
352.43050 ++			DBG(POLL, ("poll reports %d fd awake\n", ret));
352.43051 ++		}
352.43052 ++		idle = 1;
352.43053 + 
352.43054 + 		/* pfd[0] is the timer, pfd[1] is the local display, pfd[2] is the mouse, pfd[3+] are the remotes */
352.43055 + 
352.43056 +-		DBG(POLL, ("poll reports %d fd awake\n", ret));
352.43057 + 		if (ctx.pfd[1].revents || XPending(ctx.display[0].dpy)) {
352.43058 + 			DBG(POLL,("%s woken up\n", DisplayString(ctx.display[0].dpy)));
352.43059 ++			ctx.pfd[1].revents = 0;
352.43060 ++			idle = 0;
352.43061 ++
352.43062 + 			do {
352.43063 + 				XNextEvent(ctx.display->dpy, &e);
352.43064 + 
352.43065 +-				if (e.type == ctx.display->damage_event + XDamageNotify ) {
352.43066 ++				DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[0].dpy), e.type));
352.43067 ++
352.43068 ++				if (e.type == ctx.display->saver_event + ScreenSaverNotify) {
352.43069 ++					const XScreenSaverNotifyEvent *se = (const XScreenSaverNotifyEvent *)&e;
352.43070 ++					DBG(SCREEN,
352.43071 ++					    ("%s screen saver: state=%d, kind=%d, forced=%d\n",
352.43072 ++					     DisplayString(ctx.display->dpy),
352.43073 ++					     se->state, se->kind, se->forced));
352.43074 ++					for (i = 1; i < ctx.ndisplay; i++) {
352.43075 ++						struct display *display = &ctx.display[i];
352.43076 ++
352.43077 ++						if (!display->active)
352.43078 ++							continue;
352.43079 ++
352.43080 ++						DBG(SCREEN,
352.43081 ++						    ("%s %s screen saver\n",
352.43082 ++						     DisplayString(display->dpy),
352.43083 ++						     se->state == ScreenSaverOn ? "activating" : "resetting\n"));
352.43084 ++
352.43085 ++						if (se->state == ScreenSaverOn)
352.43086 ++							XActivateScreenSaver(display->dpy);
352.43087 ++						else
352.43088 ++							XResetScreenSaver(display->dpy);
352.43089 ++						XFlush(display->dpy);
352.43090 ++					}
352.43091 ++				} else if (e.type == ctx.display->damage_event + XDamageNotify) {
352.43092 + 					const XDamageNotifyEvent *de = (const XDamageNotifyEvent *)&e;
352.43093 + 					struct clone *clone;
352.43094 + 
352.43095 +@@ -3380,19 +3639,7 @@ int main(int argc, char **argv)
352.43096 + 					if (ctx.active)
352.43097 + 						context_enable_timer(&ctx);
352.43098 + 				} else if (e.type == ctx.display->xfixes_event + XFixesCursorNotify) {
352.43099 +-					XFixesCursorImage *cur;
352.43100 +-
352.43101 +-					DBG(CURSOR, ("%s cursor changed\n",
352.43102 +-					     DisplayString(ctx.display->dpy)));
352.43103 +-
352.43104 +-					cur = XFixesGetCursorImage(ctx.display->dpy);
352.43105 +-					if (cur == NULL)
352.43106 +-						continue;
352.43107 +-
352.43108 +-					for (i = 1; i < ctx.ndisplay; i++)
352.43109 +-						display_load_visible_cursor(&ctx.display[i], cur);
352.43110 +-
352.43111 +-					XFree(cur);
352.43112 ++					update_cursor_image(&ctx);
352.43113 + 				} else if (e.type == ctx.display->rr_event + RRScreenChangeNotify) {
352.43114 + 					DBG(XRR, ("%s screen changed (reconfigure pending? %d)\n",
352.43115 + 					     DisplayString(ctx.display->dpy), reconfigure));
352.43116 +@@ -3426,13 +3673,41 @@ int main(int argc, char **argv)
352.43117 + 			if (ctx.pfd[i+2].revents == 0 && !XPending(ctx.display[i].dpy))
352.43118 + 				continue;
352.43119 + 
352.43120 ++			ctx.pfd[i+2].revents = 0;
352.43121 ++			idle = 0;
352.43122 ++
352.43123 + 			DBG(POLL, ("%s woken up\n", DisplayString(ctx.display[i].dpy)));
352.43124 + 			do {
352.43125 + 				XNextEvent(ctx.display[i].dpy, &e);
352.43126 + 
352.43127 + 				DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[i].dpy), e.type));
352.43128 +-				if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) {
352.43129 +-					XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
352.43130 ++				if (e.type == Expose) {
352.43131 ++					const XExposeEvent *xe = (XExposeEvent *)&e;
352.43132 ++					struct clone *clone;
352.43133 ++					int damaged = 0;
352.43134 ++
352.43135 ++					DBG(DAMAGE, ("%s exposed: (%d, %d)x(%d, %d)\n",
352.43136 ++					     DisplayString(ctx.display[i].dpy),
352.43137 ++					     xe->x, xe->y, xe->width, xe->height));
352.43138 ++
352.43139 ++					for (clone = ctx.active; clone; clone = clone->active) {
352.43140 ++						XRectangle r;
352.43141 ++
352.43142 ++						if (clone->dst.display != &ctx.display[i])
352.43143 ++							continue;
352.43144 ++
352.43145 ++						r.x = clone->src.x + xe->x;
352.43146 ++						r.y = clone->src.y + xe->y;
352.43147 ++						r.width  = xe->width;
352.43148 ++						r.height = xe->height;
352.43149 ++						clone_damage(clone, &r);
352.43150 ++						damaged++;
352.43151 ++					}
352.43152 ++
352.43153 ++					if (damaged)
352.43154 ++						context_enable_timer(&ctx);
352.43155 ++				} else if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) {
352.43156 ++					const XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
352.43157 + 
352.43158 + 					DBG(XRR, ("%s received RRNotify, type %d\n", DisplayString(ctx.display[i].dpy), re->subtype));
352.43159 + 					if (re->subtype == RRNotify_OutputChange) {
352.43160 +@@ -3480,6 +3755,7 @@ int main(int argc, char **argv)
352.43161 + 
352.43162 + 			DBG(TIMER, ("%s timer still active? %d\n", DisplayString(ctx.display->dpy), ret != 0));
352.43163 + 			ctx.timer_active = ret != 0;
352.43164 ++			idle = 0;
352.43165 + 		}
352.43166 + 	}
352.43167 + 
   353.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   353.2 +++ b/xf86-video-intel/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   353.3 @@ -0,0 +1,3 @@
   353.4 +# from Alpine Linux: patch git20170325
   353.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-intel
   353.6 +git.patch
   354.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   354.2 +++ b/xf86-video-mach64/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   354.3 @@ -0,0 +1,1 @@
   354.4 +../xorg/.icon.png
   354.5 \ No newline at end of file
   355.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   355.2 +++ b/xf86-video-mach64/receipt	Thu Dec 20 17:55:43 2018 +0200
   355.3 @@ -0,0 +1,30 @@
   355.4 +# SliTaz package receipt v2.
   355.5 +
   355.6 +PACKAGE="xf86-video-mach64"
   355.7 +VERSION="6.9.6" # 2018-05-18
   355.8 +CATEGORY="x-window"
   355.9 +SHORT_DESC="Xorg driver for ATI MACH 64 cards"
  355.10 +MAINTAINER="pascal.bellard@slitaz.org"
  355.11 +LICENSE="MIT"
  355.12 +WEB_SITE="https://www.x.org/wiki/"
  355.13 +REPOLOGY="xdrv:mach64"
  355.14 +
  355.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  355.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  355.17 +TARBALL_SHA1="1fdf0c3488ab88cb46b563efee166a5d54a01932"
  355.18 +
  355.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  355.20 +DEPENDS="xorg-server"
  355.21 +
  355.22 +compile_rules() {
  355.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  355.24 +
  355.25 +	./configure $CONFIGURE_ARGS &&
  355.26 +	fix libtool &&
  355.27 +	make &&
  355.28 +	make install
  355.29 +}
  355.30 +
  355.31 +TAGS="Xorg display"
  355.32 +
  355.33 +PROVIDE="xorg-xf86-video-mach64"
   356.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   356.2 +++ b/xf86-video-neomagic/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   356.3 @@ -0,0 +1,1 @@
   356.4 +../xorg/.icon.png
   356.5 \ No newline at end of file
   357.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   357.2 +++ b/xf86-video-neomagic/receipt	Thu Dec 20 17:55:43 2018 +0200
   357.3 @@ -0,0 +1,31 @@
   357.4 +# SliTaz package receipt v2.
   357.5 +
   357.6 +PACKAGE="xf86-video-neomagic"
   357.7 +VERSION="1.2.9" # 2015-05-08
   357.8 +CATEGORY="x-window"
   357.9 +SHORT_DESC="Xorg driver for the Neomagic graphics chipsets found in many \
  357.10 +laptop computers"
  357.11 +MAINTAINER="devel@slitaz.org"
  357.12 +LICENSE="MIT"
  357.13 +WEB_SITE="https://www.x.org/wiki/neomagic/"
  357.14 +REPOLOGY="xdrv:neomagic"
  357.15 +
  357.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  357.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  357.18 +TARBALL_SHA1="63762e9144926c0071f86a5a3c2bc88c02db5a4b"
  357.19 +
  357.20 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto"
  357.21 +DEPENDS="xorg-server"
  357.22 +
  357.23 +compile_rules() {
  357.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  357.25 +
  357.26 +	./configure $CONFIGURE_ARGS &&
  357.27 +	fix libtool &&
  357.28 +	make &&
  357.29 +	make install
  357.30 +}
  357.31 +
  357.32 +TAGS="Xorg display"
  357.33 +
  357.34 +PROVIDE="xorg-xf86-video-neomagic"
   358.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   358.2 +++ b/xf86-video-nouveau/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   358.3 @@ -0,0 +1,1 @@
   358.4 +../xorg/.icon.png
   358.5 \ No newline at end of file
   359.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   359.2 +++ b/xf86-video-nouveau/receipt	Thu Dec 20 17:55:43 2018 +0200
   359.3 @@ -0,0 +1,34 @@
   359.4 +# SliTaz package receipt v2.
   359.5 +
   359.6 +PACKAGE="xf86-video-nouveau"
   359.7 +VERSION="1.0.15" # 2017-04-21
   359.8 +CATEGORY="x-window"
   359.9 +SHORT_DESC="Xorg driver for NVIDIA video cards"
  359.10 +MAINTAINER="devl547@gmail.com"
  359.11 +LICENSE="GPL"
  359.12 +WEB_SITE="https://nouveau.freedesktop.org/wiki/"
  359.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-nouveau-driver"
  359.14 +REPOLOGY="xdrv:nouveau"
  359.15 +
  359.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  359.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  359.18 +TARBALL_SHA1="ed699a59ea509550f60019eef1e092ed0ccdea08"
  359.19 +
  359.20 +BUILD_DEPENDS="util-macros xorg-server-dev libxrandr-dev libxrender-dev \
  359.21 +libxv-dev eudev-dev"
  359.22 +DEPENDS="eudev libdrm libdrm-nouveau"
  359.23 +
  359.24 +compile_rules() {
  359.25 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  359.26 +
  359.27 +	./configure $CONFIGURE_ARGS &&
  359.28 +	fix libtool &&
  359.29 +	make &&
  359.30 +	make install || return 1
  359.31 +
  359.32 +	install -Dm644 $stuff/nvidia.conf $install/etc/X11/xorg.conf.d/nvidia.conf
  359.33 +}
  359.34 +
  359.35 +TAGS="Xorg display"
  359.36 +
  359.37 +PROVIDE="xorg-xf86-video-nouveau"
   360.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   360.2 +++ b/xf86-video-nouveau/stuff/nvidia.conf	Thu Dec 20 17:55:43 2018 +0200
   360.3 @@ -0,0 +1,5 @@
   360.4 +Section "Device"
   360.5 +        Identifier "nvidia"
   360.6 +        Driver "nouveau"
   360.7 +        Option "AccelMethod" "glamor"
   360.8 +EndSection
   361.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   361.2 +++ b/xf86-video-nv/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   361.3 @@ -0,0 +1,1 @@
   361.4 +../xorg/.icon.png
   361.5 \ No newline at end of file
   362.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   362.2 +++ b/xf86-video-nv/receipt	Thu Dec 20 17:55:43 2018 +0200
   362.3 @@ -0,0 +1,30 @@
   362.4 +# SliTaz package receipt v2.
   362.5 +
   362.6 +PACKAGE="xf86-video-nv"
   362.7 +VERSION="2.1.21" # 2017-01-17
   362.8 +CATEGORY="x-window"
   362.9 +SHORT_DESC="Xorg driver for NVIDIA video cards"
  362.10 +MAINTAINER="devel@slitaz.org"
  362.11 +LICENSE="MIT"
  362.12 +WEB_SITE="https://www.x.org/wiki/"
  362.13 +REPOLOGY="xdrv:nv"
  362.14 +
  362.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  362.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  362.17 +TARBALL_SHA1="708cab4a59649fc0b9816ffda580a9b7e57236be"
  362.18 +
  362.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  362.20 +DEPENDS="xorg-server"
  362.21 +
  362.22 +compile_rules() {
  362.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  362.24 +
  362.25 +	./configure $CONFIGURE_ARGS &&
  362.26 +	fix libtool &&
  362.27 +	make &&
  362.28 +	make install
  362.29 +}
  362.30 +
  362.31 +TAGS="Xorg display"
  362.32 +
  362.33 +PROVIDE="xorg-xf86-video-nv"
   363.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   363.2 +++ b/xf86-video-omap/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   363.3 @@ -0,0 +1,1 @@
   363.4 +../xorg/.icon.png
   363.5 \ No newline at end of file
   364.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   364.2 +++ b/xf86-video-omap/receipt	Thu Dec 20 17:55:43 2018 +0200
   364.3 @@ -0,0 +1,30 @@
   364.4 +# SliTaz package receipt v2.
   364.5 +
   364.6 +PACKAGE="xf86-video-omap"
   364.7 +VERSION="0.4.5" # 2016-11-25
   364.8 +CATEGORY="x-window"
   364.9 +SHORT_DESC="Xorg driver for OMAP SoCs"
  364.10 +MAINTAINER="al.bobylev@gmail.com"
  364.11 +LICENSE="MIT"
  364.12 +WEB_SITE="https://www.x.org/wiki/"
  364.13 +REPOLOGY="xdrv:omap"
  364.14 +
  364.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  364.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  364.17 +TARBALL_SHA1="b2bc385cc778f53396d61dcfecfb3ca4a608392e"
  364.18 +
  364.19 +BUILD_DEPENDS="util-macros xorg-server-dev eudev-dev"
  364.20 +DEPENDS="xorg-server libdrm libdrm-omap"
  364.21 +
  364.22 +compile_rules() {
  364.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  364.24 +
  364.25 +	./configure $CONFIGURE_ARGS &&
  364.26 +	fix libtool &&
  364.27 +	make &&
  364.28 +	make install
  364.29 +}
  364.30 +
  364.31 +TAGS="Xorg display"
  364.32 +
  364.33 +PROVIDE="xorg-xf86-video-omap"
   365.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   365.2 +++ b/xf86-video-openchrome/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   365.3 @@ -0,0 +1,1 @@
   365.4 +../xorg/.icon.png
   365.5 \ No newline at end of file
   366.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   366.2 +++ b/xf86-video-openchrome/receipt	Thu Dec 20 17:55:43 2018 +0200
   366.3 @@ -0,0 +1,31 @@
   366.4 +# SliTaz package receipt v2.
   366.5 +
   366.6 +PACKAGE="xf86-video-openchrome"
   366.7 +VERSION="0.6.0" # 2017-03-07
   366.8 +CATEGORY="x-window"
   366.9 +SHORT_DESC="Xorg driver for VIA chipsets that have an integrated Unichrome \
  366.10 +graphics engine"
  366.11 +MAINTAINER="al.bobylev@gmail.com"
  366.12 +LICENSE="MIT"
  366.13 +WEB_SITE="https://www.x.org/wiki/"
  366.14 +REPOLOGY="xdrv:openchrome"
  366.15 +
  366.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  366.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  366.18 +TARBALL_SHA1="2077181ded4d86e9cbe6d3e9b1245339692e848d"
  366.19 +
  366.20 +BUILD_DEPENDS="xorg-server-dev libxvmc-dev eudev-dev"
  366.21 +DEPENDS="xorg-server eudev libdrm libx11 libxext libxv libxvmc"
  366.22 +
  366.23 +compile_rules() {
  366.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  366.25 +
  366.26 +	./configure $CONFIGURE_ARGS &&
  366.27 +	fix libtool &&
  366.28 +	make &&
  366.29 +	make install
  366.30 +}
  366.31 +
  366.32 +TAGS="Xorg display"
  366.33 +
  366.34 +PROVIDE="xorg-xf86-video-openchrome"
   367.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   367.2 +++ b/xf86-video-qxl/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   367.3 @@ -0,0 +1,1 @@
   367.4 +../xorg/.icon.png
   367.5 \ No newline at end of file
   368.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   368.2 +++ b/xf86-video-qxl/receipt	Thu Dec 20 17:55:43 2018 +0200
   368.3 @@ -0,0 +1,31 @@
   368.4 +# SliTaz package receipt v2.
   368.5 +
   368.6 +PACKAGE="xf86-video-qxl"
   368.7 +VERSION="0.1.5" # 2016-12-19
   368.8 +CATEGORY="x-window"
   368.9 +SHORT_DESC="Xorg driver for QXL virtual GPU"
  368.10 +MAINTAINER="al.bobylev@gmail.com"
  368.11 +LICENSE="MIT"
  368.12 +WEB_SITE="https://www.x.org/wiki/"
  368.13 +REPOLOGY="xdrv:qxl"
  368.14 +
  368.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  368.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  368.17 +TARBALL_SHA1="150bbd8bf2218e33c30ca6e88422870ae08ff1af"
  368.18 +
  368.19 +BUILD_DEPENDS="util-macros xorg-server-dev libxfont2-dev xorgproto eudev-dev \
  368.20 +spice-protocol"
  368.21 +DEPENDS="xorg-server eudev"
  368.22 +
  368.23 +compile_rules() {
  368.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  368.25 +
  368.26 +	./configure $CONFIGURE_ARGS &&
  368.27 +	fix libtool &&
  368.28 +	make &&
  368.29 +	make install
  368.30 +}
  368.31 +
  368.32 +TAGS="Xorg display"
  368.33 +
  368.34 +PROVIDE="xorg-xf86-video-qxl"
   369.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   369.2 +++ b/xf86-video-r128/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   369.3 @@ -0,0 +1,1 @@
   369.4 +../xorg/.icon.png
   369.5 \ No newline at end of file
   370.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   370.2 +++ b/xf86-video-r128/receipt	Thu Dec 20 17:55:43 2018 +0200
   370.3 @@ -0,0 +1,30 @@
   370.4 +# SliTaz package receipt v2.
   370.5 +
   370.6 +PACKAGE="xf86-video-r128"
   370.7 +VERSION="6.12.0" # 2018-10-23
   370.8 +CATEGORY="x-window"
   370.9 +SHORT_DESC="Xorg driver for ATI Rage 128 based video cards"
  370.10 +MAINTAINER="al.bobylev@gmail.com"
  370.11 +LICENSE="MIT"
  370.12 +WEB_SITE="https://www.x.org/wiki/"
  370.13 +REPOLOGY="xdrv:r128"
  370.14 +
  370.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  370.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  370.17 +TARBALL_SHA1="7cfa41d386fa43b5d30299203e4845d8afba4899"
  370.18 +
  370.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  370.20 +DEPENDS="xorg-server"
  370.21 +
  370.22 +compile_rules() {
  370.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  370.24 +
  370.25 +	./configure $CONFIGURE_ARGS &&
  370.26 +	fix libtool &&
  370.27 +	make &&
  370.28 +	make install
  370.29 +}
  370.30 +
  370.31 +TAGS="Xorg display"
  370.32 +
  370.33 +PROVIDE="xorg-xf86-video-r128"
   371.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   371.2 +++ b/xf86-video-rendition/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   371.3 @@ -0,0 +1,1 @@
   371.4 +../xorg/.icon.png
   371.5 \ No newline at end of file
   372.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   372.2 +++ b/xf86-video-rendition/receipt	Thu Dec 20 17:55:43 2018 +0200
   372.3 @@ -0,0 +1,30 @@
   372.4 +# SliTaz package receipt v2.
   372.5 +
   372.6 +PACKAGE="xf86-video-rendition"
   372.7 +VERSION="4.2.7" # 2018-05-18
   372.8 +CATEGORY="x-window"
   372.9 +SHORT_DESC="Xorg driver for Rendition/Micron based video cards"
  372.10 +MAINTAINER="al.bobylev@gmail.com"
  372.11 +LICENSE="MIT"
  372.12 +WEB_SITE="https://www.x.org/wiki/"
  372.13 +REPOLOGY="xdrv:rendition"
  372.14 +
  372.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  372.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  372.17 +TARBALL_SHA1="0330d69006c5cad96a5a5448d2bdf129d4c5c8fd"
  372.18 +
  372.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  372.20 +DEPENDS="xorg-server"
  372.21 +
  372.22 +compile_rules() {
  372.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  372.24 +
  372.25 +	./configure $CONFIGURE_ARGS &&
  372.26 +	fix libtool &&
  372.27 +	make &&
  372.28 +	make install
  372.29 +}
  372.30 +
  372.31 +TAGS="Xorg display"
  372.32 +
  372.33 +PROVIDE="xorg-xf86-video-rendition"
   373.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   373.2 +++ b/xf86-video-s3/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   373.3 @@ -0,0 +1,1 @@
   373.4 +../xorg/.icon.png
   373.5 \ No newline at end of file
   374.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   374.2 +++ b/xf86-video-s3/receipt	Thu Dec 20 17:55:43 2018 +0200
   374.3 @@ -0,0 +1,30 @@
   374.4 +# SliTaz package receipt v2.
   374.5 +
   374.6 +PACKAGE="xf86-video-s3"
   374.7 +VERSION="0.6.5" # 2012-07-17
   374.8 +CATEGORY="x-window"
   374.9 +SHORT_DESC="Xorg driver for S3 video cards"
  374.10 +MAINTAINER="al.bobylev@gmail.com"
  374.11 +LICENSE="MIT"
  374.12 +WEB_SITE="https://www.x.org/wiki/"
  374.13 +REPOLOGY="xdrv:s3"
  374.14 +
  374.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  374.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  374.17 +TARBALL_SHA1="e9d715fbcddd7bef32b0216e1b7fd976c7538be2"
  374.18 +
  374.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  374.20 +DEPENDS="xorg-server"
  374.21 +
  374.22 +compile_rules() {
  374.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  374.24 +
  374.25 +	./configure $CONFIGURE_ARGS &&
  374.26 +	fix libtool &&
  374.27 +	make &&
  374.28 +	make install
  374.29 +}
  374.30 +
  374.31 +TAGS="Xorg display"
  374.32 +
  374.33 +PROVIDE="xorg-xf86-video-s3"
   375.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   375.2 +++ b/xf86-video-s3/stuff/patches/mibstore.patch	Thu Dec 20 17:55:43 2018 +0200
   375.3 @@ -0,0 +1,18 @@
   375.4 +--- ./src/s3_driver.c.orig	2013-03-07 10:10:59.468190736 +0000
   375.5 ++++ ./src/s3_driver.c	2013-03-07 10:11:57.695325050 +0000
   375.6 +@@ -52,7 +52,6 @@
   375.7 + #include "compiler.h"
   375.8 + #include "mipointer.h"
   375.9 + #include "micmap.h"
  375.10 +-#include "mibstore.h"
  375.11 + #include "fb.h"
  375.12 + #include "inputstr.h"
  375.13 + #include "shadowfb.h"
  375.14 +@@ -822,7 +821,6 @@
  375.15 + 	fbPictureInit (pScreen, 0, 0);
  375.16 + 	S3DGAInit(pScreen);
  375.17 + 
  375.18 +-        miInitializeBackingStore(pScreen);
  375.19 +         xf86SetBackingStore(pScreen);
  375.20 + 
  375.21 + 	/* framebuffer manager setup */
   376.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   376.2 +++ b/xf86-video-s3/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   376.3 @@ -0,0 +1,3 @@
   376.4 +# From Alpine Linux:
   376.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-s3?h=master
   376.6 +mibstore.patch
   377.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   377.2 +++ b/xf86-video-s3virge/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   377.3 @@ -0,0 +1,1 @@
   377.4 +../xorg/.icon.png
   377.5 \ No newline at end of file
   378.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   378.2 +++ b/xf86-video-s3virge/receipt	Thu Dec 20 17:55:43 2018 +0200
   378.3 @@ -0,0 +1,30 @@
   378.4 +# SliTaz package receipt v2.
   378.5 +
   378.6 +PACKAGE="xf86-video-s3virge"
   378.7 +VERSION="1.10.7" # 2015-09-26
   378.8 +CATEGORY="x-window"
   378.9 +SHORT_DESC="Xorg driver for Trident S3 virge cards"
  378.10 +MAINTAINER="pascal.bellard@slitaz.org"
  378.11 +LICENSE="MIT"
  378.12 +WEB_SITE="https://www.x.org/wiki/s3virge/"
  378.13 +REPOLOGY="xdrv:s3virge"
  378.14 +
  378.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  378.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  378.17 +TARBALL_SHA1="d670f02ec4372e4a4ed299d7f29b5bd6e2fa9e83"
  378.18 +
  378.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  378.20 +DEPENDS="xorg-server"
  378.21 +
  378.22 +compile_rules() {
  378.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  378.24 +
  378.25 +	./configure $CONFIGURE_ARGS &&
  378.26 +	fix libtool &&
  378.27 +	make &&
  378.28 +	make install
  378.29 +}
  378.30 +
  378.31 +TAGS="Xorg display"
  378.32 +
  378.33 +PROVIDE="xorg-xf86-video-s3virge"
   379.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   379.2 +++ b/xf86-video-s3virge/stuff/patches/check-max-value.patch	Thu Dec 20 17:55:43 2018 +0200
   379.3 @@ -0,0 +1,24 @@
   379.4 +--- a/src/s3v_driver.c
   379.5 ++++ b/src/s3v_driver.c
   379.6 +@@ -1212,8 +1212,6 @@
   379.7 +     /* todo -  The virge limit is 2048 vertical & horizontal */
   379.8 +     /* pixels, not clock register settings. */
   379.9 + 			 	/* true for all ViRGE? */
  379.10 +-  pScrn->maxHValue = 2048;
  379.11 +-  pScrn->maxVValue = 2048;
  379.12 + 
  379.13 +     				/* Lower depths default to config file */
  379.14 +   pScrn->virtualX = pScrn->display->virtualX;
  379.15 +@@ -2566,6 +2564,12 @@
  379.16 +     if ((pScrn->bitsPerPixel + 7)/8 * mode->HDisplay > 4095)
  379.17 + 	return MODE_VIRTUAL_X;
  379.18 + 
  379.19 ++    if (mode->HTotal > 2048)
  379.20 ++        return MODE_BAD_HVALUE;
  379.21 ++
  379.22 ++    if (mode->VTotal > 2048)
  379.23 ++        return MODE_BAD_VVALUE;
  379.24 ++        
  379.25 +     return MODE_OK;
  379.26 + }
  379.27 + 
   380.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   380.2 +++ b/xf86-video-s3virge/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   380.3 @@ -0,0 +1,2 @@
   380.4 +# From Alpine Linux: https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-s3virge
   380.5 +check-max-value.patch
   381.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   381.2 +++ b/xf86-video-savage/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   381.3 @@ -0,0 +1,1 @@
   381.4 +../xorg/.icon.png
   381.5 \ No newline at end of file
   382.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   382.2 +++ b/xf86-video-savage/receipt	Thu Dec 20 17:55:43 2018 +0200
   382.3 @@ -0,0 +1,30 @@
   382.4 +# SliTaz package receipt v2.
   382.5 +
   382.6 +PACKAGE="xf86-video-savage"
   382.7 +VERSION="2.3.9" # 2017-01-17
   382.8 +CATEGORY="x-window"
   382.9 +SHORT_DESC="Xorg driver for the S3 Savage family video accelerator chips"
  382.10 +MAINTAINER="pascal.bellard@slitaz.org"
  382.11 +LICENSE="MIT"
  382.12 +WEB_SITE="https://www.x.org/wiki/savage/"
  382.13 +REPOLOGY="xdrv:savage"
  382.14 +
  382.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  382.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  382.17 +TARBALL_SHA1="5896fc5560c4b7242a5d3df2e6840f09f4995a4c"
  382.18 +
  382.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  382.20 +DEPENDS="xorg-server"
  382.21 +
  382.22 +compile_rules() {
  382.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  382.24 +
  382.25 +	./configure $CONFIGURE_ARGS &&
  382.26 +	fix libtool &&
  382.27 +	make &&
  382.28 +	make install
  382.29 +}
  382.30 +
  382.31 +TAGS="Xorg display"
  382.32 +
  382.33 +PROVIDE="xorg-xf86-video-savage"
   383.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   383.2 +++ b/xf86-video-savage/stuff/patches/0001-Add-check-for-max-HV-Value-to-ValidMode-hook.patch	Thu Dec 20 17:55:43 2018 +0200
   383.3 @@ -0,0 +1,45 @@
   383.4 +From 0ece556daa8a88771b669d8104396abd9166d2d0 Mon Sep 17 00:00:00 2001
   383.5 +From: Stefan Dirsch <sndirsch@suse.de>
   383.6 +Date: Mon, 25 Jun 2018 15:55:06 +0200
   383.7 +Subject: [PATCH] Add check for max[HV]Value to ValidMode hook
   383.8 +
   383.9 +xorg-server 1.20 removed this check, so implement this in the driver
  383.10 +itself.
  383.11 +
  383.12 +Signed-off-by: Stefan Dirsch <sndirsch@suse.de>
  383.13 +Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
  383.14 +---
  383.15 + src/savage_driver.c | 10 ++++++++--
  383.16 + 1 file changed, 8 insertions(+), 2 deletions(-)
  383.17 +
  383.18 +diff --git a/src/savage_driver.c b/src/savage_driver.c
  383.19 +index 58a294d..3cda923 100644
  383.20 +--- a/src/savage_driver.c
  383.21 ++++ b/src/savage_driver.c
  383.22 +@@ -2034,8 +2034,6 @@ static Bool SavagePreInit(ScrnInfoPtr pScrn, int flags)
  383.23 +     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n",
  383.24 + 	       mclk / 1000.0);
  383.25 + 
  383.26 +-    pScrn->maxHValue = 2048 << 3;	/* 11 bits of h_total 8-pixel units */
  383.27 +-    pScrn->maxVValue = 2048;		/* 11 bits of v_total */
  383.28 +     pScrn->virtualX = pScrn->display->virtualX;
  383.29 +     pScrn->virtualY = pScrn->display->virtualY;
  383.30 + 
  383.31 +@@ -3637,6 +3635,14 @@ static ModeStatus SavageValidMode(SCRN_ARG_TYPE arg, DisplayModePtr pMode,
  383.32 +        (pMode->VDisplay > psav->PanelY)))
  383.33 + 	    return MODE_PANEL;
  383.34 + 
  383.35 ++    /* 11 bits of h_total 8-pixel units */
  383.36 ++    if (pMode->HTotal > (2048 << 3))
  383.37 ++	return MODE_BAD_HVALUE;
  383.38 ++
  383.39 ++    /* 11 bits of v_total */
  383.40 ++    if (pMode->VTotal > 2048)
  383.41 ++	return MODE_BAD_VVALUE;
  383.42 ++
  383.43 +     if (psav->UseBIOS) {
  383.44 + 	refresh = SavageGetRefresh(pMode);
  383.45 +         return (SavageMatchBiosMode(pScrn,pMode->HDisplay,
  383.46 +-- 
  383.47 +2.18.0
  383.48 +
   384.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   384.2 +++ b/xf86-video-savage/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   384.3 @@ -0,0 +1,3 @@
   384.4 +# From Alpine Linux:
   384.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-savage
   384.6 +0001-Add-check-for-max-HV-Value-to-ValidMode-hook.patch
   385.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   385.2 +++ b/xf86-video-siliconmotion/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   385.3 @@ -0,0 +1,1 @@
   385.4 +../xorg/.icon.png
   385.5 \ No newline at end of file
   386.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   386.2 +++ b/xf86-video-siliconmotion/receipt	Thu Dec 20 17:55:43 2018 +0200
   386.3 @@ -0,0 +1,30 @@
   386.4 +# SliTaz package receipt v2.
   386.5 +
   386.6 +PACKAGE="xf86-video-siliconmotion"
   386.7 +VERSION="1.7.9" # 2017-01-17
   386.8 +CATEGORY="x-window"
   386.9 +SHORT_DESC="Xorg driver for Silicon Motion based video cards"
  386.10 +MAINTAINER="al.bobylev@gmail.com"
  386.11 +LICENSE="MIT"
  386.12 +WEB_SITE="https://www.x.org/wiki/"
  386.13 +REPOLOGY="xdrv:siliconmotion"
  386.14 +
  386.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  386.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  386.17 +TARBALL_SHA1="8b694bf2b64a1c6808708ed8cb4b013493ea5ffa"
  386.18 +
  386.19 +BUILD_DEPENDS="xorg-server-dev"
  386.20 +DEPENDS="xorg-server"
  386.21 +
  386.22 +compile_rules() {
  386.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  386.24 +
  386.25 +	./configure $CONFIGURE_ARGS &&
  386.26 +	fix libtool &&
  386.27 +	make &&
  386.28 +	make install
  386.29 +}
  386.30 +
  386.31 +TAGS="Xorg display"
  386.32 +
  386.33 +PROVIDE="xorg-xf86-video-siliconmotion"
   387.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   387.2 +++ b/xf86-video-sis/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   387.3 @@ -0,0 +1,1 @@
   387.4 +../xorg/.icon.png
   387.5 \ No newline at end of file
   388.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   388.2 +++ b/xf86-video-sis/receipt	Thu Dec 20 17:55:43 2018 +0200
   388.3 @@ -0,0 +1,31 @@
   388.4 +# SliTaz package receipt v2.
   388.5 +
   388.6 +PACKAGE="xf86-video-sis"
   388.7 +VERSION="0.10.9" # 2017-01-17
   388.8 +CATEGORY="x-window"
   388.9 +SHORT_DESC="Xorg driver for SiS (Silicon Integrated Systems) and XGI video \
  388.10 +chips"
  388.11 +MAINTAINER="pascal.bellard@slitaz.org"
  388.12 +LICENSE="MIT"
  388.13 +WEB_SITE="https://www.x.org/wiki/sis/"
  388.14 +REPOLOGY="xdrv:sis"
  388.15 +
  388.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  388.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  388.18 +TARBALL_SHA1="c0009118307b8cf110d43dbd0a174de2f90dfbcc"
  388.19 +
  388.20 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto"
  388.21 +DEPENDS="xorg-server"
  388.22 +
  388.23 +compile_rules() {
  388.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  388.25 +
  388.26 +	./configure $CONFIGURE_ARGS &&
  388.27 +	fix libtool &&
  388.28 +	make &&
  388.29 +	make install
  388.30 +}
  388.31 +
  388.32 +TAGS="Xorg display"
  388.33 +
  388.34 +PROVIDE="xorg-xf86-video-sis"
   389.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   389.2 +++ b/xf86-video-sis/stuff/patches/0001-Remove-reference-to-virtualFrom.patch	Thu Dec 20 17:55:43 2018 +0200
   389.3 @@ -0,0 +1,28 @@
   389.4 +From 4b1356a2b7fd06e9a05d134caa4033681c939737 Mon Sep 17 00:00:00 2001
   389.5 +From: Adam Jackson <ajax@redhat.com>
   389.6 +Date: Thu, 16 Feb 2017 11:21:27 -0500
   389.7 +Subject: [PATCH] Remove reference to ->virtualFrom
   389.8 +
   389.9 +The core will print this information as well anyway.
  389.10 +
  389.11 +Signed-off-by: Adam Jackson <ajax@redhat.com>
  389.12 +---
  389.13 + src/sis_driver.c | 2 +-
  389.14 + 1 file changed, 1 insertion(+), 1 deletion(-)
  389.15 +
  389.16 +diff --git a/src/sis_driver.c b/src/sis_driver.c
  389.17 +index 8f06164..513f68b 100644
  389.18 +--- a/src/sis_driver.c
  389.19 ++++ b/src/sis_driver.c
  389.20 +@@ -2738,7 +2738,7 @@ SiSPrintModes(ScrnInfoPtr pScrn)
  389.21 +     float hsync, refresh = 0.0;
  389.22 +     char *desc, *desc2, *prefix, *uprefix, *output;
  389.23 + 
  389.24 +-    xf86DrvMsg(pScrn->scrnIndex, pScrn->virtualFrom, "Virtual size is %dx%d "
  389.25 ++    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Virtual size is %dx%d "
  389.26 + 	       "(pitch %d)\n", pScrn->virtualX, pScrn->virtualY,
  389.27 + 	       pScrn->displayWidth);
  389.28 + 
  389.29 +-- 
  389.30 +2.18.0
  389.31 +
   390.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   390.2 +++ b/xf86-video-sis/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   390.3 @@ -0,0 +1,3 @@
   390.4 +# From Alpine Linux:
   390.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-sis?h=master
   390.6 +0001-Remove-reference-to-virtualFrom.patch
   391.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   391.2 +++ b/xf86-video-sisusb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   391.3 @@ -0,0 +1,1 @@
   391.4 +../xorg/.icon.png
   391.5 \ No newline at end of file
   392.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   392.2 +++ b/xf86-video-sisusb/receipt	Thu Dec 20 17:55:43 2018 +0200
   392.3 @@ -0,0 +1,31 @@
   392.4 +# SliTaz package receipt v2.
   392.5 +
   392.6 +PACKAGE="xf86-video-sisusb"
   392.7 +VERSION="0.9.7" # 2017-01-17
   392.8 +CATEGORY="x-window"
   392.9 +SHORT_DESC="Xorg driver for SiS (Silicon Integrated Systems) video chips that \
  392.10 +are connected via a Net2280-based USB dongle"
  392.11 +MAINTAINER="al.bobylev@gmail.com"
  392.12 +LICENSE="MIT"
  392.13 +WEB_SITE="https://www.x.org/wiki/"
  392.14 +REPOLOGY="xdrv:sisusb"
  392.15 +
  392.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  392.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  392.18 +TARBALL_SHA1="b747632eca72ed685a160ad16481ace5404c7828"
  392.19 +
  392.20 +BUILD_DEPENDS="util-macros xorg-server-dev"
  392.21 +DEPENDS="xorg-server"
  392.22 +
  392.23 +compile_rules() {
  392.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  392.25 +
  392.26 +	./configure $CONFIGURE_ARGS &&
  392.27 +	fix libtool &&
  392.28 +	make &&
  392.29 +	make install
  392.30 +}
  392.31 +
  392.32 +TAGS="Xorg display"
  392.33 +
  392.34 +PROVIDE="xorg-xf86-video-sisusb"
   393.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   393.2 +++ b/xf86-video-suncg14/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   393.3 @@ -0,0 +1,1 @@
   393.4 +../xorg/.icon.png
   393.5 \ No newline at end of file
   394.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   394.2 +++ b/xf86-video-suncg14/receipt	Thu Dec 20 17:55:43 2018 +0200
   394.3 @@ -0,0 +1,30 @@
   394.4 +# SliTaz package receipt v2.
   394.5 +
   394.6 +PACKAGE="xf86-video-suncg14"
   394.7 +VERSION="1.1.2" # 2013-01-22
   394.8 +CATEGORY="x-window"
   394.9 +SHORT_DESC="Xorg driver for Sun CG14 video cards"
  394.10 +MAINTAINER="al.bobylev@gmail.com"
  394.11 +LICENSE="MIT"
  394.12 +WEB_SITE="https://www.x.org/wiki/"
  394.13 +REPOLOGY="xdrv:suncg14"
  394.14 +
  394.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  394.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  394.17 +TARBALL_SHA1="8335f275f89ff0801313739f4c7f58a986198053"
  394.18 +
  394.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  394.20 +DEPENDS="xorg-server"
  394.21 +
  394.22 +compile_rules() {
  394.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  394.24 +
  394.25 +	./configure $CONFIGURE_ARGS &&
  394.26 +	fix libtool &&
  394.27 +	make &&
  394.28 +	make install
  394.29 +}
  394.30 +
  394.31 +TAGS="Xorg display"
  394.32 +
  394.33 +PROVIDE="xorg-xf86-video-suncg14"
   395.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   395.2 +++ b/xf86-video-suncg3/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   395.3 @@ -0,0 +1,1 @@
   395.4 +../xorg/.icon.png
   395.5 \ No newline at end of file
   396.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   396.2 +++ b/xf86-video-suncg3/receipt	Thu Dec 20 17:55:43 2018 +0200
   396.3 @@ -0,0 +1,30 @@
   396.4 +# SliTaz package receipt v2.
   396.5 +
   396.6 +PACKAGE="xf86-video-suncg3"
   396.7 +VERSION="1.1.2" # 2013-01-22
   396.8 +CATEGORY="x-window"
   396.9 +SHORT_DESC="Xorg driver for Sun CG3 video cards"
  396.10 +MAINTAINER="al.bobylev@gmail.com"
  396.11 +LICENSE="MIT"
  396.12 +WEB_SITE="https://www.x.org/wiki/"
  396.13 +REPOLOGY="xdrv:suncg3"
  396.14 +
  396.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  396.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  396.17 +TARBALL_SHA1="d66cf986a8c58e9b6c288400d7f50f7d209c974d"
  396.18 +
  396.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  396.20 +DEPENDS="xorg-server"
  396.21 +
  396.22 +compile_rules() {
  396.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  396.24 +
  396.25 +	./configure $CONFIGURE_ARGS &&
  396.26 +	fix libtool &&
  396.27 +	make &&
  396.28 +	make install
  396.29 +}
  396.30 +
  396.31 +TAGS="Xorg display"
  396.32 +
  396.33 +PROVIDE="xorg-xf86-video-suncg3"
   397.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   397.2 +++ b/xf86-video-suncg6/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   397.3 @@ -0,0 +1,1 @@
   397.4 +../xorg/.icon.png
   397.5 \ No newline at end of file
   398.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   398.2 +++ b/xf86-video-suncg6/receipt	Thu Dec 20 17:55:43 2018 +0200
   398.3 @@ -0,0 +1,31 @@
   398.4 +# SliTaz package receipt v2.
   398.5 +
   398.6 +PACKAGE="xf86-video-suncg6"
   398.7 +VERSION="1.1.2" # 2013-01-22
   398.8 +CATEGORY="x-window"
   398.9 +SHORT_DESC="Xorg driver for Sun GX and Turbo GX (also known as cgsix) video \
  398.10 +cards"
  398.11 +MAINTAINER="al.bobylev@gmail.com"
  398.12 +LICENSE="MIT"
  398.13 +WEB_SITE="https://www.x.org/wiki/"
  398.14 +REPOLOGY="xdrv:suncg6"
  398.15 +
  398.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  398.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  398.18 +TARBALL_SHA1="f23daaa1bffb9ebe168c6c6fc101743becf113ac"
  398.19 +
  398.20 +BUILD_DEPENDS="util-macros xorg-server-dev"
  398.21 +DEPENDS="xorg-server"
  398.22 +
  398.23 +compile_rules() {
  398.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  398.25 +
  398.26 +	./configure $CONFIGURE_ARGS &&
  398.27 +	fix libtool &&
  398.28 +	make &&
  398.29 +	make install
  398.30 +}
  398.31 +
  398.32 +TAGS="Xorg display"
  398.33 +
  398.34 +PROVIDE="xorg-xf86-video-suncg6"
   399.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   399.2 +++ b/xf86-video-sunffb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   399.3 @@ -0,0 +1,1 @@
   399.4 +../xorg/.icon.png
   399.5 \ No newline at end of file
   400.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   400.2 +++ b/xf86-video-sunffb/receipt	Thu Dec 20 17:55:43 2018 +0200
   400.3 @@ -0,0 +1,30 @@
   400.4 +# SliTaz package receipt v2.
   400.5 +
   400.6 +PACKAGE="xf86-video-sunffb"
   400.7 +VERSION="1.2.2" # 2013-01-22
   400.8 +CATEGORY="x-window"
   400.9 +SHORT_DESC="Xorg driver for Sun Creator, Creator 3D and Elite 3D video cards"
  400.10 +MAINTAINER="al.bobylev@gmail.com"
  400.11 +LICENSE="MIT"
  400.12 +WEB_SITE="https://www.x.org/wiki/"
  400.13 +REPOLOGY="xdrv:sunffb"
  400.14 +
  400.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  400.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  400.17 +TARBALL_SHA1="6391d795b6bb1fa5f38c81e0a46fbc003c9a941e"
  400.18 +
  400.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  400.20 +DEPENDS="xorg-server"
  400.21 +
  400.22 +compile_rules() {
  400.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  400.24 +
  400.25 +	./configure $CONFIGURE_ARGS &&
  400.26 +	fix libtool &&
  400.27 +	make &&
  400.28 +	make install
  400.29 +}
  400.30 +
  400.31 +TAGS="Xorg display"
  400.32 +
  400.33 +PROVIDE="xorg-xf86-video-sunffb"
   401.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   401.2 +++ b/xf86-video-sunleo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   401.3 @@ -0,0 +1,1 @@
   401.4 +../xorg/.icon.png
   401.5 \ No newline at end of file
   402.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   402.2 +++ b/xf86-video-sunleo/receipt	Thu Dec 20 17:55:43 2018 +0200
   402.3 @@ -0,0 +1,30 @@
   402.4 +# SliTaz package receipt v2.
   402.5 +
   402.6 +PACKAGE="xf86-video-sunleo"
   402.7 +VERSION="1.2.2" # 2017-01-24
   402.8 +CATEGORY="x-window"
   402.9 +SHORT_DESC="Xorg driver for Sun Leo (ZX) video cards"
  402.10 +MAINTAINER="al.bobylev@gmail.com"
  402.11 +LICENSE="MIT"
  402.12 +WEB_SITE="https://www.x.org/wiki/"
  402.13 +REPOLOGY="xdrv:sunleo"
  402.14 +
  402.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  402.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  402.17 +TARBALL_SHA1="9a24e61435b7f8ddc9f0ba69f503dfe849fd66b7"
  402.18 +
  402.19 +BUILD_DEPENDS="util-macros xorg-server-dev libxfont2-dev"
  402.20 +DEPENDS="xorg-server"
  402.21 +
  402.22 +compile_rules() {
  402.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  402.24 +
  402.25 +	./configure $CONFIGURE_ARGS &&
  402.26 +	fix libtool &&
  402.27 +	make &&
  402.28 +	make install
  402.29 +}
  402.30 +
  402.31 +TAGS="Xorg display"
  402.32 +
  402.33 +PROVIDE="xorg-xf86-video-sunleo"
   403.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   403.2 +++ b/xf86-video-suntcx/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   403.3 @@ -0,0 +1,1 @@
   403.4 +../xorg/.icon.png
   403.5 \ No newline at end of file
   404.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   404.2 +++ b/xf86-video-suntcx/receipt	Thu Dec 20 17:55:43 2018 +0200
   404.3 @@ -0,0 +1,30 @@
   404.4 +# SliTaz package receipt v2.
   404.5 +
   404.6 +PACKAGE="xf86-video-suntcx"
   404.7 +VERSION="1.1.2" # 2013-01-22
   404.8 +CATEGORY="x-window"
   404.9 +SHORT_DESC="Xorg driver for Sun TCX video cards"
  404.10 +MAINTAINER="al.bobylev@gmail.com"
  404.11 +LICENSE="MIT"
  404.12 +WEB_SITE="https://www.x.org/wiki/"
  404.13 +REPOLOGY="xdrv:suntcx"
  404.14 +
  404.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  404.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  404.17 +TARBALL_SHA1="6c86212b104647e239e24b33078406fa15fdbdba"
  404.18 +
  404.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  404.20 +DEPENDS="xorg-server"
  404.21 +
  404.22 +compile_rules() {
  404.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  404.24 +
  404.25 +	./configure $CONFIGURE_ARGS &&
  404.26 +	fix libtool &&
  404.27 +	make &&
  404.28 +	make install
  404.29 +}
  404.30 +
  404.31 +TAGS="Xorg display"
  404.32 +
  404.33 +PROVIDE="xorg-xf86-video-suntcx"
   405.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   405.2 +++ b/xf86-video-tdfx/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   405.3 @@ -0,0 +1,1 @@
   405.4 +../xorg/.icon.png
   405.5 \ No newline at end of file
   406.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   406.2 +++ b/xf86-video-tdfx/receipt	Thu Dec 20 17:55:43 2018 +0200
   406.3 @@ -0,0 +1,30 @@
   406.4 +# SliTaz package receipt v2.
   406.5 +
   406.6 +PACKAGE="xf86-video-tdfx"
   406.7 +VERSION="1.4.7" # 2017-01-17
   406.8 +CATEGORY="x-window"
   406.9 +SHORT_DESC="Xorg driver for 3Dfx video cards"
  406.10 +MAINTAINER="al.bobylev@gmail.com"
  406.11 +LICENSE="MIT"
  406.12 +WEB_SITE="https://www.x.org/wiki/"
  406.13 +REPOLOGY="xdrv:tdfx"
  406.14 +
  406.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  406.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  406.17 +TARBALL_SHA1="536e3136b85e44deab36be3bf24983453ac0422a"
  406.18 +
  406.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  406.20 +DEPENDS="xorg-server"
  406.21 +
  406.22 +compile_rules() {
  406.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  406.24 +
  406.25 +	./configure $CONFIGURE_ARGS &&
  406.26 +	fix libtool &&
  406.27 +	make &&
  406.28 +	make install
  406.29 +}
  406.30 +
  406.31 +TAGS="Xorg display"
  406.32 +
  406.33 +PROVIDE="xorg-xf86-video-tdfx"
   407.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   407.2 +++ b/xf86-video-trident/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   407.3 @@ -0,0 +1,1 @@
   407.4 +../xorg/.icon.png
   407.5 \ No newline at end of file
   408.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   408.2 +++ b/xf86-video-trident/receipt	Thu Dec 20 17:55:43 2018 +0200
   408.3 @@ -0,0 +1,30 @@
   408.4 +# SliTaz package receipt v2.
   408.5 +
   408.6 +PACKAGE="xf86-video-trident"
   408.7 +VERSION="1.3.8" # 2017-01-17
   408.8 +CATEGORY="x-window"
   408.9 +SHORT_DESC="Xorg driver for Trident video cards"
  408.10 +MAINTAINER="devel@slitaz.org"
  408.11 +LICENSE="MIT"
  408.12 +WEB_SITE="https://www.x.org/wiki/trident/"
  408.13 +REPOLOGY="xdrv:trident"
  408.14 +
  408.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  408.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  408.17 +TARBALL_SHA1="8d6aa7a52dad9029b54f41ec817bdc4ece44dec3"
  408.18 +
  408.19 +BUILD_DEPENDS="util-macros xorg-server-dev xorgproto"
  408.20 +DEPENDS="xorg-server"
  408.21 +
  408.22 +compile_rules() {
  408.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  408.24 +
  408.25 +	./configure $CONFIGURE_ARGS &&
  408.26 +	fix libtool &&
  408.27 +	make &&
  408.28 +	make install
  408.29 +}
  408.30 +
  408.31 +TAGS="Xorg display"
  408.32 +
  408.33 +PROVIDE="xorg-xf86-video-trident"
   409.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   409.2 +++ b/xf86-video-vesa/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   409.3 @@ -0,0 +1,1 @@
   409.4 +../xorg/.icon.png
   409.5 \ No newline at end of file
   410.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   410.2 +++ b/xf86-video-vesa/receipt	Thu Dec 20 17:55:43 2018 +0200
   410.3 @@ -0,0 +1,31 @@
   410.4 +# SliTaz package receipt v2.
   410.5 +
   410.6 +PACKAGE="xf86-video-vesa"
   410.7 +VERSION="2.4.0" # 2018-02-15
   410.8 +CATEGORY="x-window"
   410.9 +SHORT_DESC="Xorg driver for generic VESA video cards"
  410.10 +MAINTAINER="devel@slitaz.org"
  410.11 +LICENSE="MIT"
  410.12 +WEB_SITE="https://www.x.org/wiki/vesa/"
  410.13 +REPOLOGY="xdrv:vesa"
  410.14 +
  410.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  410.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  410.17 +TARBALL_SHA1="99b69044c34292ba062e365c07dcd024462e794b"
  410.18 +
  410.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  410.20 +DEPENDS="xorg-server"
  410.21 +# We can use xorg-server-light with evdev and vesa driver.
  410.22 +
  410.23 +compile_rules() {
  410.24 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  410.25 +
  410.26 +	./configure $CONFIGURE_ARGS &&
  410.27 +	fix libtool &&
  410.28 +	make &&
  410.29 +	make install
  410.30 +}
  410.31 +
  410.32 +TAGS="Xorg display"
  410.33 +
  410.34 +PROVIDE="xorg-xf86-video-vesa"
   411.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   411.2 +++ b/xf86-video-vmware/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   411.3 @@ -0,0 +1,1 @@
   411.4 +../xorg/.icon.png
   411.5 \ No newline at end of file
   412.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   412.2 +++ b/xf86-video-vmware/receipt	Thu Dec 20 17:55:43 2018 +0200
   412.3 @@ -0,0 +1,32 @@
   412.4 +# SliTaz package receipt v2.
   412.5 +
   412.6 +PACKAGE="xf86-video-vmware"
   412.7 +VERSION="13.3.0" # 2018-05-17
   412.8 +CATEGORY="x-window"
   412.9 +SHORT_DESC="Xorg driver for VMware virtual video cards"
  412.10 +MAINTAINER="devel@slitaz.org"
  412.11 +LICENSE="MIT"
  412.12 +WEB_SITE="https://www.x.org/wiki/vmware/"
  412.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-vmware-driver"
  412.14 +REPOLOGY="xdrv:vmware"
  412.15 +
  412.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  412.17 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  412.18 +TARBALL_SHA1="f01335fe6bdb507e749571bfcd69163aed97312a"
  412.19 +
  412.20 +BUILD_DEPENDS="util-macros xorg-server-dev libxrandr-dev libxrender-dev \
  412.21 +libxinerama-dev libxv-dev xorgproto libgcrypt-dev expat-dev eudev-dev"
  412.22 +DEPENDS="eudev libdrm mesa-libxatracker"
  412.23 +
  412.24 +compile_rules() {
  412.25 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  412.26 +
  412.27 +	./configure $CONFIGURE_ARGS &&
  412.28 +	fix libtool &&
  412.29 +	make &&
  412.30 +	make install
  412.31 +}
  412.32 +
  412.33 +TAGS="Xorg display"
  412.34 +
  412.35 +PROVIDE="xorg-xf86-video-vmware"
   413.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   413.2 +++ b/xf86-video-xgixp/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   413.3 @@ -0,0 +1,1 @@
   413.4 +../xorg/.icon.png
   413.5 \ No newline at end of file
   414.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   414.2 +++ b/xf86-video-xgixp/receipt	Thu Dec 20 17:55:43 2018 +0200
   414.3 @@ -0,0 +1,30 @@
   414.4 +# SliTaz package receipt v2.
   414.5 +
   414.6 +PACKAGE="xf86-video-xgixp"
   414.7 +VERSION="1.8.1" # 2012-07-17
   414.8 +CATEGORY="x-window"
   414.9 +SHORT_DESC="Xorg driver for XGIXP video cards"
  414.10 +MAINTAINER="al.bobylev@gmail.com"
  414.11 +LICENSE="MIT"
  414.12 +WEB_SITE="https://www.x.org/wiki/"
  414.13 +REPOLOGY="xdrv:xgixp"
  414.14 +
  414.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  414.16 +WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  414.17 +TARBALL_SHA1="71698a0ee292bc69bd748db60bc422aacadcca86"
  414.18 +
  414.19 +BUILD_DEPENDS="util-macros xorg-server-dev"
  414.20 +DEPENDS="xorg-server"
  414.21 +
  414.22 +compile_rules() {
  414.23 +	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  414.24 +
  414.25 +	./configure $CONFIGURE_ARGS &&
  414.26 +	fix libtool &&
  414.27 +	make &&
  414.28 +	make install
  414.29 +}
  414.30 +
  414.31 +TAGS="Xorg display"
  414.32 +
  414.33 +PROVIDE="xorg-xf86-video-xgixp"
   415.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   415.2 +++ b/xf86-video-xgixp/stuff/patches/git-fixes.patch	Thu Dec 20 17:55:43 2018 +0200
   415.3 @@ -0,0 +1,362 @@
   415.4 +From a84753dd495bcfd724406cae470e17d0c561d0c3 Mon Sep 17 00:00:00 2001
   415.5 +From: Adam Jackson <ajax@redhat.com>
   415.6 +Date: Tue, 25 Sep 2012 12:55:05 +0000
   415.7 +Subject: Remove mibstore.h
   415.8 +
   415.9 +Signed-off-by: Adam Jackson <ajax@redhat.com>
  415.10 +---
  415.11 +diff --git a/src/xgi_driver.c b/src/xgi_driver.c
  415.12 +index 580a03a..8ce071b 100644
  415.13 +--- a/src/xgi_driver.c
  415.14 ++++ b/src/xgi_driver.c
  415.15 +@@ -53,8 +53,6 @@
  415.16 + 
  415.17 + /* initialise a SW cursor */
  415.18 + #include "mipointer.h"
  415.19 +-/* implementing backing store */
  415.20 +-#include "mibstore.h"
  415.21 + 
  415.22 + /* colormap initialization */
  415.23 + #include "micmap.h"
  415.24 +@@ -2041,10 +2039,6 @@ pScrn->pScreen = pScreen;
  415.25 +         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FB Manager init failed \n");
  415.26 +     }
  415.27 + 
  415.28 +-    /* If backing store is to be supported (as is usually the case), initialise it. */
  415.29 +-    miInitializeBackingStore(pScreen);
  415.30 +-    XGIDebug(DBG_FUNCTION, "[DBG] Jong 06142006-After miInitializeBackingStore()\n");
  415.31 +-
  415.32 +     xf86SetBackingStore(pScreen);
  415.33 +     XGIDebug(DBG_FUNCTION, "[DBG] Jong 06142006-After xf86SetBackingStore()\n");
  415.34 + 
  415.35 +--
  415.36 +cgit v0.9.0.2-2-gbebe
  415.37 +From e881cbb7cc4aa2d3a4477fd3e0681dc35075457a Mon Sep 17 00:00:00 2001
  415.38 +From: Egbert Eich <eich@freedesktop.org>
  415.39 +Date: Fri, 19 Jul 2013 12:10:57 +0200
  415.40 +Subject: Remove symbol lists as they are not used any more
  415.41 +
  415.42 +Remove symbol lists once used by the old Metrolink module
  415.43 +loader to ensure that all symbols used by the driver are
  415.44 +present.
  415.45 +This module loader has been dropped ages ago, the function
  415.46 +calls into this module loader to perform this verification
  415.47 +has been dropped from this driver howver the symbol lists
  415.48 +have survived - not referenced from anywhere any more.
  415.49 +
  415.50 +Reviewed-by:  <wharms@bfs.de>
  415.51 +Signed-off-by: Egbert Eich <eich@freedesktop.org>
  415.52 +
  415.53 +diff --git a/src/xgi_driver.c b/src/xgi_driver.c
  415.54 +index 8ce071b..c98fcf7 100644
  415.55 +--- a/src/xgi_driver.c
  415.56 ++++ b/src/xgi_driver.c
  415.57 +@@ -149,149 +149,6 @@ static void xg47_setup_fb_wrap(ReadMemoryProcPtr *read_ptr,
  415.58 +     WriteMemoryProcPtr *write_ptr, DrawablePtr pDraw);
  415.59 + static void xg47_finish_fb_wrap(DrawablePtr pDraw);
  415.60 + 
  415.61 +-
  415.62 +-static const char *vgahwSymbols[] = {
  415.63 +-    "vgaHWBlankScreen",
  415.64 +-    "vgaHWddc1SetSpeedWeak",
  415.65 +-    "vgaHWFreeHWRec",
  415.66 +-    "vgaHWGetHWRec",
  415.67 +-    "vgaHWGetIOBase",
  415.68 +-    "vgaHWGetIndex",
  415.69 +-    "vgaHWInit",
  415.70 +-    "vgaHWLock",
  415.71 +-    "vgaHWMapMem",
  415.72 +-    "vgaHWProtect",
  415.73 +-    "vgaHWRestore",
  415.74 +-    "vgaHWSave",
  415.75 +-    "vgaHWSaveScreen",
  415.76 +-    "vgaHWSetMmioFuncs",
  415.77 +-    "vgaHWUnlock",
  415.78 +-    NULL
  415.79 +-};
  415.80 +-
  415.81 +-static const char *ddcSymbols[] = {
  415.82 +-    "xf86DoEDID_DDC1",
  415.83 +-    "xf86DoEDID_DDC2",
  415.84 +-    "xf86PrintEDID",
  415.85 +-    "xf86SetDDCproperties",
  415.86 +-    NULL
  415.87 +-};
  415.88 +-
  415.89 +-static const char *i2cSymbols[] = {
  415.90 +-    "xf86CreateI2CBusRec",
  415.91 +-    "xf86I2CBusInit",
  415.92 +-    NULL
  415.93 +-};
  415.94 +-
  415.95 +-static const char *fbSymbols[] = {
  415.96 +-#if X_BYTE_ORDER == X_BIG_ENDIAN
  415.97 +-    "wfbPictureInit",
  415.98 +-    "wfbScreenInit",
  415.99 +-#else
 415.100 +-    "fbPictureInit",
 415.101 +-    "fbScreenInit",
 415.102 +-#endif
 415.103 +-    NULL
 415.104 +-};
 415.105 +-
 415.106 +-static const char *xaaSymbols[] = {
 415.107 +-    "XAACreateInfoRec",
 415.108 +-    "XAAestroyInfoRec",
 415.109 +-    "XAAFillSolidRects",
 415.110 +-    "XAAGetCopyROP",
 415.111 +-    "XAAGetPatternROP", 
 415.112 +-    "XAAInit",
 415.113 +-    "XAAScreenIndex",
 415.114 +-    "XAAStippleScanlineFuncLSBFirst",
 415.115 +-    "XAAOverlayFBfuncs",
 415.116 +-    "XAACachePlanarMonoStipple",
 415.117 +-    "XAAHelpPatternROP",
 415.118 +-    NULL
 415.119 +-};
 415.120 +-
 415.121 +-static const char *ramdacSymbols[] = {
 415.122 +-    "xf86CreateCursorInfoRec",
 415.123 +-    "xf86DestroyCursorInfoRec",
 415.124 +-    "xf86InitCursor",
 415.125 +-    NULL
 415.126 +-};
 415.127 +-
 415.128 +-static const char *drmSymbols[] = {
 415.129 +-    "drmGetInterruptFromBusID",
 415.130 +-    "drmCtlInstHandler",
 415.131 +-    "drmCtlUninstHandler",
 415.132 +-    "drmCommandNone",
 415.133 +-    "drmCommandRead",
 415.134 +-    "drmCommandWrite",
 415.135 +-    "drmCommandWriteRead",
 415.136 +-    "drmFreeVersion",
 415.137 +-    "drmGetLibVersion",
 415.138 +-    "drmGetVersion",
 415.139 +-    "drmMap",
 415.140 +-    "drmUnmap",
 415.141 +-    NULL
 415.142 +-};
 415.143 +-
 415.144 +-static const char *driSymbols[] = {
 415.145 +-    "DRICloseScreen",
 415.146 +-    "DRICreateInfoRec",
 415.147 +-    "DRIDestroyInfoRec",
 415.148 +-    "DRIFinishScreenInit",
 415.149 +-    "DRIGetContext",
 415.150 +-    "DRIGetDeviceInfo",
 415.151 +-    "DRIGetSAREAPrivate",
 415.152 +-    "DRILock",
 415.153 +-    "DRIQueryVersion",
 415.154 +-    "DRIScreenInit",
 415.155 +-    "DRIUnlock",
 415.156 +-    "DRICreatePCIBusID",
 415.157 +-    NULL
 415.158 +-};
 415.159 +-
 415.160 +-static const char *vbeSymbols[] = {
 415.161 +-    "VBEInit",
 415.162 +-    "VBEDPMSSet",
 415.163 +-    "vbeDoEDID",
 415.164 +-    "vbeFree",
 415.165 +-    NULL
 415.166 +-};
 415.167 +-
 415.168 +-static const char *int10Symbols[] = {
 415.169 +-    "xf86ExecX86int10",
 415.170 +-    "xf86FreeInt10",
 415.171 +-    "xf86InitInt10",
 415.172 +-    NULL
 415.173 +-};
 415.174 +-
 415.175 +-static const char *shadowSymbols[] = {
 415.176 +-    "shadowInit",
 415.177 +-    NULL
 415.178 +-};
 415.179 +-
 415.180 +-static const char *fbdevHWSymbols[] = {
 415.181 +-    "fbdevHWInit",
 415.182 +-    "fbdevHWUseBuildinMode",
 415.183 +-    "fbdevHWGetLineLength",
 415.184 +-    "fbdevHWGetVidmem",
 415.185 +-    "fbdevHWDPMSSet",
 415.186 +-    /* colormap */
 415.187 +-    "fbdevHWLoadPaletteWeak",
 415.188 +-    /* ScrnInfo hooks */
 415.189 +-    "fbdevHWAdjustFrameWeak",
 415.190 +-    "fbdevHWEnterVT",
 415.191 +-    "fbdevHWLeaveVT",
 415.192 +-    "fbdevHWModeInit",
 415.193 +-    "fbdevHWRestore",
 415.194 +-    "fbdevHWSave",
 415.195 +-    "fbdevHWSwitchModeWeak",
 415.196 +-    "fbdevHWValidModeWeak",
 415.197 +-    "fbdevHWMapMMIO",
 415.198 +-    "fbdevHWMapVidmem",
 415.199 +-    "fbdevHWUnmapMMIO",
 415.200 +-    "fbdevHWUnmapVidmem",
 415.201 +-    NULL
 415.202 +-};
 415.203 +-
 415.204 + #ifdef XSERVER_LIBPCIACCESS
 415.205 + #define XGI_DEVICE_MATCH(d, i) \
 415.206 +     { 0x18ca, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
 415.207 +-- 
 415.208 +cgit v0.10.2
 415.209 +
 415.210 +From e5789dfd027424996711f366e036a933d1b98c3f Mon Sep 17 00:00:00 2001
 415.211 +From: Adam Jackson <ajax@redhat.com>
 415.212 +Date: Tue, 29 Jul 2014 09:37:18 -0400
 415.213 +Subject: shadow: shadowInit -> shadowAdd/Remove
 415.214 +
 415.215 +Signed-off-by: Adam Jackson <ajax@redhat.com>
 415.216 +
 415.217 +diff --git a/src/xgi.h b/src/xgi.h
 415.218 +index 8cbe77d..e122f1c 100644
 415.219 +--- a/src/xgi.h
 415.220 ++++ b/src/xgi.h
 415.221 +@@ -534,6 +534,7 @@ typedef struct {
 415.222 +     RefreshAreaFuncPtr  RefreshArea;
 415.223 +     CloseScreenProcPtr  CloseScreen;
 415.224 +     ScreenBlockHandlerProcPtr   BlockHandler;
 415.225 ++    CreateScreenResourcesProcPtr CreateScreenResources;
 415.226 +     xf86PointerMovedProc        *PointerMoved;
 415.227 + 
 415.228 +     struct xgi_regs           savedReg;
 415.229 +diff --git a/src/xgi_driver.c b/src/xgi_driver.c
 415.230 +index c98fcf7..637e360 100644
 415.231 +--- a/src/xgi_driver.c
 415.232 ++++ b/src/xgi_driver.c
 415.233 +@@ -1702,6 +1702,25 @@ Bool XGIFBManagerInit(ScreenPtr pScreen)
 415.234 +     return ret;
 415.235 + }
 415.236 + 
 415.237 ++static Bool
 415.238 ++XGICreateScreenResources(ScreenPtr pScreen)
 415.239 ++{
 415.240 ++    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 415.241 ++    XGIPtr pXGI = XGIPTR(pScrn);
 415.242 ++    Bool ret;
 415.243 ++
 415.244 ++    pScreen->CreateScreenResources = pXGI->CreateScreenResources;
 415.245 ++    ret = pScreen->CreateScreenResources(pScreen);
 415.246 ++    pXGI->CreateScreenResources = pScreen->CreateScreenResources;
 415.247 ++    pScreen->CreateScreenResources = XGICreateScreenResources;
 415.248 ++
 415.249 ++    if (ret)
 415.250 ++	ret = shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen),
 415.251 ++			XGIShadowUpdate, NULL, 0, 0);
 415.252 ++
 415.253 ++    return ret;
 415.254 ++}
 415.255 ++
 415.256 + /* Called at the start of each server generation. */
 415.257 + Bool XGIScreenInit(SCREEN_INIT_ARGS_DECL)
 415.258 + {
 415.259 +@@ -2011,7 +2030,10 @@ pScrn->pScreen = pScreen;
 415.260 +         {
 415.261 +             pXGI->RefreshArea = XGIRefreshArea;
 415.262 +         }
 415.263 +-        shadowInit(pScreen, XGIShadowUpdate, 0);
 415.264 ++        if (!shadowSetup(pScreen))
 415.265 ++	    return FALSE;
 415.266 ++	pXGI->CreateScreenResources = pScreen->CreateScreenResources;
 415.267 ++	pScreen->CreateScreenResources = XGICreateScreenResources;
 415.268 +     }
 415.269 +     XGIDebug(DBG_FUNCTION, "[DBG] Jong 06142006-After pXGI->isShadowFB\n");
 415.270 + 
 415.271 +@@ -2272,8 +2294,10 @@ static Bool XGICloseScreen(CLOSE_SCREEN_ARGS_DECL)
 415.272 + 
 415.273 +     if (pXGI->pShadow)
 415.274 +     {
 415.275 ++	shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
 415.276 +         free(pXGI->pShadow);
 415.277 +         pXGI->pShadow = NULL;
 415.278 ++	pScreen->CreateScreenResources = pXGI->CreateScreenResources;
 415.279 +     }
 415.280 + 
 415.281 +     if (pXGI->pDgaModes)
 415.282 +-- 
 415.283 +cgit v0.10.2
 415.284 +
 415.285 +From cb0ebfa54639619c11ea8277ab7573a5db7484f9 Mon Sep 17 00:00:00 2001
 415.286 +From: Adam Jackson <ajax@redhat.com>
 415.287 +Date: Tue, 29 Jul 2014 09:37:44 -0400
 415.288 +Subject: Stop using deprecated xf86PciInfo.h
 415.289 +
 415.290 +Signed-off-by: Adam Jackson <ajax@redhat.com>
 415.291 +
 415.292 +diff --git a/src/xgi_driver.c b/src/xgi_driver.c
 415.293 +index 637e360..b440e85 100644
 415.294 +--- a/src/xgi_driver.c
 415.295 ++++ b/src/xgi_driver.c
 415.296 +@@ -43,9 +43,6 @@
 415.297 + #include <xf86RandR12.h>
 415.298 + #include "vbe.h"
 415.299 + 
 415.300 +-/* PCI vendor/device definitions */
 415.301 +-#include "xf86PciInfo.h"
 415.302 +-
 415.303 + /* fbdevhw & vgahw */
 415.304 + #include "fbdevhw.h"
 415.305 + #include "vgaHW.h"
 415.306 +-- 
 415.307 +cgit v0.10.2
 415.308 +
 415.309 +From e36331f3f2641900efe8363fe3dc15877a72c027 Mon Sep 17 00:00:00 2001
 415.310 +From: Adam Jackson <ajax@redhat.com>
 415.311 +Date: Wed, 8 Oct 2014 10:34:45 +0200
 415.312 +Subject: Update for new damage API
 415.313 +
 415.314 +Signed-off-by: Adam Jackson <ajax@redhat.com>
 415.315 +
 415.316 +diff --git a/src/xgi_shadow.c b/src/xgi_shadow.c
 415.317 +index 80f3645..c146ce4 100644
 415.318 +--- a/src/xgi_shadow.c
 415.319 ++++ b/src/xgi_shadow.c
 415.320 +@@ -86,7 +86,7 @@ void XGIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
 415.321 + 
 415.322 + void XGIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
 415.323 + {
 415.324 +-    RegionPtr       pRegion = &pBuf->damage;
 415.325 ++    RegionPtr       pRegion = DamageRegion(pBuf->pDamage);
 415.326 +     ScrnInfoPtr     pScrn;
 415.327 +     pScrn = xf86ScreenToScrn(pScreen);
 415.328 + 
 415.329 +-- 
 415.330 +cgit v0.10.2
 415.331 +
 415.332 +From 81c1cc40820a3e24efc0565b68f44eb6748a2db9 Mon Sep 17 00:00:00 2001
 415.333 +From: Adam Jackson <ajax@redhat.com>
 415.334 +Date: Tue, 19 Jul 2016 10:03:56 -0400
 415.335 +Subject: Adapt Block/WakeupHandler signature for ABI 23
 415.336 +
 415.337 +Signed-off-by: Adam Jackson <ajax@redhat.com>
 415.338 +
 415.339 +diff --git a/src/compat-api.h b/src/compat-api.h
 415.340 +index 98ba435..44daea4 100644
 415.341 +--- a/src/compat-api.h
 415.342 ++++ b/src/compat-api.h
 415.343 +@@ -78,11 +78,19 @@
 415.344 + 
 415.345 + #define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv
 415.346 + 
 415.347 ++#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0)
 415.348 ++#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout
 415.349 ++#define BLOCKHANDLER_ARGS arg, pTimeout
 415.350 ++
 415.351 ++#define WAKEUPHANDLER_ARGS_DECL ScreenPtr arg, unsigned long result
 415.352 ++#define WAKEUPHANDLER_ARGS arg, result
 415.353 ++#else
 415.354 + #define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask
 415.355 + #define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask
 415.356 + 
 415.357 + #define WAKEUPHANDLER_ARGS_DECL ScreenPtr arg, unsigned long result, pointer read_mask
 415.358 + #define WAKEUPHANDLER_ARGS arg, result, read_mask
 415.359 ++#endif
 415.360 + 
 415.361 + #define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen
 415.362 + #define CLOSE_SCREEN_ARGS pScreen
 415.363 +-- 
 415.364 +cgit v0.10.2
 415.365 +
   416.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   416.2 +++ b/xf86-video-xgixp/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   416.3 @@ -0,0 +1,3 @@
   416.4 +# From Alpine Linux:
   416.5 +# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-xgixp?h=master
   416.6 +git-fixes.patch
   417.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   417.2 +++ b/xfd/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   417.3 @@ -0,0 +1,1 @@
   417.4 +../xorg/.icon.png
   417.5 \ No newline at end of file
   418.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   418.2 +++ b/xfd/receipt	Thu Dec 20 17:55:43 2018 +0200
   418.3 @@ -0,0 +1,27 @@
   418.4 +# SliTaz package receipt v2.
   418.5 +
   418.6 +PACKAGE="xfd"
   418.7 +VERSION="1.1.2"
   418.8 +CATEGORY="x-window"
   418.9 +SHORT_DESC="Display all the characters in an X font"
  418.10 +MAINTAINER="al.bobylev@gmail.com"
  418.11 +LICENSE="MIT"
  418.12 +WEB_SITE="https://www.x.org/wiki/"
  418.13 +
  418.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  418.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  418.16 +TARBALL_SHA1="cac5ca0f5fb6044840b15cf6fb9c541bd4fbce4a"
  418.17 +
  418.18 +BUILD_DEPENDS="util-macros libxaw-dev fontconfig-dev libxft-dev libxrender-dev \
  418.19 +libxmu-dev xorgproto gettext-dev"
  418.20 +DEPENDS="fontconfig freetype libx11 libxaw libxft libxmu libxrender libxt"
  418.21 +
  418.22 +compile_rules() {
  418.23 +	./configure $CONFIGURE_ARGS &&
  418.24 +	make &&
  418.25 +	make install
  418.26 +}
  418.27 +
  418.28 +TAGS="Xorg"
  418.29 +
  418.30 +PROVIDE="xorg-xfd"
   419.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   419.2 +++ b/xfontsel/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   419.3 @@ -0,0 +1,1 @@
   419.4 +../xorg/.icon.png
   419.5 \ No newline at end of file
   420.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   420.2 +++ b/xfontsel/receipt	Thu Dec 20 17:55:43 2018 +0200
   420.3 @@ -0,0 +1,28 @@
   420.4 +# SliTaz package receipt v2.
   420.5 +
   420.6 +PACKAGE="xfontsel"
   420.7 +VERSION="1.0.6"
   420.8 +CATEGORY="x-window"
   420.9 +SHORT_DESC="Point and click selection of X11 font names"
  420.10 +MAINTAINER="devel@slitaz.org"
  420.11 +LICENSE="MIT"
  420.12 +WEB_SITE="https://www.x.org/wiki/"
  420.13 +
  420.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  420.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  420.16 +TARBALL_SHA1="3fd8d78cc270030b41298170c3e5222065dd1cfd"
  420.17 +
  420.18 +BUILD_DEPENDS="util-macros libxaw-dev"
  420.19 +DEPENDS="libx11 libxaw libxmu libxt"
  420.20 +
  420.21 +CONFIG_FILES="/etc/X11/app-defaults/XFontSel"
  420.22 +
  420.23 +compile_rules() {
  420.24 +	./configure $CONFIGURE_ARGS &&
  420.25 +	make &&
  420.26 +	make install
  420.27 +}
  420.28 +
  420.29 +TAGS="Xorg"
  420.30 +
  420.31 +PROVIDE="xorg-xfontsel"
   421.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   421.2 +++ b/xfs/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   421.3 @@ -0,0 +1,1 @@
   421.4 +../xorg/.icon.png
   421.5 \ No newline at end of file
   422.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   422.2 +++ b/xfs/receipt	Thu Dec 20 17:55:43 2018 +0200
   422.3 @@ -0,0 +1,30 @@
   422.4 +# SliTaz package receipt v2.
   422.5 +
   422.6 +PACKAGE="xfs"
   422.7 +VERSION="1.2.0"
   422.8 +CATEGORY="x-window"
   422.9 +SHORT_DESC="X Font Server"
  422.10 +MAINTAINER="al.bobylev@gmail.com"
  422.11 +LICENSE="MIT"
  422.12 +WEB_SITE="https://www.x.org/wiki/"
  422.13 +
  422.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  422.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  422.16 +TARBALL_SHA1="00848fcc2915ed8b00e75ac311c4727327324f57"
  422.17 +
  422.18 +BUILD_DEPENDS="util-macros font-util-dev xorgproto libxfont2-dev xtrans"
  422.19 +DEPENDS="libxfont2"
  422.20 +
  422.21 +CONFIG_FILES="/etc/X11/fs/config"
  422.22 +
  422.23 +compile_rules() {
  422.24 +	touch /root/missing /missing
  422.25 +
  422.26 +	./configure $CONFIGURE_ARGS &&
  422.27 +	make &&
  422.28 +	make install
  422.29 +}
  422.30 +
  422.31 +TAGS="Xorg"
  422.32 +
  422.33 +PROVIDE="xorg-xfs"
   423.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   423.2 +++ b/xfsinfo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   423.3 @@ -0,0 +1,1 @@
   423.4 +../xorg/.icon.png
   423.5 \ No newline at end of file
   424.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   424.2 +++ b/xfsinfo/receipt	Thu Dec 20 17:55:43 2018 +0200
   424.3 @@ -0,0 +1,28 @@
   424.4 +# SliTaz package receipt v2.
   424.5 +
   424.6 +PACKAGE="xfsinfo"
   424.7 +VERSION="1.0.5"
   424.8 +CATEGORY="x-window"
   424.9 +SHORT_DESC="X font server information utility"
  424.10 +MAINTAINER="al.bobylev@gmail.com"
  424.11 +LICENSE="MIT"
  424.12 +WEB_SITE="https://www.x.org/wiki/"
  424.13 +
  424.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  424.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  424.16 +TARBALL_SHA1="7513e16ba5c8fef31aeaff4a42bf131859e75ee0"
  424.17 +
  424.18 +BUILD_DEPENDS="util-macros xorgproto libfs-dev"
  424.19 +DEPENDS="libfs"
  424.20 +
  424.21 +compile_rules() {
  424.22 +	touch /root/missing
  424.23 +
  424.24 +	./configure $CONFIGURE_ARGS &&
  424.25 +	make &&
  424.26 +	make install
  424.27 +}
  424.28 +
  424.29 +TAGS="Xorg"
  424.30 +
  424.31 +PROVIDE="xorg-xfsinfo"
   425.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   425.2 +++ b/xgamma/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   425.3 @@ -0,0 +1,1 @@
   425.4 +../xorg/.icon.png
   425.5 \ No newline at end of file
   426.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   426.2 +++ b/xgamma/receipt	Thu Dec 20 17:55:43 2018 +0200
   426.3 @@ -0,0 +1,27 @@
   426.4 +# SliTaz package receipt v2.
   426.5 +
   426.6 +PACKAGE="xgamma"
   426.7 +VERSION="1.0.6"
   426.8 +CATEGORY="x-window"
   426.9 +SHORT_DESC="Alter a monitor's gamma correction through the X server"
  426.10 +MAINTAINER="al.bobylev@gmail.com"
  426.11 +LICENSE="MIT"
  426.12 +WEB_SITE="https://www.x.org/wiki/"
  426.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  426.14 +
  426.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  426.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  426.17 +TARBALL_SHA1="af1484d0d70bc71dc9d3b7b95645881b7165c41b"
  426.18 +
  426.19 +BUILD_DEPENDS="util-macros libx11-dev libxxf86vm-dev xorgproto"
  426.20 +DEPENDS="libx11 libxxf86vm"
  426.21 +
  426.22 +compile_rules() {
  426.23 +	./configure $CONFIGURE_ARGS &&
  426.24 +	make &&
  426.25 +	make install
  426.26 +}
  426.27 +
  426.28 +TAGS="Xorg"
  426.29 +
  426.30 +PROVIDE="xorg-xgamma"
   427.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   427.2 +++ b/xhost/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   427.3 @@ -0,0 +1,1 @@
   427.4 +../xorg/.icon.png
   427.5 \ No newline at end of file
   428.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   428.2 +++ b/xhost/receipt	Thu Dec 20 17:55:43 2018 +0200
   428.3 @@ -0,0 +1,27 @@
   428.4 +# SliTaz package receipt v2.
   428.5 +
   428.6 +PACKAGE="xhost"
   428.7 +VERSION="1.0.7"
   428.8 +CATEGORY="x-window"
   428.9 +SHORT_DESC="Server access control program for X"
  428.10 +MAINTAINER="pascal.bellard@slitaz.org"
  428.11 +LICENSE="MIT"
  428.12 +WEB_SITE="https://www.x.org/wiki/"
  428.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  428.14 +
  428.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  428.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  428.17 +TARBALL_SHA1="8abfb0554e14a074f0dbfdda4919880e088545cb"
  428.18 +
  428.19 +BUILD_DEPENDS="util-macros xorgproto libx11-dev libxmu-dev"
  428.20 +DEPENDS="libx11 libxmu"
  428.21 +
  428.22 +compile_rules() {
  428.23 +	./configure $CONFIGURE_ARGS &&
  428.24 +	make &&
  428.25 +	make install
  428.26 +}
  428.27 +
  428.28 +TAGS="Xorg"
  428.29 +
  428.30 +PROVIDE="xorg-xhost"
   429.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   429.2 +++ b/xinit/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   429.3 @@ -0,0 +1,1 @@
   429.4 +../xorg/.icon.png
   429.5 \ No newline at end of file
   430.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   430.2 +++ b/xinit/receipt	Thu Dec 20 17:55:43 2018 +0200
   430.3 @@ -0,0 +1,33 @@
   430.4 +# SliTaz package receipt v2.
   430.5 +
   430.6 +PACKAGE="xinit"
   430.7 +VERSION="1.4.0"
   430.8 +CATEGORY="x-window"
   430.9 +SHORT_DESC="X Window System initializer (includes startx)"
  430.10 +MAINTAINER="devel@slitaz.org"
  430.11 +LICENSE="MIT"
  430.12 +WEB_SITE="https://www.x.org/wiki/"
  430.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xinit.html"
  430.14 +
  430.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  430.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  430.17 +TARBALL_SHA1="fcdca692b09a45f546016fff78718d1cf7e7852f"
  430.18 +
  430.19 +BUILD_DEPENDS="util-macros libxmu-dev"
  430.20 +DEPENDS="libx11   openssl xorg-xauth"
  430.21 +
  430.22 +compile_rules() {
  430.23 +	sed -i '/$serverargs $vtarg/ s/serverargs/: #&/' startx.cpp
  430.24 +
  430.25 +	./configure \
  430.26 +		--with-xinitdir=/etc/X11/app-defaults \
  430.27 +		$CONFIGURE_ARGS &&
  430.28 +	make &&
  430.29 +	make install || return 1
  430.30 +
  430.31 +	install -Dm644 $stuff/xserverrc $install/etc/X11/app-defaults/xserverrc
  430.32 +}
  430.33 +
  430.34 +TAGS="Xorg"
  430.35 +
  430.36 +PROVIDE="xorg-xinit"
   431.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   431.2 +++ b/xinit/stuff/patches/06_move_serverauthfile_into_tmp.diff	Thu Dec 20 17:55:43 2018 +0200
   431.3 @@ -0,0 +1,20 @@
   431.4 +Move startx auth files in /tmp so they are removed on reboot.
   431.5 +http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=357736
   431.6 +The trap patch didn't seem to work on reboot.
   431.7 +---
   431.8 + startx.cpp |    2 +-
   431.9 + 1 file changed, 1 insertion(+), 1 deletion(-)
  431.10 +
  431.11 +Index: xinit/startx.cpp
  431.12 +===================================================================
  431.13 +--- xinit.orig/startx.cpp
  431.14 ++++ xinit/startx.cpp
  431.15 +@@ -273,7 +273,7 @@
  431.16 +     dummy=0
  431.17 + 
  431.18 +     XCOMM create a file with auth information for the server. ':0' is a dummy.
  431.19 +-    xserverauthfile=$HOME/.serverauth.$$
  431.20 ++    xserverauthfile=`mktemp -p /tmp serverauth.XXXXXXXXXX`
  431.21 +     trap "rm -f '$xserverauthfile'" HUP INT QUIT ILL TRAP KILL BUS TERM
  431.22 +     xauth -q -f "$xserverauthfile" << EOF
  431.23 + add :$dummy . $mcookie
   432.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   432.2 +++ b/xinit/stuff/patches/series	Thu Dec 20 17:55:43 2018 +0200
   432.3 @@ -0,0 +1,1 @@
   432.4 +06_move_serverauthfile_into_tmp.diff
   433.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   433.2 +++ b/xinit/stuff/xserverrc	Thu Dec 20 17:55:43 2018 +0200
   433.3 @@ -0,0 +1,1 @@
   433.4 +exec /usr/bin/X -nolisten tcp +bs
   434.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   434.2 +++ b/xinput/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   434.3 @@ -0,0 +1,1 @@
   434.4 +../xorg/.icon.png
   434.5 \ No newline at end of file
   435.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   435.2 +++ b/xinput/receipt	Thu Dec 20 17:55:43 2018 +0200
   435.3 @@ -0,0 +1,28 @@
   435.4 +# SliTaz package receipt v2.
   435.5 +
   435.6 +PACKAGE="xinput"
   435.7 +VERSION="1.6.2"
   435.8 +CATEGORY="x-window"
   435.9 +SHORT_DESC="Utility to configure and test X input devices"
  435.10 +MAINTAINER="devel@slitaz.org"
  435.11 +LICENSE="MIT"
  435.12 +WEB_SITE="https://www.x.org/wiki/"
  435.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  435.14 +
  435.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  435.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  435.17 +TARBALL_SHA1="68367ae6cb4753eeb5fd209afe033d7c4a817748"
  435.18 +
  435.19 +BUILD_DEPENDS="util-macros libx11-dev libxext-dev libxi-dev xorgproto \
  435.20 +libxrandr-dev libxinerama-dev"
  435.21 +DEPENDS="libx11 libxi libxinerama libxrandr"
  435.22 +
  435.23 +compile_rules() {
  435.24 +	./configure $CONFIGURE_ARGS &&
  435.25 +	make &&
  435.26 +	make install
  435.27 +}
  435.28 +
  435.29 +TAGS="Xorg"
  435.30 +
  435.31 +PROVIDE="xorg-xinput"
   436.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   436.2 +++ b/xkbcomp/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   436.3 @@ -0,0 +1,1 @@
   436.4 +../xorg/.icon.png
   436.5 \ No newline at end of file
   437.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   437.2 +++ b/xkbcomp/receipt	Thu Dec 20 17:55:43 2018 +0200
   437.3 @@ -0,0 +1,31 @@
   437.4 +# SliTaz package receipt v2.
   437.5 +
   437.6 +PACKAGE="xkbcomp"
   437.7 +VERSION="1.4.2"
   437.8 +CATEGORY="x-window"
   437.9 +SHORT_DESC="Compile XKB keyboard description"
  437.10 +MAINTAINER="devel@slitaz.org"
  437.11 +LICENSE="MIT"
  437.12 +WEB_SITE="https://www.x.org/wiki/"
  437.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  437.14 +
  437.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  437.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  437.17 +TARBALL_SHA1="9a39cf7a562c152465e04fc7cf1002c59f883870"
  437.18 +
  437.19 +BUILD_DEPENDS="util-macros libx11-dev libxkbfile-dev xorgproto"
  437.20 +SPLIT="$PACKAGE-dev"
  437.21 +
  437.22 +DEPENDS_std="libx11 libxkbfile"
  437.23 +DEPENDS_dev="$PACKAGE libx11-dev libxkbfile-dev xorgproto"
  437.24 +
  437.25 +compile_rules() {
  437.26 +	./configure $CONFIGURE_ARGS &&
  437.27 +	make &&
  437.28 +	make install
  437.29 +}
  437.30 +
  437.31 +TAGS="Xorg"
  437.32 +
  437.33 +PROVIDE_std="xorg-xkbcomp"
  437.34 +PROVIDE_dev="xorg-xkbcomp-dev"
   438.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   438.2 +++ b/xkbevd/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   438.3 @@ -0,0 +1,1 @@
   438.4 +../xorg/.icon.png
   438.5 \ No newline at end of file
   439.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   439.2 +++ b/xkbevd/receipt	Thu Dec 20 17:55:43 2018 +0200
   439.3 @@ -0,0 +1,27 @@
   439.4 +# SliTaz package receipt v2.
   439.5 +
   439.6 +PACKAGE="xkbevd"
   439.7 +VERSION="1.1.4"
   439.8 +CATEGORY="x-window"
   439.9 +SHORT_DESC="XKB event daemon"
  439.10 +MAINTAINER="al.bobylev@gmail.com"
  439.11 +LICENSE="MIT"
  439.12 +WEB_SITE="https://www.x.org/wiki/"
  439.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  439.14 +
  439.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  439.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  439.17 +TARBALL_SHA1="629fea940692f9d971dfae36cd697b13337caaba"
  439.18 +
  439.19 +BUILD_DEPENDS="util-macros libxkbfile-dev libx11-dev"
  439.20 +DEPENDS="libx11 libxkbfile"
  439.21 +
  439.22 +compile_rules() {
  439.23 +	./configure $CONFIGURE_ARGS &&
  439.24 +	make &&
  439.25 +	make install
  439.26 +}
  439.27 +
  439.28 +TAGS="Xorg"
  439.29 +
  439.30 +PROVIDE="xorg-xkbevd"
   440.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   440.2 +++ b/xkbprint/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   440.3 @@ -0,0 +1,1 @@
   440.4 +../xorg/.icon.png
   440.5 \ No newline at end of file
   441.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   441.2 +++ b/xkbprint/receipt	Thu Dec 20 17:55:43 2018 +0200
   441.3 @@ -0,0 +1,26 @@
   441.4 +# SliTaz package receipt v2.
   441.5 +
   441.6 +PACKAGE="xkbprint"
   441.7 +VERSION="1.0.4"
   441.8 +CATEGORY="x-window"
   441.9 +SHORT_DESC="Print an XKB keyboard description"
  441.10 +MAINTAINER="al.bobylev@gmail.com"
  441.11 +LICENSE="MIT"
  441.12 +WEB_SITE="https://www.x.org/wiki/"
  441.13 +
  441.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  441.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  441.16 +TARBALL_SHA1="c0c1e71a32f7d8bfc40539e7f315ca7e02d99205"
  441.17 +
  441.18 +BUILD_DEPENDS="util-macros libxkbfile-dev libx11-dev xorgproto"
  441.19 +DEPENDS="libx11 libxkbfile"
  441.20 +
  441.21 +compile_rules() {
  441.22 +	./configure $CONFIGURE_ARGS &&
  441.23 +	make &&
  441.24 +	make install
  441.25 +}
  441.26 +
  441.27 +TAGS="Xorg"
  441.28 +
  441.29 +PROVIDE="xorg-xkbprint"
   442.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   442.2 +++ b/xkbutils/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   442.3 @@ -0,0 +1,1 @@
   442.4 +../xorg/.icon.png
   442.5 \ No newline at end of file
   443.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   443.2 +++ b/xkbutils/receipt	Thu Dec 20 17:55:43 2018 +0200
   443.3 @@ -0,0 +1,27 @@
   443.4 +# SliTaz package receipt v2.
   443.5 +
   443.6 +PACKAGE="xkbutils"
   443.7 +VERSION="1.0.4"
   443.8 +CATEGORY="x-window"
   443.9 +SHORT_DESC="Xorg keyboard utilities"
  443.10 +MAINTAINER="devel@slitaz.org"
  443.11 +LICENSE="MIT"
  443.12 +WEB_SITE="https://www.x.org/wiki/"
  443.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  443.14 +
  443.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  443.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  443.17 +TARBALL_SHA1="b09aef7cc3853eb12dbda332f55adec3add4447b"
  443.18 +
  443.19 +BUILD_DEPENDS="util-macros libxaw-dev libxt-dev libx11-dev xorgproto"
  443.20 +DEPENDS="libx11 libxaw libxt"
  443.21 +
  443.22 +compile_rules() {
  443.23 +	./configure $CONFIGURE_ARGS &&
  443.24 +	make &&
  443.25 +	make install
  443.26 +}
  443.27 +
  443.28 +TAGS="Xorg"
  443.29 +
  443.30 +PROVIDE="xorg-xkbutils"
   444.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   444.2 +++ b/xkeyboard-config/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   444.3 @@ -0,0 +1,1 @@
   444.4 +../xorg/.icon.png
   444.5 \ No newline at end of file
   445.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   445.2 +++ b/xkeyboard-config/receipt	Thu Dec 20 17:55:43 2018 +0200
   445.3 @@ -0,0 +1,31 @@
   445.4 +# SliTaz package receipt v2.
   445.5 +
   445.6 +PACKAGE="xkeyboard-config"
   445.7 +VERSION="2.25"
   445.8 +CATEGORY="x-window"
   445.9 +SHORT_DESC="Keyboard configuration database for the X Window System"
  445.10 +MAINTAINER="devel@slitaz.org"
  445.11 +LICENSE="MIT"
  445.12 +WEB_SITE="https://www.x.org/wiki/"
  445.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xkeyboard-config.html"
  445.14 +HOST_ARCH="any"
  445.15 +
  445.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  445.17 +WGET_URL="$XORG_MIRROR/data/$PACKAGE/$TARBALL"
  445.18 +TARBALL_SHA1="1a444ceca4a4f29718771cef74c7f009b8f18f57"
  445.19 +
  445.20 +BUILD_DEPENDS="libxslt xorgproto libx11-dev intltool"
  445.21 +SPLIT="$PACKAGE-dev"
  445.22 +
  445.23 +compile_rules() {
  445.24 +	./configure \
  445.25 +		--with-xkb-base=/usr/share/X11/xkb \
  445.26 +		--with-xkb-rules-symlink=xorg \
  445.27 +		$CONFIGURE_ARGS &&
  445.28 +	make &&
  445.29 +	make install
  445.30 +}
  445.31 +
  445.32 +TAGS="Xorg"
  445.33 +
  445.34 +PROVIDE="xorg-xkeyboard-config"
   446.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   446.2 +++ b/xkill/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   446.3 @@ -0,0 +1,1 @@
   446.4 +../xorg/.icon.png
   446.5 \ No newline at end of file
   447.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   447.2 +++ b/xkill/receipt	Thu Dec 20 17:55:43 2018 +0200
   447.3 @@ -0,0 +1,27 @@
   447.4 +# SliTaz package receipt v2.
   447.5 +
   447.6 +PACKAGE="xkill"
   447.7 +VERSION="1.0.5"
   447.8 +CATEGORY="x-window"
   447.9 +SHORT_DESC="Kill a client by its X resource"
  447.10 +MAINTAINER="devel@slitaz.org"
  447.11 +LICENSE="MIT"
  447.12 +WEB_SITE="https://www.x.org/wiki/"
  447.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  447.14 +
  447.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  447.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  447.17 +TARBALL_SHA1="c5ee06b33adb252a41e4f737be6bd47651ff582a"
  447.18 +
  447.19 +BUILD_DEPENDS="util-macros libx11-dev libxmu-dev xorgproto"
  447.20 +DEPENDS="libx11 libxmu"
  447.21 +
  447.22 +compile_rules() {
  447.23 +	./configure $CONFIGURE_ARGS &&
  447.24 +	make &&
  447.25 +	make install
  447.26 +}
  447.27 +
  447.28 +TAGS="Xorg"
  447.29 +
  447.30 +PROVIDE="xorg-xkill"
   448.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   448.2 +++ b/xload/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   448.3 @@ -0,0 +1,1 @@
   448.4 +../xorg/.icon.png
   448.5 \ No newline at end of file
   449.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   449.2 +++ b/xload/receipt	Thu Dec 20 17:55:43 2018 +0200
   449.3 @@ -0,0 +1,30 @@
   449.4 +# SliTaz package receipt v2.
   449.5 +
   449.6 +PACKAGE="xload"
   449.7 +VERSION="1.1.3"
   449.8 +CATEGORY="x-window"
   449.9 +SHORT_DESC="System load average display for X"
  449.10 +MAINTAINER="devel@slitaz.org"
  449.11 +LICENSE="MIT"
  449.12 +WEB_SITE="https://www.x.org/wiki/"
  449.13 +
  449.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  449.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  449.16 +TARBALL_SHA1="fd5053d38551883309863c2a43de2ceffa908a50"
  449.17 +
  449.18 +BUILD_DEPENDS="util-macros libxaw-dev gettext-dev"
  449.19 +DEPENDS="libx11 libxaw libxmu libxt"
  449.20 +
  449.21 +CONFIG_FILES="/etc/X11/app-defaults/XLoad"
  449.22 +
  449.23 +compile_rules() {
  449.24 +	touch /root/missing /missing
  449.25 +
  449.26 +	./configure $CONFIGURE_ARGS &&
  449.27 +	make &&
  449.28 +	make install
  449.29 +}
  449.30 +
  449.31 +TAGS="Xorg"
  449.32 +
  449.33 +PROVIDE="xorg-xload"
   450.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   450.2 +++ b/xload/stuff/xorg-xload.desktop	Thu Dec 20 17:55:43 2018 +0200
   450.3 @@ -0,0 +1,7 @@
   450.4 +[Desktop Entry]
   450.5 +Type=Application
   450.6 +Name=Xload Monitor
   450.7 +Name[fr]=Moniteur Xload
   450.8 +Exec=xload -nolabel -bg black -fg lightblue -hl orange
   450.9 +Icon=applications-other
  450.10 +Categories=System;
   451.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   451.2 +++ b/xlsatoms/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   451.3 @@ -0,0 +1,1 @@
   451.4 +../xorg/.icon.png
   451.5 \ No newline at end of file
   452.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   452.2 +++ b/xlsatoms/receipt	Thu Dec 20 17:55:43 2018 +0200
   452.3 @@ -0,0 +1,27 @@
   452.4 +# SliTaz package receipt v2.
   452.5 +
   452.6 +PACKAGE="xlsatoms"
   452.7 +VERSION="1.1.2"
   452.8 +CATEGORY="x-window"
   452.9 +SHORT_DESC="List interned atoms defined on server"
  452.10 +MAINTAINER="al.bobylev@gmail.com"
  452.11 +LICENSE="MIT"
  452.12 +WEB_SITE="https://www.x.org/wiki/"
  452.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  452.14 +
  452.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  452.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  452.17 +TARBALL_SHA1="0946410a2cd02b0dee7809fd75be090fb3961e9c"
  452.18 +
  452.19 +BUILD_DEPENDS="util-macros libxcb-dev"
  452.20 +DEPENDS="libxcb"
  452.21 +
  452.22 +compile_rules() {
  452.23 +	./configure $CONFIGURE_ARGS &&
  452.24 +	make &&
  452.25 +	make install
  452.26 +}
  452.27 +
  452.28 +TAGS="Xorg"
  452.29 +
  452.30 +PROVIDE="xorg-xlsatoms"
   453.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   453.2 +++ b/xlsclients/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   453.3 @@ -0,0 +1,1 @@
   453.4 +../xorg/.icon.png
   453.5 \ No newline at end of file
   454.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   454.2 +++ b/xlsclients/receipt	Thu Dec 20 17:55:43 2018 +0200
   454.3 @@ -0,0 +1,29 @@
   454.4 +# SliTaz package receipt v2.
   454.5 +
   454.6 +PACKAGE="xlsclients"
   454.7 +VERSION="1.1.4"
   454.8 +CATEGORY="x-window"
   454.9 +SHORT_DESC="List client applications running on a display"
  454.10 +MAINTAINER="al.bobylev@gmail.com"
  454.11 +LICENSE="MIT"
  454.12 +WEB_SITE="https://www.x.org/wiki/"
  454.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  454.14 +
  454.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  454.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  454.17 +TARBALL_SHA1="175af1c216a1db3de5023ecd6cce186e7693c6e4"
  454.18 +
  454.19 +BUILD_DEPENDS="util-macros libxcb-dev"
  454.20 +DEPENDS="libxcb"
  454.21 +
  454.22 +compile_rules() {
  454.23 +	touch /root/missing /missing
  454.24 +
  454.25 +	./configure $CONFIGURE_ARGS &&
  454.26 +	make &&
  454.27 +	make install
  454.28 +}
  454.29 +
  454.30 +TAGS="Xorg"
  454.31 +
  454.32 +PROVIDE="xorg-xlsclients"
   455.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   455.2 +++ b/xlsfonts/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   455.3 @@ -0,0 +1,1 @@
   455.4 +../xorg/.icon.png
   455.5 \ No newline at end of file
   456.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   456.2 +++ b/xlsfonts/receipt	Thu Dec 20 17:55:43 2018 +0200
   456.3 @@ -0,0 +1,26 @@
   456.4 +# SliTaz package receipt v2.
   456.5 +
   456.6 +PACKAGE="xlsfonts"
   456.7 +VERSION="1.0.6"
   456.8 +CATEGORY="x-window"
   456.9 +SHORT_DESC="List X fonts available on X server"
  456.10 +MAINTAINER="al.bobylev@gmail.com"
  456.11 +LICENSE="MIT"
  456.12 +WEB_SITE="https://www.x.org/wiki/"
  456.13 +
  456.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  456.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  456.16 +TARBALL_SHA1="bf95e46e0897dcb9d197ce20d4fa024b8ace5148"
  456.17 +
  456.18 +BUILD_DEPENDS="util-macros libx11-dev xorgproto"
  456.19 +DEPENDS="libx11"
  456.20 +
  456.21 +compile_rules() {
  456.22 +	./configure $CONFIGURE_ARGS &&
  456.23 +	make &&
  456.24 +	make install
  456.25 +}
  456.26 +
  456.27 +TAGS="Xorg"
  456.28 +
  456.29 +PROVIDE="xorg-xlsfonts"
   457.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   457.2 +++ b/xmag/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   457.3 @@ -0,0 +1,1 @@
   457.4 +../xorg/.icon.png
   457.5 \ No newline at end of file
   458.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   458.2 +++ b/xmag/receipt	Thu Dec 20 17:55:43 2018 +0200
   458.3 @@ -0,0 +1,28 @@
   458.4 +# SliTaz package receipt v2.
   458.5 +
   458.6 +PACKAGE="xmag"
   458.7 +VERSION="1.0.6"
   458.8 +CATEGORY="x-window"
   458.9 +SHORT_DESC="Magnify parts of the screen"
  458.10 +MAINTAINER="al.bobylev@gmail.com"
  458.11 +LICENSE="MIT"
  458.12 +WEB_SITE="https://www.x.org/wiki/"
  458.13 +
  458.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  458.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  458.16 +TARBALL_SHA1="77c4b23765a1a30afde46a6e57afd77f20d58185"
  458.17 +
  458.18 +BUILD_DEPENDS="util-macros libxaw-dev libxmu-dev libxt-dev libx11-dev"
  458.19 +DEPENDS="libx11 libxaw libxmu libxt"
  458.20 +
  458.21 +CONFIG_FILES="/etc/X11/app-defaults/Xmag"
  458.22 +
  458.23 +compile_rules() {
  458.24 +	./configure $CONFIGURE_ARGS &&
  458.25 +	make &&
  458.26 +	make install
  458.27 +}
  458.28 +
  458.29 +TAGS="Xorg"
  458.30 +
  458.31 +PROVIDE="xorg-xmag"
   459.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   459.2 +++ b/xmessage/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   459.3 @@ -0,0 +1,1 @@
   459.4 +../xorg/.icon.png
   459.5 \ No newline at end of file
   460.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   460.2 +++ b/xmessage/receipt	Thu Dec 20 17:55:43 2018 +0200
   460.3 @@ -0,0 +1,30 @@
   460.4 +# SliTaz package receipt v2.
   460.5 +
   460.6 +PACKAGE="xmessage"
   460.7 +VERSION="1.0.5"
   460.8 +CATEGORY="x-window"
   460.9 +SHORT_DESC="Display a message or query in a window"
  460.10 +MAINTAINER="devel@slitaz.org"
  460.11 +LICENSE="MIT"
  460.12 +WEB_SITE="https://www.x.org/wiki/"
  460.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  460.14 +
  460.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  460.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  460.17 +TARBALL_SHA1="d3eca72c7173d0d9547c676a16bcec51ca1213a2"
  460.18 +
  460.19 +BUILD_DEPENDS="util-macros libxaw-dev"
  460.20 +DEPENDS="libx11 libxaw libxt"
  460.21 +
  460.22 +CONFIG_FILES="/etc/X11/app-defaults/Xmessage \
  460.23 +/etc/X11/app-defaults/Xmessage-color"
  460.24 +
  460.25 +compile_rules() {
  460.26 +	./configure $CONFIGURE_ARGS &&
  460.27 +	make &&
  460.28 +	make install
  460.29 +}
  460.30 +
  460.31 +TAGS="Xorg"
  460.32 +
  460.33 +PROVIDE="xorg-xmessage"
   461.1 --- a/xmlto/receipt	Thu Dec 13 00:46:54 2018 +0200
   461.2 +++ b/xmlto/receipt	Thu Dec 20 17:55:43 2018 +0200
   461.3 @@ -11,21 +11,21 @@
   461.4  
   461.5  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   461.6  WGET_URL="https://releases.pagure.org/xmlto/$TARBALL"
   461.7 +TARBALL_SHA1="aa63af9a86ab6ed0c92ea8b177dc808c18902c73"
   461.8  
   461.9  BUILD_DEPENDS="docbook-xsl util-linux-getopt flex"
  461.10 +DEPENDS="libxslt perl-yaml-syck perl-test-pod bash docbook-xsl"
  461.11 +# links: for text backend post-processing; fop: for PDF backend post-processing
  461.12 +SUGGESTED="links-cli fop"
  461.13  
  461.14  compile_rules() {
  461.15 +	LINKS="/usr/bin/links" \
  461.16  	./configure $CONFIGURE_ARGS &&
  461.17  	make &&
  461.18  	make DESTDIR=$install install
  461.19  
  461.20 -	for file in $install/usr/share/xmlto/format/*/*; do
  461.21 -		sed -i "s|http://docbook.sourceforge.net/release/xsl/current/|\
  461.22 -/usr/share/xml/docbook/stylesheet/docbook-xsl/|" "$file"
  461.23 -	done
  461.24 +#	for file in $install/usr/share/xmlto/format/*/*; do
  461.25 +#		sed -i "s|http://docbook.sourceforge.net/release/xsl/current/|\
  461.26 +#/usr/share/xml/docbook/stylesheet/docbook-xsl/|" "$file"
  461.27 +#	done
  461.28  }
  461.29 -
  461.30 -genpkg_rules() {
  461.31 -	copy @std
  461.32 -	DEPENDS="libxslt perl-yaml-syck perl-test-pod bash"
  461.33 -}
   462.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   462.2 +++ b/xmodmap/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   462.3 @@ -0,0 +1,1 @@
   462.4 +../xorg/.icon.png
   462.5 \ No newline at end of file
   463.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   463.2 +++ b/xmodmap/receipt	Thu Dec 20 17:55:43 2018 +0200
   463.3 @@ -0,0 +1,27 @@
   463.4 +# SliTaz package receipt v2.
   463.5 +
   463.6 +PACKAGE="xmodmap"
   463.7 +VERSION="1.0.9"
   463.8 +CATEGORY="x-window"
   463.9 +SHORT_DESC="Utility for modifying keymaps and button mappings"
  463.10 +MAINTAINER="devel@slitaz.org"
  463.11 +LICENSE="MIT"
  463.12 +WEB_SITE="https://www.x.org/wiki/"
  463.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  463.14 +
  463.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  463.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  463.17 +TARBALL_SHA1="fe735c8bbba68d7eb50f82d4e092fdcadf161314"
  463.18 +
  463.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto"
  463.20 +DEPENDS="libx11"
  463.21 +
  463.22 +compile_rules() {
  463.23 +	./configure $CONFIGURE_ARGS &&
  463.24 +	make &&
  463.25 +	make install
  463.26 +}
  463.27 +
  463.28 +TAGS="Xorg"
  463.29 +
  463.30 +PROVIDE="xorg-xmodmap"
   464.1 --- a/xorg-bdftopcf/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   464.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   464.3 @@ -1,1 +0,0 @@
   464.4 -../xorg/.icon.png
   464.5 \ No newline at end of file
   465.1 --- a/xorg-bdftopcf/receipt	Thu Dec 13 00:46:54 2018 +0200
   465.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   465.3 @@ -1,28 +0,0 @@
   465.4 -# SliTaz package receipt v2.
   465.5 -
   465.6 -PACKAGE="xorg-bdftopcf"
   465.7 -VERSION="1.1"
   465.8 -CATEGORY="x-window"
   465.9 -SHORT_DESC="Convert X font from Bitmap Distribution Format to Portable \
  465.10 -Compiled Format"
  465.11 -MAINTAINER="pascal.bellard@slitaz.org"
  465.12 -LICENSE="MIT"
  465.13 -WEB_SITE="https://www.x.org/wiki/"
  465.14 -REPOLOGY="bdftopcf"
  465.15 -
  465.16 -TARBALL="bdftopcf-$VERSION.tar.bz2"
  465.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  465.18 -
  465.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXfont-dev xorg-xtrans"
  465.20 -
  465.21 -compile_rules() {
  465.22 -	./configure $CONFIGURE_ARGS &&
  465.23 -	make &&
  465.24 -	make install
  465.25 -}
  465.26 -
  465.27 -genpkg_rules() {
  465.28 -	copy @std
  465.29 -	DEPENDS="xorg-libXfont"
  465.30 -	TAGS="utility xorg fonts"
  465.31 -}
   466.1 --- a/xorg-bitmap/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   466.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   466.3 @@ -1,1 +0,0 @@
   466.4 -../xorg/.icon.png
   466.5 \ No newline at end of file
   467.1 --- a/xorg-bitmap/receipt	Thu Dec 13 00:46:54 2018 +0200
   467.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   467.3 @@ -1,29 +0,0 @@
   467.4 -# SliTaz package receipt v2.
   467.5 -
   467.6 -PACKAGE="xorg-bitmap"
   467.7 -VERSION="1.0.8"
   467.8 -CATEGORY="x-window"
   467.9 -SHORT_DESC="XBM format bitmap editor and converter utilities"
  467.10 -MAINTAINER="al.bobylev@gmail.com"
  467.11 -LICENSE="MIT"
  467.12 -WEB_SITE="https://www.x.org/wiki/"
  467.13 -REPOLOGY="bitmap"
  467.14 -
  467.15 -TARBALL="bitmap-$VERSION.tar.bz2"
  467.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  467.17 -
  467.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXmu-dev xorg-xorgproto \
  467.19 -xorg-xbitmaps xorg-libXaw-dev"
  467.20 -
  467.21 -compile_rules() {
  467.22 -	./configure $CONFIGURE_ARGS &&
  467.23 -	make &&
  467.24 -	make install
  467.25 -}
  467.26 -
  467.27 -genpkg_rules() {
  467.28 -	copy @std @dev
  467.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  467.30 -	CONFIG_FILES="/etc/X11/app-defaults/Bitmap \
  467.31 -	/etc/X11/app-defaults/Bitmap-color /etc/X11/app-defaults/Bitmap-nocase"
  467.32 -}
   468.1 --- a/xorg-cf-files/receipt	Thu Dec 13 00:46:54 2018 +0200
   468.2 +++ b/xorg-cf-files/receipt	Thu Dec 20 17:55:43 2018 +0200
   468.3 @@ -11,6 +11,7 @@
   468.4  
   468.5  TARBALL="$PACKAGE-$VERSION.tar.bz2"
   468.6  WGET_URL="$XORG_MIRROR/util/$TARBALL"
   468.7 +TARBALL_SHA1="9b6ed71c74a83181a47eb180787e9ab9a5efdfa2"
   468.8  
   468.9  compile_rules() {
  468.10  	./configure $CONFIGURE_ARGS &&
   469.1 --- a/xorg-encodings/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   469.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   469.3 @@ -1,1 +0,0 @@
   469.4 -../xorg/.icon.png
   469.5 \ No newline at end of file
   470.1 --- a/xorg-encodings/receipt	Thu Dec 13 00:46:54 2018 +0200
   470.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   470.3 @@ -1,27 +0,0 @@
   470.4 -# SliTaz package receipt v2.
   470.5 -
   470.6 -PACKAGE="xorg-encodings"
   470.7 -VERSION="1.0.4"
   470.8 -CATEGORY="x-window"
   470.9 -SHORT_DESC="The XFree86/Xorg encoding files"
  470.10 -MAINTAINER="al.bobylev@gmail.com"
  470.11 -LICENSE="PublicDomain"
  470.12 -WEB_SITE="https://www.x.org/wiki/"
  470.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  470.14 -HOST_ARCH="any"
  470.15 -REPOLOGY="encodings"
  470.16 -
  470.17 -TARBALL="encodings-$VERSION.tar.bz2"
  470.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  470.19 -
  470.20 -BUILD_DEPENDS="xorg-util-macros xorg-mkfontscale xorg-font-util-dev"
  470.21 -
  470.22 -compile_rules() {
  470.23 -	./configure $CONFIGURE_ARGS &&
  470.24 -	make &&
  470.25 -	make install
  470.26 -}
  470.27 -
  470.28 -genpkg_rules() {
  470.29 -	copy @std
  470.30 -}
   471.1 --- a/xorg-evieext/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   471.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   471.3 @@ -1,1 +0,0 @@
   471.4 -../xorg/.icon.png
   471.5 \ No newline at end of file
   472.1 --- a/xorg-evieext/receipt	Thu Dec 13 00:46:54 2018 +0200
   472.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   472.3 @@ -1,27 +0,0 @@
   472.4 -# SliTaz package receipt v2.
   472.5 -
   472.6 -PACKAGE="xorg-evieext"
   472.7 -VERSION="1.1.1"
   472.8 -CATEGORY="development"
   472.9 -SHORT_DESC="XEvIE extension header files"
  472.10 -MAINTAINER="devel@slitaz.org"
  472.11 -LICENSE="MIT"
  472.12 -WEB_SITE="https://www.x.org/wiki/"
  472.13 -HOST_ARCH="any"
  472.14 -REPOLOGY="evieext"
  472.15 -
  472.16 -TARBALL="evieext-$VERSION.tar.bz2"
  472.17 -WGET_URL="$XORG_MIRROR/proto/$TARBALL"
  472.18 -
  472.19 -BUILD_DEPENDS="xorg-util-macros"
  472.20 -
  472.21 -compile_rules() {
  472.22 -	./configure $CONFIGURE_ARGS &&
  472.23 -	make &&
  472.24 -	make install
  472.25 -}
  472.26 -
  472.27 -genpkg_rules() {
  472.28 -	copy @dev
  472.29 -	DEPENDS="xorg-util-macros"
  472.30 -}
   473.1 --- a/xorg-font-adobe-100dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   473.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   473.3 @@ -1,1 +0,0 @@
   473.4 -../xorg/.icon.png
   473.5 \ No newline at end of file
   474.1 --- a/xorg-font-adobe-100dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   474.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   474.3 @@ -1,38 +0,0 @@
   474.4 -# SliTaz package receipt v2.
   474.5 -
   474.6 -PACKAGE="xorg-font-adobe-100dpi"
   474.7 -VERSION="1.0.3"
   474.8 -CATEGORY="x-window"
   474.9 -SHORT_DESC="Adobe bitmap fonts Courier, Helvetica, New Century Schoolbook, \
  474.10 -Symbol, Times (100 DPI)"
  474.11 -MAINTAINER="al.bobylev@gmail.com"
  474.12 -LICENSE="MIT"
  474.13 -WEB_SITE="https://www.x.org/wiki/"
  474.14 -HOST_ARCH="any"
  474.15 -REPOLOGY="fonts:adobe-100dpi"
  474.16 -
  474.17 -TARBALL="font-adobe-100dpi-$VERSION.tar.bz2"
  474.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  474.19 -
  474.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  474.21 -COOKOPTS="!gz" # too long
  474.22 -
  474.23 -compile_rules() {
  474.24 -	./configure \
  474.25 -		--disable-all-encodings \
  474.26 -		$CONFIGURE_ARGS &&
  474.27 -	make &&
  474.28 -	make install
  474.29 -}
  474.30 -
  474.31 -genpkg_rules() {
  474.32 -	copy @std
  474.33 -	TAGS="font"
  474.34 -}
  474.35 -
  474.36 -post_install() {
  474.37 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
  474.38 -}
  474.39 -post_remove() {
  474.40 -	chroot "$1/" fc-cache -r
  474.41 -}
   475.1 --- a/xorg-font-adobe-75dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   475.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   475.3 @@ -1,1 +0,0 @@
   475.4 -../xorg/.icon.png
   475.5 \ No newline at end of file
   476.1 --- a/xorg-font-adobe-75dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   476.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   476.3 @@ -1,38 +0,0 @@
   476.4 -# SliTaz package receipt v2.
   476.5 -
   476.6 -PACKAGE="xorg-font-adobe-75dpi"
   476.7 -VERSION="1.0.3"
   476.8 -CATEGORY="x-window"
   476.9 -SHORT_DESC="Adobe bitmap fonts Courier, Helvetica, New Century Schoolbook, \
  476.10 -Symbol, Times (75 DPI)"
  476.11 -MAINTAINER="al.bobylev@gmail.com"
  476.12 -LICENSE="MIT"
  476.13 -WEB_SITE="https://www.x.org/wiki/"
  476.14 -HOST_ARCH="any"
  476.15 -REPOLOGY="fonts:adobe-75dpi"
  476.16 -
  476.17 -TARBALL="font-adobe-75dpi-$VERSION.tar.bz2"
  476.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  476.19 -
  476.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  476.21 -COOKOPTS="!gz" # too long
  476.22 -
  476.23 -compile_rules() {
  476.24 -	./configure \
  476.25 -		--disable-all-encodings \
  476.26 -		$CONFIGURE_ARGS &&
  476.27 -	make &&
  476.28 -	make install
  476.29 -}
  476.30 -
  476.31 -genpkg_rules() {
  476.32 -	copy @std
  476.33 -	TAGS="font"
  476.34 -}
  476.35 -
  476.36 -post_install() {
  476.37 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi/
  476.38 -}
  476.39 -post_remove() {
  476.40 -	chroot "$1/" fc-cache -r
  476.41 -}
   477.1 --- a/xorg-font-adobe-utopia-100dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   477.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   477.3 @@ -1,1 +0,0 @@
   477.4 -../xorg/.icon.png
   477.5 \ No newline at end of file
   478.1 --- a/xorg-font-adobe-utopia-100dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   478.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   478.3 @@ -1,37 +0,0 @@
   478.4 -# SliTaz package receipt v2.
   478.5 -
   478.6 -PACKAGE="xorg-font-adobe-utopia-100dpi"
   478.7 -VERSION="1.0.4"
   478.8 -CATEGORY="x-window"
   478.9 -SHORT_DESC="Adobe bitmap font Utopia (100 DPI)"
  478.10 -MAINTAINER="al.bobylev@gmail.com"
  478.11 -LICENSE="other"
  478.12 -WEB_SITE="https://www.x.org/wiki/"
  478.13 -HOST_ARCH="any"
  478.14 -REPOLOGY="fonts:adobe-utopia-100dpi"
  478.15 -
  478.16 -TARBALL="font-adobe-utopia-100dpi-$VERSION.tar.bz2"
  478.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  478.18 -
  478.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  478.20 -COOKOPTS="!gz" # too long
  478.21 -
  478.22 -compile_rules() {
  478.23 -	./configure \
  478.24 -		--disable-all-encodings \
  478.25 -		$CONFIGURE_ARGS &&
  478.26 -	make &&
  478.27 -	make install
  478.28 -}
  478.29 -
  478.30 -genpkg_rules() {
  478.31 -	copy @std
  478.32 -	TAGS="font"
  478.33 -}
  478.34 -
  478.35 -post_install() {
  478.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
  478.37 -}
  478.38 -post_remove() {
  478.39 -	chroot "$1/" fc-cache -r
  478.40 -}
   479.1 --- a/xorg-font-adobe-utopia-75dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   479.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   479.3 @@ -1,1 +0,0 @@
   479.4 -../xorg/.icon.png
   479.5 \ No newline at end of file
   480.1 --- a/xorg-font-adobe-utopia-75dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   480.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   480.3 @@ -1,37 +0,0 @@
   480.4 -# SliTaz package receipt v2.
   480.5 -
   480.6 -PACKAGE="xorg-font-adobe-utopia-75dpi"
   480.7 -VERSION="1.0.4"
   480.8 -CATEGORY="x-window"
   480.9 -SHORT_DESC="Adobe bitmap font Utopia (75 DPI)"
  480.10 -MAINTAINER="al.bobylev@gmail.com"
  480.11 -LICENSE="other"
  480.12 -WEB_SITE="https://www.x.org/wiki/"
  480.13 -HOST_ARCH="any"
  480.14 -REPOLOGY="fonts:adobe-utopia-75dpi"
  480.15 -
  480.16 -TARBALL="font-adobe-utopia-75dpi-$VERSION.tar.bz2"
  480.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  480.18 -
  480.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  480.20 -COOKOPTS="!gz" # too long
  480.21 -
  480.22 -compile_rules() {
  480.23 -	./configure \
  480.24 -		--disable-all-encodings \
  480.25 -		$CONFIGURE_ARGS &&
  480.26 -	make &&
  480.27 -	make install
  480.28 -}
  480.29 -
  480.30 -genpkg_rules() {
  480.31 -	copy @std
  480.32 -	TAGS="font"
  480.33 -}
  480.34 -
  480.35 -post_install() {
  480.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
  480.37 -}
  480.38 -post_remove() {
  480.39 -	chroot "$1/" fc-cache -r
  480.40 -}
   481.1 --- a/xorg-font-adobe-utopia-type1/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   481.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   481.3 @@ -1,1 +0,0 @@
   481.4 -../xorg/.icon.png
   481.5 \ No newline at end of file
   482.1 --- a/xorg-font-adobe-utopia-type1/receipt	Thu Dec 13 00:46:54 2018 +0200
   482.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   482.3 @@ -1,35 +0,0 @@
   482.4 -# SliTaz package receipt v2.
   482.5 -
   482.6 -PACKAGE="xorg-font-adobe-utopia-type1"
   482.7 -VERSION="1.0.4"
   482.8 -CATEGORY="x-window"
   482.9 -SHORT_DESC="Adobe Type 1 font Utopia"
  482.10 -MAINTAINER="al.bobylev@gmail.com"
  482.11 -LICENSE="other"
  482.12 -WEB_SITE="https://www.x.org/wiki/"
  482.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  482.14 -HOST_ARCH="any"
  482.15 -REPOLOGY="fonts:adobe-utopia-type1"
  482.16 -
  482.17 -TARBALL="font-adobe-utopia-type1-$VERSION.tar.bz2"
  482.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  482.19 -
  482.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  482.21 -
  482.22 -compile_rules() {
  482.23 -	./configure $CONFIGURE_ARGS &&
  482.24 -	make &&
  482.25 -	make install
  482.26 -}
  482.27 -
  482.28 -genpkg_rules() {
  482.29 -	copy @std
  482.30 -	TAGS="font"
  482.31 -}
  482.32 -
  482.33 -post_install() {
  482.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
  482.35 -}
  482.36 -post_remove() {
  482.37 -	chroot "$1/" fc-cache -r
  482.38 -}
   483.1 --- a/xorg-font-alias/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   483.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   483.3 @@ -1,1 +0,0 @@
   483.4 -../xorg/.icon.png
   483.5 \ No newline at end of file
   484.1 --- a/xorg-font-alias/receipt	Thu Dec 13 00:46:54 2018 +0200
   484.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   484.3 @@ -1,27 +0,0 @@
   484.4 -# SliTaz package receipt v2.
   484.5 -
   484.6 -PACKAGE="xorg-font-alias"
   484.7 -VERSION="1.0.3"
   484.8 -CATEGORY="x-window"
   484.9 -SHORT_DESC="X font aliases"
  484.10 -MAINTAINER="al.bobylev@gmail.com"
  484.11 -LICENSE="other"
  484.12 -WEB_SITE="https://www.x.org/wiki/"
  484.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  484.14 -HOST_ARCH="any"
  484.15 -REPOLOGY="font-alias"
  484.16 -
  484.17 -TARBALL="font-alias-$VERSION.tar.bz2"
  484.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  484.19 -
  484.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev"
  484.21 -
  484.22 -compile_rules() {
  484.23 -	./configure $CONFIGURE_ARGS &&
  484.24 -	make &&
  484.25 -	make install
  484.26 -}
  484.27 -
  484.28 -genpkg_rules() {
  484.29 -	copy @std
  484.30 -}
   485.1 --- a/xorg-font-arabic-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   485.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   485.3 @@ -1,1 +0,0 @@
   485.4 -../xorg/.icon.png
   485.5 \ No newline at end of file
   486.1 --- a/xorg-font-arabic-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   486.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   486.3 @@ -1,34 +0,0 @@
   486.4 -# SliTaz package receipt v2.
   486.5 -
   486.6 -PACKAGE="xorg-font-arabic-misc"
   486.7 -VERSION="1.0.3"
   486.8 -CATEGORY="x-window"
   486.9 -SHORT_DESC="Misc Arabic fonts for X"
  486.10 -MAINTAINER="al.bobylev@gmail.com"
  486.11 -LICENSE="MIT"
  486.12 -WEB_SITE="https://www.x.org/wiki/"
  486.13 -HOST_ARCH="any"
  486.14 -REPOLOGY="fonts:arabic-misc"
  486.15 -
  486.16 -TARBALL="font-arabic-misc-$VERSION.tar.bz2"
  486.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  486.18 -
  486.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  486.20 -
  486.21 -compile_rules() {
  486.22 -	./configure $CONFIGURE_ARGS &&
  486.23 -	make &&
  486.24 -	make install
  486.25 -}
  486.26 -
  486.27 -genpkg_rules() {
  486.28 -	copy @std
  486.29 -	TAGS="font"
  486.30 -}
  486.31 -
  486.32 -post_install() {
  486.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  486.34 -}
  486.35 -post_remove() {
  486.36 -	chroot "$1/" fc-cache -r
  486.37 -}
   487.1 --- a/xorg-font-bh-100dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   487.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   487.3 @@ -1,1 +0,0 @@
   487.4 -../xorg/.icon.png
   487.5 \ No newline at end of file
   488.1 --- a/xorg-font-bh-100dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   488.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   488.3 @@ -1,37 +0,0 @@
   488.4 -# SliTaz package receipt v2.
   488.5 -
   488.6 -PACKAGE="xorg-font-bh-100dpi"
   488.7 -VERSION="1.0.3"
   488.8 -CATEGORY="x-window"
   488.9 -SHORT_DESC="Bigelow & Holmes bitmap fonts Lucida and LucidaBright (100 DPI)"
  488.10 -MAINTAINER="al.bobylev@gmail.com"
  488.11 -LICENSE="MIT"
  488.12 -WEB_SITE="https://www.x.org/wiki/"
  488.13 -HOST_ARCH="any"
  488.14 -REPOLOGY="fonts:bh-100dpi"
  488.15 -
  488.16 -TARBALL="font-bh-100dpi-$VERSION.tar.bz2"
  488.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  488.18 -
  488.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  488.20 -COOKOPTS="!gz" # too long
  488.21 -
  488.22 -compile_rules() {
  488.23 -	./configure \
  488.24 -		--disable-all-encodings \
  488.25 -		$CONFIGURE_ARGS &&
  488.26 -	make &&
  488.27 -	make install
  488.28 -}
  488.29 -
  488.30 -genpkg_rules() {
  488.31 -	copy @std
  488.32 -	TAGS="font"
  488.33 -}
  488.34 -
  488.35 -post_install() {
  488.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
  488.37 -}
  488.38 -post_remove() {
  488.39 -	chroot "$1/" fc-cache -r
  488.40 -}
   489.1 --- a/xorg-font-bh-75dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   489.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   489.3 @@ -1,1 +0,0 @@
   489.4 -../xorg/.icon.png
   489.5 \ No newline at end of file
   490.1 --- a/xorg-font-bh-75dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   490.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   490.3 @@ -1,37 +0,0 @@
   490.4 -# SliTaz package receipt v2.
   490.5 -
   490.6 -PACKAGE="xorg-font-bh-75dpi"
   490.7 -VERSION="1.0.3"
   490.8 -CATEGORY="x-window"
   490.9 -SHORT_DESC="Bigelow & Holmes bitmap fonts Lucida and LucidaBright (75 DPI)"
  490.10 -MAINTAINER="al.bobylev@gmail.com"
  490.11 -LICENSE="MIT"
  490.12 -WEB_SITE="https://www.x.org/wiki/"
  490.13 -HOST_ARCH="any"
  490.14 -REPOLOGY="fonts:bh-75dpi"
  490.15 -
  490.16 -TARBALL="font-bh-75dpi-$VERSION.tar.bz2"
  490.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  490.18 -
  490.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  490.20 -COOKOPTS="!gz" # too long
  490.21 -
  490.22 -compile_rules() {
  490.23 -	./configure \
  490.24 -		--disable-all-encodings \
  490.25 -		$CONFIGURE_ARGS &&
  490.26 -	make &&
  490.27 -	make install
  490.28 -}
  490.29 -
  490.30 -genpkg_rules() {
  490.31 -	copy @std
  490.32 -	TAGS="font"
  490.33 -}
  490.34 -
  490.35 -post_install() {
  490.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
  490.37 -}
  490.38 -post_remove() {
  490.39 -	chroot "$1/" fc-cache -r
  490.40 -}
   491.1 --- a/xorg-font-bh-lucidatypewriter-100dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   491.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   491.3 @@ -1,1 +0,0 @@
   491.4 -../xorg/.icon.png
   491.5 \ No newline at end of file
   492.1 --- a/xorg-font-bh-lucidatypewriter-100dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   492.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   492.3 @@ -1,37 +0,0 @@
   492.4 -# SliTaz package receipt v2.
   492.5 -
   492.6 -PACKAGE="xorg-font-bh-lucidatypewriter-100dpi"
   492.7 -VERSION="1.0.3"
   492.8 -CATEGORY="x-window"
   492.9 -SHORT_DESC="Bigelow & Holmes bitmap font LucidaTypewriter (100 DPI)"
  492.10 -MAINTAINER="al.bobylev@gmail.com"
  492.11 -LICENSE="other"
  492.12 -WEB_SITE="https://www.x.org/wiki/"
  492.13 -HOST_ARCH="any"
  492.14 -REPOLOGY="fonts:bh-lucidatypewriter-100dpi"
  492.15 -
  492.16 -TARBALL="font-bh-lucidatypewriter-100dpi-$VERSION.tar.bz2"
  492.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  492.18 -
  492.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  492.20 -COOKOPTS="!gz" # too long
  492.21 -
  492.22 -compile_rules() {
  492.23 -	./configure \
  492.24 -		--disable-all-encodings \
  492.25 -		$CONFIGURE_ARGS &&
  492.26 -	make &&
  492.27 -	make install
  492.28 -}
  492.29 -
  492.30 -genpkg_rules() {
  492.31 -	copy @std
  492.32 -	TAGS="font"
  492.33 -}
  492.34 -
  492.35 -post_install() {
  492.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
  492.37 -}
  492.38 -post_remove() {
  492.39 -	chroot "$1/" fc-cache -r
  492.40 -}
   493.1 --- a/xorg-font-bh-lucidatypewriter-75dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   493.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   493.3 @@ -1,1 +0,0 @@
   493.4 -../xorg/.icon.png
   493.5 \ No newline at end of file
   494.1 --- a/xorg-font-bh-lucidatypewriter-75dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   494.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   494.3 @@ -1,37 +0,0 @@
   494.4 -# SliTaz package receipt v2.
   494.5 -
   494.6 -PACKAGE="xorg-font-bh-lucidatypewriter-75dpi"
   494.7 -VERSION="1.0.3"
   494.8 -CATEGORY="x-window"
   494.9 -SHORT_DESC="Bigelow & Holmes bitmap font LucidaTypewriter (75 DPI)"
  494.10 -MAINTAINER="al.bobylev@gmail.com"
  494.11 -LICENSE="other"
  494.12 -WEB_SITE="https://www.x.org/wiki/"
  494.13 -HOST_ARCH="any"
  494.14 -REPOLOGY="fonts:bh-lucidatypewriter-75dpi"
  494.15 -
  494.16 -TARBALL="font-bh-lucidatypewriter-75dpi-$VERSION.tar.bz2"
  494.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  494.18 -
  494.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  494.20 -COOKOPTS="!gz" # too long
  494.21 -
  494.22 -compile_rules() {
  494.23 -	./configure \
  494.24 -		--disable-all-encodings \
  494.25 -		$CONFIGURE_ARGS &&
  494.26 -	make &&
  494.27 -	make install
  494.28 -}
  494.29 -
  494.30 -genpkg_rules() {
  494.31 -	copy @std
  494.32 -	TAGS="font"
  494.33 -}
  494.34 -
  494.35 -post_install() {
  494.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
  494.37 -}
  494.38 -post_remove() {
  494.39 -	chroot "$1/" fc-cache -r
  494.40 -}
   495.1 --- a/xorg-font-bh-ttf/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   495.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   495.3 @@ -1,1 +0,0 @@
   495.4 -../xorg/.icon.png
   495.5 \ No newline at end of file
   496.1 --- a/xorg-font-bh-ttf/receipt	Thu Dec 13 00:46:54 2018 +0200
   496.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   496.3 @@ -1,36 +0,0 @@
   496.4 -# SliTaz package receipt v2.
   496.5 -
   496.6 -PACKAGE="xorg-font-bh-ttf"
   496.7 -VERSION="1.0.3"
   496.8 -CATEGORY="x-window"
   496.9 -SHORT_DESC="Bigelow & Holmes Luxi TTF fonts"
  496.10 -MAINTAINER="al.bobylev@gmail.com"
  496.11 -LICENSE="MIT"
  496.12 -WEB_SITE="https://www.x.org/wiki/"
  496.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  496.14 -HOST_ARCH="any"
  496.15 -REPOLOGY="font-bh-ttf"
  496.16 -
  496.17 -TARBALL="font-bh-ttf-$VERSION.tar.bz2"
  496.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  496.19 -
  496.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir \
  496.21 -fontconfig-dev"
  496.22 -
  496.23 -compile_rules() {
  496.24 -	./configure $CONFIGURE_ARGS &&
  496.25 -	make &&
  496.26 -	make install
  496.27 -}
  496.28 -
  496.29 -genpkg_rules() {
  496.30 -	copy @std
  496.31 -	TAGS="font"
  496.32 -}
  496.33 -
  496.34 -post_install() {
  496.35 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/TTF
  496.36 -}
  496.37 -post_remove() {
  496.38 -	chroot "$1/" fc-cache -r
  496.39 -}
   497.1 --- a/xorg-font-bh-type1/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   497.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   497.3 @@ -1,1 +0,0 @@
   497.4 -../xorg/.icon.png
   497.5 \ No newline at end of file
   498.1 --- a/xorg-font-bh-type1/receipt	Thu Dec 13 00:46:54 2018 +0200
   498.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   498.3 @@ -1,35 +0,0 @@
   498.4 -# SliTaz package receipt v2.
   498.5 -
   498.6 -PACKAGE="xorg-font-bh-type1"
   498.7 -VERSION="1.0.3"
   498.8 -CATEGORY="x-window"
   498.9 -SHORT_DESC="Bigelow & Holmes Luxi Type1 fonts"
  498.10 -MAINTAINER="al.bobylev@gmail.com"
  498.11 -LICENSE="MIT"
  498.12 -WEB_SITE="https://www.x.org/wiki/"
  498.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  498.14 -HOST_ARCH="any"
  498.15 -REPOLOGY="fonts:bh-type1"
  498.16 -
  498.17 -TARBALL="font-bh-type1-$VERSION.tar.bz2"
  498.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  498.19 -
  498.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  498.21 -
  498.22 -compile_rules() {
  498.23 -	./configure $CONFIGURE_ARGS &&
  498.24 -	make &&
  498.25 -	make install
  498.26 -}
  498.27 -
  498.28 -genpkg_rules() {
  498.29 -	copy @std
  498.30 -	TAGS="font"
  498.31 -}
  498.32 -
  498.33 -post_install() {
  498.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
  498.35 -}
  498.36 -post_remove() {
  498.37 -	chroot "$1/" fc-cache -r
  498.38 -}
   499.1 --- a/xorg-font-bitstream-100dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   499.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   499.3 @@ -1,1 +0,0 @@
   499.4 -../xorg/.icon.png
   499.5 \ No newline at end of file
   500.1 --- a/xorg-font-bitstream-100dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   500.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   500.3 @@ -1,35 +0,0 @@
   500.4 -# SliTaz package receipt v2.
   500.5 -
   500.6 -PACKAGE="xorg-font-bitstream-100dpi"
   500.7 -VERSION="1.0.3"
   500.8 -CATEGORY="x-window"
   500.9 -SHORT_DESC="Bitstream bitmap fonts Charter, Terminal (100 DPI)"
  500.10 -MAINTAINER="al.bobylev@gmail.com"
  500.11 -LICENSE="MIT"
  500.12 -WEB_SITE="https://www.x.org/wiki/"
  500.13 -HOST_ARCH="any"
  500.14 -REPOLOGY="fonts:bitstream-100dpi"
  500.15 -
  500.16 -TARBALL="font-bitstream-100dpi-$VERSION.tar.bz2"
  500.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  500.18 -
  500.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  500.20 -COOKOPTS="!gz" # too long
  500.21 -
  500.22 -compile_rules() {
  500.23 -	./configure $CONFIGURE_ARGS &&
  500.24 -	make &&
  500.25 -	make install
  500.26 -}
  500.27 -
  500.28 -genpkg_rules() {
  500.29 -	copy @std
  500.30 -	TAGS="font"
  500.31 -}
  500.32 -
  500.33 -post_install() {
  500.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/100dpi
  500.35 -}
  500.36 -post_remove() {
  500.37 -	chroot "$1/" fc-cache -r
  500.38 -}
   501.1 --- a/xorg-font-bitstream-75dpi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   501.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   501.3 @@ -1,1 +0,0 @@
   501.4 -../xorg/.icon.png
   501.5 \ No newline at end of file
   502.1 --- a/xorg-font-bitstream-75dpi/receipt	Thu Dec 13 00:46:54 2018 +0200
   502.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   502.3 @@ -1,35 +0,0 @@
   502.4 -# SliTaz package receipt v2.
   502.5 -
   502.6 -PACKAGE="xorg-font-bitstream-75dpi"
   502.7 -VERSION="1.0.3"
   502.8 -CATEGORY="x-window"
   502.9 -SHORT_DESC="Bitstream bitmap fonts Charter, Terminal (75 DPI)"
  502.10 -MAINTAINER="al.bobylev@gmail.com"
  502.11 -LICENSE="MIT"
  502.12 -WEB_SITE="https://www.x.org/wiki/"
  502.13 -HOST_ARCH="any"
  502.14 -REPOLOGY="fonts:bitstream-75dpi"
  502.15 -
  502.16 -TARBALL="font-bitstream-75dpi-$VERSION.tar.bz2"
  502.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  502.18 -
  502.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  502.20 -COOKOPTS="!gz" # too long
  502.21 -
  502.22 -compile_rules() {
  502.23 -	./configure $CONFIGURE_ARGS &&
  502.24 -	make &&
  502.25 -	make install
  502.26 -}
  502.27 -
  502.28 -genpkg_rules() {
  502.29 -	copy @std
  502.30 -	TAGS="font"
  502.31 -}
  502.32 -
  502.33 -post_install() {
  502.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/75dpi
  502.35 -}
  502.36 -post_remove() {
  502.37 -	chroot "$1/" fc-cache -r
  502.38 -}
   503.1 --- a/xorg-font-bitstream-type1/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   503.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   503.3 @@ -1,1 +0,0 @@
   503.4 -../xorg/.icon.png
   503.5 \ No newline at end of file
   504.1 --- a/xorg-font-bitstream-type1/receipt	Thu Dec 13 00:46:54 2018 +0200
   504.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   504.3 @@ -1,34 +0,0 @@
   504.4 -# SliTaz package receipt v2.
   504.5 -
   504.6 -PACKAGE="xorg-font-bitstream-type1"
   504.7 -VERSION="1.0.3"
   504.8 -CATEGORY="x-window"
   504.9 -SHORT_DESC="Bitstream Type1 fonts Courier, Charter"
  504.10 -MAINTAINER="al.bobylev@gmail.com"
  504.11 -LICENSE="MIT"
  504.12 -WEB_SITE="https://www.x.org/wiki/"
  504.13 -HOST_ARCH="any"
  504.14 -REPOLOGY="fonts:bitstream-type1"
  504.15 -
  504.16 -TARBALL="font-bitstream-type1-$VERSION.tar.bz2"
  504.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  504.18 -
  504.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  504.20 -
  504.21 -compile_rules() {
  504.22 -	./configure $CONFIGURE_ARGS &&
  504.23 -	make &&
  504.24 -	make install
  504.25 -}
  504.26 -
  504.27 -genpkg_rules() {
  504.28 -	copy @std
  504.29 -	TAGS="font"
  504.30 -}
  504.31 -
  504.32 -post_install() {
  504.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
  504.34 -}
  504.35 -post_remove() {
  504.36 -	chroot "$1/" fc-cache -r
  504.37 -}
   505.1 --- a/xorg-font-cronyx-cyrillic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   505.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   505.3 @@ -1,1 +0,0 @@
   505.4 -../xorg/.icon.png
   505.5 \ No newline at end of file
   506.1 --- a/xorg-font-cronyx-cyrillic/receipt	Thu Dec 13 00:46:54 2018 +0200
   506.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   506.3 @@ -1,35 +0,0 @@
   506.4 -# SliTaz package receipt v2.
   506.5 -
   506.6 -PACKAGE="xorg-font-cronyx-cyrillic"
   506.7 -VERSION="1.0.3"
   506.8 -CATEGORY="x-window"
   506.9 -SHORT_DESC="Cronyx bitmap fonts Courier, Helvetica, Times, Fixed"
  506.10 -MAINTAINER="al.bobylev@gmail.com"
  506.11 -LICENSE="other"
  506.12 -WEB_SITE="https://www.x.org/wiki/"
  506.13 -HOST_ARCH="any"
  506.14 -REPOLOGY="fonts:cronyx-cyrillic"
  506.15 -
  506.16 -TARBALL="font-cronyx-cyrillic-$VERSION.tar.bz2"
  506.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  506.18 -
  506.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  506.20 -COOKOPTS="!gz" # too long
  506.21 -
  506.22 -compile_rules() {
  506.23 -	./configure $CONFIGURE_ARGS &&
  506.24 -	make &&
  506.25 -	make install
  506.26 -}
  506.27 -
  506.28 -genpkg_rules() {
  506.29 -	copy @std
  506.30 -	TAGS="font"
  506.31 -}
  506.32 -
  506.33 -post_install() {
  506.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
  506.35 -}
  506.36 -post_remove() {
  506.37 -	chroot "$1/" fc-cache -r
  506.38 -}
   507.1 --- a/xorg-font-cursor-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   507.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   507.3 @@ -1,1 +0,0 @@
   507.4 -../xorg/.icon.png
   507.5 \ No newline at end of file
   508.1 --- a/xorg-font-cursor-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   508.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   508.3 @@ -1,34 +0,0 @@
   508.4 -# SliTaz package receipt v2.
   508.5 -
   508.6 -PACKAGE="xorg-font-cursor-misc"
   508.7 -VERSION="1.0.3"
   508.8 -CATEGORY="x-window"
   508.9 -SHORT_DESC="Misc bitmap set: cursor"
  508.10 -MAINTAINER="al.bobylev@gmail.com"
  508.11 -LICENSE="other"
  508.12 -WEB_SITE="https://www.x.org/wiki/"
  508.13 -HOST_ARCH="any"
  508.14 -REPOLOGY="font-cursor-misc"
  508.15 -
  508.16 -TARBALL="font-cursor-misc-$VERSION.tar.bz2"
  508.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  508.18 -
  508.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  508.20 -
  508.21 -compile_rules() {
  508.22 -	./configure $CONFIGURE_ARGS &&
  508.23 -	make &&
  508.24 -	make install
  508.25 -}
  508.26 -
  508.27 -genpkg_rules() {
  508.28 -	copy @std
  508.29 -	TAGS="font"
  508.30 -}
  508.31 -
  508.32 -post_install() {
  508.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  508.34 -}
  508.35 -post_remove() {
  508.36 -	chroot "$1/" fc-cache -r
  508.37 -}
   509.1 --- a/xorg-font-daewoo-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   509.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   509.3 @@ -1,1 +0,0 @@
   509.4 -../xorg/.icon.png
   509.5 \ No newline at end of file
   510.1 --- a/xorg-font-daewoo-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   510.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   510.3 @@ -1,35 +0,0 @@
   510.4 -# SliTaz package receipt v2.
   510.5 -
   510.6 -PACKAGE="xorg-font-daewoo-misc"
   510.7 -VERSION="1.0.3"
   510.8 -CATEGORY="x-window"
   510.9 -SHORT_DESC="Daewoo bitmap fonts Gothic, Mincho"
  510.10 -MAINTAINER="al.bobylev@gmail.com"
  510.11 -LICENSE="other"
  510.12 -WEB_SITE="https://www.x.org/wiki/"
  510.13 -HOST_ARCH="any"
  510.14 -REPOLOGY="font-daewoo-misc"
  510.15 -
  510.16 -TARBALL="font-daewoo-misc-$VERSION.tar.bz2"
  510.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  510.18 -
  510.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  510.20 -COOKOPTS="!gz" # too long
  510.21 -
  510.22 -compile_rules() {
  510.23 -	./configure $CONFIGURE_ARGS &&
  510.24 -	make &&
  510.25 -	make install
  510.26 -}
  510.27 -
  510.28 -genpkg_rules() {
  510.29 -	copy @std
  510.30 -	TAGS="font"
  510.31 -}
  510.32 -
  510.33 -post_install() {
  510.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  510.35 -}
  510.36 -post_remove() {
  510.37 -	chroot "$1/" fc-cache -r
  510.38 -}
   511.1 --- a/xorg-font-dec-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   511.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   511.3 @@ -1,1 +0,0 @@
   511.4 -../xorg/.icon.png
   511.5 \ No newline at end of file
   512.1 --- a/xorg-font-dec-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   512.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   512.3 @@ -1,35 +0,0 @@
   512.4 -# SliTaz package receipt v2.
   512.5 -
   512.6 -PACKAGE="xorg-font-dec-misc"
   512.7 -VERSION="1.0.3"
   512.8 -CATEGORY="x-window"
   512.9 -SHORT_DESC="DEC misc bitmap sets: cursor, session"
  512.10 -MAINTAINER="al.bobylev@gmail.com"
  512.11 -LICENSE="MIT"
  512.12 -WEB_SITE="https://www.x.org/wiki/"
  512.13 -HOST_ARCH="any"
  512.14 -REPOLOGY="font-dec-misc"
  512.15 -
  512.16 -TARBALL="font-dec-misc-$VERSION.tar.bz2"
  512.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  512.18 -
  512.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  512.20 -COOKOPTS="!gz" # too long
  512.21 -
  512.22 -compile_rules() {
  512.23 -	./configure $CONFIGURE_ARGS &&
  512.24 -	make &&
  512.25 -	make install
  512.26 -}
  512.27 -
  512.28 -genpkg_rules() {
  512.29 -	copy @std
  512.30 -	TAGS="font"
  512.31 -}
  512.32 -
  512.33 -post_install() {
  512.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  512.35 -}
  512.36 -post_remove() {
  512.37 -	chroot "$1/" fc-cache -r
  512.38 -}
   513.1 --- a/xorg-font-ibm-type1/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   513.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   513.3 @@ -1,1 +0,0 @@
   513.4 -../xorg/.icon.png
   513.5 \ No newline at end of file
   514.1 --- a/xorg-font-ibm-type1/receipt	Thu Dec 13 00:46:54 2018 +0200
   514.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   514.3 @@ -1,35 +0,0 @@
   514.4 -# SliTaz package receipt v2.
   514.5 -
   514.6 -PACKAGE="xorg-font-ibm-type1"
   514.7 -VERSION="1.0.3"
   514.8 -CATEGORY="x-window"
   514.9 -SHORT_DESC="IBM Courier Type1 font"
  514.10 -MAINTAINER="al.bobylev@gmail.com"
  514.11 -LICENSE="MIT"
  514.12 -WEB_SITE="https://www.x.org/wiki/"
  514.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  514.14 -HOST_ARCH="any"
  514.15 -REPOLOGY="fonts:ibm-type1"
  514.16 -
  514.17 -TARBALL="font-ibm-type1-$VERSION.tar.bz2"
  514.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  514.19 -
  514.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  514.21 -
  514.22 -compile_rules() {
  514.23 -	./configure $CONFIGURE_ARGS &&
  514.24 -	make &&
  514.25 -	make install
  514.26 -}
  514.27 -
  514.28 -genpkg_rules() {
  514.29 -	copy @std
  514.30 -	TAGS="font"
  514.31 -}
  514.32 -
  514.33 -post_install() {
  514.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
  514.35 -}
  514.36 -post_remove() {
  514.37 -	chroot "$1/" fc-cache -r
  514.38 -}
   515.1 --- a/xorg-font-isas-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   515.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   515.3 @@ -1,1 +0,0 @@
   515.4 -../xorg/.icon.png
   515.5 \ No newline at end of file
   516.1 --- a/xorg-font-isas-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   516.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   516.3 @@ -1,35 +0,0 @@
   516.4 -# SliTaz package receipt v2.
   516.5 -
   516.6 -PACKAGE="xorg-font-isas-misc"
   516.7 -VERSION="1.0.3"
   516.8 -CATEGORY="x-window"
   516.9 -SHORT_DESC="ISAS bitmap fonts: Fangsong ti, Song ti"
  516.10 -MAINTAINER="al.bobylev@gmail.com"
  516.11 -LICENSE="MIT"
  516.12 -WEB_SITE="https://www.x.org/wiki/"
  516.13 -HOST_ARCH="any"
  516.14 -REPOLOGY="fonts:isas-misc"
  516.15 -
  516.16 -TARBALL="font-isas-misc-$VERSION.tar.bz2"
  516.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  516.18 -
  516.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  516.20 -COOKOPTS="!gz" # too long
  516.21 -
  516.22 -compile_rules() {
  516.23 -	./configure $CONFIGURE_ARGS &&
  516.24 -	make &&
  516.25 -	make install
  516.26 -}
  516.27 -
  516.28 -genpkg_rules() {
  516.29 -	copy @std
  516.30 -	TAGS="font"
  516.31 -}
  516.32 -
  516.33 -post_install() {
  516.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  516.35 -}
  516.36 -post_remove() {
  516.37 -	chroot "$1/" fc-cache -r
  516.38 -}
   517.1 --- a/xorg-font-jis-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   517.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   517.3 @@ -1,1 +0,0 @@
   517.4 -../xorg/.icon.png
   517.5 \ No newline at end of file
   518.1 --- a/xorg-font-jis-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   518.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   518.3 @@ -1,35 +0,0 @@
   518.4 -# SliTaz package receipt v2.
   518.5 -
   518.6 -PACKAGE="xorg-font-jis-misc"
   518.7 -VERSION="1.0.3"
   518.8 -CATEGORY="x-window"
   518.9 -SHORT_DESC="JIS bitmap font: Fixed"
  518.10 -MAINTAINER="al.bobylev@gmail.com"
  518.11 -LICENSE="other"
  518.12 -WEB_SITE="https://www.x.org/wiki/"
  518.13 -HOST_ARCH="any"
  518.14 -REPOLOGY="font-jis-misc"
  518.15 -
  518.16 -TARBALL="font-jis-misc-$VERSION.tar.bz2"
  518.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  518.18 -
  518.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  518.20 -COOKOPTS="!gz" # too long
  518.21 -
  518.22 -compile_rules() {
  518.23 -	./configure $CONFIGURE_ARGS &&
  518.24 -	make &&
  518.25 -	make install
  518.26 -}
  518.27 -
  518.28 -genpkg_rules() {
  518.29 -	copy @std
  518.30 -	TAGS="font"
  518.31 -}
  518.32 -
  518.33 -post_install() {
  518.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  518.35 -}
  518.36 -post_remove() {
  518.37 -	chroot "$1/" fc-cache -r
  518.38 -}
   519.1 --- a/xorg-font-micro-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   519.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   519.3 @@ -1,1 +0,0 @@
   519.4 -../xorg/.icon.png
   519.5 \ No newline at end of file
   520.1 --- a/xorg-font-micro-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   520.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   520.3 @@ -1,34 +0,0 @@
   520.4 -# SliTaz package receipt v2.
   520.5 -
   520.6 -PACKAGE="xorg-font-micro-misc"
   520.7 -VERSION="1.0.3"
   520.8 -CATEGORY="x-window"
   520.9 -SHORT_DESC="Micro bitmap font"
  520.10 -MAINTAINER="al.bobylev@gmail.com"
  520.11 -LICENSE="PublicDomain"
  520.12 -WEB_SITE="https://www.x.org/wiki/"
  520.13 -HOST_ARCH="any"
  520.14 -REPOLOGY="fonts:micro-misc"
  520.15 -
  520.16 -TARBALL="font-micro-misc-$VERSION.tar.bz2"
  520.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  520.18 -
  520.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  520.20 -
  520.21 -compile_rules() {
  520.22 -	./configure $CONFIGURE_ARGS &&
  520.23 -	make &&
  520.24 -	make install
  520.25 -}
  520.26 -
  520.27 -genpkg_rules() {
  520.28 -	copy @std
  520.29 -	TAGS="font"
  520.30 -}
  520.31 -
  520.32 -post_install() {
  520.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  520.34 -}
  520.35 -post_remove() {
  520.36 -	chroot "$1/" fc-cache -r
  520.37 -}
   521.1 --- a/xorg-font-misc-cyrillic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   521.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   521.3 @@ -1,1 +0,0 @@
   521.4 -../xorg/.icon.png
   521.5 \ No newline at end of file
   522.1 --- a/xorg-font-misc-cyrillic/receipt	Thu Dec 13 00:46:54 2018 +0200
   522.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   522.3 @@ -1,35 +0,0 @@
   522.4 -# SliTaz package receipt v2.
   522.5 -
   522.6 -PACKAGE="xorg-font-misc-cyrillic"
   522.7 -VERSION="1.0.3"
   522.8 -CATEGORY="x-window"
   522.9 -SHORT_DESC="Misc Cyrillic bitmap font: Fixed"
  522.10 -MAINTAINER="al.bobylev@gmail.com"
  522.11 -LICENSE="other"
  522.12 -WEB_SITE="https://www.x.org/wiki/"
  522.13 -HOST_ARCH="any"
  522.14 -REPOLOGY="fonts:misc-cyrillic"
  522.15 -
  522.16 -TARBALL="font-misc-cyrillic-$VERSION.tar.bz2"
  522.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  522.18 -
  522.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  522.20 -COOKOPTS="!gz" # too long
  522.21 -
  522.22 -compile_rules() {
  522.23 -	./configure $CONFIGURE_ARGS &&
  522.24 -	make &&
  522.25 -	make install
  522.26 -}
  522.27 -
  522.28 -genpkg_rules() {
  522.29 -	copy @std
  522.30 -	TAGS="font"
  522.31 -}
  522.32 -
  522.33 -post_install() {
  522.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
  522.35 -}
  522.36 -post_remove() {
  522.37 -	chroot "$1/" fc-cache -r
  522.38 -}
   523.1 --- a/xorg-font-misc-ethiopic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   523.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   523.3 @@ -1,1 +0,0 @@
   523.4 -../xorg/.icon.png
   523.5 \ No newline at end of file
   524.1 --- a/xorg-font-misc-ethiopic/receipt	Thu Dec 13 00:46:54 2018 +0200
   524.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   524.3 @@ -1,35 +0,0 @@
   524.4 -# SliTaz package receipt v2.
   524.5 -
   524.6 -PACKAGE="xorg-font-misc-ethiopic"
   524.7 -VERSION="1.0.3"
   524.8 -CATEGORY="x-window"
   524.9 -SHORT_DESC="Ethiopic font Goha-Tibeb Zemen (OTF & TTF)"
  524.10 -MAINTAINER="al.bobylev@gmail.com"
  524.11 -LICENSE="MIT"
  524.12 -WEB_SITE="https://www.x.org/wiki/"
  524.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  524.14 -HOST_ARCH="any"
  524.15 -REPOLOGY="font-misc-ethiopic"
  524.16 -
  524.17 -TARBALL="font-misc-ethiopic-$VERSION.tar.bz2"
  524.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  524.19 -
  524.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  524.21 -
  524.22 -compile_rules() {
  524.23 -	./configure $CONFIGURE_ARGS &&
  524.24 -	make &&
  524.25 -	make install
  524.26 -}
  524.27 -
  524.28 -genpkg_rules() {
  524.29 -	copy @std
  524.30 -	TAGS="font"
  524.31 -}
  524.32 -
  524.33 -post_install() {
  524.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/OTF /usr/share/fonts/X11/TTF
  524.35 -}
  524.36 -post_remove() {
  524.37 -	chroot "$1/" fc-cache -r
  524.38 -}
   525.1 --- a/xorg-font-misc-meltho/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   525.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   525.3 @@ -1,1 +0,0 @@
   525.4 -../xorg/.icon.png
   525.5 \ No newline at end of file
   526.1 --- a/xorg-font-misc-meltho/description.txt	Thu Dec 13 00:46:54 2018 +0200
   526.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   526.3 @@ -1,23 +0,0 @@
   526.4 -These fonts are designed for the display of Syriac text. They come from Beth
   526.5 -Mardutho: The Syriac Institute and are covered by a license which permits
   526.6 -redistribution but prohibits modification.
   526.7 -
   526.8 -The package contains the following font families:
   526.9 -
  526.10 -  * East Syriac Adiabene
  526.11 -  * East Syriac Ctesiphon
  526.12 -  * Estrangelo Antioch
  526.13 -  * Estrangelo Edessa
  526.14 -  * Estrangelo Midyat
  526.15 -  * Estrangelo Nisibin
  526.16 -  * Estrangelo Nisibin Outline
  526.17 -  * Estrangelo Quenneshrin
  526.18 -  * Estrangelo Talada
  526.19 -  * Estrangelo TurAbdin
  526.20 -  * Serto Batnan
  526.21 -  * Serto Jerusalem
  526.22 -  * Serto Jerusalem Outline
  526.23 -  * Serto Kharput
  526.24 -  * Serto Malankara
  526.25 -  * Serto Mardin
  526.26 -  * Serto Urhoy
   527.1 --- a/xorg-font-misc-meltho/receipt	Thu Dec 13 00:46:54 2018 +0200
   527.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   527.3 @@ -1,34 +0,0 @@
   527.4 -# SliTaz package receipt v2.
   527.5 -
   527.6 -PACKAGE="xorg-font-misc-meltho"
   527.7 -VERSION="1.0.3"
   527.8 -CATEGORY="x-window"
   527.9 -SHORT_DESC="Syriac fonts (OTF)"
  527.10 -MAINTAINER="al.bobylev@gmail.com"
  527.11 -LICENSE="MIT"
  527.12 -WEB_SITE="https://www.x.org/wiki/"
  527.13 -HOST_ARCH="any"
  527.14 -REPOLOGY="font-misc-meltho"
  527.15 -
  527.16 -TARBALL="font-misc-meltho-$VERSION.tar.bz2"
  527.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  527.18 -
  527.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  527.20 -
  527.21 -compile_rules() {
  527.22 -	./configure $CONFIGURE_ARGS &&
  527.23 -	make &&
  527.24 -	make install
  527.25 -}
  527.26 -
  527.27 -genpkg_rules() {
  527.28 -	copy @std
  527.29 -	TAGS="font"
  527.30 -}
  527.31 -
  527.32 -post_install() {
  527.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/OTF
  527.34 -}
  527.35 -post_remove() {
  527.36 -	chroot "$1/" fc-cache -r
  527.37 -}
   528.1 --- a/xorg-font-misc-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   528.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   528.3 @@ -1,1 +0,0 @@
   528.4 -../xorg/.icon.png
   528.5 \ No newline at end of file
   529.1 --- a/xorg-font-misc-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   529.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   529.3 @@ -1,49 +0,0 @@
   529.4 -# SliTaz package receipt v2.
   529.5 -
   529.6 -PACKAGE="xorg-font-misc-misc"
   529.7 -VERSION="1.1.2"
   529.8 -CATEGORY="x-window"
   529.9 -SHORT_DESC="Misc bitmap fixed fonts"
  529.10 -MAINTAINER="al.bobylev@gmail.com"
  529.11 -LICENSE="PublicDomain"
  529.12 -WEB_SITE="https://www.x.org/wiki/"
  529.13 -HOST_ARCH="any"
  529.14 -REPOLOGY="font-misc-misc"
  529.15 -
  529.16 -TARBALL="font-misc-misc-$VERSION.tar.bz2"
  529.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  529.18 -
  529.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  529.20 -SPLIT="xorg-base-fonts $PACKAGE"
  529.21 -
  529.22 -COOKOPTS="!gz" # too long
  529.23 -
  529.24 -compile_rules() {
  529.25 -	./configure \
  529.26 -		--disable-all-encodings \
  529.27 -		$CONFIGURE_ARGS &&
  529.28 -	make &&
  529.29 -	make install
  529.30 -}
  529.31 -
  529.32 -genpkg_rules() {
  529.33 -	case $PACKAGE in
  529.34 -		xorg-base-fonts)
  529.35 -			copy 6x13.pcf.gz
  529.36 -			CAT="x-window|minimal set"
  529.37 -			DEPENDS=" "
  529.38 -			;;
  529.39 -		*)
  529.40 -			copy @std @rm
  529.41 -			DEPENDS="xorg-base-fonts"
  529.42 -			;;
  529.43 -	esac
  529.44 -	TAGS="font"
  529.45 -}
  529.46 -
  529.47 -post_install() {
  529.48 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  529.49 -}
  529.50 -post_remove() {
  529.51 -	chroot "$1/" fc-cache -r
  529.52 -}
   530.1 --- a/xorg-font-mutt-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   530.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   530.3 @@ -1,1 +0,0 @@
   530.4 -../xorg/.icon.png
   530.5 \ No newline at end of file
   531.1 --- a/xorg-font-mutt-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   531.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   531.3 @@ -1,35 +0,0 @@
   531.4 -# SliTaz package receipt v2.
   531.5 -
   531.6 -PACKAGE="xorg-font-mutt-misc"
   531.7 -VERSION="1.0.3"
   531.8 -CATEGORY="x-window"
   531.9 -SHORT_DESC="Bitmap Arabic, Devanagari, Armenian font ClearlyU"
  531.10 -MAINTAINER="al.bobylev@gmail.com"
  531.11 -LICENSE="MIT"
  531.12 -WEB_SITE="https://www.x.org/wiki/"
  531.13 -HOST_ARCH="any"
  531.14 -REPOLOGY="fonts:mutt-misc"
  531.15 -
  531.16 -TARBALL="font-mutt-misc-$VERSION.tar.bz2"
  531.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  531.18 -
  531.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  531.20 -COOKOPTS="!gz" # too long
  531.21 -
  531.22 -compile_rules() {
  531.23 -	./configure $CONFIGURE_ARGS &&
  531.24 -	make &&
  531.25 -	make install
  531.26 -}
  531.27 -
  531.28 -genpkg_rules() {
  531.29 -	copy @std
  531.30 -	TAGS="font"
  531.31 -}
  531.32 -
  531.33 -post_install() {
  531.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  531.35 -}
  531.36 -post_remove() {
  531.37 -	chroot "$1/" fc-cache -r
  531.38 -}
   532.1 --- a/xorg-font-schumacher-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   532.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   532.3 @@ -1,1 +0,0 @@
   532.4 -../xorg/.icon.png
   532.5 \ No newline at end of file
   533.1 --- a/xorg-font-schumacher-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   533.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   533.3 @@ -1,37 +0,0 @@
   533.4 -# SliTaz package receipt v2.
   533.5 -
   533.6 -PACKAGE="xorg-font-schumacher-misc"
   533.7 -VERSION="1.1.2"
   533.8 -CATEGORY="x-window"
   533.9 -SHORT_DESC="Schumacher bitmap font Clean"
  533.10 -MAINTAINER="al.bobylev@gmail.com"
  533.11 -LICENSE="MIT"
  533.12 -WEB_SITE="https://www.x.org/wiki/"
  533.13 -HOST_ARCH="any"
  533.14 -REPOLOGY="font-schumacher-misc"
  533.15 -
  533.16 -TARBALL="font-schumacher-misc-$VERSION.tar.bz2"
  533.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  533.18 -
  533.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  533.20 -COOKOPTS="!gz" # too long
  533.21 -
  533.22 -compile_rules() {
  533.23 -	./configure \
  533.24 -		--disable-all-encodings \
  533.25 -		$CONFIGURE_ARGS &&
  533.26 -	make &&
  533.27 -	make install
  533.28 -}
  533.29 -
  533.30 -genpkg_rules() {
  533.31 -	copy @std
  533.32 -	TAGS="font"
  533.33 -}
  533.34 -
  533.35 -post_install() {
  533.36 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  533.37 -}
  533.38 -post_remove() {
  533.39 -	chroot "$1/" fc-cache -r
  533.40 -}
   534.1 --- a/xorg-font-screen-cyrillic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   534.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   534.3 @@ -1,1 +0,0 @@
   534.4 -../xorg/.icon.png
   534.5 \ No newline at end of file
   535.1 --- a/xorg-font-screen-cyrillic/receipt	Thu Dec 13 00:46:54 2018 +0200
   535.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   535.3 @@ -1,35 +0,0 @@
   535.4 -# SliTaz package receipt v2.
   535.5 -
   535.6 -PACKAGE="xorg-font-screen-cyrillic"
   535.7 -VERSION="1.0.4"
   535.8 -CATEGORY="x-window"
   535.9 -SHORT_DESC="Misc Screen Cyrillic bitmap font: Fixed"
  535.10 -MAINTAINER="al.bobylev@gmail.com"
  535.11 -LICENSE="other"
  535.12 -WEB_SITE="https://www.x.org/wiki/"
  535.13 -HOST_ARCH="any"
  535.14 -REPOLOGY="fonts:screen-cyrillic"
  535.15 -
  535.16 -TARBALL="font-screen-cyrillic-$VERSION.tar.bz2"
  535.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  535.18 -
  535.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  535.20 -COOKOPTS="!gz" # too long
  535.21 -
  535.22 -compile_rules() {
  535.23 -	./configure $CONFIGURE_ARGS &&
  535.24 -	make &&
  535.25 -	make install
  535.26 -}
  535.27 -
  535.28 -genpkg_rules() {
  535.29 -	copy @std
  535.30 -	TAGS="font"
  535.31 -}
  535.32 -
  535.33 -post_install() {
  535.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
  535.35 -}
  535.36 -post_remove() {
  535.37 -	chroot "$1/" fc-cache -r
  535.38 -}
   536.1 --- a/xorg-font-sony-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   536.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   536.3 @@ -1,1 +0,0 @@
   536.4 -../xorg/.icon.png
   536.5 \ No newline at end of file
   537.1 --- a/xorg-font-sony-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   537.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   537.3 @@ -1,35 +0,0 @@
   537.4 -# SliTaz package receipt v2.
   537.5 -
   537.6 -PACKAGE="xorg-font-sony-misc"
   537.7 -VERSION="1.0.3"
   537.8 -CATEGORY="x-window"
   537.9 -SHORT_DESC="Bitmap Sony fixed fonts"
  537.10 -MAINTAINER="al.bobylev@gmail.com"
  537.11 -LICENSE="MIT"
  537.12 -WEB_SITE="https://www.x.org/wiki/"
  537.13 -HOST_ARCH="any"
  537.14 -REPOLOGY="font-sony-misc"
  537.15 -
  537.16 -TARBALL="font-sony-misc-$VERSION.tar.bz2"
  537.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  537.18 -
  537.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  537.20 -COOKOPTS="!gz" # too long
  537.21 -
  537.22 -compile_rules() {
  537.23 -	./configure $CONFIGURE_ARGS &&
  537.24 -	make &&
  537.25 -	make install
  537.26 -}
  537.27 -
  537.28 -genpkg_rules() {
  537.29 -	copy @std
  537.30 -	TAGS="font"
  537.31 -}
  537.32 -
  537.33 -post_install() {
  537.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  537.35 -}
  537.36 -post_remove() {
  537.37 -	chroot "$1/" fc-cache -r
  537.38 -}
   538.1 --- a/xorg-font-sun-misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   538.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   538.3 @@ -1,1 +0,0 @@
   538.4 -../xorg/.icon.png
   538.5 \ No newline at end of file
   539.1 --- a/xorg-font-sun-misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   539.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   539.3 @@ -1,35 +0,0 @@
   539.4 -# SliTaz package receipt v2.
   539.5 -
   539.6 -PACKAGE="xorg-font-sun-misc"
   539.7 -VERSION="1.0.3"
   539.8 -CATEGORY="x-window"
   539.9 -SHORT_DESC="Sun bitmap sets: OPEN LOOK cursor, OPEN LOOK glyph"
  539.10 -MAINTAINER="al.bobylev@gmail.com"
  539.11 -LICENSE="MIT"
  539.12 -WEB_SITE="https://www.x.org/wiki/"
  539.13 -HOST_ARCH="any"
  539.14 -REPOLOGY="font-sun-misc"
  539.15 -
  539.16 -TARBALL="font-sun-misc-$VERSION.tar.bz2"
  539.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  539.18 -
  539.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  539.20 -COOKOPTS="!gz" # too long
  539.21 -
  539.22 -compile_rules() {
  539.23 -	./configure $CONFIGURE_ARGS &&
  539.24 -	make &&
  539.25 -	make install
  539.26 -}
  539.27 -
  539.28 -genpkg_rules() {
  539.29 -	copy @std
  539.30 -	TAGS="font"
  539.31 -}
  539.32 -
  539.33 -post_install() {
  539.34 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/misc
  539.35 -}
  539.36 -post_remove() {
  539.37 -	chroot "$1/" fc-cache -r
  539.38 -}
   540.1 --- a/xorg-font-util/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   540.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   540.3 @@ -1,1 +0,0 @@
   540.4 -../xorg/.icon.png
   540.5 \ No newline at end of file
   541.1 --- a/xorg-font-util/receipt	Thu Dec 13 00:46:54 2018 +0200
   541.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   541.3 @@ -1,30 +0,0 @@
   541.4 -# SliTaz package receipt v2.
   541.5 -
   541.6 -PACKAGE="xorg-font-util"
   541.7 -VERSION="1.3.1"
   541.8 -CATEGORY="x-window"
   541.9 -SHORT_DESC="Font utilities dirs"
  541.10 -MAINTAINER="al.bobylev@gmail.com"
  541.11 -LICENSE="MIT"
  541.12 -WEB_SITE="https://www.x.org/wiki/"
  541.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  541.14 -REPOLOGY="font-util"
  541.15 -
  541.16 -TARBALL="font-util-$VERSION.tar.bz2"
  541.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  541.18 -
  541.19 -BUILD_DEPENDS="xorg-util-macros"
  541.20 -SPLIT="$PACKAGE-dev"
  541.21 -
  541.22 -compile_rules() {
  541.23 -	./configure $CONFIGURE_ARGS &&
  541.24 -	make &&
  541.25 -	make install
  541.26 -}
  541.27 -
  541.28 -genpkg_rules() {
  541.29 -	case $PACKAGE in
  541.30 -		*-font-util) copy @std;;
  541.31 -		*-dev)       copy @dev;;
  541.32 -	esac
  541.33 -}
   542.1 --- a/xorg-font-winitzki-cyrillic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   542.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   542.3 @@ -1,1 +0,0 @@
   542.4 -../xorg/.icon.png
   542.5 \ No newline at end of file
   543.1 --- a/xorg-font-winitzki-cyrillic/receipt	Thu Dec 13 00:46:54 2018 +0200
   543.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   543.3 @@ -1,34 +0,0 @@
   543.4 -# SliTaz package receipt v2.
   543.5 -
   543.6 -PACKAGE="xorg-font-winitzki-cyrillic"
   543.7 -VERSION="1.0.3"
   543.8 -CATEGORY="x-window"
   543.9 -SHORT_DESC="Winitzki Cyrillic bitmap font: Proof"
  543.10 -MAINTAINER="al.bobylev@gmail.com"
  543.11 -LICENSE="PublicDomain"
  543.12 -WEB_SITE="https://www.x.org/wiki/"
  543.13 -HOST_ARCH="any"
  543.14 -REPOLOGY="fonts:winitzki-cyrillic"
  543.15 -
  543.16 -TARBALL="font-winitzki-cyrillic-$VERSION.tar.bz2"
  543.17 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  543.18 -
  543.19 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir xorg-bdftopcf"
  543.20 -
  543.21 -compile_rules() {
  543.22 -	./configure $CONFIGURE_ARGS &&
  543.23 -	make &&
  543.24 -	make install
  543.25 -}
  543.26 -
  543.27 -genpkg_rules() {
  543.28 -	copy @std
  543.29 -	TAGS="font"
  543.30 -}
  543.31 -
  543.32 -post_install() {
  543.33 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/cyrillic
  543.34 -}
  543.35 -post_remove() {
  543.36 -	chroot "$1/" fc-cache -r
  543.37 -}
   544.1 --- a/xorg-font-xfree86-type1/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   544.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   544.3 @@ -1,1 +0,0 @@
   544.4 -../xorg/.icon.png
   544.5 \ No newline at end of file
   545.1 --- a/xorg-font-xfree86-type1/receipt	Thu Dec 13 00:46:54 2018 +0200
   545.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   545.3 @@ -1,32 +0,0 @@
   545.4 -# SliTaz package receipt v2.
   545.5 -
   545.6 -PACKAGE="xorg-font-xfree86-type1"
   545.7 -VERSION="1.0.4"
   545.8 -CATEGORY="x-window"
   545.9 -SHORT_DESC="Xfree86 Type1 Cursor font"
  545.10 -MAINTAINER="al.bobylev@gmail.com"
  545.11 -LICENSE="MIT"
  545.12 -WEB_SITE="https://www.x.org/wiki/"
  545.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7font.html"
  545.14 -HOST_ARCH="any"
  545.15 -REPOLOGY="fonts:xfree86-type1"
  545.16 -
  545.17 -TARBALL="font-xfree86-type1-$VERSION.tar.bz2"
  545.18 -WGET_URL="$XORG_MIRROR/font/$TARBALL"
  545.19 -
  545.20 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-mkfontdir"
  545.21 -
  545.22 -TAGS_atd="font"
  545.23 -
  545.24 -compile_rules() {
  545.25 -	./configure $CONFIGURE_ARGS &&
  545.26 -	make &&
  545.27 -	make install
  545.28 -}
  545.29 -
  545.30 -post_install() {
  545.31 -	chroot "$1/" fc-cache -r /usr/share/fonts/X11/Type1
  545.32 -}
  545.33 -post_remove() {
  545.34 -	chroot "$1/" fc-cache -r
  545.35 -}
   546.1 --- a/xorg-fonttosfnt/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   546.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   546.3 @@ -1,1 +0,0 @@
   546.4 -../xorg/.icon.png
   546.5 \ No newline at end of file
   547.1 --- a/xorg-fonttosfnt/receipt	Thu Dec 13 00:46:54 2018 +0200
   547.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   547.3 @@ -1,27 +0,0 @@
   547.4 -# SliTaz package receipt v2.
   547.5 -
   547.6 -PACKAGE="xorg-fonttosfnt"
   547.7 -VERSION="1.0.5"
   547.8 -CATEGORY="x-window"
   547.9 -SHORT_DESC="Wrap a bitmap font in a sfnt (TrueType) wrapper"
  547.10 -MAINTAINER="pascal.bellard@slitaz.org"
  547.11 -LICENSE="MIT"
  547.12 -WEB_SITE="https://www.x.org/wiki/"
  547.13 -REPOLOGY="fonttosfnt"
  547.14 -
  547.15 -TARBALL="fonttosfnt-$VERSION.tar.bz2"
  547.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  547.17 -
  547.18 -BUILD_DEPENDS="xorg-xorgproto freetype-dev xorg-libfontenc-dev"
  547.19 -
  547.20 -compile_rules() {
  547.21 -	./configure $CONFIGURE_ARGS &&
  547.22 -	make &&
  547.23 -	make install
  547.24 -}
  547.25 -
  547.26 -genpkg_rules() {
  547.27 -	copy @std
  547.28 -	DEPENDS="freetype xorg-libfontenc"
  547.29 -	TAGS="utility xorg fonts"
  547.30 -}
   548.1 --- a/xorg-fslsfonts/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   548.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   548.3 @@ -1,1 +0,0 @@
   548.4 -../xorg/.icon.png
   548.5 \ No newline at end of file
   549.1 --- a/xorg-fslsfonts/receipt	Thu Dec 13 00:46:54 2018 +0200
   549.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   549.3 @@ -1,26 +0,0 @@
   549.4 -# SliTaz package receipt v2.
   549.5 -
   549.6 -PACKAGE="xorg-fslsfonts"
   549.7 -VERSION="1.0.5"
   549.8 -CATEGORY="x-window"
   549.9 -SHORT_DESC="List fonts served by X font server"
  549.10 -MAINTAINER="al.bobylev@gmail.com"
  549.11 -LICENSE="MIT"
  549.12 -WEB_SITE="https://www.x.org/wiki/"
  549.13 -REPOLOGY="fslsfonts"
  549.14 -
  549.15 -TARBALL="fslsfonts-$VERSION.tar.bz2"
  549.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  549.17 -
  549.18 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-libFS-dev"
  549.19 -
  549.20 -compile_rules() {
  549.21 -	./configure $CONFIGURE_ARGS &&
  549.22 -	make &&
  549.23 -	make install
  549.24 -}
  549.25 -
  549.26 -genpkg_rules() {
  549.27 -	copy @std
  549.28 -	DEPENDS="xorg-libFS"
  549.29 -}
   550.1 --- a/xorg-fstobdf/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   550.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   550.3 @@ -1,1 +0,0 @@
   550.4 -../xorg/.icon.png
   550.5 \ No newline at end of file
   551.1 --- a/xorg-fstobdf/receipt	Thu Dec 13 00:46:54 2018 +0200
   551.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   551.3 @@ -1,26 +0,0 @@
   551.4 -# SliTaz package receipt v2.
   551.5 -
   551.6 -PACKAGE="xorg-fstobdf"
   551.7 -VERSION="1.0.6"
   551.8 -CATEGORY="x-window"
   551.9 -SHORT_DESC="Generate BDF font from X font server"
  551.10 -MAINTAINER="al.bobylev@gmail.com"
  551.11 -LICENSE="MIT"
  551.12 -WEB_SITE="https://www.x.org/wiki/"
  551.13 -REPOLOGY="fstobdf"
  551.14 -
  551.15 -TARBALL="fstobdf-$VERSION.tar.bz2"
  551.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  551.17 -
  551.18 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-libX11-dev xorg-libFS-dev"
  551.19 -
  551.20 -compile_rules() {
  551.21 -	./configure $CONFIGURE_ARGS &&
  551.22 -	make &&
  551.23 -	make install
  551.24 -}
  551.25 -
  551.26 -genpkg_rules() {
  551.27 -	copy @std
  551.28 -	DEPENDS="xorg-libFS xorg-libX11"
  551.29 -}
   552.1 --- a/xorg-gccmakedep/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   552.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   552.3 @@ -1,1 +0,0 @@
   552.4 -../xorg/.icon.png
   552.5 \ No newline at end of file
   553.1 --- a/xorg-gccmakedep/receipt	Thu Dec 13 00:46:54 2018 +0200
   553.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   553.3 @@ -1,22 +0,0 @@
   553.4 -# SliTaz package receipt v2.
   553.5 -
   553.6 -PACKAGE="xorg-gccmakedep"
   553.7 -VERSION="1.0.3"
   553.8 -CATEGORY="x-window"
   553.9 -SHORT_DESC="X gccmakedep utility"
  553.10 -MAINTAINER="pascal.bellard@slitaz.org"
  553.11 -LICENSE="MIT"
  553.12 -WEB_SITE="https://www.x.org/wiki/"
  553.13 -HOST_ARCH="any"
  553.14 -REPOLOGY="gccmakedep"
  553.15 -
  553.16 -TARBALL="gccmakedep-$VERSION.tar.bz2"
  553.17 -WGET_URL="$XORG_MIRROR/util/$TARBALL"
  553.18 -
  553.19 -BUILD_DEPENDS="xorg-util-macros"
  553.20 -
  553.21 -compile_rules() {
  553.22 -	./configure $CONFIGURE_ARGS &&
  553.23 -	make &&
  553.24 -	make install
  553.25 -}
   554.1 --- a/xorg-iceauth/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   554.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   554.3 @@ -1,1 +0,0 @@
   554.4 -../xorg/.icon.png
   554.5 \ No newline at end of file
   555.1 --- a/xorg-iceauth/receipt	Thu Dec 13 00:46:54 2018 +0200
   555.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   555.3 @@ -1,28 +0,0 @@
   555.4 -# SliTaz package receipt v2.
   555.5 -
   555.6 -PACKAGE="xorg-iceauth"
   555.7 -VERSION="1.0.8"
   555.8 -CATEGORY="x-window"
   555.9 -SHORT_DESC="ICE authority file utility"
  555.10 -MAINTAINER="devel@slitaz.org"
  555.11 -LICENSE="MIT"
  555.12 -WEB_SITE="https://www.x.org/wiki/"
  555.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  555.14 -REPOLOGY="iceauth"
  555.15 -
  555.16 -TARBALL="iceauth-$VERSION.tar.bz2"
  555.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  555.18 -
  555.19 -BUILD_DEPENDS="xorg-libICE-dev"
  555.20 -
  555.21 -compile_rules() {
  555.22 -	./configure $CONFIGURE_ARGS &&
  555.23 -	fix libtool &&
  555.24 -	make &&
  555.25 -	make install
  555.26 -}
  555.27 -
  555.28 -genpkg_rules() {
  555.29 -	copy @std
  555.30 -	DEPENDS="xorg-libICE"
  555.31 -}
   556.1 --- a/xorg-imake/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   556.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   556.3 @@ -1,1 +0,0 @@
   556.4 -../xorg/.icon.png
   556.5 \ No newline at end of file
   557.1 --- a/xorg-imake/receipt	Thu Dec 13 00:46:54 2018 +0200
   557.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   557.3 @@ -1,26 +0,0 @@
   557.4 -# SliTaz package receipt v2.
   557.5 -
   557.6 -PACKAGE="xorg-imake"
   557.7 -VERSION="1.0.7"
   557.8 -CATEGORY="x-window"
   557.9 -SHORT_DESC="X imake utility"
  557.10 -MAINTAINER="pascal.bellard@slitaz.org"
  557.11 -LICENSE="MIT"
  557.12 -WEB_SITE="https://www.x.org/wiki/"
  557.13 -REPOLOGY="imake"
  557.14 -
  557.15 -TARBALL="imake-$VERSION.tar.bz2"
  557.16 -WGET_URL="$XORG_MIRROR/util/$TARBALL"
  557.17 -
  557.18 -BUILD_DEPENDS="xorg-util-macros perl xorg-xorgproto"
  557.19 -
  557.20 -compile_rules() {
  557.21 -	./configure $CONFIGURE_ARGS &&
  557.22 -	make &&
  557.23 -	make install
  557.24 -}
  557.25 -
  557.26 -genpkg_rules() {
  557.27 -	copy @std
  557.28 -	DEPENDS="xorg-cf-files"
  557.29 -}
   558.1 --- a/xorg-libFS/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   558.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   558.3 @@ -1,1 +0,0 @@
   558.4 -../xorg/.icon.png
   558.5 \ No newline at end of file
   559.1 --- a/xorg-libFS/receipt	Thu Dec 13 00:46:54 2018 +0200
   559.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   559.3 @@ -1,36 +0,0 @@
   559.4 -# SliTaz package receipt v2.
   559.5 -
   559.6 -PACKAGE="xorg-libFS"
   559.7 -VERSION="1.0.7"
   559.8 -CATEGORY="x-window"
   559.9 -SHORT_DESC="X Font Service client library"
  559.10 -MAINTAINER="pascal.bellard@slitaz.org"
  559.11 -LICENSE="MIT"
  559.12 -WEB_SITE="https://www.x.org/wiki/"
  559.13 -LFS="http://www.linuxfromscratch.org/blfs/view/stable/x/x7lib.html"
  559.14 -REPOLOGY="libfs"
  559.15 -
  559.16 -TARBALL="libFS-$VERSION.tar.bz2"
  559.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  559.18 -
  559.19 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-xtrans"
  559.20 -SPLIT="$PACKAGE-dev"
  559.21 -
  559.22 -compile_rules() {
  559.23 -	./configure $CONFIGURE_ARGS &&
  559.24 -	fix libtool &&
  559.25 -	make &&
  559.26 -	make install
  559.27 -}
  559.28 -
  559.29 -genpkg_rules() {
  559.30 -	case $PACKAGE in
  559.31 -		*-libFS)
  559.32 -			copy @std
  559.33 -			;;
  559.34 -		*-dev)
  559.35 -			copy @dev
  559.36 -			DEPENDS="xorg-libFS xorg-xorgproto"
  559.37 -			;;
  559.38 -	esac
  559.39 -}
   560.1 --- a/xorg-libICE/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   560.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   560.3 @@ -1,1 +0,0 @@
   560.4 -../xorg/.icon.png
   560.5 \ No newline at end of file
   561.1 --- a/xorg-libICE/receipt	Thu Dec 13 00:46:54 2018 +0200
   561.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   561.3 @@ -1,38 +0,0 @@
   561.4 -# SliTaz package receipt v2.
   561.5 -
   561.6 -PACKAGE="xorg-libICE"
   561.7 -VERSION="1.0.9"
   561.8 -CATEGORY="x-window"
   561.9 -SHORT_DESC="Inter-Client Exchange library"
  561.10 -MAINTAINER="devel@slitaz.org"
  561.11 -LICENSE="MIT"
  561.12 -WEB_SITE="https://www.x.org/wiki/"
  561.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  561.14 -REPOLOGY="libice"
  561.15 -
  561.16 -TARBALL="libICE-$VERSION.tar.bz2"
  561.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  561.18 -
  561.19 -BUILD_DEPENDS="xorg-xorgproto xorg-xtrans"
  561.20 -SPLIT="$PACKAGE-dev"
  561.21 -
  561.22 -compile_rules() {
  561.23 -	touch /root/missing /missing
  561.24 -
  561.25 -	./configure $CONFIGURE_ARGS &&
  561.26 -	fix libtool &&
  561.27 -	make &&
  561.28 -	make install
  561.29 -}
  561.30 -
  561.31 -genpkg_rules() {
  561.32 -	case $PACKAGE in
  561.33 -		*-libICE)
  561.34 -			copy @std
  561.35 -			;;
  561.36 -		*-dev)
  561.37 -			copy @dev
  561.38 -			DEPENDS="xorg-libICE xorg-xorgproto"
  561.39 -			;;
  561.40 -	esac
  561.41 -}
   562.1 --- a/xorg-libSM/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   562.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   562.3 @@ -1,1 +0,0 @@
   562.4 -../xorg/.icon.png
   562.5 \ No newline at end of file
   563.1 --- a/xorg-libSM/receipt	Thu Dec 13 00:46:54 2018 +0200
   563.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   563.3 @@ -1,38 +0,0 @@
   563.4 -# SliTaz package receipt v2.
   563.5 -
   563.6 -PACKAGE="xorg-libSM"
   563.7 -VERSION="1.2.2"
   563.8 -CATEGORY="x-window"
   563.9 -SHORT_DESC="Session Management library"
  563.10 -MAINTAINER="devel@slitaz.org"
  563.11 -LICENSE="MIT"
  563.12 -WEB_SITE="https://www.x.org/wiki/"
  563.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  563.14 -REPOLOGY="libsm"
  563.15 -
  563.16 -TARBALL="libSM-$VERSION.tar.bz2"
  563.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  563.18 -
  563.19 -BUILD_DEPENDS="xorg-libICE-dev xorg-xtrans util-linux-uuid-dev"
  563.20 -SPLIT="$PACKAGE-dev"
  563.21 -
  563.22 -compile_rules() {
  563.23 -	./configure $CONFIGURE_ARGS &&
  563.24 -	fix libtool &&
  563.25 -	make &&
  563.26 -	make install
  563.27 -}
  563.28 -
  563.29 -genpkg_rules() {
  563.30 -	case $PACKAGE in
  563.31 -		*-libSM)
  563.32 -			copy @std
  563.33 -			DEPENDS="util-linux-uuid xorg-libICE"
  563.34 -			;;
  563.35 -		*-dev)
  563.36 -			copy @dev
  563.37 -			DEPENDS="xorg-libSM \
  563.38 -			xorg-libICE-dev xorg-xorgproto"
  563.39 -			;;
  563.40 -	esac
  563.41 -}
   564.1 --- a/xorg-libX11/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   564.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   564.3 @@ -1,1 +0,0 @@
   564.4 -../xorg/.icon.png
   564.5 \ No newline at end of file
   565.1 --- a/xorg-libX11/receipt	Thu Dec 13 00:46:54 2018 +0200
   565.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   565.3 @@ -1,46 +0,0 @@
   565.4 -# SliTaz package receipt v2.
   565.5 -
   565.6 -PACKAGE="xorg-libX11"
   565.7 -VERSION="1.6.6"
   565.8 -CATEGORY="x-window"
   565.9 -SHORT_DESC="X11 Client library"
  565.10 -MAINTAINER="devel@slitaz.org"
  565.11 -LICENSE="MIT"
  565.12 -WEB_SITE="https://www.x.org/wiki/"
  565.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  565.14 -REPOLOGY="libx11"
  565.15 -
  565.16 -TARBALL="libX11-$VERSION.tar.bz2"
  565.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  565.18 -
  565.19 -BUILD_DEPENDS="xorg-xtrans xorg-libxcb-dev \
  565.20 -xorg-xorgproto xorg-libXau-dev xorg-libXdmcp-dev perl"
  565.21 -SPLIT="$PACKAGE-dev"
  565.22 -
  565.23 -compile_rules() {
  565.24 -	./configure $CONFIGURE_ARGS &&
  565.25 -	fix libtool &&
  565.26 -	make &&
  565.27 -	make install
  565.28 -
  565.29 -	# strip whitespace
  565.30 -	for i in $(find $install -name Compose); do
  565.31 -		sed -i 's|\t| |g; s|  *| |g; /^$/d' $i
  565.32 -	done
  565.33 -}
  565.34 -
  565.35 -genpkg_rules() {
  565.36 -	case $PACKAGE in
  565.37 -		*-libX11)
  565.38 -			copy *.so* XErrorDB Xcms.txt compose.dir locale.alias locale.dir \
  565.39 -			C/ en_US.UTF-8/
  565.40 -			# split -> locale-* packages
  565.41 -			DEPENDS="xorg-libxcb"
  565.42 -			;;
  565.43 -		*-dev)
  565.44 -			copy @dev
  565.45 -			DEPENDS="xorg-libX11 \
  565.46 -			xorg-xorgproto xorg-libxcb-dev"
  565.47 -			;;
  565.48 -	esac
  565.49 -}
   566.1 --- a/xorg-libXScrnSaver/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   566.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   566.3 @@ -1,1 +0,0 @@
   566.4 -../xorg/.icon.png
   566.5 \ No newline at end of file
   567.1 --- a/xorg-libXScrnSaver/receipt	Thu Dec 13 00:46:54 2018 +0200
   567.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   567.3 @@ -1,38 +0,0 @@
   567.4 -# SliTaz package receipt v2.
   567.5 -
   567.6 -PACKAGE="xorg-libXScrnSaver"
   567.7 -VERSION="1.2.3"
   567.8 -CATEGORY="x-window"
   567.9 -SHORT_DESC="MIT-SCREEN-SAVER extension"
  567.10 -MAINTAINER="al.bobylev@gmail.com"
  567.11 -LICENSE="MIT"
  567.12 -WEB_SITE="https://www.x.org/wiki/"
  567.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  567.14 -REPOLOGY="libxscrnsaver"
  567.15 -
  567.16 -TARBALL="libXScrnSaver-$VERSION.tar.bz2"
  567.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  567.18 -
  567.19 -BUILD_DEPENDS="xorg-libXext-dev xorg-xorgproto"
  567.20 -SPLIT="$PACKAGE-dev"
  567.21 -
  567.22 -compile_rules() {
  567.23 -	./configure $CONFIGURE_ARGS &&
  567.24 -	fix libtool &&
  567.25 -	make &&
  567.26 -	make install
  567.27 -}
  567.28 -
  567.29 -genpkg_rules() {
  567.30 -	case $PACKAGE in
  567.31 -		*-libXScrnSaver)
  567.32 -			copy @std
  567.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  567.34 -			;;
  567.35 -		*-dev)
  567.36 -			copy @dev
  567.37 -			DEPENDS="xorg-libXScrnSaver \
  567.38 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  567.39 -			;;
  567.40 -	esac
  567.41 -}
   568.1 --- a/xorg-libXau/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   568.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   568.3 @@ -1,1 +0,0 @@
   568.4 -../xorg/.icon.png
   568.5 \ No newline at end of file
   569.1 --- a/xorg-libXau/receipt	Thu Dec 13 00:46:54 2018 +0200
   569.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   569.3 @@ -1,36 +0,0 @@
   569.4 -# SliTaz package receipt v2.
   569.5 -
   569.6 -PACKAGE="xorg-libXau"
   569.7 -VERSION="1.0.8"
   569.8 -CATEGORY="x-window"
   569.9 -SHORT_DESC="X Authorization routines"
  569.10 -MAINTAINER="devel@slitaz.org"
  569.11 -LICENSE="MIT"
  569.12 -WEB_SITE="https://www.x.org/wiki/"
  569.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libXau.html"
  569.14 -REPOLOGY="libxau"
  569.15 -
  569.16 -TARBALL="libXau-$VERSION.tar.bz2"
  569.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  569.18 -
  569.19 -BUILD_DEPENDS="xorg-xorgproto"
  569.20 -SPLIT="$PACKAGE-dev"
  569.21 -
  569.22 -compile_rules() {
  569.23 -	./configure $CONFIGURE_ARGS &&
  569.24 -	fix libtool &&
  569.25 -	make &&
  569.26 -	make install
  569.27 -}
  569.28 -
  569.29 -genpkg_rules() {
  569.30 -	case $PACKAGE in
  569.31 -		*-libXau)
  569.32 -			copy @std
  569.33 -			;;
  569.34 -		*-dev)
  569.35 -			copy @dev
  569.36 -			DEPENDS="xorg-libXau xorg-xorgproto"
  569.37 -			;;
  569.38 -	esac
  569.39 -}
   570.1 --- a/xorg-libXaw/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   570.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   570.3 @@ -1,1 +0,0 @@
   570.4 -../xorg/.icon.png
   570.5 \ No newline at end of file
   571.1 --- a/xorg-libXaw/receipt	Thu Dec 13 00:46:54 2018 +0200
   571.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   571.3 @@ -1,42 +0,0 @@
   571.4 -# SliTaz package receipt v2.
   571.5 -
   571.6 -PACKAGE="xorg-libXaw"
   571.7 -VERSION="1.0.13"
   571.8 -CATEGORY="x-window"
   571.9 -SHORT_DESC="Athena Widgets toolkit"
  571.10 -MAINTAINER="devel@slitaz.org"
  571.11 -LICENSE="MIT"
  571.12 -WEB_SITE="https://www.x.org/wiki/"
  571.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  571.14 -REPOLOGY="libxaw"
  571.15 -
  571.16 -TARBALL="libXaw-$VERSION.tar.bz2"
  571.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  571.18 -
  571.19 -BUILD_DEPENDS="xorg-libXmu-dev xorg-libXpm-dev util-linux-uuid-dev"
  571.20 -SPLIT="$PACKAGE-dev"
  571.21 -
  571.22 -compile_rules() {
  571.23 -	./configure \
  571.24 -		--disable-xaw6 \
  571.25 -		$CONFIGURE_ARGS &&
  571.26 -	fix libtool &&
  571.27 -	make &&
  571.28 -	make install
  571.29 -}
  571.30 -
  571.31 -genpkg_rules() {
  571.32 -	case $PACKAGE in
  571.33 -		*-libXaw)
  571.34 -			copy @std
  571.35 -			DEPENDS="xorg-libX11 xorg-libXext xorg-libXmu xorg-libXpm \
  571.36 -			xorg-libXt"
  571.37 -			;;
  571.38 -		*-dev)
  571.39 -			copy @dev
  571.40 -			DEPENDS="xorg-libXaw \
  571.41 -			xorg-libX11-dev xorg-libXext-dev xorg-libXmu-dev xorg-libXpm-dev \
  571.42 -			xorg-libXt-dev xorg-xorgproto"
  571.43 -			;;
  571.44 -	esac
  571.45 -}
   572.1 --- a/xorg-libXaw3d/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   572.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   572.3 @@ -1,1 +0,0 @@
   572.4 -../xorg/.icon.png
   572.5 \ No newline at end of file
   573.1 --- a/xorg-libXaw3d/receipt	Thu Dec 13 00:46:54 2018 +0200
   573.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   573.3 @@ -1,37 +0,0 @@
   573.4 -# SliTaz package receipt v2.
   573.5 -
   573.6 -PACKAGE="xorg-libXaw3d"
   573.7 -VERSION="1.6.2"
   573.8 -CATEGORY="x-window"
   573.9 -SHORT_DESC="Xorg server module"
  573.10 -MAINTAINER="pascal.bellard@slitaz.org"
  573.11 -LICENSE="MIT"
  573.12 -WEB_SITE="https://www.x.org/wiki/"
  573.13 -
  573.14 -TARBALL="libXaw3d-$VERSION.tar.bz2"
  573.15 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  573.16 -
  573.17 -BUILD_DEPENDS="xorg-libXmu-dev util-linux-uuid-dev"
  573.18 -SPLIT="$PACKAGE-dev"
  573.19 -
  573.20 -compile_rules() {
  573.21 -	./configure $CONFIGURE_ARGS &&
  573.22 -	fix libtool &&
  573.23 -	make &&
  573.24 -	make install
  573.25 -}
  573.26 -
  573.27 -genpkg_rules() {
  573.28 -	case $PACKAGE in
  573.29 -		*-libXaw3d)
  573.30 -			copy @std
  573.31 -			DEPENDS="xorg-libX11 xorg-libXext xorg-libXmu xorg-libXt"
  573.32 -			;;
  573.33 -		*-dev)
  573.34 -			copy @dev
  573.35 -			DEPENDS="xorg-libXaw3d \
  573.36 -			xorg-libX11-dev xorg-libXext-dev xorg-libXmu-dev xorg-libXt-dev \
  573.37 -			xorg-xorgproto"
  573.38 -			;;
  573.39 -	esac
  573.40 -}
   574.1 --- a/xorg-libXcomposite/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   574.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   574.3 @@ -1,1 +0,0 @@
   574.4 -../xorg/.icon.png
   574.5 \ No newline at end of file
   575.1 --- a/xorg-libXcomposite/receipt	Thu Dec 13 00:46:54 2018 +0200
   575.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   575.3 @@ -1,38 +0,0 @@
   575.4 -# SliTaz package receipt v2.
   575.5 -
   575.6 -PACKAGE="xorg-libXcomposite"
   575.7 -VERSION="0.4.4"
   575.8 -CATEGORY="x-window"
   575.9 -SHORT_DESC="Composite Extension"
  575.10 -MAINTAINER="devel@slitaz.org"
  575.11 -LICENSE="MIT"
  575.12 -WEB_SITE="https://www.x.org/wiki/"
  575.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  575.14 -REPOLOGY="libxcomposite"
  575.15 -
  575.16 -TARBALL="libXcomposite-$VERSION.tar.bz2"
  575.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  575.18 -
  575.19 -BUILD_DEPENDS="xorg-xorgproto xorg-libXfixes-dev"
  575.20 -SPLIT="$PACKAGE-dev"
  575.21 -
  575.22 -compile_rules() {
  575.23 -	./configure $CONFIGURE_ARGS &&
  575.24 -	fix libtool &&
  575.25 -	make &&
  575.26 -	make install
  575.27 -}
  575.28 -
  575.29 -genpkg_rules() {
  575.30 -	case $PACKAGE in
  575.31 -		*-libXcomposite)
  575.32 -			copy @std
  575.33 -			DEPENDS="xorg-libX11"
  575.34 -			;;
  575.35 -		*-dev)
  575.36 -			copy @dev
  575.37 -			DEPENDS="xorg-libXcomposite \
  575.38 -			xorg-xorgproto xorg-libX11-dev xorg-libXfixes-dev"
  575.39 -			;;
  575.40 -	esac
  575.41 -}
   576.1 --- a/xorg-libXcursor/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   576.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   576.3 @@ -1,1 +0,0 @@
   576.4 -../xorg/.icon.png
   576.5 \ No newline at end of file
   577.1 --- a/xorg-libXcursor/receipt	Thu Dec 13 00:46:54 2018 +0200
   577.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   577.3 @@ -1,38 +0,0 @@
   577.4 -# SliTaz package receipt v2.
   577.5 -
   577.6 -PACKAGE="xorg-libXcursor"
   577.7 -VERSION="1.1.15"
   577.8 -CATEGORY="x-window"
   577.9 -SHORT_DESC="Cursor extension"
  577.10 -MAINTAINER="devel@slitaz.org"
  577.11 -LICENSE="MIT"
  577.12 -WEB_SITE="https://www.x.org/wiki/"
  577.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  577.14 -REPOLOGY="libxcursor"
  577.15 -
  577.16 -TARBALL="libXcursor-$VERSION.tar.bz2"
  577.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  577.18 -
  577.19 -BUILD_DEPENDS="xorg-libXrender-dev xorg-libXfixes-dev"
  577.20 -SPLIT="$PACKAGE-dev"
  577.21 -
  577.22 -compile_rules() {
  577.23 -	./configure $CONFIGURE_ARGS &&
  577.24 -	fix libtool &&
  577.25 -	make &&
  577.26 -	make install
  577.27 -}
  577.28 -
  577.29 -genpkg_rules() {
  577.30 -	case $PACKAGE in
  577.31 -		*-libXcursor)
  577.32 -			copy @std
  577.33 -			DEPENDS="xorg-libX11 xorg-libXfixes xorg-libXrender"
  577.34 -			;;
  577.35 -		*-dev)
  577.36 -			copy @dev
  577.37 -			DEPENDS="xorg-libXcursor \
  577.38 -			xorg-libX11-dev xorg-libXfixes-dev xorg-libXrender-dev xorg-xorgproto"
  577.39 -			;;
  577.40 -	esac
  577.41 -}
   578.1 --- a/xorg-libXdamage/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   578.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   578.3 @@ -1,1 +0,0 @@
   578.4 -../xorg/.icon.png
   578.5 \ No newline at end of file
   579.1 --- a/xorg-libXdamage/receipt	Thu Dec 13 00:46:54 2018 +0200
   579.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   579.3 @@ -1,38 +0,0 @@
   579.4 -# SliTaz package receipt v2.
   579.5 -
   579.6 -PACKAGE="xorg-libXdamage"
   579.7 -VERSION="1.1.4"
   579.8 -CATEGORY="x-window"
   579.9 -SHORT_DESC="Damage extension"
  579.10 -MAINTAINER="devel@slitaz.org"
  579.11 -LICENSE="MIT"
  579.12 -WEB_SITE="https://www.x.org/wiki/"
  579.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  579.14 -REPOLOGY="libxdamage"
  579.15 -
  579.16 -TARBALL="libXdamage-$VERSION.tar.bz2"
  579.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  579.18 -
  579.19 -BUILD_DEPENDS="xorg-xorgproto xorg-libXfixes-dev"
  579.20 -SPLIT="$PACKAGE-dev"
  579.21 -
  579.22 -compile_rules() {
  579.23 -	./configure $CONFIGURE_ARGS &&
  579.24 -	fix libtool &&
  579.25 -	make &&
  579.26 -	make install
  579.27 -}
  579.28 -
  579.29 -genpkg_rules() {
  579.30 -	case $PACKAGE in
  579.31 -		*-libXdamage)
  579.32 -			copy @std
  579.33 -			DEPENDS="xorg-libX11"
  579.34 -			;;
  579.35 -		*-dev)
  579.36 -			copy @dev
  579.37 -			DEPENDS="xorg-libXdamage \
  579.38 -			xorg-xorgproto xorg-libX11-dev xorg-libXfixes-dev"
  579.39 -			;;
  579.40 -	esac
  579.41 -}
   580.1 --- a/xorg-libXdmcp/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   580.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   580.3 @@ -1,1 +0,0 @@
   580.4 -../xorg/.icon.png
   580.5 \ No newline at end of file
   581.1 --- a/xorg-libXdmcp/receipt	Thu Dec 13 00:46:54 2018 +0200
   581.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   581.3 @@ -1,36 +0,0 @@
   581.4 -# SliTaz package receipt v2.
   581.5 -
   581.6 -PACKAGE="xorg-libXdmcp"
   581.7 -VERSION="1.1.2"
   581.8 -CATEGORY="x-window"
   581.9 -SHORT_DESC="X Display Manager Control Protocol routines"
  581.10 -MAINTAINER="devel@slitaz.org"
  581.11 -LICENSE="MIT"
  581.12 -WEB_SITE="https://www.x.org/wiki/"
  581.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libXdmcp.html"
  581.14 -REPOLOGY="libxdmcp"
  581.15 -
  581.16 -TARBALL="libXdmcp-$VERSION.tar.bz2"
  581.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  581.18 -
  581.19 -BUILD_DEPENDS="xorg-xorgproto"
  581.20 -SPLIT="$PACKAGE-dev"
  581.21 -
  581.22 -compile_rules() {
  581.23 -	./configure $CONFIGURE_ARGS &&
  581.24 -	fix libtool &&
  581.25 -	make &&
  581.26 -	make install
  581.27 -}
  581.28 -
  581.29 -genpkg_rules() {
  581.30 -	case $PACKAGE in
  581.31 -		*-libXdmcp)
  581.32 -			copy @std
  581.33 -			;;
  581.34 -		*-dev)
  581.35 -			copy @dev
  581.36 -			DEPENDS="xorg-libXdmcp xorg-xorgproto"
  581.37 -			;;
  581.38 -	esac
  581.39 -}
   582.1 --- a/xorg-libXext/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   582.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   582.3 @@ -1,1 +0,0 @@
   582.4 -../xorg/.icon.png
   582.5 \ No newline at end of file
   583.1 --- a/xorg-libXext/receipt	Thu Dec 13 00:46:54 2018 +0200
   583.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   583.3 @@ -1,38 +0,0 @@
   583.4 -# SliTaz package receipt v2.
   583.5 -
   583.6 -PACKAGE="xorg-libXext"
   583.7 -VERSION="1.3.3"
   583.8 -CATEGORY="x-window"
   583.9 -SHORT_DESC="Common X Extensions library"
  583.10 -MAINTAINER="devel@slitaz.org"
  583.11 -LICENSE="MIT"
  583.12 -WEB_SITE="https://www.x.org/wiki/"
  583.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  583.14 -REPOLOGY="libxext"
  583.15 -
  583.16 -TARBALL="libXext-$VERSION.tar.bz2"
  583.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  583.18 -
  583.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-xorgproto"
  583.20 -SPLIT="$PACKAGE-dev"
  583.21 -
  583.22 -compile_rules() {
  583.23 -	./configure $CONFIGURE_ARGS &&
  583.24 -	fix libtool &&
  583.25 -	make &&
  583.26 -	make install
  583.27 -}
  583.28 -
  583.29 -genpkg_rules() {
  583.30 -	case $PACKAGE in
  583.31 -		*-libXext)
  583.32 -			copy @std
  583.33 -			DEPENDS="xorg-libX11"
  583.34 -			;;
  583.35 -		*-dev)
  583.36 -			copy @dev
  583.37 -			DEPENDS="xorg-libXext \
  583.38 -			xorg-libX11-dev xorg-xorgproto"
  583.39 -			;;
  583.40 -	esac
  583.41 -}
   584.1 --- a/xorg-libXfixes/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   584.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   584.3 @@ -1,1 +0,0 @@
   584.4 -../xorg/.icon.png
   584.5 \ No newline at end of file
   585.1 --- a/xorg-libXfixes/receipt	Thu Dec 13 00:46:54 2018 +0200
   585.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   585.3 @@ -1,38 +0,0 @@
   585.4 -# SliTaz package receipt v2.
   585.5 -
   585.6 -PACKAGE="xorg-libXfixes"
   585.7 -VERSION="5.0.3"
   585.8 -CATEGORY="x-window"
   585.9 -SHORT_DESC="X-Fixes extension"
  585.10 -MAINTAINER="devel@slitaz.org"
  585.11 -LICENSE="MIT"
  585.12 -WEB_SITE="https://www.x.org/wiki/"
  585.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  585.14 -REPOLOGY="libxfixes"
  585.15 -
  585.16 -TARBALL="libXfixes-$VERSION.tar.bz2"
  585.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  585.18 -
  585.19 -BUILD_DEPENDS="xorg-xorgproto xorg-libX11-dev"
  585.20 -SPLIT="$PACKAGE-dev"
  585.21 -
  585.22 -compile_rules() {
  585.23 -	./configure $CONFIGURE_ARGS &&
  585.24 -	fix libtool &&
  585.25 -	make &&
  585.26 -	make install
  585.27 -}
  585.28 -
  585.29 -genpkg_rules() {
  585.30 -	case $PACKAGE in
  585.31 -		*-libXfixes)
  585.32 -			copy @std
  585.33 -			DEPENDS="xorg-libX11"
  585.34 -			;;
  585.35 -		*-dev)
  585.36 -			copy @dev
  585.37 -			DEPENDS="xorg-libXfixes \
  585.38 -			xorg-xorgproto xorg-libX11-dev"
  585.39 -			;;
  585.40 -	esac
  585.41 -}
   586.1 --- a/xorg-libXfont/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   586.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   586.3 @@ -1,1 +0,0 @@
   586.4 -../xorg/.icon.png
   586.5 \ No newline at end of file
   587.1 --- a/xorg-libXfont/receipt	Thu Dec 13 00:46:54 2018 +0200
   587.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   587.3 @@ -1,38 +0,0 @@
   587.4 -# SliTaz package receipt v2.
   587.5 -
   587.6 -PACKAGE="xorg-libXfont"
   587.7 -VERSION="1.5.4"
   587.8 -CATEGORY="x-window"
   587.9 -SHORT_DESC="X font handling library for server & utilities"
  587.10 -MAINTAINER="devel@slitaz.org"
  587.11 -LICENSE="MIT"
  587.12 -WEB_SITE="https://www.x.org/wiki/"
  587.13 -REPOLOGY="libxfont"
  587.14 -
  587.15 -TARBALL="libXfont-$VERSION.tar.bz2"
  587.16 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  587.17 -
  587.18 -BUILD_DEPENDS="bzip2-dev freetype-dev zlib-dev xorg-xtrans xorg-xorgproto \
  587.19 -xorg-libfontenc-dev"
  587.20 -SPLIT="$PACKAGE-dev"
  587.21 -
  587.22 -compile_rules() {
  587.23 -	./configure $CONFIGURE_ARGS &&
  587.24 -	fix libtool &&
  587.25 -	make &&
  587.26 -	make install
  587.27 -}
  587.28 -
  587.29 -genpkg_rules() {
  587.30 -	case $PACKAGE in
  587.31 -		*-libXfont)
  587.32 -			copy @std
  587.33 -			DEPENDS="freetype xorg-libfontenc zlib"
  587.34 -			;;
  587.35 -		*-dev)
  587.36 -			copy @dev
  587.37 -			DEPENDS="xorg-libXfont freetype-dev xorg-xorgproto \
  587.38 -			xorg-libfontenc-dev zlib-dev"
  587.39 -			;;
  587.40 -	esac
  587.41 -}
   588.1 --- a/xorg-libXfont2/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   588.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   588.3 @@ -1,1 +0,0 @@
   588.4 -../xorg/.icon.png
   588.5 \ No newline at end of file
   589.1 --- a/xorg-libXfont2/receipt	Thu Dec 13 00:46:54 2018 +0200
   589.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   589.3 @@ -1,40 +0,0 @@
   589.4 -# SliTaz package receipt v2.
   589.5 -
   589.6 -PACKAGE="xorg-libXfont2"
   589.7 -VERSION="2.0.3"
   589.8 -CATEGORY="x-window"
   589.9 -SHORT_DESC="X font2 handling library for server & utilities"
  589.10 -MAINTAINER="al.bobylev@gmail.com"
  589.11 -LICENSE="MIT"
  589.12 -WEB_SITE="https://www.x.org/wiki/"
  589.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  589.14 -REPOLOGY="libxfont2"
  589.15 -
  589.16 -TARBALL="libXfont2-$VERSION.tar.bz2"
  589.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  589.18 -
  589.19 -BUILD_DEPENDS="xorg-util-macros freetype-dev xorg-xtrans \
  589.20 -xorg-xorgproto xorg-libfontenc-dev"
  589.21 -SPLIT="$PACKAGE-dev"
  589.22 -
  589.23 -compile_rules() {
  589.24 -	./configure $CONFIGURE_ARGS &&
  589.25 -	fix libtool &&
  589.26 -	make &&
  589.27 -	make install
  589.28 -}
  589.29 -
  589.30 -genpkg_rules() {
  589.31 -	case $PACKAGE in
  589.32 -		*-libXfont2)
  589.33 -			copy @std
  589.34 -			DEPENDS="freetype xorg-libfontenc zlib"
  589.35 -			;;
  589.36 -		*-dev)
  589.37 -			copy @dev
  589.38 -			DEPENDS="xorg-libXfont2 \
  589.39 -			freetype-dev xorg-xorgproto xorg-libfontenc-dev \
  589.40 -			zlib-dev"
  589.41 -			;;
  589.42 -	esac
  589.43 -}
   590.1 --- a/xorg-libXfontcache/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   590.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   590.3 @@ -1,1 +0,0 @@
   590.4 -../xorg/.icon.png
   590.5 \ No newline at end of file
   591.1 --- a/xorg-libXfontcache/receipt	Thu Dec 13 00:46:54 2018 +0200
   591.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   591.3 @@ -1,37 +0,0 @@
   591.4 -# SliTaz package receipt v2.
   591.5 -
   591.6 -PACKAGE="xorg-libXfontcache"
   591.7 -VERSION="1.0.5"
   591.8 -CATEGORY="x-window"
   591.9 -SHORT_DESC="X-TrueType font cache extension client library"
  591.10 -MAINTAINER="al.bobylev@gmail.com"
  591.11 -LICENSE="MIT"
  591.12 -WEB_SITE="https://www.x.org/wiki/"
  591.13 -REPOLOGY="libxfontcache"
  591.14 -
  591.15 -TARBALL="libXfontcache-$VERSION.tar.bz2"
  591.16 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  591.17 -
  591.18 -BUILD_DEPENDS="gfortran xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  591.19 -SPLIT="$PACKAGE-dev"
  591.20 -
  591.21 -compile_rules() {
  591.22 -	./configure $CONFIGURE_ARGS &&
  591.23 -	fix libtool &&
  591.24 -	make &&
  591.25 -	make install
  591.26 -}
  591.27 -
  591.28 -genpkg_rules() {
  591.29 -	case $PACKAGE in
  591.30 -		*-libXfontcache)
  591.31 -			copy @std
  591.32 -			DEPENDS="xorg-libX11 xorg-libXext"
  591.33 -			;;
  591.34 -		*-dev)
  591.35 -			copy @dev
  591.36 -			DEPENDS="xorg-libXfontcache \
  591.37 -			xorg-xorgproto xorg-libX11-dev xorg-libXext-dev"
  591.38 -			;;
  591.39 -	esac
  591.40 -}
   592.1 --- a/xorg-libXft/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   592.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   592.3 @@ -1,1 +0,0 @@
   592.4 -../xorg/.icon.png
   592.5 \ No newline at end of file
   593.1 --- a/xorg-libXft/receipt	Thu Dec 13 00:46:54 2018 +0200
   593.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   593.3 @@ -1,38 +0,0 @@
   593.4 -# SliTaz package receipt v2.
   593.5 -
   593.6 -PACKAGE="xorg-libXft"
   593.7 -VERSION="2.3.2"
   593.8 -CATEGORY="x-window"
   593.9 -SHORT_DESC="Client side font rendering library"
  593.10 -MAINTAINER="devel@slitaz.org"
  593.11 -LICENSE="MIT"
  593.12 -WEB_SITE="https://www.x.org/wiki/"
  593.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  593.14 -REPOLOGY="libxft"
  593.15 -
  593.16 -TARBALL="libXft-$VERSION.tar.bz2"
  593.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  593.18 -
  593.19 -BUILD_DEPENDS="xorg-libXrender-dev freetype-dev fontconfig-dev libxml2-dev"
  593.20 -SPLIT="$PACKAGE-dev"
  593.21 -
  593.22 -compile_rules() {
  593.23 -	./configure $CONFIGURE_ARGS &&
  593.24 -	fix libtool &&
  593.25 -	make &&
  593.26 -	make install
  593.27 -}
  593.28 -
  593.29 -genpkg_rules() {
  593.30 -	case $PACKAGE in
  593.31 -		*-libXft)
  593.32 -			copy @std
  593.33 -			DEPENDS="fontconfig freetype xorg-libX11 xorg-libXrender"
  593.34 -			;;
  593.35 -		*-dev)
  593.36 -			copy @dev
  593.37 -			DEPENDS="xorg-libXft \
  593.38 -			fontconfig-dev freetype-dev xorg-libXrender-dev xorg-xorgproto"
  593.39 -			;;
  593.40 -	esac
  593.41 -}
   594.1 --- a/xorg-libXi/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   594.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   594.3 @@ -1,1 +0,0 @@
   594.4 -../xorg/.icon.png
   594.5 \ No newline at end of file
   595.1 --- a/xorg-libXi/receipt	Thu Dec 13 00:46:54 2018 +0200
   595.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   595.3 @@ -1,38 +0,0 @@
   595.4 -# SliTaz package receipt v2.
   595.5 -
   595.6 -PACKAGE="xorg-libXi"
   595.7 -VERSION="1.7.9"
   595.8 -CATEGORY="x-window"
   595.9 -SHORT_DESC="X Input Extension library"
  595.10 -MAINTAINER="devel@slitaz.org"
  595.11 -LICENSE="MIT"
  595.12 -WEB_SITE="https://www.x.org/wiki/"
  595.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  595.14 -REPOLOGY="libxi"
  595.15 -
  595.16 -TARBALL="libXi-$VERSION.tar.bz2"
  595.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  595.18 -
  595.19 -BUILD_DEPENDS="xorg-libXext-dev xorg-libXfixes-dev xorg-xorgproto"
  595.20 -SPLIT="$PACKAGE-dev"
  595.21 -
  595.22 -compile_rules() {
  595.23 -	./configure $CONFIGURE_ARGS &&
  595.24 -	fix libtool &&
  595.25 -	make &&
  595.26 -	make install
  595.27 -}
  595.28 -
  595.29 -genpkg_rules() {
  595.30 -	case $PACKAGE in
  595.31 -		*-libXi)
  595.32 -			copy @std
  595.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  595.34 -			;;
  595.35 -		*-dev)
  595.36 -			copy @dev
  595.37 -			DEPENDS="xorg-libXi \
  595.38 -			xorg-xorgproto xorg-libX11-dev xorg-libXext-dev xorg-libXfixes-dev"
  595.39 -			;;
  595.40 -	esac
  595.41 -}
   596.1 --- a/xorg-libXinerama/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   596.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   596.3 @@ -1,1 +0,0 @@
   596.4 -../xorg/.icon.png
   596.5 \ No newline at end of file
   597.1 --- a/xorg-libXinerama/receipt	Thu Dec 13 00:46:54 2018 +0200
   597.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   597.3 @@ -1,38 +0,0 @@
   597.4 -# SliTaz package receipt v2.
   597.5 -
   597.6 -PACKAGE="xorg-libXinerama"
   597.7 -VERSION="1.1.4"
   597.8 -CATEGORY="x-window"
   597.9 -SHORT_DESC="Xinerama protocol library"
  597.10 -MAINTAINER="devel@slitaz.org"
  597.11 -LICENSE="MIT"
  597.12 -WEB_SITE="https://www.x.org/wiki/"
  597.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  597.14 -REPOLOGY="libxinerama"
  597.15 -
  597.16 -TARBALL="libXinerama-$VERSION.tar.bz2"
  597.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  597.18 -
  597.19 -BUILD_DEPENDS="xorg-libXext-dev xorg-xorgproto"
  597.20 -SPLIT="$PACKAGE-dev"
  597.21 -
  597.22 -compile_rules() {
  597.23 -	./configure $CONFIGURE_ARGS &&
  597.24 -	fix libtool &&
  597.25 -	make &&
  597.26 -	make install
  597.27 -}
  597.28 -
  597.29 -genpkg_rules() {
  597.30 -	case $PACKAGE in
  597.31 -		*-libXinerama)
  597.32 -			copy @std
  597.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  597.34 -			;;
  597.35 -		*-dev)
  597.36 -			copy @dev
  597.37 -			DEPENDS="xorg-libXinerama \
  597.38 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  597.39 -			;;
  597.40 -	esac
  597.41 -}
   598.1 --- a/xorg-libXmu/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   598.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   598.3 @@ -1,1 +0,0 @@
   598.4 -../xorg/.icon.png
   598.5 \ No newline at end of file
   599.1 --- a/xorg-libXmu/receipt	Thu Dec 13 00:46:54 2018 +0200
   599.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   599.3 @@ -1,38 +0,0 @@
   599.4 -# SliTaz package receipt v2.
   599.5 -
   599.6 -PACKAGE="xorg-libXmu"
   599.7 -VERSION="1.1.2"
   599.8 -CATEGORY="x-window"
   599.9 -SHORT_DESC="X miscellaneous utility routines"
  599.10 -MAINTAINER="devel@slitaz.org"
  599.11 -LICENSE="MIT"
  599.12 -WEB_SITE="https://www.x.org/wiki/"
  599.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  599.14 -REPOLOGY="libxmu"
  599.15 -
  599.16 -TARBALL="libXmu-$VERSION.tar.bz2"
  599.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  599.18 -
  599.19 -BUILD_DEPENDS="xorg-libXext-dev xorg-libXt-dev util-linux-uuid-dev"
  599.20 -SPLIT="$PACKAGE-dev"
  599.21 -
  599.22 -compile_rules() {
  599.23 -	./configure $CONFIGURE_ARGS &&
  599.24 -	fix libtool &&
  599.25 -	make &&
  599.26 -	make install
  599.27 -}
  599.28 -
  599.29 -genpkg_rules() {
  599.30 -	case $PACKAGE in
  599.31 -		*-libXmu)
  599.32 -			copy @std
  599.33 -			DEPENDS="xorg-libX11 xorg-libXext xorg-libXt"
  599.34 -			;;
  599.35 -		*-dev)
  599.36 -			copy @dev
  599.37 -			DEPENDS="xorg-libXmu \
  599.38 -			xorg-libX11-dev xorg-libXext-dev xorg-libXt-dev xorg-xorgproto"
  599.39 -			;;
  599.40 -	esac
  599.41 -}
   600.1 --- a/xorg-libXp/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   600.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   600.3 @@ -1,1 +0,0 @@
   600.4 -../xorg/.icon.png
   600.5 \ No newline at end of file
   601.1 --- a/xorg-libXp/receipt	Thu Dec 13 00:46:54 2018 +0200
   601.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   601.3 @@ -1,39 +0,0 @@
   601.4 -# SliTaz package receipt v2.
   601.5 -
   601.6 -PACKAGE="xorg-libXp"
   601.7 -VERSION="1.0.3"
   601.8 -CATEGORY="development"
   601.9 -SHORT_DESC="Allow client applications to render to non-display devices"
  601.10 -MAINTAINER="devel@slitaz.org"
  601.11 -LICENSE="MIT"
  601.12 -WEB_SITE="https://www.x.org/wiki/"
  601.13 -REPOLOGY="libxp"
  601.14 -
  601.15 -TARBALL="libXp-$VERSION.tar.bz2"
  601.16 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  601.17 -
  601.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXext-dev \
  601.19 -xorg-libXau-dev xorg-xorgproto"
  601.20 -SPLIT="$PACKAGE-dev"
  601.21 -
  601.22 -compile_rules() {
  601.23 -	./configure $CONFIGURE_ARGS &&
  601.24 -	fix libtool &&
  601.25 -	make &&
  601.26 -	make install
  601.27 -}
  601.28 -
  601.29 -genpkg_rules() {
  601.30 -	case $PACKAGE in
  601.31 -		*-libXp)
  601.32 -			copy @std
  601.33 -			DEPENDS="xorg-libxcb xorg-libX11 xorg-libXau xorg-libXdmcp \
  601.34 -			xorg-libXext"
  601.35 -			;;
  601.36 -		*-dev)
  601.37 -			copy @dev
  601.38 -			DEPENDS="xorg-libXp xorg-libxcb-dev xorg-libX11-dev \
  601.39 -			xorg-libXau-dev xorg-libXdmcp-dev xorg-libXext-dev xorg-xorgproto"
  601.40 -			;;
  601.41 -	esac
  601.42 -}
   602.1 --- a/xorg-libXpm/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   602.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   602.3 @@ -1,1 +0,0 @@
   602.4 -../xorg/.icon.png
   602.5 \ No newline at end of file
   603.1 --- a/xorg-libXpm/receipt	Thu Dec 13 00:46:54 2018 +0200
   603.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   603.3 @@ -1,44 +0,0 @@
   603.4 -# SliTaz package receipt v2.
   603.5 -
   603.6 -PACKAGE="xorg-libXpm"
   603.7 -VERSION="3.5.12"
   603.8 -CATEGORY="x-window"
   603.9 -SHORT_DESC="XPM format pixmap library"
  603.10 -MAINTAINER="devel@slitaz.org"
  603.11 -LICENSE="MIT"
  603.12 -WEB_SITE="https://www.x.org/wiki/"
  603.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  603.14 -REPOLOGY="libxpm"
  603.15 -
  603.16 -TARBALL="libXpm-$VERSION.tar.bz2"
  603.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  603.18 -
  603.19 -BUILD_DEPENDS="xorg-libXt-dev xorg-libXext-dev xorg-libSM-dev \
  603.20 -util-linux-uuid-dev gettext-dev"
  603.21 -SPLIT="$PACKAGE-util $PACKAGE-dev"
  603.22 -
  603.23 -compile_rules() {
  603.24 -	./configure $CONFIGURE_ARGS &&
  603.25 -	fix libtool &&
  603.26 -	make &&
  603.27 -	make install
  603.28 -}
  603.29 -
  603.30 -genpkg_rules() {
  603.31 -	case $PACKAGE in
  603.32 -		*-libXpm)
  603.33 -			copy *.so*
  603.34 -			DEPENDS="xorg-libX11"
  603.35 -			;;
  603.36 -		*-util)
  603.37 -			copy bin/
  603.38 -			CAT="x-window|utilities"
  603.39 -			DEPENDS="xorg-libX11 xorg-libXext xorg-libXpm xorg-libXt"
  603.40 -			;;
  603.41 -		*-dev)
  603.42 -			copy @dev
  603.43 -			DEPENDS="xorg-libXpm xorg-libXpm-util \
  603.44 -			xorg-libX11-dev"
  603.45 -			;;
  603.46 -	esac
  603.47 -}
   604.1 --- a/xorg-libXrandr/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   604.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   604.3 @@ -1,1 +0,0 @@
   604.4 -../xorg/.icon.png
   604.5 \ No newline at end of file
   605.1 --- a/xorg-libXrandr/receipt	Thu Dec 13 00:46:54 2018 +0200
   605.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   605.3 @@ -1,39 +0,0 @@
   605.4 -# SliTaz package receipt v2.
   605.5 -
   605.6 -PACKAGE="xorg-libXrandr"
   605.7 -VERSION="1.5.1"
   605.8 -CATEGORY="x-window"
   605.9 -SHORT_DESC="Xrandr extension library"
  605.10 -MAINTAINER="devel@slitaz.org"
  605.11 -LICENSE="MIT"
  605.12 -WEB_SITE="https://www.x.org/wiki/libraries/libxrandr/"
  605.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  605.14 -REPOLOGY="libxrandr"
  605.15 -
  605.16 -TARBALL="libXrandr-$VERSION.tar.bz2"
  605.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  605.18 -
  605.19 -BUILD_DEPENDS="xorg-xorgproto xorg-libXext-dev xorg-libXrender-dev"
  605.20 -SPLIT="$PACKAGE-dev"
  605.21 -
  605.22 -compile_rules() {
  605.23 -	./configure $CONFIGURE_ARGS &&
  605.24 -	fix libtool &&
  605.25 -	make &&
  605.26 -	make install
  605.27 -}
  605.28 -
  605.29 -genpkg_rules() {
  605.30 -	case $PACKAGE in
  605.31 -		*-libXrandr)
  605.32 -			copy @std
  605.33 -			DEPENDS="xorg-libX11 xorg-libXext xorg-libXrender"
  605.34 -			;;
  605.35 -		*-dev)
  605.36 -			copy @dev
  605.37 -			DEPENDS="xorg-libXrandr \
  605.38 -			xorg-libX11-dev xorg-libXext-dev xorg-libXrender-dev \
  605.39 -			xorg-xorgproto"
  605.40 -			;;
  605.41 -	esac
  605.42 -}
   606.1 --- a/xorg-libXrender/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   606.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   606.3 @@ -1,1 +0,0 @@
   606.4 -../xorg/.icon.png
   606.5 \ No newline at end of file
   607.1 --- a/xorg-libXrender/receipt	Thu Dec 13 00:46:54 2018 +0200
   607.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   607.3 @@ -1,38 +0,0 @@
   607.4 -# SliTaz package receipt v2.
   607.5 -
   607.6 -PACKAGE="xorg-libXrender"
   607.7 -VERSION="0.9.10"
   607.8 -CATEGORY="x-window"
   607.9 -SHORT_DESC="RENDER extension library"
  607.10 -MAINTAINER="devel@slitaz.org"
  607.11 -LICENSE="MIT"
  607.12 -WEB_SITE="https://www.x.org/wiki/"
  607.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  607.14 -REPOLOGY="libxrender"
  607.15 -
  607.16 -TARBALL="libXrender-$VERSION.tar.bz2"
  607.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  607.18 -
  607.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-xorgproto"
  607.20 -SPLIT="$PACKAGE-dev"
  607.21 -
  607.22 -compile_rules() {
  607.23 -	./configure $CONFIGURE_ARGS &&
  607.24 -	fix libtool &&
  607.25 -	make &&
  607.26 -	make install
  607.27 -}
  607.28 -
  607.29 -genpkg_rules() {
  607.30 -	case $PACKAGE in
  607.31 -		*-libXrender)
  607.32 -			copy @std
  607.33 -			DEPENDS="xorg-libX11"
  607.34 -			;;
  607.35 -		*-dev)
  607.36 -			copy @dev
  607.37 -			DEPENDS="xorg-libXrender \
  607.38 -			xorg-libX11-dev xorg-xorgproto"
  607.39 -			;;
  607.40 -	esac
  607.41 -}
   608.1 --- a/xorg-libXres/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   608.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   608.3 @@ -1,1 +0,0 @@
   608.4 -../xorg/.icon.png
   608.5 \ No newline at end of file
   609.1 --- a/xorg-libXres/receipt	Thu Dec 13 00:46:54 2018 +0200
   609.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   609.3 @@ -1,39 +0,0 @@
   609.4 -# SliTaz package receipt v2.
   609.5 -
   609.6 -PACKAGE="xorg-libXres"
   609.7 -VERSION="1.2.0"
   609.8 -CATEGORY="x-window"
   609.9 -SHORT_DESC="X Resource extension"
  609.10 -MAINTAINER="pascal.bellard@slitaz.org"
  609.11 -LICENSE="MIT"
  609.12 -WEB_SITE="https://www.x.org/wiki/"
  609.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  609.14 -REPOLOGY="libxres"
  609.15 -
  609.16 -TARBALL="libXres-$VERSION.tar.bz2"
  609.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  609.18 -
  609.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXext-dev \
  609.20 -xorg-xorgproto"
  609.21 -SPLIT="$PACKAGE-dev"
  609.22 -
  609.23 -compile_rules() {
  609.24 -	./configure $CONFIGURE_ARGS &&
  609.25 -	fix libtool &&
  609.26 -	make &&
  609.27 -	make install
  609.28 -}
  609.29 -
  609.30 -genpkg_rules() {
  609.31 -	case $PACKAGE in
  609.32 -		*-libXres)
  609.33 -			copy @std
  609.34 -			DEPENDS="xorg-libX11 xorg-libXext"
  609.35 -			;;
  609.36 -		*-dev)
  609.37 -			copy @dev
  609.38 -			DEPENDS="xorg-libXres \
  609.39 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  609.40 -			;;
  609.41 -	esac
  609.42 -}
   610.1 --- a/xorg-libXt/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   610.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   610.3 @@ -1,1 +0,0 @@
   610.4 -../xorg/.icon.png
   610.5 \ No newline at end of file
   611.1 --- a/xorg-libXt/receipt	Thu Dec 13 00:46:54 2018 +0200
   611.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   611.3 @@ -1,40 +0,0 @@
   611.4 -# SliTaz package receipt v2.
   611.5 -
   611.6 -PACKAGE="xorg-libXt"
   611.7 -VERSION="1.1.5"
   611.8 -CATEGORY="x-window"
   611.9 -SHORT_DESC="X Toolkit Intrinsics library"
  611.10 -MAINTAINER="devel@slitaz.org"
  611.11 -LICENSE="MIT"
  611.12 -WEB_SITE="https://www.x.org/wiki/"
  611.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  611.14 -REPOLOGY="libxt"
  611.15 -
  611.16 -TARBALL="libXt-$VERSION.tar.bz2"
  611.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  611.18 -
  611.19 -BUILD_DEPENDS="xorg-libSM-dev xorg-libX11-dev glib-dev util-linux-uuid-dev"
  611.20 -SPLIT="$PACKAGE-dev"
  611.21 -
  611.22 -compile_rules() {
  611.23 -	./configure \
  611.24 -		--with-appdefaultdir=/etc/X11/app-defaults \
  611.25 -		$CONFIGURE_ARGS &&
  611.26 -	fix libtool &&
  611.27 -	make &&
  611.28 -	make install
  611.29 -}
  611.30 -
  611.31 -genpkg_rules() {
  611.32 -	case $PACKAGE in
  611.33 -		*-libXt)
  611.34 -			copy @std
  611.35 -			DEPENDS="xorg-libICE xorg-libSM xorg-libX11"
  611.36 -			;;
  611.37 -		*-dev)
  611.38 -			copy @dev
  611.39 -			DEPENDS="xorg-libXt \
  611.40 -			xorg-libICE-dev xorg-libSM-dev xorg-libX11-dev xorg-xorgproto"
  611.41 -			;;
  611.42 -	esac
  611.43 -}
   612.1 --- a/xorg-libXtst/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   612.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   612.3 @@ -1,1 +0,0 @@
   612.4 -../xorg/.icon.png
   612.5 \ No newline at end of file
   613.1 --- a/xorg-libXtst/receipt	Thu Dec 13 00:46:54 2018 +0200
   613.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   613.3 @@ -1,38 +0,0 @@
   613.4 -# SliTaz package receipt v2.
   613.5 -
   613.6 -PACKAGE="xorg-libXtst"
   613.7 -VERSION="1.2.3"
   613.8 -CATEGORY="x-window"
   613.9 -SHORT_DESC="Xorg server module"
  613.10 -MAINTAINER="devel@slitaz.org"
  613.11 -LICENSE="MIT"
  613.12 -WEB_SITE="https://www.x.org/wiki/"
  613.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  613.14 -REPOLOGY="libxtst"
  613.15 -
  613.16 -TARBALL="libXtst-$VERSION.tar.bz2"
  613.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  613.18 -
  613.19 -BUILD_DEPENDS="xorg-xorgproto xorg-libXext-dev xorg-libXi-dev"
  613.20 -SPLIT="$PACKAGE-dev"
  613.21 -
  613.22 -compile_rules() {
  613.23 -	./configure $CONFIGURE_ARGS
  613.24 -	fix libtool &&
  613.25 -	make &&
  613.26 -	make install
  613.27 -}
  613.28 -
  613.29 -genpkg_rules() {
  613.30 -	case $PACKAGE in
  613.31 -		*-libXtst)
  613.32 -			copy @std
  613.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  613.34 -			;;
  613.35 -		*-dev)
  613.36 -			copy @dev
  613.37 -			DEPENDS="xorg-libXtst \
  613.38 -			xorg-libX11-dev xorg-libXext-dev xorg-libXi-dev xorg-xorgproto"
  613.39 -			;;
  613.40 -	esac
  613.41 -}
   614.1 --- a/xorg-libXv/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   614.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   614.3 @@ -1,1 +0,0 @@
   614.4 -../xorg/.icon.png
   614.5 \ No newline at end of file
   615.1 --- a/xorg-libXv/receipt	Thu Dec 13 00:46:54 2018 +0200
   615.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   615.3 @@ -1,38 +0,0 @@
   615.4 -# SliTaz package receipt v2.
   615.5 -
   615.6 -PACKAGE="xorg-libXv"
   615.7 -VERSION="1.0.11"
   615.8 -CATEGORY="x-window"
   615.9 -SHORT_DESC="Xvideo extension library"
  615.10 -MAINTAINER="devel@slitaz.org"
  615.11 -LICENSE="MIT"
  615.12 -WEB_SITE="https://www.x.org/wiki/"
  615.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  615.14 -REPOLOGY="libxv"
  615.15 -
  615.16 -TARBALL="libXv-$VERSION.tar.bz2"
  615.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  615.18 -
  615.19 -BUILD_DEPENDS="xorg-libXext-dev xorg-xorgproto"
  615.20 -SPLIT="$PACKAGE-dev"
  615.21 -
  615.22 -compile_rules() {
  615.23 -	./configure $CONFIGURE_ARGS &&
  615.24 -	fix libtool &&
  615.25 -	make &&
  615.26 -	make install
  615.27 -}
  615.28 -
  615.29 -genpkg_rules() {
  615.30 -	case $PACKAGE in
  615.31 -		*-libXv)
  615.32 -			copy @std
  615.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  615.34 -			;;
  615.35 -		*-dev)
  615.36 -			copy @dev
  615.37 -			DEPENDS="xorg-libXv \
  615.38 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  615.39 -			;;
  615.40 -	esac
  615.41 -}
   616.1 --- a/xorg-libXvMC/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   616.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   616.3 @@ -1,1 +0,0 @@
   616.4 -../xorg/.icon.png
   616.5 \ No newline at end of file
   617.1 --- a/xorg-libXvMC/receipt	Thu Dec 13 00:46:54 2018 +0200
   617.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   617.3 @@ -1,38 +0,0 @@
   617.4 -# SliTaz package receipt v2.
   617.5 -
   617.6 -PACKAGE="xorg-libXvMC"
   617.7 -VERSION="1.0.10"
   617.8 -CATEGORY="x-window"
   617.9 -SHORT_DESC="Xorg server module"
  617.10 -MAINTAINER="devel@slitaz.org"
  617.11 -LICENSE="MIT"
  617.12 -WEB_SITE="https://www.x.org/wiki/"
  617.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  617.14 -REPOLOGY="libxvmc"
  617.15 -
  617.16 -TARBALL="libXvMC-$VERSION.tar.bz2"
  617.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  617.18 -
  617.19 -BUILD_DEPENDS="xorg-libXv-dev"
  617.20 -SPLIT="$PACKAGE-dev"
  617.21 -
  617.22 -compile_rules() {
  617.23 -	./configure $CONFIGURE_ARGS &&
  617.24 -	fix libtool &&
  617.25 -	make &&
  617.26 -	make install
  617.27 -}
  617.28 -
  617.29 -genpkg_rules() {
  617.30 -	case $PACKAGE in
  617.31 -		*-libXvMC)
  617.32 -			copy @std
  617.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  617.34 -			;;
  617.35 -		*-dev)
  617.36 -			copy @dev
  617.37 -			DEPENDS="xorg-libXvMC \
  617.38 -			xorg-libX11-dev xorg-libXext-dev xorg-libXv-dev xorg-xorgproto"
  617.39 -			;;
  617.40 -	esac
  617.41 -}
   618.1 --- a/xorg-libXxf86dga/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   618.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   618.3 @@ -1,1 +0,0 @@
   618.4 -../xorg/.icon.png
   618.5 \ No newline at end of file
   619.1 --- a/xorg-libXxf86dga/receipt	Thu Dec 13 00:46:54 2018 +0200
   619.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   619.3 @@ -1,39 +0,0 @@
   619.4 -# SliTaz package receipt v2.
   619.5 -
   619.6 -PACKAGE="xorg-libXxf86dga"
   619.7 -VERSION="1.1.4"
   619.8 -CATEGORY="x-window"
   619.9 -SHORT_DESC="Xorg server module"
  619.10 -MAINTAINER="pascal.bellard@slitaz.org"
  619.11 -LICENSE="MIT"
  619.12 -WEB_SITE="https://www.x.org/wiki/"
  619.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  619.14 -REPOLOGY="libxxf86dga"
  619.15 -
  619.16 -TARBALL="libXxf86dga-$VERSION.tar.bz2"
  619.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  619.18 -
  619.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto \
  619.20 -xorg-libXext-dev"
  619.21 -SPLIT="$PACKAGE-dev"
  619.22 -
  619.23 -compile_rules() {
  619.24 -	./configure $CONFIGURE_ARGS &&
  619.25 -	fix libtool &&
  619.26 -	make &&
  619.27 -	make install
  619.28 -}
  619.29 -
  619.30 -genpkg_rules() {
  619.31 -	case $PACKAGE in
  619.32 -		*-libXxf86dga)
  619.33 -			copy @std
  619.34 -			DEPENDS="xorg-libX11 xorg-libXext"
  619.35 -			;;
  619.36 -		*-dev)
  619.37 -			copy @dev
  619.38 -			DEPENDS="xorg-libXxf86dga \
  619.39 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  619.40 -			;;
  619.41 -	esac
  619.42 -}
   620.1 --- a/xorg-libXxf86misc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   620.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   620.3 @@ -1,1 +0,0 @@
   620.4 -../xorg/.icon.png
   620.5 \ No newline at end of file
   621.1 --- a/xorg-libXxf86misc/receipt	Thu Dec 13 00:46:54 2018 +0200
   621.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   621.3 @@ -1,38 +0,0 @@
   621.4 -# SliTaz package receipt v2.
   621.5 -
   621.6 -PACKAGE="xorg-libXxf86misc"
   621.7 -VERSION="1.0.4"
   621.8 -CATEGORY="x-window"
   621.9 -SHORT_DESC="XFree86-MISC extension library"
  621.10 -MAINTAINER="al.bobylev@gmail.com"
  621.11 -LICENSE="MIT"
  621.12 -WEB_SITE="https://www.x.org/wiki/"
  621.13 -REPOLOGY="libxxf86misc"
  621.14 -
  621.15 -TARBALL="libXxf86misc-$VERSION.tar.bz2"
  621.16 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  621.17 -
  621.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto \
  621.19 -xorg-libXext-dev"
  621.20 -SPLIT="$PACKAGE-dev"
  621.21 -
  621.22 -compile_rules() {
  621.23 -	./configure $CONFIGURE_ARGS &&
  621.24 -	fix libtool &&
  621.25 -	make &&
  621.26 -	make install
  621.27 -}
  621.28 -
  621.29 -genpkg_rules() {
  621.30 -	case $PACKAGE in
  621.31 -		*-libXxf86misc)
  621.32 -			copy @std
  621.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  621.34 -			;;
  621.35 -		*-dev)
  621.36 -			copy @dev
  621.37 -			DEPENDS="xorg-libXxf86misc \
  621.38 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  621.39 -			;;
  621.40 -	esac
  621.41 -}
   622.1 --- a/xorg-libXxf86vm/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   622.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   622.3 @@ -1,1 +0,0 @@
   622.4 -../xorg/.icon.png
   622.5 \ No newline at end of file
   623.1 --- a/xorg-libXxf86vm/receipt	Thu Dec 13 00:46:54 2018 +0200
   623.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   623.3 @@ -1,38 +0,0 @@
   623.4 -# SliTaz package receipt v2.
   623.5 -
   623.6 -PACKAGE="xorg-libXxf86vm"
   623.7 -VERSION="1.1.4"
   623.8 -CATEGORY="x-window"
   623.9 -SHORT_DESC="XFree86-VidMode extension library"
  623.10 -MAINTAINER="devel@slitaz.org"
  623.11 -LICENSE="MIT"
  623.12 -WEB_SITE="https://www.x.org/wiki/"
  623.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  623.14 -REPOLOGY="libxxf86vm"
  623.15 -
  623.16 -TARBALL="libXxf86vm-$VERSION.tar.bz2"
  623.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  623.18 -
  623.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  623.20 -SPLIT="$PACKAGE-dev"
  623.21 -
  623.22 -compile_rules() {
  623.23 -	./configure $CONFIGURE_ARGS &&
  623.24 -	fix libtool &&
  623.25 -	make &&
  623.26 -	make install
  623.27 -}
  623.28 -
  623.29 -genpkg_rules() {
  623.30 -	case $PACKAGE in
  623.31 -		*-libXxf86vm)
  623.32 -			copy @std
  623.33 -			DEPENDS="xorg-libX11 xorg-libXext"
  623.34 -			;;
  623.35 -		*-dev)
  623.36 -			copy @dev
  623.37 -			DEPENDS="xorg-libXxf86vm \
  623.38 -			xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  623.39 -			;;
  623.40 -	esac
  623.41 -}
   624.1 --- a/xorg-libdmx/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   624.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   624.3 @@ -1,1 +0,0 @@
   624.4 -../xorg/.icon.png
   624.5 \ No newline at end of file
   625.1 --- a/xorg-libdmx/receipt	Thu Dec 13 00:46:54 2018 +0200
   625.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   625.3 @@ -1,40 +0,0 @@
   625.4 -# SliTaz package receipt v2.
   625.5 -
   625.6 -PACKAGE="xorg-libdmx"
   625.7 -VERSION="1.1.4"
   625.8 -CATEGORY="x-window"
   625.9 -SHORT_DESC="Xorg DMX library"
  625.10 -MAINTAINER="devel@slitaz.org"
  625.11 -LICENSE="MIT"
  625.12 -WEB_SITE="https://www.x.org/wiki/"
  625.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  625.14 -REPOLOGY="libdmx"
  625.15 -
  625.16 -TARBALL="libdmx-$VERSION.tar.bz2"
  625.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  625.18 -
  625.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-libXext-dev xorg-xorgproto"
  625.20 -SPLIT="$PACKAGE-dev"
  625.21 -
  625.22 -compile_rules() {
  625.23 -	./configure \
  625.24 -		--disable-static \
  625.25 -		$CONFIGURE_ARGS &&
  625.26 -	fix libtool &&
  625.27 -	make &&
  625.28 -	make install
  625.29 -}
  625.30 -
  625.31 -genpkg_rules() {
  625.32 -	case $PACKAGE in
  625.33 -		*-libdmx)
  625.34 -			copy @std
  625.35 -			DEPENDS="xorg-libX11 xorg-libXext"
  625.36 -			;;
  625.37 -		*-dev)
  625.38 -			copy @dev
  625.39 -			DEPENDS="xorg-libdmx \
  625.40 -			xorg-xorgproto xorg-libX11-dev xorg-libXext-dev"
  625.41 -			;;
  625.42 -	esac
  625.43 -}
   626.1 --- a/xorg-libfontenc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   626.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   626.3 @@ -1,1 +0,0 @@
   626.4 -../xorg/.icon.png
   626.5 \ No newline at end of file
   627.1 --- a/xorg-libfontenc/receipt	Thu Dec 13 00:46:54 2018 +0200
   627.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   627.3 @@ -1,36 +0,0 @@
   627.4 -# SliTaz package receipt v2.
   627.5 -
   627.6 -PACKAGE="xorg-libfontenc"
   627.7 -VERSION="1.1.3"
   627.8 -CATEGORY="x-window"
   627.9 -SHORT_DESC="Font encoding library"
  627.10 -MAINTAINER="devel@slitaz.org"
  627.11 -LICENSE="MIT"
  627.12 -WEB_SITE="https://www.x.org/wiki/"
  627.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  627.14 -REPOLOGY="libfontenc"
  627.15 -
  627.16 -TARBALL="libfontenc-$VERSION.tar.bz2"
  627.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  627.18 -
  627.19 -BUILD_DEPENDS="zlib-dev xorg-xorgproto xorg-font-util-dev"
  627.20 -SPLIT="$PACKAGE-dev"
  627.21 -
  627.22 -compile_rules() {
  627.23 -	./configure $CONFIGURE_ARGS &&
  627.24 -	fix libtool &&
  627.25 -	make &&
  627.26 -	make install
  627.27 -}
  627.28 -
  627.29 -genpkg_rules() {
  627.30 -	case $PACKAGE in
  627.31 -		*-libfontenc)
  627.32 -			copy @std
  627.33 -			DEPENDS="zlib"
  627.34 -			;;
  627.35 -		*-dev)
  627.36 -			copy @dev
  627.37 -			;;
  627.38 -	esac
  627.39 -}
   628.1 --- a/xorg-liblbxutil/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   628.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   628.3 @@ -1,1 +0,0 @@
   628.4 -../xorg/.icon.png
   628.5 \ No newline at end of file
   629.1 --- a/xorg-liblbxutil/receipt	Thu Dec 13 00:46:54 2018 +0200
   629.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   629.3 @@ -1,36 +0,0 @@
   629.4 -# SliTaz package receipt v2.
   629.5 -
   629.6 -PACKAGE="xorg-liblbxutil"
   629.7 -VERSION="1.1.0"
   629.8 -CATEGORY="x-window"
   629.9 -SHORT_DESC="LBX utility routines"
  629.10 -MAINTAINER="al.bobylev@gmail.com"
  629.11 -LICENSE="MIT"
  629.12 -WEB_SITE="https://www.x.org/wiki/"
  629.13 -REPOLOGY="liblbxutil"
  629.14 -
  629.15 -TARBALL="liblbxutil-$VERSION.tar.bz2"
  629.16 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  629.17 -
  629.18 -BUILD_DEPENDS="gfortran xorg-xorgproto zlib-dev"
  629.19 -SPLIT="$PACKAGE-dev"
  629.20 -
  629.21 -compile_rules() {
  629.22 -	./configure $CONFIGURE_ARGS &&
  629.23 -	fix libtool &&
  629.24 -	make &&
  629.25 -	make install
  629.26 -}
  629.27 -
  629.28 -genpkg_rules() {
  629.29 -	case $PACKAGE in
  629.30 -		*-liblbxutil)
  629.31 -			copy @std
  629.32 -			DEPENDS="zlib"
  629.33 -			;;
  629.34 -		*-dev)
  629.35 -			copy @dev
  629.36 -			DEPENDS="xorg-liblbxutil zlib-dev"
  629.37 -			;;
  629.38 -	esac
  629.39 -}
   630.1 --- a/xorg-libpciaccess/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   630.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   630.3 @@ -1,1 +0,0 @@
   630.4 -../xorg/.icon.png
   630.5 \ No newline at end of file
   631.1 --- a/xorg-libpciaccess/receipt	Thu Dec 13 00:46:54 2018 +0200
   631.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   631.3 @@ -1,31 +0,0 @@
   631.4 -# SliTaz package receipt v2.
   631.5 -
   631.6 -PACKAGE="xorg-libpciaccess"
   631.7 -VERSION="0.14"
   631.8 -CATEGORY="x-window"
   631.9 -SHORT_DESC="Xorg server module"
  631.10 -MAINTAINER="devel@slitaz.org"
  631.11 -LICENSE="MIT"
  631.12 -WEB_SITE="https://www.x.org/wiki/"
  631.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  631.14 -REPOLOGY="libpciaccess"
  631.15 -
  631.16 -TARBALL="libpciaccess-$VERSION.tar.bz2"
  631.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  631.18 -
  631.19 -BUILD_DEPENDS="xorg-util-macros"
  631.20 -SPLIT="$PACKAGE-dev"
  631.21 -
  631.22 -compile_rules() {
  631.23 -	./configure $CONFIGURE_ARGS &&
  631.24 -	fix libtool &&
  631.25 -	make &&
  631.26 -	make install
  631.27 -}
  631.28 -
  631.29 -genpkg_rules() {
  631.30 -	case $PACKAGE in
  631.31 -		*-libpciaccess) copy @std;;
  631.32 -		*-dev)          copy @dev;;
  631.33 -	esac
  631.34 -}
   632.1 --- a/xorg-libxcb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   632.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   632.3 @@ -1,1 +0,0 @@
   632.4 -../xorg/.icon.png
   632.5 \ No newline at end of file
   633.1 --- a/xorg-libxcb/description.txt	Thu Dec 13 00:46:54 2018 +0200
   633.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   633.3 @@ -1,3 +0,0 @@
   633.4 -The X protocol C-language Binding (XCB) is a replacement for Xlib featuring
   633.5 -a small footprint, latency hiding, direct access to the protocol, improved
   633.6 -threading support, and extensibility.
   634.1 --- a/xorg-libxcb/receipt	Thu Dec 13 00:46:54 2018 +0200
   634.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   634.3 @@ -1,47 +0,0 @@
   634.4 -# SliTaz package receipt v2.
   634.5 -
   634.6 -PACKAGE="xorg-libxcb"
   634.7 -VERSION="1.13"
   634.8 -CATEGORY="x-window"
   634.9 -SHORT_DESC="A C binding to the X11 protocol"
  634.10 -MAINTAINER="devel@slitaz.org"
  634.11 -LICENSE="MIT"
  634.12 -WEB_SITE="https://xcb.freedesktop.org/"
  634.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/libxcb.html"
  634.14 -REPOLOGY="libxcb"
  634.15 -
  634.16 -TARBALL="libxcb-$VERSION.tar.bz2"
  634.17 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  634.18 -
  634.19 -BUILD_DEPENDS="xorg-util-macros libxslt-dev xorg-xcb-proto xorg-libXau-dev \
  634.20 -xorg-libXdmcp-dev autoconf automake libtool"
  634.21 -SPLIT="$PACKAGE-dev"
  634.22 -
  634.23 -compile_rules() {
  634.24 -	# Package "libpthread-stubs" no more needed:
  634.25 -	# our platform already supply all the necessary pthread stubs.
  634.26 -	sed -i "s|pthread-stubs||" $src/configure.ac
  634.27 -
  634.28 -	autoreconf -fi &&
  634.29 -	./configure \
  634.30 -		--enable-xinput \
  634.31 -		--enable-xprint \
  634.32 -		--docdir='${datadir}'/doc/$PACKAGE-$VERSION \
  634.33 -		$CONFIGURE_ARGS &&
  634.34 -	fix libtool &&
  634.35 -	make &&
  634.36 -	make DESTDIR=$install install
  634.37 -}
  634.38 -
  634.39 -genpkg_rules() {
  634.40 -	case $PACKAGE in
  634.41 -		*-libxcb)
  634.42 -			copy @std
  634.43 -			DEPENDS="xorg-libXau xorg-libXdmcp"
  634.44 -			;;
  634.45 -		*-dev)
  634.46 -			copy @dev
  634.47 -			DEPENDS="xorg-libxcb xorg-libXau-dev xorg-libXdmcp-dev"
  634.48 -			;;
  634.49 -	esac
  634.50 -}
   635.1 --- a/xorg-libxkbfile/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   635.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   635.3 @@ -1,1 +0,0 @@
   635.4 -../xorg/.icon.png
   635.5 \ No newline at end of file
   636.1 --- a/xorg-libxkbfile/receipt	Thu Dec 13 00:46:54 2018 +0200
   636.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   636.3 @@ -1,38 +0,0 @@
   636.4 -# SliTaz package receipt v2.
   636.5 -
   636.6 -PACKAGE="xorg-libxkbfile"
   636.7 -VERSION="1.0.9"
   636.8 -CATEGORY="x-window"
   636.9 -SHORT_DESC="XKB file handling routines"
  636.10 -MAINTAINER="devel@slitaz.org"
  636.11 -LICENSE="MIT"
  636.12 -WEB_SITE="https://www.x.org/wiki/"
  636.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  636.14 -REPOLOGY="libxkbfile"
  636.15 -
  636.16 -TARBALL="libxkbfile-$VERSION.tar.bz2"
  636.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  636.18 -
  636.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-libxcb-dev xorg-libXau-dev xorg-libXdmcp-dev"
  636.20 -SPLIT="$PACKAGE-dev"
  636.21 -
  636.22 -compile_rules() {
  636.23 -	./configure $CONFIGURE_ARGS &&
  636.24 -	fix libtool &&
  636.25 -	make &&
  636.26 -	make install
  636.27 -}
  636.28 -
  636.29 -genpkg_rules() {
  636.30 -	case $PACKAGE in
  636.31 -		*-libxkbfile)
  636.32 -			copy @std
  636.33 -			DEPENDS="xorg-libX11"
  636.34 -			;;
  636.35 -		*-dev)
  636.36 -			copy @dev
  636.37 -			DEPENDS="xorg-libxkbfile \
  636.38 -			xorg-xorgproto xorg-libX11-dev"
  636.39 -			;;
  636.40 -	esac
  636.41 -}
   637.1 --- a/xorg-libxshmfence/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   637.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   637.3 @@ -1,1 +0,0 @@
   637.4 -../xorg/.icon.png
   637.5 \ No newline at end of file
   638.1 --- a/xorg-libxshmfence/receipt	Thu Dec 13 00:46:54 2018 +0200
   638.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   638.3 @@ -1,31 +0,0 @@
   638.4 -# SliTaz package receipt v2.
   638.5 -
   638.6 -PACKAGE="xorg-libxshmfence"
   638.7 -VERSION="1.3"
   638.8 -CATEGORY="x-window"
   638.9 -SHORT_DESC="Xorg server Shared Memory Fence library"
  638.10 -MAINTAINER="al.bobylev@gmail.com"
  638.11 -LICENSE="MIT"
  638.12 -WEB_SITE="https://www.x.org/wiki/"
  638.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  638.14 -REPOLOGY="libxshmfence"
  638.15 -
  638.16 -TARBALL="libxshmfence-$VERSION.tar.bz2"
  638.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  638.18 -
  638.19 -BUILD_DEPENDS="xorg-xorgproto"
  638.20 -SPLIT="$PACKAGE-dev"
  638.21 -
  638.22 -compile_rules() {
  638.23 -	./configure $CONFIGURE_ARGS &&
  638.24 -	fix libtool &&
  638.25 -	make &&
  638.26 -	make install
  638.27 -}
  638.28 -
  638.29 -genpkg_rules() {
  638.30 -	case $PACKAGE in
  638.31 -		*-libxshmfence) copy @std;;
  638.32 -		*-dev)          copy @dev;;
  638.33 -	esac
  638.34 -}
   639.1 --- a/xorg-luit/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   639.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   639.3 @@ -1,1 +0,0 @@
   639.4 -../xorg/.icon.png
   639.5 \ No newline at end of file
   640.1 --- a/xorg-luit/receipt	Thu Dec 13 00:46:54 2018 +0200
   640.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   640.3 @@ -1,35 +0,0 @@
   640.4 -# SliTaz package receipt v2.
   640.5 -
   640.6 -PACKAGE="xorg-luit"
   640.7 -VERSION="1.1.1"
   640.8 -CATEGORY="x-window"
   640.9 -SHORT_DESC="Convert terminal i/o from legacy encodings to UTF-8"
  640.10 -MAINTAINER="al.bobylev@gmail.com"
  640.11 -LICENSE="MIT"
  640.12 -WEB_SITE="https://www.x.org/wiki/"
  640.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  640.14 -REPOLOGY="luit"
  640.15 -
  640.16 -TARBALL="luit-$VERSION.tar.bz2"
  640.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  640.18 -
  640.19 -BUILD_DEPENDS="xorg-util-macros xorg-libfontenc-dev xorg-libX11-dev"
  640.20 -
  640.21 -compile_rules() {
  640.22 -	line1="#ifdef _XOPEN_SOURCE"
  640.23 -	line2="#  undef _XOPEN_SOURCE"
  640.24 -	line3="#  define _XOPEN_SOURCE 600"
  640.25 -	line4="#endif"
  640.26 -	sed -i -e "s@#ifdef HAVE_CONFIG_H@$line1\n$line2\n$line3\n$line4\n\n&@" sys.c
  640.27 -	unset line1 line2 line3 line4
  640.28 -
  640.29 -	./configure $CONFIGURE_ARGS &&
  640.30 -	fix libtool &&
  640.31 -	make &&
  640.32 -	make install
  640.33 -}
  640.34 -
  640.35 -genpkg_rules() {
  640.36 -	copy @std
  640.37 -	DEPENDS="xorg-libfontenc"
  640.38 -}
   641.1 --- a/xorg-makedepend/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   641.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   641.3 @@ -1,1 +0,0 @@
   641.4 -../xorg/.icon.png
   641.5 \ No newline at end of file
   642.1 --- a/xorg-makedepend/receipt	Thu Dec 13 00:46:54 2018 +0200
   642.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   642.3 @@ -1,26 +0,0 @@
   642.4 -# SliTaz package receipt v2.
   642.5 -
   642.6 -PACKAGE="xorg-makedepend"
   642.7 -VERSION="1.0.5"
   642.8 -CATEGORY="development"
   642.9 -SHORT_DESC="Create dependencies in makefiles"
  642.10 -MAINTAINER="devel@slitaz.org"
  642.11 -LICENSE="MIT"
  642.12 -WEB_SITE="https://www.x.org/wiki/"
  642.13 -REPOLOGY="makedepend"
  642.14 -
  642.15 -TARBALL="makedepend-$VERSION.tar.bz2"
  642.16 -WGET_URL="$XORG_MIRROR/util/$TARBALL"
  642.17 -
  642.18 -BUILD_DEPENDS="xorg-xorgproto"
  642.19 -
  642.20 -compile_rules() {
  642.21 -	./configure $CONFIGURE_ARGS &&
  642.22 -	make &&
  642.23 -	make install
  642.24 -}
  642.25 -
  642.26 -genpkg_rules() {
  642.27 -	copy @std
  642.28 -	DEPENDS="xorg-xorgproto"
  642.29 -}
   643.1 --- a/xorg-mkfontdir/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   643.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   643.3 @@ -1,1 +0,0 @@
   643.4 -../xorg/.icon.png
   643.5 \ No newline at end of file
   644.1 --- a/xorg-mkfontdir/receipt	Thu Dec 13 00:46:54 2018 +0200
   644.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   644.3 @@ -1,30 +0,0 @@
   644.4 -# SliTaz package receipt v2.
   644.5 -
   644.6 -PACKAGE="xorg-mkfontdir"
   644.7 -VERSION="1.0.7"
   644.8 -CATEGORY="x-window"
   644.9 -SHORT_DESC="Create an index of X font files in a directory"
  644.10 -MAINTAINER="pascal.bellard@slitaz.org"
  644.11 -LICENSE="MIT"
  644.12 -WEB_SITE="https://www.x.org/wiki/"
  644.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  644.14 -HOST_ARCH="any"
  644.15 -REPOLOGY="mkfontdir"
  644.16 -
  644.17 -TARBALL="mkfontdir-$VERSION.tar.bz2"
  644.18 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  644.19 -
  644.20 -BUILD_DEPENDS="xorg-util-macros"
  644.21 -
  644.22 -compile_rules() {
  644.23 -	./configure $CONFIGURE_ARGS &&
  644.24 -	fix libtool &&
  644.25 -	make &&
  644.26 -	make install
  644.27 -}
  644.28 -
  644.29 -genpkg_rules() {
  644.30 -	copy @std
  644.31 -	DEPENDS="   xorg-mkfontscale"
  644.32 -	TAGS="utility xorg fonts"
  644.33 -}
   645.1 --- a/xorg-mkfontscale/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   645.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   645.3 @@ -1,1 +0,0 @@
   645.4 -../xorg/.icon.png
   645.5 \ No newline at end of file
   646.1 --- a/xorg-mkfontscale/receipt	Thu Dec 13 00:46:54 2018 +0200
   646.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   646.3 @@ -1,29 +0,0 @@
   646.4 -# SliTaz package receipt v2.
   646.5 -
   646.6 -PACKAGE="xorg-mkfontscale"
   646.7 -VERSION="1.1.3"
   646.8 -CATEGORY="x-window"
   646.9 -SHORT_DESC="Create an index of scalable font files for X"
  646.10 -MAINTAINER="pascal.bellard@slitaz.org"
  646.11 -LICENSE="MIT"
  646.12 -WEB_SITE="https://www.x.org/wiki/"
  646.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  646.14 -REPOLOGY="mkfontscale"
  646.15 -
  646.16 -TARBALL="mkfontscale-$VERSION.tar.bz2"
  646.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  646.18 -
  646.19 -BUILD_DEPENDS="xorg-util-macros xorg-libfontenc-dev freetype-dev xorg-xorgproto"
  646.20 -
  646.21 -compile_rules() {
  646.22 -	./configure $CONFIGURE_ARGS &&
  646.23 -	fix libtool &&
  646.24 -	make &&
  646.25 -	make install
  646.26 -}
  646.27 -
  646.28 -genpkg_rules() {
  646.29 -	copy @std
  646.30 -	DEPENDS="freetype xorg-libfontenc zlib"
  646.31 -	TAGS="utility xorg fonts"
  646.32 -}
   647.1 --- a/xorg-oclock/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   647.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   647.3 @@ -1,1 +0,0 @@
   647.4 -../xorg/.icon.png
   647.5 \ No newline at end of file
   648.1 --- a/xorg-oclock/receipt	Thu Dec 13 00:46:54 2018 +0200
   648.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   648.3 @@ -1,28 +0,0 @@
   648.4 -# SliTaz package receipt v2.
   648.5 -
   648.6 -PACKAGE="xorg-oclock"
   648.7 -VERSION="1.0.4"
   648.8 -CATEGORY="x-window"
   648.9 -SHORT_DESC="Round X clock"
  648.10 -MAINTAINER="al.bobylev@gmail.com"
  648.11 -LICENSE="MIT"
  648.12 -WEB_SITE="https://www.x.org/wiki/"
  648.13 -REPOLOGY="oclock"
  648.14 -
  648.15 -TARBALL="oclock-$VERSION.tar.bz2"
  648.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  648.17 -
  648.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXmu-dev \
  648.19 -xorg-libXext-dev xorg-libXt-dev xorg-libxkbfile-dev"
  648.20 -
  648.21 -compile_rules() {
  648.22 -	./configure $CONFIGURE_ARGS &&
  648.23 -	make &&
  648.24 -	make install
  648.25 -}
  648.26 -
  648.27 -genpkg_rules() {
  648.28 -	copy @std
  648.29 -	DEPENDS="xorg-libX11 xorg-libXext xorg-libXmu xorg-libXt xorg-libxkbfile"
  648.30 -	CONFIG_FILES="/etc/X11/app-defaults/Clock-color"
  648.31 -}
   649.1 --- a/xorg-pixman/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   649.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   649.3 @@ -1,1 +0,0 @@
   649.4 -../xorg/.icon.png
   649.5 \ No newline at end of file
   650.1 --- a/xorg-pixman/description.txt	Thu Dec 13 00:46:54 2018 +0200
   650.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   650.3 @@ -1,3 +0,0 @@
   650.4 -A library for manipulating pixel regions -- a set of Y-X banded rectangles,
   650.5 -image compositing using the Porter/Duff model and implicit mask generation for
   650.6 -geometric primitives including trapezoids, triangles, and rectangles.
   651.1 --- a/xorg-pixman/receipt	Thu Dec 13 00:46:54 2018 +0200
   651.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   651.3 @@ -1,33 +0,0 @@
   651.4 -# SliTaz package receipt v2.
   651.5 -
   651.6 -PACKAGE="xorg-pixman"
   651.7 -VERSION="0.34.0"
   651.8 -CATEGORY="x-window"
   651.9 -SHORT_DESC="Pixel-manipulation library for X and Cairo"
  651.10 -MAINTAINER="devel@slitaz.org"
  651.11 -LICENSE="MIT"
  651.12 -WEB_SITE="https://www.cairographics.org/"
  651.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/general/pixman.html"
  651.14 -REPOLOGY="pixman"
  651.15 -
  651.16 -TARBALL="pixman-$VERSION.tar.bz2"
  651.17 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  651.18 -
  651.19 -BUILD_DEPENDS="libpng16-dev"
  651.20 -SPLIT="$PACKAGE-dev"
  651.21 -
  651.22 -compile_rules() {
  651.23 -	./configure \
  651.24 -		--disable-static \
  651.25 -		$CONFIGURE_ARGS &&
  651.26 -	fix libtool &&
  651.27 -	make &&
  651.28 -	make install
  651.29 -}
  651.30 -
  651.31 -genpkg_rules() {
  651.32 -	case $PACKAGE in
  651.33 -		*-pixman) copy @std;;
  651.34 -		*-dev)    copy @dev;;
  651.35 -	esac
  651.36 -}
   652.1 --- a/xorg-rgb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   652.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   652.3 @@ -1,1 +0,0 @@
   652.4 -../xorg/.icon.png
   652.5 \ No newline at end of file
   653.1 --- a/xorg-rgb/receipt	Thu Dec 13 00:46:54 2018 +0200
   653.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   653.3 @@ -1,27 +0,0 @@
   653.4 -# SliTaz package receipt v2.
   653.5 -
   653.6 -PACKAGE="xorg-rgb"
   653.7 -VERSION="1.0.6"
   653.8 -CATEGORY="x-window"
   653.9 -SHORT_DESC="X colorname to RGB mapping database"
  653.10 -MAINTAINER="devel@slitaz.org"
  653.11 -LICENSE="MIT"
  653.12 -WEB_SITE="https://www.x.org/wiki/"
  653.13 -REPOLOGY="rgb"
  653.14 -
  653.15 -TARBALL="rgb-$VERSION.tar.bz2"
  653.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  653.17 -
  653.18 -BUILD_DEPENDS="xorg-xorgproto"
  653.19 -
  653.20 -compile_rules() {
  653.21 -	touch /root/missing
  653.22 -
  653.23 -	./configure $CONFIGURE_ARGS &&
  653.24 -	make &&
  653.25 -	make install
  653.26 -}
  653.27 -
  653.28 -genpkg_rules() {
  653.29 -	copy @std
  653.30 -}
   654.1 --- a/xorg-server/receipt	Thu Dec 13 00:46:54 2018 +0200
   654.2 +++ b/xorg-server/receipt	Thu Dec 20 17:55:43 2018 +0200
   654.3 @@ -1,7 +1,7 @@
   654.4  # SliTaz package receipt v2.
   654.5  
   654.6  PACKAGE="xorg-server"
   654.7 -VERSION="1.20.1"
   654.8 +VERSION="1.20.3"
   654.9  CATEGORY="x-window"
  654.10  SHORT_DESC="X server"
  654.11  MAINTAINER="devel@slitaz.org"
  654.12 @@ -11,27 +11,64 @@
  654.13  
  654.14  TARBALL="$PACKAGE-$VERSION.tar.bz2"
  654.15  WGET_URL="$XORG_MIRROR/xserver/$TARBALL"
  654.16 +TARBALL_SHA1="a522cd543606b4d0509d821b8061904951171c50"
  654.17  
  654.18 -BUILD_DEPENDS="patch xorg-util-macros xorg-pixman-dev eudev-dev dbus-dev \
  654.19 -xorg-libxshmfence-dev libdrm-dev xorg-libX11-dev mesa-dev xorg-libXdmcp-dev \
  654.20 -libgcrypt-dev xorg-xorgproto xorg-libxkbfile-dev xorg-libXfont2-dev \
  654.21 -xorg-libpciaccess-dev xorg-libXxf86dga-dev xorg-libdmx-dev xorg-libXaw-dev \
  654.22 -xorg-libXpm-dev xorg-libXtst-dev xorg-libXres-dev xorg-libXmu-dev \
  654.23 -xorg-libXext-dev xorg-libXrender-dev xorg-libXfixes-dev xorg-libXi-dev \
  654.24 -xorg-libXau-dev xorg-libXdmcp-dev libepoxy-dev tslib-dev \
  654.25 -xorg-xcb-util-renderutil-dev xorg-xcb-util-dev xorg-xcb-util-image-dev \
  654.26 -xorg-xcb-util-wm-dev xorg-xcb-util-keysyms-dev expat-dev xorg-xtrans \
  654.27 -xorg-xkbcomp-dev openssl-dev"
  654.28 -SPLIT="$PACKAGE-Xdmx $PACKAGE-Xephyr $PACKAGE-Xnest $PACKAGE-Xvfb \
  654.29 -$PACKAGE-module-glamor $PACKAGE-dev $PACKAGE $PACKAGE-light:light"
  654.30 +BUILD_DEPENDS="patch util-macros pixman-dev eudev-dev dbus-dev \
  654.31 +libxshmfence-dev libdrm-dev libx11-dev mesa-dev libxdmcp-dev libgcrypt-dev \
  654.32 +xorgproto libxkbfile-dev libxfont2-dev libpciaccess-dev libxxf86dga-dev \
  654.33 +libdmx-dev libxaw-dev libxpm-dev libxtst-dev libxres-dev libxmu-dev \
  654.34 +libxext-dev libxrender-dev libxfixes-dev libxi-dev libxau-dev libxdmcp-dev \
  654.35 +libepoxy-dev tslib-dev xcb-util-renderutil-dev xcb-util-dev xcb-util-image-dev \
  654.36 +xcb-util-wm-dev xcb-util-keysyms-dev expat-dev xtrans xkbcomp-dev openssl-dev"
  654.37 +SPLIT="\
  654.38 +$PACKAGE-xdmx          $PACKAGE-xephyr $PACKAGE-xnest $PACKAGE-xvfb \
  654.39 +$PACKAGE-module-glamor $PACKAGE-dev    $PACKAGE       $PACKAGE-light:light"
  654.40  COOKOPTS="skip-log-errors"
  654.41  
  654.42 +COPY_xdmx="Xdmx"
  654.43 +COPY_xephyr="Xephyr"
  654.44 +COPY_xnest="Xnest"
  654.45 +COPY_xvfb="Xvfb"
  654.46 +COPY_module_glamor="libglamoregl.so libglx.so"
  654.47 +COPY_dev="@dev protocol.txt"
  654.48 +COPY_std="@std var/log/ xorg.conf.d/ @rm"
  654.49 +COPY_light="@std"
  654.50 +
  654.51 +CAT_xdmx="x-window|DMX X server"
  654.52 +CAT_xephyr="x-window|Xephyr X server"
  654.53 +CAT_xnest="x-window|Xnest X server"
  654.54 +CAT_xvfb="x-window|Xvfb X server"
  654.55 +CAT_module_glamor="x-window|Glamor DIX (Device Independent X) module"
  654.56 +CAT_std="x-window|core X server"
  654.57 +CAT_light="x-window|light version without DRI, GL, and friends"
  654.58 +
  654.59 +DEPENDS_xdmx="libgcrypt libx11 libxau libxdmcp libxext libxfixes libxfont2 \
  654.60 +libxi libxmu libxrender pixman"
  654.61 +DEPENDS_xephyr="eudev libepoxy libgcrypt mesa libx11 libxau libxdmcp libxfont2 \
  654.62 +libxcb libxshmfence pixman xcb-util xcb-util-image xcb-util-keysyms \
  654.63 +xcb-util-renderutil xcb-util-wm"
  654.64 +DEPENDS_xnest="libgcrypt libx11 libxau libxdmcp libxext libxfont2 pixman"
  654.65 +DEPENDS_xvfb="libgcrypt mesa libxau libxdmcp libxfont2 pixman"
  654.66 +DEPENDS_module_glamor="libepoxy mesa mesa-libgbm"
  654.67 +DEPENDS_dev="$PACKAGE $PACKAGE-xdmx $PACKAGE-xephyr $PACKAGE-xnest \
  654.68 +$PACKAGE-xvfb $PACKAGE-module-glamor \
  654.69 +mesa-dev xorgproto libpciaccess-dev pixman-dev"
  654.70 +DEPENDS_std="eudev libdrm libgcrypt libx11 libxau libxaw libxdmcp libxfont2 \
  654.71 +libxt libdmx libpciaccess libxshmfence pixman   xkeyboard-config xkbcomp"
  654.72 +DEPENDS_light="libgcrypt libxau libxdmcp libxfont2 libpciaccess libxshmfence \
  654.73 +pixman"
  654.74 +
  654.75 +SUGGESTED_std="xf86-input-evdev xf86-video-vesa"
  654.76 +SUGGESTED_light="xf86-video-vesa xf86-video-fbdev"
  654.77 +PROVIDE_light="xorg-server"
  654.78 +
  654.79  compile_rules() {
  654.80  	case $SET in
  654.81  		'')
  654.82  			SET_ARGS="
  654.83  				--disable-static \
  654.84  				--enable-glamor \
  654.85 +				--enable-install-setuid \
  654.86  				--enable-suid-wrapper \
  654.87  				--disable-xwayland \
  654.88  				--enable-dmx \
  654.89 @@ -75,80 +112,20 @@
  654.90  		$CONFIGURE_ARGS &&
  654.91  	fix libtool &&
  654.92  	make &&
  654.93 -	make DESTDIR=$install install &&
  654.94 +	make DESTDIR=$install install || return 1
  654.95  
  654.96  	mkdir -pv $install/etc/X11/xorg.conf.d
  654.97 +
  654.98 +	# chmod 4711 $install/usr/bin/Xdmx
  654.99 +	# chmod 4711 $install/usr/bin/Xephyr
 654.100 +	# chmod 4711 $install/usr/bin/Xnest
 654.101 +	# chmod 4711 $install/usr/bin/Xvfb
 654.102  }
 654.103  
 654.104  testsuite() {
 654.105  	readelf -h $install/usr/bin/Xorg
 654.106  }
 654.107  
 654.108 -genpkg_rules() {
 654.109 -	case $PACKAGE in
 654.110 -		*-Xdmx)
 654.111 -			copy Xdmx
 654.112 -			# chmod 4711 $fs/usr/bin/Xdmx
 654.113 -			CAT="x-window|DMX X server"
 654.114 -			DEPENDS="libgcrypt xorg-libX11 xorg-libXau xorg-libXdmcp \
 654.115 -			xorg-libXext xorg-libXfixes xorg-libXfont2 xorg-libXi xorg-libXmu \
 654.116 -			xorg-libXrender xorg-pixman"
 654.117 -			;;
 654.118 -		*-Xephyr)
 654.119 -			copy Xephyr
 654.120 -			# chmod 4711 $fs/usr/bin/Xephyr
 654.121 -			CAT="x-window|Xephyr X server"
 654.122 -			DEPENDS="eudev libepoxy libgcrypt mesa xorg-libX11 xorg-libXau \
 654.123 -			xorg-libXdmcp xorg-libXfont2 xorg-libxcb xorg-libxshmfence \
 654.124 -			xorg-pixman xorg-xcb-util xorg-xcb-util-image \
 654.125 -			xorg-xcb-util-keysyms xorg-xcb-util-renderutil xorg-xcb-util-wm"
 654.126 -			;;
 654.127 -		*-Xnest)
 654.128 -			copy Xnest
 654.129 -			# chmod 4711 $fs/usr/bin/Xnest
 654.130 -			CAT="x-window|Xnest X server"
 654.131 -			DEPENDS="libgcrypt xorg-libX11 xorg-libXau xorg-libXdmcp \
 654.132 -			xorg-libXext xorg-libXfont2 xorg-pixman"
 654.133 -			;;
 654.134 -		*-Xvfb)
 654.135 -			copy Xvfb
 654.136 -			# chmod 4711 $fs/usr/bin/Xvfb
 654.137 -			CAT="x-window|Xvfb X server"
 654.138 -			DEPENDS="libgcrypt mesa xorg-libXau xorg-libXdmcp xorg-libXfont2 \
 654.139 -			xorg-pixman"
 654.140 -			;;
 654.141 -		*-module-glamor)
 654.142 -			copy libglamoregl.so libglx.so
 654.143 -			CAT="x-window|Glamor DIX (Device Independent X) module"
 654.144 -			DEPENDS="libepoxy mesa mesa-libgbm"
 654.145 -			;;
 654.146 -		*-dev)
 654.147 -			copy @dev protocol.txt
 654.148 -			DEPENDS="xorg-server xorg-server-Xdmx xorg-server-Xephyr \
 654.149 -			xorg-server-Xfbdev xorg-server-Xnest xorg-server-Xvfb \
 654.150 -			xorg-server-module-glamor \
 654.151 -			mesa-dev xorg-xorgproto xorg-libpciaccess-dev xorg-pixman-dev"
 654.152 -			;;
 654.153 -		*-server)
 654.154 -			copy @std var/log/ xorg.conf.d/ @rm
 654.155 -			CAT="x-window|core X server"
 654.156 -			DEPENDS="eudev libdrm libgcrypt xorg-libX11 xorg-libXau \
 654.157 -			xorg-libXaw xorg-libXdmcp xorg-libXfont2 xorg-libXt xorg-libdmx \
 654.158 -			xorg-libpciaccess xorg-libxshmfence xorg-pixman   \
 654.159 -			xorg-xkeyboard-config xorg-xkbcomp"
 654.160 -			SUGGESTED="xorg-xf86-input-evdev xorg-xf86-video-vesa"
 654.161 -			;;
 654.162 -		xorg-server-light)
 654.163 -			copy @std
 654.164 -			CAT="x-window|light version without dri, gl, and friends"
 654.165 -			DEPENDS="libgcrypt xorg-libXau xorg-libXdmcp xorg-libXfont2 \
 654.166 -			xorg-libpciaccess xorg-libxshmfence xorg-pixman"
 654.167 -			SUGGESTED="xorg-xf86-video-vesa xorg-xf86-video-fbdev"
 654.168 -			PROVIDE="xorg-server"
 654.169 -			;;
 654.170 -	esac
 654.171 -}
 654.172 -
 654.173  post_install_xorg_server() {
 654.174  	install -dm1777 -oroot -groot "$1/tmp/.ICE-unix" "$1/tmp/.X11-unix"
 654.175  }
 654.176 @@ -171,3 +148,11 @@
 654.177  post_install_xorg_server_light() {
 654.178  	chmod 1777 "$1/var/tmp"
 654.179  }
 654.180 +
 654.181 +
 654.182 +TAGS="Xorg"
 654.183 +
 654.184 +PROVIDE_xdmx="xorg-server-Xdmx"
 654.185 +PROVIDE_xephyr="xorg-server-Xephyr"
 654.186 +PROVIDE_xnest="xorg-server-Xnest"
 654.187 +PROVIDE_xvfb="xorg-server-Xvfb"
   655.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   655.2 +++ b/xorg-server/stuff/overrides	Thu Dec 20 17:55:43 2018 +0200
   655.3 @@ -0,0 +1,3 @@
   655.4 +4755 /usr/libexec/Xorg
   655.5 +4755 /usr/libexec/Xorg.wrap
   655.6 +4755 /usr/bin/Xorg
   656.1 --- a/xorg-sessreg/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   656.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   656.3 @@ -1,1 +0,0 @@
   656.4 -../xorg/.icon.png
   656.5 \ No newline at end of file
   657.1 --- a/xorg-sessreg/receipt	Thu Dec 13 00:46:54 2018 +0200
   657.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   657.3 @@ -1,28 +0,0 @@
   657.4 -# SliTaz package receipt v2.
   657.5 -
   657.6 -PACKAGE="xorg-sessreg"
   657.7 -VERSION="1.1.1"
   657.8 -CATEGORY="x-window"
   657.9 -SHORT_DESC="Register X sessions in system utmp/utmpx databases"
  657.10 -MAINTAINER="al.bobylev@gmail.com"
  657.11 -LICENSE="MIT"
  657.12 -WEB_SITE="https://www.x.org/wiki/"
  657.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  657.14 -REPOLOGY="sessreg"
  657.15 -
  657.16 -TARBALL="sessreg-$VERSION.tar.bz2"
  657.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  657.18 -
  657.19 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto"
  657.20 -
  657.21 -compile_rules() {
  657.22 -	sed -e 's/\$(CPP) \$(DEFS)/$(CPP) -P $(DEFS)/' -i man/Makefile.in
  657.23 -
  657.24 -	./configure $CONFIGURE_ARGS &&
  657.25 -	make &&
  657.26 -	make install
  657.27 -}
  657.28 -
  657.29 -genpkg_rules() {
  657.30 -	copy @std
  657.31 -}
   658.1 --- a/xorg-setxkbmap/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   658.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   658.3 @@ -1,1 +0,0 @@
   658.4 -../xorg/.icon.png
   658.5 \ No newline at end of file
   659.1 --- a/xorg-setxkbmap/receipt	Thu Dec 13 00:46:54 2018 +0200
   659.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   659.3 @@ -1,28 +0,0 @@
   659.4 -# SliTaz package receipt v2.
   659.5 -
   659.6 -PACKAGE="xorg-setxkbmap"
   659.7 -VERSION="1.3.1"
   659.8 -CATEGORY="x-window"
   659.9 -SHORT_DESC="Set the keyboard using the X Keyboard Extension"
  659.10 -MAINTAINER="pascal.bellard@slitaz.org"
  659.11 -LICENSE="MIT"
  659.12 -WEB_SITE="https://www.x.org/wiki/"
  659.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  659.14 -REPOLOGY="setxkbmap"
  659.15 -
  659.16 -TARBALL="setxkbmap-$VERSION.tar.bz2"
  659.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  659.18 -
  659.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxkbfile-dev xorg-libX11-dev"
  659.20 -
  659.21 -compile_rules() {
  659.22 -	./configure $CONFIGURE_ARGS &&
  659.23 -	fix libtool &&
  659.24 -	make &&
  659.25 -	make install
  659.26 -}
  659.27 -
  659.28 -genpkg_rules() {
  659.29 -	copy @std
  659.30 -	DEPENDS="xorg-libX11 xorg-libxkbfile" # xorg-xkeyboard-config?
  659.31 -}
   660.1 --- a/xorg-showfont/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   660.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   660.3 @@ -1,1 +0,0 @@
   660.4 -../xorg/.icon.png
   660.5 \ No newline at end of file
   661.1 --- a/xorg-showfont/receipt	Thu Dec 13 00:46:54 2018 +0200
   661.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   661.3 @@ -1,26 +0,0 @@
   661.4 -# SliTaz package receipt v2.
   661.5 -
   661.6 -PACKAGE="xorg-showfont"
   661.7 -VERSION="1.0.5"
   661.8 -CATEGORY="x-window"
   661.9 -SHORT_DESC="Show information about X font from font server"
  661.10 -MAINTAINER="al.bobylev@gmail.com"
  661.11 -LICENSE="MIT"
  661.12 -WEB_SITE="https://www.x.org/wiki/"
  661.13 -REPOLOGY="showfont"
  661.14 -
  661.15 -TARBALL="showfont-$VERSION.tar.bz2"
  661.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  661.17 -
  661.18 -BUILD_DEPENDS="xorg-util-macros xorg-libFS-dev"
  661.19 -
  661.20 -compile_rules() {
  661.21 -	./configure $CONFIGURE_ARGS &&
  661.22 -	make &&
  661.23 -	make install
  661.24 -}
  661.25 -
  661.26 -genpkg_rules() {
  661.27 -	copy @std
  661.28 -	DEPENDS="xorg-libFS"
  661.29 -}
   662.1 --- a/xorg-smproxy/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   662.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   662.3 @@ -1,1 +0,0 @@
   662.4 -../xorg/.icon.png
   662.5 \ No newline at end of file
   663.1 --- a/xorg-smproxy/receipt	Thu Dec 13 00:46:54 2018 +0200
   663.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   663.3 @@ -1,29 +0,0 @@
   663.4 -# SliTaz package receipt v2.
   663.5 -
   663.6 -PACKAGE="xorg-smproxy"
   663.7 -VERSION="1.0.6"
   663.8 -CATEGORY="x-window"
   663.9 -SHORT_DESC="Session Manager Proxy"
  663.10 -MAINTAINER="al.bobylev@gmail.com"
  663.11 -LICENSE="MIT"
  663.12 -WEB_SITE="https://www.x.org/wiki/"
  663.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  663.14 -REPOLOGY="smproxy"
  663.15 -
  663.16 -TARBALL="smproxy-$VERSION.tar.bz2"
  663.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  663.18 -
  663.19 -BUILD_DEPENDS="xorg-util-macros xorg-libSM-dev xorg-libICE-dev xorg-libXt-dev \
  663.20 -xorg-libXmu-dev"
  663.21 -
  663.22 -compile_rules() {
  663.23 -	./configure $CONFIGURE_ARGS &&
  663.24 -	fix libtool &&
  663.25 -	make &&
  663.26 -	make install
  663.27 -}
  663.28 -
  663.29 -genpkg_rules() {
  663.30 -	copy @std
  663.31 -	DEPENDS="xorg-libICE xorg-libSM xorg-libX11 xorg-libXmu xorg-libXt"
  663.32 -}
   664.1 --- a/xorg-twm/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   664.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   664.3 @@ -1,1 +0,0 @@
   664.4 -../xorg/.icon.png
   664.5 \ No newline at end of file
   665.1 --- a/xorg-twm/receipt	Thu Dec 13 00:46:54 2018 +0200
   665.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   665.3 @@ -1,31 +0,0 @@
   665.4 -# SliTaz package receipt v2.
   665.5 -
   665.6 -PACKAGE="xorg-twm"
   665.7 -VERSION="1.0.10"
   665.8 -CATEGORY="x-window"
   665.9 -SHORT_DESC="Simple window manager"
  665.10 -MAINTAINER="al.bobylev@gmail.com"
  665.11 -LICENSE="MIT"
  665.12 -WEB_SITE="https://en.wikipedia.org/wiki/Twm"
  665.13 -REPOLOGY="twm"
  665.14 -
  665.15 -TARBALL="twm-$VERSION.tar.bz2"
  665.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  665.17 -
  665.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXext-dev \
  665.19 -xorg-libXt-dev xorg-libXmu-dev"
  665.20 -
  665.21 -compile_rules() {
  665.22 -	sed -i '/^rcdir =/s,^\(rcdir = \).*,\1/etc/X11/app-defaults,' src/Makefile.in
  665.23 -
  665.24 -	./configure $CONFIGURE_ARGS &&
  665.25 -	make &&
  665.26 -	make install
  665.27 -}
  665.28 -
  665.29 -genpkg_rules() {
  665.30 -	copy @std
  665.31 -	DEPENDS="xorg-libICE xorg-libSM xorg-libX11 xorg-libXext xorg-libXmu \
  665.32 -	xorg-libXt"
  665.33 -	CONFIG_FILES="/etc/X11/app-defaults/system.twmrc"
  665.34 -}
   666.1 --- a/xorg-util-macros/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   666.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   666.3 @@ -1,1 +0,0 @@
   666.4 -../xorg/.icon.png
   666.5 \ No newline at end of file
   667.1 --- a/xorg-util-macros/receipt	Thu Dec 13 00:46:54 2018 +0200
   667.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   667.3 @@ -1,26 +0,0 @@
   667.4 -# SliTaz package receipt v2.
   667.5 -
   667.6 -PACKAGE="xorg-util-macros"
   667.7 -VERSION="1.19.2"
   667.8 -CATEGORY="development"
   667.9 -SHORT_DESC="Autoconf macros used in X modular configure.ac files"
  667.10 -MAINTAINER="devel@slitaz.org"
  667.11 -LICENSE="MIT"
  667.12 -WEB_SITE="https://www.x.org/wiki/"
  667.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/util-macros.html"
  667.14 -HOST_ARCH="any"
  667.15 -REPOLOGY="util-macros"
  667.16 -
  667.17 -TARBALL="util-macros-$VERSION.tar.bz2"
  667.18 -WGET_URL="$XORG_MIRROR/util/$TARBALL"
  667.19 -
  667.20 -compile_rules() {
  667.21 -	./configure $CONFIGURE_ARGS &&
  667.22 -	make &&
  667.23 -	make install
  667.24 -}
  667.25 -
  667.26 -genpkg_rules() {
  667.27 -	copy @dev
  667.28 -	DEPENDS="m4"
  667.29 -}
   668.1 --- a/xorg-x11perf/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   668.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   668.3 @@ -1,1 +0,0 @@
   668.4 -../xorg/.icon.png
   668.5 \ No newline at end of file
   669.1 --- a/xorg-x11perf/receipt	Thu Dec 13 00:46:54 2018 +0200
   669.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   669.3 @@ -1,29 +0,0 @@
   669.4 -# SliTaz package receipt v2.
   669.5 -
   669.6 -PACKAGE="xorg-x11perf"
   669.7 -VERSION="1.6.0"
   669.8 -CATEGORY="x-window"
   669.9 -SHORT_DESC="Utility who runs one or more performance tests and reports"
  669.10 -MAINTAINER="paul@slitaz.org"
  669.11 -LICENSE="MIT"
  669.12 -WEB_SITE="https://www.x.org/wiki/"
  669.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  669.14 -REPOLOGY="x11perf"
  669.15 -
  669.16 -TARBALL="x11perf-$VERSION.tar.bz2"
  669.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  669.18 -
  669.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXmu-dev xorg-xorgproto \
  669.20 -xorg-libXrender-dev xorg-libXft-dev"
  669.21 -
  669.22 -compile_rules() {
  669.23 -	./configure $CONFIGURE_ARGS &&
  669.24 -	fix libtool &&
  669.25 -	make &&
  669.26 -	make install
  669.27 -}
  669.28 -
  669.29 -genpkg_rules() {
  669.30 -	copy @std
  669.31 -	DEPENDS="xorg-libX11 xorg-libXext xorg-libXft xorg-libXmu xorg-libXrender"
  669.32 -}
   670.1 --- a/xorg-xauth/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   670.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   670.3 @@ -1,1 +0,0 @@
   670.4 -../xorg/.icon.png
   670.5 \ No newline at end of file
   671.1 --- a/xorg-xauth/receipt	Thu Dec 13 00:46:54 2018 +0200
   671.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   671.3 @@ -1,30 +0,0 @@
   671.4 -# SliTaz package receipt v2.
   671.5 -
   671.6 -PACKAGE="xorg-xauth"
   671.7 -VERSION="1.0.10"
   671.8 -CATEGORY="x-window"
   671.9 -SHORT_DESC="X authority file utility"
  671.10 -MAINTAINER="devel@slitaz.org"
  671.11 -LICENSE="MIT"
  671.12 -WEB_SITE="https://www.x.org/wiki/"
  671.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  671.14 -REPOLOGY="xauth"
  671.15 -
  671.16 -TARBALL="xauth-$VERSION.tar.bz2"
  671.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  671.18 -
  671.19 -BUILD_DEPENDS="xorg-libXmu-dev"
  671.20 -
  671.21 -compile_rules() {
  671.22 -	./configure $CONFIGURE_ARGS &&
  671.23 -	fix libtool &&
  671.24 -	make &&
  671.25 -	make install
  671.26 -}
  671.27 -
  671.28 -genpkg_rules() {
  671.29 -	copy @std
  671.30 -#	mkdir -p $fs/usr/X11R6
  671.31 -#	ln -s ../bin $fs/usr/X11R6/bin
  671.32 -	DEPENDS="xorg-libX11 xorg-libXau xorg-libXext xorg-libXmu"
  671.33 -}
   672.1 --- a/xorg-xbacklight/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   672.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   672.3 @@ -1,1 +0,0 @@
   672.4 -../xorg/.icon.png
   672.5 \ No newline at end of file
   673.1 --- a/xorg-xbacklight/receipt	Thu Dec 13 00:46:54 2018 +0200
   673.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   673.3 @@ -1,29 +0,0 @@
   673.4 -# SliTaz package receipt v2.
   673.5 -
   673.6 -PACKAGE="xorg-xbacklight"
   673.7 -VERSION="1.2.2"
   673.8 -CATEGORY="x-window"
   673.9 -SHORT_DESC="Adjust backlight brightness using RandR extension"
  673.10 -MAINTAINER="devel@slitaz.org"
  673.11 -LICENSE="MIT"
  673.12 -WEB_SITE="https://www.x.org/wiki/"
  673.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  673.14 -REPOLOGY="xbacklight"
  673.15 -
  673.16 -TARBALL="xbacklight-$VERSION.tar.bz2"
  673.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  673.18 -
  673.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxcb-dev xorg-xcb-util-dev \
  673.20 -xorg-libXrandr-dev"
  673.21 -
  673.22 -compile_rules() {
  673.23 -	./configure $CONFIGURE_ARGS &&
  673.24 -	make &&
  673.25 -	make install
  673.26 -}
  673.27 -
  673.28 -genpkg_rules() {
  673.29 -	copy @std
  673.30 -	DEPENDS="xorg-libxcb xorg-xcb-util"
  673.31 -	TAGS="utility xorg power backlight"
  673.32 -}
   674.1 --- a/xorg-xbitmaps/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   674.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   674.3 @@ -1,1 +0,0 @@
   674.4 -../xorg/.icon.png
   674.5 \ No newline at end of file
   675.1 --- a/xorg-xbitmaps/receipt	Thu Dec 13 00:46:54 2018 +0200
   675.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   675.3 @@ -1,28 +0,0 @@
   675.4 -# SliTaz package receipt v2.
   675.5 -
   675.6 -PACKAGE="xorg-xbitmaps"
   675.7 -VERSION="1.1.2"
   675.8 -CATEGORY="development"
   675.9 -SHORT_DESC="Standard set of X bitmaps"
  675.10 -MAINTAINER="devel@slitaz.org"
  675.11 -LICENSE="MIT"
  675.12 -WEB_SITE="https://www.x.org/wiki/"
  675.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xbitmaps.html"
  675.14 -HOST_ARCH="any"
  675.15 -REPOLOGY="xbitmaps"
  675.16 -
  675.17 -TARBALL="xbitmaps-$VERSION.tar.bz2"
  675.18 -WGET_URL="$XORG_MIRROR/data/$TARBALL"
  675.19 -
  675.20 -BUILD_DEPENDS="xorg-util-macros"
  675.21 -
  675.22 -compile_rules() {
  675.23 -	./configure $CONFIGURE_ARGS &&
  675.24 -	make &&
  675.25 -	make install
  675.26 -}
  675.27 -
  675.28 -genpkg_rules() {
  675.29 -	copy @dev
  675.30 -	DEPENDS="xorg-util-macros"
  675.31 -}
   676.1 --- a/xorg-xcalc/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   676.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   676.3 @@ -1,1 +0,0 @@
   676.4 -../xorg/.icon.png
   676.5 \ No newline at end of file
   677.1 --- a/xorg-xcalc/receipt	Thu Dec 13 00:46:54 2018 +0200
   677.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   677.3 @@ -1,28 +0,0 @@
   677.4 -# SliTaz package receipt v2.
   677.5 -
   677.6 -PACKAGE="xorg-xcalc"
   677.7 -VERSION="1.0.6"
   677.8 -CATEGORY="x-window"
   677.9 -SHORT_DESC="Scientific calculator for X"
  677.10 -MAINTAINER="al.bobylev@gmail.com"
  677.11 -LICENSE="MIT"
  677.12 -WEB_SITE="https://www.x.org/wiki/"
  677.13 -REPOLOGY="xcalc"
  677.14 -
  677.15 -TARBALL="xcalc-$VERSION.tar.bz2"
  677.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  677.17 -
  677.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXt-dev xorg-libX11-dev \
  677.19 -xorg-xorgproto"
  677.20 -
  677.21 -compile_rules() {
  677.22 -	./configure $CONFIGURE_ARGS &&
  677.23 -	make &&
  677.24 -	make install
  677.25 -}
  677.26 -
  677.27 -genpkg_rules() {
  677.28 -	copy @std
  677.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXt"
  677.30 -	CONFIG_FILES="/etc/X11/app-defaults/XCalc /etc/X11/app-defaults/XCalc-color"
  677.31 -}
   678.1 --- a/xorg-xcb-proto/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   678.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   678.3 @@ -1,1 +0,0 @@
   678.4 -../xorg/.icon.png
   678.5 \ No newline at end of file
   679.1 --- a/xorg-xcb-proto/description.txt	Thu Dec 13 00:46:54 2018 +0200
   679.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   679.3 @@ -1,3 +0,0 @@
   679.4 -The X protocol C-language Binding (XCB) is a replacement for Xlib featuring
   679.5 -a small footprint, latency hiding, direct access to the protocol, improved
   679.6 -threading support, and extensibility.
   680.1 --- a/xorg-xcb-proto/receipt	Thu Dec 13 00:46:54 2018 +0200
   680.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   680.3 @@ -1,28 +0,0 @@
   680.4 -# SliTaz package receipt v2.
   680.5 -
   680.6 -PACKAGE="xorg-xcb-proto"
   680.7 -VERSION="1.13"
   680.8 -CATEGORY="development"
   680.9 -SHORT_DESC="X protocol descriptions for XCB"
  680.10 -MAINTAINER="devel@slitaz.org"
  680.11 -LICENSE="MIT"
  680.12 -WEB_SITE="https://xcb.freedesktop.org/"
  680.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-proto.html"
  680.14 -HOST_ARCH="any"
  680.15 -REPOLOGY="xcb-proto"
  680.16 -
  680.17 -TARBALL="xcb-proto-$VERSION.tar.bz2"
  680.18 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  680.19 -
  680.20 -BUILD_DEPENDS="python-dev libxml2-tools"
  680.21 -
  680.22 -compile_rules() {
  680.23 -	./configure $CONFIGURE_ARGS &&
  680.24 -	make &&
  680.25 -	make install
  680.26 -}
  680.27 -
  680.28 -genpkg_rules() {
  680.29 -	copy @std @dev
  680.30 -	DEPENDS="python"
  680.31 -}
   681.1 --- a/xorg-xcb-util-cursor/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   681.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   681.3 @@ -1,1 +0,0 @@
   681.4 -../xorg/.icon.png
   681.5 \ No newline at end of file
   682.1 --- a/xorg-xcb-util-cursor/receipt	Thu Dec 13 00:46:54 2018 +0200
   682.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   682.3 @@ -1,39 +0,0 @@
   682.4 -# SliTaz package receipt v2.
   682.5 -
   682.6 -PACKAGE="xorg-xcb-util-cursor"
   682.7 -VERSION="0.1.3"
   682.8 -CATEGORY="x-window"
   682.9 -SHORT_DESC="Module that implements the XCB cursor library"
  682.10 -MAINTAINER="al.bobylev@gmail.com"
  682.11 -LICENSE="MIT"
  682.12 -WEB_SITE="https://xcb.freedesktop.org/"
  682.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-cursor.html"
  682.14 -REPOLOGY="xcb-util-cursor"
  682.15 -
  682.16 -TARBALL="xcb-util-cursor-$VERSION.tar.bz2"
  682.17 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  682.18 -
  682.19 -BUILD_DEPENDS="xorg-libxcb-dev xorg-xcb-util-dev xorg-xcb-util-renderutil-dev \
  682.20 -xorg-xcb-util-image-dev"
  682.21 -SPLIT="$PACKAGE-dev"
  682.22 -
  682.23 -compile_rules() {
  682.24 -	./configure $CONFIGURE_ARGS &&
  682.25 -	fix libtool &&
  682.26 -	make &&
  682.27 -	make install
  682.28 -}
  682.29 -
  682.30 -genpkg_rules() {
  682.31 -	case $PACKAGE in
  682.32 -		*-xcb-util-cursor)
  682.33 -			copy @std
  682.34 -			DEPENDS="xorg-libxcb xorg-xcb-util-image xorg-xcb-util-renderutil"
  682.35 -			;;
  682.36 -		*-dev)
  682.37 -			copy @dev
  682.38 -			DEPENDS="xorg-xcb-util-cursor \
  682.39 -			xorg-libxcb-dev xorg-xcb-util-image-dev xorg-xcb-util-renderutil-dev"
  682.40 -			;;
  682.41 -	esac
  682.42 -}
   683.1 --- a/xorg-xcb-util-image/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   683.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   683.3 @@ -1,1 +0,0 @@
   683.4 -../xorg/.icon.png
   683.5 \ No newline at end of file
   684.1 --- a/xorg-xcb-util-image/receipt	Thu Dec 13 00:46:54 2018 +0200
   684.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   684.3 @@ -1,38 +0,0 @@
   684.4 -# SliTaz package receipt v2.
   684.5 -
   684.6 -PACKAGE="xorg-xcb-util-image"
   684.7 -VERSION="0.4.0"
   684.8 -CATEGORY="x-window"
   684.9 -SHORT_DESC="Utility libraries for XC Binding - Port of Xlib's XImage and \
  684.10 -XShmImage functions"
  684.11 -MAINTAINER="devel@slitaz.org"
  684.12 -LICENSE="MIT"
  684.13 -WEB_SITE="https://xcb.freedesktop.org/"
  684.14 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-image.html"
  684.15 -REPOLOGY="xcb-util-image"
  684.16 -
  684.17 -TARBALL="xcb-util-image-$VERSION.tar.bz2"
  684.18 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  684.19 -
  684.20 -BUILD_DEPENDS="xorg-libxcb-dev xorg-xcb-util-dev xorg-util-macros"
  684.21 -SPLIT="$PACKAGE-dev"
  684.22 -
  684.23 -compile_rules() {
  684.24 -	./configure $CONFIGURE_ARGS &&
  684.25 -	fix libtool &&
  684.26 -	make &&
  684.27 -	make install
  684.28 -}
  684.29 -
  684.30 -genpkg_rules() {
  684.31 -	case $PACKAGE in
  684.32 -		*-image)
  684.33 -			copy @std
  684.34 -			DEPENDS="xorg-libxcb xorg-xcb-util"
  684.35 -			;;
  684.36 -		*-dev)
  684.37 -			copy @dev
  684.38 -			DEPENDS="xorg-xcb-util-image xorg-libxcb-dev"
  684.39 -			;;
  684.40 -	esac
  684.41 -}
   685.1 --- a/xorg-xcb-util-keysyms/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   685.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   685.3 @@ -1,1 +0,0 @@
   685.4 -../xorg/.icon.png
   685.5 \ No newline at end of file
   686.1 --- a/xorg-xcb-util-keysyms/receipt	Thu Dec 13 00:46:54 2018 +0200
   686.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   686.3 @@ -1,37 +0,0 @@
   686.4 -# SliTaz package receipt v2.
   686.5 -
   686.6 -PACKAGE="xorg-xcb-util-keysyms"
   686.7 -VERSION="0.4.0"
   686.8 -CATEGORY="x-window"
   686.9 -SHORT_DESC="Utility libraries for XC Binding"
  686.10 -MAINTAINER="devel@slitaz.org"
  686.11 -LICENSE="GPL"
  686.12 -WEB_SITE="https://xcb.freedesktop.org/"
  686.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-keysyms.html"
  686.14 -REPOLOGY="xcb-util-keysyms"
  686.15 -
  686.16 -TARBALL="xcb-util-keysyms-$VERSION.tar.bz2"
  686.17 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  686.18 -
  686.19 -BUILD_DEPENDS="xorg-libxcb-dev xorg-util-macros"
  686.20 -SPLIT="$PACKAGE-dev"
  686.21 -
  686.22 -compile_rules() {
  686.23 -	./configure $CONFIGURE_ARGS &&
  686.24 -	fix libtool &&
  686.25 -	make &&
  686.26 -	make install
  686.27 -}
  686.28 -
  686.29 -genpkg_rules() {
  686.30 -	case $PACKAGE in
  686.31 -		*-keysyms)
  686.32 -			copy @std
  686.33 -			DEPENDS="xorg-libxcb"
  686.34 -			;;
  686.35 -		*-dev)
  686.36 -			copy @dev
  686.37 -			DEPENDS="xorg-xcb-util-keysyms xorg-libxcb-dev"
  686.38 -			;;
  686.39 -	esac
  686.40 -}
   687.1 --- a/xorg-xcb-util-renderutil/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   687.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   687.3 @@ -1,1 +0,0 @@
   687.4 -../xorg/.icon.png
   687.5 \ No newline at end of file
   688.1 --- a/xorg-xcb-util-renderutil/receipt	Thu Dec 13 00:46:54 2018 +0200
   688.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   688.3 @@ -1,37 +0,0 @@
   688.4 -# SliTaz package receipt v2.
   688.5 -
   688.6 -PACKAGE="xorg-xcb-util-renderutil"
   688.7 -VERSION="0.3.9"
   688.8 -CATEGORY="x-window"
   688.9 -SHORT_DESC="Additional extension to the XCB library"
  688.10 -MAINTAINER="al.bobylev@gmail.com"
  688.11 -LICENSE="MIT"
  688.12 -WEB_SITE="https://xcb.freedesktop.org/"
  688.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-renderutil.html"
  688.14 -REPOLOGY="xcb-util-renderutil"
  688.15 -
  688.16 -TARBALL="xcb-util-renderutil-$VERSION.tar.bz2"
  688.17 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  688.18 -
  688.19 -BUILD_DEPENDS="xorg-libxcb-dev xorg-util-macros"
  688.20 -SPLIT="$PACKAGE-dev"
  688.21 -
  688.22 -compile_rules() {
  688.23 -	./configure $CONFIGURE_ARGS &&
  688.24 -	fix libtool &&
  688.25 -	make &&
  688.26 -	make install
  688.27 -}
  688.28 -
  688.29 -genpkg_rules() {
  688.30 -	case $PACKAGE in
  688.31 -		*-renderutil)
  688.32 -			copy @std
  688.33 -			DEPENDS="xorg-libxcb"
  688.34 -			;;
  688.35 -		*-dev)
  688.36 -			copy @dev
  688.37 -			DEPENDS="xorg-xcb-util-renderutil xorg-libxcb-dev"
  688.38 -			;;
  688.39 -	esac
  688.40 -}
   689.1 --- a/xorg-xcb-util-wm/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   689.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   689.3 @@ -1,1 +0,0 @@
   689.4 -../xorg/.icon.png
   689.5 \ No newline at end of file
   690.1 --- a/xorg-xcb-util-wm/receipt	Thu Dec 13 00:46:54 2018 +0200
   690.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   690.3 @@ -1,38 +0,0 @@
   690.4 -# SliTaz package receipt v2.
   690.5 -
   690.6 -PACKAGE="xorg-xcb-util-wm"
   690.7 -VERSION="0.4.1"
   690.8 -CATEGORY="x-window"
   690.9 -SHORT_DESC="Utility libraries for XC Binding - client and window-manager \
  690.10 -helpers for ICCCM"
  690.11 -MAINTAINER="devel@slitaz.org"
  690.12 -LICENSE="MIT"
  690.13 -WEB_SITE="https://xcb.freedesktop.org/"
  690.14 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util-wm.html"
  690.15 -REPOLOGY="xcb-util-wm"
  690.16 -
  690.17 -TARBALL="xcb-util-wm-$VERSION.tar.bz2"
  690.18 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  690.19 -
  690.20 -BUILD_DEPENDS="xorg-libxcb-dev xorg-util-macros"
  690.21 -SPLIT="$PACKAGE-dev"
  690.22 -
  690.23 -compile_rules() {
  690.24 -	./configure $CONFIGURE_ARGS &&
  690.25 -	fix libtool &&
  690.26 -	make &&
  690.27 -	make install
  690.28 -}
  690.29 -
  690.30 -genpkg_rules() {
  690.31 -	case $PACKAGE in
  690.32 -		*-wm)
  690.33 -			copy @std
  690.34 -			DEPENDS="xorg-libxcb"
  690.35 -			;;
  690.36 -		*-dev)
  690.37 -			copy @dev
  690.38 -			DEPENDS="xorg-xcb-util-wm xorg-libxcb-dev"
  690.39 -			;;
  690.40 -	esac
  690.41 -}
   691.1 --- a/xorg-xcb-util/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   691.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   691.3 @@ -1,1 +0,0 @@
   691.4 -../xorg/.icon.png
   691.5 \ No newline at end of file
   692.1 --- a/xorg-xcb-util/description.txt	Thu Dec 13 00:46:54 2018 +0200
   692.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   692.3 @@ -1,6 +0,0 @@
   692.4 -The XCB util modules provides a number of libraries which sit on top of libxcb,
   692.5 -the core X protocol library, and some of the extension libraries. These
   692.6 -experimental libraries provide convenience functions and interfaces which make
   692.7 -the raw X protocol more usable. Some of the libraries also provide client-side
   692.8 -code which is not strictly part of the X protocol but which have traditionally
   692.9 -been provided by Xlib.
   693.1 --- a/xorg-xcb-util/receipt	Thu Dec 13 00:46:54 2018 +0200
   693.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   693.3 @@ -1,37 +0,0 @@
   693.4 -# SliTaz package receipt v2.
   693.5 -
   693.6 -PACKAGE="xorg-xcb-util"
   693.7 -VERSION="0.4.0"
   693.8 -CATEGORY="x-window"
   693.9 -SHORT_DESC="XCB Utilites"
  693.10 -MAINTAINER="devel@slitaz.org"
  693.11 -LICENSE="MIT"
  693.12 -WEB_SITE="https://xcb.freedesktop.org/"
  693.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcb-util.html"
  693.14 -REPOLOGY="xcb-util"
  693.15 -
  693.16 -TARBALL="xcb-util-$VERSION.tar.bz2"
  693.17 -WGET_URL="$XORG_MIRROR/xcb/$TARBALL"
  693.18 -
  693.19 -BUILD_DEPENDS="xorg-libxcb-dev gperf"
  693.20 -SPLIT="$PACKAGE-dev"
  693.21 -
  693.22 -compile_rules() {
  693.23 -	./configure $CONFIGURE_ARGS &&
  693.24 -	fix libtool &&
  693.25 -	make &&
  693.26 -	make install
  693.27 -}
  693.28 -
  693.29 -genpkg_rules() {
  693.30 -	case $PACKAGE in
  693.31 -		*-util)
  693.32 -			copy @std
  693.33 -			DEPENDS="xorg-libxcb"
  693.34 -			;;
  693.35 -		*-dev)
  693.36 -			copy @dev
  693.37 -			DEPENDS="xorg-xcb-util xorg-libxcb-dev"
  693.38 -			;;
  693.39 -	esac
  693.40 -}
   694.1 --- a/xorg-xclipboard/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   694.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   694.3 @@ -1,1 +0,0 @@
   694.4 -../xorg/.icon.png
   694.5 \ No newline at end of file
   695.1 --- a/xorg-xclipboard/receipt	Thu Dec 13 00:46:54 2018 +0200
   695.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   695.3 @@ -1,28 +0,0 @@
   695.4 -# SliTaz package receipt v2.
   695.5 -
   695.6 -PACKAGE="xorg-xclipboard"
   695.7 -VERSION="1.1.3"
   695.8 -CATEGORY="x-window"
   695.9 -SHORT_DESC="X clipboard manager"
  695.10 -MAINTAINER="al.bobylev@gmail.com"
  695.11 -LICENSE="MIT"
  695.12 -WEB_SITE="https://www.x.org/wiki/"
  695.13 -REPOLOGY="xclipboard"
  695.14 -
  695.15 -TARBALL="xclipboard-$VERSION.tar.bz2"
  695.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  695.17 -
  695.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXmu-dev xorg-libXt-dev \
  695.19 -xorg-libX11-dev xorg-xorgproto"
  695.20 -
  695.21 -compile_rules() {
  695.22 -	./configure $CONFIGURE_ARGS &&
  695.23 -	make &&
  695.24 -	make install
  695.25 -}
  695.26 -
  695.27 -genpkg_rules() {
  695.28 -	copy @std
  695.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  695.30 -	CONFIG_FILES="/etc/X11/app-defaults/XClipboard"
  695.31 -}
   696.1 --- a/xorg-xclock/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   696.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   696.3 @@ -1,1 +0,0 @@
   696.4 -../xorg/.icon.png
   696.5 \ No newline at end of file
   697.1 --- a/xorg-xclock/receipt	Thu Dec 13 00:46:54 2018 +0200
   697.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   697.3 @@ -1,30 +0,0 @@
   697.4 -# SliTaz package receipt v2.
   697.5 -
   697.6 -PACKAGE="xorg-xclock"
   697.7 -VERSION="1.0.7"
   697.8 -CATEGORY="x-window"
   697.9 -SHORT_DESC="X clock"
  697.10 -MAINTAINER="devel@slitaz.org"
  697.11 -LICENSE="MIT"
  697.12 -WEB_SITE="https://www.x.org/wiki/"
  697.13 -REPOLOGY="xclock"
  697.14 -
  697.15 -TARBALL="xclock-$VERSION.tar.bz2"
  697.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  697.17 -
  697.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXmu-dev \
  697.19 -xorg-libX11-dev xorg-libXrender-dev xorg-libXft-dev xorg-libxkbfile-dev"
  697.20 -
  697.21 -compile_rules() {
  697.22 -	./configure $CONFIGURE_ARGS &&
  697.23 -	make &&
  697.24 -	make install
  697.25 -}
  697.26 -
  697.27 -genpkg_rules() {
  697.28 -	copy @std
  697.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXft xorg-libXmu xorg-libXrender \
  697.30 -	xorg-libXt xorg-libxkbfile"
  697.31 -	CONFIG_FILES="/etc/X11/app-defaults/XClock \
  697.32 -	/etc/X11/app-defaults/XClock-color"
  697.33 -}
   698.1 --- a/xorg-xcmsdb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   698.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   698.3 @@ -1,1 +0,0 @@
   698.4 -../xorg/.icon.png
   698.5 \ No newline at end of file
   699.1 --- a/xorg-xcmsdb/receipt	Thu Dec 13 00:46:54 2018 +0200
   699.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   699.3 @@ -1,28 +0,0 @@
   699.4 -# SliTaz package receipt v2.
   699.5 -
   699.6 -PACKAGE="xorg-xcmsdb"
   699.7 -VERSION="1.0.5"
   699.8 -CATEGORY="x-window"
   699.9 -SHORT_DESC="Device Color Characterization utility for X Color Management System"
  699.10 -MAINTAINER="al.bobylev@gmail.com"
  699.11 -LICENSE="MIT"
  699.12 -WEB_SITE="https://www.x.org/wiki/"
  699.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  699.14 -REPOLOGY="xcmsdb"
  699.15 -
  699.16 -TARBALL="xcmsdb-$VERSION.tar.bz2"
  699.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  699.18 -
  699.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev"
  699.20 -
  699.21 -compile_rules() {
  699.22 -	./configure $CONFIGURE_ARGS &&
  699.23 -	fix libtool &&
  699.24 -	make &&
  699.25 -	make install
  699.26 -}
  699.27 -
  699.28 -genpkg_rules() {
  699.29 -	copy @std
  699.30 -	DEPENDS="xorg-libX11"
  699.31 -}
   700.1 --- a/xorg-xcompmgr/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   700.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   700.3 @@ -1,1 +0,0 @@
   700.4 -../xorg/.icon.png
   700.5 \ No newline at end of file
   701.1 --- a/xorg-xcompmgr/receipt	Thu Dec 13 00:46:54 2018 +0200
   701.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   701.3 @@ -1,34 +0,0 @@
   701.4 -# SliTaz package receipt v2.
   701.5 -
   701.6 -PACKAGE="xorg-xcompmgr"
   701.7 -VERSION="1.1.7"
   701.8 -CATEGORY="x-window"
   701.9 -SHORT_DESC="X composite manager"
  701.10 -MAINTAINER="devel@slitaz.org"
  701.11 -LICENSE="MIT"
  701.12 -WEB_SITE="https://www.x.org/wiki/"
  701.13 -REPOLOGY="xcompmgr"
  701.14 -
  701.15 -TARBALL="xcompmgr-$VERSION.tar.bz2"
  701.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  701.17 -
  701.18 -BUILD_DEPENDS="xorg-libX11-dev xorg-libXdamage-dev xorg-libXcomposite-dev \
  701.19 -xorg-libXrender-dev xorg-libXfixes-dev xorg-libXext-dev xorg-libXau-dev \
  701.20 -xorg-libXdmcp-dev xorg-libxcb-dev"
  701.21 -BUILD_DEPENDS="xorg-util-macros xorg-libXcomposite-dev xorg-libXfixes-dev \
  701.22 -xorg-libXdamage-dev xorg-libXrender-dev xorg-libXext-dev"
  701.23 -
  701.24 -compile_rules() {
  701.25 -	./configure $CONFIGURE_ARGS &&
  701.26 -	make &&
  701.27 -	make install || return 1
  701.28 -
  701.29 -	install -Dm644 $stuff/autostart/xcompmgr.desktop \
  701.30 -		$install/etc/xdg/autostart/xcompmgr.desktop
  701.31 -}
  701.32 -
  701.33 -genpkg_rules() {
  701.34 -	copy @std
  701.35 -	DEPENDS="xorg-libX11 xorg-libXcomposite xorg-libXdamage xorg-libXext \
  701.36 -	xorg-libXfixes xorg-libXrender"
  701.37 -}
   702.1 --- a/xorg-xcompmgr/stuff/autostart/xcompmgr.desktop	Thu Dec 13 00:46:54 2018 +0200
   702.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   702.3 @@ -1,8 +0,0 @@
   702.4 -[Desktop Entry]
   702.5 -Type=Application
   702.6 -Name=Desktop effects with Xcompmgr
   702.7 -Name[fr]=Effects de bureau avec Xcompmgr
   702.8 -Name[pt]=Efeitos do desktop com Xcompmgr
   702.9 -Name[pt_BR]=Efeitos do desktop com Xcompmgr
  702.10 -Exec=xcompmgr -c -r 10 -o 0.5
  702.11 -NotShowIn=LXDE;XFCE;Razor;
   703.1 --- a/xorg-xcompmgr/stuff/patches/46285.diff	Thu Dec 13 00:46:54 2018 +0200
   703.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   703.3 @@ -1,28 +0,0 @@
   703.4 ---- a/xcompmgr.c	2011-11-19 01:49:52.000000000 -0600
   703.5 -+++ b/xcompmgr.c	2012-08-11 21:58:58.000000000 -0500
   703.6 -@@ -1028,7 +1028,6 @@
   703.7 - 	{
   703.8 - 	    w->borderClip = XFixesCreateRegion (dpy, NULL, 0);
   703.9 - 	    XFixesCopyRegion (dpy, w->borderClip, region);
  703.10 --	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  703.11 - 	}
  703.12 - 	w->prev_trans = t;
  703.13 - 	t = w;
  703.14 -@@ -1080,6 +1079,8 @@
  703.15 - 	if (w->mode == WINDOW_TRANS)
  703.16 - 	{
  703.17 - 	    int	x, y, wid, hei;
  703.18 -+	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  703.19 -+	    XFixesSetPictureClipRegion(dpy, rootBuffer, 0, 0, w->borderClip);
  703.20 - #if HAS_NAME_WINDOW_PIXMAP
  703.21 - 	    x = w->a.x;
  703.22 - 	    y = w->a.y;
  703.23 -@@ -1099,6 +1100,8 @@
  703.24 - 	else if (w->mode == WINDOW_ARGB)
  703.25 - 	{
  703.26 - 	    int	x, y, wid, hei;
  703.27 -+	    XFixesIntersectRegion(dpy, w->borderClip, w->borderClip, w->borderSize);
  703.28 -+	    XFixesSetPictureClipRegion(dpy, rootBuffer, 0, 0, w->borderClip);
  703.29 - #if HAS_NAME_WINDOW_PIXMAP
  703.30 - 	    x = w->a.x;
  703.31 - 	    y = w->a.y;
   704.1 --- a/xorg-xcompmgr/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   704.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   704.3 @@ -1,1 +0,0 @@
   704.4 -46285.diff # bugs.freedesktop.org/show_bug.cgi?id=46285
   705.1 --- a/xorg-xcursor-themes/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   705.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   705.3 @@ -1,1 +0,0 @@
   705.4 -../xorg/.icon.png
   705.5 \ No newline at end of file
   706.1 --- a/xorg-xcursor-themes/description.txt	Thu Dec 13 00:46:54 2018 +0200
   706.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   706.3 @@ -1,3 +0,0 @@
   706.4 -This is a default set of cursor themes for use with libXcursor, originally
   706.5 -created for the XFree86 Project, and now shipped as part of the X.Org software
   706.6 -distribution.
   707.1 --- a/xorg-xcursor-themes/receipt	Thu Dec 13 00:46:54 2018 +0200
   707.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   707.3 @@ -1,23 +0,0 @@
   707.4 -# SliTaz package receipt v2.
   707.5 -
   707.6 -PACKAGE="xorg-xcursor-themes"
   707.7 -VERSION="1.0.5"
   707.8 -CATEGORY="x-window"
   707.9 -SHORT_DESC="Standard set of X cursors"
  707.10 -MAINTAINER="al.bobylev@gmail.com"
  707.11 -LICENSE="MIT"
  707.12 -WEB_SITE="https://www.x.org/wiki/"
  707.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xcursor-themes.html"
  707.14 -HOST_ARCH="any"
  707.15 -REPOLOGY="xcursor-themes"
  707.16 -
  707.17 -TARBALL="xcursor-themes-$VERSION.tar.bz2"
  707.18 -WGET_URL="$XORG_MIRROR/data/$TARBALL"
  707.19 -
  707.20 -BUILD_DEPENDS="xorg-util-macros xorg-xcursorgen xorg-libXcursor-dev"
  707.21 -
  707.22 -compile_rules() {
  707.23 -	./configure $CONFIGURE_ARGS &&
  707.24 -	make &&
  707.25 -	make install
  707.26 -}
   708.1 --- a/xorg-xcursorgen/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   708.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   708.3 @@ -1,1 +0,0 @@
   708.4 -../xorg/.icon.png
   708.5 \ No newline at end of file
   709.1 --- a/xorg-xcursorgen/receipt	Thu Dec 13 00:46:54 2018 +0200
   709.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   709.3 @@ -1,29 +0,0 @@
   709.4 -# SliTaz package receipt v2.
   709.5 -
   709.6 -PACKAGE="xorg-xcursorgen"
   709.7 -VERSION="1.0.6"
   709.8 -CATEGORY="x-window"
   709.9 -SHORT_DESC="Create an X cursor file from PNG images"
  709.10 -MAINTAINER="devel@slitaz.org"
  709.11 -LICENSE="MIT"
  709.12 -WEB_SITE="https://www.x.org/wiki/"
  709.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  709.14 -REPOLOGY="xcursorgen"
  709.15 -
  709.16 -TARBALL="xcursorgen-$VERSION.tar.bz2"
  709.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  709.18 -
  709.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXcursor-dev \
  709.20 -libpng16-dev"
  709.21 -
  709.22 -compile_rules() {
  709.23 -	./configure $CONFIGURE_ARGS &&
  709.24 -	fix libtool &&
  709.25 -	make &&
  709.26 -	make install
  709.27 -}
  709.28 -
  709.29 -genpkg_rules() {
  709.30 -	copy @std
  709.31 -	DEPENDS="libpng16 xorg-libX11 xorg-libXcursor"
  709.32 -}
   710.1 --- a/xorg-xdpyinfo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   710.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   710.3 @@ -1,1 +0,0 @@
   710.4 -../xorg/.icon.png
   710.5 \ No newline at end of file
   711.1 --- a/xorg-xdpyinfo/receipt	Thu Dec 13 00:46:54 2018 +0200
   711.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   711.3 @@ -1,34 +0,0 @@
   711.4 -# SliTaz package receipt v2.
   711.5 -
   711.6 -PACKAGE="xorg-xdpyinfo"
   711.7 -VERSION="1.3.2"
   711.8 -CATEGORY="x-window"
   711.9 -SHORT_DESC="Display information utility for X"
  711.10 -MAINTAINER="devel@slitaz.org"
  711.11 -LICENSE="MIT"
  711.12 -WEB_SITE="https://www.x.org/wiki/"
  711.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  711.14 -REPOLOGY="xdpyinfo"
  711.15 -
  711.16 -TARBALL="xdpyinfo-$VERSION.tar.bz2"
  711.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  711.18 -
  711.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXext-dev xorg-libX11-dev \
  711.20 -xorg-libXtst-dev xorg-libxcb-dev xorg-xorgproto xorg-libXxf86vm-dev \
  711.21 -xorg-libXxf86dga-dev xorg-libXrender-dev xorg-libXcomposite-dev \
  711.22 -xorg-libXinerama-dev xorg-libdmx-dev xorg-libXxf86misc-dev"
  711.23 -
  711.24 -compile_rules() {
  711.25 -	./configure $CONFIGURE_ARGS &&
  711.26 -	fix libtool &&
  711.27 -	make &&
  711.28 -	make install
  711.29 -}
  711.30 -
  711.31 -genpkg_rules() {
  711.32 -	copy @std
  711.33 -	DEPENDS="xorg-libX11 xorg-libXcomposite xorg-libXext xorg-libXi \
  711.34 -	xorg-libXinerama xorg-libXrender xorg-libXtst xorg-libXxf86dga \
  711.35 -	xorg-libXxf86misc xorg-libXxf86vm xorg-libdmx xorg-libxcb"
  711.36 -	TAGS="utility xorg display"
  711.37 -}
   712.1 --- a/xorg-xdriinfo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   712.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   712.3 @@ -1,1 +0,0 @@
   712.4 -../xorg/.icon.png
   712.5 \ No newline at end of file
   713.1 --- a/xorg-xdriinfo/receipt	Thu Dec 13 00:46:54 2018 +0200
   713.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   713.3 @@ -1,28 +0,0 @@
   713.4 -# SliTaz package receipt v2.
   713.5 -
   713.6 -PACKAGE="xorg-xdriinfo"
   713.7 -VERSION="1.0.6"
   713.8 -CATEGORY="x-window"
   713.9 -SHORT_DESC="Query configuration information of DRI drivers"
  713.10 -MAINTAINER="devel@slitaz.org"
  713.11 -LICENSE="MIT"
  713.12 -WEB_SITE="https://www.x.org/wiki/"
  713.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  713.14 -REPOLOGY="xdriinfo"
  713.15 -
  713.16 -TARBALL="xdriinfo-$VERSION.tar.bz2"
  713.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  713.18 -
  713.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto mesa-dev"
  713.20 -
  713.21 -compile_rules() {
  713.22 -	./configure $CONFIGURE_ARGS &&
  713.23 -	make &&
  713.24 -	make install
  713.25 -}
  713.26 -
  713.27 -genpkg_rules() {
  713.28 -	copy @std
  713.29 -	DEPENDS="mesa xorg-libX11"
  713.30 -	SUGGESTED="nvidia"
  713.31 -}
   714.1 --- a/xorg-xedit/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   714.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   714.3 @@ -1,1 +0,0 @@
   714.4 -../xorg/.icon.png
   714.5 \ No newline at end of file
   715.1 --- a/xorg-xedit/receipt	Thu Dec 13 00:46:54 2018 +0200
   715.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   715.3 @@ -1,29 +0,0 @@
   715.4 -# SliTaz package receipt v2.
   715.5 -
   715.6 -PACKAGE="xorg-xedit"
   715.7 -VERSION="1.2.2"
   715.8 -CATEGORY="x-window"
   715.9 -SHORT_DESC="Simple text editor for X"
  715.10 -MAINTAINER="pascal.bellard@slitaz.org"
  715.11 -LICENSE="MIT"
  715.12 -WEB_SITE="https://www.x.org/wiki/"
  715.13 -REPOLOGY="xedit"
  715.14 -
  715.15 -TARBALL="xedit-$VERSION.tar.bz2"
  715.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  715.17 -
  715.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXmu-dev xorg-libXt-dev \
  715.19 -xorg-libX11-dev"
  715.20 -
  715.21 -compile_rules() {
  715.22 -	./configure $CONFIGURE_ARGS &&
  715.23 -	make &&
  715.24 -	make install
  715.25 -}
  715.26 -
  715.27 -genpkg_rules() {
  715.28 -	copy @std
  715.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  715.30 -	CONFIG_FILES="/etc/X11/app-defaults/Xedit /etc/X11/app-defaults/Xedit-color"
  715.31 -	TAGS="text-editor"
  715.32 -}
   716.1 --- a/xorg-xev/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   716.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   716.3 @@ -1,1 +0,0 @@
   716.4 -../xorg/.icon.png
   716.5 \ No newline at end of file
   717.1 --- a/xorg-xev/receipt	Thu Dec 13 00:46:54 2018 +0200
   717.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   717.3 @@ -1,29 +0,0 @@
   717.4 -# SliTaz package receipt v2.
   717.5 -
   717.6 -PACKAGE="xorg-xev"
   717.7 -VERSION="1.2.2"
   717.8 -CATEGORY="x-window"
   717.9 -SHORT_DESC="Print contents of X events"
  717.10 -MAINTAINER="devel@slitaz.org"
  717.11 -LICENSE="MIT"
  717.12 -WEB_SITE="https://www.x.org/wiki/"
  717.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  717.14 -REPOLOGY="xev"
  717.15 -
  717.16 -TARBALL="xev-$VERSION.tar.bz2"
  717.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  717.18 -
  717.19 -BUILD_DEPENDS="xorg-libX11-dev xorg-libXrandr-dev"
  717.20 -
  717.21 -compile_rules() {
  717.22 -	./configure $CONFIGURE_ARGS &&
  717.23 -	fix libtool &&
  717.24 -	make &&
  717.25 -	make install
  717.26 -}
  717.27 -
  717.28 -genpkg_rules() {
  717.29 -	copy @std
  717.30 -	DEPENDS="xorg-libX11 xorg-libXrandr"
  717.31 -	TAGS="utility xorg debug"
  717.32 -}
   718.1 --- a/xorg-xeyes/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   718.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   718.3 @@ -1,1 +0,0 @@
   718.4 -../xorg/.icon.png
   718.5 \ No newline at end of file
   719.1 --- a/xorg-xeyes/receipt	Thu Dec 13 00:46:54 2018 +0200
   719.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   719.3 @@ -1,27 +0,0 @@
   719.4 -# SliTaz package receipt v2.
   719.5 -
   719.6 -PACKAGE="xorg-xeyes"
   719.7 -VERSION="1.1.2"
   719.8 -CATEGORY="x-window"
   719.9 -SHORT_DESC="Follow the mouse/SHAPE extension X demo"
  719.10 -MAINTAINER="pascal.bellard@slitaz.org"
  719.11 -LICENSE="MIT"
  719.12 -WEB_SITE="https://www.x.org/wiki/"
  719.13 -REPOLOGY="xeyes"
  719.14 -
  719.15 -TARBALL="xeyes-$VERSION.tar.bz2"
  719.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  719.17 -
  719.18 -BUILD_DEPENDS="xorg-util-macros  xorg-libX11-dev xorg-libXt-dev \
  719.19 -xorg-libXext-dev xorg-libXmu-dev xorg-libXrender-dev"
  719.20 -
  719.21 -compile_rules() {
  719.22 -	./configure $CONFIGURE_ARGS &&
  719.23 -	make &&
  719.24 -	make install
  719.25 -}
  719.26 -
  719.27 -genpkg_rules() {
  719.28 -	copy @std
  719.29 -	DEPENDS="xorg-libX11 xorg-libXext xorg-libXmu xorg-libXrender xorg-libXt"
  719.30 -}
   720.1 --- a/xorg-xf86-input-acecad/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   720.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   720.3 @@ -1,1 +0,0 @@
   720.4 -../xorg/.icon.png
   720.5 \ No newline at end of file
   721.1 --- a/xorg-xf86-input-acecad/receipt	Thu Dec 13 00:46:54 2018 +0200
   721.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   721.3 @@ -1,27 +0,0 @@
   721.4 -# SliTaz package receipt v2.
   721.5 -
   721.6 -PACKAGE="xorg-xf86-input-acecad"
   721.7 -VERSION="1.5.0"
   721.8 -CATEGORY="x-window"
   721.9 -SHORT_DESC="Xorg input driver for Acecad Flair devices"
  721.10 -MAINTAINER="al.bobylev@gmail.com"
  721.11 -LICENSE="MIT"
  721.12 -WEB_SITE="https://www.x.org/wiki/"
  721.13 -REPOLOGY="xdrv:acecad"
  721.14 -
  721.15 -TARBALL="xf86-input-acecad-$VERSION.tar.bz2"
  721.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  721.17 -
  721.18 -BUILD_DEPENDS="xorg-server-dev"
  721.19 -
  721.20 -compile_rules() {
  721.21 -	./configure $CONFIGURE_ARGS &&
  721.22 -	fix libtool &&
  721.23 -	make &&
  721.24 -	make install
  721.25 -}
  721.26 -
  721.27 -genpkg_rules() {
  721.28 -	copy @std
  721.29 -	DEPENDS="xorg-server"
  721.30 -}
   722.1 --- a/xorg-xf86-input-elographics/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   722.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   722.3 @@ -1,1 +0,0 @@
   722.4 -../xorg/.icon.png
   722.5 \ No newline at end of file
   723.1 --- a/xorg-xf86-input-elographics/receipt	Thu Dec 13 00:46:54 2018 +0200
   723.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   723.3 @@ -1,27 +0,0 @@
   723.4 -# SliTaz package receipt v2.
   723.5 -
   723.6 -PACKAGE="xorg-xf86-input-elographics"
   723.7 -VERSION="1.4.1"
   723.8 -CATEGORY="x-window"
   723.9 -SHORT_DESC="Xorg input driver for Elographics touchscreen devices"
  723.10 -MAINTAINER="devel@slitaz.org"
  723.11 -LICENSE="MIT"
  723.12 -WEB_SITE="https://www.x.org/wiki/"
  723.13 -REPOLOGY="xdrv:elographics"
  723.14 -
  723.15 -TARBALL="xf86-input-elographics-$VERSION.tar.bz2"
  723.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  723.17 -
  723.18 -BUILD_DEPENDS="xorg-server-dev xorg-xorgproto"
  723.19 -
  723.20 -compile_rules() {
  723.21 -	./configure $CONFIGURE_ARGS &&
  723.22 -	fix libtool &&
  723.23 -	make &&
  723.24 -	make install
  723.25 -}
  723.26 -
  723.27 -genpkg_rules() {
  723.28 -	copy @std
  723.29 -	DEPENDS="xorg-server"
  723.30 -}
   724.1 --- a/xorg-xf86-input-evdev/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   724.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   724.3 @@ -1,1 +0,0 @@
   724.4 -../xorg/.icon.png
   724.5 \ No newline at end of file
   725.1 --- a/xorg-xf86-input-evdev/receipt	Thu Dec 13 00:46:54 2018 +0200
   725.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   725.3 @@ -1,37 +0,0 @@
   725.4 -# SliTaz package receipt v2.
   725.5 -
   725.6 -PACKAGE="xorg-xf86-input-evdev"
   725.7 -VERSION="2.10.6"
   725.8 -CATEGORY="x-window"
   725.9 -SHORT_DESC="Generic Linux input driver"
  725.10 -MAINTAINER="devel@slitaz.org"
  725.11 -LICENSE="MIT"
  725.12 -WEB_SITE="https://www.x.org/wiki/"
  725.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7driver.html#xorg-evdev-driver"
  725.14 -REPOLOGY="xdrv:evdev"
  725.15 -
  725.16 -TARBALL="xf86-input-evdev-$VERSION.tar.bz2"
  725.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  725.18 -
  725.19 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev \
  725.20 -xorg-xorgproto eudev-dev libevdev-dev mtdev-dev"
  725.21 -SPLIT="$PACKAGE-dev"
  725.22 -
  725.23 -compile_rules() {
  725.24 -	./configure $CONFIGURE_ARGS &&
  725.25 -	fix libtool &&
  725.26 -	make &&
  725.27 -	make install
  725.28 -}
  725.29 -
  725.30 -genpkg_rules() {
  725.31 -	case $PACKAGE in
  725.32 -		*-evdev)
  725.33 -			copy @std
  725.34 -			DEPENDS="eudev libevdev mtdev"
  725.35 -			;;
  725.36 -		*-dev)
  725.37 -			copy @dev
  725.38 -			;;
  725.39 -	esac
  725.40 -}
   726.1 --- a/xorg-xf86-input-fpit/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   726.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   726.3 @@ -1,1 +0,0 @@
   726.4 -../xorg/.icon.png
   726.5 \ No newline at end of file
   727.1 --- a/xorg-xf86-input-fpit/receipt	Thu Dec 13 00:46:54 2018 +0200
   727.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   727.3 @@ -1,27 +0,0 @@
   727.4 -# SliTaz package receipt v2.
   727.5 -
   727.6 -PACKAGE="xorg-xf86-input-fpit"
   727.7 -VERSION="1.4.0"
   727.8 -CATEGORY="x-window"
   727.9 -SHORT_DESC="Xorg input driver for Fujitsu Stylistic Tablet PCs"
  727.10 -MAINTAINER="al.bobylev@gmail.com"
  727.11 -LICENSE="MIT"
  727.12 -WEB_SITE="https://www.x.org/wiki/"
  727.13 -REPOLOGY="xdrv:fpit"
  727.14 -
  727.15 -TARBALL="xf86-input-fpit-$VERSION.tar.bz2"
  727.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  727.17 -
  727.18 -BUILD_DEPENDS="xorg-server-dev"
  727.19 -
  727.20 -compile_rules() {
  727.21 -	./configure $CONFIGURE_ARGS &&
  727.22 -	fix libtool &&
  727.23 -	make &&
  727.24 -	make install
  727.25 -}
  727.26 -
  727.27 -genpkg_rules() {
  727.28 -	copy @std
  727.29 -	DEPENDS="xorg-server"
  727.30 -}
   728.1 --- a/xorg-xf86-input-hyperpen/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   728.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   728.3 @@ -1,1 +0,0 @@
   728.4 -../xorg/.icon.png
   728.5 \ No newline at end of file
   729.1 --- a/xorg-xf86-input-hyperpen/receipt	Thu Dec 13 00:46:54 2018 +0200
   729.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   729.3 @@ -1,27 +0,0 @@
   729.4 -# SliTaz package receipt v2.
   729.5 -
   729.6 -PACKAGE="xorg-xf86-input-hyperpen"
   729.7 -VERSION="1.4.1"
   729.8 -CATEGORY="x-window"
   729.9 -SHORT_DESC="Xorg input driver for Aiptek HyperPen 6000"
  729.10 -MAINTAINER="al.bobylev@gmail.com"
  729.11 -LICENSE="MIT"
  729.12 -WEB_SITE="https://www.x.org/wiki/"
  729.13 -REPOLOGY="xdrv:hyperpen"
  729.14 -
  729.15 -TARBALL="xf86-input-hyperpen-$VERSION.tar.bz2"
  729.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  729.17 -
  729.18 -BUILD_DEPENDS="xorg-server-dev"
  729.19 -
  729.20 -compile_rules() {
  729.21 -	./configure $CONFIGURE_ARGS &&
  729.22 -	fix libtool &&
  729.23 -	make &&
  729.24 -	make install
  729.25 -}
  729.26 -
  729.27 -genpkg_rules() {
  729.28 -	copy @std
  729.29 -	DEPENDS="xorg-server"
  729.30 -}
   730.1 --- a/xorg-xf86-input-joystick/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   730.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   730.3 @@ -1,1 +0,0 @@
   730.4 -../xorg/.icon.png
   730.5 \ No newline at end of file
   731.1 --- a/xorg-xf86-input-joystick/receipt	Thu Dec 13 00:46:54 2018 +0200
   731.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   731.3 @@ -1,37 +0,0 @@
   731.4 -# SliTaz package receipt v2.
   731.5 -
   731.6 -PACKAGE="xorg-xf86-input-joystick"
   731.7 -VERSION="1.6.3"
   731.8 -CATEGORY="x-window"
   731.9 -SHORT_DESC="Xorg input driver for controlling the pointer with a joystick \
  731.10 -device"
  731.11 -MAINTAINER="al.bobylev@gmail.com"
  731.12 -LICENSE="MIT"
  731.13 -WEB_SITE="https://www.x.org/wiki/"
  731.14 -REPOLOGY="xdrv:joystick"
  731.15 -
  731.16 -TARBALL="xf86-input-joystick-$VERSION.tar.bz2"
  731.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  731.18 -
  731.19 -BUILD_DEPENDS="xorg-server-dev"
  731.20 -SPLIT="$PACKAGE-dev"
  731.21 -
  731.22 -compile_rules() {
  731.23 -	./configure $CONFIGURE_ARGS &&
  731.24 -	fix libtool &&
  731.25 -	make &&
  731.26 -	make install
  731.27 -}
  731.28 -
  731.29 -genpkg_rules() {
  731.30 -	case $PACKAGE in
  731.31 -		*-joystick)
  731.32 -			copy @std
  731.33 -			DEPENDS="xorg-server"
  731.34 -			;;
  731.35 -		*-dev)
  731.36 -			copy @dev
  731.37 -			DEPENDS="xorg-xf86-input-joystick xorg-server-dev"
  731.38 -			;;
  731.39 -	esac
  731.40 -}
   732.1 --- a/xorg-xf86-input-keyboard/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   732.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   732.3 @@ -1,1 +0,0 @@
   732.4 -../xorg/.icon.png
   732.5 \ No newline at end of file
   733.1 --- a/xorg-xf86-input-keyboard/receipt	Thu Dec 13 00:46:54 2018 +0200
   733.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   733.3 @@ -1,27 +0,0 @@
   733.4 -# SliTaz package receipt v2.
   733.5 -
   733.6 -PACKAGE="xorg-xf86-input-keyboard"
   733.7 -VERSION="1.9.0"
   733.8 -CATEGORY="x-window"
   733.9 -SHORT_DESC="Xorg input driver for keyboards"
  733.10 -MAINTAINER="devel@slitaz.org"
  733.11 -LICENSE="MIT"
  733.12 -WEB_SITE="https://www.x.org/wiki/"
  733.13 -REPOLOGY="xdrv:keyboard"
  733.14 -
  733.15 -TARBALL="xf86-input-keyboard-$VERSION.tar.bz2"
  733.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  733.17 -
  733.18 -BUILD_DEPENDS="xorg-server-dev"
  733.19 -
  733.20 -compile_rules() {
  733.21 -	./configure $CONFIGURE_ARGS &&
  733.22 -	fix libtool &&
  733.23 -	make &&
  733.24 -	make install
  733.25 -}
  733.26 -
  733.27 -genpkg_rules() {
  733.28 -	copy @std
  733.29 -	DEPENDS="xorg-server"
  733.30 -}
   734.1 --- a/xorg-xf86-input-libinput/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   734.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   734.3 @@ -1,1 +0,0 @@
   734.4 -../xorg/.icon.png
   734.5 \ No newline at end of file
   735.1 --- a/xorg-xf86-input-libinput/receipt	Thu Dec 13 00:46:54 2018 +0200
   735.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   735.3 @@ -1,37 +0,0 @@
   735.4 -# SliTaz package receipt v2.
   735.5 -
   735.6 -PACKAGE="xorg-xf86-input-libinput"
   735.7 -VERSION="0.28.0"
   735.8 -CATEGORY="x-window"
   735.9 -SHORT_DESC="libinput-based X.Org input driver"
  735.10 -MAINTAINER="al.bobylev@gmail.com"
  735.11 -LICENSE="MIT"
  735.12 -WEB_SITE="https://www.x.org/wiki/"
  735.13 -REPOLOGY="xdrv:libinput"
  735.14 -
  735.15 -TARBALL="xf86-input-libinput-$VERSION.tar.bz2"
  735.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  735.17 -
  735.18 -BUILD_DEPENDS="xorg-server-dev libinput-dev mtdev-dev libevdev-dev"
  735.19 -SPLIT="$PACKAGE-dev"
  735.20 -
  735.21 -compile_rules() {
  735.22 -	./configure $CONFIGURE_ARGS &&
  735.23 -	fix libtool &&
  735.24 -	make &&
  735.25 -	make install
  735.26 -}
  735.27 -
  735.28 -genpkg_rules() {
  735.29 -	case $PACKAGE in
  735.30 -		*-libinput)
  735.31 -			copy @std
  735.32 -			DEPENDS="xorg-server eudev libevdev libinput mtdev"
  735.33 -			;;
  735.34 -		*-dev)
  735.35 -			copy @dev
  735.36 -			DEPENDS="xorg-xf86-input-libinput xorg-server-dev eudev-dev \
  735.37 -			libevdev-dev libinput-dev mtdev-dev"
  735.38 -			;;
  735.39 -	esac
  735.40 -}
   736.1 --- a/xorg-xf86-input-mouse/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   736.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   736.3 @@ -1,1 +0,0 @@
   736.4 -../xorg/.icon.png
   736.5 \ No newline at end of file
   737.1 --- a/xorg-xf86-input-mouse/receipt	Thu Dec 13 00:46:54 2018 +0200
   737.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   737.3 @@ -1,36 +0,0 @@
   737.4 -# SliTaz package receipt v2.
   737.5 -
   737.6 -PACKAGE="xorg-xf86-input-mouse"
   737.7 -VERSION="1.9.3"
   737.8 -CATEGORY="x-window"
   737.9 -SHORT_DESC="Xorg mouse input driver"
  737.10 -MAINTAINER="devel@slitaz.org"
  737.11 -LICENSE="MIT"
  737.12 -WEB_SITE="https://www.x.org/wiki/"
  737.13 -REPOLOGY="xdrv:mouse"
  737.14 -
  737.15 -TARBALL="xf86-input-mouse-$VERSION.tar.bz2"
  737.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  737.17 -
  737.18 -BUILD_DEPENDS="xorg-server-dev"
  737.19 -SPLIT="$PACKAGE-dev"
  737.20 -
  737.21 -compile_rules() {
  737.22 -	./configure $CONFIGURE_ARGS &&
  737.23 -	fix libtool &&
  737.24 -	make &&
  737.25 -	make install
  737.26 -}
  737.27 -
  737.28 -genpkg_rules() {
  737.29 -	case $PACKAGE in
  737.30 -		*-mouse)
  737.31 -			copy @std
  737.32 -			DEPENDS="xorg-server" # implicit
  737.33 -			;;
  737.34 -		*-dev)
  737.35 -			copy @dev
  737.36 -			DEPENDS="xorg-xf86-input-mouse xorg-server-dev" # implicit
  737.37 -			;;
  737.38 -	esac
  737.39 -}
   738.1 --- a/xorg-xf86-input-mutouch/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   738.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   738.3 @@ -1,1 +0,0 @@
   738.4 -../xorg/.icon.png
   738.5 \ No newline at end of file
   739.1 --- a/xorg-xf86-input-mutouch/receipt	Thu Dec 13 00:46:54 2018 +0200
   739.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   739.3 @@ -1,27 +0,0 @@
   739.4 -# SliTaz package receipt v2.
   739.5 -
   739.6 -PACKAGE="xorg-xf86-input-mutouch"
   739.7 -VERSION="1.3.0"
   739.8 -CATEGORY="x-window"
   739.9 -SHORT_DESC="Xorg input driver for Microtouch devices"
  739.10 -MAINTAINER="devel@slitaz.org"
  739.11 -LICENSE="MIT"
  739.12 -WEB_SITE="https://www.x.org/wiki/"
  739.13 -REPOLOGY="xdrv:mutouch"
  739.14 -
  739.15 -TARBALL="xf86-input-mutouch-$VERSION.tar.bz2"
  739.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  739.17 -
  739.18 -BUILD_DEPENDS="xorg-server-dev"
  739.19 -
  739.20 -compile_rules() {
  739.21 -	./configure $CONFIGURE_ARGS &&
  739.22 -	fix libtool &&
  739.23 -	make &&
  739.24 -	make install
  739.25 -}
  739.26 -
  739.27 -genpkg_rules() {
  739.28 -	copy @std
  739.29 -	DEPENDS="xorg-server"
  739.30 -}
   740.1 --- a/xorg-xf86-input-penmount/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   740.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   740.3 @@ -1,1 +0,0 @@
   740.4 -../xorg/.icon.png
   740.5 \ No newline at end of file
   741.1 --- a/xorg-xf86-input-penmount/receipt	Thu Dec 13 00:46:54 2018 +0200
   741.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   741.3 @@ -1,27 +0,0 @@
   741.4 -# SliTaz package receipt v2.
   741.5 -
   741.6 -PACKAGE="xorg-xf86-input-penmount"
   741.7 -VERSION="1.5.0"
   741.8 -CATEGORY="x-window"
   741.9 -SHORT_DESC="Xorg input driver for PenMount devices"
  741.10 -MAINTAINER="al.bobylev@gmail.com"
  741.11 -LICENSE="MIT"
  741.12 -WEB_SITE="https://www.x.org/wiki/"
  741.13 -REPOLOGY="xdrv:penmount"
  741.14 -
  741.15 -TARBALL="xf86-input-penmount-$VERSION.tar.bz2"
  741.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  741.17 -
  741.18 -BUILD_DEPENDS="xorg-server-dev"
  741.19 -
  741.20 -compile_rules() {
  741.21 -	./configure $CONFIGURE_ARGS &&
  741.22 -	fix libtool &&
  741.23 -	make &&
  741.24 -	make install
  741.25 -}
  741.26 -
  741.27 -genpkg_rules() {
  741.28 -	copy @std
  741.29 -	DEPENDS="xorg-server"
  741.30 -}
   742.1 --- a/xorg-xf86-input-synaptics/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   742.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   742.3 @@ -1,1 +0,0 @@
   742.4 -../xorg/.icon.png
   742.5 \ No newline at end of file
   743.1 --- a/xorg-xf86-input-synaptics/receipt	Thu Dec 13 00:46:54 2018 +0200
   743.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   743.3 @@ -1,36 +0,0 @@
   743.4 -# SliTaz package receipt v2.
   743.5 -
   743.6 -PACKAGE="xorg-xf86-input-synaptics"
   743.7 -VERSION="1.9.1"
   743.8 -CATEGORY="x-window"
   743.9 -SHORT_DESC="Xorg input driver for touchpads"
  743.10 -MAINTAINER="devel@slitaz.org"
  743.11 -LICENSE="MIT"
  743.12 -WEB_SITE="https://www.x.org/wiki/"
  743.13 -REPOLOGY="xdrv:synaptics"
  743.14 -
  743.15 -TARBALL="xf86-input-synaptics-$VERSION.tar.bz2"
  743.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  743.17 -
  743.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-xorgproto \
  743.19 -libevdev-dev xorg-libXi-dev xorg-libXtst-dev"
  743.20 -SPLIT="$PACKAGE-dev"
  743.21 -
  743.22 -compile_rules() {
  743.23 -	./configure $CONFIGURE_ARGS &&
  743.24 -	fix libtool &&
  743.25 -	make &&
  743.26 -	make install
  743.27 -}
  743.28 -
  743.29 -genpkg_rules() {
  743.30 -	case $PACKAGE in
  743.31 -		*-synaptics)
  743.32 -			copy @std
  743.33 -			DEPENDS="libevdev xorg-libX11 xorg-libXi xorg-libXtst"
  743.34 -			;;
  743.35 -		*-dev)
  743.36 -			copy @dev
  743.37 -			;;
  743.38 -	esac
  743.39 -}
   744.1 --- a/xorg-xf86-input-vmmouse/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   744.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   744.3 @@ -1,1 +0,0 @@
   744.4 -../xorg/.icon.png
   744.5 \ No newline at end of file
   745.1 --- a/xorg-xf86-input-vmmouse/receipt	Thu Dec 13 00:46:54 2018 +0200
   745.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   745.3 @@ -1,27 +0,0 @@
   745.4 -# SliTaz package receipt v2.
   745.5 -
   745.6 -PACKAGE="xorg-xf86-input-vmmouse"
   745.7 -VERSION="13.1.0"
   745.8 -CATEGORY="x-window"
   745.9 -SHORT_DESC="Xorg input driver for VMware Mouse"
  745.10 -MAINTAINER="al.bobylev@gmail.com"
  745.11 -LICENSE="MIT"
  745.12 -WEB_SITE="https://www.x.org/wiki/"
  745.13 -REPOLOGY="xdrv:vmmouse"
  745.14 -
  745.15 -TARBALL="xf86-input-vmmouse-$VERSION.tar.bz2"
  745.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  745.17 -
  745.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev eudev-dev"
  745.19 -
  745.20 -compile_rules() {
  745.21 -	./configure $CONFIGURE_ARGS &&
  745.22 -	fix libtool &&
  745.23 -	make &&
  745.24 -	make install
  745.25 -}
  745.26 -
  745.27 -genpkg_rules() {
  745.28 -	copy @std
  745.29 -	DEPENDS="xorg-server eudev"
  745.30 -}
   746.1 --- a/xorg-xf86-input-void/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   746.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   746.3 @@ -1,1 +0,0 @@
   746.4 -../xorg/.icon.png
   746.5 \ No newline at end of file
   747.1 --- a/xorg-xf86-input-void/receipt	Thu Dec 13 00:46:54 2018 +0200
   747.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   747.3 @@ -1,27 +0,0 @@
   747.4 -# SliTaz package receipt v2.
   747.5 -
   747.6 -PACKAGE="xorg-xf86-input-void"
   747.7 -VERSION="1.4.1"
   747.8 -CATEGORY="x-window"
   747.9 -SHORT_DESC="Dummy/null Xorg input driver"
  747.10 -MAINTAINER="devel@slitaz.org"
  747.11 -LICENSE="MIT"
  747.12 -WEB_SITE="https://www.x.org/wiki/"
  747.13 -REPOLOGY="xdrv:void"
  747.14 -
  747.15 -TARBALL="xf86-input-void-$VERSION.tar.bz2"
  747.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  747.17 -
  747.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev"
  747.19 -
  747.20 -compile_rules() {
  747.21 -	./configure $CONFIGURE_ARGS &&
  747.22 -	fix libtool &&
  747.23 -	make &&
  747.24 -	make install
  747.25 -}
  747.26 -
  747.27 -genpkg_rules() {
  747.28 -	copy @std
  747.29 -	DEPENDS="xorg-server"
  747.30 -}
   748.1 Binary file xorg-xf86-input-wacom/.icon.png has changed
   749.1 --- a/xorg-xf86-input-wacom/receipt	Thu Dec 13 00:46:54 2018 +0200
   749.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   749.3 @@ -1,42 +0,0 @@
   749.4 -# SliTaz package receipt v2.
   749.5 -
   749.6 -PACKAGE="xorg-xf86-input-wacom"
   749.7 -VERSION="0.36.1"
   749.8 -CATEGORY="x-window"
   749.9 -SHORT_DESC="X input driver for Wacom and Wacom-like tablets"
  749.10 -MAINTAINER="al.bobylev@gmail.com"
  749.11 -LICENSE="GPL2"
  749.12 -WEB_SITE="https://linuxwacom.github.io/"
  749.13 -REPOLOGY="xdrv:wacom"
  749.14 -
  749.15 -TARBALL="xf86-input-wacom-$VERSION.tar.bz2"
  749.16 -WGET_URL="https://github.com/linuxwacom/xf86-input-wacom/releases/download/xf86-input-wacom-$VERSION/$TARBALL"
  749.17 -
  749.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-libXext-dev \
  749.19 -xorg-xorgproto xorg-libXi-dev xorg-libXrandr-dev \
  749.20 -xorg-libXinerama-dev eudev-dev"
  749.21 -SPLIT="$PACKAGE-dev"
  749.22 -
  749.23 -compile_rules() {
  749.24 -	./configure \
  749.25 -		--with-systemd-unit-dir=no \
  749.26 -		$CONFIGURE_ARGS &&
  749.27 -	fix libtool &&
  749.28 -	make &&
  749.29 -	make install
  749.30 -}
  749.31 -
  749.32 -genpkg_rules() {
  749.33 -	case $PACKAGE in
  749.34 -		*-wacom)
  749.35 -			copy @std
  749.36 -			DEPENDS="eudev xorg-libX11 xorg-libXau xorg-libXdmcp xorg-libXext \
  749.37 -			xorg-libXi xorg-libXinerama xorg-libXrandr xorg-libXrender \
  749.38 -			xorg-libxcb"
  749.39 -			;;
  749.40 -		*-dev)
  749.41 -			copy @dev
  749.42 -			DEPENDS="xorg-xf86-input-wacom xorg-server-dev"
  749.43 -			;;
  749.44 -	esac
  749.45 -}
   750.1 --- a/xorg-xf86-video-amdgpu/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   750.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   750.3 @@ -1,1 +0,0 @@
   750.4 -../xorg/.icon.png
   750.5 \ No newline at end of file
   751.1 --- a/xorg-xf86-video-amdgpu/receipt	Thu Dec 13 00:46:54 2018 +0200
   751.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   751.3 @@ -1,30 +0,0 @@
   751.4 -# SliTaz package receipt v2.
   751.5 -
   751.6 -PACKAGE="xorg-xf86-video-amdgpu"
   751.7 -VERSION="18.0.1"
   751.8 -CATEGORY="x-window"
   751.9 -SHORT_DESC="AMD Rx/HDxxxx video driver"
  751.10 -MAINTAINER="al.bobylev@gmail.com"
  751.11 -LICENSE="MIT"
  751.12 -WEB_SITE="https://www.x.org/wiki/"
  751.13 -REPOLOGY="xdrv:amdgpu"
  751.14 -
  751.15 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  751.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  751.17 -
  751.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev libdrm-dev expat-dev"
  751.19 -
  751.20 -compile_rules() {
  751.21 -	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  751.22 -
  751.23 -	./configure $CONFIGURE_ARGS &&
  751.24 -	fix libtool &&
  751.25 -	make &&
  751.26 -	make install
  751.27 -}
  751.28 -
  751.29 -genpkg_rules() {
  751.30 -	copy @std
  751.31 -	DEPENDS="libdrm-amdgpu mesa-libgbm"
  751.32 -	TAGS="xorg display"
  751.33 -}
   752.1 --- a/xorg-xf86-video-ast/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   752.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   752.3 @@ -1,1 +0,0 @@
   752.4 -../xorg/.icon.png
   752.5 \ No newline at end of file
   753.1 --- a/xorg-xf86-video-ast/receipt	Thu Dec 13 00:46:54 2018 +0200
   753.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   753.3 @@ -1,28 +0,0 @@
   753.4 -# SliTaz package receipt v2.
   753.5 -
   753.6 -PACKAGE="xorg-xf86-video-ast"
   753.7 -VERSION="1.1.5"
   753.8 -CATEGORY="x-window"
   753.9 -SHORT_DESC="Xorg driver for ASpeed Technologies video cards"
  753.10 -MAINTAINER="al.bobylev@gmail.com"
  753.11 -LICENSE="MIT"
  753.12 -WEB_SITE="https://www.x.org/wiki/"
  753.13 -REPOLOGY="xdrv:ast"
  753.14 -
  753.15 -TARBALL="xf86-video-ast-$VERSION.tar.bz2"
  753.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  753.17 -
  753.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev"
  753.19 -
  753.20 -compile_rules() {
  753.21 -	./configure $CONFIGURE_ARGS &&
  753.22 -	fix libtool &&
  753.23 -	make &&
  753.24 -	make install
  753.25 -}
  753.26 -
  753.27 -genpkg_rules() {
  753.28 -	copy @std
  753.29 -	DEPENDS="xorg-server"
  753.30 -	TAGS="xorg display"
  753.31 -}
   754.1 --- a/xorg-xf86-video-ati/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   754.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   754.3 @@ -1,1 +0,0 @@
   754.4 -../xorg/.icon.png
   754.5 \ No newline at end of file
   755.1 --- a/xorg-xf86-video-ati/receipt	Thu Dec 13 00:46:54 2018 +0200
   755.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   755.3 @@ -1,29 +0,0 @@
   755.4 -# SliTaz package receipt v2.
   755.5 -
   755.6 -PACKAGE="xorg-xf86-video-ati"
   755.7 -VERSION="18.0.1"
   755.8 -CATEGORY="x-window"
   755.9 -SHORT_DESC="Xorg wrapper driver for ATI video cards"
  755.10 -MAINTAINER="devel@slitaz.org"
  755.11 -LICENSE="MIT"
  755.12 -WEB_SITE="https://www.x.org/wiki/ati/"
  755.13 -REPOLOGY="xdrv:ati"
  755.14 -
  755.15 -TARBALL="xf86-video-ati-$VERSION.tar.bz2"
  755.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  755.17 -
  755.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-libXrandr-dev \
  755.19 -xorg-libXrender-dev xorg-libXv-dev libdrm-dev eudev-dev"
  755.20 -
  755.21 -compile_rules() {
  755.22 -	./configure $CONFIGURE_ARGS &&
  755.23 -	fix libtool &&
  755.24 -	make &&
  755.25 -	make install
  755.26 -}
  755.27 -
  755.28 -genpkg_rules() {
  755.29 -	copy @std
  755.30 -	DEPENDS="eudev libdrm-radeon xorg-libpciaccess"
  755.31 -	TAGS="xorg display"
  755.32 -}
   756.1 --- a/xorg-xf86-video-chips/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   756.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   756.3 @@ -1,1 +0,0 @@
   756.4 -../xorg/.icon.png
   756.5 \ No newline at end of file
   757.1 --- a/xorg-xf86-video-chips/receipt	Thu Dec 13 00:46:54 2018 +0200
   757.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   757.3 @@ -1,28 +0,0 @@
   757.4 -# SliTaz package receipt v2.
   757.5 -
   757.6 -PACKAGE="xorg-xf86-video-chips"
   757.7 -VERSION="1.2.7"
   757.8 -CATEGORY="x-window"
   757.9 -SHORT_DESC="Xorg driver for Chips and Technologies video processors"
  757.10 -MAINTAINER="al.bobylev@gmail.com"
  757.11 -LICENSE="MIT"
  757.12 -WEB_SITE="https://www.x.org/wiki/"
  757.13 -REPOLOGY="xdrv:chips"
  757.14 -
  757.15 -TARBALL="xf86-video-chips-$VERSION.tar.bz2"
  757.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  757.17 -
  757.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev"
  757.19 -
  757.20 -compile_rules() {
  757.21 -	./configure $CONFIGURE_ARGS &&
  757.22 -	fix libtool &&
  757.23 -	make &&
  757.24 -	make install
  757.25 -}
  757.26 -
  757.27 -genpkg_rules() {
  757.28 -	copy @std
  757.29 -	DEPENDS="xorg-server"
  757.30 -	TAGS="xorg display"
  757.31 -}
   758.1 --- a/xorg-xf86-video-cirrus/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   758.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   758.3 @@ -1,1 +0,0 @@
   758.4 -../xorg/.icon.png
   758.5 \ No newline at end of file
   759.1 --- a/xorg-xf86-video-cirrus/receipt	Thu Dec 13 00:46:54 2018 +0200
   759.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   759.3 @@ -1,28 +0,0 @@
   759.4 -# SliTaz package receipt v2.
   759.5 -
   759.6 -PACKAGE="xorg-xf86-video-cirrus"
   759.7 -VERSION="1.5.3"
   759.8 -CATEGORY="x-window"
   759.9 -SHORT_DESC="Xorg driver for Cirrus cards"
  759.10 -MAINTAINER="pascal.bellard@slitaz.org"
  759.11 -LICENSE="MIT"
  759.12 -WEB_SITE="https://www.x.org/wiki/cirrus/"
  759.13 -REPOLOGY="xdrv:cirrus"
  759.14 -
  759.15 -TARBALL="xf86-video-cirrus-$VERSION.tar.bz2"
  759.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  759.17 -
  759.18 -BUILD_DEPENDS="xorg-server-dev"
  759.19 -
  759.20 -compile_rules() {
  759.21 -	./configure $CONFIGURE_ARGS &&
  759.22 -	fix libtool &&
  759.23 -	make &&
  759.24 -	make install
  759.25 -}
  759.26 -
  759.27 -genpkg_rules() {
  759.28 -	copy @std
  759.29 -	DEPENDS="xorg-server"
  759.30 -	TAGS="xorg display"
  759.31 -}
   760.1 --- a/xorg-xf86-video-fbdev/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   760.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   760.3 @@ -1,1 +0,0 @@
   760.4 -../xorg/.icon.png
   760.5 \ No newline at end of file
   761.1 --- a/xorg-xf86-video-fbdev/receipt	Thu Dec 13 00:46:54 2018 +0200
   761.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   761.3 @@ -1,29 +0,0 @@
   761.4 -# SliTaz package receipt v2.
   761.5 -
   761.6 -PACKAGE="xorg-xf86-video-fbdev"
   761.7 -VERSION="0.5.0"
   761.8 -CATEGORY="x-window"
   761.9 -SHORT_DESC="Xorg video driver for framebuffer device"
  761.10 -MAINTAINER="devel@slitaz.org"
  761.11 -LICENSE="MIT"
  761.12 -WEB_SITE="https://www.x.org/wiki/fbdev/"
  761.13 -REPOLOGY="xdrv:fbdev"
  761.14 -
  761.15 -TARBALL="xf86-video-fbdev-$VERSION.tar.bz2"
  761.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  761.17 -
  761.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-libXrandr-dev \
  761.19 -xorg-libXrender-dev xorg-libXv-dev xorg-xorgproto"
  761.20 -
  761.21 -compile_rules() {
  761.22 -	./configure $CONFIGURE_ARGS &&
  761.23 -	fix libtool &&
  761.24 -	make &&
  761.25 -	make install
  761.26 -}
  761.27 -
  761.28 -genpkg_rules() {
  761.29 -	copy @std
  761.30 -	DEPENDS="xorg-server" # implicit
  761.31 -	TAGS="xorg display"
  761.32 -}
   762.1 --- a/xorg-xf86-video-fbturbo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   762.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   762.3 @@ -1,1 +0,0 @@
   762.4 -../xorg/.icon.png
   762.5 \ No newline at end of file
   763.1 --- a/xorg-xf86-video-fbturbo/receipt	Thu Dec 13 00:46:54 2018 +0200
   763.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   763.3 @@ -1,29 +0,0 @@
   763.4 -# SliTaz package receipt v2.
   763.5 -
   763.6 -PACKAGE="xorg-xf86-video-fbturbo"
   763.7 -VERSION="0.4.0.postgit20151006"
   763.8 -COMMIT="f9a6ed7"
   763.9 -CATEGORY="x-window"
  763.10 -SHORT_DESC="Xorg DDX driver for ARM devices (Allwinner, RPi and others)"
  763.11 -MAINTAINER="devel@slitaz.org"
  763.12 -LICENSE="MIT"
  763.13 -WEB_SITE="https://github.com/ssvb/xf86-video-fbturbo"
  763.14 -REPOLOGY="xdrv:fbturbo"
  763.15 -
  763.16 -TARBALL="xf86-video-fbturbo-$VERSION.tar.gz"
  763.17 -WGET_URL="$WEB_SITE/archive/${COMMIT:-VERSION}.tar.gz"
  763.18 -
  763.19 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev automake autoconf libtool"
  763.20 -
  763.21 -compile_rules() {
  763.22 -	autoreconf -vi
  763.23 -	./configure $CONFIGURE_ARGS &&
  763.24 -	fix libtool &&
  763.25 -	make &&
  763.26 -	make install
  763.27 -}
  763.28 -
  763.29 -genpkg_rules() {
  763.30 -	copy @std
  763.31 -	DEPENDS="xorg-server"
  763.32 -}
   764.1 --- a/xorg-xf86-video-geode/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   764.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   764.3 @@ -1,1 +0,0 @@
   764.4 -../xorg/.icon.png
   764.5 \ No newline at end of file
   765.1 --- a/xorg-xf86-video-geode/receipt	Thu Dec 13 00:46:54 2018 +0200
   765.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   765.3 @@ -1,29 +0,0 @@
   765.4 -# SliTaz package receipt v2.
   765.5 -
   765.6 -PACKAGE="xorg-xf86-video-geode"
   765.7 -VERSION="2.11.19"
   765.8 -CATEGORY="x-window"
   765.9 -SHORT_DESC="Xorg video driver for AMD Geode GX and LX video cards"
  765.10 -MAINTAINER="devel@slitaz.org"
  765.11 -LICENSE="MIT"
  765.12 -WEB_SITE="https://www.x.org/wiki/GeodeDriver/"
  765.13 -REPOLOGY="xdrv:geode"
  765.14 -HOST_ARCH="i486"
  765.15 -
  765.16 -TARBALL="xf86-video-geode-$VERSION.tar.bz2"
  765.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  765.18 -
  765.19 -BUILD_DEPENDS="xorg-server-dev"
  765.20 -
  765.21 -compile_rules() {
  765.22 -	./configure $CONFIGURE_ARGS &&
  765.23 -	fix libtool &&
  765.24 -	make &&
  765.25 -	make install
  765.26 -}
  765.27 -
  765.28 -genpkg_rules() {
  765.29 -	copy @std
  765.30 -	DEPENDS="xorg-server"
  765.31 -	TAGS="xorg display"
  765.32 -}
   766.1 --- a/xorg-xf86-video-glint/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   766.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   766.3 @@ -1,1 +0,0 @@
   766.4 -../xorg/.icon.png
   766.5 \ No newline at end of file
   767.1 --- a/xorg-xf86-video-glint/receipt	Thu Dec 13 00:46:54 2018 +0200
   767.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   767.3 @@ -1,29 +0,0 @@
   767.4 -# SliTaz package receipt v2.
   767.5 -
   767.6 -PACKAGE="xorg-xf86-video-glint"
   767.7 -VERSION="1.2.9"
   767.8 -CATEGORY="x-window"
   767.9 -SHORT_DESC="Xorg driver for 3Dlabs & Texas Instruments GLINT/Permedia based \
  767.10 -video cards"
  767.11 -MAINTAINER="al.bobylev@gmail.com"
  767.12 -LICENSE="MIT"
  767.13 -WEB_SITE="https://www.x.org/wiki/"
  767.14 -REPOLOGY="xdrv:glint"
  767.15 -
  767.16 -TARBALL="xf86-video-glint-$VERSION.tar.bz2"
  767.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  767.18 -
  767.19 -BUILD_DEPENDS="xorg-server-dev xorg-xorgproto"
  767.20 -
  767.21 -compile_rules() {
  767.22 -	./configure $CONFIGURE_ARGS &&
  767.23 -	fix libtool &&
  767.24 -	make &&
  767.25 -	make install
  767.26 -}
  767.27 -
  767.28 -genpkg_rules() {
  767.29 -	copy @std
  767.30 -	DEPENDS="xorg-server"
  767.31 -	TAGS="xorg display"
  767.32 -}
   768.1 --- a/xorg-xf86-video-i740/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   768.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   768.3 @@ -1,1 +0,0 @@
   768.4 -../xorg/.icon.png
   768.5 \ No newline at end of file
   769.1 --- a/xorg-xf86-video-i740/receipt	Thu Dec 13 00:46:54 2018 +0200
   769.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   769.3 @@ -1,28 +0,0 @@
   769.4 -# SliTaz package receipt v2.
   769.5 -
   769.6 -PACKAGE="xorg-xf86-video-i740"
   769.7 -VERSION="1.3.6"
   769.8 -CATEGORY="x-window"
   769.9 -SHORT_DESC="Xorg driver for Intel i740 video cards"
  769.10 -MAINTAINER="devel@slitaz.org"
  769.11 -LICENSE="MIT"
  769.12 -WEB_SITE="https://www.x.org/wiki/i740/"
  769.13 -REPOLOGY="xdrv:i740"
  769.14 -
  769.15 -TARBALL="xf86-video-i740-$VERSION.tar.bz2"
  769.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  769.17 -
  769.18 -BUILD_DEPENDS="xorg-server-dev"
  769.19 -
  769.20 -compile_rules() {
  769.21 -	./configure $CONFIGURE_ARGS &&
  769.22 -	fix libtool &&
  769.23 -	make &&
  769.24 -	make install
  769.25 -}
  769.26 -
  769.27 -genpkg_rules() {
  769.28 -	copy @std
  769.29 -	DEPENDS="xorg-server"
  769.30 -	TAGS="xorg display"
  769.31 -}
   770.1 --- a/xorg-xf86-video-intel/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   770.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   770.3 @@ -1,1 +0,0 @@
   770.4 -../xorg/.icon.png
   770.5 \ No newline at end of file
   771.1 --- a/xorg-xf86-video-intel/receipt	Thu Dec 13 00:46:54 2018 +0200
   771.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   771.3 @@ -1,47 +0,0 @@
   771.4 -# SliTaz package receipt v2.
   771.5 -
   771.6 -PACKAGE="xorg-xf86-video-intel"
   771.7 -VERSION="2.99.917"
   771.8 -CATEGORY="x-window"
   771.9 -SHORT_DESC="Xorg driver for Intel integrated graphics chipsets"
  771.10 -MAINTAINER="devel@slitaz.org"
  771.11 -LICENSE="MIT"
  771.12 -WEB_SITE="https://www.x.org/wiki/intel/"
  771.13 -REPOLOGY="xdrv:intel"
  771.14 -
  771.15 -TARBALL="xf86-video-intel-$VERSION.tar.bz2"
  771.16 -WGET_URL="https://www.x.org/releases/individual/driver/$TARBALL"
  771.17 -
  771.18 -BUILD_DEPENDS="xorg-util-macros eudev-dev xorg-libX11-dev \
  771.19 -xorg-libXcomposite-dev xorg-libXdamage-dev xorg-libXrender-dev \
  771.20 -xorg-libXrandr-dev cairo-dev xorg-libxshmfence-dev xorg-libXxf86vm-dev \
  771.21 -libdrm-dev xorg-libXinerama-dev xorg-libXcursor-dev xorg-libXtst-dev \
  771.22 -xorg-libXScrnSaver-dev xorg-server-dev xorg-libXvMC-dev xorg-xcb-util-dev \
  771.23 -xorg-libXfont2-dev automake libtool git"
  771.24 -
  771.25 -compile_rules() {
  771.26 -	autoreconf -vif
  771.27 -	export LDFLAGS="$LDFLAGS -Wl,-z,lazy"
  771.28 -
  771.29 -	./configure \
  771.30 -		--enable-kms-only \
  771.31 -		--enable-uxa \
  771.32 -		--enable-xvmc \
  771.33 -		--disable-selective-werror \
  771.34 -		--with-default-dri=3 \
  771.35 -		$CONFIGURE_ARGS &&
  771.36 -	fix libtool &&
  771.37 -	make &&
  771.38 -	make install || return 1
  771.39 -
  771.40 -	chmod o-x $install/usr/libexec/xf86-video-intel-backlight-helper
  771.41 -}
  771.42 -
  771.43 -genpkg_rules() {
  771.44 -	copy @std
  771.45 -	DEPENDS="eudev libdrm libdrm-intel xorg-libX11 xorg-libXScrnSaver \
  771.46 -	xorg-libXcursor xorg-libXdamage xorg-libXext xorg-libXfixes \
  771.47 -	xorg-libXinerama xorg-libXrandr xorg-libXrender xorg-libXtst xorg-libXv \
  771.48 -	xorg-libXvMC xorg-libxcb xorg-libxshmfence xorg-pixman xorg-xcb-util"
  771.49 -	TAGS="xorg display"
  771.50 -}
   772.1 --- a/xorg-xf86-video-intel/stuff/patches/git.patch	Thu Dec 13 00:46:54 2018 +0200
   772.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   772.3 @@ -1,43164 +0,0 @@
   772.4 -diff --git a/Makefile.am b/Makefile.am
   772.5 -index 418fdc92..de5fbe12 100644
   772.6 ---- a/Makefile.am
   772.7 -+++ b/Makefile.am
   772.8 -@@ -18,14 +18,16 @@
   772.9 - #  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  772.10 - #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  772.11 - 
  772.12 --ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
  772.13 -+#Having problems passing through user flags as libtool complains
  772.14 -+#ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
  772.15 -+ACLOCAL_AMFLAGS = -I m4
  772.16 - 
  772.17 - SUBDIRS = man libobj xvmc src tools
  772.18 - 
  772.19 - MAINTAINERCLEANFILES = ChangeLog INSTALL
  772.20 - 
  772.21 - if HAVE_X11
  772.22 --SUBDIRS += test
  772.23 -+SUBDIRS += test benchmarks
  772.24 - endif
  772.25 - 
  772.26 - .PHONY: ChangeLog INSTALL
  772.27 -diff --git a/NEWS b/NEWS
  772.28 -index 604b9cce..0e200332 100644
  772.29 ---- a/NEWS
  772.30 -+++ b/NEWS
  772.31 -@@ -21,7 +21,7 @@ should make one more snapshot before an imminent release.
  772.32 -    Before kernel 3.19, O_NONBLOCK support is broken and so we must avoid
  772.33 -    reading if we are not expecting an event.
  772.34 - 
  772.35 -- * Backwards compatibilty fix for fake triple buffering with PRIME and
  772.36 -+ * Backwards compatibility fix for fake triple buffering with PRIME and
  772.37 -    Xorg-1.15
  772.38 -    https://bugs.freedesktop.org/show_bug.cgi?id=85144#c12
  772.39 - 
  772.40 -@@ -51,7 +51,7 @@ should make one more snapshot before an imminent release.
  772.41 - Snapshot 2.99.916 (2014-09-08)
  772.42 - ==============================
  772.43 - Quick update for MST in UXA - we need to hook up the RandR outputs for
  772.44 --dynamicaly added connectors.
  772.45 -+dynamically added connectors.
  772.46 - 
  772.47 - 
  772.48 - Snapshot 2.99.915 (2014-09-08)
  772.49 -@@ -503,7 +503,7 @@ release.
  772.50 -    backlight property is queried whilst the connector is disabled
  772.51 -    https://bugs.freedesktop.org/show_bug.cgi?id=70406
  772.52 - 
  772.53 -- * Pad GETCONNECTOR ioctl for compatability between 32/64-bit userspace
  772.54 -+ * Pad GETCONNECTOR ioctl for compatibility between 32/64-bit userspace
  772.55 -    and kernel
  772.56 - 
  772.57 -  * Handle long glyph runs correctly
  772.58 -@@ -523,7 +523,7 @@ snapshot beforehand to push out the bug fixes from the last week.
  772.59 - 
  772.60 -  * Fix video output using sprites when changing the image size
  772.61 - 
  772.62 -- * Apply more restrictive tile constaints for 915g class devices
  772.63 -+ * Apply more restrictive tile constraints for 915g class devices
  772.64 -    https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1232546
  772.65 - 
  772.66 -  * Ensure all overlapping rectangles are drawn for XRenderFillRectangles
  772.67 -@@ -1132,7 +1132,7 @@ operation.
  772.68 -  * Explicitly prevent ring-switching for synchronized rendering to
  772.69 -    scanouts (for vsync).
  772.70 - 
  772.71 -- * Clip dirty region to slave pixmaps (otherwise UDL is nigh unusuable)
  772.72 -+ * Clip dirty region to slave pixmaps (otherwise UDL is nigh unusable)
  772.73 -    https://bugs.freedesktop.org/show_bug.cgi?id=59539
  772.74 - 
  772.75 - 
  772.76 -@@ -1226,7 +1226,7 @@ Release 2.20.15 (2012-12-03)
  772.77 - ============================
  772.78 - And lo, enabling more of the common acceleration paths for gen4 revealed
  772.79 - another lurking bug - something is wrong with how we prepare Y-tiling
  772.80 --surfaces for rendering. For the time being, we can surreptiously disable
  772.81 -+surfaces for rendering. For the time being, we can surreptitiously disable
  772.82 - them for gen4 and avoid hitting GPU hangs.
  772.83 - 
  772.84 -  * Avoid clobbering the render state after failing to convert the
  772.85 -@@ -1515,7 +1515,7 @@ Release 2.20.5 (2012-08-26)
  772.86 - Another silly bug found, another small bugfix release. The goal was for
  772.87 - the driver to bind to all Intel devices supported by the kernel.
  772.88 - Unfortunately we were too successful and started claiming Pouslbo,
  772.89 --Medfield and Cedarview devices which are still encumbered by propietary
  772.90 -+Medfield and Cedarview devices which are still encumbered by proprietary
  772.91 - IP and not supported by this driver.
  772.92 - 
  772.93 - Bugs fixed since 2.20.4:
  772.94 -diff --git a/README b/README
  772.95 -index cf4d88d8..348983b4 100644
  772.96 ---- a/README
  772.97 -+++ b/README
  772.98 -@@ -15,9 +15,9 @@ Intel graphics chipsets including:
  772.99 - 	G/Q33,G/Q35,G41,G/Q43,G/GM/Q45
 772.100 - 	PineView-M (Atom N400 series)
 772.101 - 	PineView-D (Atom D400/D500 series)
 772.102 --	Intel(R) HD Graphics: 2000-6000,
 772.103 --	Intel(R) Iris(TM) Graphics: 5100/6100, and
 772.104 --	Intel(R) Iris(TM) Pro Graphics: 5200/6200/P6300.
 772.105 -+	Intel(R) HD Graphics,
 772.106 -+	Intel(R) Iris(TM) Graphics,
 772.107 -+	Intel(R) Iris(TM) Pro Graphics.
 772.108 - 
 772.109 - Where to get more information about the driver
 772.110 - ----------------------------------------------
 772.111 -diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
 772.112 -new file mode 100644
 772.113 -index 00000000..301c0129
 772.114 ---- /dev/null
 772.115 -+++ b/benchmarks/.gitignore
 772.116 -@@ -0,0 +1,2 @@
 772.117 -+dri2-swap
 772.118 -+dri3-swap
 772.119 -diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am
 772.120 -new file mode 100644
 772.121 -index 00000000..4976e8a3
 772.122 ---- /dev/null
 772.123 -+++ b/benchmarks/Makefile.am
 772.124 -@@ -0,0 +1,14 @@
 772.125 -+AM_CFLAGS = @CWARNFLAGS@ $(X11_CFLAGS) $(DRM_CFLAGS)
 772.126 -+LDADD = $(X11_LIBS) $(DRM_LIBS) $(CLOCK_GETTIME_LIBS)
 772.127 -+
 772.128 -+check_PROGRAMS =
 772.129 -+
 772.130 -+if DRI2
 772.131 -+check_PROGRAMS += dri2-swap
 772.132 -+endif
 772.133 -+
 772.134 -+if DRI3
 772.135 -+check_PROGRAMS += dri3-swap
 772.136 -+AM_CFLAGS += $(X11_DRI3_CFLAGS)
 772.137 -+LDADD += $(X11_DRI3_LIBS)
 772.138 -+endif
 772.139 -diff --git a/benchmarks/dri2-swap.c b/benchmarks/dri2-swap.c
 772.140 -new file mode 100644
 772.141 -index 00000000..3d9d30aa
 772.142 ---- /dev/null
 772.143 -+++ b/benchmarks/dri2-swap.c
 772.144 -@@ -0,0 +1,588 @@
 772.145 -+/*
 772.146 -+ * Copyright (c) 2015 Intel Corporation
 772.147 -+ *
 772.148 -+ * Permission is hereby granted, free of charge, to any person obtaining a
 772.149 -+ * copy of this software and associated documentation files (the "Software"),
 772.150 -+ * to deal in the Software without restriction, including without limitation
 772.151 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 772.152 -+ * and/or sell copies of the Software, and to permit persons to whom the
 772.153 -+ * Software is furnished to do so, subject to the following conditions:
 772.154 -+ *
 772.155 -+ * The above copyright notice and this permission notice (including the next
 772.156 -+ * paragraph) shall be included in all copies or substantial portions of the
 772.157 -+ * Software.
 772.158 -+ *
 772.159 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 772.160 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 772.161 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 772.162 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 772.163 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 772.164 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 772.165 -+ * SOFTWARE.
 772.166 -+ *
 772.167 -+ */
 772.168 -+
 772.169 -+#ifdef HAVE_CONFIG_H
 772.170 -+#include "config.h"
 772.171 -+#endif
 772.172 -+
 772.173 -+#include <X11/Xlib.h>
 772.174 -+#include <X11/Xatom.h>
 772.175 -+#include <X11/Xlib-xcb.h>
 772.176 -+#include <X11/Xutil.h>
 772.177 -+#include <X11/Xlibint.h>
 772.178 -+#include <X11/extensions/dpms.h>
 772.179 -+#include <X11/extensions/randr.h>
 772.180 -+#include <X11/extensions/Xcomposite.h>
 772.181 -+#include <X11/extensions/Xdamage.h>
 772.182 -+#include <X11/extensions/Xrandr.h>
 772.183 -+#include <xcb/xcb.h>
 772.184 -+#include <xcb/dri2.h>
 772.185 -+#include <xf86drm.h>
 772.186 -+
 772.187 -+#include <stdio.h>
 772.188 -+#include <string.h>
 772.189 -+#include <fcntl.h>
 772.190 -+#include <unistd.h>
 772.191 -+#include <assert.h>
 772.192 -+#include <errno.h>
 772.193 -+#include <setjmp.h>
 772.194 -+#include <signal.h>
 772.195 -+
 772.196 -+#include <X11/Xlibint.h>
 772.197 -+#include <X11/extensions/Xext.h>
 772.198 -+#include <X11/extensions/extutil.h>
 772.199 -+#include <X11/extensions/dri2proto.h>
 772.200 -+#include <X11/extensions/dri2tokens.h>
 772.201 -+#include <X11/extensions/Xfixes.h>
 772.202 -+
 772.203 -+static char dri2ExtensionName[] = DRI2_NAME;
 772.204 -+static XExtensionInfo *dri2Info;
 772.205 -+static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
 772.206 -+
 772.207 -+static Bool
 772.208 -+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
 772.209 -+static Status
 772.210 -+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
 772.211 -+static int
 772.212 -+DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
 772.213 -+
 772.214 -+static /* const */ XExtensionHooks dri2ExtensionHooks = {
 772.215 -+  NULL,                   /* create_gc */
 772.216 -+  NULL,                   /* copy_gc */
 772.217 -+  NULL,                   /* flush_gc */
 772.218 -+  NULL,                   /* free_gc */
 772.219 -+  NULL,                   /* create_font */
 772.220 -+  NULL,                   /* free_font */
 772.221 -+  DRI2CloseDisplay,       /* close_display */
 772.222 -+  DRI2WireToEvent,        /* wire_to_event */
 772.223 -+  DRI2EventToWire,        /* event_to_wire */
 772.224 -+  DRI2Error,              /* error */
 772.225 -+  NULL,                   /* error_string */
 772.226 -+};
 772.227 -+
 772.228 -+static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
 772.229 -+                                   dri2Info,
 772.230 -+                                   dri2ExtensionName,
 772.231 -+                                   &dri2ExtensionHooks,
 772.232 -+                                   0, NULL)
 772.233 -+
 772.234 -+static Bool
 772.235 -+DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
 772.236 -+{
 772.237 -+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.238 -+
 772.239 -+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
 772.240 -+
 772.241 -+   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
 772.242 -+#ifdef X_DRI2SwapBuffers
 772.243 -+   case DRI2_BufferSwapComplete:
 772.244 -+      return False;
 772.245 -+#endif
 772.246 -+#ifdef DRI2_InvalidateBuffers
 772.247 -+   case DRI2_InvalidateBuffers:
 772.248 -+      return False;
 772.249 -+#endif
 772.250 -+   default:
 772.251 -+      /* client doesn't support server event */
 772.252 -+      break;
 772.253 -+   }
 772.254 -+
 772.255 -+   return False;
 772.256 -+}
 772.257 -+
 772.258 -+/* We don't actually support this.  It doesn't make sense for clients to
 772.259 -+ * send each other DRI2 events.
 772.260 -+ */
 772.261 -+static Status
 772.262 -+DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
 772.263 -+{
 772.264 -+   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.265 -+
 772.266 -+   XextCheckExtension(dpy, info, dri2ExtensionName, False);
 772.267 -+
 772.268 -+   switch (event->type) {
 772.269 -+   default:
 772.270 -+      /* client doesn't support server event */
 772.271 -+      break;
 772.272 -+   }
 772.273 -+
 772.274 -+   return Success;
 772.275 -+}
 772.276 -+
 772.277 -+static int
 772.278 -+DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
 772.279 -+{
 772.280 -+	if (err->majorCode == codes->major_opcode &&
 772.281 -+	    err->errorCode == BadDrawable &&
 772.282 -+	    err->minorCode == X_DRI2CopyRegion)
 772.283 -+		return True;
 772.284 -+
 772.285 -+	/* If the X drawable was destroyed before the GLX drawable, the
 772.286 -+	 * DRI2 drawble will be gone by the time we call
 772.287 -+	 * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
 772.288 -+	if (err->majorCode == codes->major_opcode &&
 772.289 -+	    err->errorCode == BadDrawable &&
 772.290 -+	    err->minorCode == X_DRI2DestroyDrawable)
 772.291 -+		return True;
 772.292 -+
 772.293 -+	/* If the server is non-local DRI2Connect will raise BadRequest.
 772.294 -+	 * Swallow this so that DRI2Connect can signal this in its return code */
 772.295 -+	if (err->majorCode == codes->major_opcode &&
 772.296 -+	    err->minorCode == X_DRI2Connect &&
 772.297 -+	    err->errorCode == BadRequest) {
 772.298 -+		*ret_code = False;
 772.299 -+		return True;
 772.300 -+	}
 772.301 -+
 772.302 -+	return False;
 772.303 -+}
 772.304 -+
 772.305 -+static Bool
 772.306 -+DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
 772.307 -+{
 772.308 -+	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.309 -+
 772.310 -+	if (XextHasExtension(info)) {
 772.311 -+		*eventBase = info->codes->first_event;
 772.312 -+		*errorBase = info->codes->first_error;
 772.313 -+		return True;
 772.314 -+	}
 772.315 -+
 772.316 -+	return False;
 772.317 -+}
 772.318 -+
 772.319 -+static Bool
 772.320 -+DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
 772.321 -+{
 772.322 -+	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.323 -+	xDRI2ConnectReply rep;
 772.324 -+	xDRI2ConnectReq *req;
 772.325 -+
 772.326 -+	XextCheckExtension(dpy, info, dri2ExtensionName, False);
 772.327 -+
 772.328 -+	LockDisplay(dpy);
 772.329 -+	GetReq(DRI2Connect, req);
 772.330 -+	req->reqType = info->codes->major_opcode;
 772.331 -+	req->dri2ReqType = X_DRI2Connect;
 772.332 -+	req->window = window;
 772.333 -+	req->driverType = DRI2DriverDRI;
 772.334 -+	if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
 772.335 -+		UnlockDisplay(dpy);
 772.336 -+		SyncHandle();
 772.337 -+		return False;
 772.338 -+	}
 772.339 -+
 772.340 -+	if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
 772.341 -+		UnlockDisplay(dpy);
 772.342 -+		SyncHandle();
 772.343 -+		return False;
 772.344 -+	}
 772.345 -+
 772.346 -+	*driverName = Xmalloc(rep.driverNameLength + 1);
 772.347 -+	if (*driverName == NULL) {
 772.348 -+		_XEatData(dpy,
 772.349 -+			  ((rep.driverNameLength + 3) & ~3) +
 772.350 -+			  ((rep.deviceNameLength + 3) & ~3));
 772.351 -+		UnlockDisplay(dpy);
 772.352 -+		SyncHandle();
 772.353 -+		return False;
 772.354 -+	}
 772.355 -+	_XReadPad(dpy, *driverName, rep.driverNameLength);
 772.356 -+	(*driverName)[rep.driverNameLength] = '\0';
 772.357 -+
 772.358 -+	*deviceName = Xmalloc(rep.deviceNameLength + 1);
 772.359 -+	if (*deviceName == NULL) {
 772.360 -+		Xfree(*driverName);
 772.361 -+		_XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
 772.362 -+		UnlockDisplay(dpy);
 772.363 -+		SyncHandle();
 772.364 -+		return False;
 772.365 -+	}
 772.366 -+	_XReadPad(dpy, *deviceName, rep.deviceNameLength);
 772.367 -+	(*deviceName)[rep.deviceNameLength] = '\0';
 772.368 -+
 772.369 -+	UnlockDisplay(dpy);
 772.370 -+	SyncHandle();
 772.371 -+
 772.372 -+	return True;
 772.373 -+}
 772.374 -+
 772.375 -+static Bool
 772.376 -+DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
 772.377 -+{
 772.378 -+	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.379 -+	xDRI2AuthenticateReq *req;
 772.380 -+	xDRI2AuthenticateReply rep;
 772.381 -+
 772.382 -+	XextCheckExtension(dpy, info, dri2ExtensionName, False);
 772.383 -+
 772.384 -+	LockDisplay(dpy);
 772.385 -+	GetReq(DRI2Authenticate, req);
 772.386 -+	req->reqType = info->codes->major_opcode;
 772.387 -+	req->dri2ReqType = X_DRI2Authenticate;
 772.388 -+	req->window = window;
 772.389 -+	req->magic = magic;
 772.390 -+
 772.391 -+	if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
 772.392 -+		UnlockDisplay(dpy);
 772.393 -+		SyncHandle();
 772.394 -+		return False;
 772.395 -+	}
 772.396 -+
 772.397 -+	UnlockDisplay(dpy);
 772.398 -+	SyncHandle();
 772.399 -+
 772.400 -+	return rep.authenticated;
 772.401 -+}
 772.402 -+
 772.403 -+static void
 772.404 -+DRI2CreateDrawable(Display * dpy, XID drawable)
 772.405 -+{
 772.406 -+	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.407 -+	xDRI2CreateDrawableReq *req;
 772.408 -+
 772.409 -+	XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
 772.410 -+
 772.411 -+	LockDisplay(dpy);
 772.412 -+	GetReq(DRI2CreateDrawable, req);
 772.413 -+	req->reqType = info->codes->major_opcode;
 772.414 -+	req->dri2ReqType = X_DRI2CreateDrawable;
 772.415 -+	req->drawable = drawable;
 772.416 -+	UnlockDisplay(dpy);
 772.417 -+	SyncHandle();
 772.418 -+}
 772.419 -+
 772.420 -+static void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
 772.421 -+{
 772.422 -+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
 772.423 -+    xDRI2SwapIntervalReq *req;
 772.424 -+
 772.425 -+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
 772.426 -+
 772.427 -+    LockDisplay(dpy);
 772.428 -+    GetReq(DRI2SwapInterval, req);
 772.429 -+    req->reqType = info->codes->major_opcode;
 772.430 -+    req->dri2ReqType = X_DRI2SwapInterval;
 772.431 -+    req->drawable = drawable;
 772.432 -+    req->interval = interval;
 772.433 -+    UnlockDisplay(dpy);
 772.434 -+    SyncHandle();
 772.435 -+}
 772.436 -+
 772.437 -+static int _x_error_occurred;
 772.438 -+
 772.439 -+static int
 772.440 -+_check_error_handler(Display     *display,
 772.441 -+		     XErrorEvent *event)
 772.442 -+{
 772.443 -+	fprintf(stderr,
 772.444 -+		"X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
 772.445 -+	       DisplayString(display),
 772.446 -+	       event->serial,
 772.447 -+	       event->error_code,
 772.448 -+	       event->request_code,
 772.449 -+	       event->minor_code);
 772.450 -+	_x_error_occurred++;
 772.451 -+	return False; /* ignored */
 772.452 -+}
 772.453 -+
 772.454 -+static double elapsed(const struct timespec *start,
 772.455 -+		      const struct timespec *end)
 772.456 -+{
 772.457 -+	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
 772.458 -+}
 772.459 -+
 772.460 -+static void run(Display *dpy, Window win)
 772.461 -+{
 772.462 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
 772.463 -+	struct timespec start, end;
 772.464 -+	int n, completed = 0;
 772.465 -+
 772.466 -+	clock_gettime(CLOCK_MONOTONIC, &start);
 772.467 -+	do {
 772.468 -+		for (n = 0; n < 1000; n++) {
 772.469 -+			unsigned int attachments[] = { DRI2BufferBackLeft };
 772.470 -+			unsigned int seq[2];
 772.471 -+
 772.472 -+			seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
 772.473 -+								 0, 0, 0, 0, 0, 0).sequence;
 772.474 -+
 772.475 -+
 772.476 -+			seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
 772.477 -+								1, 1, attachments).sequence;
 772.478 -+
 772.479 -+			xcb_flush(c);
 772.480 -+			xcb_discard_reply(c, seq[0]);
 772.481 -+			xcb_discard_reply(c, seq[1]);
 772.482 -+			completed++;
 772.483 -+		}
 772.484 -+		clock_gettime(CLOCK_MONOTONIC, &end);
 772.485 -+	} while (end.tv_sec < start.tv_sec + 10);
 772.486 -+
 772.487 -+	printf("%f\n", completed / (elapsed(&start, &end) / 1000000));
 772.488 -+}
 772.489 -+
 772.490 -+static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
 772.491 -+{
 772.492 -+	XRRScreenResources *res;
 772.493 -+
 772.494 -+	res = XRRGetScreenResourcesCurrent(dpy, window);
 772.495 -+	if (res == NULL)
 772.496 -+		res = XRRGetScreenResources(dpy, window);
 772.497 -+
 772.498 -+	return res;
 772.499 -+}
 772.500 -+
 772.501 -+static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
 772.502 -+{
 772.503 -+	int i;
 772.504 -+
 772.505 -+	for (i = 0; i < res->nmode; i++) {
 772.506 -+		if (res->modes[i].id == id)
 772.507 -+			return &res->modes[i];
 772.508 -+	}
 772.509 -+
 772.510 -+	return NULL;
 772.511 -+}
 772.512 -+
 772.513 -+static int dri2_open(Display *dpy)
 772.514 -+{
 772.515 -+	drm_auth_t auth;
 772.516 -+	char *driver, *device;
 772.517 -+	int fd;
 772.518 -+
 772.519 -+	if (!DRI2QueryExtension(dpy, &fd, &fd))
 772.520 -+		return -1;
 772.521 -+
 772.522 -+	if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
 772.523 -+		return -1;
 772.524 -+
 772.525 -+	fd = open(device, O_RDWR);
 772.526 -+	if (fd < 0)
 772.527 -+		return -1;
 772.528 -+
 772.529 -+	if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
 772.530 -+		return -1;
 772.531 -+
 772.532 -+	if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
 772.533 -+		return -1;
 772.534 -+
 772.535 -+	return fd;
 772.536 -+}
 772.537 -+
 772.538 -+static void fullscreen(Display *dpy, Window win)
 772.539 -+{
 772.540 -+	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
 772.541 -+	XChangeProperty(dpy, win,
 772.542 -+			XInternAtom(dpy, "_NET_WM_STATE", False),
 772.543 -+			XA_ATOM, 32, PropModeReplace,
 772.544 -+			(unsigned char *)&atom, 1);
 772.545 -+}
 772.546 -+
 772.547 -+static int has_composite(Display *dpy)
 772.548 -+{
 772.549 -+	int event, error;
 772.550 -+	int major, minor;
 772.551 -+
 772.552 -+	if (!XDamageQueryExtension (dpy, &event, &error))
 772.553 -+		return 0;
 772.554 -+
 772.555 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
 772.556 -+		return 0;
 772.557 -+
 772.558 -+	XCompositeQueryVersion(dpy, &major, &minor);
 772.559 -+
 772.560 -+	return major > 0 || minor >= 4;
 772.561 -+}
 772.562 -+
 772.563 -+int main(int argc, char **argv)
 772.564 -+{
 772.565 -+	Display *dpy;
 772.566 -+	Window root, win;
 772.567 -+	XRRScreenResources *res;
 772.568 -+	XRRCrtcInfo **original_crtc;
 772.569 -+	XSetWindowAttributes attr;
 772.570 -+	enum window { ROOT, FULLSCREEN, WINDOW } w = FULLSCREEN;
 772.571 -+	enum visible {REDIRECTED, NORMAL } v = NORMAL;
 772.572 -+	enum display { OFF, ON } d = OFF;
 772.573 -+	int width, height;
 772.574 -+	int i, fd;
 772.575 -+	int c;
 772.576 -+
 772.577 -+	while ((c = getopt(argc, argv, "d:v:w:")) != -1) {
 772.578 -+		switch (c) {
 772.579 -+		case 'd':
 772.580 -+			if (strcmp(optarg, "off") == 0)
 772.581 -+				d = OFF;
 772.582 -+			else if (strcmp(optarg, "on") == 0)
 772.583 -+				d = ON;
 772.584 -+			else
 772.585 -+				abort();
 772.586 -+			break;
 772.587 -+
 772.588 -+		case 'v':
 772.589 -+			if (strcmp(optarg, "redirected") == 0)
 772.590 -+				v = REDIRECTED;
 772.591 -+			else if (strcmp(optarg, "normal") == 0)
 772.592 -+				v = NORMAL;
 772.593 -+			else
 772.594 -+				abort();
 772.595 -+			break;
 772.596 -+
 772.597 -+		case 'w':
 772.598 -+			if (strcmp(optarg, "fullscreen") == 0)
 772.599 -+				w = FULLSCREEN;
 772.600 -+			else if (strcmp(optarg, "window") == 0)
 772.601 -+				w = WINDOW;
 772.602 -+			else if (strcmp(optarg, "root") == 0)
 772.603 -+				w = ROOT;
 772.604 -+			else
 772.605 -+				abort();
 772.606 -+			break;
 772.607 -+		}
 772.608 -+	}
 772.609 -+
 772.610 -+	attr.override_redirect = 1;
 772.611 -+
 772.612 -+	dpy = XOpenDisplay(NULL);
 772.613 -+	if (dpy == NULL)
 772.614 -+		return 77;
 772.615 -+
 772.616 -+	width = DisplayWidth(dpy, DefaultScreen(dpy));
 772.617 -+	height = DisplayHeight(dpy, DefaultScreen(dpy));
 772.618 -+
 772.619 -+	fd = dri2_open(dpy);
 772.620 -+	if (fd < 0)
 772.621 -+		return 77;
 772.622 -+
 772.623 -+	if (DPMSQueryExtension(dpy, &i, &i))
 772.624 -+		DPMSDisable(dpy);
 772.625 -+
 772.626 -+	root = DefaultRootWindow(dpy);
 772.627 -+
 772.628 -+	signal(SIGALRM, SIG_IGN);
 772.629 -+	XSetErrorHandler(_check_error_handler);
 772.630 -+
 772.631 -+	res = NULL;
 772.632 -+	if (XRRQueryVersion(dpy, &i, &i))
 772.633 -+		res = _XRRGetScreenResourcesCurrent(dpy, root);
 772.634 -+	if (res == NULL)
 772.635 -+		return 77;
 772.636 -+
 772.637 -+	if (v == REDIRECTED && !has_composite(dpy))
 772.638 -+		return 77;
 772.639 -+
 772.640 -+	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
 772.641 -+	for (i = 0; i < res->ncrtc; i++)
 772.642 -+		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
 772.643 -+
 772.644 -+	for (i = 0; i < res->ncrtc; i++)
 772.645 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 772.646 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
 772.647 -+
 772.648 -+	DRI2CreateDrawable(dpy, root);
 772.649 -+	DRI2SwapInterval(dpy, root, 0);
 772.650 -+
 772.651 -+	if (d != OFF) {
 772.652 -+		for (i = 0; i < res->noutput; i++) {
 772.653 -+			XRROutputInfo *output;
 772.654 -+			XRRModeInfo *mode;
 772.655 -+
 772.656 -+			output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
 772.657 -+			if (output == NULL)
 772.658 -+				continue;
 772.659 -+
 772.660 -+			mode = NULL;
 772.661 -+			if (res->nmode)
 772.662 -+				mode = lookup_mode(res, output->modes[0]);
 772.663 -+			if (mode == NULL)
 772.664 -+				continue;
 772.665 -+
 772.666 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[0], CurrentTime,
 772.667 -+					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
 772.668 -+			width = mode->width;
 772.669 -+			height = mode->height;
 772.670 -+			break;
 772.671 -+		}
 772.672 -+		if (i == res->noutput) {
 772.673 -+			_x_error_occurred = 77;
 772.674 -+			goto restore;
 772.675 -+		}
 772.676 -+	}
 772.677 -+
 772.678 -+	if (w == ROOT) {
 772.679 -+		run(dpy, root);
 772.680 -+	} else if (w == FULLSCREEN) {
 772.681 -+		win = XCreateWindow(dpy, root,
 772.682 -+				    0, 0, width, height, 0,
 772.683 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
 772.684 -+				    InputOutput,
 772.685 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
 772.686 -+				    CWOverrideRedirect, &attr);
 772.687 -+		DRI2CreateDrawable(dpy, win);
 772.688 -+		DRI2SwapInterval(dpy, win, 0);
 772.689 -+		if (v == REDIRECTED) {
 772.690 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
 772.691 -+			XDamageCreate(dpy, win, XDamageReportRawRectangles);
 772.692 -+		} else
 772.693 -+			fullscreen(dpy, win);
 772.694 -+		XMapWindow(dpy, win);
 772.695 -+		run(dpy, win);
 772.696 -+	} else if (w == WINDOW) {
 772.697 -+		win = XCreateWindow(dpy, root,
 772.698 -+				    0, 0, width/2, height/2, 0,
 772.699 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
 772.700 -+				    InputOutput,
 772.701 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
 772.702 -+				    CWOverrideRedirect, &attr);
 772.703 -+		DRI2CreateDrawable(dpy, win);
 772.704 -+		DRI2SwapInterval(dpy, win, 0);
 772.705 -+		if (v == REDIRECTED) {
 772.706 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
 772.707 -+			XDamageCreate(dpy, win, XDamageReportRawRectangles);
 772.708 -+		}
 772.709 -+		XMapWindow(dpy, win);
 772.710 -+		run(dpy, win);
 772.711 -+	}
 772.712 -+
 772.713 -+restore:
 772.714 -+	for (i = 0; i < res->ncrtc; i++)
 772.715 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 772.716 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
 772.717 -+
 772.718 -+	for (i = 0; i < res->ncrtc; i++)
 772.719 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
 772.720 -+				 original_crtc[i]->x,
 772.721 -+				 original_crtc[i]->y,
 772.722 -+				 original_crtc[i]->mode,
 772.723 -+				 original_crtc[i]->rotation,
 772.724 -+				 original_crtc[i]->outputs,
 772.725 -+				 original_crtc[i]->noutput);
 772.726 -+
 772.727 -+	if (DPMSQueryExtension(dpy, &i, &i))
 772.728 -+		DPMSEnable(dpy);
 772.729 -+
 772.730 -+	XSync(dpy, True);
 772.731 -+	return _x_error_occurred;
 772.732 -+}
 772.733 -diff --git a/benchmarks/dri3-swap.c b/benchmarks/dri3-swap.c
 772.734 -new file mode 100644
 772.735 -index 00000000..4dd423b3
 772.736 ---- /dev/null
 772.737 -+++ b/benchmarks/dri3-swap.c
 772.738 -@@ -0,0 +1,595 @@
 772.739 -+/*
 772.740 -+ * Copyright (c) 2015 Intel Corporation
 772.741 -+ *
 772.742 -+ * Permission is hereby granted, free of charge, to any person obtaining a
 772.743 -+ * copy of this software and associated documentation files (the "Software"),
 772.744 -+ * to deal in the Software without restriction, including without limitation
 772.745 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 772.746 -+ * and/or sell copies of the Software, and to permit persons to whom the
 772.747 -+ * Software is furnished to do so, subject to the following conditions:
 772.748 -+ *
 772.749 -+ * The above copyright notice and this permission notice (including the next
 772.750 -+ * paragraph) shall be included in all copies or substantial portions of the
 772.751 -+ * Software.
 772.752 -+ *
 772.753 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 772.754 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 772.755 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 772.756 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 772.757 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 772.758 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 772.759 -+ * SOFTWARE.
 772.760 -+ *
 772.761 -+ */
 772.762 -+
 772.763 -+#ifdef HAVE_CONFIG_H
 772.764 -+#include "config.h"
 772.765 -+#endif
 772.766 -+
 772.767 -+#include <X11/Xlib.h>
 772.768 -+#include <X11/Xatom.h>
 772.769 -+#include <X11/Xlib-xcb.h>
 772.770 -+#include <X11/xshmfence.h>
 772.771 -+#include <X11/Xutil.h>
 772.772 -+#include <X11/Xlibint.h>
 772.773 -+#include <X11/extensions/Xcomposite.h>
 772.774 -+#include <X11/extensions/Xdamage.h>
 772.775 -+#include <X11/extensions/dpms.h>
 772.776 -+#include <X11/extensions/randr.h>
 772.777 -+#include <X11/extensions/Xrandr.h>
 772.778 -+#include <xcb/xcb.h>
 772.779 -+#include <xcb/present.h>
 772.780 -+#include <xcb/dri3.h>
 772.781 -+#include <xcb/xfixes.h>
 772.782 -+#include <xf86drm.h>
 772.783 -+#include <i915_drm.h>
 772.784 -+
 772.785 -+#include <stdio.h>
 772.786 -+#include <string.h>
 772.787 -+#include <fcntl.h>
 772.788 -+#include <unistd.h>
 772.789 -+#include <assert.h>
 772.790 -+#include <errno.h>
 772.791 -+#include <setjmp.h>
 772.792 -+#include <signal.h>
 772.793 -+
 772.794 -+struct dri3_fence {
 772.795 -+	XID xid;
 772.796 -+	void *addr;
 772.797 -+};
 772.798 -+
 772.799 -+static int _x_error_occurred;
 772.800 -+static uint32_t stamp;
 772.801 -+
 772.802 -+struct list {
 772.803 -+    struct list *next, *prev;
 772.804 -+};
 772.805 -+
 772.806 -+static void
 772.807 -+list_init(struct list *list)
 772.808 -+{
 772.809 -+    list->next = list->prev = list;
 772.810 -+}
 772.811 -+
 772.812 -+static inline void
 772.813 -+__list_add(struct list *entry,
 772.814 -+	    struct list *prev,
 772.815 -+	    struct list *next)
 772.816 -+{
 772.817 -+    next->prev = entry;
 772.818 -+    entry->next = next;
 772.819 -+    entry->prev = prev;
 772.820 -+    prev->next = entry;
 772.821 -+}
 772.822 -+
 772.823 -+static inline void
 772.824 -+list_add(struct list *entry, struct list *head)
 772.825 -+{
 772.826 -+    __list_add(entry, head, head->next);
 772.827 -+}
 772.828 -+
 772.829 -+static inline void
 772.830 -+__list_del(struct list *prev, struct list *next)
 772.831 -+{
 772.832 -+	next->prev = prev;
 772.833 -+	prev->next = next;
 772.834 -+}
 772.835 -+
 772.836 -+static inline void
 772.837 -+_list_del(struct list *entry)
 772.838 -+{
 772.839 -+    __list_del(entry->prev, entry->next);
 772.840 -+}
 772.841 -+
 772.842 -+static inline void
 772.843 -+list_move(struct list *list, struct list *head)
 772.844 -+{
 772.845 -+	if (list->prev != head) {
 772.846 -+		_list_del(list);
 772.847 -+		list_add(list, head);
 772.848 -+	}
 772.849 -+}
 772.850 -+
 772.851 -+#define __container_of(ptr, sample, member)				\
 772.852 -+    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
 772.853 -+
 772.854 -+#define list_for_each_entry(pos, head, member)				\
 772.855 -+    for (pos = __container_of((head)->next, pos, member);		\
 772.856 -+	 &pos->member != (head);					\
 772.857 -+	 pos = __container_of(pos->member.next, pos, member))
 772.858 -+
 772.859 -+static int
 772.860 -+_check_error_handler(Display     *display,
 772.861 -+		     XErrorEvent *event)
 772.862 -+{
 772.863 -+	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
 772.864 -+	       DisplayString(display),
 772.865 -+	       event->serial,
 772.866 -+	       event->error_code,
 772.867 -+	       event->request_code,
 772.868 -+	       event->minor_code);
 772.869 -+	_x_error_occurred++;
 772.870 -+	return False; /* ignored */
 772.871 -+}
 772.872 -+
 772.873 -+static int dri3_create_fence(Display *dpy,
 772.874 -+			     Pixmap pixmap,
 772.875 -+			     struct dri3_fence *fence)
 772.876 -+{
 772.877 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
 772.878 -+	struct dri3_fence f;
 772.879 -+	int fd;
 772.880 -+
 772.881 -+	fd = xshmfence_alloc_shm();
 772.882 -+	if (fd < 0)
 772.883 -+		return -1;
 772.884 -+
 772.885 -+	f.addr = xshmfence_map_shm(fd);
 772.886 -+	if (f.addr == NULL) {
 772.887 -+		close(fd);
 772.888 -+		return -1;
 772.889 -+	}
 772.890 -+
 772.891 -+	f.xid = xcb_generate_id(c);
 772.892 -+	xcb_dri3_fence_from_fd(c, pixmap, f.xid, 0, fd);
 772.893 -+
 772.894 -+	*fence = f;
 772.895 -+	return 0;
 772.896 -+}
 772.897 -+
 772.898 -+static double elapsed(const struct timespec *start,
 772.899 -+		      const struct timespec *end)
 772.900 -+{
 772.901 -+	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
 772.902 -+}
 772.903 -+
 772.904 -+struct buffer {
 772.905 -+	struct list link;
 772.906 -+	Pixmap pixmap;
 772.907 -+	struct dri3_fence fence;
 772.908 -+	int fd;
 772.909 -+	int busy;
 772.910 -+};
 772.911 -+
 772.912 -+static void run(Display *dpy, Window win)
 772.913 -+{
 772.914 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
 772.915 -+	struct timespec start, end;
 772.916 -+#define N_BACK 8
 772.917 -+	struct buffer buffer[N_BACK];
 772.918 -+	struct list mru;
 772.919 -+	Window root;
 772.920 -+	unsigned int width, height;
 772.921 -+	unsigned border, depth;
 772.922 -+	unsigned present_flags = XCB_PRESENT_OPTION_ASYNC;
 772.923 -+	xcb_xfixes_region_t update = 0;
 772.924 -+	int completed = 0;
 772.925 -+	int queued = 0;
 772.926 -+	uint32_t eid;
 772.927 -+	void *Q;
 772.928 -+	int i, n;
 772.929 -+
 772.930 -+	list_init(&mru);
 772.931 -+
 772.932 -+	XGetGeometry(dpy, win,
 772.933 -+		     &root, &i, &n, &width, &height, &border, &depth);
 772.934 -+
 772.935 -+	_x_error_occurred = 0;
 772.936 -+
 772.937 -+	for (n = 0; n < N_BACK; n++) {
 772.938 -+		xcb_dri3_buffer_from_pixmap_reply_t *reply;
 772.939 -+		int *fds;
 772.940 -+
 772.941 -+		buffer[n].pixmap =
 772.942 -+			XCreatePixmap(dpy, win, width, height, depth);
 772.943 -+		buffer[n].fence.xid = 0;
 772.944 -+		buffer[n].fd = -1;
 772.945 -+
 772.946 -+		if (dri3_create_fence(dpy, win, &buffer[n].fence))
 772.947 -+			return;
 772.948 -+
 772.949 -+		reply = xcb_dri3_buffer_from_pixmap_reply (c,
 772.950 -+							   xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
 772.951 -+							   NULL);
 772.952 -+		if (reply == NULL)
 772.953 -+			return;
 772.954 -+
 772.955 -+		fds = xcb_dri3_buffer_from_pixmap_reply_fds (c, reply);
 772.956 -+		buffer[n].fd = fds[0];
 772.957 -+		free(reply);
 772.958 -+
 772.959 -+		/* start idle */
 772.960 -+		xshmfence_trigger(buffer[n].fence.addr);
 772.961 -+		buffer[n].busy = 0;
 772.962 -+		list_add(&buffer[n].link, &mru);
 772.963 -+	}
 772.964 -+
 772.965 -+	eid = xcb_generate_id(c);
 772.966 -+	xcb_present_select_input(c, eid, win,
 772.967 -+                                 XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY |
 772.968 -+                                 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
 772.969 -+	Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
 772.970 -+
 772.971 -+	clock_gettime(CLOCK_MONOTONIC, &start);
 772.972 -+	do {
 772.973 -+		for (n = 0; n < 1000; n++) {
 772.974 -+			struct buffer *tmp, *b = NULL;
 772.975 -+			list_for_each_entry(tmp, &mru, link) {
 772.976 -+				if (!tmp->busy) {
 772.977 -+					b = tmp;
 772.978 -+					break;
 772.979 -+				}
 772.980 -+			}
 772.981 -+			while (b == NULL) {
 772.982 -+				xcb_present_generic_event_t *ev;
 772.983 -+
 772.984 -+				ev = (xcb_present_generic_event_t *)
 772.985 -+					xcb_wait_for_special_event(c, Q);
 772.986 -+				if (ev == NULL)
 772.987 -+					abort();
 772.988 -+
 772.989 -+				do {
 772.990 -+					switch (ev->evtype) {
 772.991 -+					case XCB_PRESENT_COMPLETE_NOTIFY:
 772.992 -+						completed++;
 772.993 -+						queued--;
 772.994 -+						break;
 772.995 -+
 772.996 -+					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
 772.997 -+						{
 772.998 -+							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
 772.999 -+							assert(ie->serial < N_BACK);
772.1000 -+							buffer[ie->serial].busy = 0;
772.1001 -+							if (b == NULL)
772.1002 -+								b = &buffer[ie->serial];
772.1003 -+							break;
772.1004 -+						}
772.1005 -+					}
772.1006 -+					free(ev);
772.1007 -+				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
772.1008 -+			}
772.1009 -+
772.1010 -+			b->busy = 1;
772.1011 -+			if (b->fence.xid) {
772.1012 -+				xshmfence_await(b->fence.addr);
772.1013 -+				xshmfence_reset(b->fence.addr);
772.1014 -+			}
772.1015 -+			xcb_present_pixmap(c, win, b->pixmap, b - buffer,
772.1016 -+					   0, /* valid */
772.1017 -+					   update, /* update */
772.1018 -+					   0, /* x_off */
772.1019 -+					   0, /* y_off */
772.1020 -+					   None,
772.1021 -+					   None, /* wait fence */
772.1022 -+					   b->fence.xid,
772.1023 -+					   present_flags,
772.1024 -+					   0, /* target msc */
772.1025 -+					   0, /* divisor */
772.1026 -+					   0, /* remainder */
772.1027 -+					   0, NULL);
772.1028 -+			list_move(&b->link, &mru);
772.1029 -+			queued++;
772.1030 -+			xcb_flush(c);
772.1031 -+		}
772.1032 -+		clock_gettime(CLOCK_MONOTONIC, &end);
772.1033 -+	} while (end.tv_sec < start.tv_sec + 10);
772.1034 -+
772.1035 -+	while (queued) {
772.1036 -+		xcb_present_generic_event_t *ev;
772.1037 -+
772.1038 -+		ev = (xcb_present_generic_event_t *)
772.1039 -+			xcb_wait_for_special_event(c, Q);
772.1040 -+		if (ev == NULL)
772.1041 -+			abort();
772.1042 -+
772.1043 -+		do {
772.1044 -+			switch (ev->evtype) {
772.1045 -+			case XCB_PRESENT_COMPLETE_NOTIFY:
772.1046 -+				completed++;
772.1047 -+				queued--;
772.1048 -+				break;
772.1049 -+
772.1050 -+			case XCB_PRESENT_EVENT_IDLE_NOTIFY:
772.1051 -+				break;
772.1052 -+			}
772.1053 -+			free(ev);
772.1054 -+		} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
772.1055 -+	}
772.1056 -+	clock_gettime(CLOCK_MONOTONIC, &end);
772.1057 -+
772.1058 -+	printf("%f\n", completed / (elapsed(&start, &end) / 1000000));
772.1059 -+}
772.1060 -+
772.1061 -+static int has_present(Display *dpy)
772.1062 -+{
772.1063 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.1064 -+	xcb_generic_error_t *error = NULL;
772.1065 -+	void *reply;
772.1066 -+
772.1067 -+	reply = xcb_present_query_version_reply(c,
772.1068 -+						xcb_present_query_version(c,
772.1069 -+									  XCB_PRESENT_MAJOR_VERSION,
772.1070 -+									  XCB_PRESENT_MINOR_VERSION),
772.1071 -+						&error);
772.1072 -+
772.1073 -+	free(reply);
772.1074 -+	free(error);
772.1075 -+	if (reply == NULL) {
772.1076 -+		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
772.1077 -+		return 0;
772.1078 -+	}
772.1079 -+
772.1080 -+	return 1;
772.1081 -+}
772.1082 -+
772.1083 -+static int has_composite(Display *dpy)
772.1084 -+{
772.1085 -+	int event, error;
772.1086 -+	int major, minor;
772.1087 -+
772.1088 -+	if (!XDamageQueryExtension (dpy, &event, &error))
772.1089 -+		return 0;
772.1090 -+
772.1091 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
772.1092 -+		return 0;
772.1093 -+
772.1094 -+	XCompositeQueryVersion(dpy, &major, &minor);
772.1095 -+
772.1096 -+	return major > 0 || minor >= 4;
772.1097 -+}
772.1098 -+
772.1099 -+static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
772.1100 -+{
772.1101 -+	XRRScreenResources *res;
772.1102 -+
772.1103 -+	res = XRRGetScreenResourcesCurrent(dpy, window);
772.1104 -+	if (res == NULL)
772.1105 -+		res = XRRGetScreenResources(dpy, window);
772.1106 -+
772.1107 -+	return res;
772.1108 -+}
772.1109 -+
772.1110 -+static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
772.1111 -+{
772.1112 -+	int i;
772.1113 -+
772.1114 -+	for (i = 0; i < res->nmode; i++) {
772.1115 -+		if (res->modes[i].id == id)
772.1116 -+			return &res->modes[i];
772.1117 -+	}
772.1118 -+
772.1119 -+	return NULL;
772.1120 -+}
772.1121 -+
772.1122 -+static void fullscreen(Display *dpy, Window win)
772.1123 -+{
772.1124 -+	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
772.1125 -+	XChangeProperty(dpy, win,
772.1126 -+			XInternAtom(dpy, "_NET_WM_STATE", False),
772.1127 -+			XA_ATOM, 32, PropModeReplace,
772.1128 -+			(unsigned char *)&atom, 1);
772.1129 -+}
772.1130 -+
772.1131 -+static int dri3_query_version(Display *dpy, int *major, int *minor)
772.1132 -+{
772.1133 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.1134 -+	xcb_dri3_query_version_reply_t *reply;
772.1135 -+	xcb_generic_error_t *error;
772.1136 -+
772.1137 -+	*major = *minor = -1;
772.1138 -+
772.1139 -+	reply = xcb_dri3_query_version_reply(c,
772.1140 -+					     xcb_dri3_query_version(c,
772.1141 -+								    XCB_DRI3_MAJOR_VERSION,
772.1142 -+								    XCB_DRI3_MINOR_VERSION),
772.1143 -+					     &error);
772.1144 -+	free(error);
772.1145 -+	if (reply == NULL)
772.1146 -+		return -1;
772.1147 -+
772.1148 -+	*major = reply->major_version;
772.1149 -+	*minor = reply->minor_version;
772.1150 -+	free(reply);
772.1151 -+
772.1152 -+	return 0;
772.1153 -+}
772.1154 -+
772.1155 -+static int has_dri3(Display *dpy)
772.1156 -+{
772.1157 -+	const xcb_query_extension_reply_t *ext;
772.1158 -+	int major, minor;
772.1159 -+
772.1160 -+	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
772.1161 -+	if (ext == NULL || !ext->present)
772.1162 -+		return 0;
772.1163 -+
772.1164 -+	if (dri3_query_version(dpy, &major, &minor) < 0)
772.1165 -+		return 0;
772.1166 -+
772.1167 -+	return major >= 0;
772.1168 -+}
772.1169 -+
772.1170 -+int main(int argc, char **argv)
772.1171 -+{
772.1172 -+	Display *dpy;
772.1173 -+	Window root, win;
772.1174 -+	XRRScreenResources *res;
772.1175 -+	XRRCrtcInfo **original_crtc;
772.1176 -+	XSetWindowAttributes attr;
772.1177 -+	enum window { ROOT, FULLSCREEN, WINDOW } w = FULLSCREEN;
772.1178 -+	enum visible {REDIRECTED, NORMAL } v = NORMAL;
772.1179 -+	enum display { OFF, ON } d = OFF;
772.1180 -+	int width, height;
772.1181 -+	int i;
772.1182 -+
772.1183 -+	while ((i = getopt(argc, argv, "d:v:w:")) != -1) {
772.1184 -+		switch (i) {
772.1185 -+		case 'd':
772.1186 -+			if (strcmp(optarg, "off") == 0)
772.1187 -+				d = OFF;
772.1188 -+			else if (strcmp(optarg, "on") == 0)
772.1189 -+				d = ON;
772.1190 -+			else
772.1191 -+				abort();
772.1192 -+			break;
772.1193 -+
772.1194 -+		case 'v':
772.1195 -+			if (strcmp(optarg, "redirected") == 0)
772.1196 -+				v = REDIRECTED;
772.1197 -+			else if (strcmp(optarg, "normal") == 0)
772.1198 -+				v = NORMAL;
772.1199 -+			else
772.1200 -+				abort();
772.1201 -+			break;
772.1202 -+
772.1203 -+		case 'w':
772.1204 -+			if (strcmp(optarg, "fullscreen") == 0)
772.1205 -+				w = FULLSCREEN;
772.1206 -+			else if (strcmp(optarg, "window") == 0)
772.1207 -+				w = WINDOW;
772.1208 -+			else if (strcmp(optarg, "root") == 0)
772.1209 -+				w = ROOT;
772.1210 -+			else
772.1211 -+				abort();
772.1212 -+			break;
772.1213 -+		}
772.1214 -+	}
772.1215 -+
772.1216 -+	attr.override_redirect = 1;
772.1217 -+
772.1218 -+	dpy = XOpenDisplay(NULL);
772.1219 -+	if (dpy == NULL)
772.1220 -+		return 77;
772.1221 -+
772.1222 -+	width = DisplayWidth(dpy, DefaultScreen(dpy));
772.1223 -+	height = DisplayHeight(dpy, DefaultScreen(dpy));
772.1224 -+
772.1225 -+	if (!has_present(dpy))
772.1226 -+		return 77;
772.1227 -+
772.1228 -+	if (!has_dri3(dpy))
772.1229 -+		return 77;
772.1230 -+
772.1231 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.1232 -+		DPMSDisable(dpy);
772.1233 -+
772.1234 -+	root = DefaultRootWindow(dpy);
772.1235 -+
772.1236 -+	signal(SIGALRM, SIG_IGN);
772.1237 -+	XSetErrorHandler(_check_error_handler);
772.1238 -+
772.1239 -+	res = NULL;
772.1240 -+	if (XRRQueryVersion(dpy, &i, &i))
772.1241 -+		res = _XRRGetScreenResourcesCurrent(dpy, root);
772.1242 -+	if (res == NULL)
772.1243 -+		return 77;
772.1244 -+
772.1245 -+	if (v == REDIRECTED && !has_composite(dpy))
772.1246 -+		return 77;
772.1247 -+
772.1248 -+	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
772.1249 -+	for (i = 0; i < res->ncrtc; i++)
772.1250 -+		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
772.1251 -+
772.1252 -+	for (i = 0; i < res->ncrtc; i++)
772.1253 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.1254 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
772.1255 -+
772.1256 -+	if (d != OFF) {
772.1257 -+		for (i = 0; i < res->noutput; i++) {
772.1258 -+			XRROutputInfo *output;
772.1259 -+			XRRModeInfo *mode;
772.1260 -+
772.1261 -+			output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
772.1262 -+			if (output == NULL)
772.1263 -+				continue;
772.1264 -+
772.1265 -+			mode = NULL;
772.1266 -+			if (res->nmode)
772.1267 -+				mode = lookup_mode(res, output->modes[0]);
772.1268 -+			if (mode == NULL)
772.1269 -+				continue;
772.1270 -+
772.1271 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[0], CurrentTime,
772.1272 -+					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
772.1273 -+			width = mode->width;
772.1274 -+			height = mode->height;
772.1275 -+			break;
772.1276 -+		}
772.1277 -+		if (i == res->noutput) {
772.1278 -+			_x_error_occurred = 77;
772.1279 -+			goto restore;
772.1280 -+		}
772.1281 -+	}
772.1282 -+
772.1283 -+	if (w == ROOT) {
772.1284 -+		run(dpy, root);
772.1285 -+	} else if (w == FULLSCREEN) {
772.1286 -+		win = XCreateWindow(dpy, root,
772.1287 -+				    0, 0, width, height, 0,
772.1288 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.1289 -+				    InputOutput,
772.1290 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.1291 -+				    CWOverrideRedirect, &attr);
772.1292 -+		if (v == REDIRECTED) {
772.1293 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.1294 -+			XDamageCreate(dpy, win, XDamageReportRawRectangles);
772.1295 -+		} else
772.1296 -+			fullscreen(dpy, win);
772.1297 -+		XMapWindow(dpy, win);
772.1298 -+		run(dpy, win);
772.1299 -+	} else if (w == WINDOW) {
772.1300 -+		win = XCreateWindow(dpy, root,
772.1301 -+				    0, 0, width/2, height/2, 0,
772.1302 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.1303 -+				    InputOutput,
772.1304 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.1305 -+				    CWOverrideRedirect, &attr);
772.1306 -+		if (v == REDIRECTED) {
772.1307 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.1308 -+			XDamageCreate(dpy, win, XDamageReportRawRectangles);
772.1309 -+		}
772.1310 -+		XMapWindow(dpy, win);
772.1311 -+		run(dpy, win);
772.1312 -+	}
772.1313 -+
772.1314 -+restore:
772.1315 -+	for (i = 0; i < res->ncrtc; i++)
772.1316 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.1317 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
772.1318 -+
772.1319 -+	for (i = 0; i < res->ncrtc; i++)
772.1320 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.1321 -+				 original_crtc[i]->x,
772.1322 -+				 original_crtc[i]->y,
772.1323 -+				 original_crtc[i]->mode,
772.1324 -+				 original_crtc[i]->rotation,
772.1325 -+				 original_crtc[i]->outputs,
772.1326 -+				 original_crtc[i]->noutput);
772.1327 -+
772.1328 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.1329 -+		DPMSEnable(dpy);
772.1330 -+
772.1331 -+	XSync(dpy, True);
772.1332 -+	return _x_error_occurred;
772.1333 -+}
772.1334 -diff --git a/configure.ac b/configure.ac
772.1335 -index 61bea435..d13917ec 100644
772.1336 ---- a/configure.ac
772.1337 -+++ b/configure.ac
772.1338 -@@ -195,18 +195,24 @@ AC_ARG_ENABLE(udev,
772.1339 -               [UDEV="$enableval"],
772.1340 -               [UDEV=auto])
772.1341 - 
772.1342 -+udev_msg=" disabled"
772.1343 - if test "x$UDEV" != "xno"; then
772.1344 - 	PKG_CHECK_MODULES(UDEV, [libudev], [udev="yes"], [udev="no"])
772.1345 -+	AC_CHECK_HEADERS([sys/stat.h], [], [udev="no"])
772.1346 - 	if test "x$UDEV" = "xyes" -a "x$udev" != "xyes"; then
772.1347 - 		AC_MSG_ERROR([udev support requested but not found (libudev)])
772.1348 - 	fi
772.1349 - 	if test "x$udev" = "xyes"; then
772.1350 - 		AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
772.1351 -+		udev_msg=" yes"
772.1352 -+	else
772.1353 -+		udev_msg=" no"
772.1354 - 	fi
772.1355 - fi
772.1356 - 
772.1357 --PKG_CHECK_MODULES(X11, [x11 xrender xrandr xext xfixes cairo cairo-xlib-xrender pixman-1 libpng], [x11="yes"], [x11="no"])
772.1358 -+PKG_CHECK_MODULES(X11, [x11 x11-xcb xcb-dri2 xcomposite xdamage xrender xrandr xext xfixes cairo cairo-xlib-xrender pixman-1 libpng], [x11="yes"], [x11="no"])
772.1359 - AM_CONDITIONAL(HAVE_X11, test "x$x11" = "xyes")
772.1360 -+echo X11_CLFAGS="$X11_CLFAGS" X11_LIBS="$X11_LIBS"
772.1361 - 
772.1362 - cpuid="yes"
772.1363 - AC_TRY_LINK([
772.1364 -@@ -270,10 +276,13 @@ if test "x$shm" = "xyes"; then
772.1365 - 	AC_DEFINE([HAVE_MIT_SHM], 1, [Define to 1 if MIT-SHM is available])
772.1366 - fi
772.1367 - 
772.1368 --PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-present x11-xcb xshmfence x11 xrender xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
772.1369 -+PKG_CHECK_MODULES(X11_DRI3, [xcb-dri3 xcb-sync xcb-xfixes xcb-present x11-xcb xshmfence x11 xcomposite xdamage xrender xrandr xxf86vm xext libdrm], [x11_dri3="yes"], [x11_dri3="no"])
772.1370 - AM_CONDITIONAL(X11_DRI3, test "x$x11_dri3" = "xyes" -a "x$shm" = "xyes")
772.1371 - AM_CONDITIONAL(X11_SHM, test "x$shm" = "xyes")
772.1372 - 
772.1373 -+PKG_CHECK_MODULES(X11_VM, [xxf86vm], [x11_vm="yes"], [x11_vm="no"])
772.1374 -+AM_CONDITIONAL(X11_VM, test "x$x11_vm" = "xyes")
772.1375 -+
772.1376 - AC_ARG_ENABLE(tools,
772.1377 -               AS_HELP_STRING([--disable-tools],
772.1378 - 			     [Enable building and installing the miscellaneous tools [default=auto]]),
772.1379 -@@ -285,7 +294,7 @@ if test "x$shm" != "xyes"; then
772.1380 - 	tools="no"
772.1381 - fi
772.1382 - if test "x$tools" != "xno"; then
772.1383 --	ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xext x11 pixman-1"
772.1384 -+	ivo_requires="xrandr xdamage xfixes xcursor xtst xrender xscrnsaver xext x11 pixman-1"
772.1385 - 	extra_cflags=""
772.1386 - 
772.1387 - 	ignore="xinerama"
772.1388 -@@ -307,6 +316,8 @@ if test "x$tools" != "xno"; then
772.1389 - 		tools="no"
772.1390 - 	fi
772.1391 - 
772.1392 -+	PKG_CHECK_MODULES(TOOL_CURSOR, [xfixes x11 libpng], [cursor="yes"], [ivo="no"])
772.1393 -+
772.1394 - 	IVO_CFLAGS="$IVO_CFLAGS $extra_cflags"
772.1395 - fi
772.1396 - if test "x$tools" != "xno"; then
772.1397 -@@ -315,6 +326,7 @@ fi
772.1398 - AC_MSG_CHECKING([whether to build additional tools])
772.1399 - AC_MSG_RESULT([$tools])
772.1400 - AM_CONDITIONAL(BUILD_TOOLS, test "x$tools" != "xno")
772.1401 -+AM_CONDITIONAL(BUILD_TOOL_CURSOR, test "x$cursor" = "xyes")
772.1402 - 
772.1403 - # Define a configure option for an alternate module directory
772.1404 - AC_ARG_WITH(xorg-module-dir,
772.1405 -@@ -339,10 +351,20 @@ AC_ARG_ENABLE(dri2,
772.1406 - 	      [DRI2=$enableval],
772.1407 - 	      [DRI2=yes])
772.1408 - AC_ARG_ENABLE(dri3,
772.1409 --	      AS_HELP_STRING([--enable-dri3],
772.1410 --			     [Enable DRI3 support [[default=no]]]),
772.1411 -+	      AS_HELP_STRING([--disable-dri3],
772.1412 -+			     [Disable DRI3 support [[default=yes]]]),
772.1413 - 	      [DRI3=$enableval],
772.1414 --	      [DRI3=no])
772.1415 -+	      [DRI3=yes])
772.1416 -+AC_ARG_WITH(default-dri,
772.1417 -+	    AS_HELP_STRING([--with-default-dri],
772.1418 -+			   [Select the default maximum DRI level [default 2]]),
772.1419 -+	      [DRI_DEFAULT=$withval],
772.1420 -+	      [DRI_DEFAULT=2])
772.1421 -+if test "x$DRI_DEFAULT" = "x0"; then
772.1422 -+	AC_DEFINE(DEFAULT_DRI_LEVEL, 0,[Default DRI level])
772.1423 -+else
772.1424 -+	AC_DEFINE(DEFAULT_DRI_LEVEL, ~0, [Default DRI level])
772.1425 -+fi
772.1426 - 
772.1427 - AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc],
772.1428 -                                   [Disable XvMC support [[default=yes]]]),
772.1429 -@@ -375,14 +397,12 @@ AC_ARG_ENABLE(ums-only,
772.1430 - required_xorg_server_version=1.6
772.1431 - required_pixman_version=0.16
772.1432 - 
772.1433 --if pkg-config --exists 'pixman-1 >= 0.27.1'; then
772.1434 --	AC_DEFINE([HAS_PIXMAN_GLYPHS], 1, [Enable pixman glyph cache])
772.1435 --fi
772.1436 --
772.1437 --if pkg-config --exists 'pixman-1 >= 0.24.0'; then
772.1438 --	AC_DEFINE([HAS_PIXMAN_TRIANGLES], 1, [Enable pixman triangle rasterisation])
772.1439 --fi
772.1440 --
772.1441 -+PKG_CHECK_EXISTS([pixman-1 >= 0.24.0],
772.1442 -+		 AC_DEFINE([HAS_PIXMAN_TRIANGLES], 1, [Enable pixman triangle rasterisation])
772.1443 -+		 [])
772.1444 -+PKG_CHECK_EXISTS([pixman-1 >= 0.27.1],
772.1445 -+		 [AC_DEFINE([HAS_PIXMAN_GLYPHS], 1, [Enable pixman glyph cache])],
772.1446 -+		 [])
772.1447 - # Store the list of server defined optional extensions in REQUIRED_MODULES
772.1448 - XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
772.1449 - XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
772.1450 -@@ -398,24 +418,25 @@ AC_ARG_ENABLE(sna,
772.1451 - 	      [SNA="$enableval"],
772.1452 - 	      [SNA=auto])
772.1453 - 
772.1454 -+AC_CHECK_HEADERS([dev/wscons/wsconsio.h])
772.1455 -+AC_FUNC_ALLOCA
772.1456 -+AC_HEADER_MAJOR
772.1457 -+
772.1458 - if test "x$SNA" != "xno"; then
772.1459 - 	AC_DEFINE(USE_SNA, 1, [Enable SNA support])
772.1460 - 	AC_CHECK_HEADERS([sys/sysinfo.h], AC_CHECK_MEMBERS([struct sysinfo.totalram], [], [], [[#include <sys/sysinfo.h>]]))
772.1461 - fi
772.1462 - 
772.1463 - uxa_requires_libdrm=2.4.52
772.1464 -+uxa_requires_pixman=0.24.0
772.1465 -+
772.1466 - AC_ARG_ENABLE(uxa,
772.1467 - 	      AS_HELP_STRING([--enable-uxa],
772.1468 - 			     [Enable Unified Acceleration Architecture (UXA) [default=auto]]),
772.1469 - 	      [UXA="$enableval"],
772.1470 - 	      [UXA=auto])
772.1471 - if test "x$UXA" = "xauto"; then
772.1472 --	if ! pkg-config --exists "libdrm_intel >= $uxa_requires_libdrm"; then
772.1473 --		UXA=no
772.1474 --	fi
772.1475 --	if ! pkg-config --exists 'pixman-1 >= 0.24.0'; then
772.1476 --		UXA=no
772.1477 --	fi
772.1478 -+	PKG_CHECK_EXISTS([libdrm_intel >= $uxa_requires_libdrm pixman-1 >= $uxa_requires_pixman], [], [UXA=no])
772.1479 - fi
772.1480 - if test "x$UXA" != "xno"; then
772.1481 - 	AC_DEFINE(USE_UXA, 1, [Enable UXA support])
772.1482 -@@ -424,8 +445,10 @@ if test "x$UXA" != "xno"; then
772.1483 - 	UXA=yes
772.1484 - fi
772.1485 - 
772.1486 --PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
772.1487 -+PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto damageproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
772.1488 - ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server`
772.1489 -+XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server`
772.1490 -+PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1`
772.1491 - 
772.1492 - if test "x$ONLY_UMS" = "xyes"; then
772.1493 - 	UMS="yes"
772.1494 -@@ -519,7 +542,12 @@ AC_MSG_RESULT([$have_dri1])
772.1495 - AM_CONDITIONAL(DRI1, test "x$have_dri1" != "xno")
772.1496 - if test "x$have_dri1" != "xno"; then
772.1497 -         AC_DEFINE(HAVE_DRI1,1,[Enable DRI1 driver support])
772.1498 --	dri_msg="$dri_msg DRI1"
772.1499 -+	str="DRI1"
772.1500 -+	if test "x$DRI_DEFAULT" = "x1"; then
772.1501 -+		AC_DEFINE(DEFAULT_DRI_LEVEL,1,[Default DRI level])
772.1502 -+		str="*$str"
772.1503 -+	fi
772.1504 -+	dri_msg="$dri_msg $str"
772.1505 - else
772.1506 -         DRI1_CFLAGS=""
772.1507 -         DRI1_LIBS=""
772.1508 -@@ -576,7 +604,12 @@ AM_CONDITIONAL(DRI2, test "x$have_dri2" != "xno")
772.1509 - AC_MSG_RESULT([$have_dri2])
772.1510 - if test "x$have_dri2" != "xno"; then
772.1511 -         AC_DEFINE(HAVE_DRI2,1,[Enable DRI2 driver support])
772.1512 --	dri_msg="$dri_msg DRI2"
772.1513 -+	str="DRI2"
772.1514 -+	if test "x$DRI_DEFAULT" = "x2"; then
772.1515 -+		AC_DEFINE(DEFAULT_DRI_LEVEL,2,[Default DRI level])
772.1516 -+		str="*$str"
772.1517 -+	fi
772.1518 -+	dri_msg="$dri_msg $str"
772.1519 - else
772.1520 - 	if test "x$DRI" = "xyes" -a "x$DRI2" != "xno" -a "x$KMS" = "xyes"; then
772.1521 - 		AC_MSG_ERROR([DRI2 requested but prerequisites not found])
772.1522 -@@ -591,13 +624,21 @@ AM_CONDITIONAL(DRI3, test "x$have_dri3" != "xno")
772.1523 - AC_MSG_RESULT([$have_dri3])
772.1524 - if test "x$have_dri3" != "xno"; then
772.1525 -         AC_DEFINE(HAVE_DRI3,1,[Enable DRI3 driver support])
772.1526 --	dri_msg="$dri_msg DRI3"
772.1527 -+	str="DRI3"
772.1528 -+	if test "x$DRI_DEFAULT" = "x3"; then
772.1529 -+		AC_DEFINE(DEFAULT_DRI_LEVEL,3,[Default DRI level])
772.1530 -+		str="*$str"
772.1531 -+	fi
772.1532 -+	dri_msg="$dri_msg $str"
772.1533 - else
772.1534 - 	if test "x$DRI" = "xyes" -a "x$DRI3" != "xno" -a "x$KMS" = "xyes"; then
772.1535 - 		AC_MSG_ERROR([DRI3 requested but prerequisites not found])
772.1536 - 	fi
772.1537 - fi
772.1538 - 
772.1539 -+AC_MSG_CHECKING([default DRI support])
772.1540 -+AC_MSG_RESULT([$DEFAULT_DRI_DEFAULT])
772.1541 -+
772.1542 - AC_CHECK_HEADERS([X11/extensions/dpmsconst.h])
772.1543 - 
772.1544 - PRESENT="no"
772.1545 -@@ -711,27 +752,6 @@ if test "x$TEARFREE" = "xyes"; then
772.1546 - 	xp_msg="$xp_msg TearFree"
772.1547 - fi
772.1548 - 
772.1549 --AC_ARG_ENABLE(rendernode,
772.1550 --	      AS_HELP_STRING([--enable-rendernode],
772.1551 --			     [Enable use of render nodes (experimental) [default=no]]),
772.1552 --	      [RENDERNODE="$enableval"],
772.1553 --	      [RENDERNODE="no"])
772.1554 --AM_CONDITIONAL(USE_RENDERNODE, test "x$RENDERNODE" = "xyes")
772.1555 --if test "x$RENDERNODE" = "xyes"; then
772.1556 --	AC_DEFINE(USE_RENDERNODE,1,[Assume "rendernode" support])
772.1557 --	xp_msg="$xp_msg rendernode"
772.1558 --fi
772.1559 --
772.1560 --AC_ARG_ENABLE(wc-mmap,
772.1561 --	      AS_HELP_STRING([--enable-wc-mmap],
772.1562 --			     [Enable use of WriteCombining mmaps [default=no]]),
772.1563 --	      [WC_MMAP="$enableval"],
772.1564 --	      [WC_MMAP="no"])
772.1565 --if test "x$WC_MMAP" = "xyes"; then
772.1566 --	AC_DEFINE(USE_WC_MMAP,1,[Enable use of WriteCombining mmaps])
772.1567 --	xp_msg="$xp_msg mmap(wc)"
772.1568 --fi
772.1569 --
772.1570 - AC_ARG_ENABLE(create2,
772.1571 - 	      AS_HELP_STRING([--enable-create2],
772.1572 - 			     [Enable use of create2 ioctl (experimental) [default=no]]),
772.1573 -@@ -848,6 +868,7 @@ AC_CONFIG_FILES([
772.1574 -                 xvmc/shader/mc/Makefile
772.1575 -                 xvmc/shader/vld/Makefile
772.1576 - 		test/Makefile
772.1577 -+		benchmarks/Makefile
772.1578 - 		tools/Makefile
772.1579 - 		tools/org.x.xf86-video-intel.backlight-helper.policy
772.1580 - ])
772.1581 -@@ -855,7 +876,7 @@ AC_OUTPUT
772.1582 - 
772.1583 - echo ""
772.1584 - echo ""
772.1585 --test -e `pwd $0`/README && cat `pwd $0`/README
772.1586 -+cat $srcdir/README
772.1587 - 
772.1588 - accel_msg=""
772.1589 - if test "x$SNA" != "xno"; then
772.1590 -@@ -895,13 +916,15 @@ fi
772.1591 - 
772.1592 - echo ""
772.1593 - echo "AC_PACKAGE_STRING will be compiled with:"
772.1594 --echo "  Xorg Video ABI version: $ABI_VERSION"
772.1595 -+echo "  Xorg Video ABI version: $ABI_VERSION (xorg-server-$XSERVER_VERSION)"
772.1596 -+echo "  pixman version: pixman-1-$PIXMAN_VERSION"
772.1597 - echo "  Acceleration backends:$accel_msg"
772.1598 - echo "  Additional debugging support?$debug_msg"
772.1599 - echo "  Support for Kernel Mode Setting? $KMS"
772.1600 - echo "  Support for legacy User Mode Setting (for i810)? $UMS"
772.1601 - echo "  Support for Direct Rendering Infrastructure:$dri_msg"
772.1602 - echo "  Support for Xv motion compensation (XvMC and libXvMC):$xvmc_msg"
772.1603 -+echo "  Support for display hotplug notifications (udev):$udev_msg"
772.1604 - echo "  Build additional tools and utilities?$tools_msg"
772.1605 - if test -n "$xp_msg"; then
772.1606 - echo "  Experimental support:$xp_msg"
772.1607 -diff --git a/libobj/alloca.c b/libobj/alloca.c
772.1608 -new file mode 100644
772.1609 -index 00000000..883e1e9f
772.1610 ---- /dev/null
772.1611 -+++ b/libobj/alloca.c
772.1612 -@@ -0,0 +1,4 @@
772.1613 -+void *alloca(size_t sz)
772.1614 -+{
772.1615 -+	return NULL;
772.1616 -+}
772.1617 -diff --git a/man/intel.man b/man/intel.man
772.1618 -index 17515206..be398fbe 100644
772.1619 ---- a/man/intel.man
772.1620 -+++ b/man/intel.man
772.1621 -@@ -27,9 +27,9 @@ supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM,
772.1622 - 865G, 915G, 915GM, 945G, 945GM, 965G, 965Q, 946GZ, 965GM, 945GME,
772.1623 - G33, Q33, Q35, G35, GM45, G45, Q45, G43, G41 chipsets, Pineview-M in
772.1624 - Atom N400 series, Pineview-D in Atom D400/D500 series,
772.1625 --Intel(R) HD Graphics: 2000-6000,
772.1626 --Intel(R) Iris(TM) Graphics: 5100/6100, and
772.1627 --Intel(R) Iris(TM) Pro Graphics: 5200/6200/P6300.
772.1628 -+Intel(R) HD Graphics,
772.1629 -+Intel(R) Iris(TM) Graphics,
772.1630 -+Intel(R) Iris(TM) Pro Graphics.
772.1631 - 
772.1632 - .SH CONFIGURATION DETAILS
772.1633 - Please refer to __xconfigfile__(__filemansuffix__) for general configuration
772.1634 -@@ -112,8 +112,8 @@ The default is 8192 if AGP allocable memory is < 128 MB, 16384 if < 192 MB,
772.1635 - 24576 if higher. DRI require at least a value of 16384. Higher values may give
772.1636 - better 3D performance, at expense of available system memory.
772.1637 - .TP
772.1638 --.BI "Option \*qNoAccel\*q \*q" boolean \*q
772.1639 --Disable or enable acceleration.
772.1640 -+.BI "Option \*qAccel\*q \*q" boolean \*q
772.1641 -+Enable or disable acceleration.
772.1642 - .IP
772.1643 - Default: acceleration is enabled.
772.1644 - 
772.1645 -@@ -122,8 +122,8 @@ The following driver
772.1646 - .B Options
772.1647 - are supported for the 830M and later chipsets:
772.1648 - .TP
772.1649 --.BI "Option \*qNoAccel\*q \*q" boolean \*q
772.1650 --Disable or enable acceleration.
772.1651 -+.BI "Option \*qAccel\*q \*q" boolean \*q
772.1652 -+Enable or disable acceleration.
772.1653 - .IP
772.1654 - Default: acceleration is enabled.
772.1655 - .TP
772.1656 -@@ -201,6 +201,16 @@ that choice by specifying the entry under /sys/class/backlight to use.
772.1657 - .IP
772.1658 - Default: Automatic selection.
772.1659 - .TP
772.1660 -+.BI "Option \*qCustomEDID\*q \*q" string \*q
772.1661 -+Override the probed EDID on particular outputs. Sometimes the manufacturer
772.1662 -+supplied EDID is corrupt or lacking a few usable modes and supplying a
772.1663 -+corrected EDID may be easier than specifying every modeline. This option
772.1664 -+allows to pass the path to load an EDID from per output. The format is a
772.1665 -+comma separated string of output:path pairs, e.g.
772.1666 -+DP1:/path/to/dp1.edid,DP2:/path/to/dp2.edid
772.1667 -+.IP
772.1668 -+Default: No override, use manufacturer supplied EDIDs.
772.1669 -+.TP
772.1670 - .BI "Option \*qFallbackDebug\*q \*q" boolean \*q
772.1671 - Enable printing of debugging information on acceleration fallbacks to the
772.1672 - server log.
772.1673 -@@ -225,6 +235,15 @@ i.e. perform synchronous rendering.
772.1674 - .IP
772.1675 - Default: Disabled
772.1676 - .TP
772.1677 -+.BI "Option \*qHWRotation\*q \*q" boolean \*q
772.1678 -+Override the use of native hardware rotation and force the use of software,
772.1679 -+but GPU accelerated where possible, rotation. On some platforms the hardware
772.1680 -+can scanout directly into a rotated output bypassing the intermediate rendering
772.1681 -+and extra allocations required for software implemented rotation (i.e. native
772.1682 -+rotation uses less resources, is quicker and uses less power). This allows you
772.1683 -+to disable the native rotation in case of errors.
772.1684 -+.IP
772.1685 -+Default: Enabled (use hardware rotation)
772.1686 - .TP
772.1687 - .BI "Option \*qVSync\*q \*q" boolean \*q
772.1688 - This option controls the use of commands to synchronise rendering with the
772.1689 -@@ -324,13 +343,29 @@ Default: 0
772.1690 - .BI "Option \*qZaphodHeads\*q \*q" string \*q
772.1691 - .IP
772.1692 - Specify the randr output(s) to use with zaphod mode for a particular driver
772.1693 --instance.  If you this option you must use it with all instances of the
772.1694 --driver
772.1695 -+instance.  If you set this option you must use it with all instances of the
772.1696 -+driver. By default, each head is assigned only one CRTC (which limits
772.1697 -+using multiple outputs with that head to cloned mode). CRTC can be manually
772.1698 -+assigned to individual heads by preceding the output names with a comma
772.1699 -+delimited list of pipe numbers followed by a colon. Note that different pipes
772.1700 -+may be limited in their functionality and some outputs may only work with
772.1701 -+different pipes.
772.1702 - .br
772.1703 - For example:
772.1704 -+
772.1705 -+.RS
772.1706 - .B
772.1707 - Option \*qZaphodHeads\*q \*qLVDS1,VGA1\*q
772.1708 --will assign xrandr outputs LVDS1 and VGA0 to this instance of the driver.
772.1709 -+
772.1710 -+will assign xrandr outputs LVDS1 and VGA1 to this instance of the driver.
772.1711 -+.RE
772.1712 -+
772.1713 -+.RS
772.1714 -+.B
772.1715 -+Option \*qZaphodHeads\*q \*q0,2:HDMI1,DP2\*q
772.1716 -+
772.1717 -+will assign xrandr outputs HDMI1 and DP2 and CRTCs 0 and 2 to this instance of the driver.
772.1718 -+.RE
772.1719 - 
772.1720 - .SH OUTPUT CONFIGURATION
772.1721 - On 830M and better chipsets, the driver supports runtime configuration of
772.1722 -@@ -431,11 +466,11 @@ First DVI SDVO output
772.1723 - Second DVI SDVO output
772.1724 - 
772.1725 - .SS "TMDS-1", "TMDS-2", "HDMI-1", "HDMI-2"
772.1726 --DVI/HDMI outputs. Avaliable common properties include:
772.1727 -+DVI/HDMI outputs. Available common properties include:
772.1728 - .TP
772.1729 - \fBBROADCAST_RGB\fP - method used to set RGB color range
772.1730 - Adjusting this property allows you to set RGB color range on each
772.1731 --channel in order to match HDTV requirment(default 0 for full
772.1732 -+channel in order to match HDTV requirement(default 0 for full
772.1733 - range). Setting 1 means RGB color range is 16-235, 0 means RGB color
772.1734 - range is 0-255 on each channel.  (Full range is 0-255, not 16-235)
772.1735 - 
772.1736 -diff --git a/src/backlight.c b/src/backlight.c
772.1737 -index 9f239867..fcbb279f 100644
772.1738 ---- a/src/backlight.c
772.1739 -+++ b/src/backlight.c
772.1740 -@@ -34,6 +34,12 @@
772.1741 - #include <sys/stat.h>
772.1742 - #include <sys/ioctl.h>
772.1743 - 
772.1744 -+#if MAJOR_IN_MKDEV
772.1745 -+#include <sys/mkdev.h>
772.1746 -+#elif MAJOR_IN_SYSMACROS
772.1747 -+#include <sys/sysmacros.h>
772.1748 -+#endif
772.1749 -+
772.1750 - #include <stdio.h>
772.1751 - #include <stdlib.h>
772.1752 - #include <string.h>
772.1753 -@@ -42,6 +48,7 @@
772.1754 - #include <fcntl.h>
772.1755 - #include <unistd.h>
772.1756 - #include <dirent.h>
772.1757 -+#include <errno.h>
772.1758 - 
772.1759 - #include <xorg-server.h>
772.1760 - #include <xf86.h>
772.1761 -@@ -84,7 +91,7 @@ void backlight_init(struct backlight *b)
772.1762 - 	b->has_power = 0;
772.1763 - }
772.1764 - 
772.1765 --#ifdef __OpenBSD__
772.1766 -+#ifdef HAVE_DEV_WSCONS_WSCONSIO_H
772.1767 - 
772.1768 - #include <dev/wscons/wsconsio.h>
772.1769 - #include <xf86Priv.h>
772.1770 -@@ -122,6 +129,11 @@ int backlight_get(struct backlight *b)
772.1771 - 	return param.curval;
772.1772 - }
772.1773 - 
772.1774 -+char *backlight_find_for_device(struct pci_device *pci)
772.1775 -+{
772.1776 -+	return NULL;
772.1777 -+}
772.1778 -+
772.1779 - int backlight_open(struct backlight *b, char *iface)
772.1780 - {
772.1781 - 	struct wsdisplay_param param;
772.1782 -@@ -146,12 +158,9 @@ int backlight_open(struct backlight *b, char *iface)
772.1783 - 	return param.curval;
772.1784 - }
772.1785 - 
772.1786 --enum backlight_type backlight_exists(const char *iface)
772.1787 -+int backlight_exists(const char *iface)
772.1788 - {
772.1789 --	if (iface != NULL)
772.1790 --		return BL_NONE;
772.1791 --
772.1792 --	return BL_PLATFORM;
772.1793 -+	return iface == NULL;
772.1794 - }
772.1795 - 
772.1796 - int backlight_on(struct backlight *b)
772.1797 -@@ -163,6 +172,7 @@ int backlight_off(struct backlight *b)
772.1798 - {
772.1799 - 	return 0;
772.1800 - }
772.1801 -+
772.1802 - #else
772.1803 - 
772.1804 - static int
772.1805 -@@ -213,6 +223,24 @@ __backlight_read(const char *iface, const char *file)
772.1806 - }
772.1807 - 
772.1808 - static int
772.1809 -+writen(int fd, const char *value, int len)
772.1810 -+{
772.1811 -+	int ret;
772.1812 -+
772.1813 -+	do {
772.1814 -+		ret = write(fd, value, len);
772.1815 -+		if (ret < 0) {
772.1816 -+			if (errno == EAGAIN || errno == EINTR)
772.1817 -+				continue;
772.1818 -+
772.1819 -+			return ret;
772.1820 -+		}
772.1821 -+	} while (value += ret, len -= ret);
772.1822 -+
772.1823 -+	return 0;
772.1824 -+}
772.1825 -+
772.1826 -+static int
772.1827 - __backlight_write(const char *iface, const char *file, const char *value)
772.1828 - {
772.1829 - 	int fd, ret;
772.1830 -@@ -221,7 +249,7 @@ __backlight_write(const char *iface, const char *file, const char *value)
772.1831 - 	if (fd < 0)
772.1832 - 		return -1;
772.1833 - 
772.1834 --	ret = write(fd, value, strlen(value)+1);
772.1835 -+	ret = writen(fd, value, strlen(value)+1);
772.1836 - 	close(fd);
772.1837 - 
772.1838 - 	return ret;
772.1839 -@@ -244,10 +272,10 @@ static const char *known_interfaces[] = {
772.1840 - 	"intel_backlight",
772.1841 - };
772.1842 - 
772.1843 --static enum backlight_type __backlight_type(const char *iface)
772.1844 -+static int __backlight_type(const char *iface)
772.1845 - {
772.1846 - 	char buf[1024];
772.1847 --	int fd, v;
772.1848 -+	int fd, v, i;
772.1849 - 
772.1850 - 	v = -1;
772.1851 - 	fd = __backlight_open(iface, "type", O_RDONLY);
772.1852 -@@ -261,39 +289,41 @@ static enum backlight_type __backlight_type(const char *iface)
772.1853 - 		buf[v] = '\0';
772.1854 - 
772.1855 - 		if (strcmp(buf, "raw") == 0)
772.1856 --			v = BL_RAW;
772.1857 -+			v = BL_RAW << 8;
772.1858 - 		else if (strcmp(buf, "platform") == 0)
772.1859 --			v = BL_PLATFORM;
772.1860 -+			v = BL_PLATFORM << 8;
772.1861 - 		else if (strcmp(buf, "firmware") == 0)
772.1862 --			v = BL_FIRMWARE;
772.1863 -+			v = BL_FIRMWARE << 8;
772.1864 - 		else
772.1865 --			v = BL_NAMED;
772.1866 -+			v = BL_NAMED << 8;
772.1867 - 	} else
772.1868 --		v = BL_NAMED;
772.1869 -+		v = BL_NAMED << 8;
772.1870 - 
772.1871 --	if (v == BL_NAMED) {
772.1872 --		int i;
772.1873 --		for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
772.1874 --			if (strcmp(iface, known_interfaces[i]) == 0)
772.1875 --				break;
772.1876 --		}
772.1877 --		v += i;
772.1878 -+	for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
772.1879 -+		if (strcmp(iface, known_interfaces[i]) == 0)
772.1880 -+			break;
772.1881 - 	}
772.1882 -+	v += i;
772.1883 - 
772.1884 - 	return v;
772.1885 - }
772.1886 - 
772.1887 --enum backlight_type backlight_exists(const char *iface)
772.1888 -+static int __backlight_exists(const char *iface)
772.1889 - {
772.1890 - 	if (__backlight_read(iface, "brightness") < 0)
772.1891 --		return BL_NONE;
772.1892 -+		return -1;
772.1893 - 
772.1894 - 	if (__backlight_read(iface, "max_brightness") <= 0)
772.1895 --		return BL_NONE;
772.1896 -+		return -1;
772.1897 - 
772.1898 - 	return __backlight_type(iface);
772.1899 - }
772.1900 - 
772.1901 -+int backlight_exists(const char *iface)
772.1902 -+{
772.1903 -+	return __backlight_exists(iface) != -1;
772.1904 -+}
772.1905 -+
772.1906 - static int __backlight_init(struct backlight *b, char *iface, int fd)
772.1907 - {
772.1908 - 	b->fd = fd_move_cloexec(fd_set_nonblock(fd));
772.1909 -@@ -399,7 +429,50 @@ __backlight_find(void)
772.1910 - 			continue;
772.1911 - 
772.1912 - 		/* Fallback to priority list of known iface for old kernels */
772.1913 --		v = backlight_exists(de->d_name);
772.1914 -+		v = __backlight_exists(de->d_name);
772.1915 -+		if (v < 0)
772.1916 -+			continue;
772.1917 -+
772.1918 -+		if (v < best_type) {
772.1919 -+			char *copy = strdup(de->d_name);
772.1920 -+			if (copy) {
772.1921 -+				free(best_iface);
772.1922 -+				best_iface = copy;
772.1923 -+				best_type = v;
772.1924 -+			}
772.1925 -+		}
772.1926 -+	}
772.1927 -+	closedir(dir);
772.1928 -+
772.1929 -+	return best_iface;
772.1930 -+}
772.1931 -+
772.1932 -+char *backlight_find_for_device(struct pci_device *pci)
772.1933 -+{
772.1934 -+	char path[200];
772.1935 -+	unsigned best_type = INT_MAX;
772.1936 -+	char *best_iface = NULL;
772.1937 -+	DIR *dir;
772.1938 -+	struct dirent *de;
772.1939 -+
772.1940 -+	snprintf(path, sizeof(path),
772.1941 -+		 "/sys/bus/pci/devices/%04x:%02x:%02x.%d/backlight",
772.1942 -+		 pci->domain, pci->bus, pci->dev, pci->func);
772.1943 -+
772.1944 -+	dir = opendir(path);
772.1945 -+	if (dir == NULL)
772.1946 -+		return NULL;
772.1947 -+
772.1948 -+	while ((de = readdir(dir))) {
772.1949 -+		int v;
772.1950 -+
772.1951 -+		if (*de->d_name == '.')
772.1952 -+			continue;
772.1953 -+
772.1954 -+		v = __backlight_exists(de->d_name);
772.1955 -+		if (v < 0)
772.1956 -+			continue;
772.1957 -+
772.1958 - 		if (v < best_type) {
772.1959 - 			char *copy = strdup(de->d_name);
772.1960 - 			if (copy) {
772.1961 -@@ -416,14 +489,17 @@ __backlight_find(void)
772.1962 - 
772.1963 - int backlight_open(struct backlight *b, char *iface)
772.1964 - {
772.1965 --	int level;
772.1966 -+	int level, type;
772.1967 - 
772.1968 - 	if (iface == NULL)
772.1969 - 		iface = __backlight_find();
772.1970 - 	if (iface == NULL)
772.1971 - 		goto err;
772.1972 - 
772.1973 --	b->type = __backlight_type(iface);
772.1974 -+	type = __backlight_type(iface);
772.1975 -+	if (type < 0)
772.1976 -+		goto err;
772.1977 -+	b->type = type >> 8;
772.1978 - 
772.1979 - 	b->max = __backlight_read(iface, "max_brightness");
772.1980 - 	if (b->max <= 0)
772.1981 -@@ -447,7 +523,7 @@ err:
772.1982 - int backlight_set(struct backlight *b, int level)
772.1983 - {
772.1984 - 	char val[BACKLIGHT_VALUE_LEN];
772.1985 --	int len, ret = 0;
772.1986 -+	int len;
772.1987 - 
772.1988 - 	if (b->iface == NULL)
772.1989 - 		return 0;
772.1990 -@@ -456,10 +532,7 @@ int backlight_set(struct backlight *b, int level)
772.1991 - 		level = b->max;
772.1992 - 
772.1993 - 	len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level);
772.1994 --	if (write(b->fd, val, len) != len)
772.1995 --		ret = -1;
772.1996 --
772.1997 --	return ret;
772.1998 -+	return writen(b->fd, val, len);
772.1999 - }
772.2000 - 
772.2001 - int backlight_get(struct backlight *b)
772.2002 -@@ -517,43 +590,6 @@ void backlight_disable(struct backlight *b)
772.2003 - void backlight_close(struct backlight *b)
772.2004 - {
772.2005 - 	backlight_disable(b);
772.2006 --	if (b->pid)
772.2007 -+	if (b->pid > 0)
772.2008 - 		waitpid(b->pid, NULL, 0);
772.2009 - }
772.2010 --
772.2011 --char *backlight_find_for_device(struct pci_device *pci)
772.2012 --{
772.2013 --	char path[200];
772.2014 --	unsigned best_type = INT_MAX;
772.2015 --	char *best_iface = NULL;
772.2016 --	DIR *dir;
772.2017 --	struct dirent *de;
772.2018 --
772.2019 --	snprintf(path, sizeof(path),
772.2020 --		 "/sys/bus/pci/devices/%04x:%02x:%02x.%d/backlight",
772.2021 --		 pci->domain, pci->bus, pci->dev, pci->func);
772.2022 --
772.2023 --	dir = opendir(path);
772.2024 --	if (dir == NULL)
772.2025 --		return NULL;
772.2026 --
772.2027 --	while ((de = readdir(dir))) {
772.2028 --		int v;
772.2029 --
772.2030 --		if (*de->d_name == '.')
772.2031 --			continue;
772.2032 --
772.2033 --		v = backlight_exists(de->d_name);
772.2034 --		if (v < best_type) {
772.2035 --			char *copy = strdup(de->d_name);
772.2036 --			if (copy) {
772.2037 --				free(best_iface);
772.2038 --				best_iface = copy;
772.2039 --				best_type = v;
772.2040 --			}
772.2041 --		}
772.2042 --	}
772.2043 --	closedir(dir);
772.2044 --
772.2045 --	return best_iface;
772.2046 --}
772.2047 -diff --git a/src/backlight.h b/src/backlight.h
772.2048 -index bb0e28bc..ba17755b 100644
772.2049 ---- a/src/backlight.h
772.2050 -+++ b/src/backlight.h
772.2051 -@@ -43,7 +43,7 @@ struct backlight {
772.2052 - 	int pid, fd;
772.2053 - };
772.2054 - 
772.2055 --enum backlight_type backlight_exists(const char *iface);
772.2056 -+int backlight_exists(const char *iface);
772.2057 - 
772.2058 - void backlight_init(struct backlight *backlight);
772.2059 - int backlight_open(struct backlight *backlight, char *iface);
772.2060 -diff --git a/src/compat-api.h b/src/compat-api.h
772.2061 -index d09e1fb3..05797a08 100644
772.2062 ---- a/src/compat-api.h
772.2063 -+++ b/src/compat-api.h
772.2064 -@@ -30,6 +30,7 @@
772.2065 - 
772.2066 - #include <xorg-server.h>
772.2067 - #include <xorgVersion.h>
772.2068 -+#include <xf86Module.h>
772.2069 - 
772.2070 - #include <picturestr.h>
772.2071 - #ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR
772.2072 -@@ -39,7 +40,17 @@
772.2073 - 
772.2074 - #ifndef XF86_HAS_SCRN_CONV
772.2075 - #define xf86ScreenToScrn(s) xf86Screens[(s)->myNum]
772.2076 -+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,1,0,0,0)
772.2077 - #define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex]
772.2078 -+#else
772.2079 -+#define xf86ScrnToScreen(s) ((s)->pScreen)
772.2080 -+#endif
772.2081 -+#else
772.2082 -+#define xf86ScrnToScreen(s) ((s)->pScreen)
772.2083 -+#endif
772.2084 -+
772.2085 -+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22
772.2086 -+#define HAVE_NOTIFY_FD 1
772.2087 - #endif
772.2088 - 
772.2089 - #ifndef XF86_SCRN_INTERFACE
772.2090 -@@ -131,6 +142,17 @@ region_rects(const RegionRec *r)
772.2091 - 	return r->data ? (const BoxRec *)(r->data + 1) :  &r->extents;
772.2092 - }
772.2093 - 
772.2094 -+inline static void
772.2095 -+region_get_boxes(const RegionRec *r, const BoxRec **s, const BoxRec **e)
772.2096 -+{
772.2097 -+	int n;
772.2098 -+	if (r->data)
772.2099 -+		*s = region_boxptr(r), n = r->data->numRects;
772.2100 -+	else
772.2101 -+		*s = &r->extents, n = 1;
772.2102 -+	*e = *s + n;
772.2103 -+}
772.2104 -+
772.2105 - #ifndef INCLUDE_LEGACY_REGION_DEFINES
772.2106 - #define RegionCreate(r, s) REGION_CREATE(NULL, r, s)
772.2107 - #define RegionBreak(r) REGION_BREAK(NULL, r)
772.2108 -@@ -223,4 +245,19 @@ static inline void FreePixmap(PixmapPtr pixmap)
772.2109 - 			  dstx, dsty)
772.2110 - #endif
772.2111 - 
772.2112 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
772.2113 -+#define isGPU(S) (S)->is_gpu
772.2114 -+#else
772.2115 -+#define isGPU(S) 0
772.2116 -+#endif
772.2117 -+
772.2118 -+#if HAS_DIRTYTRACKING_ROTATION
772.2119 -+#define PixmapSyncDirtyHelper(d, dd) PixmapSyncDirtyHelper(d)
772.2120 -+#endif
772.2121 -+
772.2122 -+#if !HAVE_NOTIFY_FD
772.2123 -+#define SetNotifyFd(fd, cb, mode, data) AddGeneralSocket(fd);
772.2124 -+#define RemoveNotifyFd(fd) RemoveGeneralSocket(fd)
772.2125 -+#endif
772.2126 -+
772.2127 - #endif
772.2128 -diff --git a/src/i915_pciids.h b/src/i915_pciids.h
772.2129 -index 180ad0e6..466c7159 100644
772.2130 ---- a/src/i915_pciids.h
772.2131 -+++ b/src/i915_pciids.h
772.2132 -@@ -134,7 +134,7 @@
772.2133 - #define INTEL_IVB_Q_IDS(info) \
772.2134 - 	INTEL_QUANTA_VGA_DEVICE(info) /* Quanta transcode */
772.2135 - 
772.2136 --#define INTEL_HSW_D_IDS(info) \
772.2137 -+#define INTEL_HSW_IDS(info) \
772.2138 - 	INTEL_VGA_DEVICE(0x0402, info), /* GT1 desktop */ \
772.2139 - 	INTEL_VGA_DEVICE(0x0412, info), /* GT2 desktop */ \
772.2140 - 	INTEL_VGA_DEVICE(0x0422, info), /* GT3 desktop */ \
772.2141 -@@ -179,9 +179,7 @@
772.2142 - 	INTEL_VGA_DEVICE(0x0D2B, info), /* CRW GT3 reserved */ \
772.2143 - 	INTEL_VGA_DEVICE(0x0D0E, info), /* CRW GT1 reserved */ \
772.2144 - 	INTEL_VGA_DEVICE(0x0D1E, info), /* CRW GT2 reserved */ \
772.2145 --	INTEL_VGA_DEVICE(0x0D2E, info)  /* CRW GT3 reserved */ \
772.2146 --
772.2147 --#define INTEL_HSW_M_IDS(info) \
772.2148 -+	INTEL_VGA_DEVICE(0x0D2E, info),  /* CRW GT3 reserved */ \
772.2149 - 	INTEL_VGA_DEVICE(0x0406, info), /* GT1 mobile */ \
772.2150 - 	INTEL_VGA_DEVICE(0x0416, info), /* GT2 mobile */ \
772.2151 - 	INTEL_VGA_DEVICE(0x0426, info), /* GT2 mobile */ \
772.2152 -@@ -198,60 +196,48 @@
772.2153 - 	INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \
772.2154 - 	INTEL_VGA_DEVICE(0x0D26, info)  /* CRW GT3 mobile */
772.2155 - 
772.2156 --#define INTEL_VLV_M_IDS(info) \
772.2157 -+#define INTEL_VLV_IDS(info) \
772.2158 - 	INTEL_VGA_DEVICE(0x0f30, info), \
772.2159 - 	INTEL_VGA_DEVICE(0x0f31, info), \
772.2160 - 	INTEL_VGA_DEVICE(0x0f32, info), \
772.2161 - 	INTEL_VGA_DEVICE(0x0f33, info), \
772.2162 --	INTEL_VGA_DEVICE(0x0157, info)
772.2163 --
772.2164 --#define INTEL_VLV_D_IDS(info) \
772.2165 -+	INTEL_VGA_DEVICE(0x0157, info), \
772.2166 - 	INTEL_VGA_DEVICE(0x0155, info)
772.2167 - 
772.2168 --#define _INTEL_BDW_M(gt, id, info) \
772.2169 --	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info)
772.2170 --#define _INTEL_BDW_D(gt, id, info) \
772.2171 --	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info)
772.2172 --
772.2173 --#define _INTEL_BDW_M_IDS(gt, info) \
772.2174 --	_INTEL_BDW_M(gt, 0x1602, info), /* ULT */ \
772.2175 --	_INTEL_BDW_M(gt, 0x1606, info), /* ULT */ \
772.2176 --	_INTEL_BDW_M(gt, 0x160B, info), /* Iris */ \
772.2177 --	_INTEL_BDW_M(gt, 0x160E, info) /* ULX */
772.2178 --
772.2179 --#define _INTEL_BDW_D_IDS(gt, info) \
772.2180 --	_INTEL_BDW_D(gt, 0x160A, info), /* Server */ \
772.2181 --	_INTEL_BDW_D(gt, 0x160D, info) /* Workstation */
772.2182 --
772.2183 --#define INTEL_BDW_GT12M_IDS(info) \
772.2184 --	_INTEL_BDW_M_IDS(1, info), \
772.2185 --	_INTEL_BDW_M_IDS(2, info)
772.2186 --
772.2187 --#define INTEL_BDW_GT12D_IDS(info) \
772.2188 --	_INTEL_BDW_D_IDS(1, info), \
772.2189 --	_INTEL_BDW_D_IDS(2, info)
772.2190 --
772.2191 --#define INTEL_BDW_GT3M_IDS(info) \
772.2192 --	_INTEL_BDW_M_IDS(3, info)
772.2193 --
772.2194 --#define INTEL_BDW_GT3D_IDS(info) \
772.2195 --	_INTEL_BDW_D_IDS(3, info)
772.2196 --
772.2197 --#define INTEL_BDW_RSVDM_IDS(info) \
772.2198 --	_INTEL_BDW_M_IDS(4, info)
772.2199 --
772.2200 --#define INTEL_BDW_RSVDD_IDS(info) \
772.2201 --	_INTEL_BDW_D_IDS(4, info)
772.2202 --
772.2203 --#define INTEL_BDW_M_IDS(info) \
772.2204 --	INTEL_BDW_GT12M_IDS(info), \
772.2205 --	INTEL_BDW_GT3M_IDS(info), \
772.2206 --	INTEL_BDW_RSVDM_IDS(info)
772.2207 --
772.2208 --#define INTEL_BDW_D_IDS(info) \
772.2209 --	INTEL_BDW_GT12D_IDS(info), \
772.2210 --	INTEL_BDW_GT3D_IDS(info), \
772.2211 --	INTEL_BDW_RSVDD_IDS(info)
772.2212 -+#define INTEL_BDW_GT12_IDS(info)  \
772.2213 -+	INTEL_VGA_DEVICE(0x1602, info), /* GT1 ULT */ \
772.2214 -+	INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \
772.2215 -+	INTEL_VGA_DEVICE(0x160B, info), /* GT1 Iris */ \
772.2216 -+	INTEL_VGA_DEVICE(0x160E, info), /* GT1 ULX */ \
772.2217 -+	INTEL_VGA_DEVICE(0x1612, info), /* GT2 Halo */ \
772.2218 -+	INTEL_VGA_DEVICE(0x1616, info), /* GT2 ULT */ \
772.2219 -+	INTEL_VGA_DEVICE(0x161B, info), /* GT2 ULT */ \
772.2220 -+	INTEL_VGA_DEVICE(0x161E, info),  /* GT2 ULX */ \
772.2221 -+	INTEL_VGA_DEVICE(0x160A, info), /* GT1 Server */ \
772.2222 -+	INTEL_VGA_DEVICE(0x160D, info), /* GT1 Workstation */ \
772.2223 -+	INTEL_VGA_DEVICE(0x161A, info), /* GT2 Server */ \
772.2224 -+	INTEL_VGA_DEVICE(0x161D, info)  /* GT2 Workstation */
772.2225 -+
772.2226 -+#define INTEL_BDW_GT3_IDS(info) \
772.2227 -+	INTEL_VGA_DEVICE(0x1622, info), /* ULT */ \
772.2228 -+	INTEL_VGA_DEVICE(0x1626, info), /* ULT */ \
772.2229 -+	INTEL_VGA_DEVICE(0x162B, info), /* Iris */ \
772.2230 -+	INTEL_VGA_DEVICE(0x162E, info),  /* ULX */\
772.2231 -+	INTEL_VGA_DEVICE(0x162A, info), /* Server */ \
772.2232 -+	INTEL_VGA_DEVICE(0x162D, info)  /* Workstation */
772.2233 -+
772.2234 -+#define INTEL_BDW_RSVD_IDS(info) \
772.2235 -+	INTEL_VGA_DEVICE(0x1632, info), /* ULT */ \
772.2236 -+	INTEL_VGA_DEVICE(0x1636, info), /* ULT */ \
772.2237 -+	INTEL_VGA_DEVICE(0x163B, info), /* Iris */ \
772.2238 -+	INTEL_VGA_DEVICE(0x163E, info), /* ULX */ \
772.2239 -+	INTEL_VGA_DEVICE(0x163A, info), /* Server */ \
772.2240 -+	INTEL_VGA_DEVICE(0x163D, info)  /* Workstation */
772.2241 -+
772.2242 -+#define INTEL_BDW_IDS(info) \
772.2243 -+	INTEL_BDW_GT12_IDS(info), \
772.2244 -+	INTEL_BDW_GT3_IDS(info), \
772.2245 -+	INTEL_BDW_RSVD_IDS(info)
772.2246 - 
772.2247 - #define INTEL_CHV_IDS(info) \
772.2248 - 	INTEL_VGA_DEVICE(0x22b0, info), \
772.2249 -@@ -259,21 +245,85 @@
772.2250 - 	INTEL_VGA_DEVICE(0x22b2, info), \
772.2251 - 	INTEL_VGA_DEVICE(0x22b3, info)
772.2252 - 
772.2253 --#define INTEL_SKL_IDS(info) \
772.2254 --	INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
772.2255 -+#define INTEL_SKL_GT1_IDS(info)	\
772.2256 - 	INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */ \
772.2257 --	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
772.2258 --	INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
772.2259 - 	INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */ \
772.2260 -+	INTEL_VGA_DEVICE(0x1902, info), /* DT  GT1 */ \
772.2261 -+	INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
772.2262 -+	INTEL_VGA_DEVICE(0x190A, info) /* SRV GT1 */
772.2263 -+
772.2264 -+#define INTEL_SKL_GT2_IDS(info)	\
772.2265 -+	INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */ \
772.2266 -+	INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */ \
772.2267 - 	INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */ \
772.2268 - 	INTEL_VGA_DEVICE(0x1912, info), /* DT  GT2 */ \
772.2269 --	INTEL_VGA_DEVICE(0x1902, info), /* DT  GT1 */ \
772.2270 - 	INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */ \
772.2271 --	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
772.2272 --	INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */ \
772.2273 - 	INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */ \
772.2274 --	INTEL_VGA_DEVICE(0x192A, info), /* SRV GT3 */ \
772.2275 --	INTEL_VGA_DEVICE(0x190A, info), /* SRV GT1 */ \
772.2276 - 	INTEL_VGA_DEVICE(0x191D, info)  /* WKS GT2 */
772.2277 - 
772.2278 -+#define INTEL_SKL_GT3_IDS(info) \
772.2279 -+	INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */ \
772.2280 -+	INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */ \
772.2281 -+	INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */ \
772.2282 -+	INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */ \
772.2283 -+	INTEL_VGA_DEVICE(0x192D, info)  /* SRV GT3 */
772.2284 -+
772.2285 -+#define INTEL_SKL_GT4_IDS(info) \
772.2286 -+	INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */ \
772.2287 -+	INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */ \
772.2288 -+	INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */ \
772.2289 -+	INTEL_VGA_DEVICE(0x192A, info), /* SRV GT4 */ \
772.2290 -+	INTEL_VGA_DEVICE(0x193A, info)  /* SRV GT4e */
772.2291 -+
772.2292 -+#define INTEL_SKL_IDS(info)	 \
772.2293 -+	INTEL_SKL_GT1_IDS(info), \
772.2294 -+	INTEL_SKL_GT2_IDS(info), \
772.2295 -+	INTEL_SKL_GT3_IDS(info), \
772.2296 -+	INTEL_SKL_GT4_IDS(info)
772.2297 -+
772.2298 -+#define INTEL_BXT_IDS(info) \
772.2299 -+	INTEL_VGA_DEVICE(0x0A84, info), \
772.2300 -+	INTEL_VGA_DEVICE(0x1A84, info), \
772.2301 -+	INTEL_VGA_DEVICE(0x1A85, info), \
772.2302 -+	INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \
772.2303 -+	INTEL_VGA_DEVICE(0x5A85, info)  /* APL HD Graphics 500 */
772.2304 -+
772.2305 -+#define INTEL_GLK_IDS(info) \
772.2306 -+	INTEL_VGA_DEVICE(0x3184, info), \
772.2307 -+	INTEL_VGA_DEVICE(0x3185, info)
772.2308 -+
772.2309 -+#define INTEL_KBL_GT1_IDS(info)	\
772.2310 -+	INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \
772.2311 -+	INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \
772.2312 -+	INTEL_VGA_DEVICE(0x5917, info), /* DT  GT1.5 */ \
772.2313 -+	INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */ \
772.2314 -+	INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */ \
772.2315 -+	INTEL_VGA_DEVICE(0x5902, info), /* DT  GT1 */ \
772.2316 -+	INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */ \
772.2317 -+	INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */ \
772.2318 -+	INTEL_VGA_DEVICE(0x590A, info) /* SRV GT1 */
772.2319 -+
772.2320 -+#define INTEL_KBL_GT2_IDS(info)	\
772.2321 -+	INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
772.2322 -+	INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
772.2323 -+	INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
772.2324 -+	INTEL_VGA_DEVICE(0x5912, info), /* DT  GT2 */ \
772.2325 -+	INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */ \
772.2326 -+	INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */ \
772.2327 -+	INTEL_VGA_DEVICE(0x591D, info) /* WKS GT2 */
772.2328 -+
772.2329 -+#define INTEL_KBL_GT3_IDS(info) \
772.2330 -+	INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */ \
772.2331 -+	INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */ \
772.2332 -+	INTEL_VGA_DEVICE(0x5927, info) /* ULT GT3 */
772.2333 -+
772.2334 -+#define INTEL_KBL_GT4_IDS(info) \
772.2335 -+	INTEL_VGA_DEVICE(0x593B, info) /* Halo GT4 */
772.2336 -+
772.2337 -+#define INTEL_KBL_IDS(info) \
772.2338 -+	INTEL_KBL_GT1_IDS(info), \
772.2339 -+	INTEL_KBL_GT2_IDS(info), \
772.2340 -+	INTEL_KBL_GT3_IDS(info), \
772.2341 -+	INTEL_KBL_GT4_IDS(info)
772.2342 -+
772.2343 - #endif /* _I915_PCIIDS_H */
772.2344 -diff --git a/src/intel_device.c b/src/intel_device.c
772.2345 -index 140e1536..c4910cd8 100644
772.2346 ---- a/src/intel_device.c
772.2347 -+++ b/src/intel_device.c
772.2348 -@@ -38,6 +38,12 @@
772.2349 - #include <dirent.h>
772.2350 - #include <errno.h>
772.2351 - 
772.2352 -+#if MAJOR_IN_MKDEV
772.2353 -+#include <sys/mkdev.h>
772.2354 -+#elif MAJOR_IN_SYSMACROS
772.2355 -+#include <sys/sysmacros.h>
772.2356 -+#endif
772.2357 -+
772.2358 - #include <pciaccess.h>
772.2359 - 
772.2360 - #include <xorg-server.h>
772.2361 -@@ -197,9 +203,15 @@ static inline struct intel_device *intel_device(ScrnInfoPtr scrn)
772.2362 - 	return xf86GetEntityPrivate(scrn->entityList[0], intel_device_key)->ptr;
772.2363 - }
772.2364 - 
772.2365 -+static const char *kernel_module_names[] ={
772.2366 -+	"i915",
772.2367 -+	NULL,
772.2368 -+};
772.2369 -+
772.2370 - static int is_i915_device(int fd)
772.2371 - {
772.2372 - 	drm_version_t version;
772.2373 -+	const char **kn;
772.2374 - 	char name[5] = "";
772.2375 - 
772.2376 - 	memset(&version, 0, sizeof(version));
772.2377 -@@ -209,7 +221,22 @@ static int is_i915_device(int fd)
772.2378 - 	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
772.2379 - 		return 0;
772.2380 - 
772.2381 --	return strcmp("i915", name) == 0;
772.2382 -+	for (kn = kernel_module_names; *kn; kn++)
772.2383 -+		if (strcmp(*kn, name) == 0)
772.2384 -+			return 1;
772.2385 -+
772.2386 -+	return 0;
772.2387 -+}
772.2388 -+
772.2389 -+static int load_i915_kernel_module(void)
772.2390 -+{
772.2391 -+	const char **kn;
772.2392 -+
772.2393 -+	for (kn = kernel_module_names; *kn; kn++)
772.2394 -+		if (xf86LoadKernelModule(*kn))
772.2395 -+			return 0;
772.2396 -+
772.2397 -+	return -1;
772.2398 - }
772.2399 - 
772.2400 - static int is_i915_gem(int fd)
772.2401 -@@ -336,7 +363,7 @@ static int __intel_open_device__pci(const struct pci_device *pci)
772.2402 - 
772.2403 - 		sprintf(path + base, "driver");
772.2404 - 		if (stat(path, &st)) {
772.2405 --			if (xf86LoadKernelModule("i915"))
772.2406 -+			if (load_i915_kernel_module())
772.2407 - 				return -1;
772.2408 - 			(void)xf86LoadKernelModule("fbcon");
772.2409 - 		}
772.2410 -@@ -399,7 +426,7 @@ static int __intel_open_device__legacy(const struct pci_device *pci)
772.2411 - 
772.2412 - 	ret = drmCheckModesettingSupported(id);
772.2413 - 	if (ret) {
772.2414 --		if (xf86LoadKernelModule("i915"))
772.2415 -+		if (load_i915_kernel_module() == 0)
772.2416 - 			ret = drmCheckModesettingSupported(id);
772.2417 - 		if (ret)
772.2418 - 			return -1;
772.2419 -@@ -461,9 +488,9 @@ static int is_render_node(int fd, struct stat *st)
772.2420 - 
772.2421 - static char *find_render_node(int fd)
772.2422 - {
772.2423 --#if defined(USE_RENDERNODE)
772.2424 - 	struct stat master, render;
772.2425 - 	char buf[128];
772.2426 -+	int i;
772.2427 - 
772.2428 - 	/* Are we a render-node ourselves? */
772.2429 - 	if (is_render_node(fd, &master))
772.2430 -@@ -472,9 +499,17 @@ static char *find_render_node(int fd)
772.2431 - 	sprintf(buf, "/dev/dri/renderD%d", (int)((master.st_rdev | 0x80) & 0xbf));
772.2432 - 	if (stat(buf, &render) == 0 &&
772.2433 - 	    master.st_mode == render.st_mode &&
772.2434 --	    render.st_rdev == ((master.st_rdev | 0x80) & 0xbf))
772.2435 -+	    render.st_rdev == (master.st_rdev | 0x80))
772.2436 - 		return strdup(buf);
772.2437 --#endif
772.2438 -+
772.2439 -+	/* Misaligned card <-> renderD, do a full search */
772.2440 -+	for (i = 0; i < 16; i++) {
772.2441 -+		sprintf(buf, "/dev/dri/renderD%d", i + 128);
772.2442 -+		if (stat(buf, &render) == 0 &&
772.2443 -+		    master.st_mode == render.st_mode &&
772.2444 -+		    render.st_rdev == (master.st_rdev | 0x80))
772.2445 -+			return strdup(buf);
772.2446 -+	}
772.2447 - 
772.2448 - 	return NULL;
772.2449 - }
772.2450 -@@ -608,6 +643,27 @@ err_path:
772.2451 - 	return -1;
772.2452 - }
772.2453 - 
772.2454 -+void intel_close_device(int entity_num)
772.2455 -+{
772.2456 -+	struct intel_device *dev;
772.2457 -+
772.2458 -+	if (intel_device_key == -1)
772.2459 -+		return;
772.2460 -+
772.2461 -+	dev = xf86GetEntityPrivate(entity_num, intel_device_key)->ptr;
772.2462 -+	xf86GetEntityPrivate(entity_num, intel_device_key)->ptr = NULL;
772.2463 -+	if (!dev)
772.2464 -+		return;
772.2465 -+
772.2466 -+	if (dev->master_count == 0) /* Don't close server-fds */
772.2467 -+		close(dev->fd);
772.2468 -+
772.2469 -+	if (dev->render_node != dev->master_node)
772.2470 -+		free(dev->render_node);
772.2471 -+	free(dev->master_node);
772.2472 -+	free(dev);
772.2473 -+}
772.2474 -+
772.2475 - int __intel_peek_fd(ScrnInfoPtr scrn)
772.2476 - {
772.2477 - 	struct intel_device *dev;
772.2478 -@@ -672,6 +728,12 @@ struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd)
772.2479 - 	return dev;
772.2480 - }
772.2481 - 
772.2482 -+const char *intel_get_master_name(struct intel_device *dev)
772.2483 -+{
772.2484 -+	assert(dev && dev->master_node);
772.2485 -+	return dev->master_node;
772.2486 -+}
772.2487 -+
772.2488 - const char *intel_get_client_name(struct intel_device *dev)
772.2489 - {
772.2490 - 	assert(dev && dev->render_node);
772.2491 -diff --git a/src/intel_driver.h b/src/intel_driver.h
772.2492 -index 28ed1a0e..bece88a0 100644
772.2493 ---- a/src/intel_driver.h
772.2494 -+++ b/src/intel_driver.h
772.2495 -@@ -124,9 +124,11 @@ int intel_entity_get_devid(int index);
772.2496 - int intel_open_device(int entity_num,
772.2497 - 		      const struct pci_device *pci,
772.2498 - 		      struct xf86_platform_device *dev);
772.2499 -+void intel_close_device(int entity_num);
772.2500 - int __intel_peek_fd(ScrnInfoPtr scrn);
772.2501 - struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd);
772.2502 - int intel_has_render_node(struct intel_device *dev);
772.2503 -+const char *intel_get_master_name(struct intel_device *dev);
772.2504 - const char *intel_get_client_name(struct intel_device *dev);
772.2505 - int intel_get_client_fd(struct intel_device *dev);
772.2506 - int intel_get_device_id(struct intel_device *dev);
772.2507 -diff --git a/src/intel_list.h b/src/intel_list.h
772.2508 -index 51af825d..c8a3187a 100644
772.2509 ---- a/src/intel_list.h
772.2510 -+++ b/src/intel_list.h
772.2511 -@@ -306,8 +306,7 @@ list_is_empty(const struct list *head)
772.2512 -     list_entry((ptr)->prev, type, member)
772.2513 - 
772.2514 - #define __container_of(ptr, sample, member)				\
772.2515 --    (void *)((char *)(ptr)						\
772.2516 --	     - ((char *)&(sample)->member - (char *)(sample)))
772.2517 -+    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
772.2518 - /**
772.2519 -  * Loop through the list given by head and set pos to struct in the list.
772.2520 -  *
772.2521 -@@ -392,17 +391,50 @@ static inline void list_move_tail(struct list *list, struct list *head)
772.2522 - #define list_last_entry(ptr, type, member) \
772.2523 -     list_entry((ptr)->prev, type, member)
772.2524 - 
772.2525 --#define list_for_each_entry_reverse(pos, head, member)				\
772.2526 -+#define list_for_each_entry_reverse(pos, head, member)			\
772.2527 -     for (pos = __container_of((head)->prev, pos, member);		\
772.2528 - 	 &pos->member != (head);					\
772.2529 - 	 pos = __container_of(pos->member.prev, pos, member))
772.2530 - 
772.2531 - #endif
772.2532 - 
772.2533 -+#define list_for_each_entry_safe_from(pos, tmp, head, member)		\
772.2534 -+    for (tmp = __container_of(pos->member.next, pos, member);		\
772.2535 -+	 &pos->member != (head);					\
772.2536 -+	 pos = tmp, tmp = __container_of(tmp->member.next, tmp, member))
772.2537 -+
772.2538 - #undef container_of
772.2539 - #define container_of(ptr, type, member) \
772.2540 - 	((type *)((char *)(ptr) - (char *) &((type *)0)->member))
772.2541 - 
772.2542 -+static inline void __list_splice(const struct list *list,
772.2543 -+				 struct list *prev,
772.2544 -+				 struct list *next)
772.2545 -+{
772.2546 -+	struct list *first = list->next;
772.2547 -+	struct list *last = list->prev;
772.2548 -+
772.2549 -+	first->prev = prev;
772.2550 -+	prev->next = first;
772.2551 -+
772.2552 -+	last->next = next;
772.2553 -+	next->prev = last;
772.2554 -+}
772.2555 -+
772.2556 -+static inline void list_splice(const struct list *list,
772.2557 -+			       struct list *head)
772.2558 -+{
772.2559 -+	if (!list_is_empty(list))
772.2560 -+		__list_splice(list, head, head->next);
772.2561 -+}
772.2562 -+
772.2563 -+static inline void list_splice_tail(const struct list *list,
772.2564 -+				    struct list *head)
772.2565 -+{
772.2566 -+	if (!list_is_empty(list))
772.2567 -+		__list_splice(list, head->prev, head);
772.2568 -+}
772.2569 -+
772.2570 - static inline int list_is_singular(const struct list *list)
772.2571 - {
772.2572 - 	return list->next == list->prev;
772.2573 -diff --git a/src/intel_module.c b/src/intel_module.c
772.2574 -index 102d52aa..2e97b5ea 100644
772.2575 ---- a/src/intel_module.c
772.2576 -+++ b/src/intel_module.c
772.2577 -@@ -126,6 +126,17 @@ static const struct intel_device_info intel_skylake_info = {
772.2578 - 	.gen = 0110,
772.2579 - };
772.2580 - 
772.2581 -+static const struct intel_device_info intel_broxton_info = {
772.2582 -+	.gen = 0111,
772.2583 -+};
772.2584 -+
772.2585 -+static const struct intel_device_info intel_kabylake_info = {
772.2586 -+	.gen = 0112,
772.2587 -+};
772.2588 -+
772.2589 -+static const struct intel_device_info intel_geminilake_info = {
772.2590 -+	.gen = 0113,
772.2591 -+};
772.2592 - 
772.2593 - static const SymTabRec intel_chipsets[] = {
772.2594 - 	{PCI_CHIP_I810,				"i810"},
772.2595 -@@ -234,30 +245,63 @@ static const SymTabRec intel_chipsets[] = {
772.2596 - 	{0x0157, "HD Graphics"},
772.2597 - 
772.2598 - 	/* Broadwell Marketing names */
772.2599 --	{0x1602, "HD graphics"},
772.2600 --	{0x1606, "HD graphics"},
772.2601 --	{0x160B, "HD graphics"},
772.2602 --	{0x160A, "HD graphics"},
772.2603 --	{0x160D, "HD graphics"},
772.2604 --	{0x160E, "HD graphics"},
772.2605 --	{0x1612, "HD graphics 5600"},
772.2606 --	{0x1616, "HD graphics 5500"},
772.2607 --	{0x161B, "HD graphics"},
772.2608 --	{0x161A, "HD graphics"},
772.2609 --	{0x161D, "HD graphics"},
772.2610 --	{0x161E, "HD graphics 5300"},
772.2611 --	{0x1622, "Iris Pro graphics 6200"},
772.2612 --	{0x1626, "HD graphics 6000"},
772.2613 --	{0x162B, "Iris graphics 6100"},
772.2614 --	{0x162A, "Iris Pro graphics P6300"},
772.2615 --	{0x162D, "HD graphics"},
772.2616 --	{0x162E, "HD graphics"},
772.2617 --	{0x1632, "HD graphics"},
772.2618 --	{0x1636, "HD graphics"},
772.2619 --	{0x163B, "HD graphics"},
772.2620 --	{0x163A, "HD graphics"},
772.2621 --	{0x163D, "HD graphics"},
772.2622 --	{0x163E, "HD graphics"},
772.2623 -+	{0x1602, "HD Graphics"},
772.2624 -+	{0x1606, "HD Graphics"},
772.2625 -+	{0x160B, "HD Graphics"},
772.2626 -+	{0x160A, "HD Graphics"},
772.2627 -+	{0x160D, "HD Graphics"},
772.2628 -+	{0x160E, "HD Graphics"},
772.2629 -+	{0x1612, "HD Graphics 5600"},
772.2630 -+	{0x1616, "HD Graphics 5500"},
772.2631 -+	{0x161B, "HD Graphics"},
772.2632 -+	{0x161A, "HD Graphics"},
772.2633 -+	{0x161D, "HD Graphics"},
772.2634 -+	{0x161E, "HD Graphics 5300"},
772.2635 -+	{0x1622, "Iris Pro Graphics 6200"},
772.2636 -+	{0x1626, "HD Graphics 6000"},
772.2637 -+	{0x162B, "Iris Graphics 6100"},
772.2638 -+	{0x162A, "Iris Pro Graphics P6300"},
772.2639 -+	{0x162D, "HD Graphics"},
772.2640 -+	{0x162E, "HD Graphics"},
772.2641 -+	{0x1632, "HD Graphics"},
772.2642 -+	{0x1636, "HD Graphics"},
772.2643 -+	{0x163B, "HD Graphics"},
772.2644 -+	{0x163A, "HD Graphics"},
772.2645 -+	{0x163D, "HD Graphics"},
772.2646 -+	{0x163E, "HD Graphics"},
772.2647 -+
772.2648 -+	/* Cherryview (Cherrytrail/Braswell) */
772.2649 -+	{0x22b0, "HD Graphics"},
772.2650 -+	{0x22b1, "HD Graphics"},
772.2651 -+	{0x22b2, "HD Graphics"},
772.2652 -+	{0x22b3, "HD Graphics"},
772.2653 -+
772.2654 -+	/* Skylake */
772.2655 -+	{0x1902, "HD Graphics 510"},
772.2656 -+	{0x1906, "HD Graphics 510"},
772.2657 -+	{0x190B, "HD Graphics 510"},
772.2658 -+	{0x1912, "HD Graphics 530"},
772.2659 -+	{0x1916, "HD Graphics 520"},
772.2660 -+	{0x191B, "HD Graphics 530"},
772.2661 -+	{0x191D, "HD Graphics P530"},
772.2662 -+	{0x191E, "HD Graphics 515"},
772.2663 -+	{0x1921, "HD Graphics 520"},
772.2664 -+	{0x1926, "Iris Graphics 540"},
772.2665 -+	{0x1927, "Iris Graphics 550"},
772.2666 -+	{0x192B, "Iris Graphics 555"},
772.2667 -+	{0x192D, "Iris Graphics P555"},
772.2668 -+	{0x1932, "Iris Pro Graphics 580"},
772.2669 -+	{0x193A, "Iris Pro Graphics P580"},
772.2670 -+	{0x193B, "Iris Pro Graphics 580"},
772.2671 -+	{0x193D, "Iris Pro Graphics P580"},
772.2672 -+
772.2673 -+	/* Broxton (Apollolake) */
772.2674 -+	{0x5A84, "HD Graphics 505"},
772.2675 -+	{0x5A85, "HD Graphics 500"},
772.2676 -+
772.2677 -+	/* Kabylake */
772.2678 -+	{0x5916, "HD Graphics 620"},
772.2679 -+	{0x591E, "HD Graphics 615"},
772.2680 - 
772.2681 - 	/* When adding new identifiers, also update:
772.2682 - 	 * 1. intel_identify()
772.2683 -@@ -305,18 +349,14 @@ static const struct pci_id_match intel_device_match[] = {
772.2684 - 	INTEL_IVB_D_IDS(&intel_ivybridge_info),
772.2685 - 	INTEL_IVB_M_IDS(&intel_ivybridge_info),
772.2686 - 
772.2687 --	INTEL_HSW_D_IDS(&intel_haswell_info),
772.2688 --	INTEL_HSW_M_IDS(&intel_haswell_info),
772.2689 --
772.2690 --	INTEL_VLV_D_IDS(&intel_valleyview_info),
772.2691 --	INTEL_VLV_M_IDS(&intel_valleyview_info),
772.2692 --
772.2693 --	INTEL_BDW_D_IDS(&intel_broadwell_info),
772.2694 --	INTEL_BDW_M_IDS(&intel_broadwell_info),
772.2695 --
772.2696 -+	INTEL_HSW_IDS(&intel_haswell_info),
772.2697 -+	INTEL_VLV_IDS(&intel_valleyview_info),
772.2698 -+	INTEL_BDW_IDS(&intel_broadwell_info),
772.2699 - 	INTEL_CHV_IDS(&intel_cherryview_info),
772.2700 --
772.2701 - 	INTEL_SKL_IDS(&intel_skylake_info),
772.2702 -+	INTEL_BXT_IDS(&intel_broxton_info),
772.2703 -+	INTEL_KBL_IDS(&intel_kabylake_info),
772.2704 -+	INTEL_GLK_IDS(&intel_geminilake_info),
772.2705 - 
772.2706 - 	INTEL_VGA_DEVICE(PCI_MATCH_ANY, &intel_generic_info),
772.2707 - #endif
772.2708 -@@ -448,9 +488,9 @@ static void intel_identify(int flags)
772.2709 - 	if (unique != stack)
772.2710 - 		free(unique);
772.2711 - 
772.2712 --	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) HD Graphics: 2000-6000\n");
772.2713 --	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Graphics: 5100, 6100\n");
772.2714 --	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Pro Graphics: 5200, 6200, P6300\n");
772.2715 -+	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) HD Graphics\n");
772.2716 -+	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Graphics\n");
772.2717 -+	xf86Msg(X_INFO, INTEL_NAME ": Driver for Intel(R) Iris(TM) Pro Graphics\n");
772.2718 - }
772.2719 - 
772.2720 - static Bool intel_driver_func(ScrnInfoPtr pScrn,
772.2721 -@@ -508,6 +548,9 @@ static enum accel_method { NOACCEL, SNA, UXA } get_accel_method(void)
772.2722 - 	if (hosted())
772.2723 - 		return SNA;
772.2724 - 
772.2725 -+	if (xf86configptr == NULL) /* X -configure */
772.2726 -+		return SNA;
772.2727 -+
772.2728 - 	dev = _xf86findDriver("intel", xf86configptr->conf_device_lst);
772.2729 - 	if (dev && dev->dev_option_lst) {
772.2730 - 		const char *s;
772.2731 -@@ -582,10 +625,17 @@ intel_scrn_create(DriverPtr		driver,
772.2732 - 	case NOACCEL:
772.2733 - #endif
772.2734 - 	case UXA:
772.2735 --		  return intel_init_scrn(scrn);
772.2736 -+		return intel_init_scrn(scrn);
772.2737 - #endif
772.2738 - 
772.2739 --	default: break;
772.2740 -+	default:
772.2741 -+#if USE_SNA
772.2742 -+		return sna_init_scrn(scrn, entity_num);
772.2743 -+#elif USE_UXA
772.2744 -+		return intel_init_scrn(scrn);
772.2745 -+#else
772.2746 -+		break;
772.2747 -+#endif
772.2748 - 	}
772.2749 - #endif
772.2750 - 
772.2751 -@@ -604,6 +654,8 @@ static Bool intel_pci_probe(DriverPtr		driver,
772.2752 - 			    struct pci_device	*pci,
772.2753 - 			    intptr_t		match_data)
772.2754 - {
772.2755 -+	Bool ret;
772.2756 -+
772.2757 - 	if (intel_open_device(entity_num, pci, NULL) == -1) {
772.2758 - #if UMS
772.2759 - 		switch (pci->device_id) {
772.2760 -@@ -621,7 +673,11 @@ static Bool intel_pci_probe(DriverPtr		driver,
772.2761 - #endif
772.2762 - 	}
772.2763 - 
772.2764 --	return intel_scrn_create(driver, entity_num, match_data, 0);
772.2765 -+	ret = intel_scrn_create(driver, entity_num, match_data, 0);
772.2766 -+	if (!ret)
772.2767 -+		intel_close_device(entity_num);
772.2768 -+
772.2769 -+	return ret;
772.2770 - }
772.2771 - 
772.2772 - #ifdef XSERVER_PLATFORM_BUS
772.2773 -@@ -644,9 +700,16 @@ intel_platform_probe(DriverPtr driver,
772.2774 - 
772.2775 - 	/* if we get any flags we don't understand fail to probe for now */
772.2776 - 	if (flags)
772.2777 --		return FALSE;
772.2778 -+		goto err;
772.2779 -+
772.2780 -+	if (!intel_scrn_create(driver, entity_num, match_data, scrn_flags))
772.2781 -+		goto err;
772.2782 - 
772.2783 --	return intel_scrn_create(driver, entity_num, match_data, scrn_flags);
772.2784 -+	return TRUE;
772.2785 -+
772.2786 -+err:
772.2787 -+	intel_close_device(entity_num);
772.2788 -+	return FALSE;
772.2789 - }
772.2790 - #endif
772.2791 - 
772.2792 -diff --git a/src/intel_options.c b/src/intel_options.c
772.2793 -index ff8541a4..7f253ac1 100644
772.2794 ---- a/src/intel_options.c
772.2795 -+++ b/src/intel_options.c
772.2796 -@@ -2,18 +2,24 @@
772.2797 - #include "config.h"
772.2798 - #endif
772.2799 - 
772.2800 -+#include <xorg-server.h>
772.2801 -+#include <xorgVersion.h>
772.2802 -+#include <xf86Parser.h>
772.2803 -+
772.2804 - #include "intel_options.h"
772.2805 - 
772.2806 - const OptionInfoRec intel_options[] = {
772.2807 --	{OPTION_ACCEL_DISABLE,	"NoAccel",	OPTV_BOOLEAN,	{0},	0},
772.2808 -+	{OPTION_ACCEL_ENABLE,	"Accel",	OPTV_BOOLEAN,	{0},	0},
772.2809 - 	{OPTION_ACCEL_METHOD,	"AccelMethod",	OPTV_STRING,	{0},	0},
772.2810 - 	{OPTION_BACKLIGHT,	"Backlight",	OPTV_STRING,	{0},	0},
772.2811 -+	{OPTION_EDID,		"CustomEDID",	OPTV_STRING,	{0},	0},
772.2812 - 	{OPTION_DRI,		"DRI",		OPTV_STRING,	{0},	0},
772.2813 - 	{OPTION_PRESENT,	"Present",	OPTV_BOOLEAN,	{0},	1},
772.2814 - 	{OPTION_COLOR_KEY,	"ColorKey",	OPTV_INTEGER,	{0},	0},
772.2815 - 	{OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	0},
772.2816 - 	{OPTION_TILING_2D,	"Tiling",	OPTV_BOOLEAN,	{0},	1},
772.2817 - 	{OPTION_TILING_FB,	"LinearFramebuffer",	OPTV_BOOLEAN,	{0},	0},
772.2818 -+	{OPTION_ROTATION,	"HWRotation",	OPTV_BOOLEAN,	{0},	1},
772.2819 - 	{OPTION_VSYNC,		"VSync",	OPTV_BOOLEAN,	{0},	1},
772.2820 - 	{OPTION_PAGEFLIP,	"PageFlip",	OPTV_BOOLEAN,	{0},	1},
772.2821 - 	{OPTION_SWAPBUFFERS_WAIT, "SwapbuffersWait", OPTV_BOOLEAN,	{0},	1},
772.2822 -@@ -21,7 +27,6 @@ const OptionInfoRec intel_options[] = {
772.2823 - 	{OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, 0},
772.2824 - 	{OPTION_HOTPLUG,	"HotPlug",	OPTV_BOOLEAN,	{0},	1},
772.2825 - 	{OPTION_REPROBE,	"ReprobeOutputs", OPTV_BOOLEAN,	{0},	0},
772.2826 --	{OPTION_DELETE_DP12,	"DeleteUnusedDP12Displays", OPTV_BOOLEAN,	{0},	0},
772.2827 - #ifdef INTEL_XVMC
772.2828 - 	{OPTION_XVMC,		"XvMC",		OPTV_BOOLEAN,	{0},	1},
772.2829 - #endif
772.2830 -@@ -54,3 +59,85 @@ OptionInfoPtr intel_options_get(ScrnInfoPtr scrn)
772.2831 - 
772.2832 - 	return options;
772.2833 - }
772.2834 -+
772.2835 -+Bool intel_option_cast_to_bool(OptionInfoPtr options, int id, Bool val)
772.2836 -+{
772.2837 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.2838 -+	xf86getBoolValue(&val, xf86GetOptValString(options, id));
772.2839 -+#endif
772.2840 -+	return val;
772.2841 -+}
772.2842 -+
772.2843 -+static int
772.2844 -+namecmp(const char *s1, const char *s2)
772.2845 -+{
772.2846 -+	char c1, c2;
772.2847 -+
772.2848 -+	if (!s1 || *s1 == 0) {
772.2849 -+		if (!s2 || *s2 == 0)
772.2850 -+			return 0;
772.2851 -+		else
772.2852 -+			return 1;
772.2853 -+	}
772.2854 -+
772.2855 -+	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.2856 -+		s1++;
772.2857 -+
772.2858 -+	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.2859 -+		s2++;
772.2860 -+
772.2861 -+	c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.2862 -+	c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.2863 -+	while (c1 == c2) {
772.2864 -+		if (c1 == '\0')
772.2865 -+			return 0;
772.2866 -+
772.2867 -+		s1++;
772.2868 -+		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.2869 -+			s1++;
772.2870 -+
772.2871 -+		s2++;
772.2872 -+		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.2873 -+			s2++;
772.2874 -+
772.2875 -+		c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.2876 -+		c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.2877 -+	}
772.2878 -+
772.2879 -+	return c1 - c2;
772.2880 -+}
772.2881 -+
772.2882 -+unsigned intel_option_cast_to_unsigned(OptionInfoPtr options, int id, unsigned val)
772.2883 -+{
772.2884 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.2885 -+	const char *str = xf86GetOptValString(options, id);
772.2886 -+#else
772.2887 -+	const char *str = NULL;
772.2888 -+#endif
772.2889 -+	unsigned v;
772.2890 -+
772.2891 -+	if (str == NULL || *str == '\0')
772.2892 -+		return val;
772.2893 -+
772.2894 -+	if (namecmp(str, "on") == 0)
772.2895 -+		return val;
772.2896 -+	if (namecmp(str, "true") == 0)
772.2897 -+		return val;
772.2898 -+	if (namecmp(str, "yes") == 0)
772.2899 -+		return val;
772.2900 -+
772.2901 -+	if (namecmp(str, "0") == 0)
772.2902 -+		return 0;
772.2903 -+	if (namecmp(str, "off") == 0)
772.2904 -+		return 0;
772.2905 -+	if (namecmp(str, "false") == 0)
772.2906 -+		return 0;
772.2907 -+	if (namecmp(str, "no") == 0)
772.2908 -+		return 0;
772.2909 -+
772.2910 -+	v = atoi(str);
772.2911 -+	if (v)
772.2912 -+		return v;
772.2913 -+
772.2914 -+	return val;
772.2915 -+}
772.2916 -diff --git a/src/intel_options.h b/src/intel_options.h
772.2917 -index 7e2cbd9b..43635f1f 100644
772.2918 ---- a/src/intel_options.h
772.2919 -+++ b/src/intel_options.h
772.2920 -@@ -12,15 +12,17 @@
772.2921 -  */
772.2922 - 
772.2923 - enum intel_options {
772.2924 --	OPTION_ACCEL_DISABLE,
772.2925 -+	OPTION_ACCEL_ENABLE,
772.2926 - 	OPTION_ACCEL_METHOD,
772.2927 - 	OPTION_BACKLIGHT,
772.2928 -+	OPTION_EDID,
772.2929 - 	OPTION_DRI,
772.2930 - 	OPTION_PRESENT,
772.2931 - 	OPTION_VIDEO_KEY,
772.2932 - 	OPTION_COLOR_KEY,
772.2933 - 	OPTION_TILING_2D,
772.2934 - 	OPTION_TILING_FB,
772.2935 -+	OPTION_ROTATION,
772.2936 - 	OPTION_VSYNC,
772.2937 - 	OPTION_PAGEFLIP,
772.2938 - 	OPTION_SWAPBUFFERS_WAIT,
772.2939 -@@ -28,7 +30,6 @@ enum intel_options {
772.2940 - 	OPTION_PREFER_OVERLAY,
772.2941 - 	OPTION_HOTPLUG,
772.2942 - 	OPTION_REPROBE,
772.2943 --	OPTION_DELETE_DP12,
772.2944 - #if defined(XvMCExtension) && defined(ENABLE_XVMC)
772.2945 - 	OPTION_XVMC,
772.2946 - #define INTEL_XVMC 1
772.2947 -@@ -51,5 +52,7 @@ enum intel_options {
772.2948 - 
772.2949 - extern const OptionInfoRec intel_options[];
772.2950 - OptionInfoPtr intel_options_get(ScrnInfoPtr scrn);
772.2951 -+unsigned intel_option_cast_to_unsigned(OptionInfoPtr, int id, unsigned val);
772.2952 -+Bool intel_option_cast_to_bool(OptionInfoPtr, int id, Bool val);
772.2953 - 
772.2954 - #endif /* INTEL_OPTIONS_H */
772.2955 -diff --git a/src/legacy/i810/i810_common.h b/src/legacy/i810/i810_common.h
772.2956 -index 4cc10e8b..8355708c 100644
772.2957 ---- a/src/legacy/i810/i810_common.h
772.2958 -+++ b/src/legacy/i810/i810_common.h
772.2959 -@@ -52,7 +52,7 @@
772.2960 - 
772.2961 - #define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1))
772.2962 - 
772.2963 --/* Using usleep() makes things noticably slow. */
772.2964 -+/* Using usleep() makes things noticeably slow. */
772.2965 - #if 0
772.2966 - #define DELAY(x) usleep(x)
772.2967 - #else
772.2968 -@@ -185,7 +185,7 @@ enum {
772.2969 -  *    - zbuffer linear offset and pitch -- also invarient
772.2970 -  *    - drawing origin in back and depth buffers.
772.2971 -  *
772.2972 -- * Keep the depth/back buffer state here to acommodate private buffers
772.2973 -+ * Keep the depth/back buffer state here to accommodate private buffers
772.2974 -  * in the future.
772.2975 -  */
772.2976 - #define I810_DESTREG_DI0  0		/* CMD_OP_DESTBUFFER_INFO (2 dwords) */
772.2977 -diff --git a/src/legacy/i810/i810_hwmc.c b/src/legacy/i810/i810_hwmc.c
772.2978 -index 7cb9c1ab..58661b0a 100644
772.2979 ---- a/src/legacy/i810/i810_hwmc.c
772.2980 -+++ b/src/legacy/i810/i810_hwmc.c
772.2981 -@@ -171,7 +171,7 @@ static XF86MCAdaptorPtr ppAdapt[1] =
772.2982 -  *
772.2983 -  *  I810InitMC
772.2984 -  *
772.2985 -- *  Initialize the hardware motion compenstation extention for this 
772.2986 -+ *  Initialize the hardware motion compensation extension for this
772.2987 -  *  hardware. The initialization routines want the address of the pointers
772.2988 -  *  to the structures, not the address of the structures. This means we
772.2989 -  *  allocate (or create static?) the pointer memory and pass that 
772.2990 -diff --git a/src/legacy/i810/i810_memory.c b/src/legacy/i810/i810_memory.c
772.2991 -index c3de2777..6f274836 100644
772.2992 ---- a/src/legacy/i810/i810_memory.c
772.2993 -+++ b/src/legacy/i810/i810_memory.c
772.2994 -@@ -76,7 +76,7 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn)
772.2995 -    unsigned long size = pScrn->videoRam * 1024UL;
772.2996 -    I810Ptr pI810 = I810PTR(pScrn);
772.2997 -    int key;
772.2998 --   long tom = 0;
772.2999 -+   unsigned long tom = 0;
772.3000 -    unsigned long physical;
772.3001 - 
772.3002 -    if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) {
772.3003 -@@ -132,8 +132,8 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn)
772.3004 -     * Keep it 512K aligned for the sake of tiled regions.
772.3005 -     */
772.3006 - 
772.3007 --   tom += 0x7ffff;
772.3008 --   tom &= ~0x7ffff;
772.3009 -+   tom += 0x7ffffUL;
772.3010 -+   tom &= ~0x7ffffUL;
772.3011 - 
772.3012 -    if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) {
772.3013 -       pI810->DcacheOffset = tom;
772.3014 -diff --git a/src/legacy/i810/i810_reg.h b/src/legacy/i810/i810_reg.h
772.3015 -index 54faeb3d..fa091c5b 100644
772.3016 ---- a/src/legacy/i810/i810_reg.h
772.3017 -+++ b/src/legacy/i810/i810_reg.h
772.3018 -@@ -245,7 +245,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
772.3019 -  * not sure they refer to local (graphics) memory.
772.3020 -  *
772.3021 -  * These details are for the local memory control registers,
772.3022 -- * (pp301-310).  The test machines are not equiped with local memory,
772.3023 -+ * (pp301-310).  The test machines are not equipped with local memory,
772.3024 -  * so nothing is tested.  Only a single row seems to be supported.
772.3025 -  */
772.3026 - #define DRAM_ROW_TYPE      0x3000
772.3027 -diff --git a/src/legacy/i810/i810_video.c b/src/legacy/i810/i810_video.c
772.3028 -index be49b91d..af683c81 100644
772.3029 ---- a/src/legacy/i810/i810_video.c
772.3030 -+++ b/src/legacy/i810/i810_video.c
772.3031 -@@ -77,7 +77,11 @@ static int I810PutImage( ScrnInfoPtr,
772.3032 - static int I810QueryImageAttributes(ScrnInfoPtr, 
772.3033 - 	int, unsigned short *, unsigned short *,  int *, int *);
772.3034 - 
772.3035 -+#if !HAVE_NOTIFY_FD
772.3036 - static void I810BlockHandler(BLOCKHANDLER_ARGS_DECL);
772.3037 -+#else
772.3038 -+static void I810BlockHandler(void *data, void *_timeout);
772.3039 -+#endif
772.3040 - 
772.3041 - #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
772.3042 - 
772.3043 -@@ -418,8 +422,14 @@ I810SetupImageVideo(ScreenPtr screen)
772.3044 - 
772.3045 -     pI810->adaptor = adapt;
772.3046 - 
772.3047 -+#if !HAVE_NOTIFY_FD
772.3048 -     pI810->BlockHandler = screen->BlockHandler;
772.3049 -     screen->BlockHandler = I810BlockHandler;
772.3050 -+#else
772.3051 -+    RegisterBlockAndWakeupHandlers(I810BlockHandler,
772.3052 -+				   (ServerWakeupHandlerProcPtr)NoopDDA,
772.3053 -+				   pScrn);
772.3054 -+#endif
772.3055 - 
772.3056 -     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
772.3057 -     xvContrast   = MAKE_ATOM("XV_CONTRAST");
772.3058 -@@ -1135,6 +1145,7 @@ I810QueryImageAttributes(
772.3059 -     return size;
772.3060 - }
772.3061 - 
772.3062 -+#if !HAVE_NOTIFY_FD
772.3063 - static void
772.3064 - I810BlockHandler (BLOCKHANDLER_ARGS_DECL)
772.3065 - {
772.3066 -@@ -1172,6 +1183,38 @@ I810BlockHandler (BLOCKHANDLER_ARGS_DECL)
772.3067 -         }
772.3068 -     }
772.3069 - }
772.3070 -+#else
772.3071 -+static void
772.3072 -+I810BlockHandler(void *data, void *_timeout)
772.3073 -+{
772.3074 -+    ScrnInfoPtr pScrn = data;
772.3075 -+    I810Ptr      pI810 = I810PTR(pScrn);
772.3076 -+    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
772.3077 -+    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);
772.3078 -+
772.3079 -+    if(pPriv->videoStatus & TIMER_MASK) {
772.3080 -+	UpdateCurrentTime();
772.3081 -+	if(pPriv->videoStatus & OFF_TIMER) {
772.3082 -+	    if(pPriv->offTime < currentTime.milliseconds) {
772.3083 -+		/* Turn off the overlay */
772.3084 -+		overlay->OV0CMD &= 0xFFFFFFFE;
772.3085 -+		OVERLAY_UPDATE(pI810->OverlayPhysical);
772.3086 -+
772.3087 -+		pPriv->videoStatus = FREE_TIMER;
772.3088 -+		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
772.3089 -+	    }
772.3090 -+	} else {  /* FREE_TIMER */
772.3091 -+	    if(pPriv->freeTime < currentTime.milliseconds) {
772.3092 -+		if(pPriv->linear) {
772.3093 -+		   xf86FreeOffscreenLinear(pPriv->linear);
772.3094 -+		   pPriv->linear = NULL;
772.3095 -+		}
772.3096 -+		pPriv->videoStatus = 0;
772.3097 -+	    }
772.3098 -+        }
772.3099 -+    }
772.3100 -+}
772.3101 -+#endif
772.3102 - 
772.3103 - 
772.3104 - /***************************************************************************
772.3105 -@@ -1373,7 +1416,6 @@ I810DisplaySurface(
772.3106 -       UpdateCurrentTime();
772.3107 -       pI810Priv->videoStatus = FREE_TIMER;
772.3108 -       pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;
772.3109 --      pScrn->pScreen->BlockHandler = I810BlockHandler;
772.3110 -     }
772.3111 - 
772.3112 -     return Success;
772.3113 -diff --git a/src/legacy/i810/xvmc/I810XvMC.c b/src/legacy/i810/xvmc/I810XvMC.c
772.3114 -index e6b63d30..a538e999 100644
772.3115 ---- a/src/legacy/i810/xvmc/I810XvMC.c
772.3116 -+++ b/src/legacy/i810/xvmc/I810XvMC.c
772.3117 -@@ -61,7 +61,7 @@ static int event_base;
772.3118 - // Arguments: pI810XvMC private data structure from the current context.
772.3119 - // Notes: We faked the drmMapBufs for the i810's security so now we have
772.3120 - //   to insert an allocated page into the correct spot in the faked
772.3121 --//   list to keep up appearences.
772.3122 -+//   list to keep up appearances.
772.3123 - //   Concept for this function was taken from Mesa sources.
772.3124 - // Returns: drmBufPtr containing the information about the allocated page.
772.3125 - ***************************************************************************/
772.3126 -@@ -188,7 +188,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
772.3127 - 
772.3128 -   /* Check for drm */
772.3129 -   if(! drmAvailable()) {
772.3130 --    printf("Direct Rendering is not avilable on this system!\n");
772.3131 -+    printf("Direct Rendering is not available on this system!\n");
772.3132 -     return BadAlloc;
772.3133 -   }
772.3134 - 
772.3135 -@@ -3279,7 +3279,7 @@ _X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
772.3136 - //   display - Connection to X server
772.3137 - //   surface - Surface to flush
772.3138 - // Info:
772.3139 --//   This command is a noop for i810 becuase we always dispatch buffers in
772.3140 -+//   This command is a noop for i810 because we always dispatch buffers in
772.3141 - //   render. There is little gain to be had with 4k buffers.
772.3142 - // Returns: Status
772.3143 - ***************************************************************************/
772.3144 -diff --git a/src/render_program/exa_wm.g4i b/src/render_program/exa_wm.g4i
772.3145 -index 5d3d45b1..587b581c 100644
772.3146 ---- a/src/render_program/exa_wm.g4i
772.3147 -+++ b/src/render_program/exa_wm.g4i
772.3148 -@@ -57,7 +57,7 @@ define(`mask_dw_dy', `g6.4<0,1,0>F')
772.3149 - define(`mask_wo',    `g6.12<0,1,0>F')
772.3150 - 
772.3151 - /*
772.3152 -- * Local variables. Pairs must be aligned on even reg boundry
772.3153 -+ * Local variables. Pairs must be aligned on even reg boundary
772.3154 -  */
772.3155 - 
772.3156 - /* this holds the X dest coordinates */
772.3157 -diff --git a/src/render_program/exa_wm_yuv_rgb.g8a b/src/render_program/exa_wm_yuv_rgb.g8a
772.3158 -index 7def0930..34973ba8 100644
772.3159 ---- a/src/render_program/exa_wm_yuv_rgb.g8a
772.3160 -+++ b/src/render_program/exa_wm_yuv_rgb.g8a
772.3161 -@@ -76,7 +76,7 @@ add (16)    Cbn<1>F		Cb<8,8,1>F	-0.501961F  { compr align1 };
772.3162 -     /* 
772.3163 -      * R = Y + Cr * 1.596
772.3164 -      */
772.3165 --mov (8)    acc0<1>F		Yn<8,8,1>F		    { compr align1 };
772.3166 -+mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
772.3167 - mac.sat(8) src_sample_r_01<1>F	Crn_01<8,8,1>F	1.596F	    { compr align1 };
772.3168 -      
772.3169 - mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
772.3170 -@@ -84,7 +84,7 @@ mac.sat(8) src_sample_r_23<1>F	Crn_23<8,8,1>F	1.596F	    { compr align1 };
772.3171 -     /*
772.3172 -      * G = Crn * -0.813 + Cbn * -0.392 + Y
772.3173 -      */
772.3174 --mov (8)    acc0<1>F		Yn_23<8,8,1>F		    { compr align1 };
772.3175 -+mov (8)    acc0<1>F		Yn_01<8,8,1>F		    { compr align1 };
772.3176 - mac (8)    acc0<1>F		Crn_01<8,8,1>F    	-0.813F	    { compr align1 };
772.3177 - mac.sat(8) src_sample_g_01<1>F	Cbn_01<8,8,1>F    	-0.392F	    { compr align1 };
772.3178 - 
772.3179 -diff --git a/src/render_program/exa_wm_yuv_rgb.g8b b/src/render_program/exa_wm_yuv_rgb.g8b
772.3180 -index 44949538..2cd6fc44 100644
772.3181 ---- a/src/render_program/exa_wm_yuv_rgb.g8b
772.3182 -+++ b/src/render_program/exa_wm_yuv_rgb.g8b
772.3183 -@@ -6,7 +6,7 @@
772.3184 -    { 0x80600048, 0x21c03ae8, 0x3e8d02c0, 0x3fcc49ba },
772.3185 -    { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
772.3186 -    { 0x80600048, 0x21e03ae8, 0x3e8d02e0, 0x3fcc49ba },
772.3187 --   { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
772.3188 -+   { 0x00600001, 0x24003ae0, 0x008d0300, 0x00000000 },
772.3189 -    { 0x00600048, 0x24003ae0, 0x3e8d02c0, 0xbf5020c5 },
772.3190 -    { 0x80600048, 0x22003ae8, 0x3e8d0340, 0xbec8b439 },
772.3191 -    { 0x00600001, 0x24003ae0, 0x008d0320, 0x00000000 },
772.3192 -diff --git a/src/sna/Makefile.am b/src/sna/Makefile.am
772.3193 -index e09a8d49..adf13963 100644
772.3194 ---- a/src/sna/Makefile.am
772.3195 -+++ b/src/sna/Makefile.am
772.3196 -@@ -107,6 +107,8 @@ libsna_la_SOURCES = \
772.3197 - 	gen8_render.h \
772.3198 - 	gen8_vertex.c \
772.3199 - 	gen8_vertex.h \
772.3200 -+	gen9_render.c \
772.3201 -+	gen9_render.h \
772.3202 - 	xassert.h \
772.3203 - 	$(NULL)
772.3204 - 
772.3205 -diff --git a/src/sna/blt.c b/src/sna/blt.c
772.3206 -index b5bfee69..cb90437a 100644
772.3207 ---- a/src/sna/blt.c
772.3208 -+++ b/src/sna/blt.c
772.3209 -@@ -30,112 +30,608 @@
772.3210 - #endif
772.3211 - 
772.3212 - #include "sna.h"
772.3213 -+#include <pixman.h>
772.3214 - 
772.3215 --#if __x86_64__
772.3216 --#define USE_SSE2 1
772.3217 --#endif
772.3218 --
772.3219 --#if USE_SSE2
772.3220 -+#if defined(sse2)
772.3221 -+#pragma GCC push_options
772.3222 -+#pragma GCC target("sse2,inline-all-stringops,fpmath=sse")
772.3223 -+#pragma GCC optimize("Ofast")
772.3224 - #include <xmmintrin.h>
772.3225 - 
772.3226 - #if __x86_64__
772.3227 - #define have_sse2() 1
772.3228 - #else
772.3229 --enum {
772.3230 --	MMX = 0x1,
772.3231 --	MMX_EXTENSIONS = 0x2,
772.3232 --	SSE = 0x6,
772.3233 --	SSE2 = 0x8,
772.3234 --	CMOV = 0x10
772.3235 --};
772.3236 --
772.3237 --#ifdef __GNUC__
772.3238 --static unsigned int
772.3239 --detect_cpu_features(void)
772.3240 --{
772.3241 --	unsigned int features;
772.3242 --	unsigned int result = 0;
772.3243 --
772.3244 --	char vendor[13];
772.3245 --	vendor[0] = 0;
772.3246 --	vendor[12] = 0;
772.3247 --
772.3248 --	asm (
772.3249 --	     "pushf\n"
772.3250 --	     "pop %%eax\n"
772.3251 --	     "mov %%eax, %%ecx\n"
772.3252 --	     "xor $0x00200000, %%eax\n"
772.3253 --	     "push %%eax\n"
772.3254 --	     "popf\n"
772.3255 --	     "pushf\n"
772.3256 --	     "pop %%eax\n"
772.3257 --	     "mov $0x0, %%edx\n"
772.3258 --	     "xor %%ecx, %%eax\n"
772.3259 --	     "jz 1f\n"
772.3260 --
772.3261 --	     "mov $0x00000000, %%eax\n"
772.3262 --	     "push %%ebx\n"
772.3263 --	     "cpuid\n"
772.3264 --	     "mov %%ebx, %%eax\n"
772.3265 --	     "pop %%ebx\n"
772.3266 --	     "mov %%eax, %1\n"
772.3267 --	     "mov %%edx, %2\n"
772.3268 --	     "mov %%ecx, %3\n"
772.3269 --	     "mov $0x00000001, %%eax\n"
772.3270 --	     "push %%ebx\n"
772.3271 --	     "cpuid\n"
772.3272 --	     "pop %%ebx\n"
772.3273 --	     "1:\n"
772.3274 --	     "mov %%edx, %0\n"
772.3275 --	     : "=r" (result), "=m" (vendor[0]), "=m" (vendor[4]), "=m" (vendor[8])
772.3276 --	     :: "%eax", "%ecx", "%edx");
772.3277 --
772.3278 --	features = 0;
772.3279 --	if (result) {
772.3280 --		/* result now contains the standard feature bits */
772.3281 --		if (result & (1 << 15))
772.3282 --			features |= CMOV;
772.3283 --		if (result & (1 << 23))
772.3284 --			features |= MMX;
772.3285 --		if (result & (1 << 25))
772.3286 --			features |= SSE;
772.3287 --		if (result & (1 << 26))
772.3288 --			features |= SSE2;
772.3289 --	}
772.3290 --	return features;
772.3291 --}
772.3292 --#else
772.3293 --static unsigned int detect_cpu_features(void) { return 0; }
772.3294 --#endif
772.3295 --
772.3296 - static bool have_sse2(void)
772.3297 - {
772.3298 - 	static int sse2_present = -1;
772.3299 - 
772.3300 - 	if (sse2_present == -1)
772.3301 --		sse2_present = detect_cpu_features() & SSE2;
772.3302 -+		sse2_present = sna_cpu_detect() & SSE2;
772.3303 - 
772.3304 - 	return sse2_present;
772.3305 - }
772.3306 - #endif
772.3307 - 
772.3308 --static inline __m128i
772.3309 -+static force_inline __m128i
772.3310 - xmm_create_mask_32(uint32_t mask)
772.3311 - {
772.3312 - 	return _mm_set_epi32(mask, mask, mask, mask);
772.3313 - }
772.3314 - 
772.3315 --static inline __m128i
772.3316 -+static force_inline __m128i
772.3317 -+xmm_load_128(const __m128i *src)
772.3318 -+{
772.3319 -+	return _mm_load_si128(src);
772.3320 -+}
772.3321 -+
772.3322 -+static force_inline __m128i
772.3323 - xmm_load_128u(const __m128i *src)
772.3324 - {
772.3325 - 	return _mm_loadu_si128(src);
772.3326 - }
772.3327 - 
772.3328 --static inline void
772.3329 -+static force_inline void
772.3330 - xmm_save_128(__m128i *dst, __m128i data)
772.3331 - {
772.3332 - 	_mm_store_si128(dst, data);
772.3333 - }
772.3334 -+
772.3335 -+static force_inline void
772.3336 -+xmm_save_128u(__m128i *dst, __m128i data)
772.3337 -+{
772.3338 -+	_mm_storeu_si128(dst, data);
772.3339 -+}
772.3340 -+
772.3341 -+static force_inline void
772.3342 -+to_sse128xN(uint8_t *dst, const uint8_t *src, int bytes)
772.3343 -+{
772.3344 -+	int i;
772.3345 -+
772.3346 -+	for (i = 0; i < bytes / 128; i++) {
772.3347 -+		__m128i xmm0, xmm1, xmm2, xmm3;
772.3348 -+		__m128i xmm4, xmm5, xmm6, xmm7;
772.3349 -+
772.3350 -+		xmm0 = xmm_load_128u((const __m128i*)src + 0);
772.3351 -+		xmm1 = xmm_load_128u((const __m128i*)src + 1);
772.3352 -+		xmm2 = xmm_load_128u((const __m128i*)src + 2);
772.3353 -+		xmm3 = xmm_load_128u((const __m128i*)src + 3);
772.3354 -+		xmm4 = xmm_load_128u((const __m128i*)src + 4);
772.3355 -+		xmm5 = xmm_load_128u((const __m128i*)src + 5);
772.3356 -+		xmm6 = xmm_load_128u((const __m128i*)src + 6);
772.3357 -+		xmm7 = xmm_load_128u((const __m128i*)src + 7);
772.3358 -+
772.3359 -+		xmm_save_128((__m128i*)dst + 0, xmm0);
772.3360 -+		xmm_save_128((__m128i*)dst + 1, xmm1);
772.3361 -+		xmm_save_128((__m128i*)dst + 2, xmm2);
772.3362 -+		xmm_save_128((__m128i*)dst + 3, xmm3);
772.3363 -+		xmm_save_128((__m128i*)dst + 4, xmm4);
772.3364 -+		xmm_save_128((__m128i*)dst + 5, xmm5);
772.3365 -+		xmm_save_128((__m128i*)dst + 6, xmm6);
772.3366 -+		xmm_save_128((__m128i*)dst + 7, xmm7);
772.3367 -+
772.3368 -+		dst += 128;
772.3369 -+		src += 128;
772.3370 -+	}
772.3371 -+}
772.3372 -+
772.3373 -+static force_inline void
772.3374 -+to_sse64(uint8_t *dst, const uint8_t *src)
772.3375 -+{
772.3376 -+	__m128i xmm1, xmm2, xmm3, xmm4;
772.3377 -+
772.3378 -+	xmm1 = xmm_load_128u((const __m128i*)src + 0);
772.3379 -+	xmm2 = xmm_load_128u((const __m128i*)src + 1);
772.3380 -+	xmm3 = xmm_load_128u((const __m128i*)src + 2);
772.3381 -+	xmm4 = xmm_load_128u((const __m128i*)src + 3);
772.3382 -+
772.3383 -+	xmm_save_128((__m128i*)dst + 0, xmm1);
772.3384 -+	xmm_save_128((__m128i*)dst + 1, xmm2);
772.3385 -+	xmm_save_128((__m128i*)dst + 2, xmm3);
772.3386 -+	xmm_save_128((__m128i*)dst + 3, xmm4);
772.3387 -+}
772.3388 -+
772.3389 -+static force_inline void
772.3390 -+to_sse32(uint8_t *dst, const uint8_t *src)
772.3391 -+{
772.3392 -+	__m128i xmm1, xmm2;
772.3393 -+
772.3394 -+	xmm1 = xmm_load_128u((const __m128i*)src + 0);
772.3395 -+	xmm2 = xmm_load_128u((const __m128i*)src + 1);
772.3396 -+
772.3397 -+	xmm_save_128((__m128i*)dst + 0, xmm1);
772.3398 -+	xmm_save_128((__m128i*)dst + 1, xmm2);
772.3399 -+}
772.3400 -+
772.3401 -+static force_inline void
772.3402 -+to_sse16(uint8_t *dst, const uint8_t *src)
772.3403 -+{
772.3404 -+	xmm_save_128((__m128i*)dst, xmm_load_128u((const __m128i*)src));
772.3405 -+}
772.3406 -+
772.3407 -+static void to_memcpy(uint8_t *dst, const uint8_t *src, unsigned len)
772.3408 -+{
772.3409 -+	assert(len);
772.3410 -+	if ((uintptr_t)dst & 15) {
772.3411 -+		if (len <= 16 - ((uintptr_t)dst & 15)) {
772.3412 -+			memcpy(dst, src, len);
772.3413 -+			return;
772.3414 -+		}
772.3415 -+
772.3416 -+		if ((uintptr_t)dst & 1) {
772.3417 -+			assert(len >= 1);
772.3418 -+			*dst++ = *src++;
772.3419 -+			len--;
772.3420 -+		}
772.3421 -+		if ((uintptr_t)dst & 2) {
772.3422 -+			assert(((uintptr_t)dst & 1) == 0);
772.3423 -+			assert(len >= 2);
772.3424 -+			*(uint16_t *)dst = *(const uint16_t *)src;
772.3425 -+			dst += 2;
772.3426 -+			src += 2;
772.3427 -+			len -= 2;
772.3428 -+		}
772.3429 -+		if ((uintptr_t)dst & 4) {
772.3430 -+			assert(((uintptr_t)dst & 3) == 0);
772.3431 -+			assert(len >= 4);
772.3432 -+			*(uint32_t *)dst = *(const uint32_t *)src;
772.3433 -+			dst += 4;
772.3434 -+			src += 4;
772.3435 -+			len -= 4;
772.3436 -+		}
772.3437 -+		if ((uintptr_t)dst & 8) {
772.3438 -+			assert(((uintptr_t)dst & 7) == 0);
772.3439 -+			assert(len >= 8);
772.3440 -+			*(uint64_t *)dst = *(const uint64_t *)src;
772.3441 -+			dst += 8;
772.3442 -+			src += 8;
772.3443 -+			len -= 8;
772.3444 -+		}
772.3445 -+	}
772.3446 -+
772.3447 -+	assert(((uintptr_t)dst & 15) == 0);
772.3448 -+	while (len >= 64) {
772.3449 -+		to_sse64(dst, src);
772.3450 -+		dst += 64;
772.3451 -+		src += 64;
772.3452 -+		len -= 64;
772.3453 -+	}
772.3454 -+	if (len == 0)
772.3455 -+		return;
772.3456 -+
772.3457 -+	if (len & 32) {
772.3458 -+		to_sse32(dst, src);
772.3459 -+		dst += 32;
772.3460 -+		src += 32;
772.3461 -+	}
772.3462 -+	if (len & 16) {
772.3463 -+		to_sse16(dst, src);
772.3464 -+		dst += 16;
772.3465 -+		src += 16;
772.3466 -+	}
772.3467 -+	if (len & 8) {
772.3468 -+		*(uint64_t *)dst = *(uint64_t *)src;
772.3469 -+		dst += 8;
772.3470 -+		src += 8;
772.3471 -+	}
772.3472 -+	if (len & 4) {
772.3473 -+		*(uint32_t *)dst = *(uint32_t *)src;
772.3474 -+		dst += 4;
772.3475 -+		src += 4;
772.3476 -+	}
772.3477 -+	memcpy(dst, src, len & 3);
772.3478 -+}
772.3479 -+
772.3480 -+static void
772.3481 -+memcpy_to_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
772.3482 -+				   int32_t src_stride, int32_t dst_stride,
772.3483 -+				   int16_t src_x, int16_t src_y,
772.3484 -+				   int16_t dst_x, int16_t dst_y,
772.3485 -+				   uint16_t width, uint16_t height)
772.3486 -+{
772.3487 -+	const unsigned tile_width = 512;
772.3488 -+	const unsigned tile_height = 8;
772.3489 -+	const unsigned tile_size = 4096;
772.3490 -+
772.3491 -+	const unsigned cpp = bpp / 8;
772.3492 -+	const unsigned tile_pixels = tile_width / cpp;
772.3493 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.3494 -+	const unsigned tile_mask = tile_pixels - 1;
772.3495 -+
772.3496 -+	unsigned offset_x, length_x;
772.3497 -+
772.3498 -+	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.3499 -+	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.3500 -+	assert(src != dst);
772.3501 -+
772.3502 -+	if (src_x | src_y)
772.3503 -+		src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
772.3504 -+	width *= cpp;
772.3505 -+	assert(src_stride >= width);
772.3506 -+
772.3507 -+	if (dst_x & tile_mask) {
772.3508 -+		offset_x = (dst_x & tile_mask) * cpp;
772.3509 -+		length_x = min(tile_width - offset_x, width);
772.3510 -+	} else
772.3511 -+		length_x = 0;
772.3512 -+	dst = (uint8_t *)dst + (dst_x >> tile_shift) * tile_size;
772.3513 -+
772.3514 -+	while (height--) {
772.3515 -+		unsigned w = width;
772.3516 -+		const uint8_t *src_row = src;
772.3517 -+		uint8_t *tile_row = dst;
772.3518 -+
772.3519 -+		src = (const uint8_t *)src + src_stride;
772.3520 -+
772.3521 -+		tile_row += dst_y / tile_height * dst_stride * tile_height;
772.3522 -+		tile_row += (dst_y & (tile_height-1)) * tile_width;
772.3523 -+		dst_y++;
772.3524 -+
772.3525 -+		if (length_x) {
772.3526 -+			to_memcpy(tile_row + offset_x, src_row, length_x);
772.3527 -+
772.3528 -+			tile_row += tile_size;
772.3529 -+			src_row = (const uint8_t *)src_row + length_x;
772.3530 -+			w -= length_x;
772.3531 -+		}
772.3532 -+		while (w >= tile_width) {
772.3533 -+			assert(((uintptr_t)tile_row & (tile_width - 1)) == 0);
772.3534 -+			to_sse128xN(assume_aligned(tile_row, tile_width),
772.3535 -+				    src_row, tile_width);
772.3536 -+			tile_row += tile_size;
772.3537 -+			src_row = (const uint8_t *)src_row + tile_width;
772.3538 -+			w -= tile_width;
772.3539 -+		}
772.3540 -+		if (w) {
772.3541 -+			assert(((uintptr_t)tile_row & (tile_width - 1)) == 0);
772.3542 -+			to_memcpy(assume_aligned(tile_row, tile_width),
772.3543 -+				  src_row, w);
772.3544 -+		}
772.3545 -+	}
772.3546 -+}
772.3547 -+
772.3548 -+static force_inline void
772.3549 -+from_sse128xNu(uint8_t *dst, const uint8_t *src, int bytes)
772.3550 -+{
772.3551 -+	int i;
772.3552 -+
772.3553 -+	assert(((uintptr_t)src & 15) == 0);
772.3554 -+
772.3555 -+	for (i = 0; i < bytes / 128; i++) {
772.3556 -+		__m128i xmm0, xmm1, xmm2, xmm3;
772.3557 -+		__m128i xmm4, xmm5, xmm6, xmm7;
772.3558 -+
772.3559 -+		xmm0 = xmm_load_128((const __m128i*)src + 0);
772.3560 -+		xmm1 = xmm_load_128((const __m128i*)src + 1);
772.3561 -+		xmm2 = xmm_load_128((const __m128i*)src + 2);
772.3562 -+		xmm3 = xmm_load_128((const __m128i*)src + 3);
772.3563 -+		xmm4 = xmm_load_128((const __m128i*)src + 4);
772.3564 -+		xmm5 = xmm_load_128((const __m128i*)src + 5);
772.3565 -+		xmm6 = xmm_load_128((const __m128i*)src + 6);
772.3566 -+		xmm7 = xmm_load_128((const __m128i*)src + 7);
772.3567 -+
772.3568 -+		xmm_save_128u((__m128i*)dst + 0, xmm0);
772.3569 -+		xmm_save_128u((__m128i*)dst + 1, xmm1);
772.3570 -+		xmm_save_128u((__m128i*)dst + 2, xmm2);
772.3571 -+		xmm_save_128u((__m128i*)dst + 3, xmm3);
772.3572 -+		xmm_save_128u((__m128i*)dst + 4, xmm4);
772.3573 -+		xmm_save_128u((__m128i*)dst + 5, xmm5);
772.3574 -+		xmm_save_128u((__m128i*)dst + 6, xmm6);
772.3575 -+		xmm_save_128u((__m128i*)dst + 7, xmm7);
772.3576 -+
772.3577 -+		dst += 128;
772.3578 -+		src += 128;
772.3579 -+	}
772.3580 -+}
772.3581 -+
772.3582 -+static force_inline void
772.3583 -+from_sse128xNa(uint8_t *dst, const uint8_t *src, int bytes)
772.3584 -+{
772.3585 -+	int i;
772.3586 -+
772.3587 -+	assert(((uintptr_t)dst & 15) == 0);
772.3588 -+	assert(((uintptr_t)src & 15) == 0);
772.3589 -+
772.3590 -+	for (i = 0; i < bytes / 128; i++) {
772.3591 -+		__m128i xmm0, xmm1, xmm2, xmm3;
772.3592 -+		__m128i xmm4, xmm5, xmm6, xmm7;
772.3593 -+
772.3594 -+		xmm0 = xmm_load_128((const __m128i*)src + 0);
772.3595 -+		xmm1 = xmm_load_128((const __m128i*)src + 1);
772.3596 -+		xmm2 = xmm_load_128((const __m128i*)src + 2);
772.3597 -+		xmm3 = xmm_load_128((const __m128i*)src + 3);
772.3598 -+		xmm4 = xmm_load_128((const __m128i*)src + 4);
772.3599 -+		xmm5 = xmm_load_128((const __m128i*)src + 5);
772.3600 -+		xmm6 = xmm_load_128((const __m128i*)src + 6);
772.3601 -+		xmm7 = xmm_load_128((const __m128i*)src + 7);
772.3602 -+
772.3603 -+		xmm_save_128((__m128i*)dst + 0, xmm0);
772.3604 -+		xmm_save_128((__m128i*)dst + 1, xmm1);
772.3605 -+		xmm_save_128((__m128i*)dst + 2, xmm2);
772.3606 -+		xmm_save_128((__m128i*)dst + 3, xmm3);
772.3607 -+		xmm_save_128((__m128i*)dst + 4, xmm4);
772.3608 -+		xmm_save_128((__m128i*)dst + 5, xmm5);
772.3609 -+		xmm_save_128((__m128i*)dst + 6, xmm6);
772.3610 -+		xmm_save_128((__m128i*)dst + 7, xmm7);
772.3611 -+
772.3612 -+		dst += 128;
772.3613 -+		src += 128;
772.3614 -+	}
772.3615 -+}
772.3616 -+
772.3617 -+static force_inline void
772.3618 -+from_sse64u(uint8_t *dst, const uint8_t *src)
772.3619 -+{
772.3620 -+	__m128i xmm1, xmm2, xmm3, xmm4;
772.3621 -+
772.3622 -+	assert(((uintptr_t)src & 15) == 0);
772.3623 -+
772.3624 -+	xmm1 = xmm_load_128((const __m128i*)src + 0);
772.3625 -+	xmm2 = xmm_load_128((const __m128i*)src + 1);
772.3626 -+	xmm3 = xmm_load_128((const __m128i*)src + 2);
772.3627 -+	xmm4 = xmm_load_128((const __m128i*)src + 3);
772.3628 -+
772.3629 -+	xmm_save_128u((__m128i*)dst + 0, xmm1);
772.3630 -+	xmm_save_128u((__m128i*)dst + 1, xmm2);
772.3631 -+	xmm_save_128u((__m128i*)dst + 2, xmm3);
772.3632 -+	xmm_save_128u((__m128i*)dst + 3, xmm4);
772.3633 -+}
772.3634 -+
772.3635 -+static force_inline void
772.3636 -+from_sse64a(uint8_t *dst, const uint8_t *src)
772.3637 -+{
772.3638 -+	__m128i xmm1, xmm2, xmm3, xmm4;
772.3639 -+
772.3640 -+	assert(((uintptr_t)dst & 15) == 0);
772.3641 -+	assert(((uintptr_t)src & 15) == 0);
772.3642 -+
772.3643 -+	xmm1 = xmm_load_128((const __m128i*)src + 0);
772.3644 -+	xmm2 = xmm_load_128((const __m128i*)src + 1);
772.3645 -+	xmm3 = xmm_load_128((const __m128i*)src + 2);
772.3646 -+	xmm4 = xmm_load_128((const __m128i*)src + 3);
772.3647 -+
772.3648 -+	xmm_save_128((__m128i*)dst + 0, xmm1);
772.3649 -+	xmm_save_128((__m128i*)dst + 1, xmm2);
772.3650 -+	xmm_save_128((__m128i*)dst + 2, xmm3);
772.3651 -+	xmm_save_128((__m128i*)dst + 3, xmm4);
772.3652 -+}
772.3653 -+
772.3654 -+static force_inline void
772.3655 -+from_sse32u(uint8_t *dst, const uint8_t *src)
772.3656 -+{
772.3657 -+	__m128i xmm1, xmm2;
772.3658 -+
772.3659 -+	xmm1 = xmm_load_128((const __m128i*)src + 0);
772.3660 -+	xmm2 = xmm_load_128((const __m128i*)src + 1);
772.3661 -+
772.3662 -+	xmm_save_128u((__m128i*)dst + 0, xmm1);
772.3663 -+	xmm_save_128u((__m128i*)dst + 1, xmm2);
772.3664 -+}
772.3665 -+
772.3666 -+static force_inline void
772.3667 -+from_sse32a(uint8_t *dst, const uint8_t *src)
772.3668 -+{
772.3669 -+	__m128i xmm1, xmm2;
772.3670 -+
772.3671 -+	assert(((uintptr_t)dst & 15) == 0);
772.3672 -+	assert(((uintptr_t)src & 15) == 0);
772.3673 -+
772.3674 -+	xmm1 = xmm_load_128((const __m128i*)src + 0);
772.3675 -+	xmm2 = xmm_load_128((const __m128i*)src + 1);
772.3676 -+
772.3677 -+	xmm_save_128((__m128i*)dst + 0, xmm1);
772.3678 -+	xmm_save_128((__m128i*)dst + 1, xmm2);
772.3679 -+}
772.3680 -+
772.3681 -+static force_inline void
772.3682 -+from_sse16u(uint8_t *dst, const uint8_t *src)
772.3683 -+{
772.3684 -+	assert(((uintptr_t)src & 15) == 0);
772.3685 -+
772.3686 -+	xmm_save_128u((__m128i*)dst, xmm_load_128((const __m128i*)src));
772.3687 -+}
772.3688 -+
772.3689 -+static force_inline void
772.3690 -+from_sse16a(uint8_t *dst, const uint8_t *src)
772.3691 -+{
772.3692 -+	assert(((uintptr_t)dst & 15) == 0);
772.3693 -+	assert(((uintptr_t)src & 15) == 0);
772.3694 -+
772.3695 -+	xmm_save_128((__m128i*)dst, xmm_load_128((const __m128i*)src));
772.3696 -+}
772.3697 -+
772.3698 -+static void
772.3699 -+memcpy_from_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
772.3700 -+				     int32_t src_stride, int32_t dst_stride,
772.3701 -+				     int16_t src_x, int16_t src_y,
772.3702 -+				     int16_t dst_x, int16_t dst_y,
772.3703 -+				     uint16_t width, uint16_t height)
772.3704 -+{
772.3705 -+	const unsigned tile_width = 512;
772.3706 -+	const unsigned tile_height = 8;
772.3707 -+	const unsigned tile_size = 4096;
772.3708 -+
772.3709 -+	const unsigned cpp = bpp / 8;
772.3710 -+	const unsigned tile_pixels = tile_width / cpp;
772.3711 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.3712 -+	const unsigned tile_mask = tile_pixels - 1;
772.3713 -+
772.3714 -+	unsigned length_x, offset_x;
772.3715 -+
772.3716 -+	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.3717 -+	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.3718 -+	assert(src != dst);
772.3719 -+
772.3720 -+	if (dst_x | dst_y)
772.3721 -+		dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
772.3722 -+	width *= cpp;
772.3723 -+	assert(dst_stride >= width);
772.3724 -+	if (src_x & tile_mask) {
772.3725 -+		offset_x = (src_x & tile_mask) * cpp;
772.3726 -+		length_x = min(tile_width - offset_x, width);
772.3727 -+		dst_stride -= width;
772.3728 -+		dst_stride += (width - length_x) & 15;
772.3729 -+	} else {
772.3730 -+		offset_x = 0;
772.3731 -+		dst_stride -= width & ~15;
772.3732 -+	}
772.3733 -+	assert(dst_stride >= 0);
772.3734 -+	src = (const uint8_t *)src + (src_x >> tile_shift) * tile_size;
772.3735 -+
772.3736 -+	while (height--) {
772.3737 -+		unsigned w = width;
772.3738 -+		const uint8_t *tile_row = src;
772.3739 -+
772.3740 -+		tile_row += src_y / tile_height * src_stride * tile_height;
772.3741 -+		tile_row += (src_y & (tile_height-1)) * tile_width;
772.3742 -+		src_y++;
772.3743 -+
772.3744 -+		if (offset_x) {
772.3745 -+			memcpy(dst, tile_row + offset_x, length_x);
772.3746 -+			tile_row += tile_size;
772.3747 -+			dst = (uint8_t *)dst + length_x;
772.3748 -+			w -= length_x;
772.3749 -+		}
772.3750 -+
772.3751 -+		if ((uintptr_t)dst & 15) {
772.3752 -+			while (w >= tile_width) {
772.3753 -+				from_sse128xNu(dst,
772.3754 -+					       assume_aligned(tile_row, tile_width),
772.3755 -+					       tile_width);
772.3756 -+				tile_row += tile_size;
772.3757 -+				dst = (uint8_t *)dst + tile_width;
772.3758 -+				w -= tile_width;
772.3759 -+			}
772.3760 -+			while (w >= 64) {
772.3761 -+				from_sse64u(dst, tile_row);
772.3762 -+				tile_row += 64;
772.3763 -+				dst = (uint8_t *)dst + 64;
772.3764 -+				w -= 64;
772.3765 -+			}
772.3766 -+			if (w & 32) {
772.3767 -+				from_sse32u(dst, tile_row);
772.3768 -+				tile_row += 32;
772.3769 -+				dst = (uint8_t *)dst + 32;
772.3770 -+			}
772.3771 -+			if (w & 16) {
772.3772 -+				from_sse16u(dst, tile_row);
772.3773 -+				tile_row += 16;
772.3774 -+				dst = (uint8_t *)dst + 16;
772.3775 -+			}
772.3776 -+			memcpy(dst, assume_aligned(tile_row, 16), w & 15);
772.3777 -+		} else {
772.3778 -+			while (w >= tile_width) {
772.3779 -+				from_sse128xNa(assume_aligned(dst, 16),
772.3780 -+					       assume_aligned(tile_row, tile_width),
772.3781 -+					       tile_width);
772.3782 -+				tile_row += tile_size;
772.3783 -+				dst = (uint8_t *)dst + tile_width;
772.3784 -+				w -= tile_width;
772.3785 -+			}
772.3786 -+			while (w >= 64) {
772.3787 -+				from_sse64a(dst, tile_row);
772.3788 -+				tile_row += 64;
772.3789 -+				dst = (uint8_t *)dst + 64;
772.3790 -+				w -= 64;
772.3791 -+			}
772.3792 -+			if (w & 32) {
772.3793 -+				from_sse32a(dst, tile_row);
772.3794 -+				tile_row += 32;
772.3795 -+				dst = (uint8_t *)dst + 32;
772.3796 -+			}
772.3797 -+			if (w & 16) {
772.3798 -+				from_sse16a(dst, tile_row);
772.3799 -+				tile_row += 16;
772.3800 -+				dst = (uint8_t *)dst + 16;
772.3801 -+			}
772.3802 -+			memcpy(assume_aligned(dst, 16),
772.3803 -+			       assume_aligned(tile_row, 16),
772.3804 -+			       w & 15);
772.3805 -+		}
772.3806 -+		dst = (uint8_t *)dst + dst_stride;
772.3807 -+	}
772.3808 -+}
772.3809 -+
772.3810 -+static void
772.3811 -+memcpy_between_tiled_x__swizzle_0__sse2(const void *src, void *dst, int bpp,
772.3812 -+					int32_t src_stride, int32_t dst_stride,
772.3813 -+					int16_t src_x, int16_t src_y,
772.3814 -+					int16_t dst_x, int16_t dst_y,
772.3815 -+					uint16_t width, uint16_t height)
772.3816 -+{
772.3817 -+	const unsigned tile_width = 512;
772.3818 -+	const unsigned tile_height = 8;
772.3819 -+	const unsigned tile_size = 4096;
772.3820 -+
772.3821 -+	const unsigned cpp = bpp / 8;
772.3822 -+	const unsigned tile_pixels = tile_width / cpp;
772.3823 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.3824 -+	const unsigned tile_mask = tile_pixels - 1;
772.3825 -+
772.3826 -+	unsigned ox, lx;
772.3827 -+
772.3828 -+	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.3829 -+	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.3830 -+	assert(src != dst);
772.3831 -+
772.3832 -+	width *= cpp;
772.3833 -+	dst_stride *= tile_height;
772.3834 -+	src_stride *= tile_height;
772.3835 -+
772.3836 -+	assert((dst_x & tile_mask) == (src_x & tile_mask));
772.3837 -+	if (dst_x & tile_mask) {
772.3838 -+		ox = (dst_x & tile_mask) * cpp;
772.3839 -+		lx = min(tile_width - ox, width);
772.3840 -+		assert(lx != 0);
772.3841 -+	} else
772.3842 -+		lx = 0;
772.3843 -+
772.3844 -+	if (dst_x)
772.3845 -+		dst = (uint8_t *)dst + (dst_x >> tile_shift) * tile_size;
772.3846 -+	if (src_x)
772.3847 -+		src = (const uint8_t *)src + (src_x >> tile_shift) * tile_size;
772.3848 -+
772.3849 -+	while (height--) {
772.3850 -+		const uint8_t *src_row;
772.3851 -+		uint8_t *dst_row;
772.3852 -+		unsigned w = width;
772.3853 -+
772.3854 -+		dst_row = dst;
772.3855 -+		dst_row += dst_y / tile_height * dst_stride;
772.3856 -+		dst_row += (dst_y & (tile_height-1)) * tile_width;
772.3857 -+		dst_y++;
772.3858 -+
772.3859 -+		src_row = src;
772.3860 -+		src_row += src_y / tile_height * src_stride;
772.3861 -+		src_row += (src_y & (tile_height-1)) * tile_width;
772.3862 -+		src_y++;
772.3863 -+
772.3864 -+		if (lx) {
772.3865 -+			to_memcpy(dst_row + ox, src_row + ox, lx);
772.3866 -+			dst_row += tile_size;
772.3867 -+			src_row += tile_size;
772.3868 -+			w -= lx;
772.3869 -+		}
772.3870 -+		while (w >= tile_width) {
772.3871 -+			assert(((uintptr_t)dst_row & (tile_width - 1)) == 0);
772.3872 -+			assert(((uintptr_t)src_row & (tile_width - 1)) == 0);
772.3873 -+			to_sse128xN(assume_aligned(dst_row, tile_width),
772.3874 -+				    assume_aligned(src_row, tile_width),
772.3875 -+				    tile_width);
772.3876 -+			dst_row += tile_size;
772.3877 -+			src_row += tile_size;
772.3878 -+			w -= tile_width;
772.3879 -+		}
772.3880 -+		if (w) {
772.3881 -+			assert(((uintptr_t)dst_row & (tile_width - 1)) == 0);
772.3882 -+			assert(((uintptr_t)src_row & (tile_width - 1)) == 0);
772.3883 -+			to_memcpy(assume_aligned(dst_row, tile_width),
772.3884 -+				  assume_aligned(src_row, tile_width),
772.3885 -+				  w);
772.3886 -+		}
772.3887 -+	}
772.3888 -+}
772.3889 -+
772.3890 -+#pragma GCC push_options
772.3891 - #endif
772.3892 - 
772.3893 - fast void
772.3894 -@@ -257,7 +753,8 @@ memcpy_to_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
772.3895 - 			if (dst_x & tile_mask) {
772.3896 - 				const unsigned x = (dst_x & tile_mask) * cpp;
772.3897 - 				const unsigned len = min(tile_width - x, w);
772.3898 --				memcpy(tile_row + x, src, len);
772.3899 -+				memcpy(assume_misaligned(tile_row + x, tile_width, x),
772.3900 -+				       src, len);
772.3901 - 
772.3902 - 				tile_row += tile_size;
772.3903 - 				src = (const uint8_t *)src + len;
772.3904 -@@ -265,13 +762,13 @@ memcpy_to_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
772.3905 - 			}
772.3906 - 		}
772.3907 - 		while (w >= tile_width) {
772.3908 --			memcpy(tile_row, src, tile_width);
772.3909 --
772.3910 -+			memcpy(assume_aligned(tile_row, tile_width),
772.3911 -+			       src, tile_width);
772.3912 - 			tile_row += tile_size;
772.3913 - 			src = (const uint8_t *)src + tile_width;
772.3914 - 			w -= tile_width;
772.3915 - 		}
772.3916 --		memcpy(tile_row, src, w);
772.3917 -+		memcpy(assume_aligned(tile_row, tile_width), src, w);
772.3918 - 		src = (const uint8_t *)src + src_stride + w;
772.3919 - 		dst_y++;
772.3920 - 	}
772.3921 -@@ -313,7 +810,7 @@ memcpy_from_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
772.3922 - 			if (src_x & tile_mask) {
772.3923 - 				const unsigned x = (src_x & tile_mask) * cpp;
772.3924 - 				const unsigned len = min(tile_width - x, w);
772.3925 --				memcpy(dst, tile_row + x, len);
772.3926 -+				memcpy(dst, assume_misaligned(tile_row + x, tile_width, x), len);
772.3927 - 
772.3928 - 				tile_row += tile_size;
772.3929 - 				dst = (uint8_t *)dst + len;
772.3930 -@@ -321,440 +818,371 @@ memcpy_from_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
772.3931 - 			}
772.3932 - 		}
772.3933 - 		while (w >= tile_width) {
772.3934 --			memcpy(dst, tile_row, tile_width);
772.3935 -+			memcpy(dst,
772.3936 -+			       assume_aligned(tile_row, tile_width),
772.3937 -+			       tile_width);
772.3938 - 
772.3939 - 			tile_row += tile_size;
772.3940 - 			dst = (uint8_t *)dst + tile_width;
772.3941 - 			w -= tile_width;
772.3942 - 		}
772.3943 --		memcpy(dst, tile_row, w);
772.3944 -+		memcpy(dst, assume_aligned(tile_row, tile_width), w);
772.3945 - 		dst = (uint8_t *)dst + dst_stride + w;
772.3946 - 		src_y++;
772.3947 - 	}
772.3948 - }
772.3949 - 
772.3950 --fast_memcpy static void
772.3951 --memcpy_to_tiled_x__swizzle_9(const void *src, void *dst, int bpp,
772.3952 --			     int32_t src_stride, int32_t dst_stride,
772.3953 --			     int16_t src_x, int16_t src_y,
772.3954 --			     int16_t dst_x, int16_t dst_y,
772.3955 --			     uint16_t width, uint16_t height)
772.3956 -+static fast_memcpy void
772.3957 -+memcpy_between_tiled_x__swizzle_0(const void *src, void *dst, int bpp,
772.3958 -+				  int32_t src_stride, int32_t dst_stride,
772.3959 -+				  int16_t src_x, int16_t src_y,
772.3960 -+				  int16_t dst_x, int16_t dst_y,
772.3961 -+				  uint16_t width, uint16_t height)
772.3962 - {
772.3963 - 	const unsigned tile_width = 512;
772.3964 - 	const unsigned tile_height = 8;
772.3965 - 	const unsigned tile_size = 4096;
772.3966 - 
772.3967 - 	const unsigned cpp = bpp / 8;
772.3968 --	const unsigned stride_tiles = dst_stride / tile_width;
772.3969 --	const unsigned swizzle_pixels = 64 / cpp;
772.3970 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.3971 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.3972 --
772.3973 --	unsigned x, y;
772.3974 -+	const unsigned tile_pixels = tile_width / cpp;
772.3975 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.3976 -+	const unsigned tile_mask = tile_pixels - 1;
772.3977 - 
772.3978 - 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.3979 - 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.3980 -+	assert(src != dst);
772.3981 -+	assert((dst_x & tile_mask) == (src_x & tile_mask));
772.3982 - 
772.3983 --	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
772.3984 --
772.3985 --	for (y = 0; y < height; ++y) {
772.3986 --		const uint32_t dy = y + dst_y;
772.3987 --		const uint32_t tile_row =
772.3988 --			(dy / tile_height * stride_tiles * tile_size +
772.3989 --			 (dy & (tile_height-1)) * tile_width);
772.3990 --		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
772.3991 --		uint32_t dx = dst_x, offset;
772.3992 --
772.3993 --		x = width * cpp;
772.3994 --		if (dx & (swizzle_pixels - 1)) {
772.3995 --			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
772.3996 --			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
772.3997 --			offset = tile_row +
772.3998 --				(dx >> tile_pixels) * tile_size +
772.3999 --				(dx & tile_mask) * cpp;
772.4000 --			offset ^= (offset >> 3) & 64;
772.4001 --
772.4002 --			memcpy((char *)dst + offset, src_row, length * cpp);
772.4003 --
772.4004 --			src_row += length * cpp;
772.4005 --			x -= length * cpp;
772.4006 --			dx += length;
772.4007 --		}
772.4008 --		while (x >= 64) {
772.4009 --			offset = tile_row +
772.4010 --				(dx >> tile_pixels) * tile_size +
772.4011 --				(dx & tile_mask) * cpp;
772.4012 --			offset ^= (offset >> 3) & 64;
772.4013 --
772.4014 --			memcpy((char *)dst + offset, src_row, 64);
772.4015 --
772.4016 --			src_row += 64;
772.4017 --			x -= 64;
772.4018 --			dx += swizzle_pixels;
772.4019 --		}
772.4020 --		if (x) {
772.4021 --			offset = tile_row +
772.4022 --				(dx >> tile_pixels) * tile_size +
772.4023 --				(dx & tile_mask) * cpp;
772.4024 --			offset ^= (offset >> 3) & 64;
772.4025 --			memcpy((char *)dst + offset, src_row, x);
772.4026 --		}
772.4027 --	}
772.4028 --}
772.4029 -+	while (height--) {
772.4030 -+		unsigned w = width * cpp;
772.4031 -+		uint8_t *dst_row = dst;
772.4032 -+		const uint8_t *src_row = src;
772.4033 - 
772.4034 --fast_memcpy static void
772.4035 --memcpy_from_tiled_x__swizzle_9(const void *src, void *dst, int bpp,
772.4036 --			       int32_t src_stride, int32_t dst_stride,
772.4037 --			       int16_t src_x, int16_t src_y,
772.4038 --			       int16_t dst_x, int16_t dst_y,
772.4039 --			       uint16_t width, uint16_t height)
772.4040 --{
772.4041 --	const unsigned tile_width = 512;
772.4042 --	const unsigned tile_height = 8;
772.4043 --	const unsigned tile_size = 4096;
772.4044 -+		dst_row += dst_y / tile_height * dst_stride * tile_height;
772.4045 -+		dst_row += (dst_y & (tile_height-1)) * tile_width;
772.4046 -+		if (dst_x)
772.4047 -+			dst_row += (dst_x >> tile_shift) * tile_size;
772.4048 -+		dst_y++;
772.4049 - 
772.4050 --	const unsigned cpp = bpp / 8;
772.4051 --	const unsigned stride_tiles = src_stride / tile_width;
772.4052 --	const unsigned swizzle_pixels = 64 / cpp;
772.4053 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.4054 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.4055 -+		src_row += src_y / tile_height * src_stride * tile_height;
772.4056 -+		src_row += (src_y & (tile_height-1)) * tile_width;
772.4057 -+		if (src_x)
772.4058 -+			src_row += (src_x >> tile_shift) * tile_size;
772.4059 -+		src_y++;
772.4060 - 
772.4061 --	unsigned x, y;
772.4062 -+		if (dst_x & tile_mask) {
772.4063 -+			const unsigned x = (dst_x & tile_mask) * cpp;
772.4064 -+			const unsigned len = min(tile_width - x, w);
772.4065 - 
772.4066 --	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.4067 --	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.4068 -+			memcpy(assume_misaligned(dst_row + x, tile_width, x),
772.4069 -+			       assume_misaligned(src_row + x, tile_width, x),
772.4070 -+			       len);
772.4071 - 
772.4072 --	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
772.4073 --
772.4074 --	for (y = 0; y < height; ++y) {
772.4075 --		const uint32_t sy = y + src_y;
772.4076 --		const uint32_t tile_row =
772.4077 --			(sy / tile_height * stride_tiles * tile_size +
772.4078 --			 (sy & (tile_height-1)) * tile_width);
772.4079 --		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
772.4080 --		uint32_t sx = src_x, offset;
772.4081 --
772.4082 --		x = width * cpp;
772.4083 --		if (sx & (swizzle_pixels - 1)) {
772.4084 --			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
772.4085 --			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
772.4086 --			offset = tile_row +
772.4087 --				(sx >> tile_pixels) * tile_size +
772.4088 --				(sx & tile_mask) * cpp;
772.4089 --			offset ^= (offset >> 3) & 64;
772.4090 --
772.4091 --			memcpy(dst_row, (const char *)src + offset, length * cpp);
772.4092 --
772.4093 --			dst_row += length * cpp;
772.4094 --			x -= length * cpp;
772.4095 --			sx += length;
772.4096 -+			dst_row += tile_size;
772.4097 -+			src_row += tile_size;
772.4098 -+			w -= len;
772.4099 - 		}
772.4100 --		while (x >= 64) {
772.4101 --			offset = tile_row +
772.4102 --				(sx >> tile_pixels) * tile_size +
772.4103 --				(sx & tile_mask) * cpp;
772.4104 --			offset ^= (offset >> 3) & 64;
772.4105 - 
772.4106 --			memcpy(dst_row, (const char *)src + offset, 64);
772.4107 --
772.4108 --			dst_row += 64;
772.4109 --			x -= 64;
772.4110 --			sx += swizzle_pixels;
772.4111 --		}
772.4112 --		if (x) {
772.4113 --			offset = tile_row +
772.4114 --				(sx >> tile_pixels) * tile_size +
772.4115 --				(sx & tile_mask) * cpp;
772.4116 --			offset ^= (offset >> 3) & 64;
772.4117 --			memcpy(dst_row, (const char *)src + offset, x);
772.4118 -+		while (w >= tile_width) {
772.4119 -+			memcpy(assume_aligned(dst_row, tile_width),
772.4120 -+			       assume_aligned(src_row, tile_width),
772.4121 -+			       tile_width);
772.4122 -+			dst_row += tile_size;
772.4123 -+			src_row += tile_size;
772.4124 -+			w -= tile_width;
772.4125 - 		}
772.4126 -+		memcpy(assume_aligned(dst_row, tile_width),
772.4127 -+		       assume_aligned(src_row, tile_width),
772.4128 -+		       w);
772.4129 - 	}
772.4130 - }
772.4131 - 
772.4132 --fast_memcpy static void
772.4133 --memcpy_to_tiled_x__swizzle_9_10(const void *src, void *dst, int bpp,
772.4134 --				int32_t src_stride, int32_t dst_stride,
772.4135 --				int16_t src_x, int16_t src_y,
772.4136 --				int16_t dst_x, int16_t dst_y,
772.4137 --				uint16_t width, uint16_t height)
772.4138 --{
772.4139 --	const unsigned tile_width = 512;
772.4140 --	const unsigned tile_height = 8;
772.4141 --	const unsigned tile_size = 4096;
772.4142 --
772.4143 --	const unsigned cpp = bpp / 8;
772.4144 --	const unsigned stride_tiles = dst_stride / tile_width;
772.4145 --	const unsigned swizzle_pixels = 64 / cpp;
772.4146 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.4147 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.4148 -+#define memcpy_to_tiled_x(swizzle) \
772.4149 -+fast_memcpy static void \
772.4150 -+memcpy_to_tiled_x__##swizzle (const void *src, void *dst, int bpp, \
772.4151 -+			      int32_t src_stride, int32_t dst_stride, \
772.4152 -+			      int16_t src_x, int16_t src_y, \
772.4153 -+			      int16_t dst_x, int16_t dst_y, \
772.4154 -+			      uint16_t width, uint16_t height) \
772.4155 -+{ \
772.4156 -+	const unsigned tile_width = 512; \
772.4157 -+	const unsigned tile_height = 8; \
772.4158 -+	const unsigned tile_size = 4096; \
772.4159 -+	const unsigned cpp = bpp / 8; \
772.4160 -+	const unsigned stride_tiles = dst_stride / tile_width; \
772.4161 -+	const unsigned swizzle_pixels = 64 / cpp; \
772.4162 -+	const unsigned tile_pixels = ffs(tile_width / cpp) - 1; \
772.4163 -+	const unsigned tile_mask = (1 << tile_pixels) - 1; \
772.4164 -+	unsigned x, y; \
772.4165 -+	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n", \
772.4166 -+	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride)); \
772.4167 -+	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp; \
772.4168 -+	for (y = 0; y < height; ++y) { \
772.4169 -+		const uint32_t dy = y + dst_y; \
772.4170 -+		const uint32_t tile_row = \
772.4171 -+			(dy / tile_height * stride_tiles * tile_size + \
772.4172 -+			 (dy & (tile_height-1)) * tile_width); \
772.4173 -+		const uint8_t *src_row = (const uint8_t *)src + src_stride * y; \
772.4174 -+		uint32_t dx = dst_x; \
772.4175 -+		x = width * cpp; \
772.4176 -+		if (dx & (swizzle_pixels - 1)) { \
772.4177 -+			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels); \
772.4178 -+			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx; \
772.4179 -+			uint32_t offset = \
772.4180 -+				tile_row + \
772.4181 -+				(dx >> tile_pixels) * tile_size + \
772.4182 -+				(dx & tile_mask) * cpp; \
772.4183 -+			memcpy((char *)dst + swizzle(offset), src_row, length * cpp); \
772.4184 -+			src_row += length * cpp; \
772.4185 -+			x -= length * cpp; \
772.4186 -+			dx += length; \
772.4187 -+		} \
772.4188 -+		while (x >= 64) { \
772.4189 -+			uint32_t offset = \
772.4190 -+				tile_row + \
772.4191 -+				(dx >> tile_pixels) * tile_size + \
772.4192 -+				(dx & tile_mask) * cpp; \
772.4193 -+			memcpy(assume_aligned((char *)dst+swizzle(offset),64), \
772.4194 -+			       src_row, 64); \
772.4195 -+			src_row += 64; \
772.4196 -+			x -= 64; \
772.4197 -+			dx += swizzle_pixels; \
772.4198 -+		} \
772.4199 -+		if (x) { \
772.4200 -+			uint32_t offset = \
772.4201 -+				tile_row + \
772.4202 -+				(dx >> tile_pixels) * tile_size + \
772.4203 -+				(dx & tile_mask) * cpp; \
772.4204 -+			memcpy(assume_aligned((char *)dst + swizzle(offset), 64), src_row, x); \
772.4205 -+		} \
772.4206 -+	} \
772.4207 -+}
772.4208 - 
772.4209 --	unsigned x, y;
772.4210 -+#define memcpy_from_tiled_x(swizzle) \
772.4211 -+fast_memcpy static void \
772.4212 -+memcpy_from_tiled_x__##swizzle (const void *src, void *dst, int bpp, \
772.4213 -+				int32_t src_stride, int32_t dst_stride, \
772.4214 -+				int16_t src_x, int16_t src_y, \
772.4215 -+				int16_t dst_x, int16_t dst_y, \
772.4216 -+				uint16_t width, uint16_t height) \
772.4217 -+{ \
772.4218 -+	const unsigned tile_width = 512; \
772.4219 -+	const unsigned tile_height = 8; \
772.4220 -+	const unsigned tile_size = 4096; \
772.4221 -+	const unsigned cpp = bpp / 8; \
772.4222 -+	const unsigned stride_tiles = src_stride / tile_width; \
772.4223 -+	const unsigned swizzle_pixels = 64 / cpp; \
772.4224 -+	const unsigned tile_pixels = ffs(tile_width / cpp) - 1; \
772.4225 -+	const unsigned tile_mask = (1 << tile_pixels) - 1; \
772.4226 -+	unsigned x, y; \
772.4227 -+	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n", \
772.4228 -+	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride)); \
772.4229 -+	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp; \
772.4230 -+	for (y = 0; y < height; ++y) { \
772.4231 -+		const uint32_t sy = y + src_y; \
772.4232 -+		const uint32_t tile_row = \
772.4233 -+			(sy / tile_height * stride_tiles * tile_size + \
772.4234 -+			 (sy & (tile_height-1)) * tile_width); \
772.4235 -+		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y; \
772.4236 -+		uint32_t sx = src_x; \
772.4237 -+		x = width * cpp; \
772.4238 -+		if (sx & (swizzle_pixels - 1)) { \
772.4239 -+			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels); \
772.4240 -+			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx; \
772.4241 -+			uint32_t offset = \
772.4242 -+				tile_row + \
772.4243 -+				(sx >> tile_pixels) * tile_size + \
772.4244 -+				(sx & tile_mask) * cpp; \
772.4245 -+			memcpy(dst_row, (const char *)src + swizzle(offset), length * cpp); \
772.4246 -+			dst_row += length * cpp; \
772.4247 -+			x -= length * cpp; \
772.4248 -+			sx += length; \
772.4249 -+		} \
772.4250 -+		while (x >= 64) { \
772.4251 -+			uint32_t offset = \
772.4252 -+				tile_row + \
772.4253 -+				(sx >> tile_pixels) * tile_size + \
772.4254 -+				(sx & tile_mask) * cpp; \
772.4255 -+			memcpy(dst_row, assume_aligned((const char *)src + swizzle(offset), 64), 64); \
772.4256 -+			dst_row += 64; \
772.4257 -+			x -= 64; \
772.4258 -+			sx += swizzle_pixels; \
772.4259 -+		} \
772.4260 -+		if (x) { \
772.4261 -+			uint32_t offset = \
772.4262 -+				tile_row + \
772.4263 -+				(sx >> tile_pixels) * tile_size + \
772.4264 -+				(sx & tile_mask) * cpp; \
772.4265 -+			memcpy(dst_row, assume_aligned((const char *)src + swizzle(offset), 64), x); \
772.4266 -+		} \
772.4267 -+	} \
772.4268 -+}
772.4269 - 
772.4270 --	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.4271 --	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.4272 -+#define swizzle_9(X) ((X) ^ (((X) >> 3) & 64))
772.4273 -+memcpy_to_tiled_x(swizzle_9)
772.4274 -+memcpy_from_tiled_x(swizzle_9)
772.4275 -+#undef swizzle_9
772.4276 - 
772.4277 --	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
772.4278 --
772.4279 --	for (y = 0; y < height; ++y) {
772.4280 --		const uint32_t dy = y + dst_y;
772.4281 --		const uint32_t tile_row =
772.4282 --			(dy / tile_height * stride_tiles * tile_size +
772.4283 --			 (dy & (tile_height-1)) * tile_width);
772.4284 --		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
772.4285 --		uint32_t dx = dst_x, offset;
772.4286 --
772.4287 --		x = width * cpp;
772.4288 --		if (dx & (swizzle_pixels - 1)) {
772.4289 --			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
772.4290 --			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
772.4291 --			offset = tile_row +
772.4292 --				(dx >> tile_pixels) * tile_size +
772.4293 --				(dx & tile_mask) * cpp;
772.4294 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4295 --
772.4296 --			memcpy((char *)dst + offset, src_row, length * cpp);
772.4297 --
772.4298 --			src_row += length * cpp;
772.4299 --			x -= length * cpp;
772.4300 --			dx += length;
772.4301 --		}
772.4302 --		while (x >= 64) {
772.4303 --			offset = tile_row +
772.4304 --				(dx >> tile_pixels) * tile_size +
772.4305 --				(dx & tile_mask) * cpp;
772.4306 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4307 -+#define swizzle_9_10(X) ((X) ^ ((((X) ^ ((X) >> 1)) >> 3) & 64))
772.4308 -+memcpy_to_tiled_x(swizzle_9_10)
772.4309 -+memcpy_from_tiled_x(swizzle_9_10)
772.4310 -+#undef swizzle_9_10
772.4311 - 
772.4312 --			memcpy((char *)dst + offset, src_row, 64);
772.4313 -+#define swizzle_9_11(X) ((X) ^ ((((X) ^ ((X) >> 2)) >> 3) & 64))
772.4314 -+memcpy_to_tiled_x(swizzle_9_11)
772.4315 -+memcpy_from_tiled_x(swizzle_9_11)
772.4316 -+#undef swizzle_9_11
772.4317 - 
772.4318 --			src_row += 64;
772.4319 --			x -= 64;
772.4320 --			dx += swizzle_pixels;
772.4321 --		}
772.4322 --		if (x) {
772.4323 --			offset = tile_row +
772.4324 --				(dx >> tile_pixels) * tile_size +
772.4325 --				(dx & tile_mask) * cpp;
772.4326 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4327 --			memcpy((char *)dst + offset, src_row, x);
772.4328 --		}
772.4329 --	}
772.4330 --}
772.4331 -+#define swizzle_9_10_11(X) ((X) ^ ((((X) ^ ((X) >> 1) ^ ((X) >> 2)) >> 3) & 64))
772.4332 -+memcpy_to_tiled_x(swizzle_9_10_11)
772.4333 -+memcpy_from_tiled_x(swizzle_9_10_11)
772.4334 -+#undef swizzle_9_10_11
772.4335 - 
772.4336 --fast_memcpy static void
772.4337 --memcpy_from_tiled_x__swizzle_9_10(const void *src, void *dst, int bpp,
772.4338 --				  int32_t src_stride, int32_t dst_stride,
772.4339 --				  int16_t src_x, int16_t src_y,
772.4340 --				  int16_t dst_x, int16_t dst_y,
772.4341 --				  uint16_t width, uint16_t height)
772.4342 -+static fast_memcpy void
772.4343 -+memcpy_to_tiled_x__gen2(const void *src, void *dst, int bpp,
772.4344 -+			int32_t src_stride, int32_t dst_stride,
772.4345 -+			int16_t src_x, int16_t src_y,
772.4346 -+			int16_t dst_x, int16_t dst_y,
772.4347 -+			uint16_t width, uint16_t height)
772.4348 - {
772.4349 --	const unsigned tile_width = 512;
772.4350 --	const unsigned tile_height = 8;
772.4351 --	const unsigned tile_size = 4096;
772.4352 -+	const unsigned tile_width = 128;
772.4353 -+	const unsigned tile_height = 16;
772.4354 -+	const unsigned tile_size = 2048;
772.4355 - 
772.4356 - 	const unsigned cpp = bpp / 8;
772.4357 --	const unsigned stride_tiles = src_stride / tile_width;
772.4358 --	const unsigned swizzle_pixels = 64 / cpp;
772.4359 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.4360 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.4361 --
772.4362 --	unsigned x, y;
772.4363 -+	const unsigned tile_pixels = tile_width / cpp;
772.4364 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.4365 -+	const unsigned tile_mask = tile_pixels - 1;
772.4366 - 
772.4367 - 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.4368 - 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.4369 -+	assert(src != dst);
772.4370 - 
772.4371 --	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
772.4372 --
772.4373 --	for (y = 0; y < height; ++y) {
772.4374 --		const uint32_t sy = y + src_y;
772.4375 --		const uint32_t tile_row =
772.4376 --			(sy / tile_height * stride_tiles * tile_size +
772.4377 --			 (sy & (tile_height-1)) * tile_width);
772.4378 --		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
772.4379 --		uint32_t sx = src_x, offset;
772.4380 --
772.4381 --		x = width * cpp;
772.4382 --		if (sx & (swizzle_pixels - 1)) {
772.4383 --			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
772.4384 --			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
772.4385 --			offset = tile_row +
772.4386 --				(sx >> tile_pixels) * tile_size +
772.4387 --				(sx & tile_mask) * cpp;
772.4388 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4389 --
772.4390 --			memcpy(dst_row, (const char *)src + offset, length * cpp);
772.4391 --
772.4392 --			dst_row += length * cpp;
772.4393 --			x -= length * cpp;
772.4394 --			sx += length;
772.4395 --		}
772.4396 --		while (x >= 64) {
772.4397 --			offset = tile_row +
772.4398 --				(sx >> tile_pixels) * tile_size +
772.4399 --				(sx & tile_mask) * cpp;
772.4400 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4401 --
772.4402 --			memcpy(dst_row, (const char *)src + offset, 64);
772.4403 --
772.4404 --			dst_row += 64;
772.4405 --			x -= 64;
772.4406 --			sx += swizzle_pixels;
772.4407 --		}
772.4408 --		if (x) {
772.4409 --			offset = tile_row +
772.4410 --				(sx >> tile_pixels) * tile_size +
772.4411 --				(sx & tile_mask) * cpp;
772.4412 --			offset ^= ((offset ^ (offset >> 1)) >> 3) & 64;
772.4413 --			memcpy(dst_row, (const char *)src + offset, x);
772.4414 --		}
772.4415 --	}
772.4416 --}
772.4417 --
772.4418 --fast_memcpy static void
772.4419 --memcpy_to_tiled_x__swizzle_9_11(const void *src, void *dst, int bpp,
772.4420 --				int32_t src_stride, int32_t dst_stride,
772.4421 --				int16_t src_x, int16_t src_y,
772.4422 --				int16_t dst_x, int16_t dst_y,
772.4423 --				uint16_t width, uint16_t height)
772.4424 --{
772.4425 --	const unsigned tile_width = 512;
772.4426 --	const unsigned tile_height = 8;
772.4427 --	const unsigned tile_size = 4096;
772.4428 --
772.4429 --	const unsigned cpp = bpp / 8;
772.4430 --	const unsigned stride_tiles = dst_stride / tile_width;
772.4431 --	const unsigned swizzle_pixels = 64 / cpp;
772.4432 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.4433 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.4434 -+	if (src_x | src_y)
772.4435 -+		src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
772.4436 -+	assert(src_stride >= width * cpp);
772.4437 -+	src_stride -= width * cpp;
772.4438 - 
772.4439 --	unsigned x, y;
772.4440 -+	while (height--) {
772.4441 -+		unsigned w = width * cpp;
772.4442 -+		uint8_t *tile_row = dst;
772.4443 - 
772.4444 --	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.4445 --	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.4446 -+		tile_row += dst_y / tile_height * dst_stride * tile_height;
772.4447 -+		tile_row += (dst_y & (tile_height-1)) * tile_width;
772.4448 -+		if (dst_x) {
772.4449 -+			tile_row += (dst_x >> tile_shift) * tile_size;
772.4450 -+			if (dst_x & tile_mask) {
772.4451 -+				const unsigned x = (dst_x & tile_mask) * cpp;
772.4452 -+				const unsigned len = min(tile_width - x, w);
772.4453 -+				memcpy(assume_misaligned(tile_row + x, tile_width, x), src, len);
772.4454 - 
772.4455 --	src = (const uint8_t *)src + src_y * src_stride + src_x * cpp;
772.4456 --
772.4457 --	for (y = 0; y < height; ++y) {
772.4458 --		const uint32_t dy = y + dst_y;
772.4459 --		const uint32_t tile_row =
772.4460 --			(dy / tile_height * stride_tiles * tile_size +
772.4461 --			 (dy & (tile_height-1)) * tile_width);
772.4462 --		const uint8_t *src_row = (const uint8_t *)src + src_stride * y;
772.4463 --		uint32_t dx = dst_x, offset;
772.4464 --
772.4465 --		x = width * cpp;
772.4466 --		if (dx & (swizzle_pixels - 1)) {
772.4467 --			const uint32_t swizzle_bound_pixels = ALIGN(dx + 1, swizzle_pixels);
772.4468 --			const uint32_t length = min(dst_x + width, swizzle_bound_pixels) - dx;
772.4469 --			offset = tile_row +
772.4470 --				(dx >> tile_pixels) * tile_size +
772.4471 --				(dx & tile_mask) * cpp;
772.4472 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4473 --			memcpy((char *)dst + offset, src_row, length * cpp);
772.4474 --
772.4475 --			src_row += length * cpp;
772.4476 --			x -= length * cpp;
772.4477 --			dx += length;
772.4478 -+				tile_row += tile_size;
772.4479 -+				src = (const uint8_t *)src + len;
772.4480 -+				w -= len;
772.4481 -+			}
772.4482 - 		}
772.4483 --		while (x >= 64) {
772.4484 --			offset = tile_row +
772.4485 --				(dx >> tile_pixels) * tile_size +
772.4486 --				(dx & tile_mask) * cpp;
772.4487 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4488 --
772.4489 --			memcpy((char *)dst + offset, src_row, 64);
772.4490 -+		while (w >= tile_width) {
772.4491 -+			memcpy(assume_aligned(tile_row, tile_width),
772.4492 -+			       src, tile_width);
772.4493 - 
772.4494 --			src_row += 64;
772.4495 --			x -= 64;
772.4496 --			dx += swizzle_pixels;
772.4497 --		}
772.4498 --		if (x) {
772.4499 --			offset = tile_row +
772.4500 --				(dx >> tile_pixels) * tile_size +
772.4501 --				(dx & tile_mask) * cpp;
772.4502 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4503 --			memcpy((char *)dst + offset, src_row, x);
772.4504 -+			tile_row += tile_size;
772.4505 -+			src = (const uint8_t *)src + tile_width;
772.4506 -+			w -= tile_width;
772.4507 - 		}
772.4508 -+		memcpy(assume_aligned(tile_row, tile_width), src, w);
772.4509 -+		src = (const uint8_t *)src + src_stride + w;
772.4510 -+		dst_y++;
772.4511 - 	}
772.4512 - }
772.4513 - 
772.4514 --fast_memcpy static void
772.4515 --memcpy_from_tiled_x__swizzle_9_11(const void *src, void *dst, int bpp,
772.4516 --				  int32_t src_stride, int32_t dst_stride,
772.4517 --				  int16_t src_x, int16_t src_y,
772.4518 --				  int16_t dst_x, int16_t dst_y,
772.4519 --				  uint16_t width, uint16_t height)
772.4520 -+static fast_memcpy void
772.4521 -+memcpy_from_tiled_x__gen2(const void *src, void *dst, int bpp,
772.4522 -+			  int32_t src_stride, int32_t dst_stride,
772.4523 -+			  int16_t src_x, int16_t src_y,
772.4524 -+			  int16_t dst_x, int16_t dst_y,
772.4525 -+			  uint16_t width, uint16_t height)
772.4526 - {
772.4527 --	const unsigned tile_width = 512;
772.4528 --	const unsigned tile_height = 8;
772.4529 --	const unsigned tile_size = 4096;
772.4530 -+	const unsigned tile_width = 128;
772.4531 -+	const unsigned tile_height = 16;
772.4532 -+	const unsigned tile_size = 2048;
772.4533 - 
772.4534 - 	const unsigned cpp = bpp / 8;
772.4535 --	const unsigned stride_tiles = src_stride / tile_width;
772.4536 --	const unsigned swizzle_pixels = 64 / cpp;
772.4537 --	const unsigned tile_pixels = ffs(tile_width / cpp) - 1;
772.4538 --	const unsigned tile_mask = (1 << tile_pixels) - 1;
772.4539 --
772.4540 --	unsigned x, y;
772.4541 -+	const unsigned tile_pixels = tile_width / cpp;
772.4542 -+	const unsigned tile_shift = ffs(tile_pixels) - 1;
772.4543 -+	const unsigned tile_mask = tile_pixels - 1;
772.4544 - 
772.4545 - 	DBG(("%s(bpp=%d): src=(%d, %d), dst=(%d, %d), size=%dx%d, pitch=%d/%d\n",
772.4546 - 	     __FUNCTION__, bpp, src_x, src_y, dst_x, dst_y, width, height, src_stride, dst_stride));
772.4547 -+	assert(src != dst);
772.4548 - 
772.4549 --	dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
772.4550 --
772.4551 --	for (y = 0; y < height; ++y) {
772.4552 --		const uint32_t sy = y + src_y;
772.4553 --		const uint32_t tile_row =
772.4554 --			(sy / tile_height * stride_tiles * tile_size +
772.4555 --			 (sy & (tile_height-1)) * tile_width);
772.4556 --		uint8_t *dst_row = (uint8_t *)dst + dst_stride * y;
772.4557 --		uint32_t sx = src_x, offset;
772.4558 --
772.4559 --		x = width * cpp;
772.4560 --		if (sx & (swizzle_pixels - 1)) {
772.4561 --			const uint32_t swizzle_bound_pixels = ALIGN(sx + 1, swizzle_pixels);
772.4562 --			const uint32_t length = min(src_x + width, swizzle_bound_pixels) - sx;
772.4563 --			offset = tile_row +
772.4564 --				(sx >> tile_pixels) * tile_size +
772.4565 --				(sx & tile_mask) * cpp;
772.4566 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4567 --			memcpy(dst_row, (const char *)src + offset, length * cpp);
772.4568 --
772.4569 --			dst_row += length * cpp;
772.4570 --			x -= length * cpp;
772.4571 --			sx += length;
772.4572 --		}
772.4573 --		while (x >= 64) {
772.4574 --			offset = tile_row +
772.4575 --				(sx >> tile_pixels) * tile_size +
772.4576 --				(sx & tile_mask) * cpp;
772.4577 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4578 -+	if (dst_x | dst_y)
772.4579 -+		dst = (uint8_t *)dst + dst_y * dst_stride + dst_x * cpp;
772.4580 -+	assert(dst_stride >= width * cpp);
772.4581 -+	dst_stride -= width * cpp;
772.4582 -+
772.4583 -+	while (height--) {
772.4584 -+		unsigned w = width * cpp;
772.4585 -+		const uint8_t *tile_row = src;
772.4586 - 
772.4587 --			memcpy(dst_row, (const char *)src + offset, 64);
772.4588 -+		tile_row += src_y / tile_height * src_stride * tile_height;
772.4589 -+		tile_row += (src_y & (tile_height-1)) * tile_width;
772.4590 -+		if (src_x) {
772.4591 -+			tile_row += (src_x >> tile_shift) * tile_size;
772.4592 -+			if (src_x & tile_mask) {
772.4593 -+				const unsigned x = (src_x & tile_mask) * cpp;
772.4594 -+				const unsigned len = min(tile_width - x, w);
772.4595 -+				memcpy(dst, assume_misaligned(tile_row + x, tile_width, x), len);
772.4596 - 
772.4597 --			dst_row += 64;
772.4598 --			x -= 64;
772.4599 --			sx += swizzle_pixels;
772.4600 -+				tile_row += tile_size;
772.4601 -+				dst = (uint8_t *)dst + len;
772.4602 -+				w -= len;
772.4603 -+			}
772.4604 - 		}
772.4605 --		if (x) {
772.4606 --			offset = tile_row +
772.4607 --				(sx >> tile_pixels) * tile_size +
772.4608 --				(sx & tile_mask) * cpp;
772.4609 --			offset ^= ((offset ^ (offset >> 2)) >> 3) & 64;
772.4610 --			memcpy(dst_row, (const char *)src + offset, x);
772.4611 -+		while (w >= tile_width) {
772.4612 -+			memcpy(dst,
772.4613 -+			       assume_aligned(tile_row, tile_width),
772.4614 -+			       tile_width);
772.4615 -+
772.4616 -+			tile_row += tile_size;
772.4617 -+			dst = (uint8_t *)dst + tile_width;
772.4618 -+			w -= tile_width;
772.4619 - 		}
772.4620 -+		memcpy(dst, assume_aligned(tile_row, tile_width), w);
772.4621 -+		dst = (uint8_t *)dst + dst_stride + w;
772.4622 -+		src_y++;
772.4623 - 	}
772.4624 - }
772.4625 - 
772.4626 --void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling)
772.4627 -+void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling, unsigned cpu)
772.4628 - {
772.4629 -+	if (kgem->gen < 030) {
772.4630 -+		if (swizzling == I915_BIT_6_SWIZZLE_NONE) {
772.4631 -+			DBG(("%s: gen2, no swizzling\n", __FUNCTION__));
772.4632 -+			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__gen2;
772.4633 -+			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__gen2;
772.4634 -+		} else
772.4635 -+			DBG(("%s: no detiling with swizzle functions for gen2\n", __FUNCTION__));
772.4636 -+		return;
772.4637 -+	}
772.4638 -+
772.4639 - 	switch (swizzling) {
772.4640 - 	default:
772.4641 - 		DBG(("%s: unknown swizzling, %d\n", __FUNCTION__, swizzling));
772.4642 - 		break;
772.4643 - 	case I915_BIT_6_SWIZZLE_NONE:
772.4644 - 		DBG(("%s: no swizzling\n", __FUNCTION__));
772.4645 --		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0;
772.4646 --		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0;
772.4647 -+#if defined(sse2)
772.4648 -+		if (cpu & SSE2) {
772.4649 -+			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0__sse2;
772.4650 -+			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0__sse2;
772.4651 -+			kgem->memcpy_between_tiled_x = memcpy_between_tiled_x__swizzle_0__sse2;
772.4652 -+		} else
772.4653 -+#endif
772.4654 -+	       	{
772.4655 -+			kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_0;
772.4656 -+			kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_0;
772.4657 -+			kgem->memcpy_between_tiled_x = memcpy_between_tiled_x__swizzle_0;
772.4658 -+		}
772.4659 - 		break;
772.4660 - 	case I915_BIT_6_SWIZZLE_9:
772.4661 - 		DBG(("%s: 6^9 swizzling\n", __FUNCTION__));
772.4662 -@@ -771,6 +1199,11 @@ void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling)
772.4663 - 		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_9_11;
772.4664 - 		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_9_11;
772.4665 - 		break;
772.4666 -+	case I915_BIT_6_SWIZZLE_9_10_11:
772.4667 -+		DBG(("%s: 6^9^10^11 swizzling\n", __FUNCTION__));
772.4668 -+		kgem->memcpy_to_tiled_x = memcpy_to_tiled_x__swizzle_9_10_11;
772.4669 -+		kgem->memcpy_from_tiled_x = memcpy_from_tiled_x__swizzle_9_10_11;
772.4670 -+		break;
772.4671 - 	}
772.4672 - }
772.4673 - 
772.4674 -@@ -995,7 +1428,7 @@ memcpy_xor(const void *src, void *dst, int bpp,
772.4675 - 				height = 1;
772.4676 - 			}
772.4677 - 
772.4678 --#if USE_SSE2
772.4679 -+#if defined(sse2) && __x86_64__
772.4680 - 			if (have_sse2()) {
772.4681 - 				do {
772.4682 - 					uint32_t *d = (uint32_t *)dst_bytes;
772.4683 -@@ -1118,3 +1551,241 @@ memcpy_xor(const void *src, void *dst, int bpp,
772.4684 - 		}
772.4685 - 	}
772.4686 - }
772.4687 -+
772.4688 -+#define BILINEAR_INTERPOLATION_BITS 4
772.4689 -+static inline int
772.4690 -+bilinear_weight(pixman_fixed_t x)
772.4691 -+{
772.4692 -+	return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) &
772.4693 -+		((1 << BILINEAR_INTERPOLATION_BITS) - 1);
772.4694 -+}
772.4695 -+
772.4696 -+#if BILINEAR_INTERPOLATION_BITS <= 4
772.4697 -+/* Inspired by Filter_32_opaque from Skia */
772.4698 -+static inline uint32_t
772.4699 -+bilinear_interpolation(uint32_t tl, uint32_t tr,
772.4700 -+		       uint32_t bl, uint32_t br,
772.4701 -+		       int distx, int disty)
772.4702 -+{
772.4703 -+	int distxy, distxiy, distixy, distixiy;
772.4704 -+	uint32_t lo, hi;
772.4705 -+
772.4706 -+	distx <<= (4 - BILINEAR_INTERPOLATION_BITS);
772.4707 -+	disty <<= (4 - BILINEAR_INTERPOLATION_BITS);
772.4708 -+
772.4709 -+	distxy = distx * disty;
772.4710 -+	distxiy = (distx << 4) - distxy;	/* distx * (16 - disty) */
772.4711 -+	distixy = (disty << 4) - distxy;	/* disty * (16 - distx) */
772.4712 -+	distixiy =
772.4713 -+		16 * 16 - (disty << 4) -
772.4714 -+		(distx << 4) + distxy; /* (16 - distx) * (16 - disty) */
772.4715 -+
772.4716 -+	lo = (tl & 0xff00ff) * distixiy;
772.4717 -+	hi = ((tl >> 8) & 0xff00ff) * distixiy;
772.4718 -+
772.4719 -+	lo += (tr & 0xff00ff) * distxiy;
772.4720 -+	hi += ((tr >> 8) & 0xff00ff) * distxiy;
772.4721 -+
772.4722 -+	lo += (bl & 0xff00ff) * distixy;
772.4723 -+	hi += ((bl >> 8) & 0xff00ff) * distixy;
772.4724 -+
772.4725 -+	lo += (br & 0xff00ff) * distxy;
772.4726 -+	hi += ((br >> 8) & 0xff00ff) * distxy;
772.4727 -+
772.4728 -+	return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff);
772.4729 -+}
772.4730 -+#elif SIZEOF_LONG > 4
772.4731 -+static inline uint32_t
772.4732 -+bilinear_interpolation(uint32_t tl, uint32_t tr,
772.4733 -+		       uint32_t bl, uint32_t br,
772.4734 -+		       int distx, int disty)
772.4735 -+{
772.4736 -+	uint64_t distxy, distxiy, distixy, distixiy;
772.4737 -+	uint64_t tl64, tr64, bl64, br64;
772.4738 -+	uint64_t f, r;
772.4739 -+
772.4740 -+	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
772.4741 -+	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
772.4742 -+
772.4743 -+	distxy = distx * disty;
772.4744 -+	distxiy = distx * (256 - disty);
772.4745 -+	distixy = (256 - distx) * disty;
772.4746 -+	distixiy = (256 - distx) * (256 - disty);
772.4747 -+
772.4748 -+	/* Alpha and Blue */
772.4749 -+	tl64 = tl & 0xff0000ff;
772.4750 -+	tr64 = tr & 0xff0000ff;
772.4751 -+	bl64 = bl & 0xff0000ff;
772.4752 -+	br64 = br & 0xff0000ff;
772.4753 -+
772.4754 -+	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
772.4755 -+	r = f & 0x0000ff0000ff0000ull;
772.4756 -+
772.4757 -+	/* Red and Green */
772.4758 -+	tl64 = tl;
772.4759 -+	tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
772.4760 -+
772.4761 -+	tr64 = tr;
772.4762 -+	tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
772.4763 -+
772.4764 -+	bl64 = bl;
772.4765 -+	bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
772.4766 -+
772.4767 -+	br64 = br;
772.4768 -+	br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
772.4769 -+
772.4770 -+	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
772.4771 -+	r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
772.4772 -+
772.4773 -+	return (uint32_t)(r >> 16);
772.4774 -+}
772.4775 -+#else
772.4776 -+static inline uint32_t
772.4777 -+bilinear_interpolation(uint32_t tl, uint32_t tr,
772.4778 -+		       uint32_t bl, uint32_t br,
772.4779 -+		       int distx, int disty)
772.4780 -+{
772.4781 -+	int distxy, distxiy, distixy, distixiy;
772.4782 -+	uint32_t f, r;
772.4783 -+
772.4784 -+	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
772.4785 -+	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
772.4786 -+
772.4787 -+	distxy = distx * disty;
772.4788 -+	distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
772.4789 -+	distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
772.4790 -+	distixiy =
772.4791 -+		256 * 256 - (disty << 8) -
772.4792 -+		(distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */
772.4793 -+
772.4794 -+	/* Blue */
772.4795 -+	r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
772.4796 -+	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
772.4797 -+
772.4798 -+	/* Green */
772.4799 -+	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
772.4800 -+	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
772.4801 -+	r |= f & 0xff000000;
772.4802 -+
772.4803 -+	tl >>= 16;
772.4804 -+	tr >>= 16;
772.4805 -+	bl >>= 16;
772.4806 -+	br >>= 16;
772.4807 -+	r >>= 16;
772.4808 -+
772.4809 -+	/* Red */
772.4810 -+	f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
772.4811 -+	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
772.4812 -+	r |= f & 0x00ff0000;
772.4813 -+
772.4814 -+	/* Alpha */
772.4815 -+	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
772.4816 -+	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
772.4817 -+	r |= f & 0xff000000;
772.4818 -+
772.4819 -+	return r;
772.4820 -+}
772.4821 -+#endif
772.4822 -+
772.4823 -+static inline uint32_t convert_pixel(const uint8_t *p, int x)
772.4824 -+{
772.4825 -+	return ((uint32_t *)p)[x];
772.4826 -+}
772.4827 -+
772.4828 -+fast void
772.4829 -+affine_blt(const void *src, void *dst, int bpp,
772.4830 -+	   int16_t src_x, int16_t src_y,
772.4831 -+	   int16_t src_width, int16_t src_height,
772.4832 -+	   int32_t src_stride,
772.4833 -+	   int16_t dst_x, int16_t dst_y,
772.4834 -+	   uint16_t dst_width, uint16_t dst_height,
772.4835 -+	   int32_t dst_stride,
772.4836 -+	   const struct pixman_f_transform *t)
772.4837 -+{
772.4838 -+	static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
772.4839 -+	const pixman_fixed_t ux = pixman_double_to_fixed(t->m[0][0]);
772.4840 -+	const pixman_fixed_t uy = pixman_double_to_fixed(t->m[1][0]);
772.4841 -+	int i, j;
772.4842 -+
772.4843 -+	assert(bpp == 32);
772.4844 -+
772.4845 -+	for (j = 0; j < dst_height; j++) {
772.4846 -+		pixman_fixed_t x, y;
772.4847 -+		struct pixman_f_vector v;
772.4848 -+		uint32_t *b;
772.4849 -+
772.4850 -+		/* reference point is the center of the pixel */
772.4851 -+		v.v[0] = dst_x + 0.5;
772.4852 -+		v.v[1] = dst_y + j + 0.5;
772.4853 -+		v.v[2] = 1.0;
772.4854 -+
772.4855 -+		pixman_f_transform_point_3d(t, &v);
772.4856 -+
772.4857 -+		x = pixman_double_to_fixed(v.v[0]);
772.4858 -+		x += pixman_int_to_fixed(src_x - dst_x);
772.4859 -+		y = pixman_double_to_fixed(v.v[1]);
772.4860 -+		y +=  pixman_int_to_fixed(src_y - dst_y);
772.4861 -+
772.4862 -+		b = (uint32_t*)((uint8_t *)dst + (dst_y + j) * dst_stride + dst_x * bpp / 8);
772.4863 -+		for (i = 0; i < dst_width; i++) {
772.4864 -+			const uint8_t *row1;
772.4865 -+			const uint8_t *row2;
772.4866 -+			int x1, y1, x2, y2;
772.4867 -+			uint32_t tl, tr, bl, br;
772.4868 -+			int32_t fx, fy;
772.4869 -+
772.4870 -+			x1 = x - pixman_fixed_1/2;
772.4871 -+			y1 = y - pixman_fixed_1/2;
772.4872 -+
772.4873 -+			fx = bilinear_weight(x1);
772.4874 -+			fy = bilinear_weight(y1);
772.4875 -+
772.4876 -+			x1 = pixman_fixed_to_int(x1);
772.4877 -+			x2 = x1 + 1;
772.4878 -+			y1 = pixman_fixed_to_int(y1);
772.4879 -+			y2 = y1 + 1;
772.4880 -+
772.4881 -+			if (x1 >= src_width  || x2 < 0 ||
772.4882 -+			    y1 >= src_height || y2 < 0) {
772.4883 -+				b[i] = 0;
772.4884 -+				goto next;
772.4885 -+			}
772.4886 -+
772.4887 -+			if (y2 == 0) {
772.4888 -+				row1 = zero;
772.4889 -+			} else {
772.4890 -+				row1 = (uint8_t *)src + src_stride * y1;
772.4891 -+				row1 += bpp / 8 * x1;
772.4892 -+			}
772.4893 -+
772.4894 -+			if (y1 == src_height - 1) {
772.4895 -+				row2 = zero;
772.4896 -+			} else {
772.4897 -+				row2 = (uint8_t *)src + src_stride * y2;
772.4898 -+				row2 += bpp / 8 * x1;
772.4899 -+			}
772.4900 -+
772.4901 -+			if (x2 == 0) {
772.4902 -+				tl = 0;
772.4903 -+				bl = 0;
772.4904 -+			} else {
772.4905 -+				tl = convert_pixel(row1, 0);
772.4906 -+				bl = convert_pixel(row2, 0);
772.4907 -+			}
772.4908 -+
772.4909 -+			if (x1 == src_width - 1) {
772.4910 -+				tr = 0;
772.4911 -+				br = 0;
772.4912 -+			} else {
772.4913 -+				tr = convert_pixel(row1, 1);
772.4914 -+				br = convert_pixel(row2, 1);
772.4915 -+			}
772.4916 -+
772.4917 -+			b[i] = bilinear_interpolation(tl, tr, bl, br, fx, fy);
772.4918 -+
772.4919 -+next:
772.4920 -+			x += ux;
772.4921 -+			y += uy;
772.4922 -+		}
772.4923 -+	}
772.4924 -+}
772.4925 -diff --git a/src/sna/brw/brw_eu_emit.c b/src/sna/brw/brw_eu_emit.c
772.4926 -index 00c984d9..154f939a 100644
772.4927 ---- a/src/sna/brw/brw_eu_emit.c
772.4928 -+++ b/src/sna/brw/brw_eu_emit.c
772.4929 -@@ -178,7 +178,7 @@ validate_reg(struct brw_instruction *insn, struct brw_reg reg)
772.4930 - 	}
772.4931 - 
772.4932 - 	if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
772.4933 --	    reg.file == BRW_ARF_NULL)
772.4934 -+	    reg.nr == BRW_ARF_NULL)
772.4935 - 		return;
772.4936 - 
772.4937 - 	assert(reg.hstride >= 0 && reg.hstride < ARRAY_SIZE(hstride_for_reg));
772.4938 -@@ -700,7 +700,7 @@ push_if_stack(struct brw_compile *p, struct brw_instruction *inst)
772.4939 -  *
772.4940 -  * When the matching 'else' instruction is reached (presumably by
772.4941 -  * countdown of the instruction count patched in by our ELSE/ENDIF
772.4942 -- * functions), the relevent flags are inverted.
772.4943 -+ * functions), the relevant flags are inverted.
772.4944 -  *
772.4945 -  * When the matching 'endif' instruction is reached, the flags are
772.4946 -  * popped off.  If the stack is now empty, normal execution resumes.
772.4947 -diff --git a/src/sna/compiler.h b/src/sna/compiler.h
772.4948 -index ff412179..0f3775ec 100644
772.4949 ---- a/src/sna/compiler.h
772.4950 -+++ b/src/sna/compiler.h
772.4951 -@@ -39,6 +39,7 @@
772.4952 - #define pure __attribute__((pure))
772.4953 - #define tightly_packed __attribute__((__packed__))
772.4954 - #define flatten __attribute__((flatten))
772.4955 -+#define nonnull __attribute__((nonnull))
772.4956 - #define page_aligned __attribute__((aligned(4096)))
772.4957 - #else
772.4958 - #define likely(expr) (expr)
772.4959 -@@ -51,18 +52,15 @@
772.4960 - #define pure
772.4961 - #define tighly_packed
772.4962 - #define flatten
772.4963 -+#define nonnull
772.4964 - #define page_aligned
772.4965 - #endif
772.4966 - 
772.4967 - #define HAS_GCC(major, minor) defined(__GNUC__) && (__GNUC__ > (major) || __GNUC__ == (major) && __GNUC_MINOR__ >= (minor))
772.4968 - 
772.4969 - #if HAS_GCC(4, 5)
772.4970 --#define sse2 __attribute__((target("sse2,fpmath=sse")))
772.4971 --#define sse4_2 __attribute__((target("sse4.2,sse2,fpmath=sse")))
772.4972 --#endif
772.4973 --
772.4974 --#if HAS_GCC(4, 7)
772.4975 --#define avx2 __attribute__((target("avx2,sse4.2,sse2,fpmath=sse")))
772.4976 -+#define sse2 fast __attribute__((target("sse2,fpmath=sse")))
772.4977 -+#define sse4_2 fast __attribute__((target("sse4.2,sse2,fpmath=sse")))
772.4978 - #endif
772.4979 - 
772.4980 - #if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
772.4981 -@@ -71,10 +69,17 @@
772.4982 - #define fast
772.4983 - #endif
772.4984 - 
772.4985 --#if HAS_GCC(4, 6) && defined(__OPTIMIZE__)
772.4986 --#define fast_memcpy __attribute__((optimize("Ofast"))) __attribute__((target("inline-all-stringops")))
772.4987 --#elif HAS_GCC(4, 5) && defined(__OPTIMIZE__)
772.4988 --#define fast_memcpy __attribute__((target("inline-all-stringops")))
772.4989 -+#if HAS_GCC(4, 7)
772.4990 -+#define avx2 fast __attribute__((target("avx2,avx,sse4.2,sse2,fpmath=sse")))
772.4991 -+#define assume_aligned(ptr, align) __builtin_assume_aligned((ptr), (align))
772.4992 -+#define assume_misaligned(ptr, align, offset) __builtin_assume_aligned((ptr), (align), (offset))
772.4993 -+#else
772.4994 -+#define assume_aligned(ptr, align) (ptr)
772.4995 -+#define assume_misaligned(ptr, align, offset) (ptr)
772.4996 -+#endif
772.4997 -+
772.4998 -+#if HAS_GCC(4, 5) && defined(__OPTIMIZE__)
772.4999 -+#define fast_memcpy fast __attribute__((target("inline-all-stringops")))
772.5000 - #else
772.5001 - #define fast_memcpy
772.5002 - #endif
772.5003 -diff --git a/src/sna/fb/fb.h b/src/sna/fb/fb.h
772.5004 -index 8bf9008a..90431747 100644
772.5005 ---- a/src/sna/fb/fb.h
772.5006 -+++ b/src/sna/fb/fb.h
772.5007 -@@ -24,10 +24,6 @@
772.5008 - #ifndef FB_H
772.5009 - #define FB_H
772.5010 - 
772.5011 --#ifdef HAVE_CONFIG_H
772.5012 --#include "config.h"
772.5013 --#endif
772.5014 --
772.5015 - #include <xorg-server.h>
772.5016 - #include <servermd.h>
772.5017 - #include <gcstruct.h>
772.5018 -diff --git a/src/sna/fb/fbimage.c b/src/sna/fb/fbimage.c
772.5019 -index 5af23890..cc81c85b 100644
772.5020 ---- a/src/sna/fb/fbimage.c
772.5021 -+++ b/src/sna/fb/fbimage.c
772.5022 -@@ -229,13 +229,19 @@ fbGetImage(DrawablePtr drawable,
772.5023 - 		FbBits pm;
772.5024 - 
772.5025 - 		pm = fbReplicatePixel(planeMask, srcBpp);
772.5026 -+
772.5027 - 		dstStride = PixmapBytePad(w, drawable->depth);
772.5028 --		if (pm != FB_ALLONES)
772.5029 --			memset(d, 0, dstStride * h);
772.5030 - 		dstStride /= sizeof(FbStip);
772.5031 -+
772.5032 - 		fbBltStip((FbStip *)(src + (y + srcYoff) * srcStride), srcStride,
772.5033 - 			  (x + srcXoff) * srcBpp,
772.5034 --			  dst, dstStride, 0, w * srcBpp, h, GXcopy, pm, srcBpp);
772.5035 -+			  dst, dstStride, 0, w * srcBpp, h, GXcopy, FB_ALLONES, srcBpp);
772.5036 -+
772.5037 -+		if (pm != FB_ALLONES) {
772.5038 -+			int i = dstStride * h;
772.5039 -+			while (i--)
772.5040 -+				*dst++ &= pm;
772.5041 -+		}
772.5042 - 	} else {
772.5043 - 		dstStride = BitmapBytePad(w) / sizeof(FbStip);
772.5044 - 		fbBltPlane(src + (y + srcYoff) * srcStride,
772.5045 -diff --git a/src/sna/fb/fbpict.h b/src/sna/fb/fbpict.h
772.5046 -index 932032f9..20877777 100644
772.5047 ---- a/src/sna/fb/fbpict.h
772.5048 -+++ b/src/sna/fb/fbpict.h
772.5049 -@@ -24,10 +24,6 @@
772.5050 - #ifndef FBPICT_H
772.5051 - #define FBPICT_H
772.5052 - 
772.5053 --#ifdef HAVE_CONFIG_H
772.5054 --#include "config.h"
772.5055 --#endif
772.5056 --
772.5057 - #include <xorg-server.h>
772.5058 - #include <picturestr.h>
772.5059 - 
772.5060 -diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
772.5061 -index 1104f462..49ad16a3 100644
772.5062 ---- a/src/sna/gen2_render.c
772.5063 -+++ b/src/sna/gen2_render.c
772.5064 -@@ -35,6 +35,7 @@
772.5065 - #include "sna_reg.h"
772.5066 - #include "sna_render.h"
772.5067 - #include "sna_render_inline.h"
772.5068 -+#include "sna_video.h"
772.5069 - 
772.5070 - #include "gen2_render.h"
772.5071 - 
772.5072 -@@ -48,6 +49,7 @@
772.5073 - 
772.5074 - #define MAX_3D_SIZE 2048
772.5075 - #define MAX_3D_PITCH 8192
772.5076 -+#define MAX_INLINE (1 << 18)
772.5077 - 
772.5078 - #define BATCH(v) batch_emit(sna, v)
772.5079 - #define BATCH_F(v) batch_emit_float(sna, v)
772.5080 -@@ -596,39 +598,43 @@ gen2_get_batch(struct sna *sna, const struct sna_composite_op *op)
772.5081 - 		gen2_emit_invariant(sna);
772.5082 - }
772.5083 - 
772.5084 --static void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op)
772.5085 -+static void gen2_emit_target(struct sna *sna,
772.5086 -+			     struct kgem_bo *bo,
772.5087 -+			     int width,
772.5088 -+			     int height,
772.5089 -+			     int format)
772.5090 - {
772.5091 --	assert(!too_large(op->dst.width, op->dst.height));
772.5092 --	assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= MAX_3D_PITCH);
772.5093 -+	assert(!too_large(width, height));
772.5094 -+	assert(bo->pitch >= 8 && bo->pitch <= MAX_3D_PITCH);
772.5095 - 	assert(sna->render.vertex_offset == 0);
772.5096 - 
772.5097 --	assert(op->dst.bo->unique_id);
772.5098 --	if (sna->render_state.gen2.target == op->dst.bo->unique_id) {
772.5099 --		kgem_bo_mark_dirty(op->dst.bo);
772.5100 -+	assert(bo->unique_id);
772.5101 -+	if (sna->render_state.gen2.target == bo->unique_id) {
772.5102 -+		kgem_bo_mark_dirty(bo);
772.5103 - 		return;
772.5104 - 	}
772.5105 - 
772.5106 - 	BATCH(_3DSTATE_BUF_INFO_CMD);
772.5107 - 	BATCH(BUF_3D_ID_COLOR_BACK |
772.5108 --	      gen2_buf_tiling(op->dst.bo->tiling) |
772.5109 --	      BUF_3D_PITCH(op->dst.bo->pitch));
772.5110 -+	      gen2_buf_tiling(bo->tiling) |
772.5111 -+	      BUF_3D_PITCH(bo->pitch));
772.5112 - 	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
772.5113 --			     op->dst.bo,
772.5114 -+			     bo,
772.5115 - 			     I915_GEM_DOMAIN_RENDER << 16 |
772.5116 - 			     I915_GEM_DOMAIN_RENDER,
772.5117 - 			     0));
772.5118 - 
772.5119 - 	BATCH(_3DSTATE_DST_BUF_VARS_CMD);
772.5120 --	BATCH(gen2_get_dst_format(op->dst.format));
772.5121 -+	BATCH(gen2_get_dst_format(format));
772.5122 - 
772.5123 - 	BATCH(_3DSTATE_DRAW_RECT_CMD);
772.5124 - 	BATCH(0);
772.5125 - 	BATCH(0);	/* ymin, xmin */
772.5126 --	BATCH(DRAW_YMAX(op->dst.height - 1) |
772.5127 --	      DRAW_XMAX(op->dst.width - 1));
772.5128 -+	BATCH(DRAW_YMAX(height - 1) |
772.5129 -+	      DRAW_XMAX(width - 1));
772.5130 - 	BATCH(0);	/* yorig, xorig */
772.5131 - 
772.5132 --	sna->render_state.gen2.target = op->dst.bo->unique_id;
772.5133 -+	sna->render_state.gen2.target = bo->unique_id;
772.5134 - }
772.5135 - 
772.5136 - static void gen2_disable_logic_op(struct sna *sna)
772.5137 -@@ -701,7 +707,11 @@ static void gen2_emit_composite_state(struct sna *sna,
772.5138 - 		kgem_clear_dirty(&sna->kgem);
772.5139 - 	}
772.5140 - 
772.5141 --	gen2_emit_target(sna, op);
772.5142 -+	gen2_emit_target(sna,
772.5143 -+			 op->dst.bo,
772.5144 -+			 op->dst.width,
772.5145 -+			 op->dst.height,
772.5146 -+			 op->dst.format);
772.5147 - 
772.5148 - 	unwind = sna->kgem.nbatch;
772.5149 - 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5150 -@@ -1190,7 +1200,13 @@ inline static int gen2_get_rectangles(struct sna *sna,
772.5151 - 			sna->render.vertex_offset = sna->kgem.nbatch;
772.5152 - 			BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST);
772.5153 - 		}
772.5154 --	}
772.5155 -+
772.5156 -+		need = 0;
772.5157 -+	} else
772.5158 -+		need = sna->kgem.nbatch - sna->render.vertex_offset;
772.5159 -+
772.5160 -+	if (rem > MAX_INLINE - need)
772.5161 -+		rem = MAX_INLINE -need;
772.5162 - 
772.5163 - 	if (want > 1 && want * size > rem)
772.5164 - 		want = rem / size;
772.5165 -@@ -1572,12 +1588,12 @@ gen2_composite_picture(struct sna *sna,
772.5166 - 		if (channel->repeat &&
772.5167 - 		    (x >= 0 &&
772.5168 - 		     y >= 0 &&
772.5169 --		     x + w < pixmap->drawable.width &&
772.5170 --		     y + h < pixmap->drawable.height)) {
772.5171 -+		     x + w <= pixmap->drawable.width &&
772.5172 -+		     y + h <= pixmap->drawable.height)) {
772.5173 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.5174 - 			if (priv && priv->clear) {
772.5175 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.5176 --				return gen2_composite_solid_init(sna, channel, priv->clear_color);
772.5177 -+				return gen2_composite_solid_init(sna, channel, solid_color(picture->format, priv->clear_color));
772.5178 - 			}
772.5179 - 		}
772.5180 - 	} else
772.5181 -@@ -1619,7 +1635,9 @@ gen2_composite_set_target(struct sna *sna,
772.5182 - 	} else
772.5183 - 		sna_render_picture_extents(dst, &box);
772.5184 - 
772.5185 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.5186 -+	hint = PREFER_GPU | RENDER_GPU;
772.5187 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.5188 -+		hint |= FORCE_GPU;
772.5189 - 	if (!partial) {
772.5190 - 		hint |= IGNORE_DAMAGE;
772.5191 - 		if (w == op->dst.width && h == op->dst.height)
772.5192 -@@ -2423,7 +2441,11 @@ static void gen2_emit_composite_spans_state(struct sna *sna,
772.5193 - 	uint32_t unwind;
772.5194 - 
772.5195 - 	gen2_get_batch(sna, &op->base);
772.5196 --	gen2_emit_target(sna, &op->base);
772.5197 -+	gen2_emit_target(sna,
772.5198 -+			 op->base.dst.bo,
772.5199 -+			 op->base.dst.width,
772.5200 -+			 op->base.dst.height,
772.5201 -+			 op->base.dst.format);
772.5202 - 
772.5203 - 	unwind = sna->kgem.nbatch;
772.5204 - 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5205 -@@ -2706,7 +2728,11 @@ static void gen2_emit_fill_composite_state(struct sna *sna,
772.5206 - 	uint32_t ls1;
772.5207 - 
772.5208 - 	gen2_get_batch(sna, op);
772.5209 --	gen2_emit_target(sna, op);
772.5210 -+	gen2_emit_target(sna,
772.5211 -+			 op->dst.bo,
772.5212 -+			 op->dst.width,
772.5213 -+			 op->dst.height,
772.5214 -+			 op->dst.format);
772.5215 - 
772.5216 - 	ls1 = sna->kgem.nbatch;
772.5217 - 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5218 -@@ -2868,7 +2894,11 @@ static void gen2_emit_fill_state(struct sna *sna,
772.5219 - 	uint32_t ls1;
772.5220 - 
772.5221 - 	gen2_get_batch(sna, op);
772.5222 --	gen2_emit_target(sna, op);
772.5223 -+	gen2_emit_target(sna,
772.5224 -+			 op->dst.bo,
772.5225 -+			 op->dst.width,
772.5226 -+			 op->dst.height,
772.5227 -+			 op->dst.format);
772.5228 - 
772.5229 - 	ls1 = sna->kgem.nbatch;
772.5230 - 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5231 -@@ -3102,6 +3132,276 @@ gen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
772.5232 - }
772.5233 - 
772.5234 - static void
772.5235 -+gen2_emit_video_state(struct sna *sna,
772.5236 -+		      struct sna_video *video,
772.5237 -+		      struct sna_video_frame *frame,
772.5238 -+		      PixmapPtr pixmap,
772.5239 -+		      struct kgem_bo *dst_bo,
772.5240 -+		      int width, int height,
772.5241 -+		      bool bilinear)
772.5242 -+{
772.5243 -+	uint32_t ms1, v, unwind;
772.5244 -+
772.5245 -+	gen2_emit_target(sna, dst_bo, width, height,
772.5246 -+			 sna_format_for_depth(pixmap->drawable.depth));
772.5247 -+
772.5248 -+	unwind = sna->kgem.nbatch;
772.5249 -+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5250 -+	      I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2);
772.5251 -+	BATCH(1 << 12);
772.5252 -+	BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY);
772.5253 -+	BATCH(S8_ENABLE_COLOR_BUFFER_WRITE);
772.5254 -+	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1,
772.5255 -+		   sna->kgem.batch + unwind + 1,
772.5256 -+		   3 * sizeof(uint32_t)) == 0)
772.5257 -+		sna->kgem.nbatch = unwind;
772.5258 -+	else
772.5259 -+		sna->render_state.gen2.ls1 = unwind;
772.5260 -+
772.5261 -+	gen2_disable_logic_op(sna);
772.5262 -+
772.5263 -+	unwind = sna->kgem.nbatch;
772.5264 -+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
772.5265 -+	      LOAD_TEXTURE_BLEND_STAGE(0) | 1);
772.5266 -+	BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT |
772.5267 -+	      TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0);
772.5268 -+	BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT |
772.5269 -+	      TB0A_OP_ARG1 | TB0A_ARG1_SEL_ONE);
772.5270 -+	if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1,
772.5271 -+		   sna->kgem.batch + unwind + 1,
772.5272 -+		   2 * sizeof(uint32_t)) == 0)
772.5273 -+		sna->kgem.nbatch = unwind;
772.5274 -+	else
772.5275 -+		sna->render_state.gen2.ls2 = unwind;
772.5276 -+
772.5277 -+	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(0) | 4);
772.5278 -+	BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch,
772.5279 -+			     frame->bo,
772.5280 -+			     I915_GEM_DOMAIN_SAMPLER << 16,
772.5281 -+			     0));
772.5282 -+	ms1 = MAPSURF_422 | TM0S1_COLORSPACE_CONVERSION;
772.5283 -+	switch (frame->id) {
772.5284 -+	case FOURCC_YUY2:
772.5285 -+		ms1 |= MT_422_YCRCB_NORMAL;
772.5286 -+		break;
772.5287 -+	case FOURCC_UYVY:
772.5288 -+		ms1 |= MT_422_YCRCB_SWAPY;
772.5289 -+		break;
772.5290 -+	}
772.5291 -+	BATCH(((frame->height - 1) << TM0S1_HEIGHT_SHIFT) |
772.5292 -+	      ((frame->width - 1)  << TM0S1_WIDTH_SHIFT) |
772.5293 -+	      ms1 |
772.5294 -+	      gen2_sampler_tiling_bits(frame->bo->tiling));
772.5295 -+	BATCH((frame->pitch[0] / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
772.5296 -+	if (bilinear)
772.5297 -+		BATCH(FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT |
772.5298 -+		      FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT |
772.5299 -+		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
772.5300 -+	else
772.5301 -+		BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
772.5302 -+		      FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
772.5303 -+		      MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
772.5304 -+	BATCH(0);	/* default color */
772.5305 -+
772.5306 -+	BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(0) |
772.5307 -+	      ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | TEXCOORDTYPE_CARTESIAN |
772.5308 -+	      ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) |
772.5309 -+	      ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP));
772.5310 -+
772.5311 -+	v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D;
772.5312 -+	if (sna->render_state.gen2.vft != v) {
772.5313 -+		BATCH(v);
772.5314 -+		sna->render_state.gen2.vft = v;
772.5315 -+	}
772.5316 -+}
772.5317 -+
772.5318 -+static void
772.5319 -+gen2_video_get_batch(struct sna *sna, struct kgem_bo *bo)
772.5320 -+{
772.5321 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
772.5322 -+
772.5323 -+	if (!kgem_check_batch(&sna->kgem, 120) ||
772.5324 -+	    !kgem_check_reloc(&sna->kgem, 4) ||
772.5325 -+	    !kgem_check_exec(&sna->kgem, 2)) {
772.5326 -+		_kgem_submit(&sna->kgem);
772.5327 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.5328 -+	}
772.5329 -+
772.5330 -+	if (sna->render_state.gen2.need_invariant)
772.5331 -+		gen2_emit_invariant(sna);
772.5332 -+}
772.5333 -+
772.5334 -+static int
772.5335 -+gen2_get_inline_rectangles(struct sna *sna, int want, int floats_per_vertex)
772.5336 -+{
772.5337 -+	int size = floats_per_vertex * 3;
772.5338 -+	int rem = batch_space(sna) - 1;
772.5339 -+
772.5340 -+	if (rem > MAX_INLINE)
772.5341 -+		rem = MAX_INLINE;
772.5342 -+
772.5343 -+	if (size * want > rem)
772.5344 -+		want = rem / size;
772.5345 -+
772.5346 -+	return want;
772.5347 -+}
772.5348 -+
772.5349 -+static bool
772.5350 -+gen2_render_video(struct sna *sna,
772.5351 -+		  struct sna_video *video,
772.5352 -+		  struct sna_video_frame *frame,
772.5353 -+		  RegionPtr dstRegion,
772.5354 -+		  PixmapPtr pixmap)
772.5355 -+{
772.5356 -+	struct sna_pixmap *priv = sna_pixmap(pixmap);
772.5357 -+	const BoxRec *pbox = region_rects(dstRegion);
772.5358 -+	int nbox = region_num_rects(dstRegion);
772.5359 -+	int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
772.5360 -+	int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
772.5361 -+	int src_width = frame->src.x2 - frame->src.x1;
772.5362 -+	int src_height = frame->src.y2 - frame->src.y1;
772.5363 -+	float src_offset_x, src_offset_y;
772.5364 -+	float src_scale_x, src_scale_y;
772.5365 -+	int pix_xoff, pix_yoff;
772.5366 -+	struct kgem_bo *dst_bo;
772.5367 -+	bool bilinear;
772.5368 -+	int copy = 0;
772.5369 -+
772.5370 -+	DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__,
772.5371 -+	     src_width, src_height, frame->width, frame->height, dst_width, dst_height));
772.5372 -+
772.5373 -+	assert(priv->gpu_bo);
772.5374 -+	dst_bo = priv->gpu_bo;
772.5375 -+
772.5376 -+	bilinear = src_width != dst_width || src_height != dst_height;
772.5377 -+
772.5378 -+	src_scale_x = (float)src_width / dst_width / frame->width;
772.5379 -+	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
772.5380 -+
772.5381 -+	src_scale_y = (float)src_height / dst_height / frame->height;
772.5382 -+	src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
772.5383 -+	DBG(("%s: src offset (%f, %f), scale (%f, %f)\n",
772.5384 -+	     __FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y));
772.5385 -+
772.5386 -+	if (too_large(pixmap->drawable.width, pixmap->drawable.height) ||
772.5387 -+	    dst_bo->pitch > MAX_3D_PITCH) {
772.5388 -+		int bpp = pixmap->drawable.bitsPerPixel;
772.5389 -+
772.5390 -+		if (too_large(dst_width, dst_height))
772.5391 -+			return false;
772.5392 -+
772.5393 -+		dst_bo = kgem_create_2d(&sna->kgem,
772.5394 -+					dst_width, dst_height, bpp,
772.5395 -+					kgem_choose_tiling(&sna->kgem,
772.5396 -+							   I915_TILING_X,
772.5397 -+							   dst_width, dst_height, bpp),
772.5398 -+					0);
772.5399 -+		if (!dst_bo)
772.5400 -+			return false;
772.5401 -+
772.5402 -+		pix_xoff = -dstRegion->extents.x1;
772.5403 -+		pix_yoff = -dstRegion->extents.y1;
772.5404 -+		copy = 1;
772.5405 -+	} else {
772.5406 -+		/* Set up the offset for translating from the given region
772.5407 -+		 * (in screen coordinates) to the backing pixmap.
772.5408 -+		 */
772.5409 -+#ifdef COMPOSITE
772.5410 -+		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.5411 -+		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.5412 -+#else
772.5413 -+		pix_xoff = 0;
772.5414 -+		pix_yoff = 0;
772.5415 -+#endif
772.5416 -+
772.5417 -+		dst_width  = pixmap->drawable.width;
772.5418 -+		dst_height = pixmap->drawable.height;
772.5419 -+	}
772.5420 -+
772.5421 -+	gen2_video_get_batch(sna, dst_bo);
772.5422 -+	gen2_emit_video_state(sna, video, frame, pixmap,
772.5423 -+			      dst_bo, dst_width, dst_height, bilinear);
772.5424 -+	do {
772.5425 -+		int nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
772.5426 -+		if (nbox_this_time == 0) {
772.5427 -+			gen2_video_get_batch(sna, dst_bo);
772.5428 -+			gen2_emit_video_state(sna, video, frame, pixmap,
772.5429 -+					      dst_bo, dst_width, dst_height, bilinear);
772.5430 -+			nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4);
772.5431 -+			assert(nbox_this_time);
772.5432 -+		}
772.5433 -+		nbox -= nbox_this_time;
772.5434 -+
772.5435 -+		BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST |
772.5436 -+		      ((12 * nbox_this_time) - 1));
772.5437 -+		do {
772.5438 -+			int box_x1 = pbox->x1;
772.5439 -+			int box_y1 = pbox->y1;
772.5440 -+			int box_x2 = pbox->x2;
772.5441 -+			int box_y2 = pbox->y2;
772.5442 -+
772.5443 -+			pbox++;
772.5444 -+
772.5445 -+			DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n",
772.5446 -+			     __FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff,
772.5447 -+			     box_x1 * src_scale_x + src_offset_x,
772.5448 -+			     box_y1 * src_scale_y + src_offset_y,
772.5449 -+			     box_x2 * src_scale_x + src_offset_x,
772.5450 -+			     box_y2 * src_scale_y + src_offset_y));
772.5451 -+
772.5452 -+			/* bottom right */
772.5453 -+			BATCH_F(box_x2 + pix_xoff);
772.5454 -+			BATCH_F(box_y2 + pix_yoff);
772.5455 -+			BATCH_F(box_x2 * src_scale_x + src_offset_x);
772.5456 -+			BATCH_F(box_y2 * src_scale_y + src_offset_y);
772.5457 -+
772.5458 -+			/* bottom left */
772.5459 -+			BATCH_F(box_x1 + pix_xoff);
772.5460 -+			BATCH_F(box_y2 + pix_yoff);
772.5461 -+			BATCH_F(box_x1 * src_scale_x + src_offset_x);
772.5462 -+			BATCH_F(box_y2 * src_scale_y + src_offset_y);
772.5463 -+
772.5464 -+			/* top left */
772.5465 -+			BATCH_F(box_x1 + pix_xoff);
772.5466 -+			BATCH_F(box_y1 + pix_yoff);
772.5467 -+			BATCH_F(box_x1 * src_scale_x + src_offset_x);
772.5468 -+			BATCH_F(box_y1 * src_scale_y + src_offset_y);
772.5469 -+		} while (--nbox_this_time);
772.5470 -+	} while (nbox);
772.5471 -+
772.5472 -+	if (copy) {
772.5473 -+#ifdef COMPOSITE
772.5474 -+		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.5475 -+		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.5476 -+#else
772.5477 -+		pix_xoff = 0;
772.5478 -+		pix_yoff = 0;
772.5479 -+#endif
772.5480 -+		sna_blt_copy_boxes(sna, GXcopy,
772.5481 -+				   dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
772.5482 -+				   priv->gpu_bo, pix_xoff, pix_yoff,
772.5483 -+				   pixmap->drawable.bitsPerPixel,
772.5484 -+				   region_rects(dstRegion),
772.5485 -+				   region_num_rects(dstRegion));
772.5486 -+
772.5487 -+		kgem_bo_destroy(&sna->kgem, dst_bo);
772.5488 -+	}
772.5489 -+
772.5490 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.5491 -+		if ((pix_xoff | pix_yoff) == 0) {
772.5492 -+			sna_damage_add(&priv->gpu_damage, dstRegion);
772.5493 -+		} else {
772.5494 -+			sna_damage_add_boxes(&priv->gpu_damage,
772.5495 -+					     region_rects(dstRegion),
772.5496 -+					     region_num_rects(dstRegion),
772.5497 -+					     pix_xoff, pix_yoff);
772.5498 -+		}
772.5499 -+	}
772.5500 -+
772.5501 -+	return true;
772.5502 -+}
772.5503 -+
772.5504 -+static void
772.5505 - gen2_render_copy_setup_source(struct sna_composite_channel *channel,
772.5506 - 			      const DrawableRec *draw,
772.5507 - 			      struct kgem_bo *bo)
772.5508 -@@ -3176,7 +3476,11 @@ static void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op
772.5509 - 			      PIPELINE_FLUSH_TEXTURE_CACHE);
772.5510 - 		kgem_clear_dirty(&sna->kgem);
772.5511 - 	}
772.5512 --	gen2_emit_target(sna, op);
772.5513 -+	gen2_emit_target(sna,
772.5514 -+			 op->dst.bo,
772.5515 -+			 op->dst.width,
772.5516 -+			 op->dst.height,
772.5517 -+			 op->dst.format);
772.5518 - 
772.5519 - 	ls1 = sna->kgem.nbatch;
772.5520 - 	BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
772.5521 -@@ -3511,7 +3815,7 @@ const char *gen2_render_init(struct sna *sna, const char *backend)
772.5522 - 	render->copy = gen2_render_copy;
772.5523 - 	render->copy_boxes = gen2_render_copy_boxes;
772.5524 - 
772.5525 --	/* XXX YUV color space conversion for video? */
772.5526 -+	render->video = gen2_render_video;
772.5527 - 
772.5528 - 	render->reset = gen2_render_reset;
772.5529 - 	render->flush = gen2_render_flush;
772.5530 -diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
772.5531 -index 78289f00..4459a562 100644
772.5532 ---- a/src/sna/gen3_render.c
772.5533 -+++ b/src/sna/gen3_render.c
772.5534 -@@ -448,14 +448,14 @@ gen3_emit_composite_boxes_constant(const struct sna_composite_op *op,
772.5535 - 				   float *v)
772.5536 - {
772.5537 - 	do {
772.5538 --		v[0] = box->x2;
772.5539 --		v[1] = box->y2;
772.5540 -+		v[0] = box->x2 + op->dst.x;
772.5541 -+		v[1] = box->y2 + op->dst.y;
772.5542 - 
772.5543 --		v[2] = box->x1;
772.5544 --		v[3] = box->y2;
772.5545 -+		v[2] = box->x1 + op->dst.x;
772.5546 -+		v[3] = box->y2 + op->dst.y;
772.5547 - 
772.5548 --		v[4] = box->x1;
772.5549 --		v[5] = box->y1;
772.5550 -+		v[4] = box->x1 + op->dst.x;
772.5551 -+		v[5] = box->y1 + op->dst.y;
772.5552 - 
772.5553 - 		box++;
772.5554 - 		v += 6;
772.5555 -@@ -494,18 +494,18 @@ gen3_emit_composite_boxes_identity_gradient(const struct sna_composite_op *op,
772.5556 - 					    float *v)
772.5557 - {
772.5558 - 	do {
772.5559 --		v[0] = box->x2;
772.5560 --		v[1] = box->y2;
772.5561 -+		v[0] = box->x2 + op->dst.x;
772.5562 -+		v[1] = box->y2 + op->dst.y;
772.5563 - 		v[2] = box->x2 + op->src.offset[0];
772.5564 - 		v[3] = box->y2 + op->src.offset[1];
772.5565 - 
772.5566 --		v[4] = box->x1;
772.5567 --		v[5] = box->y2;
772.5568 -+		v[4] = box->x1 + op->dst.x;
772.5569 -+		v[5] = box->y2 + op->dst.y;
772.5570 - 		v[6] = box->x1 + op->src.offset[0];
772.5571 - 		v[7] = box->y2 + op->src.offset[1];
772.5572 - 
772.5573 --		v[8] = box->x1;
772.5574 --		v[9] = box->y1;
772.5575 -+		v[8] = box->x1 + op->dst.x;
772.5576 -+		v[9] = box->y1 + op->dst.y;
772.5577 - 		v[10] = box->x1 + op->src.offset[0];
772.5578 - 		v[11] = box->y1 + op->src.offset[1];
772.5579 - 
772.5580 -@@ -531,6 +531,7 @@ gen3_emit_composite_primitive_affine_gradient(struct sna *sna,
772.5581 - 
772.5582 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5583 - 	sna->render.vertex_used += 12;
772.5584 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5585 - 
772.5586 - 	v[0] = dst_x + r->width;
772.5587 - 	v[1] = dst_y + r->height;
772.5588 -@@ -559,22 +560,22 @@ gen3_emit_composite_boxes_affine_gradient(const struct sna_composite_op *op,
772.5589 - 	const PictTransform *transform = op->src.transform;
772.5590 - 
772.5591 - 	do {
772.5592 --		v[0] = box->x2;
772.5593 --		v[1] = box->y2;
772.5594 -+		v[0] = box->x2 + op->dst.x;
772.5595 -+		v[1] = box->y2 + op->dst.y;
772.5596 - 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
772.5597 - 					    box->y2 + op->src.offset[1],
772.5598 - 					    transform, op->src.scale,
772.5599 - 					    &v[2], &v[3]);
772.5600 - 
772.5601 --		v[4] = box->x1;
772.5602 --		v[5] = box->y2;
772.5603 -+		v[4] = box->x1 + op->dst.x;
772.5604 -+		v[5] = box->y2 + op->dst.y;
772.5605 - 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
772.5606 - 					    box->y2 + op->src.offset[1],
772.5607 - 					    transform, op->src.scale,
772.5608 - 					    &v[6], &v[7]);
772.5609 - 
772.5610 --		v[8] = box->x1;
772.5611 --		v[9] = box->y1;
772.5612 -+		v[8] = box->x1 + op->dst.x;
772.5613 -+		v[9] = box->y1 + op->dst.y;
772.5614 - 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
772.5615 - 					    box->y1 + op->src.offset[1],
772.5616 - 					    transform, op->src.scale,
772.5617 -@@ -596,6 +597,7 @@ gen3_emit_composite_primitive_identity_source(struct sna *sna,
772.5618 - 
772.5619 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5620 - 	sna->render.vertex_used += 12;
772.5621 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5622 - 
772.5623 - 	v[8] = v[4] = r->dst.x + op->dst.x;
772.5624 - 	v[0] = v[4] + w;
772.5625 -@@ -643,6 +645,7 @@ gen3_emit_composite_primitive_identity_source_no_offset(struct sna *sna,
772.5626 - 
772.5627 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5628 - 	sna->render.vertex_used += 12;
772.5629 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5630 - 
772.5631 - 	v[8] = v[4] = r->dst.x;
772.5632 - 	v[9] = r->dst.y;
772.5633 -@@ -693,6 +696,7 @@ gen3_emit_composite_primitive_affine_source(struct sna *sna,
772.5634 - 
772.5635 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5636 - 	sna->render.vertex_used += 12;
772.5637 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5638 - 
772.5639 - 	v[0] = dst_x + r->width;
772.5640 - 	v[5] = v[1] = dst_y + r->height;
772.5641 -@@ -720,10 +724,10 @@ gen3_emit_composite_boxes_affine_source(const struct sna_composite_op *op,
772.5642 - 	const PictTransform *transform = op->src.transform;
772.5643 - 
772.5644 - 	do {
772.5645 --		v[0] = box->x2;
772.5646 --		v[5] = v[1] = box->y2;
772.5647 --		v[8] = v[4] = box->x1;
772.5648 --		v[9] = box->y1;
772.5649 -+		v[0] = box->x2 + op->dst.x;
772.5650 -+		v[5] = v[1] = box->y2 + op->dst.y;
772.5651 -+		v[8] = v[4] = box->x1 + op->dst.x;
772.5652 -+		v[9] = box->y1 + op->dst.y;
772.5653 - 
772.5654 - 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
772.5655 - 					    box->y2 + op->src.offset[1],
772.5656 -@@ -756,6 +760,7 @@ gen3_emit_composite_primitive_constant_identity_mask(struct sna *sna,
772.5657 - 
772.5658 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5659 - 	sna->render.vertex_used += 12;
772.5660 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5661 - 
772.5662 - 	v[8] = v[4] = r->dst.x + op->dst.x;
772.5663 - 	v[0] = v[4] + w;
772.5664 -@@ -781,6 +786,7 @@ gen3_emit_composite_primitive_constant_identity_mask_no_offset(struct sna *sna,
772.5665 - 
772.5666 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5667 - 	sna->render.vertex_used += 12;
772.5668 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5669 - 
772.5670 - 	v[8] = v[4] = r->dst.x;
772.5671 - 	v[9] = r->dst.y;
772.5672 -@@ -817,6 +823,7 @@ gen3_emit_composite_primitive_identity_source_mask(struct sna *sna,
772.5673 - 
772.5674 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5675 - 	sna->render.vertex_used += 18;
772.5676 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5677 - 
772.5678 - 	v[0] = dst_x + w;
772.5679 - 	v[1] = dst_y + h;
772.5680 -@@ -862,6 +869,7 @@ gen3_emit_composite_primitive_affine_source_mask(struct sna *sna,
772.5681 - 
772.5682 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5683 - 	sna->render.vertex_used += 18;
772.5684 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5685 - 
772.5686 - 	v[0] = dst_x + w;
772.5687 - 	v[1] = dst_y + h;
772.5688 -@@ -978,6 +986,7 @@ gen3_emit_composite_primitive_constant__sse2(struct sna *sna,
772.5689 - 
772.5690 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5691 - 	sna->render.vertex_used += 6;
772.5692 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5693 - 
772.5694 - 	v[4] = v[2] = r->dst.x + op->dst.x;
772.5695 - 	v[5] = r->dst.y + op->dst.y;
772.5696 -@@ -993,10 +1002,10 @@ gen3_emit_composite_boxes_constant__sse2(const struct sna_composite_op *op,
772.5697 - 					 float *v)
772.5698 - {
772.5699 - 	do {
772.5700 --		v[0] = box->x2;
772.5701 --		v[3] = v[1] = box->y2;
772.5702 --		v[4] = v[2] = box->x1;
772.5703 --		v[5] = box->y1;
772.5704 -+		v[0] = box->x2 + op->dst.x;
772.5705 -+		v[3] = v[1] = box->y2 + op->dst.y;
772.5706 -+		v[4] = v[2] = box->x1 + op->dst.x;
772.5707 -+		v[5] = box->y1 + op->dst.y;
772.5708 - 
772.5709 - 		box++;
772.5710 - 		v += 6;
772.5711 -@@ -1013,6 +1022,7 @@ gen3_emit_composite_primitive_identity_gradient__sse2(struct sna *sna,
772.5712 - 
772.5713 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5714 - 	sna->render.vertex_used += 12;
772.5715 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5716 - 
772.5717 - 	x = r->dst.x + op->dst.x;
772.5718 - 	y = r->dst.y + op->dst.y;
772.5719 -@@ -1035,10 +1045,10 @@ gen3_emit_composite_boxes_identity_gradient__sse2(const struct sna_composite_op
772.5720 - 						  float *v)
772.5721 - {
772.5722 - 	do {
772.5723 --		v[0] = box->x2;
772.5724 --		v[5] = v[1] = box->y2;
772.5725 --		v[8] = v[4] = box->x1;
772.5726 --		v[9] = box->y1;
772.5727 -+		v[0] = box->x2 + op->dst.x;
772.5728 -+		v[5] = v[1] = box->y2 + op->dst.y;
772.5729 -+		v[8] = v[4] = box->x1 + op->dst.x;
772.5730 -+		v[9] = box->y1 + op->dst.y;
772.5731 - 
772.5732 - 		v[2] = box->x2 + op->src.offset[0];
772.5733 - 		v[7] = v[3] = box->y2 + op->src.offset[1];
772.5734 -@@ -1067,6 +1077,7 @@ gen3_emit_composite_primitive_affine_gradient__sse2(struct sna *sna,
772.5735 - 
772.5736 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5737 - 	sna->render.vertex_used += 12;
772.5738 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5739 - 
772.5740 - 	v[0] = dst_x + r->width;
772.5741 - 	v[1] = dst_y + r->height;
772.5742 -@@ -1095,22 +1106,22 @@ gen3_emit_composite_boxes_affine_gradient__sse2(const struct sna_composite_op *o
772.5743 - 	const PictTransform *transform = op->src.transform;
772.5744 - 
772.5745 - 	do {
772.5746 --		v[0] = box->x2;
772.5747 --		v[1] = box->y2;
772.5748 -+		v[0] = box->x2 + op->dst.x;
772.5749 -+		v[1] = box->y2 + op->dst.y;
772.5750 - 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
772.5751 - 					    box->y2 + op->src.offset[1],
772.5752 - 					    transform, op->src.scale,
772.5753 - 					    &v[2], &v[3]);
772.5754 - 
772.5755 --		v[4] = box->x1;
772.5756 --		v[5] = box->y2;
772.5757 -+		v[4] = box->x1 + op->dst.x;
772.5758 -+		v[5] = box->y2 + op->dst.y;
772.5759 - 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
772.5760 - 					    box->y2 + op->src.offset[1],
772.5761 - 					    transform, op->src.scale,
772.5762 - 					    &v[6], &v[7]);
772.5763 - 
772.5764 --		v[8] = box->x1;
772.5765 --		v[9] = box->y1;
772.5766 -+		v[8] = box->x1 + op->dst.x;
772.5767 -+		v[9] = box->y1 + op->dst.y;
772.5768 - 		_sna_get_transformed_scaled(box->x1 + op->src.offset[0],
772.5769 - 					    box->y1 + op->src.offset[1],
772.5770 - 					    transform, op->src.scale,
772.5771 -@@ -1132,6 +1143,7 @@ gen3_emit_composite_primitive_identity_source__sse2(struct sna *sna,
772.5772 - 
772.5773 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5774 - 	sna->render.vertex_used += 12;
772.5775 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5776 - 
772.5777 - 	v[8] = v[4] = r->dst.x + op->dst.x;
772.5778 - 	v[0] = v[4] + w;
772.5779 -@@ -1179,6 +1191,7 @@ gen3_emit_composite_primitive_identity_source_no_offset__sse2(struct sna *sna,
772.5780 - 
772.5781 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5782 - 	sna->render.vertex_used += 12;
772.5783 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5784 - 
772.5785 - 	v[8] = v[4] = r->dst.x;
772.5786 - 	v[9] = r->dst.y;
772.5787 -@@ -1227,8 +1240,12 @@ gen3_emit_composite_primitive_affine_source__sse2(struct sna *sna,
772.5788 - 	int src_y = r->src.y + (int)op->src.offset[1];
772.5789 - 	float *v;
772.5790 - 
772.5791 -+	DBG(("%s: src=(%d, %d), dst=(%d, %d), size=%dx%d\n",
772.5792 -+	     __FUNCTION__, src_x, src_y, dst_x, dst_y, r->width, r->height));
772.5793 -+
772.5794 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5795 - 	sna->render.vertex_used += 12;
772.5796 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5797 - 
772.5798 - 	v[0] = dst_x + r->width;
772.5799 - 	v[5] = v[1] = dst_y + r->height;
772.5800 -@@ -1256,10 +1273,13 @@ gen3_emit_composite_boxes_affine_source__sse2(const struct sna_composite_op *op,
772.5801 - 	const PictTransform *transform = op->src.transform;
772.5802 - 
772.5803 - 	do {
772.5804 --		v[0] = box->x2;
772.5805 --		v[5] = v[1] = box->y2;
772.5806 --		v[8] = v[4] = box->x1;
772.5807 --		v[9] = box->y1;
772.5808 -+		DBG(("%s: box=(%d, %d), (%d, %d), src.offset=(%d, %d)\n",
772.5809 -+		     __FUNCTION__, box->x1, box->y1, box->x2, box->y2, op->src.offset[0], op->src.offset[1]));
772.5810 -+
772.5811 -+		v[0] = box->x2 + op->dst.x;
772.5812 -+		v[5] = v[1] = box->y2 + op->dst.y;
772.5813 -+		v[8] = v[4] = box->x1 + op->dst.x;
772.5814 -+		v[9] = box->y1 + op->dst.y;
772.5815 - 
772.5816 - 		_sna_get_transformed_scaled(box->x2 + op->src.offset[0],
772.5817 - 					    box->y2 + op->src.offset[1],
772.5818 -@@ -1292,6 +1312,7 @@ gen3_emit_composite_primitive_constant_identity_mask__sse2(struct sna *sna,
772.5819 - 
772.5820 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5821 - 	sna->render.vertex_used += 12;
772.5822 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5823 - 
772.5824 - 	v[8] = v[4] = r->dst.x + op->dst.x;
772.5825 - 	v[0] = v[4] + w;
772.5826 -@@ -1317,6 +1338,7 @@ gen3_emit_composite_primitive_constant_identity_mask_no_offset__sse2(struct sna
772.5827 - 
772.5828 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5829 - 	sna->render.vertex_used += 12;
772.5830 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5831 - 
772.5832 - 	v[8] = v[4] = r->dst.x;
772.5833 - 	v[9] = r->dst.y;
772.5834 -@@ -1353,6 +1375,7 @@ gen3_emit_composite_primitive_identity_source_mask__sse2(struct sna *sna,
772.5835 - 
772.5836 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5837 - 	sna->render.vertex_used += 18;
772.5838 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5839 - 
772.5840 - 	v[0] = dst_x + w;
772.5841 - 	v[1] = dst_y + h;
772.5842 -@@ -1398,6 +1421,7 @@ gen3_emit_composite_primitive_affine_source_mask__sse2(struct sna *sna,
772.5843 - 
772.5844 - 	v = sna->render.vertices + sna->render.vertex_used;
772.5845 - 	sna->render.vertex_used += 18;
772.5846 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5847 - 
772.5848 - 	v[0] = dst_x + w;
772.5849 - 	v[1] = dst_y + h;
772.5850 -@@ -2233,6 +2257,7 @@ static void gen3_vertex_flush(struct sna *sna)
772.5851 - static int gen3_vertex_finish(struct sna *sna)
772.5852 - {
772.5853 - 	struct kgem_bo *bo;
772.5854 -+	unsigned hint, size;
772.5855 - 
772.5856 - 	DBG(("%s: used=%d/%d, vbo active? %d\n",
772.5857 - 	     __FUNCTION__, sna->render.vertex_used, sna->render.vertex_size,
772.5858 -@@ -2243,6 +2268,7 @@ static int gen3_vertex_finish(struct sna *sna)
772.5859 - 
772.5860 - 	sna_vertex_wait__locked(&sna->render);
772.5861 - 
772.5862 -+	hint = CREATE_GTT_MAP;
772.5863 - 	bo = sna->render.vbo;
772.5864 - 	if (bo) {
772.5865 - 		DBG(("%s: reloc = %d\n", __FUNCTION__,
772.5866 -@@ -2251,7 +2277,7 @@ static int gen3_vertex_finish(struct sna *sna)
772.5867 - 		if (sna->render.vertex_reloc[0]) {
772.5868 - 			sna->kgem.batch[sna->render.vertex_reloc[0]] =
772.5869 - 				kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
772.5870 --					       bo, I915_GEM_DOMAIN_VERTEX << 16, 0);
772.5871 -+					       bo, I915_GEM_DOMAIN_VERTEX << 16 | KGEM_RELOC_FENCED, 0);
772.5872 - 
772.5873 - 			sna->render.vertex_reloc[0] = 0;
772.5874 - 		}
772.5875 -@@ -2260,17 +2286,29 @@ static int gen3_vertex_finish(struct sna *sna)
772.5876 - 		sna->render.vbo = NULL;
772.5877 - 
772.5878 - 		kgem_bo_destroy(&sna->kgem, bo);
772.5879 -+		hint |= CREATE_CACHED | CREATE_NO_THROTTLE;
772.5880 - 	}
772.5881 - 
772.5882 -+	size = 256*1024;
772.5883 - 	sna->render.vertices = NULL;
772.5884 --	sna->render.vbo = kgem_create_linear(&sna->kgem,
772.5885 --					     256*1024, CREATE_GTT_MAP);
772.5886 --	if (sna->render.vbo)
772.5887 -+	sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
772.5888 -+	while (sna->render.vbo == NULL && size > sizeof(sna->render.vertex_data)) {
772.5889 -+		size /= 2;
772.5890 -+		sna->render.vbo = kgem_create_linear(&sna->kgem, size, hint);
772.5891 -+	}
772.5892 -+	if (sna->render.vbo == NULL)
772.5893 -+		sna->render.vbo = kgem_create_linear(&sna->kgem,
772.5894 -+						     256*1024, CREATE_GTT_MAP);
772.5895 -+	if (sna->render.vbo &&
772.5896 -+	    kgem_check_bo(&sna->kgem, sna->render.vbo, NULL))
772.5897 - 		sna->render.vertices = kgem_bo_map(&sna->kgem, sna->render.vbo);
772.5898 - 	if (sna->render.vertices == NULL) {
772.5899 --		if (sna->render.vbo)
772.5900 -+		if (sna->render.vbo) {
772.5901 - 			kgem_bo_destroy(&sna->kgem, sna->render.vbo);
772.5902 --		sna->render.vbo = NULL;
772.5903 -+			sna->render.vbo = NULL;
772.5904 -+		}
772.5905 -+		sna->render.vertices = sna->render.vertex_data;
772.5906 -+		sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
772.5907 - 		return 0;
772.5908 - 	}
772.5909 - 	assert(sna->render.vbo->snoop == false);
772.5910 -@@ -2280,8 +2318,14 @@ static int gen3_vertex_finish(struct sna *sna)
772.5911 - 		       sna->render.vertex_data,
772.5912 - 		       sizeof(float)*sna->render.vertex_used);
772.5913 - 	}
772.5914 --	sna->render.vertex_size = 64 * 1024 - 1;
772.5915 --	return sna->render.vertex_size - sna->render.vertex_used;
772.5916 -+
772.5917 -+	size = __kgem_bo_size(sna->render.vbo)/4;
772.5918 -+	if (size >= UINT16_MAX)
772.5919 -+		size = UINT16_MAX - 1;
772.5920 -+	assert(size > sna->render.vertex_used);
772.5921 -+
772.5922 -+	sna->render.vertex_size = size;
772.5923 -+	return size - sna->render.vertex_used;
772.5924 - }
772.5925 - 
772.5926 - static void gen3_vertex_close(struct sna *sna)
772.5927 -@@ -2345,7 +2389,7 @@ static void gen3_vertex_close(struct sna *sna)
772.5928 - 	DBG(("%s: reloc = %d\n", __FUNCTION__, sna->render.vertex_reloc[0]));
772.5929 - 	sna->kgem.batch[sna->render.vertex_reloc[0]] =
772.5930 - 		kgem_add_reloc(&sna->kgem, sna->render.vertex_reloc[0],
772.5931 --			       bo, I915_GEM_DOMAIN_VERTEX << 16, delta);
772.5932 -+			       bo, I915_GEM_DOMAIN_VERTEX << 16 | KGEM_RELOC_FENCED, delta);
772.5933 - 	sna->render.vertex_reloc[0] = 0;
772.5934 - 
772.5935 - 	if (sna->render.vbo == NULL) {
772.5936 -@@ -2580,6 +2624,7 @@ gen3_render_composite_boxes(struct sna *sna,
772.5937 - 
772.5938 - 		v = sna->render.vertices + sna->render.vertex_used;
772.5939 - 		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
772.5940 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5941 - 
772.5942 - 		op->emit_boxes(op, box, nbox_this_time, v);
772.5943 - 		box += nbox_this_time;
772.5944 -@@ -2604,6 +2649,7 @@ gen3_render_composite_boxes__thread(struct sna *sna,
772.5945 - 
772.5946 - 		v = sna->render.vertices + sna->render.vertex_used;
772.5947 - 		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
772.5948 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.5949 - 
772.5950 - 		sna_vertex_acquire__locked(&sna->render);
772.5951 - 		sna_vertex_unlock(&sna->render);
772.5952 -@@ -3065,7 +3111,7 @@ gen3_composite_picture(struct sna *sna,
772.5953 - 
772.5954 - 	if (sna_picture_is_clear(picture, x, y, w, h, &color)) {
772.5955 - 		DBG(("%s: clear drawable [%08x]\n", __FUNCTION__, color));
772.5956 --		return gen3_init_solid(channel, color_convert(color, picture->format, PICT_a8r8g8b8));
772.5957 -+		return gen3_init_solid(channel, solid_color(picture->format, color));
772.5958 - 	}
772.5959 - 
772.5960 - 	if (!gen3_check_repeat(picture))
772.5961 -@@ -3097,12 +3143,12 @@ gen3_composite_picture(struct sna *sna,
772.5962 - 		if (channel->repeat ||
772.5963 - 		    (x >= 0 &&
772.5964 - 		     y >= 0 &&
772.5965 --		     x + w < pixmap->drawable.width &&
772.5966 --		     y + h < pixmap->drawable.height)) {
772.5967 -+		     x + w <= pixmap->drawable.width &&
772.5968 -+		     y + h <= pixmap->drawable.height)) {
772.5969 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.5970 - 			if (priv && priv->clear) {
772.5971 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.5972 --				return gen3_init_solid(channel, priv->clear_color);
772.5973 -+				return gen3_init_solid(channel, solid_color(picture->format, priv->clear_color));
772.5974 - 			}
772.5975 - 		}
772.5976 - 	} else {
772.5977 -@@ -3182,7 +3228,9 @@ gen3_composite_set_target(struct sna *sna,
772.5978 - 	} else
772.5979 - 		sna_render_picture_extents(dst, &box);
772.5980 - 
772.5981 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.5982 -+	hint = PREFER_GPU | RENDER_GPU;
772.5983 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.5984 -+		hint |= FORCE_GPU;
772.5985 - 	if (!partial) {
772.5986 - 		hint |= IGNORE_DAMAGE;
772.5987 - 		if (w == op->dst.width && h == op->dst.height)
772.5988 -@@ -3645,8 +3693,11 @@ gen3_render_composite(struct sna *sna,
772.5989 - 			}
772.5990 - 		}
772.5991 - 	}
772.5992 --	DBG(("%s: final src/mask type=%d/%d, affine=%d/%d\n", __FUNCTION__,
772.5993 -+	DBG(("%s: final src/mask type=%d/%d [constant? %d/%d], transform? %d/%d, affine=%d/%d\n", __FUNCTION__,
772.5994 - 	     tmp->src.u.gen3.type, tmp->mask.u.gen3.type,
772.5995 -+	     is_constant_ps(tmp->src.u.gen3.type),
772.5996 -+	     is_constant_ps(tmp->mask.u.gen3.type),
772.5997 -+	     !!tmp->src.transform, !!tmp->mask.transform,
772.5998 - 	     tmp->src.is_affine, tmp->mask.is_affine));
772.5999 - 
772.6000 - 	tmp->prim_emit = gen3_emit_composite_primitive;
772.6001 -@@ -3862,6 +3913,7 @@ gen3_emit_composite_spans_primitive_zero(struct sna *sna,
772.6002 - {
772.6003 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6004 - 	sna->render.vertex_used += 6;
772.6005 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6006 - 
772.6007 - 	v[0] = op->base.dst.x + box->x2;
772.6008 - 	v[1] = op->base.dst.y + box->y2;
772.6009 -@@ -3901,6 +3953,7 @@ gen3_emit_composite_spans_primitive_zero_no_offset(struct sna *sna,
772.6010 - {
772.6011 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6012 - 	sna->render.vertex_used += 6;
772.6013 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6014 - 
772.6015 - 	v[0] = box->x2;
772.6016 - 	v[3] = v[1] = box->y2;
772.6017 -@@ -3932,6 +3985,7 @@ gen3_emit_composite_spans_primitive_constant(struct sna *sna,
772.6018 - {
772.6019 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6020 - 	sna->render.vertex_used += 9;
772.6021 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6022 - 
772.6023 - 	v[0] = op->base.dst.x + box->x2;
772.6024 - 	v[6] = v[3] = op->base.dst.x + box->x1;
772.6025 -@@ -3966,6 +4020,7 @@ gen3_emit_composite_spans_primitive_constant_no_offset(struct sna *sna,
772.6026 - {
772.6027 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6028 - 	sna->render.vertex_used += 9;
772.6029 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6030 - 
772.6031 - 	v[0] = box->x2;
772.6032 - 	v[6] = v[3] = box->x1;
772.6033 -@@ -3999,6 +4054,7 @@ gen3_emit_composite_spans_primitive_identity_source(struct sna *sna,
772.6034 - {
772.6035 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6036 - 	sna->render.vertex_used += 15;
772.6037 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6038 - 
772.6039 - 	v[0] = op->base.dst.x + box->x2;
772.6040 - 	v[1] = op->base.dst.y + box->y2;
772.6041 -@@ -4060,6 +4116,7 @@ gen3_emit_composite_spans_primitive_affine_source(struct sna *sna,
772.6042 - 
772.6043 - 	v = sna->render.vertices + sna->render.vertex_used;
772.6044 - 	sna->render.vertex_used += 15;
772.6045 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6046 - 
772.6047 - 	v[0]  = op->base.dst.x + box->x2;
772.6048 - 	v[6]  = v[1] = op->base.dst.y + box->y2;
772.6049 -@@ -4125,6 +4182,7 @@ gen3_emit_composite_spans_primitive_identity_gradient(struct sna *sna,
772.6050 - {
772.6051 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6052 - 	sna->render.vertex_used += 15;
772.6053 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6054 - 
772.6055 - 	v[0] = op->base.dst.x + box->x2;
772.6056 - 	v[1] = op->base.dst.y + box->y2;
772.6057 -@@ -4184,6 +4242,7 @@ gen3_emit_composite_spans_primitive_constant__sse2(struct sna *sna,
772.6058 - {
772.6059 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6060 - 	sna->render.vertex_used += 9;
772.6061 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6062 - 
772.6063 - 	v[0] = op->base.dst.x + box->x2;
772.6064 - 	v[6] = v[3] = op->base.dst.x + box->x1;
772.6065 -@@ -4229,6 +4288,7 @@ gen3_render_composite_spans_constant_box__sse2(struct sna *sna,
772.6066 - 
772.6067 - 	v = sna->render.vertices + sna->render.vertex_used;
772.6068 - 	sna->render.vertex_used += 9;
772.6069 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6070 - 
772.6071 - 	v[0] = box->x2;
772.6072 - 	v[6] = v[3] = box->x1;
772.6073 -@@ -4259,6 +4319,7 @@ gen3_render_composite_spans_constant_thread__sse2__boxes(struct sna *sna,
772.6074 - 
772.6075 - 		v = sna->render.vertices + sna->render.vertex_used;
772.6076 - 		sna->render.vertex_used += nbox_this_time * 9;
772.6077 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6078 - 
772.6079 - 		sna_vertex_acquire__locked(&sna->render);
772.6080 - 		sna_vertex_unlock(&sna->render);
772.6081 -@@ -4287,6 +4348,7 @@ gen3_emit_composite_spans_primitive_constant__sse2__no_offset(struct sna *sna,
772.6082 - {
772.6083 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6084 - 	sna->render.vertex_used += 9;
772.6085 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6086 - 
772.6087 - 	v[0] = box->x2;
772.6088 - 	v[6] = v[3] = box->x1;
772.6089 -@@ -4320,6 +4382,7 @@ gen3_emit_composite_spans_primitive_identity_source__sse2(struct sna *sna,
772.6090 - {
772.6091 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6092 - 	sna->render.vertex_used += 15;
772.6093 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6094 - 
772.6095 - 	v[0] = op->base.dst.x + box->x2;
772.6096 - 	v[1] = op->base.dst.y + box->y2;
772.6097 -@@ -4380,6 +4443,7 @@ gen3_emit_composite_spans_primitive_affine_source__sse2(struct sna *sna,
772.6098 - 
772.6099 - 	v = sna->render.vertices + sna->render.vertex_used;
772.6100 - 	sna->render.vertex_used += 15;
772.6101 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6102 - 
772.6103 - 	v[0]  = op->base.dst.x + box->x2;
772.6104 - 	v[6]  = v[1] = op->base.dst.y + box->y2;
772.6105 -@@ -4445,6 +4509,7 @@ gen3_emit_composite_spans_primitive_identity_gradient__sse2(struct sna *sna,
772.6106 - {
772.6107 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6108 - 	sna->render.vertex_used += 15;
772.6109 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6110 - 
772.6111 - 	v[0] = op->base.dst.x + box->x2;
772.6112 - 	v[1] = op->base.dst.y + box->y2;
772.6113 -@@ -4504,6 +4569,7 @@ gen3_emit_composite_spans_primitive_affine_gradient__sse2(struct sna *sna,
772.6114 - 	PictTransform *transform = op->base.src.transform;
772.6115 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6116 - 	sna->render.vertex_used += 15;
772.6117 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6118 - 
772.6119 - 	v[0] = op->base.dst.x + box->x2;
772.6120 - 	v[1] = op->base.dst.y + box->y2;
772.6121 -@@ -4577,6 +4643,7 @@ gen3_emit_composite_spans_primitive_affine_gradient(struct sna *sna,
772.6122 - 	PictTransform *transform = op->base.src.transform;
772.6123 - 	float *v = sna->render.vertices + sna->render.vertex_used;
772.6124 - 	sna->render.vertex_used += 15;
772.6125 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6126 - 
772.6127 - 	v[0] = op->base.dst.x + box->x2;
772.6128 - 	v[1] = op->base.dst.y + box->y2;
772.6129 -@@ -4676,6 +4743,7 @@ gen3_render_composite_spans_constant_box(struct sna *sna,
772.6130 - 
772.6131 - 	v = sna->render.vertices + sna->render.vertex_used;
772.6132 - 	sna->render.vertex_used += 9;
772.6133 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6134 - 
772.6135 - 	v[0] = box->x2;
772.6136 - 	v[6] = v[3] = box->x1;
772.6137 -@@ -4706,6 +4774,7 @@ gen3_render_composite_spans_constant_thread_boxes(struct sna *sna,
772.6138 - 
772.6139 - 		v = sna->render.vertices + sna->render.vertex_used;
772.6140 - 		sna->render.vertex_used += nbox_this_time * 9;
772.6141 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6142 - 
772.6143 - 		sna_vertex_acquire__locked(&sna->render);
772.6144 - 		sna_vertex_unlock(&sna->render);
772.6145 -@@ -4795,6 +4864,7 @@ gen3_render_composite_spans_boxes__thread(struct sna *sna,
772.6146 - 
772.6147 - 		v = sna->render.vertices + sna->render.vertex_used;
772.6148 - 		sna->render.vertex_used += nbox_this_time * op->base.floats_per_rect;
772.6149 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.6150 - 
772.6151 - 		sna_vertex_acquire__locked(&sna->render);
772.6152 - 		sna_vertex_unlock(&sna->render);
772.6153 -@@ -5436,17 +5506,7 @@ gen3_render_video(struct sna *sna,
772.6154 - 		pix_yoff = -dstRegion->extents.y1;
772.6155 - 		copy = 1;
772.6156 - 	} else {
772.6157 --		/* Set up the offset for translating from the given region
772.6158 --		 * (in screen coordinates) to the backing pixmap.
772.6159 --		 */
772.6160 --#ifdef COMPOSITE
772.6161 --		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.6162 --		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.6163 --#else
772.6164 --		pix_xoff = 0;
772.6165 --		pix_yoff = 0;
772.6166 --#endif
772.6167 --
772.6168 -+		pix_xoff = pix_yoff = 0;
772.6169 - 		dst_width  = pixmap->drawable.width;
772.6170 - 		dst_height = pixmap->drawable.height;
772.6171 - 	}
772.6172 -@@ -5502,16 +5562,9 @@ gen3_render_video(struct sna *sna,
772.6173 - 	} while (nbox);
772.6174 - 
772.6175 - 	if (copy) {
772.6176 --#ifdef COMPOSITE
772.6177 --		pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.6178 --		pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.6179 --#else
772.6180 --		pix_xoff = 0;
772.6181 --		pix_yoff = 0;
772.6182 --#endif
772.6183 - 		sna_blt_copy_boxes(sna, GXcopy,
772.6184 - 				   dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1,
772.6185 --				   priv->gpu_bo, pix_xoff, pix_yoff,
772.6186 -+				   priv->gpu_bo, 0, 0,
772.6187 - 				   pixmap->drawable.bitsPerPixel,
772.6188 - 				   region_rects(dstRegion),
772.6189 - 				   region_num_rects(dstRegion));
772.6190 -@@ -5519,21 +5572,8 @@ gen3_render_video(struct sna *sna,
772.6191 - 		kgem_bo_destroy(&sna->kgem, dst_bo);
772.6192 - 	}
772.6193 - 
772.6194 --	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.6195 --		if ((pix_xoff | pix_yoff) == 0) {
772.6196 --			sna_damage_add(&priv->gpu_damage, dstRegion);
772.6197 --			sna_damage_subtract(&priv->cpu_damage, dstRegion);
772.6198 --		} else {
772.6199 --			sna_damage_add_boxes(&priv->gpu_damage,
772.6200 --					     region_rects(dstRegion),
772.6201 --					     region_num_rects(dstRegion),
772.6202 --					     pix_xoff, pix_yoff);
772.6203 --			sna_damage_subtract_boxes(&priv->cpu_damage,
772.6204 --						  region_rects(dstRegion),
772.6205 --						  region_num_rects(dstRegion),
772.6206 --						  pix_xoff, pix_yoff);
772.6207 --		}
772.6208 --	}
772.6209 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.6210 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.6211 - 
772.6212 - 	return true;
772.6213 - }
772.6214 -diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
772.6215 -index 6c2d3808..72a98aee 100644
772.6216 ---- a/src/sna/gen4_render.c
772.6217 -+++ b/src/sna/gen4_render.c
772.6218 -@@ -1405,8 +1405,8 @@ gen4_render_video(struct sna *sna,
772.6219 - 	int src_height = frame->src.y2 - frame->src.y1;
772.6220 - 	float src_offset_x, src_offset_y;
772.6221 - 	float src_scale_x, src_scale_y;
772.6222 --	int nbox, pix_xoff, pix_yoff;
772.6223 - 	const BoxRec *box;
772.6224 -+	int nbox;
772.6225 - 
772.6226 - 	DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__,
772.6227 - 	     src_width, src_height, dst_width, dst_height));
772.6228 -@@ -1445,17 +1445,6 @@ gen4_render_video(struct sna *sna,
772.6229 - 	gen4_align_vertex(sna, &tmp);
772.6230 - 	gen4_video_bind_surfaces(sna, &tmp);
772.6231 - 
772.6232 --	/* Set up the offset for translating from the given region (in screen
772.6233 --	 * coordinates) to the backing pixmap.
772.6234 --	 */
772.6235 --#ifdef COMPOSITE
772.6236 --	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.6237 --	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.6238 --#else
772.6239 --	pix_xoff = 0;
772.6240 --	pix_yoff = 0;
772.6241 --#endif
772.6242 --
772.6243 - 	src_scale_x = (float)src_width / dst_width / frame->width;
772.6244 - 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
772.6245 - 
772.6246 -@@ -1473,34 +1462,26 @@ gen4_render_video(struct sna *sna,
772.6247 - 		nbox -= n;
772.6248 - 
772.6249 - 		do {
772.6250 --			BoxRec r;
772.6251 --
772.6252 --			r.x1 = box->x1 + pix_xoff;
772.6253 --			r.x2 = box->x2 + pix_xoff;
772.6254 --			r.y1 = box->y1 + pix_yoff;
772.6255 --			r.y2 = box->y2 + pix_yoff;
772.6256 --
772.6257 --			OUT_VERTEX(r.x2, r.y2);
772.6258 -+			OUT_VERTEX(box->x2, box->y2);
772.6259 - 			OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.6260 - 			OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6261 - 
772.6262 --			OUT_VERTEX(r.x1, r.y2);
772.6263 -+			OUT_VERTEX(box->x1, box->y2);
772.6264 - 			OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6265 - 			OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6266 - 
772.6267 --			OUT_VERTEX(r.x1, r.y1);
772.6268 -+			OUT_VERTEX(box->x1, box->y1);
772.6269 - 			OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6270 - 			OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.6271 - 
772.6272 --			if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.6273 --				sna_damage_add_box(&priv->gpu_damage, &r);
772.6274 --				sna_damage_subtract_box(&priv->cpu_damage, &r);
772.6275 --			}
772.6276 - 			box++;
772.6277 - 		} while (--n);
772.6278 - 	} while (nbox);
772.6279 - 	gen4_vertex_flush(sna);
772.6280 - 
772.6281 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.6282 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.6283 -+
772.6284 - 	return true;
772.6285 - }
772.6286 - 
772.6287 -@@ -1585,12 +1566,14 @@ gen4_composite_picture(struct sna *sna,
772.6288 - 		if (channel->repeat &&
772.6289 - 		    (x >= 0 &&
772.6290 - 		     y >= 0 &&
772.6291 --		     x + w < pixmap->drawable.width &&
772.6292 --		     y + h < pixmap->drawable.height)) {
772.6293 -+		     x + w <= pixmap->drawable.width &&
772.6294 -+		     y + h <= pixmap->drawable.height)) {
772.6295 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.6296 - 			if (priv && priv->clear) {
772.6297 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.6298 --				return gen4_channel_init_solid(sna, channel, priv->clear_color);
772.6299 -+				return gen4_channel_init_solid(sna, channel,
772.6300 -+							       solid_color(picture->format,
772.6301 -+									   priv->clear_color));
772.6302 - 			}
772.6303 - 		}
772.6304 - 	} else
772.6305 -@@ -1664,7 +1647,9 @@ gen4_composite_set_target(struct sna *sna,
772.6306 - 	} else
772.6307 - 		sna_render_picture_extents(dst, &box);
772.6308 - 
772.6309 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.6310 -+	hint = PREFER_GPU | RENDER_GPU;
772.6311 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.6312 -+		hint |= FORCE_GPU;
772.6313 - 	if (!partial) {
772.6314 - 		hint |= IGNORE_DAMAGE;
772.6315 - 		if (w == op->dst.width && h == op->dst.height)
772.6316 -@@ -2738,6 +2723,20 @@ gen4_render_fill_boxes(struct sna *sna,
772.6317 - 	tmp.dst.format = format;
772.6318 - 	tmp.dst.bo = dst_bo;
772.6319 - 
772.6320 -+	sna_render_composite_redirect_init(&tmp);
772.6321 -+	if (too_large(dst->width, dst->height)) {
772.6322 -+		BoxRec extents;
772.6323 -+
772.6324 -+		boxes_extents(box, n, &extents);
772.6325 -+		if (!sna_render_composite_redirect(sna, &tmp,
772.6326 -+						   extents.x1, extents.y1,
772.6327 -+						   extents.x2 - extents.x1,
772.6328 -+						   extents.y2 - extents.y1,
772.6329 -+						   n > 1))
772.6330 -+			return sna_tiling_fill_boxes(sna, op, format, color,
772.6331 -+						     dst, dst_bo, box, n);
772.6332 -+	}
772.6333 -+
772.6334 - 	gen4_channel_init_solid(sna, &tmp.src, pixel);
772.6335 - 
772.6336 - 	tmp.is_affine = true;
772.6337 -@@ -2748,8 +2747,10 @@ gen4_render_fill_boxes(struct sna *sna,
772.6338 - 
772.6339 - 	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.6340 - 		kgem_submit(&sna->kgem);
772.6341 --		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL))
772.6342 -+		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.6343 -+			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.6344 - 			return false;
772.6345 -+		}
772.6346 - 	}
772.6347 - 
772.6348 - 	gen4_align_vertex(sna, &tmp);
772.6349 -@@ -2765,6 +2766,7 @@ gen4_render_fill_boxes(struct sna *sna,
772.6350 - 
772.6351 - 	gen4_vertex_flush(sna);
772.6352 - 	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.6353 -+	sna_render_composite_redirect_done(sna, &tmp);
772.6354 - 	return true;
772.6355 - }
772.6356 - 
772.6357 -diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
772.6358 -index 37cf1ff9..fb3e79bf 100644
772.6359 ---- a/src/sna/gen5_render.c
772.6360 -+++ b/src/sna/gen5_render.c
772.6361 -@@ -1355,8 +1355,8 @@ gen5_render_video(struct sna *sna,
772.6362 - 	int src_height = frame->src.y2 - frame->src.y1;
772.6363 - 	float src_offset_x, src_offset_y;
772.6364 - 	float src_scale_x, src_scale_y;
772.6365 --	int nbox, pix_xoff, pix_yoff;
772.6366 - 	const BoxRec *box;
772.6367 -+	int nbox;
772.6368 - 
772.6369 - 	DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__,
772.6370 - 	     src_width, src_height, dst_width, dst_height));
772.6371 -@@ -1395,17 +1395,6 @@ gen5_render_video(struct sna *sna,
772.6372 - 	gen5_align_vertex(sna, &tmp);
772.6373 - 	gen5_video_bind_surfaces(sna, &tmp);
772.6374 - 
772.6375 --	/* Set up the offset for translating from the given region (in screen
772.6376 --	 * coordinates) to the backing pixmap.
772.6377 --	 */
772.6378 --#ifdef COMPOSITE
772.6379 --	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.6380 --	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.6381 --#else
772.6382 --	pix_xoff = 0;
772.6383 --	pix_yoff = 0;
772.6384 --#endif
772.6385 --
772.6386 - 	src_scale_x = (float)src_width / dst_width / frame->width;
772.6387 - 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
772.6388 - 
772.6389 -@@ -1415,35 +1404,27 @@ gen5_render_video(struct sna *sna,
772.6390 - 	box = region_rects(dstRegion);
772.6391 - 	nbox = region_num_rects(dstRegion);
772.6392 - 	while (nbox--) {
772.6393 --		BoxRec r;
772.6394 --
772.6395 --		r.x1 = box->x1 + pix_xoff;
772.6396 --		r.x2 = box->x2 + pix_xoff;
772.6397 --		r.y1 = box->y1 + pix_yoff;
772.6398 --		r.y2 = box->y2 + pix_yoff;
772.6399 --
772.6400 - 		gen5_get_rectangles(sna, &tmp, 1, gen5_video_bind_surfaces);
772.6401 - 
772.6402 --		OUT_VERTEX(r.x2, r.y2);
772.6403 -+		OUT_VERTEX(box->x2, box->y2);
772.6404 - 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.6405 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6406 - 
772.6407 --		OUT_VERTEX(r.x1, r.y2);
772.6408 -+		OUT_VERTEX(box->x1, box->y2);
772.6409 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6410 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6411 - 
772.6412 --		OUT_VERTEX(r.x1, r.y1);
772.6413 -+		OUT_VERTEX(box->x1, box->y1);
772.6414 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6415 - 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.6416 - 
772.6417 --		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.6418 --			sna_damage_add_box(&priv->gpu_damage, &r);
772.6419 --			sna_damage_subtract_box(&priv->cpu_damage, &r);
772.6420 --		}
772.6421 - 		box++;
772.6422 - 	}
772.6423 --
772.6424 - 	gen4_vertex_flush(sna);
772.6425 -+
772.6426 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.6427 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.6428 -+
772.6429 - 	return true;
772.6430 - }
772.6431 - 
772.6432 -@@ -1524,12 +1505,12 @@ gen5_composite_picture(struct sna *sna,
772.6433 - 		if (channel->repeat ||
772.6434 - 		    (x >= 0 &&
772.6435 - 		     y >= 0 &&
772.6436 --		     x + w < pixmap->drawable.width &&
772.6437 --		     y + h < pixmap->drawable.height)) {
772.6438 -+		     x + w <= pixmap->drawable.width &&
772.6439 -+		     y + h <= pixmap->drawable.height)) {
772.6440 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.6441 - 			if (priv && priv->clear) {
772.6442 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.6443 --				return gen4_channel_init_solid(sna, channel, priv->clear_color);
772.6444 -+				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
772.6445 - 			}
772.6446 - 		}
772.6447 - 	} else
772.6448 -@@ -1618,7 +1599,9 @@ gen5_composite_set_target(struct sna *sna,
772.6449 - 	} else
772.6450 - 		sna_render_picture_extents(dst, &box);
772.6451 - 
772.6452 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.6453 -+	hint = PREFER_GPU | RENDER_GPU;
772.6454 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.6455 -+		hint |= FORCE_GPU;
772.6456 - 	if (!partial) {
772.6457 - 		hint |= IGNORE_DAMAGE;
772.6458 - 		if (w == op->dst.width && h == op->dst.height)
772.6459 -@@ -2734,6 +2717,19 @@ gen5_render_fill_boxes(struct sna *sna,
772.6460 - 	tmp.dst.format = format;
772.6461 - 	tmp.dst.bo = dst_bo;
772.6462 - 
772.6463 -+	if (too_large(dst->width, dst->height)) {
772.6464 -+		BoxRec extents;
772.6465 -+
772.6466 -+		boxes_extents(box, n, &extents);
772.6467 -+		if (!sna_render_composite_redirect(sna, &tmp,
772.6468 -+						   extents.x1, extents.y1,
772.6469 -+						   extents.x2 - extents.x1,
772.6470 -+						   extents.y2 - extents.y1,
772.6471 -+						   n > 1))
772.6472 -+			return sna_tiling_fill_boxes(sna, op, format, color,
772.6473 -+						     dst, dst_bo, box, n);
772.6474 -+	}
772.6475 -+
772.6476 - 	tmp.src.bo = sna_render_get_solid(sna, pixel);
772.6477 - 	tmp.src.filter = SAMPLER_FILTER_NEAREST;
772.6478 - 	tmp.src.repeat = SAMPLER_EXTEND_REPEAT;
772.6479 -@@ -2780,6 +2776,7 @@ gen5_render_fill_boxes(struct sna *sna,
772.6480 - 
772.6481 - 	gen4_vertex_flush(sna);
772.6482 - 	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.6483 -+	sna_render_composite_redirect_done(sna, &tmp);
772.6484 - 	return true;
772.6485 - }
772.6486 - 
772.6487 -diff --git a/src/sna/gen6_common.h b/src/sna/gen6_common.h
772.6488 -index 6668620b..b53ec0c9 100644
772.6489 ---- a/src/sna/gen6_common.h
772.6490 -+++ b/src/sna/gen6_common.h
772.6491 -@@ -30,8 +30,8 @@
772.6492 - 
772.6493 - #include "sna.h"
772.6494 - 
772.6495 --#define NO_RING_SWITCH 0
772.6496 --#define PREFER_RENDER 0
772.6497 -+#define NO_RING_SWITCH(sna) (!(sna)->kgem.has_semaphores)
772.6498 -+#define PREFER_RENDER 0 /* -1 -> BLT, 1 -> RENDER */
772.6499 - 
772.6500 - static inline bool is_uncached(struct sna *sna,
772.6501 - 			       struct kgem_bo *bo)
772.6502 -@@ -46,40 +46,28 @@ inline static bool can_switch_to_blt(struct sna *sna,
772.6503 - 	if (sna->kgem.ring != KGEM_RENDER)
772.6504 - 		return true;
772.6505 - 
772.6506 --	if (NO_RING_SWITCH)
772.6507 --		return false;
772.6508 --
772.6509 --	if (!sna->kgem.has_semaphores)
772.6510 --		return false;
772.6511 --
772.6512 --	if (flags & COPY_LAST)
772.6513 --		return true;
772.6514 --
772.6515 - 	if (bo && RQ_IS_BLT(bo->rq))
772.6516 - 		return true;
772.6517 - 
772.6518 --	if (sna->render_state.gt < 2)
772.6519 --		return true;
772.6520 -+	if (bo && bo->tiling == I915_TILING_Y)
772.6521 -+		return false;
772.6522 - 
772.6523 --	return kgem_ring_is_idle(&sna->kgem, KGEM_BLT);
772.6524 --}
772.6525 -+	if (bo && !kgem_bo_can_blt(&sna->kgem, bo))
772.6526 -+		return false;
772.6527 - 
772.6528 --inline static bool can_switch_to_render(struct sna *sna,
772.6529 --					struct kgem_bo *bo)
772.6530 --{
772.6531 --	if (sna->kgem.ring == KGEM_RENDER)
772.6532 -+	if (sna->render_state.gt < 2)
772.6533 - 		return true;
772.6534 - 
772.6535 --	if (NO_RING_SWITCH)
772.6536 -+	if (bo && RQ_IS_RENDER(bo->rq))
772.6537 - 		return false;
772.6538 - 
772.6539 --	if (!sna->kgem.has_semaphores)
772.6540 -+	if (NO_RING_SWITCH(sna))
772.6541 - 		return false;
772.6542 - 
772.6543 --	if (bo && !RQ_IS_BLT(bo->rq) && !is_uncached(sna, bo))
772.6544 -+	if (flags & COPY_LAST)
772.6545 - 		return true;
772.6546 - 
772.6547 --	return !kgem_ring_is_idle(&sna->kgem, KGEM_RENDER);
772.6548 -+	return kgem_ring_is_idle(&sna->kgem, KGEM_BLT);
772.6549 - }
772.6550 - 
772.6551 - static inline bool untiled_tlb_miss(struct kgem_bo *bo)
772.6552 -@@ -90,57 +78,95 @@ static inline bool untiled_tlb_miss(struct kgem_bo *bo)
772.6553 - 	return bo->tiling == I915_TILING_NONE && bo->pitch >= 4096;
772.6554 - }
772.6555 - 
772.6556 --static int prefer_blt_bo(struct sna *sna, struct kgem_bo *bo)
772.6557 -+static int prefer_blt_bo(struct sna *sna,
772.6558 -+			 struct kgem_bo *src,
772.6559 -+			 struct kgem_bo *dst)
772.6560 - {
772.6561 -+	assert(dst != NULL);
772.6562 -+
772.6563 - 	if (PREFER_RENDER)
772.6564 - 		return PREFER_RENDER < 0;
772.6565 - 
772.6566 --	if (bo->rq)
772.6567 --		return RQ_IS_BLT(bo->rq);
772.6568 -+	if (dst->rq)
772.6569 -+		return RQ_IS_BLT(dst->rq);
772.6570 - 
772.6571 - 	if (sna->flags & SNA_POWERSAVE)
772.6572 - 		return true;
772.6573 - 
772.6574 --	return bo->tiling == I915_TILING_NONE || is_uncached(sna, bo);
772.6575 --}
772.6576 -+	if (src) {
772.6577 -+		if (sna->render_state.gt > 1)
772.6578 -+			return false;
772.6579 - 
772.6580 --inline static bool force_blt_ring(struct sna *sna)
772.6581 --{
772.6582 --	if (sna->flags & SNA_POWERSAVE)
772.6583 -+		if (src->rq)
772.6584 -+			return RQ_IS_BLT(src->rq);
772.6585 -+
772.6586 -+		if (src->tiling == I915_TILING_Y)
772.6587 -+			return false;
772.6588 -+        } else {
772.6589 -+                if (sna->render_state.gt > 2)
772.6590 -+                        return false;
772.6591 -+        }
772.6592 -+
772.6593 -+	if (sna->render_state.gt < 2)
772.6594 - 		return true;
772.6595 - 
772.6596 -+	return dst->tiling == I915_TILING_NONE || is_uncached(sna, dst);
772.6597 -+}
772.6598 -+
772.6599 -+inline static bool force_blt_ring(struct sna *sna, struct kgem_bo *bo)
772.6600 -+{
772.6601 - 	if (sna->kgem.mode == KGEM_RENDER)
772.6602 - 		return false;
772.6603 - 
772.6604 -+	if (NO_RING_SWITCH(sna))
772.6605 -+		return sna->kgem.ring == KGEM_BLT;
772.6606 -+
772.6607 -+	if (bo->tiling == I915_TILING_Y)
772.6608 -+		return false;
772.6609 -+
772.6610 -+	if (sna->flags & SNA_POWERSAVE)
772.6611 -+		return true;
772.6612 -+
772.6613 - 	if (sna->render_state.gt < 2)
772.6614 - 		return true;
772.6615 - 
772.6616 - 	return false;
772.6617 - }
772.6618 - 
772.6619 --inline static bool prefer_blt_ring(struct sna *sna,
772.6620 --				   struct kgem_bo *bo,
772.6621 --				   unsigned flags)
772.6622 -+nonnull inline static bool
772.6623 -+prefer_blt_ring(struct sna *sna, struct kgem_bo *bo, unsigned flags)
772.6624 - {
772.6625 - 	if (PREFER_RENDER)
772.6626 - 		return PREFER_RENDER < 0;
772.6627 - 
772.6628 --	assert(!force_blt_ring(sna));
772.6629 --	assert(!kgem_bo_is_render(bo));
772.6630 -+	assert(!force_blt_ring(sna, bo));
772.6631 -+	assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna));
772.6632 -+
772.6633 -+	if (kgem_bo_is_blt(bo))
772.6634 -+		return true;
772.6635 - 
772.6636 - 	return can_switch_to_blt(sna, bo, flags);
772.6637 - }
772.6638 - 
772.6639 --inline static bool prefer_render_ring(struct sna *sna,
772.6640 --				      struct kgem_bo *bo)
772.6641 -+nonnull inline static bool
772.6642 -+prefer_render_ring(struct sna *sna, struct kgem_bo *bo)
772.6643 - {
772.6644 -+	if (sna->kgem.ring == KGEM_RENDER)
772.6645 -+		return true;
772.6646 -+
772.6647 -+	if (sna->kgem.ring != KGEM_NONE && NO_RING_SWITCH(sna))
772.6648 -+                return false;
772.6649 -+
772.6650 -+	if (kgem_bo_is_render(bo))
772.6651 -+		return true;
772.6652 -+
772.6653 - 	if (sna->flags & SNA_POWERSAVE)
772.6654 - 		return false;
772.6655 - 
772.6656 --	if (sna->render_state.gt < 2)
772.6657 --		return false;
772.6658 -+	if (!prefer_blt_bo(sna, NULL, bo))
772.6659 -+		return true;
772.6660 - 
772.6661 --	return can_switch_to_render(sna, bo);
772.6662 -+	return !kgem_ring_is_idle(&sna->kgem, KGEM_RENDER);
772.6663 - }
772.6664 - 
772.6665 - inline static bool
772.6666 -@@ -153,25 +179,20 @@ prefer_blt_composite(struct sna *sna, struct sna_composite_op *tmp)
772.6667 - 	    untiled_tlb_miss(tmp->src.bo))
772.6668 - 		return true;
772.6669 - 
772.6670 --	if (force_blt_ring(sna))
772.6671 -+	if (force_blt_ring(sna, tmp->dst.bo))
772.6672 - 		return true;
772.6673 - 
772.6674 --	if (kgem_bo_is_render(tmp->dst.bo) ||
772.6675 --	    kgem_bo_is_render(tmp->src.bo))
772.6676 --		return false;
772.6677 --
772.6678 - 	if (prefer_render_ring(sna, tmp->dst.bo))
772.6679 - 		return false;
772.6680 - 
772.6681 - 	if (!prefer_blt_ring(sna, tmp->dst.bo, 0))
772.6682 - 		return false;
772.6683 - 
772.6684 --	return prefer_blt_bo(sna, tmp->dst.bo) || prefer_blt_bo(sna, tmp->src.bo);
772.6685 -+	return prefer_blt_bo(sna, tmp->src.bo, tmp->dst.bo);
772.6686 - }
772.6687 - 
772.6688 --static inline bool prefer_blt_fill(struct sna *sna,
772.6689 --				   struct kgem_bo *bo,
772.6690 --				   unsigned flags)
772.6691 -+nonnull static inline bool
772.6692 -+prefer_blt_fill(struct sna *sna, struct kgem_bo *bo, unsigned flags)
772.6693 - {
772.6694 - 	if (PREFER_RENDER)
772.6695 - 		return PREFER_RENDER < 0;
772.6696 -@@ -179,24 +200,21 @@ static inline bool prefer_blt_fill(struct sna *sna,
772.6697 - 	if (untiled_tlb_miss(bo))
772.6698 - 		return true;
772.6699 - 
772.6700 --	if (force_blt_ring(sna))
772.6701 -+	if (force_blt_ring(sna, bo))
772.6702 - 		return true;
772.6703 - 
772.6704 - 	if ((flags & (FILL_POINTS | FILL_SPANS)) == 0) {
772.6705 --		if (kgem_bo_is_render(bo))
772.6706 --			return false;
772.6707 --
772.6708 - 		if (prefer_render_ring(sna, bo))
772.6709 - 			return false;
772.6710 - 
772.6711 - 		if (!prefer_blt_ring(sna, bo, 0))
772.6712 - 			return false;
772.6713 - 	} else {
772.6714 --	    if (can_switch_to_blt(sna, bo, 0))
772.6715 -+	    if (can_switch_to_blt(sna, bo, COPY_LAST))
772.6716 - 		    return true;
772.6717 - 	}
772.6718 - 
772.6719 --	return prefer_blt_bo(sna, bo);
772.6720 -+	return prefer_blt_bo(sna, NULL, bo);
772.6721 - }
772.6722 - 
772.6723 - void gen6_render_context_switch(struct kgem *kgem, int new_mode);
772.6724 -diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
772.6725 -index 25044685..6b69f216 100644
772.6726 ---- a/src/sna/gen6_render.c
772.6727 -+++ b/src/sna/gen6_render.c
772.6728 -@@ -1633,9 +1633,9 @@ gen6_render_video(struct sna *sna,
772.6729 - 	int src_height = frame->src.y2 - frame->src.y1;
772.6730 - 	float src_offset_x, src_offset_y;
772.6731 - 	float src_scale_x, src_scale_y;
772.6732 --	int nbox, pix_xoff, pix_yoff;
772.6733 - 	unsigned filter;
772.6734 - 	const BoxRec *box;
772.6735 -+	int nbox;
772.6736 - 
772.6737 - 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
772.6738 - 	     __FUNCTION__,
772.6739 -@@ -1686,17 +1686,6 @@ gen6_render_video(struct sna *sna,
772.6740 - 	gen6_align_vertex(sna, &tmp);
772.6741 - 	gen6_emit_video_state(sna, &tmp);
772.6742 - 
772.6743 --	/* Set up the offset for translating from the given region (in screen
772.6744 --	 * coordinates) to the backing pixmap.
772.6745 --	 */
772.6746 --#ifdef COMPOSITE
772.6747 --	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.6748 --	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.6749 --#else
772.6750 --	pix_xoff = 0;
772.6751 --	pix_yoff = 0;
772.6752 --#endif
772.6753 --
772.6754 - 	src_scale_x = (float)src_width / dst_width / frame->width;
772.6755 - 	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
772.6756 - 
772.6757 -@@ -1706,35 +1695,27 @@ gen6_render_video(struct sna *sna,
772.6758 - 	box = region_rects(dstRegion);
772.6759 - 	nbox = region_num_rects(dstRegion);
772.6760 - 	while (nbox--) {
772.6761 --		BoxRec r;
772.6762 --
772.6763 --		r.x1 = box->x1 + pix_xoff;
772.6764 --		r.x2 = box->x2 + pix_xoff;
772.6765 --		r.y1 = box->y1 + pix_yoff;
772.6766 --		r.y2 = box->y2 + pix_yoff;
772.6767 --
772.6768 - 		gen6_get_rectangles(sna, &tmp, 1, gen6_emit_video_state);
772.6769 - 
772.6770 --		OUT_VERTEX(r.x2, r.y2);
772.6771 -+		OUT_VERTEX(box->x2, box->y2);
772.6772 - 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.6773 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6774 - 
772.6775 --		OUT_VERTEX(r.x1, r.y2);
772.6776 -+		OUT_VERTEX(box->x1, box->y2);
772.6777 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6778 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.6779 - 
772.6780 --		OUT_VERTEX(r.x1, r.y1);
772.6781 -+		OUT_VERTEX(box->x1, box->y1);
772.6782 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.6783 - 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.6784 - 
772.6785 --		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.6786 --			sna_damage_add_box(&priv->gpu_damage, &r);
772.6787 --			sna_damage_subtract_box(&priv->cpu_damage, &r);
772.6788 --		}
772.6789 - 		box++;
772.6790 - 	}
772.6791 --
772.6792 - 	gen4_vertex_flush(sna);
772.6793 -+
772.6794 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.6795 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.6796 -+
772.6797 - 	return true;
772.6798 - }
772.6799 - 
772.6800 -@@ -1815,12 +1796,12 @@ gen6_composite_picture(struct sna *sna,
772.6801 - 		if (channel->repeat &&
772.6802 - 		    (x >= 0 &&
772.6803 - 		     y >= 0 &&
772.6804 --		     x + w < pixmap->drawable.width &&
772.6805 --		     y + h < pixmap->drawable.height)) {
772.6806 -+		     x + w <= pixmap->drawable.width &&
772.6807 -+		     y + h <= pixmap->drawable.height)) {
772.6808 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.6809 - 			if (priv && priv->clear) {
772.6810 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.6811 --				return gen4_channel_init_solid(sna, channel, priv->clear_color);
772.6812 -+				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
772.6813 - 			}
772.6814 - 		}
772.6815 - 	} else
772.6816 -@@ -1927,7 +1908,9 @@ gen6_composite_set_target(struct sna *sna,
772.6817 - 	} else
772.6818 - 		sna_render_picture_extents(dst, &box);
772.6819 - 
772.6820 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.6821 -+	hint = PREFER_GPU | RENDER_GPU;
772.6822 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.6823 -+		hint |= FORCE_GPU;
772.6824 - 	if (!partial) {
772.6825 - 		hint |= IGNORE_DAMAGE;
772.6826 - 		if (w == op->dst.width && h == op->dst.height)
772.6827 -@@ -1965,46 +1948,77 @@ gen6_composite_set_target(struct sna *sna,
772.6828 - 
772.6829 - static bool
772.6830 - try_blt(struct sna *sna,
772.6831 --	PicturePtr dst, PicturePtr src,
772.6832 --	int width, int height)
772.6833 -+	uint8_t op,
772.6834 -+	PicturePtr src,
772.6835 -+	PicturePtr mask,
772.6836 -+	PicturePtr dst,
772.6837 -+	int16_t src_x, int16_t src_y,
772.6838 -+	int16_t msk_x, int16_t msk_y,
772.6839 -+	int16_t dst_x, int16_t dst_y,
772.6840 -+	int16_t width, int16_t height,
772.6841 -+	unsigned flags,
772.6842 -+	struct sna_composite_op *tmp)
772.6843 - {
772.6844 - 	struct kgem_bo *bo;
772.6845 - 
772.6846 - 	if (sna->kgem.mode == KGEM_BLT) {
772.6847 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.6848 --		return true;
772.6849 -+		goto execute;
772.6850 - 	}
772.6851 - 
772.6852 - 	if (too_large(width, height)) {
772.6853 - 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
772.6854 - 		     __FUNCTION__, width, height));
772.6855 --		return true;
772.6856 -+		goto execute;
772.6857 - 	}
772.6858 - 
772.6859 - 	bo = __sna_drawable_peek_bo(dst->pDrawable);
772.6860 - 	if (bo == NULL)
772.6861 --		return true;
772.6862 --	if (bo->rq)
772.6863 --		return RQ_IS_BLT(bo->rq);
772.6864 -+		goto execute;
772.6865 -+
772.6866 -+	if (untiled_tlb_miss(bo))
772.6867 -+		goto execute;
772.6868 -+
772.6869 -+	if (bo->rq) {
772.6870 -+		if (RQ_IS_BLT(bo->rq))
772.6871 -+			goto execute;
772.6872 -+
772.6873 -+		return false;
772.6874 -+	}
772.6875 -+
772.6876 -+	if (bo->tiling == I915_TILING_Y)
772.6877 -+		goto upload;
772.6878 -+
772.6879 -+	if (src->pDrawable == dst->pDrawable &&
772.6880 -+	    can_switch_to_blt(sna, bo, 0))
772.6881 -+		goto execute;
772.6882 - 
772.6883 - 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
772.6884 --		return true;
772.6885 -+		goto execute;
772.6886 - 
772.6887 - 	if (src->pDrawable) {
772.6888 --		bo = __sna_drawable_peek_bo(src->pDrawable);
772.6889 --		if (bo == NULL)
772.6890 --			return true;
772.6891 -+		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
772.6892 -+		if (s == NULL)
772.6893 -+			goto execute;
772.6894 - 
772.6895 --		if (prefer_blt_bo(sna, bo))
772.6896 --			return true;
772.6897 -+		if (prefer_blt_bo(sna, s, bo))
772.6898 -+			goto execute;
772.6899 - 	}
772.6900 - 
772.6901 - 	if (sna->kgem.ring == KGEM_BLT) {
772.6902 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.6903 --		return true;
772.6904 -+		goto execute;
772.6905 - 	}
772.6906 - 
772.6907 --	return false;
772.6908 -+upload:
772.6909 -+	flags |= COMPOSITE_UPLOAD;
772.6910 -+execute:
772.6911 -+	return sna_blt_composite(sna, op,
772.6912 -+				 src, dst,
772.6913 -+				 src_x, src_y,
772.6914 -+				 dst_x, dst_y,
772.6915 -+				 width, height,
772.6916 -+				 flags, tmp);
772.6917 - }
772.6918 - 
772.6919 - static bool
772.6920 -@@ -2234,13 +2248,13 @@ gen6_render_composite(struct sna *sna,
772.6921 - 	     width, height, sna->kgem.ring));
772.6922 - 
772.6923 - 	if (mask == NULL &&
772.6924 --	    try_blt(sna, dst, src, width, height) &&
772.6925 --	    sna_blt_composite(sna, op,
772.6926 --			      src, dst,
772.6927 --			      src_x, src_y,
772.6928 --			      dst_x, dst_y,
772.6929 --			      width, height,
772.6930 --			      flags, tmp))
772.6931 -+	    try_blt(sna, op,
772.6932 -+		    src, mask, dst,
772.6933 -+		    src_x, src_y,
772.6934 -+		    msk_x, msk_y,
772.6935 -+		    dst_x, dst_y,
772.6936 -+		    width, height,
772.6937 -+		    flags, tmp))
772.6938 - 		return true;
772.6939 - 
772.6940 - 	if (gen6_composite_fallback(sna, src, mask, dst))
772.6941 -@@ -2676,27 +2690,35 @@ static inline bool prefer_blt_copy(struct sna *sna,
772.6942 - 	if (sna->kgem.ring == KGEM_BLT)
772.6943 - 		return true;
772.6944 - 
772.6945 --	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
772.6946 -+	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
772.6947 -+		return false;
772.6948 -+
772.6949 -+	if ((flags & COPY_SMALL || src_bo == dst_bo) &&
772.6950 -+	    can_switch_to_blt(sna, dst_bo, flags))
772.6951 - 		return true;
772.6952 - 
772.6953 - 	if (untiled_tlb_miss(src_bo) ||
772.6954 - 	    untiled_tlb_miss(dst_bo))
772.6955 - 		return true;
772.6956 - 
772.6957 --	if (force_blt_ring(sna))
772.6958 -+	if (force_blt_ring(sna, dst_bo))
772.6959 - 		return true;
772.6960 - 
772.6961 - 	if (kgem_bo_is_render(dst_bo) ||
772.6962 - 	    kgem_bo_is_render(src_bo))
772.6963 - 		return false;
772.6964 - 
772.6965 -+	if (flags & COPY_LAST &&
772.6966 -+            can_switch_to_blt(sna, dst_bo, flags))
772.6967 -+		return true;
772.6968 -+
772.6969 - 	if (prefer_render_ring(sna, dst_bo))
772.6970 - 		return false;
772.6971 - 
772.6972 - 	if (!prefer_blt_ring(sna, dst_bo, flags))
772.6973 - 		return false;
772.6974 - 
772.6975 --	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
772.6976 -+	return prefer_blt_bo(sna, src_bo, dst_bo);
772.6977 - }
772.6978 - 
772.6979 - static bool
772.6980 -@@ -2758,8 +2780,7 @@ fallback_blt:
772.6981 - 		assert(src->depth == dst->depth);
772.6982 - 		assert(src->width == dst->width);
772.6983 - 		assert(src->height == dst->height);
772.6984 --		return sna_render_copy_boxes__overlap(sna, alu,
772.6985 --						      src, src_bo,
772.6986 -+		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
772.6987 - 						      src_dx, src_dy,
772.6988 - 						      dst_dx, dst_dy,
772.6989 - 						      box, n, &extents);
772.6990 -diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
772.6991 -index 2ecfd641..aabb8693 100644
772.6992 ---- a/src/sna/gen7_render.c
772.6993 -+++ b/src/sna/gen7_render.c
772.6994 -@@ -60,8 +60,6 @@
772.6995 - #define NO_FILL_ONE 0
772.6996 - #define NO_FILL_CLEAR 0
772.6997 - 
772.6998 --#define NO_RING_SWITCH 0
772.6999 --
772.7000 - #define USE_8_PIXEL_DISPATCH 1
772.7001 - #define USE_16_PIXEL_DISPATCH 1
772.7002 - #define USE_32_PIXEL_DISPATCH 0
772.7003 -@@ -149,7 +147,7 @@ static const struct gt_info hsw_gt1_info = {
772.7004 - 	.max_vs_threads = 70,
772.7005 - 	.max_gs_threads = 70,
772.7006 - 	.max_wm_threads =
772.7007 --		(102 - 1) << HSW_PS_MAX_THREADS_SHIFT |
772.7008 -+		(70 - 1) << HSW_PS_MAX_THREADS_SHIFT |
772.7009 - 		1 << HSW_PS_SAMPLE_MASK_SHIFT,
772.7010 - 	.urb = { 128, 640, 256, 8 },
772.7011 - 	.gt = 1,
772.7012 -@@ -209,6 +207,12 @@ static const uint32_t ps_kernel_planar[][4] = {
772.7013 - #include "exa_wm_write.g7b"
772.7014 - };
772.7015 - 
772.7016 -+static const uint32_t ps_kernel_rgb[][4] = {
772.7017 -+#include "exa_wm_src_affine.g7b"
772.7018 -+#include "exa_wm_src_sample_argb.g7b"
772.7019 -+#include "exa_wm_write.g7b"
772.7020 -+};
772.7021 -+
772.7022 - #define KERNEL(kernel_enum, kernel, num_surfaces) \
772.7023 -     [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces}
772.7024 - #define NOKERNEL(kernel_enum, func, num_surfaces) \
772.7025 -@@ -218,7 +222,7 @@ static const struct wm_kernel_info {
772.7026 - 	const void *data;
772.7027 - 	unsigned int size;
772.7028 - 	int num_surfaces;
772.7029 --} wm_kernels[] = {
772.7030 -+} wm_kernels[GEN7_WM_KERNEL_COUNT] = {
772.7031 - 	NOKERNEL(NOMASK, brw_wm_kernel__affine, 2),
772.7032 - 	NOKERNEL(NOMASK_P, brw_wm_kernel__projective, 2),
772.7033 - 
772.7034 -@@ -236,6 +240,7 @@ static const struct wm_kernel_info {
772.7035 - 
772.7036 - 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
772.7037 - 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
772.7038 -+	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
772.7039 - };
772.7040 - #undef KERNEL
772.7041 - 
772.7042 -@@ -810,7 +815,7 @@ gen7_emit_cc(struct sna *sna, uint32_t blend_offset)
772.7043 - 
772.7044 - 	DBG(("%s: blend = %x\n", __FUNCTION__, blend_offset));
772.7045 - 
772.7046 --	/* XXX can have upto 8 blend states preload, selectable via
772.7047 -+	/* XXX can have up to 8 blend states preload, selectable via
772.7048 - 	 * Render Target Index. What other side-effects of Render Target Index?
772.7049 - 	 */
772.7050 - 
772.7051 -@@ -1792,7 +1797,9 @@ static void gen7_emit_video_state(struct sna *sna,
772.7052 - 			frame->pitch[0];
772.7053 - 		n_src = 6;
772.7054 - 	} else {
772.7055 --		if (frame->id == FOURCC_UYVY)
772.7056 -+		if (frame->id == FOURCC_RGB888)
772.7057 -+			src_surf_format = GEN7_SURFACEFORMAT_B8G8R8X8_UNORM;
772.7058 -+		else if (frame->id == FOURCC_UYVY)
772.7059 - 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY;
772.7060 - 		else
772.7061 - 			src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL;
772.7062 -@@ -1826,6 +1833,23 @@ static void gen7_emit_video_state(struct sna *sna,
772.7063 - 	gen7_emit_state(sna, op, offset | dirty);
772.7064 - }
772.7065 - 
772.7066 -+static unsigned select_video_kernel(const struct sna_video_frame *frame)
772.7067 -+{
772.7068 -+	switch (frame->id) {
772.7069 -+	case FOURCC_YV12:
772.7070 -+	case FOURCC_I420:
772.7071 -+	case FOURCC_XVMC:
772.7072 -+		return GEN7_WM_KERNEL_VIDEO_PLANAR;
772.7073 -+
772.7074 -+	case FOURCC_RGB888:
772.7075 -+	case FOURCC_RGB565:
772.7076 -+		return GEN7_WM_KERNEL_VIDEO_RGB;
772.7077 -+
772.7078 -+	default:
772.7079 -+		return GEN7_WM_KERNEL_VIDEO_PACKED;
772.7080 -+	}
772.7081 -+}
772.7082 -+
772.7083 - static bool
772.7084 - gen7_render_video(struct sna *sna,
772.7085 - 		  struct sna_video *video,
772.7086 -@@ -1841,9 +1865,9 @@ gen7_render_video(struct sna *sna,
772.7087 - 	int src_height = frame->src.y2 - frame->src.y1;
772.7088 - 	float src_offset_x, src_offset_y;
772.7089 - 	float src_scale_x, src_scale_y;
772.7090 --	int nbox, pix_xoff, pix_yoff;
772.7091 - 	unsigned filter;
772.7092 - 	const BoxRec *box;
772.7093 -+	int nbox;
772.7094 - 
772.7095 - 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
772.7096 - 	     __FUNCTION__,
772.7097 -@@ -1878,9 +1902,7 @@ gen7_render_video(struct sna *sna,
772.7098 - 		GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
772.7099 - 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
772.7100 - 			       NO_BLEND,
772.7101 --			       is_planar_fourcc(frame->id) ?
772.7102 --			       GEN7_WM_KERNEL_VIDEO_PLANAR :
772.7103 --			       GEN7_WM_KERNEL_VIDEO_PACKED,
772.7104 -+			       select_video_kernel(frame),
772.7105 - 			       2);
772.7106 - 	tmp.priv = frame;
772.7107 - 
772.7108 -@@ -1896,17 +1918,6 @@ gen7_render_video(struct sna *sna,
772.7109 - 	gen7_align_vertex(sna, &tmp);
772.7110 - 	gen7_emit_video_state(sna, &tmp);
772.7111 - 
772.7112 --	/* Set up the offset for translating from the given region (in screen
772.7113 --	 * coordinates) to the backing pixmap.
772.7114 --	 */
772.7115 --#ifdef COMPOSITE
772.7116 --	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.7117 --	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.7118 --#else
772.7119 --	pix_xoff = 0;
772.7120 --	pix_yoff = 0;
772.7121 --#endif
772.7122 --
772.7123 - 	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
772.7124 - 	     __FUNCTION__,
772.7125 - 	     frame->src.x1, frame->src.y1,
772.7126 -@@ -1928,45 +1939,36 @@ gen7_render_video(struct sna *sna,
772.7127 - 	box = region_rects(dstRegion);
772.7128 - 	nbox = region_num_rects(dstRegion);
772.7129 - 	while (nbox--) {
772.7130 --		BoxRec r;
772.7131 --
772.7132 --		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
772.7133 -+		DBG(("%s: dst=(%d, %d), (%d, %d); src=(%f, %f), (%f, %f)\n",
772.7134 - 		     __FUNCTION__,
772.7135 - 		     box->x1, box->y1,
772.7136 - 		     box->x2, box->y2,
772.7137 --		     pix_xoff, pix_yoff,
772.7138 - 		     box->x1 * src_scale_x + src_offset_x,
772.7139 - 		     box->y1 * src_scale_y + src_offset_y,
772.7140 - 		     box->x2 * src_scale_x + src_offset_x,
772.7141 - 		     box->y2 * src_scale_y + src_offset_y));
772.7142 - 
772.7143 --		r.x1 = box->x1 + pix_xoff;
772.7144 --		r.x2 = box->x2 + pix_xoff;
772.7145 --		r.y1 = box->y1 + pix_yoff;
772.7146 --		r.y2 = box->y2 + pix_yoff;
772.7147 --
772.7148 - 		gen7_get_rectangles(sna, &tmp, 1, gen7_emit_video_state);
772.7149 - 
772.7150 --		OUT_VERTEX(r.x2, r.y2);
772.7151 -+		OUT_VERTEX(box->x2, box->y2);
772.7152 - 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.7153 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.7154 - 
772.7155 --		OUT_VERTEX(r.x1, r.y2);
772.7156 -+		OUT_VERTEX(box->x1, box->y2);
772.7157 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.7158 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.7159 - 
772.7160 --		OUT_VERTEX(r.x1, r.y1);
772.7161 -+		OUT_VERTEX(box->x1, box->y1);
772.7162 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.7163 - 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.7164 - 
772.7165 --		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.7166 --			sna_damage_add_box(&priv->gpu_damage, &r);
772.7167 --			sna_damage_subtract_box(&priv->cpu_damage, &r);
772.7168 --		}
772.7169 - 		box++;
772.7170 - 	}
772.7171 --
772.7172 - 	gen4_vertex_flush(sna);
772.7173 -+
772.7174 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.7175 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.7176 -+
772.7177 - 	return true;
772.7178 - }
772.7179 - 
772.7180 -@@ -2048,12 +2050,13 @@ gen7_composite_picture(struct sna *sna,
772.7181 - 		if (channel->repeat ||
772.7182 - 		    (x >= 0 &&
772.7183 - 		     y >= 0 &&
772.7184 --		     x + w < pixmap->drawable.width &&
772.7185 --		     y + h < pixmap->drawable.height)) {
772.7186 -+		     x + w <= pixmap->drawable.width &&
772.7187 -+		     y + h <= pixmap->drawable.height)) {
772.7188 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.7189 - 			if (priv && priv->clear) {
772.7190 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.7191 --				return gen4_channel_init_solid(sna, channel, priv->clear_color);
772.7192 -+				return gen4_channel_init_solid(sna, channel,
772.7193 -+							       solid_color(picture->format, priv->clear_color));
772.7194 - 			}
772.7195 - 		}
772.7196 - 	} else
772.7197 -@@ -2147,7 +2150,9 @@ gen7_composite_set_target(struct sna *sna,
772.7198 - 	} else
772.7199 - 		sna_render_picture_extents(dst, &box);
772.7200 - 
772.7201 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.7202 -+	hint = PREFER_GPU | RENDER_GPU;
772.7203 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.7204 -+		hint |= FORCE_GPU;
772.7205 - 	if (!partial) {
772.7206 - 		hint |= IGNORE_DAMAGE;
772.7207 - 		if (w == op->dst.width && h == op->dst.height)
772.7208 -@@ -2185,46 +2190,78 @@ gen7_composite_set_target(struct sna *sna,
772.7209 - 
772.7210 - static bool
772.7211 - try_blt(struct sna *sna,
772.7212 --	PicturePtr dst, PicturePtr src,
772.7213 --	int width, int height)
772.7214 -+	uint8_t op,
772.7215 -+	PicturePtr src,
772.7216 -+	PicturePtr mask,
772.7217 -+	PicturePtr dst,
772.7218 -+	int16_t src_x, int16_t src_y,
772.7219 -+	int16_t msk_x, int16_t msk_y,
772.7220 -+	int16_t dst_x, int16_t dst_y,
772.7221 -+	int16_t width, int16_t height,
772.7222 -+	unsigned flags,
772.7223 -+	struct sna_composite_op *tmp)
772.7224 - {
772.7225 - 	struct kgem_bo *bo;
772.7226 - 
772.7227 - 	if (sna->kgem.mode == KGEM_BLT) {
772.7228 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.7229 --		return true;
772.7230 -+		goto execute;
772.7231 - 	}
772.7232 - 
772.7233 - 	if (too_large(width, height)) {
772.7234 - 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
772.7235 - 		     __FUNCTION__, width, height));
772.7236 --		return true;
772.7237 -+		goto execute;
772.7238 - 	}
772.7239 - 
772.7240 - 	bo = __sna_drawable_peek_bo(dst->pDrawable);
772.7241 - 	if (bo == NULL)
772.7242 --		return true;
772.7243 --	if (bo->rq)
772.7244 --		return RQ_IS_BLT(bo->rq);
772.7245 -+		goto execute;
772.7246 -+
772.7247 -+	if (untiled_tlb_miss(bo))
772.7248 -+		goto execute;
772.7249 -+
772.7250 -+	if (bo->rq) {
772.7251 -+		if (RQ_IS_BLT(bo->rq))
772.7252 -+			goto execute;
772.7253 -+
772.7254 -+		return false;
772.7255 -+	}
772.7256 -+
772.7257 -+	if (bo->tiling == I915_TILING_Y)
772.7258 -+		goto upload;
772.7259 -+
772.7260 -+	if (src->pDrawable == dst->pDrawable &&
772.7261 -+	    (sna->render_state.gt < 3 || width*height < 1024) &&
772.7262 -+	    can_switch_to_blt(sna, bo, 0))
772.7263 -+		goto execute;
772.7264 - 
772.7265 - 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
772.7266 --		return true;
772.7267 -+		goto execute;
772.7268 - 
772.7269 - 	if (src->pDrawable) {
772.7270 --		bo = __sna_drawable_peek_bo(src->pDrawable);
772.7271 --		if (bo == NULL)
772.7272 --			return true;
772.7273 -+		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
772.7274 -+		if (s == NULL)
772.7275 -+			goto upload;
772.7276 - 
772.7277 --		if (prefer_blt_bo(sna, bo))
772.7278 --			return true;
772.7279 -+		if (prefer_blt_bo(sna, s, bo))
772.7280 -+			goto execute;
772.7281 - 	}
772.7282 - 
772.7283 - 	if (sna->kgem.ring == KGEM_BLT) {
772.7284 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.7285 --		return true;
772.7286 -+		goto execute;
772.7287 - 	}
772.7288 - 
772.7289 --	return false;
772.7290 -+upload:
772.7291 -+	flags |= COMPOSITE_UPLOAD;
772.7292 -+execute:
772.7293 -+	return sna_blt_composite(sna, op,
772.7294 -+				 src, dst,
772.7295 -+				 src_x, src_y,
772.7296 -+				 dst_x, dst_y,
772.7297 -+				 width, height,
772.7298 -+				 flags, tmp);
772.7299 - }
772.7300 - 
772.7301 - static bool
772.7302 -@@ -2454,13 +2491,13 @@ gen7_render_composite(struct sna *sna,
772.7303 - 	     width, height, sna->kgem.mode, sna->kgem.ring));
772.7304 - 
772.7305 - 	if (mask == NULL &&
772.7306 --	    try_blt(sna, dst, src, width, height) &&
772.7307 --	    sna_blt_composite(sna, op,
772.7308 --			      src, dst,
772.7309 --			      src_x, src_y,
772.7310 --			      dst_x, dst_y,
772.7311 --			      width, height,
772.7312 --			      flags, tmp))
772.7313 -+	    try_blt(sna, op,
772.7314 -+		    src, mask, dst,
772.7315 -+		    src_x, src_y,
772.7316 -+		    msk_x, msk_y,
772.7317 -+		    dst_x, dst_y,
772.7318 -+		    width, height,
772.7319 -+		    flags, tmp))
772.7320 - 		return true;
772.7321 - 
772.7322 - 	if (gen7_composite_fallback(sna, src, mask, dst))
772.7323 -@@ -2878,27 +2915,37 @@ prefer_blt_copy(struct sna *sna,
772.7324 - 
772.7325 - 	assert((flags & COPY_SYNC) == 0);
772.7326 - 
772.7327 --	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
772.7328 --		return true;
772.7329 --
772.7330 - 	if (untiled_tlb_miss(src_bo) ||
772.7331 - 	    untiled_tlb_miss(dst_bo))
772.7332 - 		return true;
772.7333 - 
772.7334 --	if (force_blt_ring(sna))
772.7335 -+	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
772.7336 -+		return false;
772.7337 -+
772.7338 -+	if (force_blt_ring(sna, dst_bo))
772.7339 -+		return true;
772.7340 -+
772.7341 -+	if ((flags & COPY_SMALL ||
772.7342 -+	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
772.7343 -+            can_switch_to_blt(sna, dst_bo, flags))
772.7344 - 		return true;
772.7345 - 
772.7346 - 	if (kgem_bo_is_render(dst_bo) ||
772.7347 - 	    kgem_bo_is_render(src_bo))
772.7348 - 		return false;
772.7349 - 
772.7350 -+	if (flags & COPY_LAST &&
772.7351 -+	    sna->render_state.gt < 3 &&
772.7352 -+            can_switch_to_blt(sna, dst_bo, flags))
772.7353 -+		return true;
772.7354 -+
772.7355 - 	if (prefer_render_ring(sna, dst_bo))
772.7356 - 		return false;
772.7357 - 
772.7358 - 	if (!prefer_blt_ring(sna, dst_bo, flags))
772.7359 - 		return false;
772.7360 - 
772.7361 --	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
772.7362 -+	return prefer_blt_bo(sna, src_bo, dst_bo);
772.7363 - }
772.7364 - 
772.7365 - static bool
772.7366 -@@ -2946,7 +2993,7 @@ fallback_blt:
772.7367 - 		     &extents)) {
772.7368 - 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
772.7369 - 
772.7370 --		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
772.7371 -+		if ((big || !prefer_render_ring(sna, dst_bo)) &&
772.7372 - 		    sna_blt_copy_boxes(sna, alu,
772.7373 - 				       src_bo, src_dx, src_dy,
772.7374 - 				       dst_bo, dst_dx, dst_dy,
772.7375 -@@ -2961,8 +3008,7 @@ fallback_blt:
772.7376 - 		assert(src->depth == dst->depth);
772.7377 - 		assert(src->width == dst->width);
772.7378 - 		assert(src->height == dst->height);
772.7379 --		return sna_render_copy_boxes__overlap(sna, alu,
772.7380 --						      src, src_bo,
772.7381 -+		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
772.7382 - 						      src_dx, src_dy,
772.7383 - 						      dst_dx, dst_dy,
772.7384 - 						      box, n, &extents);
772.7385 -diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
772.7386 -index 6eb11452..445983b1 100644
772.7387 ---- a/src/sna/gen8_render.c
772.7388 -+++ b/src/sna/gen8_render.c
772.7389 -@@ -106,6 +106,12 @@ static const uint32_t ps_kernel_planar[][4] = {
772.7390 - #include "exa_wm_yuv_rgb.g8b"
772.7391 - #include "exa_wm_write.g8b"
772.7392 - };
772.7393 -+
772.7394 -+static const uint32_t ps_kernel_rgb[][4] = {
772.7395 -+#include "exa_wm_src_affine.g8b"
772.7396 -+#include "exa_wm_src_sample_argb.g8b"
772.7397 -+#include "exa_wm_write.g8b"
772.7398 -+};
772.7399 - #endif
772.7400 - 
772.7401 - #define SURFACE_DW (64 / sizeof(uint32_t));
772.7402 -@@ -119,7 +125,7 @@ static const struct wm_kernel_info {
772.7403 - 	const void *data;
772.7404 - 	unsigned int size;
772.7405 - 	int num_surfaces;
772.7406 --} wm_kernels[] = {
772.7407 -+} wm_kernels[GEN8_WM_KERNEL_COUNT] = {
772.7408 - 	NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2),
772.7409 - 	NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2),
772.7410 - 
772.7411 -@@ -138,6 +144,7 @@ static const struct wm_kernel_info {
772.7412 - #if !NO_VIDEO
772.7413 - 	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
772.7414 - 	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
772.7415 -+	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
772.7416 - #endif
772.7417 - };
772.7418 - #undef KERNEL
772.7419 -@@ -205,6 +212,33 @@ static const struct blendinfo {
772.7420 - #define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
772.7421 - #define OUT_VERTEX_F(v) vertex_emit(sna, v)
772.7422 - 
772.7423 -+struct gt_info {
772.7424 -+	const char *name;
772.7425 -+	struct {
772.7426 -+		int max_vs_entries;
772.7427 -+	} urb;
772.7428 -+};
772.7429 -+
772.7430 -+static const struct gt_info bdw_gt_info = {
772.7431 -+	.name = "Broadwell (gen8)",
772.7432 -+	.urb = { .max_vs_entries = 960 },
772.7433 -+};
772.7434 -+
772.7435 -+static bool is_bdw(struct sna *sna)
772.7436 -+{
772.7437 -+	return sna->kgem.gen == 0100;
772.7438 -+}
772.7439 -+
772.7440 -+static const struct gt_info chv_gt_info = {
772.7441 -+	.name = "Cherryview (gen8)",
772.7442 -+	.urb = { .max_vs_entries = 640 },
772.7443 -+};
772.7444 -+
772.7445 -+static bool is_chv(struct sna *sna)
772.7446 -+{
772.7447 -+	return sna->kgem.gen == 0101;
772.7448 -+}
772.7449 -+
772.7450 - static inline bool too_large(int width, int height)
772.7451 - {
772.7452 - 	return width > GEN8_MAX_SIZE || height > GEN8_MAX_SIZE;
772.7453 -@@ -462,7 +496,7 @@ gen8_emit_urb(struct sna *sna)
772.7454 - {
772.7455 - 	/* num of VS entries must be divisible by 8 if size < 9 */
772.7456 - 	OUT_BATCH(GEN8_3DSTATE_URB_VS | (2 - 2));
772.7457 --	OUT_BATCH(960 << URB_ENTRY_NUMBER_SHIFT |
772.7458 -+	OUT_BATCH(sna->render_state.gen8.info->urb.max_vs_entries << URB_ENTRY_NUMBER_SHIFT |
772.7459 - 		  (2 - 1) << URB_ENTRY_SIZE_SHIFT |
772.7460 - 		  4 << URB_STARTING_ADDRESS_SHIFT);
772.7461 - 
772.7462 -@@ -873,7 +907,7 @@ gen8_emit_cc(struct sna *sna, uint32_t blend)
772.7463 - 	assert(blend / GEN8_BLENDFACTOR_COUNT > 0);
772.7464 - 	assert(blend % GEN8_BLENDFACTOR_COUNT > 0);
772.7465 - 
772.7466 --	/* XXX can have upto 8 blend states preload, selectable via
772.7467 -+	/* XXX can have up to 8 blend states preload, selectable via
772.7468 - 	 * Render Target Index. What other side-effects of Render Target Index?
772.7469 - 	 */
772.7470 - 
772.7471 -@@ -1167,6 +1201,7 @@ gen8_emit_pipe_stall(struct sna *sna)
772.7472 - {
772.7473 - 	OUT_BATCH(GEN8_PIPE_CONTROL | (6 - 2));
772.7474 - 	OUT_BATCH(PIPE_CONTROL_CS_STALL |
772.7475 -+		  PIPE_CONTROL_FLUSH |
772.7476 - 		  PIPE_CONTROL_STALL_AT_SCOREBOARD);
772.7477 - 	OUT_BATCH64(0);
772.7478 - 	OUT_BATCH64(0);
772.7479 -@@ -1876,12 +1911,12 @@ gen8_composite_picture(struct sna *sna,
772.7480 - 		if (channel->repeat ||
772.7481 - 		    (x >= 0 &&
772.7482 - 		     y >= 0 &&
772.7483 --		     x + w < pixmap->drawable.width &&
772.7484 --		     y + h < pixmap->drawable.height)) {
772.7485 -+		     x + w <= pixmap->drawable.width &&
772.7486 -+		     y + h <= pixmap->drawable.height)) {
772.7487 - 			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.7488 - 			if (priv && priv->clear) {
772.7489 - 				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.7490 --				return gen4_channel_init_solid(sna, channel, priv->clear_color);
772.7491 -+				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
772.7492 - 			}
772.7493 - 		}
772.7494 - 	} else
772.7495 -@@ -1961,7 +1996,9 @@ gen8_composite_set_target(struct sna *sna,
772.7496 - 	} else
772.7497 - 		sna_render_picture_extents(dst, &box);
772.7498 - 
772.7499 --	hint = PREFER_GPU | FORCE_GPU | RENDER_GPU;
772.7500 -+	hint = PREFER_GPU | RENDER_GPU;
772.7501 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.7502 -+		hint |= FORCE_GPU;
772.7503 - 	if (!partial) {
772.7504 - 		hint |= IGNORE_DAMAGE;
772.7505 - 		if (w == op->dst.width && h == op->dst.height)
772.7506 -@@ -2002,46 +2039,78 @@ gen8_composite_set_target(struct sna *sna,
772.7507 - 
772.7508 - static bool
772.7509 - try_blt(struct sna *sna,
772.7510 --	PicturePtr dst, PicturePtr src,
772.7511 --	int width, int height)
772.7512 -+	uint8_t op,
772.7513 -+	PicturePtr src,
772.7514 -+	PicturePtr mask,
772.7515 -+	PicturePtr dst,
772.7516 -+	int16_t src_x, int16_t src_y,
772.7517 -+	int16_t msk_x, int16_t msk_y,
772.7518 -+	int16_t dst_x, int16_t dst_y,
772.7519 -+	int16_t width, int16_t height,
772.7520 -+	unsigned flags,
772.7521 -+	struct sna_composite_op *tmp)
772.7522 - {
772.7523 - 	struct kgem_bo *bo;
772.7524 - 
772.7525 - 	if (sna->kgem.mode == KGEM_BLT) {
772.7526 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.7527 --		return true;
772.7528 -+		goto execute;
772.7529 - 	}
772.7530 - 
772.7531 - 	if (too_large(width, height)) {
772.7532 - 		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
772.7533 - 		     __FUNCTION__, width, height));
772.7534 --		return true;
772.7535 -+		goto execute;
772.7536 - 	}
772.7537 - 
772.7538 - 	bo = __sna_drawable_peek_bo(dst->pDrawable);
772.7539 - 	if (bo == NULL)
772.7540 --		return true;
772.7541 --	if (bo->rq)
772.7542 --		return RQ_IS_BLT(bo->rq);
772.7543 -+		goto execute;
772.7544 -+
772.7545 -+	if (untiled_tlb_miss(bo))
772.7546 -+		goto execute;
772.7547 -+
772.7548 -+	if (bo->rq) {
772.7549 -+		if (RQ_IS_BLT(bo->rq))
772.7550 -+			goto execute;
772.7551 -+
772.7552 -+		return false;
772.7553 -+	}
772.7554 -+
772.7555 -+	if (bo->tiling == I915_TILING_Y)
772.7556 -+		goto upload;
772.7557 - 
772.7558 - 	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
772.7559 --		return true;
772.7560 -+		goto execute;
772.7561 -+
772.7562 -+	if (src->pDrawable == dst->pDrawable &&
772.7563 -+	    (sna->render_state.gt < 3 || width*height < 1024) &&
772.7564 -+	    can_switch_to_blt(sna, bo, 0))
772.7565 -+		goto execute;
772.7566 - 
772.7567 - 	if (src->pDrawable) {
772.7568 --		bo = __sna_drawable_peek_bo(src->pDrawable);
772.7569 --		if (bo == NULL)
772.7570 --			return true;
772.7571 -+		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
772.7572 -+		if (s == NULL)
772.7573 -+			goto upload;
772.7574 - 
772.7575 --		if (prefer_blt_bo(sna, bo))
772.7576 --			return RQ_IS_BLT(bo->rq);
772.7577 -+		if (prefer_blt_bo(sna, s, bo))
772.7578 -+			goto execute;
772.7579 - 	}
772.7580 - 
772.7581 - 	if (sna->kgem.ring == KGEM_BLT) {
772.7582 - 		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.7583 --		return true;
772.7584 -+		goto execute;
772.7585 - 	}
772.7586 - 
772.7587 --	return false;
772.7588 -+upload:
772.7589 -+	flags |= COMPOSITE_UPLOAD;
772.7590 -+execute:
772.7591 -+	return sna_blt_composite(sna, op,
772.7592 -+				 src, dst,
772.7593 -+				 src_x, src_y,
772.7594 -+				 dst_x, dst_y,
772.7595 -+				 width, height,
772.7596 -+				 flags, tmp);
772.7597 - }
772.7598 - 
772.7599 - static bool
772.7600 -@@ -2271,13 +2340,13 @@ gen8_render_composite(struct sna *sna,
772.7601 - 	     width, height, sna->kgem.mode, sna->kgem.ring));
772.7602 - 
772.7603 - 	if (mask == NULL &&
772.7604 --	    try_blt(sna, dst, src, width, height) &&
772.7605 --	    sna_blt_composite(sna, op,
772.7606 --			      src, dst,
772.7607 --			      src_x, src_y,
772.7608 --			      dst_x, dst_y,
772.7609 --			      width, height,
772.7610 --			      flags, tmp))
772.7611 -+	    try_blt(sna, op,
772.7612 -+		    src, mask, dst,
772.7613 -+		    src_x, src_y,
772.7614 -+		    msk_x, msk_y,
772.7615 -+		    dst_x, dst_y,
772.7616 -+		    width, height,
772.7617 -+		    flags, tmp))
772.7618 - 		return true;
772.7619 - 
772.7620 - 	if (gen8_composite_fallback(sna, src, mask, dst))
772.7621 -@@ -2700,27 +2769,37 @@ prefer_blt_copy(struct sna *sna,
772.7622 - 
772.7623 - 	assert((flags & COPY_SYNC) == 0);
772.7624 - 
772.7625 --	if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags))
772.7626 --		return true;
772.7627 --
772.7628 - 	if (untiled_tlb_miss(src_bo) ||
772.7629 - 	    untiled_tlb_miss(dst_bo))
772.7630 - 		return true;
772.7631 - 
772.7632 --	if (force_blt_ring(sna))
772.7633 -+	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
772.7634 -+		return false;
772.7635 -+
772.7636 -+	if (force_blt_ring(sna, dst_bo))
772.7637 -+		return true;
772.7638 -+
772.7639 -+	if ((flags & COPY_SMALL ||
772.7640 -+	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
772.7641 -+	    can_switch_to_blt(sna, dst_bo, flags))
772.7642 - 		return true;
772.7643 - 
772.7644 - 	if (kgem_bo_is_render(dst_bo) ||
772.7645 - 	    kgem_bo_is_render(src_bo))
772.7646 - 		return false;
772.7647 - 
772.7648 -+	if (flags & COPY_LAST &&
772.7649 -+	    sna->render_state.gt < 3 &&
772.7650 -+            can_switch_to_blt(sna, dst_bo, flags))
772.7651 -+		return true;
772.7652 -+
772.7653 - 	if (prefer_render_ring(sna, dst_bo))
772.7654 - 		return false;
772.7655 - 
772.7656 - 	if (!prefer_blt_ring(sna, dst_bo, flags))
772.7657 - 		return false;
772.7658 - 
772.7659 --	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
772.7660 -+	return prefer_blt_bo(sna, src_bo, dst_bo);
772.7661 - }
772.7662 - 
772.7663 - static bool
772.7664 -@@ -2770,7 +2849,7 @@ fallback_blt:
772.7665 - 		     &extents)) {
772.7666 - 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
772.7667 - 
772.7668 --		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
772.7669 -+		if ((big || !prefer_render_ring(sna, dst_bo)) &&
772.7670 - 		    sna_blt_copy_boxes(sna, alu,
772.7671 - 				       src_bo, src_dx, src_dy,
772.7672 - 				       dst_bo, dst_dx, dst_dy,
772.7673 -@@ -2785,8 +2864,7 @@ fallback_blt:
772.7674 - 		assert(src->depth == dst->depth);
772.7675 - 		assert(src->width == dst->width);
772.7676 - 		assert(src->height == dst->height);
772.7677 --		return sna_render_copy_boxes__overlap(sna, alu,
772.7678 --						      src, src_bo,
772.7679 -+		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
772.7680 - 						      src_dx, src_dy,
772.7681 - 						      dst_dx, dst_dy,
772.7682 - 						      box, n, &extents);
772.7683 -@@ -3665,7 +3743,9 @@ static void gen8_emit_video_state(struct sna *sna,
772.7684 - 			frame->pitch[0];
772.7685 - 		n_src = 6;
772.7686 - 	} else {
772.7687 --		if (frame->id == FOURCC_UYVY)
772.7688 -+		if (frame->id == FOURCC_RGB888)
772.7689 -+			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
772.7690 -+		else if (frame->id == FOURCC_UYVY)
772.7691 - 			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
772.7692 - 		else
772.7693 - 			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
772.7694 -@@ -3697,6 +3777,23 @@ static void gen8_emit_video_state(struct sna *sna,
772.7695 - 	gen8_emit_state(sna, op, offset);
772.7696 - }
772.7697 - 
772.7698 -+static unsigned select_video_kernel(const struct sna_video_frame *frame)
772.7699 -+{
772.7700 -+	switch (frame->id) {
772.7701 -+	case FOURCC_YV12:
772.7702 -+	case FOURCC_I420:
772.7703 -+	case FOURCC_XVMC:
772.7704 -+		return GEN8_WM_KERNEL_VIDEO_PLANAR;
772.7705 -+
772.7706 -+	case FOURCC_RGB888:
772.7707 -+	case FOURCC_RGB565:
772.7708 -+		return GEN8_WM_KERNEL_VIDEO_RGB;
772.7709 -+
772.7710 -+	default:
772.7711 -+		return GEN8_WM_KERNEL_VIDEO_PACKED;
772.7712 -+	}
772.7713 -+}
772.7714 -+
772.7715 - static bool
772.7716 - gen8_render_video(struct sna *sna,
772.7717 - 		  struct sna_video *video,
772.7718 -@@ -3712,9 +3809,9 @@ gen8_render_video(struct sna *sna,
772.7719 - 	int src_height = frame->src.y2 - frame->src.y1;
772.7720 - 	float src_offset_x, src_offset_y;
772.7721 - 	float src_scale_x, src_scale_y;
772.7722 --	int nbox, pix_xoff, pix_yoff;
772.7723 - 	unsigned filter;
772.7724 - 	const BoxRec *box;
772.7725 -+	int nbox;
772.7726 - 
772.7727 - 	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
772.7728 - 	     __FUNCTION__,
772.7729 -@@ -3743,6 +3840,11 @@ gen8_render_video(struct sna *sna,
772.7730 - 	tmp.floats_per_vertex = 3;
772.7731 - 	tmp.floats_per_rect = 9;
772.7732 - 
772.7733 -+	DBG(("%s: scaling?=%d, planar?=%d [%x]\n",
772.7734 -+	     __FUNCTION__,
772.7735 -+	     src_width != dst_width || src_height != dst_height,
772.7736 -+	     is_planar_fourcc(frame->id), frame->id));
772.7737 -+
772.7738 - 	if (src_width == dst_width && src_height == dst_height)
772.7739 - 		filter = SAMPLER_FILTER_NEAREST;
772.7740 - 	else
772.7741 -@@ -3752,9 +3854,7 @@ gen8_render_video(struct sna *sna,
772.7742 - 		GEN8_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
772.7743 - 					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
772.7744 - 			       NO_BLEND,
772.7745 --			       is_planar_fourcc(frame->id) ?
772.7746 --			       GEN8_WM_KERNEL_VIDEO_PLANAR :
772.7747 --			       GEN8_WM_KERNEL_VIDEO_PACKED,
772.7748 -+			       select_video_kernel(frame),
772.7749 - 			       2);
772.7750 - 	tmp.priv = frame;
772.7751 - 
772.7752 -@@ -3770,17 +3870,6 @@ gen8_render_video(struct sna *sna,
772.7753 - 	gen8_align_vertex(sna, &tmp);
772.7754 - 	gen8_emit_video_state(sna, &tmp);
772.7755 - 
772.7756 --	/* Set up the offset for translating from the given region (in screen
772.7757 --	 * coordinates) to the backing pixmap.
772.7758 --	 */
772.7759 --#ifdef COMPOSITE
772.7760 --	pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
772.7761 --	pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
772.7762 --#else
772.7763 --	pix_xoff = 0;
772.7764 --	pix_yoff = 0;
772.7765 --#endif
772.7766 --
772.7767 - 	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
772.7768 - 	     __FUNCTION__,
772.7769 - 	     frame->src.x1, frame->src.y1,
772.7770 -@@ -3802,45 +3891,36 @@ gen8_render_video(struct sna *sna,
772.7771 - 	box = region_rects(dstRegion);
772.7772 - 	nbox = region_num_rects(dstRegion);
772.7773 - 	while (nbox--) {
772.7774 --		BoxRec r;
772.7775 --
772.7776 - 		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
772.7777 - 		     __FUNCTION__,
772.7778 - 		     box->x1, box->y1,
772.7779 - 		     box->x2, box->y2,
772.7780 --		     pix_xoff, pix_yoff,
772.7781 - 		     box->x1 * src_scale_x + src_offset_x,
772.7782 - 		     box->y1 * src_scale_y + src_offset_y,
772.7783 - 		     box->x2 * src_scale_x + src_offset_x,
772.7784 - 		     box->y2 * src_scale_y + src_offset_y));
772.7785 - 
772.7786 --		r.x1 = box->x1 + pix_xoff;
772.7787 --		r.x2 = box->x2 + pix_xoff;
772.7788 --		r.y1 = box->y1 + pix_yoff;
772.7789 --		r.y2 = box->y2 + pix_yoff;
772.7790 --
772.7791 - 		gen8_get_rectangles(sna, &tmp, 1, gen8_emit_video_state);
772.7792 - 
772.7793 --		OUT_VERTEX(r.x2, r.y2);
772.7794 -+		OUT_VERTEX(box->x2, box->y2);
772.7795 - 		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.7796 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.7797 - 
772.7798 --		OUT_VERTEX(r.x1, r.y2);
772.7799 -+		OUT_VERTEX(box->x1, box->y2);
772.7800 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.7801 - 		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.7802 - 
772.7803 --		OUT_VERTEX(r.x1, r.y1);
772.7804 -+		OUT_VERTEX(box->x1, box->y1);
772.7805 - 		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.7806 - 		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.7807 - 
772.7808 --		if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
772.7809 --			sna_damage_add_box(&priv->gpu_damage, &r);
772.7810 --			sna_damage_subtract_box(&priv->cpu_damage, &r);
772.7811 --		}
772.7812 - 		box++;
772.7813 - 	}
772.7814 --
772.7815 - 	gen8_vertex_flush(sna);
772.7816 -+
772.7817 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.7818 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.7819 -+
772.7820 - 	return true;
772.7821 - }
772.7822 - #endif
772.7823 -@@ -3896,6 +3976,13 @@ static bool gen8_render_setup(struct sna *sna)
772.7824 - 		state->gt = ((devid >> 4) & 0xf) + 1;
772.7825 - 	DBG(("%s: gt=%d\n", __FUNCTION__, state->gt));
772.7826 - 
772.7827 -+	if (is_bdw(sna))
772.7828 -+		state->info = &bdw_gt_info;
772.7829 -+	else if (is_chv(sna))
772.7830 -+		state->info = &chv_gt_info;
772.7831 -+	else
772.7832 -+		return false;
772.7833 -+
772.7834 - 	sna_static_stream_init(&general);
772.7835 - 
772.7836 - 	/* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
772.7837 -@@ -4007,5 +4094,5 @@ const char *gen8_render_init(struct sna *sna, const char *backend)
772.7838 - 
772.7839 - 	sna->render.max_3d_size = GEN8_MAX_SIZE;
772.7840 - 	sna->render.max_3d_pitch = 1 << 18;
772.7841 --	return "Broadwell";
772.7842 -+	return sna->render_state.gen8.info->name;
772.7843 - }
772.7844 -diff --git a/src/sna/gen8_render.h b/src/sna/gen8_render.h
772.7845 -index eb4928e7..e6a8dc55 100644
772.7846 ---- a/src/sna/gen8_render.h
772.7847 -+++ b/src/sna/gen8_render.h
772.7848 -@@ -335,6 +335,7 @@
772.7849 - #define PIPE_CONTROL_IS_FLUSH      (1 << 11)
772.7850 - #define PIPE_CONTROL_TC_FLUSH      (1 << 10)
772.7851 - #define PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
772.7852 -+#define PIPE_CONTROL_FLUSH         (1 << 7)
772.7853 - #define PIPE_CONTROL_GLOBAL_GTT    (1 << 2)
772.7854 - #define PIPE_CONTROL_LOCAL_PGTT    (0 << 2)
772.7855 - #define PIPE_CONTROL_STALL_AT_SCOREBOARD   (1 << 1)
772.7856 -diff --git a/src/sna/gen9_render.c b/src/sna/gen9_render.c
772.7857 -new file mode 100644
772.7858 -index 00000000..e5f12c72
772.7859 ---- /dev/null
772.7860 -+++ b/src/sna/gen9_render.c
772.7861 -@@ -0,0 +1,4156 @@
772.7862 -+/*
772.7863 -+ * Copyright © 2012,2013 Intel Corporation
772.7864 -+ *
772.7865 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.7866 -+ * copy of this software and associated documentation files (the "Software"),
772.7867 -+ * to deal in the Software without restriction, including without limitation
772.7868 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.7869 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.7870 -+ * Software is furnished to do so, subject to the following conditions:
772.7871 -+ *
772.7872 -+ * The above copyright notice and this permission notice (including the next
772.7873 -+ * paragraph) shall be included in all copies or substantial portions of the
772.7874 -+ * Software.
772.7875 -+ *
772.7876 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.7877 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.7878 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.7879 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.7880 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772.7881 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
772.7882 -+ * SOFTWARE.
772.7883 -+ *
772.7884 -+ * Authors:
772.7885 -+ *    Chris Wilson <chris@chris-wilson.co.uk>
772.7886 -+ *
772.7887 -+ */
772.7888 -+
772.7889 -+#ifdef HAVE_CONFIG_H
772.7890 -+#include "config.h"
772.7891 -+#endif
772.7892 -+
772.7893 -+#include "sna.h"
772.7894 -+#include "sna_reg.h"
772.7895 -+#include "sna_render.h"
772.7896 -+#include "sna_render_inline.h"
772.7897 -+#include "sna_video.h"
772.7898 -+
772.7899 -+#include "gen9_render.h"
772.7900 -+#include "gen8_eu.h"
772.7901 -+#include "gen4_common.h"
772.7902 -+#include "gen4_source.h"
772.7903 -+#include "gen4_vertex.h"
772.7904 -+#include "gen6_common.h"
772.7905 -+#include "gen8_vertex.h"
772.7906 -+
772.7907 -+#define SIM 1
772.7908 -+
772.7909 -+#define ALWAYS_INVALIDATE 0
772.7910 -+#define ALWAYS_FLUSH 0
772.7911 -+#define ALWAYS_STALL 0
772.7912 -+
772.7913 -+#define NO_COMPOSITE 0
772.7914 -+#define NO_COMPOSITE_SPANS 0
772.7915 -+#define NO_COPY 0
772.7916 -+#define NO_COPY_BOXES 0
772.7917 -+#define NO_FILL 0
772.7918 -+#define NO_FILL_BOXES 0
772.7919 -+#define NO_FILL_ONE 0
772.7920 -+#define NO_FILL_CLEAR 0
772.7921 -+#define NO_VIDEO 0
772.7922 -+
772.7923 -+#define USE_8_PIXEL_DISPATCH 1
772.7924 -+#define USE_16_PIXEL_DISPATCH 1
772.7925 -+#define USE_32_PIXEL_DISPATCH 0
772.7926 -+
772.7927 -+#if !USE_8_PIXEL_DISPATCH && !USE_16_PIXEL_DISPATCH && !USE_32_PIXEL_DISPATCH
772.7928 -+#error "Must select at least 8, 16 or 32 pixel dispatch"
772.7929 -+#endif
772.7930 -+
772.7931 -+#define GEN9_MAX_SIZE 16384
772.7932 -+#define GEN9_GT_BIAS 1 /* Each GT is bigger than previous gen */
772.7933 -+
772.7934 -+/* XXX Todo
772.7935 -+ *
772.7936 -+ * STR (software tiled rendering) mode. No, really.
772.7937 -+ * 64x32 pixel blocks align with the rendering cache. Worth considering.
772.7938 -+ */
772.7939 -+
772.7940 -+#define is_aligned(x, y) (((x) & ((y) - 1)) == 0)
772.7941 -+
772.7942 -+/* Pipeline stages:
772.7943 -+ *  1. Command Streamer (CS)
772.7944 -+ *  2. Vertex Fetch (VF)
772.7945 -+ *  3. Vertex Shader (VS)
772.7946 -+ *  4. Hull Shader (HS)
772.7947 -+ *  5. Tesselation Engine (TE)
772.7948 -+ *  6. Domain Shader (DS)
772.7949 -+ *  7. Geometry Shader (GS)
772.7950 -+ *  8. Stream Output Logic (SOL)
772.7951 -+ *  9. Clipper (CLIP)
772.7952 -+ * 10. Strip/Fan (SF)
772.7953 -+ * 11. Windower/Masker (WM)
772.7954 -+ * 12. Color Calculator (CC)
772.7955 -+ */
772.7956 -+
772.7957 -+#if !NO_VIDEO
772.7958 -+static const uint32_t ps_kernel_packed[][4] = {
772.7959 -+#include "exa_wm_src_affine.g8b"
772.7960 -+#include "exa_wm_src_sample_argb.g8b"
772.7961 -+#include "exa_wm_yuv_rgb.g8b"
772.7962 -+#include "exa_wm_write.g8b"
772.7963 -+};
772.7964 -+
772.7965 -+static const uint32_t ps_kernel_planar[][4] = {
772.7966 -+#include "exa_wm_src_affine.g8b"
772.7967 -+#include "exa_wm_src_sample_planar.g8b"
772.7968 -+#include "exa_wm_yuv_rgb.g8b"
772.7969 -+#include "exa_wm_write.g8b"
772.7970 -+};
772.7971 -+
772.7972 -+static const uint32_t ps_kernel_rgb[][4] = {
772.7973 -+#include "exa_wm_src_affine.g8b"
772.7974 -+#include "exa_wm_src_sample_argb.g8b"
772.7975 -+#include "exa_wm_write.g8b"
772.7976 -+};
772.7977 -+#endif
772.7978 -+
772.7979 -+#define SURFACE_DW (64 / sizeof(uint32_t));
772.7980 -+
772.7981 -+#define KERNEL(kernel_enum, kernel, num_surfaces) \
772.7982 -+    [GEN9_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces}
772.7983 -+#define NOKERNEL(kernel_enum, func, num_surfaces) \
772.7984 -+    [GEN9_WM_KERNEL_##kernel_enum] = {#kernel_enum, (void *)func, 0, num_surfaces}
772.7985 -+static const struct wm_kernel_info {
772.7986 -+	const char *name;
772.7987 -+	const void *data;
772.7988 -+	unsigned int size;
772.7989 -+	int num_surfaces;
772.7990 -+} wm_kernels[] = {
772.7991 -+	NOKERNEL(NOMASK, gen8_wm_kernel__affine, 2),
772.7992 -+	NOKERNEL(NOMASK_P, gen8_wm_kernel__projective, 2),
772.7993 -+
772.7994 -+	NOKERNEL(MASK, gen8_wm_kernel__affine_mask, 3),
772.7995 -+	NOKERNEL(MASK_P, gen8_wm_kernel__projective_mask, 3),
772.7996 -+
772.7997 -+	NOKERNEL(MASKCA, gen8_wm_kernel__affine_mask_ca, 3),
772.7998 -+	NOKERNEL(MASKCA_P, gen8_wm_kernel__projective_mask_ca, 3),
772.7999 -+
772.8000 -+	NOKERNEL(MASKSA, gen8_wm_kernel__affine_mask_sa, 3),
772.8001 -+	NOKERNEL(MASKSA_P, gen8_wm_kernel__projective_mask_sa, 3),
772.8002 -+
772.8003 -+	NOKERNEL(OPACITY, gen8_wm_kernel__affine_opacity, 2),
772.8004 -+	NOKERNEL(OPACITY_P, gen8_wm_kernel__projective_opacity, 2),
772.8005 -+
772.8006 -+#if !NO_VIDEO
772.8007 -+	KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7),
772.8008 -+	KERNEL(VIDEO_PACKED, ps_kernel_packed, 2),
772.8009 -+	KERNEL(VIDEO_RGB, ps_kernel_rgb, 2),
772.8010 -+#endif
772.8011 -+};
772.8012 -+#undef KERNEL
772.8013 -+
772.8014 -+static const struct blendinfo {
772.8015 -+	uint8_t src_alpha;
772.8016 -+	uint8_t src_blend;
772.8017 -+	uint8_t dst_blend;
772.8018 -+} gen9_blend_op[] = {
772.8019 -+	/* Clear */	{0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO},
772.8020 -+	/* Src */	{0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO},
772.8021 -+	/* Dst */	{0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE},
772.8022 -+	/* Over */	{1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA},
772.8023 -+	/* OverReverse */ {0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE},
772.8024 -+	/* In */	{0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO},
772.8025 -+	/* InReverse */	{1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA},
772.8026 -+	/* Out */	{0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO},
772.8027 -+	/* OutReverse */ {1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA},
772.8028 -+	/* Atop */	{1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
772.8029 -+	/* AtopReverse */ {1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA},
772.8030 -+	/* Xor */	{1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA},
772.8031 -+	/* Add */	{0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
772.8032 -+};
772.8033 -+
772.8034 -+/**
772.8035 -+ * Highest-valued BLENDFACTOR used in gen9_blend_op.
772.8036 -+ *
772.8037 -+ * This leaves out GEN9_BLENDFACTOR_INV_DST_COLOR,
772.8038 -+ * GEN9_BLENDFACTOR_INV_CONST_{COLOR,ALPHA},
772.8039 -+ * GEN9_BLENDFACTOR_INV_SRC1_{COLOR,ALPHA}
772.8040 -+ */
772.8041 -+#define GEN9_BLENDFACTOR_COUNT (BLENDFACTOR_INV_DST_ALPHA + 1)
772.8042 -+
772.8043 -+#define GEN9_BLEND_STATE_PADDED_SIZE	ALIGN(sizeof(struct gen9_blend_state), 64)
772.8044 -+
772.8045 -+#define BLEND_OFFSET(s, d) \
772.8046 -+	((d != BLENDFACTOR_ZERO) << 15 | ((s) * GEN9_BLENDFACTOR_COUNT + (d)) << 4)
772.8047 -+
772.8048 -+#define NO_BLEND BLEND_OFFSET(BLENDFACTOR_ONE, BLENDFACTOR_ZERO)
772.8049 -+#define CLEAR BLEND_OFFSET(BLENDFACTOR_ZERO, BLENDFACTOR_ZERO)
772.8050 -+
772.8051 -+#define SAMPLER_OFFSET(sf, se, mf, me) \
772.8052 -+	(((((sf) * EXTEND_COUNT + (se)) * FILTER_COUNT + (mf)) * EXTEND_COUNT + (me)) + 2)
772.8053 -+
772.8054 -+#define VERTEX_2s2s 0
772.8055 -+
772.8056 -+#define COPY_SAMPLER 0
772.8057 -+#define COPY_VERTEX VERTEX_2s2s
772.8058 -+#define COPY_FLAGS(a) GEN9_SET_FLAGS(COPY_SAMPLER, (a) == GXcopy ? NO_BLEND : CLEAR, GEN9_WM_KERNEL_NOMASK, COPY_VERTEX)
772.8059 -+
772.8060 -+#define FILL_SAMPLER 1
772.8061 -+#define FILL_VERTEX VERTEX_2s2s
772.8062 -+#define FILL_FLAGS(op, format) GEN9_SET_FLAGS(FILL_SAMPLER, gen9_get_blend((op), false, (format)), GEN9_WM_KERNEL_NOMASK, FILL_VERTEX)
772.8063 -+#define FILL_FLAGS_NOBLEND GEN9_SET_FLAGS(FILL_SAMPLER, NO_BLEND, GEN9_WM_KERNEL_NOMASK, FILL_VERTEX)
772.8064 -+
772.8065 -+#define GEN9_SAMPLER(f) (((f) >> 20) & 0xfff)
772.8066 -+#define GEN9_BLEND(f) (((f) >> 4) & 0x7ff)
772.8067 -+#define GEN9_READS_DST(f) (((f) >> 15) & 1)
772.8068 -+#define GEN9_KERNEL(f) (((f) >> 16) & 0xf)
772.8069 -+#define GEN9_VERTEX(f) (((f) >> 0) & 0xf)
772.8070 -+#define GEN9_SET_FLAGS(S, B, K, V)  ((S) << 20 | (K) << 16 | (B) | (V))
772.8071 -+
772.8072 -+#define OUT_BATCH(v) batch_emit(sna, v)
772.8073 -+#define OUT_BATCH64(v) batch_emit64(sna, v)
772.8074 -+#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
772.8075 -+#define OUT_VERTEX_F(v) vertex_emit(sna, v)
772.8076 -+
772.8077 -+struct gt_info {
772.8078 -+	const char *name;
772.8079 -+	struct {
772.8080 -+		int max_vs_entries;
772.8081 -+	} urb;
772.8082 -+};
772.8083 -+
772.8084 -+static const struct gt_info min_gt_info = {
772.8085 -+	.name = "Skylake (gen9)",
772.8086 -+	.urb = { .max_vs_entries = 240 },
772.8087 -+};
772.8088 -+
772.8089 -+static const struct gt_info skl_gt_info = {
772.8090 -+	.name = "Skylake (gen9)",
772.8091 -+	.urb = { .max_vs_entries = 960 },
772.8092 -+};
772.8093 -+
772.8094 -+static const struct gt_info bxt_gt_info = {
772.8095 -+	.name = "Broxton (gen9)",
772.8096 -+	.urb = { .max_vs_entries = 320 },
772.8097 -+};
772.8098 -+
772.8099 -+static const struct gt_info kbl_gt_info = {
772.8100 -+	.name = "Kabylake (gen9)",
772.8101 -+	.urb = { .max_vs_entries = 960 },
772.8102 -+};
772.8103 -+
772.8104 -+static const struct gt_info glk_gt_info = {
772.8105 -+	.name = "Geminilake (gen9)",
772.8106 -+	.urb = { .max_vs_entries = 320 },
772.8107 -+};
772.8108 -+
772.8109 -+static bool is_skl(struct sna *sna)
772.8110 -+{
772.8111 -+	return sna->kgem.gen == 0110;
772.8112 -+}
772.8113 -+
772.8114 -+static bool is_bxt(struct sna *sna)
772.8115 -+{
772.8116 -+	return sna->kgem.gen == 0111;
772.8117 -+}
772.8118 -+
772.8119 -+static bool is_kbl(struct sna *sna)
772.8120 -+{
772.8121 -+	return sna->kgem.gen == 0112;
772.8122 -+}
772.8123 -+
772.8124 -+static bool is_glk(struct sna *sna)
772.8125 -+{
772.8126 -+	return sna->kgem.gen == 0113;
772.8127 -+}
772.8128 -+
772.8129 -+
772.8130 -+static inline bool too_large(int width, int height)
772.8131 -+{
772.8132 -+	return width > GEN9_MAX_SIZE || height > GEN9_MAX_SIZE;
772.8133 -+}
772.8134 -+
772.8135 -+static inline bool unaligned(struct kgem_bo *bo, int bpp)
772.8136 -+{
772.8137 -+	/* XXX What exactly do we need to meet H_ALIGN and V_ALIGN? */
772.8138 -+#if 0
772.8139 -+	int x, y;
772.8140 -+
772.8141 -+	if (bo->proxy == NULL)
772.8142 -+		return false;
772.8143 -+
772.8144 -+	/* Assume that all tiled proxies are constructed correctly. */
772.8145 -+	if (bo->tiling)
772.8146 -+		return false;
772.8147 -+
772.8148 -+	DBG(("%s: checking alignment of a linear proxy, offset=%d, pitch=%d, bpp=%d: => (%d, %d)\n",
772.8149 -+	     __FUNCTION__, bo->delta, bo->pitch, bpp,
772.8150 -+	     8 * (bo->delta % bo->pitch) / bpp, bo->delta / bo->pitch));
772.8151 -+
772.8152 -+	/* This may be a random userptr map, check that it meets the
772.8153 -+	 * render alignment of SURFACE_VALIGN_4 | SURFACE_HALIGN_4.
772.8154 -+	 */
772.8155 -+	y = bo->delta / bo->pitch;
772.8156 -+	if (y & 3)
772.8157 -+		return true;
772.8158 -+
772.8159 -+	x = 8 * (bo->delta - y * bo->pitch);
772.8160 -+	if (x & (4*bpp - 1))
772.8161 -+	    return true;
772.8162 -+
772.8163 -+	return false;
772.8164 -+#else
772.8165 -+	return false;
772.8166 -+#endif
772.8167 -+}
772.8168 -+
772.8169 -+static uint32_t gen9_get_blend(int op,
772.8170 -+			       bool has_component_alpha,
772.8171 -+			       uint32_t dst_format)
772.8172 -+{
772.8173 -+	uint32_t src, dst;
772.8174 -+
772.8175 -+	COMPILE_TIME_ASSERT(BLENDFACTOR_INV_DST_ALPHA*GEN9_BLENDFACTOR_COUNT + BLENDFACTOR_INV_DST_ALPHA <= 0x7ff);
772.8176 -+
772.8177 -+	src = gen9_blend_op[op].src_blend;
772.8178 -+	dst = gen9_blend_op[op].dst_blend;
772.8179 -+
772.8180 -+	/* If there's no dst alpha channel, adjust the blend op so that
772.8181 -+	 * we'll treat it always as 1.
772.8182 -+	 */
772.8183 -+	if (PICT_FORMAT_A(dst_format) == 0) {
772.8184 -+		if (src == BLENDFACTOR_DST_ALPHA)
772.8185 -+			src = BLENDFACTOR_ONE;
772.8186 -+		else if (src == BLENDFACTOR_INV_DST_ALPHA)
772.8187 -+			src = BLENDFACTOR_ZERO;
772.8188 -+	}
772.8189 -+
772.8190 -+	/* If the source alpha is being used, then we should only be in a
772.8191 -+	 * case where the source blend factor is 0, and the source blend
772.8192 -+	 * value is the mask channels multiplied by the source picture's alpha.
772.8193 -+	 */
772.8194 -+	if (has_component_alpha && gen9_blend_op[op].src_alpha) {
772.8195 -+		if (dst == BLENDFACTOR_SRC_ALPHA)
772.8196 -+			dst = BLENDFACTOR_SRC_COLOR;
772.8197 -+		else if (dst == BLENDFACTOR_INV_SRC_ALPHA)
772.8198 -+			dst = BLENDFACTOR_INV_SRC_COLOR;
772.8199 -+	}
772.8200 -+
772.8201 -+	DBG(("blend op=%d, dst=%x [A=%d] => src=%d, dst=%d => offset=%x\n",
772.8202 -+	     op, dst_format, PICT_FORMAT_A(dst_format),
772.8203 -+	     src, dst, (int)(BLEND_OFFSET(src, dst)>>4)));
772.8204 -+	assert(BLEND_OFFSET(src, dst) >> 4 <= 0xfff);
772.8205 -+	return BLEND_OFFSET(src, dst);
772.8206 -+}
772.8207 -+
772.8208 -+static uint32_t gen9_get_card_format(PictFormat format)
772.8209 -+{
772.8210 -+	switch (format) {
772.8211 -+	default:
772.8212 -+		return -1;
772.8213 -+	case PICT_a8r8g8b8:
772.8214 -+		return SURFACEFORMAT_B8G8R8A8_UNORM;
772.8215 -+	case PICT_x8r8g8b8:
772.8216 -+		return SURFACEFORMAT_B8G8R8X8_UNORM;
772.8217 -+	case PICT_a8b8g8r8:
772.8218 -+		return SURFACEFORMAT_R8G8B8A8_UNORM;
772.8219 -+	case PICT_x8b8g8r8:
772.8220 -+		return SURFACEFORMAT_R8G8B8X8_UNORM;
772.8221 -+#ifdef PICT_a2r10g10b10
772.8222 -+	case PICT_a2r10g10b10:
772.8223 -+		return SURFACEFORMAT_B10G10R10A2_UNORM;
772.8224 -+	case PICT_x2r10g10b10:
772.8225 -+		return SURFACEFORMAT_B10G10R10X2_UNORM;
772.8226 -+#endif
772.8227 -+	case PICT_r8g8b8:
772.8228 -+		return SURFACEFORMAT_R8G8B8_UNORM;
772.8229 -+	case PICT_r5g6b5:
772.8230 -+		return SURFACEFORMAT_B5G6R5_UNORM;
772.8231 -+	case PICT_a1r5g5b5:
772.8232 -+		return SURFACEFORMAT_B5G5R5A1_UNORM;
772.8233 -+	case PICT_a8:
772.8234 -+		return SURFACEFORMAT_A8_UNORM;
772.8235 -+	case PICT_a4r4g4b4:
772.8236 -+		return SURFACEFORMAT_B4G4R4A4_UNORM;
772.8237 -+	}
772.8238 -+}
772.8239 -+
772.8240 -+static uint32_t gen9_get_dest_format(PictFormat format)
772.8241 -+{
772.8242 -+	switch (format) {
772.8243 -+	default:
772.8244 -+		return -1;
772.8245 -+	case PICT_a8r8g8b8:
772.8246 -+	case PICT_x8r8g8b8:
772.8247 -+		return SURFACEFORMAT_B8G8R8A8_UNORM;
772.8248 -+	case PICT_a8b8g8r8:
772.8249 -+	case PICT_x8b8g8r8:
772.8250 -+		return SURFACEFORMAT_R8G8B8A8_UNORM;
772.8251 -+#ifdef PICT_a2r10g10b10
772.8252 -+	case PICT_a2r10g10b10:
772.8253 -+	case PICT_x2r10g10b10:
772.8254 -+		return SURFACEFORMAT_B10G10R10A2_UNORM;
772.8255 -+#endif
772.8256 -+	case PICT_r5g6b5:
772.8257 -+		return SURFACEFORMAT_B5G6R5_UNORM;
772.8258 -+	case PICT_x1r5g5b5:
772.8259 -+	case PICT_a1r5g5b5:
772.8260 -+		return SURFACEFORMAT_B5G5R5A1_UNORM;
772.8261 -+	case PICT_a8:
772.8262 -+		return SURFACEFORMAT_A8_UNORM;
772.8263 -+	case PICT_a4r4g4b4:
772.8264 -+	case PICT_x4r4g4b4:
772.8265 -+		return SURFACEFORMAT_B4G4R4A4_UNORM;
772.8266 -+	}
772.8267 -+}
772.8268 -+
772.8269 -+static bool gen9_check_dst_format(PictFormat format)
772.8270 -+{
772.8271 -+	if (gen9_get_dest_format(format) != -1)
772.8272 -+		return true;
772.8273 -+
772.8274 -+	DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format));
772.8275 -+	return false;
772.8276 -+}
772.8277 -+
772.8278 -+static bool gen9_check_format(uint32_t format)
772.8279 -+{
772.8280 -+	if (gen9_get_card_format(format) != -1)
772.8281 -+		return true;
772.8282 -+
772.8283 -+	DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format));
772.8284 -+	return false;
772.8285 -+}
772.8286 -+
772.8287 -+static uint32_t gen9_filter(uint32_t filter)
772.8288 -+{
772.8289 -+	switch (filter) {
772.8290 -+	default:
772.8291 -+		assert(0);
772.8292 -+	case PictFilterNearest:
772.8293 -+		return SAMPLER_FILTER_NEAREST;
772.8294 -+	case PictFilterBilinear:
772.8295 -+		return SAMPLER_FILTER_BILINEAR;
772.8296 -+	}
772.8297 -+}
772.8298 -+
772.8299 -+static uint32_t gen9_check_filter(PicturePtr picture)
772.8300 -+{
772.8301 -+	switch (picture->filter) {
772.8302 -+	case PictFilterNearest:
772.8303 -+	case PictFilterBilinear:
772.8304 -+		return true;
772.8305 -+	default:
772.8306 -+		return false;
772.8307 -+	}
772.8308 -+}
772.8309 -+
772.8310 -+static uint32_t gen9_repeat(uint32_t repeat)
772.8311 -+{
772.8312 -+	switch (repeat) {
772.8313 -+	default:
772.8314 -+		assert(0);
772.8315 -+	case RepeatNone:
772.8316 -+		return SAMPLER_EXTEND_NONE;
772.8317 -+	case RepeatNormal:
772.8318 -+		return SAMPLER_EXTEND_REPEAT;
772.8319 -+	case RepeatPad:
772.8320 -+		return SAMPLER_EXTEND_PAD;
772.8321 -+	case RepeatReflect:
772.8322 -+		return SAMPLER_EXTEND_REFLECT;
772.8323 -+	}
772.8324 -+}
772.8325 -+
772.8326 -+static bool gen9_check_repeat(PicturePtr picture)
772.8327 -+{
772.8328 -+	if (!picture->repeat)
772.8329 -+		return true;
772.8330 -+
772.8331 -+	switch (picture->repeatType) {
772.8332 -+	case RepeatNone:
772.8333 -+	case RepeatNormal:
772.8334 -+	case RepeatPad:
772.8335 -+	case RepeatReflect:
772.8336 -+		return true;
772.8337 -+	default:
772.8338 -+		return false;
772.8339 -+	}
772.8340 -+}
772.8341 -+
772.8342 -+static int
772.8343 -+gen9_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine)
772.8344 -+{
772.8345 -+	int base;
772.8346 -+
772.8347 -+	if (has_mask) {
772.8348 -+		if (is_ca) {
772.8349 -+			if (gen9_blend_op[op].src_alpha)
772.8350 -+				base = GEN9_WM_KERNEL_MASKSA;
772.8351 -+			else
772.8352 -+				base = GEN9_WM_KERNEL_MASKCA;
772.8353 -+		} else
772.8354 -+			base = GEN9_WM_KERNEL_MASK;
772.8355 -+	} else
772.8356 -+		base = GEN9_WM_KERNEL_NOMASK;
772.8357 -+
772.8358 -+	return base + !is_affine;
772.8359 -+}
772.8360 -+
772.8361 -+static void
772.8362 -+gen9_emit_push_constants(struct sna *sna)
772.8363 -+{
772.8364 -+#if SIM
772.8365 -+	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_VS | (2 - 2));
772.8366 -+	OUT_BATCH(0);
772.8367 -+
772.8368 -+	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_HS | (2 - 2));
772.8369 -+	OUT_BATCH(0);
772.8370 -+
772.8371 -+	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_DS | (2 - 2));
772.8372 -+	OUT_BATCH(0);
772.8373 -+
772.8374 -+	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_GS | (2 - 2));
772.8375 -+	OUT_BATCH(0);
772.8376 -+
772.8377 -+	OUT_BATCH(GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_PS | (2 - 2));
772.8378 -+	OUT_BATCH(0);
772.8379 -+#endif
772.8380 -+}
772.8381 -+
772.8382 -+static void
772.8383 -+gen9_emit_urb(struct sna *sna)
772.8384 -+{
772.8385 -+	/* num of VS entries must be divisible by 8 if size < 9 */
772.8386 -+	OUT_BATCH(GEN9_3DSTATE_URB_VS | (2 - 2));
772.8387 -+	OUT_BATCH(sna->render_state.gen9.info->urb.max_vs_entries << URB_ENTRY_NUMBER_SHIFT |
772.8388 -+		  (2 - 1) << URB_ENTRY_SIZE_SHIFT |
772.8389 -+		  4 << URB_STARTING_ADDRESS_SHIFT);
772.8390 -+
772.8391 -+	OUT_BATCH(GEN9_3DSTATE_URB_HS | (2 - 2));
772.8392 -+	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
772.8393 -+		  4 << URB_STARTING_ADDRESS_SHIFT);
772.8394 -+
772.8395 -+	OUT_BATCH(GEN9_3DSTATE_URB_DS | (2 - 2));
772.8396 -+	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
772.8397 -+		  4 << URB_STARTING_ADDRESS_SHIFT);
772.8398 -+
772.8399 -+	OUT_BATCH(GEN9_3DSTATE_URB_GS | (2 - 2));
772.8400 -+	OUT_BATCH(0 << URB_ENTRY_SIZE_SHIFT |
772.8401 -+		  4 << URB_STARTING_ADDRESS_SHIFT);
772.8402 -+}
772.8403 -+
772.8404 -+static void
772.8405 -+gen9_emit_state_base_address(struct sna *sna)
772.8406 -+{
772.8407 -+	uint32_t num_pages;
772.8408 -+
772.8409 -+	assert(sna->kgem.surface - sna->kgem.nbatch <= 16384);
772.8410 -+
772.8411 -+	/* WaBindlessSurfaceStateModifyEnable:skl,bxt */
772.8412 -+	OUT_BATCH(GEN9_STATE_BASE_ADDRESS | (19 - 1 - 2));
772.8413 -+	OUT_BATCH64(0); /* general */
772.8414 -+	OUT_BATCH(0); /* stateless dataport */
772.8415 -+	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* surface */
772.8416 -+				     sna->kgem.nbatch,
772.8417 -+				     NULL,
772.8418 -+				     I915_GEM_DOMAIN_INSTRUCTION << 16,
772.8419 -+				     BASE_ADDRESS_MODIFY));
772.8420 -+	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* dynamic */
772.8421 -+				     sna->kgem.nbatch,
772.8422 -+				     sna->render_state.gen9.general_bo,
772.8423 -+				     I915_GEM_DOMAIN_INSTRUCTION << 16,
772.8424 -+				     BASE_ADDRESS_MODIFY));
772.8425 -+	OUT_BATCH64(0); /* indirect */
772.8426 -+	OUT_BATCH64(kgem_add_reloc64(&sna->kgem, /* instruction */
772.8427 -+				     sna->kgem.nbatch,
772.8428 -+				     sna->render_state.gen9.general_bo,
772.8429 -+				     I915_GEM_DOMAIN_INSTRUCTION << 16,
772.8430 -+				     BASE_ADDRESS_MODIFY));
772.8431 -+	/* upper bounds */
772.8432 -+	num_pages = sna->render_state.gen9.general_bo->size.pages.count;
772.8433 -+	OUT_BATCH(0); /* general */
772.8434 -+	OUT_BATCH(num_pages << 12 | 1); /* dynamic */
772.8435 -+	OUT_BATCH(0); /* indirect */
772.8436 -+	OUT_BATCH(num_pages << 12 | 1); /* instruction */
772.8437 -+
772.8438 -+	/* Bindless */
772.8439 -+	OUT_BATCH(0);
772.8440 -+	OUT_BATCH(0);
772.8441 -+	OUT_BATCH(0);
772.8442 -+}
772.8443 -+
772.8444 -+static void
772.8445 -+gen9_emit_vs_invariant(struct sna *sna)
772.8446 -+{
772.8447 -+	OUT_BATCH(GEN9_3DSTATE_VS | (9 - 2));
772.8448 -+	OUT_BATCH64(0); /* no VS kernel */
772.8449 -+	OUT_BATCH(0);
772.8450 -+	OUT_BATCH64(0); /* scratch */
772.8451 -+	OUT_BATCH(0);
772.8452 -+	OUT_BATCH(1 << 1); /* pass-through */
772.8453 -+	OUT_BATCH(1 << 16 | 1 << 21); /* urb write to SBE */
772.8454 -+
772.8455 -+#if SIM
772.8456 -+	OUT_BATCH(GEN9_3DSTATE_CONSTANT_VS | (11 - 2));
772.8457 -+	OUT_BATCH(0);
772.8458 -+	OUT_BATCH(0);
772.8459 -+	OUT_BATCH64(0);
772.8460 -+	OUT_BATCH64(0);
772.8461 -+	OUT_BATCH64(0);
772.8462 -+	OUT_BATCH64(0);
772.8463 -+
772.8464 -+	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_VS | (2 - 2));
772.8465 -+	OUT_BATCH(0);
772.8466 -+
772.8467 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_VS | (2 - 2));
772.8468 -+	OUT_BATCH(0);
772.8469 -+#endif
772.8470 -+}
772.8471 -+
772.8472 -+static void
772.8473 -+gen9_emit_hs_invariant(struct sna *sna)
772.8474 -+{
772.8475 -+	OUT_BATCH(GEN9_3DSTATE_HS | (9 - 2));
772.8476 -+	OUT_BATCH(0);
772.8477 -+	OUT_BATCH(0);
772.8478 -+	OUT_BATCH64(0); /* no HS kernel */
772.8479 -+	OUT_BATCH64(0); /* scratch */
772.8480 -+	OUT_BATCH(0);
772.8481 -+	OUT_BATCH(0); /* pass-through */
772.8482 -+
772.8483 -+#if SIM
772.8484 -+	OUT_BATCH(GEN9_3DSTATE_CONSTANT_HS | (11 - 2));
772.8485 -+	OUT_BATCH(0);
772.8486 -+	OUT_BATCH(0);
772.8487 -+	OUT_BATCH64(0);
772.8488 -+	OUT_BATCH64(0);
772.8489 -+	OUT_BATCH64(0);
772.8490 -+	OUT_BATCH64(0);
772.8491 -+
772.8492 -+#if 1
772.8493 -+	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_HS | (2 - 2));
772.8494 -+	OUT_BATCH(0);
772.8495 -+
772.8496 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_HS | (2 - 2));
772.8497 -+	OUT_BATCH(0);
772.8498 -+#endif
772.8499 -+#endif
772.8500 -+}
772.8501 -+
772.8502 -+static void
772.8503 -+gen9_emit_te_invariant(struct sna *sna)
772.8504 -+{
772.8505 -+	OUT_BATCH(GEN9_3DSTATE_TE | (4 - 2));
772.8506 -+	OUT_BATCH(0);
772.8507 -+	OUT_BATCH(0);
772.8508 -+	OUT_BATCH(0);
772.8509 -+}
772.8510 -+
772.8511 -+static void
772.8512 -+gen9_emit_ds_invariant(struct sna *sna)
772.8513 -+{
772.8514 -+	OUT_BATCH(GEN9_3DSTATE_DS | (11 - 2));
772.8515 -+	OUT_BATCH64(0); /* no kernel */
772.8516 -+	OUT_BATCH(0);
772.8517 -+	OUT_BATCH64(0); /* scratch */
772.8518 -+	OUT_BATCH(0);
772.8519 -+	OUT_BATCH(0);
772.8520 -+	OUT_BATCH(0);
772.8521 -+	OUT_BATCH(0);
772.8522 -+	OUT_BATCH(0);
772.8523 -+
772.8524 -+#if SIM
772.8525 -+	OUT_BATCH(GEN9_3DSTATE_CONSTANT_DS | (11 - 2));
772.8526 -+	OUT_BATCH(0);
772.8527 -+	OUT_BATCH(0);
772.8528 -+	OUT_BATCH64(0);
772.8529 -+	OUT_BATCH64(0);
772.8530 -+	OUT_BATCH64(0);
772.8531 -+	OUT_BATCH64(0);
772.8532 -+
772.8533 -+#if 1
772.8534 -+	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_DS | (2 - 2));
772.8535 -+	OUT_BATCH(0);
772.8536 -+
772.8537 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_DS | (2 - 2));
772.8538 -+	OUT_BATCH(0);
772.8539 -+#endif
772.8540 -+#endif
772.8541 -+}
772.8542 -+
772.8543 -+static void
772.8544 -+gen9_emit_gs_invariant(struct sna *sna)
772.8545 -+{
772.8546 -+	OUT_BATCH(GEN9_3DSTATE_GS | (10 - 2));
772.8547 -+	OUT_BATCH64(0); /* no GS kernel */
772.8548 -+	OUT_BATCH(0);
772.8549 -+	OUT_BATCH64(0); /* scratch */
772.8550 -+	OUT_BATCH(0);
772.8551 -+	OUT_BATCH(0); /* pass-through */
772.8552 -+	OUT_BATCH(0);
772.8553 -+	OUT_BATCH(0);
772.8554 -+
772.8555 -+#if SIM
772.8556 -+	OUT_BATCH(GEN9_3DSTATE_CONSTANT_GS | (11 - 2));
772.8557 -+	OUT_BATCH(0);
772.8558 -+	OUT_BATCH(0);
772.8559 -+	OUT_BATCH64(0);
772.8560 -+	OUT_BATCH64(0);
772.8561 -+	OUT_BATCH64(0);
772.8562 -+	OUT_BATCH64(0);
772.8563 -+
772.8564 -+#if 1
772.8565 -+	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_GS | (2 - 2));
772.8566 -+	OUT_BATCH(0);
772.8567 -+
772.8568 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_GS | (2 - 2));
772.8569 -+	OUT_BATCH(0);
772.8570 -+#endif
772.8571 -+#endif
772.8572 -+}
772.8573 -+
772.8574 -+static void
772.8575 -+gen9_emit_sol_invariant(struct sna *sna)
772.8576 -+{
772.8577 -+	OUT_BATCH(GEN9_3DSTATE_STREAMOUT | (5 - 2));
772.8578 -+	OUT_BATCH(0);
772.8579 -+	OUT_BATCH(0);
772.8580 -+	OUT_BATCH(0);
772.8581 -+	OUT_BATCH(0);
772.8582 -+}
772.8583 -+
772.8584 -+static void
772.8585 -+gen9_emit_sf_invariant(struct sna *sna)
772.8586 -+{
772.8587 -+	OUT_BATCH(GEN9_3DSTATE_SF | (4 - 2));
772.8588 -+	OUT_BATCH(0);
772.8589 -+	OUT_BATCH(0);
772.8590 -+	OUT_BATCH(0);
772.8591 -+}
772.8592 -+
772.8593 -+static void
772.8594 -+gen9_emit_clip_invariant(struct sna *sna)
772.8595 -+{
772.8596 -+	OUT_BATCH(GEN9_3DSTATE_CLIP | (4 - 2));
772.8597 -+	OUT_BATCH(0);
772.8598 -+	OUT_BATCH(0); /* pass-through */
772.8599 -+	OUT_BATCH(0);
772.8600 -+
772.8601 -+	OUT_BATCH(GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP | (2 - 2));
772.8602 -+	OUT_BATCH(0);
772.8603 -+
772.8604 -+	OUT_BATCH(GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_CC | (2 - 2));
772.8605 -+	OUT_BATCH(0);
772.8606 -+}
772.8607 -+
772.8608 -+static void
772.8609 -+gen9_emit_null_depth_buffer(struct sna *sna)
772.8610 -+{
772.8611 -+	OUT_BATCH(GEN9_3DSTATE_DEPTH_BUFFER | (8 - 2));
772.8612 -+#if 1
772.8613 -+	OUT_BATCH(SURFACE_NULL << DEPTH_BUFFER_TYPE_SHIFT |
772.8614 -+		  DEPTHFORMAT_D32_FLOAT << DEPTH_BUFFER_FORMAT_SHIFT);
772.8615 -+#else
772.8616 -+	OUT_BATCH(SURFACE_2D << DEPTH_BUFFER_TYPE_SHIFT |
772.8617 -+		  DEPTHFORMAT_D16_UNORM << DEPTH_BUFFER_FORMAT_SHIFT);
772.8618 -+#endif
772.8619 -+	OUT_BATCH64(0);
772.8620 -+	OUT_BATCH(0);
772.8621 -+	OUT_BATCH(0);
772.8622 -+	OUT_BATCH(0);
772.8623 -+	OUT_BATCH(0);
772.8624 -+
772.8625 -+#if SIM
772.8626 -+	OUT_BATCH(GEN9_3DSTATE_HIER_DEPTH_BUFFER | (5 - 2));
772.8627 -+	OUT_BATCH(0);
772.8628 -+	OUT_BATCH64(0);
772.8629 -+	OUT_BATCH(0);
772.8630 -+#endif
772.8631 -+
772.8632 -+#if SIM
772.8633 -+	OUT_BATCH(GEN9_3DSTATE_STENCIL_BUFFER | (5 - 2));
772.8634 -+	OUT_BATCH(0);
772.8635 -+	OUT_BATCH64(0);
772.8636 -+	OUT_BATCH(0);
772.8637 -+#endif
772.8638 -+
772.8639 -+#if SIM
772.8640 -+	OUT_BATCH(GEN9_3DSTATE_WM_DEPTH_STENCIL | (4 - 2));
772.8641 -+	OUT_BATCH(0);
772.8642 -+	OUT_BATCH(0);
772.8643 -+	OUT_BATCH(0);
772.8644 -+#endif
772.8645 -+
772.8646 -+#if SIM
772.8647 -+	OUT_BATCH(GEN9_3DSTATE_CLEAR_PARAMS | (3 - 2));
772.8648 -+	OUT_BATCH(0);
772.8649 -+	OUT_BATCH(0);
772.8650 -+#endif
772.8651 -+}
772.8652 -+
772.8653 -+static void
772.8654 -+gen9_emit_wm_invariant(struct sna *sna)
772.8655 -+{
772.8656 -+	gen9_emit_null_depth_buffer(sna);
772.8657 -+
772.8658 -+#if SIM
772.8659 -+	OUT_BATCH(GEN9_3DSTATE_SCISSOR_STATE_POINTERS | (2 - 2));
772.8660 -+	OUT_BATCH(0);
772.8661 -+#endif
772.8662 -+
772.8663 -+	OUT_BATCH(GEN9_3DSTATE_WM | (2 - 2));
772.8664 -+	//OUT_BATCH(WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC); /* XXX */
772.8665 -+	OUT_BATCH(WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
772.8666 -+
772.8667 -+#if SIM
772.8668 -+	OUT_BATCH(GEN9_3DSTATE_WM_CHROMAKEY | (2 - 2));
772.8669 -+	OUT_BATCH(0);
772.8670 -+#endif
772.8671 -+
772.8672 -+#if 0
772.8673 -+	OUT_BATCH(GEN9_3DSTATE_WM_HZ_OP | (5 - 2));
772.8674 -+	OUT_BATCH(0);
772.8675 -+	OUT_BATCH(0);
772.8676 -+	OUT_BATCH(0);
772.8677 -+	OUT_BATCH(0);
772.8678 -+#endif
772.8679 -+
772.8680 -+	OUT_BATCH(GEN9_3DSTATE_PS_EXTRA | (2 - 2));
772.8681 -+	OUT_BATCH(PSX_PIXEL_SHADER_VALID |
772.8682 -+		  PSX_ATTRIBUTE_ENABLE);
772.8683 -+
772.8684 -+	OUT_BATCH(GEN9_3DSTATE_RASTER | (5 - 2));
772.8685 -+	OUT_BATCH(RASTER_FRONT_WINDING_CCW |
772.8686 -+		  RASTER_CULL_NONE);
772.8687 -+	OUT_BATCH(0);
772.8688 -+	OUT_BATCH(0);
772.8689 -+	OUT_BATCH(0);
772.8690 -+
772.8691 -+	OUT_BATCH(GEN9_3DSTATE_SBE_SWIZ | (11 - 2));
772.8692 -+	OUT_BATCH(0);
772.8693 -+	OUT_BATCH(0);
772.8694 -+	OUT_BATCH(0);
772.8695 -+	OUT_BATCH(0);
772.8696 -+	OUT_BATCH(0);
772.8697 -+	OUT_BATCH(0);
772.8698 -+	OUT_BATCH(0);
772.8699 -+	OUT_BATCH(0);
772.8700 -+	OUT_BATCH(0);
772.8701 -+	OUT_BATCH(0);
772.8702 -+
772.8703 -+#if SIM
772.8704 -+	OUT_BATCH(GEN9_3DSTATE_CONSTANT_PS | (11 - 2));
772.8705 -+	OUT_BATCH(0);
772.8706 -+	OUT_BATCH(0);
772.8707 -+	OUT_BATCH64(0);
772.8708 -+	OUT_BATCH64(0);
772.8709 -+	OUT_BATCH64(0);
772.8710 -+	OUT_BATCH64(0);
772.8711 -+#endif
772.8712 -+}
772.8713 -+
772.8714 -+static void
772.8715 -+gen9_emit_cc_invariant(struct sna *sna)
772.8716 -+{
772.8717 -+}
772.8718 -+
772.8719 -+static void
772.8720 -+gen9_emit_vf_invariant(struct sna *sna)
772.8721 -+{
772.8722 -+	int n;
772.8723 -+
772.8724 -+#if 1
772.8725 -+	OUT_BATCH(GEN9_3DSTATE_VF | (2 - 2));
772.8726 -+	OUT_BATCH(0);
772.8727 -+#endif
772.8728 -+
772.8729 -+	OUT_BATCH(GEN9_3DSTATE_VF_SGVS | (2 - 2));
772.8730 -+	OUT_BATCH(0);
772.8731 -+
772.8732 -+	OUT_BATCH(GEN9_3DSTATE_VF_TOPOLOGY | (2 - 2));
772.8733 -+	OUT_BATCH(RECTLIST);
772.8734 -+
772.8735 -+	OUT_BATCH(GEN9_3DSTATE_VF_STATISTICS | 0);
772.8736 -+
772.8737 -+	for (n = 1; n <= 3; n++) {
772.8738 -+		OUT_BATCH(GEN9_3DSTATE_VF_INSTANCING | (3 - 2));
772.8739 -+		OUT_BATCH(n);
772.8740 -+		OUT_BATCH(0);
772.8741 -+	}
772.8742 -+}
772.8743 -+
772.8744 -+static void
772.8745 -+gen9_emit_invariant(struct sna *sna)
772.8746 -+{
772.8747 -+	OUT_BATCH(GEN9_PIPELINE_SELECT |
772.8748 -+		  PIPELINE_SELECTION_MASK |
772.8749 -+		  PIPELINE_SELECT_3D);
772.8750 -+
772.8751 -+#if SIM
772.8752 -+	OUT_BATCH(GEN9_STATE_SIP | (3 - 2));
772.8753 -+	OUT_BATCH64(0);
772.8754 -+#endif
772.8755 -+
772.8756 -+	OUT_BATCH(GEN9_3DSTATE_MULTISAMPLE | (2 - 2));
772.8757 -+	OUT_BATCH(MULTISAMPLE_PIXEL_LOCATION_CENTER |
772.8758 -+		  MULTISAMPLE_NUMSAMPLES_1); /* 1 sample/pixel */
772.8759 -+
772.8760 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLE_MASK | (2 - 2));
772.8761 -+	OUT_BATCH(1);
772.8762 -+
772.8763 -+#if SIM
772.8764 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLE_PATTERN | (5 - 2));
772.8765 -+	OUT_BATCH(0);
772.8766 -+	OUT_BATCH(0);
772.8767 -+	OUT_BATCH(0);
772.8768 -+	//OUT_BATCH(8<<20 | 8<<16);
772.8769 -+	OUT_BATCH(0);
772.8770 -+#endif
772.8771 -+
772.8772 -+	gen9_emit_push_constants(sna);
772.8773 -+	gen9_emit_urb(sna);
772.8774 -+
772.8775 -+	gen9_emit_state_base_address(sna);
772.8776 -+
772.8777 -+	gen9_emit_vf_invariant(sna);
772.8778 -+	gen9_emit_vs_invariant(sna);
772.8779 -+	gen9_emit_hs_invariant(sna);
772.8780 -+	gen9_emit_te_invariant(sna);
772.8781 -+	gen9_emit_ds_invariant(sna);
772.8782 -+	gen9_emit_gs_invariant(sna);
772.8783 -+	gen9_emit_sol_invariant(sna);
772.8784 -+	gen9_emit_clip_invariant(sna);
772.8785 -+	gen9_emit_sf_invariant(sna);
772.8786 -+	gen9_emit_wm_invariant(sna);
772.8787 -+	gen9_emit_cc_invariant(sna);
772.8788 -+
772.8789 -+	sna->render_state.gen9.needs_invariant = false;
772.8790 -+}
772.8791 -+
772.8792 -+static void
772.8793 -+gen9_emit_cc(struct sna *sna, uint32_t blend)
772.8794 -+{
772.8795 -+	struct gen9_render_state *render = &sna->render_state.gen9;
772.8796 -+
772.8797 -+	if (render->blend == blend)
772.8798 -+		return;
772.8799 -+
772.8800 -+	DBG(("%s: blend=%x (current=%x), src=%d, dst=%d\n",
772.8801 -+	     __FUNCTION__, blend, render->blend,
772.8802 -+	     blend / GEN9_BLENDFACTOR_COUNT,
772.8803 -+	     blend % GEN9_BLENDFACTOR_COUNT));
772.8804 -+
772.8805 -+	assert(blend < GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT);
772.8806 -+	assert(blend / GEN9_BLENDFACTOR_COUNT > 0);
772.8807 -+	assert(blend % GEN9_BLENDFACTOR_COUNT > 0);
772.8808 -+
772.8809 -+	/* XXX can have up to 8 blend states preload, selectable via
772.8810 -+	 * Render Target Index. What other side-effects of Render Target Index?
772.8811 -+	 */
772.8812 -+
772.8813 -+	OUT_BATCH(GEN9_3DSTATE_PS_BLEND | (2 - 2));
772.8814 -+	if (blend != GEN9_BLEND(NO_BLEND)) {
772.8815 -+		uint32_t src = blend / GEN9_BLENDFACTOR_COUNT;
772.8816 -+		uint32_t dst = blend % GEN9_BLENDFACTOR_COUNT;
772.8817 -+		OUT_BATCH(PS_BLEND_HAS_WRITEABLE_RT |
772.8818 -+			  PS_BLEND_COLOR_BLEND_ENABLE |
772.8819 -+			  src << PS_BLEND_SRC_ALPHA_SHIFT |
772.8820 -+			  dst << PS_BLEND_DST_ALPHA_SHIFT |
772.8821 -+			  src << PS_BLEND_SRC_SHIFT |
772.8822 -+			  dst << PS_BLEND_DST_SHIFT);
772.8823 -+	} else
772.8824 -+		OUT_BATCH(PS_BLEND_HAS_WRITEABLE_RT);
772.8825 -+
772.8826 -+	assert(is_aligned(render->cc_blend + blend * GEN9_BLEND_STATE_PADDED_SIZE, 64));
772.8827 -+	OUT_BATCH(GEN9_3DSTATE_BLEND_STATE_POINTERS | (2 - 2));
772.8828 -+	OUT_BATCH((render->cc_blend + blend * GEN9_BLEND_STATE_PADDED_SIZE) | 1);
772.8829 -+
772.8830 -+	/* Force a CC_STATE pointer change to improve blend performance */
772.8831 -+	OUT_BATCH(GEN9_3DSTATE_CC_STATE_POINTERS | (2 - 2));
772.8832 -+	OUT_BATCH(0);
772.8833 -+
772.8834 -+	render->blend = blend;
772.8835 -+}
772.8836 -+
772.8837 -+static void
772.8838 -+gen9_emit_sampler(struct sna *sna, uint32_t state)
772.8839 -+{
772.8840 -+	if (sna->render_state.gen9.samplers == state)
772.8841 -+		return;
772.8842 -+
772.8843 -+	sna->render_state.gen9.samplers = state;
772.8844 -+
772.8845 -+	DBG(("%s: sampler = %x\n", __FUNCTION__, state));
772.8846 -+
772.8847 -+	assert(2 * sizeof(struct gen9_sampler_state) == 32);
772.8848 -+	OUT_BATCH(GEN9_3DSTATE_SAMPLER_STATE_POINTERS_PS | (2 - 2));
772.8849 -+	OUT_BATCH(sna->render_state.gen9.wm_state + state * 2 * sizeof(struct gen9_sampler_state));
772.8850 -+}
772.8851 -+
772.8852 -+static void
772.8853 -+gen9_emit_sf(struct sna *sna, bool has_mask)
772.8854 -+{
772.8855 -+	int num_sf_outputs = has_mask ? 2 : 1;
772.8856 -+
772.8857 -+	if (sna->render_state.gen9.num_sf_outputs == num_sf_outputs)
772.8858 -+		return;
772.8859 -+
772.8860 -+	DBG(("%s: num_sf_outputs=%d\n", __FUNCTION__, num_sf_outputs));
772.8861 -+
772.8862 -+	sna->render_state.gen9.num_sf_outputs = num_sf_outputs;
772.8863 -+
772.8864 -+	OUT_BATCH(GEN9_3DSTATE_SBE | (6 - 2));
772.8865 -+	OUT_BATCH(num_sf_outputs << SBE_NUM_OUTPUTS_SHIFT |
772.8866 -+		  SBE_FORCE_VERTEX_URB_READ_LENGTH | /* forced is faster */
772.8867 -+		  SBE_FORCE_VERTEX_URB_READ_OFFSET |
772.8868 -+		  1 << SBE_URB_ENTRY_READ_LENGTH_SHIFT |
772.8869 -+		  1 << SBE_URB_ENTRY_READ_OFFSET_SHIFT);
772.8870 -+	OUT_BATCH(0);
772.8871 -+	OUT_BATCH(0);
772.8872 -+        OUT_BATCH(SBE_ACTIVE_COMPONENT_XYZW << 0 |
772.8873 -+		  SBE_ACTIVE_COMPONENT_XYZW << 1);
772.8874 -+        OUT_BATCH(0);
772.8875 -+}
772.8876 -+
772.8877 -+static void
772.8878 -+gen9_emit_wm(struct sna *sna, int kernel)
772.8879 -+{
772.8880 -+	const uint32_t *kernels;
772.8881 -+
772.8882 -+	assert(kernel < ARRAY_SIZE(wm_kernels));
772.8883 -+	if (sna->render_state.gen9.kernel == kernel)
772.8884 -+		return;
772.8885 -+
772.8886 -+	sna->render_state.gen9.kernel = kernel;
772.8887 -+	kernels = sna->render_state.gen9.wm_kernel[kernel];
772.8888 -+
772.8889 -+	DBG(("%s: switching to %s, num_surfaces=%d (8-wide? %d, 16-wide? %d, 32-wide? %d)\n",
772.8890 -+	     __FUNCTION__,
772.8891 -+	     wm_kernels[kernel].name,
772.8892 -+	     wm_kernels[kernel].num_surfaces,
772.8893 -+	     kernels[0], kernels[1], kernels[2]));
772.8894 -+	assert(is_aligned(kernels[0], 64));
772.8895 -+	assert(is_aligned(kernels[1], 64));
772.8896 -+	assert(is_aligned(kernels[2], 64));
772.8897 -+
772.8898 -+	OUT_BATCH(GEN9_3DSTATE_PS | (12 - 2));
772.8899 -+	OUT_BATCH64(kernels[0] ?: kernels[1] ?: kernels[2]);
772.8900 -+	OUT_BATCH(1 << PS_SAMPLER_COUNT_SHIFT |
772.8901 -+		  PS_VECTOR_MASK_ENABLE |
772.8902 -+		  wm_kernels[kernel].num_surfaces << PS_BINDING_TABLE_ENTRY_COUNT_SHIFT);
772.8903 -+	OUT_BATCH64(0); /* scratch address */
772.8904 -+	OUT_BATCH(PS_MAX_THREADS |
772.8905 -+		  (kernels[0] ? PS_8_DISPATCH_ENABLE : 0) |
772.8906 -+		  (kernels[1] ? PS_16_DISPATCH_ENABLE : 0) |
772.8907 -+		  (kernels[2] ? PS_32_DISPATCH_ENABLE : 0));
772.8908 -+	OUT_BATCH((kernels[0] ? 4 : kernels[1] ? 6 : 8) << PS_DISPATCH_START_GRF_SHIFT_0 |
772.8909 -+		  8 << PS_DISPATCH_START_GRF_SHIFT_1 |
772.8910 -+		  6 << PS_DISPATCH_START_GRF_SHIFT_2);
772.8911 -+	OUT_BATCH64(kernels[2]);
772.8912 -+	OUT_BATCH64(kernels[1]);
772.8913 -+}
772.8914 -+
772.8915 -+static bool
772.8916 -+gen9_emit_binding_table(struct sna *sna, uint16_t offset)
772.8917 -+{
772.8918 -+	if (sna->render_state.gen9.surface_table == offset)
772.8919 -+		return false;
772.8920 -+
772.8921 -+	/* Binding table pointers */
772.8922 -+	assert(is_aligned(4*offset, 32));
772.8923 -+	OUT_BATCH(GEN9_3DSTATE_BINDING_TABLE_POINTERS_PS | (2 - 2));
772.8924 -+	OUT_BATCH(offset*4);
772.8925 -+
772.8926 -+	sna->render_state.gen9.surface_table = offset;
772.8927 -+	return true;
772.8928 -+}
772.8929 -+
772.8930 -+static bool
772.8931 -+gen9_emit_drawing_rectangle(struct sna *sna,
772.8932 -+			    const struct sna_composite_op *op)
772.8933 -+{
772.8934 -+	uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
772.8935 -+	uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
772.8936 -+
772.8937 -+	assert(!too_large(abs(op->dst.x), abs(op->dst.y)));
772.8938 -+	assert(!too_large(op->dst.width, op->dst.height));
772.8939 -+
772.8940 -+	if (sna->render_state.gen9.drawrect_limit == limit &&
772.8941 -+	    sna->render_state.gen9.drawrect_offset == offset)
772.8942 -+		return true;
772.8943 -+
772.8944 -+	sna->render_state.gen9.drawrect_offset = offset;
772.8945 -+	sna->render_state.gen9.drawrect_limit = limit;
772.8946 -+
772.8947 -+	OUT_BATCH(GEN9_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
772.8948 -+	OUT_BATCH(0);
772.8949 -+	OUT_BATCH(limit);
772.8950 -+	OUT_BATCH(offset);
772.8951 -+	return false;
772.8952 -+}
772.8953 -+
772.8954 -+static void
772.8955 -+gen9_emit_vertex_elements(struct sna *sna,
772.8956 -+			  const struct sna_composite_op *op)
772.8957 -+{
772.8958 -+	/*
772.8959 -+	 * vertex data in vertex buffer
772.8960 -+	 *    position: (x, y)
772.8961 -+	 *    texture coordinate 0: (u0, v0) if (is_affine is true) else (u0, v0, w0)
772.8962 -+	 *    texture coordinate 1 if (has_mask is true): same as above
772.8963 -+	 */
772.8964 -+	struct gen9_render_state *render = &sna->render_state.gen9;
772.8965 -+	uint32_t src_format, dw;
772.8966 -+	int id = GEN9_VERTEX(op->u.gen9.flags);
772.8967 -+	bool has_mask;
772.8968 -+
772.8969 -+	DBG(("%s: setup id=%d\n", __FUNCTION__, id));
772.8970 -+
772.8971 -+	if (render->ve_id == id)
772.8972 -+		return;
772.8973 -+	render->ve_id = id;
772.8974 -+
772.8975 -+	if (render->ve_dirty) {
772.8976 -+		/* dummy primitive to flush vertex before change? */
772.8977 -+		OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
772.8978 -+		OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
772.8979 -+		OUT_BATCH(0);
772.8980 -+		OUT_BATCH(0);
772.8981 -+		OUT_BATCH(1);	/* single instance */
772.8982 -+		OUT_BATCH(0);	/* start instance location */
772.8983 -+		OUT_BATCH(0);	/* index buffer offset, ignored */
772.8984 -+	}
772.8985 -+
772.8986 -+	/* The VUE layout
772.8987 -+	 *    dword 0-3: pad (0.0, 0.0, 0.0. 0.0)
772.8988 -+	 *    dword 4-7: position (x, y, 1.0, 1.0),
772.8989 -+	 *    dword 8-11: texture coordinate 0 (u0, v0, w0, 1.0)
772.8990 -+	 *    dword 12-15: texture coordinate 1 (u1, v1, w1, 1.0)
772.8991 -+	 *
772.8992 -+	 * dword 4-15 are fetched from vertex buffer
772.8993 -+	 */
772.8994 -+	has_mask = (id >> 2) != 0;
772.8995 -+	OUT_BATCH(GEN9_3DSTATE_VERTEX_ELEMENTS |
772.8996 -+		((2 * (3 + has_mask)) + 1 - 2));
772.8997 -+
772.8998 -+	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
772.8999 -+		  SURFACEFORMAT_R32G32B32A32_FLOAT << VE_FORMAT_SHIFT |
772.9000 -+		  0 << VE_OFFSET_SHIFT);
772.9001 -+	OUT_BATCH(COMPONENT_STORE_0 << VE_COMPONENT_0_SHIFT |
772.9002 -+		  COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT |
772.9003 -+		  COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT |
772.9004 -+		  COMPONENT_STORE_0 << VE_COMPONENT_3_SHIFT);
772.9005 -+
772.9006 -+	/* x,y */
772.9007 -+	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
772.9008 -+		  SURFACEFORMAT_R16G16_SSCALED << VE_FORMAT_SHIFT |
772.9009 -+		  0 << VE_OFFSET_SHIFT);
772.9010 -+	OUT_BATCH(COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT |
772.9011 -+		  COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT |
772.9012 -+		  COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT |
772.9013 -+		  COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT);
772.9014 -+
772.9015 -+	/* u0, v0, w0 */
772.9016 -+	DBG(("%s: first channel %d floats, offset=4\n", __FUNCTION__, id & 3));
772.9017 -+	dw = COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT;
772.9018 -+	switch (id & 3) {
772.9019 -+	default:
772.9020 -+		assert(0);
772.9021 -+	case 0:
772.9022 -+		src_format = SURFACEFORMAT_R16G16_SSCALED;
772.9023 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9024 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
772.9025 -+		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
772.9026 -+		break;
772.9027 -+	case 1:
772.9028 -+		src_format = SURFACEFORMAT_R32_FLOAT;
772.9029 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9030 -+		dw |= COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT;
772.9031 -+		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
772.9032 -+		break;
772.9033 -+	case 2:
772.9034 -+		src_format = SURFACEFORMAT_R32G32_FLOAT;
772.9035 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9036 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
772.9037 -+		dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
772.9038 -+		break;
772.9039 -+	case 3:
772.9040 -+		src_format = SURFACEFORMAT_R32G32B32_FLOAT;
772.9041 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9042 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
772.9043 -+		dw |= COMPONENT_STORE_SRC << VE_COMPONENT_2_SHIFT;
772.9044 -+		break;
772.9045 -+	}
772.9046 -+	OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
772.9047 -+		  src_format << VE_FORMAT_SHIFT |
772.9048 -+		  4 << VE_OFFSET_SHIFT);
772.9049 -+	OUT_BATCH(dw);
772.9050 -+
772.9051 -+	/* u1, v1, w1 */
772.9052 -+	if (has_mask) {
772.9053 -+		unsigned offset = 4 + ((id & 3) ?: 1) * sizeof(float);
772.9054 -+		DBG(("%s: second channel %d floats, offset=%d\n", __FUNCTION__, (id >> 2) & 3, offset));
772.9055 -+		dw = COMPONENT_STORE_1_FLT << VE_COMPONENT_3_SHIFT;
772.9056 -+		switch (id >> 2) {
772.9057 -+		case 1:
772.9058 -+			src_format = SURFACEFORMAT_R32_FLOAT;
772.9059 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9060 -+			dw |= COMPONENT_STORE_0 << VE_COMPONENT_1_SHIFT;
772.9061 -+			dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
772.9062 -+			break;
772.9063 -+		default:
772.9064 -+			assert(0);
772.9065 -+		case 2:
772.9066 -+			src_format = SURFACEFORMAT_R32G32_FLOAT;
772.9067 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9068 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
772.9069 -+			dw |= COMPONENT_STORE_0 << VE_COMPONENT_2_SHIFT;
772.9070 -+			break;
772.9071 -+		case 3:
772.9072 -+			src_format = SURFACEFORMAT_R32G32B32_FLOAT;
772.9073 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_0_SHIFT;
772.9074 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_1_SHIFT;
772.9075 -+			dw |= COMPONENT_STORE_SRC << VE_COMPONENT_2_SHIFT;
772.9076 -+			break;
772.9077 -+		}
772.9078 -+		OUT_BATCH(id << VE_INDEX_SHIFT | VE_VALID |
772.9079 -+			  src_format << VE_FORMAT_SHIFT |
772.9080 -+			  offset << VE_OFFSET_SHIFT);
772.9081 -+		OUT_BATCH(dw);
772.9082 -+	}
772.9083 -+
772.9084 -+	render->ve_dirty = true;
772.9085 -+}
772.9086 -+
772.9087 -+inline static void
772.9088 -+gen9_emit_pipe_invalidate(struct sna *sna)
772.9089 -+{
772.9090 -+	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
772.9091 -+	OUT_BATCH(PIPE_CONTROL_WC_FLUSH |
772.9092 -+		  PIPE_CONTROL_TC_FLUSH |
772.9093 -+		  PIPE_CONTROL_CS_STALL);
772.9094 -+	OUT_BATCH64(0);
772.9095 -+	OUT_BATCH64(0);
772.9096 -+}
772.9097 -+
772.9098 -+inline static void
772.9099 -+gen9_emit_pipe_flush(struct sna *sna, bool need_stall)
772.9100 -+{
772.9101 -+	unsigned stall;
772.9102 -+
772.9103 -+	stall = 0;
772.9104 -+	if (need_stall)
772.9105 -+		stall = (PIPE_CONTROL_CS_STALL |
772.9106 -+			 PIPE_CONTROL_STALL_AT_SCOREBOARD);
772.9107 -+
772.9108 -+	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
772.9109 -+	OUT_BATCH(PIPE_CONTROL_WC_FLUSH | stall);
772.9110 -+	OUT_BATCH64(0);
772.9111 -+	OUT_BATCH64(0);
772.9112 -+}
772.9113 -+
772.9114 -+inline static void
772.9115 -+gen9_emit_pipe_stall(struct sna *sna)
772.9116 -+{
772.9117 -+	OUT_BATCH(GEN9_PIPE_CONTROL | (6 - 2));
772.9118 -+	OUT_BATCH(PIPE_CONTROL_CS_STALL |
772.9119 -+		  PIPE_CONTROL_FLUSH |
772.9120 -+		  PIPE_CONTROL_STALL_AT_SCOREBOARD);
772.9121 -+	OUT_BATCH64(0);
772.9122 -+	OUT_BATCH64(0);
772.9123 -+}
772.9124 -+
772.9125 -+static void
772.9126 -+gen9_emit_state(struct sna *sna,
772.9127 -+		const struct sna_composite_op *op,
772.9128 -+		uint16_t wm_binding_table)
772.9129 -+{
772.9130 -+	bool need_invalidate;
772.9131 -+	bool need_flush;
772.9132 -+	bool need_stall;
772.9133 -+
772.9134 -+	assert(op->dst.bo->exec);
772.9135 -+
772.9136 -+	need_flush = wm_binding_table & 1 ||
772.9137 -+		(sna->render_state.gen9.emit_flush && GEN9_READS_DST(op->u.gen9.flags));
772.9138 -+	if (ALWAYS_FLUSH)
772.9139 -+		need_flush = true;
772.9140 -+
772.9141 -+	wm_binding_table &= ~1;
772.9142 -+
772.9143 -+	need_stall = sna->render_state.gen9.surface_table != wm_binding_table;
772.9144 -+
772.9145 -+	need_invalidate = kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo);
772.9146 -+	if (ALWAYS_INVALIDATE)
772.9147 -+		need_invalidate = true;
772.9148 -+
772.9149 -+	need_stall &= gen9_emit_drawing_rectangle(sna, op);
772.9150 -+	if (ALWAYS_STALL)
772.9151 -+		need_stall = true;
772.9152 -+
772.9153 -+	if (need_invalidate) {
772.9154 -+		gen9_emit_pipe_invalidate(sna);
772.9155 -+		kgem_clear_dirty(&sna->kgem);
772.9156 -+		assert(op->dst.bo->exec);
772.9157 -+		kgem_bo_mark_dirty(op->dst.bo);
772.9158 -+
772.9159 -+		need_flush = false;
772.9160 -+		need_stall = false;
772.9161 -+	}
772.9162 -+	if (need_flush) {
772.9163 -+		gen9_emit_pipe_flush(sna, need_stall);
772.9164 -+		need_stall = false;
772.9165 -+	}
772.9166 -+	if (need_stall)
772.9167 -+		gen9_emit_pipe_stall(sna);
772.9168 -+
772.9169 -+	gen9_emit_cc(sna, GEN9_BLEND(op->u.gen9.flags));
772.9170 -+	gen9_emit_sampler(sna, GEN9_SAMPLER(op->u.gen9.flags));
772.9171 -+	gen9_emit_sf(sna, GEN9_VERTEX(op->u.gen9.flags) >> 2);
772.9172 -+	gen9_emit_wm(sna, GEN9_KERNEL(op->u.gen9.flags));
772.9173 -+	gen9_emit_vertex_elements(sna, op);
772.9174 -+	gen9_emit_binding_table(sna, wm_binding_table);
772.9175 -+
772.9176 -+	sna->render_state.gen9.emit_flush = GEN9_READS_DST(op->u.gen9.flags);
772.9177 -+}
772.9178 -+
772.9179 -+static bool gen9_magic_ca_pass(struct sna *sna,
772.9180 -+			       const struct sna_composite_op *op)
772.9181 -+{
772.9182 -+	struct gen9_render_state *state = &sna->render_state.gen9;
772.9183 -+
772.9184 -+	if (!op->need_magic_ca_pass)
772.9185 -+		return false;
772.9186 -+
772.9187 -+	DBG(("%s: CA fixup (%d -> %d)\n", __FUNCTION__,
772.9188 -+	     sna->render.vertex_start, sna->render.vertex_index));
772.9189 -+
772.9190 -+	gen9_emit_pipe_stall(sna);
772.9191 -+
772.9192 -+	gen9_emit_cc(sna,
772.9193 -+		     GEN9_BLEND(gen9_get_blend(PictOpAdd, true,
772.9194 -+					       op->dst.format)));
772.9195 -+	gen9_emit_wm(sna,
772.9196 -+		     gen9_choose_composite_kernel(PictOpAdd,
772.9197 -+						  true, true,
772.9198 -+						  op->is_affine));
772.9199 -+
772.9200 -+	OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
772.9201 -+	OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
772.9202 -+	OUT_BATCH(sna->render.vertex_index - sna->render.vertex_start);
772.9203 -+	OUT_BATCH(sna->render.vertex_start);
772.9204 -+	OUT_BATCH(1);	/* single instance */
772.9205 -+	OUT_BATCH(0);	/* start instance location */
772.9206 -+	OUT_BATCH(0);	/* index buffer offset, ignored */
772.9207 -+
772.9208 -+	state->last_primitive = sna->kgem.nbatch;
772.9209 -+	state->ve_dirty = false;
772.9210 -+	return true;
772.9211 -+}
772.9212 -+
772.9213 -+static void null_create(struct sna_static_stream *stream)
772.9214 -+{
772.9215 -+	/* A bunch of zeros useful for legacy border color and depth-stencil */
772.9216 -+	sna_static_stream_map(stream, 64, 64);
772.9217 -+}
772.9218 -+
772.9219 -+static void
772.9220 -+sampler_state_init(struct gen9_sampler_state *sampler_state,
772.9221 -+		   sampler_filter_t filter,
772.9222 -+		   sampler_extend_t extend)
772.9223 -+{
772.9224 -+	COMPILE_TIME_ASSERT(sizeof(*sampler_state) == 4*sizeof(uint32_t));
772.9225 -+
772.9226 -+	sampler_state->ss0.lod_preclamp = 2;	/* GL mode */
772.9227 -+	sampler_state->ss0.default_color_mode = 1;
772.9228 -+
772.9229 -+	switch (filter) {
772.9230 -+	default:
772.9231 -+	case SAMPLER_FILTER_NEAREST:
772.9232 -+		sampler_state->ss0.min_filter = MAPFILTER_NEAREST;
772.9233 -+		sampler_state->ss0.mag_filter = MAPFILTER_NEAREST;
772.9234 -+		break;
772.9235 -+	case SAMPLER_FILTER_BILINEAR:
772.9236 -+		sampler_state->ss0.min_filter = MAPFILTER_LINEAR;
772.9237 -+		sampler_state->ss0.mag_filter = MAPFILTER_LINEAR;
772.9238 -+		break;
772.9239 -+	}
772.9240 -+
772.9241 -+	/* XXX bicubic filter using MAPFILTER_FLEXIBLE */
772.9242 -+
772.9243 -+	switch (extend) {
772.9244 -+	default:
772.9245 -+	case SAMPLER_EXTEND_NONE:
772.9246 -+		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
772.9247 -+		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
772.9248 -+		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
772.9249 -+		break;
772.9250 -+	case SAMPLER_EXTEND_REPEAT:
772.9251 -+		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_WRAP;
772.9252 -+		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_WRAP;
772.9253 -+		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_WRAP;
772.9254 -+		break;
772.9255 -+	case SAMPLER_EXTEND_PAD:
772.9256 -+		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_CLAMP;
772.9257 -+		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_CLAMP;
772.9258 -+		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_CLAMP;
772.9259 -+		break;
772.9260 -+	case SAMPLER_EXTEND_REFLECT:
772.9261 -+		sampler_state->ss3.r_wrap_mode = TEXCOORDMODE_MIRROR;
772.9262 -+		sampler_state->ss3.s_wrap_mode = TEXCOORDMODE_MIRROR;
772.9263 -+		sampler_state->ss3.t_wrap_mode = TEXCOORDMODE_MIRROR;
772.9264 -+		break;
772.9265 -+	}
772.9266 -+}
772.9267 -+
772.9268 -+static void
772.9269 -+sampler_copy_init(struct gen9_sampler_state *ss)
772.9270 -+{
772.9271 -+	sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
772.9272 -+	ss->ss3.non_normalized_coord = 1;
772.9273 -+
772.9274 -+	sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
772.9275 -+}
772.9276 -+
772.9277 -+static void
772.9278 -+sampler_fill_init(struct gen9_sampler_state *ss)
772.9279 -+{
772.9280 -+	sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_REPEAT);
772.9281 -+	ss->ss3.non_normalized_coord = 1;
772.9282 -+
772.9283 -+	sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE);
772.9284 -+}
772.9285 -+
772.9286 -+static uint32_t
772.9287 -+gen9_tiling_bits(uint32_t tiling)
772.9288 -+{
772.9289 -+	switch (tiling) {
772.9290 -+	default: assert(0);
772.9291 -+	case I915_TILING_NONE: return 0;
772.9292 -+	case I915_TILING_X: return SURFACE_TILED;
772.9293 -+	case I915_TILING_Y: return SURFACE_TILED | SURFACE_TILED_Y;
772.9294 -+	}
772.9295 -+}
772.9296 -+
772.9297 -+#define MOCS_PTE (1 << 1)
772.9298 -+#define MOCS_WB (2 << 1)
772.9299 -+
772.9300 -+/**
772.9301 -+ * Sets up the common fields for a surface state buffer for the given
772.9302 -+ * picture in the given surface state buffer.
772.9303 -+ */
772.9304 -+static uint32_t
772.9305 -+gen9_bind_bo(struct sna *sna,
772.9306 -+	     struct kgem_bo *bo,
772.9307 -+	     uint32_t width,
772.9308 -+	     uint32_t height,
772.9309 -+	     uint32_t format,
772.9310 -+	     bool is_dst)
772.9311 -+{
772.9312 -+	uint32_t *ss;
772.9313 -+	uint32_t domains;
772.9314 -+	int offset;
772.9315 -+	uint32_t is_scanout = is_dst && bo->scanout;
772.9316 -+
772.9317 -+	/* After the first bind, we manage the cache domains within the batch */
772.9318 -+	offset = kgem_bo_get_binding(bo, format | is_dst << 30 | is_scanout << 31);
772.9319 -+	if (offset) {
772.9320 -+		if (is_dst)
772.9321 -+			kgem_bo_mark_dirty(bo);
772.9322 -+		assert(offset >= sna->kgem.surface);
772.9323 -+		return offset * sizeof(uint32_t);
772.9324 -+	}
772.9325 -+
772.9326 -+	offset = sna->kgem.surface -= SURFACE_DW;
772.9327 -+	ss = sna->kgem.batch + offset;
772.9328 -+	ss[0] = (SURFACE_2D << SURFACE_TYPE_SHIFT |
772.9329 -+		 gen9_tiling_bits(bo->tiling) |
772.9330 -+		 format << SURFACE_FORMAT_SHIFT |
772.9331 -+		 SURFACE_VALIGN_4 | SURFACE_HALIGN_4);
772.9332 -+	if (is_dst) {
772.9333 -+		ss[0] |= SURFACE_RC_READ_WRITE;
772.9334 -+		domains = I915_GEM_DOMAIN_RENDER << 16 |I915_GEM_DOMAIN_RENDER;
772.9335 -+	} else
772.9336 -+		domains = I915_GEM_DOMAIN_SAMPLER << 16;
772.9337 -+	ss[1] = (is_scanout || (is_dst && is_uncached(sna, bo))) ? MOCS_PTE << 24 : MOCS_WB << 24;
772.9338 -+	ss[2] = ((width - 1)  << SURFACE_WIDTH_SHIFT |
772.9339 -+		 (height - 1) << SURFACE_HEIGHT_SHIFT);
772.9340 -+	ss[3] = (bo->pitch - 1) << SURFACE_PITCH_SHIFT;
772.9341 -+	ss[4] = 0;
772.9342 -+	ss[5] = 0;
772.9343 -+	ss[6] = 0;
772.9344 -+	ss[7] = SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA);
772.9345 -+	*(uint64_t *)(ss+8) = kgem_add_reloc64(&sna->kgem, offset + 8, bo, domains, 0);
772.9346 -+	ss[10] = 0;
772.9347 -+	ss[11] = 0;
772.9348 -+	ss[12] = 0;
772.9349 -+	ss[13] = 0;
772.9350 -+	ss[14] = 0;
772.9351 -+	ss[15] = 0;
772.9352 -+
772.9353 -+	kgem_bo_set_binding(bo, format | is_dst << 30 | is_scanout << 31, offset);
772.9354 -+
772.9355 -+	DBG(("[%x] bind bo(handle=%d, addr=%lx), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> %s\n",
772.9356 -+	     offset, bo->handle, *(uint64_t *)(ss+8),
772.9357 -+	     format, width, height, bo->pitch, bo->tiling,
772.9358 -+	     domains & 0xffff ? "render" : "sampler"));
772.9359 -+
772.9360 -+	return offset * sizeof(uint32_t);
772.9361 -+}
772.9362 -+
772.9363 -+static void gen9_emit_vertex_buffer(struct sna *sna,
772.9364 -+				    const struct sna_composite_op *op)
772.9365 -+{
772.9366 -+	int id = GEN9_VERTEX(op->u.gen9.flags);
772.9367 -+
772.9368 -+	OUT_BATCH(GEN9_3DSTATE_VERTEX_BUFFERS | (5 - 2));
772.9369 -+	OUT_BATCH(id << VB_INDEX_SHIFT | VB_MODIFY_ENABLE |
772.9370 -+		  4*op->floats_per_vertex);
772.9371 -+	sna->render.vertex_reloc[sna->render.nvertex_reloc++] = sna->kgem.nbatch;
772.9372 -+	OUT_BATCH64(0);
772.9373 -+	OUT_BATCH(~0); /* buffer size: disabled */
772.9374 -+
772.9375 -+	sna->render.vb_id |= 1 << id;
772.9376 -+}
772.9377 -+
772.9378 -+static void gen9_emit_primitive(struct sna *sna)
772.9379 -+{
772.9380 -+	if (sna->kgem.nbatch == sna->render_state.gen9.last_primitive) {
772.9381 -+		sna->render.vertex_offset = sna->kgem.nbatch - 5;
772.9382 -+		return;
772.9383 -+	}
772.9384 -+
772.9385 -+	OUT_BATCH(GEN9_3DPRIMITIVE | (7 - 2));
772.9386 -+	OUT_BATCH(0); /* ignored, see VF_TOPOLOGY */
772.9387 -+	sna->render.vertex_offset = sna->kgem.nbatch;
772.9388 -+	OUT_BATCH(0);	/* vertex count, to be filled in later */
772.9389 -+	OUT_BATCH(sna->render.vertex_index);
772.9390 -+	OUT_BATCH(1);	/* single instance */
772.9391 -+	OUT_BATCH(0);	/* start instance location */
772.9392 -+	OUT_BATCH(0);	/* index buffer offset, ignored */
772.9393 -+	sna->render.vertex_start = sna->render.vertex_index;
772.9394 -+
772.9395 -+	sna->render_state.gen9.last_primitive = sna->kgem.nbatch;
772.9396 -+	sna->render_state.gen9.ve_dirty = false;
772.9397 -+}
772.9398 -+
772.9399 -+static bool gen9_rectangle_begin(struct sna *sna,
772.9400 -+				 const struct sna_composite_op *op)
772.9401 -+{
772.9402 -+	int id = 1 << GEN9_VERTEX(op->u.gen9.flags);
772.9403 -+	int ndwords;
772.9404 -+
772.9405 -+	if (sna_vertex_wait__locked(&sna->render) && sna->render.vertex_offset)
772.9406 -+		return true;
772.9407 -+
772.9408 -+	ndwords = op->need_magic_ca_pass ? 60 : 6;
772.9409 -+	if ((sna->render.vb_id & id) == 0)
772.9410 -+		ndwords += 5;
772.9411 -+	if (!kgem_check_batch(&sna->kgem, ndwords))
772.9412 -+		return false;
772.9413 -+
772.9414 -+	if ((sna->render.vb_id & id) == 0)
772.9415 -+		gen9_emit_vertex_buffer(sna, op);
772.9416 -+
772.9417 -+	gen9_emit_primitive(sna);
772.9418 -+	return true;
772.9419 -+}
772.9420 -+
772.9421 -+static int gen9_get_rectangles__flush(struct sna *sna,
772.9422 -+				      const struct sna_composite_op *op)
772.9423 -+{
772.9424 -+	/* Preventing discarding new vbo after lock contention */
772.9425 -+	if (sna_vertex_wait__locked(&sna->render)) {
772.9426 -+		int rem = vertex_space(sna);
772.9427 -+		if (rem > op->floats_per_rect)
772.9428 -+			return rem;
772.9429 -+	}
772.9430 -+
772.9431 -+	if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 65 : 6))
772.9432 -+		return 0;
772.9433 -+	if (!kgem_check_reloc_and_exec(&sna->kgem, 2))
772.9434 -+		return 0;
772.9435 -+
772.9436 -+	if (sna->render.vertex_offset) {
772.9437 -+		gen8_vertex_flush(sna);
772.9438 -+		if (gen9_magic_ca_pass(sna, op)) {
772.9439 -+			gen9_emit_pipe_invalidate(sna);
772.9440 -+			gen9_emit_cc(sna, GEN9_BLEND(op->u.gen9.flags));
772.9441 -+			gen9_emit_wm(sna, GEN9_KERNEL(op->u.gen9.flags));
772.9442 -+		}
772.9443 -+	}
772.9444 -+
772.9445 -+	return gen8_vertex_finish(sna);
772.9446 -+}
772.9447 -+
772.9448 -+inline static int gen9_get_rectangles(struct sna *sna,
772.9449 -+				      const struct sna_composite_op *op,
772.9450 -+				      int want,
772.9451 -+				      void (*emit_state)(struct sna *sna, const struct sna_composite_op *op))
772.9452 -+{
772.9453 -+	int rem;
772.9454 -+
772.9455 -+	assert(want);
772.9456 -+
772.9457 -+start:
772.9458 -+	rem = vertex_space(sna);
772.9459 -+	if (unlikely(rem < op->floats_per_rect)) {
772.9460 -+		DBG(("flushing vbo for %s: %d < %d\n",
772.9461 -+		     __FUNCTION__, rem, op->floats_per_rect));
772.9462 -+		rem = gen9_get_rectangles__flush(sna, op);
772.9463 -+		if (unlikely(rem == 0))
772.9464 -+			goto flush;
772.9465 -+	}
772.9466 -+
772.9467 -+	if (unlikely(sna->render.vertex_offset == 0)) {
772.9468 -+		if (!gen9_rectangle_begin(sna, op))
772.9469 -+			goto flush;
772.9470 -+		else
772.9471 -+			goto start;
772.9472 -+	}
772.9473 -+
772.9474 -+	assert(rem <= vertex_space(sna));
772.9475 -+	assert(op->floats_per_rect <= rem);
772.9476 -+	if (want > 1 && want * op->floats_per_rect > rem)
772.9477 -+		want = rem / op->floats_per_rect;
772.9478 -+
772.9479 -+	assert(want > 0);
772.9480 -+	sna->render.vertex_index += 3*want;
772.9481 -+	return want;
772.9482 -+
772.9483 -+flush:
772.9484 -+	if (sna->render.vertex_offset) {
772.9485 -+		gen8_vertex_flush(sna);
772.9486 -+		gen9_magic_ca_pass(sna, op);
772.9487 -+	}
772.9488 -+	sna_vertex_wait__locked(&sna->render);
772.9489 -+	_kgem_submit(&sna->kgem);
772.9490 -+	emit_state(sna, op);
772.9491 -+	goto start;
772.9492 -+}
772.9493 -+
772.9494 -+inline static uint32_t *gen9_composite_get_binding_table(struct sna *sna,
772.9495 -+							 uint16_t *offset)
772.9496 -+{
772.9497 -+	uint32_t *table;
772.9498 -+
772.9499 -+	assert(sna->kgem.surface <= 16384);
772.9500 -+	sna->kgem.surface -= SURFACE_DW;
772.9501 -+	/* Clear all surplus entries to zero in case of prefetch */
772.9502 -+	table = memset(sna->kgem.batch + sna->kgem.surface, 0, 64);
772.9503 -+
772.9504 -+	DBG(("%s(%x)\n", __FUNCTION__, 4*sna->kgem.surface));
772.9505 -+
772.9506 -+	*offset = sna->kgem.surface;
772.9507 -+	return table;
772.9508 -+}
772.9509 -+
772.9510 -+static void
772.9511 -+gen9_get_batch(struct sna *sna, const struct sna_composite_op *op)
772.9512 -+{
772.9513 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo);
772.9514 -+
772.9515 -+	if (!kgem_check_batch_with_surfaces(&sna->kgem, 150, 2*(1+3))) {
772.9516 -+		DBG(("%s: flushing batch: %d < %d+%d\n",
772.9517 -+		     __FUNCTION__, sna->kgem.surface - sna->kgem.nbatch,
772.9518 -+		     150, 4*8*2));
772.9519 -+		_kgem_submit(&sna->kgem);
772.9520 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.9521 -+	}
772.9522 -+
772.9523 -+	assert(sna->kgem.mode == KGEM_RENDER);
772.9524 -+	assert(sna->kgem.ring == KGEM_RENDER);
772.9525 -+
772.9526 -+	if (sna->render_state.gen9.needs_invariant)
772.9527 -+		gen9_emit_invariant(sna);
772.9528 -+}
772.9529 -+
772.9530 -+static void gen9_emit_composite_state(struct sna *sna,
772.9531 -+				      const struct sna_composite_op *op)
772.9532 -+{
772.9533 -+	uint32_t *binding_table;
772.9534 -+	uint16_t offset, dirty;
772.9535 -+
772.9536 -+	gen9_get_batch(sna, op);
772.9537 -+
772.9538 -+	binding_table = gen9_composite_get_binding_table(sna, &offset);
772.9539 -+
772.9540 -+	dirty = kgem_bo_is_dirty(op->dst.bo);
772.9541 -+
772.9542 -+	binding_table[0] =
772.9543 -+		gen9_bind_bo(sna,
772.9544 -+			    op->dst.bo, op->dst.width, op->dst.height,
772.9545 -+			    gen9_get_dest_format(op->dst.format),
772.9546 -+			    true);
772.9547 -+	binding_table[1] =
772.9548 -+		gen9_bind_bo(sna,
772.9549 -+			     op->src.bo, op->src.width, op->src.height,
772.9550 -+			     op->src.card_format,
772.9551 -+			     false);
772.9552 -+	if (op->mask.bo) {
772.9553 -+		binding_table[2] =
772.9554 -+			gen9_bind_bo(sna,
772.9555 -+				     op->mask.bo,
772.9556 -+				     op->mask.width,
772.9557 -+				     op->mask.height,
772.9558 -+				     op->mask.card_format,
772.9559 -+				     false);
772.9560 -+	}
772.9561 -+
772.9562 -+	if (sna->kgem.surface == offset &&
772.9563 -+	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table &&
772.9564 -+	    (op->mask.bo == NULL ||
772.9565 -+	     sna->kgem.batch[sna->render_state.gen9.surface_table+2] == binding_table[2])) {
772.9566 -+		sna->kgem.surface += SURFACE_DW;
772.9567 -+		offset = sna->render_state.gen9.surface_table;
772.9568 -+	}
772.9569 -+
772.9570 -+	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
772.9571 -+		dirty = 0;
772.9572 -+
772.9573 -+	gen9_emit_state(sna, op, offset | dirty);
772.9574 -+}
772.9575 -+
772.9576 -+static void
772.9577 -+gen9_align_vertex(struct sna *sna, const struct sna_composite_op *op)
772.9578 -+{
772.9579 -+	if (op->floats_per_vertex != sna->render_state.gen9.floats_per_vertex) {
772.9580 -+		DBG(("aligning vertex: was %d, now %d floats per vertex\n",
772.9581 -+		     sna->render_state.gen9.floats_per_vertex, op->floats_per_vertex));
772.9582 -+		gen8_vertex_align(sna, op);
772.9583 -+		sna->render_state.gen9.floats_per_vertex = op->floats_per_vertex;
772.9584 -+	}
772.9585 -+}
772.9586 -+
772.9587 -+fastcall static void
772.9588 -+gen9_render_composite_blt(struct sna *sna,
772.9589 -+			  const struct sna_composite_op *op,
772.9590 -+			  const struct sna_composite_rectangles *r)
772.9591 -+{
772.9592 -+	gen9_get_rectangles(sna, op, 1, gen9_emit_composite_state);
772.9593 -+	op->prim_emit(sna, op, r);
772.9594 -+}
772.9595 -+
772.9596 -+fastcall static void
772.9597 -+gen9_render_composite_box(struct sna *sna,
772.9598 -+			  const struct sna_composite_op *op,
772.9599 -+			  const BoxRec *box)
772.9600 -+{
772.9601 -+	struct sna_composite_rectangles r;
772.9602 -+
772.9603 -+	gen9_get_rectangles(sna, op, 1, gen9_emit_composite_state);
772.9604 -+
772.9605 -+	DBG(("  %s: (%d, %d), (%d, %d)\n",
772.9606 -+	     __FUNCTION__,
772.9607 -+	     box->x1, box->y1, box->x2, box->y2));
772.9608 -+
772.9609 -+	r.dst.x = box->x1;
772.9610 -+	r.dst.y = box->y1;
772.9611 -+	r.width  = box->x2 - box->x1;
772.9612 -+	r.height = box->y2 - box->y1;
772.9613 -+	r.src = r.mask = r.dst;
772.9614 -+
772.9615 -+	op->prim_emit(sna, op, &r);
772.9616 -+}
772.9617 -+
772.9618 -+static void
772.9619 -+gen9_render_composite_boxes__blt(struct sna *sna,
772.9620 -+				 const struct sna_composite_op *op,
772.9621 -+				 const BoxRec *box, int nbox)
772.9622 -+{
772.9623 -+	DBG(("composite_boxes(%d)\n", nbox));
772.9624 -+
772.9625 -+	do {
772.9626 -+		int nbox_this_time;
772.9627 -+
772.9628 -+		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
772.9629 -+						     gen9_emit_composite_state);
772.9630 -+		nbox -= nbox_this_time;
772.9631 -+
772.9632 -+		do {
772.9633 -+			struct sna_composite_rectangles r;
772.9634 -+
772.9635 -+			DBG(("  %s: (%d, %d), (%d, %d)\n",
772.9636 -+			     __FUNCTION__,
772.9637 -+			     box->x1, box->y1, box->x2, box->y2));
772.9638 -+
772.9639 -+			r.dst.x = box->x1;
772.9640 -+			r.dst.y = box->y1;
772.9641 -+			r.width  = box->x2 - box->x1;
772.9642 -+			r.height = box->y2 - box->y1;
772.9643 -+			r.src = r.mask = r.dst;
772.9644 -+
772.9645 -+			op->prim_emit(sna, op, &r);
772.9646 -+			box++;
772.9647 -+		} while (--nbox_this_time);
772.9648 -+	} while (nbox);
772.9649 -+}
772.9650 -+
772.9651 -+static void
772.9652 -+gen9_render_composite_boxes(struct sna *sna,
772.9653 -+			    const struct sna_composite_op *op,
772.9654 -+			    const BoxRec *box, int nbox)
772.9655 -+{
772.9656 -+	DBG(("%s: nbox=%d\n", __FUNCTION__, nbox));
772.9657 -+
772.9658 -+	do {
772.9659 -+		int nbox_this_time;
772.9660 -+		float *v;
772.9661 -+
772.9662 -+		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
772.9663 -+						     gen9_emit_composite_state);
772.9664 -+		assert(nbox_this_time);
772.9665 -+		nbox -= nbox_this_time;
772.9666 -+
772.9667 -+		v = sna->render.vertices + sna->render.vertex_used;
772.9668 -+		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
772.9669 -+
772.9670 -+		op->emit_boxes(op, box, nbox_this_time, v);
772.9671 -+		box += nbox_this_time;
772.9672 -+	} while (nbox);
772.9673 -+}
772.9674 -+
772.9675 -+static void
772.9676 -+gen9_render_composite_boxes__thread(struct sna *sna,
772.9677 -+				    const struct sna_composite_op *op,
772.9678 -+				    const BoxRec *box, int nbox)
772.9679 -+{
772.9680 -+	DBG(("%s: nbox=%d\n", __FUNCTION__, nbox));
772.9681 -+
772.9682 -+	sna_vertex_lock(&sna->render);
772.9683 -+	do {
772.9684 -+		int nbox_this_time;
772.9685 -+		float *v;
772.9686 -+
772.9687 -+		nbox_this_time = gen9_get_rectangles(sna, op, nbox,
772.9688 -+						     gen9_emit_composite_state);
772.9689 -+		assert(nbox_this_time);
772.9690 -+		nbox -= nbox_this_time;
772.9691 -+
772.9692 -+		v = sna->render.vertices + sna->render.vertex_used;
772.9693 -+		sna->render.vertex_used += nbox_this_time * op->floats_per_rect;
772.9694 -+
772.9695 -+		sna_vertex_acquire__locked(&sna->render);
772.9696 -+		sna_vertex_unlock(&sna->render);
772.9697 -+
772.9698 -+		op->emit_boxes(op, box, nbox_this_time, v);
772.9699 -+		box += nbox_this_time;
772.9700 -+
772.9701 -+		sna_vertex_lock(&sna->render);
772.9702 -+		sna_vertex_release__locked(&sna->render);
772.9703 -+	} while (nbox);
772.9704 -+	sna_vertex_unlock(&sna->render);
772.9705 -+}
772.9706 -+
772.9707 -+static uint32_t
772.9708 -+gen9_create_blend_state(struct sna_static_stream *stream)
772.9709 -+{
772.9710 -+	char *base, *ptr;
772.9711 -+	int src, dst;
772.9712 -+
772.9713 -+	COMPILE_TIME_ASSERT(((GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT << 4) & (1 << 15)) == 0);
772.9714 -+
772.9715 -+	base = sna_static_stream_map(stream,
772.9716 -+				     GEN9_BLENDFACTOR_COUNT * GEN9_BLENDFACTOR_COUNT * GEN9_BLEND_STATE_PADDED_SIZE,
772.9717 -+				     64);
772.9718 -+
772.9719 -+	ptr = base;
772.9720 -+	for (src = 0; src < GEN9_BLENDFACTOR_COUNT; src++) {
772.9721 -+		for (dst = 0; dst < GEN9_BLENDFACTOR_COUNT; dst++) {
772.9722 -+			struct gen9_blend_state *blend =
772.9723 -+				(struct gen9_blend_state *)ptr;
772.9724 -+
772.9725 -+			assert(((ptr - base) & 63) == 0);
772.9726 -+			COMPILE_TIME_ASSERT(sizeof(blend->common) == 4);
772.9727 -+			COMPILE_TIME_ASSERT(sizeof(blend->rt) == 8);
772.9728 -+			COMPILE_TIME_ASSERT((char *)&blend->rt - (char *)blend == 4);
772.9729 -+
772.9730 -+			blend->rt.post_blend_clamp = 1;
772.9731 -+			blend->rt.pre_blend_clamp = 1;
772.9732 -+
772.9733 -+			blend->rt.color_blend =
772.9734 -+				!(dst == BLENDFACTOR_ZERO && src == BLENDFACTOR_ONE);
772.9735 -+			blend->rt.dest_blend_factor = dst;
772.9736 -+			blend->rt.source_blend_factor = src;
772.9737 -+			blend->rt.color_blend_function = BLENDFUNCTION_ADD;
772.9738 -+
772.9739 -+			blend->rt.dest_alpha_blend_factor = dst;
772.9740 -+			blend->rt.source_alpha_blend_factor = src;
772.9741 -+			blend->rt.alpha_blend_function = BLENDFUNCTION_ADD;
772.9742 -+
772.9743 -+			ptr += GEN9_BLEND_STATE_PADDED_SIZE;
772.9744 -+		}
772.9745 -+	}
772.9746 -+
772.9747 -+	return sna_static_stream_offsetof(stream, base);
772.9748 -+}
772.9749 -+
772.9750 -+static int
772.9751 -+gen9_composite_picture(struct sna *sna,
772.9752 -+		       PicturePtr picture,
772.9753 -+		       struct sna_composite_channel *channel,
772.9754 -+		       int x, int y,
772.9755 -+		       int w, int h,
772.9756 -+		       int dst_x, int dst_y,
772.9757 -+		       bool precise)
772.9758 -+{
772.9759 -+	PixmapPtr pixmap;
772.9760 -+	uint32_t color;
772.9761 -+	int16_t dx, dy;
772.9762 -+
772.9763 -+	DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n",
772.9764 -+	     __FUNCTION__, x, y, w, h, dst_x, dst_y));
772.9765 -+
772.9766 -+	channel->is_solid = false;
772.9767 -+	channel->card_format = -1;
772.9768 -+
772.9769 -+	if (sna_picture_is_solid(picture, &color))
772.9770 -+		return gen4_channel_init_solid(sna, channel, color);
772.9771 -+
772.9772 -+	if (picture->pDrawable == NULL) {
772.9773 -+		int ret;
772.9774 -+
772.9775 -+		if (picture->pSourcePict->type == SourcePictTypeLinear)
772.9776 -+			return gen4_channel_init_linear(sna, picture, channel,
772.9777 -+							x, y,
772.9778 -+							w, h,
772.9779 -+							dst_x, dst_y);
772.9780 -+
772.9781 -+		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
772.9782 -+		ret = -1;
772.9783 -+		if (!precise)
772.9784 -+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
772.9785 -+								      x, y, w, h, dst_x, dst_y);
772.9786 -+		if (ret == -1)
772.9787 -+			ret = sna_render_picture_fixup(sna, picture, channel,
772.9788 -+						       x, y, w, h, dst_x, dst_y);
772.9789 -+		return ret;
772.9790 -+	}
772.9791 -+
772.9792 -+	if (picture->alphaMap) {
772.9793 -+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
772.9794 -+		return sna_render_picture_fixup(sna, picture, channel,
772.9795 -+						x, y, w, h, dst_x, dst_y);
772.9796 -+	}
772.9797 -+
772.9798 -+	if (!gen9_check_repeat(picture))
772.9799 -+		return sna_render_picture_fixup(sna, picture, channel,
772.9800 -+						x, y, w, h, dst_x, dst_y);
772.9801 -+
772.9802 -+	if (!gen9_check_filter(picture))
772.9803 -+		return sna_render_picture_fixup(sna, picture, channel,
772.9804 -+						x, y, w, h, dst_x, dst_y);
772.9805 -+
772.9806 -+	channel->repeat = picture->repeat ? picture->repeatType : RepeatNone;
772.9807 -+	channel->filter = picture->filter;
772.9808 -+
772.9809 -+	pixmap = get_drawable_pixmap(picture->pDrawable);
772.9810 -+	get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy);
772.9811 -+
772.9812 -+	x += dx + picture->pDrawable->x;
772.9813 -+	y += dy + picture->pDrawable->y;
772.9814 -+
772.9815 -+	channel->is_affine = sna_transform_is_affine(picture->transform);
772.9816 -+	if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) {
772.9817 -+		DBG(("%s: integer translation (%d, %d), removing\n",
772.9818 -+		     __FUNCTION__, dx, dy));
772.9819 -+		x += dx;
772.9820 -+		y += dy;
772.9821 -+		channel->transform = NULL;
772.9822 -+		channel->filter = PictFilterNearest;
772.9823 -+
772.9824 -+		if (channel->repeat ||
772.9825 -+		    (x >= 0 &&
772.9826 -+		     y >= 0 &&
772.9827 -+		     x + w <= pixmap->drawable.width &&
772.9828 -+		     y + h <= pixmap->drawable.height)) {
772.9829 -+			struct sna_pixmap *priv = sna_pixmap(pixmap);
772.9830 -+			if (priv && priv->clear) {
772.9831 -+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
772.9832 -+				return gen4_channel_init_solid(sna, channel, solid_color(picture->format, priv->clear_color));
772.9833 -+			}
772.9834 -+		}
772.9835 -+	} else
772.9836 -+		channel->transform = picture->transform;
772.9837 -+
772.9838 -+	channel->pict_format = picture->format;
772.9839 -+	channel->card_format = gen9_get_card_format(picture->format);
772.9840 -+	if (channel->card_format == (unsigned)-1)
772.9841 -+		return sna_render_picture_convert(sna, picture, channel, pixmap,
772.9842 -+						  x, y, w, h, dst_x, dst_y,
772.9843 -+						  false);
772.9844 -+
772.9845 -+	if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
772.9846 -+		DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__,
772.9847 -+		     pixmap->drawable.width, pixmap->drawable.height));
772.9848 -+		return sna_render_picture_extract(sna, picture, channel,
772.9849 -+						  x, y, w, h, dst_x, dst_y);
772.9850 -+	}
772.9851 -+
772.9852 -+	return sna_render_pixmap_bo(sna, channel, pixmap,
772.9853 -+				    x, y, w, h, dst_x, dst_y);
772.9854 -+}
772.9855 -+
772.9856 -+inline static bool gen9_composite_channel_convert(struct sna_composite_channel *channel)
772.9857 -+{
772.9858 -+	if (unaligned(channel->bo, PICT_FORMAT_BPP(channel->pict_format)))
772.9859 -+		return false;
772.9860 -+
772.9861 -+	channel->repeat = gen9_repeat(channel->repeat);
772.9862 -+	channel->filter = gen9_filter(channel->filter);
772.9863 -+	if (channel->card_format == (unsigned)-1)
772.9864 -+		channel->card_format = gen9_get_card_format(channel->pict_format);
772.9865 -+	assert(channel->card_format != (unsigned)-1);
772.9866 -+
772.9867 -+	return true;
772.9868 -+}
772.9869 -+
772.9870 -+static void gen9_render_composite_done(struct sna *sna,
772.9871 -+				       const struct sna_composite_op *op)
772.9872 -+{
772.9873 -+	if (sna->render.vertex_offset) {
772.9874 -+		gen8_vertex_flush(sna);
772.9875 -+		gen9_magic_ca_pass(sna, op);
772.9876 -+	}
772.9877 -+
772.9878 -+	if (op->mask.bo)
772.9879 -+		kgem_bo_destroy(&sna->kgem, op->mask.bo);
772.9880 -+	if (op->src.bo)
772.9881 -+		kgem_bo_destroy(&sna->kgem, op->src.bo);
772.9882 -+
772.9883 -+	sna_render_composite_redirect_done(sna, op);
772.9884 -+}
772.9885 -+
772.9886 -+inline static bool
772.9887 -+gen9_composite_set_target(struct sna *sna,
772.9888 -+			  struct sna_composite_op *op,
772.9889 -+			  PicturePtr dst,
772.9890 -+			  int x, int y, int w, int h,
772.9891 -+			  bool partial)
772.9892 -+{
772.9893 -+	BoxRec box;
772.9894 -+	unsigned int hint;
772.9895 -+
772.9896 -+	DBG(("%s: (%d, %d)x(%d, %d), partial?=%d\n", __FUNCTION__, x, y, w, h, partial));
772.9897 -+
772.9898 -+	op->dst.pixmap = get_drawable_pixmap(dst->pDrawable);
772.9899 -+	op->dst.format = dst->format;
772.9900 -+	op->dst.width  = op->dst.pixmap->drawable.width;
772.9901 -+	op->dst.height = op->dst.pixmap->drawable.height;
772.9902 -+
772.9903 -+	if (w | h) {
772.9904 -+		assert(w && h);
772.9905 -+		box.x1 = x;
772.9906 -+		box.y1 = y;
772.9907 -+		box.x2 = x + w;
772.9908 -+		box.y2 = y + h;
772.9909 -+	} else
772.9910 -+		sna_render_picture_extents(dst, &box);
772.9911 -+
772.9912 -+	hint = PREFER_GPU | RENDER_GPU;
772.9913 -+	if (!need_tiling(sna, op->dst.width, op->dst.height))
772.9914 -+		hint |= FORCE_GPU;
772.9915 -+	if (!partial) {
772.9916 -+		hint |= IGNORE_DAMAGE;
772.9917 -+		if (w == op->dst.width && h == op->dst.height)
772.9918 -+			hint |= REPLACES;
772.9919 -+	}
772.9920 -+
772.9921 -+	op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage);
772.9922 -+	if (op->dst.bo == NULL)
772.9923 -+		return false;
772.9924 -+
772.9925 -+	assert(!op->damage || !DAMAGE_IS_ALL(*op->damage));
772.9926 -+
772.9927 -+	if (unaligned(op->dst.bo, dst->pDrawable->bitsPerPixel))
772.9928 -+		return false;
772.9929 -+
772.9930 -+	if (hint & REPLACES) {
772.9931 -+		struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap);
772.9932 -+		kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
772.9933 -+	}
772.9934 -+
772.9935 -+	get_drawable_deltas(dst->pDrawable, op->dst.pixmap,
772.9936 -+			    &op->dst.x, &op->dst.y);
772.9937 -+
772.9938 -+	DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n",
772.9939 -+	     __FUNCTION__,
772.9940 -+	     op->dst.pixmap->drawable.serialNumber, (int)op->dst.format,
772.9941 -+	     op->dst.width, op->dst.height,
772.9942 -+	     op->dst.bo->pitch,
772.9943 -+	     op->dst.x, op->dst.y,
772.9944 -+	     op->damage ? *op->damage : (void *)-1));
772.9945 -+
772.9946 -+	assert(op->dst.bo->proxy == NULL);
772.9947 -+
772.9948 -+	if (too_large(op->dst.width, op->dst.height) &&
772.9949 -+	    !sna_render_composite_redirect(sna, op, x, y, w, h, partial))
772.9950 -+		return false;
772.9951 -+
772.9952 -+	return true;
772.9953 -+}
772.9954 -+
772.9955 -+static bool
772.9956 -+try_blt(struct sna *sna,
772.9957 -+	uint8_t op,
772.9958 -+	PicturePtr src,
772.9959 -+	PicturePtr mask,
772.9960 -+	PicturePtr dst,
772.9961 -+	int16_t src_x, int16_t src_y,
772.9962 -+	int16_t msk_x, int16_t msk_y,
772.9963 -+	int16_t dst_x, int16_t dst_y,
772.9964 -+	int16_t width, int16_t height,
772.9965 -+	unsigned flags,
772.9966 -+	struct sna_composite_op *tmp)
772.9967 -+{
772.9968 -+	struct kgem_bo *bo;
772.9969 -+
772.9970 -+	if (sna->kgem.mode == KGEM_BLT) {
772.9971 -+		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.9972 -+		goto execute;
772.9973 -+	}
772.9974 -+
772.9975 -+	if (too_large(width, height)) {
772.9976 -+		DBG(("%s: operation too large for 3D pipe (%d, %d)\n",
772.9977 -+		     __FUNCTION__, width, height));
772.9978 -+		goto execute;
772.9979 -+	}
772.9980 -+
772.9981 -+	bo = __sna_drawable_peek_bo(dst->pDrawable);
772.9982 -+	if (bo == NULL)
772.9983 -+		goto execute;
772.9984 -+
772.9985 -+	if (untiled_tlb_miss(bo))
772.9986 -+		goto execute;
772.9987 -+
772.9988 -+	if (bo->rq) {
772.9989 -+		if (RQ_IS_BLT(bo->rq))
772.9990 -+			goto execute;
772.9991 -+
772.9992 -+		return false;
772.9993 -+	}
772.9994 -+
772.9995 -+	if (bo->tiling == I915_TILING_Y)
772.9996 -+		goto upload;
772.9997 -+
772.9998 -+	if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0))
772.9999 -+		goto execute;
772.10000 -+
772.10001 -+	if (src->pDrawable == dst->pDrawable &&
772.10002 -+	    (sna->render_state.gt < 3 || width*height < 1024) &&
772.10003 -+	    can_switch_to_blt(sna, bo, 0))
772.10004 -+		goto execute;
772.10005 -+
772.10006 -+	if (src->pDrawable) {
772.10007 -+		struct kgem_bo *s = __sna_drawable_peek_bo(src->pDrawable);
772.10008 -+		if (s == NULL)
772.10009 -+			goto upload;
772.10010 -+
772.10011 -+		if (prefer_blt_bo(sna, s, bo))
772.10012 -+			goto execute;
772.10013 -+	}
772.10014 -+
772.10015 -+	if (sna->kgem.ring == KGEM_BLT) {
772.10016 -+		DBG(("%s: already performing BLT\n", __FUNCTION__));
772.10017 -+		goto execute;
772.10018 -+	}
772.10019 -+
772.10020 -+upload:
772.10021 -+	flags |= COMPOSITE_UPLOAD;
772.10022 -+execute:
772.10023 -+	return sna_blt_composite(sna, op,
772.10024 -+				 src, dst,
772.10025 -+				 src_x, src_y,
772.10026 -+				 dst_x, dst_y,
772.10027 -+				 width, height,
772.10028 -+				 flags, tmp);
772.10029 -+}
772.10030 -+
772.10031 -+static bool
772.10032 -+check_gradient(PicturePtr picture, bool precise)
772.10033 -+{
772.10034 -+	if (picture->pDrawable)
772.10035 -+		return false;
772.10036 -+
772.10037 -+	switch (picture->pSourcePict->type) {
772.10038 -+	case SourcePictTypeSolidFill:
772.10039 -+	case SourcePictTypeLinear:
772.10040 -+		return false;
772.10041 -+	default:
772.10042 -+		return precise;
772.10043 -+	}
772.10044 -+}
772.10045 -+
772.10046 -+static bool
772.10047 -+has_alphamap(PicturePtr p)
772.10048 -+{
772.10049 -+	return p->alphaMap != NULL;
772.10050 -+}
772.10051 -+
772.10052 -+static bool
772.10053 -+need_upload(PicturePtr p)
772.10054 -+{
772.10055 -+	return p->pDrawable && unattached(p->pDrawable) && untransformed(p);
772.10056 -+}
772.10057 -+
772.10058 -+static bool
772.10059 -+source_is_busy(PixmapPtr pixmap)
772.10060 -+{
772.10061 -+	struct sna_pixmap *priv = sna_pixmap(pixmap);
772.10062 -+	if (priv == NULL || priv->clear)
772.10063 -+		return false;
772.10064 -+
772.10065 -+	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
772.10066 -+		return true;
772.10067 -+
772.10068 -+	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
772.10069 -+		return true;
772.10070 -+
772.10071 -+	return priv->gpu_damage && !priv->cpu_damage;
772.10072 -+}
772.10073 -+
772.10074 -+static bool
772.10075 -+source_fallback(PicturePtr p, PixmapPtr pixmap, bool precise)
772.10076 -+{
772.10077 -+	if (sna_picture_is_solid(p, NULL))
772.10078 -+		return false;
772.10079 -+
772.10080 -+	if (p->pSourcePict)
772.10081 -+		return check_gradient(p, precise);
772.10082 -+
772.10083 -+	if (!gen9_check_repeat(p) || !gen9_check_format(p->format))
772.10084 -+		return true;
772.10085 -+
772.10086 -+	if (pixmap && source_is_busy(pixmap))
772.10087 -+		return false;
772.10088 -+
772.10089 -+	return has_alphamap(p) || !gen9_check_filter(p) || need_upload(p);
772.10090 -+}
772.10091 -+
772.10092 -+static bool
772.10093 -+gen9_composite_fallback(struct sna *sna,
772.10094 -+			PicturePtr src,
772.10095 -+			PicturePtr mask,
772.10096 -+			PicturePtr dst)
772.10097 -+{
772.10098 -+	PixmapPtr src_pixmap;
772.10099 -+	PixmapPtr mask_pixmap;
772.10100 -+	PixmapPtr dst_pixmap;
772.10101 -+	bool src_fallback, mask_fallback;
772.10102 -+
772.10103 -+	if (!gen9_check_dst_format(dst->format)) {
772.10104 -+		DBG(("%s: unknown destination format: %d\n",
772.10105 -+		     __FUNCTION__, dst->format));
772.10106 -+		return true;
772.10107 -+	}
772.10108 -+
772.10109 -+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
772.10110 -+
772.10111 -+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
772.10112 -+	src_fallback = source_fallback(src, src_pixmap,
772.10113 -+				       dst->polyMode == PolyModePrecise);
772.10114 -+
772.10115 -+	if (mask) {
772.10116 -+		mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL;
772.10117 -+		mask_fallback = source_fallback(mask, mask_pixmap,
772.10118 -+						dst->polyMode == PolyModePrecise);
772.10119 -+	} else {
772.10120 -+		mask_pixmap = NULL;
772.10121 -+		mask_fallback = false;
772.10122 -+	}
772.10123 -+
772.10124 -+	/* If we are using the destination as a source and need to
772.10125 -+	 * readback in order to upload the source, do it all
772.10126 -+	 * on the cpu.
772.10127 -+	 */
772.10128 -+	if (src_pixmap == dst_pixmap && src_fallback) {
772.10129 -+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
772.10130 -+		return true;
772.10131 -+	}
772.10132 -+	if (mask_pixmap == dst_pixmap && mask_fallback) {
772.10133 -+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
772.10134 -+		return true;
772.10135 -+	}
772.10136 -+
772.10137 -+	/* If anything is on the GPU, push everything out to the GPU */
772.10138 -+	if (dst_use_gpu(dst_pixmap)) {
772.10139 -+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
772.10140 -+		     __FUNCTION__));
772.10141 -+		return false;
772.10142 -+	}
772.10143 -+
772.10144 -+	if (src_pixmap && !src_fallback) {
772.10145 -+		DBG(("%s: src is already on the GPU, try to use GPU\n",
772.10146 -+		     __FUNCTION__));
772.10147 -+		return false;
772.10148 -+	}
772.10149 -+	if (mask_pixmap && !mask_fallback) {
772.10150 -+		DBG(("%s: mask is already on the GPU, try to use GPU\n",
772.10151 -+		     __FUNCTION__));
772.10152 -+		return false;
772.10153 -+	}
772.10154 -+
772.10155 -+	/* However if the dst is not on the GPU and we need to
772.10156 -+	 * render one of the sources using the CPU, we may
772.10157 -+	 * as well do the entire operation in place onthe CPU.
772.10158 -+	 */
772.10159 -+	if (src_fallback) {
772.10160 -+		DBG(("%s: dst is on the CPU and src will fallback\n",
772.10161 -+		     __FUNCTION__));
772.10162 -+		return true;
772.10163 -+	}
772.10164 -+
772.10165 -+	if (mask && mask_fallback) {
772.10166 -+		DBG(("%s: dst is on the CPU and mask will fallback\n",
772.10167 -+		     __FUNCTION__));
772.10168 -+		return true;
772.10169 -+	}
772.10170 -+
772.10171 -+	if (too_large(dst_pixmap->drawable.width,
772.10172 -+		      dst_pixmap->drawable.height) &&
772.10173 -+	    dst_is_cpu(dst_pixmap)) {
772.10174 -+		DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__));
772.10175 -+		return true;
772.10176 -+	}
772.10177 -+
772.10178 -+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
772.10179 -+	     __FUNCTION__));
772.10180 -+	return dst_use_cpu(dst_pixmap);
772.10181 -+}
772.10182 -+
772.10183 -+static int
772.10184 -+reuse_source(struct sna *sna,
772.10185 -+	     PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
772.10186 -+	     PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
772.10187 -+{
772.10188 -+	uint32_t color;
772.10189 -+
772.10190 -+	if (src_x != msk_x || src_y != msk_y)
772.10191 -+		return false;
772.10192 -+
772.10193 -+	if (src == mask) {
772.10194 -+		DBG(("%s: mask is source\n", __FUNCTION__));
772.10195 -+		*mc = *sc;
772.10196 -+		mc->bo = kgem_bo_reference(mc->bo);
772.10197 -+		return true;
772.10198 -+	}
772.10199 -+
772.10200 -+	if (sna_picture_is_solid(mask, &color))
772.10201 -+		return gen4_channel_init_solid(sna, mc, color);
772.10202 -+
772.10203 -+	if (sc->is_solid)
772.10204 -+		return false;
772.10205 -+
772.10206 -+	if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
772.10207 -+		return false;
772.10208 -+
772.10209 -+	DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
772.10210 -+
772.10211 -+	if (!sna_transform_equal(src->transform, mask->transform))
772.10212 -+		return false;
772.10213 -+
772.10214 -+	if (!sna_picture_alphamap_equal(src, mask))
772.10215 -+		return false;
772.10216 -+
772.10217 -+	if (!gen9_check_repeat(mask))
772.10218 -+		return false;
772.10219 -+
772.10220 -+	if (!gen9_check_filter(mask))
772.10221 -+		return false;
772.10222 -+
772.10223 -+	if (!gen9_check_format(mask->format))
772.10224 -+		return false;
772.10225 -+
772.10226 -+	DBG(("%s: reusing source channel for mask with a twist\n",
772.10227 -+	     __FUNCTION__));
772.10228 -+
772.10229 -+	*mc = *sc;
772.10230 -+	mc->repeat = gen9_repeat(mask->repeat ? mask->repeatType : RepeatNone);
772.10231 -+	mc->filter = gen9_filter(mask->filter);
772.10232 -+	mc->pict_format = mask->format;
772.10233 -+	mc->card_format = gen9_get_card_format(mask->format);
772.10234 -+	mc->bo = kgem_bo_reference(mc->bo);
772.10235 -+	return true;
772.10236 -+}
772.10237 -+
772.10238 -+static bool
772.10239 -+gen9_render_composite(struct sna *sna,
772.10240 -+		      uint8_t op,
772.10241 -+		      PicturePtr src,
772.10242 -+		      PicturePtr mask,
772.10243 -+		      PicturePtr dst,
772.10244 -+		      int16_t src_x, int16_t src_y,
772.10245 -+		      int16_t msk_x, int16_t msk_y,
772.10246 -+		      int16_t dst_x, int16_t dst_y,
772.10247 -+		      int16_t width, int16_t height,
772.10248 -+		      unsigned flags,
772.10249 -+		      struct sna_composite_op *tmp)
772.10250 -+{
772.10251 -+	if (op >= ARRAY_SIZE(gen9_blend_op))
772.10252 -+		return false;
772.10253 -+
772.10254 -+	DBG(("%s: %dx%d, current mode=%d/%d\n", __FUNCTION__,
772.10255 -+	     width, height, sna->kgem.mode, sna->kgem.ring));
772.10256 -+
772.10257 -+	if (mask == NULL &&
772.10258 -+	    try_blt(sna, op,
772.10259 -+		    src, mask, dst,
772.10260 -+		    src_x, src_y,
772.10261 -+		    msk_x, msk_y,
772.10262 -+		    dst_x, dst_y,
772.10263 -+		    width, height,
772.10264 -+		    flags, tmp))
772.10265 -+		return true;
772.10266 -+
772.10267 -+	if (gen9_composite_fallback(sna, src, mask, dst))
772.10268 -+		goto fallback;
772.10269 -+
772.10270 -+	if (need_tiling(sna, width, height))
772.10271 -+		return sna_tiling_composite(op, src, mask, dst,
772.10272 -+					    src_x, src_y,
772.10273 -+					    msk_x, msk_y,
772.10274 -+					    dst_x, dst_y,
772.10275 -+					    width, height,
772.10276 -+					    tmp);
772.10277 -+
772.10278 -+	if (op == PictOpClear && src == sna->clear)
772.10279 -+		op = PictOpSrc;
772.10280 -+	tmp->op = op;
772.10281 -+	if (!gen9_composite_set_target(sna, tmp, dst,
772.10282 -+				       dst_x, dst_y, width, height,
772.10283 -+				       flags & COMPOSITE_PARTIAL || op > PictOpSrc))
772.10284 -+		goto fallback;
772.10285 -+
772.10286 -+	switch (gen9_composite_picture(sna, src, &tmp->src,
772.10287 -+				       src_x, src_y,
772.10288 -+				       width, height,
772.10289 -+				       dst_x, dst_y,
772.10290 -+				       dst->polyMode == PolyModePrecise)) {
772.10291 -+	case -1:
772.10292 -+		goto cleanup_dst;
772.10293 -+	case 0:
772.10294 -+		if (!gen4_channel_init_solid(sna, &tmp->src, 0))
772.10295 -+			goto cleanup_dst;
772.10296 -+		/* fall through to fixup */
772.10297 -+	case 1:
772.10298 -+		/* Did we just switch rings to prepare the source? */
772.10299 -+		if (mask == NULL &&
772.10300 -+		    (prefer_blt_composite(sna, tmp) ||
772.10301 -+		     unaligned(tmp->src.bo, PICT_FORMAT_BPP(tmp->src.pict_format))) &&
772.10302 -+		    sna_blt_composite__convert(sna,
772.10303 -+					       dst_x, dst_y, width, height,
772.10304 -+					       tmp))
772.10305 -+			return true;
772.10306 -+
772.10307 -+		if (!gen9_composite_channel_convert(&tmp->src))
772.10308 -+			goto cleanup_src;
772.10309 -+
772.10310 -+		break;
772.10311 -+	}
772.10312 -+
772.10313 -+	tmp->is_affine = tmp->src.is_affine;
772.10314 -+	tmp->has_component_alpha = false;
772.10315 -+	tmp->need_magic_ca_pass = false;
772.10316 -+
772.10317 -+	tmp->mask.bo = NULL;
772.10318 -+	tmp->mask.filter = SAMPLER_FILTER_NEAREST;
772.10319 -+	tmp->mask.repeat = SAMPLER_EXTEND_NONE;
772.10320 -+
772.10321 -+	if (mask) {
772.10322 -+		if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
772.10323 -+			tmp->has_component_alpha = true;
772.10324 -+
772.10325 -+			/* Check if it's component alpha that relies on a source alpha and on
772.10326 -+			 * the source value.  We can only get one of those into the single
772.10327 -+			 * source value that we get to blend with.
772.10328 -+			 */
772.10329 -+			if (gen9_blend_op[op].src_alpha &&
772.10330 -+			    (gen9_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
772.10331 -+				if (op != PictOpOver)
772.10332 -+					goto cleanup_src;
772.10333 -+
772.10334 -+				tmp->need_magic_ca_pass = true;
772.10335 -+				tmp->op = PictOpOutReverse;
772.10336 -+			}
772.10337 -+		}
772.10338 -+
772.10339 -+		if (!reuse_source(sna,
772.10340 -+				  src, &tmp->src, src_x, src_y,
772.10341 -+				  mask, &tmp->mask, msk_x, msk_y)) {
772.10342 -+			switch (gen9_composite_picture(sna, mask, &tmp->mask,
772.10343 -+						       msk_x, msk_y,
772.10344 -+						       width, height,
772.10345 -+						       dst_x, dst_y,
772.10346 -+						       dst->polyMode == PolyModePrecise)) {
772.10347 -+			case -1:
772.10348 -+				goto cleanup_src;
772.10349 -+			case 0:
772.10350 -+				if (!gen4_channel_init_solid(sna, &tmp->mask, 0))
772.10351 -+					goto cleanup_src;
772.10352 -+				/* fall through to fixup */
772.10353 -+			case 1:
772.10354 -+				if (!gen9_composite_channel_convert(&tmp->mask))
772.10355 -+					goto cleanup_mask;
772.10356 -+				break;
772.10357 -+			}
772.10358 -+		}
772.10359 -+
772.10360 -+		tmp->is_affine &= tmp->mask.is_affine;
772.10361 -+	}
772.10362 -+
772.10363 -+	tmp->u.gen9.flags =
772.10364 -+		GEN9_SET_FLAGS(SAMPLER_OFFSET(tmp->src.filter,
772.10365 -+					      tmp->src.repeat,
772.10366 -+					      tmp->mask.filter,
772.10367 -+					      tmp->mask.repeat),
772.10368 -+			       gen9_get_blend(tmp->op,
772.10369 -+					      tmp->has_component_alpha,
772.10370 -+					      tmp->dst.format),
772.10371 -+			       gen9_choose_composite_kernel(tmp->op,
772.10372 -+							    tmp->mask.bo != NULL,
772.10373 -+							    tmp->has_component_alpha,
772.10374 -+							    tmp->is_affine),
772.10375 -+			       gen4_choose_composite_emitter(sna, tmp));
772.10376 -+
772.10377 -+	tmp->blt   = gen9_render_composite_blt;
772.10378 -+	tmp->box   = gen9_render_composite_box;
772.10379 -+	tmp->boxes = gen9_render_composite_boxes__blt;
772.10380 -+	if (tmp->emit_boxes){
772.10381 -+		tmp->boxes = gen9_render_composite_boxes;
772.10382 -+		tmp->thread_boxes = gen9_render_composite_boxes__thread;
772.10383 -+	}
772.10384 -+	tmp->done  = gen9_render_composite_done;
772.10385 -+
772.10386 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo);
772.10387 -+	if (!kgem_check_bo(&sna->kgem,
772.10388 -+			   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
772.10389 -+			   NULL)) {
772.10390 -+		kgem_submit(&sna->kgem);
772.10391 -+		if (!kgem_check_bo(&sna->kgem,
772.10392 -+				   tmp->dst.bo, tmp->src.bo, tmp->mask.bo,
772.10393 -+				   NULL))
772.10394 -+			goto cleanup_mask;
772.10395 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.10396 -+	}
772.10397 -+
772.10398 -+	gen9_align_vertex(sna, tmp);
772.10399 -+	gen9_emit_composite_state(sna, tmp);
772.10400 -+	return true;
772.10401 -+
772.10402 -+cleanup_mask:
772.10403 -+	if (tmp->mask.bo) {
772.10404 -+		kgem_bo_destroy(&sna->kgem, tmp->mask.bo);
772.10405 -+		tmp->mask.bo = NULL;
772.10406 -+	}
772.10407 -+cleanup_src:
772.10408 -+	if (tmp->src.bo) {
772.10409 -+		kgem_bo_destroy(&sna->kgem, tmp->src.bo);
772.10410 -+		tmp->src.bo = NULL;
772.10411 -+	}
772.10412 -+cleanup_dst:
772.10413 -+	if (tmp->redirect.real_bo) {
772.10414 -+		kgem_bo_destroy(&sna->kgem, tmp->dst.bo);
772.10415 -+		tmp->redirect.real_bo = NULL;
772.10416 -+	}
772.10417 -+fallback:
772.10418 -+	return (mask == NULL &&
772.10419 -+		sna_blt_composite(sna, op,
772.10420 -+				  src, dst,
772.10421 -+				  src_x, src_y,
772.10422 -+				  dst_x, dst_y,
772.10423 -+				  width, height,
772.10424 -+				  flags | COMPOSITE_FALLBACK, tmp));
772.10425 -+}
772.10426 -+
772.10427 -+#if !NO_COMPOSITE_SPANS
772.10428 -+fastcall static void
772.10429 -+gen9_render_composite_spans_box(struct sna *sna,
772.10430 -+				const struct sna_composite_spans_op *op,
772.10431 -+				const BoxRec *box, float opacity)
772.10432 -+{
772.10433 -+	DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n",
772.10434 -+	     __FUNCTION__,
772.10435 -+	     op->base.src.offset[0], op->base.src.offset[1],
772.10436 -+	     opacity,
772.10437 -+	     op->base.dst.x, op->base.dst.y,
772.10438 -+	     box->x1, box->y1,
772.10439 -+	     box->x2 - box->x1,
772.10440 -+	     box->y2 - box->y1));
772.10441 -+
772.10442 -+	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_composite_state);
772.10443 -+	op->prim_emit(sna, op, box, opacity);
772.10444 -+}
772.10445 -+
772.10446 -+static void
772.10447 -+gen9_render_composite_spans_boxes(struct sna *sna,
772.10448 -+				  const struct sna_composite_spans_op *op,
772.10449 -+				  const BoxRec *box, int nbox,
772.10450 -+				  float opacity)
772.10451 -+{
772.10452 -+	DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n",
772.10453 -+	     __FUNCTION__, nbox,
772.10454 -+	     op->base.src.offset[0], op->base.src.offset[1],
772.10455 -+	     opacity,
772.10456 -+	     op->base.dst.x, op->base.dst.y));
772.10457 -+
772.10458 -+	do {
772.10459 -+		int nbox_this_time;
772.10460 -+
772.10461 -+		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
772.10462 -+						     gen9_emit_composite_state);
772.10463 -+		nbox -= nbox_this_time;
772.10464 -+
772.10465 -+		do {
772.10466 -+			DBG(("  %s: (%d, %d) x (%d, %d)\n", __FUNCTION__,
772.10467 -+			     box->x1, box->y1,
772.10468 -+			     box->x2 - box->x1,
772.10469 -+			     box->y2 - box->y1));
772.10470 -+
772.10471 -+			op->prim_emit(sna, op, box++, opacity);
772.10472 -+		} while (--nbox_this_time);
772.10473 -+	} while (nbox);
772.10474 -+}
772.10475 -+
772.10476 -+fastcall static void
772.10477 -+gen9_render_composite_spans_boxes__thread(struct sna *sna,
772.10478 -+					  const struct sna_composite_spans_op *op,
772.10479 -+					  const struct sna_opacity_box *box,
772.10480 -+					  int nbox)
772.10481 -+{
772.10482 -+	DBG(("%s: nbox=%d, src=+(%d, %d), dst=+(%d, %d)\n",
772.10483 -+	     __FUNCTION__, nbox,
772.10484 -+	     op->base.src.offset[0], op->base.src.offset[1],
772.10485 -+	     op->base.dst.x, op->base.dst.y));
772.10486 -+
772.10487 -+	sna_vertex_lock(&sna->render);
772.10488 -+	do {
772.10489 -+		int nbox_this_time;
772.10490 -+		float *v;
772.10491 -+
772.10492 -+		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
772.10493 -+						     gen9_emit_composite_state);
772.10494 -+		assert(nbox_this_time);
772.10495 -+		nbox -= nbox_this_time;
772.10496 -+
772.10497 -+		v = sna->render.vertices + sna->render.vertex_used;
772.10498 -+		sna->render.vertex_used += nbox_this_time * op->base.floats_per_rect;
772.10499 -+
772.10500 -+		sna_vertex_acquire__locked(&sna->render);
772.10501 -+		sna_vertex_unlock(&sna->render);
772.10502 -+
772.10503 -+		op->emit_boxes(op, box, nbox_this_time, v);
772.10504 -+		box += nbox_this_time;
772.10505 -+
772.10506 -+		sna_vertex_lock(&sna->render);
772.10507 -+		sna_vertex_release__locked(&sna->render);
772.10508 -+	} while (nbox);
772.10509 -+	sna_vertex_unlock(&sna->render);
772.10510 -+}
772.10511 -+
772.10512 -+fastcall static void
772.10513 -+gen9_render_composite_spans_done(struct sna *sna,
772.10514 -+				 const struct sna_composite_spans_op *op)
772.10515 -+{
772.10516 -+	if (sna->render.vertex_offset)
772.10517 -+		gen8_vertex_flush(sna);
772.10518 -+
772.10519 -+	DBG(("%s()\n", __FUNCTION__));
772.10520 -+
772.10521 -+	if (op->base.src.bo)
772.10522 -+		kgem_bo_destroy(&sna->kgem, op->base.src.bo);
772.10523 -+
772.10524 -+	sna_render_composite_redirect_done(sna, &op->base);
772.10525 -+}
772.10526 -+
772.10527 -+static bool
772.10528 -+gen9_check_composite_spans(struct sna *sna,
772.10529 -+			   uint8_t op, PicturePtr src, PicturePtr dst,
772.10530 -+			   int16_t width, int16_t height, unsigned flags)
772.10531 -+{
772.10532 -+	if (op >= ARRAY_SIZE(gen9_blend_op))
772.10533 -+		return false;
772.10534 -+
772.10535 -+	if (gen9_composite_fallback(sna, src, NULL, dst))
772.10536 -+		return false;
772.10537 -+
772.10538 -+	if (need_tiling(sna, width, height) &&
772.10539 -+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
772.10540 -+		DBG(("%s: fallback, tiled operation not on GPU\n",
772.10541 -+		     __FUNCTION__));
772.10542 -+		return false;
772.10543 -+	}
772.10544 -+
772.10545 -+	return true;
772.10546 -+}
772.10547 -+
772.10548 -+static bool
772.10549 -+gen9_render_composite_spans(struct sna *sna,
772.10550 -+			    uint8_t op,
772.10551 -+			    PicturePtr src,
772.10552 -+			    PicturePtr dst,
772.10553 -+			    int16_t src_x,  int16_t src_y,
772.10554 -+			    int16_t dst_x,  int16_t dst_y,
772.10555 -+			    int16_t width,  int16_t height,
772.10556 -+			    unsigned flags,
772.10557 -+			    struct sna_composite_spans_op *tmp)
772.10558 -+{
772.10559 -+	DBG(("%s: %dx%d with flags=%x, current mode=%d\n", __FUNCTION__,
772.10560 -+	     width, height, flags, sna->kgem.ring));
772.10561 -+
772.10562 -+	assert(gen9_check_composite_spans(sna, op, src, dst, width, height, flags));
772.10563 -+
772.10564 -+	if (need_tiling(sna, width, height)) {
772.10565 -+		DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n",
772.10566 -+		     __FUNCTION__, width, height));
772.10567 -+		return sna_tiling_composite_spans(op, src, dst,
772.10568 -+						  src_x, src_y, dst_x, dst_y,
772.10569 -+						  width, height, flags, tmp);
772.10570 -+	}
772.10571 -+
772.10572 -+	tmp->base.op = op;
772.10573 -+	if (!gen9_composite_set_target(sna, &tmp->base, dst,
772.10574 -+				       dst_x, dst_y, width, height, true))
772.10575 -+		return false;
772.10576 -+
772.10577 -+	switch (gen9_composite_picture(sna, src, &tmp->base.src,
772.10578 -+				       src_x, src_y,
772.10579 -+				       width, height,
772.10580 -+				       dst_x, dst_y,
772.10581 -+				       dst->polyMode == PolyModePrecise)) {
772.10582 -+	case -1:
772.10583 -+		goto cleanup_dst;
772.10584 -+	case 0:
772.10585 -+		if (!gen4_channel_init_solid(sna, &tmp->base.src, 0))
772.10586 -+			goto cleanup_dst;
772.10587 -+		/* fall through to fixup */
772.10588 -+	case 1:
772.10589 -+		if (!gen9_composite_channel_convert(&tmp->base.src))
772.10590 -+			goto cleanup_src;
772.10591 -+		break;
772.10592 -+	}
772.10593 -+	tmp->base.mask.bo = NULL;
772.10594 -+
772.10595 -+	tmp->base.is_affine = tmp->base.src.is_affine;
772.10596 -+	tmp->base.need_magic_ca_pass = false;
772.10597 -+
772.10598 -+	tmp->base.u.gen9.flags =
772.10599 -+		GEN9_SET_FLAGS(SAMPLER_OFFSET(tmp->base.src.filter,
772.10600 -+					      tmp->base.src.repeat,
772.10601 -+					      SAMPLER_FILTER_NEAREST,
772.10602 -+					      SAMPLER_EXTEND_PAD),
772.10603 -+			       gen9_get_blend(tmp->base.op, false, tmp->base.dst.format),
772.10604 -+			       GEN9_WM_KERNEL_OPACITY | !tmp->base.is_affine,
772.10605 -+			       gen4_choose_spans_emitter(sna, tmp));
772.10606 -+
772.10607 -+	tmp->box   = gen9_render_composite_spans_box;
772.10608 -+	tmp->boxes = gen9_render_composite_spans_boxes;
772.10609 -+	if (tmp->emit_boxes)
772.10610 -+		tmp->thread_boxes = gen9_render_composite_spans_boxes__thread;
772.10611 -+	tmp->done  = gen9_render_composite_spans_done;
772.10612 -+
772.10613 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->base.dst.bo);
772.10614 -+	if (!kgem_check_bo(&sna->kgem,
772.10615 -+			   tmp->base.dst.bo, tmp->base.src.bo,
772.10616 -+			   NULL)) {
772.10617 -+		kgem_submit(&sna->kgem);
772.10618 -+		if (!kgem_check_bo(&sna->kgem,
772.10619 -+				   tmp->base.dst.bo, tmp->base.src.bo,
772.10620 -+				   NULL))
772.10621 -+			goto cleanup_src;
772.10622 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.10623 -+	}
772.10624 -+
772.10625 -+	gen9_align_vertex(sna, &tmp->base);
772.10626 -+	gen9_emit_composite_state(sna, &tmp->base);
772.10627 -+	return true;
772.10628 -+
772.10629 -+cleanup_src:
772.10630 -+	if (tmp->base.src.bo)
772.10631 -+		kgem_bo_destroy(&sna->kgem, tmp->base.src.bo);
772.10632 -+cleanup_dst:
772.10633 -+	if (tmp->base.redirect.real_bo)
772.10634 -+		kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo);
772.10635 -+	return false;
772.10636 -+}
772.10637 -+#endif
772.10638 -+
772.10639 -+static void
772.10640 -+gen9_emit_copy_state(struct sna *sna,
772.10641 -+		     const struct sna_composite_op *op)
772.10642 -+{
772.10643 -+	uint32_t *binding_table;
772.10644 -+	uint16_t offset, dirty;
772.10645 -+
772.10646 -+	gen9_get_batch(sna, op);
772.10647 -+
772.10648 -+	binding_table = gen9_composite_get_binding_table(sna, &offset);
772.10649 -+
772.10650 -+	dirty = kgem_bo_is_dirty(op->dst.bo);
772.10651 -+
772.10652 -+	binding_table[0] =
772.10653 -+		gen9_bind_bo(sna,
772.10654 -+			     op->dst.bo, op->dst.width, op->dst.height,
772.10655 -+			     gen9_get_dest_format(op->dst.format),
772.10656 -+			     true);
772.10657 -+	binding_table[1] =
772.10658 -+		gen9_bind_bo(sna,
772.10659 -+			     op->src.bo, op->src.width, op->src.height,
772.10660 -+			     op->src.card_format,
772.10661 -+			     false);
772.10662 -+
772.10663 -+	if (sna->kgem.surface == offset &&
772.10664 -+	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table) {
772.10665 -+		sna->kgem.surface += SURFACE_DW;
772.10666 -+		offset = sna->render_state.gen9.surface_table;
772.10667 -+	}
772.10668 -+
772.10669 -+	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
772.10670 -+		dirty = 0;
772.10671 -+
772.10672 -+	assert(!GEN9_READS_DST(op->u.gen9.flags));
772.10673 -+	gen9_emit_state(sna, op, offset | dirty);
772.10674 -+}
772.10675 -+
772.10676 -+static inline bool
772.10677 -+prefer_blt_copy(struct sna *sna,
772.10678 -+		struct kgem_bo *src_bo,
772.10679 -+		struct kgem_bo *dst_bo,
772.10680 -+		unsigned flags)
772.10681 -+{
772.10682 -+	if (sna->kgem.mode == KGEM_BLT)
772.10683 -+		return true;
772.10684 -+
772.10685 -+	assert((flags & COPY_SYNC) == 0);
772.10686 -+
772.10687 -+	if (untiled_tlb_miss(src_bo) ||
772.10688 -+	    untiled_tlb_miss(dst_bo))
772.10689 -+		return true;
772.10690 -+
772.10691 -+	if (flags & COPY_DRI && !sna->kgem.has_semaphores)
772.10692 -+		return false;
772.10693 -+
772.10694 -+	if (force_blt_ring(sna, dst_bo))
772.10695 -+		return true;
772.10696 -+
772.10697 -+	if ((flags & COPY_SMALL ||
772.10698 -+	     (sna->render_state.gt < 3 && src_bo == dst_bo)) &&
772.10699 -+	    can_switch_to_blt(sna, dst_bo, flags))
772.10700 -+		return true;
772.10701 -+
772.10702 -+	if (kgem_bo_is_render(dst_bo) ||
772.10703 -+	    kgem_bo_is_render(src_bo))
772.10704 -+		return false;
772.10705 -+
772.10706 -+	if (flags & COPY_LAST &&
772.10707 -+	    sna->render_state.gt < 3 &&
772.10708 -+            can_switch_to_blt(sna, dst_bo, flags))
772.10709 -+		return true;
772.10710 -+
772.10711 -+	if (prefer_render_ring(sna, dst_bo))
772.10712 -+		return false;
772.10713 -+
772.10714 -+	if (!prefer_blt_ring(sna, dst_bo, flags))
772.10715 -+		return false;
772.10716 -+
772.10717 -+	return prefer_blt_bo(sna, src_bo, dst_bo);
772.10718 -+}
772.10719 -+
772.10720 -+static bool
772.10721 -+gen9_render_copy_boxes(struct sna *sna, uint8_t alu,
772.10722 -+		       const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
772.10723 -+		       const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
772.10724 -+		       const BoxRec *box, int n, unsigned flags)
772.10725 -+{
772.10726 -+	struct sna_composite_op tmp;
772.10727 -+	BoxRec extents;
772.10728 -+
772.10729 -+	DBG(("%s (%d, %d)->(%d, %d) x %d, alu=%x, flags=%x, self-copy=%d, overlaps? %d\n",
772.10730 -+	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n, alu, flags,
772.10731 -+	     src_bo == dst_bo,
772.10732 -+	     overlaps(sna,
772.10733 -+		      src_bo, src_dx, src_dy,
772.10734 -+		      dst_bo, dst_dx, dst_dy,
772.10735 -+		      box, n, flags, &extents)));
772.10736 -+
772.10737 -+	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
772.10738 -+	    sna_blt_compare_depth(src, dst) &&
772.10739 -+	    sna_blt_copy_boxes(sna, alu,
772.10740 -+			       src_bo, src_dx, src_dy,
772.10741 -+			       dst_bo, dst_dx, dst_dy,
772.10742 -+			       dst->bitsPerPixel,
772.10743 -+			       box, n))
772.10744 -+		return true;
772.10745 -+
772.10746 -+	if (!(alu == GXcopy || alu == GXclear) ||
772.10747 -+	    unaligned(src_bo, src->bitsPerPixel) ||
772.10748 -+	    unaligned(dst_bo, dst->bitsPerPixel)) {
772.10749 -+fallback_blt:
772.10750 -+		DBG(("%s: fallback blt\n", __FUNCTION__));
772.10751 -+		if (!sna_blt_compare_depth(src, dst))
772.10752 -+			return false;
772.10753 -+
772.10754 -+		return sna_blt_copy_boxes_fallback(sna, alu,
772.10755 -+						   src, src_bo, src_dx, src_dy,
772.10756 -+						   dst, dst_bo, dst_dx, dst_dy,
772.10757 -+						   box, n);
772.10758 -+	}
772.10759 -+
772.10760 -+	if (overlaps(sna,
772.10761 -+		     src_bo, src_dx, src_dy,
772.10762 -+		     dst_bo, dst_dx, dst_dy,
772.10763 -+		     box, n, flags,
772.10764 -+		     &extents)) {
772.10765 -+		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
772.10766 -+
772.10767 -+		if ((big || !prefer_render_ring(sna, dst_bo)) &&
772.10768 -+		    sna_blt_copy_boxes(sna, alu,
772.10769 -+				       src_bo, src_dx, src_dy,
772.10770 -+				       dst_bo, dst_dx, dst_dy,
772.10771 -+				       dst->bitsPerPixel,
772.10772 -+				       box, n))
772.10773 -+			return true;
772.10774 -+
772.10775 -+		if (big)
772.10776 -+			goto fallback_blt;
772.10777 -+
772.10778 -+		assert(src_bo == dst_bo);
772.10779 -+		assert(src->depth == dst->depth);
772.10780 -+		assert(src->width == dst->width);
772.10781 -+		assert(src->height == dst->height);
772.10782 -+		return sna_render_copy_boxes__overlap(sna, alu, dst, dst_bo,
772.10783 -+						      src_dx, src_dy,
772.10784 -+						      dst_dx, dst_dy,
772.10785 -+						      box, n, &extents);
772.10786 -+	}
772.10787 -+
772.10788 -+	if (dst->depth == src->depth) {
772.10789 -+		tmp.dst.format = sna_render_format_for_depth(dst->depth);
772.10790 -+		tmp.src.pict_format = tmp.dst.format;
772.10791 -+	} else {
772.10792 -+		tmp.dst.format = sna_format_for_depth(dst->depth);
772.10793 -+		tmp.src.pict_format = sna_format_for_depth(src->depth);
772.10794 -+	}
772.10795 -+	if (!gen9_check_format(tmp.src.pict_format))
772.10796 -+		goto fallback_blt;
772.10797 -+
772.10798 -+	tmp.dst.pixmap = (PixmapPtr)dst;
772.10799 -+	tmp.dst.width  = dst->width;
772.10800 -+	tmp.dst.height = dst->height;
772.10801 -+	tmp.dst.bo = dst_bo;
772.10802 -+	tmp.dst.x = tmp.dst.y = 0;
772.10803 -+	tmp.damage = NULL;
772.10804 -+
772.10805 -+	sna_render_composite_redirect_init(&tmp);
772.10806 -+	if (too_large(tmp.dst.width, tmp.dst.height)) {
772.10807 -+		int i;
772.10808 -+
772.10809 -+		extents = box[0];
772.10810 -+		for (i = 1; i < n; i++) {
772.10811 -+			if (box[i].x1 < extents.x1)
772.10812 -+				extents.x1 = box[i].x1;
772.10813 -+			if (box[i].y1 < extents.y1)
772.10814 -+				extents.y1 = box[i].y1;
772.10815 -+
772.10816 -+			if (box[i].x2 > extents.x2)
772.10817 -+				extents.x2 = box[i].x2;
772.10818 -+			if (box[i].y2 > extents.y2)
772.10819 -+				extents.y2 = box[i].y2;
772.10820 -+		}
772.10821 -+
772.10822 -+		if (!sna_render_composite_redirect(sna, &tmp,
772.10823 -+						   extents.x1 + dst_dx,
772.10824 -+						   extents.y1 + dst_dy,
772.10825 -+						   extents.x2 - extents.x1,
772.10826 -+						   extents.y2 - extents.y1,
772.10827 -+						   n > 1))
772.10828 -+			goto fallback_tiled;
772.10829 -+	}
772.10830 -+
772.10831 -+	tmp.src.card_format = gen9_get_card_format(tmp.src.pict_format);
772.10832 -+	if (too_large(src->width, src->height)) {
772.10833 -+		int i;
772.10834 -+
772.10835 -+		extents = box[0];
772.10836 -+		for (i = 1; i < n; i++) {
772.10837 -+			if (box[i].x1 < extents.x1)
772.10838 -+				extents.x1 = box[i].x1;
772.10839 -+			if (box[i].y1 < extents.y1)
772.10840 -+				extents.y1 = box[i].y1;
772.10841 -+
772.10842 -+			if (box[i].x2 > extents.x2)
772.10843 -+				extents.x2 = box[i].x2;
772.10844 -+			if (box[i].y2 > extents.y2)
772.10845 -+				extents.y2 = box[i].y2;
772.10846 -+		}
772.10847 -+
772.10848 -+		if (!sna_render_pixmap_partial(sna, src, src_bo, &tmp.src,
772.10849 -+					       extents.x1 + src_dx,
772.10850 -+					       extents.y1 + src_dy,
772.10851 -+					       extents.x2 - extents.x1,
772.10852 -+					       extents.y2 - extents.y1))
772.10853 -+			goto fallback_tiled_dst;
772.10854 -+	} else {
772.10855 -+		tmp.src.bo = src_bo;
772.10856 -+		tmp.src.width  = src->width;
772.10857 -+		tmp.src.height = src->height;
772.10858 -+		tmp.src.offset[0] = tmp.src.offset[1] = 0;
772.10859 -+	}
772.10860 -+
772.10861 -+	tmp.mask.bo = NULL;
772.10862 -+
772.10863 -+	tmp.floats_per_vertex = 2;
772.10864 -+	tmp.floats_per_rect = 6;
772.10865 -+	tmp.need_magic_ca_pass = 0;
772.10866 -+
772.10867 -+	tmp.u.gen9.flags = COPY_FLAGS(alu);
772.10868 -+
772.10869 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo);
772.10870 -+	if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) {
772.10871 -+		kgem_submit(&sna->kgem);
772.10872 -+		if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) {
772.10873 -+			if (tmp.src.bo != src_bo)
772.10874 -+				kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.10875 -+			if (tmp.redirect.real_bo)
772.10876 -+				kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
772.10877 -+			goto fallback_blt;
772.10878 -+		}
772.10879 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.10880 -+	}
772.10881 -+
772.10882 -+	src_dx += tmp.src.offset[0];
772.10883 -+	src_dy += tmp.src.offset[1];
772.10884 -+
772.10885 -+	dst_dx += tmp.dst.x;
772.10886 -+	dst_dy += tmp.dst.y;
772.10887 -+
772.10888 -+	tmp.dst.x = tmp.dst.y = 0;
772.10889 -+
772.10890 -+	gen9_align_vertex(sna, &tmp);
772.10891 -+	gen9_emit_copy_state(sna, &tmp);
772.10892 -+
772.10893 -+	do {
772.10894 -+		int16_t *v;
772.10895 -+		int n_this_time;
772.10896 -+
772.10897 -+		n_this_time = gen9_get_rectangles(sna, &tmp, n,
772.10898 -+						  gen9_emit_copy_state);
772.10899 -+		n -= n_this_time;
772.10900 -+
772.10901 -+		v = (int16_t *)(sna->render.vertices + sna->render.vertex_used);
772.10902 -+		sna->render.vertex_used += 6 * n_this_time;
772.10903 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.10904 -+		do {
772.10905 -+
772.10906 -+			DBG(("	(%d, %d) -> (%d, %d) + (%d, %d)\n",
772.10907 -+			     box->x1 + src_dx, box->y1 + src_dy,
772.10908 -+			     box->x1 + dst_dx, box->y1 + dst_dy,
772.10909 -+			     box->x2 - box->x1, box->y2 - box->y1));
772.10910 -+			v[0] = box->x2 + dst_dx;
772.10911 -+			v[2] = box->x2 + src_dx;
772.10912 -+			v[1]  = v[5] = box->y2 + dst_dy;
772.10913 -+			v[3]  = v[7] = box->y2 + src_dy;
772.10914 -+			v[8]  = v[4] = box->x1 + dst_dx;
772.10915 -+			v[10] = v[6] = box->x1 + src_dx;
772.10916 -+			v[9]  = box->y1 + dst_dy;
772.10917 -+			v[11] = box->y1 + src_dy;
772.10918 -+			v += 12; box++;
772.10919 -+		} while (--n_this_time);
772.10920 -+	} while (n);
772.10921 -+
772.10922 -+	gen8_vertex_flush(sna);
772.10923 -+	sna_render_composite_redirect_done(sna, &tmp);
772.10924 -+	if (tmp.src.bo != src_bo)
772.10925 -+		kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.10926 -+	return true;
772.10927 -+
772.10928 -+fallback_tiled_dst:
772.10929 -+	if (tmp.redirect.real_bo)
772.10930 -+		kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
772.10931 -+fallback_tiled:
772.10932 -+	DBG(("%s: fallback tiled\n", __FUNCTION__));
772.10933 -+	if (sna_blt_compare_depth(src, dst) &&
772.10934 -+	    sna_blt_copy_boxes(sna, alu,
772.10935 -+			       src_bo, src_dx, src_dy,
772.10936 -+			       dst_bo, dst_dx, dst_dy,
772.10937 -+			       dst->bitsPerPixel,
772.10938 -+			       box, n))
772.10939 -+		return true;
772.10940 -+
772.10941 -+	return sna_tiling_copy_boxes(sna, alu,
772.10942 -+				     src, src_bo, src_dx, src_dy,
772.10943 -+				     dst, dst_bo, dst_dx, dst_dy,
772.10944 -+				     box, n);
772.10945 -+}
772.10946 -+
772.10947 -+static void
772.10948 -+gen9_render_copy_blt(struct sna *sna,
772.10949 -+		     const struct sna_copy_op *op,
772.10950 -+		     int16_t sx, int16_t sy,
772.10951 -+		     int16_t w,  int16_t h,
772.10952 -+		     int16_t dx, int16_t dy)
772.10953 -+{
772.10954 -+	int16_t *v;
772.10955 -+
772.10956 -+	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_copy_state);
772.10957 -+
772.10958 -+	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.10959 -+	sna->render.vertex_used += 6;
772.10960 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.10961 -+
772.10962 -+	v[0]  = dx+w; v[1]  = dy+h;
772.10963 -+	v[2]  = sx+w; v[3]  = sy+h;
772.10964 -+	v[4]  = dx;   v[5]  = dy+h;
772.10965 -+	v[6]  = sx;   v[7]  = sy+h;
772.10966 -+	v[8]  = dx;   v[9]  = dy;
772.10967 -+	v[10] = sx;   v[11] = sy;
772.10968 -+}
772.10969 -+
772.10970 -+static void
772.10971 -+gen9_render_copy_done(struct sna *sna, const struct sna_copy_op *op)
772.10972 -+{
772.10973 -+	if (sna->render.vertex_offset)
772.10974 -+		gen8_vertex_flush(sna);
772.10975 -+}
772.10976 -+
772.10977 -+static bool
772.10978 -+gen9_render_copy(struct sna *sna, uint8_t alu,
772.10979 -+		 PixmapPtr src, struct kgem_bo *src_bo,
772.10980 -+		 PixmapPtr dst, struct kgem_bo *dst_bo,
772.10981 -+		 struct sna_copy_op *op)
772.10982 -+{
772.10983 -+	DBG(("%s (alu=%d, src=(%dx%d), dst=(%dx%d))\n",
772.10984 -+	     __FUNCTION__, alu,
772.10985 -+	     src->drawable.width, src->drawable.height,
772.10986 -+	     dst->drawable.width, dst->drawable.height));
772.10987 -+
772.10988 -+	if (prefer_blt_copy(sna, src_bo, dst_bo, 0) &&
772.10989 -+	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
772.10990 -+	    sna_blt_copy(sna, alu,
772.10991 -+			 src_bo, dst_bo,
772.10992 -+			 dst->drawable.bitsPerPixel,
772.10993 -+			 op))
772.10994 -+		return true;
772.10995 -+
772.10996 -+	if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo ||
772.10997 -+	    too_large(src->drawable.width, src->drawable.height) ||
772.10998 -+	    too_large(dst->drawable.width, dst->drawable.height) ||
772.10999 -+	    unaligned(src_bo, src->drawable.bitsPerPixel) ||
772.11000 -+	    unaligned(dst_bo, dst->drawable.bitsPerPixel)) {
772.11001 -+fallback:
772.11002 -+		if (!sna_blt_compare_depth(&src->drawable, &dst->drawable))
772.11003 -+			return false;
772.11004 -+
772.11005 -+		return sna_blt_copy(sna, alu, src_bo, dst_bo,
772.11006 -+				    dst->drawable.bitsPerPixel,
772.11007 -+				    op);
772.11008 -+	}
772.11009 -+
772.11010 -+	if (dst->drawable.depth == src->drawable.depth) {
772.11011 -+		op->base.dst.format = sna_render_format_for_depth(dst->drawable.depth);
772.11012 -+		op->base.src.pict_format = op->base.dst.format;
772.11013 -+	} else {
772.11014 -+		op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
772.11015 -+		op->base.src.pict_format = sna_format_for_depth(src->drawable.depth);
772.11016 -+	}
772.11017 -+	if (!gen9_check_format(op->base.src.pict_format))
772.11018 -+		goto fallback;
772.11019 -+
772.11020 -+	op->base.dst.pixmap = dst;
772.11021 -+	op->base.dst.width  = dst->drawable.width;
772.11022 -+	op->base.dst.height = dst->drawable.height;
772.11023 -+	op->base.dst.bo = dst_bo;
772.11024 -+
772.11025 -+	op->base.src.bo = src_bo;
772.11026 -+	op->base.src.card_format =
772.11027 -+		gen9_get_card_format(op->base.src.pict_format);
772.11028 -+	op->base.src.width  = src->drawable.width;
772.11029 -+	op->base.src.height = src->drawable.height;
772.11030 -+
772.11031 -+	op->base.mask.bo = NULL;
772.11032 -+
772.11033 -+	op->base.floats_per_vertex = 2;
772.11034 -+	op->base.floats_per_rect = 6;
772.11035 -+
772.11036 -+	op->base.u.gen9.flags = COPY_FLAGS(alu);
772.11037 -+
772.11038 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
772.11039 -+	if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) {
772.11040 -+		kgem_submit(&sna->kgem);
772.11041 -+		if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL))
772.11042 -+			goto fallback;
772.11043 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11044 -+	}
772.11045 -+
772.11046 -+	gen9_align_vertex(sna, &op->base);
772.11047 -+	gen9_emit_copy_state(sna, &op->base);
772.11048 -+
772.11049 -+	op->blt  = gen9_render_copy_blt;
772.11050 -+	op->done = gen9_render_copy_done;
772.11051 -+	return true;
772.11052 -+}
772.11053 -+
772.11054 -+static void
772.11055 -+gen9_emit_fill_state(struct sna *sna, const struct sna_composite_op *op)
772.11056 -+{
772.11057 -+	uint32_t *binding_table;
772.11058 -+	uint16_t offset, dirty;
772.11059 -+
772.11060 -+	/* XXX Render Target Fast Clear
772.11061 -+	 * Set RTFC Enable in PS and render a rectangle.
772.11062 -+	 * Limited to a clearing the full MSC surface only with a
772.11063 -+	 * specific kernel.
772.11064 -+	 */
772.11065 -+
772.11066 -+	gen9_get_batch(sna, op);
772.11067 -+
772.11068 -+	binding_table = gen9_composite_get_binding_table(sna, &offset);
772.11069 -+
772.11070 -+	dirty = kgem_bo_is_dirty(op->dst.bo);
772.11071 -+
772.11072 -+	binding_table[0] =
772.11073 -+		gen9_bind_bo(sna,
772.11074 -+			     op->dst.bo, op->dst.width, op->dst.height,
772.11075 -+			     gen9_get_dest_format(op->dst.format),
772.11076 -+			     true);
772.11077 -+	binding_table[1] =
772.11078 -+		gen9_bind_bo(sna,
772.11079 -+			     op->src.bo, 1, 1,
772.11080 -+			     SURFACEFORMAT_B8G8R8A8_UNORM,
772.11081 -+			     false);
772.11082 -+
772.11083 -+	if (sna->kgem.surface == offset &&
772.11084 -+	    *(uint64_t *)(sna->kgem.batch + sna->render_state.gen9.surface_table) == *(uint64_t*)binding_table) {
772.11085 -+		sna->kgem.surface += SURFACE_DW;
772.11086 -+		offset = sna->render_state.gen9.surface_table;
772.11087 -+	}
772.11088 -+
772.11089 -+	if (sna->kgem.batch[sna->render_state.gen9.surface_table] == binding_table[0])
772.11090 -+		dirty = 0;
772.11091 -+
772.11092 -+	gen9_emit_state(sna, op, offset | dirty);
772.11093 -+}
772.11094 -+
772.11095 -+static bool
772.11096 -+gen9_render_fill_boxes(struct sna *sna,
772.11097 -+		       CARD8 op,
772.11098 -+		       PictFormat format,
772.11099 -+		       const xRenderColor *color,
772.11100 -+		       const DrawableRec *dst, struct kgem_bo *dst_bo,
772.11101 -+		       const BoxRec *box, int n)
772.11102 -+{
772.11103 -+	struct sna_composite_op tmp;
772.11104 -+	uint32_t pixel;
772.11105 -+
772.11106 -+	DBG(("%s (op=%d, color=(%04x, %04x, %04x, %04x) [%08x])\n",
772.11107 -+	     __FUNCTION__, op,
772.11108 -+	     color->red, color->green, color->blue, color->alpha, (int)format));
772.11109 -+
772.11110 -+	if (op >= ARRAY_SIZE(gen9_blend_op)) {
772.11111 -+		DBG(("%s: fallback due to unhandled blend op: %d\n",
772.11112 -+		     __FUNCTION__, op));
772.11113 -+		return false;
772.11114 -+	}
772.11115 -+
772.11116 -+	if (prefer_blt_fill(sna, dst_bo, FILL_BOXES) ||
772.11117 -+	    !gen9_check_dst_format(format) ||
772.11118 -+	    unaligned(dst_bo, PICT_FORMAT_BPP(format))) {
772.11119 -+		uint8_t alu = GXinvalid;
772.11120 -+
772.11121 -+		if (op <= PictOpSrc) {
772.11122 -+			pixel = 0;
772.11123 -+			if (op == PictOpClear)
772.11124 -+				alu = GXclear;
772.11125 -+			else if (sna_get_pixel_from_rgba(&pixel,
772.11126 -+							 color->red,
772.11127 -+							 color->green,
772.11128 -+							 color->blue,
772.11129 -+							 color->alpha,
772.11130 -+							 format))
772.11131 -+				alu = GXcopy;
772.11132 -+		}
772.11133 -+
772.11134 -+		if (alu != GXinvalid &&
772.11135 -+		    sna_blt_fill_boxes(sna, alu,
772.11136 -+				       dst_bo, dst->bitsPerPixel,
772.11137 -+				       pixel, box, n))
772.11138 -+			return true;
772.11139 -+
772.11140 -+		if (!gen9_check_dst_format(format))
772.11141 -+			return false;
772.11142 -+	}
772.11143 -+
772.11144 -+	if (op == PictOpClear) {
772.11145 -+		pixel = 0;
772.11146 -+		op = PictOpSrc;
772.11147 -+	} else if (!sna_get_pixel_from_rgba(&pixel,
772.11148 -+					    color->red,
772.11149 -+					    color->green,
772.11150 -+					    color->blue,
772.11151 -+					    color->alpha,
772.11152 -+					    PICT_a8r8g8b8))
772.11153 -+		return false;
772.11154 -+
772.11155 -+	DBG(("%s(%08x x %d [(%d, %d), (%d, %d) ...])\n",
772.11156 -+	     __FUNCTION__, pixel, n,
772.11157 -+	     box[0].x1, box[0].y1, box[0].x2, box[0].y2));
772.11158 -+
772.11159 -+	tmp.dst.pixmap = (PixmapPtr)dst;
772.11160 -+	tmp.dst.width  = dst->width;
772.11161 -+	tmp.dst.height = dst->height;
772.11162 -+	tmp.dst.format = format;
772.11163 -+	tmp.dst.bo = dst_bo;
772.11164 -+	tmp.dst.x = tmp.dst.y = 0;
772.11165 -+	tmp.damage = NULL;
772.11166 -+
772.11167 -+	sna_render_composite_redirect_init(&tmp);
772.11168 -+	if (too_large(dst->width, dst->height)) {
772.11169 -+		BoxRec extents;
772.11170 -+
772.11171 -+		boxes_extents(box, n, &extents);
772.11172 -+		if (!sna_render_composite_redirect(sna, &tmp,
772.11173 -+						   extents.x1, extents.y1,
772.11174 -+						   extents.x2 - extents.x1,
772.11175 -+						   extents.y2 - extents.y1,
772.11176 -+						   n > 1))
772.11177 -+			return sna_tiling_fill_boxes(sna, op, format, color,
772.11178 -+						     dst, dst_bo, box, n);
772.11179 -+	}
772.11180 -+
772.11181 -+	tmp.src.bo = sna_render_get_solid(sna, pixel);
772.11182 -+	tmp.mask.bo = NULL;
772.11183 -+
772.11184 -+	tmp.floats_per_vertex = 2;
772.11185 -+	tmp.floats_per_rect = 6;
772.11186 -+	tmp.need_magic_ca_pass = false;
772.11187 -+
772.11188 -+	tmp.u.gen9.flags = FILL_FLAGS(op, format);
772.11189 -+
772.11190 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
772.11191 -+	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.11192 -+		kgem_submit(&sna->kgem);
772.11193 -+		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.11194 -+			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11195 -+			tmp.src.bo = NULL;
772.11196 -+
772.11197 -+			if (tmp.redirect.real_bo) {
772.11198 -+				kgem_bo_destroy(&sna->kgem, tmp.dst.bo);
772.11199 -+				tmp.redirect.real_bo = NULL;
772.11200 -+			}
772.11201 -+
772.11202 -+			return false;
772.11203 -+		}
772.11204 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11205 -+	}
772.11206 -+
772.11207 -+	gen9_align_vertex(sna, &tmp);
772.11208 -+	gen9_emit_fill_state(sna, &tmp);
772.11209 -+
772.11210 -+	do {
772.11211 -+		int n_this_time;
772.11212 -+		int16_t *v;
772.11213 -+
772.11214 -+		n_this_time = gen9_get_rectangles(sna, &tmp, n,
772.11215 -+						  gen9_emit_fill_state);
772.11216 -+		n -= n_this_time;
772.11217 -+
772.11218 -+		v = (int16_t *)(sna->render.vertices + sna->render.vertex_used);
772.11219 -+		sna->render.vertex_used += 6 * n_this_time;
772.11220 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11221 -+		do {
772.11222 -+			DBG(("	(%d, %d), (%d, %d)\n",
772.11223 -+			     box->x1, box->y1, box->x2, box->y2));
772.11224 -+
772.11225 -+			v[0] = box->x2;
772.11226 -+			v[5] = v[1] = box->y2;
772.11227 -+			v[8] = v[4] = box->x1;
772.11228 -+			v[9] = box->y1;
772.11229 -+			v[2] = v[3]  = v[7]  = 1;
772.11230 -+			v[6] = v[10] = v[11] = 0;
772.11231 -+			v += 12; box++;
772.11232 -+		} while (--n_this_time);
772.11233 -+	} while (n);
772.11234 -+
772.11235 -+	gen8_vertex_flush(sna);
772.11236 -+	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11237 -+	sna_render_composite_redirect_done(sna, &tmp);
772.11238 -+	return true;
772.11239 -+}
772.11240 -+
772.11241 -+static void
772.11242 -+gen9_render_fill_op_blt(struct sna *sna,
772.11243 -+			const struct sna_fill_op *op,
772.11244 -+			int16_t x, int16_t y, int16_t w, int16_t h)
772.11245 -+{
772.11246 -+	int16_t *v;
772.11247 -+
772.11248 -+	DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
772.11249 -+
772.11250 -+	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_fill_state);
772.11251 -+
772.11252 -+	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.11253 -+	sna->render.vertex_used += 6;
772.11254 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11255 -+
772.11256 -+	v[0] = x+w;
772.11257 -+	v[4] = v[8] = x;
772.11258 -+	v[1] = v[5] = y+h;
772.11259 -+	v[9] = y;
772.11260 -+
772.11261 -+	v[2] = v[3]  = v[7]  = 1;
772.11262 -+	v[6] = v[10] = v[11] = 0;
772.11263 -+}
772.11264 -+
772.11265 -+fastcall static void
772.11266 -+gen9_render_fill_op_box(struct sna *sna,
772.11267 -+			const struct sna_fill_op *op,
772.11268 -+			const BoxRec *box)
772.11269 -+{
772.11270 -+	int16_t *v;
772.11271 -+
772.11272 -+	DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
772.11273 -+	     box->x1, box->y1, box->x2, box->y2));
772.11274 -+
772.11275 -+	gen9_get_rectangles(sna, &op->base, 1, gen9_emit_fill_state);
772.11276 -+
772.11277 -+	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.11278 -+	sna->render.vertex_used += 6;
772.11279 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11280 -+
772.11281 -+	v[0] = box->x2;
772.11282 -+	v[8] = v[4] = box->x1;
772.11283 -+	v[5] = v[1] = box->y2;
772.11284 -+	v[9] = box->y1;
772.11285 -+
772.11286 -+	v[7] = v[2]  = v[3]  = 1;
772.11287 -+	v[6] = v[10] = v[11] = 0;
772.11288 -+}
772.11289 -+
772.11290 -+fastcall static void
772.11291 -+gen9_render_fill_op_boxes(struct sna *sna,
772.11292 -+			  const struct sna_fill_op *op,
772.11293 -+			  const BoxRec *box,
772.11294 -+			  int nbox)
772.11295 -+{
772.11296 -+	DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__,
772.11297 -+	     box->x1, box->y1, box->x2, box->y2, nbox));
772.11298 -+
772.11299 -+	do {
772.11300 -+		int nbox_this_time;
772.11301 -+		int16_t *v;
772.11302 -+
772.11303 -+		nbox_this_time = gen9_get_rectangles(sna, &op->base, nbox,
772.11304 -+						     gen9_emit_fill_state);
772.11305 -+		nbox -= nbox_this_time;
772.11306 -+
772.11307 -+		v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.11308 -+		sna->render.vertex_used += 6 * nbox_this_time;
772.11309 -+		assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11310 -+
772.11311 -+		do {
772.11312 -+			v[0] = box->x2;
772.11313 -+			v[8] = v[4] = box->x1;
772.11314 -+			v[5] = v[1] = box->y2;
772.11315 -+			v[9] = box->y1;
772.11316 -+			v[7] = v[2]  = v[3]  = 1;
772.11317 -+			v[6] = v[10] = v[11] = 0;
772.11318 -+			box++; v += 12;
772.11319 -+		} while (--nbox_this_time);
772.11320 -+	} while (nbox);
772.11321 -+}
772.11322 -+
772.11323 -+static void
772.11324 -+gen9_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op)
772.11325 -+{
772.11326 -+	if (sna->render.vertex_offset)
772.11327 -+		gen8_vertex_flush(sna);
772.11328 -+	kgem_bo_destroy(&sna->kgem, op->base.src.bo);
772.11329 -+}
772.11330 -+
772.11331 -+static bool
772.11332 -+gen9_render_fill(struct sna *sna, uint8_t alu,
772.11333 -+		 PixmapPtr dst, struct kgem_bo *dst_bo,
772.11334 -+		 uint32_t color, unsigned flags,
772.11335 -+		 struct sna_fill_op *op)
772.11336 -+{
772.11337 -+	DBG(("%s: (alu=%d, color=%x)\n", __FUNCTION__, alu, color));
772.11338 -+
772.11339 -+	if (prefer_blt_fill(sna, dst_bo, flags) &&
772.11340 -+	    sna_blt_fill(sna, alu,
772.11341 -+			 dst_bo, dst->drawable.bitsPerPixel,
772.11342 -+			 color,
772.11343 -+			 op))
772.11344 -+		return true;
772.11345 -+
772.11346 -+	if (!(alu == GXcopy || alu == GXclear) ||
772.11347 -+	    too_large(dst->drawable.width, dst->drawable.height) ||
772.11348 -+	    unaligned(dst_bo, dst->drawable.bitsPerPixel))
772.11349 -+		return sna_blt_fill(sna, alu,
772.11350 -+				    dst_bo, dst->drawable.bitsPerPixel,
772.11351 -+				    color,
772.11352 -+				    op);
772.11353 -+
772.11354 -+	if (alu == GXclear)
772.11355 -+		color = 0;
772.11356 -+
772.11357 -+	op->base.dst.pixmap = dst;
772.11358 -+	op->base.dst.width  = dst->drawable.width;
772.11359 -+	op->base.dst.height = dst->drawable.height;
772.11360 -+	op->base.dst.format = sna_format_for_depth(dst->drawable.depth);
772.11361 -+	op->base.dst.bo = dst_bo;
772.11362 -+	op->base.dst.x = op->base.dst.y = 0;
772.11363 -+
772.11364 -+	op->base.src.bo =
772.11365 -+		sna_render_get_solid(sna,
772.11366 -+				     sna_rgba_for_color(color,
772.11367 -+							dst->drawable.depth));
772.11368 -+	op->base.mask.bo = NULL;
772.11369 -+
772.11370 -+	op->base.need_magic_ca_pass = false;
772.11371 -+	op->base.floats_per_vertex = 2;
772.11372 -+	op->base.floats_per_rect = 6;
772.11373 -+
772.11374 -+	op->base.u.gen9.flags = FILL_FLAGS_NOBLEND;
772.11375 -+
772.11376 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo);
772.11377 -+	if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.11378 -+		kgem_submit(&sna->kgem);
772.11379 -+		if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) {
772.11380 -+			kgem_bo_destroy(&sna->kgem, op->base.src.bo);
772.11381 -+			return false;
772.11382 -+		}
772.11383 -+
772.11384 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11385 -+	}
772.11386 -+
772.11387 -+	gen9_align_vertex(sna, &op->base);
772.11388 -+	gen9_emit_fill_state(sna, &op->base);
772.11389 -+
772.11390 -+	op->blt   = gen9_render_fill_op_blt;
772.11391 -+	op->box   = gen9_render_fill_op_box;
772.11392 -+	op->boxes = gen9_render_fill_op_boxes;
772.11393 -+	op->points = NULL;
772.11394 -+	op->done  = gen9_render_fill_op_done;
772.11395 -+	return true;
772.11396 -+}
772.11397 -+
772.11398 -+static bool
772.11399 -+gen9_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
772.11400 -+			     uint32_t color,
772.11401 -+			     int16_t x1, int16_t y1, int16_t x2, int16_t y2,
772.11402 -+			     uint8_t alu)
772.11403 -+{
772.11404 -+	BoxRec box;
772.11405 -+
772.11406 -+	box.x1 = x1;
772.11407 -+	box.y1 = y1;
772.11408 -+	box.x2 = x2;
772.11409 -+	box.y2 = y2;
772.11410 -+
772.11411 -+	return sna_blt_fill_boxes(sna, alu,
772.11412 -+				  bo, dst->drawable.bitsPerPixel,
772.11413 -+				  color, &box, 1);
772.11414 -+}
772.11415 -+
772.11416 -+static bool
772.11417 -+gen9_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo,
772.11418 -+		     uint32_t color,
772.11419 -+		     int16_t x1, int16_t y1,
772.11420 -+		     int16_t x2, int16_t y2,
772.11421 -+		     uint8_t alu)
772.11422 -+{
772.11423 -+	struct sna_composite_op tmp;
772.11424 -+	int16_t *v;
772.11425 -+
772.11426 -+	/* Prefer to use the BLT if already engaged */
772.11427 -+	if (prefer_blt_fill(sna, bo, FILL_BOXES) &&
772.11428 -+	    gen9_render_fill_one_try_blt(sna, dst, bo, color,
772.11429 -+					 x1, y1, x2, y2, alu))
772.11430 -+		return true;
772.11431 -+
772.11432 -+	/* Must use the BLT if we can't RENDER... */
772.11433 -+	if (!(alu == GXcopy || alu == GXclear) ||
772.11434 -+	    too_large(dst->drawable.width, dst->drawable.height) ||
772.11435 -+	    unaligned(bo, dst->drawable.bitsPerPixel))
772.11436 -+		return gen9_render_fill_one_try_blt(sna, dst, bo, color,
772.11437 -+						    x1, y1, x2, y2, alu);
772.11438 -+
772.11439 -+	if (alu == GXclear)
772.11440 -+		color = 0;
772.11441 -+
772.11442 -+	tmp.dst.pixmap = dst;
772.11443 -+	tmp.dst.width  = dst->drawable.width;
772.11444 -+	tmp.dst.height = dst->drawable.height;
772.11445 -+	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
772.11446 -+	tmp.dst.bo = bo;
772.11447 -+	tmp.dst.x = tmp.dst.y = 0;
772.11448 -+
772.11449 -+	tmp.src.bo =
772.11450 -+		sna_render_get_solid(sna,
772.11451 -+				     sna_rgba_for_color(color,
772.11452 -+							dst->drawable.depth));
772.11453 -+	tmp.mask.bo = NULL;
772.11454 -+
772.11455 -+	tmp.floats_per_vertex = 2;
772.11456 -+	tmp.floats_per_rect = 6;
772.11457 -+	tmp.need_magic_ca_pass = false;
772.11458 -+
772.11459 -+	tmp.u.gen9.flags = FILL_FLAGS_NOBLEND;
772.11460 -+
772.11461 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
772.11462 -+	if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
772.11463 -+		kgem_submit(&sna->kgem);
772.11464 -+		if (kgem_check_bo(&sna->kgem, bo, NULL)) {
772.11465 -+			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11466 -+			return false;
772.11467 -+		}
772.11468 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11469 -+	}
772.11470 -+
772.11471 -+	gen9_align_vertex(sna, &tmp);
772.11472 -+	gen9_emit_fill_state(sna, &tmp);
772.11473 -+
772.11474 -+	gen9_get_rectangles(sna, &tmp, 1, gen9_emit_fill_state);
772.11475 -+
772.11476 -+	DBG(("	(%d, %d), (%d, %d)\n", x1, y1, x2, y2));
772.11477 -+
772.11478 -+	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.11479 -+	sna->render.vertex_used += 6;
772.11480 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11481 -+
772.11482 -+	v[0] = x2;
772.11483 -+	v[8] = v[4] = x1;
772.11484 -+	v[5] = v[1] = y2;
772.11485 -+	v[9] = y1;
772.11486 -+	v[7] = v[2]  = v[3]  = 1;
772.11487 -+	v[6] = v[10] = v[11] = 0;
772.11488 -+
772.11489 -+	gen8_vertex_flush(sna);
772.11490 -+	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11491 -+
772.11492 -+	return true;
772.11493 -+}
772.11494 -+
772.11495 -+static bool
772.11496 -+gen9_render_clear_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
772.11497 -+{
772.11498 -+	BoxRec box;
772.11499 -+
772.11500 -+	box.x1 = 0;
772.11501 -+	box.y1 = 0;
772.11502 -+	box.x2 = dst->drawable.width;
772.11503 -+	box.y2 = dst->drawable.height;
772.11504 -+
772.11505 -+	return sna_blt_fill_boxes(sna, GXclear,
772.11506 -+				  bo, dst->drawable.bitsPerPixel,
772.11507 -+				  0, &box, 1);
772.11508 -+}
772.11509 -+
772.11510 -+static bool
772.11511 -+gen9_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo)
772.11512 -+{
772.11513 -+	struct sna_composite_op tmp;
772.11514 -+	int16_t *v;
772.11515 -+
772.11516 -+	DBG(("%s: %dx%d\n",
772.11517 -+	     __FUNCTION__,
772.11518 -+	     dst->drawable.width,
772.11519 -+	     dst->drawable.height));
772.11520 -+
772.11521 -+	/* Prefer to use the BLT if already engaged */
772.11522 -+	if (sna->kgem.mode == KGEM_BLT &&
772.11523 -+	    gen9_render_clear_try_blt(sna, dst, bo))
772.11524 -+		return true;
772.11525 -+
772.11526 -+	/* Must use the BLT if we can't RENDER... */
772.11527 -+	if (too_large(dst->drawable.width, dst->drawable.height) ||
772.11528 -+	    unaligned(bo, dst->drawable.bitsPerPixel))
772.11529 -+		return gen9_render_clear_try_blt(sna, dst, bo);
772.11530 -+
772.11531 -+	tmp.dst.pixmap = dst;
772.11532 -+	tmp.dst.width  = dst->drawable.width;
772.11533 -+	tmp.dst.height = dst->drawable.height;
772.11534 -+	tmp.dst.format = sna_format_for_depth(dst->drawable.depth);
772.11535 -+	tmp.dst.bo = bo;
772.11536 -+	tmp.dst.x = tmp.dst.y = 0;
772.11537 -+
772.11538 -+	tmp.src.bo = sna_render_get_solid(sna, 0);
772.11539 -+	tmp.mask.bo = NULL;
772.11540 -+
772.11541 -+	tmp.floats_per_vertex = 2;
772.11542 -+	tmp.floats_per_rect = 6;
772.11543 -+	tmp.need_magic_ca_pass = false;
772.11544 -+
772.11545 -+	tmp.u.gen9.flags = FILL_FLAGS_NOBLEND;
772.11546 -+
772.11547 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, bo);
772.11548 -+	if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
772.11549 -+		kgem_submit(&sna->kgem);
772.11550 -+		if (!kgem_check_bo(&sna->kgem, bo, NULL)) {
772.11551 -+			kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11552 -+			return false;
772.11553 -+		}
772.11554 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11555 -+	}
772.11556 -+
772.11557 -+	gen9_align_vertex(sna, &tmp);
772.11558 -+	gen9_emit_fill_state(sna, &tmp);
772.11559 -+
772.11560 -+	gen9_get_rectangles(sna, &tmp, 1, gen9_emit_fill_state);
772.11561 -+
772.11562 -+	v = (int16_t *)&sna->render.vertices[sna->render.vertex_used];
772.11563 -+	sna->render.vertex_used += 6;
772.11564 -+	assert(sna->render.vertex_used <= sna->render.vertex_size);
772.11565 -+
772.11566 -+	v[0] = dst->drawable.width;
772.11567 -+	v[5] = v[1] = dst->drawable.height;
772.11568 -+	v[8] = v[4] = 0;
772.11569 -+	v[9] = 0;
772.11570 -+
772.11571 -+	v[7] = v[2]  = v[3]  = 1;
772.11572 -+	v[6] = v[10] = v[11] = 0;
772.11573 -+
772.11574 -+	gen8_vertex_flush(sna);
772.11575 -+	kgem_bo_destroy(&sna->kgem, tmp.src.bo);
772.11576 -+
772.11577 -+	return true;
772.11578 -+}
772.11579 -+
772.11580 -+#if !NO_VIDEO
772.11581 -+static uint32_t gen9_bind_video_source(struct sna *sna,
772.11582 -+				       struct kgem_bo *bo,
772.11583 -+				       uint32_t delta,
772.11584 -+				       int width,
772.11585 -+				       int height,
772.11586 -+				       int pitch,
772.11587 -+				       uint32_t format)
772.11588 -+{
772.11589 -+	uint32_t *ss;
772.11590 -+	int offset;
772.11591 -+
772.11592 -+	offset = sna->kgem.surface -= SURFACE_DW;
772.11593 -+	ss = sna->kgem.batch + offset;
772.11594 -+	ss[0] = (SURFACE_2D << SURFACE_TYPE_SHIFT |
772.11595 -+		 gen9_tiling_bits(bo->tiling) |
772.11596 -+		 format << SURFACE_FORMAT_SHIFT |
772.11597 -+		 SURFACE_VALIGN_4 | SURFACE_HALIGN_4);
772.11598 -+	ss[1] = 0;
772.11599 -+	ss[2] = ((width - 1)  << SURFACE_WIDTH_SHIFT |
772.11600 -+		 (height - 1) << SURFACE_HEIGHT_SHIFT);
772.11601 -+	ss[3] = (pitch - 1) << SURFACE_PITCH_SHIFT;
772.11602 -+	ss[4] = 0;
772.11603 -+	ss[5] = 0;
772.11604 -+	ss[6] = 0;
772.11605 -+	ss[7] = SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA);
772.11606 -+	*(uint64_t *)(ss+8) =
772.11607 -+		kgem_add_reloc64(&sna->kgem, offset + 8, bo,
772.11608 -+				 I915_GEM_DOMAIN_SAMPLER << 16,
772.11609 -+				 delta);
772.11610 -+	ss[10] = 0;
772.11611 -+	ss[11] = 0;
772.11612 -+	ss[12] = 0;
772.11613 -+	ss[13] = 0;
772.11614 -+	ss[14] = 0;
772.11615 -+	ss[15] = 0;
772.11616 -+
772.11617 -+	DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> sampler\n",
772.11618 -+	     offset, bo->handle, ss[1],
772.11619 -+	     format, width, height, bo->pitch, bo->tiling));
772.11620 -+
772.11621 -+	return offset * sizeof(uint32_t);
772.11622 -+}
772.11623 -+
772.11624 -+static void gen9_emit_video_state(struct sna *sna,
772.11625 -+				  const struct sna_composite_op *op)
772.11626 -+{
772.11627 -+	struct sna_video_frame *frame = op->priv;
772.11628 -+	uint32_t src_surf_format;
772.11629 -+	uint32_t src_surf_base[6];
772.11630 -+	int src_width[6];
772.11631 -+	int src_height[6];
772.11632 -+	int src_pitch[6];
772.11633 -+	uint32_t *binding_table;
772.11634 -+	uint16_t offset;
772.11635 -+	int n_src, n;
772.11636 -+
772.11637 -+	/* XXX VeBox, bicubic */
772.11638 -+
772.11639 -+	gen9_get_batch(sna, op);
772.11640 -+
772.11641 -+	src_surf_base[0] = 0;
772.11642 -+	src_surf_base[1] = 0;
772.11643 -+	src_surf_base[2] = frame->VBufOffset;
772.11644 -+	src_surf_base[3] = frame->VBufOffset;
772.11645 -+	src_surf_base[4] = frame->UBufOffset;
772.11646 -+	src_surf_base[5] = frame->UBufOffset;
772.11647 -+
772.11648 -+	if (is_planar_fourcc(frame->id)) {
772.11649 -+		src_surf_format = SURFACEFORMAT_R8_UNORM;
772.11650 -+		src_width[1]  = src_width[0]  = frame->width;
772.11651 -+		src_height[1] = src_height[0] = frame->height;
772.11652 -+		src_pitch[1]  = src_pitch[0]  = frame->pitch[1];
772.11653 -+		src_width[4]  = src_width[5]  = src_width[2]  = src_width[3] =
772.11654 -+			frame->width / 2;
772.11655 -+		src_height[4] = src_height[5] = src_height[2] = src_height[3] =
772.11656 -+			frame->height / 2;
772.11657 -+		src_pitch[4]  = src_pitch[5]  = src_pitch[2]  = src_pitch[3] =
772.11658 -+			frame->pitch[0];
772.11659 -+		n_src = 6;
772.11660 -+	} else {
772.11661 -+		if (frame->id == FOURCC_RGB888)
772.11662 -+			src_surf_format = SURFACEFORMAT_B8G8R8X8_UNORM;
772.11663 -+		else if (frame->id == FOURCC_UYVY)
772.11664 -+			src_surf_format = SURFACEFORMAT_YCRCB_SWAPY;
772.11665 -+		else
772.11666 -+			src_surf_format = SURFACEFORMAT_YCRCB_NORMAL;
772.11667 -+
772.11668 -+		src_width[0]  = frame->width;
772.11669 -+		src_height[0] = frame->height;
772.11670 -+		src_pitch[0]  = frame->pitch[0];
772.11671 -+		n_src = 1;
772.11672 -+	}
772.11673 -+
772.11674 -+	binding_table = gen9_composite_get_binding_table(sna, &offset);
772.11675 -+
772.11676 -+	binding_table[0] =
772.11677 -+		gen9_bind_bo(sna,
772.11678 -+			     op->dst.bo, op->dst.width, op->dst.height,
772.11679 -+			     gen9_get_dest_format(op->dst.format),
772.11680 -+			     true);
772.11681 -+	for (n = 0; n < n_src; n++) {
772.11682 -+		binding_table[1+n] =
772.11683 -+			gen9_bind_video_source(sna,
772.11684 -+					       frame->bo,
772.11685 -+					       src_surf_base[n],
772.11686 -+					       src_width[n],
772.11687 -+					       src_height[n],
772.11688 -+					       src_pitch[n],
772.11689 -+					       src_surf_format);
772.11690 -+	}
772.11691 -+
772.11692 -+	gen9_emit_state(sna, op, offset);
772.11693 -+}
772.11694 -+
772.11695 -+static unsigned select_video_kernel(const struct sna_video_frame *frame)
772.11696 -+{
772.11697 -+	switch (frame->id) {
772.11698 -+	case FOURCC_YV12:
772.11699 -+	case FOURCC_I420:
772.11700 -+	case FOURCC_XVMC:
772.11701 -+		return GEN9_WM_KERNEL_VIDEO_PLANAR;
772.11702 -+
772.11703 -+	case FOURCC_RGB888:
772.11704 -+	case FOURCC_RGB565:
772.11705 -+		return GEN9_WM_KERNEL_VIDEO_RGB;
772.11706 -+
772.11707 -+	default:
772.11708 -+		return GEN9_WM_KERNEL_VIDEO_PACKED;
772.11709 -+	}
772.11710 -+}
772.11711 -+
772.11712 -+static bool
772.11713 -+gen9_render_video(struct sna *sna,
772.11714 -+		  struct sna_video *video,
772.11715 -+		  struct sna_video_frame *frame,
772.11716 -+		  RegionPtr dstRegion,
772.11717 -+		  PixmapPtr pixmap)
772.11718 -+{
772.11719 -+	struct sna_composite_op tmp;
772.11720 -+	struct sna_pixmap *priv = sna_pixmap(pixmap);
772.11721 -+	int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1;
772.11722 -+	int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1;
772.11723 -+	int src_width = frame->src.x2 - frame->src.x1;
772.11724 -+	int src_height = frame->src.y2 - frame->src.y1;
772.11725 -+	float src_offset_x, src_offset_y;
772.11726 -+	float src_scale_x, src_scale_y;
772.11727 -+	unsigned filter;
772.11728 -+	const BoxRec *box;
772.11729 -+	int nbox;
772.11730 -+
772.11731 -+	DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n",
772.11732 -+	     __FUNCTION__,
772.11733 -+	     src_width, src_height, dst_width, dst_height,
772.11734 -+	     region_num_rects(dstRegion),
772.11735 -+	     REGION_EXTENTS(NULL, dstRegion)->x1,
772.11736 -+	     REGION_EXTENTS(NULL, dstRegion)->y1,
772.11737 -+	     REGION_EXTENTS(NULL, dstRegion)->x2,
772.11738 -+	     REGION_EXTENTS(NULL, dstRegion)->y2));
772.11739 -+
772.11740 -+	assert(priv->gpu_bo);
772.11741 -+	assert(!too_large(pixmap->drawable.width, pixmap->drawable.height));
772.11742 -+	assert(!unaligned(priv->gpu_bo, pixmap->drawable.bitsPerPixel));
772.11743 -+
772.11744 -+	memset(&tmp, 0, sizeof(tmp));
772.11745 -+
772.11746 -+	tmp.dst.pixmap = pixmap;
772.11747 -+	tmp.dst.width  = pixmap->drawable.width;
772.11748 -+	tmp.dst.height = pixmap->drawable.height;
772.11749 -+	tmp.dst.format = sna_render_format_for_depth(pixmap->drawable.depth);
772.11750 -+	tmp.dst.bo = priv->gpu_bo;
772.11751 -+
772.11752 -+	tmp.src.bo = frame->bo;
772.11753 -+	tmp.mask.bo = NULL;
772.11754 -+
772.11755 -+	tmp.floats_per_vertex = 3;
772.11756 -+	tmp.floats_per_rect = 9;
772.11757 -+
772.11758 -+	DBG(("%s: scaling?=%d, planar?=%d [%x]\n",
772.11759 -+	     __FUNCTION__,
772.11760 -+	     src_width != dst_width || src_height != dst_height,
772.11761 -+	     is_planar_fourcc(frame->id), frame->id));
772.11762 -+
772.11763 -+	if (src_width == dst_width && src_height == dst_height)
772.11764 -+		filter = SAMPLER_FILTER_NEAREST;
772.11765 -+	else
772.11766 -+		filter = SAMPLER_FILTER_BILINEAR;
772.11767 -+
772.11768 -+	tmp.u.gen9.flags =
772.11769 -+		GEN9_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD,
772.11770 -+					      SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE),
772.11771 -+			       NO_BLEND,
772.11772 -+			       select_video_kernel(frame),
772.11773 -+			       2);
772.11774 -+	tmp.priv = frame;
772.11775 -+
772.11776 -+	kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo);
772.11777 -+	if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL)) {
772.11778 -+		kgem_submit(&sna->kgem);
772.11779 -+		if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL))
772.11780 -+			return false;
772.11781 -+
772.11782 -+		_kgem_set_mode(&sna->kgem, KGEM_RENDER);
772.11783 -+	}
772.11784 -+
772.11785 -+	gen9_align_vertex(sna, &tmp);
772.11786 -+	gen9_emit_video_state(sna, &tmp);
772.11787 -+
772.11788 -+	DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n",
772.11789 -+	     __FUNCTION__,
772.11790 -+	     frame->src.x1, frame->src.y1,
772.11791 -+	     src_width, src_height,
772.11792 -+	     dst_width, dst_height,
772.11793 -+	     frame->width, frame->height));
772.11794 -+
772.11795 -+	src_scale_x = (float)src_width / dst_width / frame->width;
772.11796 -+	src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x;
772.11797 -+
772.11798 -+	src_scale_y = (float)src_height / dst_height / frame->height;
772.11799 -+	src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y;
772.11800 -+
772.11801 -+	DBG(("%s: scale=(%f, %f), offset=(%f, %f)\n",
772.11802 -+	     __FUNCTION__,
772.11803 -+	     src_scale_x, src_scale_y,
772.11804 -+	     src_offset_x, src_offset_y));
772.11805 -+
772.11806 -+	box = region_rects(dstRegion);
772.11807 -+	nbox = region_num_rects(dstRegion);
772.11808 -+	while (nbox--) {
772.11809 -+		DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n",
772.11810 -+		     __FUNCTION__,
772.11811 -+		     box->x1, box->y1,
772.11812 -+		     box->x2, box->y2,
772.11813 -+		     box->x1 * src_scale_x + src_offset_x,
772.11814 -+		     box->y1 * src_scale_y + src_offset_y,
772.11815 -+		     box->x2 * src_scale_x + src_offset_x,
772.11816 -+		     box->y2 * src_scale_y + src_offset_y));
772.11817 -+
772.11818 -+		gen9_get_rectangles(sna, &tmp, 1, gen9_emit_video_state);
772.11819 -+
772.11820 -+		OUT_VERTEX(box->x2, box->y2);
772.11821 -+		OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x);
772.11822 -+		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.11823 -+
772.11824 -+		OUT_VERTEX(box->x1, box->y2);
772.11825 -+		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.11826 -+		OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y);
772.11827 -+
772.11828 -+		OUT_VERTEX(box->x1, box->y1);
772.11829 -+		OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x);
772.11830 -+		OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y);
772.11831 -+
772.11832 -+		box++;
772.11833 -+	}
772.11834 -+	gen8_vertex_flush(sna);
772.11835 -+
772.11836 -+	if (!DAMAGE_IS_ALL(priv->gpu_damage))
772.11837 -+		sna_damage_add(&priv->gpu_damage, dstRegion);
772.11838 -+
772.11839 -+	return true;
772.11840 -+}
772.11841 -+#endif
772.11842 -+
772.11843 -+static void gen9_render_flush(struct sna *sna)
772.11844 -+{
772.11845 -+	gen8_vertex_close(sna);
772.11846 -+
772.11847 -+	assert(sna->render.vb_id == 0);
772.11848 -+	assert(sna->render.vertex_offset == 0);
772.11849 -+}
772.11850 -+
772.11851 -+static void gen9_render_reset(struct sna *sna)
772.11852 -+{
772.11853 -+	sna->render_state.gen9.emit_flush = false;
772.11854 -+	sna->render_state.gen9.needs_invariant = true;
772.11855 -+	sna->render_state.gen9.ve_id = 3 << 2;
772.11856 -+	sna->render_state.gen9.ve_dirty = false;
772.11857 -+	sna->render_state.gen9.last_primitive = -1;
772.11858 -+
772.11859 -+	sna->render_state.gen9.num_sf_outputs = 0;
772.11860 -+	sna->render_state.gen9.samplers = -1;
772.11861 -+	sna->render_state.gen9.blend = -1;
772.11862 -+	sna->render_state.gen9.kernel = -1;
772.11863 -+	sna->render_state.gen9.drawrect_offset = -1;
772.11864 -+	sna->render_state.gen9.drawrect_limit = -1;
772.11865 -+	sna->render_state.gen9.surface_table = 0;
772.11866 -+
772.11867 -+	if (sna->render.vbo && !kgem_bo_can_map(&sna->kgem, sna->render.vbo)) {
772.11868 -+		DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
772.11869 -+		discard_vbo(sna);
772.11870 -+	}
772.11871 -+
772.11872 -+	sna->render.vertex_offset = 0;
772.11873 -+	sna->render.nvertex_reloc = 0;
772.11874 -+	sna->render.vb_id = 0;
772.11875 -+}
772.11876 -+
772.11877 -+static void gen9_render_fini(struct sna *sna)
772.11878 -+{
772.11879 -+	kgem_bo_destroy(&sna->kgem, sna->render_state.gen9.general_bo);
772.11880 -+}
772.11881 -+
772.11882 -+static bool gen9_render_setup(struct sna *sna)
772.11883 -+{
772.11884 -+	struct gen9_render_state *state = &sna->render_state.gen9;
772.11885 -+	struct sna_static_stream general;
772.11886 -+	struct gen9_sampler_state *ss;
772.11887 -+	int i, j, k, l, m;
772.11888 -+	uint32_t devid;
772.11889 -+
772.11890 -+	devid = intel_get_device_id(sna->dev);
772.11891 -+	if (devid & 0xf)
772.11892 -+		state->gt = GEN9_GT_BIAS + ((devid >> 4) & 0xf) + 1;
772.11893 -+	DBG(("%s: gt=%d\n", __FUNCTION__, state->gt));
772.11894 -+
772.11895 -+	state->info = &min_gt_info;
772.11896 -+	if (is_skl(sna))
772.11897 -+		state->info = &skl_gt_info;
772.11898 -+	if (is_bxt(sna))
772.11899 -+		state->info = &bxt_gt_info;
772.11900 -+	if (is_kbl(sna))
772.11901 -+		state->info = &kbl_gt_info;
772.11902 -+	if (is_glk(sna))
772.11903 -+		state->info = &glk_gt_info;
772.11904 -+
772.11905 -+	sna_static_stream_init(&general);
772.11906 -+
772.11907 -+	/* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
772.11908 -+	 * dumps, you know it points to zero.
772.11909 -+	 */
772.11910 -+	null_create(&general);
772.11911 -+
772.11912 -+	for (m = 0; m < ARRAY_SIZE(wm_kernels); m++) {
772.11913 -+		if (wm_kernels[m].size) {
772.11914 -+			state->wm_kernel[m][1] =
772.11915 -+				sna_static_stream_add(&general,
772.11916 -+						      wm_kernels[m].data,
772.11917 -+						      wm_kernels[m].size,
772.11918 -+						      64);
772.11919 -+		} else {
772.11920 -+			if (USE_8_PIXEL_DISPATCH) {
772.11921 -+				state->wm_kernel[m][0] =
772.11922 -+					sna_static_stream_compile_wm(sna, &general,
772.11923 -+								     wm_kernels[m].data, 8);
772.11924 -+			}
772.11925 -+
772.11926 -+			if (USE_16_PIXEL_DISPATCH) {
772.11927 -+				state->wm_kernel[m][1] =
772.11928 -+					sna_static_stream_compile_wm(sna, &general,
772.11929 -+								     wm_kernels[m].data, 16);
772.11930 -+			}
772.11931 -+
772.11932 -+			if (USE_32_PIXEL_DISPATCH) {
772.11933 -+				state->wm_kernel[m][2] =
772.11934 -+					sna_static_stream_compile_wm(sna, &general,
772.11935 -+								     wm_kernels[m].data, 32);
772.11936 -+			}
772.11937 -+		}
772.11938 -+		assert(state->wm_kernel[m][0]|state->wm_kernel[m][1]|state->wm_kernel[m][2]);
772.11939 -+	}
772.11940 -+
772.11941 -+	COMPILE_TIME_ASSERT(SAMPLER_OFFSET(FILTER_COUNT, EXTEND_COUNT, FILTER_COUNT, EXTEND_COUNT) <= 0x7ff);
772.11942 -+	ss = sna_static_stream_map(&general,
772.11943 -+				   2 * sizeof(*ss) *
772.11944 -+				   (2 +
772.11945 -+				    FILTER_COUNT * EXTEND_COUNT *
772.11946 -+				    FILTER_COUNT * EXTEND_COUNT),
772.11947 -+				   32);
772.11948 -+	state->wm_state = sna_static_stream_offsetof(&general, ss);
772.11949 -+	sampler_copy_init(ss); ss += 2;
772.11950 -+	sampler_fill_init(ss); ss += 2;
772.11951 -+	for (i = 0; i < FILTER_COUNT; i++) {
772.11952 -+		for (j = 0; j < EXTEND_COUNT; j++) {
772.11953 -+			for (k = 0; k < FILTER_COUNT; k++) {
772.11954 -+				for (l = 0; l < EXTEND_COUNT; l++) {
772.11955 -+					sampler_state_init(ss++, i, j);
772.11956 -+					sampler_state_init(ss++, k, l);
772.11957 -+				}
772.11958 -+			}
772.11959 -+		}
772.11960 -+	}
772.11961 -+
772.11962 -+	state->cc_blend = gen9_create_blend_state(&general);
772.11963 -+
772.11964 -+	state->general_bo = sna_static_stream_fini(sna, &general);
772.11965 -+	return state->general_bo != NULL;
772.11966 -+}
772.11967 -+
772.11968 -+const char *gen9_render_init(struct sna *sna, const char *backend)
772.11969 -+{
772.11970 -+	if (!gen9_render_setup(sna))
772.11971 -+		return backend;
772.11972 -+
772.11973 -+	sna->kgem.context_switch = gen6_render_context_switch;
772.11974 -+	sna->kgem.retire = gen6_render_retire;
772.11975 -+	sna->kgem.expire = gen4_render_expire;
772.11976 -+
772.11977 -+#if !NO_COMPOSITE
772.11978 -+	sna->render.composite = gen9_render_composite;
772.11979 -+	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
772.11980 -+#endif
772.11981 -+#if !NO_COMPOSITE_SPANS
772.11982 -+	sna->render.check_composite_spans = gen9_check_composite_spans;
772.11983 -+	sna->render.composite_spans = gen9_render_composite_spans;
772.11984 -+	sna->render.prefer_gpu |= PREFER_GPU_SPANS;
772.11985 -+#endif
772.11986 -+#if !NO_VIDEO
772.11987 -+	sna->render.video = gen9_render_video;
772.11988 -+#endif
772.11989 -+
772.11990 -+#if !NO_COPY_BOXES
772.11991 -+	sna->render.copy_boxes = gen9_render_copy_boxes;
772.11992 -+#endif
772.11993 -+#if !NO_COPY
772.11994 -+	sna->render.copy = gen9_render_copy;
772.11995 -+#endif
772.11996 -+
772.11997 -+#if !NO_FILL_BOXES
772.11998 -+	sna->render.fill_boxes = gen9_render_fill_boxes;
772.11999 -+#endif
772.12000 -+#if !NO_FILL
772.12001 -+	sna->render.fill = gen9_render_fill;
772.12002 -+#endif
772.12003 -+#if !NO_FILL_ONE
772.12004 -+	sna->render.fill_one = gen9_render_fill_one;
772.12005 -+#endif
772.12006 -+#if !NO_FILL_CLEAR
772.12007 -+	sna->render.clear = gen9_render_clear;
772.12008 -+#endif
772.12009 -+
772.12010 -+	sna->render.flush = gen9_render_flush;
772.12011 -+	sna->render.reset = gen9_render_reset;
772.12012 -+	sna->render.fini = gen9_render_fini;
772.12013 -+
772.12014 -+	sna->render.max_3d_size = GEN9_MAX_SIZE;
772.12015 -+	sna->render.max_3d_pitch = 1 << 18;
772.12016 -+	return sna->render_state.gen9.info->name;
772.12017 -+}
772.12018 -diff --git a/src/sna/gen9_render.h b/src/sna/gen9_render.h
772.12019 -new file mode 100644
772.12020 -index 00000000..e3cb3f93
772.12021 ---- /dev/null
772.12022 -+++ b/src/sna/gen9_render.h
772.12023 -@@ -0,0 +1,1130 @@
772.12024 -+#ifndef GEN9_RENDER_H
772.12025 -+#define GEN9_RENDER_H
772.12026 -+
772.12027 -+#define INTEL_MASK(high, low) (((1 << ((high) - (low) + 1)) - 1) << (low))
772.12028 -+
772.12029 -+#define GEN9_3D(pipeline,op,sub) \
772.12030 -+	((3 << 29) | ((pipeline) << 27) | ((op) << 24) | ((sub) << 16))
772.12031 -+
772.12032 -+#define GEN9_STATE_BASE_ADDRESS			GEN9_3D(0, 1, 1)
772.12033 -+# define BASE_ADDRESS_MODIFY			(1 << 0)
772.12034 -+
772.12035 -+#define GEN9_STATE_SIP				GEN9_3D(0, 1, 2)
772.12036 -+
772.12037 -+#define GEN9_3DSTATE_VF_STATISTICS		GEN9_3D(1, 0, 0xb)
772.12038 -+#define GEN9_PIPELINE_SELECT			GEN9_3D(1, 1, 4)
772.12039 -+# define PIPELINE_SELECT_3D		0
772.12040 -+# define PIPELINE_SELECT_MEDIA		1
772.12041 -+#define PIPELINE_SELECTION_MASK            (3 << 8)
772.12042 -+
772.12043 -+#define GEN9_MEDIA_STATE_POINTERS		GEN9_3D(2, 0, 0)
772.12044 -+#define GEN9_MEDIA_OBJECT			GEN9_3D(2, 1, 0)
772.12045 -+
772.12046 -+#define GEN9_3DSTATE_CLEAR_PARAMS               GEN9_3D(3, 0, 0x04)
772.12047 -+#define GEN9_3DSTATE_DEPTH_BUFFER               GEN9_3D(3, 0, 0x05)
772.12048 -+# define DEPTH_BUFFER_TYPE_SHIFT	29
772.12049 -+# define DEPTH_BUFFER_FORMAT_SHIFT	18
772.12050 -+
772.12051 -+#define GEN9_3DSTATE_STENCIL_BUFFER		GEN9_3D(3, 0, 0x06)
772.12052 -+#define GEN9_3DSTATE_HIER_DEPTH_BUFFER		GEN9_3D(3, 0, 0x07)
772.12053 -+#define GEN9_3DSTATE_VERTEX_BUFFERS		GEN9_3D(3, 0, 0x08)
772.12054 -+# define VB_INDEX_SHIFT			26
772.12055 -+# define VB_MODIFY_ENABLE		(1 << 14)
772.12056 -+#define GEN9_3DSTATE_VERTEX_ELEMENTS		GEN9_3D(3, 0, 0x09)
772.12057 -+# define VE_INDEX_SHIFT		26
772.12058 -+# define VE_VALID					(1 << 25)
772.12059 -+# define VE_FORMAT_SHIFT				16
772.12060 -+# define VE_OFFSET_SHIFT				0
772.12061 -+# define VE_COMPONENT_0_SHIFT			28
772.12062 -+# define VE_COMPONENT_1_SHIFT			24
772.12063 -+# define VE_COMPONENT_2_SHIFT			20
772.12064 -+# define VE_COMPONENT_3_SHIFT			16
772.12065 -+#define GEN9_3DSTATE_INDEX_BUFFER		GEN9_3D(3, 0, 0x0a)
772.12066 -+#define GEN9_3DSTATE_VF				GEN9_3D(3, 0, 0x0c)
772.12067 -+
772.12068 -+#define GEN9_3DSTATE_MULTISAMPLE		GEN9_3D(3, 0, 0x0d)
772.12069 -+/* DW1 */
772.12070 -+# define MULTISAMPLE_PIXEL_LOCATION_CENTER		(0 << 4)
772.12071 -+# define MULTISAMPLE_PIXEL_LOCATION_UPPER_LEFT	(1 << 4)
772.12072 -+# define MULTISAMPLE_NUMSAMPLES_1			(0 << 1)
772.12073 -+# define MULTISAMPLE_NUMSAMPLES_4			(2 << 1)
772.12074 -+# define MULTISAMPLE_NUMSAMPLES_8			(3 << 1)
772.12075 -+
772.12076 -+#define GEN9_3DSTATE_CC_STATE_POINTERS		GEN9_3D(3, 0, 0x0e)
772.12077 -+#define GEN9_3DSTATE_SCISSOR_STATE_POINTERS	GEN9_3D(3, 0, 0x0f)
772.12078 -+
772.12079 -+#define GEN9_3DSTATE_VS				GEN9_3D(3, 0, 0x10)
772.12080 -+#define GEN9_3DSTATE_GS				GEN9_3D(3, 0, 0x11)
772.12081 -+#define GEN9_3DSTATE_CLIP			GEN9_3D(3, 0, 0x12)
772.12082 -+#define GEN9_3DSTATE_SF				GEN9_3D(3, 0, 0x13)
772.12083 -+# define SF_TRI_PROVOKE_SHIFT		29
772.12084 -+# define SF_LINE_PROVOKE_SHIFT		27
772.12085 -+# define SF_FAN_PROVOKE_SHIFT		25
772.12086 -+
772.12087 -+#define GEN9_3DSTATE_WM				GEN9_3D(3, 0, 0x14)
772.12088 -+/* DW1 */
772.12089 -+# define WM_STATISTICS_ENABLE                              (1 << 31)
772.12090 -+# define WM_DEPTH_CLEAR                                    (1 << 30)
772.12091 -+# define WM_DEPTH_RESOLVE                                  (1 << 28)
772.12092 -+# define WM_HIERARCHICAL_DEPTH_RESOLVE                     (1 << 27)
772.12093 -+# define WM_KILL_ENABLE                                    (1 << 25)
772.12094 -+# define WM_POSITION_ZW_PIXEL                              (0 << 17)
772.12095 -+# define WM_POSITION_ZW_CENTROID                           (2 << 17)
772.12096 -+# define WM_POSITION_ZW_SAMPLE                             (3 << 17)
772.12097 -+# define WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC              (1 << 16)
772.12098 -+# define WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC            (1 << 15)
772.12099 -+# define WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC               (1 << 14)
772.12100 -+# define WM_PERSPECTIVE_SAMPLE_BARYCENTRIC                 (1 << 13)
772.12101 -+# define WM_PERSPECTIVE_CENTROID_BARYCENTRIC               (1 << 12)
772.12102 -+# define WM_PERSPECTIVE_PIXEL_BARYCENTRIC                  (1 << 11)
772.12103 -+# define WM_LINE_END_CAP_AA_WIDTH_0_5                      (0 << 8)
772.12104 -+# define WM_LINE_END_CAP_AA_WIDTH_1_0                      (1 << 8)
772.12105 -+# define WM_LINE_END_CAP_AA_WIDTH_2_0                      (2 << 8)
772.12106 -+# define WM_LINE_END_CAP_AA_WIDTH_4_0                      (3 << 8)
772.12107 -+# define WM_LINE_AA_WIDTH_0_5                              (0 << 6)
772.12108 -+# define WM_LINE_AA_WIDTH_1_0                              (1 << 6)
772.12109 -+# define WM_LINE_AA_WIDTH_2_0                              (2 << 6)
772.12110 -+# define WM_LINE_AA_WIDTH_4_0                              (3 << 6)
772.12111 -+# define WM_POLYGON_STIPPLE_ENABLE                         (1 << 4)
772.12112 -+# define WM_LINE_STIPPLE_ENABLE                            (1 << 3)
772.12113 -+# define WM_POINT_RASTRULE_UPPER_RIGHT                     (1 << 2)
772.12114 -+# define WM_MSRAST_OFF_PIXEL                               (0 << 0)
772.12115 -+# define WM_MSRAST_OFF_PATTERN                             (1 << 0)
772.12116 -+# define WM_MSRAST_ON_PIXEL                                (2 << 0)
772.12117 -+# define WM_MSRAST_ON_PATTERN                              (3 << 0)
772.12118 -+
772.12119 -+#define GEN9_3DSTATE_CONSTANT_VS		GEN9_3D(3, 0, 0x15)
772.12120 -+#define GEN9_3DSTATE_CONSTANT_GS		GEN9_3D(3, 0, 0x16)
772.12121 -+#define GEN9_3DSTATE_CONSTANT_PS		GEN9_3D(3, 0, 0x17)
772.12122 -+
772.12123 -+#define GEN9_3DSTATE_SAMPLE_MASK		GEN9_3D(3, 0, 0x18)
772.12124 -+
772.12125 -+#define GEN9_3DSTATE_CONSTANT_HS                GEN9_3D(3, 0, 0x19)
772.12126 -+#define GEN9_3DSTATE_CONSTANT_DS                GEN9_3D(3, 0, 0x1a)
772.12127 -+
772.12128 -+#define GEN9_3DSTATE_HS                         GEN9_3D(3, 0, 0x1b)
772.12129 -+#define GEN9_3DSTATE_TE                         GEN9_3D(3, 0, 0x1c)
772.12130 -+#define GEN9_3DSTATE_DS                         GEN9_3D(3, 0, 0x1d)
772.12131 -+#define GEN9_3DSTATE_STREAMOUT                  GEN9_3D(3, 0, 0x1e)
772.12132 -+
772.12133 -+#define GEN9_3DSTATE_SBE                        GEN9_3D(3, 0, 0x1f)
772.12134 -+/* DW1 */
772.12135 -+# define SBE_FORCE_VERTEX_URB_READ_LENGTH  (1<<29)
772.12136 -+# define SBE_FORCE_VERTEX_URB_READ_OFFSET  (1<<28)
772.12137 -+# define SBE_NUM_OUTPUTS_SHIFT             22
772.12138 -+# define SBE_SWIZZLE_ENABLE                (1 << 21)
772.12139 -+# define SBE_POINT_SPRITE_LOWERLEFT        (1 << 20)
772.12140 -+# define SBE_URB_ENTRY_READ_LENGTH_SHIFT   11
772.12141 -+# define SBE_URB_ENTRY_READ_OFFSET_SHIFT   5
772.12142 -+#define SBE_ACTIVE_COMPONENT_NONE          0
772.12143 -+#define SBE_ACTIVE_COMPONENT_XY            1 
772.12144 -+#define SBE_ACTIVE_COMPONENT_XYZ           2
772.12145 -+#define SBE_ACTIVE_COMPONENT_XYZW          3
772.12146 -+
772.12147 -+
772.12148 -+#define GEN9_3DSTATE_PS                                 GEN9_3D(3, 0, 0x20)
772.12149 -+/* DW1:DW2 kernel pointer */
772.12150 -+/* DW3 */
772.12151 -+# define PS_SPF_MODE                               (1 << 31)
772.12152 -+# define PS_VECTOR_MASK_ENABLE                     (1 << 30)
772.12153 -+# define PS_SAMPLER_COUNT_SHIFT                    27
772.12154 -+# define PS_BINDING_TABLE_ENTRY_COUNT_SHIFT        18
772.12155 -+# define PS_FLOATING_POINT_MODE_IEEE_754           (0 << 16)
772.12156 -+# define PS_FLOATING_POINT_MODE_ALT                (1 << 16)
772.12157 -+/* DW4:DW5: scratch space */
772.12158 -+/* DW6 */
772.12159 -+# define PS_MAX_THREADS_SHIFT                      23
772.12160 -+# define PS_MAX_THREADS                            (63 << PS_MAX_THREADS_SHIFT)
772.12161 -+# define PS_PUSH_CONSTANT_ENABLE                   (1 << 11)
772.12162 -+# define PS_RENDER_TARGET_CLEAR			   (1 << 8)
772.12163 -+# define PS_RENDER_TARGET_RESOLVE		   (1 << 6)
772.12164 -+# define PS_POSOFFSET_NONE                         (0 << 3)
772.12165 -+# define PS_POSOFFSET_CENTROID                     (2 << 3)
772.12166 -+# define PS_POSOFFSET_SAMPLE                       (3 << 3)
772.12167 -+# define PS_32_DISPATCH_ENABLE                     (1 << 2)
772.12168 -+# define PS_16_DISPATCH_ENABLE                     (1 << 1)
772.12169 -+# define PS_8_DISPATCH_ENABLE                      (1 << 0)
772.12170 -+/* DW7 */
772.12171 -+# define PS_DISPATCH_START_GRF_SHIFT_0             16
772.12172 -+# define PS_DISPATCH_START_GRF_SHIFT_1             8
772.12173 -+# define PS_DISPATCH_START_GRF_SHIFT_2             0
772.12174 -+/* DW8:D9: kernel 1 pointer */
772.12175 -+/* DW10:D11: kernel 2 pointer */
772.12176 -+
772.12177 -+#define GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP      GEN9_3D(3, 0, 0x21)
772.12178 -+#define GEN9_3DSTATE_VIEWPORT_STATE_POINTERS_CC         GEN9_3D(3, 0, 0x23)
772.12179 -+
772.12180 -+#define GEN9_3DSTATE_BLEND_STATE_POINTERS               GEN9_3D(3, 0, 0x24)
772.12181 -+
772.12182 -+#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_VS          GEN9_3D(3, 0, 0x26)
772.12183 -+#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_HS          GEN9_3D(3, 0, 0x27)
772.12184 -+#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_DS          GEN9_3D(3, 0, 0x28)
772.12185 -+#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_GS          GEN9_3D(3, 0, 0x29)
772.12186 -+#define GEN9_3DSTATE_BINDING_TABLE_POINTERS_PS          GEN9_3D(3, 0, 0x2a)
772.12187 -+
772.12188 -+#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_VS          GEN9_3D(3, 0, 0x2b)
772.12189 -+#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_HS          GEN9_3D(3, 0, 0x2c)
772.12190 -+#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_DS          GEN9_3D(3, 0, 0x2d)
772.12191 -+#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_GS          GEN9_3D(3, 0, 0x2e)
772.12192 -+#define GEN9_3DSTATE_SAMPLER_STATE_POINTERS_PS          GEN9_3D(3, 0, 0x2f)
772.12193 -+
772.12194 -+#define GEN9_3DSTATE_URB_VS                             GEN9_3D(3, 0, 0x30)
772.12195 -+#define GEN9_3DSTATE_URB_HS                             GEN9_3D(3, 0, 0x31)
772.12196 -+#define GEN9_3DSTATE_URB_DS                             GEN9_3D(3, 0, 0x32)
772.12197 -+#define GEN9_3DSTATE_URB_GS                             GEN9_3D(3, 0, 0x33)
772.12198 -+/* DW1 */
772.12199 -+# define URB_ENTRY_NUMBER_SHIFT            0
772.12200 -+# define URB_ENTRY_SIZE_SHIFT              16
772.12201 -+# define URB_STARTING_ADDRESS_SHIFT        25
772.12202 -+
772.12203 -+#define GEN9_3DSTATE_GATHER_CONSTANT_VS             GEN9_3D(3, 0, 0x34)
772.12204 -+#define GEN9_3DSTATE_GATHER_CONSTANT_GS             GEN9_3D(3, 0, 0x35)
772.12205 -+#define GEN9_3DSTATE_GATHER_CONSTANT_HS             GEN9_3D(3, 0, 0x36)
772.12206 -+#define GEN9_3DSTATE_GATHER_CONSTANT_DS             GEN9_3D(3, 0, 0x37)
772.12207 -+#define GEN9_3DSTATE_GATHER_CONSTANT_PS             GEN9_3D(3, 0, 0x38)
772.12208 -+
772.12209 -+#define GEN9_3DSTATE_DX9_CONSTANTF_VS             GEN9_3D(3, 0, 0x39)
772.12210 -+#define GEN9_3DSTATE_DX9_CONSTANTF_PS             GEN9_3D(3, 0, 0x3a)
772.12211 -+#define GEN9_3DSTATE_DX9_CONSTANTI_VS             GEN9_3D(3, 0, 0x3b)
772.12212 -+#define GEN9_3DSTATE_DX9_CONSTANTI_PS             GEN9_3D(3, 0, 0x3c)
772.12213 -+#define GEN9_3DSTATE_DX9_CONSTANTB_VS             GEN9_3D(3, 0, 0x3d)
772.12214 -+#define GEN9_3DSTATE_DX9_CONSTANTB_PS             GEN9_3D(3, 0, 0x3e)
772.12215 -+#define GEN9_3DSTATE_DX9_LOCAL_VALID_VS           GEN9_3D(3, 0, 0x3f)
772.12216 -+#define GEN9_3DSTATE_DX9_LOCAL_VALID_PS           GEN9_3D(3, 0, 0x40)
772.12217 -+#define GEN9_3DSTATE_DX9_GENERATE_ACTIVE_VS       GEN9_3D(3, 0, 0x41)
772.12218 -+#define GEN9_3DSTATE_DX9_GENERATE_ACTIVE_PS       GEN9_3D(3, 0, 0x42)
772.12219 -+
772.12220 -+#define GEN9_3DSTATE_BINDING_TABLE_EDIT_VS       GEN9_3D(3, 0, 0x43)
772.12221 -+#define GEN9_3DSTATE_BINDING_TABLE_EDIT_GS       GEN9_3D(3, 0, 0x44)
772.12222 -+#define GEN9_3DSTATE_BINDING_TABLE_EDIT_HS       GEN9_3D(3, 0, 0x45)
772.12223 -+#define GEN9_3DSTATE_BINDING_TABLE_EDIT_DS       GEN9_3D(3, 0, 0x46)
772.12224 -+#define GEN9_3DSTATE_BINDING_TABLE_EDIT_PS       GEN9_3D(3, 0, 0x47)
772.12225 -+
772.12226 -+#define GEN9_3DSTATE_VF_INSTANCING		GEN9_3D(3, 0, 0x49)
772.12227 -+#define GEN9_3DSTATE_VF_SGVS			GEN9_3D(3, 0, 0x4a)
772.12228 -+# define SGVS_ENABLE_INSTANCE_ID			(1 << 31)
772.12229 -+# define SGVS_INSTANCE_ID_COMPONENT_SHIFT		29
772.12230 -+# define SGVS_INSTANCE_ID_ELEMENT_OFFSET_SHIFT	16
772.12231 -+# define SGVS_ENABLE_VERTEX_ID			(1 << 15)
772.12232 -+# define SGVS_VERTEX_ID_COMPONENT_SHIFT            13
772.12233 -+# define SGVS_VERTEX_ID_ELEMENT_OFFSET_SHIFT	0
772.12234 -+#define GEN9_3DSTATE_VF_TOPOLOGY		GEN9_3D(3, 0, 0x4b)
772.12235 -+# define POINTLIST         0x01
772.12236 -+# define LINELIST          0x02
772.12237 -+# define LINESTRIP         0x03
772.12238 -+# define TRILIST           0x04
772.12239 -+# define TRISTRIP          0x05
772.12240 -+# define TRIFAN            0x06
772.12241 -+# define QUADLIST          0x07
772.12242 -+# define QUADSTRIP         0x08
772.12243 -+# define LINELIST_ADJ      0x09
772.12244 -+# define LINESTRIP_ADJ     0x0A
772.12245 -+# define TRILIST_ADJ       0x0B
772.12246 -+# define TRISTRIP_ADJ      0x0C
772.12247 -+# define TRISTRIP_REVERSE  0x0D
772.12248 -+# define POLYGON           0x0E
772.12249 -+# define RECTLIST          0x0F
772.12250 -+# define LINELOOP          0x10
772.12251 -+# define POINTLIST_BF      0x11
772.12252 -+# define LINESTRIP_CONT    0x12
772.12253 -+# define LINESTRIP_BF      0x13
772.12254 -+# define LINESTRIP_CONT_BF 0x14
772.12255 -+# define TRIFAN_NOSTIPPLE  0x15
772.12256 -+
772.12257 -+#define GEN9_3DSTATE_WM_CHROMAKEY		GEN9_3D(3, 0, 0x4c)
772.12258 -+
772.12259 -+#define GEN9_3DSTATE_PS_BLEND				GEN9_3D(3, 0, 0x4d)
772.12260 -+# define PS_BLEND_ALPHA_TO_COVERAGE_ENABLE		(1 << 31)
772.12261 -+# define PS_BLEND_HAS_WRITEABLE_RT			(1 << 30)
772.12262 -+# define PS_BLEND_COLOR_BLEND_ENABLE			(1 << 29)
772.12263 -+# define PS_BLEND_SRC_ALPHA_SHIFT			24
772.12264 -+# define PS_BLEND_DST_ALPHA_SHIFT			19
772.12265 -+# define PS_BLEND_SRC_SHIFT				14
772.12266 -+# define PS_BLEND_DST_SHIFT				9
772.12267 -+# define PS_BLEND_ALPHA_TEST_ENABLE			(1 << 8)
772.12268 -+# define PS_BLEND_INDEPENDENT_ALPHA_BLEND_ENABLE	(1 << 7)
772.12269 -+
772.12270 -+#define GEN9_3DSTATE_WM_DEPTH_STENCIL		GEN9_3D(3, 0, 0x4e)
772.12271 -+/* DW1 */
772.12272 -+# define WM_DS_STENCIL_TEST_MASK_MASK		INTEL_MASK(31, 24)
772.12273 -+# define WM_DS_STENCIL_TEST_MASK_SHIFT		24
772.12274 -+# define WM_DS_STENCIL_WRITE_MASK_MASK		INTEL_MASK(23, 16)
772.12275 -+# define WM_DS_STENCIL_WRITE_MASK_SHIFT		16
772.12276 -+# define WM_DS_BF_STENCIL_TEST_MASK_MASK		INTEL_MASK(15, 8)
772.12277 -+# define WM_DS_BF_STENCIL_TEST_MASK_SHIFT		8
772.12278 -+# define WM_DS_BF_STENCIL_WRITE_MASK_MASK		INTEL_MASK(7, 0)
772.12279 -+# define WM_DS_DEPTH_FUNC_SHIFT			5
772.12280 -+# define WM_DS_DOUBLE_SIDED_STENCIL_ENABLE		(1 << 4)
772.12281 -+# define WM_DS_STENCIL_TEST_ENABLE			(1 << 3)
772.12282 -+# define WM_DS_STENCIL_BUFFER_WRITE_ENABLE		(1 << 2)
772.12283 -+# define WM_DS_DEPTH_TEST_ENABLE			(1 << 1)
772.12284 -+# define WM_DS_DEPTH_BUFFER_WRITE_ENABLE		(1 << 0)
772.12285 -+/* DW2 */
772.12286 -+# define WM_DS_STENCIL_TEST_MASK_MASK		INTEL_MASK(31, 24)
772.12287 -+# define WM_DS_STENCIL_TEST_MASK_SHIFT		24
772.12288 -+# define WM_DS_STENCIL_WRITE_MASK_MASK		INTEL_MASK(23, 16)
772.12289 -+# define WM_DS_STENCIL_WRITE_MASK_SHIFT		16
772.12290 -+# define WM_DS_BF_STENCIL_TEST_MASK_MASK		INTEL_MASK(15, 8)
772.12291 -+# define WM_DS_BF_STENCIL_TEST_MASK_SHIFT		8
772.12292 -+# define WM_DS_BF_STENCIL_WRITE_MASK_MASK		INTEL_MASK(7, 0)
772.12293 -+# define WM_DS_BF_STENCIL_WRITE_MASK_SHIFT		0
772.12294 -+
772.12295 -+#define GEN9_3DSTATE_PS_EXTRA		GEN9_3D(3, 0, 0x4f)
772.12296 -+# define PSX_PIXEL_SHADER_VALID                    (1 << 31)
772.12297 -+# define PSX_PIXEL_SHADER_NO_RT_WRITE              (1 << 30)
772.12298 -+# define PSX_OMASK_TO_RENDER_TARGET                (1 << 29)
772.12299 -+# define PSX_KILL_ENABLE                           (1 << 28)
772.12300 -+# define PSX_PSCDEPTH_OFF                          (0 << 26)
772.12301 -+# define PSX_PSCDEPTH_ON                           (1 << 26)
772.12302 -+# define PSX_PSCDEPTH_ON_GE                        (2 << 26)
772.12303 -+# define PSX_PSCDEPTH_ON_LE                        (3 << 26)
772.12304 -+# define PSX_FORCE_COMPUTED_DEPTH                  (1 << 25)
772.12305 -+# define PSX_USES_SOURCE_DEPTH                     (1 << 24)
772.12306 -+# define PSX_USES_SOURCE_W                         (1 << 23)
772.12307 -+# define PSX_ATTRIBUTE_ENABLE                      (1 << 8)
772.12308 -+# define PSX_SHADER_DISABLES_ALPHA_TO_COVERAGE     (1 << 7)
772.12309 -+# define PSX_SHADER_IS_PER_SAMPLE                  (1 << 6)
772.12310 -+# define PSX_SHADER_HAS_UAV                        (1 << 2)
772.12311 -+# define PSX_SHADER_USES_INPUT_COVERAGE_MASK       (1 << 1)
772.12312 -+
772.12313 -+#define GEN9_3DSTATE_RASTER		GEN9_3D(3, 0, 0x50)
772.12314 -+/* DW1 */
772.12315 -+# define RASTER_FRONT_WINDING_CCW                  (1 << 21)
772.12316 -+# define RASTER_CULL_BOTH                          (0 << 16)
772.12317 -+# define RASTER_CULL_NONE                          (1 << 16)
772.12318 -+# define RASTER_CULL_FRONT                         (2 << 16)
772.12319 -+# define RASTER_CULL_BACK                          (3 << 16)
772.12320 -+# define RASTER_SMOOTH_POINT_ENABLE                (1 << 13)
772.12321 -+# define RASTER_LINE_AA_ENABLE                     (1 << 2)
772.12322 -+# define RASTER_VIEWPORT_Z_CLIP_TEST_ENABLE        (1 << 0)
772.12323 -+
772.12324 -+#define GEN9_3DSTATE_SBE_SWIZ		GEN9_3D(3, 0, 0x51)
772.12325 -+#define GEN9_3DSTATE_WM_HZ_OP		GEN9_3D(3, 0, 0x52)
772.12326 -+
772.12327 -+#define GEN9_3DSTATE_COMPONENT_PACKING          GEN6_3D(3, 0, 0x55)
772.12328 -+
772.12329 -+
772.12330 -+
772.12331 -+#define GEN9_3DSTATE_DRAWING_RECTANGLE		GEN9_3D(3, 1, 0x00)
772.12332 -+#define GEN9_3DSTATE_SAMPLER_PALETTE_LOAD	GEN9_3D(3, 1, 0x02)
772.12333 -+#define GEN9_3DSTATE_CHROMA_KEY			GEN9_3D(3, 1, 0x04)
772.12334 -+
772.12335 -+#define GEN9_3DSTATE_POLY_STIPPLE_OFFSET	GEN9_3D(3, 1, 0x06)
772.12336 -+#define GEN9_3DSTATE_POLY_STIPPLE_PATTERN	GEN9_3D(3, 1, 0x07)
772.12337 -+#define GEN9_3DSTATE_LINE_STIPPLE		GEN9_3D(3, 1, 0x08)
772.12338 -+#define GEN9_3DSTATE_AA_LINE_PARAMS		GEN9_3D(3, 1, 0x0a)
772.12339 -+#define GEN9_3DSTATE_SAMPLER_PALETTE_LOAD1	GEN9_3D(3, 1, 0x0c)
772.12340 -+#define GEN9_3DSTATE_MONOFILTER_SIZE		GEN9_3D(3, 1, 0x11)
772.12341 -+#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_VS	GEN9_3D(3, 1, 0x12)
772.12342 -+#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_HS	GEN9_3D(3, 1, 0x13)
772.12343 -+#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_DS	GEN9_3D(3, 1, 0x14)
772.12344 -+#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_GS	GEN9_3D(3, 1, 0x15)
772.12345 -+#define GEN9_3DSTATE_PUSH_CONSTANT_ALLOC_PS	GEN9_3D(3, 1, 0x16)
772.12346 -+/* DW1 */
772.12347 -+# define PUSH_CONSTANT_BUFFER_OFFSET_SHIFT 16
772.12348 -+# define PUSH_CONSTANT_BUFFER_SIZE_SHIFT 0
772.12349 -+
772.12350 -+#define GEN9_3DSTATE_SO_DECL_LIST		GEN9_3D(3, 1, 0x17)
772.12351 -+#define GEN9_3DSTATE_SO_BUFFER			GEN9_3D(3, 1, 0x18)
772.12352 -+#define GEN9_3DSTATE_BINDING_TABLE_POOL_ALLOC	GEN9_3D(3, 1, 0x19)
772.12353 -+#define GEN9_3DSTATE_GATHER_BUFFER_POOL_ALLOC	GEN9_3D(3, 1, 0x1a)
772.12354 -+#define GEN9_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC	GEN9_3D(3, 1, 0x1b)
772.12355 -+#define GEN9_3DSTATE_SAMPLE_PATTERN		GEN9_3D(3, 1, 0x1c)
772.12356 -+
772.12357 -+
772.12358 -+/* for GEN9_PIPE_CONTROL */
772.12359 -+#define GEN9_PIPE_CONTROL		GEN9_3D(3, 2, 0)
772.12360 -+#define PIPE_CONTROL_CS_STALL      (1 << 20)
772.12361 -+#define PIPE_CONTROL_NOWRITE       (0 << 14)
772.12362 -+#define PIPE_CONTROL_WRITE_QWORD   (1 << 14)
772.12363 -+#define PIPE_CONTROL_WRITE_DEPTH   (2 << 14)
772.12364 -+#define PIPE_CONTROL_WRITE_TIME    (3 << 14)
772.12365 -+#define PIPE_CONTROL_DEPTH_STALL   (1 << 13)
772.12366 -+#define PIPE_CONTROL_WC_FLUSH      (1 << 12)
772.12367 -+#define PIPE_CONTROL_IS_FLUSH      (1 << 11)
772.12368 -+#define PIPE_CONTROL_TC_FLUSH      (1 << 10)
772.12369 -+#define PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
772.12370 -+#define PIPE_CONTROL_FLUSH         (1 << 7)
772.12371 -+#define PIPE_CONTROL_GLOBAL_GTT    (1 << 2)
772.12372 -+#define PIPE_CONTROL_LOCAL_PGTT    (0 << 2)
772.12373 -+#define PIPE_CONTROL_STALL_AT_SCOREBOARD   (1 << 1)
772.12374 -+#define PIPE_CONTROL_DEPTH_CACHE_FLUSH	(1 << 0)
772.12375 -+
772.12376 -+
772.12377 -+#define GEN9_3DPRIMITIVE			GEN9_3D(3, 3, 0)
772.12378 -+
772.12379 -+/* 3DPRIMITIVE bits */
772.12380 -+#define VERTEX_SEQUENTIAL (0 << 15)
772.12381 -+#define VERTEX_RANDOM	  (1 << 15)
772.12382 -+
772.12383 -+#define ANISORATIO_2     0
772.12384 -+#define ANISORATIO_4     1
772.12385 -+#define ANISORATIO_6     2
772.12386 -+#define ANISORATIO_8     3
772.12387 -+#define ANISORATIO_10    4
772.12388 -+#define ANISORATIO_12    5
772.12389 -+#define ANISORATIO_14    6
772.12390 -+#define ANISORATIO_16    7
772.12391 -+
772.12392 -+#define BLENDFACTOR_ONE                 0x1
772.12393 -+#define BLENDFACTOR_SRC_COLOR           0x2
772.12394 -+#define BLENDFACTOR_SRC_ALPHA           0x3
772.12395 -+#define BLENDFACTOR_DST_ALPHA           0x4
772.12396 -+#define BLENDFACTOR_DST_COLOR           0x5
772.12397 -+#define BLENDFACTOR_SRC_ALPHA_SATURATE  0x6
772.12398 -+#define BLENDFACTOR_CONST_COLOR         0x7
772.12399 -+#define BLENDFACTOR_CONST_ALPHA         0x8
772.12400 -+#define BLENDFACTOR_SRC1_COLOR          0x9
772.12401 -+#define BLENDFACTOR_SRC1_ALPHA          0x0A
772.12402 -+#define BLENDFACTOR_ZERO                0x11
772.12403 -+#define BLENDFACTOR_INV_SRC_COLOR       0x12
772.12404 -+#define BLENDFACTOR_INV_SRC_ALPHA       0x13
772.12405 -+#define BLENDFACTOR_INV_DST_ALPHA       0x14
772.12406 -+#define BLENDFACTOR_INV_DST_COLOR       0x15
772.12407 -+#define BLENDFACTOR_INV_CONST_COLOR     0x17
772.12408 -+#define BLENDFACTOR_INV_CONST_ALPHA     0x18
772.12409 -+#define BLENDFACTOR_INV_SRC1_COLOR      0x19
772.12410 -+#define BLENDFACTOR_INV_SRC1_ALPHA      0x1A
772.12411 -+
772.12412 -+#define BLENDFUNCTION_ADD               0
772.12413 -+#define BLENDFUNCTION_SUBTRACT          1
772.12414 -+#define BLENDFUNCTION_REVERSE_SUBTRACT  2
772.12415 -+#define GEN9_BLENDFUNCTION_MIN               3
772.12416 -+#define BLENDFUNCTION_MAX               4
772.12417 -+
772.12418 -+#define ALPHATEST_FORMAT_UNORM8         0
772.12419 -+#define ALPHATEST_FORMAT_FLOAT32        1
772.12420 -+
772.12421 -+#define CHROMAKEY_KILL_ON_ANY_MATCH  0
772.12422 -+#define CHROMAKEY_REPLACE_BLACK      1
772.12423 -+
772.12424 -+#define CLIP_API_OGL     0
772.12425 -+#define CLIP_API_DX      1
772.12426 -+
772.12427 -+#define CLIPMODE_NORMAL              0
772.12428 -+#define CLIPMODE_CLIP_ALL            1
772.12429 -+#define CLIPMODE_CLIP_NON_REJECTED   2
772.12430 -+#define CLIPMODE_REJECT_ALL          3
772.12431 -+#define CLIPMODE_ACCEPT_ALL          4
772.12432 -+
772.12433 -+#define CLIP_NDCSPACE     0
772.12434 -+#define CLIP_SCREENSPACE  1
772.12435 -+
772.12436 -+#define COMPAREFUNCTION_ALWAYS       0
772.12437 -+#define COMPAREFUNCTION_NEVER        1
772.12438 -+#define COMPAREFUNCTION_LESS         2
772.12439 -+#define COMPAREFUNCTION_EQUAL        3
772.12440 -+#define COMPAREFUNCTION_LEQUAL       4
772.12441 -+#define COMPAREFUNCTION_GREATER      5
772.12442 -+#define COMPAREFUNCTION_NOTEQUAL     6
772.12443 -+#define COMPAREFUNCTION_GEQUAL       7
772.12444 -+
772.12445 -+#define COVERAGE_PIXELS_HALF     0
772.12446 -+#define COVERAGE_PIXELS_1        1
772.12447 -+#define COVERAGE_PIXELS_2        2
772.12448 -+#define COVERAGE_PIXELS_4        3
772.12449 -+
772.12450 -+#define DEPTHFORMAT_D32_FLOAT_S8X24_UINT     0
772.12451 -+#define DEPTHFORMAT_D32_FLOAT                1
772.12452 -+#define DEPTHFORMAT_D24_UNORM_S8_UINT        2
772.12453 -+#define DEPTHFORMAT_D16_UNORM                5
772.12454 -+
772.12455 -+#define FLOATING_POINT_IEEE_754        0
772.12456 -+#define FLOATING_POINT_NON_IEEE_754    1
772.12457 -+
772.12458 -+#define INDEX_BYTE     0
772.12459 -+#define INDEX_WORD     1
772.12460 -+#define INDEX_DWORD    2
772.12461 -+
772.12462 -+#define LOGICOPFUNCTION_CLEAR            0
772.12463 -+#define LOGICOPFUNCTION_NOR              1
772.12464 -+#define LOGICOPFUNCTION_AND_INVERTED     2
772.12465 -+#define LOGICOPFUNCTION_COPY_INVERTED    3
772.12466 -+#define LOGICOPFUNCTION_AND_REVERSE      4
772.12467 -+#define LOGICOPFUNCTION_INVERT           5
772.12468 -+#define LOGICOPFUNCTION_XOR              6
772.12469 -+#define LOGICOPFUNCTION_NAND             7
772.12470 -+#define LOGICOPFUNCTION_AND              8
772.12471 -+#define LOGICOPFUNCTION_EQUIV            9
772.12472 -+#define LOGICOPFUNCTION_NOOP             10
772.12473 -+#define LOGICOPFUNCTION_OR_INVERTED      11
772.12474 -+#define LOGICOPFUNCTION_COPY             12
772.12475 -+#define LOGICOPFUNCTION_OR_REVERSE       13
772.12476 -+#define LOGICOPFUNCTION_OR               14
772.12477 -+#define LOGICOPFUNCTION_SET              15
772.12478 -+
772.12479 -+#define MAPFILTER_NEAREST	0x0
772.12480 -+#define MAPFILTER_LINEAR	0x1
772.12481 -+#define MAPFILTER_ANISOTROPIC	0x2
772.12482 -+#define MAPFILTER_FLEXIBLE 	0x3
772.12483 -+#define MAPFILTER_MONO 		0x6
772.12484 -+
772.12485 -+#define MIPFILTER_NONE        0
772.12486 -+#define MIPFILTER_NEAREST     1
772.12487 -+#define MIPFILTER_LINEAR      3
772.12488 -+
772.12489 -+#define POLYGON_FRONT_FACING     0
772.12490 -+#define POLYGON_BACK_FACING      1
772.12491 -+
772.12492 -+#define PREFILTER_ALWAYS     0x0
772.12493 -+#define PREFILTER_NEVER      0x1
772.12494 -+#define PREFILTER_LESS       0x2
772.12495 -+#define PREFILTER_EQUAL      0x3
772.12496 -+#define PREFILTER_LEQUAL     0x4
772.12497 -+#define PREFILTER_GREATER    0x5
772.12498 -+#define PREFILTER_NOTEQUAL   0x6
772.12499 -+#define PREFILTER_GEQUAL     0x7
772.12500 -+
772.12501 -+#define RASTRULE_UPPER_LEFT  0
772.12502 -+#define RASTRULE_UPPER_RIGHT 1
772.12503 -+
772.12504 -+#define STENCILOP_KEEP               0
772.12505 -+#define STENCILOP_ZERO               1
772.12506 -+#define STENCILOP_REPLACE            2
772.12507 -+#define STENCILOP_INCRSAT            3
772.12508 -+#define STENCILOP_DECRSAT            4
772.12509 -+#define STENCILOP_INCR               5
772.12510 -+#define STENCILOP_DECR               6
772.12511 -+#define STENCILOP_INVERT             7
772.12512 -+
772.12513 -+#define SURFACE_MIPMAPLAYOUT_BELOW   0
772.12514 -+#define SURFACE_MIPMAPLAYOUT_RIGHT   1
772.12515 -+
772.12516 -+#define SURFACEFORMAT_R32G32B32A32_FLOAT             0x000
772.12517 -+#define SURFACEFORMAT_R32G32B32A32_SINT              0x001
772.12518 -+#define SURFACEFORMAT_R32G32B32A32_UINT              0x002
772.12519 -+#define SURFACEFORMAT_R32G32B32A32_UNORM             0x003
772.12520 -+#define SURFACEFORMAT_R32G32B32A32_SNORM             0x004
772.12521 -+#define SURFACEFORMAT_R64G64_FLOAT                   0x005
772.12522 -+#define SURFACEFORMAT_R32G32B32X32_FLOAT             0x006
772.12523 -+#define SURFACEFORMAT_R32G32B32A32_SSCALED           0x007
772.12524 -+#define SURFACEFORMAT_R32G32B32A32_USCALED           0x008
772.12525 -+#define SURFACEFORMAT_R32G32B32_FLOAT                0x040
772.12526 -+#define SURFACEFORMAT_R32G32B32_SINT                 0x041
772.12527 -+#define SURFACEFORMAT_R32G32B32_UINT                 0x042
772.12528 -+#define SURFACEFORMAT_R32G32B32_UNORM                0x043
772.12529 -+#define SURFACEFORMAT_R32G32B32_SNORM                0x044
772.12530 -+#define SURFACEFORMAT_R32G32B32_SSCALED              0x045
772.12531 -+#define SURFACEFORMAT_R32G32B32_USCALED              0x046
772.12532 -+#define SURFACEFORMAT_R16G16B16A16_UNORM             0x080
772.12533 -+#define SURFACEFORMAT_R16G16B16A16_SNORM             0x081
772.12534 -+#define SURFACEFORMAT_R16G16B16A16_SINT              0x082
772.12535 -+#define SURFACEFORMAT_R16G16B16A16_UINT              0x083
772.12536 -+#define SURFACEFORMAT_R16G16B16A16_FLOAT             0x084
772.12537 -+#define SURFACEFORMAT_R32G32_FLOAT                   0x085
772.12538 -+#define SURFACEFORMAT_R32G32_SINT                    0x086
772.12539 -+#define SURFACEFORMAT_R32G32_UINT                    0x087
772.12540 -+#define SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS       0x088
772.12541 -+#define SURFACEFORMAT_X32_TYPELESS_G8X24_UINT        0x089
772.12542 -+#define SURFACEFORMAT_L32A32_FLOAT                   0x08A
772.12543 -+#define SURFACEFORMAT_R32G32_UNORM                   0x08B
772.12544 -+#define SURFACEFORMAT_R32G32_SNORM                   0x08C
772.12545 -+#define SURFACEFORMAT_R64_FLOAT                      0x08D
772.12546 -+#define SURFACEFORMAT_R16G16B16X16_UNORM             0x08E
772.12547 -+#define SURFACEFORMAT_R16G16B16X16_FLOAT             0x08F
772.12548 -+#define SURFACEFORMAT_A32X32_FLOAT                   0x090
772.12549 -+#define SURFACEFORMAT_L32X32_FLOAT                   0x091
772.12550 -+#define SURFACEFORMAT_I32X32_FLOAT                   0x092
772.12551 -+#define SURFACEFORMAT_R16G16B16A16_SSCALED           0x093
772.12552 -+#define SURFACEFORMAT_R16G16B16A16_USCALED           0x094
772.12553 -+#define SURFACEFORMAT_R32G32_SSCALED                 0x095
772.12554 -+#define SURFACEFORMAT_R32G32_USCALED                 0x096
772.12555 -+#define SURFACEFORMAT_B8G8R8A8_UNORM                 0x0C0
772.12556 -+#define SURFACEFORMAT_B8G8R8A8_UNORM_SRGB            0x0C1
772.12557 -+#define SURFACEFORMAT_R10G10B10A2_UNORM              0x0C2
772.12558 -+#define SURFACEFORMAT_R10G10B10A2_UNORM_SRGB         0x0C3
772.12559 -+#define SURFACEFORMAT_R10G10B10A2_UINT               0x0C4
772.12560 -+#define SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM       0x0C5
772.12561 -+#define SURFACEFORMAT_R8G8B8A8_UNORM                 0x0C7
772.12562 -+#define SURFACEFORMAT_R8G8B8A8_UNORM_SRGB            0x0C8
772.12563 -+#define SURFACEFORMAT_R8G8B8A8_SNORM                 0x0C9
772.12564 -+#define SURFACEFORMAT_R8G8B8A8_SINT                  0x0CA
772.12565 -+#define SURFACEFORMAT_R8G8B8A8_UINT                  0x0CB
772.12566 -+#define SURFACEFORMAT_R16G16_UNORM                   0x0CC
772.12567 -+#define SURFACEFORMAT_R16G16_SNORM                   0x0CD
772.12568 -+#define SURFACEFORMAT_R16G16_SINT                    0x0CE
772.12569 -+#define SURFACEFORMAT_R16G16_UINT                    0x0CF
772.12570 -+#define SURFACEFORMAT_R16G16_FLOAT                   0x0D0
772.12571 -+#define SURFACEFORMAT_B10G10R10A2_UNORM              0x0D1
772.12572 -+#define SURFACEFORMAT_B10G10R10A2_UNORM_SRGB         0x0D2
772.12573 -+#define SURFACEFORMAT_R11G11B10_FLOAT                0x0D3
772.12574 -+#define SURFACEFORMAT_R32_SINT                       0x0D6
772.12575 -+#define SURFACEFORMAT_R32_UINT                       0x0D7
772.12576 -+#define SURFACEFORMAT_R32_FLOAT                      0x0D8
772.12577 -+#define SURFACEFORMAT_R24_UNORM_X8_TYPELESS          0x0D9
772.12578 -+#define SURFACEFORMAT_X24_TYPELESS_G8_UINT           0x0DA
772.12579 -+#define SURFACEFORMAT_L16A16_UNORM                   0x0DF
772.12580 -+#define SURFACEFORMAT_I24X8_UNORM                    0x0E0
772.12581 -+#define SURFACEFORMAT_L24X8_UNORM                    0x0E1
772.12582 -+#define SURFACEFORMAT_A24X8_UNORM                    0x0E2
772.12583 -+#define SURFACEFORMAT_I32_FLOAT                      0x0E3
772.12584 -+#define SURFACEFORMAT_L32_FLOAT                      0x0E4
772.12585 -+#define SURFACEFORMAT_A32_FLOAT                      0x0E5
772.12586 -+#define SURFACEFORMAT_B8G8R8X8_UNORM                 0x0E9
772.12587 -+#define SURFACEFORMAT_B8G8R8X8_UNORM_SRGB            0x0EA
772.12588 -+#define SURFACEFORMAT_R8G8B8X8_UNORM                 0x0EB
772.12589 -+#define SURFACEFORMAT_R8G8B8X8_UNORM_SRGB            0x0EC
772.12590 -+#define SURFACEFORMAT_R9G9B9E5_SHAREDEXP             0x0ED
772.12591 -+#define SURFACEFORMAT_B10G10R10X2_UNORM              0x0EE
772.12592 -+#define SURFACEFORMAT_L16A16_FLOAT                   0x0F0
772.12593 -+#define SURFACEFORMAT_R32_UNORM                      0x0F1
772.12594 -+#define SURFACEFORMAT_R32_SNORM                      0x0F2
772.12595 -+#define SURFACEFORMAT_R10G10B10X2_USCALED            0x0F3
772.12596 -+#define SURFACEFORMAT_R8G8B8A8_SSCALED               0x0F4
772.12597 -+#define SURFACEFORMAT_R8G8B8A8_USCALED               0x0F5
772.12598 -+#define SURFACEFORMAT_R16G16_SSCALED                 0x0F6
772.12599 -+#define SURFACEFORMAT_R16G16_USCALED                 0x0F7
772.12600 -+#define SURFACEFORMAT_R32_SSCALED                    0x0F8
772.12601 -+#define SURFACEFORMAT_R32_USCALED                    0x0F9
772.12602 -+#define SURFACEFORMAT_B5G6R5_UNORM                   0x100
772.12603 -+#define SURFACEFORMAT_B5G6R5_UNORM_SRGB              0x101
772.12604 -+#define SURFACEFORMAT_B5G5R5A1_UNORM                 0x102
772.12605 -+#define SURFACEFORMAT_B5G5R5A1_UNORM_SRGB            0x103
772.12606 -+#define SURFACEFORMAT_B4G4R4A4_UNORM                 0x104
772.12607 -+#define SURFACEFORMAT_B4G4R4A4_UNORM_SRGB            0x105
772.12608 -+#define SURFACEFORMAT_R8G8_UNORM                     0x106
772.12609 -+#define SURFACEFORMAT_R8G8_SNORM                     0x107
772.12610 -+#define SURFACEFORMAT_R8G8_SINT                      0x108
772.12611 -+#define SURFACEFORMAT_R8G8_UINT                      0x109
772.12612 -+#define SURFACEFORMAT_R16_UNORM                      0x10A
772.12613 -+#define SURFACEFORMAT_R16_SNORM                      0x10B
772.12614 -+#define SURFACEFORMAT_R16_SINT                       0x10C
772.12615 -+#define SURFACEFORMAT_R16_UINT                       0x10D
772.12616 -+#define SURFACEFORMAT_R16_FLOAT                      0x10E
772.12617 -+#define SURFACEFORMAT_I16_UNORM                      0x111
772.12618 -+#define SURFACEFORMAT_L16_UNORM                      0x112
772.12619 -+#define SURFACEFORMAT_A16_UNORM                      0x113
772.12620 -+#define SURFACEFORMAT_L8A8_UNORM                     0x114
772.12621 -+#define SURFACEFORMAT_I16_FLOAT                      0x115
772.12622 -+#define SURFACEFORMAT_L16_FLOAT                      0x116
772.12623 -+#define SURFACEFORMAT_A16_FLOAT                      0x117
772.12624 -+#define SURFACEFORMAT_R5G5_SNORM_B6_UNORM            0x119
772.12625 -+#define SURFACEFORMAT_B5G5R5X1_UNORM                 0x11A
772.12626 -+#define SURFACEFORMAT_B5G5R5X1_UNORM_SRGB            0x11B
772.12627 -+#define SURFACEFORMAT_R8G8_SSCALED                   0x11C
772.12628 -+#define SURFACEFORMAT_R8G8_USCALED                   0x11D
772.12629 -+#define SURFACEFORMAT_R16_SSCALED                    0x11E
772.12630 -+#define SURFACEFORMAT_R16_USCALED                    0x11F
772.12631 -+#define SURFACEFORMAT_R8_UNORM                       0x140
772.12632 -+#define SURFACEFORMAT_R8_SNORM                       0x141
772.12633 -+#define SURFACEFORMAT_R8_SINT                        0x142
772.12634 -+#define SURFACEFORMAT_R8_UINT                        0x143
772.12635 -+#define SURFACEFORMAT_A8_UNORM                       0x144
772.12636 -+#define SURFACEFORMAT_I8_UNORM                       0x145
772.12637 -+#define SURFACEFORMAT_L8_UNORM                       0x146
772.12638 -+#define SURFACEFORMAT_P4A4_UNORM                     0x147
772.12639 -+#define SURFACEFORMAT_A4P4_UNORM                     0x148
772.12640 -+#define SURFACEFORMAT_R8_SSCALED                     0x149
772.12641 -+#define SURFACEFORMAT_R8_USCALED                     0x14A
772.12642 -+#define SURFACEFORMAT_R1_UINT                        0x181
772.12643 -+#define SURFACEFORMAT_YCRCB_NORMAL                   0x182
772.12644 -+#define SURFACEFORMAT_YCRCB_SWAPUVY                  0x183
772.12645 -+#define SURFACEFORMAT_BC1_UNORM                      0x186
772.12646 -+#define SURFACEFORMAT_BC2_UNORM                      0x187
772.12647 -+#define SURFACEFORMAT_BC3_UNORM                      0x188
772.12648 -+#define SURFACEFORMAT_BC4_UNORM                      0x189
772.12649 -+#define SURFACEFORMAT_BC5_UNORM                      0x18A
772.12650 -+#define SURFACEFORMAT_BC1_UNORM_SRGB                 0x18B
772.12651 -+#define SURFACEFORMAT_BC2_UNORM_SRGB                 0x18C
772.12652 -+#define SURFACEFORMAT_BC3_UNORM_SRGB                 0x18D
772.12653 -+#define SURFACEFORMAT_MONO8                          0x18E
772.12654 -+#define SURFACEFORMAT_YCRCB_SWAPUV                   0x18F
772.12655 -+#define SURFACEFORMAT_YCRCB_SWAPY                    0x190
772.12656 -+#define SURFACEFORMAT_DXT1_RGB                       0x191
772.12657 -+#define SURFACEFORMAT_FXT1                           0x192
772.12658 -+#define SURFACEFORMAT_R8G8B8_UNORM                   0x193
772.12659 -+#define SURFACEFORMAT_R8G8B8_SNORM                   0x194
772.12660 -+#define SURFACEFORMAT_R8G8B8_SSCALED                 0x195
772.12661 -+#define SURFACEFORMAT_R8G8B8_USCALED                 0x196
772.12662 -+#define SURFACEFORMAT_R64G64B64A64_FLOAT             0x197
772.12663 -+#define SURFACEFORMAT_R64G64B64_FLOAT                0x198
772.12664 -+#define SURFACEFORMAT_BC4_SNORM                      0x199
772.12665 -+#define SURFACEFORMAT_BC5_SNORM                      0x19A
772.12666 -+#define SURFACEFORMAT_R16G16B16_UNORM                0x19C
772.12667 -+#define SURFACEFORMAT_R16G16B16_SNORM                0x19D
772.12668 -+#define SURFACEFORMAT_R16G16B16_SSCALED              0x19E
772.12669 -+#define SURFACEFORMAT_R16G16B16_USCALED              0x19F
772.12670 -+
772.12671 -+#define SURFACE_1D      0
772.12672 -+#define SURFACE_2D      1
772.12673 -+#define SURFACE_3D      2
772.12674 -+#define SURFACE_CUBE    3
772.12675 -+#define SURFACE_BUFFER  4
772.12676 -+#define SURFACE_NULL    7
772.12677 -+
772.12678 -+#define TEXCOORDMODE_WRAP            0
772.12679 -+#define TEXCOORDMODE_MIRROR          1
772.12680 -+#define TEXCOORDMODE_CLAMP           2
772.12681 -+#define TEXCOORDMODE_CUBE            3
772.12682 -+#define TEXCOORDMODE_CLAMP_BORDER    4
772.12683 -+#define TEXCOORDMODE_MIRROR_ONCE     5
772.12684 -+
772.12685 -+#define THREAD_PRIORITY_NORMAL   0
772.12686 -+#define THREAD_PRIORITY_HIGH     1
772.12687 -+
772.12688 -+#define VERTEX_SUBPIXEL_PRECISION_8BITS  0
772.12689 -+#define VERTEX_SUBPIXEL_PRECISION_4BITS  1
772.12690 -+
772.12691 -+#define COMPONENT_NOSTORE      0
772.12692 -+#define COMPONENT_STORE_SRC    1
772.12693 -+#define COMPONENT_STORE_0      2
772.12694 -+#define COMPONENT_STORE_1_FLT  3
772.12695 -+#define COMPONENT_STORE_1_INT  4
772.12696 -+#define COMPONENT_STORE_VID    5
772.12697 -+#define COMPONENT_STORE_IID    6
772.12698 -+#define COMPONENT_STORE_PID    7
772.12699 -+
772.12700 -+/* Execution Unit (EU) defines
772.12701 -+ */
772.12702 -+
772.12703 -+#define GEN9_ALIGN_1   0
772.12704 -+#define GEN9_ALIGN_16  1
772.12705 -+
772.12706 -+#define GEN9_ADDRESS_DIRECT                        0
772.12707 -+#define GEN9_ADDRESS_REGISTER_INDIRECT_REGISTER    1
772.12708 -+
772.12709 -+#define GEN9_CHANNEL_X     0
772.12710 -+#define GEN9_CHANNEL_Y     1
772.12711 -+#define GEN9_CHANNEL_Z     2
772.12712 -+#define GEN9_CHANNEL_W     3
772.12713 -+
772.12714 -+#define GEN9_COMPRESSION_NONE          0
772.12715 -+#define GEN9_COMPRESSION_2NDHALF       1
772.12716 -+#define GEN9_COMPRESSION_COMPRESSED    2
772.12717 -+
772.12718 -+#define GEN9_CONDITIONAL_NONE  0
772.12719 -+#define GEN9_CONDITIONAL_Z     1
772.12720 -+#define GEN9_CONDITIONAL_NZ    2
772.12721 -+#define GEN9_CONDITIONAL_EQ    1	/* Z */
772.12722 -+#define GEN9_CONDITIONAL_NEQ   2	/* NZ */
772.12723 -+#define GEN9_CONDITIONAL_G     3
772.12724 -+#define GEN9_CONDITIONAL_GE    4
772.12725 -+#define GEN9_CONDITIONAL_L     5
772.12726 -+#define GEN9_CONDITIONAL_LE    6
772.12727 -+#define GEN9_CONDITIONAL_C     7
772.12728 -+#define GEN9_CONDITIONAL_O     8
772.12729 -+
772.12730 -+#define GEN9_DEBUG_NONE        0
772.12731 -+#define GEN9_DEBUG_BREAKPOINT  1
772.12732 -+
772.12733 -+#define GEN9_DEPENDENCY_NORMAL         0
772.12734 -+#define GEN9_DEPENDENCY_NOTCLEARED     1
772.12735 -+#define GEN9_DEPENDENCY_NOTCHECKED     2
772.12736 -+#define GEN9_DEPENDENCY_DISABLE        3
772.12737 -+
772.12738 -+#define GEN9_EXECUTE_1     0
772.12739 -+#define GEN9_EXECUTE_2     1
772.12740 -+#define GEN9_EXECUTE_4     2
772.12741 -+#define GEN9_EXECUTE_8     3
772.12742 -+#define GEN9_EXECUTE_16    4
772.12743 -+#define GEN9_EXECUTE_32    5
772.12744 -+
772.12745 -+#define GEN9_HORIZONTAL_STRIDE_0   0
772.12746 -+#define GEN9_HORIZONTAL_STRIDE_1   1
772.12747 -+#define GEN9_HORIZONTAL_STRIDE_2   2
772.12748 -+#define GEN9_HORIZONTAL_STRIDE_4   3
772.12749 -+
772.12750 -+#define GEN9_INSTRUCTION_NORMAL    0
772.12751 -+#define GEN9_INSTRUCTION_SATURATE  1
772.12752 -+
772.12753 -+#define GEN9_OPCODE_MOV        1
772.12754 -+#define GEN9_OPCODE_SEL        2
772.12755 -+#define GEN9_OPCODE_NOT        4
772.12756 -+#define GEN9_OPCODE_AND        5
772.12757 -+#define GEN9_OPCODE_OR         6
772.12758 -+#define GEN9_OPCODE_XOR        7
772.12759 -+#define GEN9_OPCODE_SHR        8
772.12760 -+#define GEN9_OPCODE_SHL        9
772.12761 -+#define GEN9_OPCODE_RSR        10
772.12762 -+#define GEN9_OPCODE_RSL        11
772.12763 -+#define GEN9_OPCODE_ASR        12
772.12764 -+#define GEN9_OPCODE_CMP        16
772.12765 -+#define GEN9_OPCODE_JMPI       32
772.12766 -+#define GEN9_OPCODE_IF         34
772.12767 -+#define GEN9_OPCODE_IFF        35
772.12768 -+#define GEN9_OPCODE_ELSE       36
772.12769 -+#define GEN9_OPCODE_ENDIF      37
772.12770 -+#define GEN9_OPCODE_DO         38
772.12771 -+#define GEN9_OPCODE_WHILE      39
772.12772 -+#define GEN9_OPCODE_BREAK      40
772.12773 -+#define GEN9_OPCODE_CONTINUE   41
772.12774 -+#define GEN9_OPCODE_HALT       42
772.12775 -+#define GEN9_OPCODE_MSAVE      44
772.12776 -+#define GEN9_OPCODE_MRESTORE   45
772.12777 -+#define GEN9_OPCODE_PUSH       46
772.12778 -+#define GEN9_OPCODE_POP        47
772.12779 -+#define GEN9_OPCODE_WAIT       48
772.12780 -+#define GEN9_OPCODE_SEND       49
772.12781 -+#define GEN9_OPCODE_ADD        64
772.12782 -+#define GEN9_OPCODE_MUL        65
772.12783 -+#define GEN9_OPCODE_AVG        66
772.12784 -+#define GEN9_OPCODE_FRC        67
772.12785 -+#define GEN9_OPCODE_RNDU       68
772.12786 -+#define GEN9_OPCODE_RNDD       69
772.12787 -+#define GEN9_OPCODE_RNDE       70
772.12788 -+#define GEN9_OPCODE_RNDZ       71
772.12789 -+#define GEN9_OPCODE_MAC        72
772.12790 -+#define GEN9_OPCODE_MACH       73
772.12791 -+#define GEN9_OPCODE_LZD        74
772.12792 -+#define GEN9_OPCODE_SAD2       80
772.12793 -+#define GEN9_OPCODE_SADA2      81
772.12794 -+#define GEN9_OPCODE_DP4        84
772.12795 -+#define GEN9_OPCODE_DPH        85
772.12796 -+#define GEN9_OPCODE_DP3        86
772.12797 -+#define GEN9_OPCODE_DP2        87
772.12798 -+#define GEN9_OPCODE_DPA2       88
772.12799 -+#define GEN9_OPCODE_LINE       89
772.12800 -+#define GEN9_OPCODE_NOP        126
772.12801 -+
772.12802 -+#define GEN9_PREDICATE_NONE             0
772.12803 -+#define GEN9_PREDICATE_NORMAL           1
772.12804 -+#define GEN9_PREDICATE_ALIGN1_ANYV             2
772.12805 -+#define GEN9_PREDICATE_ALIGN1_ALLV             3
772.12806 -+#define GEN9_PREDICATE_ALIGN1_ANY2H            4
772.12807 -+#define GEN9_PREDICATE_ALIGN1_ALL2H            5
772.12808 -+#define GEN9_PREDICATE_ALIGN1_ANY4H            6
772.12809 -+#define GEN9_PREDICATE_ALIGN1_ALL4H            7
772.12810 -+#define GEN9_PREDICATE_ALIGN1_ANY8H            8
772.12811 -+#define GEN9_PREDICATE_ALIGN1_ALL8H            9
772.12812 -+#define GEN9_PREDICATE_ALIGN1_ANY16H           10
772.12813 -+#define GEN9_PREDICATE_ALIGN1_ALL16H           11
772.12814 -+#define GEN9_PREDICATE_ALIGN16_REPLICATE_X     2
772.12815 -+#define GEN9_PREDICATE_ALIGN16_REPLICATE_Y     3
772.12816 -+#define GEN9_PREDICATE_ALIGN16_REPLICATE_Z     4
772.12817 -+#define GEN9_PREDICATE_ALIGN16_REPLICATE_W     5
772.12818 -+#define GEN9_PREDICATE_ALIGN16_ANY4H           6
772.12819 -+#define GEN9_PREDICATE_ALIGN16_ALL4H           7
772.12820 -+
772.12821 -+#define GEN9_ARCHITECTURE_REGISTER_FILE    0
772.12822 -+#define GEN9_GENERAL_REGISTER_FILE         1
772.12823 -+#define GEN9_MESSAGE_REGISTER_FILE         2
772.12824 -+#define GEN9_IMMEDIATE_VALUE               3
772.12825 -+
772.12826 -+#define GEN9_REGISTER_TYPE_UD  0
772.12827 -+#define GEN9_REGISTER_TYPE_D   1
772.12828 -+#define GEN9_REGISTER_TYPE_UW  2
772.12829 -+#define GEN9_REGISTER_TYPE_W   3
772.12830 -+#define GEN9_REGISTER_TYPE_UB  4
772.12831 -+#define GEN9_REGISTER_TYPE_B   5
772.12832 -+#define GEN9_REGISTER_TYPE_VF  5	/* packed float vector, immediates only? */
772.12833 -+#define GEN9_REGISTER_TYPE_HF  6
772.12834 -+#define GEN9_REGISTER_TYPE_V   6	/* packed int vector, immediates only, uword dest only */
772.12835 -+#define GEN9_REGISTER_TYPE_F   7
772.12836 -+
772.12837 -+#define GEN9_ARF_NULL                  0x00
772.12838 -+#define GEN9_ARF_ADDRESS               0x10
772.12839 -+#define GEN9_ARF_ACCUMULATOR           0x20
772.12840 -+#define GEN9_ARF_FLAG                  0x30
772.12841 -+#define GEN9_ARF_MASK                  0x40
772.12842 -+#define GEN9_ARF_MASK_STACK            0x50
772.12843 -+#define GEN9_ARF_MASK_STACK_DEPTH      0x60
772.12844 -+#define GEN9_ARF_STATE                 0x70
772.12845 -+#define GEN9_ARF_CONTROL               0x80
772.12846 -+#define GEN9_ARF_NOTIFICATION_COUNT    0x90
772.12847 -+#define GEN9_ARF_IP                    0xA0
772.12848 -+
772.12849 -+#define GEN9_AMASK   0
772.12850 -+#define GEN9_IMASK   1
772.12851 -+#define GEN9_LMASK   2
772.12852 -+#define GEN9_CMASK   3
772.12853 -+
772.12854 -+#define GEN9_THREAD_NORMAL     0
772.12855 -+#define GEN9_THREAD_ATOMIC     1
772.12856 -+#define GEN9_THREAD_SWITCH     2
772.12857 -+
772.12858 -+#define GEN9_VERTICAL_STRIDE_0                 0
772.12859 -+#define GEN9_VERTICAL_STRIDE_1                 1
772.12860 -+#define GEN9_VERTICAL_STRIDE_2                 2
772.12861 -+#define GEN9_VERTICAL_STRIDE_4                 3
772.12862 -+#define GEN9_VERTICAL_STRIDE_8                 4
772.12863 -+#define GEN9_VERTICAL_STRIDE_16                5
772.12864 -+#define GEN9_VERTICAL_STRIDE_32                6
772.12865 -+#define GEN9_VERTICAL_STRIDE_64                7
772.12866 -+#define GEN9_VERTICAL_STRIDE_128               8
772.12867 -+#define GEN9_VERTICAL_STRIDE_256               9
772.12868 -+#define GEN9_VERTICAL_STRIDE_ONE_DIMENSIONAL   0xF
772.12869 -+
772.12870 -+#define GEN9_WIDTH_1       0
772.12871 -+#define GEN9_WIDTH_2       1
772.12872 -+#define GEN9_WIDTH_4       2
772.12873 -+#define GEN9_WIDTH_8       3
772.12874 -+#define GEN9_WIDTH_16      4
772.12875 -+
772.12876 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_1K      0
772.12877 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_2K      1
772.12878 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_4K      2
772.12879 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_8K      3
772.12880 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_16K     4
772.12881 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_32K     5
772.12882 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_64K     6
772.12883 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_128K    7
772.12884 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_256K    8
772.12885 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_512K    9
772.12886 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_1M      10
772.12887 -+#define GEN9_STATELESS_BUFFER_BOUNDARY_2M      11
772.12888 -+
772.12889 -+#define GEN9_POLYGON_FACING_FRONT      0
772.12890 -+#define GEN9_POLYGON_FACING_BACK       1
772.12891 -+
772.12892 -+#define GEN9_MESSAGE_TARGET_NULL               0
772.12893 -+#define GEN9_MESSAGE_TARGET_MATH               1
772.12894 -+#define GEN9_MESSAGE_TARGET_SAMPLER            2
772.12895 -+#define GEN9_MESSAGE_TARGET_GATEWAY            3
772.12896 -+#define GEN9_MESSAGE_TARGET_DATAPORT_READ      4
772.12897 -+#define GEN9_MESSAGE_TARGET_DATAPORT_WRITE     5
772.12898 -+#define GEN9_MESSAGE_TARGET_URB                6
772.12899 -+#define GEN9_MESSAGE_TARGET_THREAD_SPAWNER     7
772.12900 -+
772.12901 -+#define GEN9_SAMPLER_RETURN_FORMAT_FLOAT32     0
772.12902 -+#define GEN9_SAMPLER_RETURN_FORMAT_UINT32      2
772.12903 -+#define GEN9_SAMPLER_RETURN_FORMAT_SINT32      3
772.12904 -+
772.12905 -+#define GEN9_SAMPLER_MESSAGE_SIMD8_SAMPLE              0
772.12906 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE             0
772.12907 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS        0
772.12908 -+#define GEN9_SAMPLER_MESSAGE_SIMD8_KILLPIX             1
772.12909 -+#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD        1
772.12910 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD         1
772.12911 -+#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS  2
772.12912 -+#define GEN9_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS    2
772.12913 -+#define GEN9_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE    0
772.12914 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE     2
772.12915 -+#define GEN9_SAMPLER_MESSAGE_SIMD4X2_RESINFO           2
772.12916 -+#define GEN9_SAMPLER_MESSAGE_SIMD8_RESINFO             2
772.12917 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_RESINFO            2
772.12918 -+#define GEN9_SAMPLER_MESSAGE_SIMD4X2_LD                3
772.12919 -+#define GEN9_SAMPLER_MESSAGE_SIMD8_LD                  3
772.12920 -+#define GEN9_SAMPLER_MESSAGE_SIMD16_LD                 3
772.12921 -+
772.12922 -+#define GEN9_DATAPORT_OWORD_BLOCK_1_OWORDLOW   0
772.12923 -+#define GEN9_DATAPORT_OWORD_BLOCK_1_OWORDHIGH  1
772.12924 -+#define GEN9_DATAPORT_OWORD_BLOCK_2_OWORDS     2
772.12925 -+#define GEN9_DATAPORT_OWORD_BLOCK_4_OWORDS     3
772.12926 -+#define GEN9_DATAPORT_OWORD_BLOCK_8_OWORDS     4
772.12927 -+
772.12928 -+#define GEN9_DATAPORT_OWORD_DUAL_BLOCK_1OWORD     0
772.12929 -+#define GEN9_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS    2
772.12930 -+
772.12931 -+#define GEN9_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS   2
772.12932 -+#define GEN9_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS  3
772.12933 -+
772.12934 -+#define GEN9_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ          0
772.12935 -+#define GEN9_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ     1
772.12936 -+#define GEN9_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ          2
772.12937 -+#define GEN9_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ      3
772.12938 -+
772.12939 -+#define GEN9_DATAPORT_READ_TARGET_DATA_CACHE      0
772.12940 -+#define GEN9_DATAPORT_READ_TARGET_RENDER_CACHE    1
772.12941 -+#define GEN9_DATAPORT_READ_TARGET_SAMPLER_CACHE   2
772.12942 -+
772.12943 -+#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE                0
772.12944 -+#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED     1
772.12945 -+#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01         2
772.12946 -+#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23         3
772.12947 -+#define GEN9_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01       4
772.12948 -+
772.12949 -+#define GEN9_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE                0
772.12950 -+#define GEN9_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE           1
772.12951 -+#define GEN9_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE                2
772.12952 -+#define GEN9_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE            3
772.12953 -+#define GEN9_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE              4
772.12954 -+#define GEN9_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE     5
772.12955 -+#define GEN9_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE               7
772.12956 -+
772.12957 -+#define GEN9_MATH_FUNCTION_INV                              1
772.12958 -+#define GEN9_MATH_FUNCTION_LOG                              2
772.12959 -+#define GEN9_MATH_FUNCTION_EXP                              3
772.12960 -+#define GEN9_MATH_FUNCTION_SQRT                             4
772.12961 -+#define GEN9_MATH_FUNCTION_RSQ                              5
772.12962 -+#define GEN9_MATH_FUNCTION_SIN                              6 /* was 7 */
772.12963 -+#define GEN9_MATH_FUNCTION_COS                              7 /* was 8 */
772.12964 -+#define GEN9_MATH_FUNCTION_SINCOS                           8 /* was 6 */
772.12965 -+#define GEN9_MATH_FUNCTION_TAN                              9
772.12966 -+#define GEN9_MATH_FUNCTION_POW                              10
772.12967 -+#define GEN9_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER   11
772.12968 -+#define GEN9_MATH_FUNCTION_INT_DIV_QUOTIENT                 12
772.12969 -+#define GEN9_MATH_FUNCTION_INT_DIV_REMAINDER                13
772.12970 -+
772.12971 -+#define GEN9_MATH_INTEGER_UNSIGNED     0
772.12972 -+#define GEN9_MATH_INTEGER_SIGNED       1
772.12973 -+
772.12974 -+#define GEN9_MATH_PRECISION_FULL        0
772.12975 -+#define GEN9_MATH_PRECISION_PARTIAL     1
772.12976 -+
772.12977 -+#define GEN9_MATH_SATURATE_NONE         0
772.12978 -+#define GEN9_MATH_SATURATE_SATURATE     1
772.12979 -+
772.12980 -+#define GEN9_MATH_DATA_VECTOR  0
772.12981 -+#define GEN9_MATH_DATA_SCALAR  1
772.12982 -+
772.12983 -+#define GEN9_URB_OPCODE_WRITE  0
772.12984 -+
772.12985 -+#define GEN9_URB_SWIZZLE_NONE          0
772.12986 -+#define GEN9_URB_SWIZZLE_INTERLEAVE    1
772.12987 -+#define GEN9_URB_SWIZZLE_TRANSPOSE     2
772.12988 -+
772.12989 -+#define GEN9_SCRATCH_SPACE_SIZE_1K     0
772.12990 -+#define GEN9_SCRATCH_SPACE_SIZE_2K     1
772.12991 -+#define GEN9_SCRATCH_SPACE_SIZE_4K     2
772.12992 -+#define GEN9_SCRATCH_SPACE_SIZE_8K     3
772.12993 -+#define GEN9_SCRATCH_SPACE_SIZE_16K    4
772.12994 -+#define GEN9_SCRATCH_SPACE_SIZE_32K    5
772.12995 -+#define GEN9_SCRATCH_SPACE_SIZE_64K    6
772.12996 -+#define GEN9_SCRATCH_SPACE_SIZE_128K   7
772.12997 -+#define GEN9_SCRATCH_SPACE_SIZE_256K   8
772.12998 -+#define GEN9_SCRATCH_SPACE_SIZE_512K   9
772.12999 -+#define GEN9_SCRATCH_SPACE_SIZE_1M     10
772.13000 -+#define GEN9_SCRATCH_SPACE_SIZE_2M     11
772.13001 -+
772.13002 -+struct gen9_blend_state {
772.13003 -+	struct {
772.13004 -+		/* 00 */ uint32_t pad:19;
772.13005 -+		/* 19 */ uint32_t y_dither_offset:2;
772.13006 -+		/* 21 */ uint32_t x_dither_offset:2;
772.13007 -+		/* 23 */ uint32_t color_dither_enable:1;
772.13008 -+		/* 24 */ uint32_t alpha_test_function:3;
772.13009 -+		/* 27 */ uint32_t alpha_test:1;
772.13010 -+		/* 28 */ uint32_t alpha_to_coverage_dither:1;
772.13011 -+		/* 29 */ uint32_t alpha_to_one:1;
772.13012 -+		/* 30 */ uint32_t ia_blend:1;
772.13013 -+		/* 31 */ uint32_t alpha_to_coverage:1;
772.13014 -+	} common;
772.13015 -+
772.13016 -+	struct {
772.13017 -+		/* 00 */ uint32_t write_disable_blue:1;
772.13018 -+		/* 01 */ uint32_t write_disable_green:1;
772.13019 -+		/* 02 */ uint32_t write_disable_red:1;
772.13020 -+		/* 03 */ uint32_t write_disable_alpha:1;
772.13021 -+		/* 04 */ uint32_t pad0:1;
772.13022 -+		/* 05 */ uint32_t alpha_blend_function:3;
772.13023 -+		/* 08 */ uint32_t dest_alpha_blend_factor:5;
772.13024 -+		/* 13 */ uint32_t source_alpha_blend_factor:5;
772.13025 -+		/* 18 */ uint32_t color_blend_function:3;
772.13026 -+		/* 21 */ uint32_t dest_blend_factor:5;
772.13027 -+		/* 26 */ uint32_t source_blend_factor:5;
772.13028 -+		/* 31 */ uint32_t color_blend:1;
772.13029 -+		/* 32 */ uint32_t post_blend_clamp:1;
772.13030 -+		/* 33 */ uint32_t pre_blend_clamp:1;
772.13031 -+		/* 34 */ uint32_t color_clamp_range:2;
772.13032 -+		/* 36 */ uint32_t pre_blend_source_only_clamp:1;
772.13033 -+		/* 37 */ uint32_t pad1:22;
772.13034 -+		/* 59 */ uint32_t logic_op_function:4;
772.13035 -+		/* 63 */ uint32_t logic_op:1;
772.13036 -+	} rt;
772.13037 -+};
772.13038 -+
772.13039 -+struct gen9_color_calc_state {
772.13040 -+	struct {
772.13041 -+		/* 00 */ uint32_t alpha_test_format:1;
772.13042 -+		/* 01 */ uint32_t pad0:14;
772.13043 -+		/* 15 */ uint32_t round_disable:1;
772.13044 -+		/* 16 */ uint32_t bf_stencil_ref:8;
772.13045 -+		/* 24 */ uint32_t stencil_ref:8;
772.13046 -+	} cc0;
772.13047 -+
772.13048 -+	union {
772.13049 -+		float alpha_ref_f;
772.13050 -+		struct {
772.13051 -+			uint32_t ui:8;
772.13052 -+			uint32_t pad0:24;
772.13053 -+		} alpha_ref_fi;
772.13054 -+	} cc1;
772.13055 -+
772.13056 -+	float constant_r;
772.13057 -+	float constant_g;
772.13058 -+	float constant_b;
772.13059 -+	float constant_a;
772.13060 -+};
772.13061 -+
772.13062 -+struct gen9_sampler_state {
772.13063 -+	struct {
772.13064 -+		/* 00 */ unsigned int aniso_algorithm:1;
772.13065 -+		/* 01 */ unsigned int lod_bias:13;
772.13066 -+		/* 14 */ unsigned int min_filter:3;
772.13067 -+		/* 17 */ unsigned int mag_filter:3;
772.13068 -+		/* 20 */ unsigned int mip_filter:2;
772.13069 -+		/* 22 */ unsigned int base_level:5;
772.13070 -+		/* 27 */ unsigned int lod_preclamp:2;
772.13071 -+		/* 29 */ unsigned int default_color_mode:1;
772.13072 -+		/* 30 */ unsigned int flexible_filter_clamp:1;
772.13073 -+		/* 31 */ unsigned int disable:1;
772.13074 -+	} ss0;
772.13075 -+
772.13076 -+	struct {
772.13077 -+		/* 00 */ unsigned int cube_control_mode:1;
772.13078 -+		/* 01 */ unsigned int shadow_function:3;
772.13079 -+		/* 04 */ unsigned int chroma_key_mode:1;
772.13080 -+		/* 05 */ unsigned int chroma_key_index:2;
772.13081 -+		/* 07 */ unsigned int chroma_key_enable:1;
772.13082 -+		/* 08 */ unsigned int max_lod:12;
772.13083 -+		/* 20 */ unsigned int min_lod:12;
772.13084 -+	} ss1;
772.13085 -+
772.13086 -+	struct {
772.13087 -+		unsigned int pad:6;
772.13088 -+		unsigned int default_color_pointer:26;
772.13089 -+	} ss2;
772.13090 -+
772.13091 -+	struct {
772.13092 -+		/* 00 */ unsigned int r_wrap_mode:3;
772.13093 -+		/* 03 */ unsigned int t_wrap_mode:3;
772.13094 -+		/* 06 */ unsigned int s_wrap_mode:3;
772.13095 -+		/* 09 */ unsigned int pad:1;
772.13096 -+		/* 10 */ unsigned int non_normalized_coord:1;
772.13097 -+		/* 11 */ unsigned int trilinear_quality:2;
772.13098 -+		/* 13 */ unsigned int address_round:6;
772.13099 -+		/* 19 */ unsigned int max_aniso:3;
772.13100 -+		/* 22 */ unsigned int pad0:2;
772.13101 -+		/* 24 */ unsigned int non_separable_filter:8;
772.13102 -+	} ss3;
772.13103 -+};
772.13104 -+
772.13105 -+/* Surface state DW0 */
772.13106 -+#define SURFACE_RC_READ_WRITE	(1 << 8)
772.13107 -+#define SURFACE_TILED		(1 << 13)
772.13108 -+#define SURFACE_TILED_Y		(1 << 12)
772.13109 -+#define SURFACE_FORMAT_SHIFT	18
772.13110 -+#define SURFACE_VALIGN_1	(0 << 16) /* reserved! */
772.13111 -+#define SURFACE_VALIGN_4	(1 << 16)
772.13112 -+#define SURFACE_VALIGN_8	(2 << 16)
772.13113 -+#define SURFACE_VALIGN_16	(3 << 16)
772.13114 -+#define SURFACE_HALIGN_1	(0 << 14) /* reserved! */
772.13115 -+#define SURFACE_HALIGN_4	(1 << 14)
772.13116 -+#define SURFACE_HALIGN_8	(2 << 14)
772.13117 -+#define SURFACE_HALIGN_16	(3 << 14)
772.13118 -+#define SURFACE_TYPE_SHIFT		29
772.13119 -+
772.13120 -+/* Surface state DW2 */
772.13121 -+#define SURFACE_HEIGHT_SHIFT        16
772.13122 -+#define SURFACE_WIDTH_SHIFT         0
772.13123 -+
772.13124 -+/* Surface state DW3 */
772.13125 -+#define SURFACE_DEPTH_SHIFT         21
772.13126 -+#define SURFACE_PITCH_SHIFT         0
772.13127 -+
772.13128 -+#define SWIZZLE_ZERO		0
772.13129 -+#define SWIZZLE_ONE		1
772.13130 -+#define SWIZZLE_RED		4
772.13131 -+#define SWIZZLE_GREEN		5
772.13132 -+#define SWIZZLE_BLUE		6
772.13133 -+#define SWIZZLE_ALPHA		7
772.13134 -+#define __SURFACE_SWIZZLE(r,g,b,a) \
772.13135 -+	((a) << 16 | (b) << 19 | (g) << 22 | (r) << 25)
772.13136 -+#define SURFACE_SWIZZLE(r,g,b,a) \
772.13137 -+	__SURFACE_SWIZZLE(SWIZZLE_##r, SWIZZLE_##g, SWIZZLE_##b, SWIZZLE_##a)
772.13138 -+
772.13139 -+typedef enum {
772.13140 -+	SAMPLER_FILTER_NEAREST = 0,
772.13141 -+	SAMPLER_FILTER_BILINEAR,
772.13142 -+	FILTER_COUNT
772.13143 -+} sampler_filter_t;
772.13144 -+
772.13145 -+typedef enum {
772.13146 -+	SAMPLER_EXTEND_NONE = 0,
772.13147 -+	SAMPLER_EXTEND_REPEAT,
772.13148 -+	SAMPLER_EXTEND_PAD,
772.13149 -+	SAMPLER_EXTEND_REFLECT,
772.13150 -+	EXTEND_COUNT
772.13151 -+} sampler_extend_t;
772.13152 -+
772.13153 -+#endif
772.13154 -diff --git a/src/sna/kgem.c b/src/sna/kgem.c
772.13155 -index 78ed5407..f0d171ac 100644
772.13156 ---- a/src/sna/kgem.c
772.13157 -+++ b/src/sna/kgem.c
772.13158 -@@ -84,6 +84,10 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
772.13159 - #define DBG_NO_HANDLE_LUT 0
772.13160 - #define DBG_NO_WT 0
772.13161 - #define DBG_NO_WC_MMAP 0
772.13162 -+#define DBG_NO_BLT_Y 0
772.13163 -+#define DBG_NO_SCANOUT_Y 0
772.13164 -+#define DBG_NO_DIRTYFB 0
772.13165 -+#define DBG_NO_DETILING 0
772.13166 - #define DBG_DUMP 0
772.13167 - #define DBG_NO_MALLOC_CACHE 0
772.13168 - 
772.13169 -@@ -96,11 +100,6 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
772.13170 - #define SHOW_BATCH_BEFORE 0
772.13171 - #define SHOW_BATCH_AFTER 0
772.13172 - 
772.13173 --#if !USE_WC_MMAP
772.13174 --#undef DBG_NO_WC_MMAP
772.13175 --#define DBG_NO_WC_MMAP 1
772.13176 --#endif
772.13177 --
772.13178 - #if 0
772.13179 - #define ASSERT_IDLE(kgem__, handle__) assert(!__kgem_busy(kgem__, handle__))
772.13180 - #define ASSERT_MAYBE_IDLE(kgem__, handle__, expect__) assert(!(expect__) || !__kgem_busy(kgem__, handle__))
772.13181 -@@ -187,6 +186,15 @@ struct local_i915_gem_caching {
772.13182 - #define LOCAL_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_SET_CACHING, struct local_i915_gem_caching)
772.13183 - #define LOCAL_IOCTL_I915_GEM_GET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_GET_CACHING, struct local_i915_gem_caching)
772.13184 - 
772.13185 -+struct local_i915_gem_mmap {
772.13186 -+	uint32_t handle;
772.13187 -+	uint32_t pad;
772.13188 -+	uint64_t offset;
772.13189 -+	uint64_t size;
772.13190 -+	uint64_t addr_ptr;
772.13191 -+};
772.13192 -+#define LOCAL_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct local_i915_gem_mmap)
772.13193 -+
772.13194 - struct local_i915_gem_mmap2 {
772.13195 - 	uint32_t handle;
772.13196 - 	uint32_t pad;
772.13197 -@@ -216,6 +224,12 @@ static struct kgem_bo *__kgem_freed_bo;
772.13198 - static struct kgem_request *__kgem_freed_request;
772.13199 - static struct drm_i915_gem_exec_object2 _kgem_dummy_exec;
772.13200 - 
772.13201 -+static inline struct sna *__to_sna(struct kgem *kgem)
772.13202 -+{
772.13203 -+	/* minor layering violations */
772.13204 -+	return container_of(kgem, struct sna, kgem);
772.13205 -+}
772.13206 -+
772.13207 - static inline int bytes(struct kgem_bo *bo)
772.13208 - {
772.13209 - 	return __kgem_bo_size(bo);
772.13210 -@@ -224,25 +238,31 @@ static inline int bytes(struct kgem_bo *bo)
772.13211 - #define bucket(B) (B)->size.pages.bucket
772.13212 - #define num_pages(B) (B)->size.pages.count
772.13213 - 
772.13214 --static int do_ioctl(int fd, unsigned long req, void *arg)
772.13215 -+static int __do_ioctl(int fd, unsigned long req, void *arg)
772.13216 - {
772.13217 --	int err;
772.13218 --
772.13219 --restart:
772.13220 --	if (ioctl(fd, req, arg) == 0)
772.13221 --		return 0;
772.13222 -+	do {
772.13223 -+		int err;
772.13224 - 
772.13225 --	err = errno;
772.13226 -+		switch ((err = errno)) {
772.13227 -+		case EAGAIN:
772.13228 -+			sched_yield();
772.13229 -+		case EINTR:
772.13230 -+			break;
772.13231 -+		default:
772.13232 -+			return -err;
772.13233 -+		}
772.13234 - 
772.13235 --	if (err == EINTR)
772.13236 --		goto restart;
772.13237 -+		if (likely(ioctl(fd, req, arg) == 0))
772.13238 -+			return 0;
772.13239 -+	} while (1);
772.13240 -+}
772.13241 - 
772.13242 --	if (err == EAGAIN) {
772.13243 --		sched_yield();
772.13244 --		goto restart;
772.13245 --	}
772.13246 -+inline static int do_ioctl(int fd, unsigned long req, void *arg)
772.13247 -+{
772.13248 -+	if (likely(ioctl(fd, req, arg) == 0))
772.13249 -+		return 0;
772.13250 - 
772.13251 --	return -err;
772.13252 -+	return __do_ioctl(fd, req, arg);
772.13253 - }
772.13254 - 
772.13255 - #ifdef DEBUG_MEMORY
772.13256 -@@ -266,6 +286,9 @@ static void assert_tiling(struct kgem *kgem, struct kgem_bo *bo)
772.13257 - 
772.13258 - 	assert(bo);
772.13259 - 
772.13260 -+	if (!kgem->can_fence && kgem->gen >= 040 && bo->tiling)
772.13261 -+		return; /* lies */
772.13262 -+
772.13263 - 	VG_CLEAR(tiling);
772.13264 - 	tiling.handle = bo->handle;
772.13265 - 	tiling.tiling_mode = bo->tiling;
772.13266 -@@ -273,7 +296,7 @@ static void assert_tiling(struct kgem *kgem, struct kgem_bo *bo)
772.13267 - 	assert(tiling.tiling_mode == bo->tiling);
772.13268 - }
772.13269 - 
772.13270 --static void assert_cacheing(struct kgem *kgem, struct kgem_bo *bo)
772.13271 -+static void assert_caching(struct kgem *kgem, struct kgem_bo *bo)
772.13272 - {
772.13273 - 	struct local_i915_gem_caching arg;
772.13274 - 	int expect = kgem->has_llc ? SNOOPED : UNCACHED;
772.13275 -@@ -294,24 +317,117 @@ static void assert_bo_retired(struct kgem_bo *bo)
772.13276 - 	assert(bo->refcnt);
772.13277 - 	assert(bo->rq == NULL);
772.13278 - 	assert(bo->exec == NULL);
772.13279 -+	assert(!bo->needs_flush);
772.13280 - 	assert(list_is_empty(&bo->request));
772.13281 - }
772.13282 - #else
772.13283 - #define assert_tiling(kgem, bo)
772.13284 --#define assert_cacheing(kgem, bo)
772.13285 -+#define assert_caching(kgem, bo)
772.13286 - #define assert_bo_retired(bo)
772.13287 - #endif
772.13288 - 
772.13289 -+static int __find_debugfs(struct kgem *kgem)
772.13290 -+{
772.13291 -+	int i;
772.13292 -+
772.13293 -+	for (i = 0; i < DRM_MAX_MINOR; i++) {
772.13294 -+		char path[80];
772.13295 -+
772.13296 -+		sprintf(path, "/sys/kernel/debug/dri/%d/i915_wedged", i);
772.13297 -+		if (access(path, R_OK) == 0)
772.13298 -+			return i;
772.13299 -+
772.13300 -+		sprintf(path, "/debug/dri/%d/i915_wedged", i);
772.13301 -+		if (access(path, R_OK) == 0)
772.13302 -+			return i;
772.13303 -+	}
772.13304 -+
772.13305 -+	return -1;
772.13306 -+}
772.13307 -+
772.13308 -+static int kgem_get_minor(struct kgem *kgem)
772.13309 -+{
772.13310 -+	struct stat st;
772.13311 -+
772.13312 -+	if (fstat(kgem->fd, &st))
772.13313 -+		return __find_debugfs(kgem);
772.13314 -+
772.13315 -+	if (!S_ISCHR(st.st_mode))
772.13316 -+		return __find_debugfs(kgem);
772.13317 -+
772.13318 -+	return st.st_rdev & 0x63;
772.13319 -+}
772.13320 -+
772.13321 -+static bool find_hang_state(struct kgem *kgem, char *path, int maxlen)
772.13322 -+{
772.13323 -+	int minor = kgem_get_minor(kgem);
772.13324 -+
772.13325 -+	/* Search for our hang state in a few canonical locations.
772.13326 -+	 * In the unlikely event of having multiple devices, we
772.13327 -+	 * will need to check which minor actually corresponds to ours.
772.13328 -+	 */
772.13329 -+
772.13330 -+	snprintf(path, maxlen, "/sys/class/drm/card%d/error", minor);
772.13331 -+	if (access(path, R_OK) == 0)
772.13332 -+		return true;
772.13333 -+
772.13334 -+	snprintf(path, maxlen, "/sys/kernel/debug/dri/%d/i915_error_state", minor);
772.13335 -+	if (access(path, R_OK) == 0)
772.13336 -+		return true;
772.13337 -+
772.13338 -+	snprintf(path, maxlen, "/debug/dri/%d/i915_error_state", minor);
772.13339 -+	if (access(path, R_OK) == 0)
772.13340 -+		return true;
772.13341 -+
772.13342 -+	path[0] = '\0';
772.13343 -+	return false;
772.13344 -+}
772.13345 -+
772.13346 -+static bool has_error_state(struct kgem *kgem, char *path)
772.13347 -+{
772.13348 -+   bool ret = false;
772.13349 -+   char no;
772.13350 -+   int fd;
772.13351 -+
772.13352 -+   fd = open(path, O_RDONLY);
772.13353 -+   if (fd >= 0) {
772.13354 -+      ret = read(fd, &no, 1) == 1 && no != 'N';
772.13355 -+      close(fd);
772.13356 -+   }
772.13357 -+
772.13358 -+   return ret;
772.13359 -+}
772.13360 -+
772.13361 -+static int kgem_get_screen_index(struct kgem *kgem)
772.13362 -+{
772.13363 -+	return __to_sna(kgem)->scrn->scrnIndex;
772.13364 -+}
772.13365 -+
772.13366 - static void
772.13367 - __kgem_set_wedged(struct kgem *kgem)
772.13368 - {
772.13369 -+	static int once;
772.13370 -+	char path[256];
772.13371 -+
772.13372 -+	if (kgem->wedged)
772.13373 -+		return;
772.13374 -+
772.13375 -+	if (!once &&
772.13376 -+	    find_hang_state(kgem, path, sizeof(path)) &&
772.13377 -+            has_error_state(kgem, path)) {
772.13378 -+		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
772.13379 -+			   "When reporting this, please include %s and the full dmesg.\n",
772.13380 -+			   path);
772.13381 -+		once = 1;
772.13382 -+	}
772.13383 -+
772.13384 - 	kgem->wedged = true;
772.13385 --	sna_render_mark_wedged(container_of(kgem, struct sna, kgem));
772.13386 -+	sna_render_mark_wedged(__to_sna(kgem));
772.13387 - }
772.13388 - 
772.13389 - static void kgem_sna_reset(struct kgem *kgem)
772.13390 - {
772.13391 --	struct sna *sna = container_of(kgem, struct sna, kgem);
772.13392 -+	struct sna *sna = __to_sna(kgem);
772.13393 - 
772.13394 - 	sna->render.reset(sna);
772.13395 - 	sna->blt_state.fill_bo = 0;
772.13396 -@@ -319,7 +435,7 @@ static void kgem_sna_reset(struct kgem *kgem)
772.13397 - 
772.13398 - static void kgem_sna_flush(struct kgem *kgem)
772.13399 - {
772.13400 --	struct sna *sna = container_of(kgem, struct sna, kgem);
772.13401 -+	struct sna *sna = __to_sna(kgem);
772.13402 - 
772.13403 - 	sna->render.flush(sna);
772.13404 - 
772.13405 -@@ -327,22 +443,53 @@ static void kgem_sna_flush(struct kgem *kgem)
772.13406 - 		sna_render_flush_solid(sna);
772.13407 - }
772.13408 - 
772.13409 --static bool gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
772.13410 -+static bool kgem_bo_rmfb(struct kgem *kgem, struct kgem_bo *bo)
772.13411 -+{
772.13412 -+	if (bo->scanout && bo->delta) {
772.13413 -+		DBG(("%s: releasing fb=%d for handle=%d\n",
772.13414 -+		     __FUNCTION__, bo->delta, bo->handle));
772.13415 -+		/* XXX will leak if we are not DRM_MASTER. *shrug* */
772.13416 -+		do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
772.13417 -+		bo->delta = 0;
772.13418 -+		return true;
772.13419 -+	} else
772.13420 -+		return false;
772.13421 -+}
772.13422 -+
772.13423 -+static bool kgem_set_tiling(struct kgem *kgem, struct kgem_bo *bo,
772.13424 -+			    int tiling, int stride)
772.13425 - {
772.13426 - 	struct drm_i915_gem_set_tiling set_tiling;
772.13427 - 	int err;
772.13428 - 
772.13429 -+	if (tiling == bo->tiling) {
772.13430 -+		if (tiling == I915_TILING_NONE) {
772.13431 -+			bo->pitch = stride;
772.13432 -+			return true;
772.13433 -+		}
772.13434 -+		if (stride == bo->pitch)
772.13435 -+			return true;
772.13436 -+	}
772.13437 -+
772.13438 - 	if (DBG_NO_TILING)
772.13439 - 		return false;
772.13440 - 
772.13441 - 	VG_CLEAR(set_tiling);
772.13442 - restart:
772.13443 --	set_tiling.handle = handle;
772.13444 -+	set_tiling.handle = bo->handle;
772.13445 - 	set_tiling.tiling_mode = tiling;
772.13446 --	set_tiling.stride = stride;
772.13447 -+	set_tiling.stride = tiling ? stride : 0;
772.13448 - 
772.13449 --	if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
772.13450 --		return true;
772.13451 -+	if (ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0) {
772.13452 -+		bo->tiling = set_tiling.tiling_mode;
772.13453 -+		bo->pitch = set_tiling.tiling_mode ? set_tiling.stride : stride;
772.13454 -+		DBG(("%s: handle=%d, tiling=%d [%d], pitch=%d [%d]: %d\n",
772.13455 -+		     __FUNCTION__, bo->handle,
772.13456 -+		     bo->tiling, tiling,
772.13457 -+		     bo->pitch, stride,
772.13458 -+		     set_tiling.tiling_mode == tiling));
772.13459 -+		return set_tiling.tiling_mode == tiling;
772.13460 -+	}
772.13461 - 
772.13462 - 	err = errno;
772.13463 - 	if (err == EINTR)
772.13464 -@@ -353,6 +500,11 @@ restart:
772.13465 - 		goto restart;
772.13466 - 	}
772.13467 - 
772.13468 -+	if (err == EBUSY && kgem_bo_rmfb(kgem, bo))
772.13469 -+		goto restart;
772.13470 -+
772.13471 -+	ERR(("%s: failed to set-tiling(tiling=%d, pitch=%d) for handle=%d: %d\n",
772.13472 -+	     __FUNCTION__, tiling, stride, bo->handle, err));
772.13473 - 	return false;
772.13474 - }
772.13475 - 
772.13476 -@@ -437,10 +589,15 @@ static void *__kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo)
772.13477 - 	DBG(("%s(handle=%d, size=%d)\n", __FUNCTION__,
772.13478 - 	     bo->handle, bytes(bo)));
772.13479 - 
772.13480 -+	if (bo->tiling && !kgem->can_fence)
772.13481 -+		return NULL;
772.13482 -+
772.13483 - 	VG_CLEAR(gtt);
772.13484 - retry_gtt:
772.13485 - 	gtt.handle = bo->handle;
772.13486 - 	if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gtt))) {
772.13487 -+		DBG(("%s: failed %d, throttling/cleaning caches\n",
772.13488 -+		     __FUNCTION__, err));
772.13489 - 		assert(err != EINVAL);
772.13490 - 
772.13491 - 		(void)__kgem_throttle_retire(kgem, 0);
772.13492 -@@ -460,6 +617,8 @@ retry_mmap:
772.13493 - 		   kgem->fd, gtt.offset);
772.13494 - 	if (ptr == MAP_FAILED) {
772.13495 - 		err = errno;
772.13496 -+		DBG(("%s: failed %d, throttling/cleaning caches\n",
772.13497 -+		     __FUNCTION__, err));
772.13498 - 		assert(err != EINVAL);
772.13499 - 
772.13500 - 		if (__kgem_throttle_retire(kgem, 0))
772.13501 -@@ -498,6 +657,8 @@ retry_wc:
772.13502 - 	wc.size = bytes(bo);
772.13503 - 	wc.flags = I915_MMAP_WC;
772.13504 - 	if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP_v2, &wc))) {
772.13505 -+		DBG(("%s: failed %d, throttling/cleaning caches\n",
772.13506 -+		     __FUNCTION__, err));
772.13507 - 		assert(err != EINVAL);
772.13508 - 
772.13509 - 		if (__kgem_throttle_retire(kgem, 0))
772.13510 -@@ -519,16 +680,19 @@ retry_wc:
772.13511 - 
772.13512 - static void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
772.13513 - {
772.13514 --	struct drm_i915_gem_mmap mmap_arg;
772.13515 -+	struct local_i915_gem_mmap arg;
772.13516 - 	int err;
772.13517 - 
772.13518 -+	VG_CLEAR(arg);
772.13519 -+	arg.offset = 0;
772.13520 -+
772.13521 - retry:
772.13522 --	VG_CLEAR(mmap_arg);
772.13523 --	mmap_arg.handle = bo->handle;
772.13524 --	mmap_arg.offset = 0;
772.13525 --	mmap_arg.size = bytes(bo);
772.13526 --	if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))) {
772.13527 --		assert(err != EINVAL);
772.13528 -+	arg.handle = bo->handle;
772.13529 -+	arg.size = bytes(bo);
772.13530 -+	if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP, &arg))) {
772.13531 -+		DBG(("%s: failed %d, throttling/cleaning caches\n",
772.13532 -+		     __FUNCTION__, err));
772.13533 -+		assert(err != -EINVAL || bo->prime);
772.13534 - 
772.13535 - 		if (__kgem_throttle_retire(kgem, 0))
772.13536 - 			goto retry;
772.13537 -@@ -536,15 +700,16 @@ retry:
772.13538 - 		if (kgem_cleanup_cache(kgem))
772.13539 - 			goto retry;
772.13540 - 
772.13541 --		ERR(("%s: failed to mmap handle=%d, %d bytes, into CPU domain: %d\n",
772.13542 --		     __FUNCTION__, bo->handle, bytes(bo), -err));
772.13543 -+		ERR(("%s: failed to mmap handle=%d (prime? %d), %d bytes, into CPU domain: %d\n",
772.13544 -+		     __FUNCTION__, bo->handle, bo->prime, bytes(bo), -err));
772.13545 -+		bo->purged = 1;
772.13546 - 		return NULL;
772.13547 - 	}
772.13548 - 
772.13549 --	VG(VALGRIND_MAKE_MEM_DEFINED(mmap_arg.addr_ptr, bytes(bo)));
772.13550 -+	VG(VALGRIND_MAKE_MEM_DEFINED(arg.addr_ptr, bytes(bo)));
772.13551 - 
772.13552 - 	DBG(("%s: caching CPU vma for %d\n", __FUNCTION__, bo->handle));
772.13553 --	return bo->map__cpu = (void *)(uintptr_t)mmap_arg.addr_ptr;
772.13554 -+	return bo->map__cpu = (void *)(uintptr_t)arg.addr_ptr;
772.13555 - }
772.13556 - 
772.13557 - static int gem_write(int fd, uint32_t handle,
772.13558 -@@ -634,16 +799,10 @@ static void kgem_bo_retire(struct kgem *kgem, struct kgem_bo *bo)
772.13559 - 	assert(bo->exec == NULL);
772.13560 - 	assert(list_is_empty(&bo->vma));
772.13561 - 
772.13562 --	if (bo->rq) {
772.13563 --		__kgem_bo_clear_busy(bo);
772.13564 --		kgem_retire(kgem);
772.13565 --		assert_bo_retired(bo);
772.13566 --	} else {
772.13567 --		assert(bo->exec == NULL);
772.13568 --		assert(list_is_empty(&bo->request));
772.13569 --		assert(!bo->needs_flush);
772.13570 --		ASSERT_IDLE(kgem, bo->handle);
772.13571 --	}
772.13572 -+	if (bo->rq)
772.13573 -+		__kgem_retire_requests_upto(kgem, bo);
772.13574 -+	ASSERT_IDLE(kgem, bo->handle);
772.13575 -+	assert_bo_retired(bo);
772.13576 - }
772.13577 - 
772.13578 - static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
772.13579 -@@ -655,10 +814,8 @@ static void kgem_bo_maybe_retire(struct kgem *kgem, struct kgem_bo *bo)
772.13580 - 	assert(list_is_empty(&bo->vma));
772.13581 - 
772.13582 - 	if (bo->rq) {
772.13583 --		if (!__kgem_busy(kgem, bo->handle)) {
772.13584 --			__kgem_bo_clear_busy(bo);
772.13585 --			kgem_retire(kgem);
772.13586 --		}
772.13587 -+		if (!__kgem_busy(kgem, bo->handle))
772.13588 -+			__kgem_retire_requests_upto(kgem, bo);
772.13589 - 	} else {
772.13590 - 		assert(!bo->needs_flush);
772.13591 - 		ASSERT_IDLE(kgem, bo->handle);
772.13592 -@@ -694,6 +851,8 @@ retry:
772.13593 - 	}
772.13594 - 
772.13595 - 	if ((err = gem_write(kgem->fd, bo->handle, 0, length, data))) {
772.13596 -+		DBG(("%s: failed %d, throttling/cleaning caches\n",
772.13597 -+		     __FUNCTION__, err));
772.13598 - 		assert(err != EINVAL);
772.13599 - 
772.13600 - 		(void)__kgem_throttle_retire(kgem, 0);
772.13601 -@@ -728,27 +887,21 @@ static uint32_t gem_create(int fd, int num_pages)
772.13602 - 	return create.handle;
772.13603 - }
772.13604 - 
772.13605 --static bool
772.13606 -+static void
772.13607 - kgem_bo_set_purgeable(struct kgem *kgem, struct kgem_bo *bo)
772.13608 - {
772.13609 --#if DBG_NO_MADV
772.13610 --	return true;
772.13611 --#else
772.13612 -+#if !DBG_NO_MADV
772.13613 - 	struct drm_i915_gem_madvise madv;
772.13614 - 
772.13615 - 	assert(bo->exec == NULL);
772.13616 --	assert(!bo->purged);
772.13617 - 
772.13618 - 	VG_CLEAR(madv);
772.13619 - 	madv.handle = bo->handle;
772.13620 - 	madv.madv = I915_MADV_DONTNEED;
772.13621 - 	if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv) == 0) {
772.13622 --		bo->purged = 1;
772.13623 --		kgem->need_purge |= !madv.retained && bo->domain == DOMAIN_GPU;
772.13624 --		return madv.retained;
772.13625 -+		bo->purged = true;
772.13626 -+		kgem->need_purge |= !madv.retained && bo->domain != DOMAIN_CPU;
772.13627 - 	}
772.13628 --
772.13629 --	return true;
772.13630 - #endif
772.13631 - }
772.13632 - 
772.13633 -@@ -788,7 +941,7 @@ kgem_bo_clear_purgeable(struct kgem *kgem, struct kgem_bo *bo)
772.13634 - 	madv.madv = I915_MADV_WILLNEED;
772.13635 - 	if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MADVISE, &madv) == 0) {
772.13636 - 		bo->purged = !madv.retained;
772.13637 --		kgem->need_purge |= !madv.retained && bo->domain == DOMAIN_GPU;
772.13638 -+		kgem->need_purge |= !madv.retained && bo->domain != DOMAIN_CPU;
772.13639 - 		return madv.retained;
772.13640 - 	}
772.13641 - 
772.13642 -@@ -869,13 +1022,17 @@ static struct kgem_request *__kgem_request_alloc(struct kgem *kgem)
772.13643 - {
772.13644 - 	struct kgem_request *rq;
772.13645 - 
772.13646 --	rq = __kgem_freed_request;
772.13647 --	if (rq) {
772.13648 --		__kgem_freed_request = *(struct kgem_request **)rq;
772.13649 -+	if (unlikely(kgem->wedged)) {
772.13650 -+		rq = &kgem->static_request;
772.13651 - 	} else {
772.13652 --		rq = malloc(sizeof(*rq));
772.13653 --		if (rq == NULL)
772.13654 --			rq = &kgem->static_request;
772.13655 -+		rq = __kgem_freed_request;
772.13656 -+		if (rq) {
772.13657 -+			__kgem_freed_request = *(struct kgem_request **)rq;
772.13658 -+		} else {
772.13659 -+			rq = malloc(sizeof(*rq));
772.13660 -+			if (rq == NULL)
772.13661 -+				rq = &kgem->static_request;
772.13662 -+		}
772.13663 - 	}
772.13664 - 
772.13665 - 	list_init(&rq->buffers);
772.13666 -@@ -925,11 +1082,11 @@ total_ram_size(void)
772.13667 - #ifdef HAVE_STRUCT_SYSINFO_TOTALRAM
772.13668 - 	struct sysinfo info;
772.13669 - 	if (sysinfo(&info) == 0)
772.13670 --		return info.totalram * info.mem_unit;
772.13671 -+		return (size_t)info.totalram * info.mem_unit;
772.13672 - #endif
772.13673 - 
772.13674 - #ifdef _SC_PHYS_PAGES
772.13675 --	 return sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
772.13676 -+	 return (size_t)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGE_SIZE);
772.13677 - #endif
772.13678 - 
772.13679 - 	return 0;
772.13680 -@@ -1150,6 +1307,10 @@ static bool test_has_wc_mmap(struct kgem *kgem)
772.13681 - 	if (DBG_NO_WC_MMAP)
772.13682 - 		return false;
772.13683 - 
772.13684 -+	/* XXX See https://bugs.freedesktop.org/show_bug.cgi?id=90841 */
772.13685 -+	if (kgem->gen < 033)
772.13686 -+		return false;
772.13687 -+
772.13688 - 	if (gem_param(kgem, LOCAL_I915_PARAM_MMAP_VERSION) < 1)
772.13689 - 		return false;
772.13690 - 
772.13691 -@@ -1187,7 +1348,7 @@ static bool test_has_caching(struct kgem *kgem)
772.13692 - 
772.13693 - static bool test_has_userptr(struct kgem *kgem)
772.13694 - {
772.13695 --	uint32_t handle;
772.13696 -+	struct local_i915_gem_userptr arg;
772.13697 - 	void *ptr;
772.13698 - 
772.13699 - 	if (DBG_NO_USERPTR)
772.13700 -@@ -1200,11 +1361,23 @@ static bool test_has_userptr(struct kgem *kgem)
772.13701 - 	if (posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE))
772.13702 - 		return false;
772.13703 - 
772.13704 --	handle = gem_userptr(kgem->fd, ptr, PAGE_SIZE, false);
772.13705 --	gem_close(kgem->fd, handle);
772.13706 --	free(ptr);
772.13707 -+	VG_CLEAR(arg);
772.13708 -+	arg.user_ptr = (uintptr_t)ptr;
772.13709 -+	arg.user_size = PAGE_SIZE;
772.13710 -+	arg.flags = I915_USERPTR_UNSYNCHRONIZED;
772.13711 - 
772.13712 --	return handle != 0;
772.13713 -+	if (DBG_NO_UNSYNCHRONIZED_USERPTR ||
772.13714 -+	    do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_USERPTR, &arg)) {
772.13715 -+		arg.flags &= ~I915_USERPTR_UNSYNCHRONIZED;
772.13716 -+		if (do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_USERPTR, &arg))
772.13717 -+			arg.handle = 0;
772.13718 -+		/* Leak the userptr bo to keep the mmu_notifier alive */
772.13719 -+	} else {
772.13720 -+		gem_close(kgem->fd, arg.handle);
772.13721 -+		free(ptr);
772.13722 -+	}
772.13723 -+
772.13724 -+	return arg.handle != 0;
772.13725 - }
772.13726 - 
772.13727 - static bool test_has_create2(struct kgem *kgem)
772.13728 -@@ -1227,67 +1400,187 @@ static bool test_has_create2(struct kgem *kgem)
772.13729 - #endif
772.13730 - }
772.13731 - 
772.13732 --static bool test_has_secure_batches(struct kgem *kgem)
772.13733 -+static bool test_can_blt_y(struct kgem *kgem)
772.13734 - {
772.13735 --	if (DBG_NO_SECURE_BATCHES)
772.13736 -+	struct drm_i915_gem_exec_object2 object;
772.13737 -+	uint32_t batch[] = {
772.13738 -+#define MI_LOAD_REGISTER_IMM (0x22<<23 | (3-2))
772.13739 -+#define BCS_SWCTRL 0x22200
772.13740 -+#define BCS_SRC_Y (1 << 0)
772.13741 -+#define BCS_DST_Y (1 << 1)
772.13742 -+		MI_LOAD_REGISTER_IMM,
772.13743 -+		BCS_SWCTRL,
772.13744 -+		(BCS_SRC_Y | BCS_DST_Y) << 16 | (BCS_SRC_Y | BCS_DST_Y),
772.13745 -+
772.13746 -+		MI_LOAD_REGISTER_IMM,
772.13747 -+		BCS_SWCTRL,
772.13748 -+		(BCS_SRC_Y | BCS_DST_Y) << 16,
772.13749 -+
772.13750 -+		MI_BATCH_BUFFER_END,
772.13751 -+		0,
772.13752 -+	};
772.13753 -+	int ret;
772.13754 -+
772.13755 -+	if (DBG_NO_BLT_Y)
772.13756 - 		return false;
772.13757 - 
772.13758 --	return gem_param(kgem, LOCAL_I915_PARAM_HAS_SECURE_BATCHES) > 0;
772.13759 -+	if (kgem->gen < 060)
772.13760 -+		return false;
772.13761 -+
772.13762 -+	memset(&object, 0, sizeof(object));
772.13763 -+	object.handle = gem_create(kgem->fd, 1);
772.13764 -+
772.13765 -+	ret = gem_write(kgem->fd, object.handle, 0, sizeof(batch), batch);
772.13766 -+	if (ret == 0) {
772.13767 -+		struct drm_i915_gem_execbuffer2 execbuf;
772.13768 -+
772.13769 -+		memset(&execbuf, 0, sizeof(execbuf));
772.13770 -+		execbuf.buffers_ptr = (uintptr_t)&object;
772.13771 -+		execbuf.buffer_count = 1;
772.13772 -+		execbuf.flags = KGEM_BLT;
772.13773 -+
772.13774 -+		ret = do_ioctl(kgem->fd,
772.13775 -+			       DRM_IOCTL_I915_GEM_EXECBUFFER2,
772.13776 -+			       &execbuf);
772.13777 -+	}
772.13778 -+	gem_close(kgem->fd, object.handle);
772.13779 -+
772.13780 -+	return ret == 0;
772.13781 - }
772.13782 - 
772.13783 --static bool test_has_pinned_batches(struct kgem *kgem)
772.13784 -+static bool gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
772.13785 - {
772.13786 --	if (DBG_NO_PINNED_BATCHES)
772.13787 -+	struct drm_i915_gem_set_tiling set_tiling;
772.13788 -+
772.13789 -+	if (DBG_NO_TILING)
772.13790 - 		return false;
772.13791 - 
772.13792 --	return gem_param(kgem, LOCAL_I915_PARAM_HAS_PINNED_BATCHES) > 0;
772.13793 -+	VG_CLEAR(set_tiling);
772.13794 -+	set_tiling.handle = handle;
772.13795 -+	set_tiling.tiling_mode = tiling;
772.13796 -+	set_tiling.stride = stride;
772.13797 -+
772.13798 -+	if (ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
772.13799 -+		return set_tiling.tiling_mode == tiling;
772.13800 -+
772.13801 -+	return false;
772.13802 - }
772.13803 - 
772.13804 --static int kgem_get_screen_index(struct kgem *kgem)
772.13805 -+static bool test_can_scanout_y(struct kgem *kgem)
772.13806 - {
772.13807 --	struct sna *sna = container_of(kgem, struct sna, kgem);
772.13808 --	return sna->scrn->scrnIndex;
772.13809 -+	struct drm_mode_fb_cmd arg;
772.13810 -+	bool ret = false;
772.13811 -+
772.13812 -+	if (DBG_NO_SCANOUT_Y)
772.13813 -+		return false;
772.13814 -+
772.13815 -+	VG_CLEAR(arg);
772.13816 -+	arg.width = 32;
772.13817 -+	arg.height = 32;
772.13818 -+	arg.pitch = 4*32;
772.13819 -+	arg.bpp = 32;
772.13820 -+	arg.depth = 24;
772.13821 -+	arg.handle = gem_create(kgem->fd, 1);
772.13822 -+
772.13823 -+	if (gem_set_tiling(kgem->fd, arg.handle, I915_TILING_Y, arg.pitch))
772.13824 -+		ret = do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg) == 0;
772.13825 -+	if (!ret) {
772.13826 -+		struct local_mode_fb_cmd2 {
772.13827 -+			uint32_t fb_id;
772.13828 -+			uint32_t width, height;
772.13829 -+			uint32_t pixel_format;
772.13830 -+			uint32_t flags;
772.13831 -+
772.13832 -+			uint32_t handles[4];
772.13833 -+			uint32_t pitches[4];
772.13834 -+			uint32_t offsets[4];
772.13835 -+			uint64_t modifiers[4];
772.13836 -+		} f;
772.13837 -+#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
772.13838 -+		memset(&f, 0, sizeof(f));
772.13839 -+		f.width = arg.width;
772.13840 -+		f.height = arg.height;
772.13841 -+		f.handles[0] = arg.handle;
772.13842 -+		f.pitches[0] = arg.pitch;
772.13843 -+		f.modifiers[0] = (uint64_t)1 << 56 | 2; /* MOD_Y_TILED */
772.13844 -+		f.pixel_format = 'X' | 'R' << 8 | '2' << 16 | '4' << 24; /* XRGB8888 */
772.13845 -+		f.flags = 1 << 1; /* + modifier */
772.13846 -+		if (drmIoctl(kgem->fd, LOCAL_IOCTL_MODE_ADDFB2, &f) == 0) {
772.13847 -+			ret = true;
772.13848 -+			arg.fb_id = f.fb_id;
772.13849 -+		}
772.13850 -+	}
772.13851 -+	do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &arg.fb_id);
772.13852 -+	gem_close(kgem->fd, arg.handle);
772.13853 -+
772.13854 -+	return ret;
772.13855 - }
772.13856 - 
772.13857 --static int __find_debugfs(struct kgem *kgem)
772.13858 -+static bool test_has_dirtyfb(struct kgem *kgem)
772.13859 - {
772.13860 --	int i;
772.13861 -+	struct drm_mode_fb_cmd create;
772.13862 -+	bool ret = false;
772.13863 - 
772.13864 --	for (i = 0; i < DRM_MAX_MINOR; i++) {
772.13865 --		char path[80];
772.13866 -+	if (DBG_NO_DIRTYFB)
772.13867 -+		return false;
772.13868 - 
772.13869 --		sprintf(path, "/sys/kernel/debug/dri/%d/i915_wedged", i);
772.13870 --		if (access(path, R_OK) == 0)
772.13871 --			return i;
772.13872 -+	VG_CLEAR(create);
772.13873 -+	create.width = 32;
772.13874 -+	create.height = 32;
772.13875 -+	create.pitch = 4*32;
772.13876 -+	create.bpp = 32;
772.13877 -+	create.depth = 32;
772.13878 -+	create.handle = gem_create(kgem->fd, 1);
772.13879 -+	if (create.handle == 0)
772.13880 -+		return false;
772.13881 - 
772.13882 --		sprintf(path, "/debug/dri/%d/i915_wedged", i);
772.13883 --		if (access(path, R_OK) == 0)
772.13884 --			return i;
772.13885 -+	if (drmIoctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &create) == 0) {
772.13886 -+		struct drm_mode_fb_dirty_cmd dirty;
772.13887 -+
772.13888 -+		memset(&dirty, 0, sizeof(dirty));
772.13889 -+		dirty.fb_id = create.fb_id;
772.13890 -+		ret = drmIoctl(kgem->fd,
772.13891 -+			       DRM_IOCTL_MODE_DIRTYFB,
772.13892 -+			       &dirty) == 0;
772.13893 -+
772.13894 -+		/* XXX There may be multiple levels of DIRTYFB, depending on
772.13895 -+		 * whether the kernel thinks tracking dirty regions is
772.13896 -+		 * beneficial vs flagging the whole fb as dirty.
772.13897 -+		 */
772.13898 -+
772.13899 -+		drmIoctl(kgem->fd,
772.13900 -+			 DRM_IOCTL_MODE_RMFB,
772.13901 -+			 &create.fb_id);
772.13902 - 	}
772.13903 -+	gem_close(kgem->fd, create.handle);
772.13904 - 
772.13905 --	return -1;
772.13906 -+	return ret;
772.13907 - }
772.13908 - 
772.13909 --static int kgem_get_minor(struct kgem *kgem)
772.13910 -+static bool test_has_secure_batches(struct kgem *kgem)
772.13911 - {
772.13912 --	struct stat st;
772.13913 -+	if (DBG_NO_SECURE_BATCHES)
772.13914 -+		return false;
772.13915 - 
772.13916 --	if (fstat(kgem->fd, &st))
772.13917 --		return __find_debugfs(kgem);
772.13918 -+	return gem_param(kgem, LOCAL_I915_PARAM_HAS_SECURE_BATCHES) > 0;
772.13919 -+}
772.13920 - 
772.13921 --	if (!S_ISCHR(st.st_mode))
772.13922 --		return __find_debugfs(kgem);
772.13923 -+static bool test_has_pinned_batches(struct kgem *kgem)
772.13924 -+{
772.13925 -+	if (DBG_NO_PINNED_BATCHES)
772.13926 -+		return false;
772.13927 - 
772.13928 --	return st.st_rdev & 0x63;
772.13929 -+	return gem_param(kgem, LOCAL_I915_PARAM_HAS_PINNED_BATCHES) > 0;
772.13930 - }
772.13931 - 
772.13932 - static bool kgem_init_pinned_batches(struct kgem *kgem)
772.13933 - {
772.13934 - 	int count[2] = { 16, 4 };
772.13935 - 	int size[2] = { 1, 4 };
772.13936 -+	int ret = 0;
772.13937 - 	int n, i;
772.13938 - 
772.13939 --	if (kgem->wedged)
772.13940 -+	if (unlikely(kgem->wedged))
772.13941 - 		return true;
772.13942 - 
772.13943 - 	for (n = 0; n < ARRAY_SIZE(count); n++) {
772.13944 -@@ -1311,7 +1604,8 @@ static bool kgem_init_pinned_batches(struct kgem *kgem)
772.13945 - 			}
772.13946 - 
772.13947 - 			pin.alignment = 0;
772.13948 --			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_PIN, &pin)) {
772.13949 -+			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
772.13950 -+			if (ret) {
772.13951 - 				gem_close(kgem->fd, pin.handle);
772.13952 - 				free(bo);
772.13953 - 				goto err;
772.13954 -@@ -1333,6 +1627,16 @@ err:
772.13955 - 		}
772.13956 - 	}
772.13957 - 
772.13958 -+	/* If we fail to pin some memory for 830gm/845g, we need to disable
772.13959 -+	 * acceleration as otherwise the machine will eventually fail. However,
772.13960 -+	 * the kernel started arbitrarily rejecting PIN, so hope for the best
772.13961 -+	 * if the ioctl no longer works.
772.13962 -+	 */
772.13963 -+	if (ret != -ENODEV && kgem->gen == 020)
772.13964 -+		return false;
772.13965 -+
772.13966 -+	kgem->has_pinned_batches = false;
772.13967 -+
772.13968 - 	/* For simplicity populate the lists with a single unpinned bo */
772.13969 - 	for (n = 0; n < ARRAY_SIZE(count); n++) {
772.13970 - 		struct kgem_bo *bo;
772.13971 -@@ -1340,18 +1644,18 @@ err:
772.13972 - 
772.13973 - 		handle = gem_create(kgem->fd, size[n]);
772.13974 - 		if (handle == 0)
772.13975 --			break;
772.13976 -+			return false;
772.13977 - 
772.13978 - 		bo = __kgem_bo_alloc(handle, size[n]);
772.13979 - 		if (bo == NULL) {
772.13980 - 			gem_close(kgem->fd, handle);
772.13981 --			break;
772.13982 -+			return false;
772.13983 - 		}
772.13984 - 
772.13985 - 		debug_alloc__bo(kgem, bo);
772.13986 - 		list_add(&bo->list, &kgem->pinned_batches[n]);
772.13987 - 	}
772.13988 --	return false;
772.13989 -+	return true;
772.13990 - }
772.13991 - 
772.13992 - static void kgem_init_swizzling(struct kgem *kgem)
772.13993 -@@ -1364,7 +1668,7 @@ static void kgem_init_swizzling(struct kgem *kgem)
772.13994 - 	} tiling;
772.13995 - #define LOCAL_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct local_i915_gem_get_tiling_v2)
772.13996 - 
772.13997 --	VG_CLEAR(tiling);
772.13998 -+	memset(&tiling, 0, sizeof(tiling));
772.13999 - 	tiling.handle = gem_create(kgem->fd, 1);
772.14000 - 	if (!tiling.handle)
772.14001 - 		return;
772.14002 -@@ -1375,12 +1679,23 @@ static void kgem_init_swizzling(struct kgem *kgem)
772.14003 - 	if (do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_GET_TILING, &tiling))
772.14004 - 		goto out;
772.14005 - 
772.14006 --	if (kgem->gen < 50 && tiling.phys_swizzle_mode != tiling.swizzle_mode)
772.14007 -+	DBG(("%s: swizzle_mode=%d, phys_swizzle_mode=%d\n",
772.14008 -+	     __FUNCTION__, tiling.swizzle_mode, tiling.phys_swizzle_mode));
772.14009 -+
772.14010 -+	kgem->can_fence =
772.14011 -+		!DBG_NO_TILING &&
772.14012 -+		tiling.swizzle_mode != I915_BIT_6_SWIZZLE_UNKNOWN;
772.14013 -+
772.14014 -+	if (kgem->gen < 050 && tiling.phys_swizzle_mode != tiling.swizzle_mode)
772.14015 - 		goto out;
772.14016 - 
772.14017 --	choose_memcpy_tiled_x(kgem, tiling.swizzle_mode);
772.14018 -+	if (!DBG_NO_DETILING)
772.14019 -+		choose_memcpy_tiled_x(kgem,
772.14020 -+				      tiling.swizzle_mode,
772.14021 -+				      __to_sna(kgem)->cpu_features);
772.14022 - out:
772.14023 - 	gem_close(kgem->fd, tiling.handle);
772.14024 -+	DBG(("%s: can fence?=%d\n", __FUNCTION__, kgem->can_fence));
772.14025 - }
772.14026 - 
772.14027 - static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
772.14028 -@@ -1399,6 +1714,7 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
772.14029 - 	     bo->handle, (long long)bo->presumed_offset));
772.14030 - 	for (n = 0; n < kgem->nreloc__self; n++) {
772.14031 - 		int i = kgem->reloc__self[n];
772.14032 -+		uint64_t addr;
772.14033 - 
772.14034 - 		assert(kgem->reloc[i].target_handle == ~0U);
772.14035 - 		kgem->reloc[i].target_handle = bo->target_handle;
772.14036 -@@ -1412,13 +1728,17 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
772.14037 - 
772.14038 - 			kgem->reloc[i].delta -= shrink;
772.14039 - 		}
772.14040 --		kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t)] =
772.14041 --			kgem->reloc[i].delta + bo->presumed_offset;
772.14042 -+		addr = (int)kgem->reloc[i].delta + bo->presumed_offset;
772.14043 -+		kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t)] = addr;
772.14044 -+		if (kgem->gen >= 0100)
772.14045 -+			kgem->batch[kgem->reloc[i].offset/sizeof(uint32_t) + 1] = addr >> 32;
772.14046 - 	}
772.14047 - 
772.14048 - 	if (n == 256) {
772.14049 - 		for (n = kgem->reloc__self[255]; n < kgem->nreloc; n++) {
772.14050 - 			if (kgem->reloc[n].target_handle == ~0U) {
772.14051 -+				uint64_t addr;
772.14052 -+
772.14053 - 				kgem->reloc[n].target_handle = bo->target_handle;
772.14054 - 				kgem->reloc[n].presumed_offset = bo->presumed_offset;
772.14055 - 
772.14056 -@@ -1429,8 +1749,11 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
772.14057 - 					     kgem->reloc[n].delta - shrink));
772.14058 - 					kgem->reloc[n].delta -= shrink;
772.14059 - 				}
772.14060 --				kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t)] =
772.14061 --					kgem->reloc[n].delta + bo->presumed_offset;
772.14062 -+
772.14063 -+				addr = (int)kgem->reloc[n].delta + bo->presumed_offset;
772.14064 -+				kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t)] = addr;
772.14065 -+				if (kgem->gen >= 0100)
772.14066 -+					kgem->batch[kgem->reloc[n].offset/sizeof(uint32_t) + 1] = addr >> 32;
772.14067 - 			}
772.14068 - 		}
772.14069 - 	}
772.14070 -@@ -1444,6 +1767,44 @@ static void kgem_fixup_relocs(struct kgem *kgem, struct kgem_bo *bo, int shrink)
772.14071 - 	}
772.14072 - }
772.14073 - 
772.14074 -+static int kgem_bo_wait(struct kgem *kgem, struct kgem_bo *bo)
772.14075 -+{
772.14076 -+	struct local_i915_gem_wait {
772.14077 -+		uint32_t handle;
772.14078 -+		uint32_t flags;
772.14079 -+		int64_t timeout;
772.14080 -+	} wait;
772.14081 -+#define LOCAL_I915_GEM_WAIT       0x2c
772.14082 -+#define LOCAL_IOCTL_I915_GEM_WAIT         DRM_IOWR(DRM_COMMAND_BASE + LOCAL_I915_GEM_WAIT, struct local_i915_gem_wait)
772.14083 -+	int ret;
772.14084 -+
772.14085 -+	DBG(("%s: waiting for handle=%d\n", __FUNCTION__, bo->handle));
772.14086 -+	if (bo->rq == NULL)
772.14087 -+		return 0;
772.14088 -+
772.14089 -+	VG_CLEAR(wait);
772.14090 -+	wait.handle = bo->handle;
772.14091 -+	wait.flags = 0;
772.14092 -+	wait.timeout = -1;
772.14093 -+	ret = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_WAIT, &wait);
772.14094 -+	if (ret) {
772.14095 -+		struct drm_i915_gem_set_domain set_domain;
772.14096 -+
772.14097 -+		VG_CLEAR(set_domain);
772.14098 -+		set_domain.handle = bo->handle;
772.14099 -+		set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.14100 -+		set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.14101 -+		ret = do_ioctl(kgem->fd,
772.14102 -+			       DRM_IOCTL_I915_GEM_SET_DOMAIN,
772.14103 -+			       &set_domain);
772.14104 -+	}
772.14105 -+
772.14106 -+	if (ret == 0)
772.14107 -+		__kgem_retire_requests_upto(kgem, bo);
772.14108 -+
772.14109 -+	return ret;
772.14110 -+}
772.14111 -+
772.14112 - static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
772.14113 - {
772.14114 - 	struct kgem_bo *last;
772.14115 -@@ -1464,20 +1825,41 @@ static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
772.14116 - 	if (!kgem->has_llc)
772.14117 - 		flags |= CREATE_UNCACHED;
772.14118 - 
772.14119 -+restart:
772.14120 - 	kgem->batch_bo = kgem_create_linear(kgem,
772.14121 - 					    sizeof(uint32_t)*kgem->batch_size,
772.14122 - 					    flags);
772.14123 - 	if (kgem->batch_bo)
772.14124 - 		kgem->batch = kgem_bo_map__cpu(kgem, kgem->batch_bo);
772.14125 - 	if (kgem->batch == NULL) {
772.14126 --		DBG(("%s: unable to map batch bo, mallocing(size=%d)\n",
772.14127 --		     __FUNCTION__,
772.14128 --		     sizeof(uint32_t)*kgem->batch_size));
772.14129 -+		int ring = kgem->ring == KGEM_BLT;
772.14130 -+		assert(ring < ARRAY_SIZE(kgem->requests));
772.14131 -+
772.14132 - 		if (kgem->batch_bo) {
772.14133 - 			kgem_bo_destroy(kgem, kgem->batch_bo);
772.14134 - 			kgem->batch_bo = NULL;
772.14135 - 		}
772.14136 - 
772.14137 -+		if (!list_is_empty(&kgem->requests[ring])) {
772.14138 -+			struct kgem_request *rq;
772.14139 -+
772.14140 -+			rq = list_first_entry(&kgem->requests[ring],
772.14141 -+					      struct kgem_request, list);
772.14142 -+			assert(rq->ring == ring);
772.14143 -+			assert(rq->bo);
772.14144 -+			assert(RQ(rq->bo->rq) == rq);
772.14145 -+			if (kgem_bo_wait(kgem, rq->bo) == 0)
772.14146 -+				goto restart;
772.14147 -+		}
772.14148 -+
772.14149 -+		if (flags & CREATE_NO_THROTTLE) {
772.14150 -+			flags &= ~CREATE_NO_THROTTLE;
772.14151 -+			if (kgem_cleanup_cache(kgem))
772.14152 -+				goto restart;
772.14153 -+		}
772.14154 -+
772.14155 -+		DBG(("%s: unable to map batch bo, mallocing(size=%d)\n",
772.14156 -+		     __FUNCTION__, sizeof(uint32_t)*kgem->batch_size));
772.14157 - 		if (posix_memalign((void **)&kgem->batch, PAGE_SIZE,
772.14158 - 				   ALIGN(sizeof(uint32_t) * kgem->batch_size, PAGE_SIZE))) {
772.14159 - 			ERR(("%s: batch allocation failed, disabling acceleration\n", __FUNCTION__));
772.14160 -@@ -1495,18 +1877,79 @@ static struct kgem_bo *kgem_new_batch(struct kgem *kgem)
772.14161 - 	return last;
772.14162 - }
772.14163 - 
772.14164 --void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14165 -+static void
772.14166 -+no_retire(struct kgem *kgem)
772.14167 -+{
772.14168 -+	(void)kgem;
772.14169 -+}
772.14170 -+
772.14171 -+static void
772.14172 -+no_expire(struct kgem *kgem)
772.14173 -+{
772.14174 -+	(void)kgem;
772.14175 -+}
772.14176 -+
772.14177 -+static void
772.14178 -+no_context_switch(struct kgem *kgem, int new_mode)
772.14179 -+{
772.14180 -+	(void)kgem;
772.14181 -+	(void)new_mode;
772.14182 -+}
772.14183 -+
772.14184 -+static uint64_t get_gtt_size(int fd)
772.14185 - {
772.14186 - 	struct drm_i915_gem_get_aperture aperture;
772.14187 -+	struct local_i915_gem_context_param {
772.14188 -+		uint32_t context;
772.14189 -+		uint32_t size;
772.14190 -+		uint64_t param;
772.14191 -+#define LOCAL_CONTEXT_PARAM_BAN_PERIOD	0x1
772.14192 -+#define LOCAL_CONTEXT_PARAM_NO_ZEROMAP	0x2
772.14193 -+#define LOCAL_CONTEXT_PARAM_GTT_SIZE	0x3
772.14194 -+		uint64_t value;
772.14195 -+	} p;
772.14196 -+#define LOCAL_I915_GEM_CONTEXT_GETPARAM       0x34
772.14197 -+#define LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_CONTEXT_GETPARAM, struct local_i915_gem_context_param)
772.14198 -+
772.14199 -+	memset(&aperture, 0, sizeof(aperture));
772.14200 -+
772.14201 -+	memset(&p, 0, sizeof(p));
772.14202 -+	p.param = LOCAL_CONTEXT_PARAM_GTT_SIZE;
772.14203 -+	if (drmIoctl(fd, LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM, &p) == 0)
772.14204 -+		aperture.aper_size = p.value;
772.14205 -+	if (aperture.aper_size == 0)
772.14206 -+		(void)drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
772.14207 -+	if (aperture.aper_size == 0)
772.14208 -+		aperture.aper_size = 64*1024*1024;
772.14209 -+
772.14210 -+	DBG(("%s: aperture size %lld, available now %lld\n",
772.14211 -+	     __FUNCTION__,
772.14212 -+	     (long long)aperture.aper_size,
772.14213 -+	     (long long)aperture.aper_available_size));
772.14214 -+
772.14215 -+	/* clamp aperture to uint32_t for simplicity */
772.14216 -+	if (aperture.aper_size > 0xc0000000)
772.14217 -+		aperture.aper_size = 0xc0000000;
772.14218 -+
772.14219 -+	return aperture.aper_size;
772.14220 -+}
772.14221 -+
772.14222 -+void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14223 -+{
772.14224 - 	size_t totalram;
772.14225 - 	unsigned half_gpu_max;
772.14226 - 	unsigned int i, j;
772.14227 -+	uint64_t gtt_size;
772.14228 - 
772.14229 - 	DBG(("%s: fd=%d, gen=%d\n", __FUNCTION__, fd, gen));
772.14230 - 
772.14231 - 	kgem->fd = fd;
772.14232 - 	kgem->gen = gen;
772.14233 - 
772.14234 -+	kgem->retire = no_retire;
772.14235 -+	kgem->expire = no_expire;
772.14236 -+	kgem->context_switch = no_context_switch;
772.14237 -+
772.14238 - 	list_init(&kgem->requests[0]);
772.14239 - 	list_init(&kgem->requests[1]);
772.14240 - 	list_init(&kgem->batch_buffers);
772.14241 -@@ -1586,10 +2029,21 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14242 - 	DBG(("%s: can blt to cpu? %d\n", __FUNCTION__,
772.14243 - 	     kgem->can_blt_cpu));
772.14244 - 
772.14245 -+	kgem->can_blt_y = test_can_blt_y(kgem);
772.14246 -+	DBG(("%s: can blit to Y-tiled surfaces? %d\n", __FUNCTION__,
772.14247 -+	     kgem->can_blt_y));
772.14248 -+
772.14249 - 	kgem->can_render_y = gen != 021 && (gen >> 3) != 4;
772.14250 - 	DBG(("%s: can render to Y-tiled surfaces? %d\n", __FUNCTION__,
772.14251 - 	     kgem->can_render_y));
772.14252 - 
772.14253 -+	kgem->can_scanout_y = test_can_scanout_y(kgem);
772.14254 -+	DBG(("%s: can scanout Y-tiled surfaces? %d\n", __FUNCTION__,
772.14255 -+	     kgem->can_scanout_y));
772.14256 -+
772.14257 -+	kgem->has_dirtyfb = test_has_dirtyfb(kgem);
772.14258 -+	DBG(("%s: has dirty fb? %d\n", __FUNCTION__, kgem->has_dirtyfb));
772.14259 -+
772.14260 - 	kgem->has_secure_batches = test_has_secure_batches(kgem);
772.14261 - 	DBG(("%s: can use privileged batchbuffers? %d\n", __FUNCTION__,
772.14262 - 	     kgem->has_secure_batches));
772.14263 -@@ -1620,7 +2074,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14264 - 	if (!kgem->has_relaxed_delta && kgem->batch_size > 4*1024)
772.14265 - 		kgem->batch_size = 4*1024;
772.14266 - 
772.14267 --	if (!kgem_init_pinned_batches(kgem) && gen == 020) {
772.14268 -+	if (!kgem_init_pinned_batches(kgem)) {
772.14269 - 		xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
772.14270 - 			   "Unable to reserve memory for GPU, disabling acceleration.\n");
772.14271 - 		__kgem_set_wedged(kgem);
772.14272 -@@ -1640,35 +2094,24 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14273 - 	     !DBG_NO_CPU && (kgem->has_llc | kgem->has_userptr | kgem->has_caching),
772.14274 - 	     kgem->has_llc, kgem->has_caching, kgem->has_userptr));
772.14275 - 
772.14276 --	VG_CLEAR(aperture);
772.14277 --	aperture.aper_size = 0;
772.14278 --	(void)do_ioctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
772.14279 --	if (aperture.aper_size == 0)
772.14280 --		aperture.aper_size = 64*1024*1024;
772.14281 --
772.14282 --	DBG(("%s: aperture size %lld, available now %lld\n",
772.14283 --	     __FUNCTION__,
772.14284 --	     (long long)aperture.aper_size,
772.14285 --	     (long long)aperture.aper_available_size));
772.14286 --
772.14287 --	kgem->aperture_total = aperture.aper_size;
772.14288 --	kgem->aperture_high = aperture.aper_size * 3/4;
772.14289 --	kgem->aperture_low = aperture.aper_size * 1/3;
772.14290 -+	gtt_size = get_gtt_size(fd);
772.14291 -+	kgem->aperture_total = gtt_size;
772.14292 -+	kgem->aperture_high = gtt_size * 3/4;
772.14293 -+	kgem->aperture_low = gtt_size * 1/3;
772.14294 - 	if (gen < 033) {
772.14295 - 		/* Severe alignment penalties */
772.14296 - 		kgem->aperture_high /= 2;
772.14297 - 		kgem->aperture_low /= 2;
772.14298 - 	}
772.14299 --	DBG(("%s: aperture low=%d [%d], high=%d [%d]\n", __FUNCTION__,
772.14300 -+	DBG(("%s: aperture low=%u [%u], high=%u [%u]\n", __FUNCTION__,
772.14301 - 	     kgem->aperture_low, kgem->aperture_low / (1024*1024),
772.14302 - 	     kgem->aperture_high, kgem->aperture_high / (1024*1024)));
772.14303 - 
772.14304 - 	kgem->aperture_mappable = 256 * 1024 * 1024;
772.14305 - 	if (dev != NULL)
772.14306 - 		kgem->aperture_mappable = agp_aperture_size(dev, gen);
772.14307 --	if (kgem->aperture_mappable == 0 ||
772.14308 --	    kgem->aperture_mappable > aperture.aper_size)
772.14309 --		kgem->aperture_mappable = aperture.aper_size;
772.14310 -+	if (kgem->aperture_mappable == 0 || kgem->aperture_mappable > gtt_size)
772.14311 -+		kgem->aperture_mappable = gtt_size;
772.14312 - 	DBG(("%s: aperture mappable=%d [%d MiB]\n", __FUNCTION__,
772.14313 - 	     kgem->aperture_mappable, kgem->aperture_mappable / (1024*1024)));
772.14314 - 
772.14315 -@@ -1697,7 +2140,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14316 - 		     __FUNCTION__));
772.14317 - 		totalram = kgem->aperture_total;
772.14318 - 	}
772.14319 --	DBG(("%s: total ram=%ld\n", __FUNCTION__, (long)totalram));
772.14320 -+	DBG(("%s: total ram=%lld\n", __FUNCTION__, (long long)totalram));
772.14321 - 	if (kgem->max_object_size > totalram / 2)
772.14322 - 		kgem->max_object_size = totalram / 2;
772.14323 - 	if (kgem->max_gpu_size > totalram / 4)
772.14324 -@@ -1749,11 +2192,11 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
772.14325 - 	if (DBG_NO_CPU)
772.14326 - 		kgem->max_cpu_size = 0;
772.14327 - 
772.14328 --	DBG(("%s: maximum object size=%d\n",
772.14329 -+	DBG(("%s: maximum object size=%u\n",
772.14330 - 	     __FUNCTION__, kgem->max_object_size));
772.14331 --	DBG(("%s: large object thresold=%d\n",
772.14332 -+	DBG(("%s: large object thresold=%u\n",
772.14333 - 	     __FUNCTION__, kgem->large_object_size));
772.14334 --	DBG(("%s: max object sizes (gpu=%d, cpu=%d, tile upload=%d, copy=%d)\n",
772.14335 -+	DBG(("%s: max object sizes (gpu=%u, cpu=%u, tile upload=%u, copy=%u)\n",
772.14336 - 	     __FUNCTION__,
772.14337 - 	     kgem->max_gpu_size, kgem->max_cpu_size,
772.14338 - 	     kgem->max_upload_tile_size, kgem->max_copy_tile_size));
772.14339 -@@ -2043,8 +2486,34 @@ static void kgem_add_bo(struct kgem *kgem, struct kgem_bo *bo)
772.14340 - 	kgem->flush |= bo->flush;
772.14341 - }
772.14342 - 
772.14343 -+static void kgem_clear_swctrl(struct kgem *kgem)
772.14344 -+{
772.14345 -+	uint32_t *b;
772.14346 -+
772.14347 -+	if (kgem->bcs_state == 0)
772.14348 -+		return;
772.14349 -+
772.14350 -+	DBG(("%s: clearin SWCTRL LRI from %x\n",
772.14351 -+	     __FUNCTION__, kgem->bcs_state));
772.14352 -+
772.14353 -+	b = kgem->batch + kgem->nbatch;
772.14354 -+	kgem->nbatch += 7;
772.14355 -+
772.14356 -+	*b++ = MI_FLUSH_DW;
772.14357 -+	*b++ = 0;
772.14358 -+	*b++ = 0;
772.14359 -+	*b++ = 0;
772.14360 -+
772.14361 -+	*b++ = MI_LOAD_REGISTER_IMM;
772.14362 -+	*b++ = BCS_SWCTRL;
772.14363 -+	*b++ = (BCS_SRC_Y | BCS_DST_Y) << 16;
772.14364 -+
772.14365 -+	kgem->bcs_state = 0;
772.14366 -+}
772.14367 -+
772.14368 - static uint32_t kgem_end_batch(struct kgem *kgem)
772.14369 - {
772.14370 -+	kgem_clear_swctrl(kgem);
772.14371 - 	kgem->batch[kgem->nbatch++] = MI_BATCH_BUFFER_END;
772.14372 - 	if (kgem->nbatch & 1)
772.14373 - 		kgem->batch[kgem->nbatch++] = MI_NOOP;
772.14374 -@@ -2064,17 +2533,6 @@ static void kgem_bo_binding_free(struct kgem *kgem, struct kgem_bo *bo)
772.14375 - 	}
772.14376 - }
772.14377 - 
772.14378 --static void kgem_bo_rmfb(struct kgem *kgem, struct kgem_bo *bo)
772.14379 --{
772.14380 --	if (bo->scanout && bo->delta) {
772.14381 --		DBG(("%s: releasing fb=%d for handle=%d\n",
772.14382 --		     __FUNCTION__, bo->delta, bo->handle));
772.14383 --		/* XXX will leak if we are not DRM_MASTER. *shrug* */
772.14384 --		do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
772.14385 --		bo->delta = 0;
772.14386 --	}
772.14387 --}
772.14388 --
772.14389 - static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
772.14390 - {
772.14391 - 	DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
772.14392 -@@ -2150,13 +2608,16 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem,
772.14393 - 	assert(!bo->snoop);
772.14394 - 	assert(!bo->flush);
772.14395 - 	assert(!bo->needs_flush);
772.14396 -+	assert(!bo->delta);
772.14397 - 	assert(list_is_empty(&bo->vma));
772.14398 - 	assert_tiling(kgem, bo);
772.14399 --	assert_cacheing(kgem, bo);
772.14400 -+	assert_caching(kgem, bo);
772.14401 - 	ASSERT_IDLE(kgem, bo->handle);
772.14402 - 
772.14403 - 	if (bucket(bo) >= NUM_CACHE_BUCKETS) {
772.14404 - 		if (bo->map__gtt) {
772.14405 -+			DBG(("%s: relinquishing large GTT mapping for handle=%d\n",
772.14406 -+			     __FUNCTION__, bo->handle));
772.14407 - 			munmap(bo->map__gtt, bytes(bo));
772.14408 - 			bo->map__gtt = NULL;
772.14409 - 		}
772.14410 -@@ -2167,6 +2628,8 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem,
772.14411 - 		assert(list_is_empty(&bo->vma));
772.14412 - 		list_move(&bo->list, &kgem->inactive[bucket(bo)]);
772.14413 - 		if (bo->map__gtt && !kgem_bo_can_map(kgem, bo)) {
772.14414 -+			DBG(("%s: relinquishing old GTT mapping for handle=%d\n",
772.14415 -+			     __FUNCTION__, bo->handle));
772.14416 - 			munmap(bo->map__gtt, bytes(bo));
772.14417 - 			bo->map__gtt = NULL;
772.14418 - 		}
772.14419 -@@ -2191,6 +2654,10 @@ static struct kgem_bo *kgem_bo_replace_io(struct kgem_bo *bo)
772.14420 - 		return bo;
772.14421 - 
772.14422 - 	assert(!bo->snoop);
772.14423 -+	assert(!bo->purged);
772.14424 -+	assert(!bo->scanout);
772.14425 -+	assert(!bo->delta);
772.14426 -+
772.14427 - 	if (__kgem_freed_bo) {
772.14428 - 		base = __kgem_freed_bo;
772.14429 - 		__kgem_freed_bo = *(struct kgem_bo **)base;
772.14430 -@@ -2221,6 +2688,7 @@ inline static void kgem_bo_remove_from_inactive(struct kgem *kgem,
772.14431 - 	list_del(&bo->list);
772.14432 - 	assert(bo->rq == NULL);
772.14433 - 	assert(bo->exec == NULL);
772.14434 -+	assert(!bo->purged);
772.14435 - 	if (!list_is_empty(&bo->vma)) {
772.14436 - 		assert(bo->map__gtt || bo->map__wc || bo->map__cpu);
772.14437 - 		list_del(&bo->vma);
772.14438 -@@ -2305,7 +2773,6 @@ static void kgem_bo_move_to_scanout(struct kgem *kgem, struct kgem_bo *bo)
772.14439 - 		list_move(&bo->list, &kgem->scanout);
772.14440 - 
772.14441 - 	kgem->need_expire = true;
772.14442 --
772.14443 - }
772.14444 - 
772.14445 - static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
772.14446 -@@ -2316,6 +2783,8 @@ static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
772.14447 - 	assert(!bo->needs_flush);
772.14448 - 	assert(bo->refcnt == 0);
772.14449 - 	assert(bo->exec == NULL);
772.14450 -+	assert(!bo->purged);
772.14451 -+	assert(!bo->delta);
772.14452 - 
772.14453 - 	if (DBG_NO_SNOOP_CACHE) {
772.14454 - 		kgem_bo_free(kgem, bo);
772.14455 -@@ -2351,8 +2820,7 @@ static bool kgem_bo_move_to_cache(struct kgem *kgem, struct kgem_bo *bo)
772.14456 - 		kgem_bo_move_to_snoop(kgem, bo);
772.14457 - 	} else if (bo->scanout) {
772.14458 - 		kgem_bo_move_to_scanout(kgem, bo);
772.14459 --	} else if ((bo = kgem_bo_replace_io(bo))->reusable &&
772.14460 --		   kgem_bo_set_purgeable(kgem, bo)) {
772.14461 -+	} else if ((bo = kgem_bo_replace_io(bo))->reusable) {
772.14462 - 		kgem_bo_move_to_inactive(kgem, bo);
772.14463 - 		retired = true;
772.14464 - 	} else
772.14465 -@@ -2429,7 +2897,7 @@ void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo)
772.14466 - 	DBG(("%s: only handle in batch, discarding last operations for handle=%d\n",
772.14467 - 	     __FUNCTION__, bo->handle));
772.14468 - 
772.14469 --	assert(bo->exec == &kgem->exec[0]);
772.14470 -+	assert(bo->exec == &_kgem_dummy_exec || bo->exec == &kgem->exec[0]);
772.14471 - 	assert(kgem->exec[0].handle == bo->handle);
772.14472 - 	assert(RQ(bo->rq) == kgem->next_request);
772.14473 - 
772.14474 -@@ -2457,16 +2925,23 @@ void kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b)
772.14475 - 
772.14476 - 	if (a == NULL || b == NULL)
772.14477 - 		return;
772.14478 -+	assert(a != b);
772.14479 - 	if (a->exec == NULL || b->exec == NULL)
772.14480 - 		return;
772.14481 - 
772.14482 --	DBG(("%s: only handles in batch, discarding last operations for handle=%d and handle=%d\n",
772.14483 --	     __FUNCTION__, a->handle, b->handle));
772.14484 -+	DBG(("%s: only handles in batch, discarding last operations for handle=%d (index=%d) and handle=%d (index=%d)\n",
772.14485 -+	     __FUNCTION__,
772.14486 -+	     a->handle, a->proxy ? -1 : a->exec - kgem->exec,
772.14487 -+	     b->handle, b->proxy ? -1 : b->exec - kgem->exec));
772.14488 - 
772.14489 --	assert(a->exec == &kgem->exec[0] || a->exec == &kgem->exec[1]);
772.14490 -+	assert(a->exec == &_kgem_dummy_exec ||
772.14491 -+	       a->exec == &kgem->exec[0] ||
772.14492 -+	       a->exec == &kgem->exec[1]);
772.14493 - 	assert(a->handle == kgem->exec[0].handle || a->handle == kgem->exec[1].handle);
772.14494 - 	assert(RQ(a->rq) == kgem->next_request);
772.14495 --	assert(b->exec == &kgem->exec[0] || b->exec == &kgem->exec[1]);
772.14496 -+	assert(b->exec == &_kgem_dummy_exec ||
772.14497 -+	       b->exec == &kgem->exec[0] ||
772.14498 -+	       b->exec == &kgem->exec[1]);
772.14499 - 	assert(b->handle == kgem->exec[0].handle || b->handle == kgem->exec[1].handle);
772.14500 - 	assert(RQ(b->rq) == kgem->next_request);
772.14501 - 
772.14502 -@@ -2487,6 +2962,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
772.14503 - 	DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
772.14504 - 
772.14505 - 	assert(list_is_empty(&bo->list));
772.14506 -+	assert(list_is_empty(&bo->vma));
772.14507 - 	assert(bo->refcnt == 0);
772.14508 - 	assert(bo->proxy == NULL);
772.14509 - 	assert(bo->active_scanout == 0);
772.14510 -@@ -2532,7 +3008,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
772.14511 - 	assert(bo->snoop == false);
772.14512 - 	assert(bo->io == false);
772.14513 - 	assert(bo->scanout == false);
772.14514 --	assert_cacheing(kgem, bo);
772.14515 -+	assert_caching(kgem, bo);
772.14516 - 
772.14517 - 	kgem_bo_undo(kgem, bo);
772.14518 - 	assert(bo->refcnt == 0);
772.14519 -@@ -2556,9 +3032,6 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
772.14520 - 	assert(list_is_empty(&bo->request));
772.14521 - 
772.14522 - 	if (bo->map__cpu == NULL || bucket(bo) >= NUM_CACHE_BUCKETS) {
772.14523 --		if (!kgem_bo_set_purgeable(kgem, bo))
772.14524 --			goto destroy;
772.14525 --
772.14526 - 		if (!kgem->has_llc && bo->domain == DOMAIN_CPU)
772.14527 - 			goto destroy;
772.14528 - 
772.14529 -@@ -2647,7 +3120,7 @@ static bool kgem_retire__flushing(struct kgem *kgem)
772.14530 - 		int count = 0;
772.14531 - 		list_for_each_entry(bo, &kgem->flushing, request)
772.14532 - 			count++;
772.14533 --		DBG(("%s: %d bo on flushing list\n", __FUNCTION__, count));
772.14534 -+		DBG(("%s: %d bo on flushing list, retired? %d\n", __FUNCTION__, count, retired));
772.14535 - 	}
772.14536 - #endif
772.14537 - 
772.14538 -@@ -2656,6 +3129,34 @@ static bool kgem_retire__flushing(struct kgem *kgem)
772.14539 - 	return retired;
772.14540 - }
772.14541 - 
772.14542 -+static bool __kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
772.14543 -+{
772.14544 -+	struct drm_i915_gem_busy busy;
772.14545 -+
772.14546 -+	if (!bo->needs_flush)
772.14547 -+		return false;
772.14548 -+
772.14549 -+	bo->needs_flush = false;
772.14550 -+
772.14551 -+	VG_CLEAR(busy);
772.14552 -+	busy.handle = bo->handle;
772.14553 -+	busy.busy = !kgem->wedged;
772.14554 -+	(void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
772.14555 -+	DBG(("%s: handle=%d, busy=%d, wedged=%d\n",
772.14556 -+	     __FUNCTION__, bo->handle, busy.busy, kgem->wedged));
772.14557 -+
772.14558 -+	if (busy.busy == 0)
772.14559 -+		return false;
772.14560 -+
772.14561 -+	DBG(("%s: moving %d to flushing\n",
772.14562 -+	     __FUNCTION__, bo->handle));
772.14563 -+	list_add(&bo->request, &kgem->flushing);
772.14564 -+	bo->rq = MAKE_REQUEST(kgem, !!(busy.busy & ~0x1ffff));
772.14565 -+	bo->needs_flush = busy.busy & 0xffff;
772.14566 -+	kgem->need_retire = true;
772.14567 -+	return true;
772.14568 -+}
772.14569 -+
772.14570 - static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
772.14571 - {
772.14572 - 	bool retired = false;
772.14573 -@@ -2663,6 +3164,8 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
772.14574 - 	DBG(("%s: request %d complete\n",
772.14575 - 	     __FUNCTION__, rq->bo->handle));
772.14576 - 	assert(RQ(rq->bo->rq) == rq);
772.14577 -+	assert(rq != (struct kgem_request *)kgem);
772.14578 -+	assert(rq != &kgem->static_request);
772.14579 - 
772.14580 - 	if (rq == kgem->fence[rq->ring])
772.14581 - 		kgem->fence[rq->ring] = NULL;
772.14582 -@@ -2680,19 +3183,14 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
772.14583 - 
772.14584 - 		list_del(&bo->request);
772.14585 - 
772.14586 --		if (bo->needs_flush)
772.14587 --			bo->needs_flush = __kgem_busy(kgem, bo->handle);
772.14588 --		if (bo->needs_flush) {
772.14589 --			DBG(("%s: moving %d to flushing\n",
772.14590 -+		if (unlikely(__kgem_bo_flush(kgem, bo))) {
772.14591 -+			assert(bo != rq->bo);
772.14592 -+			DBG(("%s: movied %d to flushing\n",
772.14593 - 			     __FUNCTION__, bo->handle));
772.14594 --			list_add(&bo->request, &kgem->flushing);
772.14595 --			bo->rq = MAKE_REQUEST(kgem, RQ_RING(bo->rq));
772.14596 --			kgem->need_retire = true;
772.14597 - 			continue;
772.14598 - 		}
772.14599 - 
772.14600 - 		bo->domain = DOMAIN_NONE;
772.14601 --		bo->gtt_dirty = false;
772.14602 - 		bo->rq = NULL;
772.14603 - 		if (bo->refcnt)
772.14604 - 			continue;
772.14605 -@@ -2706,14 +3204,8 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
772.14606 - 	assert(rq->bo->refcnt > 0);
772.14607 - 
772.14608 - 	if (--rq->bo->refcnt == 0) {
772.14609 --		if (kgem_bo_set_purgeable(kgem, rq->bo)) {
772.14610 --			kgem_bo_move_to_inactive(kgem, rq->bo);
772.14611 --			retired = true;
772.14612 --		} else {
772.14613 --			DBG(("%s: closing %d\n",
772.14614 --			     __FUNCTION__, rq->bo->handle));
772.14615 --			kgem_bo_free(kgem, rq->bo);
772.14616 --		}
772.14617 -+		kgem_bo_move_to_inactive(kgem, rq->bo);
772.14618 -+		retired = true;
772.14619 - 	}
772.14620 - 
772.14621 - 	__kgem_request_free(rq);
772.14622 -@@ -2724,13 +3216,18 @@ static bool kgem_retire__requests_ring(struct kgem *kgem, int ring)
772.14623 - {
772.14624 - 	bool retired = false;
772.14625 - 
772.14626 -+	assert(ring < ARRAY_SIZE(kgem->requests));
772.14627 - 	while (!list_is_empty(&kgem->requests[ring])) {
772.14628 - 		struct kgem_request *rq;
772.14629 - 
772.14630 -+		DBG(("%s: retiring ring %d\n", __FUNCTION__, ring));
772.14631 -+
772.14632 - 		rq = list_first_entry(&kgem->requests[ring],
772.14633 - 				      struct kgem_request,
772.14634 - 				      list);
772.14635 - 		assert(rq->ring == ring);
772.14636 -+		assert(rq->bo);
772.14637 -+		assert(RQ(rq->bo->rq) == rq);
772.14638 - 		if (__kgem_busy(kgem, rq->bo->handle))
772.14639 - 			break;
772.14640 - 
772.14641 -@@ -2751,8 +3248,8 @@ static bool kgem_retire__requests_ring(struct kgem *kgem, int ring)
772.14642 - 					      struct kgem_request,
772.14643 - 					      list)->bo;
772.14644 - 
772.14645 --		DBG(("%s: ring=%d, %d outstanding requests, oldest=%d\n",
772.14646 --		     __FUNCTION__, ring, count, bo ? bo->handle : 0));
772.14647 -+		DBG(("%s: ring=%d, %d outstanding requests, oldest=%d, retired? %d\n",
772.14648 -+		     __FUNCTION__, ring, count, bo ? bo->handle : 0, retired));
772.14649 - 	}
772.14650 - #endif
772.14651 - 
772.14652 -@@ -2824,6 +3321,8 @@ bool __kgem_ring_is_idle(struct kgem *kgem, int ring)
772.14653 - 	rq = list_last_entry(&kgem->requests[ring],
772.14654 - 			     struct kgem_request, list);
772.14655 - 	assert(rq->ring == ring);
772.14656 -+	assert(rq->bo);
772.14657 -+	assert(RQ(rq->bo->rq) == rq);
772.14658 - 	if (__kgem_busy(kgem, rq->bo->handle)) {
772.14659 - 		DBG(("%s: last requests handle=%d still busy\n",
772.14660 - 		     __FUNCTION__, rq->bo->handle));
772.14661 -@@ -2845,23 +3344,30 @@ bool __kgem_ring_is_idle(struct kgem *kgem, int ring)
772.14662 - 	return true;
772.14663 - }
772.14664 - 
772.14665 --void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
772.14666 -+bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
772.14667 - {
772.14668 --	struct kgem_request *rq = bo->rq, *tmp;
772.14669 --	struct list *requests = &kgem->requests[RQ_RING(rq) == I915_EXEC_BLT];
772.14670 -+	struct kgem_request * const rq = RQ(bo->rq), *tmp;
772.14671 -+	struct list *requests = &kgem->requests[rq->ring];
772.14672 -+
772.14673 -+	DBG(("%s(handle=%d, ring=%d)\n", __FUNCTION__, bo->handle, rq->ring));
772.14674 - 
772.14675 --	rq = RQ(rq);
772.14676 - 	assert(rq != &kgem->static_request);
772.14677 - 	if (rq == (struct kgem_request *)kgem) {
772.14678 - 		__kgem_bo_clear_busy(bo);
772.14679 --		return;
772.14680 -+		return false;
772.14681 - 	}
772.14682 - 
772.14683 -+	assert(rq->ring < ARRAY_SIZE(kgem->requests));
772.14684 - 	do {
772.14685 - 		tmp = list_first_entry(requests, struct kgem_request, list);
772.14686 - 		assert(tmp->ring == rq->ring);
772.14687 - 		__kgem_retire_rq(kgem, tmp);
772.14688 - 	} while (tmp != rq);
772.14689 -+
772.14690 -+	assert(bo->needs_flush || bo->rq == NULL);
772.14691 -+	assert(bo->needs_flush || list_is_empty(&bo->request));
772.14692 -+	assert(bo->needs_flush || bo->domain == DOMAIN_NONE);
772.14693 -+	return bo->rq;
772.14694 - }
772.14695 - 
772.14696 - #if 0
772.14697 -@@ -2932,6 +3438,7 @@ static void kgem_commit(struct kgem *kgem)
772.14698 - 		bo->binding.offset = 0;
772.14699 - 		bo->domain = DOMAIN_GPU;
772.14700 - 		bo->gpu_dirty = false;
772.14701 -+		bo->gtt_dirty = false;
772.14702 - 
772.14703 - 		if (bo->proxy) {
772.14704 - 			/* proxies are not used for domain tracking */
772.14705 -@@ -2955,6 +3462,23 @@ static void kgem_commit(struct kgem *kgem)
772.14706 - 			kgem_throttle(kgem);
772.14707 - 		}
772.14708 - 
772.14709 -+		while (!list_is_empty(&rq->buffers)) {
772.14710 -+			bo = list_first_entry(&rq->buffers,
772.14711 -+					      struct kgem_bo,
772.14712 -+					      request);
772.14713 -+
772.14714 -+			assert(RQ(bo->rq) == rq);
772.14715 -+			assert(bo->exec == NULL);
772.14716 -+			assert(bo->domain == DOMAIN_GPU);
772.14717 -+
772.14718 -+			list_del(&bo->request);
772.14719 -+			bo->domain = DOMAIN_NONE;
772.14720 -+			bo->rq = NULL;
772.14721 -+
772.14722 -+			if (bo->refcnt == 0)
772.14723 -+				_kgem_bo_destroy(kgem, bo);
772.14724 -+		}
772.14725 -+
772.14726 - 		kgem_retire(kgem);
772.14727 - 		assert(list_is_empty(&rq->buffers));
772.14728 - 
772.14729 -@@ -2964,7 +3488,9 @@ static void kgem_commit(struct kgem *kgem)
772.14730 - 		gem_close(kgem->fd, rq->bo->handle);
772.14731 - 		kgem_cleanup_cache(kgem);
772.14732 - 	} else {
772.14733 -+		assert(rq != (struct kgem_request *)kgem);
772.14734 - 		assert(rq->ring < ARRAY_SIZE(kgem->requests));
772.14735 -+		assert(rq->bo);
772.14736 - 		list_add_tail(&rq->list, &kgem->requests[rq->ring]);
772.14737 - 		kgem->need_throttle = kgem->need_retire = 1;
772.14738 - 
772.14739 -@@ -2988,8 +3514,10 @@ static void kgem_close_inactive(struct kgem *kgem)
772.14740 - {
772.14741 - 	unsigned int i;
772.14742 - 
772.14743 --	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++)
772.14744 -+	for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) {
772.14745 - 		kgem_close_list(kgem, &kgem->inactive[i]);
772.14746 -+		assert(list_is_empty(&kgem->inactive[i]));
772.14747 -+	}
772.14748 - }
772.14749 - 
772.14750 - static void kgem_finish_buffers(struct kgem *kgem)
772.14751 -@@ -3079,10 +3607,13 @@ static void kgem_finish_buffers(struct kgem *kgem)
772.14752 - 						kgem->has_handle_lut ? bo->base.target_handle : shrink->handle;
772.14753 - 					for (n = 0; n < kgem->nreloc; n++) {
772.14754 - 						if (kgem->reloc[n].target_handle == bo->base.target_handle) {
772.14755 -+							uint64_t addr = (int)kgem->reloc[n].delta + shrink->presumed_offset;
772.14756 -+							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] = addr;
772.14757 -+							if (kgem->gen >= 0100)
772.14758 -+								kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0]) + 1] = addr >> 32;
772.14759 -+
772.14760 - 							kgem->reloc[n].target_handle = shrink->target_handle;
772.14761 - 							kgem->reloc[n].presumed_offset = shrink->presumed_offset;
772.14762 --							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] =
772.14763 --								kgem->reloc[n].delta + shrink->presumed_offset;
772.14764 - 						}
772.14765 - 					}
772.14766 - 
772.14767 -@@ -3124,10 +3655,13 @@ static void kgem_finish_buffers(struct kgem *kgem)
772.14768 - 						kgem->has_handle_lut ? bo->base.target_handle : shrink->handle;
772.14769 - 					for (n = 0; n < kgem->nreloc; n++) {
772.14770 - 						if (kgem->reloc[n].target_handle == bo->base.target_handle) {
772.14771 -+							uint64_t addr = (int)kgem->reloc[n].delta + shrink->presumed_offset;
772.14772 -+							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] = addr;
772.14773 -+							if (kgem->gen >= 0100)
772.14774 -+								kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0]) + 1] = addr >> 32;
772.14775 -+
772.14776 - 							kgem->reloc[n].target_handle = shrink->target_handle;
772.14777 - 							kgem->reloc[n].presumed_offset = shrink->presumed_offset;
772.14778 --							kgem->batch[kgem->reloc[n].offset/sizeof(kgem->batch[0])] =
772.14779 --								kgem->reloc[n].delta + shrink->presumed_offset;
772.14780 - 						}
772.14781 - 					}
772.14782 - 
772.14783 -@@ -3195,6 +3729,9 @@ static void kgem_cleanup(struct kgem *kgem)
772.14784 - 					kgem_bo_free(kgem, bo);
772.14785 - 			}
772.14786 - 
772.14787 -+			if (--rq->bo->refcnt == 0)
772.14788 -+				kgem_bo_free(kgem, rq->bo);
772.14789 -+
772.14790 - 			__kgem_request_free(rq);
772.14791 - 		}
772.14792 - 	}
772.14793 -@@ -3210,7 +3747,9 @@ kgem_batch_write(struct kgem *kgem,
772.14794 - 	char *ptr;
772.14795 - 	int ret;
772.14796 - 
772.14797 --	ASSERT_IDLE(kgem, bo->handle);
772.14798 -+	assert(bo->exec == NULL);
772.14799 -+	assert(bo->rq == NULL);
772.14800 -+	assert(!__kgem_busy(kgem, bo->handle));
772.14801 - 
772.14802 - #if DBG_NO_EXEC
772.14803 - 	{
772.14804 -@@ -3371,55 +3910,54 @@ static int compact_batch_surface(struct kgem *kgem, int *shrink)
772.14805 - 	return size * sizeof(uint32_t);
772.14806 - }
772.14807 - 
772.14808 -+static struct kgem_bo *first_available(struct kgem *kgem, struct list *list)
772.14809 -+{
772.14810 -+	struct kgem_bo *bo;
772.14811 -+
772.14812 -+	list_for_each_entry(bo, list, list) {
772.14813 -+		assert(bo->refcnt > 0);
772.14814 -+
772.14815 -+		if (bo->rq) {
772.14816 -+			assert(RQ(bo->rq)->bo == bo);
772.14817 -+			if (__kgem_busy(kgem, bo->handle))
772.14818 -+				break;
772.14819 -+
772.14820 -+			__kgem_retire_rq(kgem, RQ(bo->rq));
772.14821 -+			assert(bo->rq == NULL);
772.14822 -+		}
772.14823 -+
772.14824 -+		if (bo->refcnt > 1)
772.14825 -+			continue;
772.14826 -+
772.14827 -+		list_move_tail(&bo->list, list);
772.14828 -+		return kgem_bo_reference(bo);
772.14829 -+	}
772.14830 -+
772.14831 -+	return NULL;
772.14832 -+}
772.14833 -+
772.14834 - static struct kgem_bo *
772.14835 - kgem_create_batch(struct kgem *kgem)
772.14836 - {
772.14837 --#if !DBG_NO_SHRINK_BATCHES
772.14838 --	struct drm_i915_gem_set_domain set_domain;
772.14839 - 	struct kgem_bo *bo;
772.14840 --	int shrink = 0;
772.14841 --	int size;
772.14842 -+	int size, shrink = 0;
772.14843 - 
772.14844 -+#if !DBG_NO_SHRINK_BATCHES
772.14845 - 	if (kgem->surface != kgem->batch_size)
772.14846 - 		size = compact_batch_surface(kgem, &shrink);
772.14847 - 	else
772.14848 - 		size = kgem->nbatch * sizeof(uint32_t);
772.14849 - 
772.14850 - 	if (size <= 4096) {
772.14851 --		bo = list_first_entry(&kgem->pinned_batches[0],
772.14852 --				      struct kgem_bo,
772.14853 --				      list);
772.14854 --		if (!bo->rq) {
772.14855 --out_4096:
772.14856 --			assert(bo->refcnt > 0);
772.14857 --			list_move_tail(&bo->list, &kgem->pinned_batches[0]);
772.14858 --			bo = kgem_bo_reference(bo);
772.14859 -+		bo = first_available(kgem, &kgem->pinned_batches[0]);
772.14860 -+		if (bo)
772.14861 - 			goto write;
772.14862 --		}
772.14863 --
772.14864 --		if (!__kgem_busy(kgem, bo->handle)) {
772.14865 --			assert(RQ(bo->rq)->bo == bo);
772.14866 --			__kgem_retire_rq(kgem, RQ(bo->rq));
772.14867 --			goto out_4096;
772.14868 --		}
772.14869 - 	}
772.14870 - 
772.14871 --	if (size <= 16384) {
772.14872 --		bo = list_first_entry(&kgem->pinned_batches[1],
772.14873 --				      struct kgem_bo,
772.14874 --				      list);
772.14875 --		if (!bo->rq) {
772.14876 --out_16384:
772.14877 --			assert(bo->refcnt > 0);
772.14878 --			list_move_tail(&bo->list, &kgem->pinned_batches[1]);
772.14879 --			bo = kgem_bo_reference(bo);
772.14880 --			goto write;
772.14881 --		}
772.14882 --
772.14883 --		if (!__kgem_busy(kgem, bo->handle)) {
772.14884 --			__kgem_retire_rq(kgem, RQ(bo->rq));
772.14885 --			goto out_16384;
772.14886 --		}
772.14887 -+	if (size <= 16384) {
772.14888 -+		bo = first_available(kgem, &kgem->pinned_batches[1]);
772.14889 -+		if (bo)
772.14890 -+			goto write;
772.14891 - 	}
772.14892 - 
772.14893 - 	if (kgem->gen == 020) {
772.14894 -@@ -3443,16 +3981,8 @@ out_16384:
772.14895 - 			list_move_tail(&bo->list, &kgem->pinned_batches[size > 4096]);
772.14896 - 
772.14897 - 			DBG(("%s: syncing due to busy batches\n", __FUNCTION__));
772.14898 --
772.14899 --			VG_CLEAR(set_domain);
772.14900 --			set_domain.handle = bo->handle;
772.14901 --			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.14902 --			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.14903 --			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
772.14904 --				DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
772.14905 --				kgem_throttle(kgem);
772.14906 -+			if (kgem_bo_wait(kgem, bo))
772.14907 - 				return NULL;
772.14908 --			}
772.14909 - 
772.14910 - 			kgem_retire(kgem);
772.14911 - 			assert(bo->rq == NULL);
772.14912 -@@ -3460,9 +3990,14 @@ out_16384:
772.14913 - 			goto write;
772.14914 - 		}
772.14915 - 	}
772.14916 -+#else
772.14917 -+	if (kgem->surface != kgem->batch_size)
772.14918 -+		size = kgem->batch_size * sizeof(uint32_t);
772.14919 -+	else
772.14920 -+		size = kgem->nbatch * sizeof(uint32_t);
772.14921 -+#endif
772.14922 - 
772.14923 --	bo = NULL;
772.14924 --	if (!kgem->has_llc) {
772.14925 -+	if (!kgem->batch_bo || !kgem->has_llc) {
772.14926 - 		bo = kgem_create_linear(kgem, size, CREATE_NO_THROTTLE);
772.14927 - 		if (bo) {
772.14928 - write:
772.14929 -@@ -3471,14 +4006,11 @@ write:
772.14930 - 				kgem_bo_destroy(kgem, bo);
772.14931 - 				return NULL;
772.14932 - 			}
772.14933 -+			return bo;
772.14934 - 		}
772.14935 - 	}
772.14936 --	if (bo == NULL)
772.14937 --		bo = kgem_new_batch(kgem);
772.14938 --	return bo;
772.14939 --#else
772.14940 -+
772.14941 - 	return kgem_new_batch(kgem);
772.14942 --#endif
772.14943 - }
772.14944 - 
772.14945 - #if !NDEBUG
772.14946 -@@ -3530,7 +4062,7 @@ static void dump_fence_regs(struct kgem *kgem)
772.14947 - 
772.14948 - static int do_execbuf(struct kgem *kgem, struct drm_i915_gem_execbuffer2 *execbuf)
772.14949 - {
772.14950 --	int ret, err;
772.14951 -+	int ret;
772.14952 - 
772.14953 - retry:
772.14954 - 	ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
772.14955 -@@ -3547,26 +4079,25 @@ retry:
772.14956 - 
772.14957 - 	/* last gasp */
772.14958 - 	ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
772.14959 --	if (ret == 0)
772.14960 --		return 0;
772.14961 -+	if (ret != -ENOSPC)
772.14962 -+		return ret;
772.14963 -+
772.14964 -+	/* One final trick up our sleeve for when we run out of space.
772.14965 -+	 * We turn everything off to free up our pinned framebuffers,
772.14966 -+	 * sprites and cursors, and try just one more time.
772.14967 -+	 */
772.14968 - 
772.14969 - 	xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
772.14970 - 		   "Failed to submit rendering commands, trying again with outputs disabled.\n");
772.14971 - 
772.14972 --	/* One last trick up our sleeve for when we run out of space.
772.14973 --	 * We turn everything off to free up our pinned framebuffers,
772.14974 --	 * sprites and cursors, and try one last time.
772.14975 --	 */
772.14976 --	err = errno;
772.14977 --	if (sna_mode_disable(container_of(kgem, struct sna, kgem))) {
772.14978 -+	if (sna_mode_disable(__to_sna(kgem))) {
772.14979 - 		kgem_cleanup_cache(kgem);
772.14980 - 		ret = do_ioctl(kgem->fd,
772.14981 - 			       DRM_IOCTL_I915_GEM_EXECBUFFER2,
772.14982 - 			       execbuf);
772.14983 - 		DBG(("%s: last_gasp ret=%d\n", __FUNCTION__, ret));
772.14984 --		sna_mode_enable(container_of(kgem, struct sna, kgem));
772.14985 -+		sna_mode_enable(__to_sna(kgem));
772.14986 - 	}
772.14987 --	errno = err;
772.14988 - 
772.14989 - 	return ret;
772.14990 - }
772.14991 -@@ -3575,6 +4106,7 @@ void _kgem_submit(struct kgem *kgem)
772.14992 - {
772.14993 - 	struct kgem_request *rq;
772.14994 - 	uint32_t batch_end;
772.14995 -+	int i, ret;
772.14996 - 
772.14997 - 	assert(!DBG_NO_HW);
772.14998 - 	assert(!kgem->wedged);
772.14999 -@@ -3609,7 +4141,6 @@ void _kgem_submit(struct kgem *kgem)
772.15000 - 	rq->bo = kgem_create_batch(kgem);
772.15001 - 	if (rq->bo) {
772.15002 - 		struct drm_i915_gem_execbuffer2 execbuf;
772.15003 --		int i, ret;
772.15004 - 
772.15005 - 		assert(!rq->bo->needs_flush);
772.15006 - 
772.15007 -@@ -3619,7 +4150,8 @@ void _kgem_submit(struct kgem *kgem)
772.15008 - 		kgem->exec[i].relocs_ptr = (uintptr_t)kgem->reloc;
772.15009 - 		kgem->exec[i].alignment = 0;
772.15010 - 		kgem->exec[i].offset = rq->bo->presumed_offset;
772.15011 --		kgem->exec[i].flags = 0;
772.15012 -+		/* Make sure the kernel releases any fence, ignored if gen4+ */
772.15013 -+		kgem->exec[i].flags = EXEC_OBJECT_NEEDS_FENCE;
772.15014 - 		kgem->exec[i].rsvd1 = 0;
772.15015 - 		kgem->exec[i].rsvd2 = 0;
772.15016 - 
772.15017 -@@ -3631,7 +4163,8 @@ void _kgem_submit(struct kgem *kgem)
772.15018 - 		memset(&execbuf, 0, sizeof(execbuf));
772.15019 - 		execbuf.buffers_ptr = (uintptr_t)kgem->exec;
772.15020 - 		execbuf.buffer_count = kgem->nexec;
772.15021 --		execbuf.batch_len = batch_end*sizeof(uint32_t);
772.15022 -+		if (kgem->gen < 030)
772.15023 -+			execbuf.batch_len = batch_end*sizeof(uint32_t);
772.15024 - 		execbuf.flags = kgem->ring | kgem->batch_flags;
772.15025 - 
772.15026 - 		if (DBG_DUMP) {
772.15027 -@@ -3645,91 +4178,98 @@ void _kgem_submit(struct kgem *kgem)
772.15028 - 		}
772.15029 - 
772.15030 - 		ret = do_execbuf(kgem, &execbuf);
772.15031 --		if (DEBUG_SYNC && ret == 0) {
772.15032 --			struct drm_i915_gem_set_domain set_domain;
772.15033 --
772.15034 --			VG_CLEAR(set_domain);
772.15035 --			set_domain.handle = rq->bo->handle;
772.15036 --			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.15037 --			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.15038 -+	} else
772.15039 -+		ret = -ENOMEM;
772.15040 - 
772.15041 --			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
772.15042 -+	if (ret < 0) {
772.15043 -+		kgem_throttle(kgem);
772.15044 -+		if (!kgem->wedged) {
772.15045 -+			xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
772.15046 -+				   "Failed to submit rendering commands (%s), disabling acceleration.\n",
772.15047 -+				   strerror(-ret));
772.15048 -+			__kgem_set_wedged(kgem);
772.15049 - 		}
772.15050 --		if (ret < 0) {
772.15051 --			kgem_throttle(kgem);
772.15052 --			if (!kgem->wedged) {
772.15053 --				xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
772.15054 --					   "Failed to submit rendering commands, disabling acceleration.\n");
772.15055 --				__kgem_set_wedged(kgem);
772.15056 --			}
772.15057 - 
772.15058 - #if !NDEBUG
772.15059 --			ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
772.15060 --			       kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
772.15061 --			       kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
772.15062 -+		ErrorF("batch[%d/%d]: %d %d %d, nreloc=%d, nexec=%d, nfence=%d, aperture=%d, fenced=%d, high=%d,%d: errno=%d\n",
772.15063 -+		       kgem->mode, kgem->ring, batch_end, kgem->nbatch, kgem->surface,
772.15064 -+		       kgem->nreloc, kgem->nexec, kgem->nfence, kgem->aperture, kgem->aperture_fenced, kgem->aperture_high, kgem->aperture_total, -ret);
772.15065 - 
772.15066 --			for (i = 0; i < kgem->nexec; i++) {
772.15067 --				struct kgem_bo *bo, *found = NULL;
772.15068 -+		for (i = 0; i < kgem->nexec; i++) {
772.15069 -+			struct kgem_bo *bo, *found = NULL;
772.15070 - 
772.15071 --				list_for_each_entry(bo, &kgem->next_request->buffers, request) {
772.15072 --					if (bo->handle == kgem->exec[i].handle) {
772.15073 --						found = bo;
772.15074 --						break;
772.15075 --					}
772.15076 -+			list_for_each_entry(bo, &kgem->next_request->buffers, request) {
772.15077 -+				if (bo->handle == kgem->exec[i].handle) {
772.15078 -+					found = bo;
772.15079 -+					break;
772.15080 - 				}
772.15081 --				ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
772.15082 --				       i,
772.15083 --				       kgem->exec[i].handle,
772.15084 --				       (int)kgem->exec[i].offset,
772.15085 --				       found ? kgem_bo_size(found) : -1,
772.15086 --				       found ? found->tiling : -1,
772.15087 --				       (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
772.15088 --				       found ? found->snoop : -1,
772.15089 --				       found ? found->purged : -1);
772.15090 - 			}
772.15091 --			for (i = 0; i < kgem->nreloc; i++) {
772.15092 --				ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
772.15093 --				       i,
772.15094 --				       (int)kgem->reloc[i].offset,
772.15095 --				       kgem->reloc[i].target_handle,
772.15096 --				       kgem->reloc[i].delta,
772.15097 --				       kgem->reloc[i].read_domains,
772.15098 --				       kgem->reloc[i].write_domain,
772.15099 --				       (int)kgem->reloc[i].presumed_offset);
772.15100 -+			ErrorF("exec[%d] = handle:%d, presumed offset: %x, size: %d, tiling %d, fenced %d, snooped %d, deleted %d\n",
772.15101 -+			       i,
772.15102 -+			       kgem->exec[i].handle,
772.15103 -+			       (int)kgem->exec[i].offset,
772.15104 -+			       found ? kgem_bo_size(found) : -1,
772.15105 -+			       found ? found->tiling : -1,
772.15106 -+			       (int)(kgem->exec[i].flags & EXEC_OBJECT_NEEDS_FENCE),
772.15107 -+			       found ? found->snoop : -1,
772.15108 -+			       found ? found->purged : -1);
772.15109 -+		}
772.15110 -+		for (i = 0; i < kgem->nreloc; i++) {
772.15111 -+			ErrorF("reloc[%d] = pos:%d, target:%d, delta:%d, read:%x, write:%x, offset:%x\n",
772.15112 -+			       i,
772.15113 -+			       (int)kgem->reloc[i].offset,
772.15114 -+			       kgem->reloc[i].target_handle,
772.15115 -+			       kgem->reloc[i].delta,
772.15116 -+			       kgem->reloc[i].read_domains,
772.15117 -+			       kgem->reloc[i].write_domain,
772.15118 -+			       (int)kgem->reloc[i].presumed_offset);
772.15119 -+		}
772.15120 -+
772.15121 -+		{
772.15122 -+			struct drm_i915_gem_get_aperture aperture;
772.15123 -+			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
772.15124 -+				ErrorF("Aperture size %lld, available %lld\n",
772.15125 -+				       (long long)aperture.aper_size,
772.15126 -+				       (long long)aperture.aper_available_size);
772.15127 -+		}
772.15128 -+
772.15129 -+		if (ret == -ENOSPC)
772.15130 -+			dump_gtt_info(kgem);
772.15131 -+		if (ret == -EDEADLK)
772.15132 -+			dump_fence_regs(kgem);
772.15133 -+
772.15134 -+		if (DEBUG_SYNC) {
772.15135 -+			int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
772.15136 -+			if (fd != -1) {
772.15137 -+				int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
772.15138 -+				assert(ignored == batch_end*sizeof(uint32_t));
772.15139 -+				close(fd);
772.15140 - 			}
772.15141 - 
772.15142 --			{
772.15143 --				struct drm_i915_gem_get_aperture aperture;
772.15144 --				if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture) == 0)
772.15145 --					ErrorF("Aperture size %lld, available %lld\n",
772.15146 --					       (long long)aperture.aper_size,
772.15147 --					       (long long)aperture.aper_available_size);
772.15148 --			}
772.15149 -+			FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
772.15150 -+		}
772.15151 -+#endif
772.15152 -+	} else {
772.15153 -+		if (DEBUG_SYNC) {
772.15154 -+			struct drm_i915_gem_set_domain set_domain;
772.15155 - 
772.15156 --			if (ret == -ENOSPC)
772.15157 --				dump_gtt_info(kgem);
772.15158 --			if (ret == -EDEADLK)
772.15159 --				dump_fence_regs(kgem);
772.15160 --
772.15161 --			if (DEBUG_SYNC) {
772.15162 --				int fd = open("/tmp/batchbuffer", O_WRONLY | O_CREAT | O_APPEND, 0666);
772.15163 --				if (fd != -1) {
772.15164 --					int ignored = write(fd, kgem->batch, batch_end*sizeof(uint32_t));
772.15165 --					assert(ignored == batch_end*sizeof(uint32_t));
772.15166 --					close(fd);
772.15167 --				}
772.15168 -+			VG_CLEAR(set_domain);
772.15169 -+			set_domain.handle = rq->bo->handle;
772.15170 -+			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.15171 -+			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.15172 - 
772.15173 --				FatalError("SNA: failed to submit batchbuffer, errno=%d\n", -ret);
772.15174 --			}
772.15175 --#endif
772.15176 -+			ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
772.15177 - 		}
772.15178 --	}
772.15179 -+
772.15180 - #if SHOW_BATCH_AFTER
772.15181 --	if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t)) == 0)
772.15182 --		__kgem_batch_debug(kgem, batch_end);
772.15183 -+		if (gem_read(kgem->fd, rq->bo->handle, kgem->batch, 0, batch_end*sizeof(uint32_t)) == 0)
772.15184 -+			__kgem_batch_debug(kgem, batch_end);
772.15185 - #endif
772.15186 --	kgem_commit(kgem);
772.15187 --	if (kgem->wedged)
772.15188 -+
772.15189 -+		kgem_commit(kgem);
772.15190 -+	}
772.15191 -+
772.15192 -+	if (unlikely(kgem->wedged))
772.15193 - 		kgem_cleanup(kgem);
772.15194 - 
772.15195 - 	kgem_reset(kgem);
772.15196 -@@ -3737,49 +4277,14 @@ void _kgem_submit(struct kgem *kgem)
772.15197 - 	assert(kgem->next_request != NULL);
772.15198 - }
772.15199 - 
772.15200 --static bool find_hang_state(struct kgem *kgem, char *path, int maxlen)
772.15201 --{
772.15202 --	int minor = kgem_get_minor(kgem);
772.15203 --
772.15204 --	/* Search for our hang state in a few canonical locations.
772.15205 --	 * In the unlikely event of having multiple devices, we
772.15206 --	 * will need to check which minor actually corresponds to ours.
772.15207 --	 */
772.15208 --
772.15209 --	snprintf(path, maxlen, "/sys/class/drm/card%d/error", minor);
772.15210 --	if (access(path, R_OK) == 0)
772.15211 --		return true;
772.15212 --
772.15213 --	snprintf(path, maxlen, "/sys/kernel/debug/dri/%d/i915_error_state", minor);
772.15214 --	if (access(path, R_OK) == 0)
772.15215 --		return true;
772.15216 --
772.15217 --	snprintf(path, maxlen, "/debug/dri/%d/i915_error_state", minor);
772.15218 --	if (access(path, R_OK) == 0)
772.15219 --		return true;
772.15220 --
772.15221 --	path[0] = '\0';
772.15222 --	return false;
772.15223 --}
772.15224 --
772.15225 - void kgem_throttle(struct kgem *kgem)
772.15226 - {
772.15227 --	if (kgem->wedged)
772.15228 -+	if (unlikely(kgem->wedged))
772.15229 - 		return;
772.15230 - 
772.15231 - 	if (__kgem_throttle(kgem, true)) {
772.15232 --		static int once;
772.15233 --		char path[128];
772.15234 --
772.15235 - 		xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
772.15236 - 			   "Detected a hung GPU, disabling acceleration.\n");
772.15237 --		if (!once && find_hang_state(kgem, path, sizeof(path))) {
772.15238 --			xf86DrvMsg(kgem_get_screen_index(kgem), X_ERROR,
772.15239 --				   "When reporting this, please include %s and the full dmesg.\n",
772.15240 --				   path);
772.15241 --			once = 1;
772.15242 --		}
772.15243 --
772.15244 - 		__kgem_set_wedged(kgem);
772.15245 - 		kgem->need_throttle = false;
772.15246 - 	}
772.15247 -@@ -3860,7 +4365,8 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15248 - 	bool idle;
772.15249 - 	unsigned int i;
772.15250 - 
772.15251 --	time(&now);
772.15252 -+	if (!time(&now))
772.15253 -+		return false;
772.15254 - 
772.15255 - 	while (__kgem_freed_bo) {
772.15256 - 		bo = __kgem_freed_bo;
772.15257 -@@ -3875,7 +4381,7 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15258 - 	}
772.15259 - 
772.15260 - 	kgem_clean_large_cache(kgem);
772.15261 --	if (container_of(kgem, struct sna, kgem)->scrn->vtSema)
772.15262 -+	if (__to_sna(kgem)->scrn->vtSema)
772.15263 - 		kgem_clean_scanout_cache(kgem);
772.15264 - 
772.15265 - 	expire = 0;
772.15266 -@@ -3885,6 +4391,7 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15267 - 			break;
772.15268 - 		}
772.15269 - 
772.15270 -+		assert(now);
772.15271 - 		bo->delta = now;
772.15272 - 	}
772.15273 - 	if (expire) {
772.15274 -@@ -3909,7 +4416,7 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15275 - #endif
772.15276 - 
772.15277 - 	kgem_retire(kgem);
772.15278 --	if (kgem->wedged)
772.15279 -+	if (unlikely(kgem->wedged))
772.15280 - 		kgem_cleanup(kgem);
772.15281 - 
772.15282 - 	kgem->expire(kgem);
772.15283 -@@ -3930,6 +4437,8 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15284 - 				break;
772.15285 - 			}
772.15286 - 
772.15287 -+			assert(now);
772.15288 -+			kgem_bo_set_purgeable(kgem, bo);
772.15289 - 			bo->delta = now;
772.15290 - 		}
772.15291 - 	}
772.15292 -@@ -3960,16 +4469,11 @@ bool kgem_expire_cache(struct kgem *kgem)
772.15293 - 				count++;
772.15294 - 				size += bytes(bo);
772.15295 - 				kgem_bo_free(kgem, bo);
772.15296 --				DBG(("%s: expiring %d\n",
772.15297 -+				DBG(("%s: expiring handle=%d\n",
772.15298 - 				     __FUNCTION__, bo->handle));
772.15299 - 			}
772.15300 - 		}
772.15301 --		if (!list_is_empty(&preserve)) {
772.15302 --			preserve.prev->next = kgem->inactive[i].next;
772.15303 --			kgem->inactive[i].next->prev = preserve.prev;
772.15304 --			kgem->inactive[i].next = preserve.next;
772.15305 --			preserve.next->prev = &kgem->inactive[i];
772.15306 --		}
772.15307 -+		list_splice_tail(&preserve, &kgem->inactive[i]);
772.15308 - 	}
772.15309 - 
772.15310 - #ifdef DEBUG_MEMORY
772.15311 -@@ -3998,31 +4502,30 @@ bool kgem_cleanup_cache(struct kgem *kgem)
772.15312 - 	unsigned int i;
772.15313 - 	int n;
772.15314 - 
772.15315 -+	DBG(("%s\n", __FUNCTION__));
772.15316 -+
772.15317 - 	/* sync to the most recent request */
772.15318 - 	for (n = 0; n < ARRAY_SIZE(kgem->requests); n++) {
772.15319 - 		if (!list_is_empty(&kgem->requests[n])) {
772.15320 - 			struct kgem_request *rq;
772.15321 --			struct drm_i915_gem_set_domain set_domain;
772.15322 - 
772.15323 --			rq = list_first_entry(&kgem->requests[n],
772.15324 --					      struct kgem_request,
772.15325 --					      list);
772.15326 -+			rq = list_last_entry(&kgem->requests[n],
772.15327 -+					     struct kgem_request,
772.15328 -+					     list);
772.15329 - 
772.15330 - 			DBG(("%s: sync on cleanup\n", __FUNCTION__));
772.15331 --
772.15332 --			VG_CLEAR(set_domain);
772.15333 --			set_domain.handle = rq->bo->handle;
772.15334 --			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.15335 --			set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.15336 --			(void)do_ioctl(kgem->fd,
772.15337 --				       DRM_IOCTL_I915_GEM_SET_DOMAIN,
772.15338 --				       &set_domain);
772.15339 -+			assert(rq->ring == n);
772.15340 -+			assert(rq->bo);
772.15341 -+			assert(RQ(rq->bo->rq) == rq);
772.15342 -+			kgem_bo_wait(kgem, rq->bo);
772.15343 - 		}
772.15344 -+		assert(list_is_empty(&kgem->requests[n]));
772.15345 - 	}
772.15346 - 
772.15347 - 	kgem_retire(kgem);
772.15348 - 	kgem_cleanup(kgem);
772.15349 - 
772.15350 -+	DBG(("%s: need_expire?=%d\n", __FUNCTION__, kgem->need_expire));
772.15351 - 	if (!kgem->need_expire)
772.15352 - 		return false;
772.15353 - 
772.15354 -@@ -4049,6 +4552,8 @@ bool kgem_cleanup_cache(struct kgem *kgem)
772.15355 - 
772.15356 - 	kgem->need_purge = false;
772.15357 - 	kgem->need_expire = false;
772.15358 -+
772.15359 -+	DBG(("%s: complete\n", __FUNCTION__));
772.15360 - 	return true;
772.15361 - }
772.15362 - 
772.15363 -@@ -4079,16 +4584,15 @@ retry_large:
772.15364 - 				goto discard;
772.15365 - 
772.15366 - 			if (bo->tiling != I915_TILING_NONE) {
772.15367 --				if (use_active)
772.15368 -+				if (use_active && kgem->gen < 040)
772.15369 - 					goto discard;
772.15370 - 
772.15371 --				if (!gem_set_tiling(kgem->fd, bo->handle,
772.15372 -+				if (!kgem_set_tiling(kgem, bo,
772.15373 - 						    I915_TILING_NONE, 0))
772.15374 - 					goto discard;
772.15375 --
772.15376 --				bo->tiling = I915_TILING_NONE;
772.15377 --				bo->pitch = 0;
772.15378 - 			}
772.15379 -+			assert(bo->tiling == I915_TILING_NONE);
772.15380 -+			bo->pitch = 0;
772.15381 - 
772.15382 - 			if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo))
772.15383 - 				goto discard;
772.15384 -@@ -4169,17 +4673,17 @@ discard:
772.15385 - 				break;
772.15386 - 			}
772.15387 - 
772.15388 --			if (I915_TILING_NONE != bo->tiling &&
772.15389 --			    !gem_set_tiling(kgem->fd, bo->handle,
772.15390 --					    I915_TILING_NONE, 0))
772.15391 --				continue;
772.15392 -+			if (!kgem_set_tiling(kgem, bo, I915_TILING_NONE, 0)) {
772.15393 -+				kgem_bo_free(kgem, bo);
772.15394 -+				break;
772.15395 -+			}
772.15396 - 
772.15397 - 			kgem_bo_remove_from_inactive(kgem, bo);
772.15398 - 			assert(list_is_empty(&bo->vma));
772.15399 - 			assert(list_is_empty(&bo->list));
772.15400 - 
772.15401 --			bo->tiling = I915_TILING_NONE;
772.15402 --			bo->pitch = 0;
772.15403 -+			assert(bo->tiling == I915_TILING_NONE);
772.15404 -+			assert(bo->pitch == 0);
772.15405 - 			bo->delta = 0;
772.15406 - 			DBG(("  %s: found handle=%d (num_pages=%d) in linear vma cache\n",
772.15407 - 			     __FUNCTION__, bo->handle, num_pages(bo)));
772.15408 -@@ -4225,13 +4729,13 @@ discard:
772.15409 - 			if (first)
772.15410 - 				continue;
772.15411 - 
772.15412 --			if (!gem_set_tiling(kgem->fd, bo->handle,
772.15413 --					    I915_TILING_NONE, 0))
772.15414 --				continue;
772.15415 --
772.15416 --			bo->tiling = I915_TILING_NONE;
772.15417 --			bo->pitch = 0;
772.15418 -+			if (!kgem_set_tiling(kgem, bo, I915_TILING_NONE, 0)) {
772.15419 -+				kgem_bo_free(kgem, bo);
772.15420 -+				break;
772.15421 -+			}
772.15422 - 		}
772.15423 -+		assert(bo->tiling == I915_TILING_NONE);
772.15424 -+		bo->pitch = 0;
772.15425 - 
772.15426 - 		if (bo->map__gtt || bo->map__wc || bo->map__cpu) {
772.15427 - 			if (flags & (CREATE_CPU_MAP | CREATE_GTT_MAP)) {
772.15428 -@@ -4269,7 +4773,7 @@ discard:
772.15429 - 			kgem_bo_remove_from_inactive(kgem, bo);
772.15430 - 
772.15431 - 		assert(bo->tiling == I915_TILING_NONE);
772.15432 --		bo->pitch = 0;
772.15433 -+		assert(bo->pitch == 0);
772.15434 - 		bo->delta = 0;
772.15435 - 		DBG(("  %s: found handle=%d (num_pages=%d) in linear %s cache\n",
772.15436 - 		     __FUNCTION__, bo->handle, num_pages(bo),
772.15437 -@@ -4340,9 +4844,9 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
772.15438 - 
772.15439 - 	bo->unique_id = kgem_get_unique_id(kgem);
772.15440 - 	bo->tiling = tiling.tiling_mode;
772.15441 --	bo->reusable = false;
772.15442 - 	bo->prime = true;
772.15443 --	bo->purged = true; /* no coherency guarantees */
772.15444 -+	bo->reusable = false;
772.15445 -+	kgem_bo_unclean(kgem, bo);
772.15446 - 
772.15447 - 	debug_alloc__bo(kgem, bo);
772.15448 - 	return bo;
772.15449 -@@ -4448,6 +4952,8 @@ int kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo)
772.15450 - #if defined(DRM_IOCTL_PRIME_HANDLE_TO_FD) && defined(O_CLOEXEC)
772.15451 - 	struct drm_prime_handle args;
772.15452 - 
772.15453 -+	assert(kgem_bo_is_fenced(kgem, bo));
772.15454 -+
772.15455 - 	VG_CLEAR(args);
772.15456 - 	args.handle = bo->handle;
772.15457 - 	args.flags = O_CLOEXEC;
772.15458 -@@ -4479,6 +4985,8 @@ struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags)
772.15459 - 	if ((flags & CREATE_UNCACHED) == 0) {
772.15460 - 		bo = search_linear_cache(kgem, size, CREATE_INACTIVE | flags);
772.15461 - 		if (bo) {
772.15462 -+			assert(!bo->purged);
772.15463 -+			assert(!bo->delta);
772.15464 - 			assert(bo->domain != DOMAIN_GPU);
772.15465 - 			ASSERT_IDLE(kgem, bo->handle);
772.15466 - 			bo->refcnt = 1;
772.15467 -@@ -4760,8 +5268,7 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
772.15468 - 				   struct kgem_bo *bo,
772.15469 - 				   int width, int height)
772.15470 - {
772.15471 --	ScrnInfoPtr scrn =
772.15472 --		container_of(kgem, struct sna, kgem)->scrn;
772.15473 -+	ScrnInfoPtr scrn = __to_sna(kgem)->scrn;
772.15474 - 	struct drm_mode_fb_cmd arg;
772.15475 - 
772.15476 - 	assert(bo->proxy == NULL);
772.15477 -@@ -4809,6 +5316,48 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
772.15478 - 	}
772.15479 - }
772.15480 - 
772.15481 -+static bool tiling_changed(struct kgem_bo *bo, int tiling, int pitch)
772.15482 -+{
772.15483 -+	if (tiling != bo->tiling)
772.15484 -+		return true;
772.15485 -+
772.15486 -+	return tiling != I915_TILING_NONE && pitch != bo->pitch;
772.15487 -+}
772.15488 -+
772.15489 -+static void set_gpu_tiling(struct kgem *kgem,
772.15490 -+			   struct kgem_bo *bo,
772.15491 -+			   int tiling, int pitch)
772.15492 -+{
772.15493 -+	DBG(("%s: handle=%d, tiling=%d, pitch=%d\n",
772.15494 -+	     __FUNCTION__, bo->handle, tiling, pitch));
772.15495 -+
772.15496 -+	if (tiling_changed(bo, tiling, pitch) && bo->map__gtt) {
772.15497 -+		if (!list_is_empty(&bo->vma)) {
772.15498 -+			list_del(&bo->vma);
772.15499 -+			kgem->vma[0].count--;
772.15500 -+		}
772.15501 -+		munmap(bo->map__gtt, bytes(bo));
772.15502 -+		bo->map__gtt = NULL;
772.15503 -+	}
772.15504 -+
772.15505 -+	bo->tiling = tiling;
772.15506 -+	bo->pitch = pitch;
772.15507 -+}
772.15508 -+
772.15509 -+bool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo)
772.15510 -+{
772.15511 -+	struct drm_i915_gem_get_tiling tiling;
772.15512 -+
772.15513 -+	assert(kgem);
772.15514 -+	assert(bo);
772.15515 -+
772.15516 -+	VG_CLEAR(tiling);
772.15517 -+	tiling.handle = bo->handle;
772.15518 -+	tiling.tiling_mode = bo->tiling;
772.15519 -+	(void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling);
772.15520 -+	return tiling.tiling_mode == bo->tiling; /* assume pitch is fine! */
772.15521 -+}
772.15522 -+
772.15523 - struct kgem_bo *kgem_create_2d(struct kgem *kgem,
772.15524 - 			       int width,
772.15525 - 			       int height,
772.15526 -@@ -4892,8 +5441,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
772.15527 - 			return last;
772.15528 - 		}
772.15529 - 
772.15530 --		if (container_of(kgem, struct sna, kgem)->scrn->vtSema) {
772.15531 --			ScrnInfoPtr scrn = container_of(kgem, struct sna, kgem)->scrn;
772.15532 -+		if (__to_sna(kgem)->scrn->vtSema) {
772.15533 -+			ScrnInfoPtr scrn = __to_sna(kgem)->scrn;
772.15534 - 
772.15535 - 			list_for_each_entry_reverse(bo, &kgem->scanout, list) {
772.15536 - 				struct drm_mode_fb_cmd arg;
772.15537 -@@ -4915,11 +5464,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
772.15538 - 						bo->delta = 0;
772.15539 - 					}
772.15540 - 
772.15541 --					if (gem_set_tiling(kgem->fd, bo->handle,
772.15542 --							   tiling, pitch)) {
772.15543 --						bo->tiling = tiling;
772.15544 --						bo->pitch = pitch;
772.15545 --					} else {
772.15546 -+					if (!kgem_set_tiling(kgem, bo,
772.15547 -+							     tiling, pitch)) {
772.15548 - 						kgem_bo_free(kgem, bo);
772.15549 - 						break;
772.15550 - 					}
772.15551 -@@ -4950,6 +5496,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
772.15552 - 			}
772.15553 - 		}
772.15554 - 
772.15555 -+		if (flags & CREATE_CACHED)
772.15556 -+			return NULL;
772.15557 -+
772.15558 - 		bo = __kgem_bo_create_as_display(kgem, size, tiling, pitch);
772.15559 - 		if (bo)
772.15560 - 			return bo;
772.15561 -@@ -4987,14 +5536,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
772.15562 - 				if (num_pages(bo) < size)
772.15563 - 					continue;
772.15564 - 
772.15565 --				if (bo->pitch != pitch || bo->tiling != tiling) {
772.15566 --					if (!gem_set_tiling(kgem->fd, bo->handle,
772.15567 --							    tiling, pitch))
772.15568 --						continue;
772.15569 --
772.15570 --					bo->pitch = pitch;
772.15571 --					bo->tiling = tiling;
772.15572 --				}
772.15573 -+				if (!kgem_set_tiling(kgem, bo, tiling, pitch) &&
772.15574 -+				    !exact)
772.15575 -+					set_gpu_tiling(kgem, bo, tiling, pitch);
772.15576 - 			}
772.15577 - 
772.15578 - 			kgem_bo_remove_from_active(kgem, bo);
772.15579 -@@ -5020,14 +5564,11 @@ large_inactive:
772.15580 - 			if (size > num_pages(bo))
772.15581 - 				continue;
772.15582 - 
772.15583 --			if (bo->tiling != tiling ||
772.15584 --			    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
772.15585 --				if (!gem_set_tiling(kgem->fd, bo->handle,
772.15586 --						    tiling, pitch))
772.15587 -+			if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
772.15588 -+				if (kgem->gen >= 040 && !exact)
772.15589 -+					set_gpu_tiling(kgem, bo, tiling, pitch);
772.15590 -+				else
772.15591 - 					continue;
772.15592 --
772.15593 --				bo->tiling = tiling;
772.15594 --				bo->pitch = pitch;
772.15595 - 			}
772.15596 - 
772.15597 - 			if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
772.15598 -@@ -5039,7 +5580,6 @@ large_inactive:
772.15599 - 
772.15600 - 			assert(bo->domain != DOMAIN_GPU);
772.15601 - 			bo->unique_id = kgem_get_unique_id(kgem);
772.15602 --			bo->pitch = pitch;
772.15603 - 			bo->delta = 0;
772.15604 - 			DBG(("  1:from large inactive: pitch=%d, tiling=%d, handle=%d, id=%d\n",
772.15605 - 			     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
772.15606 -@@ -5088,14 +5628,13 @@ large_inactive:
772.15607 - 				if (bo->tiling != tiling ||
772.15608 - 				    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
772.15609 - 					if (bo->map__gtt ||
772.15610 --					    !gem_set_tiling(kgem->fd, bo->handle,
772.15611 --							    tiling, pitch)) {
772.15612 -+					    !kgem_set_tiling(kgem, bo,
772.15613 -+							     tiling, pitch)) {
772.15614 - 						DBG(("inactive GTT vma with wrong tiling: %d < %d\n",
772.15615 - 						     bo->tiling, tiling));
772.15616 --						continue;
772.15617 -+						kgem_bo_free(kgem, bo);
772.15618 -+						break;
772.15619 - 					}
772.15620 --					bo->tiling = tiling;
772.15621 --					bo->pitch = pitch;
772.15622 - 				}
772.15623 - 
772.15624 - 				if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
772.15625 -@@ -5103,8 +5642,11 @@ large_inactive:
772.15626 - 					break;
772.15627 - 				}
772.15628 - 
772.15629 -+				if (tiling == I915_TILING_NONE)
772.15630 -+					bo->pitch = pitch;
772.15631 -+
772.15632 - 				assert(bo->tiling == tiling);
772.15633 --				bo->pitch = pitch;
772.15634 -+				assert(bo->pitch >= pitch);
772.15635 - 				bo->delta = 0;
772.15636 - 				bo->unique_id = kgem_get_unique_id(kgem);
772.15637 - 
772.15638 -@@ -5170,15 +5712,12 @@ search_active:
772.15639 - 				if (num_pages(bo) < size)
772.15640 - 					continue;
772.15641 - 
772.15642 --				if (bo->pitch != pitch) {
772.15643 --					if (!gem_set_tiling(kgem->fd,
772.15644 --							    bo->handle,
772.15645 --							    tiling, pitch))
772.15646 --						continue;
772.15647 --
772.15648 --					bo->pitch = pitch;
772.15649 --				}
772.15650 -+				if (!kgem_set_tiling(kgem, bo, tiling, pitch) &&
772.15651 -+				    !exact)
772.15652 -+					set_gpu_tiling(kgem, bo, tiling, pitch);
772.15653 - 			}
772.15654 -+			assert(bo->tiling == tiling);
772.15655 -+			assert(bo->pitch >= pitch);
772.15656 - 
772.15657 - 			kgem_bo_remove_from_active(kgem, bo);
772.15658 - 
772.15659 -@@ -5233,19 +5772,21 @@ search_active:
772.15660 - 				if (num_pages(bo) < size)
772.15661 - 					continue;
772.15662 - 
772.15663 --				if (bo->tiling != tiling ||
772.15664 --				    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
772.15665 --					if (!gem_set_tiling(kgem->fd,
772.15666 --							    bo->handle,
772.15667 --							    tiling, pitch))
772.15668 --						continue;
772.15669 -+				if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
772.15670 -+					if (kgem->gen >= 040 && !exact) {
772.15671 -+						set_gpu_tiling(kgem, bo,
772.15672 -+							       tiling, pitch);
772.15673 -+					} else {
772.15674 -+						kgem_bo_free(kgem, bo);
772.15675 -+						break;
772.15676 -+					}
772.15677 - 				}
772.15678 -+				assert(bo->tiling == tiling);
772.15679 -+				assert(bo->pitch >= pitch);
772.15680 - 
772.15681 - 				kgem_bo_remove_from_active(kgem, bo);
772.15682 - 
772.15683 - 				bo->unique_id = kgem_get_unique_id(kgem);
772.15684 --				bo->pitch = pitch;
772.15685 --				bo->tiling = tiling;
772.15686 - 				bo->delta = 0;
772.15687 - 				DBG(("  1:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
772.15688 - 				     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
772.15689 -@@ -5323,11 +5864,13 @@ search_inactive:
772.15690 - 			continue;
772.15691 - 		}
772.15692 - 
772.15693 --		if (bo->tiling != tiling ||
772.15694 --		    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
772.15695 --			if (!gem_set_tiling(kgem->fd, bo->handle,
772.15696 --					    tiling, pitch))
772.15697 --				continue;
772.15698 -+		if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
772.15699 -+			if (kgem->gen >= 040 && !exact) {
772.15700 -+				set_gpu_tiling(kgem, bo, tiling, pitch);
772.15701 -+			} else {
772.15702 -+				kgem_bo_free(kgem, bo);
772.15703 -+				break;
772.15704 -+			}
772.15705 - 		}
772.15706 - 
772.15707 - 		if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) {
772.15708 -@@ -5338,9 +5881,8 @@ search_inactive:
772.15709 - 		kgem_bo_remove_from_inactive(kgem, bo);
772.15710 - 		assert(list_is_empty(&bo->list));
772.15711 - 		assert(list_is_empty(&bo->vma));
772.15712 --
772.15713 --		bo->pitch = pitch;
772.15714 --		bo->tiling = tiling;
772.15715 -+		assert(bo->tiling == tiling);
772.15716 -+		assert(bo->pitch >= pitch);
772.15717 - 
772.15718 - 		bo->delta = 0;
772.15719 - 		bo->unique_id = kgem_get_unique_id(kgem);
772.15720 -@@ -5388,14 +5930,17 @@ search_inactive:
772.15721 - 			kgem_bo_remove_from_active(kgem, bo);
772.15722 - 			__kgem_bo_clear_busy(bo);
772.15723 - 
772.15724 --			if (tiling != I915_TILING_NONE && bo->pitch != pitch) {
772.15725 --				if (!gem_set_tiling(kgem->fd, bo->handle, tiling, pitch)) {
772.15726 -+			if (!kgem_set_tiling(kgem, bo, tiling, pitch)) {
772.15727 -+				if (kgem->gen >= 040 && !exact) {
772.15728 -+					set_gpu_tiling(kgem, bo, tiling, pitch);
772.15729 -+				} else {
772.15730 - 					kgem_bo_free(kgem, bo);
772.15731 - 					goto no_retire;
772.15732 - 				}
772.15733 - 			}
772.15734 -+			assert(bo->tiling == tiling);
772.15735 -+			assert(bo->pitch >= pitch);
772.15736 - 
772.15737 --			bo->pitch = pitch;
772.15738 - 			bo->unique_id = kgem_get_unique_id(kgem);
772.15739 - 			bo->delta = 0;
772.15740 - 			DBG(("  2:from active: pitch=%d, tiling=%d, handle=%d, id=%d\n",
772.15741 -@@ -5440,18 +5985,21 @@ create:
772.15742 - 	}
772.15743 - 
772.15744 - 	bo->unique_id = kgem_get_unique_id(kgem);
772.15745 --	if (tiling == I915_TILING_NONE ||
772.15746 --	    gem_set_tiling(kgem->fd, handle, tiling, pitch)) {
772.15747 --		bo->tiling = tiling;
772.15748 --		bo->pitch = pitch;
772.15749 -+	if (kgem_set_tiling(kgem, bo, tiling, pitch)) {
772.15750 - 		if (flags & CREATE_SCANOUT)
772.15751 - 			__kgem_bo_make_scanout(kgem, bo, width, height);
772.15752 - 	} else {
772.15753 --		if (flags & CREATE_EXACT) {
772.15754 --			DBG(("%s: failed to set exact tiling (gem_set_tiling)\n", __FUNCTION__));
772.15755 --			gem_close(kgem->fd, handle);
772.15756 --			free(bo);
772.15757 --			return NULL;
772.15758 -+		if (kgem->gen >= 040) {
772.15759 -+			assert(!kgem->can_fence);
772.15760 -+			bo->tiling = tiling;
772.15761 -+			bo->pitch = pitch;
772.15762 -+		} else {
772.15763 -+			if (flags & CREATE_EXACT) {
772.15764 -+				DBG(("%s: failed to set exact tiling (gem_set_tiling)\n", __FUNCTION__));
772.15765 -+				gem_close(kgem->fd, handle);
772.15766 -+				free(bo);
772.15767 -+				return NULL;
772.15768 -+			}
772.15769 - 		}
772.15770 - 	}
772.15771 - 
772.15772 -@@ -5608,7 +6156,7 @@ static void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo)
772.15773 - 
772.15774 - void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
772.15775 - {
772.15776 --	if (!bo->needs_flush)
772.15777 -+	if (!bo->needs_flush && !bo->gtt_dirty)
772.15778 - 		return;
772.15779 - 
772.15780 - 	kgem_bo_submit(kgem, bo);
772.15781 -@@ -5621,18 +6169,24 @@ void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
772.15782 - 	if (bo->rq)
772.15783 - 		__kgem_flush(kgem, bo);
772.15784 - 
772.15785 -+	if (bo->scanout && kgem->needs_dirtyfb) {
772.15786 -+		struct drm_mode_fb_dirty_cmd cmd;
772.15787 -+		memset(&cmd, 0, sizeof(cmd));
772.15788 -+		cmd.fb_id = bo->delta;
772.15789 -+		(void)drmIoctl(kgem->fd, DRM_IOCTL_MODE_DIRTYFB, &cmd);
772.15790 -+	}
772.15791 -+
772.15792 - 	/* Whatever actually happens, we can regard the GTT write domain
772.15793 - 	 * as being flushed.
772.15794 - 	 */
772.15795 --	bo->gtt_dirty = false;
772.15796 --	bo->needs_flush = false;
772.15797 --	bo->domain = DOMAIN_NONE;
772.15798 -+	__kgem_bo_clear_dirty(bo);
772.15799 - }
772.15800 - 
772.15801 - inline static bool nearly_idle(struct kgem *kgem)
772.15802 - {
772.15803 - 	int ring = kgem->ring == KGEM_BLT;
772.15804 - 
772.15805 -+	assert(ring < ARRAY_SIZE(kgem->requests));
772.15806 - 	if (list_is_singular(&kgem->requests[ring]))
772.15807 - 		return true;
772.15808 - 
772.15809 -@@ -5720,7 +6274,7 @@ static inline bool kgem_flush(struct kgem *kgem, bool flush)
772.15810 - 	if (kgem->nreloc == 0)
772.15811 - 		return true;
772.15812 - 
772.15813 --	if (container_of(kgem, struct sna, kgem)->flags & SNA_POWERSAVE)
772.15814 -+	if (__to_sna(kgem)->flags & SNA_POWERSAVE)
772.15815 - 		return true;
772.15816 - 
772.15817 - 	if (kgem->flush == flush && kgem->aperture < kgem->aperture_low)
772.15818 -@@ -5982,6 +6536,55 @@ bool kgem_check_many_bo_fenced(struct kgem *kgem, ...)
772.15819 - 	return kgem_flush(kgem, flush);
772.15820 - }
772.15821 - 
772.15822 -+void __kgem_bcs_set_tiling(struct kgem *kgem,
772.15823 -+			   struct kgem_bo *src,
772.15824 -+			   struct kgem_bo *dst)
772.15825 -+{
772.15826 -+	uint32_t state, *b;
772.15827 -+
772.15828 -+	DBG(("%s: src handle=%d:tiling=%d, dst handle=%d:tiling=%d\n",
772.15829 -+	     __FUNCTION__,
772.15830 -+	     src ? src->handle : 0, src ? src->tiling : 0,
772.15831 -+	     dst ? dst->handle : 0, dst ? dst->tiling : 0));
772.15832 -+	assert(kgem->mode == KGEM_BLT);
772.15833 -+	assert(dst == NULL || kgem_bo_can_blt(kgem, dst));
772.15834 -+	assert(src == NULL || kgem_bo_can_blt(kgem, src));
772.15835 -+
772.15836 -+	state = 0;
772.15837 -+	if (dst && dst->tiling == I915_TILING_Y)
772.15838 -+		state |= BCS_DST_Y;
772.15839 -+	if (src && src->tiling == I915_TILING_Y)
772.15840 -+		state |= BCS_SRC_Y;
772.15841 -+
772.15842 -+	if (kgem->bcs_state == state)
772.15843 -+		return;
772.15844 -+
772.15845 -+	DBG(("%s: updating SWCTRL %x -> %x\n", __FUNCTION__,
772.15846 -+	     kgem->bcs_state, state));
772.15847 -+
772.15848 -+	/* Over-estimate space in case we need to re-emit the cmd packet */
772.15849 -+	if (!kgem_check_batch(kgem, 24)) {
772.15850 -+		_kgem_submit(kgem);
772.15851 -+		_kgem_set_mode(kgem, KGEM_BLT);
772.15852 -+		if (state == 0)
772.15853 -+			return;
772.15854 -+	}
772.15855 -+
772.15856 -+	b = kgem->batch + kgem->nbatch;
772.15857 -+	if (kgem->nbatch) {
772.15858 -+		*b++ = MI_FLUSH_DW;
772.15859 -+		*b++ = 0;
772.15860 -+		*b++ = 0;
772.15861 -+		*b++ = 0;
772.15862 -+	}
772.15863 -+	*b++ = MI_LOAD_REGISTER_IMM;
772.15864 -+	*b++ = BCS_SWCTRL;
772.15865 -+	*b++ = (BCS_SRC_Y | BCS_DST_Y) << 16 | state;
772.15866 -+	kgem->nbatch = b - kgem->batch;
772.15867 -+
772.15868 -+	kgem->bcs_state = state;
772.15869 -+}
772.15870 -+
772.15871 - uint32_t kgem_add_reloc(struct kgem *kgem,
772.15872 - 			uint32_t pos,
772.15873 - 			struct kgem_bo *bo,
772.15874 -@@ -6195,12 +6798,6 @@ static void kgem_trim_vma_cache(struct kgem *kgem, int type, int bucket)
772.15875 - 
772.15876 - 		list_del(&bo->vma);
772.15877 - 		kgem->vma[type].count--;
772.15878 --
772.15879 --		if (!bo->purged && !kgem_bo_set_purgeable(kgem, bo)) {
772.15880 --			DBG(("%s: freeing unpurgeable old mapping\n",
772.15881 --			     __FUNCTION__));
772.15882 --			kgem_bo_free(kgem, bo);
772.15883 --		}
772.15884 - 	}
772.15885 - }
772.15886 - 
772.15887 -@@ -6216,8 +6813,8 @@ static void *__kgem_bo_map__gtt_or_wc(struct kgem *kgem, struct kgem_bo *bo)
772.15888 - 	kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
772.15889 - 
772.15890 - 	if (bo->tiling || !kgem->has_wc_mmap) {
772.15891 --		assert(num_pages(bo) <= kgem->aperture_mappable / 2);
772.15892 - 		assert(kgem->gen != 021 || bo->tiling != I915_TILING_Y);
772.15893 -+		warn_unless(num_pages(bo) <= kgem->aperture_mappable / 2);
772.15894 - 
772.15895 - 		ptr = bo->map__gtt;
772.15896 - 		if (ptr == NULL)
772.15897 -@@ -6291,6 +6888,7 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
772.15898 - 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
772.15899 - 			kgem_throttle(kgem);
772.15900 - 		}
772.15901 -+		bo->needs_flush = false;
772.15902 - 		kgem_bo_retire(kgem, bo);
772.15903 - 		bo->domain = DOMAIN_GTT;
772.15904 - 		bo->gtt_dirty = true;
772.15905 -@@ -6319,14 +6917,16 @@ void *kgem_bo_map__wc(struct kgem *kgem, struct kgem_bo *bo)
772.15906 - 	     bo->handle, (long)bo->presumed_offset, bo->tiling, bo->map__gtt, bo->map__cpu, bo->domain));
772.15907 - 
772.15908 - 	assert(bo->proxy == NULL);
772.15909 --	assert(bo->exec == NULL);
772.15910 - 	assert(list_is_empty(&bo->list));
772.15911 - 	assert_tiling(kgem, bo);
772.15912 - 	assert(!bo->purged || bo->reusable);
772.15913 - 
772.15914 - 	if (bo->map__wc)
772.15915 - 		return bo->map__wc;
772.15916 -+	if (!kgem->has_wc_mmap)
772.15917 -+		return NULL;
772.15918 - 
772.15919 -+	kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
772.15920 - 	return __kgem_bo_map__wc(kgem, bo);
772.15921 - }
772.15922 - 
772.15923 -@@ -6373,6 +6973,8 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
772.15924 - {
772.15925 - 	struct drm_gem_flink flink;
772.15926 - 
772.15927 -+	assert(kgem_bo_is_fenced(kgem, bo));
772.15928 -+
772.15929 - 	VG_CLEAR(flink);
772.15930 - 	flink.handle = bo->handle;
772.15931 - 	if (do_ioctl(kgem->fd, DRM_IOCTL_GEM_FLINK, &flink))
772.15932 -@@ -6387,7 +6989,6 @@ uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
772.15933 - 	 * party, we track the lifetime accurately.
772.15934 - 	 */
772.15935 - 	bo->reusable = false;
772.15936 --
772.15937 - 	kgem_bo_unclean(kgem, bo);
772.15938 - 
772.15939 - 	return flink.name;
772.15940 -@@ -6411,16 +7012,34 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
772.15941 - 	first_page = (uintptr_t)ptr;
772.15942 - 	last_page = first_page + size + PAGE_SIZE - 1;
772.15943 - 
772.15944 --	first_page &= ~(PAGE_SIZE-1);
772.15945 --	last_page &= ~(PAGE_SIZE-1);
772.15946 -+	first_page &= ~(uintptr_t)(PAGE_SIZE-1);
772.15947 -+	last_page &= ~(uintptr_t)(PAGE_SIZE-1);
772.15948 - 	assert(last_page > first_page);
772.15949 - 
772.15950 - 	handle = gem_userptr(kgem->fd,
772.15951 - 			     (void *)first_page, last_page-first_page,
772.15952 - 			     read_only);
772.15953 - 	if (handle == 0) {
772.15954 --		DBG(("%s: import failed, errno=%d\n", __FUNCTION__, errno));
772.15955 --		return NULL;
772.15956 -+		if (read_only && kgem->has_wc_mmap) {
772.15957 -+			struct drm_i915_gem_set_domain set_domain;
772.15958 -+
772.15959 -+			handle = gem_userptr(kgem->fd,
772.15960 -+					     (void *)first_page, last_page-first_page,
772.15961 -+					     false);
772.15962 -+
772.15963 -+			VG_CLEAR(set_domain);
772.15964 -+			set_domain.handle = handle;
772.15965 -+			set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.15966 -+			set_domain.write_domain = 0;
772.15967 -+			if (do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
772.15968 -+				gem_close(kgem->fd, handle);
772.15969 -+				handle = 0;
772.15970 -+			}
772.15971 -+		}
772.15972 -+		if (handle == 0) {
772.15973 -+			DBG(("%s: import failed, errno=%d\n", __FUNCTION__, errno));
772.15974 -+			return NULL;
772.15975 -+		}
772.15976 - 	}
772.15977 - 
772.15978 - 	bo = __kgem_bo_alloc(handle, (last_page - first_page) / PAGE_SIZE);
772.15979 -@@ -6483,8 +7102,10 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
772.15980 - 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
772.15981 - 			kgem_throttle(kgem);
772.15982 - 		}
772.15983 -+		bo->needs_flush = false;
772.15984 - 		kgem_bo_retire(kgem, bo);
772.15985 - 		bo->domain = DOMAIN_CPU;
772.15986 -+		bo->gtt_dirty = true;
772.15987 - 	}
772.15988 - }
772.15989 - 
772.15990 -@@ -6505,6 +7126,9 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
772.15991 - 	assert(bo->refcnt);
772.15992 - 	assert(!bo->purged);
772.15993 - 
772.15994 -+	if (bo->rq == NULL && (kgem->has_llc || bo->snoop) && !write)
772.15995 -+		return;
772.15996 -+
772.15997 - 	if (bo->domain != DOMAIN_CPU || FORCE_MMAP_SYNC & (1 << DOMAIN_CPU)) {
772.15998 - 		struct drm_i915_gem_set_domain set_domain;
772.15999 - 
772.16000 -@@ -6522,9 +7146,11 @@ void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
772.16001 - 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
772.16002 - 			kgem_throttle(kgem);
772.16003 - 		}
772.16004 -+		bo->needs_flush = false;
772.16005 - 		if (write) {
772.16006 - 			kgem_bo_retire(kgem, bo);
772.16007 - 			bo->domain = DOMAIN_CPU;
772.16008 -+			bo->gtt_dirty = true;
772.16009 - 		} else {
772.16010 - 			if (bo->exec == NULL)
772.16011 - 				kgem_bo_maybe_retire(kgem, bo);
772.16012 -@@ -6539,6 +7165,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
772.16013 - 	assert(bo->refcnt);
772.16014 - 	assert(bo->proxy == NULL);
772.16015 - 	assert_tiling(kgem, bo);
772.16016 -+	assert(!bo->snoop);
772.16017 - 
772.16018 - 	kgem_bo_submit(kgem, bo);
772.16019 - 
772.16020 -@@ -6559,6 +7186,7 @@ void kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo)
772.16021 - 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
772.16022 - 			kgem_throttle(kgem);
772.16023 - 		}
772.16024 -+		bo->needs_flush = false;
772.16025 - 		kgem_bo_retire(kgem, bo);
772.16026 - 		bo->domain = DOMAIN_GTT;
772.16027 - 		bo->gtt_dirty = true;
772.16028 -@@ -7485,6 +8113,7 @@ kgem_replace_bo(struct kgem *kgem,
772.16029 - 		}
772.16030 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.16031 - 	}
772.16032 -+	kgem_bcs_set_tiling(kgem, src, dst);
772.16033 - 
772.16034 - 	br00 = XY_SRC_COPY_BLT_CMD;
772.16035 - 	br13 = pitch;
772.16036 -@@ -7553,6 +8182,9 @@ bool kgem_bo_convert_to_gpu(struct kgem *kgem,
772.16037 - 	     __FUNCTION__, bo->handle, flags, __kgem_bo_is_busy(kgem, bo)));
772.16038 - 	assert(bo->tiling == I915_TILING_NONE);
772.16039 - 
772.16040 -+	if (flags & (__MOVE_PRIME | __MOVE_SCANOUT))
772.16041 -+		return false;
772.16042 -+
772.16043 - 	if (kgem->has_llc)
772.16044 - 		return true;
772.16045 - 
772.16046 -diff --git a/src/sna/kgem.h b/src/sna/kgem.h
772.16047 -index 2267bacf..08b4eb20 100644
772.16048 ---- a/src/sna/kgem.h
772.16049 -+++ b/src/sna/kgem.h
772.16050 -@@ -42,6 +42,7 @@ struct kgem_bo {
772.16051 - #define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3))
772.16052 - #define RQ_RING(rq) ((uintptr_t)(rq) & 3)
772.16053 - #define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT)
772.16054 -+#define RQ_IS_RENDER(rq) (RQ_RING(rq) == KGEM_RENDER)
772.16055 - #define MAKE_REQUEST(rq, ring) ((struct kgem_request *)((uintptr_t)(rq) | (ring)))
772.16056 - 
772.16057 - 	struct drm_i915_gem_exec_object2 *exec;
772.16058 -@@ -103,7 +104,7 @@ struct kgem_request {
772.16059 - 	struct list list;
772.16060 - 	struct kgem_bo *bo;
772.16061 - 	struct list buffers;
772.16062 --	int ring;
772.16063 -+	unsigned ring;
772.16064 - };
772.16065 - 
772.16066 - enum {
772.16067 -@@ -112,6 +113,12 @@ enum {
772.16068 - 	NUM_MAP_TYPES,
772.16069 - };
772.16070 - 
772.16071 -+typedef void (*memcpy_box_func)(const void *src, void *dst, int bpp,
772.16072 -+				int32_t src_stride, int32_t dst_stride,
772.16073 -+				int16_t src_x, int16_t src_y,
772.16074 -+				int16_t dst_x, int16_t dst_y,
772.16075 -+				uint16_t width, uint16_t height);
772.16076 -+
772.16077 - struct kgem {
772.16078 - 	unsigned wedged;
772.16079 - 	int fd;
772.16080 -@@ -157,6 +164,8 @@ struct kgem {
772.16081 - 		int16_t count;
772.16082 - 	} vma[NUM_MAP_TYPES];
772.16083 - 
772.16084 -+	uint32_t bcs_state;
772.16085 -+
772.16086 - 	uint32_t batch_flags;
772.16087 - 	uint32_t batch_flags_base;
772.16088 - #define I915_EXEC_SECURE (1<<9)
772.16089 -@@ -186,9 +195,15 @@ struct kgem {
772.16090 - 	uint32_t has_no_reloc :1;
772.16091 - 	uint32_t has_handle_lut :1;
772.16092 - 	uint32_t has_wc_mmap :1;
772.16093 -+	uint32_t has_dirtyfb :1;
772.16094 - 
772.16095 -+	uint32_t can_fence :1;
772.16096 - 	uint32_t can_blt_cpu :1;
772.16097 -+	uint32_t can_blt_y :1;
772.16098 - 	uint32_t can_render_y :1;
772.16099 -+	uint32_t can_scanout_y :1;
772.16100 -+
772.16101 -+	uint32_t needs_dirtyfb :1;
772.16102 - 
772.16103 - 	uint16_t fence_max;
772.16104 - 	uint16_t half_cpu_cache_pages;
772.16105 -@@ -203,16 +218,9 @@ struct kgem {
772.16106 - 	void (*retire)(struct kgem *kgem);
772.16107 - 	void (*expire)(struct kgem *kgem);
772.16108 - 
772.16109 --	void (*memcpy_to_tiled_x)(const void *src, void *dst, int bpp,
772.16110 --				  int32_t src_stride, int32_t dst_stride,
772.16111 --				  int16_t src_x, int16_t src_y,
772.16112 --				  int16_t dst_x, int16_t dst_y,
772.16113 --				  uint16_t width, uint16_t height);
772.16114 --	void (*memcpy_from_tiled_x)(const void *src, void *dst, int bpp,
772.16115 --				    int32_t src_stride, int32_t dst_stride,
772.16116 --				    int16_t src_x, int16_t src_y,
772.16117 --				    int16_t dst_x, int16_t dst_y,
772.16118 --				    uint16_t width, uint16_t height);
772.16119 -+	memcpy_box_func memcpy_to_tiled_x;
772.16120 -+	memcpy_box_func memcpy_from_tiled_x;
772.16121 -+	memcpy_box_func memcpy_between_tiled_x;
772.16122 - 
772.16123 - 	struct kgem_bo *batch_bo;
772.16124 - 
772.16125 -@@ -230,7 +238,7 @@ struct kgem {
772.16126 - 
772.16127 - #define KGEM_MAX_DEFERRED_VBO 16
772.16128 - 
772.16129 --#define KGEM_BATCH_RESERVED 1
772.16130 -+#define KGEM_BATCH_RESERVED 8 /* LRI(SWCTRL) + END */
772.16131 - #define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
772.16132 - #define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
772.16133 - 
772.16134 -@@ -317,6 +325,7 @@ bool kgem_bo_convert_to_gpu(struct kgem *kgem,
772.16135 - 			    struct kgem_bo *bo,
772.16136 - 			    unsigned flags);
772.16137 - 
772.16138 -+bool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo);
772.16139 - uint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format);
772.16140 - void kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset);
772.16141 - 
772.16142 -@@ -342,6 +351,11 @@ static inline bool kgem_ring_is_idle(struct kgem *kgem, int ring)
772.16143 - {
772.16144 - 	ring = ring == KGEM_BLT;
772.16145 - 
772.16146 -+	if (kgem->needs_semaphore &&
772.16147 -+	    !list_is_empty(&kgem->requests[!ring]) &&
772.16148 -+	    !__kgem_ring_is_idle(kgem, !ring))
772.16149 -+		return false;
772.16150 -+
772.16151 - 	if (list_is_empty(&kgem->requests[ring]))
772.16152 - 		return true;
772.16153 - 
772.16154 -@@ -390,6 +404,7 @@ void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
772.16155 - static inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
772.16156 - {
772.16157 - 	assert(bo->refcnt);
772.16158 -+	assert(bo->refcnt > bo->active_scanout);
772.16159 - 	if (--bo->refcnt == 0)
772.16160 - 		_kgem_bo_destroy(kgem, bo);
772.16161 - }
772.16162 -@@ -400,13 +415,13 @@ static inline void kgem_set_mode(struct kgem *kgem,
772.16163 - 				 enum kgem_mode mode,
772.16164 - 				 struct kgem_bo *bo)
772.16165 - {
772.16166 --	assert(!kgem->wedged);
772.16167 -+	warn_unless(!kgem->wedged);
772.16168 - 
772.16169 - #if DEBUG_FLUSH_BATCH
772.16170 - 	kgem_submit(kgem);
772.16171 - #endif
772.16172 - 
772.16173 --	if (kgem->nreloc && bo->exec == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
772.16174 -+	if (kgem->nreloc && bo->rq == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
772.16175 - 		DBG(("%s: flushing before new bo\n", __FUNCTION__));
772.16176 - 		_kgem_submit(kgem);
772.16177 - 	}
772.16178 -@@ -422,7 +437,7 @@ static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode)
772.16179 - {
772.16180 - 	assert(kgem->mode == KGEM_NONE);
772.16181 - 	assert(kgem->nbatch == 0);
772.16182 --	assert(!kgem->wedged);
772.16183 -+	warn_unless(!kgem->wedged);
772.16184 - 	kgem->context_switch(kgem, mode);
772.16185 - 	kgem->mode = mode;
772.16186 - }
772.16187 -@@ -566,7 +581,7 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
772.16188 - {
772.16189 - 	assert(bo->refcnt);
772.16190 - 
772.16191 --	if (bo->tiling == I915_TILING_Y) {
772.16192 -+	if (bo->tiling == I915_TILING_Y && !kgem->can_blt_y) {
772.16193 - 		DBG(("%s: can not blt to handle=%d, tiling=Y\n",
772.16194 - 		     __FUNCTION__, bo->handle));
772.16195 - 		return false;
772.16196 -@@ -581,6 +596,22 @@ static inline bool kgem_bo_can_blt(struct kgem *kgem,
772.16197 - 	return kgem_bo_blt_pitch_is_ok(kgem, bo);
772.16198 - }
772.16199 - 
772.16200 -+void __kgem_bcs_set_tiling(struct kgem *kgem,
772.16201 -+			   struct kgem_bo *src,
772.16202 -+			   struct kgem_bo *dst);
772.16203 -+
772.16204 -+inline static void kgem_bcs_set_tiling(struct kgem *kgem,
772.16205 -+				       struct kgem_bo *src,
772.16206 -+				       struct kgem_bo *dst)
772.16207 -+{
772.16208 -+	assert(kgem->mode == KGEM_BLT);
772.16209 -+
772.16210 -+	if (!kgem->can_blt_y)
772.16211 -+		return;
772.16212 -+
772.16213 -+	__kgem_bcs_set_tiling(kgem, src, dst);
772.16214 -+}
772.16215 -+
772.16216 - static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
772.16217 - {
772.16218 - 	assert(bo->refcnt);
772.16219 -@@ -607,17 +638,24 @@ static inline void kgem_bo_mark_busy(struct kgem *kgem, struct kgem_bo *bo, int
772.16220 - 	}
772.16221 - }
772.16222 - 
772.16223 --inline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
772.16224 -+static inline void __kgem_bo_clear_dirty(struct kgem_bo *bo)
772.16225 - {
772.16226 - 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
772.16227 --	bo->rq = NULL;
772.16228 --	list_del(&bo->request);
772.16229 - 
772.16230 - 	bo->domain = DOMAIN_NONE;
772.16231 - 	bo->needs_flush = false;
772.16232 - 	bo->gtt_dirty = false;
772.16233 - }
772.16234 - 
772.16235 -+inline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
772.16236 -+{
772.16237 -+	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
772.16238 -+	bo->rq = NULL;
772.16239 -+	list_del(&bo->request);
772.16240 -+
772.16241 -+	__kgem_bo_clear_dirty(bo);
772.16242 -+}
772.16243 -+
772.16244 - static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
772.16245 - {
772.16246 - 	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
772.16247 -@@ -626,7 +664,7 @@ static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
772.16248 - 	return bo->rq;
772.16249 - }
772.16250 - 
772.16251 --void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
772.16252 -+bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
772.16253 - static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
772.16254 - {
772.16255 - 	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
772.16256 -@@ -636,14 +674,13 @@ static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
772.16257 - 	if (bo->exec)
772.16258 - 		return true;
772.16259 - 
772.16260 --	if (bo->rq && !__kgem_busy(kgem, bo->handle)) {
772.16261 --		__kgem_retire_requests_upto(kgem, bo);
772.16262 --		assert(list_is_empty(&bo->request));
772.16263 --		assert(bo->rq == NULL);
772.16264 --		assert(bo->domain == DOMAIN_NONE);
772.16265 --	}
772.16266 -+	if (bo->rq == NULL)
772.16267 -+		return false;
772.16268 -+
772.16269 -+	if (__kgem_busy(kgem, bo->handle))
772.16270 -+		return true;
772.16271 - 
772.16272 --	return kgem_bo_is_busy(bo);
772.16273 -+	return __kgem_retire_requests_upto(kgem, bo);
772.16274 - }
772.16275 - 
772.16276 - static inline bool kgem_bo_is_render(struct kgem_bo *bo)
772.16277 -@@ -651,7 +688,15 @@ static inline bool kgem_bo_is_render(struct kgem_bo *bo)
772.16278 - 	DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__,
772.16279 - 	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
772.16280 - 	assert(bo->refcnt);
772.16281 --	return bo->rq && RQ_RING(bo->rq) == I915_EXEC_RENDER;
772.16282 -+	return bo->rq && RQ_RING(bo->rq) != KGEM_BLT;
772.16283 -+}
772.16284 -+
772.16285 -+static inline bool kgem_bo_is_blt(struct kgem_bo *bo)
772.16286 -+{
772.16287 -+	DBG(("%s: handle=%d, rq? %d\n", __FUNCTION__,
772.16288 -+	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
772.16289 -+	assert(bo->refcnt);
772.16290 -+	return RQ_RING(bo->rq) == KGEM_BLT;
772.16291 - }
772.16292 - 
772.16293 - static inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
772.16294 -@@ -852,6 +897,6 @@ memcpy_from_tiled_x(struct kgem *kgem,
772.16295 - 					 width, height);
772.16296 - }
772.16297 - 
772.16298 --void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling);
772.16299 -+void choose_memcpy_tiled_x(struct kgem *kgem, int swizzling, unsigned cpu);
772.16300 - 
772.16301 - #endif /* KGEM_H */
772.16302 -diff --git a/src/sna/kgem_debug_gen4.c b/src/sna/kgem_debug_gen4.c
772.16303 -index 9b80dc88..8e6e47b6 100644
772.16304 ---- a/src/sna/kgem_debug_gen4.c
772.16305 -+++ b/src/sna/kgem_debug_gen4.c
772.16306 -@@ -598,7 +598,7 @@ int kgem_gen4_decode_3d(struct kgem *kgem, uint32_t offset)
772.16307 - 		assert(len == 7);
772.16308 - 		kgem_debug_print(data, offset, 0,
772.16309 - 			  "3DSTATE_DEPTH_BUFFER\n");
772.16310 --		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
772.16311 -+		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
772.16312 - 			  get_965_surfacetype(data[1] >> 29),
772.16313 - 			  get_965_depthformat((data[1] >> 18) & 0x7),
772.16314 - 			  (data[1] & 0x0001ffff) + 1,
772.16315 -diff --git a/src/sna/kgem_debug_gen5.c b/src/sna/kgem_debug_gen5.c
772.16316 -index 8b55dd91..f1b1275f 100644
772.16317 ---- a/src/sna/kgem_debug_gen5.c
772.16318 -+++ b/src/sna/kgem_debug_gen5.c
772.16319 -@@ -573,7 +573,7 @@ int kgem_gen5_decode_3d(struct kgem *kgem, uint32_t offset)
772.16320 - 		assert(len == 7);
772.16321 - 		kgem_debug_print(data, offset, 0,
772.16322 - 			  "3DSTATE_DEPTH_BUFFER\n");
772.16323 --		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
772.16324 -+		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
772.16325 - 			  get_965_surfacetype(data[1] >> 29),
772.16326 - 			  get_965_depthformat((data[1] >> 18) & 0x7),
772.16327 - 			  (data[1] & 0x0001ffff) + 1,
772.16328 -diff --git a/src/sna/kgem_debug_gen6.c b/src/sna/kgem_debug_gen6.c
772.16329 -index 7ef55d38..579c5d54 100644
772.16330 ---- a/src/sna/kgem_debug_gen6.c
772.16331 -+++ b/src/sna/kgem_debug_gen6.c
772.16332 -@@ -985,7 +985,7 @@ int kgem_gen6_decode_3d(struct kgem *kgem, uint32_t offset)
772.16333 - 		assert(len == 7);
772.16334 - 		kgem_debug_print(data, offset, 0,
772.16335 - 			  "3DSTATE_DEPTH_BUFFER\n");
772.16336 --		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
772.16337 -+		kgem_debug_print(data, offset, 1, "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Separate Stencil %d\n",
772.16338 - 			  get_965_surfacetype(data[1] >> 29),
772.16339 - 			  get_965_depthformat((data[1] >> 18) & 0x7),
772.16340 - 			  (data[1] & 0x0001ffff) + 1,
772.16341 -diff --git a/src/sna/sna.h b/src/sna/sna.h
772.16342 -index 18425e30..7861110a 100644
772.16343 ---- a/src/sna/sna.h
772.16344 -+++ b/src/sna/sna.h
772.16345 -@@ -154,6 +154,8 @@ struct sna_pixmap {
772.16346 - #define MAPPED_GTT 1
772.16347 - #define MAPPED_CPU 2
772.16348 - 	uint8_t flush :2;
772.16349 -+#define FLUSH_READ 1
772.16350 -+#define FLUSH_WRITE 2
772.16351 - 	uint8_t shm :1;
772.16352 - 	uint8_t clear :1;
772.16353 - 	uint8_t header :1;
772.16354 -@@ -179,18 +181,31 @@ static inline WindowPtr get_root_window(ScreenPtr screen)
772.16355 - #endif
772.16356 - }
772.16357 - 
772.16358 -+#if !NDEBUG
772.16359 -+static PixmapPtr check_pixmap(PixmapPtr pixmap)
772.16360 -+{
772.16361 -+	if (pixmap != NULL) {
772.16362 -+		assert(pixmap->refcnt >= 1);
772.16363 -+		assert(pixmap->devKind != 0xdeadbeef);
772.16364 -+	}
772.16365 -+	return pixmap;
772.16366 -+}
772.16367 -+#else
772.16368 -+#define check_pixmap(p) p
772.16369 -+#endif
772.16370 -+
772.16371 - static inline PixmapPtr get_window_pixmap(WindowPtr window)
772.16372 - {
772.16373 - 	assert(window);
772.16374 - 	assert(window->drawable.type != DRAWABLE_PIXMAP);
772.16375 --	return fbGetWindowPixmap(window);
772.16376 -+	return check_pixmap(fbGetWindowPixmap(window));
772.16377 - }
772.16378 - 
772.16379 - static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
772.16380 - {
772.16381 - 	assert(drawable);
772.16382 - 	if (drawable->type == DRAWABLE_PIXMAP)
772.16383 --		return (PixmapPtr)drawable;
772.16384 -+		return check_pixmap((PixmapPtr)drawable);
772.16385 - 	else
772.16386 - 		return get_window_pixmap((WindowPtr)drawable);
772.16387 - }
772.16388 -@@ -244,11 +259,12 @@ struct sna {
772.16389 - #define SNA_NO_VSYNC		0x40
772.16390 - #define SNA_TRIPLE_BUFFER	0x80
772.16391 - #define SNA_TEAR_FREE		0x100
772.16392 --#define SNA_FORCE_SHADOW	0x200
772.16393 --#define SNA_FLUSH_GTT		0x400
772.16394 -+#define SNA_WANT_TEAR_FREE	0x200
772.16395 -+#define SNA_FORCE_SHADOW	0x400
772.16396 -+#define SNA_FLUSH_GTT		0x800
772.16397 - #define SNA_PERFORMANCE		0x1000
772.16398 - #define SNA_POWERSAVE		0x2000
772.16399 --#define SNA_REMOVE_OUTPUTS	0x4000
772.16400 -+#define SNA_NO_DPMS		0x4000
772.16401 - #define SNA_HAS_FLIP		0x10000
772.16402 - #define SNA_HAS_ASYNC_FLIP	0x20000
772.16403 - #define SNA_LINEAR_FB		0x40000
772.16404 -@@ -265,7 +281,13 @@ struct sna {
772.16405 - #define AVX 0x80
772.16406 - #define AVX2 0x100
772.16407 - 
772.16408 --	unsigned watch_flush;
772.16409 -+	bool ignore_copy_area : 1;
772.16410 -+
772.16411 -+	unsigned watch_shm_flush;
772.16412 -+	unsigned watch_dri_flush;
772.16413 -+	unsigned damage_event;
772.16414 -+	bool needs_shm_flush;
772.16415 -+	bool needs_dri_flush;
772.16416 - 
772.16417 - 	struct timeval timer_tv;
772.16418 - 	uint32_t timer_expire[NUM_TIMERS];
772.16419 -@@ -284,9 +306,17 @@ struct sna {
772.16420 - 		struct kgem_bo *shadow;
772.16421 - 		unsigned front_active;
772.16422 - 		unsigned shadow_active;
772.16423 -+		unsigned rr_active;
772.16424 - 		unsigned flip_active;
772.16425 -+		unsigned hidden;
772.16426 -+		bool shadow_enabled;
772.16427 -+		bool shadow_wait;
772.16428 - 		bool dirty;
772.16429 - 
772.16430 -+		struct drm_event_vblank *shadow_events;
772.16431 -+		int shadow_nevent;
772.16432 -+		int shadow_size;
772.16433 -+
772.16434 - 		int max_crtc_width, max_crtc_height;
772.16435 - 		RegionRec shadow_region;
772.16436 - 		RegionRec shadow_cancel;
772.16437 -@@ -318,7 +348,8 @@ struct sna {
772.16438 - 		uint32_t fg, bg;
772.16439 - 		int size;
772.16440 - 
772.16441 --		int active;
772.16442 -+		bool disable;
772.16443 -+		bool active;
772.16444 - 		int last_x;
772.16445 - 		int last_y;
772.16446 - 
772.16447 -@@ -331,8 +362,9 @@ struct sna {
772.16448 - 	} cursor;
772.16449 - 
772.16450 - 	struct sna_dri2 {
772.16451 --		bool available;
772.16452 --		bool open;
772.16453 -+		bool available : 1;
772.16454 -+		bool enable : 1;
772.16455 -+		bool open : 1;
772.16456 - 
772.16457 - #if HAVE_DRI2
772.16458 - 		void *flip_pending;
772.16459 -@@ -341,8 +373,11 @@ struct sna {
772.16460 - 	} dri2;
772.16461 - 
772.16462 - 	struct sna_dri3 {
772.16463 --		bool available;
772.16464 --		bool open;
772.16465 -+		bool available :1;
772.16466 -+		bool override : 1;
772.16467 -+		bool enable : 1;
772.16468 -+		bool open :1;
772.16469 -+
772.16470 - #if HAVE_DRI3
772.16471 - 		SyncScreenCreateFenceFunc create_fence;
772.16472 - 		struct list pixmaps;
772.16473 -@@ -353,6 +388,9 @@ struct sna {
772.16474 - 		bool available;
772.16475 - 		bool open;
772.16476 - #if HAVE_PRESENT
772.16477 -+		struct list vblank_queue;
772.16478 -+		uint64_t unflip;
772.16479 -+		void *freed_info;
772.16480 - #endif
772.16481 - 	} present;
772.16482 - 
772.16483 -@@ -364,8 +402,10 @@ struct sna {
772.16484 - 	EntityInfoPtr pEnt;
772.16485 - 	const struct intel_device_info *info;
772.16486 - 
772.16487 -+#if !HAVE_NOTIFY_FD
772.16488 - 	ScreenBlockHandlerProcPtr BlockHandler;
772.16489 - 	ScreenWakeupHandlerProcPtr WakeupHandler;
772.16490 -+#endif
772.16491 - 	CloseScreenProcPtr CloseScreen;
772.16492 - 
772.16493 - 	PicturePtr clear;
772.16494 -@@ -383,6 +423,7 @@ struct sna {
772.16495 - 		struct gen6_render_state gen6;
772.16496 - 		struct gen7_render_state gen7;
772.16497 - 		struct gen8_render_state gen8;
772.16498 -+		struct gen9_render_state gen9;
772.16499 - 	} render_state;
772.16500 - 
772.16501 - 	/* Broken-out options. */
772.16502 -@@ -420,7 +461,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
772.16503 - bool sna_mode_fake_init(struct sna *sna, int num_fake);
772.16504 - bool sna_mode_wants_tear_free(struct sna *sna);
772.16505 - void sna_mode_adjust_frame(struct sna *sna, int x, int y);
772.16506 --extern void sna_mode_discover(struct sna *sna);
772.16507 -+extern void sna_mode_discover(struct sna *sna, bool tell);
772.16508 - extern void sna_mode_check(struct sna *sna);
772.16509 - extern bool sna_mode_disable(struct sna *sna);
772.16510 - extern void sna_mode_enable(struct sna *sna);
772.16511 -@@ -434,6 +475,7 @@ extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc);
772.16512 - extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
772.16513 - 					     const RegionRec *region);
772.16514 - extern void sna_mode_set_primary(struct sna *sna);
772.16515 -+extern bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id);
772.16516 - extern void sna_mode_close(struct sna *sna);
772.16517 - extern void sna_mode_fini(struct sna *sna);
772.16518 - 
772.16519 -@@ -444,6 +486,7 @@ extern bool sna_cursors_init(ScreenPtr screen, struct sna *sna);
772.16520 - typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
772.16521 - 				   void *data);
772.16522 - 
772.16523 -+extern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo);
772.16524 - extern int sna_page_flip(struct sna *sna,
772.16525 - 			 struct kgem_bo *bo,
772.16526 - 			 sna_flip_handler_t handler,
772.16527 -@@ -461,6 +504,11 @@ to_sna_from_screen(ScreenPtr screen)
772.16528 - 	return to_sna(xf86ScreenToScrn(screen));
772.16529 - }
772.16530 - 
772.16531 -+pure static inline ScreenPtr to_screen_from_sna(struct sna *sna)
772.16532 -+{
772.16533 -+	return xf86ScrnToScreen(sna->scrn);
772.16534 -+}
772.16535 -+
772.16536 - pure static inline struct sna *
772.16537 - to_sna_from_pixmap(PixmapPtr pixmap)
772.16538 - {
772.16539 -@@ -498,12 +546,11 @@ to_sna_from_kgem(struct kgem *kgem)
772.16540 - extern xf86CrtcPtr sna_covering_crtc(struct sna *sna,
772.16541 - 				     const BoxRec *box,
772.16542 - 				     xf86CrtcPtr desired);
772.16543 -+extern xf86CrtcPtr sna_primary_crtc(struct sna *sna);
772.16544 - 
772.16545 - extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap,
772.16546 - 				  xf86CrtcPtr crtc, const BoxRec *clip);
772.16547 - 
772.16548 --xf86CrtcPtr sna_mode_first_crtc(struct sna *sna);
772.16549 --
772.16550 - const struct ust_msc {
772.16551 - 	uint64_t msc;
772.16552 - 	int tv_sec;
772.16553 -@@ -536,6 +583,11 @@ static inline uint64_t ust64(int tv_sec, int tv_usec)
772.16554 - 	return (uint64_t)tv_sec * 1000000 + tv_usec;
772.16555 - }
772.16556 - 
772.16557 -+static inline uint64_t swap_ust(const struct ust_msc *swap)
772.16558 -+{
772.16559 -+	return ust64(swap->tv_sec, swap->tv_usec);
772.16560 -+}
772.16561 -+
772.16562 - #if HAVE_DRI2
772.16563 - bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
772.16564 - void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
772.16565 -@@ -567,20 +619,59 @@ bool sna_present_open(struct sna *sna, ScreenPtr pScreen);
772.16566 - void sna_present_update(struct sna *sna);
772.16567 - void sna_present_close(struct sna *sna, ScreenPtr pScreen);
772.16568 - void sna_present_vblank_handler(struct drm_event_vblank *event);
772.16569 -+void sna_present_cancel_flip(struct sna *sna);
772.16570 - #else
772.16571 - static inline bool sna_present_open(struct sna *sna, ScreenPtr pScreen) { return false; }
772.16572 - static inline void sna_present_update(struct sna *sna) { }
772.16573 - static inline void sna_present_close(struct sna *sna, ScreenPtr pScreen) { }
772.16574 - static inline void sna_present_vblank_handler(struct drm_event_vblank *event) { }
772.16575 -+static inline void sna_present_cancel_flip(struct sna *sna) { }
772.16576 - #endif
772.16577 - 
772.16578 --extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
772.16579 --extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
772.16580 --extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
772.16581 --extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
772.16582 --extern bool sna_crtc_is_on(xf86CrtcPtr crtc);
772.16583 -+extern unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc);
772.16584 -+extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, unsigned idx, uint32_t rotation);
772.16585 -+extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx);
772.16586 - extern bool sna_crtc_is_transformed(xf86CrtcPtr crtc);
772.16587 - 
772.16588 -+#define CRTC_VBLANK 0x3
772.16589 -+#define CRTC_ON 0x80000000
772.16590 -+
772.16591 -+uint32_t sna_crtc_id(xf86CrtcPtr crtc);
772.16592 -+
772.16593 -+static inline unsigned long *sna_crtc_flags(xf86CrtcPtr crtc)
772.16594 -+{
772.16595 -+	unsigned long *flags = crtc->driver_private;
772.16596 -+	assert(flags);
772.16597 -+	return flags;
772.16598 -+}
772.16599 -+
772.16600 -+static inline unsigned sna_crtc_pipe(xf86CrtcPtr crtc)
772.16601 -+{
772.16602 -+	return *sna_crtc_flags(crtc) >> 8 & 0xff;
772.16603 -+}
772.16604 -+
772.16605 -+static inline bool sna_crtc_is_on(xf86CrtcPtr crtc)
772.16606 -+{
772.16607 -+	return *sna_crtc_flags(crtc) & CRTC_ON;
772.16608 -+}
772.16609 -+
772.16610 -+static inline void sna_crtc_set_vblank(xf86CrtcPtr crtc)
772.16611 -+{
772.16612 -+	assert((*sna_crtc_flags(crtc) & CRTC_VBLANK) < 3);
772.16613 -+	++*sna_crtc_flags(crtc);
772.16614 -+}
772.16615 -+
772.16616 -+static inline void sna_crtc_clear_vblank(xf86CrtcPtr crtc)
772.16617 -+{
772.16618 -+	assert(*sna_crtc_flags(crtc) & CRTC_VBLANK);
772.16619 -+	--*sna_crtc_flags(crtc);
772.16620 -+}
772.16621 -+
772.16622 -+static inline bool sna_crtc_has_vblank(xf86CrtcPtr crtc)
772.16623 -+{
772.16624 -+	return *sna_crtc_flags(crtc) & CRTC_VBLANK;
772.16625 -+}
772.16626 -+
772.16627 - CARD32 sna_format_for_depth(int depth);
772.16628 - CARD32 sna_render_format_for_depth(int depth);
772.16629 - 
772.16630 -@@ -998,15 +1089,14 @@ static inline uint32_t pixmap_size(PixmapPtr pixmap)
772.16631 - 
772.16632 - bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
772.16633 - void sna_accel_create(struct sna *sna);
772.16634 --void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
772.16635 --void sna_accel_wakeup_handler(struct sna *sna);
772.16636 --void sna_accel_watch_flush(struct sna *sna, int enable);
772.16637 -+void sna_accel_block(struct sna *sna, struct timeval **tv);
772.16638 - void sna_accel_flush(struct sna *sna);
772.16639 - void sna_accel_enter(struct sna *sna);
772.16640 - void sna_accel_leave(struct sna *sna);
772.16641 - void sna_accel_close(struct sna *sna);
772.16642 - void sna_accel_free(struct sna *sna);
772.16643 - 
772.16644 -+void sna_watch_flush(struct sna *sna, int enable);
772.16645 - void sna_copy_fbcon(struct sna *sna);
772.16646 - 
772.16647 - bool sna_composite_create(struct sna *sna);
772.16648 -@@ -1127,6 +1217,16 @@ memcpy_blt(const void *src, void *dst, int bpp,
772.16649 - 	   uint16_t width, uint16_t height);
772.16650 - 
772.16651 - void
772.16652 -+affine_blt(const void *src, void *dst, int bpp,
772.16653 -+	   int16_t src_x, int16_t src_y,
772.16654 -+	   int16_t src_width, int16_t src_height,
772.16655 -+	   int32_t src_stride,
772.16656 -+	   int16_t dst_x, int16_t dst_y,
772.16657 -+	   uint16_t dst_width, uint16_t dst_height,
772.16658 -+	   int32_t dst_stride,
772.16659 -+	   const struct pixman_f_transform *t);
772.16660 -+
772.16661 -+void
772.16662 - memmove_box(const void *src, void *dst,
772.16663 - 	    int bpp, int32_t stride,
772.16664 - 	    const BoxRec *box,
772.16665 -@@ -1182,6 +1282,31 @@ box_intersect(BoxPtr a, const BoxRec *b)
772.16666 - 	return true;
772.16667 - }
772.16668 - 
772.16669 -+const BoxRec *
772.16670 -+__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y);
772.16671 -+inline static const BoxRec *
772.16672 -+find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
772.16673 -+{
772.16674 -+	/* Special case for incremental trapezoid clipping */
772.16675 -+	if (begin == end)
772.16676 -+		return end;
772.16677 -+
772.16678 -+	/* Quick test if scanline is within range of clip boxes */
772.16679 -+	if (begin->y2 > y) {
772.16680 -+		assert(end == begin + 1 ||
772.16681 -+		       __find_clip_box_for_y(begin, end, y) == begin);
772.16682 -+		return begin;
772.16683 -+	}
772.16684 -+	if (y >= end[-1].y2) {
772.16685 -+		assert(end == begin + 1 ||
772.16686 -+		       __find_clip_box_for_y(begin, end, y) == end);
772.16687 -+		return end;
772.16688 -+	}
772.16689 -+
772.16690 -+	/* Otherwise bisect to find the first box crossing y */
772.16691 -+	return __find_clip_box_for_y(begin, end, y);
772.16692 -+}
772.16693 -+
772.16694 - unsigned sna_cpu_detect(void);
772.16695 - char *sna_cpu_features_to_string(unsigned features, char *line);
772.16696 - 
772.16697 -@@ -1237,4 +1362,17 @@ static inline void sigtrap_put(void)
772.16698 - extern int getline(char **line, size_t *len, FILE *file);
772.16699 - #endif
772.16700 - 
772.16701 -+static inline void add_shm_flush(struct sna *sna, struct sna_pixmap *priv)
772.16702 -+{
772.16703 -+	if (!priv->shm)
772.16704 -+		return;
772.16705 -+
772.16706 -+	DBG(("%s: marking handle=%d for SHM flush\n",
772.16707 -+	     __FUNCTION__, priv->cpu_bo->handle));
772.16708 -+
772.16709 -+	assert(!priv->flush);
772.16710 -+	sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.16711 -+	sna->needs_shm_flush = true;
772.16712 -+}
772.16713 -+
772.16714 - #endif /* _SNA_H */
772.16715 -diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
772.16716 -index baf5f609..25a075cf 100644
772.16717 ---- a/src/sna/sna_accel.c
772.16718 -+++ b/src/sna/sna_accel.c
772.16719 -@@ -50,8 +50,11 @@
772.16720 - #endif
772.16721 - #include <shmint.h>
772.16722 - 
772.16723 -+#include <X11/extensions/damageproto.h>
772.16724 -+
772.16725 - #include <sys/time.h>
772.16726 - #include <sys/mman.h>
772.16727 -+#include <sys/ioctl.h>
772.16728 - #include <unistd.h>
772.16729 - 
772.16730 - #ifdef HAVE_VALGRIND
772.16731 -@@ -66,7 +69,8 @@
772.16732 - #define FORCE_FLUSH 0
772.16733 - #define FORCE_FULL_SYNC 0 /* https://bugs.freedesktop.org/show_bug.cgi?id=61628 */
772.16734 - 
772.16735 --#define DEFAULT_TILING I915_TILING_X
772.16736 -+#define DEFAULT_PIXMAP_TILING I915_TILING_X
772.16737 -+#define DEFAULT_SCANOUT_TILING I915_TILING_X
772.16738 - 
772.16739 - #define USE_INPLACE 1
772.16740 - #define USE_SPANS 0 /* -1 force CPU, 1 force GPU */
772.16741 -@@ -115,6 +119,11 @@
772.16742 - #define RECTILINEAR	0x4
772.16743 - #define OVERWRITES	0x8
772.16744 - 
772.16745 -+#if XFONT2_CLIENT_FUNCS_VERSION >= 1
772.16746 -+#define AllocateFontPrivateIndex() xfont2_allocate_font_private_index()
772.16747 -+#define FontSetPrivate(font, idx, data) xfont2_font_set_private(font, idx, data)
772.16748 -+#endif
772.16749 -+
772.16750 - #if 0
772.16751 - static void __sna_fallback_flush(DrawablePtr d)
772.16752 - {
772.16753 -@@ -213,6 +222,7 @@ static GCOps sna_gc_ops__tmp;
772.16754 - static const GCFuncs sna_gc_funcs;
772.16755 - static const GCFuncs sna_gc_funcs__cpu;
772.16756 - 
772.16757 -+static void sna_shm_watch_flush(struct sna *sna, int enable);
772.16758 - static void
772.16759 - sna_poly_fill_rect__gpu(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect);
772.16760 - 
772.16761 -@@ -527,10 +537,10 @@ sna_pixmap_alloc_cpu(struct sna *sna,
772.16762 - 		DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__,
772.16763 - 		     pixmap->drawable.width, pixmap->drawable.height));
772.16764 - 
772.16765 --		hint = 0;
772.16766 --		if ((flags & MOVE_ASYNC_HINT) == 0 &&
772.16767 --		    ((flags & MOVE_READ) == 0 || (priv->gpu_damage && !priv->clear && !sna->kgem.has_llc)))
772.16768 --			hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
772.16769 -+		hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
772.16770 -+		if ((flags & MOVE_ASYNC_HINT) ||
772.16771 -+		    (priv->gpu_damage && !priv->clear && kgem_bo_is_busy(priv->gpu_bo) && sna->kgem.can_blt_cpu))
772.16772 -+			hint = 0;
772.16773 - 
772.16774 - 		priv->cpu_bo = kgem_create_cpu_2d(&sna->kgem,
772.16775 - 						  pixmap->drawable.width,
772.16776 -@@ -580,7 +590,7 @@ static void __sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
772.16777 - 		if (priv->cpu_bo->flush) {
772.16778 - 			assert(!priv->cpu_bo->reusable);
772.16779 - 			kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
772.16780 --			sna_accel_watch_flush(sna, -1);
772.16781 -+			sna_shm_watch_flush(sna, -1);
772.16782 - 		}
772.16783 - 		kgem_bo_destroy(&sna->kgem, priv->cpu_bo);
772.16784 - 	} else if (!IS_STATIC_PTR(priv->ptr))
772.16785 -@@ -612,9 +622,9 @@ static bool sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv, bool a
772.16786 - 
772.16787 - static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
772.16788 - {
772.16789 --#if DEFAULT_TILING == I915_TILING_NONE
772.16790 -+#if DEFAULT_PIXMAP_TILING == I915_TILING_NONE
772.16791 - 	return I915_TILING_NONE;
772.16792 --#elif DEFAULT_TILING == I915_TILING_X
772.16793 -+#elif DEFAULT_PIXMAP_TILING == I915_TILING_X
772.16794 - 	return I915_TILING_X;
772.16795 - #else
772.16796 - 	/* Try to avoid hitting the Y-tiling GTT mapping bug on 855GM */
772.16797 -@@ -630,15 +640,6 @@ static inline uint32_t default_tiling(struct sna *sna, PixmapPtr pixmap)
772.16798 - 	     pixmap->drawable.height > sna->render.max_3d_size))
772.16799 - 		return I915_TILING_X;
772.16800 - 
772.16801 --	if (sna_damage_is_all(&sna_pixmap(pixmap)->cpu_damage,
772.16802 --			      pixmap->drawable.width,
772.16803 --			      pixmap->drawable.height)) {
772.16804 --		DBG(("%s: entire source is damaged, using Y-tiling\n",
772.16805 --		     __FUNCTION__));
772.16806 --		sna_damage_destroy(&sna_pixmap(priv)->gpu_damage);
772.16807 --		return I915_TILING_Y;
772.16808 --	}
772.16809 --
772.16810 - 	return I915_TILING_Y;
772.16811 - #endif
772.16812 - }
772.16813 -@@ -666,6 +667,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
772.16814 - 	     __FUNCTION__, priv->gpu_bo->tiling, tiling,
772.16815 - 	     pixmap->drawable.width, pixmap->drawable.height));
772.16816 - 	assert(priv->gpu_damage == NULL || priv->gpu_bo);
772.16817 -+	assert(priv->gpu_bo->tiling != tiling);
772.16818 - 
772.16819 - 	if (priv->pinned) {
772.16820 - 		DBG(("%s: can't convert pinned bo\n", __FUNCTION__));
772.16821 -@@ -690,6 +692,12 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
772.16822 - 		return NULL;
772.16823 - 	}
772.16824 - 
772.16825 -+	if (bo->tiling == priv->gpu_bo->tiling) {
772.16826 -+		DBG(("%s: tiling request failed\n", __FUNCTION__));
772.16827 -+		kgem_bo_destroy(&sna->kgem, bo);
772.16828 -+		return NULL;
772.16829 -+	}
772.16830 -+
772.16831 - 	box.x1 = box.y1 = 0;
772.16832 - 	box.x2 = pixmap->drawable.width;
772.16833 - 	box.y2 = pixmap->drawable.height;
772.16834 -@@ -824,8 +832,8 @@ create_pixmap(struct sna *sna, ScreenPtr screen,
772.16835 - 		datasize += adjust;
772.16836 - 	}
772.16837 - 
772.16838 --	DBG(("%s: allocating pixmap %dx%d, depth=%d, size=%ld\n",
772.16839 --	     __FUNCTION__, width, height, depth, (long)datasize));
772.16840 -+	DBG(("%s: allocating pixmap %dx%d, depth=%d/%d, size=%ld\n",
772.16841 -+	     __FUNCTION__, width, height, depth, bpp, (long)datasize));
772.16842 - 	pixmap = AllocatePixmap(screen, datasize);
772.16843 - 	if (!pixmap)
772.16844 - 		return NullPixmap;
772.16845 -@@ -878,7 +886,11 @@ __pop_freed_pixmap(struct sna *sna)
772.16846 - 	pixmap = sna->freed_pixmap;
772.16847 - 	sna->freed_pixmap = pixmap->devPrivate.ptr;
772.16848 - 
772.16849 -+	DBG(("%s: reusing freed pixmap=%ld header\n",
772.16850 -+	     __FUNCTION__, pixmap->drawable.serialNumber));
772.16851 -+
772.16852 - 	assert(pixmap->refcnt == 0);
772.16853 -+	assert(pixmap->devKind = 0xdeadbeef);
772.16854 - 	assert(sna_pixmap(pixmap));
772.16855 - 	assert(sna_pixmap(pixmap)->header);
772.16856 - 
772.16857 -@@ -990,7 +1002,7 @@ fallback:
772.16858 - 	}
772.16859 - 	priv->cpu_bo->pitch = pitch;
772.16860 - 	kgem_bo_mark_unreusable(priv->cpu_bo);
772.16861 --	sna_accel_watch_flush(sna, 1);
772.16862 -+	sna_shm_watch_flush(sna, 1);
772.16863 - #ifdef DEBUG_MEMORY
772.16864 - 	sna->debug_memory.cpu_bo_allocs++;
772.16865 - 	sna->debug_memory.cpu_bo_bytes += kgem_bo_size(priv->cpu_bo);
772.16866 -@@ -1081,6 +1093,18 @@ sna_pixmap_create_scratch(ScreenPtr screen,
772.16867 - 	return pixmap;
772.16868 - }
772.16869 - 
772.16870 -+static unsigned small_copy(const RegionRec *region)
772.16871 -+{
772.16872 -+	if ((region->extents.x2 - region->extents.x1)*(region->extents.y2 - region->extents.y1) < 1024) {
772.16873 -+		DBG(("%s: region:%dx%d\n", __FUNCTION__,
772.16874 -+		     (region->extents.x2 - region->extents.x1),
772.16875 -+		     (region->extents.y2 - region->extents.y1)));
772.16876 -+		return COPY_SMALL;
772.16877 -+	}
772.16878 -+
772.16879 -+	return 0;
772.16880 -+}
772.16881 -+
772.16882 - #ifdef CREATE_PIXMAP_USAGE_SHARED
772.16883 - static Bool
772.16884 - sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
772.16885 -@@ -1124,7 +1148,7 @@ sna_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, void **fd_handle)
772.16886 - 				    pixmap->drawable.height,
772.16887 - 				    pixmap->drawable.bitsPerPixel,
772.16888 - 				    I915_TILING_NONE,
772.16889 --				    CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT);
772.16890 -+				    CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT);
772.16891 - 		if (bo == NULL) {
772.16892 - 			DBG(("%s: allocation failed\n", __FUNCTION__));
772.16893 - 			return FALSE;
772.16894 -@@ -1243,7 +1267,7 @@ sna_create_pixmap_shared(struct sna *sna, ScreenPtr screen,
772.16895 - 					      width, height,
772.16896 - 					      pixmap->drawable.bitsPerPixel,
772.16897 - 					      I915_TILING_NONE,
772.16898 --					      CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT);
772.16899 -+					      CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT);
772.16900 - 		if (priv->gpu_bo == NULL) {
772.16901 - 			free(priv);
772.16902 - 			FreePixmap(pixmap);
772.16903 -@@ -1311,7 +1335,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
772.16904 - 
772.16905 - 	if (unlikely((sna->render.prefer_gpu & PREFER_GPU_RENDER) == 0))
772.16906 - 		flags &= ~KGEM_CAN_CREATE_GPU;
772.16907 --	if (wedged(sna))
772.16908 -+	if (wedged(sna) && usage != SNA_CREATE_FB)
772.16909 - 		flags &= ~KGEM_CAN_CREATE_GTT;
772.16910 - 
772.16911 - 	DBG(("%s: usage=%d, flags=%x\n", __FUNCTION__, usage, flags));
772.16912 -@@ -1417,10 +1441,13 @@ static void __sna_free_pixmap(struct sna *sna,
772.16913 - 	__sna_pixmap_free_cpu(sna, priv);
772.16914 - 
772.16915 - 	if (priv->flush)
772.16916 --		sna_accel_watch_flush(sna, -1);
772.16917 -+		sna_watch_flush(sna, -1);
772.16918 - 
772.16919 -+#if !NDEBUG
772.16920 -+	pixmap->devKind = 0xdeadbeef;
772.16921 -+#endif
772.16922 - 	if (priv->header) {
772.16923 --		assert(pixmap->drawable.pScreen == sna->scrn->pScreen);
772.16924 -+		assert(pixmap->drawable.pScreen == to_screen_from_sna(sna));
772.16925 - 		assert(!priv->shm);
772.16926 - 		pixmap->devPrivate.ptr = sna->freed_pixmap;
772.16927 - 		sna->freed_pixmap = pixmap;
772.16928 -@@ -1485,7 +1512,7 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
772.16929 - 	if (priv->shm && kgem_bo_is_busy(priv->cpu_bo)) {
772.16930 - 		DBG(("%s: deferring release of active SHM pixmap=%ld\n",
772.16931 - 		     __FUNCTION__, pixmap->drawable.serialNumber));
772.16932 --		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.16933 -+		add_shm_flush(sna, priv);
772.16934 - 		kgem_bo_submit(&sna->kgem, priv->cpu_bo); /* XXX ShmDetach */
772.16935 - 	} else
772.16936 - 		__sna_free_pixmap(sna, pixmap, priv);
772.16937 -@@ -1529,7 +1556,7 @@ static inline bool has_coherent_ptr(struct sna *sna, struct sna_pixmap *priv, un
772.16938 - 		if (!priv->cpu_bo)
772.16939 - 			return true;
772.16940 - 
772.16941 --		assert(!priv->cpu_bo->needs_flush);
772.16942 -+		assert(!priv->cpu_bo->needs_flush || (flags & MOVE_WRITE) == 0);
772.16943 - 		assert(priv->pixmap->devKind == priv->cpu_bo->pitch);
772.16944 - 		return priv->pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu);
772.16945 - 	}
772.16946 -@@ -1557,6 +1584,11 @@ static inline bool has_coherent_ptr(struct sna *sna, struct sna_pixmap *priv, un
772.16947 - 		return true;
772.16948 - 	}
772.16949 - 
772.16950 -+	if (priv->pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map__wc)) {
772.16951 -+		assert(priv->mapped == MAPPED_GTT);
772.16952 -+		return true;
772.16953 -+	}
772.16954 -+
772.16955 - 	return false;
772.16956 - }
772.16957 - 
772.16958 -@@ -1577,6 +1609,16 @@ static inline bool pixmap_inplace(struct sna *sna,
772.16959 - 		return false;
772.16960 - 
772.16961 - 	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) {
772.16962 -+		if (priv->clear) {
772.16963 -+			DBG(("%s: no, clear GPU bo is busy\n", __FUNCTION__));
772.16964 -+			return false;
772.16965 -+		}
772.16966 -+
772.16967 -+		if (flags & MOVE_ASYNC_HINT) {
772.16968 -+			DBG(("%s: no, async hint and GPU bo is busy\n", __FUNCTION__));
772.16969 -+			return false;
772.16970 -+		}
772.16971 -+
772.16972 - 		if ((flags & (MOVE_WRITE | MOVE_READ)) == (MOVE_WRITE | MOVE_READ)) {
772.16973 - 			DBG(("%s: no, GPU bo is busy\n", __FUNCTION__));
772.16974 - 			return false;
772.16975 -@@ -1624,7 +1666,7 @@ static bool sna_pixmap_alloc_gpu(struct sna *sna,
772.16976 - 	if (pixmap->usage_hint == SNA_CREATE_FB && (sna->flags & SNA_LINEAR_FB) == 0) {
772.16977 - 		flags |= CREATE_SCANOUT;
772.16978 - 		tiling = kgem_choose_tiling(&sna->kgem,
772.16979 --					    -I915_TILING_X,
772.16980 -+					    -DEFAULT_SCANOUT_TILING,
772.16981 - 					    pixmap->drawable.width,
772.16982 - 					    pixmap->drawable.height,
772.16983 - 					    pixmap->drawable.bitsPerPixel);
772.16984 -@@ -1861,7 +1903,9 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
772.16985 - 	assert(priv->gpu_bo == cow->bo);
772.16986 - 	assert(cow->refcnt);
772.16987 - 
772.16988 --	if (flags && (flags & MOVE_WRITE) == 0 && IS_COW_OWNER(priv->cow))
772.16989 -+	if (flags && /* flags == 0 => force decouple */
772.16990 -+	    (flags & MOVE_WRITE) == 0 &&
772.16991 -+	    (((flags & __MOVE_FORCE) == 0) || IS_COW_OWNER(priv->cow)))
772.16992 - 		return true;
772.16993 - 
772.16994 - 	if (!IS_COW_OWNER(priv->cow))
772.16995 -@@ -1933,7 +1977,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
772.16996 - 			box.y2 = pixmap->drawable.height;
772.16997 - 
772.16998 - 			if (flags & __MOVE_PRIME) {
772.16999 --				create = CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT;
772.17000 -+				create = CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT;
772.17001 - 				tiling = I915_TILING_NONE;
772.17002 - 			} else {
772.17003 - 				create = 0;
772.17004 -@@ -2021,6 +2065,10 @@ sna_pixmap_make_cow(struct sna *sna,
772.17005 - 		     cow->bo->handle));
772.17006 - 
772.17007 - 		src_priv->cow = MAKE_COW_OWNER(cow);
772.17008 -+		if (src_priv->flush & FLUSH_WRITE) {
772.17009 -+			assert(!src_priv->shm);
772.17010 -+			sna_add_flush_pixmap(sna, src_priv, src_priv->gpu_bo);
772.17011 -+		}
772.17012 - 	}
772.17013 - 
772.17014 - 	if (cow == COW(dst_priv->cow)) {
772.17015 -@@ -2267,6 +2315,7 @@ skip_inplace_map:
772.17016 - 	    (flags & MOVE_WRITE ? (void *)priv->gpu_bo : (void *)priv->gpu_damage) && priv->cpu_damage == NULL &&
772.17017 - 	    priv->gpu_bo->tiling == I915_TILING_NONE &&
772.17018 - 	    (flags & MOVE_READ || kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, flags & MOVE_WRITE)) &&
772.17019 -+	    (!priv->clear || !kgem_bo_is_busy(priv->gpu_bo)) &&
772.17020 - 	    ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 ||
772.17021 - 	     (!priv->cow && !priv->move_to_gpu && !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)))) {
772.17022 - 		void *ptr;
772.17023 -@@ -2330,7 +2379,9 @@ skip_inplace_map:
772.17024 - 			     pixmap->devKind, pixmap->devKind * pixmap->drawable.height));
772.17025 - 
772.17026 - 			if (priv->cpu_bo) {
772.17027 -+				kgem_bo_undo(&sna->kgem, priv->cpu_bo);
772.17028 - 				if ((flags & MOVE_ASYNC_HINT || priv->cpu_bo->exec) &&
772.17029 -+				    sna->kgem.can_blt_cpu &&
772.17030 - 				    sna->render.fill_one(sna,
772.17031 - 							  pixmap, priv->cpu_bo, priv->clear_color,
772.17032 - 							  0, 0,
772.17033 -@@ -2344,21 +2395,26 @@ skip_inplace_map:
772.17034 - 				assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
772.17035 - 			}
772.17036 - 
772.17037 --			assert(pixmap->devKind);
772.17038 --			if (priv->clear_color == 0 ||
772.17039 --			    pixmap->drawable.bitsPerPixel == 8 ||
772.17040 --			    priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
772.17041 --				memset(pixmap->devPrivate.ptr, priv->clear_color,
772.17042 --				       (size_t)pixmap->devKind * pixmap->drawable.height);
772.17043 --			} else {
772.17044 --				pixman_fill(pixmap->devPrivate.ptr,
772.17045 --					    pixmap->devKind/sizeof(uint32_t),
772.17046 --					    pixmap->drawable.bitsPerPixel,
772.17047 --					    0, 0,
772.17048 --					    pixmap->drawable.width,
772.17049 --					    pixmap->drawable.height,
772.17050 --					    priv->clear_color);
772.17051 --			}
772.17052 -+			if (sigtrap_get() == 0) {
772.17053 -+				assert(pixmap->devKind);
772.17054 -+				sigtrap_assert_active();
772.17055 -+				if (priv->clear_color == 0 ||
772.17056 -+				    pixmap->drawable.bitsPerPixel == 8 ||
772.17057 -+				    priv->clear_color == (1 << pixmap->drawable.depth) - 1) {
772.17058 -+					memset(pixmap->devPrivate.ptr, priv->clear_color,
772.17059 -+					       (size_t)pixmap->devKind * pixmap->drawable.height);
772.17060 -+				} else {
772.17061 -+					pixman_fill(pixmap->devPrivate.ptr,
772.17062 -+						    pixmap->devKind/sizeof(uint32_t),
772.17063 -+						    pixmap->drawable.bitsPerPixel,
772.17064 -+						    0, 0,
772.17065 -+						    pixmap->drawable.width,
772.17066 -+						    pixmap->drawable.height,
772.17067 -+						    priv->clear_color);
772.17068 -+				}
772.17069 -+				sigtrap_put();
772.17070 -+			} else
772.17071 -+				return false;
772.17072 - 
772.17073 - clear_done:
772.17074 - 			sna_damage_all(&priv->cpu_damage, pixmap);
772.17075 -@@ -2414,6 +2470,10 @@ done:
772.17076 - 			DBG(("%s: discarding idle GPU bo\n", __FUNCTION__));
772.17077 - 			sna_pixmap_free_gpu(sna, priv);
772.17078 - 		}
772.17079 -+		if (priv->flush) {
772.17080 -+			assert(!priv->shm);
772.17081 -+			sna_add_flush_pixmap(sna, priv, priv->gpu_bo);
772.17082 -+		}
772.17083 - 		priv->source_count = SOURCE_BIAS;
772.17084 - 	}
772.17085 - 
772.17086 -@@ -2531,6 +2591,9 @@ static bool cpu_clear_boxes(struct sna *sna,
772.17087 - {
772.17088 - 	struct sna_fill_op fill;
772.17089 - 
772.17090 -+	if (!sna->kgem.can_blt_cpu)
772.17091 -+		return false;
772.17092 -+
772.17093 - 	if (!sna_fill_init_blt(&fill, sna,
772.17094 - 			       pixmap, priv->cpu_bo,
772.17095 - 			       GXcopy, priv->clear_color,
772.17096 -@@ -2659,6 +2722,10 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
772.17097 - 					}
772.17098 - 				}
772.17099 - 				sna_damage_add_to_pixmap(&priv->cpu_damage, region, pixmap);
772.17100 -+				if (priv->flush) {
772.17101 -+					assert(!priv->shm);
772.17102 -+					sna_add_flush_pixmap(sna, priv, priv->gpu_bo);
772.17103 -+				}
772.17104 - 
772.17105 - 				if (dx | dy)
772.17106 - 					RegionTranslate(region, -dx, -dy);
772.17107 -@@ -2904,17 +2971,22 @@ move_to_cpu:
772.17108 - 			assert(pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map__cpu));
772.17109 - 		}
772.17110 - 
772.17111 --		assert(pixmap->devKind);
772.17112 --		do {
772.17113 --			pixman_fill(pixmap->devPrivate.ptr,
772.17114 --				    pixmap->devKind/sizeof(uint32_t),
772.17115 --				    pixmap->drawable.bitsPerPixel,
772.17116 --				    box->x1, box->y1,
772.17117 --				    box->x2 - box->x1,
772.17118 --				    box->y2 - box->y1,
772.17119 --				    priv->clear_color);
772.17120 --			box++;
772.17121 --		} while (--n);
772.17122 -+		if (sigtrap_get() == 0) {
772.17123 -+			assert(pixmap->devKind);
772.17124 -+			sigtrap_assert_active();
772.17125 -+			do {
772.17126 -+				pixman_fill(pixmap->devPrivate.ptr,
772.17127 -+					    pixmap->devKind/sizeof(uint32_t),
772.17128 -+					    pixmap->drawable.bitsPerPixel,
772.17129 -+					    box->x1, box->y1,
772.17130 -+					    box->x2 - box->x1,
772.17131 -+					    box->y2 - box->y1,
772.17132 -+					    priv->clear_color);
772.17133 -+				box++;
772.17134 -+			} while (--n);
772.17135 -+			sigtrap_put();
772.17136 -+		} else
772.17137 -+			return false;
772.17138 - 
772.17139 - clear_done:
772.17140 - 		if (flags & MOVE_WRITE ||
772.17141 -@@ -3209,13 +3281,14 @@ __sna_pixmap_for_gpu(struct sna *sna, PixmapPtr pixmap, unsigned flags)
772.17142 - {
772.17143 - 	struct sna_pixmap *priv;
772.17144 - 
772.17145 -+	assert(flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE));
772.17146 - 	if ((flags & __MOVE_FORCE) == 0 && wedged(sna))
772.17147 - 		return NULL;
772.17148 - 
772.17149 - 	priv = sna_pixmap(pixmap);
772.17150 - 	if (priv == NULL) {
772.17151 - 		DBG(("%s: not attached\n", __FUNCTION__));
772.17152 --		if ((flags & __MOVE_DRI) == 0)
772.17153 -+		if ((flags & (__MOVE_DRI | __MOVE_SCANOUT)) == 0)
772.17154 - 			return NULL;
772.17155 - 
772.17156 - 		if (pixmap->usage_hint == -1) {
772.17157 -@@ -3238,6 +3311,44 @@ __sna_pixmap_for_gpu(struct sna *sna, PixmapPtr pixmap, unsigned flags)
772.17158 - 	return priv;
772.17159 - }
772.17160 - 
772.17161 -+inline static void sna_pixmap_unclean(struct sna *sna,
772.17162 -+				      struct sna_pixmap *priv,
772.17163 -+				      unsigned flags)
772.17164 -+{
772.17165 -+	struct drm_i915_gem_busy busy;
772.17166 -+
772.17167 -+	assert(DAMAGE_IS_ALL(priv->gpu_damage));
772.17168 -+	assert(priv->gpu_bo);
772.17169 -+	assert(priv->gpu_bo->proxy == NULL);
772.17170 -+	assert_pixmap_map(priv->pixmap, priv);
772.17171 -+
772.17172 -+	sna_damage_destroy(&priv->cpu_damage);
772.17173 -+	list_del(&priv->flush_list);
772.17174 -+
772.17175 -+	if (flags & (__MOVE_DRI | __MOVE_SCANOUT))
772.17176 -+		return;
772.17177 -+
772.17178 -+	if (!priv->flush || priv->gpu_bo->exec)
772.17179 -+		return;
772.17180 -+
772.17181 -+	busy.handle = priv->gpu_bo->handle;
772.17182 -+	busy.busy = 0;
772.17183 -+	ioctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
772.17184 -+
772.17185 -+	DBG(("%s(pixmap=%ld): cleaning foreign bo handle=%u, busy=%x [ring=%d]\n",
772.17186 -+	     __FUNCTION__,
772.17187 -+	     priv->pixmap->drawable.serialNumber,
772.17188 -+	     busy.handle, busy.busy, !!(busy.busy & (0xfffe << 16))));
772.17189 -+
772.17190 -+	if (busy.busy) {
772.17191 -+		unsigned mode = KGEM_RENDER;
772.17192 -+		if (busy.busy & (0xfffe << 16))
772.17193 -+			mode = KGEM_BLT;
772.17194 -+		kgem_bo_mark_busy(&sna->kgem, priv->gpu_bo, mode);
772.17195 -+	} else
772.17196 -+		__kgem_bo_clear_busy(priv->gpu_bo);
772.17197 -+}
772.17198 -+
772.17199 - struct sna_pixmap *
772.17200 - sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int flags)
772.17201 - {
772.17202 -@@ -3287,12 +3398,14 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
772.17203 - 	if (priv->cow) {
772.17204 - 		unsigned cow = flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE);
772.17205 - 
772.17206 -+		assert(cow);
772.17207 -+
772.17208 - 		if ((flags & MOVE_READ) == 0) {
772.17209 - 			if (priv->gpu_damage) {
772.17210 - 				r.extents = *box;
772.17211 - 				r.data = NULL;
772.17212 - 				if (!region_subsumes_damage(&r, priv->gpu_damage))
772.17213 --					cow |= MOVE_READ;
772.17214 -+					cow |= MOVE_READ | __MOVE_FORCE;
772.17215 - 			}
772.17216 - 		} else {
772.17217 - 			if (priv->cpu_damage) {
772.17218 -@@ -3303,22 +3416,18 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
772.17219 - 			}
772.17220 - 		}
772.17221 - 
772.17222 --		if (cow) {
772.17223 --			if (!sna_pixmap_undo_cow(sna, priv, cow))
772.17224 --				return NULL;
772.17225 -+		if (!sna_pixmap_undo_cow(sna, priv, cow))
772.17226 -+			return NULL;
772.17227 - 
772.17228 --			if (priv->gpu_bo == NULL)
772.17229 --				sna_damage_destroy(&priv->gpu_damage);
772.17230 --		}
772.17231 -+		if (priv->gpu_bo == NULL)
772.17232 -+			sna_damage_destroy(&priv->gpu_damage);
772.17233 - 	}
772.17234 - 
772.17235 - 	if (sna_damage_is_all(&priv->gpu_damage,
772.17236 - 			      pixmap->drawable.width,
772.17237 - 			      pixmap->drawable.height)) {
772.17238 --		assert(priv->gpu_bo);
772.17239 --		assert(priv->gpu_bo->proxy == NULL);
772.17240 --		sna_damage_destroy(&priv->cpu_damage);
772.17241 --		list_del(&priv->flush_list);
772.17242 -+		DBG(("%s: already all-damaged\n", __FUNCTION__));
772.17243 -+		sna_pixmap_unclean(sna, priv, flags);
772.17244 - 		goto done;
772.17245 - 	}
772.17246 - 
772.17247 -@@ -3360,10 +3469,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
772.17248 - 		return priv;
772.17249 - 	}
772.17250 - 
772.17251 --	if (priv->shm) {
772.17252 --		assert(!priv->flush);
772.17253 --		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.17254 --	}
772.17255 -+	add_shm_flush(sna, priv);
772.17256 - 
772.17257 - 	assert(priv->cpu_damage);
772.17258 - 	region_set(&r, box);
772.17259 -@@ -3527,7 +3633,8 @@ sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
772.17260 - 	}
772.17261 - 
772.17262 - 	if (priv->cow) {
772.17263 --		unsigned cow = MOVE_WRITE | MOVE_READ;
772.17264 -+		unsigned cow = MOVE_WRITE | MOVE_READ | __MOVE_FORCE;
772.17265 -+		assert(cow);
772.17266 - 
772.17267 - 		if (flags & IGNORE_DAMAGE) {
772.17268 - 			if (priv->gpu_damage) {
772.17269 -@@ -3717,8 +3824,11 @@ create_gpu_bo:
772.17270 - 				else
772.17271 - 					move = MOVE_WRITE | MOVE_READ | MOVE_ASYNC_HINT;
772.17272 - 
772.17273 --				if (sna_pixmap_move_to_gpu(pixmap, move))
772.17274 -+				if (sna_pixmap_move_to_gpu(pixmap, move)) {
772.17275 -+					sna_damage_all(&priv->gpu_damage,
772.17276 -+						       pixmap);
772.17277 - 					goto use_gpu_bo;
772.17278 -+				}
772.17279 - 			}
772.17280 - 
772.17281 - 			if (DAMAGE_IS_ALL(priv->gpu_damage) ||
772.17282 -@@ -3934,26 +4044,28 @@ prefer_gpu_bo:
772.17283 - 			goto move_to_gpu;
772.17284 - 		}
772.17285 - 
772.17286 --		if ((priv->cpu_damage == NULL || flags & IGNORE_DAMAGE)) {
772.17287 --			if (priv->gpu_bo && priv->gpu_bo->tiling) {
772.17288 --				DBG(("%s: prefer to use GPU bo for rendering large pixmaps\n", __FUNCTION__));
772.17289 --				goto prefer_gpu_bo;
772.17290 -+		if (!priv->shm) {
772.17291 -+			if ((priv->cpu_damage == NULL || flags & IGNORE_DAMAGE)) {
772.17292 -+				if (priv->gpu_bo && priv->gpu_bo->tiling) {
772.17293 -+					DBG(("%s: prefer to use GPU bo for rendering large pixmaps\n", __FUNCTION__));
772.17294 -+					goto prefer_gpu_bo;
772.17295 -+				}
772.17296 -+
772.17297 -+				if (priv->cpu_bo->pitch >= 4096) {
772.17298 -+					DBG(("%s: prefer to use GPU bo for rendering wide pixmaps\n", __FUNCTION__));
772.17299 -+					goto prefer_gpu_bo;
772.17300 -+				}
772.17301 - 			}
772.17302 - 
772.17303 --			if (priv->cpu_bo->pitch >= 4096) {
772.17304 --				DBG(("%s: prefer to use GPU bo for rendering wide pixmaps\n", __FUNCTION__));
772.17305 -+			if ((flags & IGNORE_DAMAGE) == 0 && priv->cpu_bo->snoop) {
772.17306 -+				DBG(("%s: prefer to use GPU bo for reading from snooped target bo\n", __FUNCTION__));
772.17307 - 				goto prefer_gpu_bo;
772.17308 - 			}
772.17309 --		}
772.17310 --
772.17311 --		if ((flags & IGNORE_DAMAGE) == 0 && priv->cpu_bo->snoop) {
772.17312 --			DBG(("%s: prefer to use GPU bo for reading from snooped target bo\n", __FUNCTION__));
772.17313 --			goto prefer_gpu_bo;
772.17314 --		}
772.17315 - 
772.17316 --		if (!sna->kgem.can_blt_cpu) {
772.17317 --			DBG(("%s: can't render to CPU bo, try to use GPU bo\n", __FUNCTION__));
772.17318 --			goto prefer_gpu_bo;
772.17319 -+			if (!sna->kgem.can_blt_cpu) {
772.17320 -+				DBG(("%s: can't render to CPU bo, try to use GPU bo\n", __FUNCTION__));
772.17321 -+				goto prefer_gpu_bo;
772.17322 -+			}
772.17323 - 		}
772.17324 - 	}
772.17325 - 
772.17326 -@@ -3967,9 +4079,7 @@ prefer_gpu_bo:
772.17327 - 	}
772.17328 - 
772.17329 - 	if (priv->shm) {
772.17330 --		assert(!priv->flush);
772.17331 --		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.17332 --
772.17333 -+		add_shm_flush(sna, priv);
772.17334 - 		/* As we may have flushed and retired,, recheck for busy bo */
772.17335 - 		if ((flags & FORCE_GPU) == 0 && !kgem_bo_is_busy(priv->cpu_bo))
772.17336 - 			return NULL;
772.17337 -@@ -4019,7 +4129,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
772.17338 - 	assert(width);
772.17339 - 	assert(height);
772.17340 - 
772.17341 --	if (depth == 1)
772.17342 -+	if (depth < 8)
772.17343 - 		return create_pixmap(sna, screen, width, height, depth,
772.17344 - 				     CREATE_PIXMAP_USAGE_SCRATCH);
772.17345 - 
772.17346 -@@ -4121,27 +4231,21 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
772.17347 - 
772.17348 - 	if (priv->cow) {
772.17349 - 		unsigned cow = flags & (MOVE_READ | MOVE_WRITE | __MOVE_FORCE);
772.17350 -+		assert(cow);
772.17351 - 		if (flags & MOVE_READ && priv->cpu_damage)
772.17352 - 			cow |= MOVE_WRITE;
772.17353 --		if (cow) {
772.17354 --			if (!sna_pixmap_undo_cow(sna, priv, cow))
772.17355 --				return NULL;
772.17356 -+		if (!sna_pixmap_undo_cow(sna, priv, cow))
772.17357 -+			return NULL;
772.17358 - 
772.17359 --			if (priv->gpu_bo == NULL)
772.17360 --				sna_damage_destroy(&priv->gpu_damage);
772.17361 --		}
772.17362 -+		if (priv->gpu_bo == NULL)
772.17363 -+			sna_damage_destroy(&priv->gpu_damage);
772.17364 - 	}
772.17365 - 
772.17366 - 	if (sna_damage_is_all(&priv->gpu_damage,
772.17367 - 			      pixmap->drawable.width,
772.17368 - 			      pixmap->drawable.height)) {
772.17369 - 		DBG(("%s: already all-damaged\n", __FUNCTION__));
772.17370 --		assert(DAMAGE_IS_ALL(priv->gpu_damage));
772.17371 --		assert(priv->gpu_bo);
772.17372 --		assert(priv->gpu_bo->proxy == NULL);
772.17373 --		assert_pixmap_map(pixmap, priv);
772.17374 --		sna_damage_destroy(&priv->cpu_damage);
772.17375 --		list_del(&priv->flush_list);
772.17376 -+		sna_pixmap_unclean(sna, priv, flags);
772.17377 - 		goto active;
772.17378 - 	}
772.17379 - 
772.17380 -@@ -4206,7 +4310,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
772.17381 - 				if (flags & MOVE_INPLACE_HINT || (priv->cpu_damage && priv->cpu_bo == NULL))
772.17382 - 					create = CREATE_GTT_MAP | CREATE_INACTIVE;
772.17383 - 				if (flags & __MOVE_PRIME)
772.17384 --					create |= CREATE_GTT_MAP | CREATE_PRIME | CREATE_EXACT;
772.17385 -+					create |= CREATE_GTT_MAP | CREATE_SCANOUT | CREATE_PRIME | CREATE_EXACT;
772.17386 - 
772.17387 - 				sna_pixmap_alloc_gpu(sna, pixmap, priv, create);
772.17388 - 			}
772.17389 -@@ -4282,10 +4386,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
772.17390 - 		goto done;
772.17391 - 	}
772.17392 - 
772.17393 --	if (priv->shm) {
772.17394 --		assert(!priv->flush);
772.17395 --		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.17396 --	}
772.17397 -+	add_shm_flush(sna, priv);
772.17398 - 
772.17399 - 	n = sna_damage_get_boxes(priv->cpu_damage, &box);
772.17400 - 	assert(n);
772.17401 -@@ -4534,7 +4635,7 @@ static inline bool box32_trim_and_translate(Box32Rec *box, DrawablePtr d, GCPtr
772.17402 - 	return box32_clip(box, gc);
772.17403 - }
772.17404 - 
772.17405 --static inline void box_add_pt(BoxPtr box, int16_t x, int16_t y)
772.17406 -+static inline void box_add_xy(BoxPtr box, int16_t x, int16_t y)
772.17407 - {
772.17408 - 	if (box->x1 > x)
772.17409 - 		box->x1 = x;
772.17410 -@@ -4547,6 +4648,11 @@ static inline void box_add_pt(BoxPtr box, int16_t x, int16_t y)
772.17411 - 		box->y2 = y;
772.17412 - }
772.17413 - 
772.17414 -+static inline void box_add_pt(BoxPtr box, const DDXPointRec *pt)
772.17415 -+{
772.17416 -+	box_add_xy(box, pt->x, pt->y);
772.17417 -+}
772.17418 -+
772.17419 - static inline bool box32_to_box16(const Box32Rec *b32, BoxRec *b16)
772.17420 - {
772.17421 - 	b16->x1 = b32->x1;
772.17422 -@@ -4864,6 +4970,7 @@ try_upload__inplace(PixmapPtr pixmap, RegionRec *region,
772.17423 - 	pixmap->devPrivate.ptr = dst;
772.17424 - 	pixmap->devKind = priv->gpu_bo->pitch;
772.17425 - 	priv->mapped = dst == MAP(priv->gpu_bo->map__cpu) ? MAPPED_CPU : MAPPED_GTT;
772.17426 -+	priv->cpu &= priv->mapped == MAPPED_CPU;
772.17427 - 	assert(has_coherent_ptr(sna, priv, MOVE_WRITE));
772.17428 - 
772.17429 - 	box = region_rects(region);
772.17430 -@@ -4923,8 +5030,7 @@ done:
772.17431 - 			sna_damage_all(&priv->gpu_damage, pixmap);
772.17432 - 		}
772.17433 - 
772.17434 --		if (priv->shm)
772.17435 --			sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.17436 -+		add_shm_flush(sna, priv);
772.17437 - 	}
772.17438 - 
772.17439 - 	assert(!priv->clear);
772.17440 -@@ -5172,6 +5278,16 @@ static inline uint8_t blt_depth(int depth)
772.17441 - 	}
772.17442 - }
772.17443 - 
772.17444 -+inline static void blt_done(struct sna *sna)
772.17445 -+{
772.17446 -+	sna->blt_state.fill_bo = 0;
772.17447 -+	if (sna->kgem.nbatch && __kgem_ring_empty(&sna->kgem)) {
772.17448 -+		DBG(("%s: flushing BLT operation on empty ring\n",
772.17449 -+		     __FUNCTION__));
772.17450 -+		_kgem_submit(&sna->kgem);
772.17451 -+	}
772.17452 -+}
772.17453 -+
772.17454 - static bool
772.17455 - sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17456 - 		     int x, int y, int w, int  h, char *bits)
772.17457 -@@ -5217,6 +5333,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17458 - 
772.17459 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.17460 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.17461 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.17462 - 
772.17463 - 	/* Region is pre-clipped and translated into pixmap space */
772.17464 - 	box = region_rects(region);
772.17465 -@@ -5238,6 +5355,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17466 - 				return false;
772.17467 - 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.17468 - 		}
772.17469 -+		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.17470 - 
772.17471 - 		upload = kgem_create_buffer(&sna->kgem,
772.17472 - 					    bstride*bh,
772.17473 -@@ -5331,7 +5449,7 @@ sna_put_xybitmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17474 - 		box++;
772.17475 - 	} while (--n);
772.17476 - 
772.17477 --	sna->blt_state.fill_bo = 0;
772.17478 -+	blt_done(sna);
772.17479 - 	return true;
772.17480 - }
772.17481 - 
772.17482 -@@ -5381,6 +5499,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17483 - 
772.17484 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.17485 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.17486 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.17487 - 
772.17488 - 	skip = h * BitmapBytePad(w + left);
772.17489 - 	for (i = 1 << (gc->depth-1); i; i >>= 1, bits += skip) {
772.17490 -@@ -5408,6 +5527,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17491 - 					return false;
772.17492 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.17493 - 			}
772.17494 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.17495 - 
772.17496 - 			upload = kgem_create_buffer(&sna->kgem,
772.17497 - 						    bstride*bh,
772.17498 -@@ -5509,7 +5629,7 @@ sna_put_xypixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
772.17499 - 		} while (--n);
772.17500 - 	}
772.17501 - 
772.17502 --	sna->blt_state.fill_bo = 0;
772.17503 -+	blt_done(sna);
772.17504 - 	return true;
772.17505 - }
772.17506 - 
772.17507 -@@ -5837,7 +5957,7 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
772.17508 - 		if (!sna->render.copy_boxes(sna, alu,
772.17509 - 					    &pixmap->drawable, priv->gpu_bo, sx, sy,
772.17510 - 					    &pixmap->drawable, priv->gpu_bo, tx, ty,
772.17511 --					    box, n, 0)) {
772.17512 -+					    box, n, small_copy(region))) {
772.17513 - 			DBG(("%s: fallback - accelerated copy boxes failed\n",
772.17514 - 			     __FUNCTION__));
772.17515 - 			goto fallback;
772.17516 -@@ -6098,6 +6218,9 @@ sna_copy_boxes__inplace(struct sna *sna, RegionPtr region, int alu,
772.17517 - 
772.17518 - 	kgem_bo_sync__cpu_full(&sna->kgem, src_priv->gpu_bo, FORCE_FULL_SYNC);
772.17519 - 
772.17520 -+	if (sigtrap_get())
772.17521 -+		return false;
772.17522 -+
772.17523 - 	box = region_rects(region);
772.17524 - 	n = region_num_rects(region);
772.17525 - 	if (src_priv->gpu_bo->tiling) {
772.17526 -@@ -6137,6 +6260,8 @@ sna_copy_boxes__inplace(struct sna *sna, RegionPtr region, int alu,
772.17527 - 		}
772.17528 - 	}
772.17529 - 
772.17530 -+	sigtrap_put();
772.17531 -+
772.17532 - 	return true;
772.17533 - 
772.17534 - upload_inplace:
772.17535 -@@ -6234,6 +6359,9 @@ upload_inplace:
772.17536 - 
772.17537 - 	assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
772.17538 - 
772.17539 -+	if (sigtrap_get())
772.17540 -+		return false;
772.17541 -+
772.17542 - 	box = region_rects(region);
772.17543 - 	n = region_num_rects(region);
772.17544 - 	if (dst_priv->gpu_bo->tiling) {
772.17545 -@@ -6265,15 +6393,19 @@ upload_inplace:
772.17546 - 		} while (--n);
772.17547 - 
772.17548 - 		if (!dst_priv->shm) {
772.17549 --			assert(ptr == MAP(dst_priv->gpu_bo->map__cpu));
772.17550 - 			dst_pixmap->devPrivate.ptr = ptr;
772.17551 - 			dst_pixmap->devKind = dst_priv->gpu_bo->pitch;
772.17552 --			dst_priv->mapped = MAPPED_CPU;
772.17553 -+			if (ptr == MAP(dst_priv->gpu_bo->map__cpu)) {
772.17554 -+				dst_priv->mapped = MAPPED_CPU;
772.17555 -+				dst_priv->cpu = true;
772.17556 -+			} else
772.17557 -+				dst_priv->mapped = MAPPED_GTT;
772.17558 - 			assert_pixmap_map(dst_pixmap, dst_priv);
772.17559 --			dst_priv->cpu = true;
772.17560 - 		}
772.17561 - 	}
772.17562 - 
772.17563 -+	sigtrap_put();
772.17564 -+
772.17565 - 	return true;
772.17566 - }
772.17567 - 
772.17568 -@@ -6326,6 +6458,16 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
772.17569 - 
772.17570 - 	assert(region_num_rects(region));
772.17571 - 
772.17572 -+	if (src_priv &&
772.17573 -+	    src_priv->gpu_bo == NULL &&
772.17574 -+	    src_priv->cpu_bo == NULL &&
772.17575 -+	    src_priv->ptr == NULL) {
772.17576 -+		/* Rare but still happens, nothing to copy */
772.17577 -+		DBG(("%s: src pixmap=%ld is empty\n",
772.17578 -+		     __FUNCTION__, src_pixmap->drawable.serialNumber));
772.17579 -+		return;
772.17580 -+	}
772.17581 -+
772.17582 - 	if (src_pixmap == dst_pixmap)
772.17583 - 		return sna_self_copy_boxes(src, dst, gc,
772.17584 - 					   region, dx, dy,
772.17585 -@@ -6491,15 +6633,14 @@ discard_cow:
772.17586 - 					sna_damage_all(&dst_priv->gpu_damage, dst_pixmap);
772.17587 - 					sna_damage_destroy(&dst_priv->cpu_damage);
772.17588 - 					list_del(&dst_priv->flush_list);
772.17589 --					if (dst_priv->shm)
772.17590 --						sna_add_flush_pixmap(sna, dst_priv, dst_priv->cpu_bo);
772.17591 -+					add_shm_flush(sna, dst_priv);
772.17592 - 					return;
772.17593 - 				}
772.17594 - 			}
772.17595 - 			if (!sna->render.copy_boxes(sna, alu,
772.17596 - 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
772.17597 - 						    &dst_pixmap->drawable, bo, 0, 0,
772.17598 --						    box, n, 0)) {
772.17599 -+						    box, n, small_copy(region))) {
772.17600 - 				DBG(("%s: fallback - accelerated copy boxes failed\n",
772.17601 - 				     __FUNCTION__));
772.17602 - 				goto fallback;
772.17603 -@@ -6536,7 +6677,7 @@ discard_cow:
772.17604 - 			if (!sna->render.copy_boxes(sna, alu,
772.17605 - 						    &src_pixmap->drawable, src_priv->gpu_bo, src_dx, src_dy,
772.17606 - 						    &dst_pixmap->drawable, bo, 0, 0,
772.17607 --						    box, n, 0)) {
772.17608 -+						    box, n, small_copy(region))) {
772.17609 - 				DBG(("%s: fallback - accelerated copy boxes failed\n",
772.17610 - 				     __FUNCTION__));
772.17611 - 				goto fallback;
772.17612 -@@ -6571,15 +6712,12 @@ discard_cow:
772.17613 - 			if (replaces && UNDO)
772.17614 - 				kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
772.17615 - 
772.17616 --			if (src_priv->shm) {
772.17617 --				assert(!src_priv->flush);
772.17618 --				sna_add_flush_pixmap(sna, src_priv, src_priv->cpu_bo);
772.17619 --			}
772.17620 -+			add_shm_flush(sna, src_priv);
772.17621 - 
772.17622 - 			if (!sna->render.copy_boxes(sna, alu,
772.17623 - 						    &src_pixmap->drawable, src_priv->cpu_bo, src_dx, src_dy,
772.17624 - 						    &dst_pixmap->drawable, bo, 0, 0,
772.17625 --						    box, n, src_priv->shm ? COPY_LAST : 0)) {
772.17626 -+						    box, n, small_copy(region) | (src_priv->shm ? COPY_LAST : 0))) {
772.17627 - 				DBG(("%s: fallback - accelerated copy boxes failed\n",
772.17628 - 				     __FUNCTION__));
772.17629 - 				goto fallback;
772.17630 -@@ -6631,8 +6769,7 @@ discard_cow:
772.17631 - 				ok = sna->render.copy_boxes(sna, alu,
772.17632 - 							    &src_pixmap->drawable, src_bo, src_dx, src_dy,
772.17633 - 							    &dst_pixmap->drawable, bo, 0, 0,
772.17634 --							    box, n, COPY_LAST);
772.17635 --
772.17636 -+							    box, n, small_copy(region) |  COPY_LAST);
772.17637 - 				kgem_bo_sync__cpu(&sna->kgem, src_bo);
772.17638 - 				assert(src_bo->rq == NULL);
772.17639 - 				kgem_bo_destroy(&sna->kgem, src_bo);
772.17640 -@@ -6780,18 +6917,22 @@ fallback:
772.17641 - 				return;
772.17642 - 		}
772.17643 - 
772.17644 --		assert(dst_pixmap->devPrivate.ptr);
772.17645 --		assert(dst_pixmap->devKind);
772.17646 --		do {
772.17647 --			pixman_fill(dst_pixmap->devPrivate.ptr,
772.17648 --				    dst_pixmap->devKind/sizeof(uint32_t),
772.17649 --				    dst_pixmap->drawable.bitsPerPixel,
772.17650 --				    box->x1, box->y1,
772.17651 --				    box->x2 - box->x1,
772.17652 --				    box->y2 - box->y1,
772.17653 --				    src_priv->clear_color);
772.17654 --			box++;
772.17655 --		} while (--n);
772.17656 -+		if (sigtrap_get() == 0) {
772.17657 -+			assert(dst_pixmap->devPrivate.ptr);
772.17658 -+			assert(dst_pixmap->devKind);
772.17659 -+			sigtrap_assert_active();
772.17660 -+			do {
772.17661 -+				pixman_fill(dst_pixmap->devPrivate.ptr,
772.17662 -+					    dst_pixmap->devKind/sizeof(uint32_t),
772.17663 -+					    dst_pixmap->drawable.bitsPerPixel,
772.17664 -+					    box->x1, box->y1,
772.17665 -+					    box->x2 - box->x1,
772.17666 -+					    box->y2 - box->y1,
772.17667 -+					    src_priv->clear_color);
772.17668 -+				box++;
772.17669 -+			} while (--n);
772.17670 -+			sigtrap_put();
772.17671 -+		}
772.17672 - 	} else if (!sna_copy_boxes__inplace(sna, region, alu,
772.17673 - 					    src_pixmap, src_priv,
772.17674 - 					    src_dx, src_dy,
772.17675 -@@ -6848,36 +6989,39 @@ fallback:
772.17676 - 				((char *)src_pixmap->devPrivate.ptr +
772.17677 - 				 src_dy * src_stride + src_dx * bpp / 8);
772.17678 - 
772.17679 --			do {
772.17680 --				DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
772.17681 --				     __FUNCTION__,
772.17682 --				     box->x1, box->y1,
772.17683 --				     box->x2 - box->x1,
772.17684 --				     box->y2 - box->y1,
772.17685 --				     src_dx, src_dy,
772.17686 --				     src_stride, dst_stride));
772.17687 --
772.17688 --				assert(box->x1 >= 0);
772.17689 --				assert(box->y1 >= 0);
772.17690 --				assert(box->x2 <= dst_pixmap->drawable.width);
772.17691 --				assert(box->y2 <= dst_pixmap->drawable.height);
772.17692 --
772.17693 --				assert(box->x1 + src_dx >= 0);
772.17694 --				assert(box->y1 + src_dy >= 0);
772.17695 --				assert(box->x2 + src_dx <= src_pixmap->drawable.width);
772.17696 --				assert(box->y2 + src_dy <= src_pixmap->drawable.height);
772.17697 --				assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
772.17698 --				assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
772.17699 --				assert(src_stride);
772.17700 --				assert(dst_stride);
772.17701 --				memcpy_blt(src_bits, dst_bits, bpp,
772.17702 --					   src_stride, dst_stride,
772.17703 --					   box->x1, box->y1,
772.17704 --					   box->x1, box->y1,
772.17705 --					   box->x2 - box->x1,
772.17706 --					   box->y2 - box->y1);
772.17707 --				box++;
772.17708 --			} while (--n);
772.17709 -+			if (sigtrap_get() == 0) {
772.17710 -+				do {
772.17711 -+					DBG(("%s: memcpy_blt(box=(%d, %d), (%d, %d), src=(%d, %d), pitches=(%d, %d))\n",
772.17712 -+					     __FUNCTION__,
772.17713 -+					     box->x1, box->y1,
772.17714 -+					     box->x2 - box->x1,
772.17715 -+					     box->y2 - box->y1,
772.17716 -+					     src_dx, src_dy,
772.17717 -+					     src_stride, dst_stride));
772.17718 -+
772.17719 -+					assert(box->x1 >= 0);
772.17720 -+					assert(box->y1 >= 0);
772.17721 -+					assert(box->x2 <= dst_pixmap->drawable.width);
772.17722 -+					assert(box->y2 <= dst_pixmap->drawable.height);
772.17723 -+
772.17724 -+					assert(box->x1 + src_dx >= 0);
772.17725 -+					assert(box->y1 + src_dy >= 0);
772.17726 -+					assert(box->x2 + src_dx <= src_pixmap->drawable.width);
772.17727 -+					assert(box->y2 + src_dy <= src_pixmap->drawable.height);
772.17728 -+					assert(has_coherent_ptr(sna, src_priv, MOVE_READ));
772.17729 -+					assert(has_coherent_ptr(sna, dst_priv, MOVE_WRITE));
772.17730 -+					assert(src_stride);
772.17731 -+					assert(dst_stride);
772.17732 -+					memcpy_blt(src_bits, dst_bits, bpp,
772.17733 -+						   src_stride, dst_stride,
772.17734 -+						   box->x1, box->y1,
772.17735 -+						   box->x1, box->y1,
772.17736 -+						   box->x2 - box->x1,
772.17737 -+						   box->y2 - box->y1);
772.17738 -+					box++;
772.17739 -+				} while (--n);
772.17740 -+				sigtrap_put();
772.17741 -+			}
772.17742 - 		} else {
772.17743 - 			DBG(("%s: fallback -- miCopyRegion\n", __FUNCTION__));
772.17744 - 
772.17745 -@@ -6931,7 +7075,8 @@ sna_do_copy(DrawablePtr src, DrawablePtr dst, GCPtr gc,
772.17746 - 
772.17747 - 	/* Short cut for unmapped windows */
772.17748 - 	if (dst->type == DRAWABLE_WINDOW && !((WindowPtr)dst)->realized) {
772.17749 --		DBG(("%s: unmapped\n", __FUNCTION__));
772.17750 -+		DBG(("%s: unmapped/unrealized dst (pixmap=%ld)\n",
772.17751 -+		     __FUNCTION__, get_window_pixmap((WindowPtr)dst)));
772.17752 - 		return NULL;
772.17753 - 	}
772.17754 - 
772.17755 -@@ -7115,19 +7260,28 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
772.17756 - 	if (gc->planemask == 0)
772.17757 - 		return NULL;
772.17758 - 
772.17759 --	DBG(("%s: src=(%d, %d)x(%d, %d)+(%d, %d) -> dst=(%d, %d)+(%d, %d); alu=%d, pm=%lx, depth=%d\n",
772.17760 -+	if (sna->ignore_copy_area)
772.17761 -+		return NULL;
772.17762 -+
772.17763 -+	DBG(("%s: src=pixmap=%ld:(%d, %d)x(%d, %d)+(%d, %d) -> dst=pixmap=%ld:(%d, %d)+(%d, %d); alu=%d, pm=%lx, depth=%d\n",
772.17764 - 	     __FUNCTION__,
772.17765 -+	     get_drawable_pixmap(src)->drawable.serialNumber,
772.17766 - 	     src_x, src_y, width, height, src->x, src->y,
772.17767 -+	     get_drawable_pixmap(dst)->drawable.serialNumber,
772.17768 - 	     dst_x, dst_y, dst->x, dst->y,
772.17769 - 	     gc->alu, gc->planemask, gc->depth));
772.17770 - 
772.17771 - 	if (FORCE_FALLBACK || !ACCEL_COPY_AREA || wedged(sna) ||
772.17772 --	    !PM_IS_SOLID(dst, gc->planemask) || gc->depth < 8)
772.17773 -+	    !PM_IS_SOLID(dst, gc->planemask) || gc->depth < 8) {
772.17774 -+		DBG(("%s: fallback copy\n", __FUNCTION__));
772.17775 - 		copy = sna_fallback_copy_boxes;
772.17776 --	else if (src == dst)
772.17777 -+	} else if (src == dst) {
772.17778 -+		DBG(("%s: self copy\n", __FUNCTION__));
772.17779 - 		copy = sna_self_copy_boxes;
772.17780 --	else
772.17781 -+	} else {
772.17782 -+		DBG(("%s: normal copy\n", __FUNCTION__));
772.17783 - 		copy = sna_copy_boxes;
772.17784 -+	}
772.17785 - 
772.17786 - 	return sna_do_copy(src, dst, gc,
772.17787 - 			   src_x, src_y,
772.17788 -@@ -7136,30 +7290,21 @@ sna_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
772.17789 - 			   copy, 0, NULL);
772.17790 - }
772.17791 - 
772.17792 --static const BoxRec *
772.17793 --find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
772.17794 -+const BoxRec *
772.17795 -+__find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
772.17796 - {
772.17797 --    const BoxRec *mid;
772.17798 --
772.17799 --    if (end == begin)
772.17800 --	return end;
772.17801 --
772.17802 --    if (end - begin == 1) {
772.17803 -+	assert(end - begin > 1);
772.17804 -+	do {
772.17805 -+		const BoxRec *mid = begin + (end - begin) / 2;
772.17806 -+		if (mid->y2 > y)
772.17807 -+			end = mid;
772.17808 -+		else
772.17809 -+			begin = mid;
772.17810 -+	} while (end > begin + 1);
772.17811 - 	if (begin->y2 > y)
772.17812 --	    return begin;
772.17813 -+		return begin;
772.17814 - 	else
772.17815 --	    return end;
772.17816 --    }
772.17817 --
772.17818 --    mid = begin + (end - begin) / 2;
772.17819 --    if (mid->y2 > y)
772.17820 --	/* If no box is found in [begin, mid], the function
772.17821 --	 * will return @mid, which is then known to be the
772.17822 --	 * correct answer.
772.17823 --	 */
772.17824 --	return find_clip_box_for_y(begin, mid, y);
772.17825 --    else
772.17826 --	return find_clip_box_for_y(mid, end, y);
772.17827 -+		return end;
772.17828 - }
772.17829 - 
772.17830 - struct sna_fill_spans {
772.17831 -@@ -8223,6 +8368,8 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
772.17832 - 	}
772.17833 - 	br13 |= blt_depth(drawable->depth) << 24;
772.17834 - 	br13 |= copy_ROP[gc->alu] << 16;
772.17835 -+	DBG(("%s: target-depth=%d, alu=%d, bg=%08x, fg=%08x\n",
772.17836 -+	     __FUNCTION__, drawable->depth, gc->alu, gc->bgPixel, gc->fgPixel));
772.17837 - 
772.17838 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, arg->bo);
772.17839 - 	assert(kgem_bo_can_blt(&sna->kgem, arg->bo));
772.17840 -@@ -8255,6 +8402,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
772.17841 - 					return; /* XXX fallback? */
772.17842 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.17843 - 			}
772.17844 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
772.17845 - 
772.17846 - 			assert(sna->kgem.mode == KGEM_BLT);
772.17847 - 			if (sna->kgem.gen >= 0100) {
772.17848 -@@ -8270,8 +8418,8 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
772.17849 - 							 I915_GEM_DOMAIN_RENDER |
772.17850 - 							 KGEM_RELOC_FENCED,
772.17851 - 							 0);
772.17852 --				b[5] = gc->bgPixel;
772.17853 --				b[6] = gc->fgPixel;
772.17854 -+				b[6] = gc->bgPixel;
772.17855 -+				b[7] = gc->fgPixel;
772.17856 - 
772.17857 - 				dst = (uint8_t *)&b[8];
772.17858 - 				sna->kgem.nbatch += 8 + src_stride;
772.17859 -@@ -8322,6 +8470,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
772.17860 - 					return; /* XXX fallback? */
772.17861 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.17862 - 			}
772.17863 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
772.17864 - 
772.17865 - 			upload = kgem_create_buffer(&sna->kgem,
772.17866 - 						    bstride*bh,
772.17867 -@@ -8408,7 +8557,7 @@ sna_copy_bitmap_blt(DrawablePtr _bitmap, DrawablePtr drawable, GCPtr gc,
772.17868 - 		sna_damage_add_to_pixmap(arg->damage, region, pixmap);
772.17869 - 	}
772.17870 - 	assert_pixmap_damage(pixmap);
772.17871 --	sna->blt_state.fill_bo = 0;
772.17872 -+	blt_done(sna);
772.17873 - }
772.17874 - 
772.17875 - static void
772.17876 -@@ -8472,6 +8621,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
772.17877 - 				return; /* XXX fallback? */
772.17878 - 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.17879 - 		}
772.17880 -+		kgem_bcs_set_tiling(&sna->kgem, NULL, arg->bo);
772.17881 - 
772.17882 - 		upload = kgem_create_buffer(&sna->kgem,
772.17883 - 					    bstride*bh,
772.17884 -@@ -8588,6 +8738,8 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
772.17885 - 				}
772.17886 - 			}
772.17887 - 
772.17888 -+			kgem_bcs_set_tiling(&sna->kgem, upload, arg->bo);
772.17889 -+
772.17890 - 			assert(sna->kgem.mode == KGEM_BLT);
772.17891 - 			b = sna->kgem.batch + sna->kgem.nbatch;
772.17892 - 			if (sna->kgem.gen >= 0100) {
772.17893 -@@ -8641,7 +8793,7 @@ sna_copy_plane_blt(DrawablePtr source, DrawablePtr drawable, GCPtr gc,
772.17894 - 		sna_damage_add_to_pixmap(arg->damage, region, dst_pixmap);
772.17895 - 	}
772.17896 - 	assert_pixmap_damage(dst_pixmap);
772.17897 --	sna->blt_state.fill_bo = 0;
772.17898 -+	blt_done(sna);
772.17899 - }
772.17900 - 
772.17901 - static RegionPtr
772.17902 -@@ -8895,36 +9047,11 @@ sna_poly_point_extents(DrawablePtr drawable, GCPtr gc,
772.17903 - 			last.x += pt->x;
772.17904 - 			last.y += pt->y;
772.17905 - 			pt++;
772.17906 --			box_add_pt(&box, last.x, last.y);
772.17907 -+			box_add_xy(&box, last.x, last.y);
772.17908 - 		}
772.17909 - 	} else {
772.17910 --		--n; ++pt;
772.17911 --		while (n >= 8) {
772.17912 --			box_add_pt(&box, pt[0].x, pt[0].y);
772.17913 --			box_add_pt(&box, pt[1].x, pt[1].y);
772.17914 --			box_add_pt(&box, pt[2].x, pt[2].y);
772.17915 --			box_add_pt(&box, pt[3].x, pt[3].y);
772.17916 --			box_add_pt(&box, pt[4].x, pt[4].y);
772.17917 --			box_add_pt(&box, pt[5].x, pt[5].y);
772.17918 --			box_add_pt(&box, pt[6].x, pt[6].y);
772.17919 --			box_add_pt(&box, pt[7].x, pt[7].y);
772.17920 --			pt += 8;
772.17921 --			n -= 8;
772.17922 --		}
772.17923 --		if (n & 4) {
772.17924 --			box_add_pt(&box, pt[0].x, pt[0].y);
772.17925 --			box_add_pt(&box, pt[1].x, pt[1].y);
772.17926 --			box_add_pt(&box, pt[2].x, pt[2].y);
772.17927 --			box_add_pt(&box, pt[3].x, pt[3].y);
772.17928 --			pt += 4;
772.17929 --		}
772.17930 --		if (n & 2) {
772.17931 --			box_add_pt(&box, pt[0].x, pt[0].y);
772.17932 --			box_add_pt(&box, pt[1].x, pt[1].y);
772.17933 --			pt += 2;
772.17934 --		}
772.17935 --		if (n & 1)
772.17936 --			box_add_pt(&box, pt[0].x, pt[0].y);
772.17937 -+		while (--n)
772.17938 -+			box_add_pt(&box, ++pt);
772.17939 - 	}
772.17940 - 	box.x2++;
772.17941 - 	box.y2++;
772.17942 -@@ -9636,7 +9763,7 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
772.17943 - 			y += pt->y;
772.17944 - 			if (blt)
772.17945 - 				blt &= pt->x == 0 || pt->y == 0;
772.17946 --			box_add_pt(&box, x, y);
772.17947 -+			box_add_xy(&box, x, y);
772.17948 - 		}
772.17949 - 	} else {
772.17950 - 		int x = box.x1;
772.17951 -@@ -9648,7 +9775,7 @@ sna_poly_line_extents(DrawablePtr drawable, GCPtr gc,
772.17952 - 				x = pt->x;
772.17953 - 				y = pt->y;
772.17954 - 			}
772.17955 --			box_add_pt(&box, pt->x, pt->y);
772.17956 -+			box_add_pt(&box, pt);
772.17957 - 		}
772.17958 - 	}
772.17959 - 	box.x2++;
772.17960 -@@ -10037,7 +10164,7 @@ out:
772.17961 - 	RegionUninit(&data.region);
772.17962 - }
772.17963 - 
772.17964 --static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
772.17965 -+static inline bool box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
772.17966 - {
772.17967 - 	if (seg->x1 == seg->x2) {
772.17968 - 		if (seg->y1 > seg->y2) {
772.17969 -@@ -10051,6 +10178,9 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
772.17970 - 			if (gc->capStyle != CapNotLast)
772.17971 - 				b->y2++;
772.17972 - 		}
772.17973 -+		if (b->y1 >= b->y2)
772.17974 -+			return false;
772.17975 -+
772.17976 - 		b->x1 = seg->x1;
772.17977 - 		b->x2 = seg->x1 + 1;
772.17978 - 	} else {
772.17979 -@@ -10065,6 +10195,9 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
772.17980 - 			if (gc->capStyle != CapNotLast)
772.17981 - 				b->x2++;
772.17982 - 		}
772.17983 -+		if (b->x1 >= b->x2)
772.17984 -+			return false;
772.17985 -+
772.17986 - 		b->y1 = seg->y1;
772.17987 - 		b->y2 = seg->y1 + 1;
772.17988 - 	}
772.17989 -@@ -10073,6 +10206,7 @@ static inline void box_from_seg(BoxPtr b, const xSegment *seg, GCPtr gc)
772.17990 - 	     __FUNCTION__,
772.17991 - 	     seg->x1, seg->y1, seg->x2, seg->y2,
772.17992 - 	     b->x1, b->y1, b->x2, b->y2));
772.17993 -+	return true;
772.17994 - }
772.17995 - 
772.17996 - static bool
772.17997 -@@ -10107,12 +10241,13 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.17998 - 					nbox = ARRAY_SIZE(boxes);
772.17999 - 				n -= nbox;
772.18000 - 				do {
772.18001 --					box_from_seg(b, seg++, gc);
772.18002 --					if (b->y2 > b->y1 && b->x2 > b->x1) {
772.18003 -+					if (box_from_seg(b, seg++, gc)) {
772.18004 -+						assert(!box_empty(b));
772.18005 - 						b->x1 += dx;
772.18006 - 						b->x2 += dx;
772.18007 - 						b->y1 += dy;
772.18008 - 						b->y2 += dy;
772.18009 -+						assert(!box_empty(b));
772.18010 - 						b++;
772.18011 - 					}
772.18012 - 				} while (--nbox);
772.18013 -@@ -10131,7 +10266,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.18014 - 					nbox = ARRAY_SIZE(boxes);
772.18015 - 				n -= nbox;
772.18016 - 				do {
772.18017 --					box_from_seg(b++, seg++, gc);
772.18018 -+					if (box_from_seg(b, seg++, gc)) {
772.18019 -+						assert(!box_empty(b));
772.18020 -+						b++;
772.18021 -+					}
772.18022 - 				} while (--nbox);
772.18023 - 
772.18024 - 				if (b != boxes) {
772.18025 -@@ -10156,7 +10294,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.18026 - 			do {
772.18027 - 				BoxRec box;
772.18028 - 
772.18029 --				box_from_seg(&box, seg++, gc);
772.18030 -+				if (!box_from_seg(&box, seg++, gc))
772.18031 -+					continue;
772.18032 -+
772.18033 -+				assert(!box_empty(&box));
772.18034 - 				box.x1 += drawable->x;
772.18035 - 				box.x2 += drawable->x;
772.18036 - 				box.y1 += drawable->y;
772.18037 -@@ -10174,6 +10315,7 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.18038 - 						b->x2 += dx;
772.18039 - 						b->y1 += dy;
772.18040 - 						b->y2 += dy;
772.18041 -+						assert(!box_empty(b));
772.18042 - 						if (++b == last_box) {
772.18043 - 							fill.boxes(sna, &fill, boxes, last_box-boxes);
772.18044 - 							if (damage)
772.18045 -@@ -10185,7 +10327,10 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.18046 - 			} while (--n);
772.18047 - 		} else {
772.18048 - 			do {
772.18049 --				box_from_seg(b, seg++, gc);
772.18050 -+				if (!box_from_seg(b, seg++, gc))
772.18051 -+					continue;
772.18052 -+
772.18053 -+				assert(!box_empty(b));
772.18054 - 				b->x1 += drawable->x;
772.18055 - 				b->x2 += drawable->x;
772.18056 - 				b->y1 += drawable->y;
772.18057 -@@ -10195,6 +10340,7 @@ sna_poly_segment_blt(DrawablePtr drawable,
772.18058 - 					b->x2 += dx;
772.18059 - 					b->y1 += dy;
772.18060 - 					b->y2 += dy;
772.18061 -+					assert(!box_empty(b));
772.18062 - 					if (++b == last_box) {
772.18063 - 						fill.boxes(sna, &fill, boxes, last_box-boxes);
772.18064 - 						if (damage)
772.18065 -@@ -10319,8 +10465,11 @@ sna_poly_zero_segment_blt(DrawablePtr drawable,
772.18066 - 				}
772.18067 - 				b->x2++;
772.18068 - 				b->y2++;
772.18069 --				if (oc1 | oc2)
772.18070 --					box_intersect(b, extents);
772.18071 -+
772.18072 -+				if ((oc1 | oc2) && !box_intersect(b, extents))
772.18073 -+					continue;
772.18074 -+
772.18075 -+				assert(!box_empty(b));
772.18076 - 				if (++b == last_box) {
772.18077 - 					ret = &&rectangle_continue;
772.18078 - 					goto *jump;
772.18079 -@@ -10383,6 +10532,7 @@ rectangle_continue:
772.18080 - 						     __FUNCTION__, x1, y1,
772.18081 - 						     b->x1, b->y1, b->x2, b->y2));
772.18082 - 
772.18083 -+						assert(!box_empty(b));
772.18084 - 						if (++b == last_box) {
772.18085 - 							ret = &&X_continue;
772.18086 - 							goto *jump;
772.18087 -@@ -10407,6 +10557,7 @@ X_continue:
772.18088 - 						b->x2 = x1 + 1;
772.18089 - 					b->y2 = b->y1 + 1;
772.18090 - 
772.18091 -+					assert(!box_empty(b));
772.18092 - 					if (++b == last_box) {
772.18093 - 						ret = &&X2_continue;
772.18094 - 						goto *jump;
772.18095 -@@ -10468,6 +10619,7 @@ X2_continue:
772.18096 - 							b->y2 = y1 + 1;
772.18097 - 						b->x2 = x1 + 1;
772.18098 - 
772.18099 -+						assert(!box_empty(b));
772.18100 - 						if (++b == last_box) {
772.18101 - 							ret = &&Y_continue;
772.18102 - 							goto *jump;
772.18103 -@@ -10491,6 +10643,7 @@ Y_continue:
772.18104 - 						b->y2 = y1 + 1;
772.18105 - 					b->x2 = x1 + 1;
772.18106 - 
772.18107 -+					assert(!box_empty(b));
772.18108 - 					if (++b == last_box) {
772.18109 - 						ret = &&Y2_continue;
772.18110 - 						goto *jump;
772.18111 -@@ -11785,14 +11938,29 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
772.18112 - 				if (nbox > ARRAY_SIZE(boxes))
772.18113 - 					nbox = ARRAY_SIZE(boxes);
772.18114 - 				n -= nbox;
772.18115 --				do {
772.18116 -+				while (nbox >= 2) {
772.18117 -+					b[0].x1 = rect[0].x + dx;
772.18118 -+					b[0].y1 = rect[0].y + dy;
772.18119 -+					b[0].x2 = b[0].x1 + rect[0].width;
772.18120 -+					b[0].y2 = b[0].y1 + rect[0].height;
772.18121 -+
772.18122 -+					b[1].x1 = rect[1].x + dx;
772.18123 -+					b[1].y1 = rect[1].y + dy;
772.18124 -+					b[1].x2 = b[1].x1 + rect[1].width;
772.18125 -+					b[1].y2 = b[1].y1 + rect[1].height;
772.18126 -+
772.18127 -+					b += 2;
772.18128 -+					rect += 2;
772.18129 -+					nbox -= 2;
772.18130 -+				}
772.18131 -+				if (nbox) {
772.18132 - 					b->x1 = rect->x + dx;
772.18133 - 					b->y1 = rect->y + dy;
772.18134 - 					b->x2 = b->x1 + rect->width;
772.18135 - 					b->y2 = b->y1 + rect->height;
772.18136 - 					b++;
772.18137 - 					rect++;
772.18138 --				} while (--nbox);
772.18139 -+				}
772.18140 - 				fill.boxes(sna, &fill, boxes, b-boxes);
772.18141 - 				b = boxes;
772.18142 - 			} while (n);
772.18143 -@@ -11802,14 +11970,29 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
772.18144 - 				if (nbox > ARRAY_SIZE(boxes))
772.18145 - 					nbox = ARRAY_SIZE(boxes);
772.18146 - 				n -= nbox;
772.18147 --				do {
772.18148 -+				while (nbox >= 2) {
772.18149 -+					b[0].x1 = rect[0].x;
772.18150 -+					b[0].y1 = rect[0].y;
772.18151 -+					b[0].x2 = b[0].x1 + rect[0].width;
772.18152 -+					b[0].y2 = b[0].y1 + rect[0].height;
772.18153 -+
772.18154 -+					b[1].x1 = rect[1].x;
772.18155 -+					b[1].y1 = rect[1].y;
772.18156 -+					b[1].x2 = b[1].x1 + rect[1].width;
772.18157 -+					b[1].y2 = b[1].y1 + rect[1].height;
772.18158 -+
772.18159 -+					b += 2;
772.18160 -+					rect += 2;
772.18161 -+					nbox -= 2;
772.18162 -+				}
772.18163 -+				if (nbox) {
772.18164 - 					b->x1 = rect->x;
772.18165 - 					b->y1 = rect->y;
772.18166 - 					b->x2 = b->x1 + rect->width;
772.18167 - 					b->y2 = b->y1 + rect->height;
772.18168 - 					b++;
772.18169 - 					rect++;
772.18170 --				} while (--nbox);
772.18171 -+				}
772.18172 - 				fill.boxes(sna, &fill, boxes, b-boxes);
772.18173 - 				b = boxes;
772.18174 - 			} while (n);
772.18175 -@@ -12192,6 +12375,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
772.18176 - 			return false;
772.18177 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18178 - 	}
772.18179 -+	kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
772.18180 - 
772.18181 - 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
772.18182 - 	assert(extents->x1 + dx >= 0);
772.18183 -@@ -12335,6 +12519,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
772.18184 - 
772.18185 - 			_kgem_submit(&sna->kgem);
772.18186 - 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18187 -+			kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
772.18188 - 		} while (1);
772.18189 - 	} else {
772.18190 - 		RegionRec clip;
772.18191 -@@ -12403,6 +12588,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
772.18192 - 					if (!kgem_check_batch(&sna->kgem, 3)) {
772.18193 - 						_kgem_submit(&sna->kgem);
772.18194 - 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18195 -+						kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
772.18196 - 
772.18197 - 						unwind_batch = sna->kgem.nbatch;
772.18198 - 						unwind_reloc = sna->kgem.nreloc;
772.18199 -@@ -12499,6 +12685,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
772.18200 - 							DBG(("%s: emitting split batch\n", __FUNCTION__));
772.18201 - 							_kgem_submit(&sna->kgem);
772.18202 - 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18203 -+							kgem_bcs_set_tiling(&sna->kgem, tile_bo, bo);
772.18204 - 
772.18205 - 							unwind_batch = sna->kgem.nbatch;
772.18206 - 							unwind_reloc = sna->kgem.nreloc;
772.18207 -@@ -12572,7 +12759,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable,
772.18208 - 	}
772.18209 - done:
772.18210 - 	assert_pixmap_damage(pixmap);
772.18211 --	sna->blt_state.fill_bo = 0;
772.18212 -+	blt_done(sna);
772.18213 - 	return true;
772.18214 - }
772.18215 - 
772.18216 -@@ -13128,6 +13315,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
772.18217 - 			return false;
772.18218 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18219 - 	}
772.18220 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18221 - 
772.18222 - 	if (!clipped) {
772.18223 - 		dx += drawable->x;
772.18224 -@@ -13240,6 +13428,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
772.18225 - 
772.18226 - 			_kgem_submit(&sna->kgem);
772.18227 - 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18228 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18229 - 		} while (1);
772.18230 - 	} else {
772.18231 - 		RegionRec clip;
772.18232 -@@ -13297,6 +13486,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
772.18233 - 					if (!kgem_check_batch(&sna->kgem, 3)) {
772.18234 - 						_kgem_submit(&sna->kgem);
772.18235 - 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18236 -+						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18237 - 
772.18238 - 						assert(sna->kgem.mode == KGEM_BLT);
772.18239 - 						b = sna->kgem.batch + sna->kgem.nbatch;
772.18240 -@@ -13369,6 +13559,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
772.18241 - 						if (!kgem_check_batch(&sna->kgem, 3)) {
772.18242 - 							_kgem_submit(&sna->kgem);
772.18243 - 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18244 -+							kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18245 - 
772.18246 - 							assert(sna->kgem.mode == KGEM_BLT);
772.18247 - 							b = sna->kgem.batch + sna->kgem.nbatch;
772.18248 -@@ -13419,7 +13610,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable,
772.18249 - 	}
772.18250 - 
772.18251 - 	assert_pixmap_damage(pixmap);
772.18252 --	sna->blt_state.fill_bo = 0;
772.18253 -+	blt_done(sna);
772.18254 - 	return true;
772.18255 - }
772.18256 - 
772.18257 -@@ -13499,6 +13690,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18258 - 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
772.18259 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.18260 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.18261 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18262 - 
772.18263 - 	br00 = 3 << 20;
772.18264 - 	br13 = bo->pitch;
772.18265 -@@ -13543,6 +13735,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18266 - 						return false;
772.18267 - 					_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18268 - 				}
772.18269 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18270 - 
772.18271 - 				assert(sna->kgem.mode == KGEM_BLT);
772.18272 - 				b = sna->kgem.batch + sna->kgem.nbatch;
772.18273 -@@ -13606,6 +13799,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18274 - 						return false;
772.18275 - 					_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18276 - 				}
772.18277 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18278 - 
772.18279 - 				upload = kgem_create_buffer(&sna->kgem,
772.18280 - 							    bstride*bh,
772.18281 -@@ -13736,6 +13930,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18282 - 							return false;
772.18283 - 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18284 - 					}
772.18285 -+					kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18286 - 
772.18287 - 					assert(sna->kgem.mode == KGEM_BLT);
772.18288 - 					b = sna->kgem.batch + sna->kgem.nbatch;
772.18289 -@@ -13797,6 +13992,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18290 - 							return false;
772.18291 - 						_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18292 - 					}
772.18293 -+					kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18294 - 
772.18295 - 					upload = kgem_create_buffer(&sna->kgem,
772.18296 - 								    bstride*bh,
772.18297 -@@ -13927,6 +14123,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18298 - 								return false;
772.18299 - 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18300 - 						}
772.18301 -+						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18302 - 
772.18303 - 						assert(sna->kgem.mode == KGEM_BLT);
772.18304 - 						b = sna->kgem.batch + sna->kgem.nbatch;
772.18305 -@@ -13987,6 +14184,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18306 - 								return false;
772.18307 - 							_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18308 - 						}
772.18309 -+						kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18310 - 
772.18311 - 						upload = kgem_create_buffer(&sna->kgem,
772.18312 - 									    bstride*bh,
772.18313 -@@ -14064,7 +14262,7 @@ sna_poly_fill_rect_stippled_1_blt(DrawablePtr drawable,
772.18314 - 		}
772.18315 - 	}
772.18316 - 
772.18317 --	sna->blt_state.fill_bo = 0;
772.18318 -+	blt_done(sna);
772.18319 - 	return true;
772.18320 - }
772.18321 - 
772.18322 -@@ -14126,6 +14324,7 @@ sna_poly_fill_rect_stippled_n_box__imm(struct sna *sna,
772.18323 - 					return; /* XXX fallback? */
772.18324 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18325 - 			}
772.18326 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18327 - 
772.18328 - 			assert(sna->kgem.mode == KGEM_BLT);
772.18329 - 			b = sna->kgem.batch + sna->kgem.nbatch;
772.18330 -@@ -14251,6 +14450,7 @@ sna_poly_fill_rect_stippled_n_box(struct sna *sna,
772.18331 - 					return; /* XXX fallback? */
772.18332 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18333 - 			}
772.18334 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18335 - 
772.18336 - 			assert(sna->kgem.mode == KGEM_BLT);
772.18337 - 			b = sna->kgem.batch + sna->kgem.nbatch;
772.18338 -@@ -14414,6 +14614,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
772.18339 - 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
772.18340 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.18341 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.18342 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18343 - 
772.18344 - 	br00 = XY_MONO_SRC_COPY_IMM | 3 << 20;
772.18345 - 	br13 = bo->pitch;
772.18346 -@@ -14526,7 +14727,7 @@ sna_poly_fill_rect_stippled_n_blt__imm(DrawablePtr drawable,
772.18347 - 	}
772.18348 - 
772.18349 - 	assert_pixmap_damage(pixmap);
772.18350 --	sna->blt_state.fill_bo = 0;
772.18351 -+	blt_done(sna);
772.18352 - 	return true;
772.18353 - }
772.18354 - 
772.18355 -@@ -14559,6 +14760,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
772.18356 - 	get_drawable_deltas(drawable, pixmap, &dx, &dy);
772.18357 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.18358 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.18359 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18360 - 
772.18361 - 	br00 = XY_MONO_SRC_COPY | 3 << 20;
772.18362 - 	br13 = bo->pitch;
772.18363 -@@ -14673,7 +14875,7 @@ sna_poly_fill_rect_stippled_n_blt(DrawablePtr drawable,
772.18364 - 	assert_pixmap_damage(pixmap);
772.18365 - 	if (tile)
772.18366 - 		kgem_bo_destroy(&sna->kgem, tile);
772.18367 --	sna->blt_state.fill_bo = 0;
772.18368 -+	blt_done(sna);
772.18369 - 	return true;
772.18370 - }
772.18371 - 
772.18372 -@@ -15281,6 +15483,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
772.18373 - 		}
772.18374 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18375 - 	}
772.18376 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18377 - 
772.18378 - 	DBG(("%s: glyph clip box (%d, %d), (%d, %d)\n",
772.18379 - 	     __FUNCTION__,
772.18380 -@@ -15368,6 +15571,7 @@ sna_glyph_blt(DrawablePtr drawable, GCPtr gc,
772.18381 - 			if (!kgem_check_batch(&sna->kgem, 3+len)) {
772.18382 - 				_kgem_submit(&sna->kgem);
772.18383 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18384 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18385 - 
772.18386 - 				DBG(("%s: new batch, glyph clip box (%d, %d), (%d, %d)\n",
772.18387 - 				     __FUNCTION__,
772.18388 -@@ -15479,7 +15683,7 @@ skip:
772.18389 - 	}
772.18390 - 
772.18391 - 	assert_pixmap_damage(pixmap);
772.18392 --	sna->blt_state.fill_bo = 0;
772.18393 -+	blt_done(sna);
772.18394 - 	return true;
772.18395 - }
772.18396 - 
772.18397 -@@ -16002,6 +16206,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
772.18398 - 		}
772.18399 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18400 - 	}
772.18401 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18402 - 
772.18403 - 	unwind_batch = sna->kgem.nbatch;
772.18404 - 	unwind_reloc = sna->kgem.nreloc;
772.18405 -@@ -16111,6 +16316,7 @@ sna_reversed_glyph_blt(DrawablePtr drawable, GCPtr gc,
772.18406 - 			if (!kgem_check_batch(&sna->kgem, 3+len)) {
772.18407 - 				_kgem_submit(&sna->kgem);
772.18408 - 				_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18409 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18410 - 
772.18411 - 				unwind_batch = sna->kgem.nbatch;
772.18412 - 				unwind_reloc = sna->kgem.nreloc;
772.18413 -@@ -16229,7 +16435,7 @@ skip:
772.18414 - 	}
772.18415 - 
772.18416 - 	assert_pixmap_damage(pixmap);
772.18417 --	sna->blt_state.fill_bo = 0;
772.18418 -+	blt_done(sna);
772.18419 - 	return true;
772.18420 - }
772.18421 - 
772.18422 -@@ -16450,6 +16656,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
772.18423 - 
772.18424 - 	kgem_set_mode(&sna->kgem, KGEM_BLT, bo);
772.18425 - 	assert(kgem_bo_can_blt(&sna->kgem, bo));
772.18426 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18427 - 
772.18428 - 	/* Region is pre-clipped and translated into pixmap space */
772.18429 - 	box = region_rects(region);
772.18430 -@@ -16471,6 +16678,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
772.18431 - 				return false;
772.18432 - 			_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.18433 - 		}
772.18434 -+		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.18435 - 
772.18436 - 		upload = kgem_create_buffer(&sna->kgem,
772.18437 - 					    bstride*bh,
772.18438 -@@ -16564,7 +16772,7 @@ sna_push_pixels_solid_blt(GCPtr gc,
772.18439 - 		box++;
772.18440 - 	} while (--n);
772.18441 - 
772.18442 --	sna->blt_state.fill_bo = 0;
772.18443 -+	blt_done(sna);
772.18444 - 	return true;
772.18445 - }
772.18446 - 
772.18447 -@@ -16754,7 +16962,9 @@ static int sna_create_gc(GCPtr gc)
772.18448 - 
772.18449 - 	gc->freeCompClip = 0;
772.18450 - 	gc->pCompositeClip = 0;
772.18451 -+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,99,1,0)
772.18452 - 	gc->pRotatedPixmap = 0;
772.18453 -+#endif
772.18454 - 
772.18455 - 	fb_gc(gc)->bpp = bits_per_pixel(gc->depth);
772.18456 - 
772.18457 -@@ -16789,7 +16999,8 @@ sna_get_image__inplace(PixmapPtr pixmap,
772.18458 - 		break;
772.18459 - 	}
772.18460 - 
772.18461 --	if (!kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC))
772.18462 -+	if ((flags & MOVE_INPLACE_HINT) == 0 &&
772.18463 -+	    !kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC))
772.18464 - 		return false;
772.18465 - 
772.18466 - 	if (idle && __kgem_bo_is_busy(&sna->kgem, priv->gpu_bo))
772.18467 -@@ -16801,11 +17012,19 @@ sna_get_image__inplace(PixmapPtr pixmap,
772.18468 - 	assert(sna_damage_contains_box(&priv->gpu_damage, &region->extents) == PIXMAN_REGION_IN);
772.18469 - 	assert(sna_damage_contains_box(&priv->cpu_damage, &region->extents) == PIXMAN_REGION_OUT);
772.18470 - 
772.18471 --	src = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
772.18472 --	if (src == NULL)
772.18473 --		return false;
772.18474 -+	if (kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC)) {
772.18475 -+		src = kgem_bo_map__cpu(&sna->kgem, priv->gpu_bo);
772.18476 -+		if (src == NULL)
772.18477 -+			return false;
772.18478 - 
772.18479 --	kgem_bo_sync__cpu_full(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC);
772.18480 -+		kgem_bo_sync__cpu_full(&sna->kgem, priv->gpu_bo, FORCE_FULL_SYNC);
772.18481 -+	} else {
772.18482 -+		src = kgem_bo_map__wc(&sna->kgem, priv->gpu_bo);
772.18483 -+		if (src == NULL)
772.18484 -+			return false;
772.18485 -+
772.18486 -+		kgem_bo_sync__gtt(&sna->kgem, priv->gpu_bo);
772.18487 -+	}
772.18488 - 
772.18489 - 	if (sigtrap_get())
772.18490 - 		return false;
772.18491 -@@ -16833,12 +17052,11 @@ sna_get_image__inplace(PixmapPtr pixmap,
772.18492 - 			   region->extents.x2 - region->extents.x1,
772.18493 - 			   region->extents.y2 - region->extents.y1);
772.18494 - 		if (!priv->shm) {
772.18495 --			assert(src == MAP(priv->gpu_bo->map__cpu));
772.18496 - 			pixmap->devPrivate.ptr = src;
772.18497 - 			pixmap->devKind = priv->gpu_bo->pitch;
772.18498 --			priv->mapped = MAPPED_CPU;
772.18499 -+			priv->mapped = src == MAP(priv->gpu_bo->map__cpu) ? MAPPED_CPU : MAPPED_GTT;
772.18500 - 			assert_pixmap_map(pixmap, priv);
772.18501 --			priv->cpu = true;
772.18502 -+			priv->cpu &= priv->mapped == MAPPED_CPU;
772.18503 - 		}
772.18504 - 	}
772.18505 - 
772.18506 -@@ -16930,7 +17148,7 @@ sna_get_image__fast(PixmapPtr pixmap,
772.18507 - 	if (priv == NULL || priv->gpu_damage == NULL)
772.18508 - 		return false;
772.18509 - 
772.18510 --	if (priv->clear) {
772.18511 -+	if (priv->clear && sigtrap_get() == 0) {
772.18512 - 		int w = region->extents.x2 - region->extents.x1;
772.18513 - 		int h = region->extents.y2 - region->extents.y1;
772.18514 - 		int pitch = PixmapBytePad(w, pixmap->drawable.depth);
772.18515 -@@ -16939,6 +17157,7 @@ sna_get_image__fast(PixmapPtr pixmap,
772.18516 - 		     __FUNCTION__, priv->clear_color));
772.18517 - 		assert(DAMAGE_IS_ALL(priv->gpu_damage));
772.18518 - 		assert(priv->cpu_damage == NULL);
772.18519 -+		sigtrap_assert_active();
772.18520 - 
772.18521 - 		if (priv->clear_color == 0 ||
772.18522 - 		    pixmap->drawable.bitsPerPixel == 8 ||
772.18523 -@@ -16955,6 +17174,7 @@ sna_get_image__fast(PixmapPtr pixmap,
772.18524 - 				    priv->clear_color);
772.18525 - 		}
772.18526 - 
772.18527 -+		sigtrap_put();
772.18528 - 		return true;
772.18529 - 	}
772.18530 - 
772.18531 -@@ -17001,8 +17221,7 @@ sna_get_image(DrawablePtr drawable,
772.18532 - 	if (ACCEL_GET_IMAGE &&
772.18533 - 	    !FORCE_FALLBACK &&
772.18534 - 	    format == ZPixmap &&
772.18535 --	    drawable->bitsPerPixel >= 8 &&
772.18536 --	    PM_IS_SOLID(drawable, mask)) {
772.18537 -+	    drawable->bitsPerPixel >= 8) {
772.18538 - 		PixmapPtr pixmap = get_drawable_pixmap(drawable);
772.18539 - 		int16_t dx, dy;
772.18540 - 
772.18541 -@@ -17014,7 +17233,7 @@ sna_get_image(DrawablePtr drawable,
772.18542 - 		region.data = NULL;
772.18543 - 
772.18544 - 		if (sna_get_image__fast(pixmap, &region, dst, flags))
772.18545 --			return;
772.18546 -+			goto apply_planemask;
772.18547 - 
772.18548 - 		if (!sna_drawable_move_region_to_cpu(&pixmap->drawable,
772.18549 - 						     &region, flags))
772.18550 -@@ -17032,6 +17251,16 @@ sna_get_image(DrawablePtr drawable,
772.18551 - 				   region.extents.x1, region.extents.y1, 0, 0, w, h);
772.18552 - 			sigtrap_put();
772.18553 - 		}
772.18554 -+
772.18555 -+apply_planemask:
772.18556 -+		if (!PM_IS_SOLID(drawable, mask)) {
772.18557 -+			FbStip pm = fbReplicatePixel(mask, drawable->bitsPerPixel);
772.18558 -+			FbStip *d = (FbStip *)dst;
772.18559 -+			int i, n = PixmapBytePad(w, drawable->depth) / sizeof(FbStip) * h;
772.18560 -+
772.18561 -+			for (i = 0; i < n; i++)
772.18562 -+				d[i] &= pm;
772.18563 -+		}
772.18564 - 	} else {
772.18565 - 		region.extents.x1 = x + drawable->x;
772.18566 - 		region.extents.y1 = y + drawable->y;
772.18567 -@@ -17162,17 +17391,19 @@ void sna_accel_flush(struct sna *sna)
772.18568 - 				__sna_free_pixmap(sna, priv->pixmap, priv);
772.18569 - 			}
772.18570 - 		} else {
772.18571 -+			unsigned hints;
772.18572 - 			DBG(("%s: flushing DRI pixmap=%ld\n", __FUNCTION__,
772.18573 - 			     priv->pixmap->drawable.serialNumber));
772.18574 - 			assert(priv->flush);
772.18575 --			if (sna_pixmap_move_to_gpu(priv->pixmap,
772.18576 --						   MOVE_READ | __MOVE_FORCE)) {
772.18577 --				if (priv->flush & IS_CLIPPED) {
772.18578 -+			hints = MOVE_READ | __MOVE_FORCE;
772.18579 -+			if (priv->flush & FLUSH_WRITE)
772.18580 -+				hints |= MOVE_WRITE;
772.18581 -+			if (sna_pixmap_move_to_gpu(priv->pixmap, hints)) {
772.18582 -+				if (priv->flush & FLUSH_WRITE) {
772.18583 - 					kgem_bo_unclean(&sna->kgem, priv->gpu_bo);
772.18584 - 					sna_damage_all(&priv->gpu_damage, priv->pixmap);
772.18585 - 					assert(priv->cpu_damage == NULL);
772.18586 --					priv->clear = false;
772.18587 --					priv->cpu = false;
772.18588 -+					assert(priv->clear == false);
772.18589 - 				}
772.18590 - 			}
772.18591 - 		}
772.18592 -@@ -17184,10 +17415,46 @@ void sna_accel_flush(struct sna *sna)
772.18593 - }
772.18594 - 
772.18595 - static void
772.18596 --sna_accel_flush_callback(CallbackListPtr *list,
772.18597 --			 pointer user_data, pointer call_data)
772.18598 -+sna_shm_flush_callback(CallbackListPtr *list,
772.18599 -+		       pointer user_data, pointer call_data)
772.18600 - {
772.18601 --	sna_accel_flush(user_data);
772.18602 -+	struct sna *sna = user_data;
772.18603 -+
772.18604 -+	if (!sna->needs_shm_flush)
772.18605 -+		return;
772.18606 -+
772.18607 -+	sna_accel_flush(sna);
772.18608 -+	sna->needs_shm_flush = false;
772.18609 -+}
772.18610 -+
772.18611 -+static void
772.18612 -+sna_flush_callback(CallbackListPtr *list, pointer user_data, pointer call_data)
772.18613 -+{
772.18614 -+	struct sna *sna = user_data;
772.18615 -+
772.18616 -+	if (!sna->needs_dri_flush)
772.18617 -+		return;
772.18618 -+
772.18619 -+	sna_accel_flush(sna);
772.18620 -+	sna->needs_dri_flush = false;
772.18621 -+}
772.18622 -+
772.18623 -+static void
772.18624 -+sna_event_callback(CallbackListPtr *list, pointer user_data, pointer call_data)
772.18625 -+{
772.18626 -+	EventInfoRec *eventinfo = call_data;
772.18627 -+	struct sna *sna = user_data;
772.18628 -+	int i;
772.18629 -+
772.18630 -+	if (sna->needs_dri_flush)
772.18631 -+		return;
772.18632 -+
772.18633 -+	for (i = 0; i < eventinfo->count; i++) {
772.18634 -+		if (eventinfo->events[i].u.u.type == sna->damage_event) {
772.18635 -+			sna->needs_dri_flush = true;
772.18636 -+			return;
772.18637 -+		}
772.18638 -+	}
772.18639 - }
772.18640 - 
772.18641 - static struct sna_pixmap *sna_accel_scanout(struct sna *sna)
772.18642 -@@ -17199,6 +17466,7 @@ static struct sna_pixmap *sna_accel_scanout(struct sna *sna)
772.18643 - 
772.18644 - 	assert(sna->vblank_interval);
772.18645 - 	assert(sna->front);
772.18646 -+	assert(!sna->mode.hidden);
772.18647 - 
772.18648 - 	priv = sna_pixmap(sna->front);
772.18649 - 	if (priv->gpu_bo == NULL)
772.18650 -@@ -17217,7 +17485,7 @@ static void sna_accel_disarm_timer(struct sna *sna, int id)
772.18651 - static bool has_offload_slaves(struct sna *sna)
772.18652 - {
772.18653 - #if HAS_PIXMAP_SHARING
772.18654 --	ScreenPtr screen = sna->scrn->pScreen;
772.18655 -+	ScreenPtr screen = to_screen_from_sna(sna);
772.18656 - 	PixmapDirtyUpdatePtr dirty;
772.18657 - 
772.18658 - 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
772.18659 -@@ -17231,11 +17499,14 @@ static bool has_offload_slaves(struct sna *sna)
772.18660 - 
772.18661 - static bool has_shadow(struct sna *sna)
772.18662 - {
772.18663 --	DamagePtr damage = sna->mode.shadow_damage;
772.18664 -+	DamagePtr damage;
772.18665 - 
772.18666 --	if (damage == NULL)
772.18667 -+	if (!sna->mode.shadow_enabled)
772.18668 - 		return false;
772.18669 - 
772.18670 -+	damage = sna->mode.shadow_damage;
772.18671 -+	assert(damage);
772.18672 -+
772.18673 - 	DBG(("%s: has pending damage? %d, outstanding flips: %d\n",
772.18674 - 	     __FUNCTION__,
772.18675 - 	     RegionNotEmpty(DamageRegion(damage)),
772.18676 -@@ -17365,9 +17636,8 @@ static bool sna_accel_do_expire(struct sna *sna)
772.18677 - static void sna_accel_post_damage(struct sna *sna)
772.18678 - {
772.18679 - #if HAS_PIXMAP_SHARING
772.18680 --	ScreenPtr screen = sna->scrn->pScreen;
772.18681 -+	ScreenPtr screen = to_screen_from_sna(sna);
772.18682 - 	PixmapDirtyUpdatePtr dirty;
772.18683 --	bool flush = false;
772.18684 - 
772.18685 - 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
772.18686 - 		RegionRec region, *damage;
772.18687 -@@ -17376,8 +17646,6 @@ static void sna_accel_post_damage(struct sna *sna)
772.18688 - 		int16_t dx, dy;
772.18689 - 		int n;
772.18690 - 
772.18691 --		assert(dirty->src == sna->front);
772.18692 --
772.18693 - 		damage = DamageRegion(dirty->damage);
772.18694 - 		if (RegionNil(damage))
772.18695 - 			continue;
772.18696 -@@ -17477,7 +17745,14 @@ fallback:
772.18697 - 						    box, n, COPY_LAST))
772.18698 - 				goto fallback;
772.18699 - 
772.18700 --			flush = true;
772.18701 -+			/* Before signalling the slave via ProcessPending,
772.18702 -+			 * ensure not only the batch is submitted as the
772.18703 -+			 * slave may be using the Damage callback to perform
772.18704 -+			 * its copy, but also that the memory must be coherent
772.18705 -+			 * - we need to treat it as uncached for the PCI slave
772.18706 -+			 * will bypass LLC.
772.18707 -+			 */
772.18708 -+			kgem_bo_sync__gtt(&sna->kgem, __sna_pixmap_get_bo(dst));
772.18709 - 		}
772.18710 - 
772.18711 - 		DamageRegionProcessPending(&dirty->slave_dst->drawable);
772.18712 -@@ -17485,8 +17760,6 @@ skip:
772.18713 - 		RegionUninit(&region);
772.18714 - 		DamageEmpty(dirty->damage);
772.18715 - 	}
772.18716 --	if (flush)
772.18717 --		kgem_submit(&sna->kgem);
772.18718 - #endif
772.18719 - }
772.18720 - 
772.18721 -@@ -17689,6 +17962,7 @@ sna_set_screen_pixmap(PixmapPtr pixmap)
772.18722 - static Bool
772.18723 - sna_create_window(WindowPtr win)
772.18724 - {
772.18725 -+	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
772.18726 - 	sna_set_window_pixmap(win, win->drawable.pScreen->devPrivate);
772.18727 - 	return TRUE;
772.18728 - }
772.18729 -@@ -17714,6 +17988,7 @@ sna_unmap_window(WindowPtr win)
772.18730 - static Bool
772.18731 - sna_destroy_window(WindowPtr win)
772.18732 - {
772.18733 -+	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
772.18734 - 	sna_video_destroy_window(win);
772.18735 - 	sna_dri2_destroy_window(win);
772.18736 - 	return TRUE;
772.18737 -@@ -17790,20 +18065,34 @@ static bool sna_option_accel_none(struct sna *sna)
772.18738 - 	if (wedged(sna))
772.18739 - 		return true;
772.18740 - 
772.18741 --	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE))
772.18742 -+	if (!xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_ENABLE, TRUE))
772.18743 - 		return true;
772.18744 - 
772.18745 -+	if (sna->kgem.gen >= 0120)
772.18746 -+		return true;
772.18747 -+
772.18748 -+	if (!intel_option_cast_to_bool(sna->Options,
772.18749 -+				       OPTION_ACCEL_METHOD,
772.18750 -+				       !IS_DEFAULT_ACCEL_METHOD(NOACCEL)))
772.18751 -+		return false;
772.18752 -+
772.18753 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.18754 - 	s = xf86GetOptValString(sna->Options, OPTION_ACCEL_METHOD);
772.18755 - 	if (s == NULL)
772.18756 - 		return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
772.18757 - 
772.18758 - 	return strcasecmp(s, "none") == 0;
772.18759 -+#else
772.18760 -+	return IS_DEFAULT_ACCEL_METHOD(NOACCEL);
772.18761 -+#endif
772.18762 - }
772.18763 - 
772.18764 - static bool sna_option_accel_blt(struct sna *sna)
772.18765 - {
772.18766 - 	const char *s;
772.18767 - 
772.18768 -+	assert(sna->kgem.gen < 0120);
772.18769 -+
772.18770 - 	s = xf86GetOptValString(sna->Options, OPTION_ACCEL_METHOD);
772.18771 - 	if (s == NULL)
772.18772 - 		return false;
772.18773 -@@ -17811,6 +18100,13 @@ static bool sna_option_accel_blt(struct sna *sna)
772.18774 - 	return strcasecmp(s, "blt") == 0;
772.18775 - }
772.18776 - 
772.18777 -+#if HAVE_NOTIFY_FD
772.18778 -+static void sna_accel_notify(int fd, int ready, void *data)
772.18779 -+{
772.18780 -+	sna_mode_wakeup(data);
772.18781 -+}
772.18782 -+#endif
772.18783 -+
772.18784 - bool sna_accel_init(ScreenPtr screen, struct sna *sna)
772.18785 - {
772.18786 - 	const char *backend;
772.18787 -@@ -17822,7 +18118,7 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
772.18788 - 	list_init(&sna->flush_pixmaps);
772.18789 - 	list_init(&sna->active_pixmaps);
772.18790 - 
772.18791 --	AddGeneralSocket(sna->kgem.fd);
772.18792 -+	SetNotifyFd(sna->kgem.fd, sna_accel_notify, X_NOTIFY_READ, sna);
772.18793 - 
772.18794 - #ifdef DEBUG_MEMORY
772.18795 - 	sna->timer_expire[DEBUG_MEMORY_TIMER] = GetTimeInMillis()+ 10 * 1000;
772.18796 -@@ -17892,21 +18188,23 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
772.18797 - 		backend = "disabled";
772.18798 - 		sna->kgem.wedged = true;
772.18799 - 		sna_render_mark_wedged(sna);
772.18800 --	} else if (sna_option_accel_blt(sna) || sna->info->gen >= 0110)
772.18801 -+	} else if (sna_option_accel_blt(sna))
772.18802 - 		(void)backend;
772.18803 --	else if (sna->info->gen >= 0100)
772.18804 -+	else if (sna->kgem.gen >= 0110)
772.18805 -+		backend = gen9_render_init(sna, backend);
772.18806 -+	else if (sna->kgem.gen >= 0100)
772.18807 - 		backend = gen8_render_init(sna, backend);
772.18808 --	else if (sna->info->gen >= 070)
772.18809 -+	else if (sna->kgem.gen >= 070)
772.18810 - 		backend = gen7_render_init(sna, backend);
772.18811 --	else if (sna->info->gen >= 060)
772.18812 -+	else if (sna->kgem.gen >= 060)
772.18813 - 		backend = gen6_render_init(sna, backend);
772.18814 --	else if (sna->info->gen >= 050)
772.18815 -+	else if (sna->kgem.gen >= 050)
772.18816 - 		backend = gen5_render_init(sna, backend);
772.18817 --	else if (sna->info->gen >= 040)
772.18818 -+	else if (sna->kgem.gen >= 040)
772.18819 - 		backend = gen4_render_init(sna, backend);
772.18820 --	else if (sna->info->gen >= 030)
772.18821 -+	else if (sna->kgem.gen >= 030)
772.18822 - 		backend = gen3_render_init(sna, backend);
772.18823 --	else if (sna->info->gen >= 020)
772.18824 -+	else if (sna->kgem.gen >= 020)
772.18825 - 		backend = gen2_render_init(sna, backend);
772.18826 - 
772.18827 - 	DBG(("%s(backend=%s, prefer_gpu=%x)\n",
772.18828 -@@ -17924,8 +18222,14 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
772.18829 - 
772.18830 - void sna_accel_create(struct sna *sna)
772.18831 - {
772.18832 -+	ExtensionEntry *damage;
772.18833 -+
772.18834 - 	DBG(("%s\n", __FUNCTION__));
772.18835 - 
772.18836 -+	damage = CheckExtension("DAMAGE");
772.18837 -+	if (damage)
772.18838 -+		sna->damage_event = damage->eventBase + XDamageNotify;
772.18839 -+
772.18840 - 	if (!sna_glyphs_create(sna))
772.18841 - 		goto fail;
772.18842 - 
772.18843 -@@ -17943,27 +18247,59 @@ fail:
772.18844 - 	no_render_init(sna);
772.18845 - }
772.18846 - 
772.18847 --void sna_accel_watch_flush(struct sna *sna, int enable)
772.18848 -+static void sna_shm_watch_flush(struct sna *sna, int enable)
772.18849 - {
772.18850 - 	DBG(("%s: enable=%d\n", __FUNCTION__, enable));
772.18851 - 	assert(enable);
772.18852 - 
772.18853 --	if (sna->watch_flush == 0) {
772.18854 -+	if (sna->watch_shm_flush == 0) {
772.18855 -+		DBG(("%s: installing shm watchers\n", __FUNCTION__));
772.18856 -+		assert(enable > 0);
772.18857 -+
772.18858 -+		if (!AddCallback(&FlushCallback, sna_shm_flush_callback, sna))
772.18859 -+			return;
772.18860 -+
772.18861 -+		sna->watch_shm_flush++;
772.18862 -+	}
772.18863 -+
772.18864 -+	sna->watch_shm_flush += enable;
772.18865 -+}
772.18866 -+
772.18867 -+void sna_watch_flush(struct sna *sna, int enable)
772.18868 -+{
772.18869 -+	DBG(("%s: enable=%d\n", __FUNCTION__, enable));
772.18870 -+	assert(enable);
772.18871 -+
772.18872 -+	if (sna->watch_dri_flush == 0) {
772.18873 -+		int err = 0;
772.18874 -+
772.18875 - 		DBG(("%s: installing watchers\n", __FUNCTION__));
772.18876 - 		assert(enable > 0);
772.18877 --		if (!AddCallback(&FlushCallback, sna_accel_flush_callback, sna)) {
772.18878 -+
772.18879 -+		if (!sna->damage_event)
772.18880 -+			return;
772.18881 -+
772.18882 -+		if (!AddCallback(&EventCallback, sna_event_callback, sna))
772.18883 -+			err = 1;
772.18884 -+
772.18885 -+		if (!AddCallback(&FlushCallback, sna_flush_callback, sna))
772.18886 -+			err = 1;
772.18887 -+
772.18888 -+		if (err) {
772.18889 - 			xf86DrvMsg(sna->scrn->scrnIndex, X_Error,
772.18890 - 				   "Failed to attach ourselves to the flush callbacks, expect missing synchronisation with DRI clients (e.g a compositor)\n");
772.18891 - 		}
772.18892 --		sna->watch_flush++;
772.18893 -+
772.18894 -+		sna->watch_dri_flush++;
772.18895 - 	}
772.18896 - 
772.18897 --	sna->watch_flush += enable;
772.18898 -+	sna->watch_dri_flush += enable;
772.18899 - }
772.18900 - 
772.18901 - void sna_accel_leave(struct sna *sna)
772.18902 - {
772.18903 - 	DBG(("%s\n", __FUNCTION__));
772.18904 -+	sna_scanout_flush(sna);
772.18905 - 
772.18906 - 	/* as root we always have permission to render */
772.18907 - 	if (geteuid() == 0)
772.18908 -@@ -17997,13 +18333,15 @@ void sna_accel_close(struct sna *sna)
772.18909 - 
772.18910 - 	sna_pixmap_expire(sna);
772.18911 - 
772.18912 --	DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
772.18913 --	RemoveGeneralSocket(sna->kgem.fd);
772.18914 -+	DeleteCallback(&FlushCallback, sna_shm_flush_callback, sna);
772.18915 -+	DeleteCallback(&FlushCallback, sna_flush_callback, sna);
772.18916 -+	DeleteCallback(&EventCallback, sna_event_callback, sna);
772.18917 -+	RemoveNotifyFd(sna->kgem.fd);
772.18918 - 
772.18919 - 	kgem_cleanup_cache(&sna->kgem);
772.18920 - }
772.18921 - 
772.18922 --void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
772.18923 -+void sna_accel_block(struct sna *sna, struct timeval **tv)
772.18924 - {
772.18925 - 	sigtrap_assert_inactive();
772.18926 - 
772.18927 -@@ -18044,10 +18382,17 @@ restart:
772.18928 - 	if (sna_accel_do_debug_memory(sna))
772.18929 - 		sna_accel_debug_memory(sna);
772.18930 - 
772.18931 --	if (sna->watch_flush == 1) {
772.18932 --		DBG(("%s: removing watchers\n", __FUNCTION__));
772.18933 --		DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
772.18934 --		sna->watch_flush = 0;
772.18935 -+	if (sna->watch_shm_flush == 1) {
772.18936 -+		DBG(("%s: removing shm watchers\n", __FUNCTION__));
772.18937 -+		DeleteCallback(&FlushCallback, sna_shm_flush_callback, sna);
772.18938 -+		sna->watch_shm_flush = 0;
772.18939 -+	}
772.18940 -+
772.18941 -+	if (sna->watch_dri_flush == 1) {
772.18942 -+		DBG(("%s: removing dri watchers\n", __FUNCTION__));
772.18943 -+		DeleteCallback(&FlushCallback, sna_flush_callback, sna);
772.18944 -+		DeleteCallback(&EventCallback, sna_event_callback, sna);
772.18945 -+		sna->watch_dri_flush = 0;
772.18946 - 	}
772.18947 - 
772.18948 - 	if (sna->timer_active & 1) {
772.18949 -@@ -18083,22 +18428,6 @@ set_tv:
772.18950 - 	}
772.18951 - }
772.18952 - 
772.18953 --void sna_accel_wakeup_handler(struct sna *sna)
772.18954 --{
772.18955 --	DBG(("%s: nbatch=%d, need_retire=%d, need_purge=%d\n", __FUNCTION__,
772.18956 --	     sna->kgem.nbatch, sna->kgem.need_retire, sna->kgem.need_purge));
772.18957 --
772.18958 --	if (!sna->kgem.nbatch)
772.18959 --		return;
772.18960 --
772.18961 --	if (kgem_is_idle(&sna->kgem)) {
772.18962 --		DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
772.18963 --		_kgem_submit(&sna->kgem);
772.18964 --	}
772.18965 --
772.18966 --	sigtrap_assert_inactive();
772.18967 --}
772.18968 --
772.18969 - void sna_accel_free(struct sna *sna)
772.18970 - {
772.18971 - 	DBG(("%s\n", __FUNCTION__));
772.18972 -diff --git a/src/sna/sna_acpi.c b/src/sna/sna_acpi.c
772.18973 -index dcc0287b..643d04af 100644
772.18974 ---- a/src/sna/sna_acpi.c
772.18975 -+++ b/src/sna/sna_acpi.c
772.18976 -@@ -92,7 +92,7 @@ void _sna_acpi_wakeup(struct sna *sna)
772.18977 - 		DBG(("%s: error [%d], detaching from acpid\n", __FUNCTION__, n));
772.18978 - 
772.18979 - 		/* XXX reattach later? */
772.18980 --		RemoveGeneralSocket(sna->acpi.fd);
772.18981 -+		RemoveNotifyFd(sna->acpi.fd);
772.18982 - 		sna_acpi_fini(sna);
772.18983 - 		return;
772.18984 - 	}
772.18985 -@@ -136,6 +136,13 @@ void _sna_acpi_wakeup(struct sna *sna)
772.18986 - 	} while (n);
772.18987 - }
772.18988 - 
772.18989 -+#if HAVE_NOTIFY_FD
772.18990 -+static void sna_acpi_notify(int fd, int read, void *data)
772.18991 -+{
772.18992 -+	_sna_acpi_wakeup(data);
772.18993 -+}
772.18994 -+#endif
772.18995 -+
772.18996 - static int read_power_state(const char *path)
772.18997 - {
772.18998 - 	DIR *dir;
772.18999 -@@ -200,7 +207,7 @@ void sna_acpi_init(struct sna *sna)
772.19000 - 
772.19001 - 	DBG(("%s: attaching to acpid\n", __FUNCTION__));
772.19002 - 
772.19003 --	AddGeneralSocket(sna->acpi.fd);
772.19004 -+	SetNotifyFd(sna->acpi.fd, sna_acpi_notify, X_NOTIFY_READ, sna);
772.19005 - 	sna->acpi.remain = sizeof(sna->acpi.event) - 1;
772.19006 - 	sna->acpi.offset = 0;
772.19007 - 
772.19008 -diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
772.19009 -index de8f6ec3..ddd2586d 100644
772.19010 ---- a/src/sna/sna_blt.c
772.19011 -+++ b/src/sna/sna_blt.c
772.19012 -@@ -86,6 +86,11 @@ static const uint8_t fill_ROP[] = {
772.19013 - 	ROP_1
772.19014 - };
772.19015 - 
772.19016 -+static void sig_done(struct sna *sna, const struct sna_composite_op *op)
772.19017 -+{
772.19018 -+	sigtrap_put();
772.19019 -+}
772.19020 -+
772.19021 - static void nop_done(struct sna *sna, const struct sna_composite_op *op)
772.19022 - {
772.19023 - 	assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem));
772.19024 -@@ -129,7 +134,6 @@ static bool sna_blt_fill_init(struct sna *sna,
772.19025 - 	struct kgem *kgem = &sna->kgem;
772.19026 - 
772.19027 - 	assert(kgem_bo_can_blt (kgem, bo));
772.19028 --	assert(bo->tiling != I915_TILING_Y);
772.19029 - 	blt->bo[0] = bo;
772.19030 - 
772.19031 - 	blt->br13 = bo->pitch;
772.19032 -@@ -183,6 +187,7 @@ static bool sna_blt_fill_init(struct sna *sna,
772.19033 - 				return false;
772.19034 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19035 - 		}
772.19036 -+		kgem_bcs_set_tiling(kgem, NULL, bo);
772.19037 - 
772.19038 - 		assert(sna->kgem.mode == KGEM_BLT);
772.19039 - 		b = kgem->batch + kgem->nbatch;
772.19040 -@@ -237,17 +242,13 @@ static bool sna_blt_fill_init(struct sna *sna,
772.19041 - 	return true;
772.19042 - }
772.19043 - 
772.19044 --noinline static void sna_blt_fill_begin(struct sna *sna,
772.19045 --					const struct sna_blt_state *blt)
772.19046 -+noinline static void __sna_blt_fill_begin(struct sna *sna,
772.19047 -+					  const struct sna_blt_state *blt)
772.19048 - {
772.19049 - 	struct kgem *kgem = &sna->kgem;
772.19050 - 	uint32_t *b;
772.19051 - 
772.19052 --	if (kgem->nreloc) {
772.19053 --		_kgem_submit(kgem);
772.19054 --		_kgem_set_mode(kgem, KGEM_BLT);
772.19055 --		assert(kgem->nbatch == 0);
772.19056 --	}
772.19057 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, blt->bo[0]);
772.19058 - 
772.19059 - 	assert(kgem->mode == KGEM_BLT);
772.19060 - 	b = kgem->batch + kgem->nbatch;
772.19061 -@@ -293,6 +294,21 @@ noinline static void sna_blt_fill_begin(struct sna *sna,
772.19062 - 	}
772.19063 - }
772.19064 - 
772.19065 -+inline static void sna_blt_fill_begin(struct sna *sna,
772.19066 -+				      const struct sna_blt_state *blt)
772.19067 -+{
772.19068 -+	struct kgem *kgem = &sna->kgem;
772.19069 -+
772.19070 -+	if (kgem->nreloc) {
772.19071 -+		_kgem_submit(kgem);
772.19072 -+		_kgem_set_mode(kgem, KGEM_BLT);
772.19073 -+		kgem_bcs_set_tiling(kgem, NULL, blt->bo[0]);
772.19074 -+		assert(kgem->nbatch == 0);
772.19075 -+	}
772.19076 -+
772.19077 -+	__sna_blt_fill_begin(sna, blt);
772.19078 -+}
772.19079 -+
772.19080 - inline static void sna_blt_fill_one(struct sna *sna,
772.19081 - 				    const struct sna_blt_state *blt,
772.19082 - 				    int16_t x, int16_t y,
772.19083 -@@ -330,8 +346,8 @@ static bool sna_blt_copy_init(struct sna *sna,
772.19084 - {
772.19085 - 	struct kgem *kgem = &sna->kgem;
772.19086 - 
772.19087 --	assert(kgem_bo_can_blt (kgem, src));
772.19088 --	assert(kgem_bo_can_blt (kgem, dst));
772.19089 -+	assert(kgem_bo_can_blt(kgem, src));
772.19090 -+	assert(kgem_bo_can_blt(kgem, dst));
772.19091 - 
772.19092 - 	blt->bo[0] = src;
772.19093 - 	blt->bo[1] = dst;
772.19094 -@@ -370,6 +386,7 @@ static bool sna_blt_copy_init(struct sna *sna,
772.19095 - 			return false;
772.19096 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19097 - 	}
772.19098 -+	kgem_bcs_set_tiling(&sna->kgem, src, dst);
772.19099 - 
772.19100 - 	sna->blt_state.fill_bo = 0;
772.19101 - 	return true;
772.19102 -@@ -424,6 +441,7 @@ static bool sna_blt_alpha_fixup_init(struct sna *sna,
772.19103 - 			return false;
772.19104 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19105 - 	}
772.19106 -+	kgem_bcs_set_tiling(&sna->kgem, src, dst);
772.19107 - 
772.19108 - 	sna->blt_state.fill_bo = 0;
772.19109 - 	return true;
772.19110 -@@ -454,6 +472,7 @@ static void sna_blt_alpha_fixup_one(struct sna *sna,
772.19111 - 	    !kgem_check_reloc(kgem, 2)) {
772.19112 - 		_kgem_submit(kgem);
772.19113 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19114 -+		kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
772.19115 - 	}
772.19116 - 
772.19117 - 	assert(sna->kgem.mode == KGEM_BLT);
772.19118 -@@ -582,6 +601,7 @@ static void sna_blt_copy_one(struct sna *sna,
772.19119 - 	    !kgem_check_reloc(kgem, 2)) {
772.19120 - 		_kgem_submit(kgem);
772.19121 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19122 -+		kgem_bcs_set_tiling(&sna->kgem, blt->bo[0], blt->bo[1]);
772.19123 - 	}
772.19124 - 
772.19125 - 	assert(sna->kgem.mode == KGEM_BLT);
772.19126 -@@ -912,8 +932,27 @@ sna_composite_mask_is_opaque(PicturePtr mask)
772.19127 - 		return is_solid(mask) && is_white(mask);
772.19128 - 	else if (!PICT_FORMAT_A(mask->format))
772.19129 - 		return true;
772.19130 --	else
772.19131 --		return is_solid(mask) && is_opaque_solid(mask);
772.19132 -+	else if (mask->pSourcePict) {
772.19133 -+		PictSolidFill *fill = (PictSolidFill *) mask->pSourcePict;
772.19134 -+		return (fill->color >> 24) == 0xff;
772.19135 -+	} else {
772.19136 -+		struct sna_pixmap *priv;
772.19137 -+		assert(mask->pDrawable);
772.19138 -+
772.19139 -+		if (mask->pDrawable->width  == 1 &&
772.19140 -+		    mask->pDrawable->height == 1 &&
772.19141 -+		    mask->repeat)
772.19142 -+			return pixel_is_opaque(get_pixel(mask), mask->format);
772.19143 -+
772.19144 -+		if (mask->transform)
772.19145 -+			return false;
772.19146 -+
772.19147 -+		priv = sna_pixmap_from_drawable(mask->pDrawable);
772.19148 -+		if (priv == NULL || !priv->clear)
772.19149 -+			return false;
772.19150 -+
772.19151 -+		return pixel_is_opaque(priv->clear_color, mask->format);
772.19152 -+	}
772.19153 - }
772.19154 - 
772.19155 - fastcall
772.19156 -@@ -971,6 +1010,7 @@ static void blt_composite_fill__cpu(struct sna *sna,
772.19157 - 
772.19158 - 	assert(op->dst.pixmap->devPrivate.ptr);
772.19159 - 	assert(op->dst.pixmap->devKind);
772.19160 -+	sigtrap_assert_active();
772.19161 - 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
772.19162 - 		    op->dst.pixmap->devKind / sizeof(uint32_t),
772.19163 - 		    op->dst.pixmap->drawable.bitsPerPixel,
772.19164 -@@ -990,6 +1030,7 @@ blt_composite_fill_box_no_offset__cpu(struct sna *sna,
772.19165 - 
772.19166 - 	assert(op->dst.pixmap->devPrivate.ptr);
772.19167 - 	assert(op->dst.pixmap->devKind);
772.19168 -+	sigtrap_assert_active();
772.19169 - 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
772.19170 - 		    op->dst.pixmap->devKind / sizeof(uint32_t),
772.19171 - 		    op->dst.pixmap->drawable.bitsPerPixel,
772.19172 -@@ -1010,6 +1051,7 @@ blt_composite_fill_boxes_no_offset__cpu(struct sna *sna,
772.19173 - 
772.19174 - 		assert(op->dst.pixmap->devPrivate.ptr);
772.19175 - 		assert(op->dst.pixmap->devKind);
772.19176 -+		sigtrap_assert_active();
772.19177 - 		pixman_fill(op->dst.pixmap->devPrivate.ptr,
772.19178 - 			    op->dst.pixmap->devKind / sizeof(uint32_t),
772.19179 - 			    op->dst.pixmap->drawable.bitsPerPixel,
772.19180 -@@ -1031,6 +1073,7 @@ blt_composite_fill_box__cpu(struct sna *sna,
772.19181 - 
772.19182 - 	assert(op->dst.pixmap->devPrivate.ptr);
772.19183 - 	assert(op->dst.pixmap->devKind);
772.19184 -+	sigtrap_assert_active();
772.19185 - 	pixman_fill(op->dst.pixmap->devPrivate.ptr,
772.19186 - 		    op->dst.pixmap->devKind / sizeof(uint32_t),
772.19187 - 		    op->dst.pixmap->drawable.bitsPerPixel,
772.19188 -@@ -1052,6 +1095,7 @@ blt_composite_fill_boxes__cpu(struct sna *sna,
772.19189 - 
772.19190 - 		assert(op->dst.pixmap->devPrivate.ptr);
772.19191 - 		assert(op->dst.pixmap->devKind);
772.19192 -+		sigtrap_assert_active();
772.19193 - 		pixman_fill(op->dst.pixmap->devPrivate.ptr,
772.19194 - 			    op->dst.pixmap->devKind / sizeof(uint32_t),
772.19195 - 			    op->dst.pixmap->drawable.bitsPerPixel,
772.19196 -@@ -1159,12 +1203,15 @@ static inline void _sna_blt_maybe_clear(const struct sna_composite_op *op, const
772.19197 - 	    box->y2 - box->y1 >= op->dst.height) {
772.19198 - 		struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap);
772.19199 - 		if (op->dst.bo == priv->gpu_bo) {
772.19200 -+			sna_damage_all(&priv->gpu_damage, op->dst.pixmap);
772.19201 -+			sna_damage_destroy(&priv->cpu_damage);
772.19202 - 			priv->clear = true;
772.19203 - 			priv->clear_color = op->u.blt.pixel;
772.19204 - 			DBG(("%s: pixmap=%ld marking clear [%08x]\n",
772.19205 - 			     __FUNCTION__,
772.19206 - 			     op->dst.pixmap->drawable.serialNumber,
772.19207 - 			     op->u.blt.pixel));
772.19208 -+			((struct sna_composite_op *)op)->damage = NULL;
772.19209 - 		}
772.19210 - 	}
772.19211 - }
772.19212 -@@ -1404,6 +1451,7 @@ begin_blt(struct sna *sna,
772.19213 - 			return false;
772.19214 - 
772.19215 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.19216 -+		kgem_bcs_set_tiling(&sna->kgem, NULL, op->dst.bo);
772.19217 - 	}
772.19218 - 
772.19219 - 	return true;
772.19220 -@@ -1429,6 +1477,7 @@ prepare_blt_clear(struct sna *sna,
772.19221 - 	DBG(("%s\n", __FUNCTION__));
772.19222 - 
772.19223 - 	if (op->dst.bo == NULL) {
772.19224 -+		op->u.blt.pixel = 0;
772.19225 - 		op->blt   = blt_composite_fill__cpu;
772.19226 - 		if (op->dst.x|op->dst.y) {
772.19227 - 			op->box   = blt_composite_fill_box__cpu;
772.19228 -@@ -1439,9 +1488,8 @@ prepare_blt_clear(struct sna *sna,
772.19229 - 			op->boxes = blt_composite_fill_boxes_no_offset__cpu;
772.19230 - 			op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
772.19231 - 		}
772.19232 --		op->done  = nop_done;
772.19233 --		op->u.blt.pixel = 0;
772.19234 --		return true;
772.19235 -+		op->done = sig_done;
772.19236 -+		return sigtrap_get() == 0;
772.19237 - 	}
772.19238 - 
772.19239 - 	op->blt = blt_composite_fill;
772.19240 -@@ -1484,8 +1532,8 @@ prepare_blt_fill(struct sna *sna,
772.19241 - 			op->boxes = blt_composite_fill_boxes_no_offset__cpu;
772.19242 - 			op->thread_boxes = blt_composite_fill_boxes_no_offset__cpu;
772.19243 - 		}
772.19244 --		op->done = nop_done;
772.19245 --		return true;
772.19246 -+		op->done = sig_done;
772.19247 -+		return sigtrap_get() == 0;
772.19248 - 	}
772.19249 - 
772.19250 - 	op->blt = blt_composite_fill;
772.19251 -@@ -1668,6 +1716,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
772.19252 - 
772.19253 - 			_kgem_submit(kgem);
772.19254 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19255 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19256 - 		} while (1);
772.19257 - 	} else {
772.19258 - 		do {
772.19259 -@@ -1724,6 +1773,7 @@ static void blt_composite_copy_boxes__thread(struct sna *sna,
772.19260 - 
772.19261 - 			_kgem_submit(kgem);
772.19262 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19263 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19264 - 		} while (1);
772.19265 - 	}
772.19266 - 	sna_vertex_unlock(&sna->render);
772.19267 -@@ -1806,6 +1856,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
772.19268 - 
772.19269 - 			_kgem_submit(kgem);
772.19270 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19271 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19272 - 		} while (1);
772.19273 - 	} else {
772.19274 - 		do {
772.19275 -@@ -1864,6 +1915,7 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna,
772.19276 - 
772.19277 - 			_kgem_submit(kgem);
772.19278 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19279 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19280 - 		} while (1);
772.19281 - 	}
772.19282 - 	sna_vertex_unlock(&sna->render);
772.19283 -@@ -1973,6 +2025,7 @@ prepare_blt_copy(struct sna *sna,
772.19284 - 		}
772.19285 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.19286 - 	}
772.19287 -+	kgem_bcs_set_tiling(&sna->kgem, bo, op->dst.bo);
772.19288 - 
772.19289 - 	DBG(("%s\n", __FUNCTION__));
772.19290 - 
772.19291 -@@ -2396,6 +2449,9 @@ prepare_blt_put(struct sna *sna,
772.19292 - 			op->box   = blt_put_composite_box;
772.19293 - 			op->boxes = blt_put_composite_boxes;
772.19294 - 		}
772.19295 -+
772.19296 -+		op->done = nop_done;
772.19297 -+		return true;
772.19298 - 	} else {
772.19299 - 		if (alpha_fixup) {
772.19300 - 			op->u.blt.pixel = alpha_fixup;
772.19301 -@@ -2407,10 +2463,10 @@ prepare_blt_put(struct sna *sna,
772.19302 - 			op->box   = blt_put_composite_box__cpu;
772.19303 - 			op->boxes = blt_put_composite_boxes__cpu;
772.19304 - 		}
772.19305 --	}
772.19306 --	op->done = nop_done;
772.19307 - 
772.19308 --	return true;
772.19309 -+		op->done = sig_done;
772.19310 -+		return sigtrap_get() == 0;
772.19311 -+	}
772.19312 - }
772.19313 - 
772.19314 - static bool
772.19315 -@@ -2544,6 +2600,7 @@ sna_blt_composite(struct sna *sna,
772.19316 - clear:
772.19317 - 		if (was_clear && sna_pixmap(tmp->dst.pixmap)->clear_color == 0) {
772.19318 - 			sna_pixmap(tmp->dst.pixmap)->clear = true;
772.19319 -+nop:
772.19320 - 			return prepare_blt_nop(sna, tmp);
772.19321 - 		}
772.19322 - 
772.19323 -@@ -2559,6 +2616,7 @@ clear:
772.19324 - 		}
772.19325 - 		tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
772.19326 - 						  &dst_box, &tmp->damage);
772.19327 -+		assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
772.19328 - 		if (tmp->dst.bo) {
772.19329 - 			if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
772.19330 - 				DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
772.19331 -@@ -2567,6 +2625,8 @@ clear:
772.19332 - 			}
772.19333 - 			if (hint & REPLACES)
772.19334 - 				kgem_bo_undo(&sna->kgem, tmp->dst.bo);
772.19335 -+			if (flags & COMPOSITE_UPLOAD)
772.19336 -+				return false;
772.19337 - 		} else {
772.19338 - 			RegionRec region;
772.19339 - 
772.19340 -@@ -2590,32 +2650,40 @@ clear:
772.19341 - 		}
772.19342 - 		if (op == PictOpOver && is_opaque_solid(src))
772.19343 - 			op = PictOpSrc;
772.19344 --		if (op == PictOpAdd && is_white(src))
772.19345 -+		if (op == PictOpAdd &&
772.19346 -+		    PICT_FORMAT_RGB(src->format) == PICT_FORMAT_RGB(dst->format) &&
772.19347 -+		    is_white(src))
772.19348 - 			op = PictOpSrc;
772.19349 - 		if (was_clear && (op == PictOpAdd || op == PictOpOver)) {
772.19350 - 			if (sna_pixmap(tmp->dst.pixmap)->clear_color == 0)
772.19351 - 				op = PictOpSrc;
772.19352 - 			if (op == PictOpOver) {
772.19353 -+				unsigned dst_color = solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color);
772.19354 - 				color = over(get_solid_color(src, PICT_a8r8g8b8),
772.19355 --					     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
772.19356 --							   dst->format, PICT_a8r8g8b8));
772.19357 -+					     dst_color);
772.19358 - 				op = PictOpSrc;
772.19359 - 				DBG(("%s: precomputing solid OVER (%08x, %08x) -> %08x\n",
772.19360 - 				     __FUNCTION__, get_solid_color(src, PICT_a8r8g8b8),
772.19361 --				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
772.19362 --						   dst->format, PICT_a8r8g8b8),
772.19363 -+				     solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color),
772.19364 - 				     color));
772.19365 -+				if (color == dst_color)
772.19366 -+					goto nop;
772.19367 -+				else
772.19368 -+					goto fill;
772.19369 - 			}
772.19370 - 			if (op == PictOpAdd) {
772.19371 -+				unsigned dst_color = solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color);
772.19372 - 				color = add(get_solid_color(src, PICT_a8r8g8b8),
772.19373 --					    color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
772.19374 --							  dst->format, PICT_a8r8g8b8));
772.19375 -+					    dst_color);
772.19376 - 				op = PictOpSrc;
772.19377 - 				DBG(("%s: precomputing solid ADD (%08x, %08x) -> %08x\n",
772.19378 - 				     __FUNCTION__, get_solid_color(src, PICT_a8r8g8b8),
772.19379 --				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
772.19380 --						   dst->format, PICT_a8r8g8b8),
772.19381 -+				     solid_color(dst->format, sna_pixmap(tmp->dst.pixmap)->clear_color),
772.19382 - 				     color));
772.19383 -+				if (color == dst_color)
772.19384 -+					goto nop;
772.19385 -+				else
772.19386 -+					goto fill;
772.19387 - 			}
772.19388 - 		}
772.19389 - 		if (op == PictOpOutReverse && is_opaque_solid(src))
772.19390 -@@ -2649,6 +2717,7 @@ fill:
772.19391 - 		}
772.19392 - 		tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
772.19393 - 						  &dst_box, &tmp->damage);
772.19394 -+		assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
772.19395 - 		if (tmp->dst.bo) {
772.19396 - 			if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) {
772.19397 - 				DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n",
772.19398 -@@ -2657,6 +2726,8 @@ fill:
772.19399 - 			}
772.19400 - 			if (hint & REPLACES)
772.19401 - 				kgem_bo_undo(&sna->kgem, tmp->dst.bo);
772.19402 -+			if (flags & COMPOSITE_UPLOAD)
772.19403 -+				return false;
772.19404 - 		} else {
772.19405 - 			RegionRec region;
772.19406 - 
772.19407 -@@ -2720,8 +2791,8 @@ fill:
772.19408 - 	if (is_clear(src_pixmap)) {
772.19409 - 		if (src->repeat ||
772.19410 - 		    (x >= 0 && y >= 0 &&
772.19411 --		     x + width  < src_pixmap->drawable.width &&
772.19412 --		     y + height < src_pixmap->drawable.height)) {
772.19413 -+		     x + width  <= src_pixmap->drawable.width &&
772.19414 -+		     y + height <= src_pixmap->drawable.height)) {
772.19415 - 			color = color_convert(sna_pixmap(src_pixmap)->clear_color,
772.19416 - 					      src->format, tmp->dst.format);
772.19417 - 			goto fill;
772.19418 -@@ -2795,7 +2866,7 @@ fill:
772.19419 - 		if (src_pixmap->drawable.width  <= sna->render.max_3d_size &&
772.19420 - 		    src_pixmap->drawable.height <= sna->render.max_3d_size &&
772.19421 - 		    bo->pitch <= sna->render.max_3d_pitch &&
772.19422 --		    (flags & COMPOSITE_FALLBACK) == 0)
772.19423 -+		    (flags & (COMPOSITE_UPLOAD | COMPOSITE_FALLBACK)) == 0)
772.19424 - 		{
772.19425 - 			return false;
772.19426 - 		}
772.19427 -@@ -2817,6 +2888,7 @@ fill:
772.19428 - 	}
772.19429 - 	tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint,
772.19430 - 					  &dst_box, &tmp->damage);
772.19431 -+	assert(!tmp->damage || !DAMAGE_IS_ALL(*tmp->damage));
772.19432 - 
772.19433 - 	if (tmp->dst.bo && hint & REPLACES) {
772.19434 - 		struct sna_pixmap *priv = sna_pixmap(tmp->dst.pixmap);
772.19435 -@@ -2846,7 +2918,7 @@ fallback:
772.19436 - 			DBG(("%s: fallback -- unaccelerated upload\n",
772.19437 - 			     __FUNCTION__));
772.19438 - 			goto fallback;
772.19439 --		} else {
772.19440 -+		} else if ((flags & COMPOSITE_UPLOAD) == 0) {
772.19441 - 			ret = prepare_blt_copy(sna, tmp, bo, alpha_fixup);
772.19442 - 			if (!ret)
772.19443 - 				goto fallback;
772.19444 -@@ -3023,6 +3095,7 @@ sna_blt_composite__convert(struct sna *sna,
772.19445 - 		}
772.19446 - 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
772.19447 - 	}
772.19448 -+	kgem_bcs_set_tiling(&sna->kgem, tmp->src.bo, tmp->dst.bo);
772.19449 - 
772.19450 - 	if (alpha_fixup) {
772.19451 - 		tmp->blt   = blt_composite_copy_with_alpha;
772.19452 -@@ -3062,7 +3135,7 @@ static void sna_blt_fill_op_blt(struct sna *sna,
772.19453 - 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
772.19454 - 		const struct sna_blt_state *blt = &op->base.u.blt;
772.19455 - 
772.19456 --		sna_blt_fill_begin(sna, blt);
772.19457 -+		__sna_blt_fill_begin(sna, blt);
772.19458 - 
772.19459 - 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
772.19460 - 		sna->blt_state.fill_pixel = blt->pixel;
772.19461 -@@ -3079,7 +3152,7 @@ fastcall static void sna_blt_fill_op_box(struct sna *sna,
772.19462 - 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
772.19463 - 		const struct sna_blt_state *blt = &op->base.u.blt;
772.19464 - 
772.19465 --		sna_blt_fill_begin(sna, blt);
772.19466 -+		__sna_blt_fill_begin(sna, blt);
772.19467 - 
772.19468 - 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
772.19469 - 		sna->blt_state.fill_pixel = blt->pixel;
772.19470 -@@ -3097,7 +3170,7 @@ fastcall static void sna_blt_fill_op_boxes(struct sna *sna,
772.19471 - 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
772.19472 - 		const struct sna_blt_state *blt = &op->base.u.blt;
772.19473 - 
772.19474 --		sna_blt_fill_begin(sna, blt);
772.19475 -+		__sna_blt_fill_begin(sna, blt);
772.19476 - 
772.19477 - 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
772.19478 - 		sna->blt_state.fill_pixel = blt->pixel;
772.19479 -@@ -3132,7 +3205,7 @@ fastcall static void sna_blt_fill_op_points(struct sna *sna,
772.19480 - 	DBG(("%s: %08x x %d\n", __FUNCTION__, blt->pixel, n));
772.19481 - 
772.19482 - 	if (sna->blt_state.fill_bo != op->base.u.blt.bo[0]->unique_id) {
772.19483 --		sna_blt_fill_begin(sna, blt);
772.19484 -+		__sna_blt_fill_begin(sna, blt);
772.19485 - 
772.19486 - 		sna->blt_state.fill_bo = blt->bo[0]->unique_id;
772.19487 - 		sna->blt_state.fill_pixel = blt->pixel;
772.19488 -@@ -3162,65 +3235,15 @@ fastcall static void sna_blt_fill_op_points(struct sna *sna,
772.19489 - 		assert(kgem->nbatch < kgem->surface);
772.19490 - 
772.19491 - 		if ((dx|dy) == 0) {
772.19492 --			while (n_this_time >= 8) {
772.19493 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
772.19494 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
772.19495 --				*((uint64_t *)b + 2) = pt_add(cmd, p+2, 0, 0);
772.19496 --				*((uint64_t *)b + 3) = pt_add(cmd, p+3, 0, 0);
772.19497 --				*((uint64_t *)b + 4) = pt_add(cmd, p+4, 0, 0);
772.19498 --				*((uint64_t *)b + 5) = pt_add(cmd, p+5, 0, 0);
772.19499 --				*((uint64_t *)b + 6) = pt_add(cmd, p+6, 0, 0);
772.19500 --				*((uint64_t *)b + 7) = pt_add(cmd, p+7, 0, 0);
772.19501 --				b += 16;
772.19502 --				n_this_time -= 8;
772.19503 --				p += 8;
772.19504 --			}
772.19505 --			if (n_this_time & 4) {
772.19506 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
772.19507 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
772.19508 --				*((uint64_t *)b + 2) = pt_add(cmd, p+2, 0, 0);
772.19509 --				*((uint64_t *)b + 3) = pt_add(cmd, p+3, 0, 0);
772.19510 --				b += 8;
772.19511 --				p += 4;
772.19512 --			}
772.19513 --			if (n_this_time & 2) {
772.19514 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, 0, 0);
772.19515 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, 0, 0);
772.19516 --				b += 4;
772.19517 --				p += 2;
772.19518 --			}
772.19519 --			if (n_this_time & 1)
772.19520 --				*((uint64_t *)b + 0) = pt_add(cmd, p++, 0, 0);
772.19521 -+			do {
772.19522 -+				*(uint64_t *)b = pt_add(cmd, p++, 0, 0);
772.19523 -+				b += 2;
772.19524 -+			} while (--n_this_time);
772.19525 - 		} else {
772.19526 --			while (n_this_time >= 8) {
772.19527 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
772.19528 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
772.19529 --				*((uint64_t *)b + 2) = pt_add(cmd, p+2, dx, dy);
772.19530 --				*((uint64_t *)b + 3) = pt_add(cmd, p+3, dx, dy);
772.19531 --				*((uint64_t *)b + 4) = pt_add(cmd, p+4, dx, dy);
772.19532 --				*((uint64_t *)b + 5) = pt_add(cmd, p+5, dx, dy);
772.19533 --				*((uint64_t *)b + 6) = pt_add(cmd, p+6, dx, dy);
772.19534 --				*((uint64_t *)b + 7) = pt_add(cmd, p+7, dx, dy);
772.19535 --				b += 16;
772.19536 --				n_this_time -= 8;
772.19537 --				p += 8;
772.19538 --			}
772.19539 --			if (n_this_time & 4) {
772.19540 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
772.19541 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
772.19542 --				*((uint64_t *)b + 2) = pt_add(cmd, p+2, dx, dy);
772.19543 --				*((uint64_t *)b + 3) = pt_add(cmd, p+3, dx, dy);
772.19544 --				b += 8;
772.19545 --				p += 8;
772.19546 --			}
772.19547 --			if (n_this_time & 2) {
772.19548 --				*((uint64_t *)b + 0) = pt_add(cmd, p+0, dx, dy);
772.19549 --				*((uint64_t *)b + 1) = pt_add(cmd, p+1, dx, dy);
772.19550 --				b += 4;
772.19551 --				p += 2;
772.19552 --			}
772.19553 --			if (n_this_time & 1)
772.19554 --				*((uint64_t *)b + 0) = pt_add(cmd, p++, dx, dy);
772.19555 -+			do {
772.19556 -+				*(uint64_t *)b = pt_add(cmd, p++, dx, dy);
772.19557 -+				b += 2;
772.19558 -+			} while (--n_this_time);
772.19559 - 		}
772.19560 - 
772.19561 - 		if (!n)
772.19562 -@@ -3414,6 +3437,7 @@ static bool sna_blt_fill_box(struct sna *sna, uint8_t alu,
772.19563 - 
772.19564 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19565 - 	}
772.19566 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.19567 - 
772.19568 - 	assert(kgem_check_batch(kgem, 6));
772.19569 - 	assert(kgem_check_reloc(kgem, 1));
772.19570 -@@ -3520,6 +3544,8 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
772.19571 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19572 - 		}
772.19573 - 
772.19574 -+		kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.19575 -+
772.19576 - 		assert(sna->kgem.mode == KGEM_BLT);
772.19577 - 		b = kgem->batch + kgem->nbatch;
772.19578 - 		if (kgem->gen >= 0100) {
772.19579 -@@ -3608,6 +3634,7 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu,
772.19580 - 
772.19581 - 			_kgem_submit(kgem);
772.19582 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19583 -+			kgem_bcs_set_tiling(&sna->kgem, NULL, bo);
772.19584 - 
772.19585 - 			assert(sna->kgem.mode == KGEM_BLT);
772.19586 - 			b = kgem->batch + kgem->nbatch;
772.19587 -@@ -3754,6 +3781,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
772.19588 - 		}
772.19589 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.19590 - 	}
772.19591 -+	kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19592 - 
772.19593 - 	if ((dst_dx | dst_dy) == 0) {
772.19594 - 		if (kgem->gen >= 0100) {
772.19595 -@@ -3814,6 +3842,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
772.19596 - 
772.19597 - 				_kgem_submit(kgem);
772.19598 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.19599 -+				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19600 - 			} while (1);
772.19601 - 		} else {
772.19602 - 			uint64_t hdr = (uint64_t)br13 << 32 | cmd | 6;
772.19603 -@@ -3871,6 +3900,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
772.19604 - 
772.19605 - 				_kgem_submit(kgem);
772.19606 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.19607 -+				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19608 - 			} while (1);
772.19609 - 		}
772.19610 - 	} else {
772.19611 -@@ -3932,6 +3962,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
772.19612 - 
772.19613 - 				_kgem_submit(kgem);
772.19614 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.19615 -+				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19616 - 			} while (1);
772.19617 - 		} else {
772.19618 - 			cmd |= 6;
772.19619 -@@ -3989,6 +4020,7 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu,
772.19620 - 
772.19621 - 				_kgem_submit(kgem);
772.19622 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.19623 -+				kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19624 - 			} while (1);
772.19625 - 		}
772.19626 - 	}
772.19627 -@@ -4095,6 +4127,7 @@ bool sna_blt_copy_boxes__with_alpha(struct sna *sna, uint8_t alu,
772.19628 - 		    !kgem_check_reloc(kgem, 2)) {
772.19629 - 			_kgem_submit(kgem);
772.19630 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.19631 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, dst_bo);
772.19632 - 		}
772.19633 - 
772.19634 - 		assert(sna->kgem.mode == KGEM_BLT);
772.19635 -@@ -4190,6 +4223,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
772.19636 - 		DBG(("%s: dst == src\n", __FUNCTION__));
772.19637 - 
772.19638 - 		if (src_bo->tiling == I915_TILING_Y &&
772.19639 -+		    !sna->kgem.can_blt_y &&
772.19640 - 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
772.19641 - 			struct kgem_bo *bo;
772.19642 - 
772.19643 -@@ -4237,6 +4271,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
772.19644 - 		}
772.19645 - 	} else {
772.19646 - 		if (src_bo->tiling == I915_TILING_Y &&
772.19647 -+		    !sna->kgem.can_blt_y &&
772.19648 - 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) {
772.19649 - 			DBG(("%s: src is y-tiled\n", __FUNCTION__));
772.19650 - 			if (src->type != DRAWABLE_PIXMAP)
772.19651 -@@ -4251,6 +4286,7 @@ bool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu,
772.19652 - 		}
772.19653 - 
772.19654 - 		if (dst_bo->tiling == I915_TILING_Y &&
772.19655 -+		    !sna->kgem.can_blt_y &&
772.19656 - 		    kgem_bo_blt_pitch_is_ok(&sna->kgem, dst_bo)) {
772.19657 - 			DBG(("%s: dst is y-tiled\n", __FUNCTION__));
772.19658 - 			if (dst->type != DRAWABLE_PIXMAP)
772.19659 -diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
772.19660 -index f01f020e..1da8c291 100644
772.19661 ---- a/src/sna/sna_composite.c
772.19662 -+++ b/src/sna/sna_composite.c
772.19663 -@@ -452,6 +452,8 @@ static void apply_damage(struct sna_composite_op *op, RegionPtr region)
772.19664 - 		op->damage = NULL;
772.19665 - 	} else
772.19666 - 		sna_damage_add(op->damage, region);
772.19667 -+
772.19668 -+	assert(!op->damage || !DAMAGE_IS_ALL(*op->damage));
772.19669 - }
772.19670 - 
772.19671 - static inline bool use_cpu(PixmapPtr pixmap, struct sna_pixmap *priv,
772.19672 -@@ -653,8 +655,9 @@ sna_composite(CARD8 op,
772.19673 - 	RegionRec region;
772.19674 - 	int dx, dy;
772.19675 - 
772.19676 --	DBG(("%s(%d src=%ld+(%d, %d), mask=%ld+(%d, %d), dst=%ld+(%d, %d)+(%d, %d), size=(%d, %d)\n",
772.19677 --	     __FUNCTION__, op,
772.19678 -+	DBG(("%s(pixmap=%ld, op=%d, src=%ld+(%d, %d), mask=%ld+(%d, %d), dst=%ld+(%d, %d)+(%d, %d), size=(%d, %d)\n",
772.19679 -+	     __FUNCTION__,
772.19680 -+	     pixmap->drawable.serialNumber, op,
772.19681 - 	     get_picture_id(src), src_x, src_y,
772.19682 - 	     get_picture_id(mask), mask_x, mask_y,
772.19683 - 	     get_picture_id(dst), dst_x, dst_y,
772.19684 -@@ -673,13 +676,6 @@ sna_composite(CARD8 op,
772.19685 - 			src = sna->clear;
772.19686 - 	}
772.19687 - 
772.19688 --	if (mask && sna_composite_mask_is_opaque(mask)) {
772.19689 --		DBG(("%s: removing opaque %smask\n",
772.19690 --		     __FUNCTION__,
772.19691 --		     mask->componentAlpha && PICT_FORMAT_RGB(mask->format) ? "CA " : ""));
772.19692 --		mask = NULL;
772.19693 --	}
772.19694 --
772.19695 - 	if (!sna_compute_composite_region(&region,
772.19696 - 					  src, mask, dst,
772.19697 - 					  src_x,  src_y,
772.19698 -@@ -688,6 +684,13 @@ sna_composite(CARD8 op,
772.19699 - 					  width,  height))
772.19700 - 		return;
772.19701 - 
772.19702 -+	if (mask && sna_composite_mask_is_opaque(mask)) {
772.19703 -+		DBG(("%s: removing opaque %smask\n",
772.19704 -+		     __FUNCTION__,
772.19705 -+		     mask->componentAlpha && PICT_FORMAT_RGB(mask->format) ? "CA " : ""));
772.19706 -+		mask = NULL;
772.19707 -+	}
772.19708 -+
772.19709 - 	if (NO_COMPOSITE)
772.19710 - 		goto fallback;
772.19711 - 
772.19712 -@@ -756,6 +759,7 @@ sna_composite(CARD8 op,
772.19713 - 		DBG(("%s: fallback due unhandled composite op\n", __FUNCTION__));
772.19714 - 		goto fallback;
772.19715 - 	}
772.19716 -+	assert(!tmp.damage || !DAMAGE_IS_ALL(*tmp.damage));
772.19717 - 
772.19718 - 	if (region.data == NULL)
772.19719 - 		tmp.box(sna, &tmp, &region.extents);
772.19720 -@@ -797,8 +801,10 @@ sna_composite_rectangles(CARD8		 op,
772.19721 - 	int i, num_boxes;
772.19722 - 	unsigned hint;
772.19723 - 
772.19724 --	DBG(("%s(op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n",
772.19725 --	     __FUNCTION__, op,
772.19726 -+	DBG(("%s(pixmap=%ld, op=%d, %08x x %d [(%d, %d)x(%d, %d) ...])\n",
772.19727 -+	     __FUNCTION__,
772.19728 -+	     get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber,
772.19729 -+	     op,
772.19730 - 	     (color->alpha >> 8 << 24) |
772.19731 - 	     (color->red   >> 8 << 16) |
772.19732 - 	     (color->green >> 8 << 8) |
772.19733 -@@ -814,38 +820,40 @@ sna_composite_rectangles(CARD8		 op,
772.19734 - 		return;
772.19735 - 	}
772.19736 - 
772.19737 --	if ((color->red|color->green|color->blue|color->alpha) <= 0x00ff) {
772.19738 --		switch (op) {
772.19739 --		case PictOpOver:
772.19740 --		case PictOpOutReverse:
772.19741 --		case PictOpAdd:
772.19742 --			return;
772.19743 --		case  PictOpInReverse:
772.19744 --		case  PictOpSrc:
772.19745 --			op = PictOpClear;
772.19746 --			break;
772.19747 --		case  PictOpAtopReverse:
772.19748 --			op = PictOpOut;
772.19749 --			break;
772.19750 --		case  PictOpXor:
772.19751 --			op = PictOpOverReverse;
772.19752 --			break;
772.19753 --		}
772.19754 --	}
772.19755 - 	if (color->alpha <= 0x00ff) {
772.19756 --		switch (op) {
772.19757 --		case PictOpOver:
772.19758 --		case PictOpOutReverse:
772.19759 --			return;
772.19760 --		case  PictOpInReverse:
772.19761 --			op = PictOpClear;
772.19762 --			break;
772.19763 --		case  PictOpAtopReverse:
772.19764 --			op = PictOpOut;
772.19765 --			break;
772.19766 --		case  PictOpXor:
772.19767 --			op = PictOpOverReverse;
772.19768 --			break;
772.19769 -+		if (PICT_FORMAT_TYPE(dst->format) == PICT_TYPE_A ||
772.19770 -+		    (color->red|color->green|color->blue) <= 0x00ff) {
772.19771 -+			switch (op) {
772.19772 -+			case PictOpOver:
772.19773 -+			case PictOpOutReverse:
772.19774 -+			case PictOpAdd:
772.19775 -+				return;
772.19776 -+			case  PictOpInReverse:
772.19777 -+			case  PictOpSrc:
772.19778 -+				op = PictOpClear;
772.19779 -+				break;
772.19780 -+			case  PictOpAtopReverse:
772.19781 -+				op = PictOpOut;
772.19782 -+				break;
772.19783 -+			case  PictOpXor:
772.19784 -+				op = PictOpOverReverse;
772.19785 -+				break;
772.19786 -+			}
772.19787 -+		} else {
772.19788 -+			switch (op) {
772.19789 -+			case PictOpOver:
772.19790 -+			case PictOpOutReverse:
772.19791 -+				return;
772.19792 -+			case  PictOpInReverse:
772.19793 -+				op = PictOpClear;
772.19794 -+				break;
772.19795 -+			case  PictOpAtopReverse:
772.19796 -+				op = PictOpOut;
772.19797 -+				break;
772.19798 -+			case  PictOpXor:
772.19799 -+				op = PictOpOverReverse;
772.19800 -+				break;
772.19801 -+			}
772.19802 - 		}
772.19803 - 	} else if (color->alpha >= 0xff00) {
772.19804 - 		switch (op) {
772.19805 -@@ -863,11 +871,16 @@ sna_composite_rectangles(CARD8		 op,
772.19806 - 		case  PictOpXor:
772.19807 - 			op = PictOpOut;
772.19808 - 			break;
772.19809 -+		case PictOpAdd:
772.19810 -+			if (PICT_FORMAT_TYPE(dst->format) == PICT_TYPE_A ||
772.19811 -+			    (color->red&color->green&color->blue) >= 0xff00)
772.19812 -+				op = PictOpSrc;
772.19813 -+			break;
772.19814 - 		}
772.19815 - 	}
772.19816 - 
772.19817 - 	/* Avoid reducing overlapping translucent rectangles */
772.19818 --	if (op == PictOpOver &&
772.19819 -+	if ((op == PictOpOver || op == PictOpAdd) &&
772.19820 - 	    num_rects == 1 &&
772.19821 - 	    sna_drawable_is_clear(dst->pDrawable))
772.19822 - 		op = PictOpSrc;
772.19823 -@@ -979,6 +992,9 @@ sna_composite_rectangles(CARD8		 op,
772.19824 - 			bool ok;
772.19825 - 
772.19826 - 			if (op == PictOpClear) {
772.19827 -+				if (priv->clear_color == 0)
772.19828 -+					goto done;
772.19829 -+
772.19830 - 				ok = sna_get_pixel_from_rgba(&pixel,
772.19831 - 							     0, 0, 0, 0,
772.19832 - 							     dst->format);
772.19833 -@@ -990,8 +1006,11 @@ sna_composite_rectangles(CARD8		 op,
772.19834 - 							     color->alpha,
772.19835 - 							     dst->format);
772.19836 - 			}
772.19837 --			if (ok && priv->clear_color == pixel)
772.19838 -+			if (ok && priv->clear_color == pixel) {
772.19839 -+				DBG(("%s: matches current clear, skipping\n",
772.19840 -+				     __FUNCTION__));
772.19841 - 				goto done;
772.19842 -+			}
772.19843 - 		}
772.19844 - 
772.19845 - 		if (region.data == NULL) {
772.19846 -diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
772.19847 -index 272e83bc..d5c727ee 100644
772.19848 ---- a/src/sna/sna_damage.h
772.19849 -+++ b/src/sna/sna_damage.h
772.19850 -@@ -267,7 +267,7 @@ int _sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes);
772.19851 - static inline int
772.19852 - sna_damage_get_boxes(struct sna_damage *damage, const BoxRec **boxes)
772.19853 - {
772.19854 --	assert(damage);
772.19855 -+	assert(DAMAGE_PTR(damage));
772.19856 - 
772.19857 - 	if (DAMAGE_IS_ALL(damage)) {
772.19858 - 		*boxes = &DAMAGE_PTR(damage)->extents;
772.19859 -@@ -322,7 +322,8 @@ static inline void sna_damage_destroy(struct sna_damage **damage)
772.19860 - 	if (*damage == NULL)
772.19861 - 		return;
772.19862 - 
772.19863 --	__sna_damage_destroy(DAMAGE_PTR(*damage));
772.19864 -+	if (DAMAGE_PTR(*damage))
772.19865 -+		__sna_damage_destroy(DAMAGE_PTR(*damage));
772.19866 - 	*damage = NULL;
772.19867 - }
772.19868 - 
772.19869 -diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
772.19870 -index 4b218b70..9b77550e 100644
772.19871 ---- a/src/sna/sna_display.c
772.19872 -+++ b/src/sna/sna_display.c
772.19873 -@@ -39,6 +39,25 @@
772.19874 - #include <errno.h>
772.19875 - #include <poll.h>
772.19876 - #include <ctype.h>
772.19877 -+#include <dirent.h>
772.19878 -+
772.19879 -+#if HAVE_ALLOCA_H
772.19880 -+#include <alloca.h>
772.19881 -+#elif defined __GNUC__
772.19882 -+#define alloca __builtin_alloca
772.19883 -+#elif defined _AIX
772.19884 -+#define alloca __alloca
772.19885 -+#elif defined _MSC_VER
772.19886 -+#include <malloc.h>
772.19887 -+#define alloca _alloca
772.19888 -+#else
772.19889 -+void *alloca(size_t);
772.19890 -+#endif
772.19891 -+
772.19892 -+#define _PARSE_EDID_
772.19893 -+/* Jump through a few hoops in order to fixup EDIDs */
772.19894 -+#undef VERSION
772.19895 -+#undef REVISION
772.19896 - 
772.19897 - #include "sna.h"
772.19898 - #include "sna_reg.h"
772.19899 -@@ -72,6 +91,10 @@
772.19900 - #include <memcheck.h>
772.19901 - #endif
772.19902 - 
772.19903 -+#define FAIL_CURSOR_IOCTL 0
772.19904 -+
772.19905 -+#define COLDPLUG_DELAY_MS 2000
772.19906 -+
772.19907 - /* Minor discrepancy between 32-bit/64-bit ABI in old kernels */
772.19908 - union compat_mode_get_connector{
772.19909 - 	struct drm_mode_get_connector conn;
772.19910 -@@ -88,6 +111,8 @@ union compat_mode_get_connector{
772.19911 - #define DEFAULT_DPI 96
772.19912 - #endif
772.19913 - 
772.19914 -+#define OUTPUT_STATUS_CACHE_MS 15000
772.19915 -+
772.19916 - #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
772.19917 - 
772.19918 - #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
772.19919 -@@ -106,33 +131,87 @@ struct local_mode_obj_get_properties {
772.19920 - };
772.19921 - #define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee
772.19922 - 
772.19923 --#if 0
772.19924 -+struct local_mode_set_plane {
772.19925 -+	uint32_t plane_id;
772.19926 -+	uint32_t crtc_id;
772.19927 -+	uint32_t fb_id; /* fb object contains surface format type */
772.19928 -+	uint32_t flags;
772.19929 -+
772.19930 -+	/* Signed dest location allows it to be partially off screen */
772.19931 -+	int32_t crtc_x, crtc_y;
772.19932 -+	uint32_t crtc_w, crtc_h;
772.19933 -+
772.19934 -+	/* Source values are 16.16 fixed point */
772.19935 -+	uint32_t src_x, src_y;
772.19936 -+	uint32_t src_h, src_w;
772.19937 -+};
772.19938 -+#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane)
772.19939 -+
772.19940 -+struct local_mode_get_plane {
772.19941 -+	uint32_t plane_id;
772.19942 -+
772.19943 -+	uint32_t crtc_id;
772.19944 -+	uint32_t fb_id;
772.19945 -+
772.19946 -+	uint32_t possible_crtcs;
772.19947 -+	uint32_t gamma_size;
772.19948 -+
772.19949 -+	uint32_t count_format_types;
772.19950 -+	uint64_t format_type_ptr;
772.19951 -+};
772.19952 -+#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane)
772.19953 -+
772.19954 -+struct local_mode_get_plane_res {
772.19955 -+	uint64_t plane_id_ptr;
772.19956 -+	uint64_t count_planes;
772.19957 -+};
772.19958 -+#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
772.19959 -+
772.19960 -+#if 1
772.19961 - #define __DBG DBG
772.19962 - #else
772.19963 - #define __DBG(x)
772.19964 - #endif
772.19965 - 
772.19966 -+#define DBG_NATIVE_ROTATION ~0 /* minimum RR_Rotate_0 */
772.19967 -+
772.19968 - extern XF86ConfigPtr xf86configptr;
772.19969 - 
772.19970 -+struct sna_cursor {
772.19971 -+	struct sna_cursor *next;
772.19972 -+	uint32_t *image;
772.19973 -+	bool transformed;
772.19974 -+	Rotation rotation;
772.19975 -+	int ref;
772.19976 -+	int size;
772.19977 -+	int last_width;
772.19978 -+	int last_height;
772.19979 -+	unsigned handle;
772.19980 -+	unsigned serial;
772.19981 -+	unsigned alloc;
772.19982 -+};
772.19983 -+
772.19984 - struct sna_crtc {
772.19985 -+	unsigned long flags;
772.19986 -+	uint32_t id;
772.19987 - 	xf86CrtcPtr base;
772.19988 - 	struct drm_mode_modeinfo kmode;
772.19989 --	int dpms_mode;
772.19990 - 	PixmapPtr slave_pixmap;
772.19991 - 	DamagePtr slave_damage;
772.19992 --	struct kgem_bo *bo, *shadow_bo, *client_bo;
772.19993 -+	struct kgem_bo *bo, *shadow_bo, *client_bo, *cache_bo;
772.19994 - 	struct sna_cursor *cursor;
772.19995 - 	unsigned int last_cursor_size;
772.19996 - 	uint32_t offset;
772.19997 - 	bool shadow;
772.19998 - 	bool fallback_shadow;
772.19999 - 	bool transform;
772.20000 -+	bool cursor_transform;
772.20001 -+	bool hwcursor;
772.20002 - 	bool flip_pending;
772.20003 --	uint8_t id;
772.20004 --	uint8_t pipe;
772.20005 - 
772.20006 --	RegionRec client_damage; /* XXX overlap with shadow damage? */
772.20007 -+	struct pict_f_transform cursor_to_fb, fb_to_cursor;
772.20008 - 
772.20009 -+	RegionRec crtc_damage;
772.20010 - 	uint16_t shadow_bo_width, shadow_bo_height;
772.20011 - 
772.20012 - 	uint32_t rotation;
772.20013 -@@ -143,7 +222,9 @@ struct sna_crtc {
772.20014 - 			uint32_t supported;
772.20015 - 			uint32_t current;
772.20016 - 		} rotation;
772.20017 --	} primary, sprite;
772.20018 -+		struct list link;
772.20019 -+	} primary;
772.20020 -+	struct list sprites;
772.20021 - 
772.20022 - 	uint32_t mode_serial, flip_serial;
772.20023 - 
772.20024 -@@ -173,21 +254,33 @@ struct sna_output {
772.20025 - 
772.20026 - 	unsigned int is_panel : 1;
772.20027 - 	unsigned int add_default_modes : 1;
772.20028 -+	int connector_type;
772.20029 -+	int connector_type_id;
772.20030 -+
772.20031 -+	uint32_t link_status_idx;
772.20032 - 
772.20033 - 	uint32_t edid_idx;
772.20034 - 	uint32_t edid_blob_id;
772.20035 - 	uint32_t edid_len;
772.20036 - 	void *edid_raw;
772.20037 -+	xf86MonPtr fake_edid_mon;
772.20038 -+	void *fake_edid_raw;
772.20039 - 
772.20040 - 	bool has_panel_limits;
772.20041 - 	int panel_hdisplay;
772.20042 - 	int panel_vdisplay;
772.20043 - 
772.20044 - 	uint32_t dpms_id;
772.20045 --	int dpms_mode;
772.20046 -+	uint8_t dpms_mode;
772.20047 - 	struct backlight backlight;
772.20048 - 	int backlight_active_level;
772.20049 - 
772.20050 -+	uint32_t last_detect;
772.20051 -+	uint32_t status;
772.20052 -+	unsigned int hotplug_count;
772.20053 -+	bool update_properties;
772.20054 -+	bool reprobe;
772.20055 -+
772.20056 - 	int num_modes;
772.20057 - 	struct drm_mode_modeinfo *modes;
772.20058 - 
772.20059 -@@ -218,13 +311,91 @@ enum { /* XXX copied from hw/xfree86/modes/xf86Crtc.c */
772.20060 - 	OPTION_DEFAULT_MODES,
772.20061 - };
772.20062 - 
772.20063 -+static void __sna_output_dpms(xf86OutputPtr output, int dpms, int fixup);
772.20064 - static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
772.20065 -+static bool sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc,
772.20066 -+			  struct kgem_bo *bo, int x, int y);
772.20067 - 
772.20068 - static bool is_zaphod(ScrnInfoPtr scrn)
772.20069 - {
772.20070 - 	return xf86IsEntityShared(scrn->entityList[0]);
772.20071 - }
772.20072 - 
772.20073 -+static bool
772.20074 -+sna_zaphod_match(struct sna *sna, const char *output)
772.20075 -+{
772.20076 -+	const char *s, *colon;
772.20077 -+	char t[20];
772.20078 -+	unsigned int i = 0;
772.20079 -+
772.20080 -+	s = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
772.20081 -+	if (s == NULL)
772.20082 -+		return false;
772.20083 -+
772.20084 -+	colon = strchr(s, ':');
772.20085 -+	if (colon) /* Skip over the ZaphodPipes */
772.20086 -+		s = colon + 1;
772.20087 -+
772.20088 -+	do {
772.20089 -+		/* match any outputs in a comma list, stopping at whitespace */
772.20090 -+		switch (*s) {
772.20091 -+		case '\0':
772.20092 -+			t[i] = '\0';
772.20093 -+			return strcmp(t, output) == 0;
772.20094 -+
772.20095 -+		case ',':
772.20096 -+			t[i] ='\0';
772.20097 -+			if (strcmp(t, output) == 0)
772.20098 -+				return TRUE;
772.20099 -+			i = 0;
772.20100 -+			break;
772.20101 -+
772.20102 -+		case ' ':
772.20103 -+		case '\t':
772.20104 -+		case '\n':
772.20105 -+		case '\r':
772.20106 -+			break;
772.20107 -+
772.20108 -+		default:
772.20109 -+			t[i++] = *s;
772.20110 -+			break;
772.20111 -+		}
772.20112 -+
772.20113 -+		s++;
772.20114 -+	} while (i < sizeof(t));
772.20115 -+
772.20116 -+	return false;
772.20117 -+}
772.20118 -+
772.20119 -+static unsigned
772.20120 -+get_zaphod_crtcs(struct sna *sna)
772.20121 -+{
772.20122 -+	const char *str, *colon;
772.20123 -+	unsigned crtcs = 0;
772.20124 -+
772.20125 -+	str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
772.20126 -+	if (str == NULL || (colon = strchr(str, ':')) == NULL) {
772.20127 -+		DBG(("%s: no zaphod pipes, using screen number: %x\n",
772.20128 -+		     __FUNCTION__,
772.20129 -+		     sna->scrn->confScreen->device->screen));
772.20130 -+		return 1 << sna->scrn->confScreen->device->screen;
772.20131 -+	}
772.20132 -+
772.20133 -+	DBG(("%s: ZaphodHeads='%s'\n", __FUNCTION__, str));
772.20134 -+	while (str < colon) {
772.20135 -+		char *end;
772.20136 -+		unsigned crtc = strtoul(str, &end, 0);
772.20137 -+		if (end == str)
772.20138 -+			break;
772.20139 -+		DBG(("%s: adding CRTC %d to zaphod pipes\n",
772.20140 -+		     __FUNCTION__, crtc));
772.20141 -+		crtcs |= 1 << crtc;
772.20142 -+		str = end + 1;
772.20143 -+	}
772.20144 -+	DBG(("%s: ZaphodPipes=%x\n", __FUNCTION__, crtcs));
772.20145 -+	return crtcs;
772.20146 -+}
772.20147 -+
772.20148 - inline static unsigned count_to_mask(int x)
772.20149 - {
772.20150 - 	return (1 << x) - 1;
772.20151 -@@ -247,6 +418,21 @@ static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
772.20152 - 	return crtc->driver_private;
772.20153 - }
772.20154 - 
772.20155 -+static inline unsigned __sna_crtc_pipe(struct sna_crtc *crtc)
772.20156 -+{
772.20157 -+	return crtc->flags >> 8 & 0xff;
772.20158 -+}
772.20159 -+
772.20160 -+static inline unsigned __sna_crtc_id(struct sna_crtc *crtc)
772.20161 -+{
772.20162 -+	return crtc->id;
772.20163 -+}
772.20164 -+
772.20165 -+uint32_t sna_crtc_id(xf86CrtcPtr crtc)
772.20166 -+{
772.20167 -+	return __sna_crtc_id(to_sna_crtc(crtc));
772.20168 -+}
772.20169 -+
772.20170 - static inline bool event_pending(int fd)
772.20171 - {
772.20172 - 	struct pollfd pfd;
772.20173 -@@ -268,29 +454,37 @@ static inline uint32_t fb_id(struct kgem_bo *bo)
772.20174 - 	return bo->delta;
772.20175 - }
772.20176 - 
772.20177 --uint32_t sna_crtc_id(xf86CrtcPtr crtc)
772.20178 -+unsigned sna_crtc_count_sprites(xf86CrtcPtr crtc)
772.20179 - {
772.20180 --	if (to_sna_crtc(crtc) == NULL)
772.20181 --		return 0;
772.20182 --	return to_sna_crtc(crtc)->id;
772.20183 --}
772.20184 -+	struct plane *sprite;
772.20185 -+	unsigned count;
772.20186 - 
772.20187 --int sna_crtc_to_pipe(xf86CrtcPtr crtc)
772.20188 --{
772.20189 --	assert(to_sna_crtc(crtc));
772.20190 --	return to_sna_crtc(crtc)->pipe;
772.20191 -+	count = 0;
772.20192 -+	list_for_each_entry(sprite, &to_sna_crtc(crtc)->sprites, link)
772.20193 -+		count++;
772.20194 -+
772.20195 -+	return count;
772.20196 - }
772.20197 - 
772.20198 --uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
772.20199 -+static struct plane *lookup_sprite(struct sna_crtc *crtc, unsigned idx)
772.20200 - {
772.20201 --	assert(to_sna_crtc(crtc));
772.20202 --	return to_sna_crtc(crtc)->sprite.id;
772.20203 -+	struct plane *sprite;
772.20204 -+
772.20205 -+	list_for_each_entry(sprite, &crtc->sprites, link)
772.20206 -+		if (idx-- == 0)
772.20207 -+			return sprite;
772.20208 -+
772.20209 -+	return NULL;
772.20210 - }
772.20211 - 
772.20212 --bool sna_crtc_is_on(xf86CrtcPtr crtc)
772.20213 -+uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc, unsigned idx)
772.20214 - {
772.20215 -+	struct plane *sprite;
772.20216 -+
772.20217 - 	assert(to_sna_crtc(crtc));
772.20218 --	return to_sna_crtc(crtc)->bo != NULL;
772.20219 -+
772.20220 -+	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
772.20221 -+	return sprite ? sprite->id : 0;
772.20222 - }
772.20223 - 
772.20224 - bool sna_crtc_is_transformed(xf86CrtcPtr crtc)
772.20225 -@@ -299,34 +493,48 @@ bool sna_crtc_is_transformed(xf86CrtcPtr crtc)
772.20226 - 	return to_sna_crtc(crtc)->transform;
772.20227 - }
772.20228 - 
772.20229 --static inline uint64_t msc64(struct sna_crtc *sna_crtc, uint32_t seq)
772.20230 -+static inline bool msc64(struct sna_crtc *sna_crtc, uint32_t seq, uint64_t *msc)
772.20231 - {
772.20232 -+	bool record = true;
772.20233 - 	if (seq < sna_crtc->last_seq) {
772.20234 - 		if (sna_crtc->last_seq - seq > 0x40000000) {
772.20235 - 			sna_crtc->wrap_seq++;
772.20236 - 			DBG(("%s: pipe=%d wrapped; was %u, now %u, wraps=%u\n",
772.20237 --			     __FUNCTION__, sna_crtc->pipe,
772.20238 -+			     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
772.20239 - 			     sna_crtc->last_seq, seq, sna_crtc->wrap_seq));
772.20240 --		} else  {
772.20241 --			ERR(("%s: pipe=%d msc went backwards; was %u, now %u\n",
772.20242 --			     __FUNCTION__, sna_crtc->pipe, sna_crtc->last_seq, seq));
772.20243 --			seq = sna_crtc->last_seq;
772.20244 -+		} else {
772.20245 -+			DBG(("%s: pipe=%d msc went backwards; was %u, now %u; ignoring for last_swap\n",
772.20246 -+			     __FUNCTION__, __sna_crtc_pipe(sna_crtc), sna_crtc->last_seq, seq));
772.20247 -+
772.20248 -+			record = false;
772.20249 - 		}
772.20250 - 	}
772.20251 --	sna_crtc->last_seq = seq;
772.20252 --	return (uint64_t)sna_crtc->wrap_seq << 32 | seq;
772.20253 -+	*msc = (uint64_t)sna_crtc->wrap_seq << 32 | seq;
772.20254 -+	return record;
772.20255 - }
772.20256 - 
772.20257 - uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc,
772.20258 - 			      int tv_sec, int tv_usec, unsigned seq)
772.20259 - {
772.20260 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.20261 -+	uint64_t msc;
772.20262 -+
772.20263 - 	assert(sna_crtc);
772.20264 --	DBG(("%s: recording last swap on pipe=%d, frame %d, time %d.%06d\n",
772.20265 --	     __FUNCTION__, sna_crtc->pipe, seq, tv_sec, tv_usec));
772.20266 --	sna_crtc->swap.tv_sec = tv_sec;
772.20267 --	sna_crtc->swap.tv_usec = tv_usec;
772.20268 --	return sna_crtc->swap.msc = msc64(sna_crtc, seq);
772.20269 -+
772.20270 -+	if (msc64(sna_crtc, seq, &msc)) {
772.20271 -+		DBG(("%s: recording last swap on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
772.20272 -+		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
772.20273 -+		     tv_sec, tv_usec));
772.20274 -+		sna_crtc->swap.tv_sec = tv_sec;
772.20275 -+		sna_crtc->swap.tv_usec = tv_usec;
772.20276 -+		sna_crtc->swap.msc = msc;
772.20277 -+	} else {
772.20278 -+		DBG(("%s: swap event on pipe=%d, frame %d [msc=%08lld], time %d.%06d\n",
772.20279 -+		     __FUNCTION__, __sna_crtc_pipe(sna_crtc), seq, (long long)msc,
772.20280 -+		     tv_sec, tv_usec));
772.20281 -+	}
772.20282 -+
772.20283 -+	return msc;
772.20284 - }
772.20285 - 
772.20286 - const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc)
772.20287 -@@ -342,15 +550,6 @@ const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc)
772.20288 - 	}
772.20289 - }
772.20290 - 
772.20291 --xf86CrtcPtr sna_mode_first_crtc(struct sna *sna)
772.20292 --{
772.20293 --	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.20294 --	if (sna->mode.num_real_crtc)
772.20295 --		return config->crtc[0];
772.20296 --	else
772.20297 --		return NULL;
772.20298 --}
772.20299 --
772.20300 - #ifndef NDEBUG
772.20301 - static void gem_close(int fd, uint32_t handle);
772.20302 - static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
772.20303 -@@ -372,12 +571,24 @@ static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo,
772.20304 - #define assert_scanout(k, b, w, h)
772.20305 - #endif
772.20306 - 
772.20307 -+static void assert_crtc_fb(struct sna *sna, struct sna_crtc *crtc)
772.20308 -+{
772.20309 -+#ifndef NDEBUG
772.20310 -+	struct drm_mode_crtc mode = { .crtc_id = __sna_crtc_id(crtc) };
772.20311 -+	drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
772.20312 -+	assert(mode.fb_id == fb_id(crtc->bo));
772.20313 -+#endif
772.20314 -+}
772.20315 -+
772.20316 - static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
772.20317 - 		       int width, int height)
772.20318 - {
772.20319 - 	ScrnInfoPtr scrn = sna->scrn;
772.20320 - 	struct drm_mode_fb_cmd arg;
772.20321 - 
772.20322 -+	if (!kgem_bo_is_fenced(&sna->kgem, bo))
772.20323 -+		return 0;
772.20324 -+
772.20325 - 	assert(bo->refcnt);
772.20326 - 	assert(bo->proxy == NULL);
772.20327 - 	assert(!bo->snoop);
772.20328 -@@ -393,8 +604,9 @@ static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
772.20329 - 	DBG(("%s: create fb %dx%d@%d/%d\n",
772.20330 - 	     __FUNCTION__, width, height, scrn->depth, scrn->bitsPerPixel));
772.20331 - 
772.20332 --	assert(bo->tiling != I915_TILING_Y);
772.20333 -+	assert(bo->tiling != I915_TILING_Y || sna->kgem.can_scanout_y);
772.20334 - 	assert((bo->pitch & 63) == 0);
772.20335 -+	assert(scrn->vtSema); /* must be master */
772.20336 - 
772.20337 - 	VG_CLEAR(arg);
772.20338 - 	arg.width = width;
772.20339 -@@ -404,21 +616,83 @@ static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
772.20340 - 	arg.depth = scrn->depth;
772.20341 - 	arg.handle = bo->handle;
772.20342 - 
772.20343 --	assert(sna->scrn->vtSema); /* must be master */
772.20344 - 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
772.20345 --		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
772.20346 --			   "%s: failed to add fb: %dx%d depth=%d, bpp=%d, pitch=%d: %d\n",
772.20347 --			   __FUNCTION__, width, height,
772.20348 --			   scrn->depth, scrn->bitsPerPixel, bo->pitch, errno);
772.20349 --		return 0;
772.20350 -+		/* Try again with the fancy version */
772.20351 -+		struct local_mode_fb_cmd2 {
772.20352 -+			uint32_t fb_id;
772.20353 -+			uint32_t width, height;
772.20354 -+			uint32_t pixel_format;
772.20355 -+			uint32_t flags;
772.20356 -+
772.20357 -+			uint32_t handles[4];
772.20358 -+			uint32_t pitches[4]; /* pitch for each plane */
772.20359 -+			uint32_t offsets[4]; /* offset of each plane */
772.20360 -+			uint64_t modifiers[4];
772.20361 -+		} f;
772.20362 -+#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2)
772.20363 -+		memset(&f, 0, sizeof(f));
772.20364 -+		f.width = width;
772.20365 -+		f.height = height;
772.20366 -+		/* XXX interlaced */
772.20367 -+		f.flags = 1 << 1; /* +modifiers */
772.20368 -+		f.handles[0] = bo->handle;
772.20369 -+		f.pitches[0] = bo->pitch;
772.20370 -+
772.20371 -+		switch (bo->tiling) {
772.20372 -+		case I915_TILING_NONE:
772.20373 -+			break;
772.20374 -+		case I915_TILING_X:
772.20375 -+			/* I915_FORMAT_MOD_X_TILED */
772.20376 -+			f.modifiers[0] = (uint64_t)1 << 56 | 1;
772.20377 -+			break;
772.20378 -+		case I915_TILING_Y:
772.20379 -+			/* I915_FORMAT_MOD_X_TILED */
772.20380 -+			f.modifiers[0] = (uint64_t)1 << 56 | 2;
772.20381 -+			break;
772.20382 -+		}
772.20383 -+
772.20384 -+#define fourcc(a,b,c,d) ((a) | (b) << 8 | (c) << 16 | (d) << 24)
772.20385 -+		switch (scrn->depth) {
772.20386 -+		default:
772.20387 -+			ERR(("%s: unhandled screen format, depth=%d\n",
772.20388 -+			     __FUNCTION__, scrn->depth));
772.20389 -+			goto fail;
772.20390 -+		case 8:
772.20391 -+			f.pixel_format = fourcc('C', '8', ' ', ' ');
772.20392 -+			break;
772.20393 -+		case 15:
772.20394 -+			f.pixel_format = fourcc('X', 'R', '1', '5');
772.20395 -+			break;
772.20396 -+		case 16:
772.20397 -+			f.pixel_format = fourcc('R', 'G', '1', '6');
772.20398 -+			break;
772.20399 -+		case 24:
772.20400 -+			f.pixel_format = fourcc('X', 'R', '2', '4');
772.20401 -+			break;
772.20402 -+		case 30:
772.20403 -+			f.pixel_format = fourcc('X', 'R', '3', '0');
772.20404 -+			break;
772.20405 -+		}
772.20406 -+#undef fourcc
772.20407 -+
772.20408 -+		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_ADDFB2, &f)) {
772.20409 -+fail:
772.20410 -+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
772.20411 -+				   "%s: failed to add fb: %dx%d depth=%d, bpp=%d, pitch=%d: %d\n",
772.20412 -+				   __FUNCTION__, width, height,
772.20413 -+				   scrn->depth, scrn->bitsPerPixel, bo->pitch, errno);
772.20414 -+			return 0;
772.20415 -+		}
772.20416 -+
772.20417 -+		arg.fb_id = f.fb_id;
772.20418 - 	}
772.20419 - 	assert(arg.fb_id != 0);
772.20420 --
772.20421 -+	bo->delta = arg.fb_id;
772.20422 - 	DBG(("%s: attached fb=%d to handle=%d\n",
772.20423 --	     __FUNCTION__, arg.fb_id, arg.handle));
772.20424 -+	     __FUNCTION__, bo->delta, arg.handle));
772.20425 - 
772.20426 - 	bo->scanout = true;
772.20427 --	return bo->delta = arg.fb_id;
772.20428 -+	return bo->delta;
772.20429 - }
772.20430 - 
772.20431 - static uint32_t gem_create(int fd, int size)
772.20432 -@@ -438,6 +712,7 @@ static uint32_t gem_create(int fd, int size)
772.20433 - static void *gem_mmap(int fd, int handle, int size)
772.20434 - {
772.20435 - 	struct drm_i915_gem_mmap_gtt mmap_arg;
772.20436 -+	struct drm_i915_gem_set_domain set_domain;
772.20437 - 	void *ptr;
772.20438 - 
772.20439 - 	VG_CLEAR(mmap_arg);
772.20440 -@@ -449,6 +724,15 @@ static void *gem_mmap(int fd, int handle, int size)
772.20441 - 	if (ptr == MAP_FAILED)
772.20442 - 		return NULL;
772.20443 - 
772.20444 -+	VG_CLEAR(set_domain);
772.20445 -+	set_domain.handle = handle;
772.20446 -+	set_domain.read_domains = I915_GEM_DOMAIN_GTT;
772.20447 -+	set_domain.write_domain = I915_GEM_DOMAIN_GTT;
772.20448 -+	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
772.20449 -+		munmap(ptr, size);
772.20450 -+		return NULL;
772.20451 -+	}
772.20452 -+
772.20453 - 	return ptr;
772.20454 - }
772.20455 - 
772.20456 -@@ -497,8 +781,6 @@ sna_backlight_uevent(int fd, void *closure)
772.20457 - 		if (sna_output->dpms_mode != DPMSModeOn)
772.20458 - 			continue;
772.20459 - 
772.20460 --		assert(output->randr_output);
772.20461 --
772.20462 - 		val = backlight_get(&sna_output->backlight);
772.20463 - 		if (val < 0)
772.20464 - 			continue;
772.20465 -@@ -523,6 +805,7 @@ sna_backlight_uevent(int fd, void *closure)
772.20466 - 					       TRUE, FALSE);
772.20467 - 		}
772.20468 - 	}
772.20469 -+	DBG(("%s: complete\n", __FUNCTION__));
772.20470 - }
772.20471 - 
772.20472 - static void sna_backlight_pre_init(struct sna *sna)
772.20473 -@@ -570,6 +853,7 @@ static void sna_backlight_drain_uevents(struct sna *sna)
772.20474 - 	if (sna->mode.backlight_monitor == NULL)
772.20475 - 		return;
772.20476 - 
772.20477 -+	DBG(("%s()\n", __FUNCTION__));
772.20478 - 	sna_backlight_uevent(udev_monitor_get_fd(sna->mode.backlight_monitor),
772.20479 - 			     sna);
772.20480 - }
772.20481 -@@ -632,9 +916,22 @@ sna_output_backlight_set(struct sna_output *sna_output, int level)
772.20482 - 	return ret;
772.20483 - }
772.20484 - 
772.20485 -+static bool
772.20486 -+has_native_backlight(struct sna_output *sna_output)
772.20487 -+{
772.20488 -+	return sna_output->backlight.type == BL_RAW;
772.20489 -+}
772.20490 -+
772.20491 - static void
772.20492 - sna_output_backlight_off(struct sna_output *sna_output)
772.20493 - {
772.20494 -+	/* Trust the kernel to turn the native backlight off. However, we
772.20495 -+	 * do explicitly turn the backlight back on (when we wake the output)
772.20496 -+	 * just in case a third party turns it off!
772.20497 -+	 */
772.20498 -+	if (has_native_backlight(sna_output))
772.20499 -+		return;
772.20500 -+
772.20501 - 	DBG(("%s(%s)\n", __FUNCTION__, sna_output->base->name));
772.20502 - 	backlight_off(&sna_output->backlight);
772.20503 - 	sna_output_backlight_set(sna_output, 0);
772.20504 -@@ -674,7 +971,7 @@ has_user_backlight_override(xf86OutputPtr output)
772.20505 - 	if (*str == '\0')
772.20506 - 		return (char *)str;
772.20507 - 
772.20508 --	if (backlight_exists(str) == BL_NONE) {
772.20509 -+	if (!backlight_exists(str)) {
772.20510 - 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.20511 - 			   "Unrecognised backlight control interface '%s'\n",
772.20512 - 			   str);
772.20513 -@@ -684,6 +981,93 @@ has_user_backlight_override(xf86OutputPtr output)
772.20514 - 	return strdup(str);
772.20515 - }
772.20516 - 
772.20517 -+static int get_device_minor(int fd)
772.20518 -+{
772.20519 -+	struct stat st;
772.20520 -+
772.20521 -+	if (fstat(fd, &st) || !S_ISCHR(st.st_mode))
772.20522 -+		return -1;
772.20523 -+
772.20524 -+	return st.st_rdev & 0x63;
772.20525 -+}
772.20526 -+
772.20527 -+static const char * const sysfs_connector_types[] = {
772.20528 -+	/* DRM_MODE_CONNECTOR_Unknown */	"Unknown",
772.20529 -+	/* DRM_MODE_CONNECTOR_VGA */		"VGA",
772.20530 -+	/* DRM_MODE_CONNECTOR_DVII */		"DVI-I",
772.20531 -+	/* DRM_MODE_CONNECTOR_DVID */		"DVI-D",
772.20532 -+	/* DRM_MODE_CONNECTOR_DVIA */		"DVI-A",
772.20533 -+	/* DRM_MODE_CONNECTOR_Composite */	"Composite",
772.20534 -+	/* DRM_MODE_CONNECTOR_SVIDEO */		"SVIDEO",
772.20535 -+	/* DRM_MODE_CONNECTOR_LVDS */		"LVDS",
772.20536 -+	/* DRM_MODE_CONNECTOR_Component */	"Component",
772.20537 -+	/* DRM_MODE_CONNECTOR_9PinDIN */	"DIN",
772.20538 -+	/* DRM_MODE_CONNECTOR_DisplayPort */	"DP",
772.20539 -+	/* DRM_MODE_CONNECTOR_HDMIA */		"HDMI-A",
772.20540 -+	/* DRM_MODE_CONNECTOR_HDMIB */		"HDMI-B",
772.20541 -+	/* DRM_MODE_CONNECTOR_TV */		"TV",
772.20542 -+	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
772.20543 -+	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
772.20544 -+	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
772.20545 -+	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
772.20546 -+};
772.20547 -+
772.20548 -+static char *has_connector_backlight(xf86OutputPtr output)
772.20549 -+{
772.20550 -+	struct sna_output *sna_output = output->driver_private;
772.20551 -+	struct sna *sna = to_sna(output->scrn);
772.20552 -+	char path[1024];
772.20553 -+	DIR *dir;
772.20554 -+	struct dirent *de;
772.20555 -+	int minor, len;
772.20556 -+	char *str = NULL;
772.20557 -+
772.20558 -+	if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types))
772.20559 -+		return NULL;
772.20560 -+
772.20561 -+	minor = get_device_minor(sna->kgem.fd);
772.20562 -+	if (minor < 0)
772.20563 -+		return NULL;
772.20564 -+
772.20565 -+	len = snprintf(path, sizeof(path),
772.20566 -+		       "/sys/class/drm/card%d-%s-%d",
772.20567 -+		       minor,
772.20568 -+		       sysfs_connector_types[sna_output->connector_type],
772.20569 -+		       sna_output->connector_type_id);
772.20570 -+	DBG(("%s: lookup %s\n", __FUNCTION__, path));
772.20571 -+
772.20572 -+	dir = opendir(path);
772.20573 -+	if (dir == NULL)
772.20574 -+		return NULL;
772.20575 -+
772.20576 -+	while ((de = readdir(dir))) {
772.20577 -+		struct stat st;
772.20578 -+
772.20579 -+		if (*de->d_name == '.')
772.20580 -+			continue;
772.20581 -+
772.20582 -+		snprintf(path + len, sizeof(path) - len,
772.20583 -+			 "/%s", de->d_name);
772.20584 -+
772.20585 -+		if (stat(path, &st))
772.20586 -+			continue;
772.20587 -+
772.20588 -+		if (!S_ISDIR(st.st_mode))
772.20589 -+			continue;
772.20590 -+
772.20591 -+		DBG(("%s: testing %s as backlight\n",
772.20592 -+		     __FUNCTION__, de->d_name));
772.20593 -+
772.20594 -+		if (backlight_exists(de->d_name)) {
772.20595 -+			str = strdup(de->d_name); /* leak! */
772.20596 -+			break;
772.20597 -+		}
772.20598 -+	}
772.20599 -+
772.20600 -+	closedir(dir);
772.20601 -+	return str;
772.20602 -+}
772.20603 -+
772.20604 - static void
772.20605 - sna_output_backlight_init(xf86OutputPtr output)
772.20606 - {
772.20607 -@@ -696,11 +1080,20 @@ sna_output_backlight_init(xf86OutputPtr output)
772.20608 - 	return;
772.20609 - #endif
772.20610 - 
772.20611 --	from = X_CONFIG;
772.20612 --	best_iface = has_user_backlight_override(output);
772.20613 -+	if (sna_output->is_panel) {
772.20614 -+		from = X_CONFIG;
772.20615 -+		best_iface = has_user_backlight_override(output);
772.20616 -+		if (best_iface)
772.20617 -+			goto done;
772.20618 -+	}
772.20619 -+
772.20620 -+	best_iface = has_connector_backlight(output);
772.20621 - 	if (best_iface)
772.20622 - 		goto done;
772.20623 - 
772.20624 -+	if (!sna_output->is_panel)
772.20625 -+		return;
772.20626 -+
772.20627 - 	/* XXX detect right backlight for multi-GPU/panels */
772.20628 - 	from = X_PROBED;
772.20629 - 	pci = xf86GetPciInfoForEntity(to_sna(output->scrn)->pEnt->index);
772.20630 -@@ -728,6 +1121,38 @@ done:
772.20631 - 		   sna_output->backlight.iface, best_iface, output->name);
772.20632 - }
772.20633 - 
772.20634 -+#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(22, 0)
772.20635 -+static inline int sigio_block(void)
772.20636 -+{
772.20637 -+	return 0;
772.20638 -+}
772.20639 -+static inline void sigio_unblock(int was_blocked)
772.20640 -+{
772.20641 -+	(void)was_blocked;
772.20642 -+}
772.20643 -+#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
772.20644 -+static inline int sigio_block(void)
772.20645 -+{
772.20646 -+	OsBlockSIGIO();
772.20647 -+	return 0;
772.20648 -+}
772.20649 -+static inline void sigio_unblock(int was_blocked)
772.20650 -+{
772.20651 -+	OsReleaseSIGIO();
772.20652 -+	(void)was_blocked;
772.20653 -+}
772.20654 -+#else
772.20655 -+#include <xf86_OSproc.h>
772.20656 -+static inline int sigio_block(void)
772.20657 -+{
772.20658 -+	return xf86BlockSIGIO();
772.20659 -+}
772.20660 -+static inline void sigio_unblock(int was_blocked)
772.20661 -+{
772.20662 -+	xf86UnblockSIGIO(was_blocked);
772.20663 -+}
772.20664 -+#endif
772.20665 -+
772.20666 - static char *canonical_kmode_name(const struct drm_mode_modeinfo *kmode)
772.20667 - {
772.20668 - 	char tmp[32], *buf;
772.20669 -@@ -781,6 +1206,7 @@ mode_from_kmode(ScrnInfoPtr scrn,
772.20670 - 	mode->VTotal = kmode->vtotal;
772.20671 - 	mode->VScan = kmode->vscan;
772.20672 - 
772.20673 -+	mode->VRefresh = kmode->vrefresh;
772.20674 - 	mode->Flags = kmode->flags;
772.20675 - 	mode->name = get_kmode_name(kmode);
772.20676 - 
772.20677 -@@ -814,6 +1240,7 @@ mode_to_kmode(struct drm_mode_modeinfo *kmode, DisplayModePtr mode)
772.20678 - 	kmode->vtotal = mode->VTotal;
772.20679 - 	kmode->vscan = mode->VScan;
772.20680 - 
772.20681 -+	kmode->vrefresh = mode->VRefresh;
772.20682 - 	kmode->flags = mode->Flags;
772.20683 - 	if (mode->name)
772.20684 - 		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
772.20685 -@@ -824,11 +1251,12 @@ static void
772.20686 - sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
772.20687 - {
772.20688 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
772.20689 -+	/* All attached outputs are valid, so update our timestamps */
772.20690 -+	unsigned now = GetTimeInMillis();
772.20691 - 	int i;
772.20692 - 
772.20693 - 	assert(to_sna_crtc(crtc));
772.20694 --	DBG(("%s(pipe=%d), currently? %d\n", __FUNCTION__,
772.20695 --	     to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->dpms_mode));
772.20696 -+	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
772.20697 - 
772.20698 - 	/* DPMS handling by the kernel is inconsistent, so after setting a
772.20699 - 	 * mode on an output presume that we intend for it to be on, or that
772.20700 -@@ -843,10 +1271,11 @@ sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
772.20701 - 		if (output->crtc != crtc)
772.20702 - 			continue;
772.20703 - 
772.20704 --		output->funcs->dpms(output, DPMSModeOn);
772.20705 -+		__sna_output_dpms(output, DPMSModeOn, false);
772.20706 -+		if (to_sna_output(output)->last_detect)
772.20707 -+			to_sna_output(output)->last_detect = now;
772.20708 - 	}
772.20709 - 
772.20710 --	to_sna_crtc(crtc)->dpms_mode = DPMSModeOn;
772.20711 - #if XF86_CRTC_VERSION >= 3
772.20712 - 	crtc->active = TRUE;
772.20713 - #endif
772.20714 -@@ -859,8 +1288,7 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
772.20715 - 	int i;
772.20716 - 
772.20717 - 	assert(to_sna_crtc(crtc));
772.20718 --	DBG(("%s(pipe=%d), currently? %d\n", __FUNCTION__,
772.20719 --	     to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->dpms_mode));
772.20720 -+	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc)));
772.20721 - 
772.20722 - 	/* DPMS handling by the kernel is inconsistent, so after setting a
772.20723 - 	 * mode on an output presume that we intend for it to be on, or that
772.20724 -@@ -875,35 +1303,47 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
772.20725 - 		if (output->crtc != crtc)
772.20726 - 			continue;
772.20727 - 
772.20728 --		output->funcs->dpms(output, DPMSModeOff);
772.20729 -+		__sna_output_dpms(output, DPMSModeOff, false);
772.20730 - 	}
772.20731 --
772.20732 --	to_sna_crtc(crtc)->dpms_mode = DPMSModeOff;
772.20733 - }
772.20734 - 
772.20735 - static unsigned
772.20736 --rotation_reduce(struct plane *p, unsigned rotation)
772.20737 -+rotation_reflect(unsigned rotation)
772.20738 - {
772.20739 --	unsigned unsupported_rotations = rotation & ~p->rotation.supported;
772.20740 -+	unsigned other_bits;
772.20741 - 
772.20742 --	if (unsupported_rotations == 0)
772.20743 --		return rotation;
772.20744 -+	/* paranoia for future extensions */
772.20745 -+	other_bits = rotation & ~RR_Rotate_All;
772.20746 - 
772.20747 --#define RR_Reflect_XY (RR_Reflect_X | RR_Reflect_Y)
772.20748 -+	/* flip the reflection to compensate for reflecting the rotation */
772.20749 -+	other_bits ^= RR_Reflect_X | RR_Reflect_Y;
772.20750 - 
772.20751 --	if ((unsupported_rotations & RR_Reflect_XY) == RR_Reflect_XY &&
772.20752 --	    p->rotation.supported& RR_Rotate_180) {
772.20753 --		rotation &= ~RR_Reflect_XY;
772.20754 --		rotation ^= RR_Rotate_180;
772.20755 --	}
772.20756 -+	/* Reflect the screen by rotating the rotation bit,
772.20757 -+	 * which has to have at least RR_Rotate_0 set. This allows
772.20758 -+	 * us to reflect any of the rotation bits, not just 0.
772.20759 -+	 */
772.20760 -+	rotation &= RR_Rotate_All;
772.20761 -+	assert(rotation);
772.20762 -+	rotation <<= 2; /* RR_Rotate_0 -> RR_Rotate_180 etc */
772.20763 -+	rotation |= rotation >> 4; /* RR_Rotate_270' to RR_Rotate_90 */
772.20764 -+	rotation &= RR_Rotate_All;
772.20765 -+	assert(rotation);
772.20766 - 
772.20767 --	if ((unsupported_rotations & RR_Rotate_180) &&
772.20768 --	    (p->rotation.supported& RR_Reflect_XY) == RR_Reflect_XY) {
772.20769 --		rotation ^= RR_Reflect_XY;
772.20770 --		rotation &= ~RR_Rotate_180;
772.20771 -+	return rotation | other_bits;
772.20772 -+}
772.20773 -+
772.20774 -+static unsigned
772.20775 -+rotation_reduce(struct plane *p, unsigned rotation)
772.20776 -+{
772.20777 -+	/* If unsupported try exchanging rotation for a reflection */
772.20778 -+	if (rotation & ~p->rotation.supported) {
772.20779 -+		unsigned new_rotation = rotation_reflect(rotation);
772.20780 -+		if ((new_rotation & p->rotation.supported) == new_rotation)
772.20781 -+			rotation = new_rotation;
772.20782 - 	}
772.20783 - 
772.20784 --#undef RR_Reflect_XY
772.20785 -+	/* Only one rotation bit should be set */
772.20786 -+	assert(is_power_of_two(rotation & RR_Rotate_All));
772.20787 - 
772.20788 - 	return rotation;
772.20789 - }
772.20790 -@@ -923,7 +1363,7 @@ rotation_set(struct sna *sna, struct plane *p, uint32_t desired)
772.20791 - 	if (desired == p->rotation.current)
772.20792 - 		return true;
772.20793 - 
772.20794 --	if ((desired & p->rotation.supported) == 0) {
772.20795 -+	if ((desired & p->rotation.supported) != desired) {
772.20796 - 		errno = EINVAL;
772.20797 - 		return false;
772.20798 - 	}
772.20799 -@@ -956,20 +1396,105 @@ rotation_reset(struct plane *p)
772.20800 - 	p->rotation.current = 0;
772.20801 - }
772.20802 - 
772.20803 --bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
772.20804 -+bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc,
772.20805 -+				  unsigned idx,
772.20806 -+				  uint32_t rotation)
772.20807 - {
772.20808 -+	struct plane *sprite;
772.20809 - 	assert(to_sna_crtc(crtc));
772.20810 -+
772.20811 -+	sprite = lookup_sprite(to_sna_crtc(crtc), idx);
772.20812 -+	if (!sprite)
772.20813 -+		return false;
772.20814 -+
772.20815 - 	DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
772.20816 - 	     __FUNCTION__,
772.20817 --	     to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite.id,
772.20818 --	     rotation));
772.20819 -+	     sna_crtc_id(crtc), sna_crtc_pipe(crtc),
772.20820 -+	     sprite->id, rotation));
772.20821 - 
772.20822 --	return rotation_set(to_sna(crtc->scrn),
772.20823 --			    &to_sna_crtc(crtc)->sprite,
772.20824 --			    rotation_reduce(&to_sna_crtc(crtc)->sprite, rotation));
772.20825 -+	return rotation_set(to_sna(crtc->scrn), sprite,
772.20826 -+			    rotation_reduce(sprite, rotation));
772.20827 - }
772.20828 - 
772.20829 --static bool
772.20830 -+#if HAS_DEBUG_FULL
772.20831 -+#if !HAS_DEBUG_FULL
772.20832 -+#define LogF ErrorF
772.20833 -+#endif
772.20834 -+struct kmsg {
772.20835 -+	int fd;
772.20836 -+	int saved_loglevel;
772.20837 -+};
772.20838 -+
772.20839 -+static int kmsg_get_debug(void)
772.20840 -+{
772.20841 -+	FILE *file;
772.20842 -+	int v = -1;
772.20843 -+
772.20844 -+	file = fopen("/sys/module/drm/parameters/debug", "r");
772.20845 -+	if (file) {
772.20846 -+		fscanf(file, "%d", &v);
772.20847 -+		fclose(file);
772.20848 -+	}
772.20849 -+
772.20850 -+	return v;
772.20851 -+}
772.20852 -+
772.20853 -+static void kmsg_set_debug(int v)
772.20854 -+{
772.20855 -+	FILE *file;
772.20856 -+
772.20857 -+	file = fopen("/sys/module/drm/parameters/debug", "w");
772.20858 -+	if (file) {
772.20859 -+		fprintf(file, "%d\n", v);
772.20860 -+		fclose(file);
772.20861 -+	}
772.20862 -+}
772.20863 -+
772.20864 -+static void kmsg_open(struct kmsg *k)
772.20865 -+{
772.20866 -+	k->saved_loglevel = kmsg_get_debug();
772.20867 -+	if (k->saved_loglevel != -1)
772.20868 -+		kmsg_set_debug(0xff);
772.20869 -+
772.20870 -+	k->fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
772.20871 -+	if (k->fd != -1)
772.20872 -+		lseek(k->fd, 0, SEEK_END);
772.20873 -+}
772.20874 -+
772.20875 -+static void kmsg_close(struct kmsg *k, int dump)
772.20876 -+{
772.20877 -+	FILE *file;
772.20878 -+
772.20879 -+	file = NULL;
772.20880 -+	if (k->fd != -1 && dump)
772.20881 -+		file = fdopen(k->fd, "r");
772.20882 -+	if (file) {
772.20883 -+		size_t len = 0;
772.20884 -+		char *line = NULL;
772.20885 -+
772.20886 -+		while (getline(&line, &len, file) != -1) {
772.20887 -+			char *start = strchr(line, ';');
772.20888 -+			if (start)
772.20889 -+				LogF("KMSG: %s", start + 1);
772.20890 -+		}
772.20891 -+
772.20892 -+		free(line);
772.20893 -+		fclose(file);
772.20894 -+	}
772.20895 -+
772.20896 -+	if (k->fd != -1)
772.20897 -+		close(k->fd);
772.20898 -+
772.20899 -+	if (k->saved_loglevel != -1)
772.20900 -+		kmsg_set_debug(k->saved_loglevel);
772.20901 -+}
772.20902 -+#else
772.20903 -+struct kmsg { int unused; };
772.20904 -+static void kmsg_open(struct kmsg *k) {}
772.20905 -+static void kmsg_close(struct kmsg *k, int dump) {}
772.20906 -+#endif
772.20907 -+
772.20908 -+static int
772.20909 - sna_crtc_apply(xf86CrtcPtr crtc)
772.20910 - {
772.20911 - 	struct sna *sna = to_sna(crtc->scrn);
772.20912 -@@ -978,26 +1503,39 @@ sna_crtc_apply(xf86CrtcPtr crtc)
772.20913 - 	struct drm_mode_crtc arg;
772.20914 - 	uint32_t output_ids[32];
772.20915 - 	int output_count = 0;
772.20916 --	int i;
772.20917 -+	int sigio, i;
772.20918 -+	struct kmsg kmsg;
772.20919 -+	int ret = EINVAL;
772.20920 - 
772.20921 --	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->bo->handle));
772.20922 -+	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__,
772.20923 -+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
772.20924 -+	     sna_crtc->bo->handle));
772.20925 - 	if (!sna_crtc->kmode.clock) {
772.20926 - 		ERR(("%s(CRTC:%d [pipe=%d]): attempted to set an invalid mode\n",
772.20927 --		     __FUNCTION__, sna_crtc->id, sna_crtc->pipe));
772.20928 --		return false;
772.20929 -+		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc)));
772.20930 -+		return EINVAL;
772.20931 - 	}
772.20932 - 
772.20933 -+	kmsg_open(&kmsg);
772.20934 -+	sigio = sigio_block();
772.20935 -+
772.20936 - 	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
772.20937 - 	sna_crtc_disable_cursor(sna, sna_crtc);
772.20938 - 
772.20939 - 	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
772.20940 -+		memset(&arg, 0, sizeof(arg));
772.20941 -+		arg.crtc_id = __sna_crtc_id(sna_crtc);
772.20942 -+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
772.20943 -+	}
772.20944 -+
772.20945 -+	if (!rotation_set(sna, &sna_crtc->primary, sna_crtc->rotation)) {
772.20946 - 		ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n",
772.20947 --		     __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno));
772.20948 -+		     __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
772.20949 - 		sna_crtc->primary.rotation.supported &= ~sna_crtc->rotation;
772.20950 --		return false;
772.20951 -+		goto unblock;
772.20952 - 	}
772.20953 - 	DBG(("%s: CRTC:%d [pipe=%d] primary rotation set to %x\n",
772.20954 --	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->rotation));
772.20955 -+	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna_crtc->rotation));
772.20956 - 
772.20957 - 	for (i = 0; i < sna->mode.num_real_output; i++) {
772.20958 - 		xf86OutputPtr output = config->output[i];
772.20959 -@@ -1008,7 +1546,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
772.20960 - 		 * and we lose track of the user settings.
772.20961 - 		 */
772.20962 - 		if (output->crtc == NULL)
772.20963 --			output->funcs->dpms(output, DPMSModeOff);
772.20964 -+			__sna_output_dpms(output, DPMSModeOff, false);
772.20965 - 
772.20966 - 		if (output->crtc != crtc)
772.20967 - 			continue;
772.20968 -@@ -1022,29 +1560,27 @@ sna_crtc_apply(xf86CrtcPtr crtc)
772.20969 - 
772.20970 - 		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
772.20971 - 		     __FUNCTION__, output->name, i, to_connector_id(output),
772.20972 --		     sna_crtc->id, sna_crtc->pipe,
772.20973 -+		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
772.20974 - 		     (uint32_t)output->possible_crtcs,
772.20975 - 		     (uint32_t)output->possible_clones));
772.20976 - 
772.20977 --		assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
772.20978 -+		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(sna_crtc)) ||
772.20979 - 		       is_zaphod(crtc->scrn));
772.20980 - 
772.20981 - 		output_ids[output_count] = to_connector_id(output);
772.20982 - 		if (++output_count == ARRAY_SIZE(output_ids)) {
772.20983 - 			DBG(("%s: too many outputs (%d) for me!\n",
772.20984 - 			     __FUNCTION__, output_count));
772.20985 --			errno = EINVAL;
772.20986 --			return false;
772.20987 -+			goto unblock;
772.20988 - 		}
772.20989 - 	}
772.20990 - 	if (output_count == 0) {
772.20991 - 		DBG(("%s: no outputs\n", __FUNCTION__));
772.20992 --		errno = EINVAL;
772.20993 --		return false;
772.20994 -+		goto unblock;
772.20995 - 	}
772.20996 - 
772.20997 - 	VG_CLEAR(arg);
772.20998 --	arg.crtc_id = sna_crtc->id;
772.20999 -+	arg.crtc_id = __sna_crtc_id(sna_crtc);
772.21000 - 	arg.fb_id = fb_id(sna_crtc->bo);
772.21001 - 	if (sna_crtc->transform || sna_crtc->slave_pixmap) {
772.21002 - 		arg.x = 0;
772.21003 -@@ -1061,7 +1597,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
772.21004 - 	arg.mode_valid = 1;
772.21005 - 
772.21006 - 	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d%s%s update to %d outputs [%d...]\n",
772.21007 --	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
772.21008 -+	     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
772.21009 - 	     arg.mode.hdisplay,
772.21010 - 	     arg.mode.vdisplay,
772.21011 - 	     arg.x, arg.y,
772.21012 -@@ -1071,12 +1607,19 @@ sna_crtc_apply(xf86CrtcPtr crtc)
772.21013 - 	     sna_crtc->transform ? " [transformed]" : "",
772.21014 - 	     output_count, output_count ? output_ids[0] : 0));
772.21015 - 
772.21016 --	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
772.21017 --		return false;
772.21018 -+	ret = 0;
772.21019 -+	if (unlikely(drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))) {
772.21020 -+		ret = errno;
772.21021 -+		goto unblock;
772.21022 -+	}
772.21023 - 
772.21024 - 	sna_crtc->mode_serial++;
772.21025 - 	sna_crtc_force_outputs_on(crtc);
772.21026 --	return true;
772.21027 -+
772.21028 -+unblock:
772.21029 -+	sigio_unblock(sigio);
772.21030 -+	kmsg_close(&kmsg, ret);
772.21031 -+	return ret;
772.21032 - }
772.21033 - 
772.21034 - static bool overlap(const BoxRec *a, const BoxRec *b)
772.21035 -@@ -1094,26 +1637,73 @@ static bool overlap(const BoxRec *a, const BoxRec *b)
772.21036 - 	return true;
772.21037 - }
772.21038 - 
772.21039 -+static void defer_event(struct sna *sna, struct drm_event *base)
772.21040 -+{
772.21041 -+	if (sna->mode.shadow_nevent == sna->mode.shadow_size) {
772.21042 -+		int size = sna->mode.shadow_size * 2;
772.21043 -+		void *ptr;
772.21044 -+
772.21045 -+		ptr = realloc(sna->mode.shadow_events,
772.21046 -+			      sizeof(struct drm_event_vblank)*size);
772.21047 -+		if (!ptr)
772.21048 -+			return;
772.21049 -+
772.21050 -+		sna->mode.shadow_events = ptr;
772.21051 -+		sna->mode.shadow_size = size;
772.21052 -+	}
772.21053 -+
772.21054 -+	memcpy(&sna->mode.shadow_events[sna->mode.shadow_nevent++],
772.21055 -+	       base, sizeof(struct drm_event_vblank));
772.21056 -+	DBG(("%s: deferring event count=%d\n",
772.21057 -+	     __func__, sna->mode.shadow_nevent));
772.21058 -+}
772.21059 -+
772.21060 -+static void flush_events(struct sna *sna)
772.21061 -+{
772.21062 -+	int n;
772.21063 -+
772.21064 -+	if (!sna->mode.shadow_nevent)
772.21065 -+		return;
772.21066 -+
772.21067 -+	DBG(("%s: flushing %d events=%d\n", __func__, sna->mode.shadow_nevent));
772.21068 -+
772.21069 -+	for (n = 0; n < sna->mode.shadow_nevent; n++) {
772.21070 -+		struct drm_event_vblank *vb = &sna->mode.shadow_events[n];
772.21071 -+
772.21072 -+		if ((uintptr_t)(vb->user_data) & 2)
772.21073 -+			sna_present_vblank_handler(vb);
772.21074 -+		else
772.21075 -+			sna_dri2_vblank_handler(vb);
772.21076 -+	}
772.21077 -+
772.21078 -+	sna->mode.shadow_nevent = 0;
772.21079 -+}
772.21080 -+
772.21081 -+
772.21082 - static bool wait_for_shadow(struct sna *sna,
772.21083 - 			    struct sna_pixmap *priv,
772.21084 - 			    unsigned flags)
772.21085 - {
772.21086 - 	PixmapPtr pixmap = priv->pixmap;
772.21087 --	DamagePtr damage;
772.21088 - 	struct kgem_bo *bo, *tmp;
772.21089 - 	int flip_active;
772.21090 - 	bool ret = true;
772.21091 - 
772.21092 --	DBG(("%s: flags=%x, flips=%d, handle=%d, shadow=%d\n",
772.21093 --	     __FUNCTION__, flags, sna->mode.flip_active,
772.21094 -+	DBG(("%s: enabled? %d waiting? %d, flags=%x, flips=%d, pixmap=%ld [front?=%d], handle=%d, shadow=%d\n",
772.21095 -+	     __FUNCTION__, sna->mode.shadow_enabled, sna->mode.shadow_wait,
772.21096 -+	     flags, sna->mode.flip_active,
772.21097 -+	     pixmap->drawable.serialNumber, pixmap == sna->front,
772.21098 - 	     priv->gpu_bo->handle, sna->mode.shadow->handle));
772.21099 - 
772.21100 - 	assert(priv->move_to_gpu_data == sna);
772.21101 - 	assert(sna->mode.shadow != priv->gpu_bo);
772.21102 - 
772.21103 --	if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_damage)
772.21104 -+	if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_enabled)
772.21105 - 		goto done;
772.21106 - 
772.21107 -+	assert(sna->mode.shadow_damage);
772.21108 -+	assert(!sna->mode.shadow_wait);
772.21109 -+
772.21110 - 	if ((flags & MOVE_WRITE) == 0) {
772.21111 - 		if ((flags & __MOVE_SCANOUT) == 0) {
772.21112 - 			struct sna_crtc *crtc;
772.21113 -@@ -1154,9 +1744,7 @@ static bool wait_for_shadow(struct sna *sna,
772.21114 - 	}
772.21115 - 
772.21116 - 	assert(sna->mode.shadow_active);
772.21117 --
772.21118 --	damage = sna->mode.shadow_damage;
772.21119 --	sna->mode.shadow_damage = NULL;
772.21120 -+	sna->mode.shadow_wait = true;
772.21121 - 
772.21122 - 	flip_active = sna->mode.flip_active;
772.21123 - 	if (flip_active) {
772.21124 -@@ -1208,6 +1796,8 @@ static bool wait_for_shadow(struct sna *sna,
772.21125 - 			bo = sna->mode.shadow;
772.21126 - 		}
772.21127 - 	}
772.21128 -+	assert(sna->mode.shadow_wait);
772.21129 -+	sna->mode.shadow_wait = false;
772.21130 - 
772.21131 - 	if (bo->refcnt > 1) {
772.21132 - 		bo = kgem_create_2d(&sna->kgem,
772.21133 -@@ -1230,8 +1820,6 @@ static bool wait_for_shadow(struct sna *sna,
772.21134 - 			bo = sna->mode.shadow;
772.21135 - 	}
772.21136 - 
772.21137 --	sna->mode.shadow_damage = damage;
772.21138 --
772.21139 - 	RegionSubtract(&sna->mode.shadow_region,
772.21140 - 		       &sna->mode.shadow_region,
772.21141 - 		       &sna->mode.shadow_cancel);
772.21142 -@@ -1269,6 +1857,7 @@ static bool wait_for_shadow(struct sna *sna,
772.21143 - 			RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, &region);
772.21144 - 		}
772.21145 - 
772.21146 -+		crtc->client_bo->active_scanout--;
772.21147 - 		kgem_bo_destroy(&sna->kgem, crtc->client_bo);
772.21148 - 		crtc->client_bo = NULL;
772.21149 - 		list_del(&crtc->shadow_link);
772.21150 -@@ -1281,12 +1870,13 @@ static bool wait_for_shadow(struct sna *sna,
772.21151 - 		     sna->mode.shadow_region.extents.y1,
772.21152 - 		     sna->mode.shadow_region.extents.x2,
772.21153 - 		     sna->mode.shadow_region.extents.y2));
772.21154 --		ret = sna->render.copy_boxes(sna, GXcopy,
772.21155 --					     &pixmap->drawable, priv->gpu_bo, 0, 0,
772.21156 --					     &pixmap->drawable, bo, 0, 0,
772.21157 --					     region_rects(&sna->mode.shadow_region),
772.21158 --					     region_num_rects(&sna->mode.shadow_region),
772.21159 --					     0);
772.21160 -+		if (!sna->render.copy_boxes(sna, GXcopy,
772.21161 -+					    &pixmap->drawable, priv->gpu_bo, 0, 0,
772.21162 -+					    &pixmap->drawable, bo, 0, 0,
772.21163 -+					    region_rects(&sna->mode.shadow_region),
772.21164 -+					    region_num_rects(&sna->mode.shadow_region),
772.21165 -+					    0))
772.21166 -+			ERR(("%s: copy failed\n", __FUNCTION__));
772.21167 - 	}
772.21168 - 
772.21169 - 	if (priv->cow)
772.21170 -@@ -1295,11 +1885,13 @@ static bool wait_for_shadow(struct sna *sna,
772.21171 - 	sna_pixmap_unmap(pixmap, priv);
772.21172 - 
772.21173 - 	DBG(("%s: setting front pixmap to handle=%d\n", __FUNCTION__, bo->handle));
772.21174 -+	sna->mode.shadow->active_scanout--;
772.21175 - 	tmp = priv->gpu_bo;
772.21176 - 	priv->gpu_bo = bo;
772.21177 - 	if (bo != sna->mode.shadow)
772.21178 - 		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
772.21179 - 	sna->mode.shadow = tmp;
772.21180 -+	sna->mode.shadow->active_scanout++;
772.21181 - 
772.21182 - 	sna_dri2_pixmap_update_bo(sna, pixmap, bo);
772.21183 - 
772.21184 -@@ -1311,6 +1903,9 @@ done:
772.21185 - 	priv->move_to_gpu_data = NULL;
772.21186 - 	priv->move_to_gpu = NULL;
772.21187 - 
772.21188 -+	assert(!sna->mode.shadow_wait);
772.21189 -+	flush_events(sna);
772.21190 -+
772.21191 - 	return ret;
772.21192 - }
772.21193 - 
772.21194 -@@ -1358,22 +1953,43 @@ bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
772.21195 - 	return RegionNil(&sna->mode.shadow_region);
772.21196 - }
772.21197 - 
772.21198 -+static void sna_mode_damage(DamagePtr damage, RegionPtr region, void *closure)
772.21199 -+{
772.21200 -+	struct sna *sna = closure;
772.21201 -+
772.21202 -+	if (sna->mode.rr_active)
772.21203 -+		return;
772.21204 -+
772.21205 -+	/* Throw away the rectangles if the region grows too big */
772.21206 -+	region = DamageRegion(damage);
772.21207 -+	if (region->data) {
772.21208 -+		RegionRec dup;
772.21209 -+
772.21210 -+		dup = *region;
772.21211 -+		RegionUninit(&dup);
772.21212 -+
772.21213 -+		region->data = NULL;
772.21214 -+	}
772.21215 -+}
772.21216 -+
772.21217 - static bool sna_mode_enable_shadow(struct sna *sna)
772.21218 - {
772.21219 --	ScreenPtr screen = sna->scrn->pScreen;
772.21220 -+	ScreenPtr screen = to_screen_from_sna(sna);
772.21221 - 
772.21222 - 	DBG(("%s\n", __FUNCTION__));
772.21223 - 	assert(sna->mode.shadow == NULL);
772.21224 - 	assert(sna->mode.shadow_damage == NULL);
772.21225 - 	assert(sna->mode.shadow_active == 0);
772.21226 -+	assert(!sna->mode.shadow_enabled);
772.21227 - 
772.21228 --	sna->mode.shadow_damage = DamageCreate(NULL, NULL,
772.21229 --					       DamageReportNone, TRUE,
772.21230 --					       screen, screen);
772.21231 -+	sna->mode.shadow_damage = DamageCreate(sna_mode_damage, NULL,
772.21232 -+					       DamageReportRawRegion,
772.21233 -+					       TRUE, screen, sna);
772.21234 - 	if (!sna->mode.shadow_damage)
772.21235 - 		return false;
772.21236 - 
772.21237 - 	DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
772.21238 -+	sna->mode.shadow_enabled = true;
772.21239 - 	return true;
772.21240 - }
772.21241 - 
772.21242 -@@ -1381,8 +1997,10 @@ static void sna_mode_disable_shadow(struct sna *sna)
772.21243 - {
772.21244 - 	struct sna_pixmap *priv;
772.21245 - 
772.21246 --	if (!sna->mode.shadow_damage)
772.21247 -+	if (!sna->mode.shadow_damage) {
772.21248 -+		assert(!sna->mode.shadow_enabled);
772.21249 - 		return;
772.21250 -+	}
772.21251 - 
772.21252 - 	DBG(("%s\n", __FUNCTION__));
772.21253 - 
772.21254 -@@ -1393,8 +2011,10 @@ static void sna_mode_disable_shadow(struct sna *sna)
772.21255 - 	DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
772.21256 - 	DamageDestroy(sna->mode.shadow_damage);
772.21257 - 	sna->mode.shadow_damage = NULL;
772.21258 -+	sna->mode.shadow_enabled = false;
772.21259 - 
772.21260 - 	if (sna->mode.shadow) {
772.21261 -+		sna->mode.shadow->active_scanout--;
772.21262 - 		kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
772.21263 - 		sna->mode.shadow = NULL;
772.21264 - 	}
772.21265 -@@ -1413,7 +2033,7 @@ static void sna_crtc_slave_damage(DamagePtr damage, RegionPtr region, void *clos
772.21266 - 	     __FUNCTION__,
772.21267 - 	     region->extents.x1, region->extents.y1, region->extents.x2, region->extents.y2,
772.21268 - 	     region_num_rects(region),
772.21269 --	     crtc->pipe, crtc->base->x, crtc->base->y));
772.21270 -+	     __sna_crtc_pipe(crtc), crtc->base->x, crtc->base->y));
772.21271 - 
772.21272 - 	assert(crtc->slave_damage == damage);
772.21273 - 	assert(sna->mode.shadow_damage);
772.21274 -@@ -1431,7 +2051,7 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
772.21275 - 		return true;
772.21276 - 	}
772.21277 - 
772.21278 --	DBG(("%s: enabling for crtc %d\n", __FUNCTION__, crtc->id));
772.21279 -+	DBG(("%s: enabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
772.21280 - 
772.21281 - 	if (!sna->mode.shadow_active) {
772.21282 - 		if (!sna_mode_enable_shadow(sna))
772.21283 -@@ -1443,9 +2063,12 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
772.21284 - 	if (crtc->slave_pixmap) {
772.21285 - 		assert(crtc->slave_damage == NULL);
772.21286 - 
772.21287 -+		DBG(("%s: enabling PRIME slave tracking on CRTC %d [pipe=%d], pixmap=%ld\n",
772.21288 -+		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->slave_pixmap->drawable.serialNumber));
772.21289 - 		crtc->slave_damage = DamageCreate(sna_crtc_slave_damage, NULL,
772.21290 - 						  DamageReportRawRegion, TRUE,
772.21291 --						  sna->scrn->pScreen, crtc);
772.21292 -+						  to_screen_from_sna(sna),
772.21293 -+						  crtc);
772.21294 - 		if (crtc->slave_damage == NULL) {
772.21295 - 			if (!--sna->mode.shadow_active)
772.21296 - 				sna_mode_disable_shadow(sna);
772.21297 -@@ -1465,6 +2088,9 @@ static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
772.21298 - 	if (crtc->client_bo == NULL)
772.21299 - 		return;
772.21300 - 
772.21301 -+	assert(crtc->client_bo->refcnt >= crtc->client_bo->active_scanout);
772.21302 -+	crtc->client_bo->active_scanout--;
772.21303 -+
772.21304 - 	if (!crtc->transform) {
772.21305 - 		DrawableRec tmp;
772.21306 - 
772.21307 -@@ -1489,7 +2115,7 @@ static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
772.21308 - 	if (!crtc->shadow)
772.21309 - 		return;
772.21310 - 
772.21311 --	DBG(("%s: disabling for crtc %d\n", __FUNCTION__, crtc->id));
772.21312 -+	DBG(("%s: disabling for crtc %d\n", __FUNCTION__, __sna_crtc_id(crtc)));
772.21313 - 	assert(sna->mode.shadow_active > 0);
772.21314 - 
772.21315 - 	if (crtc->slave_damage) {
772.21316 -@@ -1517,14 +2143,24 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
772.21317 - 	sna_crtc_disable_shadow(sna, sna_crtc);
772.21318 - 
772.21319 - 	if (sna_crtc->bo) {
772.21320 -+		DBG(("%s: releasing handle=%d from scanout, active=%d\n",
772.21321 -+		     __FUNCTION__,sna_crtc->bo->handle, sna_crtc->bo->active_scanout-1));
772.21322 -+		assert(sna_crtc->flags & CRTC_ON);
772.21323 - 		assert(sna_crtc->bo->active_scanout);
772.21324 - 		assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
772.21325 - 		sna_crtc->bo->active_scanout--;
772.21326 - 		kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
772.21327 - 		sna_crtc->bo = NULL;
772.21328 -+		sna_crtc->flags &= ~CRTC_ON;
772.21329 - 
772.21330 --		assert(sna->mode.front_active);
772.21331 --		sna->mode.front_active--;
772.21332 -+		if (sna->mode.hidden) {
772.21333 -+			sna->mode.hidden--;
772.21334 -+			assert(sna->mode.hidden);
772.21335 -+			assert(sna->mode.front_active == 0);
772.21336 -+		} else {
772.21337 -+			assert(sna->mode.front_active);
772.21338 -+			sna->mode.front_active--;
772.21339 -+		}
772.21340 - 		sna->mode.dirty = true;
772.21341 - 	}
772.21342 - 
772.21343 -@@ -1532,13 +2168,19 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
772.21344 - 		kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
772.21345 - 		sna_crtc->shadow_bo = NULL;
772.21346 - 	}
772.21347 --	sna_crtc->transform = false;
772.21348 -+	if (sna_crtc->transform) {
772.21349 -+		assert(sna->mode.rr_active);
772.21350 -+		sna->mode.rr_active--;
772.21351 -+		sna_crtc->transform = false;
772.21352 -+	}
772.21353 - 
772.21354 -+	sna_crtc->cursor_transform = false;
772.21355 -+	sna_crtc->hwcursor = true;
772.21356 - 	assert(!sna_crtc->shadow);
772.21357 - }
772.21358 - 
772.21359 - static void
772.21360 --sna_crtc_disable(xf86CrtcPtr crtc)
772.21361 -+sna_crtc_disable(xf86CrtcPtr crtc, bool force)
772.21362 - {
772.21363 - 	struct sna *sna = to_sna(crtc->scrn);
772.21364 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.21365 -@@ -1547,14 +2189,16 @@ sna_crtc_disable(xf86CrtcPtr crtc)
772.21366 - 	if (sna_crtc == NULL)
772.21367 - 		return;
772.21368 - 
772.21369 --	DBG(("%s: disabling crtc [%d, pipe=%d]\n", __FUNCTION__,
772.21370 --	     sna_crtc->id, sna_crtc->pipe));
772.21371 -+	if (!force && sna_crtc->bo == NULL)
772.21372 -+		return;
772.21373 -+
772.21374 -+	DBG(("%s: disabling crtc [%d, pipe=%d], force?=%d\n", __FUNCTION__,
772.21375 -+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), force));
772.21376 - 
772.21377 - 	sna_crtc_force_outputs_off(crtc);
772.21378 --	assert(sna_crtc->dpms_mode == DPMSModeOff);
772.21379 - 
772.21380 - 	memset(&arg, 0, sizeof(arg));
772.21381 --	arg.crtc_id = sna_crtc->id;
772.21382 -+	arg.crtc_id = __sna_crtc_id(sna_crtc);
772.21383 - 	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg);
772.21384 - 
772.21385 - 	__sna_crtc_disable(sna, sna_crtc);
772.21386 -@@ -1574,19 +2218,19 @@ static void update_flush_interval(struct sna *sna)
772.21387 - 
772.21388 - 		if (!crtc->enabled) {
772.21389 - 			DBG(("%s: CRTC:%d (pipe %d) disabled\n",
772.21390 --			     __FUNCTION__,i, to_sna_crtc(crtc)->pipe));
772.21391 -+			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
772.21392 - 			assert(to_sna_crtc(crtc)->bo == NULL);
772.21393 - 			continue;
772.21394 - 		}
772.21395 - 
772.21396 --		if (to_sna_crtc(crtc)->dpms_mode != DPMSModeOn) {
772.21397 -+		if (to_sna_crtc(crtc)->bo == NULL) {
772.21398 - 			DBG(("%s: CRTC:%d (pipe %d) turned off\n",
772.21399 --			     __FUNCTION__,i, to_sna_crtc(crtc)->pipe));
772.21400 -+			     __FUNCTION__,i, sna_crtc_pipe(crtc)));
772.21401 - 			continue;
772.21402 - 		}
772.21403 - 
772.21404 - 		DBG(("%s: CRTC:%d (pipe %d) vrefresh=%f\n",
772.21405 --		     __FUNCTION__, i, to_sna_crtc(crtc)->pipe,
772.21406 -+		     __FUNCTION__, i, sna_crtc_pipe(crtc),
772.21407 - 		     xf86ModeVRefresh(&crtc->mode)));
772.21408 - 		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(&crtc->mode));
772.21409 - 	}
772.21410 -@@ -1642,7 +2286,7 @@ void sna_copy_fbcon(struct sna *sna)
772.21411 - 	int dx, dy;
772.21412 - 	int i;
772.21413 - 
772.21414 --	if (wedged(sna))
772.21415 -+	if (wedged(sna) || isGPU(sna->scrn))
772.21416 - 		return;
772.21417 - 
772.21418 - 	DBG(("%s\n", __FUNCTION__));
772.21419 -@@ -1662,7 +2306,7 @@ void sna_copy_fbcon(struct sna *sna)
772.21420 - 		assert(crtc != NULL);
772.21421 - 
772.21422 - 		VG_CLEAR(mode);
772.21423 --		mode.crtc_id = crtc->id;
772.21424 -+		mode.crtc_id = __sna_crtc_id(crtc);
772.21425 - 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
772.21426 - 			continue;
772.21427 - 		if (!mode.fb_id)
772.21428 -@@ -1726,7 +2370,7 @@ void sna_copy_fbcon(struct sna *sna)
772.21429 - 	kgem_bo_destroy(&sna->kgem, bo);
772.21430 - 
772.21431 - #if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
772.21432 --	sna->scrn->pScreen->canDoBGNoneRoot = ok;
772.21433 -+	to_screen_from_sna(sna)->canDoBGNoneRoot = ok;
772.21434 - #endif
772.21435 - }
772.21436 - 
772.21437 -@@ -1736,7 +2380,6 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
772.21438 - 	PictTransform crtc_to_fb;
772.21439 - 	struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
772.21440 - 	unsigned pitch_limit;
772.21441 --	struct sna_pixmap *priv;
772.21442 - 	BoxRec b;
772.21443 - 
772.21444 - 	assert(sna->scrn->virtualX && sna->scrn->virtualY);
772.21445 -@@ -1765,27 +2408,31 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
772.21446 - 		return true;
772.21447 - 	}
772.21448 - 
772.21449 --	priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
772.21450 --	if (priv == NULL)
772.21451 --		return true; /* maybe we can create a bo for the scanout? */
772.21452 --
772.21453 --	if (sna->kgem.gen == 071)
772.21454 --		pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
772.21455 --	else if ((sna->kgem.gen >> 3) > 4)
772.21456 --		pitch_limit = 32 * 1024;
772.21457 --	else if ((sna->kgem.gen >> 3) == 4)
772.21458 --		pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
772.21459 --	else if ((sna->kgem.gen >> 3) == 3)
772.21460 --		pitch_limit = priv->gpu_bo->tiling ? 8 * 1024 : 16 * 1024;
772.21461 --	else
772.21462 --		pitch_limit = 8 * 1024;
772.21463 --	DBG(("%s: gpu bo handle=%d tiling=%d pitch=%d, limit=%d\n", __FUNCTION__, priv->gpu_bo->handle, priv->gpu_bo->tiling, priv->gpu_bo->pitch, pitch_limit));
772.21464 --	if (priv->gpu_bo->pitch > pitch_limit)
772.21465 --		return true;
772.21466 -+	if (!isGPU(sna->scrn)) {
772.21467 -+		struct sna_pixmap *priv;
772.21468 - 
772.21469 --	if (priv->gpu_bo->tiling && sna->flags & SNA_LINEAR_FB) {
772.21470 --		DBG(("%s: gpu bo is tiled, need linear, forcing shadow\n", __FUNCTION__));
772.21471 --		return true;
772.21472 -+		priv = sna_pixmap_force_to_gpu(sna->front, MOVE_READ | __MOVE_SCANOUT);
772.21473 -+		if (priv == NULL)
772.21474 -+			return true; /* maybe we can create a bo for the scanout? */
772.21475 -+
772.21476 -+		if (sna->kgem.gen == 071)
772.21477 -+			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
772.21478 -+		else if ((sna->kgem.gen >> 3) > 4)
772.21479 -+			pitch_limit = 32 * 1024;
772.21480 -+		else if ((sna->kgem.gen >> 3) == 4)
772.21481 -+			pitch_limit = priv->gpu_bo->tiling ? 16 * 1024 : 32 * 1024;
772.21482 -+		else if ((sna->kgem.gen >> 3) == 3)
772.21483 -+			pitch_limit = priv->gpu_bo->tiling ? 8 * 1024 : 16 * 1024;
772.21484 -+		else
772.21485 -+			pitch_limit = 8 * 1024;
772.21486 -+		DBG(("%s: gpu bo handle=%d tiling=%d pitch=%d, limit=%d\n", __FUNCTION__, priv->gpu_bo->handle, priv->gpu_bo->tiling, priv->gpu_bo->pitch, pitch_limit));
772.21487 -+		if (priv->gpu_bo->pitch > pitch_limit)
772.21488 -+			return true;
772.21489 -+
772.21490 -+		if (priv->gpu_bo->tiling && sna->flags & SNA_LINEAR_FB) {
772.21491 -+			DBG(("%s: gpu bo is tiled, need linear, forcing shadow\n", __FUNCTION__));
772.21492 -+			return true;
772.21493 -+		}
772.21494 - 	}
772.21495 - 
772.21496 - 	transform = NULL;
772.21497 -@@ -1800,9 +2447,9 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
772.21498 - 		bool needs_transform = true;
772.21499 - 		unsigned rotation = rotation_reduce(&to_sna_crtc(crtc)->primary, crtc->rotation);
772.21500 - 		DBG(("%s: natively supported rotation? rotation=%x & supported=%x == %d\n",
772.21501 --		     __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->primary.rotation.supported,
772.21502 --		     !!(crtc->rotation & to_sna_crtc(crtc)->primary.rotation.supported)));
772.21503 --		if (to_sna_crtc(crtc)->primary.rotation.supported & rotation)
772.21504 -+		     __FUNCTION__, rotation, to_sna_crtc(crtc)->primary.rotation.supported,
772.21505 -+		     rotation == (rotation & to_sna_crtc(crtc)->primary.rotation.supported)));
772.21506 -+		if ((to_sna_crtc(crtc)->primary.rotation.supported & rotation) == rotation)
772.21507 - 			needs_transform = RRTransformCompute(crtc->x, crtc->y,
772.21508 - 							     crtc->mode.HDisplay, crtc->mode.VDisplay,
772.21509 - 							     RR_Rotate_0, transform,
772.21510 -@@ -1839,6 +2486,7 @@ static void set_shadow(struct sna *sna, RegionPtr region)
772.21511 - 
772.21512 - 	assert(priv->gpu_bo);
772.21513 - 	assert(sna->mode.shadow);
772.21514 -+	assert(sna->mode.shadow->active_scanout);
772.21515 - 
772.21516 - 	DBG(("%s: waiting for region %dx[(%d, %d), (%d, %d)], front handle=%d, shadow handle=%d\n",
772.21517 - 	     __FUNCTION__,
772.21518 -@@ -1912,6 +2560,28 @@ get_scanout_bo(struct sna *sna, PixmapPtr pixmap)
772.21519 - 	return priv->gpu_bo;
772.21520 - }
772.21521 - 
772.21522 -+static void shadow_clear(struct sna *sna,
772.21523 -+			 PixmapPtr front, struct kgem_bo *bo,
772.21524 -+			 xf86CrtcPtr crtc)
772.21525 -+{
772.21526 -+	bool ok = false;
772.21527 -+	if (!wedged(sna))
772.21528 -+		ok = sna->render.fill_one(sna, front, bo, 0,
772.21529 -+					  0, 0, crtc->mode.HDisplay, crtc->mode.VDisplay,
772.21530 -+					  GXclear);
772.21531 -+	if (!ok) {
772.21532 -+		void *ptr = kgem_bo_map__gtt(&sna->kgem, bo);
772.21533 -+		if (ptr)
772.21534 -+			memset(ptr, 0, bo->pitch * crtc->mode.HDisplay);
772.21535 -+	}
772.21536 -+	sna->mode.shadow_dirty = true;
772.21537 -+}
772.21538 -+
772.21539 -+static bool rr_active(xf86CrtcPtr crtc)
772.21540 -+{
772.21541 -+	return crtc->transformPresent || crtc->rotation != RR_Rotate_0;
772.21542 -+}
772.21543 -+
772.21544 - static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
772.21545 - {
772.21546 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.21547 -@@ -1919,10 +2589,15 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
772.21548 - 	struct sna *sna = to_sna(scrn);
772.21549 - 	struct kgem_bo *bo;
772.21550 - 
772.21551 --	sna_crtc->transform = false;
772.21552 -+	if (sna_crtc->transform) {
772.21553 -+		assert(sna->mode.rr_active);
772.21554 -+		sna_crtc->transform = false;
772.21555 -+		sna->mode.rr_active--;
772.21556 -+	}
772.21557 - 	sna_crtc->rotation = RR_Rotate_0;
772.21558 - 
772.21559 - 	if (use_shadow(sna, crtc)) {
772.21560 -+		PixmapPtr front;
772.21561 - 		unsigned long tiled_limit;
772.21562 - 		int tiling;
772.21563 - 
772.21564 -@@ -1949,6 +2624,10 @@ force_shadow:
772.21565 - 		}
772.21566 - 
772.21567 - 		tiling = I915_TILING_X;
772.21568 -+		if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270) &&
772.21569 -+		    sna->kgem.can_scanout_y)
772.21570 -+			tiling = I915_TILING_Y;
772.21571 -+
772.21572 - 		if (sna->kgem.gen == 071)
772.21573 - 			tiled_limit = 16 * 1024 * 8;
772.21574 - 		else if ((sna->kgem.gen >> 3) > 4)
772.21575 -@@ -1977,8 +2656,8 @@ force_shadow:
772.21576 - 			return NULL;
772.21577 - 		}
772.21578 - 
772.21579 --		if (__sna_pixmap_get_bo(sna->front) && !crtc->transformPresent) {
772.21580 --			DrawableRec tmp;
772.21581 -+		front = sna_crtc->slave_pixmap ?: sna->front;
772.21582 -+		if (__sna_pixmap_get_bo(front) && !rr_active(crtc)) {
772.21583 - 			BoxRec b;
772.21584 - 
772.21585 - 			b.x1 = crtc->x;
772.21586 -@@ -1986,28 +2665,48 @@ force_shadow:
772.21587 - 			b.x2 = crtc->x + crtc->mode.HDisplay;
772.21588 - 			b.y2 = crtc->y + crtc->mode.VDisplay;
772.21589 - 
772.21590 --			DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d), handle=%d\n",
772.21591 --			     __FUNCTION__,
772.21592 --			     b.x1, b.y1,
772.21593 --			     b.x2, b.y2,
772.21594 --			     bo->handle));
772.21595 --
772.21596 --			tmp.width = crtc->mode.HDisplay;
772.21597 --			tmp.height = crtc->mode.VDisplay;
772.21598 --			tmp.depth = sna->front->drawable.depth;
772.21599 --			tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
772.21600 --
772.21601 --			(void)sna->render.copy_boxes(sna, GXcopy,
772.21602 --						     &sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
772.21603 --						     &tmp, bo, -b.x1, -b.y1,
772.21604 --						     &b, 1, 0);
772.21605 --		}
772.21606 -+			if (b.x1 < 0)
772.21607 -+				b.x1 = 0;
772.21608 -+			if (b.y1 < 0)
772.21609 -+				b.y1 = 0;
772.21610 -+			if (b.x2 > scrn->virtualX)
772.21611 -+				b.x2 = scrn->virtualX;
772.21612 -+			if (b.y2 > scrn->virtualY)
772.21613 -+				b.y2 = scrn->virtualY;
772.21614 -+			if (b.x2 - b.x1 < crtc->mode.HDisplay ||
772.21615 -+			    b.y2 - b.y1 < crtc->mode.VDisplay)
772.21616 -+				shadow_clear(sna, front, bo, crtc);
772.21617 -+
772.21618 -+			if (b.y2 > b.y1 && b.x2 > b.x1) {
772.21619 -+				DrawableRec tmp;
772.21620 -+
772.21621 -+				DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d) [fb=%dx%d], handle=%d\n",
772.21622 -+				     __FUNCTION__,
772.21623 -+				     b.x1, b.y1,
772.21624 -+				     b.x2-b.x1, b.y2-b.y1,
772.21625 -+				     scrn->virtualX, scrn->virtualY,
772.21626 -+				     bo->handle));
772.21627 -+
772.21628 -+				tmp.width = crtc->mode.HDisplay;
772.21629 -+				tmp.height = crtc->mode.VDisplay;
772.21630 -+				tmp.depth = front->drawable.depth;
772.21631 -+				tmp.bitsPerPixel = front->drawable.bitsPerPixel;
772.21632 -+
772.21633 -+				if (!sna->render.copy_boxes(sna, GXcopy,
772.21634 -+							     &front->drawable, __sna_pixmap_get_bo(front), 0, 0,
772.21635 -+							     &tmp, bo, -crtc->x, -crtc->y,
772.21636 -+							     &b, 1, COPY_LAST))
772.21637 -+					shadow_clear(sna, front, bo, crtc);
772.21638 -+			}
772.21639 -+		} else
772.21640 -+			shadow_clear(sna, front, bo, crtc);
772.21641 - 
772.21642 - 		sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
772.21643 - 		sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
772.21644 - 		sna_crtc->shadow_bo = bo;
772.21645 - out_shadow:
772.21646 - 		sna_crtc->transform = true;
772.21647 -+		sna->mode.rr_active++;
772.21648 - 		return kgem_bo_reference(bo);
772.21649 - 	} else {
772.21650 - 		if (sna_crtc->shadow_bo) {
772.21651 -@@ -2048,26 +2747,26 @@ out_shadow:
772.21652 - 		}
772.21653 - 
772.21654 - 		if (sna->flags & SNA_TEAR_FREE) {
772.21655 -+			RegionRec region;
772.21656 -+
772.21657 - 			assert(sna_crtc->slave_pixmap == NULL);
772.21658 - 
772.21659 - 			DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
772.21660 -+			region.extents.x1 = 0;
772.21661 -+			region.extents.y1 = 0;
772.21662 -+			region.extents.x2 = sna->scrn->virtualX;
772.21663 -+			region.extents.y2 = sna->scrn->virtualY;
772.21664 -+			region.data = NULL;
772.21665 -+
772.21666 - 			if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
772.21667 - 				DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
772.21668 - 				return NULL;
772.21669 - 			}
772.21670 - 
772.21671 --			if (sna->mode.shadow == NULL && !wedged(sna)) {
772.21672 --				RegionRec region;
772.21673 -+			if (sna->mode.shadow == NULL) {
772.21674 - 				struct kgem_bo *shadow;
772.21675 - 
772.21676 - 				DBG(("%s: creating TearFree shadow bo\n", __FUNCTION__));
772.21677 --
772.21678 --				region.extents.x1 = 0;
772.21679 --				region.extents.y1 = 0;
772.21680 --				region.extents.x2 = sna->scrn->virtualX;
772.21681 --				region.extents.y2 = sna->scrn->virtualY;
772.21682 --				region.data = NULL;
772.21683 --
772.21684 - 				shadow = kgem_create_2d(&sna->kgem,
772.21685 - 							region.extents.x2,
772.21686 - 							region.extents.y2,
772.21687 -@@ -2093,9 +2792,12 @@ out_shadow:
772.21688 - 					goto force_shadow;
772.21689 - 				}
772.21690 - 
772.21691 -+				assert(__sna_pixmap_get_bo(sna->front) == NULL ||
772.21692 -+				       __sna_pixmap_get_bo(sna->front)->pitch == shadow->pitch);
772.21693 - 				sna->mode.shadow = shadow;
772.21694 --				set_shadow(sna, &region);
772.21695 -+				sna->mode.shadow->active_scanout++;
772.21696 - 			}
772.21697 -+			set_shadow(sna, &region);
772.21698 - 
772.21699 - 			sna_crtc_disable_override(sna, sna_crtc);
772.21700 - 		} else
772.21701 -@@ -2107,6 +2809,37 @@ out_shadow:
772.21702 - 	}
772.21703 - }
772.21704 - 
772.21705 -+#define SCALING_EPSILON (1./256)
772.21706 -+
772.21707 -+static bool
772.21708 -+is_affine(const struct pixman_f_transform *t)
772.21709 -+{
772.21710 -+	return (fabs(t->m[2][0]) < SCALING_EPSILON &&
772.21711 -+		fabs(t->m[2][1]) < SCALING_EPSILON);
772.21712 -+}
772.21713 -+
772.21714 -+static double determinant(const struct pixman_f_transform *t)
772.21715 -+{
772.21716 -+	return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1];
772.21717 -+}
772.21718 -+
772.21719 -+static bool
772.21720 -+affine_is_pixel_exact(const struct pixman_f_transform *t)
772.21721 -+{
772.21722 -+	double det = t->m[2][2] * determinant(t);
772.21723 -+	if (fabs (det * det - 1.0) < SCALING_EPSILON) {
772.21724 -+		if (fabs(t->m[0][1]) < SCALING_EPSILON &&
772.21725 -+		    fabs(t->m[1][0]) < SCALING_EPSILON)
772.21726 -+			return true;
772.21727 -+
772.21728 -+		if (fabs(t->m[0][0]) < SCALING_EPSILON &&
772.21729 -+		    fabs(t->m[1][1]) < SCALING_EPSILON)
772.21730 -+			return true;
772.21731 -+	}
772.21732 -+
772.21733 -+	return false;
772.21734 -+}
772.21735 -+
772.21736 - static void sna_crtc_randr(xf86CrtcPtr crtc)
772.21737 - {
772.21738 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.21739 -@@ -2152,6 +2885,25 @@ static void sna_crtc_randr(xf86CrtcPtr crtc)
772.21740 - 	} else
772.21741 - 		crtc->transform_in_use = sna_crtc->rotation != RR_Rotate_0;
772.21742 - 
772.21743 -+	/* Recompute the cursor after a potential change in transform */
772.21744 -+	if (sna_crtc->cursor) {
772.21745 -+		assert(sna_crtc->cursor->ref > 0);
772.21746 -+		sna_crtc->cursor->ref--;
772.21747 -+		sna_crtc->cursor = NULL;
772.21748 -+	}
772.21749 -+
772.21750 -+	if (needs_transform) {
772.21751 -+		sna_crtc->hwcursor = is_affine(&f_fb_to_crtc);
772.21752 -+		sna_crtc->cursor_transform =
772.21753 -+			sna_crtc->hwcursor &&
772.21754 -+			!affine_is_pixel_exact(&f_fb_to_crtc);
772.21755 -+	} else {
772.21756 -+		sna_crtc->hwcursor = true;
772.21757 -+		sna_crtc->cursor_transform = false;
772.21758 -+	}
772.21759 -+	DBG(("%s: hwcursor?=%d, cursor_transform?=%d\n",
772.21760 -+	     __FUNCTION__, sna_crtc->hwcursor, sna_crtc->cursor_transform));
772.21761 -+
772.21762 - 	crtc->crtc_to_framebuffer = crtc_to_fb;
772.21763 - 	crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
772.21764 - 	crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
772.21765 -@@ -2184,7 +2936,7 @@ static void sna_crtc_randr(xf86CrtcPtr crtc)
772.21766 - static void
772.21767 - sna_crtc_damage(xf86CrtcPtr crtc)
772.21768 - {
772.21769 --	ScreenPtr screen = crtc->scrn->pScreen;
772.21770 -+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
772.21771 - 	struct sna *sna = to_sna(crtc->scrn);
772.21772 - 	RegionRec region, *damage;
772.21773 - 
772.21774 -@@ -2200,15 +2952,21 @@ sna_crtc_damage(xf86CrtcPtr crtc)
772.21775 - 	if (region.extents.y2 > screen->height)
772.21776 - 		region.extents.y2 = screen->height;
772.21777 - 
772.21778 -+	if (region.extents.x2 <= region.extents.x1 ||
772.21779 -+	    region.extents.y2 <= region.extents.y1) {
772.21780 -+		DBG(("%s: crtc not damaged, all-clipped\n", __FUNCTION__));
772.21781 -+		return;
772.21782 -+	}
772.21783 -+
772.21784 - 	DBG(("%s: marking crtc %d as completely damaged (%d, %d), (%d, %d)\n",
772.21785 --	     __FUNCTION__, to_sna_crtc(crtc)->id,
772.21786 -+	     __FUNCTION__, sna_crtc_id(crtc),
772.21787 - 	     region.extents.x1, region.extents.y1,
772.21788 - 	     region.extents.x2, region.extents.y2));
772.21789 --	to_sna_crtc(crtc)->client_damage = region;
772.21790 - 
772.21791 - 	assert(sna->mode.shadow_damage && sna->mode.shadow_active);
772.21792 - 	damage = DamageRegion(sna->mode.shadow_damage);
772.21793 - 	RegionUnion(damage, damage, &region);
772.21794 -+	to_sna_crtc(crtc)->crtc_damage = region;
772.21795 - 
772.21796 - 	DBG(("%s: damage now %dx[(%d, %d), (%d, %d)]\n",
772.21797 - 	     __FUNCTION__,
772.21798 -@@ -2260,6 +3018,21 @@ static const char *reflection_to_str(Rotation rotation)
772.21799 - 	}
772.21800 - }
772.21801 - 
772.21802 -+static void reprobe_connectors(xf86CrtcPtr crtc)
772.21803 -+{
772.21804 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
772.21805 -+	struct sna *sna = to_sna(crtc->scrn);
772.21806 -+	int i;
772.21807 -+
772.21808 -+	for (i = 0; i < sna->mode.num_real_output; i++) {
772.21809 -+		xf86OutputPtr output = config->output[i];
772.21810 -+		if (output->crtc == crtc)
772.21811 -+			to_sna_output(output)->reprobe = true;
772.21812 -+	}
772.21813 -+
772.21814 -+	sna_mode_discover(sna, true);
772.21815 -+}
772.21816 -+
772.21817 - static Bool
772.21818 - __sna_crtc_set_mode(xf86CrtcPtr crtc)
772.21819 - {
772.21820 -@@ -2268,11 +3041,19 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
772.21821 - 	struct kgem_bo *saved_bo, *bo;
772.21822 - 	uint32_t saved_offset;
772.21823 - 	bool saved_transform;
772.21824 -+	bool saved_hwcursor;
772.21825 -+	bool saved_cursor_transform;
772.21826 -+	int ret;
772.21827 - 
772.21828 --	DBG(("%s\n", __FUNCTION__));
772.21829 -+	DBG(("%s: CRTC=%d, pipe=%d, hidden?=%d\n", __FUNCTION__,
772.21830 -+	     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), sna->mode.hidden));
772.21831 -+	if (sna->mode.hidden)
772.21832 -+		return TRUE;
772.21833 - 
772.21834 - 	saved_bo = sna_crtc->bo;
772.21835 - 	saved_transform = sna_crtc->transform;
772.21836 -+	saved_cursor_transform = sna_crtc->cursor_transform;
772.21837 -+	saved_hwcursor = sna_crtc->hwcursor;
772.21838 - 	saved_offset = sna_crtc->offset;
772.21839 - 
772.21840 - 	sna_crtc->fallback_shadow = false;
772.21841 -@@ -2285,26 +3066,31 @@ retry: /* Attach per-crtc pixmap or direct */
772.21842 - 	}
772.21843 - 
772.21844 - 	/* Prevent recursion when enabling outputs during execbuffer */
772.21845 --	if (bo->exec && RQ(bo->rq)->bo == NULL)
772.21846 -+	if (bo->exec && RQ(bo->rq)->bo == NULL) {
772.21847 - 		_kgem_submit(&sna->kgem);
772.21848 -+		__kgem_bo_clear_dirty(bo);
772.21849 -+	}
772.21850 - 
772.21851 - 	sna_crtc->bo = bo;
772.21852 --	if (!sna_crtc_apply(crtc)) {
772.21853 --		int err = errno;
772.21854 --
772.21855 -+	ret = sna_crtc_apply(crtc);
772.21856 -+	if (ret) {
772.21857 - 		kgem_bo_destroy(&sna->kgem, bo);
772.21858 - 
772.21859 --		if (!sna_crtc->shadow) {
772.21860 -+		if (!sna_crtc->fallback_shadow) {
772.21861 - 			sna_crtc->fallback_shadow = true;
772.21862 - 			goto retry;
772.21863 - 		}
772.21864 - 
772.21865 - 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
772.21866 --			   "failed to set mode: %s [%d]\n", strerror(err), err);
772.21867 -+			   "failed to set mode: %s [%d]\n", strerror(ret), ret);
772.21868 - 		goto error;
772.21869 - 	}
772.21870 - 
772.21871 -+	sna_crtc->flags |= CRTC_ON;
772.21872 - 	bo->active_scanout++;
772.21873 -+	DBG(("%s: marking handle=%d as active=%d (removing %d from scanout, active=%d)\n",
772.21874 -+	     __FUNCTION__, bo->handle, bo->active_scanout,
772.21875 -+	     saved_bo ? saved_bo->handle : 0, saved_bo ? saved_bo->active_scanout - 1: -1));
772.21876 - 	if (saved_bo) {
772.21877 - 		assert(saved_bo->active_scanout);
772.21878 - 		assert(saved_bo->refcnt >= saved_bo->active_scanout);
772.21879 -@@ -2315,17 +3101,34 @@ retry: /* Attach per-crtc pixmap or direct */
772.21880 - 	sna_crtc_randr(crtc);
772.21881 - 	if (sna_crtc->transform)
772.21882 - 		sna_crtc_damage(crtc);
772.21883 -+	if (sna_crtc->cursor &&  /* Reload cursor if RandR maybe changed */
772.21884 -+	    (!sna_crtc->hwcursor ||
772.21885 -+	     saved_cursor_transform || sna_crtc->cursor_transform ||
772.21886 -+	     sna_crtc->cursor->rotation != crtc->rotation))
772.21887 -+		sna_crtc_disable_cursor(sna, sna_crtc);
772.21888 -+
772.21889 -+	assert(!sna->mode.hidden);
772.21890 - 	sna->mode.front_active += saved_bo == NULL;
772.21891 - 	sna->mode.dirty = true;
772.21892 --	DBG(("%s: front_active=%d\n", __FUNCTION__, sna->mode.front_active));
772.21893 -+	DBG(("%s: handle=%d, scanout_active=%d, front_active=%d\n",
772.21894 -+	     __FUNCTION__, bo->handle, bo->active_scanout, sna->mode.front_active));
772.21895 - 
772.21896 - 	return TRUE;
772.21897 - 
772.21898 - error:
772.21899 - 	sna_crtc->offset = saved_offset;
772.21900 -+	if (sna_crtc->transform) {
772.21901 -+		assert(sna->mode.rr_active);
772.21902 -+		sna->mode.rr_active--;
772.21903 -+	}
772.21904 -+	if (saved_transform)
772.21905 -+		sna->mode.rr_active++;
772.21906 - 	sna_crtc->transform = saved_transform;
772.21907 -+	sna_crtc->cursor_transform = saved_cursor_transform;
772.21908 -+	sna_crtc->hwcursor = saved_hwcursor;
772.21909 - 	sna_crtc->bo = saved_bo;
772.21910 --	sna_mode_discover(sna);
772.21911 -+
772.21912 -+	reprobe_connectors(crtc);
772.21913 - 	return FALSE;
772.21914 - }
772.21915 - 
772.21916 -@@ -2346,14 +3149,14 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
772.21917 - 	xf86DrvMsg(crtc->scrn->scrnIndex, X_INFO,
772.21918 - 		   "switch to mode %dx%d@%.1f on %s using pipe %d, position (%d, %d), rotation %s, reflection %s\n",
772.21919 - 		   mode->HDisplay, mode->VDisplay, xf86ModeVRefresh(mode),
772.21920 --		   outputs_for_crtc(crtc, outputs, sizeof(outputs)), sna_crtc->pipe,
772.21921 -+		   outputs_for_crtc(crtc, outputs, sizeof(outputs)), __sna_crtc_pipe(sna_crtc),
772.21922 - 		   x, y, rotation_to_str(rotation), reflection_to_str(rotation));
772.21923 - 
772.21924 - 	assert(mode->HDisplay <= sna->mode.max_crtc_width &&
772.21925 - 	       mode->VDisplay <= sna->mode.max_crtc_height);
772.21926 - 
772.21927 - #if HAS_GAMMA
772.21928 --	drmModeCrtcSetGamma(sna->kgem.fd, sna_crtc->id,
772.21929 -+	drmModeCrtcSetGamma(sna->kgem.fd, __sna_crtc_id(sna_crtc),
772.21930 - 			    crtc->gamma_size,
772.21931 - 			    crtc->gamma_red,
772.21932 - 			    crtc->gamma_green,
772.21933 -@@ -2372,17 +3175,10 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
772.21934 - static void
772.21935 - sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
772.21936 - {
772.21937 --	struct sna_crtc *priv = to_sna_crtc(crtc);
772.21938 --
772.21939 - 	DBG(("%s(pipe %d, dpms mode -> %d):= active=%d\n",
772.21940 --	     __FUNCTION__, priv->pipe, mode, mode == DPMSModeOn));
772.21941 --	if (priv->dpms_mode == mode)
772.21942 --		return;
772.21943 --
772.21944 --	assert(priv);
772.21945 --	priv->dpms_mode = mode;
772.21946 -+	     __FUNCTION__, sna_crtc_pipe(crtc), mode, mode == DPMSModeOn));
772.21947 - 
772.21948 --	if (mode == DPMSModeOn && crtc->enabled && priv->bo == NULL) {
772.21949 -+	if (mode == DPMSModeOn && crtc->enabled) {
772.21950 - 		if (__sna_crtc_set_mode(crtc))
772.21951 - 			update_flush_interval(to_sna(crtc->scrn));
772.21952 - 		else
772.21953 -@@ -2390,7 +3186,7 @@ sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
772.21954 - 	}
772.21955 - 
772.21956 - 	if (mode != DPMSModeOn)
772.21957 --		sna_crtc_disable(crtc);
772.21958 -+		sna_crtc_disable(crtc, false);
772.21959 - }
772.21960 - 
772.21961 - void sna_mode_adjust_frame(struct sna *sna, int x, int y)
772.21962 -@@ -2426,7 +3222,7 @@ sna_crtc_gamma_set(xf86CrtcPtr crtc,
772.21963 - {
772.21964 - 	assert(to_sna_crtc(crtc));
772.21965 - 	drmModeCrtcSetGamma(to_sna(crtc->scrn)->kgem.fd,
772.21966 --			    to_sna_crtc(crtc)->id,
772.21967 -+			    sna_crtc_id(crtc),
772.21968 - 			    size, red, green, blue);
772.21969 - }
772.21970 - 
772.21971 -@@ -2434,10 +3230,14 @@ static void
772.21972 - sna_crtc_destroy(xf86CrtcPtr crtc)
772.21973 - {
772.21974 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.21975 -+	struct plane *sprite, *sn;
772.21976 - 
772.21977 - 	if (sna_crtc == NULL)
772.21978 - 		return;
772.21979 - 
772.21980 -+	list_for_each_entry_safe(sprite, sn, &sna_crtc->sprites, link)
772.21981 -+		free(sprite);
772.21982 -+
772.21983 - 	free(sna_crtc);
772.21984 - 	crtc->driver_private = NULL;
772.21985 - }
772.21986 -@@ -2455,7 +3255,7 @@ sna_crtc_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr pixmap)
772.21987 - 		return TRUE;
772.21988 - 
772.21989 - 	DBG(("%s: CRTC:%d, pipe=%d setting scanout pixmap=%ld\n",
772.21990 --	     __FUNCTION__, sna_crtc->id,  sna_crtc->pipe,
772.21991 -+	     __FUNCTION__, __sna_crtc_id(sna_crtc),  __sna_crtc_pipe(sna_crtc),
772.21992 - 	     pixmap ? pixmap->drawable.serialNumber : 0));
772.21993 - 
772.21994 - 	/* Disable first so that we can unregister the damage tracking */
772.21995 -@@ -2576,6 +3376,10 @@ static int plane_details(struct sna *sna, struct plane *p)
772.21996 - 		}
772.21997 - 	}
772.21998 - 
772.21999 -+	p->rotation.supported &= DBG_NATIVE_ROTATION;
772.22000 -+	if (!xf86ReturnOptValBool(sna->Options, OPTION_ROTATION, TRUE))
772.22001 -+		p->rotation.supported = RR_Rotate_0;
772.22002 -+
772.22003 - 	if (props != (uint32_t *)stack_props)
772.22004 - 		free(props);
772.22005 - 
772.22006 -@@ -2583,20 +3387,26 @@ static int plane_details(struct sna *sna, struct plane *p)
772.22007 - 	return type;
772.22008 - }
772.22009 - 
772.22010 -+static void add_sprite_plane(struct sna_crtc *crtc,
772.22011 -+			     struct plane *details)
772.22012 -+{
772.22013 -+	struct plane *sprite = malloc(sizeof(*sprite));
772.22014 -+	if (!sprite)
772.22015 -+		return;
772.22016 -+
772.22017 -+	memcpy(sprite, details, sizeof(*sprite));
772.22018 -+	list_add(&sprite->link, &crtc->sprites);
772.22019 -+}
772.22020 -+
772.22021 - static void
772.22022 - sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
772.22023 - {
772.22024 - #define LOCAL_IOCTL_SET_CAP	DRM_IOWR(0x0d, struct local_set_cap)
772.22025 --#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res)
772.22026 --#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane)
772.22027 - 	struct local_set_cap {
772.22028 - 		uint64_t name;
772.22029 - 		uint64_t value;
772.22030 - 	} cap;
772.22031 --	struct local_mode_get_plane_res {
772.22032 --		uint64_t plane_id_ptr;
772.22033 --		uint64_t count_planes;
772.22034 --	} r;
772.22035 -+	struct local_mode_get_plane_res r;
772.22036 - 	uint32_t stack_planes[32];
772.22037 - 	uint32_t *planes = stack_planes;
772.22038 - 	int i;
772.22039 -@@ -2629,18 +3439,7 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
772.22040 - 	VG(VALGRIND_MAKE_MEM_DEFINED(planes, sizeof(uint32_t)*r.count_planes));
772.22041 - 
772.22042 - 	for (i = 0; i < r.count_planes; i++) {
772.22043 --		struct local_mode_get_plane {
772.22044 --			uint32_t plane_id;
772.22045 --
772.22046 --			uint32_t crtc_id;
772.22047 --			uint32_t fb_id;
772.22048 --
772.22049 --			uint32_t possible_crtcs;
772.22050 --			uint32_t gamma_size;
772.22051 --
772.22052 --			uint32_t count_format_types;
772.22053 --			uint64_t format_type_ptr;
772.22054 --		} p;
772.22055 -+		struct local_mode_get_plane p;
772.22056 - 		struct plane details;
772.22057 - 
772.22058 - 		VG_CLEAR(p);
772.22059 -@@ -2649,11 +3448,11 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
772.22060 - 		if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANE, &p))
772.22061 - 			continue;
772.22062 - 
772.22063 --		if ((p.possible_crtcs & (1 << crtc->pipe)) == 0)
772.22064 -+		if ((p.possible_crtcs & (1 << __sna_crtc_pipe(crtc))) == 0)
772.22065 - 			continue;
772.22066 - 
772.22067 - 		DBG(("%s: plane %d is attached to our pipe=%d\n",
772.22068 --		     __FUNCTION__, planes[i], crtc->pipe));
772.22069 -+		     __FUNCTION__, planes[i], __sna_crtc_pipe(crtc)));
772.22070 - 
772.22071 - 		details.id = p.plane_id;
772.22072 - 		details.rotation.prop = 0;
772.22073 -@@ -2672,8 +3471,7 @@ sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc)
772.22074 - 			break;
772.22075 - 
772.22076 - 		case DRM_PLANE_TYPE_OVERLAY:
772.22077 --			if (crtc->sprite.id == 0)
772.22078 --				crtc->sprite = details;
772.22079 -+			add_sprite_plane(crtc, &details);
772.22080 - 			break;
772.22081 - 		}
772.22082 - 	}
772.22083 -@@ -2688,7 +3486,6 @@ sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *crtc)
772.22084 - 	crtc->rotation = RR_Rotate_0;
772.22085 - 	crtc->primary.rotation.supported = RR_Rotate_0;
772.22086 - 	crtc->primary.rotation.current = RR_Rotate_0;
772.22087 --	crtc->sprite.rotation = crtc->primary.rotation;
772.22088 - }
772.22089 - 
772.22090 - static void
772.22091 -@@ -2698,55 +3495,55 @@ sna_crtc_init__cursor(struct sna *sna, struct sna_crtc *crtc)
772.22092 - 
772.22093 - 	VG_CLEAR(arg);
772.22094 - 	arg.flags = DRM_MODE_CURSOR_BO;
772.22095 --	arg.crtc_id = crtc->id;
772.22096 -+	arg.crtc_id = __sna_crtc_id(crtc);
772.22097 - 	arg.width = arg.height = 0;
772.22098 - 	arg.handle = 0;
772.22099 - 
772.22100 - 	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
772.22101 -+	crtc->hwcursor = true;
772.22102 - }
772.22103 - 
772.22104 - static bool
772.22105 --sna_crtc_add(ScrnInfoPtr scrn, int id)
772.22106 -+sna_crtc_add(ScrnInfoPtr scrn, unsigned id)
772.22107 - {
772.22108 - 	struct sna *sna = to_sna(scrn);
772.22109 - 	xf86CrtcPtr crtc;
772.22110 - 	struct sna_crtc *sna_crtc;
772.22111 - 	struct drm_i915_get_pipe_from_crtc_id get_pipe;
772.22112 - 
772.22113 --	DBG(("%s(%d)\n", __FUNCTION__, id));
772.22114 -+	DBG(("%s(%d): is-zaphod? %d\n", __FUNCTION__, id, is_zaphod(scrn)));
772.22115 - 
772.22116 - 	sna_crtc = calloc(sizeof(struct sna_crtc), 1);
772.22117 - 	if (sna_crtc == NULL)
772.22118 - 		return false;
772.22119 - 
772.22120 - 	sna_crtc->id = id;
772.22121 --	sna_crtc->dpms_mode = -1;
772.22122 - 
772.22123 - 	VG_CLEAR(get_pipe);
772.22124 - 	get_pipe.pipe = 0;
772.22125 --	get_pipe.crtc_id = sna_crtc->id;
772.22126 -+	get_pipe.crtc_id = id;
772.22127 - 	if (drmIoctl(sna->kgem.fd,
772.22128 - 		     DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
772.22129 - 		     &get_pipe)) {
772.22130 - 		free(sna_crtc);
772.22131 - 		return false;
772.22132 - 	}
772.22133 --	sna_crtc->pipe = get_pipe.pipe;
772.22134 -+	assert((unsigned)get_pipe.pipe < 256);
772.22135 -+	sna_crtc->flags |= get_pipe.pipe << 8;
772.22136 - 
772.22137 - 	if (is_zaphod(scrn) &&
772.22138 --	    scrn->confScreen->device->screen != sna_crtc->pipe) {
772.22139 -+	    (get_zaphod_crtcs(sna) & (1 << get_pipe.pipe)) == 0) {
772.22140 - 		free(sna_crtc);
772.22141 - 		return true;
772.22142 - 	}
772.22143 - 
772.22144 -+	list_init(&sna_crtc->sprites);
772.22145 - 	sna_crtc_init__rotation(sna, sna_crtc);
772.22146 --
772.22147 - 	sna_crtc_find_planes(sna, sna_crtc);
772.22148 - 
772.22149 --	DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x, sprite id=%x: supported-rotations=%x, current-rotation=%x\n",
772.22150 --	     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
772.22151 --	     sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current,
772.22152 --	     sna_crtc->sprite.id, sna_crtc->sprite.rotation.supported, sna_crtc->sprite.rotation.current));
772.22153 -+	DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x\n",
772.22154 -+	     __FUNCTION__, id, get_pipe.pipe,
772.22155 -+	     sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current));
772.22156 - 
772.22157 - 	list_init(&sna_crtc->shadow_link);
772.22158 - 
772.22159 -@@ -2761,7 +3558,7 @@ sna_crtc_add(ScrnInfoPtr scrn, int id)
772.22160 - 	crtc->driver_private = sna_crtc;
772.22161 - 	sna_crtc->base = crtc;
772.22162 - 	DBG(("%s: attached crtc[%d] pipe=%d\n",
772.22163 --	     __FUNCTION__, id, sna_crtc->pipe));
772.22164 -+	     __FUNCTION__, id, __sna_crtc_pipe(sna_crtc)));
772.22165 - 
772.22166 - 	return true;
772.22167 - }
772.22168 -@@ -2798,20 +3595,56 @@ find_property(struct sna *sna, struct sna_output *output, const char *name)
772.22169 - 	return -1;
772.22170 - }
772.22171 - 
772.22172 -+static void update_properties(struct sna *sna, struct sna_output *output)
772.22173 -+{
772.22174 -+	union compat_mode_get_connector compat_conn;
772.22175 -+	struct drm_mode_modeinfo dummy;
772.22176 -+
772.22177 -+	VG_CLEAR(compat_conn);
772.22178 -+
772.22179 -+	compat_conn.conn.connector_id = output->id;
772.22180 -+	compat_conn.conn.count_props = output->num_props;
772.22181 -+	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
772.22182 -+	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
772.22183 -+	compat_conn.conn.count_modes = 1; /* skip detect */
772.22184 -+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
772.22185 -+	compat_conn.conn.count_encoders = 0;
772.22186 -+
772.22187 -+	(void)drmIoctl(sna->kgem.fd,
772.22188 -+		       DRM_IOCTL_MODE_GETCONNECTOR,
772.22189 -+		       &compat_conn.conn);
772.22190 -+
772.22191 -+	assert(compat_conn.conn.count_props == output->num_props);
772.22192 -+	output->update_properties = false;
772.22193 -+}
772.22194 -+
772.22195 - static xf86OutputStatus
772.22196 - sna_output_detect(xf86OutputPtr output)
772.22197 - {
772.22198 - 	struct sna *sna = to_sna(output->scrn);
772.22199 - 	struct sna_output *sna_output = output->driver_private;
772.22200 - 	union compat_mode_get_connector compat_conn;
772.22201 -+	uint32_t now;
772.22202 - 
772.22203 - 	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
772.22204 -+	sna_output->update_properties = false;
772.22205 - 
772.22206 - 	if (!sna_output->id) {
772.22207 - 		DBG(("%s(%s) hiding due to lost connection\n", __FUNCTION__, output->name));
772.22208 - 		return XF86OutputStatusDisconnected;
772.22209 - 	}
772.22210 - 
772.22211 -+	/* Cache detections for 15s or hotplug event  */
772.22212 -+	now = GetTimeInMillis();
772.22213 -+	if (sna_output->last_detect != 0 &&
772.22214 -+	    (int32_t)(now - sna_output->last_detect) <= OUTPUT_STATUS_CACHE_MS) {
772.22215 -+		DBG(("%s(%s) reporting cached status (since %dms): %d\n",
772.22216 -+		     __FUNCTION__, output->name, now - sna_output->last_detect,
772.22217 -+		     sna_output->status));
772.22218 -+		sna_output->update_properties = true;
772.22219 -+		return sna_output->status;
772.22220 -+	}
772.22221 -+
772.22222 - 	VG_CLEAR(compat_conn);
772.22223 - 	compat_conn.conn.connector_id = sna_output->id;
772.22224 - 	sna_output->num_modes = compat_conn.conn.count_modes = 0; /* reprobe */
772.22225 -@@ -2854,15 +3687,23 @@ sna_output_detect(xf86OutputPtr output)
772.22226 - 	DBG(("%s(%s): found %d modes, connection status=%d\n",
772.22227 - 	     __FUNCTION__, output->name, sna_output->num_modes, compat_conn.conn.connection));
772.22228 - 
772.22229 -+	sna_output->reprobe = false;
772.22230 -+	sna_output->last_detect = now;
772.22231 - 	switch (compat_conn.conn.connection) {
772.22232 - 	case DRM_MODE_CONNECTED:
772.22233 --		return XF86OutputStatusConnected;
772.22234 -+		sna_output->status = XF86OutputStatusConnected;
772.22235 -+		output->mm_width = compat_conn.conn.mm_width;
772.22236 -+		output->mm_height = compat_conn.conn.mm_height;
772.22237 -+		break;
772.22238 - 	case DRM_MODE_DISCONNECTED:
772.22239 --		return XF86OutputStatusDisconnected;
772.22240 -+		sna_output->status = XF86OutputStatusDisconnected;
772.22241 -+		break;
772.22242 - 	default:
772.22243 - 	case DRM_MODE_UNKNOWNCONNECTION:
772.22244 --		return XF86OutputStatusUnknown;
772.22245 -+		sna_output->status = XF86OutputStatusUnknown;
772.22246 -+		break;
772.22247 - 	}
772.22248 -+	return sna_output->status;
772.22249 - }
772.22250 - 
772.22251 - static Bool
772.22252 -@@ -2895,6 +3736,27 @@ sna_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
772.22253 - 	return MODE_OK;
772.22254 - }
772.22255 - 
772.22256 -+static void sna_output_set_parsed_edid(xf86OutputPtr output, xf86MonPtr mon)
772.22257 -+{
772.22258 -+	unsigned conn_mm_width, conn_mm_height;
772.22259 -+
772.22260 -+	/* We set the output size based on values from the kernel */
772.22261 -+	conn_mm_width = output->mm_width;
772.22262 -+	conn_mm_height = output->mm_height;
772.22263 -+
772.22264 -+	xf86OutputSetEDID(output, mon);
772.22265 -+
772.22266 -+	if (output->mm_width != conn_mm_width || output->mm_height != conn_mm_height) {
772.22267 -+		DBG(("%s)%s): kernel and Xorg disagree over physical size: kernel=%dx%dmm, Xorg=%dx%dmm\n",
772.22268 -+		     __FUNCTION__, output->name,
772.22269 -+		     conn_mm_width, conn_mm_height,
772.22270 -+		     output->mm_width, output->mm_height));
772.22271 -+	}
772.22272 -+
772.22273 -+	output->mm_width = conn_mm_width;
772.22274 -+	output->mm_height = conn_mm_height;
772.22275 -+}
772.22276 -+
772.22277 - static void
772.22278 - sna_output_attach_edid(xf86OutputPtr output)
772.22279 - {
772.22280 -@@ -2907,6 +3769,13 @@ sna_output_attach_edid(xf86OutputPtr output)
772.22281 - 	if (sna_output->edid_idx == -1)
772.22282 - 		return;
772.22283 - 
772.22284 -+	/* Always refresh the blob as the kernel may randomly update the
772.22285 -+	 * id even if the contents of the blob doesn't change, and a
772.22286 -+	 * request for the stale id will return nothing.
772.22287 -+	 */
772.22288 -+	if (sna_output->update_properties)
772.22289 -+		update_properties(sna, sna_output);
772.22290 -+
772.22291 - 	raw = sna_output->edid_raw;
772.22292 - 	blob.length = sna_output->edid_len;
772.22293 - 
772.22294 -@@ -2917,8 +3786,12 @@ sna_output_attach_edid(xf86OutputPtr output)
772.22295 - 		old = NULL;
772.22296 - 
772.22297 - 	blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
772.22298 --	DBG(("%s: attaching EDID id=%d, current=%d\n",
772.22299 --	     __FUNCTION__, blob.blob_id, sna_output->edid_blob_id));
772.22300 -+	if (!blob.blob_id)
772.22301 -+		goto done;
772.22302 -+
772.22303 -+	DBG(("%s(%s): attaching EDID id=%d, current=%d\n",
772.22304 -+	     __FUNCTION__, output->name,
772.22305 -+	     blob.blob_id, sna_output->edid_blob_id));
772.22306 - 	if (blob.blob_id == sna_output->edid_blob_id && 0) { /* sigh */
772.22307 - 		if (output->MonInfo) {
772.22308 - 			/* XXX the property keeps on disappearing... */
772.22309 -@@ -2936,26 +3809,45 @@ sna_output_attach_edid(xf86OutputPtr output)
772.22310 - 	}
772.22311 - 
772.22312 - 	blob.data = (uintptr_t)raw;
772.22313 --	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
772.22314 --		goto done;
772.22315 -+	do {
772.22316 -+		while (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
772.22317 -+			update_properties(sna, sna_output);
772.22318 -+			if (blob.blob_id == sna_output->prop_values[sna_output->edid_idx]) {
772.22319 -+				DBG(("%s(%s): failed to read blob, reusing previous\n",
772.22320 -+				     __FUNCTION__, output->name));
772.22321 -+				goto done;
772.22322 -+			}
772.22323 -+			blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
772.22324 -+		}
772.22325 - 
772.22326 --	DBG(("%s: retrieving blob id=%d, length=%d\n",
772.22327 --	     __FUNCTION__, blob.blob_id, blob.length));
772.22328 -+		DBG(("%s(%s): retrieving blob id=%d, length=%d\n",
772.22329 -+		     __FUNCTION__, output->name, blob.blob_id, blob.length));
772.22330 - 
772.22331 --	if (blob.length > sna_output->edid_len) {
772.22332 --		raw = realloc(raw, blob.length);
772.22333 --		if (raw == NULL)
772.22334 -+		if (blob.length < 128)
772.22335 - 			goto done;
772.22336 - 
772.22337 --		VG(memset(raw, 0, blob.length));
772.22338 --		blob.data = (uintptr_t)raw;
772.22339 --		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
772.22340 --			goto done;
772.22341 -+		if (blob.length > sna_output->edid_len) {
772.22342 -+			raw = realloc(raw, blob.length);
772.22343 -+			if (raw == NULL)
772.22344 -+				goto done;
772.22345 -+
772.22346 -+			VG(memset(raw, 0, blob.length));
772.22347 -+			blob.data = (uintptr_t)raw;
772.22348 -+		}
772.22349 -+	} while (blob.length != sna_output->edid_len &&
772.22350 -+		 drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob));
772.22351 -+
772.22352 -+	if (blob.length & 127) {
772.22353 -+		/* Truncated EDID! Make sure no one reads too far */
772.22354 -+		*SECTION(NO_EDID, (uint8_t*)raw) = blob.length/128 - 1;
772.22355 -+		blob.length &= -128;
772.22356 - 	}
772.22357 - 
772.22358 - 	if (old &&
772.22359 - 	    blob.length == sna_output->edid_len &&
772.22360 - 	    memcmp(old, raw, blob.length) == 0) {
772.22361 -+		DBG(("%s(%s): EDID + MonInfo is unchanged\n",
772.22362 -+		     __FUNCTION__, output->name));
772.22363 - 		assert(sna_output->edid_raw == raw);
772.22364 - 		sna_output->edid_blob_id = blob.blob_id;
772.22365 - 		RRChangeOutputProperty(output->randr_output,
772.22366 -@@ -2974,31 +3866,186 @@ skip_read:
772.22367 - 			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
772.22368 - 	}
772.22369 - 
772.22370 --done:
772.22371 --	xf86OutputSetEDID(output, mon);
772.22372 --	if (raw) {
772.22373 --		sna_output->edid_raw = raw;
772.22374 --		sna_output->edid_len = blob.length;
772.22375 --		sna_output->edid_blob_id = blob.blob_id;
772.22376 -+done:
772.22377 -+	sna_output_set_parsed_edid(output, mon);
772.22378 -+	if (raw) {
772.22379 -+		sna_output->edid_raw = raw;
772.22380 -+		sna_output->edid_len = blob.length;
772.22381 -+		sna_output->edid_blob_id = blob.blob_id;
772.22382 -+	}
772.22383 -+}
772.22384 -+
772.22385 -+static void
772.22386 -+sna_output_attach_tile(xf86OutputPtr output)
772.22387 -+{
772.22388 -+#if XF86_OUTPUT_VERSION >= 3
772.22389 -+	struct sna *sna = to_sna(output->scrn);
772.22390 -+	struct sna_output *sna_output = output->driver_private;
772.22391 -+	struct drm_mode_get_blob blob;
772.22392 -+	struct xf86CrtcTileInfo tile_info, *set = NULL;
772.22393 -+	char *tile;
772.22394 -+	int id;
772.22395 -+
772.22396 -+	id = find_property(sna, sna_output, "TILE");
772.22397 -+	DBG(("%s: found? TILE=%d\n", __FUNCTION__, id));
772.22398 -+	if (id == -1)
772.22399 -+		goto out;
772.22400 -+
772.22401 -+	if (sna_output->update_properties)
772.22402 -+		update_properties(sna, sna_output);
772.22403 -+
772.22404 -+	VG_CLEAR(blob);
772.22405 -+	blob.blob_id = sna_output->prop_values[id];
772.22406 -+	blob.length = 0;
772.22407 -+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
772.22408 -+		goto out;
772.22409 -+
772.22410 -+	do {
772.22411 -+		id = blob.length;
772.22412 -+		tile = alloca(id + 1);
772.22413 -+		blob.data = (uintptr_t)tile;
772.22414 -+		VG(memset(tile, 0, id));
772.22415 -+		DBG(("%s: reading %d bytes for TILE blob\n", __FUNCTION__, id));
772.22416 -+		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
772.22417 -+			goto out;
772.22418 -+	} while (id != blob.length);
772.22419 -+
772.22420 -+	tile[blob.length] = '\0'; /* paranoia */
772.22421 -+	DBG(("%s: TILE='%s'\n", __FUNCTION__, tile));
772.22422 -+	if (xf86OutputParseKMSTile(tile, blob.length, &tile_info))
772.22423 -+		set = &tile_info;
772.22424 -+out:
772.22425 -+	xf86OutputSetTile(output, set);
772.22426 -+#endif
772.22427 -+}
772.22428 -+
772.22429 -+static bool duplicate_mode(DisplayModePtr modes, DisplayModePtr m)
772.22430 -+{
772.22431 -+	if (m == NULL)
772.22432 -+		return false;
772.22433 -+
772.22434 -+	while (modes) {
772.22435 -+		if (xf86ModesEqual(modes, m))
772.22436 -+			return true;
772.22437 -+
772.22438 -+		modes = modes->next;
772.22439 -+	}
772.22440 -+
772.22441 -+	return false;
772.22442 -+}
772.22443 -+
772.22444 -+static struct pixel_count {
772.22445 -+	int16_t width, height;
772.22446 -+} common_16_9[] = {
772.22447 -+	{ 640, 360 },
772.22448 -+	{ 720, 405 },
772.22449 -+	{ 864, 486 },
772.22450 -+	{ 960, 540 },
772.22451 -+	{ 1024, 576 },
772.22452 -+	{ 1280, 720 },
772.22453 -+	{ 1366, 768 },
772.22454 -+	{ 1600, 900 },
772.22455 -+	{ 1920, 1080 },
772.22456 -+	{ 2048, 1152 },
772.22457 -+	{ 2560, 1440 },
772.22458 -+	{ 2880, 1620 },
772.22459 -+	{ 3200, 1800 },
772.22460 -+	{ 3840, 2160 },
772.22461 -+	{ 4096, 2304 },
772.22462 -+	{ 5120, 2880 },
772.22463 -+	{ 7680, 4320 },
772.22464 -+	{ 15360, 8640 },
772.22465 -+}, common_16_10[] = {
772.22466 -+	{ 1280, 800 },
772.22467 -+	{ 1400, 900 },
772.22468 -+	{ 1680, 1050 },
772.22469 -+	{ 1920, 1200 },
772.22470 -+	{ 2560, 1600 },
772.22471 -+};
772.22472 -+
772.22473 -+static DisplayModePtr
772.22474 -+default_modes(DisplayModePtr preferred)
772.22475 -+{
772.22476 -+	DisplayModePtr modes;
772.22477 -+	int n;
772.22478 -+
772.22479 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0)
772.22480 -+	modes = xf86GetDefaultModes();
772.22481 -+#else
772.22482 -+	modes = xf86GetDefaultModes(0, 0);
772.22483 -+#endif
772.22484 -+
772.22485 -+	/* XXX O(n^2) mode list generation :( */
772.22486 -+
772.22487 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,4,99,901,0)
772.22488 -+	if (preferred) {
772.22489 -+		DisplayModePtr m;
772.22490 -+
772.22491 -+		/* Add a half-resolution mode useful for large panels */
772.22492 -+		m = xf86GTFMode(preferred->HDisplay/2,
772.22493 -+				preferred->VDisplay/2,
772.22494 -+				xf86ModeVRefresh(preferred),
772.22495 -+				FALSE, FALSE);
772.22496 -+		if (!duplicate_mode(modes, m))
772.22497 -+			modes = xf86ModesAdd(modes, m);
772.22498 -+		else
772.22499 -+			free(m);
772.22500 -+
772.22501 -+		if (preferred->VDisplay * 16 > preferred->HDisplay*9 - preferred->HDisplay/32 &&
772.22502 -+		    preferred->VDisplay * 16 < preferred->HDisplay*9 + preferred->HDisplay/32) {
772.22503 -+			DBG(("Adding 16:9 modes -- %d < %d > %d\n",
772.22504 -+			     preferred->HDisplay*9 - preferred->HDisplay/32,
772.22505 -+			     preferred->VDisplay * 16,
772.22506 -+			     preferred->HDisplay*9 + preferred->HDisplay/32));
772.22507 -+			for (n = 0; n < ARRAY_SIZE(common_16_9); n++) {
772.22508 -+				if (preferred->HDisplay <= common_16_9[n].width ||
772.22509 -+				    preferred->VDisplay <= common_16_9[n].height)
772.22510 -+					break;
772.22511 -+
772.22512 -+				m = xf86GTFMode(common_16_9[n].width,
772.22513 -+						common_16_9[n].height,
772.22514 -+						xf86ModeVRefresh(preferred),
772.22515 -+						FALSE, FALSE);
772.22516 -+				if (!duplicate_mode(modes, m))
772.22517 -+					modes = xf86ModesAdd(modes, m);
772.22518 -+				else
772.22519 -+					free(m);
772.22520 -+			}
772.22521 -+		}
772.22522 -+
772.22523 -+		if (preferred->VDisplay * 16 > preferred->HDisplay*10 - preferred->HDisplay/32 &&
772.22524 -+		    preferred->VDisplay * 16 < preferred->HDisplay*10 + preferred->HDisplay/32) {
772.22525 -+			DBG(("Adding 16:10 modes -- %d < %d > %d\n",
772.22526 -+			     preferred->HDisplay*10 - preferred->HDisplay/32,
772.22527 -+			     preferred->VDisplay * 16,
772.22528 -+			     preferred->HDisplay*10 + preferred->HDisplay/32));
772.22529 -+			for (n = 0; n < ARRAY_SIZE(common_16_10); n++) {
772.22530 -+				if (preferred->HDisplay <= common_16_10[n].width ||
772.22531 -+				    preferred->VDisplay <= common_16_10[n].height)
772.22532 -+					break;
772.22533 -+
772.22534 -+				m = xf86GTFMode(common_16_10[n].width,
772.22535 -+						common_16_10[n].height,
772.22536 -+						xf86ModeVRefresh(preferred),
772.22537 -+						FALSE, FALSE);
772.22538 -+				if (!duplicate_mode(modes, m))
772.22539 -+					modes = xf86ModesAdd(modes, m);
772.22540 -+				else
772.22541 -+					free(m);
772.22542 -+			}
772.22543 -+		}
772.22544 - 	}
772.22545 --}
772.22546 --
772.22547 --static DisplayModePtr
772.22548 --default_modes(void)
772.22549 --{
772.22550 --#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,900,0)
772.22551 --	return xf86GetDefaultModes();
772.22552 --#else
772.22553 --	return xf86GetDefaultModes(0, 0);
772.22554 - #endif
772.22555 -+
772.22556 -+	return modes;
772.22557 - }
772.22558 - 
772.22559 - static DisplayModePtr
772.22560 --sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
772.22561 -+sna_output_add_default_modes(xf86OutputPtr output, DisplayModePtr modes)
772.22562 - {
772.22563 - 	xf86MonPtr mon = output->MonInfo;
772.22564 - 	DisplayModePtr i, m, preferred = NULL;
772.22565 --	int max_x = 0, max_y = 0;
772.22566 -+	int max_x = 0, max_y = 0, max_clock = 0;
772.22567 - 	float max_vrefresh = 0.0;
772.22568 - 
772.22569 - 	if (mon && GTF_SUPPORTED(mon->features.msc))
772.22570 -@@ -3009,16 +4056,17 @@ sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
772.22571 - 			preferred = m;
772.22572 - 		max_x = max(max_x, m->HDisplay);
772.22573 - 		max_y = max(max_y, m->VDisplay);
772.22574 -+		max_clock = max(max_clock, m->Clock);
772.22575 - 		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
772.22576 - 	}
772.22577 --
772.22578 --	max_vrefresh = max(max_vrefresh, 60.0);
772.22579 - 	max_vrefresh *= (1 + SYNC_TOLERANCE);
772.22580 - 
772.22581 --	m = default_modes();
772.22582 -+	m = default_modes(preferred);
772.22583 - 	xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
772.22584 - 
772.22585 - 	for (i = m; i; i = i->next) {
772.22586 -+		if (i->Clock > max_clock)
772.22587 -+			i->status = MODE_CLOCK_HIGH;
772.22588 - 		if (xf86ModeVRefresh(i) > max_vrefresh)
772.22589 - 			i->status = MODE_VSYNC;
772.22590 - 		if (preferred &&
772.22591 -@@ -3034,28 +4082,47 @@ sna_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
772.22592 - }
772.22593 - 
772.22594 - static DisplayModePtr
772.22595 -+sna_output_override_edid(xf86OutputPtr output)
772.22596 -+{
772.22597 -+	struct sna_output *sna_output = output->driver_private;
772.22598 -+
772.22599 -+	if (sna_output->fake_edid_mon == NULL)
772.22600 -+		return NULL;
772.22601 -+
772.22602 -+	xf86OutputSetEDID(output, sna_output->fake_edid_mon);
772.22603 -+	return xf86DDCGetModes(output->scrn->scrnIndex,
772.22604 -+			       sna_output->fake_edid_mon);
772.22605 -+}
772.22606 -+
772.22607 -+static DisplayModePtr
772.22608 - sna_output_get_modes(xf86OutputPtr output)
772.22609 - {
772.22610 - 	struct sna_output *sna_output = output->driver_private;
772.22611 --	DisplayModePtr Modes = NULL, current = NULL;
772.22612 -+	DisplayModePtr Modes, current;
772.22613 - 	int i;
772.22614 - 
772.22615 - 	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
772.22616 - 	assert(sna_output->id);
772.22617 - 
772.22618 -+	Modes = sna_output_override_edid(output);
772.22619 -+	if (Modes)
772.22620 -+		return Modes;
772.22621 -+
772.22622 - 	sna_output_attach_edid(output);
772.22623 -+	sna_output_attach_tile(output);
772.22624 - 
772.22625 --	if (output->crtc) {
772.22626 -+	current = NULL;
772.22627 -+	if (output->crtc && !sna_output->hotplug_count) {
772.22628 - 		struct drm_mode_crtc mode;
772.22629 - 
772.22630 - 		VG_CLEAR(mode);
772.22631 - 		assert(to_sna_crtc(output->crtc));
772.22632 --		mode.crtc_id = to_sna_crtc(output->crtc)->id;
772.22633 -+		mode.crtc_id = sna_crtc_id(output->crtc);
772.22634 - 
772.22635 - 		if (drmIoctl(to_sna(output->scrn)->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode) == 0) {
772.22636 - 			DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
772.22637 --			     to_sna_crtc(output->crtc)->id,
772.22638 --			     to_sna_crtc(output->crtc)->pipe,
772.22639 -+			     sna_crtc_id(output->crtc),
772.22640 -+			     sna_crtc_pipe(output->crtc),
772.22641 - 			     mode.mode_valid && mode.mode.clock));
772.22642 - 
772.22643 - 			if (mode.mode_valid && mode.mode.clock) {
772.22644 -@@ -3117,7 +4184,7 @@ sna_output_get_modes(xf86OutputPtr output)
772.22645 - 	}
772.22646 - 
772.22647 - 	if (sna_output->add_default_modes)
772.22648 --		Modes = sna_output_panel_edid(output, Modes);
772.22649 -+		Modes = sna_output_add_default_modes(output, Modes);
772.22650 - 
772.22651 - 	return Modes;
772.22652 - }
772.22653 -@@ -3132,6 +4199,8 @@ sna_output_destroy(xf86OutputPtr output)
772.22654 - 		return;
772.22655 - 
772.22656 - 	free(sna_output->edid_raw);
772.22657 -+	free(sna_output->fake_edid_raw);
772.22658 -+
772.22659 - 	for (i = 0; i < sna_output->num_props; i++) {
772.22660 - 		if (sna_output->props[i].kprop == NULL)
772.22661 - 			continue;
772.22662 -@@ -3155,7 +4224,7 @@ sna_output_destroy(xf86OutputPtr output)
772.22663 - }
772.22664 - 
772.22665 - static void
772.22666 --sna_output_dpms(xf86OutputPtr output, int dpms)
772.22667 -+__sna_output_dpms(xf86OutputPtr output, int dpms, int fixup)
772.22668 - {
772.22669 - 	struct sna *sna = to_sna(output->scrn);
772.22670 - 	struct sna_output *sna_output = output->driver_private;
772.22671 -@@ -3182,8 +4251,9 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
772.22672 - 	if (sna_output->backlight.iface && dpms != DPMSModeOn) {
772.22673 - 		if (old_dpms == DPMSModeOn) {
772.22674 - 			sna_output->backlight_active_level = sna_output_backlight_get(output);
772.22675 --			DBG(("%s: saving current backlight %d\n",
772.22676 --			     __FUNCTION__, sna_output->backlight_active_level));
772.22677 -+			DBG(("%s(%s:%d): saving current backlight %d\n",
772.22678 -+			     __FUNCTION__, output->name, sna_output->id,
772.22679 -+			     sna_output->backlight_active_level));
772.22680 - 		}
772.22681 - 		sna_output->dpms_mode = dpms;
772.22682 - 		sna_output_backlight_off(sna_output);
772.22683 -@@ -3193,18 +4263,31 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
772.22684 - 	    drmModeConnectorSetProperty(sna->kgem.fd,
772.22685 - 					sna_output->id,
772.22686 - 					sna_output->dpms_id,
772.22687 --					dpms))
772.22688 --		dpms = old_dpms;
772.22689 -+					dpms)) {
772.22690 -+		DBG(("%s(%s:%d): failed to set DPMS to %d (fixup? %d)\n",
772.22691 -+		     __FUNCTION__, output->name, sna_output->id, dpms, fixup));
772.22692 -+		if (fixup && dpms != DPMSModeOn) {
772.22693 -+			sna_crtc_disable(output->crtc, false);
772.22694 -+			return;
772.22695 -+		}
772.22696 -+	}
772.22697 - 
772.22698 - 	if (sna_output->backlight.iface && dpms == DPMSModeOn) {
772.22699 --		DBG(("%s: restoring previous backlight %d\n",
772.22700 --		     __FUNCTION__, sna_output->backlight_active_level));
772.22701 -+		DBG(("%s(%d:%d: restoring previous backlight %d\n",
772.22702 -+		     __FUNCTION__, output->name, sna_output->id,
772.22703 -+		     sna_output->backlight_active_level));
772.22704 - 		sna_output_backlight_on(sna_output);
772.22705 - 	}
772.22706 - 
772.22707 - 	sna_output->dpms_mode = dpms;
772.22708 - }
772.22709 - 
772.22710 -+static void
772.22711 -+sna_output_dpms(xf86OutputPtr output, int dpms)
772.22712 -+{
772.22713 -+	__sna_output_dpms(output, dpms, true);
772.22714 -+}
772.22715 -+
772.22716 - static bool
772.22717 - sna_property_ignore(drmModePropertyPtr prop)
772.22718 - {
772.22719 -@@ -3239,14 +4322,14 @@ sna_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
772.22720 - 	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
772.22721 - 					TRUE, immutable, 2, atom_range);
772.22722 - 	if (err != 0)
772.22723 --		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.22724 -+		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22725 - 			   "RRConfigureOutputProperty error, %d\n", err);
772.22726 - 
772.22727 - 	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
772.22728 - 				     32, PropModeReplace, 1, &value,
772.22729 - 				     FALSE, FALSE);
772.22730 - 	if (err != 0)
772.22731 --		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.22732 -+		xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22733 - 			   "RRChangeOutputProperty error, %d\n", err);
772.22734 - }
772.22735 - 
772.22736 -@@ -3303,7 +4386,7 @@ sna_output_create_resources(xf86OutputPtr output)
772.22737 - 							p->kprop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
772.22738 - 							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
772.22739 - 			if (err != 0) {
772.22740 --				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.22741 -+				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22742 - 					   "RRConfigureOutputProperty error, %d\n", err);
772.22743 - 			}
772.22744 - 
772.22745 -@@ -3315,7 +4398,7 @@ sna_output_create_resources(xf86OutputPtr output)
772.22746 - 						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1],
772.22747 - 						     FALSE, FALSE);
772.22748 - 			if (err != 0) {
772.22749 --				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.22750 -+				xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22751 - 					   "RRChangeOutputProperty error, %d\n", err);
772.22752 - 			}
772.22753 - 		}
772.22754 -@@ -3385,18 +4468,19 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
772.22755 - 			if (value->type != XA_INTEGER || value->format != 32 ||
772.22756 - 			    value->size != 1)
772.22757 - 				return FALSE;
772.22758 --			val = *(uint32_t *)value->data;
772.22759 - 
772.22760 -+			val = *(uint32_t *)value->data;
772.22761 - 			drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
772.22762 - 						    p->kprop->prop_id, (uint64_t)val);
772.22763 - 			return TRUE;
772.22764 - 		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
772.22765 --			Atom	atom;
772.22766 --			const char	*name;
772.22767 --			int		j;
772.22768 -+			Atom atom;
772.22769 -+			const char *name;
772.22770 -+			int j;
772.22771 - 
772.22772 - 			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
772.22773 - 				return FALSE;
772.22774 -+
772.22775 - 			memcpy(&atom, value->data, 4);
772.22776 - 			name = NameForAtom(atom);
772.22777 - 			if (name == NULL)
772.22778 -@@ -3425,7 +4509,7 @@ static Bool
772.22779 - sna_output_get_property(xf86OutputPtr output, Atom property)
772.22780 - {
772.22781 - 	struct sna_output *sna_output = output->driver_private;
772.22782 --	int err;
772.22783 -+	int err, i, j;
772.22784 - 
772.22785 - 	if (property == backlight_atom || property == backlight_deprecated_atom) {
772.22786 - 		INT32 val;
772.22787 -@@ -3449,7 +4533,7 @@ sna_output_get_property(xf86OutputPtr output, Atom property)
772.22788 - 					     XA_INTEGER, 32, PropModeReplace, 1, &val,
772.22789 - 					     FALSE, FALSE);
772.22790 - 		if (err != 0) {
772.22791 --			xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.22792 -+			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22793 - 				   "RRChangeOutputProperty error, %d\n", err);
772.22794 - 			return FALSE;
772.22795 - 		}
772.22796 -@@ -3457,6 +4541,40 @@ sna_output_get_property(xf86OutputPtr output, Atom property)
772.22797 - 		return TRUE;
772.22798 - 	}
772.22799 - 
772.22800 -+	for (i = 0; i < sna_output->num_props; i++) {
772.22801 -+		struct sna_property *p = &sna_output->props[i];
772.22802 -+
772.22803 -+		if (p->atoms == NULL || p->atoms[0] != property)
772.22804 -+			continue;
772.22805 -+
772.22806 -+		if (sna_output->update_properties && output->scrn->vtSema)
772.22807 -+			update_properties(to_sna(output->scrn), sna_output);
772.22808 -+
772.22809 -+		err = 0;
772.22810 -+		if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
772.22811 -+			err = RRChangeOutputProperty(output->randr_output,
772.22812 -+						     property, XA_INTEGER, 32,
772.22813 -+						     PropModeReplace, 1,
772.22814 -+						     &sna_output->prop_values[i],
772.22815 -+						     FALSE, FALSE);
772.22816 -+		} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
772.22817 -+			for (j = 0; j < p->kprop->count_enums; j++) {
772.22818 -+				if (p->kprop->enums[j].value == sna_output->prop_values[i])
772.22819 -+					break;
772.22820 -+			}
772.22821 -+			err = RRChangeOutputProperty(output->randr_output,
772.22822 -+						     property, XA_ATOM, 32,
772.22823 -+						     PropModeReplace, 1,
772.22824 -+						     &p->atoms[j+1],
772.22825 -+						     FALSE, FALSE);
772.22826 -+		}
772.22827 -+
772.22828 -+		if (err != 0)
772.22829 -+			xf86DrvMsg(output->scrn->scrnIndex, X_WARNING,
772.22830 -+				   "RRChangeOutputProperty error, %d\n", err);
772.22831 -+		return TRUE;
772.22832 -+	}
772.22833 -+
772.22834 - 	return FALSE;
772.22835 - }
772.22836 - 
772.22837 -@@ -3500,47 +4618,11 @@ static const char * const output_names[] = {
772.22838 - 	/* DRM_MODE_CONNECTOR_TV */		"TV",
772.22839 - 	/* DRM_MODE_CONNECTOR_eDP */		"eDP",
772.22840 - 	/* DRM_MODE_CONNECTOR_VIRTUAL */	"Virtual",
772.22841 --	/* DRM_MODE_CONNECTOR_DSI */		"DSI"
772.22842 -+	/* DRM_MODE_CONNECTOR_DSI */		"DSI",
772.22843 -+	/* DRM_MODE_CONNECTOR_DPI */		"DPI"
772.22844 - };
772.22845 - 
772.22846 - static bool
772.22847 --sna_zaphod_match(const char *s, const char *output)
772.22848 --{
772.22849 --	char t[20];
772.22850 --	unsigned int i = 0;
772.22851 --
772.22852 --	do {
772.22853 --		/* match any outputs in a comma list, stopping at whitespace */
772.22854 --		switch (*s) {
772.22855 --		case '\0':
772.22856 --			t[i] = '\0';
772.22857 --			return strcmp(t, output) == 0;
772.22858 --
772.22859 --		case ',':
772.22860 --			t[i] ='\0';
772.22861 --			if (strcmp(t, output) == 0)
772.22862 --				return TRUE;
772.22863 --			i = 0;
772.22864 --			break;
772.22865 --
772.22866 --		case ' ':
772.22867 --		case '\t':
772.22868 --		case '\n':
772.22869 --		case '\r':
772.22870 --			break;
772.22871 --
772.22872 --		default:
772.22873 --			t[i++] = *s;
772.22874 --			break;
772.22875 --		}
772.22876 --
772.22877 --		s++;
772.22878 --	} while (i < sizeof(t));
772.22879 --
772.22880 --	return false;
772.22881 --}
772.22882 --
772.22883 --static bool
772.22884 - output_ignored(ScrnInfoPtr scrn, const char *name)
772.22885 - {
772.22886 - 	char monitor_name[64];
772.22887 -@@ -3572,14 +4654,21 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
772.22888 - 	struct drm_mode_get_encoder enc;
772.22889 - 	uint32_t *ids = NULL;
772.22890 - 
772.22891 -+	DBG(("%s(%d): expected count=%d\n", __FUNCTION__, id, count));
772.22892 -+
772.22893 - 	VG_CLEAR(compat_conn);
772.22894 -+	VG_CLEAR(enc);
772.22895 - 	memset(out, 0, sizeof(*out));
772.22896 - 
772.22897 - 	do {
772.22898 --		free(ids);
772.22899 --		ids = malloc(sizeof(*ids) * count);
772.22900 --		if (ids == 0)
772.22901 -+		uint32_t *nids;
772.22902 -+
772.22903 -+		nids = realloc(ids, sizeof(*ids) * count);
772.22904 -+		if (nids == NULL) {
772.22905 -+			free(ids);
772.22906 - 			return false;
772.22907 -+		}
772.22908 -+		ids = nids;
772.22909 - 
772.22910 - 		compat_conn.conn.connector_id = id;
772.22911 - 		compat_conn.conn.count_props = 0;
772.22912 -@@ -3593,12 +4682,14 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
772.22913 - 			compat_conn.conn.count_encoders = count = 0;
772.22914 - 		}
772.22915 - 
772.22916 -+		VG(VALGRIND_MAKE_MEM_DEFINED(ids, sizeof(uint32_t)*compat_conn.conn.count_encoders));
772.22917 - 		if (count == compat_conn.conn.count_encoders)
772.22918 - 			break;
772.22919 - 
772.22920 - 		count = compat_conn.conn.count_encoders;
772.22921 - 	} while (1);
772.22922 - 
772.22923 -+	DBG(("%s(%d): gathering %d encoders\n", __FUNCTION__, id, count));
772.22924 - 	for (count = 0; count < compat_conn.conn.count_encoders; count++) {
772.22925 - 		enc.encoder_id = ids[count];
772.22926 - 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc)) {
772.22927 -@@ -3606,6 +4697,8 @@ gather_encoders(struct sna *sna, uint32_t id, int count,
772.22928 - 			count = 0;
772.22929 - 			break;
772.22930 - 		}
772.22931 -+		DBG(("%s(%d): encoder=%d, possible_crtcs=%x, possible_clones=%x\n",
772.22932 -+		     __FUNCTION__, id, enc.encoder_id, enc.possible_crtcs, enc.possible_clones));
772.22933 - 		out->possible_crtcs |= enc.possible_crtcs;
772.22934 - 		out->possible_clones |= enc.possible_clones;
772.22935 - 
772.22936 -@@ -3731,6 +4824,116 @@ static int name_from_path(struct sna *sna,
772.22937 - 	return 0;
772.22938 - }
772.22939 - 
772.22940 -+static char *fake_edid_name(xf86OutputPtr output)
772.22941 -+{
772.22942 -+	struct sna *sna = to_sna(output->scrn);
772.22943 -+	const char *str, *colon;
772.22944 -+
772.22945 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.22946 -+	str = xf86GetOptValString(sna->Options, OPTION_EDID);
772.22947 -+#else
772.22948 -+	str = NULL;
772.22949 -+#endif
772.22950 -+	if (str == NULL)
772.22951 -+		return NULL;
772.22952 -+
772.22953 -+	do {
772.22954 -+		colon = strchr(str, ':');
772.22955 -+		if (colon == NULL)
772.22956 -+			return NULL;
772.22957 -+
772.22958 -+		if (strncmp(str, output->name, colon-str) == 0 &&
772.22959 -+		    output->name[colon-str] == '\0') {
772.22960 -+			char *path;
772.22961 -+			int len;
772.22962 -+
772.22963 -+			str = colon + 1;
772.22964 -+			colon = strchr(str, ',');
772.22965 -+			if (colon)
772.22966 -+				len = colon - str;
772.22967 -+			else
772.22968 -+				len = strlen(str);
772.22969 -+
772.22970 -+			path = malloc(len + 1);
772.22971 -+			if (path == NULL)
772.22972 -+				return NULL;
772.22973 -+
772.22974 -+			memcpy(path, str, len);
772.22975 -+			path[len] = '\0';
772.22976 -+			return path;
772.22977 -+		}
772.22978 -+
772.22979 -+		str = strchr(colon + 1, ',');
772.22980 -+		if (str == NULL)
772.22981 -+			return NULL;
772.22982 -+
772.22983 -+		str++;
772.22984 -+	} while (1);
772.22985 -+}
772.22986 -+
772.22987 -+static void
772.22988 -+sna_output_load_fake_edid(xf86OutputPtr output)
772.22989 -+{
772.22990 -+	struct sna_output *sna_output = output->driver_private;
772.22991 -+	const char *filename;
772.22992 -+	FILE *file;
772.22993 -+	void *raw;
772.22994 -+	int size;
772.22995 -+	xf86MonPtr mon;
772.22996 -+
772.22997 -+	filename = fake_edid_name(output);
772.22998 -+	if (filename == NULL)
772.22999 -+		return;
772.23000 -+
772.23001 -+	file = fopen(filename, "rb");
772.23002 -+	if (file == NULL)
772.23003 -+		goto err;
772.23004 -+
772.23005 -+	fseek(file, 0, SEEK_END);
772.23006 -+	size = ftell(file);
772.23007 -+	if (size % 128) {
772.23008 -+		fclose(file);
772.23009 -+		goto err;
772.23010 -+	}
772.23011 -+
772.23012 -+	raw = malloc(size);
772.23013 -+	if (raw == NULL) {
772.23014 -+		fclose(file);
772.23015 -+		free(raw);
772.23016 -+		goto err;
772.23017 -+	}
772.23018 -+
772.23019 -+	fseek(file, 0, SEEK_SET);
772.23020 -+	if (fread(raw, size, 1, file) != 1) {
772.23021 -+		fclose(file);
772.23022 -+		free(raw);
772.23023 -+		goto err;
772.23024 -+	}
772.23025 -+	fclose(file);
772.23026 -+
772.23027 -+	mon = xf86InterpretEDID(output->scrn->scrnIndex, raw);
772.23028 -+	if (mon == NULL) {
772.23029 -+		free(raw);
772.23030 -+		goto err;
772.23031 -+	}
772.23032 -+
772.23033 -+	if (mon && size > 128)
772.23034 -+		mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
772.23035 -+
772.23036 -+	sna_output->fake_edid_mon = mon;
772.23037 -+	sna_output->fake_edid_raw = raw;
772.23038 -+
772.23039 -+	xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
772.23040 -+		   "Loading EDID from \"%s\" for output %s\n",
772.23041 -+		   filename, output->name);
772.23042 -+	return;
772.23043 -+
772.23044 -+err:
772.23045 -+	xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
772.23046 -+		   "Could not read EDID file \"%s\" for output %s\n",
772.23047 -+		   filename, output->name);
772.23048 -+}
772.23049 -+
772.23050 - static int
772.23051 - sna_output_add(struct sna *sna, unsigned id, unsigned serial)
772.23052 - {
772.23053 -@@ -3765,6 +4968,7 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
772.23054 - 		return -1;
772.23055 - 	}
772.23056 - 	assert(compat_conn.conn.connector_id == id);
772.23057 -+	DBG(("%s(%d): has %d associated encoders\n", __FUNCTION__, id, compat_conn.conn.count_encoders));
772.23058 - 
772.23059 - 	if (compat_conn.conn.connector_type < ARRAY_SIZE(output_names))
772.23060 - 		output_name = output_names[compat_conn.conn.connector_type];
772.23061 -@@ -3813,34 +5017,43 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
772.23062 - 	}
772.23063 - 
772.23064 - 	if (is_zaphod(scrn)) {
772.23065 --		const char *str;
772.23066 -+		unsigned zaphod_crtcs;
772.23067 - 
772.23068 --		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
772.23069 --		if (str && !sna_zaphod_match(str, name)) {
772.23070 --			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
772.23071 -+		if (!sna_zaphod_match(sna, name)) {
772.23072 -+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
772.23073 -+			     __FUNCTION__,
772.23074 -+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
772.23075 -+			     name));
772.23076 - 			return 0;
772.23077 - 		}
772.23078 - 
772.23079 --		if ((possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
772.23080 --			if (str) {
772.23081 --				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
772.23082 --					   "%s is an invalid output for screen (pipe) %d\n",
772.23083 --					   name, scrn->confScreen->device->screen);
772.23084 --				return -1;
772.23085 --			} else
772.23086 --				return 0;
772.23087 -+		zaphod_crtcs = get_zaphod_crtcs(sna);
772.23088 -+		possible_crtcs &= zaphod_crtcs;
772.23089 -+		if (possible_crtcs == 0) {
772.23090 -+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
772.23091 -+				   "%s is an invalid output for screen %d\n",
772.23092 -+				   name, scrn->confScreen->device->screen);
772.23093 -+			return -1;
772.23094 - 		}
772.23095 - 
772.23096 --		possible_crtcs = 1;
772.23097 -+		possible_crtcs >>= ffs(zaphod_crtcs) - 1;
772.23098 - 	}
772.23099 - 
772.23100 - 	sna_output = calloc(sizeof(struct sna_output), 1);
772.23101 - 	if (!sna_output)
772.23102 - 		return -1;
772.23103 - 
772.23104 -+	sna_output->connector_type = compat_conn.conn.connector_type;
772.23105 -+	sna_output->connector_type_id = compat_conn.conn.connector_type_id;
772.23106 - 	sna_output->num_props = compat_conn.conn.count_props;
772.23107 - 	sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props);
772.23108 - 	sna_output->prop_values = malloc(sizeof(uint64_t)*compat_conn.conn.count_props);
772.23109 -+	if (sna_output->prop_ids == NULL || sna_output->prop_values == NULL) {
772.23110 -+		free(sna_output->prop_ids);
772.23111 -+		free(sna_output->prop_values);
772.23112 -+		free(sna_output);
772.23113 -+		return -1;
772.23114 -+	}
772.23115 - 
772.23116 - 	compat_conn.conn.count_encoders = 0;
772.23117 - 
772.23118 -@@ -3865,16 +5078,16 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
772.23119 - 	/* Construct name from topology, and recheck if output is acceptable */
772.23120 - 	path = name_from_path(sna, sna_output, name);
772.23121 - 	if (path) {
772.23122 --		const char *str;
772.23123 --
772.23124 - 		if (output_ignored(scrn, name)) {
772.23125 - 			len = 0;
772.23126 - 			goto skip;
772.23127 - 		}
772.23128 - 
772.23129 --		str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
772.23130 --		if (str && !sna_zaphod_match(str, name)) {
772.23131 --			DBG(("%s: zaphod mismatch, want %s, have %s\n", __FUNCTION__, str, name));
772.23132 -+		if (is_zaphod(scrn) && !sna_zaphod_match(sna, name)) {
772.23133 -+			DBG(("%s: zaphod mismatch, want %s, have %s\n",
772.23134 -+			     __FUNCTION__,
772.23135 -+			     xf86GetOptValString(sna->Options, OPTION_ZAPHOD) ?: "???",
772.23136 -+			     name));
772.23137 - 			len = 0;
772.23138 - 			goto skip;
772.23139 - 		}
772.23140 -@@ -3889,7 +5102,6 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
772.23141 - 			if (strcmp(output->name, name) == 0) {
772.23142 - 				assert(output->scrn == scrn);
772.23143 - 				assert(output->funcs == &sna_output_funcs);
772.23144 --				assert(to_sna_output(output)->id == 0);
772.23145 - 				sna_output_destroy(output);
772.23146 - 				goto reset;
772.23147 - 			}
772.23148 -@@ -3935,6 +5147,8 @@ reset:
772.23149 - 	sna_output->id = compat_conn.conn.connector_id;
772.23150 - 	sna_output->is_panel = is_panel(compat_conn.conn.connector_type);
772.23151 - 	sna_output->edid_idx = find_property(sna, sna_output, "EDID");
772.23152 -+	sna_output->link_status_idx =
772.23153 -+		find_property(sna, sna_output, "link-status");
772.23154 - 	if (find_property(sna, sna_output, "scaling mode") != -1)
772.23155 - 		sna_output->add_default_modes =
772.23156 - 			xf86ReturnOptValBool(output->options, OPTION_DEFAULT_MODES, TRUE);
772.23157 -@@ -3945,10 +5159,8 @@ reset:
772.23158 - 		sna_output->dpms_mode = sna_output->prop_values[i];
772.23159 - 		DBG(("%s: found 'DPMS' (idx=%d, id=%d), initial value=%d\n",
772.23160 - 		     __FUNCTION__, i, sna_output->dpms_id, sna_output->dpms_mode));
772.23161 --	} else {
772.23162 --		sna_output->dpms_id = -1;
772.23163 -+	} else
772.23164 - 		sna_output->dpms_mode = DPMSModeOff;
772.23165 --	}
772.23166 - 
772.23167 - 	sna_output->possible_encoders = possible_encoders;
772.23168 - 	sna_output->attached_encoders = attached_encoders;
772.23169 -@@ -3963,12 +5175,13 @@ reset:
772.23170 - 	sna_output->base = output;
772.23171 - 
772.23172 - 	backlight_init(&sna_output->backlight);
772.23173 --	if (sna_output->is_panel)
772.23174 --		sna_output_backlight_init(output);
772.23175 -+	sna_output_backlight_init(output);
772.23176 - 
772.23177 - 	output->possible_crtcs = possible_crtcs & count_to_mask(sna->mode.num_real_crtc);
772.23178 - 	output->interlaceAllowed = TRUE;
772.23179 - 
772.23180 -+	sna_output_load_fake_edid(output);
772.23181 -+
772.23182 - 	if (serial) {
772.23183 - 		if (output->randr_output == NULL) {
772.23184 - 			output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), name, len, output);
772.23185 -@@ -3976,6 +5189,7 @@ reset:
772.23186 - 				goto cleanup;
772.23187 - 		}
772.23188 - 
772.23189 -+		RROutputChanged(output->randr_output, TRUE);
772.23190 - 		sna_output_create_resources(output);
772.23191 - 		RRPostPendingProperties(output->randr_output);
772.23192 - 
772.23193 -@@ -4009,38 +5223,6 @@ skip:
772.23194 - 	return len;
772.23195 - }
772.23196 - 
772.23197 --static void sna_output_del(xf86OutputPtr output)
772.23198 --{
772.23199 --	ScrnInfoPtr scrn = output->scrn;
772.23200 --	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
772.23201 --	int i;
772.23202 --
772.23203 --	DBG(("%s(%s)\n", __FUNCTION__, output->name));
772.23204 --	assert(to_sna_output(output));
772.23205 --
772.23206 --	RROutputDestroy(output->randr_output);
772.23207 --	sna_output_destroy(output);
772.23208 --
772.23209 --	while (output->probed_modes)
772.23210 --		xf86DeleteMode(&output->probed_modes, output->probed_modes);
772.23211 --
772.23212 --	free(output);
772.23213 --
772.23214 --	for (i = 0; i < config->num_output; i++)
772.23215 --		if (config->output[i] == output)
772.23216 --			break;
772.23217 --	assert(i < to_sna(scrn)->mode.num_real_output);
772.23218 --	DBG(("%s: removing output #%d of %d\n",
772.23219 --	     __FUNCTION__, i, to_sna(scrn)->mode.num_real_output));
772.23220 --
772.23221 --	for (; i < config->num_output; i++) {
772.23222 --		config->output[i] = config->output[i+1];
772.23223 --		config->output[i]->possible_clones >>= 1;
772.23224 --	}
772.23225 --	config->num_output--;
772.23226 --	to_sna(scrn)->mode.num_real_output--;
772.23227 --}
772.23228 --
772.23229 - static int output_rank(const void *A, const void *B)
772.23230 - {
772.23231 - 	const xf86OutputPtr *a = A;
772.23232 -@@ -4058,6 +5240,7 @@ static void sort_config_outputs(struct sna *sna)
772.23233 - {
772.23234 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.23235 - 	qsort(config->output, sna->mode.num_real_output, sizeof(*config->output), output_rank);
772.23236 -+	config->compat_output = 0; /* make sure it is a sane value */
772.23237 - 	sna_mode_compute_possible_outputs(sna);
772.23238 - }
772.23239 - 
772.23240 -@@ -4080,11 +5263,15 @@ static bool disable_unused_crtc(struct sna *sna)
772.23241 - 	bool update = false;
772.23242 - 	int o, c;
772.23243 - 
772.23244 -+	DBG(("%s\n", __FUNCTION__));
772.23245 -+
772.23246 - 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.23247 - 		xf86CrtcPtr crtc = config->crtc[c];
772.23248 - 
772.23249 --		if (!crtc->enabled)
772.23250 -+		if (!crtc->enabled) {
772.23251 -+			sna_crtc_disable(crtc, false);
772.23252 - 			continue;
772.23253 -+		}
772.23254 - 
772.23255 - 		for (o = 0; o < sna->mode.num_real_output; o++) {
772.23256 - 			xf86OutputPtr output = config->output[o];
772.23257 -@@ -4094,7 +5281,7 @@ static bool disable_unused_crtc(struct sna *sna)
772.23258 - 
772.23259 - 		if (o == sna->mode.num_real_output) {
772.23260 - 			DBG(("%s: CRTC:%d was enabled with no outputs\n",
772.23261 --			     __FUNCTION__, to_sna_crtc(crtc)->id));
772.23262 -+			     __FUNCTION__, sna_crtc_id(crtc)));
772.23263 - 			crtc->enabled = false;
772.23264 - 			update = true;
772.23265 - 		}
772.23266 -@@ -4108,17 +5295,145 @@ static bool disable_unused_crtc(struct sna *sna)
772.23267 - 	return update;
772.23268 - }
772.23269 - 
772.23270 --void sna_mode_discover(struct sna *sna)
772.23271 -+bool sna_mode_find_hotplug_connector(struct sna *sna, unsigned id)
772.23272 -+{
772.23273 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.23274 -+	int i;
772.23275 -+
772.23276 -+	for (i = 0; i < sna->mode.num_real_output; i++) {
772.23277 -+		struct sna_output *output = to_sna_output(config->output[i]);
772.23278 -+		if (output->id == id) {
772.23279 -+			output->reprobe = true;
772.23280 -+			return true;
772.23281 -+		}
772.23282 -+	}
772.23283 -+
772.23284 -+	return false;
772.23285 -+}
772.23286 -+
772.23287 -+static bool
772.23288 -+output_retrain_link(struct sna *sna, struct sna_output *output)
772.23289 -+{
772.23290 -+	struct sna_crtc *crtc = to_sna_crtc(output->base->crtc);
772.23291 -+	int crtc_x = crtc->offset & 0xffff;
772.23292 -+	int crtc_y = crtc->offset >> 16;
772.23293 -+
772.23294 -+	return sna_crtc_flip(sna, crtc, crtc->bo, crtc_x, crtc_y);
772.23295 -+}
772.23296 -+
772.23297 -+static bool
772.23298 -+output_check_link(struct sna *sna, struct sna_output *output)
772.23299 -+{
772.23300 -+	uint64_t link_status;
772.23301 -+
772.23302 -+	if (!output->base->crtc)
772.23303 -+		return true;
772.23304 -+
772.23305 -+	if (output->link_status_idx == -1)
772.23306 -+		return true;
772.23307 -+
772.23308 -+#define LINK_STATUS_GOOD 0
772.23309 -+	link_status = output->prop_values[output->link_status_idx];
772.23310 -+	DBG(("%s: link_status=%d\n", __FUNCTION__, link_status));
772.23311 -+	if (link_status == LINK_STATUS_GOOD)
772.23312 -+		return true;
772.23313 -+
772.23314 -+	/* Perform a modeset as required for "link-status" = BAD */
772.23315 -+	if (!output_retrain_link(sna, output))
772.23316 -+		return false;
772.23317 -+
772.23318 -+	/* Query the "link-status" again to confirm the modeset */
772.23319 -+	update_properties(sna, output);
772.23320 -+
772.23321 -+	link_status = output->prop_values[output->link_status_idx];
772.23322 -+	DBG(("%s: link_status=%d after modeset\n", __FUNCTION__, link_status));
772.23323 -+	return link_status == LINK_STATUS_GOOD;
772.23324 -+}
772.23325 -+
772.23326 -+static bool
772.23327 -+output_check_status(struct sna *sna, struct sna_output *output)
772.23328 -+{
772.23329 -+	union compat_mode_get_connector compat_conn;
772.23330 -+	struct drm_mode_modeinfo dummy;
772.23331 -+	struct drm_mode_get_blob blob;
772.23332 -+	xf86OutputStatus status;
772.23333 -+	char *edid;
772.23334 -+
772.23335 -+	VG_CLEAR(compat_conn);
772.23336 -+
772.23337 -+	compat_conn.conn.connection = -1;
772.23338 -+	compat_conn.conn.connector_id = output->id;
772.23339 -+	compat_conn.conn.count_modes = 1; /* skip detect */
772.23340 -+	compat_conn.conn.modes_ptr = (uintptr_t)&dummy;
772.23341 -+	compat_conn.conn.count_encoders = 0;
772.23342 -+	compat_conn.conn.props_ptr = (uintptr_t)output->prop_ids;
772.23343 -+	compat_conn.conn.prop_values_ptr = (uintptr_t)output->prop_values;
772.23344 -+	compat_conn.conn.count_props = output->num_props;
772.23345 -+
772.23346 -+	if (drmIoctl(sna->kgem.fd,
772.23347 -+		     DRM_IOCTL_MODE_GETCONNECTOR,
772.23348 -+		     &compat_conn.conn) == 0)
772.23349 -+		output->update_properties = false;
772.23350 -+
772.23351 -+	if (!output_check_link(sna, output))
772.23352 -+		return false;
772.23353 -+
772.23354 -+	if (output->reprobe)
772.23355 -+		return false;
772.23356 -+
772.23357 -+	switch (compat_conn.conn.connection) {
772.23358 -+	case DRM_MODE_CONNECTED:
772.23359 -+		status = XF86OutputStatusConnected;
772.23360 -+		break;
772.23361 -+	case DRM_MODE_DISCONNECTED:
772.23362 -+		status = XF86OutputStatusDisconnected;
772.23363 -+		break;
772.23364 -+	default:
772.23365 -+	case DRM_MODE_UNKNOWNCONNECTION:
772.23366 -+		status = XF86OutputStatusUnknown;
772.23367 -+		break;
772.23368 -+	}
772.23369 -+	if (output->status != status)
772.23370 -+		return false;
772.23371 -+
772.23372 -+	if (status != XF86OutputStatusConnected)
772.23373 -+		return true;
772.23374 -+
772.23375 -+	if (output->num_modes != compat_conn.conn.count_modes)
772.23376 -+		return false;
772.23377 -+
772.23378 -+	if (output->edid_len == 0)
772.23379 -+		return false;
772.23380 -+
772.23381 -+	edid = alloca(output->edid_len);
772.23382 -+
772.23383 -+	VG_CLEAR(blob);
772.23384 -+	blob.blob_id = output->prop_values[output->edid_idx];
772.23385 -+	blob.length = output->edid_len;
772.23386 -+	blob.data = (uintptr_t)edid;
772.23387 -+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
772.23388 -+		return false;
772.23389 -+
772.23390 -+	if (blob.length != output->edid_len)
772.23391 -+		return false;
772.23392 -+
772.23393 -+	return memcmp(edid, output->edid_raw, output->edid_len) == 0;
772.23394 -+}
772.23395 -+
772.23396 -+void sna_mode_discover(struct sna *sna, bool tell)
772.23397 - {
772.23398 - 	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
772.23399 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.23400 -+	bool force = sna->flags & SNA_REPROBE;
772.23401 - 	struct drm_mode_card_res res;
772.23402 --	uint32_t connectors[32];
772.23403 -+	uint32_t connectors[32], now;
772.23404 - 	unsigned changed = 0;
772.23405 - 	unsigned serial;
772.23406 - 	int i, j;
772.23407 - 
772.23408 - 	DBG(("%s()\n", __FUNCTION__));
772.23409 -+	sna->flags &= ~SNA_REPROBE;
772.23410 -+
772.23411 - 	VG_CLEAR(connectors);
772.23412 - 
772.23413 - 	memset(&res, 0, sizeof(res));
772.23414 -@@ -4128,10 +5443,11 @@ void sna_mode_discover(struct sna *sna)
772.23415 - 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
772.23416 - 		return;
772.23417 - 
772.23418 --	DBG(("%s: now %d (was %d) connectors\n", __FUNCTION__,
772.23419 --	     res.count_connectors, sna->mode.num_real_output));
772.23420 -+	DBG(("%s: now %d (was %d) connectors, %d encoders, %d crtc\n", __FUNCTION__,
772.23421 -+	     res.count_connectors, sna->mode.num_real_output,
772.23422 -+	     res.count_encoders, res.count_crtcs));
772.23423 - 	if (res.count_connectors > 32)
772.23424 --		return;
772.23425 -+		res.count_connectors = 32;
772.23426 - 
772.23427 - 	assert(sna->mode.num_real_crtc == res.count_crtcs || is_zaphod(sna->scrn));
772.23428 - 	assert(sna->mode.max_crtc_width  == res.max_width);
772.23429 -@@ -4142,6 +5458,11 @@ void sna_mode_discover(struct sna *sna)
772.23430 - 	if (serial == 0)
772.23431 - 		serial = ++sna->mode.serial;
772.23432 - 
772.23433 -+	if (force) {
772.23434 -+		changed = 4;
772.23435 -+		now = 0;
772.23436 -+	} else
772.23437 -+		now = GetTimeInMillis();
772.23438 - 	for (i = 0; i < res.count_connectors; i++) {
772.23439 - 		DBG(("%s: connector[%d] = %d\n", __FUNCTION__, i, connectors[i]));
772.23440 - 		for (j = 0; j < sna->mode.num_real_output; j++) {
772.23441 -@@ -4161,32 +5482,42 @@ void sna_mode_discover(struct sna *sna)
772.23442 - 
772.23443 - 	for (i = 0; i < sna->mode.num_real_output; i++) {
772.23444 - 		xf86OutputPtr output = config->output[i];
772.23445 -+		struct sna_output *sna_output = to_sna_output(output);
772.23446 - 
772.23447 --		if (to_sna_output(output)->id == 0)
772.23448 -+		if (sna_output->id == 0)
772.23449 - 			continue;
772.23450 - 
772.23451 --		if (to_sna_output(output)->serial == serial)
772.23452 -+		if (sna_output->serial == serial) {
772.23453 -+			if (output_check_status(sna, sna_output)) {
772.23454 -+				DBG(("%s: output %s (id=%d), retained state\n",
772.23455 -+				     __FUNCTION__, output->name, sna_output->id));
772.23456 -+				sna_output->last_detect = now;
772.23457 -+			} else {
772.23458 -+				DBG(("%s: output %s (id=%d), changed state, reprobing\n",
772.23459 -+				     __FUNCTION__, output->name, sna_output->id));
772.23460 -+				sna_output->hotplug_count++;
772.23461 -+				sna_output->last_detect = 0;
772.23462 -+				changed |= 4;
772.23463 -+			}
772.23464 - 			continue;
772.23465 -+		}
772.23466 - 
772.23467 - 		DBG(("%s: removing output %s (id=%d), serial=%u [now %u]\n",
772.23468 --		     __FUNCTION__, output->name, to_sna_output(output)->id,
772.23469 --		    to_sna_output(output)->serial, serial));
772.23470 -+		     __FUNCTION__, output->name, sna_output->id,
772.23471 -+		    sna_output->serial, serial));
772.23472 - 
772.23473 - 		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
772.23474 --			   "%s output %s\n",
772.23475 --			   sna->flags & SNA_REMOVE_OUTPUTS ? "Removed" : "Disabled",
772.23476 -+			   "Disabled output %s\n",
772.23477 - 			   output->name);
772.23478 --		if (sna->flags & SNA_REMOVE_OUTPUTS) {
772.23479 --			sna_output_del(output);
772.23480 --			i--;
772.23481 --		} else {
772.23482 --			to_sna_output(output)->id = 0;
772.23483 --			output->crtc = NULL;
772.23484 --		}
772.23485 -+		sna_output->id = 0;
772.23486 -+		sna_output->last_detect = 0;
772.23487 -+		output->crtc = NULL;
772.23488 -+		RROutputChanged(output->randr_output, TRUE);
772.23489 - 		changed |= 2;
772.23490 - 	}
772.23491 - 
772.23492 --	if (changed) {
772.23493 -+	/* Have the list of available outputs been updated? */
772.23494 -+	if (changed & 3) {
772.23495 - 		DBG(("%s: outputs changed, broadcasting\n", __FUNCTION__));
772.23496 - 
772.23497 - 		sna_mode_set_primary(sna);
772.23498 -@@ -4200,6 +5531,51 @@ void sna_mode_discover(struct sna *sna)
772.23499 - 
772.23500 - 		xf86RandR12TellChanged(screen);
772.23501 - 	}
772.23502 -+
772.23503 -+	/* If anything has changed, refresh the RandR information.
772.23504 -+	 * Note this could recurse once from udevless RRGetInfo() probes,
772.23505 -+	 * but only once.
772.23506 -+	 */
772.23507 -+	if (changed && tell)
772.23508 -+		RRGetInfo(screen, TRUE);
772.23509 -+}
772.23510 -+
772.23511 -+/* Since we only probe the current mode on startup, we may not have the full
772.23512 -+ * list of modes available until the user explicitly requests them. Fake a
772.23513 -+ * hotplug event after a second after starting to fill in any missing modes.
772.23514 -+ */
772.23515 -+static CARD32 sna_mode_coldplug(OsTimerPtr timer, CARD32 now, void *data)
772.23516 -+{
772.23517 -+	struct sna *sna = data;
772.23518 -+	ScreenPtr screen = xf86ScrnToScreen(sna->scrn);
772.23519 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.23520 -+	bool reprobe = false;
772.23521 -+	int i;
772.23522 -+
772.23523 -+	DBG(("%s()\n", __FUNCTION__));
772.23524 -+
772.23525 -+	for (i = 0; i < sna->mode.num_real_output; i++) {
772.23526 -+		xf86OutputPtr output = config->output[i];
772.23527 -+		struct sna_output *sna_output = to_sna_output(output);
772.23528 -+
772.23529 -+		if (sna_output->id == 0)
772.23530 -+			continue;
772.23531 -+		if (sna_output->last_detect)
772.23532 -+			continue;
772.23533 -+		if (output->status == XF86OutputStatusDisconnected)
772.23534 -+			continue;
772.23535 -+
772.23536 -+		DBG(("%s: output %s connected, needs reprobe\n",
772.23537 -+		     __FUNCTION__, output->name));
772.23538 -+		reprobe = true;
772.23539 -+	}
772.23540 -+
772.23541 -+	if (reprobe) {
772.23542 -+		RRGetInfo(screen, TRUE);
772.23543 -+		RRTellChanged(screen);
772.23544 -+	}
772.23545 -+	free(timer);
772.23546 -+	return 0;
772.23547 - }
772.23548 - 
772.23549 - static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
772.23550 -@@ -4208,7 +5584,7 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
772.23551 - 
772.23552 - 	DBG(("%s\n", __FUNCTION__));
772.23553 - 
772.23554 --	if (wedged(sna))
772.23555 -+	if (wedged(sna) || isGPU(sna->scrn))
772.23556 - 		return;
772.23557 - 
772.23558 - 	old_priv = sna_pixmap_force_to_gpu(old, MOVE_READ);
772.23559 -@@ -4220,12 +5596,19 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
772.23560 - 		return;
772.23561 - 
772.23562 - 	if (old_priv->clear) {
772.23563 --		(void)sna->render.fill_one(sna, new, new_priv->gpu_bo,
772.23564 --					   old_priv->clear_color,
772.23565 --					   0, 0,
772.23566 --					   new->drawable.width,
772.23567 --					   new->drawable.height,
772.23568 --					   GXcopy);
772.23569 -+		bool ok = false;
772.23570 -+		if (!wedged(sna))
772.23571 -+			ok = sna->render.fill_one(sna, new, new_priv->gpu_bo,
772.23572 -+						  old_priv->clear_color,
772.23573 -+						  0, 0,
772.23574 -+						  new->drawable.width,
772.23575 -+						  new->drawable.height,
772.23576 -+						  GXcopy);
772.23577 -+		if (!ok) {
772.23578 -+			void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
772.23579 -+			if (ptr)
772.23580 -+				memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
772.23581 -+		}
772.23582 - 		new_priv->clear = true;
772.23583 - 		new_priv->clear_color = old_priv->clear_color;
772.23584 - 	} else {
772.23585 -@@ -4281,11 +5664,18 @@ static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
772.23586 - 			     __FUNCTION__, box.x2, box.y2, sx, sy, dx, dy));
772.23587 - 
772.23588 - 			if (box.x2 != new->drawable.width || box.y2 != new->drawable.height) {
772.23589 --				(void)sna->render.fill_one(sna, new, new_priv->gpu_bo, 0,
772.23590 --							   0, 0,
772.23591 --							   new->drawable.width,
772.23592 --							   new->drawable.height,
772.23593 --							   GXclear);
772.23594 -+				bool ok = false;
772.23595 -+				if (!wedged(sna))
772.23596 -+					ok = sna->render.fill_one(sna, new, new_priv->gpu_bo, 0,
772.23597 -+								  0, 0,
772.23598 -+								  new->drawable.width,
772.23599 -+								  new->drawable.height,
772.23600 -+								  GXclear);
772.23601 -+				if (!ok) {
772.23602 -+					void *ptr = kgem_bo_map__gtt(&sna->kgem, new_priv->gpu_bo);
772.23603 -+					if (ptr)
772.23604 -+						memset(ptr, 0, new_priv->gpu_bo->pitch*new->drawable.height);
772.23605 -+				}
772.23606 - 			}
772.23607 - 			(void)sna->render.copy_boxes(sna, GXcopy,
772.23608 - 						     &old->drawable, old_priv->gpu_bo, sx, sy,
772.23609 -@@ -4302,7 +5692,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.23610 - {
772.23611 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
772.23612 - 	struct sna *sna = to_sna(scrn);
772.23613 --	ScreenPtr screen = scrn->pScreen;
772.23614 -+	ScreenPtr screen = xf86ScrnToScreen(scrn);
772.23615 - 	PixmapPtr new_front;
772.23616 - 	int i;
772.23617 - 
772.23618 -@@ -4337,9 +5727,20 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.23619 - 	for (i = 0; i < sna->mode.num_real_crtc; i++)
772.23620 - 		sna_crtc_disable_shadow(sna, to_sna_crtc(config->crtc[i]));
772.23621 - 	assert(sna->mode.shadow_active == 0);
772.23622 -+	assert(!sna->mode.shadow_enabled);
772.23623 - 	assert(sna->mode.shadow_damage == NULL);
772.23624 - 	assert(sna->mode.shadow == NULL);
772.23625 - 
772.23626 -+	/* Flush pending shadow updates */
772.23627 -+	if (sna->mode.flip_active) {
772.23628 -+		DBG(("%s: waiting for %d outstanding TearFree flips\n",
772.23629 -+		     __FUNCTION__, sna->mode.flip_active));
772.23630 -+		while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
772.23631 -+			sna_mode_wakeup(sna);
772.23632 -+	}
772.23633 -+
772.23634 -+	/* Cancel a pending [un]flip (as the pixmaps no longer match) */
772.23635 -+	sna_present_cancel_flip(sna);
772.23636 - 	copy_front(sna, sna->front, new_front);
772.23637 - 
772.23638 - 	screen->SetScreenPixmap(new_front);
772.23639 -@@ -4351,14 +5752,6 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.23640 - 	scrn->virtualY = height;
772.23641 - 	scrn->displayWidth = width;
772.23642 - 
772.23643 --	/* Flush pending shadow updates */
772.23644 --	if (sna->mode.flip_active) {
772.23645 --		DBG(("%s: waiting for %d outstanding TearFree flips\n",
772.23646 --		     __FUNCTION__, sna->mode.flip_active));
772.23647 --		while (sna->mode.flip_active && sna_mode_wait_for_event(sna))
772.23648 --			sna_mode_wakeup(sna);
772.23649 --	}
772.23650 --
772.23651 - 	/* Only update the CRTCs if we are in control */
772.23652 - 	if (!scrn->vtSema)
772.23653 - 		return TRUE;
772.23654 -@@ -4371,7 +5764,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.23655 - 			continue;
772.23656 - 
772.23657 - 		if (!__sna_crtc_set_mode(crtc))
772.23658 --			sna_crtc_disable(crtc);
772.23659 -+			sna_crtc_disable(crtc, false);
772.23660 - 	}
772.23661 - 
772.23662 - 	sna_mode_wakeup(sna);
772.23663 -@@ -4381,19 +5774,6 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.23664 - }
772.23665 - 
772.23666 - /* cursor handling */
772.23667 --struct sna_cursor {
772.23668 --	struct sna_cursor *next;
772.23669 --	uint32_t *image;
772.23670 --	Rotation rotation;
772.23671 --	int ref;
772.23672 --	int size;
772.23673 --	int last_width;
772.23674 --	int last_height;
772.23675 --	unsigned handle;
772.23676 --	unsigned serial;
772.23677 --	unsigned alloc;
772.23678 --};
772.23679 --
772.23680 - static void
772.23681 - rotate_coord(Rotation rotation, int size,
772.23682 - 	     int x_dst, int y_dst,
772.23683 -@@ -4429,36 +5809,6 @@ rotate_coord(Rotation rotation, int size,
772.23684 - 	*y_src = y_dst;
772.23685 - }
772.23686 - 
772.23687 --static void
772.23688 --rotate_coord_back(Rotation rotation, int size, int *x, int *y)
772.23689 --{
772.23690 --	int t;
772.23691 --
772.23692 --	if (rotation & RR_Reflect_X)
772.23693 --		*x = size - *x - 1;
772.23694 --	if (rotation & RR_Reflect_Y)
772.23695 --		*y = size - *y - 1;
772.23696 --
772.23697 --	switch (rotation & 0xf) {
772.23698 --	case RR_Rotate_0:
772.23699 --		break;
772.23700 --	case RR_Rotate_90:
772.23701 --		t = *x;
772.23702 --		*x = *y;
772.23703 --		*y = size - t - 1;
772.23704 --		break;
772.23705 --	case RR_Rotate_180:
772.23706 --		*x = size - *x - 1;
772.23707 --		*y = size - *y - 1;
772.23708 --		break;
772.23709 --	case RR_Rotate_270:
772.23710 --		t = *x;
772.23711 --		*x = size - *y - 1;
772.23712 --		*y = t;
772.23713 --		break;
772.23714 --	}
772.23715 --}
772.23716 --
772.23717 - static struct sna_cursor *__sna_create_cursor(struct sna *sna, int size)
772.23718 - {
772.23719 - 	struct sna_cursor *c;
772.23720 -@@ -4519,6 +5869,17 @@ static uint32_t *get_cursor_argb(CursorPtr c)
772.23721 - #endif
772.23722 - }
772.23723 - 
772.23724 -+static int __cursor_size(int width, int height)
772.23725 -+{
772.23726 -+	int i, size;
772.23727 -+
772.23728 -+	i = MAX(width, height);
772.23729 -+	for (size = 64; size < i; size <<= 1)
772.23730 -+		;
772.23731 -+
772.23732 -+	return size;
772.23733 -+}
772.23734 -+
772.23735 - static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23736 - {
772.23737 - 	struct sna_cursor *cursor;
772.23738 -@@ -4526,6 +5887,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23739 - 	const uint32_t *argb;
772.23740 - 	uint32_t *image;
772.23741 - 	int width, height, pitch, size, x, y;
772.23742 -+	bool transformed;
772.23743 - 	Rotation rotation;
772.23744 - 
772.23745 - 	assert(sna->cursor.ref);
772.23746 -@@ -4537,8 +5899,8 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23747 - 	       cursor ? cursor->serial : 0,
772.23748 - 	       sna->cursor.serial));
772.23749 - 	if (cursor && cursor->serial == sna->cursor.serial) {
772.23750 --		assert(cursor->size == sna->cursor.size);
772.23751 --		assert(cursor->rotation == crtc->transform_in_use ? crtc->rotation : RR_Rotate_0);
772.23752 -+		assert(cursor->size == sna->cursor.size || cursor->transformed);
772.23753 -+		assert(cursor->rotation == (!to_sna_crtc(crtc)->cursor_transform && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0);
772.23754 - 		assert(cursor->ref);
772.23755 - 		return cursor;
772.23756 - 	}
772.23757 -@@ -4550,22 +5912,81 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23758 - 	       sna->cursor.serial,
772.23759 - 	       get_cursor_argb(sna->cursor.ref) != NULL));
772.23760 - 
772.23761 --	rotation = crtc->transform_in_use ? crtc->rotation : RR_Rotate_0;
772.23762 -+	transformed = to_sna_crtc(crtc)->cursor_transform;
772.23763 -+	rotation = (!transformed && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0;
772.23764 -+
772.23765 -+	if (transformed) {
772.23766 -+		struct pixman_box16 box;
772.23767 -+
772.23768 -+		box.x1 = box.y1 = 0;
772.23769 -+		box.x2 = sna->cursor.ref->bits->width;
772.23770 -+		box.y2 = sna->cursor.ref->bits->height;
772.23771 - 
772.23772 --	if (sna->cursor.use_gtt) { /* Don't allow phys cursor sharing */
772.23773 -+		pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer, &box);
772.23774 -+		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
772.23775 -+		__DBG(("%s: transformed cursor %dx%d -> %dx%d\n",
772.23776 -+		       __FUNCTION__ ,
772.23777 -+		       sna->cursor.ref->bits->width,
772.23778 -+		       sna->cursor.ref->bits->height,
772.23779 -+		       box.x2 - box.x1, box.y2 - box.y1));
772.23780 -+	} else
772.23781 -+		size = sna->cursor.size;
772.23782 -+
772.23783 -+	if (crtc->transform_in_use) {
772.23784 -+		RRTransformPtr T = NULL;
772.23785 -+		struct pixman_vector v;
772.23786 -+
772.23787 -+		if (crtc->transformPresent) {
772.23788 -+			T = &crtc->transform;
772.23789 -+
772.23790 -+			/* Cancel any translation from this affine
772.23791 -+			 * transformation. We just want to rotate and scale
772.23792 -+			 * the cursor image.
772.23793 -+			 */
772.23794 -+			v.vector[0] = 0;
772.23795 -+			v.vector[1] = 0;
772.23796 -+			v.vector[2] = pixman_fixed_1;
772.23797 -+			pixman_transform_point(&crtc->transform.transform, &v);
772.23798 -+		}
772.23799 -+
772.23800 -+		RRTransformCompute(0, 0, size, size, crtc->rotation, T, NULL,
772.23801 -+				   &to_sna_crtc(crtc)->cursor_to_fb,
772.23802 -+				   &to_sna_crtc(crtc)->fb_to_cursor);
772.23803 -+		if (T)
772.23804 -+			pixman_f_transform_translate(
772.23805 -+					&to_sna_crtc(crtc)->cursor_to_fb,
772.23806 -+					&to_sna_crtc(crtc)->fb_to_cursor,
772.23807 -+					-pixman_fixed_to_double(v.vector[0]),
772.23808 -+					-pixman_fixed_to_double(v.vector[1]));
772.23809 -+
772.23810 -+		__DBG(("%s: cursor_to_fb [%f %f %f, %f %f %f, %f %f %f]\n",
772.23811 -+		       __FUNCTION__,
772.23812 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][0],
772.23813 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][1],
772.23814 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[0][2],
772.23815 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][0],
772.23816 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][1],
772.23817 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[1][2],
772.23818 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][0],
772.23819 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][1],
772.23820 -+		       to_sna_crtc(crtc)->cursor_to_fb.m[2][2]));
772.23821 -+	}
772.23822 -+
772.23823 -+	/* Don't allow phys cursor sharing */
772.23824 -+	if (sna->cursor.use_gtt && !transformed) {
772.23825 - 		for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) {
772.23826 --			if (cursor->serial == sna->cursor.serial && cursor->rotation == rotation) {
772.23827 -+			if (cursor->serial == sna->cursor.serial &&
772.23828 -+			    cursor->rotation == rotation &&
772.23829 -+			    !cursor->transformed) {
772.23830 - 				__DBG(("%s: reusing handle=%d, serial=%d, rotation=%d, size=%d\n",
772.23831 - 				       __FUNCTION__, cursor->handle, cursor->serial, cursor->rotation, cursor->size));
772.23832 - 				assert(cursor->size == sna->cursor.size);
772.23833 - 				return cursor;
772.23834 - 			}
772.23835 - 		}
772.23836 --
772.23837 --		cursor = to_sna_crtc(crtc)->cursor;
772.23838 - 	}
772.23839 - 
772.23840 --	size = sna->cursor.size;
772.23841 -+	cursor = to_sna_crtc(crtc)->cursor;
772.23842 - 	if (cursor && cursor->alloc < 4*size*size)
772.23843 - 		cursor = NULL;
772.23844 - 
772.23845 -@@ -4577,7 +5998,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23846 - 		}
772.23847 - 	}
772.23848 - 
772.23849 --	width = sna->cursor.ref->bits->width;
772.23850 -+	width  = sna->cursor.ref->bits->width;
772.23851 - 	height = sna->cursor.ref->bits->height;
772.23852 - 	source = sna->cursor.ref->bits->source;
772.23853 - 	mask = sna->cursor.ref->bits->mask;
772.23854 -@@ -4585,7 +6006,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23855 - 	pitch = BitmapBytePad(width);
772.23856 - 
772.23857 - 	image = cursor->image;
772.23858 --	if (image == NULL) {
772.23859 -+	if (image == NULL || transformed) {
772.23860 - 		image = sna->cursor.scratch;
772.23861 - 		cursor->last_width = cursor->last_height = size;
772.23862 - 	}
772.23863 -@@ -4616,6 +6037,21 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23864 - 				mask += pitch;
772.23865 - 				source += pitch;
772.23866 - 			}
772.23867 -+			if (transformed) {
772.23868 -+				__DBG(("%s: Applying affine BLT to bitmap\n", __FUNCTION__));
772.23869 -+				affine_blt(image, cursor->image, 32,
772.23870 -+					   0, 0, width, height, size * 4,
772.23871 -+					   0, 0, size, size, size * 4,
772.23872 -+					   &to_sna_crtc(crtc)->cursor_to_fb);
772.23873 -+				image = cursor->image;
772.23874 -+			}
772.23875 -+		} else if (transformed) {
772.23876 -+			__DBG(("%s: Applying affine BLT to ARGB\n", __FUNCTION__));
772.23877 -+			affine_blt(argb, cursor->image, 32,
772.23878 -+				   0, 0, width, height, width * 4,
772.23879 -+				   0, 0, size, size, size * 4,
772.23880 -+				   &to_sna_crtc(crtc)->cursor_to_fb);
772.23881 -+			image = cursor->image;
772.23882 - 		} else
772.23883 - 			memcpy_blt(argb, image, 32,
772.23884 - 				   width * 4, size * 4,
772.23885 -@@ -4662,9 +6098,16 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
772.23886 - 
772.23887 - 	cursor->size = size;
772.23888 - 	cursor->rotation = rotation;
772.23889 -+	cursor->transformed = transformed;
772.23890 - 	cursor->serial = sna->cursor.serial;
772.23891 --	cursor->last_width = width;
772.23892 --	cursor->last_height = height;
772.23893 -+	if (transformed) {
772.23894 -+		/* mark the transformed rectangle as dirty, not input */
772.23895 -+		cursor->last_width = size;
772.23896 -+		cursor->last_height = size;
772.23897 -+	} else {
772.23898 -+		cursor->last_width = width;
772.23899 -+		cursor->last_height = height;
772.23900 -+	}
772.23901 - 	return cursor;
772.23902 - }
772.23903 - 
772.23904 -@@ -4674,40 +6117,55 @@ sna_realize_cursor(xf86CursorInfoPtr info, CursorPtr cursor)
772.23905 - 	return NULL;
772.23906 - }
772.23907 - 
772.23908 --#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
772.23909 --static inline int sigio_block(void)
772.23910 --{
772.23911 --	OsBlockSIGIO();
772.23912 --	return 0;
772.23913 --}
772.23914 --static inline void sigio_unblock(int was_blocked)
772.23915 -+static void enable_fb_access(ScrnInfoPtr scrn, int state)
772.23916 - {
772.23917 --	OsReleaseSIGIO();
772.23918 --	(void)was_blocked;
772.23919 --}
772.23920 -+	scrn->EnableDisableFBAccess(
772.23921 -+#ifdef XF86_HAS_SCRN_CONV
772.23922 -+				    scrn,
772.23923 - #else
772.23924 --#include <xf86_OSproc.h>
772.23925 --static inline int sigio_block(void)
772.23926 -+				    scrn->scrnIndex,
772.23927 -+#endif
772.23928 -+				    state);
772.23929 -+}
772.23930 -+
772.23931 -+
772.23932 -+static void __restore_swcursor(ScrnInfoPtr scrn)
772.23933 - {
772.23934 --	return xf86BlockSIGIO();
772.23935 -+	DBG(("%s: attempting to restore SW cursor\n", __FUNCTION__));
772.23936 -+	enable_fb_access(scrn, FALSE);
772.23937 -+	enable_fb_access(scrn, TRUE);
772.23938 -+
772.23939 -+	RemoveBlockAndWakeupHandlers((void *)__restore_swcursor,
772.23940 -+				     (void *)NoopDDA,
772.23941 -+				     scrn);
772.23942 - }
772.23943 --static inline void sigio_unblock(int was_blocked)
772.23944 -+
772.23945 -+static void restore_swcursor(struct sna *sna)
772.23946 - {
772.23947 --	xf86UnblockSIGIO(was_blocked);
772.23948 -+	sna->cursor.info->HideCursor(sna->scrn);
772.23949 -+
772.23950 -+	/* XXX Force the cursor to be restored (avoiding recursion) */
772.23951 -+	FreeCursor(sna->cursor.ref, None);
772.23952 -+	sna->cursor.ref = NULL;
772.23953 -+
772.23954 -+	RegisterBlockAndWakeupHandlers((void *)__restore_swcursor,
772.23955 -+				       (void *)NoopDDA,
772.23956 -+				       sna->scrn);
772.23957 - }
772.23958 --#endif
772.23959 - 
772.23960 - static void
772.23961 - sna_show_cursors(ScrnInfoPtr scrn)
772.23962 - {
772.23963 - 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
772.23964 - 	struct sna *sna = to_sna(scrn);
772.23965 -+	struct kmsg kmsg;
772.23966 - 	int sigio, c;
772.23967 - 
772.23968 - 	DBG(("%s: cursor?=%d\n", __FUNCTION__, sna->cursor.ref != NULL));
772.23969 - 	if (sna->cursor.ref == NULL)
772.23970 - 		return;
772.23971 - 
772.23972 -+	kmsg_open(&kmsg);
772.23973 - 	sigio = sigio_block();
772.23974 - 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.23975 - 		xf86CrtcPtr crtc = xf86_config->crtc[c];
772.23976 -@@ -4721,7 +6179,7 @@ sna_show_cursors(ScrnInfoPtr scrn)
772.23977 - 
772.23978 - 		if (!crtc->cursor_in_range) {
772.23979 - 			DBG(("%s: skipping cursor outside CRTC (pipe=%d)\n",
772.23980 --			     __FUNCTION__, sna_crtc->pipe));
772.23981 -+			     __FUNCTION__, sna_crtc_pipe(crtc)));
772.23982 - 			continue;
772.23983 - 		}
772.23984 - 
772.23985 -@@ -4729,20 +6187,21 @@ sna_show_cursors(ScrnInfoPtr scrn)
772.23986 - 		if (cursor == NULL ||
772.23987 - 		    (sna_crtc->cursor == cursor && sna_crtc->last_cursor_size == cursor->size)) {
772.23988 - 			DBG(("%s: skipping cursor already show on CRTC (pipe=%d)\n",
772.23989 --			     __FUNCTION__, sna_crtc->pipe));
772.23990 -+			     __FUNCTION__, sna_crtc_pipe(crtc)));
772.23991 - 			continue;
772.23992 - 		}
772.23993 - 
772.23994 - 		DBG(("%s: CRTC pipe=%d, handle->%d\n", __FUNCTION__,
772.23995 --		     sna_crtc->pipe, cursor->handle));
772.23996 -+		     sna_crtc_pipe(crtc), cursor->handle));
772.23997 - 
772.23998 - 		VG_CLEAR(arg);
772.23999 - 		arg.flags = DRM_MODE_CURSOR_BO;
772.24000 --		arg.crtc_id = sna_crtc->id;
772.24001 -+		arg.crtc_id = __sna_crtc_id(sna_crtc);
772.24002 - 		arg.width = arg.height = cursor->size;
772.24003 - 		arg.handle = cursor->handle;
772.24004 - 
772.24005 --		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
772.24006 -+		if (!FAIL_CURSOR_IOCTL &&
772.24007 -+		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
772.24008 - 			if (sna_crtc->cursor) {
772.24009 - 				assert(sna_crtc->cursor->ref > 0);
772.24010 - 				sna_crtc->cursor->ref--;
772.24011 -@@ -4750,10 +6209,18 @@ sna_show_cursors(ScrnInfoPtr scrn)
772.24012 - 			cursor->ref++;
772.24013 - 			sna_crtc->cursor = cursor;
772.24014 - 			sna_crtc->last_cursor_size = cursor->size;
772.24015 -+		} else {
772.24016 -+			ERR(("%s: failed to show cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
772.24017 -+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
772.24018 -+			sna->cursor.disable = true;
772.24019 - 		}
772.24020 - 	}
772.24021 - 	sigio_unblock(sigio);
772.24022 - 	sna->cursor.active = true;
772.24023 -+	kmsg_close(&kmsg, sna->cursor.disable);
772.24024 -+
772.24025 -+	if (unlikely(sna->cursor.disable))
772.24026 -+		restore_swcursor(sna);
772.24027 - }
772.24028 - 
772.24029 - static void
772.24030 -@@ -4789,24 +6256,45 @@ static void
772.24031 - sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc)
772.24032 - {
772.24033 - 	struct drm_mode_cursor arg;
772.24034 -+	int sigio;
772.24035 - 
772.24036 - 	if (!crtc->cursor)
772.24037 - 		return;
772.24038 - 
772.24039 --	DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, crtc->id, crtc->cursor->handle));
772.24040 --	assert(crtc->cursor->ref);
772.24041 -+	sigio = sigio_block();
772.24042 -+	if (crtc->cursor) {
772.24043 -+		DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), crtc->cursor->handle));
772.24044 -+		assert(crtc->cursor->ref > 0);
772.24045 -+		crtc->cursor->ref--;
772.24046 -+		crtc->cursor = NULL;
772.24047 -+		crtc->last_cursor_size = 0;
772.24048 - 
772.24049 --	VG_CLEAR(arg);
772.24050 --	arg.flags = DRM_MODE_CURSOR_BO;
772.24051 --	arg.crtc_id = crtc->id;
772.24052 --	arg.width = arg.height = 0;
772.24053 --	arg.handle = 0;
772.24054 -+		VG_CLEAR(arg);
772.24055 -+		arg.flags = DRM_MODE_CURSOR_BO;
772.24056 -+		arg.crtc_id = __sna_crtc_id(crtc);
772.24057 -+		arg.width = arg.height = 0;
772.24058 -+		arg.handle = 0;
772.24059 - 
772.24060 --	(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
772.24061 --	assert(crtc->cursor->ref > 0);
772.24062 --	crtc->cursor->ref--;
772.24063 --	crtc->cursor = NULL;
772.24064 --	crtc->last_cursor_size = 0;
772.24065 -+		(void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg);
772.24066 -+	}
772.24067 -+	sigio_unblock(sigio);
772.24068 -+}
772.24069 -+
772.24070 -+static void
772.24071 -+sna_disable_cursors(ScrnInfoPtr scrn)
772.24072 -+{
772.24073 -+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
772.24074 -+	struct sna *sna = to_sna(scrn);
772.24075 -+	int sigio, c;
772.24076 -+
772.24077 -+	DBG(("%s\n", __FUNCTION__));
772.24078 -+
772.24079 -+	sigio = sigio_block();
772.24080 -+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.24081 -+		assert(to_sna_crtc(xf86_config->crtc[c]));
772.24082 -+		sna_crtc_disable_cursor(sna, to_sna_crtc(xf86_config->crtc[c]));
772.24083 -+	}
772.24084 -+	sigio_unblock(sigio);
772.24085 - }
772.24086 - 
772.24087 - static void
772.24088 -@@ -4852,6 +6340,7 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
772.24089 - {
772.24090 - 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
772.24091 - 	struct sna *sna = to_sna(scrn);
772.24092 -+	struct kmsg kmsg;
772.24093 - 	int sigio, c;
772.24094 - 
772.24095 - 	__DBG(("%s(%d, %d), cursor? %d\n", __FUNCTION__,
772.24096 -@@ -4859,6 +6348,7 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
772.24097 - 	if (sna->cursor.ref == NULL)
772.24098 - 		return;
772.24099 - 
772.24100 -+	kmsg_open(&kmsg);
772.24101 - 	sigio = sigio_block();
772.24102 - 	sna->cursor.last_x = x;
772.24103 - 	sna->cursor.last_y = y;
772.24104 -@@ -4876,27 +6366,37 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
772.24105 - 
772.24106 - 		VG_CLEAR(arg);
772.24107 - 		arg.flags = 0;
772.24108 --		arg.crtc_id = sna_crtc->id;
772.24109 -+		arg.crtc_id = __sna_crtc_id(sna_crtc);
772.24110 - 		arg.handle = 0;
772.24111 - 
772.24112 - 		if (sna_crtc->bo == NULL)
772.24113 - 			goto disable;
772.24114 - 
772.24115 -+		cursor = __sna_get_cursor(sna, crtc);
772.24116 -+		if (cursor == NULL)
772.24117 -+			cursor = sna_crtc->cursor;
772.24118 -+		if (cursor == NULL) {
772.24119 -+			__DBG(("%s: failed to grab cursor, disabling\n", __FUNCTION__));
772.24120 -+			goto disable;
772.24121 -+		}
772.24122 -+
772.24123 - 		if (crtc->transform_in_use) {
772.24124 - 			int xhot = sna->cursor.ref->bits->xhot;
772.24125 - 			int yhot = sna->cursor.ref->bits->yhot;
772.24126 --			struct pict_f_vector v;
772.24127 -+			struct pict_f_vector v, hot;
772.24128 - 
772.24129 --			v.v[0] = (x + xhot) + 0.5;
772.24130 --			v.v[1] = (y + yhot) + 0.5;
772.24131 --			v.v[2] = 1;
772.24132 -+			v.v[0] = x + xhot + .5;
772.24133 -+			v.v[1] = y + yhot + .5;
772.24134 -+			v.v[2] = 1.;
772.24135 - 			pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &v);
772.24136 - 
772.24137 --			rotate_coord_back(crtc->rotation, sna->cursor.size, &xhot, &yhot);
772.24138 -+			hot.v[0] = xhot;
772.24139 -+			hot.v[1] = yhot;
772.24140 -+			hot.v[2] = 1.;
772.24141 -+			pixman_f_transform_point(&sna_crtc->fb_to_cursor, &hot);
772.24142 - 
772.24143 --			/* cursor will have 0.5 added to it already so floor is sufficent */
772.24144 --			arg.x = floor(v.v[0]) - xhot;
772.24145 --			arg.y = floor(v.v[1]) - yhot;
772.24146 -+			arg.x = floor(v.v[0] - hot.v[0]);
772.24147 -+			arg.y = floor(v.v[1] - hot.v[1]);
772.24148 - 		} else {
772.24149 - 			arg.x = x - crtc->x;
772.24150 - 			arg.y = y - crtc->y;
772.24151 -@@ -4904,15 +6404,6 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
772.24152 - 
772.24153 - 		if (arg.x < crtc->mode.HDisplay && arg.x > -sna->cursor.size &&
772.24154 - 		    arg.y < crtc->mode.VDisplay && arg.y > -sna->cursor.size) {
772.24155 --			cursor = __sna_get_cursor(sna, crtc);
772.24156 --			if (cursor == NULL)
772.24157 --				cursor = sna_crtc->cursor;
772.24158 --			if (cursor == NULL) {
772.24159 --				__DBG(("%s: failed to grab cursor, disabling\n",
772.24160 --				       __FUNCTION__));
772.24161 --				goto disable;
772.24162 --			}
772.24163 --
772.24164 - 			if (sna_crtc->cursor != cursor || sna_crtc->last_cursor_size != cursor->size) {
772.24165 - 				arg.flags |= DRM_MODE_CURSOR_BO;
772.24166 - 				arg.handle = cursor->handle;
772.24167 -@@ -4932,10 +6423,13 @@ disable:
772.24168 - 		}
772.24169 - 
772.24170 - 		__DBG(("%s: CRTC:%d (%d, %d), handle=%d, flags=%x (old cursor handle=%d), move? %d, update handle? %d\n",
772.24171 --		       __FUNCTION__, sna_crtc->id, arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0,
772.24172 -+		       __FUNCTION__, __sna_crtc_id(sna_crtc), arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0,
772.24173 - 		       arg.flags & DRM_MODE_CURSOR_MOVE, arg.flags & DRM_MODE_CURSOR_BO));
772.24174 - 
772.24175 --		if (arg.flags &&
772.24176 -+		if (arg.flags == 0)
772.24177 -+			continue;
772.24178 -+
772.24179 -+		if (!FAIL_CURSOR_IOCTL &&
772.24180 - 		    drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) {
772.24181 - 			if (arg.flags & DRM_MODE_CURSOR_BO) {
772.24182 - 				if (sna_crtc->cursor) {
772.24183 -@@ -4949,9 +6443,21 @@ disable:
772.24184 - 				} else
772.24185 - 					sna_crtc->last_cursor_size = 0;
772.24186 - 			}
772.24187 -+		} else {
772.24188 -+			ERR(("%s: failed to update cursor on CRTC:%d [pipe=%d], disabling hwcursor: errno=%d\n",
772.24189 -+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc), errno));
772.24190 -+			/* XXX How to force switch back to SW cursor?
772.24191 -+			 * Right now we just want until the next cursor image
772.24192 -+			 * change, which is fairly frequent.
772.24193 -+			 */
772.24194 -+			sna->cursor.disable = true;
772.24195 - 		}
772.24196 - 	}
772.24197 - 	sigio_unblock(sigio);
772.24198 -+	kmsg_close(&kmsg, sna->cursor.disable);
772.24199 -+
772.24200 -+	if (unlikely(sna->cursor.disable))
772.24201 -+		restore_swcursor(sna);
772.24202 - }
772.24203 - 
772.24204 - #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2)
772.24205 -@@ -4978,17 +6484,6 @@ sna_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
772.24206 - {
772.24207 - }
772.24208 - 
772.24209 --static int __cursor_size(CursorPtr cursor)
772.24210 --{
772.24211 --	int i, size;
772.24212 --
772.24213 --	i = MAX(cursor->bits->width, cursor->bits->height);
772.24214 --	for (size = 64; size < i; size <<= 1)
772.24215 --		;
772.24216 --
772.24217 --	return size;
772.24218 --}
772.24219 --
772.24220 - static bool
772.24221 - sna_cursor_preallocate(struct sna *sna)
772.24222 - {
772.24223 -@@ -5006,6 +6501,50 @@ sna_cursor_preallocate(struct sna *sna)
772.24224 - 	return true;
772.24225 - }
772.24226 - 
772.24227 -+static bool
772.24228 -+transformable_cursor(struct sna *sna, CursorPtr cursor)
772.24229 -+{
772.24230 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24231 -+	int i;
772.24232 -+
772.24233 -+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24234 -+		xf86CrtcPtr crtc = config->crtc[i];
772.24235 -+		struct pixman_box16 box;
772.24236 -+		int size;
772.24237 -+
772.24238 -+		if (!to_sna_crtc(crtc)->hwcursor) {
772.24239 -+			DBG(("%s: hwcursor disabled on CRTC:%d [pipe=%d]\n",
772.24240 -+			     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc)));
772.24241 -+			return false;
772.24242 -+		}
772.24243 -+
772.24244 -+		if (!sna->cursor.use_gtt || !sna->cursor.scratch) {
772.24245 -+			DBG(("%s: unable to use GTT curosor access [%d] or no scratch [%d]\n",
772.24246 -+			     __FUNCTION__, sna->cursor.use_gtt, sna->cursor.scratch));
772.24247 -+			return false;
772.24248 -+		}
772.24249 -+
772.24250 -+		box.x1 = box.y1 = 0;
772.24251 -+		box.x2 = cursor->bits->width;
772.24252 -+		box.y2 = cursor->bits->height;
772.24253 -+
772.24254 -+		if (!pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer,
772.24255 -+					       &box)) {
772.24256 -+			DBG(("%s: unable to transform bounds\n", __FUNCTION__));
772.24257 -+			return false;
772.24258 -+		}
772.24259 -+
772.24260 -+		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
772.24261 -+		if (size > sna->cursor.max_size) {
772.24262 -+			DBG(("%s: transformed cursor size=%d too large, max=%d\n",
772.24263 -+			     __FUNCTION__, size, sna->cursor.max_size));
772.24264 -+			return false;
772.24265 -+		}
772.24266 -+	}
772.24267 -+
772.24268 -+	return true;
772.24269 -+}
772.24270 -+
772.24271 - static Bool
772.24272 - sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
772.24273 - {
772.24274 -@@ -5014,6 +6553,9 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
772.24275 - 	DBG(("%s (%dx%d)?\n", __FUNCTION__,
772.24276 - 	     cursor->bits->width, cursor->bits->height));
772.24277 - 
772.24278 -+	if (sna->cursor.disable)
772.24279 -+		return FALSE;
772.24280 -+
772.24281 - 	/* cursors are invariant */
772.24282 - 	if (cursor == sna->cursor.ref)
772.24283 - 		return TRUE;
772.24284 -@@ -5023,12 +6565,24 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
772.24285 - 		sna->cursor.ref = NULL;
772.24286 - 	}
772.24287 - 
772.24288 --	sna->cursor.size = __cursor_size(cursor);
772.24289 --	if (sna->cursor.size > sna->cursor.max_size)
772.24290 -+	sna->cursor.size =
772.24291 -+		__cursor_size(cursor->bits->width, cursor->bits->height);
772.24292 -+	if (sna->cursor.size > sna->cursor.max_size) {
772.24293 -+		DBG(("%s: cursor size=%d too large, max %d: using sw cursor\n",
772.24294 -+		     __FUNCTION__, sna->cursor.size, sna->cursor.max_size));
772.24295 - 		return FALSE;
772.24296 -+	}
772.24297 -+
772.24298 -+	if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) {
772.24299 -+		DBG(("%s: RandR active [%d] and non-transformable cursor: using sw cursor\n",
772.24300 -+		     __FUNCTION__, sna->mode.rr_active));
772.24301 -+		return FALSE;
772.24302 -+	}
772.24303 - 
772.24304 --	if (!sna_cursor_preallocate(sna))
772.24305 -+	if (!sna_cursor_preallocate(sna)) {
772.24306 -+		DBG(("%s: cursor preallocation failed: using sw cursor\n", __FUNCTION__));
772.24307 - 		return FALSE;
772.24308 -+	}
772.24309 - 
772.24310 - 	sna->cursor.ref = cursor;
772.24311 - 	cursor->refcnt++;
772.24312 -@@ -5056,8 +6610,12 @@ sna_cursor_pre_init(struct sna *sna)
772.24313 - 		return;
772.24314 - 
772.24315 - #define LOCAL_IOCTL_GET_CAP	DRM_IOWR(0x0c, struct local_get_cap)
772.24316 --#define DRM_CAP_CURSOR_WIDTH	8
772.24317 --#define DRM_CAP_CURSOR_HEIGHT	9
772.24318 -+#ifndef DRM_CAP_CURSOR_WIDTH
772.24319 -+#define DRM_CAP_CURSOR_WIDTH	0x8
772.24320 -+#endif
772.24321 -+#ifndef DRM_CAP_CURSOR_HEIGHT
772.24322 -+#define DRM_CAP_CURSOR_HEIGHT	0x9
772.24323 -+#endif
772.24324 - 
772.24325 - #define I915_PARAM_HAS_COHERENT_PHYS_GTT 29
772.24326 - 
772.24327 -@@ -5087,11 +6645,9 @@ sna_cursor_pre_init(struct sna *sna)
772.24328 - 	DBG(("%s: cursor updates use_gtt?=%d\n",
772.24329 - 	     __FUNCTION__, sna->cursor.use_gtt));
772.24330 - 
772.24331 --	if (!sna->cursor.use_gtt) {
772.24332 --		sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4);
772.24333 --		if (!sna->cursor.scratch)
772.24334 --			sna->cursor.max_size = 0;
772.24335 --	}
772.24336 -+	sna->cursor.scratch = malloc(sna->cursor.max_size * sna->cursor.max_size * 4);
772.24337 -+	if (!sna->cursor.scratch && !sna->cursor.use_gtt)
772.24338 -+		sna->cursor.max_size = 0;
772.24339 - 
772.24340 - 	sna->cursor.num_stash = -sna->mode.num_real_crtc;
772.24341 - 
772.24342 -@@ -5193,7 +6749,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
772.24343 - 	int output_count = 0;
772.24344 - 	int i;
772.24345 - 
772.24346 --	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, crtc->id, crtc->pipe, bo->handle));
772.24347 -+	DBG(("%s CRTC:%d [pipe=%d], handle=%d\n", __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), bo->handle));
772.24348 - 
772.24349 - 	assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids));
772.24350 - 	assert(crtc->bo);
772.24351 -@@ -5207,11 +6763,11 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
772.24352 - 
772.24353 - 		DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
772.24354 - 		     __FUNCTION__, output->name, i, to_connector_id(output),
772.24355 --		     crtc->id, crtc->pipe,
772.24356 -+		     __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
772.24357 - 		     (uint32_t)output->possible_crtcs,
772.24358 - 		     (uint32_t)output->possible_clones));
772.24359 - 
772.24360 --		assert(output->possible_crtcs & (1 << crtc->pipe) ||
772.24361 -+		assert(output->possible_crtcs & (1 << __sna_crtc_pipe(crtc)) ||
772.24362 - 		       is_zaphod(sna->scrn));
772.24363 - 
772.24364 - 		output_ids[output_count] = to_connector_id(output);
772.24365 -@@ -5221,7 +6777,7 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
772.24366 - 	assert(output_count);
772.24367 - 
772.24368 - 	VG_CLEAR(arg);
772.24369 --	arg.crtc_id = crtc->id;
772.24370 -+	arg.crtc_id = __sna_crtc_id(crtc);
772.24371 - 	arg.fb_id = fb_id(bo);
772.24372 - 	assert(arg.fb_id);
772.24373 - 	arg.x = x;
772.24374 -@@ -5231,20 +6787,74 @@ sna_crtc_flip(struct sna *sna, struct sna_crtc *crtc, struct kgem_bo *bo, int x,
772.24375 - 	arg.mode = crtc->kmode;
772.24376 - 	arg.mode_valid = 1;
772.24377 - 
772.24378 --	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d across %d outputs [%d...]\n",
772.24379 --	     __FUNCTION__, crtc->id, crtc->pipe,
772.24380 --	     arg.mode.hdisplay,
772.24381 --	     arg.mode.vdisplay,
772.24382 --	     arg.x, arg.y,
772.24383 --	     arg.mode.clock,
772.24384 --	     arg.fb_id,
772.24385 --	     output_count, output_count ? output_ids[0] : 0));
772.24386 -+	DBG(("%s: applying crtc [%d, pipe=%d] mode=%dx%d+%d+%d@%d, fb=%d across %d outputs [%d...]\n",
772.24387 -+	     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc),
772.24388 -+	     arg.mode.hdisplay,
772.24389 -+	     arg.mode.vdisplay,
772.24390 -+	     arg.x, arg.y,
772.24391 -+	     arg.mode.clock,
772.24392 -+	     arg.fb_id,
772.24393 -+	     output_count, output_count ? output_ids[0] : 0));
772.24394 -+
772.24395 -+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
772.24396 -+		return false;
772.24397 -+
772.24398 -+	crtc->offset = y << 16 | x;
772.24399 -+	__kgem_bo_clear_dirty(bo);
772.24400 -+	return true;
772.24401 -+}
772.24402 -+
772.24403 -+static void sna_mode_restore(struct sna *sna)
772.24404 -+{
772.24405 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24406 -+	int error = 0;
772.24407 -+	int i;
772.24408 -+
772.24409 -+	assert(!sna->mode.hidden);
772.24410 -+
772.24411 -+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24412 -+		xf86CrtcPtr crtc = config->crtc[i];
772.24413 -+
772.24414 -+		assert(to_sna_crtc(crtc) != NULL);
772.24415 -+		if (to_sna_crtc(crtc)->bo == NULL)
772.24416 -+			continue;
772.24417 -+
772.24418 -+		assert(crtc->enabled);
772.24419 -+		if (!__sna_crtc_set_mode(crtc)) {
772.24420 -+			sna_crtc_disable(crtc, false);
772.24421 -+			error++;
772.24422 -+		}
772.24423 -+	}
772.24424 -+	sna_mode_wakeup(sna);
772.24425 -+	while (sna->mode.flip_active && sna_mode_wakeup(sna))
772.24426 -+		;
772.24427 -+	update_flush_interval(sna);
772.24428 -+	sna_cursors_reload(sna);
772.24429 -+	sna->mode.dirty = false;
772.24430 -+
772.24431 -+	if (error)
772.24432 -+		xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.24433 -+			   "Failed to restore display configuration\n");
772.24434 -+}
772.24435 -+
772.24436 -+bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo)
772.24437 -+{
772.24438 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24439 -+	int i;
772.24440 -+
772.24441 -+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24442 -+		struct sna_crtc *crtc = config->crtc[i]->driver_private;
772.24443 -+
772.24444 -+		if (crtc->bo == NULL)
772.24445 -+			continue;
772.24446 - 
772.24447 --	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg))
772.24448 --		return false;
772.24449 -+		if (crtc->bo == bo)
772.24450 -+			continue;
772.24451 - 
772.24452 --	crtc->offset = y << 16 | x;
772.24453 --	return true;
772.24454 -+		return true;
772.24455 -+	}
772.24456 -+
772.24457 -+	return false;
772.24458 - }
772.24459 - 
772.24460 - int
772.24461 -@@ -5256,6 +6866,7 @@ sna_page_flip(struct sna *sna,
772.24462 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24463 - 	const int width = sna->scrn->virtualX;
772.24464 - 	const int height = sna->scrn->virtualY;
772.24465 -+	int sigio;
772.24466 - 	int count = 0;
772.24467 - 	int i;
772.24468 - 
772.24469 -@@ -5263,23 +6874,26 @@ sna_page_flip(struct sna *sna,
772.24470 - 	assert(bo->refcnt);
772.24471 - 
772.24472 - 	assert((sna->flags & SNA_IS_HOSTED) == 0);
772.24473 --	assert((sna->flags & SNA_TEAR_FREE) == 0);
772.24474 - 	assert(sna->mode.flip_active == 0);
772.24475 - 	assert(sna->mode.front_active);
772.24476 -+	assert(!sna->mode.hidden);
772.24477 - 	assert(sna->scrn->vtSema);
772.24478 - 
772.24479 - 	if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0)
772.24480 - 		return 0;
772.24481 - 
772.24482 - 	kgem_bo_submit(&sna->kgem, bo);
772.24483 -+	__kgem_bo_clear_dirty(bo);
772.24484 - 
772.24485 -+	sigio = sigio_block();
772.24486 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24487 - 		struct sna_crtc *crtc = config->crtc[i]->driver_private;
772.24488 - 		struct drm_mode_crtc_page_flip arg;
772.24489 - 		uint32_t crtc_offset;
772.24490 -+		int fixup;
772.24491 - 
772.24492 - 		DBG(("%s: crtc %d id=%d, pipe=%d active? %d\n",
772.24493 --		     __FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo != NULL));
772.24494 -+		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo != NULL));
772.24495 - 		if (crtc->bo == NULL)
772.24496 - 			continue;
772.24497 - 		assert(!crtc->transform);
772.24498 -@@ -5288,13 +6902,18 @@ sna_page_flip(struct sna *sna,
772.24499 - 		assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
772.24500 - 		assert(crtc->flip_bo == NULL);
772.24501 - 
772.24502 --		arg.crtc_id = crtc->id;
772.24503 -+		assert_crtc_fb(sna, crtc);
772.24504 -+		if (data == NULL && crtc->bo == bo)
772.24505 -+			goto next_crtc;
772.24506 -+
772.24507 -+		arg.crtc_id = __sna_crtc_id(crtc);
772.24508 - 		arg.fb_id = get_fb(sna, bo, width, height);
772.24509 - 		if (arg.fb_id == 0) {
772.24510 - 			assert(count == 0);
772.24511 --			return 0;
772.24512 -+			break;
772.24513 - 		}
772.24514 - 
772.24515 -+		fixup = 0;
772.24516 - 		crtc_offset = crtc->base->y << 16 | crtc->base->x;
772.24517 - 
772.24518 - 		if (bo->pitch != crtc->bo->pitch || crtc_offset != crtc->offset) {
772.24519 -@@ -5303,7 +6922,12 @@ sna_page_flip(struct sna *sna,
772.24520 - 			     bo->pitch, crtc->bo->pitch,
772.24521 - 			     crtc_offset, crtc->offset));
772.24522 - fixup_flip:
772.24523 -+			fixup = 1;
772.24524 - 			if (crtc->bo != bo && sna_crtc_flip(sna, crtc, bo, crtc->base->x, crtc->base->y)) {
772.24525 -+update_scanout:
772.24526 -+				DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
772.24527 -+				     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout,
772.24528 -+				     bo->handle, bo->active_scanout));
772.24529 - 				assert(crtc->bo->active_scanout);
772.24530 - 				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
772.24531 - 				crtc->bo->active_scanout--;
772.24532 -@@ -5321,15 +6945,8 @@ fixup_flip:
772.24533 - 					goto next_crtc;
772.24534 - 
772.24535 - 				/* queue a flip in order to send the event */
772.24536 --			} else {
772.24537 --				if (count && !xf86SetDesiredModes(sna->scrn)) {
772.24538 --					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.24539 --						   "failed to restore display configuration\n");
772.24540 --					for (; i < sna->mode.num_real_crtc; i++)
772.24541 --						sna_crtc_disable(config->crtc[i]);
772.24542 --				}
772.24543 --				return 0;
772.24544 --			}
772.24545 -+			} else
772.24546 -+				goto error;
772.24547 - 		}
772.24548 - 
772.24549 - 		/* Only the reference crtc will finally deliver its page flip
772.24550 -@@ -5346,7 +6963,7 @@ fixup_flip:
772.24551 - 
772.24552 - retry_flip:
772.24553 - 		DBG(("%s: crtc %d id=%d, pipe=%d  --> fb %d\n",
772.24554 --		     __FUNCTION__, i, crtc->id, crtc->pipe, arg.fb_id));
772.24555 -+		     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), arg.fb_id));
772.24556 - 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
772.24557 - 			ERR(("%s: pageflip failed with err=%d\n", __FUNCTION__, errno));
772.24558 - 
772.24559 -@@ -5354,7 +6971,7 @@ retry_flip:
772.24560 - 				struct drm_mode_crtc mode;
772.24561 - 
772.24562 - 				memset(&mode, 0, sizeof(mode));
772.24563 --				mode.crtc_id = crtc->id;
772.24564 -+				mode.crtc_id = __sna_crtc_id(crtc);
772.24565 - 				drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode);
772.24566 - 
772.24567 - 				DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=%d\n",
772.24568 -@@ -5366,7 +6983,7 @@ retry_flip:
772.24569 - 					goto fixup_flip;
772.24570 - 
772.24571 - 				if (count == 0)
772.24572 --					return 0;
772.24573 -+					break;
772.24574 - 
772.24575 - 				DBG(("%s: throttling on busy flip / waiting for kernel to catch up\n", __FUNCTION__));
772.24576 - 				drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_THROTTLE, 0);
772.24577 -@@ -5375,15 +6992,25 @@ retry_flip:
772.24578 - 				goto retry_flip;
772.24579 - 			}
772.24580 - 
772.24581 -+			if (!fixup)
772.24582 -+				goto fixup_flip;
772.24583 -+
772.24584 -+error:
772.24585 - 			xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.24586 --				   "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
772.24587 --				   crtc->id, crtc->pipe, data ? "synchronous": "asynchronous");
772.24588 -+					"page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
772.24589 -+					__sna_crtc_id(crtc), __sna_crtc_pipe(crtc), data ? "synchronous": "asynchronous");
772.24590 -+
772.24591 -+			if (count || crtc->bo == bo)
772.24592 -+				sna_mode_restore(sna);
772.24593 -+
772.24594 - 			sna->flags &= ~(data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP);
772.24595 --			goto fixup_flip;
772.24596 -+			count = 0;
772.24597 -+			break;
772.24598 - 		}
772.24599 - 
772.24600 - 		if (data) {
772.24601 - 			assert(crtc->flip_bo == NULL);
772.24602 -+			assert(handler);
772.24603 - 			crtc->flip_handler = handler;
772.24604 - 			crtc->flip_data = data;
772.24605 - 			crtc->flip_bo = kgem_bo_reference(bo);
772.24606 -@@ -5391,11 +7018,15 @@ retry_flip:
772.24607 - 			crtc->flip_serial = crtc->mode_serial;
772.24608 - 			crtc->flip_pending = true;
772.24609 - 			sna->mode.flip_active++;
772.24610 --		}
772.24611 - 
772.24612 -+			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
772.24613 -+			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
772.24614 -+		} else
772.24615 -+			goto update_scanout;
772.24616 - next_crtc:
772.24617 - 		count++;
772.24618 - 	}
772.24619 -+	sigio_unblock(sigio);
772.24620 - 
772.24621 - 	DBG(("%s: page flipped %d crtcs\n", __FUNCTION__, count));
772.24622 - 	return count;
772.24623 -@@ -5471,7 +7102,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
772.24624 - 
772.24625 - 		assert(sna_crtc);
772.24626 - 
772.24627 --		lut.crtc_id = sna_crtc->id;
772.24628 -+		lut.crtc_id = __sna_crtc_id(sna_crtc);
772.24629 - 		lut.gamma_size = 256;
772.24630 - 		lut.red = (uintptr_t)(gamma);
772.24631 - 		lut.green = (uintptr_t)(gamma + 256);
772.24632 -@@ -5485,7 +7116,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
772.24633 - 		}
772.24634 - 
772.24635 - 		DBG(("%s: CRTC:%d, pipe=%d: gamma set?=%d\n",
772.24636 --		     __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
772.24637 -+		     __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
772.24638 - 		     gamma_set));
772.24639 - 		if (!gamma_set) {
772.24640 - 			int i;
772.24641 -@@ -5502,6 +7133,7 @@ static void crtc_init_gamma(xf86CrtcPtr crtc)
772.24642 - 			crtc->gamma_red = gamma;
772.24643 - 			crtc->gamma_green = gamma + 256;
772.24644 - 			crtc->gamma_blue = gamma + 2*256;
772.24645 -+			crtc->gamma_size = 256;
772.24646 - 		}
772.24647 - 	}
772.24648 - }
772.24649 -@@ -5528,6 +7160,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24650 - {
772.24651 - 	ScrnInfoPtr scrn = sna->scrn;
772.24652 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
772.24653 -+	int crtc_active, crtc_enabled;
772.24654 - 	int width, height;
772.24655 - 	int i, j;
772.24656 - 
772.24657 -@@ -5565,6 +7198,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24658 - 	}
772.24659 - 
772.24660 - 	/* Copy the existing modes on each CRTCs */
772.24661 -+	crtc_active = crtc_enabled = 0;
772.24662 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24663 - 		xf86CrtcPtr crtc = config->crtc[i];
772.24664 - 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.24665 -@@ -5577,12 +7211,12 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24666 - 
772.24667 - 		/* Retrieve the current mode */
772.24668 - 		VG_CLEAR(mode);
772.24669 --		mode.crtc_id = sna_crtc->id;
772.24670 -+		mode.crtc_id = __sna_crtc_id(sna_crtc);
772.24671 - 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
772.24672 - 			continue;
772.24673 - 
772.24674 - 		DBG(("%s: CRTC:%d, pipe=%d: has mode?=%d\n", __FUNCTION__,
772.24675 --		     sna_crtc->id, sna_crtc->pipe,
772.24676 -+		     __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc),
772.24677 - 		     mode.mode_valid && mode.mode.clock));
772.24678 - 
772.24679 - 		if (!mode.mode_valid || mode.mode.clock == 0)
772.24680 -@@ -5593,6 +7227,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24681 - 		crtc->desiredX = mode.x;
772.24682 - 		crtc->desiredY = mode.y;
772.24683 - 		crtc->desiredTransformPresent = FALSE;
772.24684 -+		crtc_active++;
772.24685 - 	}
772.24686 - 
772.24687 - 	/* Reconstruct outputs pointing to active CRTC */
772.24688 -@@ -5604,6 +7239,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24689 - 
772.24690 - 		crtc_id = (uintptr_t)output->crtc;
772.24691 - 		output->crtc = NULL;
772.24692 -+		output->status = XF86OutputStatusUnknown;
772.24693 - 		if (sna->flags & SNA_IS_SLAVED)
772.24694 - 			continue;
772.24695 - 
772.24696 -@@ -5623,7 +7259,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24697 - 			xf86CrtcPtr crtc = config->crtc[j];
772.24698 - 
772.24699 - 			assert(to_sna_crtc(crtc));
772.24700 --			if (to_sna_crtc(crtc)->id != crtc_id)
772.24701 -+			if (sna_crtc_id(crtc) != crtc_id)
772.24702 - 				continue;
772.24703 - 
772.24704 - 			if (crtc->desiredMode.status == MODE_OK) {
772.24705 -@@ -5641,18 +7277,30 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24706 - 					   "Output %s using initial mode %s on pipe %d\n",
772.24707 - 					   output->name,
772.24708 - 					   crtc->desiredMode.name,
772.24709 --					   to_sna_crtc(crtc)->pipe);
772.24710 -+					   sna_crtc_pipe(crtc));
772.24711 - 
772.24712 - 				output->crtc = crtc;
772.24713 -+				output->status = XF86OutputStatusConnected;
772.24714 - 				crtc->enabled = TRUE;
772.24715 -+				crtc_enabled++;
772.24716 -+
772.24717 -+				output_set_gamma(output, crtc);
772.24718 -+
772.24719 -+				if (output->conf_monitor) {
772.24720 -+					output->mm_width = output->conf_monitor->mon_width;
772.24721 -+					output->mm_height = output->conf_monitor->mon_height;
772.24722 -+				}
772.24723 -+
772.24724 -+#if 0
772.24725 -+				sna_output_attach_edid(output);
772.24726 -+				sna_output_attach_tile(output);
772.24727 -+#endif
772.24728 - 
772.24729 - 				if (output->mm_width == 0 || output->mm_height == 0) {
772.24730 - 					output->mm_height = (crtc->desiredMode.VDisplay * 254) / (10*DEFAULT_DPI);
772.24731 - 					output->mm_width = (crtc->desiredMode.HDisplay * 254) / (10*DEFAULT_DPI);
772.24732 - 				}
772.24733 - 
772.24734 --				output_set_gamma(output, crtc);
772.24735 --
772.24736 - 				M = calloc(1, sizeof(DisplayModeRec));
772.24737 - 				if (M) {
772.24738 - 					*M = crtc->desiredMode;
772.24739 -@@ -5673,6 +7321,12 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24740 - 		}
772.24741 - 	}
772.24742 - 
772.24743 -+	if (crtc_active != crtc_enabled) {
772.24744 -+		DBG(("%s: only enabled %d out of %d active CRTC, forcing a reconfigure\n",
772.24745 -+		     __FUNCTION__, crtc_enabled, crtc_active));
772.24746 -+		return false;
772.24747 -+	}
772.24748 -+
772.24749 - 	width = height = 0;
772.24750 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24751 - 		xf86CrtcPtr crtc = config->crtc[i];
772.24752 -@@ -5707,8 +7361,8 @@ static bool sna_probe_initial_configuration(struct sna *sna)
772.24753 - 			if (sna_output->num_modes == 0)
772.24754 - 				continue;
772.24755 - 
772.24756 --			width = sna_output->modes[0].hdisplay;
772.24757 --			height= sna_output->modes[0].vdisplay;
772.24758 -+			width  = sna_output->modes[0].hdisplay;
772.24759 -+			height = sna_output->modes[0].vdisplay;
772.24760 - 
772.24761 - 			DBG(("%s: panel '%s' is %dx%d\n",
772.24762 - 			     __FUNCTION__, output->name, width, height));
772.24763 -@@ -5788,7 +7442,7 @@ probe_capabilities(struct sna *sna)
772.24764 - 	sna->flags &= ~(SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP);
772.24765 - 	if (has_flip(sna))
772.24766 - 		sna->flags |= SNA_HAS_FLIP;
772.24767 --	if (has_flip__async(sna))
772.24768 -+	if (has_flip__async(sna) && (sna->flags & SNA_TEAR_FREE) == 0)
772.24769 - 		sna->flags |= SNA_HAS_ASYNC_FLIP;
772.24770 - 	DBG(("%s: page flips? %s, async? %s\n", __FUNCTION__,
772.24771 - 	     sna->flags & SNA_HAS_FLIP ? "enabled" : "disabled",
772.24772 -@@ -5813,12 +7467,25 @@ sna_crtc_config_notify(ScreenPtr screen)
772.24773 - 		return;
772.24774 - 	}
772.24775 - 
772.24776 -+	/* Flush any events completed by the modeset */
772.24777 -+	sna_mode_wakeup(sna);
772.24778 -+
772.24779 - 	update_flush_interval(sna);
772.24780 -+	sna->cursor.disable = false; /* Reset HW cursor until the next fail */
772.24781 - 	sna_cursors_reload(sna);
772.24782 - 
772.24783 - 	probe_capabilities(sna);
772.24784 - 	sna_present_update(sna);
772.24785 - 
772.24786 -+	/* Allow TearFree to come back on when everything is off */
772.24787 -+	if (!sna->mode.front_active && sna->flags & SNA_WANT_TEAR_FREE) {
772.24788 -+		if ((sna->flags & SNA_TEAR_FREE) == 0)
772.24789 -+			DBG(("%s: enable TearFree next modeset\n",
772.24790 -+			     __FUNCTION__));
772.24791 -+
772.24792 -+		sna->flags |= SNA_TEAR_FREE;
772.24793 -+	}
772.24794 -+
772.24795 - 	sna->mode.dirty = false;
772.24796 - }
772.24797 - 
772.24798 -@@ -5840,6 +7507,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
772.24799 - 	}
772.24800 - 
772.24801 - 	probe_capabilities(sna);
772.24802 -+	sna->mode.hidden = 1;
772.24803 - 
772.24804 - 	if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake))
772.24805 - 		num_fake = 1;
772.24806 -@@ -5855,6 +7523,9 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
772.24807 - 	if (res) {
772.24808 - 		xf86CrtcConfigPtr xf86_config;
772.24809 - 
772.24810 -+		DBG(("%s: found %d CRTC, %d encoders, %d connectors\n",
772.24811 -+		     __FUNCTION__, res->count_crtcs, res->count_encoders, res->count_connectors));
772.24812 -+
772.24813 - 		assert(res->count_crtcs);
772.24814 - 		assert(res->count_connectors);
772.24815 - 
772.24816 -@@ -5862,6 +7533,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
772.24817 - 
772.24818 - 		xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
772.24819 - 		xf86_config->xf86_crtc_notify = sna_crtc_config_notify;
772.24820 -+		xf86_config->compat_output = 0;
772.24821 - 
772.24822 - 		for (i = 0; i < res->count_crtcs; i++)
772.24823 - 			if (!sna_crtc_add(scrn, res->crtcs[i]))
772.24824 -@@ -5900,6 +7572,11 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
772.24825 - 	if (!sna_mode_fake_init(sna, num_fake))
772.24826 - 		return false;
772.24827 - 
772.24828 -+	sna->mode.shadow_size = 256;
772.24829 -+	sna->mode.shadow_events = malloc(sna->mode.shadow_size * sizeof(struct drm_event_vblank));
772.24830 -+	if (!sna->mode.shadow_events)
772.24831 -+		return false;
772.24832 -+
772.24833 - 	if (!sna_probe_initial_configuration(sna)) {
772.24834 - 		xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
772.24835 - 
772.24836 -@@ -5912,6 +7589,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
772.24837 - 		}
772.24838 - 	}
772.24839 - 	sort_config_outputs(sna);
772.24840 -+	TimerSet(NULL, 0, COLDPLUG_DELAY_MS, sna_mode_coldplug, sna);
772.24841 - 
772.24842 - 	sna_setup_provider(scrn);
772.24843 - 	return scrn->modes != NULL;
772.24844 -@@ -5921,18 +7599,58 @@ bool
772.24845 - sna_mode_wants_tear_free(struct sna *sna)
772.24846 - {
772.24847 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24848 -+	bool found = false;
772.24849 -+	FILE *file;
772.24850 - 	int i;
772.24851 - 
772.24852 -+	file = fopen("/sys/module/i915/parameters/enable_fbc", "r");
772.24853 -+	if (file) {
772.24854 -+		int fbc_enabled = 0;
772.24855 -+		int value;
772.24856 -+
772.24857 -+		if (fscanf(file, "%d", &value) == 1)
772.24858 -+			fbc_enabled = value > 0;
772.24859 -+		fclose(file);
772.24860 -+
772.24861 -+		DBG(("%s: module parameter 'enable_fbc' enabled? %d\n",
772.24862 -+		     __FUNCTION__, fbc_enabled));
772.24863 -+
772.24864 -+		if (fbc_enabled)
772.24865 -+			return true;
772.24866 -+	}
772.24867 -+
772.24868 - 	for (i = 0; i < sna->mode.num_real_output; i++) {
772.24869 - 		struct sna_output *output = to_sna_output(config->output[i]);
772.24870 - 		int id = find_property(sna, output, "Panel Self-Refresh");
772.24871 --		if (id !=-1 && output->prop_values[id] != -1) {
772.24872 -+		if (id == -1)
772.24873 -+			continue;
772.24874 -+
772.24875 -+		found = true;
772.24876 -+		if (output->prop_values[id] != -1) {
772.24877 - 			DBG(("%s: Panel Self-Refresh detected on %s\n",
772.24878 - 			     __FUNCTION__, config->output[i]->name));
772.24879 - 			return true;
772.24880 - 		}
772.24881 - 	}
772.24882 - 
772.24883 -+	if (!found) {
772.24884 -+		file = fopen("/sys/module/i915/parameters/enable_psr", "r");
772.24885 -+		if (file) {
772.24886 -+			int psr_enabled = 0;
772.24887 -+			int value;
772.24888 -+
772.24889 -+			if (fscanf(file, "%d", &value) == 1)
772.24890 -+				psr_enabled = value > 0;
772.24891 -+			fclose(file);
772.24892 -+
772.24893 -+			DBG(("%s: module parameter 'enable_psr' enabled? %d\n",
772.24894 -+			     __FUNCTION__, psr_enabled));
772.24895 -+
772.24896 -+			if (psr_enabled)
772.24897 -+				return true;
772.24898 -+		}
772.24899 -+	}
772.24900 -+
772.24901 - 	return false;
772.24902 - }
772.24903 - 
772.24904 -@@ -5955,7 +7673,7 @@ sna_mode_set_primary(struct sna *sna)
772.24905 - 
772.24906 - 		DBG(("%s: setting PrimaryOutput %s\n", __FUNCTION__, output->name));
772.24907 - 		rr->primaryOutput = output->randr_output;
772.24908 --		RROutputChanged(rr->primaryOutput, 0);
772.24909 -+		RROutputChanged(rr->primaryOutput, FALSE);
772.24910 - 		rr->layoutChanged = TRUE;
772.24911 - 		break;
772.24912 - 	}
772.24913 -@@ -5974,12 +7692,9 @@ sna_mode_disable(struct sna *sna)
772.24914 - 	if (!sna->scrn->vtSema)
772.24915 - 		return false;
772.24916 - 
772.24917 --	/* XXX we will cause previously hidden cursors to be reshown, but
772.24918 --	 * this should be a rare fixup case for severe fragmentation.
772.24919 --	 */
772.24920 --	sna_hide_cursors(sna->scrn);
772.24921 -+	sna_disable_cursors(sna->scrn);
772.24922 - 	for (i = 0; i < sna->mode.num_real_crtc; i++)
772.24923 --		sna_crtc_disable(config->crtc[i]);
772.24924 -+		sna_crtc_disable(config->crtc[i], false);
772.24925 - 	assert(sna->mode.front_active == 0);
772.24926 - 
772.24927 - 	sna_mode_wakeup(sna);
772.24928 -@@ -6001,6 +7716,11 @@ sna_mode_enable(struct sna *sna)
772.24929 - 	if (!sna->scrn->vtSema)
772.24930 - 		return;
772.24931 - 
772.24932 -+	if (sna->mode.hidden) {
772.24933 -+		DBG(("%s: hidden outputs\n", __FUNCTION__));
772.24934 -+		return;
772.24935 -+	}
772.24936 -+
772.24937 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.24938 - 		xf86CrtcPtr crtc = config->crtc[i];
772.24939 - 
772.24940 -@@ -6016,13 +7736,30 @@ sna_mode_enable(struct sna *sna)
772.24941 - 	}
772.24942 - 
772.24943 - 	update_flush_interval(sna);
772.24944 --	sna_show_cursors(sna->scrn);
772.24945 -+	sna_cursors_reload(sna);
772.24946 - 	sna->mode.dirty = false;
772.24947 - }
772.24948 - 
772.24949 -+static void sna_randr_close(struct sna *sna)
772.24950 -+{
772.24951 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24952 -+	int n;
772.24953 -+
772.24954 -+	/* The RR structs are freed early during CloseScreen as they
772.24955 -+	 * are tracked as Resources. However, we may be tempted to
772.24956 -+	 * access them during shutdown so decouple them now.
772.24957 -+	 */
772.24958 -+	  for (n = 0; n < config->num_output; n++)
772.24959 -+		  config->output[n]->randr_output = NULL;
772.24960 -+
772.24961 -+	  for (n = 0; n < config->num_crtc; n++)
772.24962 -+		  config->crtc[n]->randr_crtc = NULL;
772.24963 -+}
772.24964 -+
772.24965 - void
772.24966 - sna_mode_close(struct sna *sna)
772.24967 - {
772.24968 -+	sna_randr_close(sna);
772.24969 - 	sna_mode_wakeup(sna);
772.24970 - 
772.24971 - 	if (sna->flags & SNA_IS_HOSTED)
772.24972 -@@ -6077,15 +7814,22 @@ xf86CrtcPtr
772.24973 - sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
772.24974 - {
772.24975 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.24976 --	xf86CrtcPtr best_crtc;
772.24977 --	int best_coverage, c;
772.24978 -+	xf86CrtcPtr best_crtc = NULL;
772.24979 -+	int best_coverage = -1, c;
772.24980 - 
772.24981 - 	if (sna->flags & SNA_IS_HOSTED)
772.24982 - 		return NULL;
772.24983 - 
772.24984 - 	/* If we do not own the VT, we do not own the CRTC either */
772.24985 --	if (!sna->scrn->vtSema)
772.24986 -+	if (!sna->scrn->vtSema) {
772.24987 -+		DBG(("%s: none, VT switched\n", __FUNCTION__));
772.24988 -+		return NULL;
772.24989 -+	}
772.24990 -+
772.24991 -+	if (sna->mode.hidden) {
772.24992 -+		DBG(("%s: none, hidden outputs\n", __FUNCTION__));
772.24993 - 		return NULL;
772.24994 -+	}
772.24995 - 
772.24996 - 	DBG(("%s for box=(%d, %d), (%d, %d)\n",
772.24997 - 	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
772.24998 -@@ -6107,10 +7851,10 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
772.24999 - 			     cover_box.x2, cover_box.y2));
772.25000 - 			return desired;
772.25001 - 		}
772.25002 -+		best_crtc = desired;
772.25003 -+		best_coverage = 0;
772.25004 - 	}
772.25005 - 
772.25006 --	best_crtc = NULL;
772.25007 --	best_coverage = 0;
772.25008 - 	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.25009 - 		xf86CrtcPtr crtc = config->crtc[c];
772.25010 - 		BoxRec cover_box;
772.25011 -@@ -6156,6 +7900,38 @@ sna_covering_crtc(struct sna *sna, const BoxRec *box, xf86CrtcPtr desired)
772.25012 - 	return best_crtc;
772.25013 - }
772.25014 - 
772.25015 -+static xf86CrtcPtr first_active_crtc(struct sna *sna)
772.25016 -+{
772.25017 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.25018 -+	int n;
772.25019 -+
772.25020 -+	for (n = 0; n < sna->mode.num_real_crtc; n++) {
772.25021 -+		xf86CrtcPtr crtc = config->crtc[n];
772.25022 -+		if (to_sna_crtc(crtc)->bo)
772.25023 -+			return crtc;
772.25024 -+	}
772.25025 -+
772.25026 -+	/* No active, use the first as a placeholder */
772.25027 -+	if (sna->mode.num_real_crtc)
772.25028 -+		return config->crtc[0];
772.25029 -+
772.25030 -+	return NULL;
772.25031 -+}
772.25032 -+
772.25033 -+xf86CrtcPtr sna_primary_crtc(struct sna *sna)
772.25034 -+{
772.25035 -+	rrScrPrivPtr rr = rrGetScrPriv(xf86ScrnToScreen(sna->scrn));
772.25036 -+	if (rr && rr->primaryOutput) {
772.25037 -+		xf86OutputPtr output = rr->primaryOutput->devPrivate;
772.25038 -+		if (output->crtc &&
772.25039 -+		    output->scrn == sna->scrn &&
772.25040 -+		    to_sna_crtc(output->crtc))
772.25041 -+			return output->crtc;
772.25042 -+	}
772.25043 -+
772.25044 -+	return first_active_crtc(sna);
772.25045 -+}
772.25046 -+
772.25047 - #define MI_LOAD_REGISTER_IMM			(0x22<<23)
772.25048 - 
772.25049 - static bool sna_emit_wait_for_scanline_hsw(struct sna *sna,
772.25050 -@@ -6433,7 +8209,7 @@ sna_wait_for_scanline(struct sna *sna,
772.25051 - 		y2 /= 2;
772.25052 - 	}
772.25053 - 
772.25054 --	pipe = sna_crtc_to_pipe(crtc);
772.25055 -+	pipe = sna_crtc_pipe(crtc);
772.25056 - 	DBG(("%s: pipe=%d, y1=%d, y2=%d, full_height?=%d\n",
772.25057 - 	     __FUNCTION__, pipe, y1, y2, full_height));
772.25058 - 
772.25059 -@@ -6457,19 +8233,101 @@ sna_wait_for_scanline(struct sna *sna,
772.25060 - 	return ret;
772.25061 - }
772.25062 - 
772.25063 -+static bool sna_mode_shutdown_crtc(xf86CrtcPtr crtc)
772.25064 -+{
772.25065 -+	struct sna *sna = to_sna(crtc->scrn);
772.25066 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
772.25067 -+	bool disabled = false;
772.25068 -+	int o;
772.25069 -+
772.25070 -+	xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
772.25071 -+		   "%s: invalid state found on pipe %d, disabling CRTC:%d\n",
772.25072 -+		   __FUNCTION__,
772.25073 -+		   __sna_crtc_pipe(to_sna_crtc(crtc)),
772.25074 -+		   __sna_crtc_id(to_sna_crtc(crtc)));
772.25075 -+	sna_crtc_disable(crtc, true);
772.25076 -+#if XF86_CRTC_VERSION >= 3
772.25077 -+	crtc->active = FALSE;
772.25078 -+#endif
772.25079 -+	if (crtc->enabled) {
772.25080 -+		crtc->enabled = FALSE;
772.25081 -+		disabled = true;
772.25082 -+	}
772.25083 -+
772.25084 -+	for (o = 0; o < sna->mode.num_real_output; o++) {
772.25085 -+		xf86OutputPtr output = config->output[o];
772.25086 -+
772.25087 -+		if (output->crtc != crtc)
772.25088 -+			continue;
772.25089 -+
772.25090 -+		output->funcs->dpms(output, DPMSModeOff);
772.25091 -+		output->crtc = NULL;
772.25092 -+	}
772.25093 -+
772.25094 -+	return disabled;
772.25095 -+}
772.25096 -+
772.25097 -+static bool
772.25098 -+sna_mode_disable_secondary_planes(struct sna *sna)
772.25099 -+{
772.25100 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.25101 -+	bool disabled = false;
772.25102 -+	int c;
772.25103 -+
772.25104 -+	/* Disable all secondary planes on our CRTCs, just in case
772.25105 -+	 * other userspace left garbage in them.
772.25106 -+	 */
772.25107 -+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.25108 -+		xf86CrtcPtr crtc = config->crtc[c];
772.25109 -+		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.25110 -+		struct plane *plane;
772.25111 -+
772.25112 -+		list_for_each_entry(plane, &sna_crtc->sprites, link) {
772.25113 -+			struct local_mode_get_plane p;
772.25114 -+			struct local_mode_set_plane s;
772.25115 -+
772.25116 -+			VG_CLEAR(p);
772.25117 -+			p.plane_id = plane->id;
772.25118 -+			p.count_format_types = 0;
772.25119 -+			if (drmIoctl(sna->kgem.fd,
772.25120 -+				     LOCAL_IOCTL_MODE_GETPLANE,
772.25121 -+				     &p))
772.25122 -+				continue;
772.25123 -+
772.25124 -+			if (p.fb_id == 0 || p.crtc_id == 0)
772.25125 -+				continue;
772.25126 -+
772.25127 -+			memset(&s, 0, sizeof(s));
772.25128 -+			s.plane_id = p.plane_id;
772.25129 -+			s.crtc_id = p.crtc_id;
772.25130 -+			if (drmIoctl(sna->kgem.fd,
772.25131 -+				     LOCAL_IOCTL_MODE_SETPLANE,
772.25132 -+				     &s))
772.25133 -+				disabled |= sna_mode_shutdown_crtc(crtc);
772.25134 -+		}
772.25135 -+	}
772.25136 -+
772.25137 -+	return disabled;
772.25138 -+}
772.25139 -+
772.25140 - void sna_mode_check(struct sna *sna)
772.25141 - {
772.25142 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.25143 --	int i;
772.25144 -+	bool disabled;
772.25145 -+	int c, o;
772.25146 - 
772.25147 - 	if (sna->flags & SNA_IS_HOSTED)
772.25148 - 		return;
772.25149 - 
772.25150 --	DBG(("%s\n", __FUNCTION__));
772.25151 -+	DBG(("%s: hidden?=%d\n", __FUNCTION__, sna->mode.hidden));
772.25152 -+	if (sna->mode.hidden)
772.25153 -+		return;
772.25154 -+
772.25155 -+	disabled = sna_mode_disable_secondary_planes(sna);
772.25156 - 
772.25157 - 	/* Validate CRTC attachments and force consistency upon the kernel */
772.25158 --	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.25159 --		xf86CrtcPtr crtc = config->crtc[i];
772.25160 -+	for (c = 0; c < sna->mode.num_real_crtc; c++) {
772.25161 -+		xf86CrtcPtr crtc = config->crtc[c];
772.25162 - 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.25163 - 		struct drm_mode_crtc mode;
772.25164 - 		uint32_t expected[2];
772.25165 -@@ -6483,7 +8341,7 @@ void sna_mode_check(struct sna *sna)
772.25166 - 		expected[1] = sna_crtc->flip_bo ? fb_id(sna_crtc->flip_bo) : -1;
772.25167 - 
772.25168 - 		VG_CLEAR(mode);
772.25169 --		mode.crtc_id = sna_crtc->id;
772.25170 -+		mode.crtc_id = __sna_crtc_id(sna_crtc);
772.25171 - 		if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode))
772.25172 - 			continue;
772.25173 - 
772.25174 -@@ -6492,16 +8350,12 @@ void sna_mode_check(struct sna *sna)
772.25175 - 		     mode.crtc_id, mode.mode_valid,
772.25176 - 		     mode.fb_id, expected[0], expected[1]));
772.25177 - 
772.25178 --		if (mode.fb_id != expected[0] && mode.fb_id != expected[1]) {
772.25179 --			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
772.25180 --				   "%s: invalid state found on pipe %d, disabling CRTC:%d\n",
772.25181 --				   __FUNCTION__, sna_crtc->pipe, sna_crtc->id);
772.25182 --			sna_crtc_disable(crtc);
772.25183 --		}
772.25184 -+		if (mode.fb_id != expected[0] && mode.fb_id != expected[1])
772.25185 -+			disabled |= sna_mode_shutdown_crtc(crtc);
772.25186 - 	}
772.25187 - 
772.25188 --	for (i = 0; i < config->num_output; i++) {
772.25189 --		xf86OutputPtr output = config->output[i];
772.25190 -+	for (o = 0; o < config->num_output; o++) {
772.25191 -+		xf86OutputPtr output = config->output[o];
772.25192 - 		struct sna_output *sna_output;
772.25193 - 
772.25194 - 		if (output->crtc)
772.25195 -@@ -6515,26 +8369,16 @@ void sna_mode_check(struct sna *sna)
772.25196 - 	}
772.25197 - 
772.25198 - 	update_flush_interval(sna);
772.25199 -+
772.25200 -+	if (disabled)
772.25201 -+		xf86RandR12TellChanged(xf86ScrnToScreen(sna->scrn));
772.25202 - }
772.25203 - 
772.25204 - static bool
772.25205 - sna_crtc_hide_planes(struct sna *sna, struct sna_crtc *crtc)
772.25206 - {
772.25207 --#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane)
772.25208 --	struct local_mode_set_plane {
772.25209 --		uint32_t plane_id;
772.25210 --		uint32_t crtc_id;
772.25211 --		uint32_t fb_id; /* fb object contains surface format type */
772.25212 --		uint32_t flags;
772.25213 --
772.25214 --		/* Signed dest location allows it to be partially off screen */
772.25215 --		int32_t crtc_x, crtc_y;
772.25216 --		uint32_t crtc_w, crtc_h;
772.25217 --
772.25218 --		/* Source values are 16.16 fixed point */
772.25219 --		uint32_t src_x, src_y;
772.25220 --		uint32_t src_h, src_w;
772.25221 --	} s;
772.25222 -+	struct local_mode_set_plane s;
772.25223 -+	struct plane *plane;
772.25224 - 
772.25225 - 	if (crtc->primary.id == 0)
772.25226 - 		return false;
772.25227 -@@ -6544,8 +8388,10 @@ sna_crtc_hide_planes(struct sna *sna, struct sna_crtc *crtc)
772.25228 - 	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
772.25229 - 		return false;
772.25230 - 
772.25231 --	s.plane_id = crtc->sprite.id;
772.25232 --	(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
772.25233 -+	list_for_each_entry(plane, &crtc->sprites, link) {
772.25234 -+		s.plane_id = plane->id;
772.25235 -+		(void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s);
772.25236 -+	}
772.25237 - 
772.25238 - 	__sna_crtc_disable(sna, crtc);
772.25239 - 	return true;
772.25240 -@@ -6561,21 +8407,22 @@ void sna_mode_reset(struct sna *sna)
772.25241 - 
772.25242 - 	DBG(("%s\n", __FUNCTION__));
772.25243 - 
772.25244 --	sna_hide_cursors(sna->scrn);
772.25245 -+	sna_disable_cursors(sna->scrn);
772.25246 - 	for (i = 0; i < sna->mode.num_real_crtc; i++)
772.25247 - 		if (!sna_crtc_hide_planes(sna, to_sna_crtc(config->crtc[i])))
772.25248 --			sna_crtc_disable(config->crtc[i]);
772.25249 -+			sna_crtc_disable(config->crtc[i], true);
772.25250 - 	assert(sna->mode.front_active == 0);
772.25251 - 
772.25252 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.25253 - 		struct sna_crtc *sna_crtc = to_sna_crtc(config->crtc[i]);
772.25254 -+		struct plane *plane;
772.25255 - 
772.25256 - 		assert(sna_crtc != NULL);
772.25257 --		sna_crtc->dpms_mode = -1;
772.25258 - 
772.25259 - 		/* Force the rotation property to be reset on next use */
772.25260 - 		rotation_reset(&sna_crtc->primary);
772.25261 --		rotation_reset(&sna_crtc->sprite);
772.25262 -+		list_for_each_entry(plane, &sna_crtc->sprites, link)
772.25263 -+			rotation_reset(plane);
772.25264 - 	}
772.25265 - 
772.25266 - 	/* VT switching, likely to be fbcon so make the backlight usable */
772.25267 -@@ -6641,9 +8488,10 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25268 - {
772.25269 - 	int16_t sx, sy;
772.25270 - 	struct sna *sna = to_sna(crtc->scrn);
772.25271 --	ScreenPtr screen = sna->scrn->pScreen;
772.25272 -+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
772.25273 - 	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
772.25274 - 	PictFormatPtr format;
772.25275 -+	PictTransform T;
772.25276 - 	PicturePtr src, dst;
772.25277 - 	PixmapPtr pixmap;
772.25278 - 	int depth, error;
772.25279 -@@ -6664,6 +8512,14 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25280 - 	     __FUNCTION__, format->format, depth, draw->bitsPerPixel,
772.25281 - 	     bo->pitch, crtc->mode.HDisplay, crtc->mode.VDisplay));
772.25282 - 
772.25283 -+	if (sx | sy)
772.25284 -+		RegionTranslate(region, sx, sy);
772.25285 -+	error = !sna_drawable_move_region_to_cpu(draw, region, MOVE_READ);
772.25286 -+	if (sx | sy)
772.25287 -+		RegionTranslate(region, -sx, -sy);
772.25288 -+	if (error)
772.25289 -+		return;
772.25290 -+
772.25291 - 	ptr = kgem_bo_map__gtt(&sna->kgem, bo);
772.25292 - 	if (ptr == NULL)
772.25293 - 		return;
772.25294 -@@ -6683,9 +8539,37 @@ sna_crtc_redisplay__fallback(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25295 - 	if (!src)
772.25296 - 		goto free_pixmap;
772.25297 - 
772.25298 --	error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);
772.25299 --	if (error)
772.25300 --		goto free_src;
772.25301 -+	pixman_transform_init_translate(&T, sx << 16, sy << 16);
772.25302 -+	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
772.25303 -+	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
772.25304 -+#define f2d(x) (((double)(x))/65536.)
772.25305 -+		DBG(("%s: transform=[[%f %f %f], [%f %f %f], [%f %f %f]] (raw [[%x %x %x], [%x %x %x], [%x %x %x]])\n",
772.25306 -+		     __FUNCTION__,
772.25307 -+		     f2d(T.matrix[0][0]),
772.25308 -+		     f2d(T.matrix[0][1]),
772.25309 -+		     f2d(T.matrix[0][2]),
772.25310 -+		     f2d(T.matrix[1][0]),
772.25311 -+		     f2d(T.matrix[1][1]),
772.25312 -+		     f2d(T.matrix[1][2]),
772.25313 -+		     f2d(T.matrix[2][0]),
772.25314 -+		     f2d(T.matrix[2][1]),
772.25315 -+		     f2d(T.matrix[2][2]),
772.25316 -+		     T.matrix[0][0],
772.25317 -+		     T.matrix[0][1],
772.25318 -+		     T.matrix[0][2],
772.25319 -+		     T.matrix[1][0],
772.25320 -+		     T.matrix[1][1],
772.25321 -+		     T.matrix[1][2],
772.25322 -+		     T.matrix[2][0],
772.25323 -+		     T.matrix[2][1],
772.25324 -+		     T.matrix[2][2]));
772.25325 -+#undef f2d
772.25326 -+
772.25327 -+		error = SetPictureTransform(src, &T);
772.25328 -+		if (error)
772.25329 -+			goto free_src;
772.25330 -+		sx = sy = 0;
772.25331 -+	}
772.25332 - 
772.25333 - 	if (crtc->filter && crtc->transform_in_use)
772.25334 - 		SetPicturePictFilter(src, crtc->filter,
772.25335 -@@ -6733,10 +8617,11 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25336 - {
772.25337 - 	int16_t sx, sy;
772.25338 - 	struct sna *sna = to_sna(crtc->scrn);
772.25339 --	ScreenPtr screen = crtc->scrn->pScreen;
772.25340 -+	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
772.25341 - 	DrawablePtr draw = crtc_source(crtc, &sx, &sy);
772.25342 - 	struct sna_composite_op tmp;
772.25343 - 	PictFormatPtr format;
772.25344 -+	PictTransform T;
772.25345 - 	PicturePtr src, dst;
772.25346 - 	PixmapPtr pixmap;
772.25347 - 	const BoxRec *b;
772.25348 -@@ -6777,9 +8662,14 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25349 - 	if (!src)
772.25350 - 		goto free_pixmap;
772.25351 - 
772.25352 --	error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);
772.25353 --	if (error)
772.25354 --		goto free_src;
772.25355 -+	pixman_transform_init_translate(&T, sx << 16, sy << 16);
772.25356 -+	pixman_transform_multiply(&T, &T, &crtc->crtc_to_framebuffer);
772.25357 -+	if (!sna_transform_is_integer_translation(&T, &sx, &sy)) {
772.25358 -+		error = SetPictureTransform(src, &T);
772.25359 -+		if (error)
772.25360 -+			goto free_src;
772.25361 -+		sx = sy = 0;
772.25362 -+	}
772.25363 - 
772.25364 - 	if (crtc->filter && crtc->transform_in_use)
772.25365 - 		SetPicturePictFilter(src, crtc->filter,
772.25366 -@@ -6793,36 +8683,38 @@ sna_crtc_redisplay__composite(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo
772.25367 - 	ValidatePicture(src);
772.25368 - 	ValidatePicture(dst);
772.25369 - 
772.25370 --	if (!sna->render.composite(sna,
772.25371 --				   PictOpSrc, src, NULL, dst,
772.25372 --				   sx, sy,
772.25373 --				   0, 0,
772.25374 --				   0, 0,
772.25375 --				   crtc->mode.HDisplay, crtc->mode.VDisplay,
772.25376 --				   COMPOSITE_PARTIAL, memset(&tmp, 0, sizeof(tmp)))) {
772.25377 --		DBG(("%s: unsupported operation!\n", __FUNCTION__));
772.25378 --		sna_crtc_redisplay__fallback(crtc, region, bo);
772.25379 --		goto free_dst;
772.25380 --	}
772.25381 --
772.25382 -+	/* Composite each box individually as if we are dealing with a rotation
772.25383 -+	 * on a large display, we may have to perform intermediate copies. We
772.25384 -+	 * can then minimise the overdraw by looking at individual boxes rather
772.25385 -+	 * than the bbox.
772.25386 -+	 */
772.25387 - 	n = region_num_rects(region);
772.25388 - 	b = region_rects(region);
772.25389 - 	do {
772.25390 --		BoxRec box;
772.25391 --
772.25392 --		box = *b++;
772.25393 -+		BoxRec box = *b;
772.25394 - 		transformed_box(&box, crtc);
772.25395 - 
772.25396 - 		DBG(("%s: (%d, %d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
772.25397 - 		     __FUNCTION__,
772.25398 --		     b[-1].x1, b[-1].y1, b[-1].x2-b[-1].x1, b[-1].y2-b[-1].y1,
772.25399 -+		     b->x1, b->y1, b->x2-b->x1, b->y2-b->y1,
772.25400 - 		     box.x1, box.y1, box.x2, box.y2));
772.25401 - 
772.25402 --		tmp.box(sna, &tmp, &box);
772.25403 --	} while (--n);
772.25404 --	tmp.done(sna, &tmp);
772.25405 -+		if (!sna->render.composite(sna,
772.25406 -+					   PictOpSrc, src, NULL, dst,
772.25407 -+					   sx + box.x1, sy + box.y1,
772.25408 -+					   0, 0,
772.25409 -+					   box.x1, box.y1,
772.25410 -+					   box.x2 - box.x1, box.y2 - box.y1,
772.25411 -+					   0, memset(&tmp, 0, sizeof(tmp)))) {
772.25412 -+			DBG(("%s: unsupported operation!\n", __FUNCTION__));
772.25413 -+			sna_crtc_redisplay__fallback(crtc, region, bo);
772.25414 -+			break;
772.25415 -+		} else {
772.25416 -+			tmp.box(sna, &tmp, &box);
772.25417 -+			tmp.done(sna, &tmp);
772.25418 -+		}
772.25419 -+	} while (b++, --n);
772.25420 - 
772.25421 --free_dst:
772.25422 - 	FreePicture(dst, None);
772.25423 - free_src:
772.25424 - 	FreePicture(src, None);
772.25425 -@@ -6839,7 +8731,7 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
772.25426 - 	struct sna_pixmap *priv = sna_pixmap((PixmapPtr)draw);
772.25427 - 
772.25428 - 	DBG(("%s: crtc %d [pipe=%d], damage (%d, %d), (%d, %d) x %d\n",
772.25429 --	     __FUNCTION__, to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe,
772.25430 -+	     __FUNCTION__, sna_crtc_id(crtc), sna_crtc_pipe(crtc),
772.25431 - 	     region->extents.x1, region->extents.y1,
772.25432 - 	     region->extents.x2, region->extents.y2,
772.25433 - 	     region_num_rects(region)));
772.25434 -@@ -6898,7 +8790,10 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
772.25435 - static void shadow_flip_handler(struct drm_event_vblank *e,
772.25436 - 				void *data)
772.25437 - {
772.25438 --	sna_mode_redisplay(data);
772.25439 -+	struct sna *sna = data;
772.25440 -+
772.25441 -+	if (!sna->mode.shadow_wait)
772.25442 -+		sna_mode_redisplay(sna);
772.25443 - }
772.25444 - 
772.25445 - void sna_shadow_set_crtc(struct sna *sna,
772.25446 -@@ -6908,18 +8803,23 @@ void sna_shadow_set_crtc(struct sna *sna,
772.25447 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.25448 - 	struct sna_pixmap *priv;
772.25449 - 
772.25450 -+	assert(sna_crtc);
772.25451 - 	DBG(("%s: setting shadow override for CRTC:%d to handle=%d\n",
772.25452 --	     __FUNCTION__, sna_crtc->id, bo->handle));
772.25453 -+	     __FUNCTION__, __sna_crtc_id(sna_crtc), bo->handle));
772.25454 - 
772.25455 - 	assert(sna->flags & SNA_TEAR_FREE);
772.25456 --	assert(sna_crtc);
772.25457 - 	assert(!sna_crtc->transform);
772.25458 - 
772.25459 - 	if (sna_crtc->client_bo != bo) {
772.25460 --		if (sna_crtc->client_bo)
772.25461 -+		if (sna_crtc->client_bo) {
772.25462 -+			assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
772.25463 -+			sna_crtc->client_bo->active_scanout--;
772.25464 - 			kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
772.25465 -+		}
772.25466 - 
772.25467 - 		sna_crtc->client_bo = kgem_bo_reference(bo);
772.25468 -+		sna_crtc->client_bo->active_scanout++;
772.25469 -+		assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
772.25470 - 		sna_crtc_damage(crtc);
772.25471 - 	}
772.25472 - 
772.25473 -@@ -6969,11 +8869,13 @@ void sna_shadow_unset_crtc(struct sna *sna,
772.25474 - 	struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.25475 - 
772.25476 - 	DBG(("%s: clearin shadow override for CRTC:%d\n",
772.25477 --	     __FUNCTION__, sna_crtc->id));
772.25478 -+	     __FUNCTION__, __sna_crtc_id(sna_crtc)));
772.25479 - 
772.25480 - 	if (sna_crtc->client_bo == NULL)
772.25481 - 		return;
772.25482 - 
772.25483 -+	assert(sna_crtc->client_bo->refcnt >= sna_crtc->client_bo->active_scanout);
772.25484 -+	sna_crtc->client_bo->active_scanout--;
772.25485 - 	kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
772.25486 - 	sna_crtc->client_bo = NULL;
772.25487 - 	list_del(&sna_crtc->shadow_link);
772.25488 -@@ -6982,15 +8884,57 @@ void sna_shadow_unset_crtc(struct sna *sna,
772.25489 - 	sna_crtc_damage(crtc);
772.25490 - }
772.25491 - 
772.25492 -+static bool move_crtc_to_gpu(struct sna *sna)
772.25493 -+{
772.25494 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.25495 -+	int i;
772.25496 -+
772.25497 -+	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.25498 -+		struct sna_crtc *crtc = to_sna_crtc(config->crtc[i]);
772.25499 -+		unsigned hint;
772.25500 -+
772.25501 -+		assert(crtc);
772.25502 -+
772.25503 -+		if (crtc->bo == NULL)
772.25504 -+			continue;
772.25505 -+
772.25506 -+		if (crtc->slave_pixmap)
772.25507 -+			continue;
772.25508 -+
772.25509 -+		if (crtc->client_bo)
772.25510 -+			continue;
772.25511 -+
772.25512 -+		if (crtc->shadow_bo)
772.25513 -+			continue;
772.25514 -+
772.25515 -+		hint = MOVE_READ | MOVE_ASYNC_HINT | __MOVE_SCANOUT;
772.25516 -+		if (sna->flags & SNA_TEAR_FREE)
772.25517 -+			hint |= __MOVE_FORCE;
772.25518 -+
772.25519 -+		DBG(("%s: CRTC %d [pipe=%d] requires frontbuffer\n",
772.25520 -+		     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc)));
772.25521 -+		return sna_pixmap_move_to_gpu(sna->front, hint);
772.25522 -+	}
772.25523 -+
772.25524 -+	return true;
772.25525 -+}
772.25526 -+
772.25527 - void sna_mode_redisplay(struct sna *sna)
772.25528 - {
772.25529 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.25530 - 	RegionPtr region;
772.25531 - 	int i;
772.25532 - 
772.25533 --	if (!sna->mode.shadow_damage)
772.25534 -+	if (sna->mode.hidden) {
772.25535 -+		DBG(("%s: hidden outputs, skipping\n", __FUNCTION__));
772.25536 -+		return;
772.25537 -+	}
772.25538 -+
772.25539 -+	if (!sna->mode.shadow_enabled)
772.25540 - 		return;
772.25541 - 
772.25542 -+	assert(sna->mode.shadow_damage);
772.25543 -+
772.25544 - 	DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",
772.25545 - 	     __FUNCTION__,
772.25546 - 	     !RegionNil(DamageRegion(sna->mode.shadow_damage)),
772.25547 -@@ -7012,21 +8956,23 @@ void sna_mode_redisplay(struct sna *sna)
772.25548 - 	     region->extents.x2, region->extents.y2));
772.25549 - 
772.25550 - 	if (sna->mode.flip_active) {
772.25551 --		DamagePtr damage;
772.25552 --
772.25553 --		damage = sna->mode.shadow_damage;
772.25554 --		sna->mode.shadow_damage = NULL;
772.25555 -+		DBG(("%s: checking for %d outstanding flip completions\n",
772.25556 -+		     __FUNCTION__, sna->mode.flip_active));
772.25557 - 
772.25558 -+		sna->mode.dirty = true;
772.25559 - 		while (sna->mode.flip_active && sna_mode_wakeup(sna))
772.25560 - 			;
772.25561 -+		sna->mode.dirty = false;
772.25562 - 
772.25563 --		sna->mode.shadow_damage = damage;
772.25564 -+		DBG(("%s: now %d outstanding flip completions (enabled? %d)\n",
772.25565 -+		     __FUNCTION__,
772.25566 -+		     sna->mode.flip_active,
772.25567 -+		     sna->mode.shadow_enabled));
772.25568 -+		if (sna->mode.flip_active || !sna->mode.shadow_enabled)
772.25569 -+			return;
772.25570 - 	}
772.25571 - 
772.25572 --	if (sna->mode.flip_active)
772.25573 --		return;
772.25574 --
772.25575 --	if (wedged(sna) || !sna_pixmap_move_to_gpu(sna->front, MOVE_READ | MOVE_ASYNC_HINT | __MOVE_SCANOUT)) {
772.25576 -+	if (!move_crtc_to_gpu(sna)) {
772.25577 - 		DBG(("%s: forcing scanout update using the CPU\n", __FUNCTION__));
772.25578 - 		if (!sna_pixmap_move_to_cpu(sna->front, MOVE_READ))
772.25579 - 			return;
772.25580 -@@ -7047,90 +8993,14 @@ void sna_mode_redisplay(struct sna *sna)
772.25581 - 			damage.data = NULL;
772.25582 - 			RegionIntersect(&damage, &damage, region);
772.25583 - 			if (!box_empty(&damage.extents)) {
772.25584 --				struct kgem_bo *bo = NULL;
772.25585 --
772.25586 - 				DBG(("%s: fallback intersects pipe=%d [(%d, %d), (%d, %d)]\n",
772.25587 --				     __FUNCTION__, sna_crtc->pipe,
772.25588 -+				     __FUNCTION__, __sna_crtc_pipe(sna_crtc),
772.25589 - 				     damage.extents.x1, damage.extents.y1,
772.25590 - 				     damage.extents.x2, damage.extents.y2));
772.25591 - 
772.25592 --				if (sna->flags & SNA_TEAR_FREE) {
772.25593 --					RegionRec new_damage;
772.25594 --
772.25595 --					RegionNull(&new_damage);
772.25596 --					RegionCopy(&new_damage, &damage);
772.25597 --
772.25598 --					bo = sna_crtc->client_bo;
772.25599 --					if (bo == NULL) {
772.25600 --						damage.extents = crtc->bounds;
772.25601 --						damage.data = NULL;
772.25602 --						bo = kgem_create_2d(&sna->kgem,
772.25603 --								crtc->mode.HDisplay,
772.25604 --								crtc->mode.VDisplay,
772.25605 --								crtc->scrn->bitsPerPixel,
772.25606 --								sna_crtc->bo->tiling,
772.25607 --								CREATE_SCANOUT);
772.25608 --					} else
772.25609 --						RegionUnion(&damage, &damage, &sna_crtc->client_damage);
772.25610 --
772.25611 --					DBG(("%s: TearFree fallback, shadow handle=%d, crtc handle=%d\n", __FUNCTION__, bo->handle, sna_crtc->bo->handle));
772.25612 --
772.25613 --					sna_crtc->client_damage = new_damage;
772.25614 --				}
772.25615 --
772.25616 --				if (bo == NULL)
772.25617 --					bo = sna_crtc->bo;
772.25618 --				sna_crtc_redisplay__fallback(crtc, &damage, bo);
772.25619 --
772.25620 --				if (bo != sna_crtc->bo) {
772.25621 --					struct drm_mode_crtc_page_flip arg;
772.25622 --
772.25623 --					arg.crtc_id = sna_crtc->id;
772.25624 --					arg.fb_id = get_fb(sna, bo,
772.25625 --							   crtc->mode.HDisplay,
772.25626 --							   crtc->mode.VDisplay);
772.25627 --
772.25628 --					arg.user_data = (uintptr_t)sna_crtc;
772.25629 --					arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
772.25630 --					arg.reserved = 0;
772.25631 --
772.25632 --					if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
772.25633 --						if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
772.25634 --							assert(sna_crtc->bo->active_scanout);
772.25635 --							assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
772.25636 --							sna_crtc->bo->active_scanout--;
772.25637 --							kgem_bo_destroy(&sna->kgem, sna_crtc->bo);
772.25638 --
772.25639 --							sna_crtc->bo = bo;
772.25640 --							sna_crtc->bo->active_scanout++;
772.25641 --							sna_crtc->client_bo = NULL;
772.25642 --						} else {
772.25643 --							DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
772.25644 --							     __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
772.25645 --							xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.25646 --								   "Page flipping failed, disabling TearFree\n");
772.25647 --							sna->flags &= ~SNA_TEAR_FREE;
772.25648 --
772.25649 --							damage.extents = crtc->bounds;
772.25650 --							damage.data = NULL;
772.25651 --							sna_crtc_redisplay__fallback(crtc, &damage, sna_crtc->bo);
772.25652 --
772.25653 --							kgem_bo_destroy(&sna->kgem, bo);
772.25654 --							sna_crtc->client_bo = NULL;
772.25655 --						}
772.25656 --					} else {
772.25657 --						sna->mode.flip_active++;
772.25658 --
772.25659 --						assert(sna_crtc->flip_bo == NULL);
772.25660 --						sna_crtc->flip_handler = shadow_flip_handler;
772.25661 --						sna_crtc->flip_data = sna;
772.25662 --						sna_crtc->flip_bo = bo;
772.25663 --						sna_crtc->flip_bo->active_scanout++;
772.25664 --						sna_crtc->flip_serial = sna_crtc->mode_serial;
772.25665 --
772.25666 --						sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
772.25667 --					}
772.25668 --				}
772.25669 -+				sna_crtc_redisplay__fallback(crtc,
772.25670 -+							     &damage,
772.25671 -+							     sna_crtc->bo);
772.25672 - 			}
772.25673 - 			RegionUninit(&damage);
772.25674 - 
772.25675 -@@ -7171,6 +9041,7 @@ void sna_mode_redisplay(struct sna *sna)
772.25676 - 		xf86CrtcPtr crtc = config->crtc[i];
772.25677 - 		struct sna_crtc *sna_crtc = to_sna_crtc(crtc);
772.25678 - 		RegionRec damage;
772.25679 -+		int sigio;
772.25680 - 
772.25681 - 		assert(sna_crtc != NULL);
772.25682 - 		DBG(("%s: crtc[%d] transformed? %d\n",
772.25683 -@@ -7192,30 +9063,38 @@ void sna_mode_redisplay(struct sna *sna)
772.25684 - 		     region_num_rects(&damage),
772.25685 - 		     damage.extents.x1, damage.extents.y1,
772.25686 - 		     damage.extents.x2, damage.extents.y2));
772.25687 -+		sigio = sigio_block();
772.25688 - 		if (!box_empty(&damage.extents)) {
772.25689 - 			if (sna->flags & SNA_TEAR_FREE) {
772.25690 -+				RegionRec new_damage;
772.25691 - 				struct drm_mode_crtc_page_flip arg;
772.25692 - 				struct kgem_bo *bo;
772.25693 - 
772.25694 --				RegionUninit(&damage);
772.25695 --				damage.extents = crtc->bounds;
772.25696 --				damage.data = NULL;
772.25697 -+				RegionNull(&new_damage);
772.25698 -+				RegionCopy(&new_damage, &damage);
772.25699 - 
772.25700 --				bo = sna_crtc->client_bo;
772.25701 --				if (bo == NULL)
772.25702 -+				bo = sna_crtc->cache_bo;
772.25703 -+				if (bo == NULL) {
772.25704 -+					damage.extents = crtc->bounds;
772.25705 -+					damage.data = NULL;
772.25706 - 					bo = kgem_create_2d(&sna->kgem,
772.25707 - 							    crtc->mode.HDisplay,
772.25708 - 							    crtc->mode.VDisplay,
772.25709 - 							    crtc->scrn->bitsPerPixel,
772.25710 - 							    sna_crtc->bo->tiling,
772.25711 - 							    CREATE_SCANOUT);
772.25712 --				if (bo == NULL)
772.25713 --					goto disable1;
772.25714 -+					if (bo == NULL)
772.25715 -+						continue;
772.25716 -+				} else
772.25717 -+					RegionUnion(&damage, &damage, &sna_crtc->crtc_damage);
772.25718 -+				sna_crtc->crtc_damage = new_damage;
772.25719 - 
772.25720 - 				sna_crtc_redisplay(crtc, &damage, bo);
772.25721 - 				kgem_bo_submit(&sna->kgem, bo);
772.25722 -+				__kgem_bo_clear_dirty(bo);
772.25723 - 
772.25724 --				arg.crtc_id = sna_crtc->id;
772.25725 -+				assert_crtc_fb(sna, sna_crtc);
772.25726 -+				arg.crtc_id = __sna_crtc_id(sna_crtc);
772.25727 - 				arg.fb_id = get_fb(sna, bo,
772.25728 - 						   crtc->mode.HDisplay,
772.25729 - 						   crtc->mode.VDisplay);
772.25730 -@@ -7228,6 +9107,9 @@ void sna_mode_redisplay(struct sna *sna)
772.25731 - 
772.25732 - 				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
772.25733 - 					if (sna_crtc_flip(sna, sna_crtc, bo, 0, 0)) {
772.25734 -+						DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
772.25735 -+						     __FUNCTION__, sna_crtc->bo->handle, sna_crtc->bo->active_scanout - 1,
772.25736 -+						     bo->handle, bo->active_scanout));
772.25737 - 						assert(sna_crtc->bo->active_scanout);
772.25738 - 						assert(sna_crtc->bo->refcnt >= sna_crtc->bo->active_scanout);
772.25739 - 						sna_crtc->bo->active_scanout--;
772.25740 -@@ -7235,13 +9117,12 @@ void sna_mode_redisplay(struct sna *sna)
772.25741 - 
772.25742 - 						sna_crtc->bo = kgem_bo_reference(bo);
772.25743 - 						sna_crtc->bo->active_scanout++;
772.25744 --						sna_crtc->client_bo = kgem_bo_reference(bo);
772.25745 - 					} else {
772.25746 - 						BoxRec box;
772.25747 - 						DrawableRec tmp;
772.25748 - 
772.25749 - 						DBG(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
772.25750 --						     __FUNCTION__, arg.fb_id, i, sna_crtc->id, sna_crtc->pipe, errno));
772.25751 -+						     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc), errno));
772.25752 - 						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.25753 - 							   "Page flipping failed, disabling TearFree\n");
772.25754 - 						sna->flags &= ~SNA_TEAR_FREE;
772.25755 -@@ -7260,13 +9141,13 @@ disable1:
772.25756 - 									    &box, 1, COPY_LAST)) {
772.25757 - 							xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
772.25758 - 								   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
772.25759 --								   __FUNCTION__, sna_crtc->id, sna_crtc->pipe);
772.25760 --							sna_crtc_disable(crtc);
772.25761 -+								   __FUNCTION__, __sna_crtc_id(sna_crtc), __sna_crtc_pipe(sna_crtc));
772.25762 -+							sna_crtc_disable(crtc, false);
772.25763 - 						}
772.25764 --
772.25765 --						kgem_bo_destroy(&sna->kgem, bo);
772.25766 --						sna_crtc->client_bo = NULL;
772.25767 - 					}
772.25768 -+
772.25769 -+					kgem_bo_destroy(&sna->kgem, bo);
772.25770 -+					sna_crtc->cache_bo = NULL;
772.25771 - 					continue;
772.25772 - 				}
772.25773 - 				sna->mode.flip_active++;
772.25774 -@@ -7279,13 +9160,20 @@ disable1:
772.25775 - 				sna_crtc->flip_serial = sna_crtc->mode_serial;
772.25776 - 				sna_crtc->flip_pending = true;
772.25777 - 
772.25778 --				sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
772.25779 -+				if (sna_crtc->bo != sna->mode.shadow) {
772.25780 -+					assert_scanout(&sna->kgem, sna_crtc->bo,
772.25781 -+						       crtc->mode.HDisplay, crtc->mode.VDisplay);
772.25782 -+					sna_crtc->cache_bo = kgem_bo_reference(sna_crtc->bo);
772.25783 -+				}
772.25784 -+				DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
772.25785 -+				     __FUNCTION__, __sna_crtc_id(sna_crtc), sna_crtc->flip_bo->handle, sna_crtc->flip_bo->active_scanout, sna_crtc->flip_serial));
772.25786 - 			} else {
772.25787 - 				sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
772.25788 - 				kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
772.25789 - 			}
772.25790 - 		}
772.25791 - 		RegionUninit(&damage);
772.25792 -+		sigio_unblock(sigio);
772.25793 - 
772.25794 - 		if (sna_crtc->slave_damage)
772.25795 - 			DamageEmpty(sna_crtc->slave_damage);
772.25796 -@@ -7296,6 +9184,7 @@ disable1:
772.25797 - 		struct kgem_bo *old = sna->mode.shadow;
772.25798 - 		struct drm_mode_crtc_page_flip arg;
772.25799 - 		uint32_t fb = 0;
772.25800 -+		int sigio;
772.25801 - 
772.25802 - 		DBG(("%s: flipping TearFree outputs, current scanout handle=%d [active?=%d], new handle=%d [active=%d]\n",
772.25803 - 		     __FUNCTION__, old->handle, old->active_scanout, new->handle, new->active_scanout));
772.25804 -@@ -7307,7 +9196,9 @@ disable1:
772.25805 - 		arg.reserved = 0;
772.25806 - 
772.25807 - 		kgem_bo_submit(&sna->kgem, new);
772.25808 -+		__kgem_bo_clear_dirty(new);
772.25809 - 
772.25810 -+		sigio = sigio_block();
772.25811 - 		for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.25812 - 			struct sna_crtc *crtc = config->crtc[i]->driver_private;
772.25813 - 			struct kgem_bo *flip_bo;
772.25814 -@@ -7315,20 +9206,20 @@ disable1:
772.25815 - 
772.25816 - 			assert(crtc != NULL);
772.25817 - 			DBG(("%s: crtc %d [%d, pipe=%d] active? %d, transformed? %d\n",
772.25818 --			     __FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo ? crtc->bo->handle : 0, crtc->transform));
772.25819 -+			     __FUNCTION__, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->bo ? crtc->bo->handle : 0, crtc->transform));
772.25820 - 			if (crtc->bo == NULL || crtc->transform)
772.25821 - 				continue;
772.25822 - 
772.25823 - 			assert(config->crtc[i]->enabled);
772.25824 --			assert(crtc->dpms_mode <= DPMSModeOn);
772.25825 - 			assert(crtc->flip_bo == NULL);
772.25826 -+			assert_crtc_fb(sna, crtc);
772.25827 - 
772.25828 --			arg.crtc_id = crtc->id;
772.25829 -+			arg.crtc_id = __sna_crtc_id(crtc);
772.25830 - 			arg.user_data = (uintptr_t)crtc;
772.25831 - 
772.25832 - 			if (crtc->client_bo) {
772.25833 - 				DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
772.25834 --				     __FUNCTION__, crtc->id, crtc->pipe, crtc->client_bo->handle));
772.25835 -+				     __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), crtc->client_bo->handle));
772.25836 - 				arg.fb_id = get_fb(sna, crtc->client_bo,
772.25837 - 						   crtc->base->mode.HDisplay,
772.25838 - 						   crtc->base->mode.VDisplay);
772.25839 -@@ -7356,6 +9247,7 @@ fixup_shadow:
772.25840 - 						}
772.25841 - 					}
772.25842 - 
772.25843 -+					sigio_unblock(sigio);
772.25844 - 					return;
772.25845 - 				}
772.25846 - 
772.25847 -@@ -7365,8 +9257,12 @@ fixup_shadow:
772.25848 - 				y = crtc->base->y;
772.25849 - 			}
772.25850 - 
772.25851 --			if (crtc->bo == flip_bo)
772.25852 -+			if (crtc->bo == flip_bo) {
772.25853 -+				assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
772.25854 -+				DBG(("%s: flip handle=%d is already on the CRTC\n",
772.25855 -+				     __FUNCTION__, flip_bo->handle));
772.25856 - 				continue;
772.25857 -+			}
772.25858 - 
772.25859 - 			if (flip_bo->pitch != crtc->bo->pitch || (y << 16 | x)  != crtc->offset) {
772.25860 - 				DBG(("%s: changing pitch (new %d =?= old %d) or offset (new %x =?= old %x)\n",
772.25861 -@@ -7375,6 +9271,9 @@ fixup_shadow:
772.25862 - 				     y << 16 | x, crtc->offset));
772.25863 - fixup_flip:
772.25864 - 				if (sna_crtc_flip(sna, crtc, flip_bo, x, y)) {
772.25865 -+					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
772.25866 -+					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout-1,
772.25867 -+					     flip_bo->handle, flip_bo->active_scanout));
772.25868 - 					assert(flip_bo != crtc->bo);
772.25869 - 					assert(crtc->bo->active_scanout);
772.25870 - 					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
772.25871 -@@ -7389,9 +9288,11 @@ fixup_flip:
772.25872 - 					crtc->bo = kgem_bo_reference(flip_bo);
772.25873 - 					crtc->bo->active_scanout++;
772.25874 - 				} else {
772.25875 --					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.25876 --						   "Failed to prepare CRTC for page flipping, disabling TearFree\n");
772.25877 --					sna->flags &= ~SNA_TEAR_FREE;
772.25878 -+					if (sna->flags & SNA_TEAR_FREE) {
772.25879 -+						xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.25880 -+								"Failed to prepare CRTC for page flipping, disabling TearFree\n");
772.25881 -+						sna->flags &= ~SNA_TEAR_FREE;
772.25882 -+					}
772.25883 - 
772.25884 - 					if (sna->mode.flip_active == 0) {
772.25885 - 						DBG(("%s: abandoning flip attempt\n", __FUNCTION__));
772.25886 -@@ -7400,15 +9301,15 @@ fixup_flip:
772.25887 - 
772.25888 - 					xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
772.25889 - 						   "%s: page flipping failed, disabling CRTC:%d (pipe=%d)\n",
772.25890 --						   __FUNCTION__, crtc->id, crtc->pipe);
772.25891 --					sna_crtc_disable(crtc->base);
772.25892 -+						   __FUNCTION__, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc));
772.25893 -+					sna_crtc_disable(crtc->base, false);
772.25894 - 				}
772.25895 - 				continue;
772.25896 - 			}
772.25897 - 
772.25898 - 			if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) {
772.25899 - 				ERR(("%s: flip [fb=%d] on crtc %d [%d, pipe=%d] failed - %d\n",
772.25900 --				     __FUNCTION__, arg.fb_id, i, crtc->id, crtc->pipe, errno));
772.25901 -+				     __FUNCTION__, arg.fb_id, i, __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), errno));
772.25902 - 				goto fixup_flip;
772.25903 - 			}
772.25904 - 			sna->mode.flip_active++;
772.25905 -@@ -7421,6 +9322,9 @@ fixup_flip:
772.25906 - 			crtc->flip_serial = crtc->mode_serial;
772.25907 - 			crtc->flip_pending = true;
772.25908 - 
772.25909 -+			DBG(("%s: recording flip on CRTC:%d handle=%d, active_scanout=%d, serial=%d\n",
772.25910 -+			     __FUNCTION__, __sna_crtc_id(crtc), crtc->flip_bo->handle, crtc->flip_bo->active_scanout, crtc->flip_serial));
772.25911 -+
772.25912 - 			{
772.25913 - 				struct drm_i915_gem_busy busy = { flip_bo->handle };
772.25914 - 				if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy) == 0) {
772.25915 -@@ -7435,6 +9339,7 @@ fixup_flip:
772.25916 - 				}
772.25917 - 			}
772.25918 - 		}
772.25919 -+		sigio_unblock(sigio);
772.25920 - 
772.25921 - 		DBG(("%s: flipped %d outputs, shadow active? %d\n",
772.25922 - 		     __FUNCTION__,
772.25923 -@@ -7486,7 +9391,9 @@ again:
772.25924 - 		struct drm_event *e = (struct drm_event *)&buffer[i];
772.25925 - 		switch (e->type) {
772.25926 - 		case DRM_EVENT_VBLANK:
772.25927 --			if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
772.25928 -+			if (sna->mode.shadow_wait)
772.25929 -+				defer_event(sna, e);
772.25930 -+			else if (((uintptr_t)((struct drm_event_vblank *)e)->user_data) & 2)
772.25931 - 				sna_present_vblank_handler((struct drm_event_vblank *)e);
772.25932 - 			else
772.25933 - 				sna_dri2_vblank_handler((struct drm_event_vblank *)e);
772.25934 -@@ -7495,13 +9402,19 @@ again:
772.25935 - 			{
772.25936 - 				struct drm_event_vblank *vbl = (struct drm_event_vblank *)e;
772.25937 - 				struct sna_crtc *crtc = (void *)(uintptr_t)vbl->user_data;
772.25938 -+				uint64_t msc;
772.25939 - 
772.25940 - 				/* Beware Zaphod! */
772.25941 - 				sna = to_sna(crtc->base->scrn);
772.25942 - 
772.25943 --				crtc->swap.tv_sec = vbl->tv_sec;
772.25944 --				crtc->swap.tv_usec = vbl->tv_usec;
772.25945 --				crtc->swap.msc = msc64(crtc, vbl->sequence);
772.25946 -+				if (msc64(crtc, vbl->sequence, &msc)) {
772.25947 -+					DBG(("%s: recording last swap on pipe=%d, frame %d [%08llx], time %d.%06d\n",
772.25948 -+					     __FUNCTION__, __sna_crtc_pipe(crtc), vbl->sequence, (long long)msc, vbl->tv_sec, vbl->tv_usec));
772.25949 -+					crtc->swap.tv_sec = vbl->tv_sec;
772.25950 -+					crtc->swap.tv_usec = vbl->tv_usec;
772.25951 -+					crtc->swap.msc = msc;
772.25952 -+				}
772.25953 -+				assert(crtc->flip_pending);
772.25954 - 				crtc->flip_pending = false;
772.25955 - 
772.25956 - 				assert(crtc->flip_bo);
772.25957 -@@ -7509,10 +9422,12 @@ again:
772.25958 - 				assert(crtc->flip_bo->refcnt >= crtc->flip_bo->active_scanout);
772.25959 - 
772.25960 - 				if (crtc->flip_serial == crtc->mode_serial) {
772.25961 --					DBG(("%s: removing handle=%d from scanout, installing handle=%d\n",
772.25962 --					     __FUNCTION__, crtc->bo->handle, crtc->flip_bo->handle));
772.25963 -+					DBG(("%s: removing handle=%d [active_scanout=%d] from scanout, installing handle=%d [active_scanout=%d]\n",
772.25964 -+					     __FUNCTION__, crtc->bo->handle, crtc->bo->active_scanout - 1,
772.25965 -+					     crtc->flip_bo->handle, crtc->flip_bo->active_scanout));
772.25966 - 					assert(crtc->bo->active_scanout);
772.25967 - 					assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
772.25968 -+
772.25969 - 					crtc->bo->active_scanout--;
772.25970 - 					kgem_bo_destroy(&sna->kgem, crtc->bo);
772.25971 - 
772.25972 -@@ -7523,6 +9438,8 @@ again:
772.25973 - 
772.25974 - 					crtc->bo = crtc->flip_bo;
772.25975 - 					crtc->flip_bo = NULL;
772.25976 -+
772.25977 -+					assert_crtc_fb(sna, crtc);
772.25978 - 				} else {
772.25979 - 					crtc->flip_bo->active_scanout--;
772.25980 - 					kgem_bo_destroy(&sna->kgem, crtc->flip_bo);
772.25981 -@@ -7531,8 +9448,10 @@ again:
772.25982 - 
772.25983 - 				DBG(("%s: flip complete, pending? %d\n", __FUNCTION__, sna->mode.flip_active));
772.25984 - 				assert(sna->mode.flip_active);
772.25985 --				if (--sna->mode.flip_active == 0)
772.25986 -+				if (--sna->mode.flip_active == 0) {
772.25987 -+					assert(crtc->flip_handler);
772.25988 - 					crtc->flip_handler(vbl, crtc->flip_data);
772.25989 -+				}
772.25990 - 			}
772.25991 - 			break;
772.25992 - 		default:
772.25993 -diff --git a/src/sna/sna_display_fake.c b/src/sna/sna_display_fake.c
772.25994 -index 4d74c38d..fa26bda1 100644
772.25995 ---- a/src/sna/sna_display_fake.c
772.25996 -+++ b/src/sna/sna_display_fake.c
772.25997 -@@ -96,12 +96,6 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
772.25998 - }
772.25999 - 
772.26000 - static void
772.26001 --sna_crtc_gamma_set(xf86CrtcPtr crtc,
772.26002 --		       CARD16 *red, CARD16 *green, CARD16 *blue, int size)
772.26003 --{
772.26004 --}
772.26005 --
772.26006 --static void
772.26007 - sna_crtc_destroy(xf86CrtcPtr crtc)
772.26008 - {
772.26009 - }
772.26010 -@@ -109,7 +103,6 @@ sna_crtc_destroy(xf86CrtcPtr crtc)
772.26011 - static const xf86CrtcFuncsRec sna_crtc_funcs = {
772.26012 - 	.dpms = sna_crtc_dpms,
772.26013 - 	.set_mode_major = sna_crtc_set_mode_major,
772.26014 --	.gamma_set = sna_crtc_gamma_set,
772.26015 - 	.destroy = sna_crtc_destroy,
772.26016 - };
772.26017 - 
772.26018 -@@ -192,7 +185,7 @@ static const xf86OutputFuncsRec sna_output_funcs = {
772.26019 - static Bool
772.26020 - sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
772.26021 - {
772.26022 --	ScreenPtr screen = scrn->pScreen;
772.26023 -+	ScreenPtr screen = xf86ScrnToScreen(scrn);
772.26024 - 	PixmapPtr new_front;
772.26025 - 
772.26026 - 	DBG(("%s (%d, %d) -> (%d, %d)\n", __FUNCTION__,
772.26027 -@@ -262,6 +255,7 @@ static bool add_fake_output(struct sna *sna, bool late)
772.26028 - 	output->mm_height = 0;
772.26029 - 	output->interlaceAllowed = FALSE;
772.26030 - 	output->subpixel_order = SubPixelNone;
772.26031 -+	output->status = XF86OutputStatusDisconnected;
772.26032 - 
772.26033 - 	output->possible_crtcs = ~((1 << sna->mode.num_real_crtc) - 1);
772.26034 - 	output->possible_clones = ~((1 << sna->mode.num_real_output) - 1);
772.26035 -@@ -297,6 +291,8 @@ static bool add_fake_output(struct sna *sna, bool late)
772.26036 - 
772.26037 - 		RRCrtcSetRotations(crtc->randr_crtc,
772.26038 - 				   RR_Rotate_All | RR_Reflect_All);
772.26039 -+		if (!RRCrtcGammaSetSize(crtc->randr_crtc, 256))
772.26040 -+			goto err;
772.26041 - 	}
772.26042 - 
772.26043 - 	sna->mode.num_fake++;
772.26044 -@@ -312,13 +308,16 @@ err:
772.26045 - 			continue;
772.26046 - 
772.26047 - 		xf86OutputDestroy(output);
772.26048 -+		i--;
772.26049 - 	}
772.26050 - 
772.26051 - 	for (i = 0; i < xf86_config->num_crtc; i++) {
772.26052 - 		crtc = xf86_config->crtc[i];
772.26053 - 		if (crtc->driver_private)
772.26054 - 			continue;
772.26055 -+
772.26056 - 		xf86CrtcDestroy(crtc);
772.26057 -+		i--;
772.26058 - 	}
772.26059 - 	sna->mode.num_fake = -1;
772.26060 - 	return false;
772.26061 -diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
772.26062 -index e5c4d53e..d89525cc 100644
772.26063 ---- a/src/sna/sna_dri2.c
772.26064 -+++ b/src/sna/sna_dri2.c
772.26065 -@@ -82,12 +82,23 @@ get_private(void *buffer)
772.26066 - 	return (struct sna_dri2_private *)((DRI2Buffer2Ptr)buffer+1);
772.26067 - }
772.26068 - 
772.26069 -+pure static inline DRI2BufferPtr sna_pixmap_get_buffer(PixmapPtr pixmap)
772.26070 -+{
772.26071 -+	assert(pixmap->refcnt);
772.26072 -+	return ((void **)__get_private(pixmap, sna_pixmap_key))[2];
772.26073 -+}
772.26074 -+
772.26075 -+static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr)
772.26076 -+{
772.26077 -+	assert(pixmap->refcnt);
772.26078 -+	((void **)__get_private(pixmap, sna_pixmap_key))[2] = ptr;
772.26079 -+}
772.26080 -+
772.26081 - #if DRI2INFOREC_VERSION >= 4
772.26082 - enum event_type {
772.26083 - 	WAITMSC = 0,
772.26084 - 	SWAP,
772.26085 --	SWAP_WAIT,
772.26086 --	SWAP_THROTTLE,
772.26087 -+	SWAP_COMPLETE,
772.26088 - 	FLIP,
772.26089 - 	FLIP_THROTTLE,
772.26090 - 	FLIP_COMPLETE,
772.26091 -@@ -98,6 +109,7 @@ struct dri_bo {
772.26092 - 	struct list link;
772.26093 - 	struct kgem_bo *bo;
772.26094 - 	uint32_t name;
772.26095 -+	unsigned flags;
772.26096 - };
772.26097 - 
772.26098 - struct sna_dri2_event {
772.26099 -@@ -108,6 +120,8 @@ struct sna_dri2_event {
772.26100 - 	xf86CrtcPtr crtc;
772.26101 - 	int pipe;
772.26102 - 	bool queued;
772.26103 -+	bool sync;
772.26104 -+	bool chained;
772.26105 - 
772.26106 - 	/* for swaps & flips only */
772.26107 - 	DRI2SwapEventPtr event_complete;
772.26108 -@@ -116,35 +130,146 @@ struct sna_dri2_event {
772.26109 - 	DRI2BufferPtr back;
772.26110 - 	struct kgem_bo *bo;
772.26111 - 
772.26112 -+	struct copy {
772.26113 -+		struct kgem_bo *bo;
772.26114 -+		unsigned flags;
772.26115 -+		uint32_t name;
772.26116 -+		uint32_t size;
772.26117 -+	} pending;
772.26118 -+
772.26119 - 	struct sna_dri2_event *chain;
772.26120 - 
772.26121 --	struct list cache;
772.26122 - 	struct list link;
772.26123 - 
772.26124 --	int mode;
772.26125 -+	int flip_continue;
772.26126 -+	int keepalive;
772.26127 -+	int signal;
772.26128 - };
772.26129 - 
772.26130 -+#if DRI2INFOREC_VERSION < 10
772.26131 -+#undef USE_ASYNC_SWAP
772.26132 -+#endif
772.26133 -+
772.26134 -+#if USE_ASYNC_SWAP
772.26135 -+#define KEEPALIVE 8 /* wait ~100ms before discarding swap caches */
772.26136 -+#define APPLY_DAMAGE 0
772.26137 -+#else
772.26138 -+#define USE_ASYNC_SWAP 0
772.26139 -+#define KEEPALIVE 1
772.26140 -+#define APPLY_DAMAGE 1
772.26141 -+#endif
772.26142 -+
772.26143 - static void sna_dri2_flip_event(struct sna_dri2_event *flip);
772.26144 -+inline static DRI2BufferPtr dri2_window_get_front(WindowPtr win);
772.26145 -+
772.26146 -+static struct kgem_bo *
772.26147 -+__sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.26148 -+		      DRI2BufferPtr src, DRI2BufferPtr dst,
772.26149 -+		      unsigned flags);
772.26150 -+
772.26151 -+inline static void
772.26152 -+__sna_dri2_copy_event(struct sna_dri2_event *info, unsigned flags)
772.26153 -+{
772.26154 -+	DBG(("%s: flags = %x\n", __FUNCTION__, flags));
772.26155 -+	assert(info->front != info->back);
772.26156 -+	info->bo = __sna_dri2_copy_region(info->sna, info->draw, NULL,
772.26157 -+					  info->back, info->front,
772.26158 -+					  flags);
772.26159 -+	info->front->flags = info->back->flags;
772.26160 -+}
772.26161 -+
772.26162 -+static int front_pitch(DrawablePtr draw)
772.26163 -+{
772.26164 -+	DRI2BufferPtr buffer;
772.26165 -+
772.26166 -+	buffer = NULL;
772.26167 -+	if (draw->type != DRAWABLE_PIXMAP)
772.26168 -+		buffer = dri2_window_get_front((WindowPtr)draw);
772.26169 -+	if (buffer == NULL)
772.26170 -+		buffer = sna_pixmap_get_buffer(get_drawable_pixmap(draw));
772.26171 -+
772.26172 -+	return buffer ? buffer->pitch : 0;
772.26173 -+}
772.26174 -+
772.26175 -+struct dri2_window {
772.26176 -+	DRI2BufferPtr front;
772.26177 -+	struct sna_dri2_event *chain;
772.26178 -+	xf86CrtcPtr crtc;
772.26179 -+	int64_t msc_delta;
772.26180 -+	struct list cache;
772.26181 -+	uint32_t cache_size;
772.26182 -+	int scanout;
772.26183 -+};
772.26184 -+
772.26185 -+static struct dri2_window *dri2_window(WindowPtr win)
772.26186 -+{
772.26187 -+	assert(win->drawable.type != DRAWABLE_PIXMAP);
772.26188 -+	return ((void **)__get_private(win, sna_window_key))[1];
772.26189 -+}
772.26190 -+
772.26191 -+static bool use_scanout(struct sna *sna,
772.26192 -+			DrawablePtr draw,
772.26193 -+			struct dri2_window *priv)
772.26194 -+{
772.26195 -+	if (priv->front)
772.26196 -+		return true;
772.26197 -+
772.26198 -+	if (priv->scanout < 0)
772.26199 -+		priv->scanout =
772.26200 -+			(sna->flags & (SNA_LINEAR_FB | SNA_NO_WAIT | SNA_NO_FLIP)) == 0 &&
772.26201 -+			draw->width  == sna->front->drawable.width &&
772.26202 -+			draw->height == sna->front->drawable.height &&
772.26203 -+			draw->bitsPerPixel == sna->front->drawable.bitsPerPixel;
772.26204 -+
772.26205 -+	return priv->scanout;
772.26206 -+}
772.26207 - 
772.26208 - static void
772.26209 - sna_dri2_get_back(struct sna *sna,
772.26210 - 		  DrawablePtr draw,
772.26211 --		  DRI2BufferPtr back,
772.26212 --		  struct sna_dri2_event *info)
772.26213 -+		  DRI2BufferPtr back)
772.26214 - {
772.26215 -+	struct dri2_window *priv = dri2_window((WindowPtr)draw);
772.26216 -+	uint32_t size;
772.26217 - 	struct kgem_bo *bo;
772.26218 -+	struct dri_bo *c;
772.26219 - 	uint32_t name;
772.26220 -+	int flags;
772.26221 - 	bool reuse;
772.26222 - 
772.26223 --	DBG(("%s: draw size=%dx%d, buffer size=%dx%d\n",
772.26224 -+	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, active?=%d, pitch=%d, front pitch=%d\n",
772.26225 - 	     __FUNCTION__, draw->width, draw->height,
772.26226 --	     get_private(back)->size & 0xffff, get_private(back)->size >> 16));
772.26227 --	reuse = (draw->height << 16 | draw->width) == get_private(back)->size;
772.26228 -+	     get_private(back)->bo->handle,
772.26229 -+	     get_private(back)->size & 0xffff, get_private(back)->size >> 16,
772.26230 -+	     get_private(back)->bo->scanout,
772.26231 -+	     get_private(back)->bo->active_scanout,
772.26232 -+	     back->pitch, front_pitch(draw)));
772.26233 -+	assert(priv);
772.26234 -+
772.26235 -+	size = draw->height << 16 | draw->width;
772.26236 -+	if (size != priv->cache_size) {
772.26237 -+		while (!list_is_empty(&priv->cache)) {
772.26238 -+			c = list_first_entry(&priv->cache, struct dri_bo, link);
772.26239 -+			list_del(&c->link);
772.26240 -+
772.26241 -+			DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
772.26242 -+			assert(c->bo);
772.26243 -+			kgem_bo_destroy(&sna->kgem, c->bo);
772.26244 -+
772.26245 -+			free(c);
772.26246 -+		}
772.26247 -+		priv->cache_size = size;
772.26248 -+	}
772.26249 -+
772.26250 -+	reuse = size == get_private(back)->size;
772.26251 -+	if (reuse)
772.26252 -+		reuse = get_private(back)->bo->scanout == use_scanout(sna, draw, priv);
772.26253 -+	DBG(("%s: reuse backbuffer? %d\n", __FUNCTION__, reuse));
772.26254 - 	if (reuse) {
772.26255 - 		bo = get_private(back)->bo;
772.26256 - 		assert(bo->refcnt);
772.26257 --		DBG(("%s: back buffer handle=%d, scanout?=%d, refcnt=%d\n",
772.26258 --					__FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
772.26259 -+		DBG(("%s: back buffer handle=%d, active?=%d, refcnt=%d\n",
772.26260 -+		     __FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
772.26261 - 		if (bo->active_scanout == 0) {
772.26262 - 			DBG(("%s: reuse unattached back\n", __FUNCTION__));
772.26263 - 			get_private(back)->stale = false;
772.26264 -@@ -153,24 +278,37 @@ sna_dri2_get_back(struct sna *sna,
772.26265 - 	}
772.26266 - 
772.26267 - 	bo = NULL;
772.26268 --	if (info) {
772.26269 --		struct dri_bo *c;
772.26270 --		list_for_each_entry(c, &info->cache, link) {
772.26271 --			if (c->bo && c->bo->scanout == 0) {
772.26272 --				bo = c->bo;
772.26273 --				name = c->name;
772.26274 --				DBG(("%s: reuse cache handle=%d\n", __FUNCTION__, bo->handle));
772.26275 --				list_move_tail(&c->link, &info->cache);
772.26276 --				c->bo = NULL;
772.26277 -+	list_for_each_entry(c, &priv->cache, link) {
772.26278 -+		DBG(("%s: cache: handle=%d, active=%d\n",
772.26279 -+		     __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
772.26280 -+		assert(c->bo);
772.26281 -+		if (c->bo->active_scanout == 0) {
772.26282 -+			_list_del(&c->link);
772.26283 -+			if (c->bo == NULL) {
772.26284 -+				free(c);
772.26285 -+				goto out;
772.26286 - 			}
772.26287 -+			bo = c->bo;
772.26288 -+			name = c->name;
772.26289 -+			flags = c->flags;
772.26290 -+			DBG(("%s: reuse cache handle=%d, name=%d, flags=%d\n", __FUNCTION__, bo->handle, name, flags));
772.26291 -+			c->bo = NULL;
772.26292 -+			break;
772.26293 - 		}
772.26294 - 	}
772.26295 - 	if (bo == NULL) {
772.26296 - 		DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
772.26297 -+		flags = CREATE_EXACT;
772.26298 -+
772.26299 -+		if (use_scanout(sna, draw, priv)) {
772.26300 -+			DBG(("%s: requesting scanout compatible back\n", __FUNCTION__));
772.26301 -+			flags |= CREATE_SCANOUT;
772.26302 -+		}
772.26303 -+
772.26304 - 		bo = kgem_create_2d(&sna->kgem,
772.26305 - 				    draw->width, draw->height, draw->bitsPerPixel,
772.26306 - 				    get_private(back)->bo->tiling,
772.26307 --				    get_private(back)->bo->scanout ? CREATE_SCANOUT : 0);
772.26308 -+				    flags);
772.26309 - 		if (bo == NULL)
772.26310 - 			return;
772.26311 - 
772.26312 -@@ -179,30 +317,42 @@ sna_dri2_get_back(struct sna *sna,
772.26313 - 			kgem_bo_destroy(&sna->kgem, bo);
772.26314 - 			return;
772.26315 - 		}
772.26316 -+
772.26317 -+		flags = 0;
772.26318 -+		if (USE_ASYNC_SWAP && back->flags) {
772.26319 -+			BoxRec box;
772.26320 -+
772.26321 -+			box.x1 = 0;
772.26322 -+			box.y1 = 0;
772.26323 -+			box.x2 = draw->width;
772.26324 -+			box.y2 = draw->height;
772.26325 -+
772.26326 -+			DBG(("%s: filling new buffer with old back\n", __FUNCTION__));
772.26327 -+			if (sna->render.copy_boxes(sna, GXcopy,
772.26328 -+						   draw, get_private(back)->bo, 0, 0,
772.26329 -+						   draw, bo, 0, 0,
772.26330 -+						   &box, 1, COPY_LAST | COPY_DRI))
772.26331 -+				flags = back->flags;
772.26332 -+		}
772.26333 - 	}
772.26334 - 	assert(bo->active_scanout == 0);
772.26335 - 
772.26336 --	if (info && reuse) {
772.26337 --		bool found = false;
772.26338 --		struct dri_bo *c;
772.26339 --
772.26340 --		list_for_each_entry_reverse(c, &info->cache, link) {
772.26341 --			if (c->bo == NULL) {
772.26342 --				found = true;
772.26343 --				_list_del(&c->link);
772.26344 --				break;
772.26345 --			}
772.26346 --		}
772.26347 --		if (!found)
772.26348 -+	if (reuse && get_private(back)->bo->refcnt == 1 + get_private(back)->bo->active_scanout) {
772.26349 -+		if (&c->link == &priv->cache)
772.26350 - 			c = malloc(sizeof(*c));
772.26351 - 		if (c != NULL) {
772.26352 - 			c->bo = ref(get_private(back)->bo);
772.26353 - 			c->name = back->name;
772.26354 --			list_add(&c->link, &info->cache);
772.26355 --			DBG(("%s: cacheing handle=%d (name=%d)\n", __FUNCTION__, c->bo->handle, c->name));
772.26356 -+			c->flags = back->flags;
772.26357 -+			list_add(&c->link, &priv->cache);
772.26358 -+			DBG(("%s: caching handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, c->bo->handle, c->name, c->flags, c->bo->active_scanout));
772.26359 - 		}
772.26360 -+	} else {
772.26361 -+		if (&c->link != &priv->cache)
772.26362 -+			free(c);
772.26363 - 	}
772.26364 - 
772.26365 -+	assert(bo->active_scanout == 0);
772.26366 - 	assert(bo != get_private(back)->bo);
772.26367 - 	kgem_bo_destroy(&sna->kgem, get_private(back)->bo);
772.26368 - 
772.26369 -@@ -210,21 +360,13 @@ sna_dri2_get_back(struct sna *sna,
772.26370 - 	get_private(back)->size = draw->height << 16 | draw->width;
772.26371 - 	back->pitch = bo->pitch;
772.26372 - 	back->name = name;
772.26373 -+	back->flags = flags;
772.26374 - 
772.26375 --	get_private(back)->stale = false;
772.26376 --}
772.26377 --
772.26378 --struct dri2_window {
772.26379 --	DRI2BufferPtr front;
772.26380 --	struct sna_dri2_event *chain;
772.26381 --	xf86CrtcPtr crtc;
772.26382 --	int64_t msc_delta;
772.26383 --};
772.26384 -+	assert(back->pitch);
772.26385 -+	assert(back->name);
772.26386 - 
772.26387 --static struct dri2_window *dri2_window(WindowPtr win)
772.26388 --{
772.26389 --	assert(win->drawable.type != DRAWABLE_PIXMAP);
772.26390 --	return ((void **)__get_private(win, sna_window_key))[1];
772.26391 -+out:
772.26392 -+	get_private(back)->stale = false;
772.26393 - }
772.26394 - 
772.26395 - static struct sna_dri2_event *
772.26396 -@@ -232,21 +374,25 @@ dri2_chain(DrawablePtr d)
772.26397 - {
772.26398 - 	struct dri2_window *priv = dri2_window((WindowPtr)d);
772.26399 - 	assert(priv != NULL);
772.26400 -+	assert(priv->chain == NULL || priv->chain->chained);
772.26401 - 	return priv->chain;
772.26402 - }
772.26403 - inline static DRI2BufferPtr dri2_window_get_front(WindowPtr win)
772.26404 - {
772.26405 - 	struct dri2_window *priv = dri2_window(win);
772.26406 -+	assert(priv->front == NULL || get_private(priv->front)->bo->active_scanout);
772.26407 - 	return priv ? priv->front : NULL;
772.26408 - }
772.26409 - #else
772.26410 - inline static void *dri2_window_get_front(WindowPtr win) { return NULL; }
772.26411 -+#define APPLY_DAMAGE 1
772.26412 - #endif
772.26413 - 
772.26414 - #if DRI2INFOREC_VERSION < 6
772.26415 - 
772.26416 - #define xorg_can_triple_buffer() 0
772.26417 - #define swap_limit(d, l) false
772.26418 -+#define mark_stale(b)
772.26419 - 
772.26420 - #else
772.26421 - 
772.26422 -@@ -273,6 +419,8 @@ mark_stale(DRI2BufferPtr back)
772.26423 - 	 * stale frame. (This is mostly useful for tracking down
772.26424 - 	 * driver bugs!)
772.26425 - 	 */
772.26426 -+	DBG(("%s(handle=%d) => %d\n", __FUNCTION__,
772.26427 -+	     get_private(back)->bo->handle, xorg_can_triple_buffer()));
772.26428 - 	get_private(back)->stale = xorg_can_triple_buffer();
772.26429 - }
772.26430 - 
772.26431 -@@ -286,21 +434,29 @@ sna_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit)
772.26432 - static void
772.26433 - sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
772.26434 - {
772.26435 -+	struct sna *sna = to_sna_from_drawable(draw);
772.26436 -+
772.26437 - 	DBG(("%s: reusing buffer pixmap=%ld, attachment=%d, handle=%d, name=%d\n",
772.26438 - 	     __FUNCTION__, get_drawable_pixmap(draw)->drawable.serialNumber,
772.26439 - 	     buffer->attachment, get_private(buffer)->bo->handle, buffer->name));
772.26440 - 	assert(get_private(buffer)->refcnt);
772.26441 --	assert(get_private(buffer)->bo->refcnt > get_private(buffer)->bo->active_scanout);
772.26442 -+	assert(get_private(buffer)->bo->refcnt >= get_private(buffer)->bo->active_scanout);
772.26443 -+	assert(kgem_bo_flink(&sna->kgem, get_private(buffer)->bo) == buffer->name);
772.26444 - 
772.26445 - 	if (buffer->attachment == DRI2BufferBackLeft &&
772.26446 - 	    draw->type != DRAWABLE_PIXMAP) {
772.26447 --		DBG(("%s: replacing back buffer\n", __FUNCTION__));
772.26448 --		sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer, dri2_chain(draw));
772.26449 -+		DBG(("%s: replacing back buffer on window %ld\n", __FUNCTION__, draw->id));
772.26450 -+		sna_dri2_get_back(sna, draw, buffer);
772.26451 - 
772.26452 --		assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
772.26453 - 		assert(get_private(buffer)->bo->refcnt);
772.26454 - 		assert(get_private(buffer)->bo->active_scanout == 0);
772.26455 -+		assert(kgem_bo_flink(&sna->kgem, get_private(buffer)->bo) == buffer->name);
772.26456 -+		DBG(("%s: reusing back buffer handle=%d, name=%d, pitch=%d, age=%d\n",
772.26457 -+		     __FUNCTION__, get_private(buffer)->bo->handle,
772.26458 -+		     buffer->name, buffer->pitch, buffer->flags));
772.26459 - 	}
772.26460 -+
772.26461 -+	kgem_bo_submit(&sna->kgem, get_private(buffer)->bo);
772.26462 - }
772.26463 - 
772.26464 - static bool swap_limit(DrawablePtr draw, int limit)
772.26465 -@@ -314,11 +470,6 @@ static bool swap_limit(DrawablePtr draw, int limit)
772.26466 - }
772.26467 - #endif
772.26468 - 
772.26469 --#if DRI2INFOREC_VERSION < 10
772.26470 --#undef USE_ASYNC_SWAP
772.26471 --#define USE_ASYNC_SWAP 0
772.26472 --#endif
772.26473 --
772.26474 - #define COLOR_PREFER_TILING_Y 0
772.26475 - 
772.26476 - /* Prefer to enable TILING_Y if this buffer will never be a
772.26477 -@@ -328,6 +479,9 @@ static uint32_t color_tiling(struct sna *sna, DrawablePtr draw)
772.26478 - {
772.26479 - 	uint32_t tiling;
772.26480 - 
772.26481 -+	if (!sna->kgem.can_fence)
772.26482 -+		return I915_TILING_NONE;
772.26483 -+
772.26484 - 	if (COLOR_PREFER_TILING_Y &&
772.26485 - 	    (draw->width  != sna->front->drawable.width ||
772.26486 - 	     draw->height != sna->front->drawable.height))
772.26487 -@@ -355,7 +509,6 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
772.26488 - 					  PixmapPtr pixmap)
772.26489 - {
772.26490 - 	struct sna_pixmap *priv;
772.26491 --	int tiling;
772.26492 - 
772.26493 - 	DBG(("%s: attaching DRI client to pixmap=%ld\n",
772.26494 - 	     __FUNCTION__, pixmap->drawable.serialNumber));
772.26495 -@@ -373,31 +526,29 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
772.26496 - 		return NULL;
772.26497 - 	}
772.26498 - 
772.26499 --	assert(priv->flush == false);
772.26500 -+	assert(priv->flush == false || priv->pinned & PIN_DRI3);
772.26501 -+	assert(priv->gpu_bo->flush == false || priv->pinned & PIN_DRI3);
772.26502 - 	assert(priv->cpu_damage == NULL);
772.26503 - 	assert(priv->gpu_bo);
772.26504 - 	assert(priv->gpu_bo->proxy == NULL);
772.26505 --	assert(priv->gpu_bo->flush == false);
772.26506 --
772.26507 --	tiling = color_tiling(sna, &pixmap->drawable);
772.26508 --	if (tiling < 0)
772.26509 --		tiling = -tiling;
772.26510 --	if (priv->gpu_bo->tiling != tiling)
772.26511 --		sna_pixmap_change_tiling(pixmap, tiling);
772.26512 - 
772.26513 --	return priv->gpu_bo;
772.26514 --}
772.26515 -+	if (!kgem_bo_is_fenced(&sna->kgem, priv->gpu_bo)) {
772.26516 -+		if (priv->gpu_bo->tiling &&
772.26517 -+		    !sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
772.26518 -+			DBG(("%s: failed to discard tiling (%d) for DRI2 protocol\n", __FUNCTION__, priv->gpu_bo->tiling));
772.26519 -+			return NULL;
772.26520 -+		}
772.26521 -+	} else {
772.26522 -+		int tiling = color_tiling(sna, &pixmap->drawable);
772.26523 -+		if (tiling < 0)
772.26524 -+			tiling = -tiling;
772.26525 -+		if (priv->gpu_bo->tiling < tiling && !priv->gpu_bo->scanout)
772.26526 -+			sna_pixmap_change_tiling(pixmap, tiling);
772.26527 -+	}
772.26528 - 
772.26529 --pure static inline void *sna_pixmap_get_buffer(PixmapPtr pixmap)
772.26530 --{
772.26531 --	assert(pixmap->refcnt);
772.26532 --	return ((void **)__get_private(pixmap, sna_pixmap_key))[2];
772.26533 --}
772.26534 -+	priv->gpu_bo->active_scanout++;
772.26535 - 
772.26536 --static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr)
772.26537 --{
772.26538 --	assert(pixmap->refcnt);
772.26539 --	((void **)__get_private(pixmap, sna_pixmap_key))[2] = ptr;
772.26540 -+	return priv->gpu_bo;
772.26541 - }
772.26542 - 
772.26543 - void
772.26544 -@@ -422,13 +573,18 @@ sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo)
772.26545 - 	if (private->bo == bo)
772.26546 - 		return;
772.26547 - 
772.26548 -+	assert(private->bo->active_scanout > 0);
772.26549 -+	private->bo->active_scanout--;
772.26550 -+
772.26551 - 	DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, private->bo->handle));
772.26552 - 	private->bo->flush = false;
772.26553 - 	kgem_bo_destroy(&sna->kgem, private->bo);
772.26554 - 
772.26555 -+
772.26556 - 	buffer->name = kgem_bo_flink(&sna->kgem, bo);
772.26557 - 	buffer->pitch = bo->pitch;
772.26558 - 	private->bo = ref(bo);
772.26559 -+	bo->active_scanout++;
772.26560 - 
772.26561 - 	DBG(("%s: adding flush hint to handle=%d\n", __FUNCTION__, bo->handle));
772.26562 - 	bo->flush = true;
772.26563 -@@ -449,9 +605,9 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26564 - 	struct sna_dri2_private *private;
772.26565 - 	PixmapPtr pixmap;
772.26566 - 	struct kgem_bo *bo;
772.26567 --	unsigned flags = 0;
772.26568 -+	unsigned bpp = format ?: draw->bitsPerPixel;
772.26569 -+	unsigned flags = CREATE_EXACT;
772.26570 - 	uint32_t size;
772.26571 --	int bpp;
772.26572 - 
772.26573 - 	DBG(("%s pixmap=%ld, (attachment=%d, format=%d, drawable=%dx%d), window?=%d\n",
772.26574 - 	     __FUNCTION__,
772.26575 -@@ -468,11 +624,11 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26576 - 		if (draw->type != DRAWABLE_PIXMAP)
772.26577 - 			buffer = dri2_window_get_front((WindowPtr)draw);
772.26578 - 		if (buffer == NULL)
772.26579 --			buffer = sna_pixmap_get_buffer(pixmap);
772.26580 -+			buffer = (DRI2Buffer2Ptr)sna_pixmap_get_buffer(pixmap);
772.26581 - 		if (buffer) {
772.26582 - 			private = get_private(buffer);
772.26583 - 
772.26584 --			DBG(("%s: reusing front buffer attachment, win=%lu %dx%d, pixmap=%ld [%ld] %dx%d, handle=%d, name=%d\n",
772.26585 -+			DBG(("%s: reusing front buffer attachment, win=%lu %dx%d, pixmap=%ld [%ld] %dx%d, handle=%d, name=%d, active_scanout=%d\n",
772.26586 - 			     __FUNCTION__,
772.26587 - 			     draw->type != DRAWABLE_PIXMAP ? (long)draw->id : (long)0,
772.26588 - 			     draw->width, draw->height,
772.26589 -@@ -480,12 +636,22 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26590 - 			     private->pixmap->drawable.serialNumber,
772.26591 - 			     pixmap->drawable.width,
772.26592 - 			     pixmap->drawable.height,
772.26593 --			     private->bo->handle, buffer->name));
772.26594 -+			     private->bo->handle, buffer->name,
772.26595 -+			     private->bo->active_scanout));
772.26596 - 
772.26597 -+			assert(buffer->attachment == DRI2BufferFrontLeft);
772.26598 - 			assert(private->pixmap == pixmap);
772.26599 - 			assert(sna_pixmap(pixmap)->flush);
772.26600 - 			assert(sna_pixmap(pixmap)->pinned & PIN_DRI2);
772.26601 - 			assert(kgem_bo_flink(&sna->kgem, private->bo) == buffer->name);
772.26602 -+			assert(private->bo->pitch == buffer->pitch);
772.26603 -+			assert(private->bo->active_scanout);
772.26604 -+
772.26605 -+			sna_pixmap_move_to_gpu(pixmap,
772.26606 -+					       MOVE_READ |
772.26607 -+					       __MOVE_FORCE |
772.26608 -+					       __MOVE_DRI);
772.26609 -+			kgem_bo_submit(&sna->kgem, private->bo);
772.26610 - 
772.26611 - 			private->refcnt++;
772.26612 - 			return buffer;
772.26613 -@@ -498,7 +664,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26614 - 		assert(sna_pixmap(pixmap) != NULL);
772.26615 - 
772.26616 - 		bo = ref(bo);
772.26617 --		bpp = pixmap->drawable.bitsPerPixel;
772.26618 - 		if (pixmap == sna->front && !(sna->flags & SNA_LINEAR_FB))
772.26619 - 			flags |= CREATE_SCANOUT;
772.26620 - 		DBG(("%s: attaching to front buffer %dx%d [%p:%d], scanout? %d\n",
772.26621 -@@ -506,6 +671,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26622 - 		     pixmap->drawable.width, pixmap->drawable.height,
772.26623 - 		     pixmap, pixmap->refcnt, flags & CREATE_SCANOUT));
772.26624 - 		size = (uint32_t)pixmap->drawable.height << 16 | pixmap->drawable.width;
772.26625 -+		bpp = pixmap->drawable.bitsPerPixel;
772.26626 - 		break;
772.26627 - 
772.26628 - 	case DRI2BufferBackLeft:
772.26629 -@@ -514,6 +680,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26630 - 				flags |= CREATE_SCANOUT;
772.26631 - 			if (draw->width  == sna->front->drawable.width &&
772.26632 - 			    draw->height == sna->front->drawable.height &&
772.26633 -+			    draw->bitsPerPixel == bpp &&
772.26634 - 			    (sna->flags & (SNA_LINEAR_FB | SNA_NO_WAIT | SNA_NO_FLIP)) == 0)
772.26635 - 				flags |= CREATE_SCANOUT;
772.26636 - 		}
772.26637 -@@ -521,7 +688,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26638 - 	case DRI2BufferFrontRight:
772.26639 - 	case DRI2BufferFakeFrontLeft:
772.26640 - 	case DRI2BufferFakeFrontRight:
772.26641 --		bpp = draw->bitsPerPixel;
772.26642 - 		DBG(("%s: creating back buffer %dx%d, suitable for scanout? %d\n",
772.26643 - 		     __FUNCTION__,
772.26644 - 		     draw->width, draw->height,
772.26645 -@@ -530,7 +696,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26646 - 		bo = kgem_create_2d(&sna->kgem,
772.26647 - 				    draw->width,
772.26648 - 				    draw->height,
772.26649 --				    draw->bitsPerPixel,
772.26650 -+				    bpp,
772.26651 - 				    color_tiling(sna, draw),
772.26652 - 				    flags);
772.26653 - 		break;
772.26654 -@@ -558,7 +724,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26655 - 		 * not understand W tiling and the GTT is incapable of
772.26656 - 		 * W fencing.
772.26657 - 		 */
772.26658 --		bpp = format ? format : draw->bitsPerPixel;
772.26659 - 		bpp *= 2;
772.26660 - 		bo = kgem_create_2d(&sna->kgem,
772.26661 - 				    ALIGN(draw->width, 64),
772.26662 -@@ -570,7 +735,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26663 - 	case DRI2BufferDepthStencil:
772.26664 - 	case DRI2BufferHiz:
772.26665 - 	case DRI2BufferAccum:
772.26666 --		bpp = format ? format : draw->bitsPerPixel,
772.26667 - 		bo = kgem_create_2d(&sna->kgem,
772.26668 - 				    draw->width, draw->height, bpp,
772.26669 - 				    other_tiling(sna, draw),
772.26670 -@@ -614,7 +778,7 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26671 - 		pixmap->refcnt++;
772.26672 - 
772.26673 - 		priv = sna_pixmap(pixmap);
772.26674 --		assert(priv->flush == false);
772.26675 -+		assert(priv->flush == false || priv->pinned & PIN_DRI3);
772.26676 - 		assert((priv->pinned & PIN_DRI2) == 0);
772.26677 - 
772.26678 - 		/* Don't allow this named buffer to be replaced */
772.26679 -@@ -630,17 +794,17 @@ sna_dri2_create_buffer(DrawablePtr draw,
772.26680 - 		if (priv->gpu_bo->exec)
772.26681 - 			sna->kgem.flush = 1;
772.26682 - 
772.26683 --		priv->flush |= 1;
772.26684 -+		priv->flush |= FLUSH_READ;
772.26685 - 		if (draw->type == DRAWABLE_PIXMAP) {
772.26686 - 			/* DRI2 renders directly into GLXPixmaps, treat as hostile */
772.26687 - 			kgem_bo_unclean(&sna->kgem, priv->gpu_bo);
772.26688 - 			sna_damage_all(&priv->gpu_damage, pixmap);
772.26689 - 			priv->clear = false;
772.26690 - 			priv->cpu = false;
772.26691 --			priv->flush |= 2;
772.26692 -+			priv->flush |= FLUSH_WRITE;
772.26693 - 		}
772.26694 - 
772.26695 --		sna_accel_watch_flush(sna, 1);
772.26696 -+		sna_watch_flush(sna, 1);
772.26697 - 	}
772.26698 - 
772.26699 - 	return buffer;
772.26700 -@@ -651,16 +815,80 @@ err:
772.26701 - 	return NULL;
772.26702 - }
772.26703 - 
772.26704 --static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
772.26705 -+static void
772.26706 -+sna_dri2_cache_bo(struct sna *sna,
772.26707 -+		  DrawablePtr draw,
772.26708 -+		  struct kgem_bo *bo,
772.26709 -+		  uint32_t name,
772.26710 -+		  uint32_t size,
772.26711 -+		  uint32_t flags)
772.26712 -+{
772.26713 -+	struct dri_bo *c;
772.26714 -+
772.26715 -+	DBG(("%s(handle=%d, name=%d)\n", __FUNCTION__, bo->handle, name));
772.26716 -+
772.26717 -+	if (draw == NULL) {
772.26718 -+		DBG(("%s: no draw, releasing handle=%d\n",
772.26719 -+		     __FUNCTION__, bo->handle));
772.26720 -+		goto err;
772.26721 -+	}
772.26722 -+
772.26723 -+	if (draw->type == DRAWABLE_PIXMAP) {
772.26724 -+		DBG(("%s: not a window, releasing handle=%d\n",
772.26725 -+		     __FUNCTION__, bo->handle));
772.26726 -+		goto err;
772.26727 -+	}
772.26728 -+
772.26729 -+	if (bo->refcnt > 1 + bo->active_scanout) {
772.26730 -+		DBG(("%s: multiple references [%d], releasing handle\n",
772.26731 -+		     __FUNCTION__, bo->refcnt, bo->handle));
772.26732 -+		goto err;
772.26733 -+	}
772.26734 -+
772.26735 -+	if ((draw->height << 16 | draw->width) != size) {
772.26736 -+		DBG(("%s: wrong size [%dx%d], releasing handle\n",
772.26737 -+		     __FUNCTION__,
772.26738 -+		     size & 0xffff, size >> 16,
772.26739 -+		     bo->handle));
772.26740 -+		goto err;
772.26741 -+	}
772.26742 -+
772.26743 -+	if (bo->scanout && front_pitch(draw) != bo->pitch) {
772.26744 -+		DBG(("%s: scanout with pitch change [%d != %d], releasing handle\n",
772.26745 -+		     __FUNCTION__, bo->pitch, front_pitch(draw), bo->handle));
772.26746 -+		goto err;
772.26747 -+	}
772.26748 -+
772.26749 -+	c = malloc(sizeof(*c));
772.26750 -+	if (!c)
772.26751 -+		goto err;
772.26752 -+
772.26753 -+	DBG(("%s: caching handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, bo->handle, name, flags, bo->active_scanout));
772.26754 -+
772.26755 -+	c->bo = bo;
772.26756 -+	c->name = name;
772.26757 -+	c->flags = flags;
772.26758 -+	list_add(&c->link, &dri2_window((WindowPtr)draw)->cache);
772.26759 -+	return;
772.26760 -+
772.26761 -+err:
772.26762 -+	kgem_bo_destroy(&sna->kgem, bo);
772.26763 -+}
772.26764 -+
772.26765 -+static void _sna_dri2_destroy_buffer(struct sna *sna,
772.26766 -+				     DrawablePtr draw,
772.26767 -+				     DRI2Buffer2Ptr buffer)
772.26768 - {
772.26769 - 	struct sna_dri2_private *private = get_private(buffer);
772.26770 - 
772.26771 - 	if (buffer == NULL)
772.26772 - 		return;
772.26773 - 
772.26774 --	DBG(("%s: %p [handle=%d] -- refcnt=%d, pixmap=%ld\n",
772.26775 -+	DBG(("%s: %p [handle=%d] -- refcnt=%d, draw=%ld, pixmap=%ld, proxy?=%d\n",
772.26776 - 	     __FUNCTION__, buffer, private->bo->handle, private->refcnt,
772.26777 --	     private->pixmap ? private->pixmap->drawable.serialNumber : 0));
772.26778 -+	     draw ? draw->id : 0,
772.26779 -+	     private->pixmap ? private->pixmap->drawable.serialNumber : 0,
772.26780 -+	     private->proxy != NULL));
772.26781 - 	assert(private->refcnt > 0);
772.26782 - 	if (--private->refcnt)
772.26783 - 		return;
772.26784 -@@ -669,7 +897,10 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
772.26785 - 
772.26786 - 	if (private->proxy) {
772.26787 - 		DBG(("%s: destroying proxy\n", __FUNCTION__));
772.26788 --		_sna_dri2_destroy_buffer(sna, private->proxy);
772.26789 -+		assert(private->bo->active_scanout > 0);
772.26790 -+		private->bo->active_scanout--;
772.26791 -+
772.26792 -+		_sna_dri2_destroy_buffer(sna, draw, private->proxy);
772.26793 - 		private->pixmap = NULL;
772.26794 - 	}
772.26795 - 
772.26796 -@@ -683,6 +914,11 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
772.26797 - 		assert(priv->pinned & PIN_DRI2);
772.26798 - 		assert(priv->flush);
772.26799 - 
772.26800 -+		DBG(("%s: removing active_scanout=%d from pixmap handle=%d\n",
772.26801 -+		     __FUNCTION__, priv->gpu_bo->active_scanout, priv->gpu_bo->handle));
772.26802 -+		assert(priv->gpu_bo->active_scanout > 0);
772.26803 -+		priv->gpu_bo->active_scanout--;
772.26804 -+
772.26805 - 		/* Undo the DRI markings on this pixmap */
772.26806 - 		DBG(("%s: releasing last DRI pixmap=%ld, scanout?=%d\n",
772.26807 - 		     __FUNCTION__,
772.26808 -@@ -692,28 +928,34 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
772.26809 - 		list_del(&priv->flush_list);
772.26810 - 
772.26811 - 		DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, private->bo->handle));
772.26812 --		priv->gpu_bo->flush = false;
772.26813 - 		priv->pinned &= ~PIN_DRI2;
772.26814 - 
772.26815 --		priv->flush = false;
772.26816 --		sna_accel_watch_flush(sna, -1);
772.26817 -+		if ((priv->pinned & PIN_DRI3) == 0) {
772.26818 -+			priv->gpu_bo->flush = false;
772.26819 -+			priv->flush = false;
772.26820 -+		}
772.26821 -+		sna_watch_flush(sna, -1);
772.26822 - 
772.26823 - 		sna_pixmap_set_buffer(pixmap, NULL);
772.26824 - 		pixmap->drawable.pScreen->DestroyPixmap(pixmap);
772.26825 - 	}
772.26826 --	assert(private->bo->flush == false);
772.26827 - 
772.26828 --	kgem_bo_destroy(&sna->kgem, private->bo);
772.26829 -+	sna_dri2_cache_bo(sna, draw,
772.26830 -+			  private->bo,
772.26831 -+			  buffer->name,
772.26832 -+			  private->size,
772.26833 -+			  buffer->flags);
772.26834 - 	free(buffer);
772.26835 - }
772.26836 - 
772.26837 - static void sna_dri2_destroy_buffer(DrawablePtr draw, DRI2Buffer2Ptr buffer)
772.26838 - {
772.26839 --	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), buffer);
772.26840 -+	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), draw, buffer);
772.26841 - }
772.26842 - 
772.26843 - static DRI2BufferPtr sna_dri2_reference_buffer(DRI2BufferPtr buffer)
772.26844 - {
772.26845 -+	assert(get_private(buffer)->refcnt > 0);
772.26846 - 	get_private(buffer)->refcnt++;
772.26847 - 	return buffer;
772.26848 - }
772.26849 -@@ -746,10 +988,9 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
772.26850 - {
772.26851 - 	struct sna *sna = to_sna_from_pixmap(pixmap);
772.26852 - 	struct sna_pixmap *priv = sna_pixmap(pixmap);
772.26853 --	RegionRec region;
772.26854 - 
772.26855 --	DBG(("%s: pixmap=%ld, handle=%d\n",
772.26856 --	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle));
772.26857 -+	DBG(("%s: pixmap=%ld, handle=%d (old handle=%d)\n",
772.26858 -+	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle, priv->gpu_bo->handle));
772.26859 - 
772.26860 - 	assert(pixmap->drawable.width * pixmap->drawable.bitsPerPixel <= 8*bo->pitch);
772.26861 - 	assert(pixmap->drawable.height * bo->pitch <= kgem_bo_size(bo));
772.26862 -@@ -758,21 +999,34 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
772.26863 - 	assert((priv->pinned & (PIN_PRIME | PIN_DRI3)) == 0);
772.26864 - 	assert(priv->flush);
772.26865 - 
772.26866 --	/* Post damage on the new front buffer so that listeners, such
772.26867 --	 * as DisplayLink know take a copy and shove it over the USB,
772.26868 --	 * also for software cursors and the like.
772.26869 --	 */
772.26870 --	region.extents.x1 = region.extents.y1 = 0;
772.26871 --	region.extents.x2 = pixmap->drawable.width;
772.26872 --	region.extents.y2 = pixmap->drawable.height;
772.26873 --	region.data = NULL;
772.26874 --	DamageRegionAppend(&pixmap->drawable, &region);
772.26875 -+	if (APPLY_DAMAGE) {
772.26876 -+		RegionRec region;
772.26877 -+
772.26878 -+		/* Post damage on the new front buffer so that listeners, such
772.26879 -+		 * as DisplayLink know take a copy and shove it over the USB,
772.26880 -+		 * also for software cursors and the like.
772.26881 -+		 */
772.26882 -+		region.extents.x1 = region.extents.y1 = 0;
772.26883 -+		region.extents.x2 = pixmap->drawable.width;
772.26884 -+		region.extents.y2 = pixmap->drawable.height;
772.26885 -+		region.data = NULL;
772.26886 -+
772.26887 -+		/*
772.26888 -+		 * Eeek, beware the sw cursor copying to the old bo
772.26889 -+		 * causing recursion and mayhem.
772.26890 -+		 */
772.26891 -+		DBG(("%s: marking whole pixmap as damaged\n", __FUNCTION__));
772.26892 -+		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
772.26893 -+		DamageRegionAppend(&pixmap->drawable, &region);
772.26894 -+	}
772.26895 - 
772.26896 - 	damage(pixmap, priv, NULL);
772.26897 - 
772.26898 - 	assert(bo->refcnt);
772.26899 --	if (priv->move_to_gpu)
772.26900 -+	if (priv->move_to_gpu) {
772.26901 -+		DBG(("%s: applying final/discard move-to-gpu\n", __FUNCTION__));
772.26902 - 		priv->move_to_gpu(sna, priv, 0);
772.26903 -+	}
772.26904 - 	if (priv->gpu_bo != bo) {
772.26905 - 		DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, priv->gpu_bo->handle));
772.26906 - 		priv->gpu_bo->flush = false;
772.26907 -@@ -792,8 +1046,27 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
772.26908 - 		bo->domain = DOMAIN_NONE;
772.26909 - 	assert(bo->flush);
772.26910 - 
772.26911 --	DamageRegionProcessPending(&pixmap->drawable);
772.26912 -+	if (APPLY_DAMAGE) {
772.26913 -+		sna->ignore_copy_area = false;
772.26914 -+		DamageRegionProcessPending(&pixmap->drawable);
772.26915 -+	}
772.26916 -+}
772.26917 -+
772.26918 -+#if defined(__GNUC__)
772.26919 -+#define popcount(x) __builtin_popcount(x)
772.26920 -+#else
772.26921 -+static int popcount(unsigned int x)
772.26922 -+{
772.26923 -+	int count = 0;
772.26924 -+
772.26925 -+	while (x) {
772.26926 -+		count += x&1;
772.26927 -+		x >>= 1;
772.26928 -+	}
772.26929 -+
772.26930 -+	return count;
772.26931 - }
772.26932 -+#endif
772.26933 - 
772.26934 - static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kgem_bo *src, bool sync)
772.26935 - {
772.26936 -@@ -823,6 +1096,12 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
772.26937 - 		return;
772.26938 - 	}
772.26939 - 
772.26940 -+	if (sna->render_state.gt < 2 && sna->kgem.has_semaphores) {
772.26941 -+		DBG(("%s: small GT [%d], not forcing selection\n",
772.26942 -+		     __FUNCTION__, sna->render_state.gt));
772.26943 -+		return;
772.26944 -+	}
772.26945 -+
772.26946 - 	VG_CLEAR(busy);
772.26947 - 	busy.handle = src->handle;
772.26948 - 	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy))
772.26949 -@@ -860,9 +1139,11 @@ static void sna_dri2_select_mode(struct sna *sna, struct kgem_bo *dst, struct kg
772.26950 - 	 * the cost of the query.
772.26951 - 	 */
772.26952 - 	mode = KGEM_RENDER;
772.26953 --	if (busy.busy & (0xfffe << 16))
772.26954 -+	if ((busy.busy & 0xffff) == I915_EXEC_BLT)
772.26955 - 		mode = KGEM_BLT;
772.26956 --	kgem_bo_mark_busy(&sna->kgem, busy.handle == src->handle ? src : dst, mode);
772.26957 -+	kgem_bo_mark_busy(&sna->kgem,
772.26958 -+			  busy.handle == src->handle ? src : dst,
772.26959 -+			  mode);
772.26960 - 	_kgem_set_mode(&sna->kgem, mode);
772.26961 - }
772.26962 - 
772.26963 -@@ -871,10 +1152,13 @@ static bool is_front(int attachment)
772.26964 - 	return attachment == DRI2BufferFrontLeft;
772.26965 - }
772.26966 - 
772.26967 -+#define DRI2_SYNC 0x1
772.26968 -+#define DRI2_DAMAGE 0x2
772.26969 -+#define DRI2_BO 0x4
772.26970 - static struct kgem_bo *
772.26971 - __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.26972 - 		      DRI2BufferPtr src, DRI2BufferPtr dst,
772.26973 --		      bool sync)
772.26974 -+		      unsigned flags)
772.26975 - {
772.26976 - 	PixmapPtr pixmap = get_drawable_pixmap(draw);
772.26977 - 	DrawableRec scratch, *src_draw = &pixmap->drawable, *dst_draw = &pixmap->drawable;
772.26978 -@@ -886,7 +1170,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.26979 - 	struct kgem_bo *dst_bo;
772.26980 - 	const BoxRec *boxes;
772.26981 - 	int16_t dx, dy, sx, sy;
772.26982 --	unsigned flags;
772.26983 -+	unsigned hint;
772.26984 - 	int n;
772.26985 - 
772.26986 - 	/* To hide a stale DRI2Buffer, one may choose to substitute
772.26987 -@@ -962,8 +1246,9 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.26988 - 			}
772.26989 - 		}
772.26990 - 	} else
772.26991 --		sync = false;
772.26992 -+		flags &= ~DRI2_SYNC;
772.26993 - 
772.26994 -+	scratch.pScreen = draw->pScreen;
772.26995 - 	scratch.x = scratch.y = 0;
772.26996 - 	scratch.width = scratch.height = 0;
772.26997 - 	scratch.depth = draw->depth;
772.26998 -@@ -971,6 +1256,7 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.26999 - 
772.27000 - 	src_bo = src_priv->bo;
772.27001 - 	assert(src_bo->refcnt);
772.27002 -+	kgem_bo_unclean(&sna->kgem, src_bo);
772.27003 - 	if (is_front(src->attachment)) {
772.27004 - 		struct sna_pixmap *priv;
772.27005 - 
772.27006 -@@ -987,11 +1273,12 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27007 - 		scratch.height = src_priv->size >> 16;
772.27008 - 		src_draw = &scratch;
772.27009 - 
772.27010 --		DBG(("%s: source size %dx%d, region size %dx%d\n",
772.27011 -+		DBG(("%s: source size %dx%d, region size %dx%d, src offset %dx%d\n",
772.27012 - 		     __FUNCTION__,
772.27013 - 		     scratch.width, scratch.height,
772.27014 - 		     clip.extents.x2 - clip.extents.x1,
772.27015 --		     clip.extents.y2 - clip.extents.y1));
772.27016 -+		     clip.extents.y2 - clip.extents.y1,
772.27017 -+		     -sx, -sy));
772.27018 - 
772.27019 - 		source.extents.x1 = -sx;
772.27020 - 		source.extents.y1 = -sy;
772.27021 -@@ -1002,6 +1289,10 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27022 - 		assert(region == NULL || region == &clip);
772.27023 - 		pixman_region_intersect(&clip, &clip, &source);
772.27024 - 
772.27025 -+		if (!pixman_region_not_empty(&clip)) {
772.27026 -+			DBG(("%s: region doesn't overlap pixmap\n", __FUNCTION__));
772.27027 -+			return NULL;
772.27028 -+		}
772.27029 - 	}
772.27030 - 
772.27031 - 	dst_bo = dst_priv->bo;
772.27032 -@@ -1013,12 +1304,12 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27033 - 		/* Preserve the CRTC shadow overrides */
772.27034 - 		sna_shadow_steal_crtcs(sna, &shadow);
772.27035 - 
772.27036 --		flags = MOVE_WRITE | __MOVE_FORCE;
772.27037 -+		hint = MOVE_WRITE | __MOVE_FORCE;
772.27038 - 		if (clip.data)
772.27039 --			flags |= MOVE_READ;
772.27040 -+			hint |= MOVE_READ;
772.27041 - 
772.27042 - 		assert(region == NULL || region == &clip);
772.27043 --		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, flags);
772.27044 -+		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, hint);
772.27045 - 		if (priv) {
772.27046 - 			damage(pixmap, priv, region);
772.27047 - 			dst_bo = priv->gpu_bo;
772.27048 -@@ -1050,20 +1341,20 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27049 - 		assert(region == NULL || region == &clip);
772.27050 - 		pixman_region_intersect(&clip, &clip, &target);
772.27051 - 
772.27052 --		sync = false;
772.27053 -+		flags &= ~DRI2_SYNC;
772.27054 - 	}
772.27055 - 
772.27056 - 	if (!wedged(sna)) {
772.27057 - 		xf86CrtcPtr crtc;
772.27058 - 
772.27059 - 		crtc = NULL;
772.27060 --		if (sync && sna_pixmap_is_scanout(sna, pixmap))
772.27061 -+		if (flags & DRI2_SYNC && sna_pixmap_is_scanout(sna, pixmap))
772.27062 - 			crtc = sna_covering_crtc(sna, &clip.extents, NULL);
772.27063 - 		sna_dri2_select_mode(sna, dst_bo, src_bo, crtc != NULL);
772.27064 - 
772.27065 --		sync = (crtc != NULL&&
772.27066 --			sna_wait_for_scanline(sna, pixmap, crtc,
772.27067 --					      &clip.extents));
772.27068 -+		if (crtc == NULL ||
772.27069 -+		    !sna_wait_for_scanline(sna, pixmap, crtc, &clip.extents))
772.27070 -+			flags &= ~DRI2_SYNC;
772.27071 - 	}
772.27072 - 
772.27073 - 	if (region) {
772.27074 -@@ -1075,8 +1366,11 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27075 - 		boxes = &clip.extents;
772.27076 - 		n = 1;
772.27077 - 	}
772.27078 --	DamageRegionAppend(&pixmap->drawable, region);
772.27079 --
772.27080 -+	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
772.27081 -+		DBG(("%s: marking region as damaged\n", __FUNCTION__));
772.27082 -+		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
772.27083 -+		DamageRegionAppend(&pixmap->drawable, region);
772.27084 -+	}
772.27085 - 
772.27086 - 	DBG(("%s: copying [(%d, %d), (%d, %d)]x%d src=(%d, %d), dst=(%d, %d)\n",
772.27087 - 	     __FUNCTION__,
772.27088 -@@ -1084,29 +1378,36 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
772.27089 - 	     boxes[0].x2, boxes[0].y2,
772.27090 - 	     n, sx, sy, dx, dy));
772.27091 - 
772.27092 --	flags = COPY_LAST;
772.27093 --	if (sync)
772.27094 --		flags |= COPY_SYNC;
772.27095 -+	hint = COPY_LAST | COPY_DRI;
772.27096 -+	if (flags & DRI2_SYNC)
772.27097 -+		hint |= COPY_SYNC;
772.27098 - 	if (!sna->render.copy_boxes(sna, GXcopy,
772.27099 - 				    src_draw, src_bo, sx, sy,
772.27100 - 				    dst_draw, dst_bo, dx, dy,
772.27101 --				    boxes, n, flags))
772.27102 -+				    boxes, n, hint))
772.27103 - 		memcpy_copy_boxes(sna, GXcopy,
772.27104 - 				  src_draw, src_bo, sx, sy,
772.27105 - 				  dst_draw, dst_bo, dx, dy,
772.27106 --				  boxes, n, flags);
772.27107 --
772.27108 --	DBG(("%s: flushing? %d\n", __FUNCTION__, sync));
772.27109 --	if (sync) { /* STAT! */
772.27110 --		struct kgem_request *rq = sna->kgem.next_request;
772.27111 --		kgem_submit(&sna->kgem);
772.27112 --		if (rq->bo) {
772.27113 --			bo = ref(rq->bo);
772.27114 --			DBG(("%s: recording sync fence handle=%d\n", __FUNCTION__, bo->handle));
772.27115 -+				  boxes, n, hint);
772.27116 -+
772.27117 -+	sna->needs_dri_flush = true;
772.27118 -+	if (flags & (DRI2_SYNC | DRI2_BO)) { /* STAT! */
772.27119 -+		struct kgem_request *rq = RQ(dst_bo->rq);
772.27120 -+		if (rq && rq != (void *)&sna->kgem) {
772.27121 -+			if (rq->bo == NULL)
772.27122 -+				kgem_submit(&sna->kgem);
772.27123 -+			if (rq->bo) { /* Becareful in case the gpu is wedged */
772.27124 -+				bo = ref(rq->bo);
772.27125 -+				DBG(("%s: recording sync fence handle=%d\n",
772.27126 -+				     __FUNCTION__, bo->handle));
772.27127 -+			}
772.27128 - 		}
772.27129 - 	}
772.27130 - 
772.27131 --	DamageRegionProcessPending(&pixmap->drawable);
772.27132 -+	if (APPLY_DAMAGE || flags & DRI2_DAMAGE) {
772.27133 -+		sna->ignore_copy_area = false;
772.27134 -+		DamageRegionProcessPending(&pixmap->drawable);
772.27135 -+	}
772.27136 - 
772.27137 - 	if (clip.data)
772.27138 - 		pixman_region_fini(&clip);
772.27139 -@@ -1142,6 +1443,8 @@ sna_dri2_copy_region(DrawablePtr draw,
772.27140 - 	assert(get_private(src)->refcnt);
772.27141 - 	assert(get_private(dst)->refcnt);
772.27142 - 
772.27143 -+	assert(get_private(src)->bo != get_private(dst)->bo);
772.27144 -+
772.27145 - 	assert(get_private(src)->bo->refcnt);
772.27146 - 	assert(get_private(dst)->bo->refcnt);
772.27147 - 
772.27148 -@@ -1151,7 +1454,7 @@ sna_dri2_copy_region(DrawablePtr draw,
772.27149 - 	     region->extents.x2, region->extents.y2,
772.27150 - 	     region_num_rects(region)));
772.27151 - 
772.27152 --	__sna_dri2_copy_region(sna, draw, region, src, dst, false);
772.27153 -+	__sna_dri2_copy_region(sna, draw, region, src, dst, DRI2_DAMAGE);
772.27154 - }
772.27155 - 
772.27156 - inline static uint32_t pipe_select(int pipe)
772.27157 -@@ -1161,6 +1464,7 @@ inline static uint32_t pipe_select(int pipe)
772.27158 - 	 * we can safely ignore the capability check - if we have more
772.27159 - 	 * than two pipes, we can assume that they are fully supported.
772.27160 - 	 */
772.27161 -+	assert(pipe < _DRM_VBLANK_HIGH_CRTC_MASK);
772.27162 - 	if (pipe > 1)
772.27163 - 		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
772.27164 - 	else if (pipe > 0)
772.27165 -@@ -1169,15 +1473,53 @@ inline static uint32_t pipe_select(int pipe)
772.27166 - 		return 0;
772.27167 - }
772.27168 - 
772.27169 --static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, int pipe)
772.27170 -+static inline bool sna_next_vblank(struct sna_dri2_event *info)
772.27171 - {
772.27172 --	DBG(("%s(pipe=%d, waiting until seq=%u%s)\n",
772.27173 --	     __FUNCTION__, pipe, vbl->request.sequence,
772.27174 --	     vbl->request.type & DRM_VBLANK_RELATIVE ? " [relative]" : ""));
772.27175 --	assert(pipe != -1);
772.27176 -+	union drm_wait_vblank vbl;
772.27177 - 
772.27178 --	vbl->request.type |= pipe_select(pipe);
772.27179 --	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
772.27180 -+	DBG(("%s(pipe=%d, waiting until next vblank)\n",
772.27181 -+	     __FUNCTION__, info->pipe));
772.27182 -+	assert(info->pipe != -1);
772.27183 -+
772.27184 -+	VG_CLEAR(vbl);
772.27185 -+	vbl.request.type =
772.27186 -+		DRM_VBLANK_RELATIVE |
772.27187 -+		DRM_VBLANK_EVENT |
772.27188 -+		pipe_select(info->pipe);
772.27189 -+	vbl.request.sequence = 1;
772.27190 -+	vbl.request.signal = (uintptr_t)info;
772.27191 -+
772.27192 -+	assert(!info->queued);
772.27193 -+	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
772.27194 -+		return false;
772.27195 -+
772.27196 -+	info->queued = true;
772.27197 -+	return true;
772.27198 -+}
772.27199 -+
772.27200 -+static inline bool sna_wait_vblank(struct sna_dri2_event *info,
772.27201 -+				   unsigned seq)
772.27202 -+{
772.27203 -+	union drm_wait_vblank vbl;
772.27204 -+
772.27205 -+	DBG(("%s(pipe=%d, waiting until vblank %u)\n",
772.27206 -+	     __FUNCTION__, info->pipe, seq));
772.27207 -+	assert(info->pipe != -1);
772.27208 -+
772.27209 -+	VG_CLEAR(vbl);
772.27210 -+	vbl.request.type =
772.27211 -+		DRM_VBLANK_ABSOLUTE |
772.27212 -+		DRM_VBLANK_EVENT |
772.27213 -+		pipe_select(info->pipe);
772.27214 -+	vbl.request.sequence = seq;
772.27215 -+	vbl.request.signal = (uintptr_t)info;
772.27216 -+
772.27217 -+	assert(!info->queued);
772.27218 -+	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
772.27219 -+		return false;
772.27220 -+
772.27221 -+	info->queued = true;
772.27222 -+	return true;
772.27223 - }
772.27224 - 
772.27225 - #if DRI2INFOREC_VERSION >= 4
772.27226 -@@ -1195,6 +1537,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
772.27227 - {
772.27228 - 	struct dri2_window *priv;
772.27229 - 
772.27230 -+	assert(draw);
772.27231 - 	if (draw->type != DRAWABLE_WINDOW)
772.27232 - 		return msc;
772.27233 - 
772.27234 -@@ -1206,6 +1549,9 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
772.27235 - 			priv->crtc = crtc;
772.27236 - 			priv->msc_delta = 0;
772.27237 - 			priv->chain = NULL;
772.27238 -+			priv->scanout = -1;
772.27239 -+			priv->cache_size = 0;
772.27240 -+			list_init(&priv->cache);
772.27241 - 			dri2_window_attach((WindowPtr)draw, priv);
772.27242 - 		}
772.27243 - 	} else {
772.27244 -@@ -1214,8 +1560,8 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
772.27245 - 			const struct ust_msc *this = sna_crtc_last_swap(crtc);
772.27246 - 			DBG(("%s: Window transferring from pipe=%d [msc=%llu] to pipe=%d [msc=%llu], delta now %lld\n",
772.27247 - 			     __FUNCTION__,
772.27248 --			     sna_crtc_to_pipe(priv->crtc), (long long)last->msc,
772.27249 --			     sna_crtc_to_pipe(crtc), (long long)this->msc,
772.27250 -+			     sna_crtc_pipe(priv->crtc), (long long)last->msc,
772.27251 -+			     sna_crtc_pipe(crtc), (long long)this->msc,
772.27252 - 			     (long long)(priv->msc_delta + this->msc - last->msc)));
772.27253 - 			priv->msc_delta += this->msc - last->msc;
772.27254 - 			priv->crtc = crtc;
772.27255 -@@ -1248,57 +1594,119 @@ sna_dri2_get_crtc(DrawablePtr draw)
772.27256 - 				 NULL);
772.27257 - }
772.27258 - 
772.27259 --static void
772.27260 --sna_dri2_remove_event(WindowPtr win, struct sna_dri2_event *info)
772.27261 -+static void frame_swap_complete(struct sna_dri2_event *frame, int type)
772.27262 - {
772.27263 --	struct dri2_window *priv;
772.27264 --	struct sna_dri2_event *chain;
772.27265 --
772.27266 --	assert(win->drawable.type == DRAWABLE_WINDOW);
772.27267 --	DBG(("%s: remove[%p] from window %ld, active? %d\n",
772.27268 --	     __FUNCTION__, info, (long)win->drawable.id, info->draw != NULL));
772.27269 -+	const struct ust_msc *swap;
772.27270 - 
772.27271 --	priv = dri2_window(win);
772.27272 --	assert(priv);
772.27273 --	assert(priv->chain != NULL);
772.27274 -+	assert(frame->signal);
772.27275 -+	frame->signal = false;
772.27276 - 
772.27277 --	if (priv->chain == info) {
772.27278 --		priv->chain = info->chain;
772.27279 -+	if (frame->client == NULL) {
772.27280 -+		DBG(("%s: client already gone\n", __FUNCTION__));
772.27281 - 		return;
772.27282 - 	}
772.27283 - 
772.27284 --	chain = priv->chain;
772.27285 --	while (chain->chain != info)
772.27286 --		chain = chain->chain;
772.27287 --	assert(chain != info);
772.27288 --	assert(info->chain != chain);
772.27289 --	chain->chain = info->chain;
772.27290 -+	assert(frame->draw);
772.27291 -+
772.27292 -+	swap = sna_crtc_last_swap(frame->crtc);
772.27293 -+	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc=%lld], tv=%d.%06d\n",
772.27294 -+	     __FUNCTION__, type, (long)frame->draw->id, frame->pipe,
772.27295 -+	     (long long)swap->msc,
772.27296 -+	     (long long)draw_current_msc(frame->draw, frame->crtc, swap->msc),
772.27297 -+	     swap->tv_sec, swap->tv_usec));
772.27298 -+
772.27299 -+	DRI2SwapComplete(frame->client, frame->draw,
772.27300 -+			 draw_current_msc(frame->draw, frame->crtc, swap->msc),
772.27301 -+			 swap->tv_sec, swap->tv_usec,
772.27302 -+			 type, frame->event_complete, frame->event_data);
772.27303 - }
772.27304 - 
772.27305 --static void
772.27306 --sna_dri2_event_free(struct sna_dri2_event *info)
772.27307 -+static void fake_swap_complete(struct sna *sna, ClientPtr client,
772.27308 -+			       DrawablePtr draw, xf86CrtcPtr crtc,
772.27309 -+			       int type, DRI2SwapEventPtr func, void *data)
772.27310 - {
772.27311 --	DrawablePtr draw = info->draw;
772.27312 -+	const struct ust_msc *swap;
772.27313 - 
772.27314 --	DBG(("%s(draw?=%d)\n", __FUNCTION__, draw != NULL));
772.27315 --	if (draw && draw->type == DRAWABLE_WINDOW)
772.27316 --		sna_dri2_remove_event((WindowPtr)draw, info);
772.27317 -+	assert(draw);
772.27318 - 
772.27319 --	_sna_dri2_destroy_buffer(info->sna, info->front);
772.27320 --	_sna_dri2_destroy_buffer(info->sna, info->back);
772.27321 -+	if (crtc == NULL)
772.27322 -+		crtc = sna_primary_crtc(sna);
772.27323 - 
772.27324 --	while (!list_is_empty(&info->cache)) {
772.27325 --		struct dri_bo *c;
772.27326 -+	swap = sna_crtc_last_swap(crtc);
772.27327 -+	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n",
772.27328 -+	     __FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_pipe(crtc) : -1,
772.27329 -+	     (long long)swap->msc,
772.27330 -+	     (long long)draw_current_msc(draw, crtc, swap->msc),
772.27331 -+	     swap->tv_sec, swap->tv_usec));
772.27332 - 
772.27333 --		c = list_first_entry(&info->cache, struct dri_bo, link);
772.27334 --		list_del(&c->link);
772.27335 -+	DRI2SwapComplete(client, draw,
772.27336 -+			 draw_current_msc(draw, crtc, swap->msc),
772.27337 -+			 swap->tv_sec, swap->tv_usec,
772.27338 -+			 type, func, data);
772.27339 -+}
772.27340 - 
772.27341 --		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
772.27342 --		if (c->bo)
772.27343 --			kgem_bo_destroy(&info->sna->kgem, c->bo);
772.27344 -+static void
772.27345 -+sna_dri2_remove_event(struct sna_dri2_event *info)
772.27346 -+{
772.27347 -+	WindowPtr win = (WindowPtr)info->draw;
772.27348 -+	struct dri2_window *priv;
772.27349 - 
772.27350 --		free(c);
772.27351 -+	assert(win->drawable.type == DRAWABLE_WINDOW);
772.27352 -+	DBG(("%s: remove[%p] from window %ld, active? %d\n",
772.27353 -+	     __FUNCTION__, info, (long)win->drawable.id, info->draw != NULL));
772.27354 -+	assert(!info->signal);
772.27355 -+
772.27356 -+	priv = dri2_window(win);
772.27357 -+	assert(priv);
772.27358 -+	assert(priv->chain != NULL);
772.27359 -+	assert(info->chained);
772.27360 -+	info->chained = false;
772.27361 -+
772.27362 -+	if (priv->chain != info) {
772.27363 -+		struct sna_dri2_event *chain = priv->chain;
772.27364 -+		while (chain->chain != info) {
772.27365 -+			assert(chain->chained);
772.27366 -+			chain = chain->chain;
772.27367 -+		}
772.27368 -+		assert(chain != info);
772.27369 -+		assert(info->chain != chain);
772.27370 -+		chain->chain = info->chain;
772.27371 -+		return;
772.27372 -+	}
772.27373 -+
772.27374 -+	priv->chain = info->chain;
772.27375 -+	if (priv->chain == NULL) {
772.27376 -+		struct dri_bo *c, *tmp;
772.27377 -+
772.27378 -+		c = list_entry(priv->cache.next->next, struct dri_bo, link);
772.27379 -+		list_for_each_entry_safe_from(c, tmp, &priv->cache, link) {
772.27380 -+			list_del(&c->link);
772.27381 -+
772.27382 -+			DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
772.27383 -+			assert(c->bo);
772.27384 -+			kgem_bo_destroy(&info->sna->kgem, c->bo);
772.27385 -+			free(c);
772.27386 -+		}
772.27387 - 	}
772.27388 -+}
772.27389 -+
772.27390 -+static void
772.27391 -+sna_dri2_event_free(struct sna_dri2_event *info)
772.27392 -+{
772.27393 -+	DBG(("%s(draw?=%d)\n", __FUNCTION__, info->draw != NULL));
772.27394 -+	assert(!info->queued);
772.27395 -+	assert(!info->signal);
772.27396 -+	assert(info->pending.bo == NULL);
772.27397 -+
772.27398 -+	if (info->sna->dri2.flip_pending == info)
772.27399 -+		info->sna->dri2.flip_pending = NULL;
772.27400 -+	assert(info->sna->dri2.flip_pending != info);
772.27401 -+	if (info->chained)
772.27402 -+		sna_dri2_remove_event(info);
772.27403 -+
772.27404 -+	assert((info->front == NULL && info->back == NULL) || info->front != info->back);
772.27405 -+	_sna_dri2_destroy_buffer(info->sna, info->draw, info->front);
772.27406 -+	_sna_dri2_destroy_buffer(info->sna, info->draw, info->back);
772.27407 - 
772.27408 - 	if (info->bo) {
772.27409 - 		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
772.27410 -@@ -1331,15 +1739,26 @@ sna_dri2_client_gone(CallbackListPtr *list, void *closure, void *data)
772.27411 - 
772.27412 - 		event = list_first_entry(&priv->events, struct sna_dri2_event, link);
772.27413 - 		assert(event->client == client);
772.27414 -+		list_del(&event->link);
772.27415 -+		event->signal = false;
772.27416 - 
772.27417 --		if (event->queued) {
772.27418 --			if (event->draw)
772.27419 --				sna_dri2_remove_event((WindowPtr)event->draw,
772.27420 --						      event);
772.27421 --			event->client = NULL;
772.27422 --			event->draw = NULL;
772.27423 --			list_del(&event->link);
772.27424 --		} else
772.27425 -+		if (event->pending.bo) {
772.27426 -+			assert(event->pending.bo->active_scanout > 0);
772.27427 -+			event->pending.bo->active_scanout--;
772.27428 -+
772.27429 -+			kgem_bo_destroy(&sna->kgem, event->pending.bo);
772.27430 -+			event->pending.bo = NULL;
772.27431 -+		}
772.27432 -+
772.27433 -+		if (event->chained)
772.27434 -+			sna_dri2_remove_event(event);
772.27435 -+
772.27436 -+		event->client = NULL;
772.27437 -+		event->draw = NULL;
772.27438 -+		event->keepalive = 1;
772.27439 -+		assert(!event->signal);
772.27440 -+
772.27441 -+		if (!event->queued)
772.27442 - 			sna_dri2_event_free(event);
772.27443 - 	}
772.27444 - 
772.27445 -@@ -1365,11 +1784,15 @@ static bool add_event_to_client(struct sna_dri2_event *info, struct sna *sna, Cl
772.27446 - }
772.27447 - 
772.27448 - static struct sna_dri2_event *
772.27449 --sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
772.27450 -+sna_dri2_add_event(struct sna *sna,
772.27451 -+		   DrawablePtr draw,
772.27452 -+		   ClientPtr client,
772.27453 -+		   xf86CrtcPtr crtc)
772.27454 - {
772.27455 - 	struct dri2_window *priv;
772.27456 - 	struct sna_dri2_event *info, *chain;
772.27457 - 
772.27458 -+	assert(draw != NULL);
772.27459 - 	assert(draw->type == DRAWABLE_WINDOW);
772.27460 - 	DBG(("%s: adding event to window %ld)\n",
772.27461 - 	     __FUNCTION__, (long)draw->id));
772.27462 -@@ -1382,11 +1805,11 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
772.27463 - 	if (info == NULL)
772.27464 - 		return NULL;
772.27465 - 
772.27466 --	list_init(&info->cache);
772.27467 - 	info->sna = sna;
772.27468 - 	info->draw = draw;
772.27469 --	info->crtc = priv->crtc;
772.27470 --	info->pipe = sna_crtc_to_pipe(priv->crtc);
772.27471 -+	info->crtc = crtc;
772.27472 -+	info->pipe = sna_crtc_pipe(crtc);
772.27473 -+	info->keepalive = 1;
772.27474 - 
772.27475 - 	if (!add_event_to_client(info, sna, client)) {
772.27476 - 		free(info);
772.27477 -@@ -1394,6 +1817,7 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
772.27478 - 	}
772.27479 - 
772.27480 - 	assert(priv->chain != info);
772.27481 -+	info->chained = true;
772.27482 - 
772.27483 - 	if (priv->chain == NULL) {
772.27484 - 		priv->chain = info;
772.27485 -@@ -1409,6 +1833,66 @@ sna_dri2_add_event(struct sna *sna, DrawablePtr draw, ClientPtr client)
772.27486 - 	return info;
772.27487 - }
772.27488 - 
772.27489 -+static void decouple_window(WindowPtr win,
772.27490 -+			    struct dri2_window *priv,
772.27491 -+			    struct sna *sna,
772.27492 -+			    bool signal)
772.27493 -+{
772.27494 -+	if (priv->front) {
772.27495 -+		DBG(("%s: decouple private front\n", __FUNCTION__));
772.27496 -+		assert(priv->crtc);
772.27497 -+		sna_shadow_unset_crtc(sna, priv->crtc);
772.27498 -+
772.27499 -+		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
772.27500 -+		priv->front = NULL;
772.27501 -+	}
772.27502 -+
772.27503 -+	if (priv->chain) {
772.27504 -+		struct sna_dri2_event *info, *chain;
772.27505 -+
772.27506 -+		DBG(("%s: freeing chain\n", __FUNCTION__));
772.27507 -+
772.27508 -+		chain = priv->chain;
772.27509 -+		while ((info = chain)) {
772.27510 -+			DBG(("%s: freeing event, pending signal? %d, pending swap? handle=%d\n",
772.27511 -+			     __FUNCTION__, info->signal,
772.27512 -+			     info->pending.bo ? info->pending.bo->handle : 0));
772.27513 -+			assert(info->draw == &win->drawable);
772.27514 -+
772.27515 -+			if (info->pending.bo) {
772.27516 -+				if (signal) {
772.27517 -+					bool was_signalling = info->signal;
772.27518 -+					info->signal = true;
772.27519 -+					frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
772.27520 -+					info->signal = was_signalling;
772.27521 -+				}
772.27522 -+				assert(info->pending.bo->active_scanout > 0);
772.27523 -+				info->pending.bo->active_scanout--;
772.27524 -+
772.27525 -+				kgem_bo_destroy(&sna->kgem, info->pending.bo);
772.27526 -+				info->pending.bo = NULL;
772.27527 -+			}
772.27528 -+
772.27529 -+			if (info->signal && signal)
772.27530 -+				frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
772.27531 -+			info->signal = false;
772.27532 -+			info->draw = NULL;
772.27533 -+			info->keepalive = 1;
772.27534 -+			assert(!info->signal);
772.27535 -+			list_del(&info->link);
772.27536 -+
772.27537 -+			chain = info->chain;
772.27538 -+			info->chain = NULL;
772.27539 -+			info->chained = false;
772.27540 -+
772.27541 -+			if (!info->queued)
772.27542 -+				sna_dri2_event_free(info);
772.27543 -+		}
772.27544 -+
772.27545 -+		priv->chain = NULL;
772.27546 -+	}
772.27547 -+}
772.27548 -+
772.27549 - void sna_dri2_decouple_window(WindowPtr win)
772.27550 - {
772.27551 - 	struct dri2_window *priv;
772.27552 -@@ -1418,50 +1902,34 @@ void sna_dri2_decouple_window(WindowPtr win)
772.27553 - 		return;
772.27554 - 
772.27555 - 	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
772.27556 -+	decouple_window(win, priv, to_sna_from_drawable(&win->drawable), true);
772.27557 - 
772.27558 --	if (priv->front) {
772.27559 --		struct sna *sna = to_sna_from_drawable(&win->drawable);
772.27560 --		assert(priv->crtc);
772.27561 --		sna_shadow_unset_crtc(sna, priv->crtc);
772.27562 --		_sna_dri2_destroy_buffer(sna, priv->front);
772.27563 --		priv->front = NULL;
772.27564 --	}
772.27565 -+	priv->scanout = -1;
772.27566 - }
772.27567 - 
772.27568 - void sna_dri2_destroy_window(WindowPtr win)
772.27569 - {
772.27570 - 	struct dri2_window *priv;
772.27571 -+	struct sna *sna;
772.27572 - 
772.27573 - 	priv = dri2_window(win);
772.27574 - 	if (priv == NULL)
772.27575 - 		return;
772.27576 - 
772.27577 - 	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
772.27578 -+	sna = to_sna_from_drawable(&win->drawable);
772.27579 -+	decouple_window(win, priv, sna, false);
772.27580 - 
772.27581 --	if (priv->front) {
772.27582 --		struct sna *sna = to_sna_from_drawable(&win->drawable);
772.27583 --		assert(priv->crtc);
772.27584 --		sna_shadow_unset_crtc(sna, priv->crtc);
772.27585 --		_sna_dri2_destroy_buffer(sna, priv->front);
772.27586 --	}
772.27587 --
772.27588 --	if (priv->chain) {
772.27589 --		struct sna_dri2_event *info, *chain;
772.27590 --
772.27591 --		DBG(("%s: freeing chain\n", __FUNCTION__));
772.27592 --
772.27593 --		chain = priv->chain;
772.27594 --		while ((info = chain)) {
772.27595 --			info->draw = NULL;
772.27596 --			info->client = NULL;
772.27597 --			list_del(&info->link);
772.27598 -+	while (!list_is_empty(&priv->cache)) {
772.27599 -+		struct dri_bo *c;
772.27600 - 
772.27601 --			chain = info->chain;
772.27602 --			info->chain = NULL;
772.27603 -+		c = list_first_entry(&priv->cache, struct dri_bo, link);
772.27604 -+		list_del(&c->link);
772.27605 - 
772.27606 --			if (!info->queued)
772.27607 --				sna_dri2_event_free(info);
772.27608 --		}
772.27609 -+		DBG(("%s: releasing cached handle=%d\n", __FUNCTION__, c->bo ? c->bo->handle : 0));
772.27610 -+		assert(c->bo);
772.27611 -+		kgem_bo_destroy(&sna->kgem, c->bo);
772.27612 -+		free(c);
772.27613 - 	}
772.27614 - 
772.27615 - 	free(priv);
772.27616 -@@ -1479,19 +1947,30 @@ sna_dri2_flip(struct sna_dri2_event *info)
772.27617 - {
772.27618 - 	struct kgem_bo *bo = get_private(info->back)->bo;
772.27619 - 	struct kgem_bo *tmp_bo;
772.27620 --	uint32_t tmp_name;
772.27621 -+	uint32_t tmp_name, tmp_flags;
772.27622 - 	int tmp_pitch;
772.27623 - 
772.27624 - 	DBG(("%s(type=%d)\n", __FUNCTION__, info->type));
772.27625 - 
772.27626 - 	assert(sna_pixmap_get_buffer(info->sna->front) == info->front);
772.27627 - 	assert(get_drawable_pixmap(info->draw)->drawable.height * bo->pitch <= kgem_bo_size(bo));
772.27628 -+	assert(get_private(info->front)->size == get_private(info->back)->size);
772.27629 - 	assert(bo->refcnt);
772.27630 - 
772.27631 -+	if (info->sna->mode.flip_active) {
772.27632 -+		DBG(("%s: %d flips still active, aborting\n",
772.27633 -+		     __FUNCTION__, info->sna->mode.flip_active));
772.27634 -+		return false;
772.27635 -+	}
772.27636 -+
772.27637 -+	assert(!info->queued);
772.27638 - 	if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler,
772.27639 - 			   info->type == FLIP_ASYNC ? NULL : info))
772.27640 - 		return false;
772.27641 - 
772.27642 -+	DBG(("%s: queued flip=%p\n", __FUNCTION__, info->type == FLIP_ASYNC ? NULL : info));
772.27643 -+	assert(info->signal || info->type != FLIP_THROTTLE);
772.27644 -+
772.27645 - 	assert(info->sna->dri2.flip_pending == NULL ||
772.27646 - 	       info->sna->dri2.flip_pending == info);
772.27647 - 	if (info->type != FLIP_ASYNC)
772.27648 -@@ -1505,13 +1984,21 @@ sna_dri2_flip(struct sna_dri2_event *info)
772.27649 - 	tmp_bo = get_private(info->front)->bo;
772.27650 - 	tmp_name = info->front->name;
772.27651 - 	tmp_pitch = info->front->pitch;
772.27652 -+	tmp_flags = info->front->flags;
772.27653 -+
772.27654 -+	assert(tmp_bo->active_scanout > 0);
772.27655 -+	tmp_bo->active_scanout--;
772.27656 - 
772.27657 - 	set_bo(info->sna->front, bo);
772.27658 - 
772.27659 -+	info->front->flags = info->back->flags;
772.27660 - 	info->front->name = info->back->name;
772.27661 - 	info->front->pitch = info->back->pitch;
772.27662 - 	get_private(info->front)->bo = bo;
772.27663 -+	bo->active_scanout++;
772.27664 -+	assert(bo->active_scanout <= bo->refcnt);
772.27665 - 
772.27666 -+	info->back->flags = tmp_flags;
772.27667 - 	info->back->name = tmp_name;
772.27668 - 	info->back->pitch = tmp_pitch;
772.27669 - 	get_private(info->back)->bo = tmp_bo;
772.27670 -@@ -1521,6 +2008,7 @@ sna_dri2_flip(struct sna_dri2_event *info)
772.27671 - 	assert(get_private(info->back)->bo->refcnt);
772.27672 - 	assert(get_private(info->front)->bo != get_private(info->back)->bo);
772.27673 - 
772.27674 -+	info->keepalive = KEEPALIVE;
772.27675 - 	info->queued = true;
772.27676 - 	return true;
772.27677 - }
772.27678 -@@ -1549,15 +2037,16 @@ can_flip(struct sna * sna,
772.27679 - 	}
772.27680 - 
772.27681 - 	assert(sna->scrn->vtSema);
772.27682 -+	assert(!sna->mode.hidden);
772.27683 - 
772.27684 - 	if ((sna->flags & (SNA_HAS_FLIP | SNA_HAS_ASYNC_FLIP)) == 0) {
772.27685 - 		DBG(("%s: no, pageflips disabled\n", __FUNCTION__));
772.27686 - 		return false;
772.27687 - 	}
772.27688 - 
772.27689 --	if (front->format != back->format) {
772.27690 -+	if (front->cpp != back->cpp) {
772.27691 - 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
772.27692 --		     __FUNCTION__, front->format, back->format));
772.27693 -+		     __FUNCTION__, front->cpp, back->cpp));
772.27694 - 		return false;
772.27695 - 	}
772.27696 - 
772.27697 -@@ -1567,7 +2056,7 @@ can_flip(struct sna * sna,
772.27698 - 	}
772.27699 - 
772.27700 - 	if (!sna_crtc_is_on(crtc)) {
772.27701 --		DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_to_pipe(crtc)));
772.27702 -+		DBG(("%s: ref-pipe=%d is disabled\n", __FUNCTION__, sna_crtc_pipe(crtc)));
772.27703 - 		return false;
772.27704 - 	}
772.27705 - 
772.27706 -@@ -1581,7 +2070,7 @@ can_flip(struct sna * sna,
772.27707 - 	if (sna_pixmap_get_buffer(pixmap) != front) {
772.27708 - 		DBG(("%s: no, DRI2 drawable is no longer attached (old name=%d, new name=%d) to pixmap=%ld\n",
772.27709 - 		     __FUNCTION__, front->name,
772.27710 --		     sna_pixmap_get_buffer(pixmap) ? ((DRI2BufferPtr)sna_pixmap_get_buffer(pixmap))->name : 0,
772.27711 -+		     sna_pixmap_get_buffer(pixmap) ? sna_pixmap_get_buffer(pixmap)->name : 0,
772.27712 - 		     pixmap->drawable.serialNumber));
772.27713 - 		return false;
772.27714 - 	}
772.27715 -@@ -1661,7 +2150,6 @@ can_flip(struct sna * sna,
772.27716 - 	}
772.27717 - 
772.27718 - 	DBG(("%s: yes, pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber));
772.27719 --	assert(dri2_window(win)->front == NULL);
772.27720 - 	return true;
772.27721 - }
772.27722 - 
772.27723 -@@ -1680,9 +2168,9 @@ can_xchg(struct sna *sna,
772.27724 - 	if (draw->type == DRAWABLE_PIXMAP)
772.27725 - 		return false;
772.27726 - 
772.27727 --	if (front->format != back->format) {
772.27728 -+	if (front->cpp != back->cpp) {
772.27729 - 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
772.27730 --		     __FUNCTION__, front->format, back->format));
772.27731 -+		     __FUNCTION__, front->cpp, back->cpp));
772.27732 - 		return false;
772.27733 - 	}
772.27734 - 
772.27735 -@@ -1714,6 +2202,8 @@ can_xchg(struct sna *sna,
772.27736 - 		return false;
772.27737 - 	}
772.27738 - 
772.27739 -+	DBG(("%s: back size=%x, front size=%x\n",
772.27740 -+	     __FUNCTION__, get_private(back)->size, get_private(front)->size));
772.27741 - 	if (get_private(back)->size != get_private(front)->size) {
772.27742 - 		DBG(("%s: no, back buffer %dx%d does not match front buffer %dx%d\n",
772.27743 - 		     __FUNCTION__,
772.27744 -@@ -1766,9 +2256,9 @@ overlaps_other_crtc(struct sna *sna, xf86CrtcPtr desired)
772.27745 - static bool
772.27746 - can_xchg_crtc(struct sna *sna,
772.27747 - 	      DrawablePtr draw,
772.27748 -+	      xf86CrtcPtr crtc,
772.27749 - 	      DRI2BufferPtr front,
772.27750 --	      DRI2BufferPtr back,
772.27751 --	      xf86CrtcPtr crtc)
772.27752 -+	      DRI2BufferPtr back)
772.27753 - {
772.27754 - 	WindowPtr win = (WindowPtr)draw;
772.27755 - 	PixmapPtr pixmap;
772.27756 -@@ -1785,9 +2275,9 @@ can_xchg_crtc(struct sna *sna,
772.27757 - 	if (draw->type == DRAWABLE_PIXMAP)
772.27758 - 		return false;
772.27759 - 
772.27760 --	if (front->format != back->format) {
772.27761 -+	if (front->cpp != back->cpp) {
772.27762 - 		DBG(("%s: no, format mismatch, front = %d, back = %d\n",
772.27763 --		     __FUNCTION__, front->format, back->format));
772.27764 -+		     __FUNCTION__, front->cpp, back->cpp));
772.27765 - 		return false;
772.27766 - 	}
772.27767 - 
772.27768 -@@ -1866,20 +2356,21 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
772.27769 - 
772.27770 - 	back_bo = get_private(back)->bo;
772.27771 - 	front_bo = get_private(front)->bo;
772.27772 --	assert(front_bo != back_bo);
772.27773 - 
772.27774 --	DBG(("%s: win=%ld, exchange front=%d/%d and back=%d/%d, pixmap=%ld %dx%d\n",
772.27775 -+	DBG(("%s: win=%ld, exchange front=%d/%d,ref=%d and back=%d/%d,ref=%d, pixmap=%ld %dx%d\n",
772.27776 - 	     __FUNCTION__, win->drawable.id,
772.27777 --	     front_bo->handle, front->name,
772.27778 --	     back_bo->handle, back->name,
772.27779 -+	     front_bo->handle, front->name, get_private(front)->refcnt,
772.27780 -+	     back_bo->handle, back->name, get_private(back)->refcnt,
772.27781 - 	     pixmap->drawable.serialNumber,
772.27782 - 	     pixmap->drawable.width,
772.27783 - 	     pixmap->drawable.height));
772.27784 - 
772.27785 --	DBG(("%s: back_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
772.27786 --	     __FUNCTION__, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
772.27787 --	DBG(("%s: front_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
772.27788 --	     __FUNCTION__, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
772.27789 -+	DBG(("%s: back_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
772.27790 -+	     __FUNCTION__, back_bo->handle, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
772.27791 -+	DBG(("%s: front_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
772.27792 -+	     __FUNCTION__, front_bo->handle, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
772.27793 -+
772.27794 -+	assert(front_bo != back_bo);
772.27795 - 	assert(front_bo->refcnt);
772.27796 - 	assert(back_bo->refcnt);
772.27797 - 
772.27798 -@@ -1894,6 +2385,11 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
772.27799 - 	get_private(back)->bo = front_bo;
772.27800 - 	mark_stale(back);
772.27801 - 
772.27802 -+	assert(front_bo->active_scanout > 0);
772.27803 -+	front_bo->active_scanout--;
772.27804 -+	back_bo->active_scanout++;
772.27805 -+	assert(back_bo->active_scanout <= back_bo->refcnt);
772.27806 -+
772.27807 - 	tmp = front->name;
772.27808 - 	front->name = back->name;
772.27809 - 	back->name = tmp;
772.27810 -@@ -1902,17 +2398,23 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
772.27811 - 	front->pitch = back->pitch;
772.27812 - 	back->pitch = tmp;
772.27813 - 
772.27814 -+	tmp = front->flags;
772.27815 -+	front->flags = back->flags;
772.27816 -+	back->flags = tmp;
772.27817 -+
772.27818 - 	assert(front_bo->refcnt);
772.27819 - 	assert(back_bo->refcnt);
772.27820 - 
772.27821 -+	assert(front_bo->pitch == get_private(front)->bo->pitch);
772.27822 -+	assert(back_bo->pitch == get_private(back)->bo->pitch);
772.27823 -+
772.27824 - 	assert(get_private(front)->bo == sna_pixmap(pixmap)->gpu_bo);
772.27825 - }
772.27826 - 
772.27827 - static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc, DRI2BufferPtr front, DRI2BufferPtr back)
772.27828 - {
772.27829 - 	WindowPtr win = (WindowPtr)draw;
772.27830 --	DRI2Buffer2Ptr tmp;
772.27831 --	struct kgem_bo *bo;
772.27832 -+	struct dri2_window *priv = dri2_window(win);
772.27833 - 
772.27834 - 	DBG(("%s: exchange front=%d/%d and back=%d/%d, win id=%lu, pixmap=%ld %dx%d\n",
772.27835 - 	     __FUNCTION__,
772.27836 -@@ -1922,162 +2424,130 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
772.27837 - 	     get_window_pixmap(win)->drawable.serialNumber,
772.27838 - 	     get_window_pixmap(win)->drawable.width,
772.27839 - 	     get_window_pixmap(win)->drawable.height));
772.27840 -+	assert(can_xchg_crtc(sna, draw, crtc, front, back));
772.27841 - 
772.27842 --	DamageRegionAppend(&win->drawable, &win->clipList);
772.27843 -+	if (APPLY_DAMAGE) {
772.27844 -+		DBG(("%s: marking drawable as damaged\n", __FUNCTION__));
772.27845 -+		sna->ignore_copy_area = sna->flags & SNA_TEAR_FREE;
772.27846 -+		DamageRegionAppend(&win->drawable, &win->clipList);
772.27847 -+	}
772.27848 - 	sna_shadow_set_crtc(sna, crtc, get_private(back)->bo);
772.27849 --	DamageRegionProcessPending(&win->drawable);
772.27850 -+	if (APPLY_DAMAGE) {
772.27851 -+		sna->ignore_copy_area = false;
772.27852 -+		DamageRegionProcessPending(&win->drawable);
772.27853 -+	}
772.27854 - 
772.27855 --	assert(dri2_window(win)->front == NULL);
772.27856 -+	if (priv->front == NULL) {
772.27857 -+		DRI2Buffer2Ptr tmp;
772.27858 - 
772.27859 --	tmp = calloc(1, sizeof(*tmp) + sizeof(struct sna_dri2_private));
772.27860 --	if (tmp == NULL) {
772.27861 --		back->attachment = -1;
772.27862 --		if (get_private(back)->proxy == NULL) {
772.27863 --			get_private(back)->pixmap = get_window_pixmap(win);
772.27864 --			get_private(back)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(back)->pixmap));
772.27865 -+		tmp = calloc(1, sizeof(*tmp) + sizeof(struct sna_dri2_private));
772.27866 -+		if (tmp == NULL) {
772.27867 -+			sna_shadow_unset_crtc(sna, crtc);
772.27868 -+			return;
772.27869 - 		}
772.27870 --		dri2_window(win)->front = sna_dri2_reference_buffer(back);
772.27871 --		return;
772.27872 --	}
772.27873 - 
772.27874 --	*tmp = *back;
772.27875 --	tmp->attachment = DRI2BufferFrontLeft;
772.27876 --	tmp->driverPrivate = tmp + 1;
772.27877 --	get_private(tmp)->refcnt = 1;
772.27878 --	get_private(tmp)->bo = get_private(back)->bo;
772.27879 --	get_private(tmp)->size = get_private(back)->size;
772.27880 --	get_private(tmp)->pixmap = get_window_pixmap(win);
772.27881 --	get_private(tmp)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(tmp)->pixmap));
772.27882 --	dri2_window(win)->front = tmp;
772.27883 --
772.27884 --	DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
772.27885 --	back->name = 0;
772.27886 --	bo = kgem_create_2d(&sna->kgem,
772.27887 --			    draw->width, draw->height, draw->bitsPerPixel,
772.27888 --			    get_private(back)->bo->tiling,
772.27889 --			    CREATE_SCANOUT);
772.27890 --	if (bo != NULL) {
772.27891 --		get_private(back)->bo = bo;
772.27892 --		back->pitch = bo->pitch;
772.27893 --		back->name = kgem_bo_flink(&sna->kgem, bo);
772.27894 --	}
772.27895 --	if (back->name == 0) {
772.27896 --		if (bo != NULL)
772.27897 --			kgem_bo_destroy(&sna->kgem, bo);
772.27898 --		get_private(back)->bo = NULL;
772.27899 --		back->attachment = -1;
772.27900 -+		tmp->attachment = DRI2BufferFrontLeft;
772.27901 -+		tmp->driverPrivate = tmp + 1;
772.27902 -+		tmp->cpp = back->cpp;
772.27903 -+		tmp->format = back->format;
772.27904 -+
772.27905 -+		get_private(tmp)->refcnt = 1;
772.27906 -+		get_private(tmp)->bo = kgem_create_2d(&sna->kgem,
772.27907 -+						      draw->width, draw->height, draw->bitsPerPixel,
772.27908 -+						      get_private(back)->bo->tiling,
772.27909 -+						      CREATE_SCANOUT | CREATE_EXACT);
772.27910 -+		if (get_private(tmp)->bo != NULL) {
772.27911 -+			tmp->pitch = get_private(tmp)->bo->pitch;
772.27912 -+			tmp->name = kgem_bo_flink(&sna->kgem, get_private(tmp)->bo);
772.27913 -+		}
772.27914 -+		if (tmp->name == 0) {
772.27915 -+			if (get_private(tmp)->bo != NULL)
772.27916 -+				kgem_bo_destroy(&sna->kgem, get_private(tmp)->bo);
772.27917 -+			sna_shadow_unset_crtc(sna, crtc);
772.27918 -+			return;
772.27919 -+		}
772.27920 -+		get_private(tmp)->size = get_private(back)->size;
772.27921 -+		get_private(tmp)->pixmap = get_private(front)->pixmap;
772.27922 -+		get_private(tmp)->proxy = sna_dri2_reference_buffer(front);
772.27923 -+		get_private(tmp)->bo->active_scanout++;
772.27924 -+
772.27925 -+		priv->front = front = tmp;
772.27926 - 	}
772.27927 --}
772.27928 -+	assert(front == priv->front);
772.27929 - 
772.27930 --static void frame_swap_complete(struct sna_dri2_event *frame, int type)
772.27931 --{
772.27932 --	const struct ust_msc *swap;
772.27933 -+	{
772.27934 -+		struct kgem_bo *front_bo = get_private(front)->bo;
772.27935 -+		struct kgem_bo *back_bo = get_private(back)->bo;
772.27936 -+		unsigned tmp;
772.27937 - 
772.27938 --	if (frame->draw == NULL)
772.27939 --		return;
772.27940 -+		assert(front_bo->refcnt);
772.27941 -+		assert(back_bo->refcnt);
772.27942 - 
772.27943 --	assert(frame->client);
772.27944 -+		get_private(back)->bo = front_bo;
772.27945 -+		get_private(front)->bo = back_bo;
772.27946 -+		mark_stale(back);
772.27947 - 
772.27948 --	swap = sna_crtc_last_swap(frame->crtc);
772.27949 --	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc=%lld], tv=%d.%06d\n",
772.27950 --	     __FUNCTION__, type, (long)frame->draw, frame->pipe,
772.27951 --	     (long long)swap->msc,
772.27952 --	     (long long)draw_current_msc(frame->draw, frame->crtc, swap->msc),
772.27953 --	     swap->tv_sec, swap->tv_usec));
772.27954 -+		assert(front_bo->active_scanout > 0);
772.27955 -+		front_bo->active_scanout--;
772.27956 -+		back_bo->active_scanout++;
772.27957 -+		assert(back_bo->active_scanout <= back_bo->refcnt);
772.27958 - 
772.27959 --	DRI2SwapComplete(frame->client, frame->draw,
772.27960 --			 draw_current_msc(frame->draw, frame->crtc, swap->msc),
772.27961 --			 swap->tv_sec, swap->tv_usec,
772.27962 --			 type, frame->event_complete, frame->event_data);
772.27963 --}
772.27964 -+		tmp = front->name;
772.27965 -+		front->name = back->name;
772.27966 -+		back->name = tmp;
772.27967 - 
772.27968 --static void fake_swap_complete(struct sna *sna, ClientPtr client,
772.27969 --			       DrawablePtr draw, xf86CrtcPtr crtc,
772.27970 --			       int type, DRI2SwapEventPtr func, void *data)
772.27971 --{
772.27972 --	const struct ust_msc *swap;
772.27973 --
772.27974 --	swap = sna_crtc_last_swap(crtc);
772.27975 --	DBG(("%s(type=%d): draw=%ld, pipe=%d, frame=%lld [msc %lld], tv=%d.%06d\n",
772.27976 --	     __FUNCTION__, type, (long)draw->id, crtc ? sna_crtc_to_pipe(crtc) : -1,
772.27977 --	     (long long)swap->msc,
772.27978 --	     (long long)draw_current_msc(draw, crtc, swap->msc),
772.27979 --	     swap->tv_sec, swap->tv_usec));
772.27980 -+		tmp = front->pitch;
772.27981 -+		front->pitch = back->pitch;
772.27982 -+		back->pitch = tmp;
772.27983 - 
772.27984 --	DRI2SwapComplete(client, draw,
772.27985 --			 draw_current_msc(draw, crtc, swap->msc),
772.27986 --			 swap->tv_sec, swap->tv_usec,
772.27987 --			 type, func, data);
772.27988 -+		tmp = front->flags;
772.27989 -+		front->flags = back->flags;
772.27990 -+		back->flags = tmp;
772.27991 -+	}
772.27992 - }
772.27993 - 
772.27994 - static void chain_swap(struct sna_dri2_event *chain)
772.27995 - {
772.27996 --	union drm_wait_vblank vbl;
772.27997 -+	DBG(("%s: draw=%ld, queued?=%d, type=%d\n",
772.27998 -+	     __FUNCTION__, (long)chain->draw->id, chain->queued, chain->type));
772.27999 -+
772.28000 -+	if (chain->queued) /* too early! */
772.28001 -+		return;
772.28002 - 
772.28003 - 	if (chain->draw == NULL) {
772.28004 - 		sna_dri2_event_free(chain);
772.28005 - 		return;
772.28006 - 	}
772.28007 - 
772.28008 --	if (chain->queued) /* too early! */
772.28009 --		return;
772.28010 --
772.28011 - 	assert(chain == dri2_chain(chain->draw));
772.28012 --	DBG(("%s: chaining draw=%ld, type=%d\n",
772.28013 --	     __FUNCTION__, (long)chain->draw->id, chain->type));
772.28014 --	chain->queued = true;
772.28015 -+	assert(chain->signal);
772.28016 - 
772.28017 - 	switch (chain->type) {
772.28018 --	case SWAP_THROTTLE:
772.28019 -+	case SWAP_COMPLETE:
772.28020 - 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
772.28021 --		if (chain->sna->mode.shadow &&
772.28022 --		    !chain->sna->mode.shadow_damage) {
772.28023 --			/* recursed from wait_for_shadow(), simply requeue */
772.28024 --			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
772.28025 --			VG_CLEAR(vbl);
772.28026 --			vbl.request.type =
772.28027 --				DRM_VBLANK_RELATIVE |
772.28028 --				DRM_VBLANK_EVENT;
772.28029 --			vbl.request.sequence = 1;
772.28030 --			vbl.request.signal = (uintptr_t)chain;
772.28031 --
772.28032 --			if (!sna_wait_vblank(chain->sna, &vbl, chain->pipe))
772.28033 --				return;
772.28034 --
772.28035 --			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
772.28036 --		}
772.28037 --
772.28038 - 		if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
772.28039 - 			sna_dri2_xchg(chain->draw, chain->front, chain->back);
772.28040 --		} else if (can_xchg_crtc(chain->sna, chain->draw, chain->front, chain->back, chain->crtc)) {
772.28041 --			sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc, chain->front, chain->back);
772.28042 -+		} else if (can_xchg_crtc(chain->sna, chain->draw, chain->crtc,
772.28043 -+					 chain->front, chain->back)) {
772.28044 -+			sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc,
772.28045 -+					   chain->front, chain->back);
772.28046 - 		} else {
772.28047 --			assert(chain->queued);
772.28048 --			chain->bo = __sna_dri2_copy_region(chain->sna, chain->draw, NULL,
772.28049 --							   chain->back, chain->front,
772.28050 --							   true);
772.28051 -+			__sna_dri2_copy_event(chain, chain->sync | DRI2_BO);
772.28052 - 		}
772.28053 -+		assert(get_private(chain->back)->bo != get_private(chain->front)->bo);
772.28054 - 	case SWAP:
772.28055 - 		break;
772.28056 - 	default:
772.28057 - 		return;
772.28058 - 	}
772.28059 - 
772.28060 --	VG_CLEAR(vbl);
772.28061 --	vbl.request.type =
772.28062 --		DRM_VBLANK_RELATIVE |
772.28063 --		DRM_VBLANK_EVENT;
772.28064 --	vbl.request.sequence = 1;
772.28065 --	vbl.request.signal = (uintptr_t)chain;
772.28066 --	if (sna_wait_vblank(chain->sna, &vbl, chain->pipe)) {
772.28067 -+	if ((chain->type == SWAP_COMPLETE &&
772.28068 -+	     !swap_limit(chain->draw, 2 + !chain->sync) &&
772.28069 -+	     !chain->sync) ||
772.28070 -+	    !sna_next_vblank(chain)) {
772.28071 - 		DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
772.28072 - 		frame_swap_complete(chain, DRI2_BLIT_COMPLETE);
772.28073 - 		sna_dri2_event_free(chain);
772.28074 --	} else {
772.28075 --		if (chain->type == SWAP_THROTTLE && !swap_limit(chain->draw, 2)) {
772.28076 --			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28077 --			frame_swap_complete(chain, DRI2_BLIT_COMPLETE);
772.28078 --		}
772.28079 - 	}
772.28080 - }
772.28081 - 
772.28082 -@@ -2086,40 +2556,27 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
772.28083 - 	if (bo == NULL)
772.28084 - 		return false;
772.28085 - 
772.28086 --	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
772.28087 --	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
772.28088 --	assert(bo->refcnt);
772.28089 --
772.28090 --	if (bo->exec)
772.28091 --		return true;
772.28092 --
772.28093 --	if (bo->rq == NULL)
772.28094 --		return false;
772.28095 --
772.28096 --	return __kgem_busy(kgem, bo->handle);
772.28097 -+	return __kgem_bo_is_busy(kgem, bo);
772.28098 - }
772.28099 - 
772.28100 --static bool sna_dri2_blit_complete(struct sna *sna,
772.28101 --				   struct sna_dri2_event *info)
772.28102 -+static bool sna_dri2_blit_complete(struct sna_dri2_event *info)
772.28103 - {
772.28104 --	if (rq_is_busy(&sna->kgem, info->bo)) {
772.28105 --		union drm_wait_vblank vbl;
772.28106 -+	if (!info->bo)
772.28107 -+		return true;
772.28108 - 
772.28109 -+	if (__kgem_bo_is_busy(&info->sna->kgem, info->bo)) {
772.28110 - 		DBG(("%s: vsync'ed blit is still busy, postponing\n",
772.28111 - 		     __FUNCTION__));
772.28112 --
772.28113 --		VG_CLEAR(vbl);
772.28114 --		vbl.request.type =
772.28115 --			DRM_VBLANK_RELATIVE |
772.28116 --			DRM_VBLANK_EVENT;
772.28117 --		vbl.request.sequence = 1;
772.28118 --		vbl.request.signal = (uintptr_t)info;
772.28119 --		assert(info->queued);
772.28120 --		if (!sna_wait_vblank(sna, &vbl, info->pipe))
772.28121 -+		if (sna_next_vblank(info))
772.28122 - 			return false;
772.28123 -+
772.28124 -+		kgem_bo_sync__gtt(&info->sna->kgem, info->bo);
772.28125 - 	}
772.28126 - 
772.28127 - 	DBG(("%s: blit finished\n", __FUNCTION__));
772.28128 -+	kgem_bo_destroy(&info->sna->kgem, info->bo);
772.28129 -+	info->bo = NULL;
772.28130 -+
772.28131 - 	return true;
772.28132 - }
772.28133 - 
772.28134 -@@ -2128,11 +2585,12 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
772.28135 - 	struct sna_dri2_event *info = (void *)(uintptr_t)event->user_data;
772.28136 - 	struct sna *sna = info->sna;
772.28137 - 	DrawablePtr draw;
772.28138 --	union drm_wait_vblank vbl;
772.28139 - 	uint64_t msc;
772.28140 - 
772.28141 --	DBG(("%s(type=%d, sequence=%d)\n", __FUNCTION__, info->type, event->sequence));
772.28142 -+	DBG(("%s(type=%d, sequence=%d, draw=%ld)\n", __FUNCTION__, info->type, event->sequence, info->draw ? info->draw->serialNumber : 0));
772.28143 - 	assert(info->queued);
772.28144 -+	info->queued = false;
772.28145 -+
772.28146 - 	msc = sna_crtc_record_event(info->crtc, event);
772.28147 - 
772.28148 - 	draw = info->draw;
772.28149 -@@ -2141,68 +2599,120 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
772.28150 - 		goto done;
772.28151 - 	}
772.28152 - 
772.28153 -+	assert((info->front == NULL && info->back == NULL) || info->front != info->back);
772.28154 - 	switch (info->type) {
772.28155 - 	case FLIP:
772.28156 - 		/* If we can still flip... */
772.28157 -+		assert(info->signal);
772.28158 - 		if (can_flip(sna, draw, info->front, info->back, info->crtc) &&
772.28159 - 		    sna_dri2_flip(info))
772.28160 - 			return;
772.28161 - 
772.28162 - 		/* else fall through to blit */
772.28163 - 	case SWAP:
772.28164 --		assert(info->queued);
772.28165 --		if (sna->mode.shadow && !sna->mode.shadow_damage) {
772.28166 --			/* recursed from wait_for_shadow(), simply requeue */
772.28167 --			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
772.28168 --
772.28169 --		} else if (can_xchg(info->sna, draw, info->front, info->back)) {
772.28170 -+		assert(info->signal);
772.28171 -+		if (can_xchg(info->sna, draw, info->front, info->back)) {
772.28172 - 			sna_dri2_xchg(draw, info->front, info->back);
772.28173 --			info->type = SWAP_WAIT;
772.28174 --		} else if (can_xchg_crtc(sna, draw, info->front, info->back, info->crtc)) {
772.28175 --			sna_dri2_xchg_crtc(sna, draw, info->crtc, info->front, info->back);
772.28176 --			info->type = SWAP_WAIT;
772.28177 -+			info->type = SWAP_COMPLETE;
772.28178 -+		} else if (can_xchg_crtc(sna, draw, info->crtc,
772.28179 -+					 info->front, info->back)) {
772.28180 -+			sna_dri2_xchg_crtc(sna, draw, info->crtc,
772.28181 -+					   info->front, info->back);
772.28182 -+			info->type = SWAP_COMPLETE;
772.28183 - 		}  else {
772.28184 --			assert(info->queued);
772.28185 --			info->bo = __sna_dri2_copy_region(sna, draw, NULL,
772.28186 --							  info->back, info->front, true);
772.28187 --			info->type = SWAP_WAIT;
772.28188 -+			__sna_dri2_copy_event(info, DRI2_BO | DRI2_SYNC);
772.28189 -+			info->type = SWAP_COMPLETE;
772.28190 - 		}
772.28191 - 
772.28192 --		VG_CLEAR(vbl);
772.28193 --		vbl.request.type =
772.28194 --			DRM_VBLANK_RELATIVE |
772.28195 --			DRM_VBLANK_EVENT;
772.28196 --		vbl.request.sequence = 1;
772.28197 --		vbl.request.signal = (uintptr_t)info;
772.28198 --
772.28199 --		assert(info->queued);
772.28200 --		if (!sna_wait_vblank(sna, &vbl, info->pipe))
772.28201 -+		if (sna_next_vblank(info))
772.28202 - 			return;
772.28203 - 
772.28204 - 		DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
772.28205 -+		assert(info->pending.bo == NULL);
772.28206 -+		assert(info->keepalive == 1);
772.28207 - 		/* fall through to SwapComplete */
772.28208 --	case SWAP_WAIT:
772.28209 --		if (!sna_dri2_blit_complete(sna, info))
772.28210 --			return;
772.28211 --
772.28212 --		DBG(("%s: swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
772.28213 --		     event->sequence, event->tv_sec, event->tv_usec));
772.28214 --		frame_swap_complete(info, DRI2_BLIT_COMPLETE);
772.28215 --		break;
772.28216 --
772.28217 --	case SWAP_THROTTLE:
772.28218 -+	case SWAP_COMPLETE:
772.28219 - 		DBG(("%s: %d complete, frame=%d tv=%d.%06d\n",
772.28220 - 		     __FUNCTION__, info->type,
772.28221 - 		     event->sequence, event->tv_sec, event->tv_usec));
772.28222 - 
772.28223 --		if (xorg_can_triple_buffer()) {
772.28224 --			if (!sna_dri2_blit_complete(sna, info))
772.28225 -+		if (info->signal) {
772.28226 -+			if (!sna_dri2_blit_complete(info))
772.28227 - 				return;
772.28228 - 
772.28229 - 			DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
772.28230 - 			     event->sequence, event->tv_sec, event->tv_usec));
772.28231 - 			frame_swap_complete(info, DRI2_BLIT_COMPLETE);
772.28232 - 		}
772.28233 -+
772.28234 -+		if (info->pending.bo) {
772.28235 -+			struct copy current_back;
772.28236 -+
772.28237 -+			DBG(("%s: swapping back handle=%d [name=%d, active=%d] for pending handle=%d [name=%d, active=%d], front handle=%d [name=%d, active=%d]\n",
772.28238 -+			     __FUNCTION__,
772.28239 -+			     get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
772.28240 -+			     info->pending.bo->handle, info->pending.name, info->pending.bo->active_scanout,
772.28241 -+			     get_private(info->front)->bo->handle, info->front->name, get_private(info->front)->bo->active_scanout));
772.28242 -+
772.28243 -+			assert(info->pending.bo->active_scanout > 0);
772.28244 -+			info->pending.bo->active_scanout--;
772.28245 -+
772.28246 -+			current_back.bo = get_private(info->back)->bo;
772.28247 -+			current_back.size = get_private(info->back)->size;
772.28248 -+			current_back.name = info->back->name;
772.28249 -+			current_back.flags = info->back->flags;
772.28250 -+
772.28251 -+			get_private(info->back)->bo = info->pending.bo;
772.28252 -+			get_private(info->back)->size = info->pending.size;
772.28253 -+			info->back->name = info->pending.name;
772.28254 -+			info->back->pitch = info->pending.bo->pitch;
772.28255 -+			info->back->flags = info->pending.flags;
772.28256 -+			info->pending.bo = NULL;
772.28257 -+
772.28258 -+			assert(get_private(info->back)->bo != get_private(info->front)->bo);
772.28259 -+
772.28260 -+			if (can_xchg(info->sna, info->draw, info->front, info->back))
772.28261 -+				sna_dri2_xchg(info->draw, info->front, info->back);
772.28262 -+			else if (can_xchg_crtc(info->sna, info->draw, info->crtc,
772.28263 -+						 info->front, info->back))
772.28264 -+				sna_dri2_xchg_crtc(info->sna, info->draw, info->crtc,
772.28265 -+						   info->front, info->back);
772.28266 -+			else
772.28267 -+				__sna_dri2_copy_event(info, info->sync | DRI2_BO);
772.28268 -+
772.28269 -+			sna_dri2_cache_bo(info->sna, info->draw,
772.28270 -+					  get_private(info->back)->bo,
772.28271 -+					  info->back->name,
772.28272 -+					  get_private(info->back)->size,
772.28273 -+					  info->back->flags);
772.28274 -+
772.28275 -+			get_private(info->back)->bo = current_back.bo;
772.28276 -+			get_private(info->back)->size = current_back.size;
772.28277 -+			info->back->name = current_back.name;
772.28278 -+			info->back->pitch = current_back.bo->pitch;
772.28279 -+			info->back->flags = current_back.flags;
772.28280 -+
772.28281 -+			DBG(("%s: restored current back handle=%d [name=%d, active=%d], active=%d], front handle=%d [name=%d, active=%d]\n",
772.28282 -+			     __FUNCTION__,
772.28283 -+			     get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
772.28284 -+			     get_private(info->front)->bo->handle, info->front->name, get_private(info->front)->bo->active_scanout));
772.28285 -+
772.28286 -+			assert(info->draw);
772.28287 -+			assert(!info->signal);
772.28288 -+			info->keepalive++;
772.28289 -+			info->signal = true;
772.28290 -+		}
772.28291 -+
772.28292 -+		if (--info->keepalive) {
772.28293 -+			if (sna_next_vblank(info))
772.28294 -+				return;
772.28295 -+
772.28296 -+			if (info->signal) {
772.28297 -+				DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
772.28298 -+				     event->sequence, event->tv_sec, event->tv_usec));
772.28299 -+				frame_swap_complete(info, DRI2_BLIT_COMPLETE);
772.28300 -+			}
772.28301 -+		}
772.28302 - 		break;
772.28303 - 
772.28304 - 	case WAITMSC:
772.28305 -@@ -2218,11 +2728,11 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
772.28306 - 	}
772.28307 - 
772.28308 - 	if (info->chain) {
772.28309 -+		DBG(("%s: continuing chain\n", __FUNCTION__));
772.28310 - 		assert(info->chain != info);
772.28311 - 		assert(info->draw == draw);
772.28312 --		sna_dri2_remove_event((WindowPtr)draw, info);
772.28313 -+		sna_dri2_remove_event(info);
772.28314 - 		chain_swap(info->chain);
772.28315 --		info->draw = NULL;
772.28316 - 	}
772.28317 - 
772.28318 - done:
772.28319 -@@ -2230,101 +2740,148 @@ done:
772.28320 - 	DBG(("%s complete\n", __FUNCTION__));
772.28321 - }
772.28322 - 
772.28323 --static bool
772.28324 -+static void
772.28325 - sna_dri2_immediate_blit(struct sna *sna,
772.28326 - 			struct sna_dri2_event *info,
772.28327 --			bool sync, bool event)
772.28328 -+			bool sync)
772.28329 - {
772.28330 --	DrawablePtr draw = info->draw;
772.28331 --	bool ret = false;
772.28332 -+	struct sna_dri2_event *chain = dri2_chain(info->draw);
772.28333 - 
772.28334 - 	if (sna->flags & SNA_NO_WAIT)
772.28335 - 		sync = false;
772.28336 - 
772.28337 --	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, send-event? %d\n",
772.28338 --	     __FUNCTION__, sync, dri2_chain(draw) != info,
772.28339 --	     event));
772.28340 -+	DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, pipe %d\n",
772.28341 -+	     __FUNCTION__, sync, chain != info, info->pipe));
772.28342 -+	assert(chain);
772.28343 - 
772.28344 --	info->type = SWAP_THROTTLE;
772.28345 --	if (!sync || dri2_chain(draw) == info) {
772.28346 --		DBG(("%s: no pending blit, starting chain\n",
772.28347 --		     __FUNCTION__));
772.28348 -+	info->type = SWAP_COMPLETE;
772.28349 -+	info->sync = sync;
772.28350 -+	info->keepalive = KEEPALIVE;
772.28351 - 
772.28352 --		info->queued = true;
772.28353 --		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
772.28354 --						  info->back,
772.28355 --						  info->front,
772.28356 --						  sync);
772.28357 --		if (event) {
772.28358 --			if (sync) {
772.28359 --				union drm_wait_vblank vbl;
772.28360 --
772.28361 --				VG_CLEAR(vbl);
772.28362 --				vbl.request.type =
772.28363 --					DRM_VBLANK_RELATIVE |
772.28364 --					DRM_VBLANK_EVENT;
772.28365 --				vbl.request.sequence = 1;
772.28366 --				vbl.request.signal = (uintptr_t)info;
772.28367 --				ret = !sna_wait_vblank(sna, &vbl, info->pipe);
772.28368 --				if (ret)
772.28369 --					event = !swap_limit(draw, 2);
772.28370 --			}
772.28371 --			if (event) {
772.28372 --				DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28373 --				frame_swap_complete(info, DRI2_BLIT_COMPLETE);
772.28374 --			}
772.28375 -+	if (chain == info) {
772.28376 -+		DBG(("%s: no pending blit, starting chain\n", __FUNCTION__));
772.28377 -+
772.28378 -+		assert(info->front != info->back);
772.28379 -+		if (can_xchg(info->sna, info->draw, info->front, info->back)) {
772.28380 -+			sna_dri2_xchg(info->draw, info->front, info->back);
772.28381 -+		} else if (can_xchg_crtc(info->sna, info->draw, info->crtc,
772.28382 -+					 info->front, info->back)) {
772.28383 -+			sna_dri2_xchg_crtc(info->sna, info->draw, info->crtc,
772.28384 -+					   info->front, info->back);
772.28385 -+		} else
772.28386 -+			__sna_dri2_copy_event(info, sync | DRI2_BO);
772.28387 -+
772.28388 -+		assert(info->signal);
772.28389 -+
772.28390 -+		if ((!swap_limit(info->draw, 2 + !sync) && !sync) ||
772.28391 -+		    !sna_next_vblank(info)) {
772.28392 -+			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28393 -+			frame_swap_complete(info, DRI2_BLIT_COMPLETE);
772.28394 -+			sna_dri2_event_free(info);
772.28395 -+		}
772.28396 -+		return;
772.28397 -+	}
772.28398 -+
772.28399 -+	DBG(("%s: current event front=%d [name=%d, active?=%d], back=%d [name=%d, active?=%d]\n", __FUNCTION__,
772.28400 -+	     get_private(chain->front)->bo->handle, chain->front->name, get_private(chain->front)->bo->active_scanout,
772.28401 -+	     get_private(chain->back)->bo->handle, chain->back->name, get_private(chain->back)->bo->active_scanout));
772.28402 -+
772.28403 -+	if (chain->type == SWAP_COMPLETE && chain->front == info->front) {
772.28404 -+		assert(chain->draw == info->draw);
772.28405 -+		assert(chain->client == info->client);
772.28406 -+		assert(chain->event_complete == info->event_complete);
772.28407 -+		assert(chain->event_data == info->event_data);
772.28408 -+		assert(chain->queued);
772.28409 -+
772.28410 -+		if ((!sync || !chain->sync) && chain->pending.bo) {
772.28411 -+			bool signal = chain->signal;
772.28412 -+
772.28413 -+			DBG(("%s: swap elision, unblocking client\n", __FUNCTION__));
772.28414 -+			assert(chain->draw);
772.28415 -+			chain->signal = true;
772.28416 -+			frame_swap_complete(chain, DRI2_EXCHANGE_COMPLETE);
772.28417 -+			chain->signal = signal;
772.28418 -+
772.28419 -+			assert(chain->pending.bo->active_scanout > 0);
772.28420 -+			chain->pending.bo->active_scanout--;
772.28421 -+
772.28422 -+			sna_dri2_cache_bo(chain->sna, chain->draw,
772.28423 -+					  chain->pending.bo,
772.28424 -+					  chain->pending.name,
772.28425 -+					  chain->pending.size,
772.28426 -+					  chain->pending.flags);
772.28427 -+			chain->pending.bo = NULL;
772.28428 -+		}
772.28429 -+
772.28430 -+		if (chain->pending.bo == NULL && swap_limit(info->draw, 2 + !sync)) {
772.28431 -+			DBG(("%s: setting handle=%d as pending blit (current event front=%d, back=%d)\n", __FUNCTION__,
772.28432 -+			     get_private(info->back)->bo->handle,
772.28433 -+			     get_private(chain->front)->bo->handle,
772.28434 -+			     get_private(chain->back)->bo->handle));
772.28435 -+			chain->pending.bo = ref(get_private(info->back)->bo);
772.28436 -+			chain->pending.size = get_private(info->back)->size;
772.28437 -+			chain->pending.name = info->back->name;
772.28438 -+			chain->pending.flags = info->back->flags;
772.28439 -+			chain->sync = sync;
772.28440 -+			info->signal = false; /* transfer signal to pending */
772.28441 -+
772.28442 -+			/* Prevent us from handing it back on next GetBuffers */
772.28443 -+			chain->pending.bo->active_scanout++;
772.28444 -+
772.28445 -+			sna_dri2_event_free(info);
772.28446 -+			return;
772.28447 - 		}
772.28448 --	} else {
772.28449 --		DBG(("%s: pending blit, chained\n", __FUNCTION__));
772.28450 --		ret = true;
772.28451 - 	}
772.28452 - 
772.28453 --	DBG(("%s: continue? %d\n", __FUNCTION__, ret));
772.28454 --	return ret;
772.28455 -+	DBG(("%s: pending blit, chained\n", __FUNCTION__));
772.28456 - }
772.28457 - 
772.28458 - static bool
772.28459 - sna_dri2_flip_continue(struct sna_dri2_event *info)
772.28460 - {
772.28461 --	DBG(("%s(mode=%d)\n", __FUNCTION__, info->mode));
772.28462 -+	struct kgem_bo *bo = get_private(info->front)->bo;
772.28463 - 
772.28464 --	if (info->mode > 0){
772.28465 --		struct kgem_bo *bo = get_private(info->front)->bo;
772.28466 -+	DBG(("%s(mode=%d)\n", __FUNCTION__, info->flip_continue));
772.28467 -+	assert(info->flip_continue > 0);
772.28468 -+	info->type = info->flip_continue;
772.28469 -+	info->flip_continue = 0;
772.28470 - 
772.28471 --		info->type = info->mode;
772.28472 -+	assert(!info->signal);
772.28473 -+	info->signal = info->type == FLIP_THROTTLE && info->draw;
772.28474 - 
772.28475 --		if (bo != sna_pixmap(info->sna->front)->gpu_bo)
772.28476 --			return false;
772.28477 -+	if (info->sna->mode.front_active == 0)
772.28478 -+		return false;
772.28479 - 
772.28480 --		if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
772.28481 --			return false;
772.28482 -+	if (bo != sna_pixmap(info->sna->front)->gpu_bo)
772.28483 -+		return false;
772.28484 - 
772.28485 --		assert(info->sna->dri2.flip_pending == NULL ||
772.28486 --		       info->sna->dri2.flip_pending == info);
772.28487 --		info->sna->dri2.flip_pending = info;
772.28488 --		assert(info->queued);
772.28489 --	} else {
772.28490 --		info->type = -info->mode;
772.28491 -+	assert(!info->queued);
772.28492 -+	if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
772.28493 -+		return false;
772.28494 - 
772.28495 --		if (!info->draw)
772.28496 --			return false;
772.28497 -+	DBG(("%s: queued flip=%p\n", __FUNCTION__, info));
772.28498 -+	assert(info->sna->dri2.flip_pending == NULL ||
772.28499 -+	       info->sna->dri2.flip_pending == info);
772.28500 -+	info->sna->dri2.flip_pending = info;
772.28501 -+	info->queued = true;
772.28502 - 
772.28503 --		if (!can_flip(info->sna, info->draw, info->front, info->back, info->crtc))
772.28504 --			return false;
772.28505 -+	return true;
772.28506 -+}
772.28507 - 
772.28508 --		assert(sna_pixmap_get_buffer(get_drawable_pixmap(info->draw)) == info->front);
772.28509 --		if (!sna_dri2_flip(info))
772.28510 --			return false;
772.28511 -+static bool
772.28512 -+sna_dri2_flip_keepalive(struct sna_dri2_event *info)
772.28513 -+{
772.28514 -+	DBG(("%s(keepalive?=%d)\n", __FUNCTION__, info->keepalive-1));
772.28515 -+	assert(info->keepalive > 0);
772.28516 -+	if (!--info->keepalive)
772.28517 -+		return false;
772.28518 - 
772.28519 --		if (!xorg_can_triple_buffer()) {
772.28520 --			sna_dri2_get_back(info->sna, info->draw, info->back, info);
772.28521 --			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28522 --			frame_swap_complete(info, DRI2_FLIP_COMPLETE);
772.28523 --		}
772.28524 --	}
772.28525 -+	if (info->draw == NULL)
772.28526 -+		return false;
772.28527 - 
772.28528 --	info->mode = 0;
772.28529 --	return true;
772.28530 -+	DBG(("%s: marking next flip as complete\n", __FUNCTION__));
772.28531 -+	info->flip_continue = FLIP_COMPLETE;
772.28532 -+	return sna_dri2_flip_continue(info);
772.28533 - }
772.28534 - 
772.28535 - static void chain_flip(struct sna *sna)
772.28536 -@@ -2332,8 +2889,8 @@ static void chain_flip(struct sna *sna)
772.28537 - 	struct sna_dri2_event *chain = sna->dri2.flip_pending;
772.28538 - 
772.28539 - 	assert(chain->type == FLIP);
772.28540 --	DBG(("%s: chaining type=%d, cancelled?=%d\n",
772.28541 --	     __FUNCTION__, chain->type, chain->draw == NULL));
772.28542 -+	DBG(("%s: chaining type=%d, cancelled?=%d window=%ld\n",
772.28543 -+	     __FUNCTION__, chain->type, chain->draw == NULL, chain->draw ? chain->draw->id : 0));
772.28544 - 
772.28545 - 	sna->dri2.flip_pending = NULL;
772.28546 - 	if (chain->draw == NULL) {
772.28547 -@@ -2343,31 +2900,18 @@ static void chain_flip(struct sna *sna)
772.28548 - 
772.28549 - 	assert(chain == dri2_chain(chain->draw));
772.28550 - 	assert(!chain->queued);
772.28551 --	chain->queued = true;
772.28552 - 
772.28553 - 	if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
772.28554 - 	    sna_dri2_flip(chain)) {
772.28555 - 		DBG(("%s: performing chained flip\n", __FUNCTION__));
772.28556 - 	} else {
772.28557 - 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
772.28558 --		chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
772.28559 --						  chain->back, chain->front,
772.28560 --						  true);
772.28561 -+		__sna_dri2_copy_event(chain, DRI2_SYNC);
772.28562 - 
772.28563 - 		if (xorg_can_triple_buffer()) {
772.28564 --			union drm_wait_vblank vbl;
772.28565 --
772.28566 --			VG_CLEAR(vbl);
772.28567 --
772.28568 --			chain->type = SWAP_WAIT;
772.28569 --			vbl.request.type =
772.28570 --				DRM_VBLANK_RELATIVE |
772.28571 --				DRM_VBLANK_EVENT;
772.28572 --			vbl.request.sequence = 1;
772.28573 --			vbl.request.signal = (uintptr_t)chain;
772.28574 --
772.28575 --			assert(chain->queued);
772.28576 --			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
772.28577 -+			chain->type = SWAP_COMPLETE;
772.28578 -+			assert(chain->signal);
772.28579 -+			if (sna_next_vblank(chain))
772.28580 - 				return;
772.28581 - 		}
772.28582 - 
772.28583 -@@ -2381,8 +2925,10 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
772.28584 - {
772.28585 - 	struct sna *sna = flip->sna;
772.28586 - 
772.28587 --	DBG(("%s(pipe=%d, event=%d)\n", __FUNCTION__, flip->pipe, flip->type));
772.28588 --	assert(flip->queued);
772.28589 -+	DBG(("%s flip=%p (pipe=%d, event=%d, queued?=%d)\n", __FUNCTION__, flip, flip->pipe, flip->type, flip->queued));
772.28590 -+	if (!flip->queued) /* pageflip died whilst being queued */
772.28591 -+		return;
772.28592 -+	flip->queued = false;
772.28593 - 
772.28594 - 	if (sna->dri2.flip_pending == flip)
772.28595 - 		sna->dri2.flip_pending = NULL;
772.28596 -@@ -2390,8 +2936,10 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
772.28597 - 	/* We assume our flips arrive in order, so we don't check the frame */
772.28598 - 	switch (flip->type) {
772.28599 - 	case FLIP:
772.28600 --		DBG(("%s: swap complete, unblocking client\n", __FUNCTION__));
772.28601 --		frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
772.28602 -+		if (flip->signal) {
772.28603 -+			DBG(("%s: swap complete, unblocking client\n", __FUNCTION__));
772.28604 -+			frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
772.28605 -+		}
772.28606 - 		sna_dri2_event_free(flip);
772.28607 - 
772.28608 - 		if (sna->dri2.flip_pending)
772.28609 -@@ -2399,27 +2947,35 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
772.28610 - 		break;
772.28611 - 
772.28612 - 	case FLIP_THROTTLE:
772.28613 --		DBG(("%s: triple buffer swap complete, unblocking client\n", __FUNCTION__));
772.28614 --		frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
772.28615 -+		if (flip->signal) {
772.28616 -+			DBG(("%s: triple buffer swap complete, unblocking client\n", __FUNCTION__));
772.28617 -+			frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
772.28618 -+		}
772.28619 - 	case FLIP_COMPLETE:
772.28620 -+		assert(!flip->signal);
772.28621 - 		if (sna->dri2.flip_pending) {
772.28622 -+			DBG(("%s: pending flip\n", __FUNCTION__));
772.28623 - 			sna_dri2_event_free(flip);
772.28624 - 			chain_flip(sna);
772.28625 --		} else if (!flip->mode) {
772.28626 -+		} else if (!flip->flip_continue) {
772.28627 - 			DBG(("%s: flip chain complete\n", __FUNCTION__));
772.28628 -+			if (!sna_dri2_flip_keepalive(flip)) {
772.28629 -+				if (flip->chain) {
772.28630 -+					sna_dri2_remove_event(flip);
772.28631 -+					chain_swap(flip->chain);
772.28632 -+				}
772.28633 - 
772.28634 --			if (flip->chain) {
772.28635 --				sna_dri2_remove_event((WindowPtr)flip->draw,
772.28636 --						      flip);
772.28637 --				chain_swap(flip->chain);
772.28638 --				flip->draw = NULL;
772.28639 -+				sna_dri2_event_free(flip);
772.28640 - 			}
772.28641 --
772.28642 --			sna_dri2_event_free(flip);
772.28643 - 		} else if (!sna_dri2_flip_continue(flip)) {
772.28644 - 			DBG(("%s: no longer able to flip\n", __FUNCTION__));
772.28645 --			if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->mode < 0))
772.28646 --				sna_dri2_event_free(flip);
772.28647 -+			if (flip->draw != NULL)
772.28648 -+				__sna_dri2_copy_event(flip, 0);
772.28649 -+			if (flip->signal) {
772.28650 -+				DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28651 -+				frame_swap_complete(flip, DRI2_BLIT_COMPLETE);
772.28652 -+			}
772.28653 -+			sna_dri2_event_free(flip);
772.28654 - 		}
772.28655 - 		break;
772.28656 - 
772.28657 -@@ -2433,17 +2989,27 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
772.28658 - 	}
772.28659 - }
772.28660 - 
772.28661 -+static int
772.28662 -+sna_query_vblank(struct sna *sna, xf86CrtcPtr crtc, union drm_wait_vblank *vbl)
772.28663 -+{
772.28664 -+	VG_CLEAR(*vbl);
772.28665 -+	vbl->request.type =
772.28666 -+		_DRM_VBLANK_RELATIVE | pipe_select(sna_crtc_pipe(crtc));
772.28667 -+	vbl->request.sequence = 0;
772.28668 -+
772.28669 -+	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
772.28670 -+}
772.28671 -+
772.28672 - static uint64_t
772.28673 - get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
772.28674 - {
772.28675 - 	union drm_wait_vblank vbl;
772.28676 --	uint64_t ret = -1;
772.28677 -+	uint64_t ret;
772.28678 - 
772.28679 --	VG_CLEAR(vbl);
772.28680 --	vbl.request.type = _DRM_VBLANK_RELATIVE;
772.28681 --	vbl.request.sequence = 0;
772.28682 --	if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
772.28683 -+	if (sna_query_vblank(sna, crtc, &vbl) == 0)
772.28684 - 		ret = sna_crtc_record_vblank(crtc, &vbl);
772.28685 -+	else
772.28686 -+		ret = sna_crtc_last_swap(crtc)->msc;
772.28687 - 
772.28688 - 	return draw_current_msc(draw, crtc, ret);
772.28689 - }
772.28690 -@@ -2494,12 +3060,18 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async)
772.28691 - }
772.28692 - 
772.28693 - static bool immediate_swap(struct sna *sna,
772.28694 --			   uint64_t target_msc,
772.28695 --			   uint64_t divisor,
772.28696 - 			   DrawablePtr draw,
772.28697 - 			   xf86CrtcPtr crtc,
772.28698 -+			   uint64_t *target_msc,
772.28699 -+			   uint64_t divisor,
772.28700 -+			   uint64_t remainder,
772.28701 - 			   uint64_t *current_msc)
772.28702 - {
772.28703 -+	/*
772.28704 -+	 * If divisor is zero, or current_msc is smaller than target_msc
772.28705 -+	 * we just need to make sure target_msc passes before initiating
772.28706 -+	 * the swap.
772.28707 -+	 */
772.28708 - 	if (divisor == 0) {
772.28709 - 		*current_msc = -1;
772.28710 - 
772.28711 -@@ -2508,72 +3080,97 @@ static bool immediate_swap(struct sna *sna,
772.28712 - 			return true;
772.28713 - 		}
772.28714 - 
772.28715 --		if (target_msc)
772.28716 -+		if (*target_msc)
772.28717 - 			*current_msc = get_current_msc(sna, draw, crtc);
772.28718 - 
772.28719 - 		DBG(("%s: current_msc=%ld, target_msc=%ld -- %s\n",
772.28720 --		     __FUNCTION__, (long)*current_msc, (long)target_msc,
772.28721 --		     (*current_msc >= target_msc - 1) ? "yes" : "no"));
772.28722 --		return *current_msc >= target_msc - 1;
772.28723 -+		     __FUNCTION__, (long)*current_msc, (long)*target_msc,
772.28724 -+		     (*current_msc >= *target_msc - 1) ? "yes" : "no"));
772.28725 -+		return *current_msc >= *target_msc - 1;
772.28726 - 	}
772.28727 - 
772.28728 - 	DBG(("%s: explicit waits requests, divisor=%ld\n",
772.28729 - 	     __FUNCTION__, (long)divisor));
772.28730 - 	*current_msc = get_current_msc(sna, draw, crtc);
772.28731 --	return false;
772.28732 -+	if (*current_msc >= *target_msc) {
772.28733 -+		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
772.28734 -+		     __FUNCTION__,
772.28735 -+		     (long long)*current_msc,
772.28736 -+		     (long long)*target_msc,
772.28737 -+		     (long long)divisor,
772.28738 -+		     (long long)remainder));
772.28739 -+
772.28740 -+		*target_msc = *current_msc + remainder - *current_msc % divisor;
772.28741 -+		if (*target_msc <= *current_msc)
772.28742 -+			*target_msc += divisor;
772.28743 -+	}
772.28744 -+
772.28745 -+	DBG(("%s: target_msc=%lld, current_msc=%lld, immediate?=%d\n",
772.28746 -+	     __FUNCTION__, (long long)*target_msc, (long long)*current_msc,
772.28747 -+	     *current_msc >= *target_msc - 1));
772.28748 -+	return *current_msc >= *target_msc - 1;
772.28749 - }
772.28750 - 
772.28751 - static bool
772.28752 - sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
772.28753 - 		       DRI2BufferPtr front, DRI2BufferPtr back,
772.28754 --		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
772.28755 -+		       bool immediate, CARD64 *target_msc, CARD64 current_msc,
772.28756 - 		       DRI2SwapEventPtr func, void *data)
772.28757 - {
772.28758 - 	struct sna *sna = to_sna_from_drawable(draw);
772.28759 - 	struct sna_dri2_event *info;
772.28760 --	uint64_t current_msc;
772.28761 --
772.28762 --	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
772.28763 --		int type;
772.28764 - 
772.28765 -+	if (immediate) {
772.28766 -+		bool signal = false;
772.28767 - 		info = sna->dri2.flip_pending;
772.28768 - 		DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d, continuation? %d\n",
772.28769 --		     __FUNCTION__, sna_crtc_to_pipe(crtc),
772.28770 --		     info != NULL, info ? info->mode : 0,
772.28771 -+		     __FUNCTION__, sna_crtc_pipe(crtc),
772.28772 -+		     info != NULL, info ? info->flip_continue : 0,
772.28773 - 		     info && info->draw == draw));
772.28774 - 
772.28775 - 		if (info && info->draw == draw) {
772.28776 - 			assert(info->type != FLIP);
772.28777 --			assert(info->front == front);
772.28778 -+			assert(info->queued);
772.28779 -+			assert(info->front != info->back);
772.28780 -+			if (info->front != front) {
772.28781 -+				assert(info->front != NULL);
772.28782 -+				_sna_dri2_destroy_buffer(sna, draw, info->front);
772.28783 -+				info->front = sna_dri2_reference_buffer(front);
772.28784 -+			}
772.28785 - 			if (info->back != back) {
772.28786 --				_sna_dri2_destroy_buffer(sna, info->back);
772.28787 -+				assert(info->back != NULL);
772.28788 -+				_sna_dri2_destroy_buffer(sna, draw, info->back);
772.28789 - 				info->back = sna_dri2_reference_buffer(back);
772.28790 - 			}
772.28791 --			if (info->mode || current_msc >= *target_msc) {
772.28792 --				DBG(("%s: executing xchg of pending flip\n",
772.28793 --				     __FUNCTION__));
772.28794 --				sna_dri2_xchg(draw, front, back);
772.28795 --				info->mode = type = FLIP_COMPLETE;
772.28796 --				goto new_back;
772.28797 --			} else {
772.28798 -+			assert(info->front != info->back);
772.28799 -+			DBG(("%s: executing xchg of pending flip: flip_continue=%d, keepalive=%d, chain?=%d\n", __FUNCTION__, info->flip_continue, info->keepalive, current_msc < *target_msc));
772.28800 -+			sna_dri2_xchg(draw, front, back);
772.28801 -+			info->keepalive = KEEPALIVE;
772.28802 -+			if (xorg_can_triple_buffer() &&
772.28803 -+			    current_msc < *target_msc) {
772.28804 - 				DBG(("%s: chaining flip\n", __FUNCTION__));
772.28805 --				type = FLIP_THROTTLE;
772.28806 --				if (xorg_can_triple_buffer())
772.28807 --					info->mode = -type;
772.28808 --				else
772.28809 --					info->mode = -FLIP_COMPLETE;
772.28810 -+				info->flip_continue = FLIP_THROTTLE;
772.28811 - 				goto out;
772.28812 -+			} else {
772.28813 -+				info->flip_continue = FLIP_COMPLETE;
772.28814 -+				signal = info->signal;
772.28815 -+				assert(info->draw);
772.28816 -+				info->signal = true;
772.28817 -+				goto new_back;
772.28818 - 			}
772.28819 - 		}
772.28820 - 
772.28821 --		info = sna_dri2_add_event(sna, draw, client);
772.28822 -+		info = sna_dri2_add_event(sna, draw, client, crtc);
772.28823 - 		if (info == NULL)
772.28824 - 			return false;
772.28825 - 
772.28826 - 		assert(info->crtc == crtc);
772.28827 - 		info->event_complete = func;
772.28828 - 		info->event_data = data;
772.28829 -+		assert(info->draw);
772.28830 -+		info->signal = true;
772.28831 - 
772.28832 -+		assert(front != back);
772.28833 - 		info->front = sna_dri2_reference_buffer(front);
772.28834 - 		info->back = sna_dri2_reference_buffer(back);
772.28835 - 
772.28836 -@@ -2584,26 +3181,33 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
772.28837 - 			 */
772.28838 - 			DBG(("%s: queueing flip after pending completion\n",
772.28839 - 			     __FUNCTION__));
772.28840 --			info->type = type = FLIP;
772.28841 -+			info->type = FLIP;
772.28842 - 			sna->dri2.flip_pending = info;
772.28843 --			assert(info->queued);
772.28844 - 			current_msc++;
772.28845 -+		} else if (sna->mode.flip_active) {
772.28846 -+			DBG(("%s: %d outstanding flips from old client, queueing\n",
772.28847 -+			     __FUNCTION__, sna->mode.flip_active));
772.28848 -+			goto queue;
772.28849 - 		} else {
772.28850 --			info->type = type = use_triple_buffer(sna, client, *target_msc == 0);
772.28851 -+			info->type = use_triple_buffer(sna, client, *target_msc == 0);
772.28852 - 			if (!sna_dri2_flip(info)) {
772.28853 - 				DBG(("%s: flip failed, falling back\n", __FUNCTION__));
772.28854 -+				info->signal = false;
772.28855 - 				sna_dri2_event_free(info);
772.28856 - 				return false;
772.28857 - 			}
772.28858 -+			assert(get_private(info->front)->bo->active_scanout);
772.28859 - 		}
772.28860 - 
772.28861 --		swap_limit(draw, 1 + (type == FLIP_THROTTLE));
772.28862 --		if (type >= FLIP_COMPLETE) {
772.28863 -+		swap_limit(draw, 1 + (info->type == FLIP_THROTTLE));
772.28864 -+		if (info->type >= FLIP_COMPLETE) {
772.28865 - new_back:
772.28866 - 			if (!xorg_can_triple_buffer())
772.28867 --				sna_dri2_get_back(sna, draw, back, info);
772.28868 -+				sna_dri2_get_back(sna, draw, back);
772.28869 - 			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
772.28870 - 			frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE);
772.28871 -+			assert(info->draw);
772.28872 -+			info->signal = signal;
772.28873 - 			if (info->type == FLIP_ASYNC)
772.28874 - 				sna_dri2_event_free(info);
772.28875 - 		}
772.28876 -@@ -2613,57 +3217,34 @@ out:
772.28877 - 		return true;
772.28878 - 	}
772.28879 - 
772.28880 --	info = sna_dri2_add_event(sna, draw, client);
772.28881 -+queue:
772.28882 -+	if (KEEPALIVE > 1 && sna->dri2.flip_pending) {
772.28883 -+		info = sna->dri2.flip_pending;
772.28884 -+		info->keepalive = 1;
772.28885 -+	}
772.28886 -+
772.28887 -+	info = sna_dri2_add_event(sna, draw, client, crtc);
772.28888 - 	if (info == NULL)
772.28889 - 		return false;
772.28890 - 
772.28891 - 	assert(info->crtc == crtc);
772.28892 - 	info->event_complete = func;
772.28893 - 	info->event_data = data;
772.28894 -+	assert(info->draw);
772.28895 -+	info->signal = true;
772.28896 - 	info->type = FLIP;
772.28897 - 
772.28898 -+	assert(front != back);
772.28899 - 	info->front = sna_dri2_reference_buffer(front);
772.28900 - 	info->back = sna_dri2_reference_buffer(back);
772.28901 - 
772.28902 --	/*
772.28903 --	 * If divisor is zero, or current_msc is smaller than target_msc
772.28904 --	 * we just need to make sure target_msc passes before initiating
772.28905 --	 * the swap.
772.28906 --	 */
772.28907 --	if (divisor && current_msc >= *target_msc) {
772.28908 --		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
772.28909 --		     __FUNCTION__,
772.28910 --		     (long long)current_msc,
772.28911 --		     (long long)*target_msc,
772.28912 --		     (long long)divisor,
772.28913 --		     (long long)remainder));
772.28914 --
772.28915 --		*target_msc = current_msc + remainder - current_msc % divisor;
772.28916 --		if (*target_msc <= current_msc)
772.28917 --			*target_msc += divisor;
772.28918 --	}
772.28919 --
772.28920 --	if (*target_msc <= current_msc + 1) {
772.28921 --		if (!sna_dri2_flip(info)) {
772.28922 --			sna_dri2_event_free(info);
772.28923 --			return false;
772.28924 --		}
772.28925 -+	if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) {
772.28926 - 		*target_msc = current_msc + 1;
772.28927 - 	} else {
772.28928 --		union drm_wait_vblank vbl;
772.28929 --
772.28930 --		VG_CLEAR(vbl);
772.28931 --
772.28932 --		vbl.request.type =
772.28933 --			DRM_VBLANK_ABSOLUTE |
772.28934 --			DRM_VBLANK_EVENT;
772.28935 --
772.28936 - 		/* Account for 1 frame extra pageflip delay */
772.28937 --		vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
772.28938 --		vbl.request.signal = (uintptr_t)info;
772.28939 --
772.28940 --		info->queued = true;
772.28941 --		if (sna_wait_vblank(sna, &vbl, info->pipe)) {
772.28942 -+		if (!sna_wait_vblank(info,
772.28943 -+				     draw_target_seq(draw, *target_msc - 1))) {
772.28944 -+			info->signal = false;
772.28945 - 			sna_dri2_event_free(info);
772.28946 - 			return false;
772.28947 - 		}
772.28948 -@@ -2674,128 +3255,6 @@ out:
772.28949 - 	return true;
772.28950 - }
772.28951 - 
772.28952 --static bool
772.28953 --sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
772.28954 --		       DRI2BufferPtr front, DRI2BufferPtr back,
772.28955 --		       CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
772.28956 --		       DRI2SwapEventPtr func, void *data)
772.28957 --{
772.28958 --	struct sna *sna = to_sna_from_drawable(draw);
772.28959 --	uint64_t current_msc;
772.28960 --	bool sync, event;
772.28961 --
772.28962 --	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
772.28963 --		return false;
772.28964 --
772.28965 --	sync = current_msc < *target_msc;
772.28966 --	event = dri2_chain(draw) == NULL;
772.28967 --	if (!sync || event) {
772.28968 --		DBG(("%s: performing immediate xchg on pipe %d\n",
772.28969 --		     __FUNCTION__, sna_crtc_to_pipe(crtc)));
772.28970 --		sna_dri2_xchg(draw, front, back);
772.28971 --	}
772.28972 --	if (sync) {
772.28973 --		struct sna_dri2_event *info;
772.28974 --
772.28975 --		info = sna_dri2_add_event(sna, draw, client);
772.28976 --		if (!info)
772.28977 --			goto complete;
772.28978 --
772.28979 --		info->event_complete = func;
772.28980 --		info->event_data = data;
772.28981 --
772.28982 --		info->front = sna_dri2_reference_buffer(front);
772.28983 --		info->back = sna_dri2_reference_buffer(back);
772.28984 --		info->type = SWAP_THROTTLE;
772.28985 --
772.28986 --		if (event) {
772.28987 --			union drm_wait_vblank vbl;
772.28988 --
772.28989 --			VG_CLEAR(vbl);
772.28990 --			vbl.request.type =
772.28991 --				DRM_VBLANK_RELATIVE |
772.28992 --				DRM_VBLANK_EVENT;
772.28993 --			vbl.request.sequence = 1;
772.28994 --			vbl.request.signal = (uintptr_t)info;
772.28995 --
772.28996 --			info->queued = true;
772.28997 --			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
772.28998 --				sna_dri2_event_free(info);
772.28999 --				goto complete;
772.29000 --			}
772.29001 --
772.29002 --			swap_limit(draw, 2);
772.29003 --		}
772.29004 --	} else {
772.29005 --complete:
772.29006 --		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
772.29007 --	}
772.29008 --
772.29009 --	*target_msc = current_msc + 1;
772.29010 --	return true;
772.29011 --}
772.29012 --
772.29013 --static bool
772.29014 --sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
772.29015 --			    DRI2BufferPtr front, DRI2BufferPtr back,
772.29016 --			    CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
772.29017 --			    DRI2SwapEventPtr func, void *data)
772.29018 --{
772.29019 --	struct sna *sna = to_sna_from_drawable(draw);
772.29020 --	uint64_t current_msc;
772.29021 --	bool sync, event;
772.29022 --
772.29023 --	if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
772.29024 --		return false;
772.29025 --
772.29026 --	sync = current_msc < *target_msc;
772.29027 --	event = dri2_chain(draw) == NULL;
772.29028 --	if (!sync || event) {
772.29029 --		DBG(("%s: performing immediate xchg only on pipe %d\n",
772.29030 --		     __FUNCTION__, sna_crtc_to_pipe(crtc)));
772.29031 --		sna_dri2_xchg_crtc(sna, draw, crtc, front, back);
772.29032 --	}
772.29033 --	if (sync) {
772.29034 --		struct sna_dri2_event *info;
772.29035 --
772.29036 --		info = sna_dri2_add_event(sna, draw, client);
772.29037 --		if (!info)
772.29038 --			goto complete;
772.29039 --
772.29040 --		info->event_complete = func;
772.29041 --		info->event_data = data;
772.29042 --
772.29043 --		info->front = sna_dri2_reference_buffer(front);
772.29044 --		info->back = sna_dri2_reference_buffer(back);
772.29045 --		info->type = SWAP_THROTTLE;
772.29046 --
772.29047 --		if (event) {
772.29048 --			union drm_wait_vblank vbl;
772.29049 --
772.29050 --			VG_CLEAR(vbl);
772.29051 --			vbl.request.type =
772.29052 --				DRM_VBLANK_RELATIVE |
772.29053 --				DRM_VBLANK_EVENT;
772.29054 --			vbl.request.sequence = 1;
772.29055 --			vbl.request.signal = (uintptr_t)info;
772.29056 --
772.29057 --			info->queued = true;
772.29058 --			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
772.29059 --				sna_dri2_event_free(info);
772.29060 --				goto complete;
772.29061 --			}
772.29062 --
772.29063 --			swap_limit(draw, 2);
772.29064 --		}
772.29065 --	} else {
772.29066 --complete:
772.29067 --		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
772.29068 --	}
772.29069 --
772.29070 --	*target_msc = current_msc + 1;
772.29071 --	return true;
772.29072 --}
772.29073 --
772.29074 - static bool has_pending_events(struct sna *sna)
772.29075 - {
772.29076 - 	struct pollfd pfd;
772.29077 -@@ -2830,11 +3289,11 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.29078 - 		       CARD64 remainder, DRI2SwapEventPtr func, void *data)
772.29079 - {
772.29080 - 	struct sna *sna = to_sna_from_drawable(draw);
772.29081 --	union drm_wait_vblank vbl;
772.29082 - 	xf86CrtcPtr crtc = NULL;
772.29083 - 	struct sna_dri2_event *info = NULL;
772.29084 - 	int type = DRI2_EXCHANGE_COMPLETE;
772.29085 - 	CARD64 current_msc;
772.29086 -+	bool immediate;
772.29087 - 
772.29088 - 	DBG(("%s: draw=%lu %dx%d, pixmap=%ld %dx%d, back=%u (refs=%d/%d, flush=%d) , front=%u (refs=%d/%d, flush=%d)\n",
772.29089 - 	     __FUNCTION__,
772.29090 -@@ -2860,6 +3319,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.29091 - 	assert(get_private(front)->refcnt);
772.29092 - 	assert(get_private(back)->refcnt);
772.29093 - 
772.29094 -+	assert(get_private(back)->bo != get_private(front)->bo);
772.29095 - 	assert(get_private(front)->bo->refcnt);
772.29096 - 	assert(get_private(back)->bo->refcnt);
772.29097 - 
772.29098 -@@ -2876,17 +3336,17 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.29099 - 		goto skip;
772.29100 - 	}
772.29101 - 
772.29102 --	assert(sna_pixmap_from_drawable(draw)->flush);
772.29103 --
772.29104 - 	if (draw->type != DRAWABLE_PIXMAP) {
772.29105 - 		WindowPtr win = (WindowPtr)draw;
772.29106 - 		struct dri2_window *priv = dri2_window(win);
772.29107 -+
772.29108 - 		if (priv->front) {
772.29109 --			assert(front == priv->front);
772.29110 --			assert(get_private(priv->front)->refcnt > 1);
772.29111 --			get_private(priv->front)->refcnt--;
772.29112 --			priv->front = NULL;
772.29113 -+			front = priv->front;
772.29114 -+			assert(front->attachment == DRI2BufferFrontLeft);
772.29115 -+			assert(get_private(front)->refcnt);
772.29116 -+			assert(get_private(front)->pixmap == get_drawable_pixmap(draw));
772.29117 - 		}
772.29118 -+
772.29119 - 		if (win->clipList.extents.x2 <= win->clipList.extents.x1 ||
772.29120 - 		    win->clipList.extents.y2 <= win->clipList.extents.y1) {
772.29121 - 			DBG(("%s: window clipped (%d, %d), (%d, %d)\n",
772.29122 -@@ -2899,6 +3359,10 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.29123 - 		}
772.29124 - 	}
772.29125 - 
772.29126 -+	DBG(("%s: using front handle=%d, active_scanout?=%d, flush?=%d\n", __FUNCTION__, get_private(front)->bo->handle, get_private(front)->bo->active_scanout, sna_pixmap_from_drawable(draw)->flush));
772.29127 -+	assert(get_private(front)->bo->active_scanout);
772.29128 -+	assert(sna_pixmap_from_drawable(draw)->flush);
772.29129 -+
772.29130 - 	/* Drawable not displayed... just complete the swap */
772.29131 - 	if ((sna->flags & SNA_NO_WAIT) == 0)
772.29132 - 		crtc = sna_dri2_get_crtc(draw);
772.29133 -@@ -2914,109 +3378,112 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.29134 - 		sna_mode_wakeup(sna);
772.29135 - 	}
772.29136 - 
772.29137 --	if (can_xchg(sna, draw, front, back) &&
772.29138 --	    sna_dri2_schedule_xchg(client, draw, crtc, front, back,
772.29139 -+	immediate = immediate_swap(sna, draw, crtc,
772.29140 - 				   target_msc, divisor, remainder,
772.29141 --				   func, data))
772.29142 --		return TRUE;
772.29143 --
772.29144 --	if (can_xchg_crtc(sna, draw, front, back, crtc) &&
772.29145 --	    sna_dri2_schedule_xchg_crtc(client, draw, crtc, front, back,
772.29146 --					target_msc, divisor, remainder,
772.29147 --					func, data))
772.29148 --		return TRUE;
772.29149 -+				   &current_msc);
772.29150 - 
772.29151 - 	if (can_flip(sna, draw, front, back, crtc) &&
772.29152 - 	    sna_dri2_schedule_flip(client, draw, crtc, front, back,
772.29153 --				  target_msc, divisor, remainder,
772.29154 -+				  immediate, target_msc, current_msc,
772.29155 - 				  func, data))
772.29156 - 		return TRUE;
772.29157 - 
772.29158 --	VG_CLEAR(vbl);
772.29159 --
772.29160 --	info = sna_dri2_add_event(sna, draw, client);
772.29161 -+	info = sna_dri2_add_event(sna, draw, client, crtc);
772.29162 - 	if (!info)
772.29163 - 		goto blit;
772.29164 - 
772.29165 - 	assert(info->crtc == crtc);
772.29166 - 	info->event_complete = func;
772.29167 - 	info->event_data = data;
772.29168 -+	assert(info->draw);
772.29169 -+	info->signal = true;
772.29170 - 
772.29171 -+	assert(front != back);
772.29172 - 	info->front = sna_dri2_reference_buffer(front);
772.29173 - 	info->back = sna_dri2_reference_buffer(back);
772.29174 - 
772.29175 --	if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
772.29176 -+	if (immediate) {
772.29177 - 		bool sync = current_msc < *target_msc;
772.29178 --		if (!sna_dri2_immediate_blit(sna, info, sync, true))
772.29179 --			sna_dri2_event_free(info);
772.29180 -+		sna_dri2_immediate_blit(sna, info, sync);
772.29181 - 		*target_msc = current_msc + sync;
772.29182 -+		DBG(("%s: reported target_msc=%llu\n",
772.29183 -+		     __FUNCTION__, *target_msc));
772.29184 - 		return TRUE;
772.29185 - 	}
772.29186 - 
772.29187 --	vbl.request.type =
772.29188 --		DRM_VBLANK_ABSOLUTE |
772.29189 --		DRM_VBLANK_EVENT;
772.29190 --	vbl.request.signal = (uintptr_t)info;
772.29191 --
772.29192 --	/*
772.29193 --	 * If divisor is zero, or current_msc is smaller than target_msc
772.29194 --	 * we just need to make sure target_msc passes before initiating
772.29195 --	 * the swap.
772.29196 --	 */
772.29197 - 	info->type = SWAP;
772.29198 --	info->queued = true;
772.29199 --	if (divisor && current_msc >= *target_msc) {
772.29200 --		DBG(("%s: missed target, queueing event for next: current=%lld, target=%lld, divisor=%lld, remainder=%lld\n",
772.29201 --		     __FUNCTION__,
772.29202 --		     (long long)current_msc,
772.29203 --		     (long long)*target_msc,
772.29204 --		     (long long)divisor,
772.29205 --		     (long long)remainder));
772.29206 --
772.29207 --		*target_msc = current_msc + remainder - current_msc % divisor;
772.29208 --		if (*target_msc <= current_msc)
772.29209 --			*target_msc += divisor;
772.29210 --	}
772.29211 --	vbl.request.sequence = draw_target_seq(draw, *target_msc - 1);
772.29212 - 	if (*target_msc <= current_msc + 1) {
772.29213 - 		DBG(("%s: performing blit before queueing\n", __FUNCTION__));
772.29214 --		assert(info->queued);
772.29215 --		info->bo = __sna_dri2_copy_region(sna, draw, NULL,
772.29216 --						  back, front,
772.29217 --						  true);
772.29218 --		info->type = SWAP_WAIT;
772.29219 --
772.29220 --		vbl.request.type =
772.29221 --			DRM_VBLANK_RELATIVE |
772.29222 --			DRM_VBLANK_EVENT;
772.29223 --		vbl.request.sequence = 1;
772.29224 -+		__sna_dri2_copy_event(info, DRI2_SYNC);
772.29225 -+		info->type = SWAP_COMPLETE;
772.29226 -+		if (!sna_next_vblank(info))
772.29227 -+			goto fake;
772.29228 -+
772.29229 -+		DBG(("%s: reported target_msc=%llu\n",
772.29230 -+		     __FUNCTION__, *target_msc));
772.29231 - 		*target_msc = current_msc + 1;
772.29232 --	}
772.29233 -+		swap_limit(draw, 2);
772.29234 -+	} else {
772.29235 -+		if (!sna_wait_vblank(info,
772.29236 -+				     draw_target_seq(draw, *target_msc - 1)))
772.29237 -+			goto blit;
772.29238 - 
772.29239 --	assert(info->queued);
772.29240 --	if (sna_wait_vblank(sna, &vbl, info->pipe))
772.29241 --		goto blit;
772.29242 -+		DBG(("%s: reported target_msc=%llu (in)\n",
772.29243 -+		     __FUNCTION__, *target_msc));
772.29244 -+		swap_limit(draw, 1);
772.29245 -+	}
772.29246 - 
772.29247 --	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
772.29248 --	swap_limit(draw, 1 + (info->type == SWAP_WAIT));
772.29249 - 	return TRUE;
772.29250 - 
772.29251 - blit:
772.29252 - 	DBG(("%s -- blit\n", __FUNCTION__));
772.29253 --	if (info)
772.29254 --		sna_dri2_event_free(info);
772.29255 - 	if (can_xchg(sna, draw, front, back)) {
772.29256 - 		sna_dri2_xchg(draw, front, back);
772.29257 - 	} else {
772.29258 --		__sna_dri2_copy_region(sna, draw, NULL, back, front, false);
772.29259 -+		__sna_dri2_copy_region(sna, draw, NULL, back, front, 0);
772.29260 -+		front->flags = back->flags;
772.29261 - 		type = DRI2_BLIT_COMPLETE;
772.29262 - 	}
772.29263 -+	if (draw->type == DRAWABLE_PIXMAP)
772.29264 -+		goto fake;
772.29265 - skip:
772.29266 - 	DBG(("%s: unable to show frame, unblocking client\n", __FUNCTION__));
772.29267 --	if (crtc == NULL)
772.29268 --		crtc = sna_mode_first_crtc(sna);
772.29269 --	fake_swap_complete(sna, client, draw, crtc, type, func, data);
772.29270 --	*target_msc = 0; /* offscreen, so zero out target vblank count */
772.29271 -+	if (crtc == NULL && (sna->flags & SNA_NO_WAIT) == 0)
772.29272 -+		crtc = sna_primary_crtc(sna);
772.29273 -+	if (crtc && sna_crtc_is_on(crtc)) {
772.29274 -+		if (info == NULL)
772.29275 -+			info = sna_dri2_add_event(sna, draw, client, crtc);
772.29276 -+		if (info != dri2_chain(draw))
772.29277 -+			goto fake;
772.29278 -+
772.29279 -+		assert(info->crtc == crtc);
772.29280 -+
772.29281 -+		info->type = SWAP_COMPLETE;
772.29282 -+		info->event_complete = func;
772.29283 -+		info->event_data = data;
772.29284 -+		assert(info->draw);
772.29285 -+		info->signal = true;
772.29286 -+
772.29287 -+		if (info->front == NULL)
772.29288 -+			info->front = sna_dri2_reference_buffer(front);
772.29289 -+		if (info->back == NULL)
772.29290 -+			info->back = sna_dri2_reference_buffer(back);
772.29291 -+
772.29292 -+		if (!sna_next_vblank(info))
772.29293 -+			goto fake;
772.29294 -+
772.29295 -+		swap_limit(draw, 1);
772.29296 -+	} else {
772.29297 -+fake:
772.29298 -+		/* XXX Use a Timer to throttle the client? */
772.29299 -+		fake_swap_complete(sna, client, draw, crtc, type, func, data);
772.29300 -+		if (info) {
772.29301 -+			assert(info->draw);
772.29302 -+			info->signal = false;
772.29303 -+			sna_dri2_event_free(info);
772.29304 -+		}
772.29305 -+	}
772.29306 -+	DBG(("%s: reported target_msc=%llu (in)\n", __FUNCTION__, *target_msc));
772.29307 - 	return TRUE;
772.29308 - }
772.29309 - 
772.29310 -@@ -3030,27 +3497,25 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
772.29311 - 	struct sna *sna = to_sna_from_drawable(draw);
772.29312 - 	xf86CrtcPtr crtc = sna_dri2_get_crtc(draw);
772.29313 - 	const struct ust_msc *swap;
772.29314 -+	union drm_wait_vblank vbl;
772.29315 - 
772.29316 - 	DBG(("%s(draw=%ld, pipe=%d)\n", __FUNCTION__, draw->id,
772.29317 --	     crtc ? sna_crtc_to_pipe(crtc) : -1));
772.29318 -+	     crtc ? sna_crtc_pipe(crtc) : -1));
772.29319 - 
772.29320 --	if (crtc != NULL) {
772.29321 --		union drm_wait_vblank vbl;
772.29322 -+	/* Drawable not displayed, make up a *monotonic* value */
772.29323 -+	if (crtc == NULL)
772.29324 -+		crtc = sna_primary_crtc(sna);
772.29325 -+	if (crtc == NULL)
772.29326 -+		return FALSE;
772.29327 - 
772.29328 --		VG_CLEAR(vbl);
772.29329 --		vbl.request.type = _DRM_VBLANK_RELATIVE;
772.29330 --		vbl.request.sequence = 0;
772.29331 --		if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0)
772.29332 --			sna_crtc_record_vblank(crtc, &vbl);
772.29333 --	} else
772.29334 --		/* Drawable not displayed, make up a *monotonic* value */
772.29335 --		crtc = sna_mode_first_crtc(sna);
772.29336 -+	if (sna_query_vblank(sna, crtc, &vbl) == 0)
772.29337 -+		sna_crtc_record_vblank(crtc, &vbl);
772.29338 - 
772.29339 - 	swap = sna_crtc_last_swap(crtc);
772.29340 - 	*msc = draw_current_msc(draw, crtc, swap->msc);
772.29341 - 	*ust = ust64(swap->tv_sec, swap->tv_usec);
772.29342 --	DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
772.29343 --	     (long long)*msc, (long long)*ust));
772.29344 -+	DBG(("%s: msc=%llu [raw=%llu], ust=%llu\n", __FUNCTION__,
772.29345 -+	     (long long)*msc, swap->msc, (long long)*ust));
772.29346 - 	return TRUE;
772.29347 - }
772.29348 - 
772.29349 -@@ -3068,32 +3533,22 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
772.29350 - 	struct sna_dri2_event *info = NULL;
772.29351 - 	xf86CrtcPtr crtc;
772.29352 - 	CARD64 current_msc;
772.29353 --	union drm_wait_vblank vbl;
772.29354 - 	const struct ust_msc *swap;
772.29355 --	int pipe;
772.29356 - 
772.29357 - 	crtc = sna_dri2_get_crtc(draw);
772.29358 - 	DBG(("%s(pipe=%d, target_msc=%llu, divisor=%llu, rem=%llu)\n",
772.29359 --	     __FUNCTION__, crtc ? sna_crtc_to_pipe(crtc) : -1,
772.29360 -+	     __FUNCTION__, crtc ? sna_crtc_pipe(crtc) : -1,
772.29361 - 	     (long long)target_msc,
772.29362 - 	     (long long)divisor,
772.29363 - 	     (long long)remainder));
772.29364 - 
772.29365 - 	/* Drawable not visible, return immediately */
772.29366 - 	if (crtc == NULL)
772.29367 --		goto out_complete;
772.29368 --
772.29369 --	pipe = sna_crtc_to_pipe(crtc);
772.29370 --
772.29371 --	VG_CLEAR(vbl);
772.29372 --
772.29373 --	/* Get current count */
772.29374 --	vbl.request.type = _DRM_VBLANK_RELATIVE;
772.29375 --	vbl.request.sequence = 0;
772.29376 --	if (sna_wait_vblank(sna, &vbl, pipe))
772.29377 --		goto out_complete;
772.29378 -+		crtc = sna_primary_crtc(sna);
772.29379 -+	if (crtc == NULL)
772.29380 -+		return FALSE;
772.29381 - 
772.29382 --	current_msc = draw_current_msc(draw, crtc, sna_crtc_record_vblank(crtc, &vbl));
772.29383 -+	current_msc = get_current_msc(sna, draw, crtc);
772.29384 - 
772.29385 - 	/* If target_msc already reached or passed, set it to
772.29386 - 	 * current_msc to ensure we return a reasonable value back
772.29387 -@@ -3104,15 +3559,13 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
772.29388 - 	if (divisor == 0 && current_msc >= target_msc)
772.29389 - 		goto out_complete;
772.29390 - 
772.29391 --	info = sna_dri2_add_event(sna, draw, client);
772.29392 -+	info = sna_dri2_add_event(sna, draw, client, crtc);
772.29393 - 	if (!info)
772.29394 - 		goto out_complete;
772.29395 - 
772.29396 - 	assert(info->crtc == crtc);
772.29397 - 	info->type = WAITMSC;
772.29398 - 
772.29399 --	vbl.request.signal = (uintptr_t)info;
772.29400 --	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
772.29401 - 	/*
772.29402 - 	 * If divisor is zero, or current_msc is smaller than target_msc,
772.29403 - 	 * we just need to make sure target_msc passes before waking up the
772.29404 -@@ -3129,10 +3582,8 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
772.29405 - 		if (target_msc <= current_msc)
772.29406 - 			target_msc += divisor;
772.29407 - 	}
772.29408 --	vbl.request.sequence = draw_target_seq(draw, target_msc);
772.29409 - 
772.29410 --	info->queued = true;
772.29411 --	if (sna_wait_vblank(sna, &vbl, pipe))
772.29412 -+	if (!sna_wait_vblank(info, draw_target_seq(draw, target_msc)))
772.29413 - 		goto out_free_info;
772.29414 - 
772.29415 - 	DRI2BlockClient(client, draw);
772.29416 -@@ -3141,8 +3592,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
772.29417 - out_free_info:
772.29418 - 	sna_dri2_event_free(info);
772.29419 - out_complete:
772.29420 --	if (crtc == NULL)
772.29421 --		crtc = sna_mode_first_crtc(sna);
772.29422 - 	swap = sna_crtc_last_swap(crtc);
772.29423 - 	DRI2WaitMSCComplete(client, draw,
772.29424 - 			    draw_current_msc(draw, crtc, swap->msc),
772.29425 -@@ -3231,9 +3680,18 @@ static bool is_level(const char **str)
772.29426 - 	return false;
772.29427 - }
772.29428 - 
772.29429 -+static const char *options_get_dri(struct sna *sna)
772.29430 -+{
772.29431 -+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.29432 -+	return xf86GetOptValString(sna->Options, OPTION_DRI);
772.29433 -+#else
772.29434 -+	return NULL;
772.29435 -+#endif
772.29436 -+}
772.29437 -+
772.29438 - static const char *dri_driver_name(struct sna *sna)
772.29439 - {
772.29440 --	const char *s = xf86GetOptValString(sna->Options, OPTION_DRI);
772.29441 -+	const char *s = options_get_dri(sna);
772.29442 - 
772.29443 - 	if (is_level(&s)) {
772.29444 - 		if (sna->kgem.gen < 030)
772.29445 -@@ -3259,7 +3717,7 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
772.29446 - 
772.29447 - 	if (wedged(sna)) {
772.29448 - 		xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
772.29449 --			   "loading DRI2 whilst the GPU is wedged.\n");
772.29450 -+			   "loading DRI2 whilst acceleration is disabled.\n");
772.29451 - 	}
772.29452 - 
772.29453 - 	if (xf86LoaderCheckSymbol("DRI2Version"))
772.29454 -@@ -3274,7 +3732,7 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
772.29455 - 	memset(&info, '\0', sizeof(info));
772.29456 - 	info.fd = sna->kgem.fd;
772.29457 - 	info.driverName = dri_driver_name(sna);
772.29458 --	info.deviceName = intel_get_client_name(sna->dev);
772.29459 -+	info.deviceName = intel_get_master_name(sna->dev);
772.29460 - 
772.29461 - 	DBG(("%s: loading dri driver '%s' [gen=%d] for device '%s'\n",
772.29462 - 	     __FUNCTION__, info.driverName, sna->kgem.gen, info.deviceName));
772.29463 -@@ -3299,11 +3757,12 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
772.29464 - 	info.numDrivers = 2;
772.29465 - 	info.driverNames = driverNames;
772.29466 - 	driverNames[0] = info.driverName;
772.29467 --	driverNames[1] = info.driverName;
772.29468 -+	driverNames[1] = "va_gl";
772.29469 - #endif
772.29470 - 
772.29471 - #if DRI2INFOREC_VERSION >= 6
772.29472 - 	if (xorg_can_triple_buffer()) {
772.29473 -+		DBG(("%s: enabling Xorg triple buffering\n", __FUNCTION__));
772.29474 - 		info.version = 6;
772.29475 - 		info.SwapLimitValidate = sna_dri2_swap_limit_validate;
772.29476 - 		info.ReuseBufferNotify = sna_dri2_reuse_buffer;
772.29477 -@@ -3311,8 +3770,10 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
772.29478 - #endif
772.29479 - 
772.29480 - #if USE_ASYNC_SWAP
772.29481 -+	DBG(("%s: enabled async swap and buffer age\n", __FUNCTION__));
772.29482 - 	info.version = 10;
772.29483 - 	info.scheduleSwap0 = 1;
772.29484 -+	info.bufferAge = 1;
772.29485 - #endif
772.29486 - 
772.29487 - 	return DRI2ScreenInit(screen, &info);
772.29488 -diff --git a/src/sna/sna_dri3.c b/src/sna/sna_dri3.c
772.29489 -index f586e242..ce4970ae 100644
772.29490 ---- a/src/sna/sna_dri3.c
772.29491 -+++ b/src/sna/sna_dri3.c
772.29492 -@@ -55,11 +55,14 @@ static inline void mark_dri3_pixmap(struct sna *sna, struct sna_pixmap *priv, st
772.29493 - 	if (bo->exec)
772.29494 - 		sna->kgem.flush = 1;
772.29495 - 	if (bo == priv->gpu_bo)
772.29496 --		priv->flush |= 3;
772.29497 -+		priv->flush |= FLUSH_READ | FLUSH_WRITE;
772.29498 - 	else
772.29499 - 		priv->shm = true;
772.29500 - 
772.29501 --	sna_accel_watch_flush(sna, 1);
772.29502 -+	sna_watch_flush(sna, 1);
772.29503 -+
772.29504 -+	kgem_bo_submit(&sna->kgem, bo);
772.29505 -+	kgem_bo_unclean(&sna->kgem, bo);
772.29506 - }
772.29507 - 
772.29508 - static void sna_sync_flush(struct sna *sna, struct sna_pixmap *priv)
772.29509 -@@ -270,6 +273,8 @@ static PixmapPtr sna_dri3_pixmap_from_fd(ScreenPtr screen,
772.29510 - 		priv->ptr = MAKE_STATIC_PTR(pixmap->devPrivate.ptr);
772.29511 - 	} else {
772.29512 - 		assert(priv->gpu_bo == bo);
772.29513 -+		priv->create = kgem_can_create_2d(&sna->kgem,
772.29514 -+						  width, height, depth);
772.29515 - 		priv->pinned |= PIN_DRI3;
772.29516 - 	}
772.29517 - 	list_add(&priv->cow_list, &sna->dri3.pixmaps);
772.29518 -@@ -325,6 +330,15 @@ static int sna_dri3_fd_from_pixmap(ScreenPtr screen,
772.29519 - 		return -1;
772.29520 - 	}
772.29521 - 
772.29522 -+	if (bo->tiling && !sna->kgem.can_fence) {
772.29523 -+		if (!sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
772.29524 -+			DBG(("%s: unable to discard GPU tiling (%d) for DRI3 protocol\n",
772.29525 -+			     __FUNCTION__, bo->tiling));
772.29526 -+			return -1;
772.29527 -+		}
772.29528 -+		bo = priv->gpu_bo;
772.29529 -+	}
772.29530 -+
772.29531 - 	fd = kgem_bo_export_to_prime(&sna->kgem, bo);
772.29532 - 	if (fd == -1) {
772.29533 - 		DBG(("%s: exporting handle=%d to fd failed\n", __FUNCTION__, bo->handle));
772.29534 -diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
772.29535 -index 8a3599c7..1b4015de 100644
772.29536 ---- a/src/sna/sna_driver.c
772.29537 -+++ b/src/sna/sna_driver.c
772.29538 -@@ -57,6 +57,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
772.29539 - #include <mi.h>
772.29540 - #include <micmap.h>
772.29541 - 
772.29542 -+#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
772.29543 -+#include <X11/extensions/dpmsconst.h>
772.29544 -+#else
772.29545 -+#define DPMSModeOn 0
772.29546 -+#define DPMSModeOff 3
772.29547 -+#endif
772.29548 -+
772.29549 - #include <sys/ioctl.h>
772.29550 - #include <sys/fcntl.h>
772.29551 - #include <sys/poll.h>
772.29552 -@@ -69,6 +76,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
772.29553 - 
772.29554 - #if HAVE_DOT_GIT
772.29555 - #include "git_version.h"
772.29556 -+#else
772.29557 -+#define git_version "not compiled from git"
772.29558 - #endif
772.29559 - 
772.29560 - #ifdef TEARFREE
772.29561 -@@ -185,12 +194,12 @@ sna_set_fallback_mode(ScrnInfoPtr scrn)
772.29562 - 
772.29563 - 	xf86DisableUnusedFunctions(scrn);
772.29564 - #ifdef RANDR_12_INTERFACE
772.29565 --	if (get_root_window(scrn->pScreen))
772.29566 --		xf86RandR12TellChanged(scrn->pScreen);
772.29567 -+	if (get_root_window(xf86ScrnToScreen(scrn)))
772.29568 -+		xf86RandR12TellChanged(xf86ScrnToScreen(scrn));
772.29569 - #endif
772.29570 - }
772.29571 - 
772.29572 --static Bool sna_set_desired_mode(struct sna *sna)
772.29573 -+static void sna_set_desired_mode(struct sna *sna)
772.29574 - {
772.29575 - 	ScrnInfoPtr scrn = sna->scrn;
772.29576 - 
772.29577 -@@ -203,7 +212,6 @@ static Bool sna_set_desired_mode(struct sna *sna)
772.29578 - 	}
772.29579 - 
772.29580 - 	sna_mode_check(sna);
772.29581 --	return TRUE;
772.29582 - }
772.29583 - 
772.29584 - /**
772.29585 -@@ -222,7 +230,7 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
772.29586 - 	     screen->width, screen->height, screen->rootDepth));
772.29587 - 
772.29588 - 	assert(sna->scrn == xf86ScreenToScrn(screen));
772.29589 --	assert(sna->scrn->pScreen == screen);
772.29590 -+	assert(to_screen_from_sna(sna) == screen);
772.29591 - 
772.29592 - 	/* free the data used during miInitScreen */
772.29593 - 	free(screen->devPrivate);
772.29594 -@@ -273,33 +281,89 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
772.29595 - 		if (serverGeneration == 1 && (sna->flags & SNA_IS_HOSTED) == 0)
772.29596 - 			sna_copy_fbcon(sna);
772.29597 - 
772.29598 --		(void)sna_set_desired_mode(sna);
772.29599 -+		sna_set_desired_mode(sna);
772.29600 - 	}
772.29601 - 
772.29602 - 	return TRUE;
772.29603 - }
772.29604 - 
772.29605 --static Bool sna_save_screen(ScreenPtr screen, int mode)
772.29606 -+static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
772.29607 - {
772.29608 --	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
772.29609 -+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
772.29610 -+	struct sna *sna = to_sna(scrn);
772.29611 -+	bool changed = false;
772.29612 -+	int i;
772.29613 - 
772.29614 --	DBG(("%s(mode=%d)\n", __FUNCTION__, mode));
772.29615 -+	DBG(("%s(mode=%d, flags=%d), vtSema=%d => off?=%d\n",
772.29616 -+	     __FUNCTION__, mode, flags, scrn->vtSema, mode!=DPMSModeOn));
772.29617 - 	if (!scrn->vtSema)
772.29618 --		return FALSE;
772.29619 -+		return;
772.29620 - 
772.29621 --	xf86SaveScreen(screen, mode);
772.29622 --	sna_crtc_config_notify(screen);
772.29623 --	return TRUE;
772.29624 -+	/* Opencoded version of xf86DPMSSet().
772.29625 -+	 *
772.29626 -+	 * The principle difference is to skip calling crtc->dpms() when
772.29627 -+	 * turning off the display. This (on recent enough kernels at
772.29628 -+	 * least) should be equivalent in power consumption, but require
772.29629 -+	 * less work (hence quicker and less likely to fail) when switching
772.29630 -+	 * back on.
772.29631 -+	 */
772.29632 -+	if (mode != DPMSModeOn) {
772.29633 -+		if (sna->mode.hidden == 0 && !(sna->flags & SNA_NO_DPMS)) {
772.29634 -+			DBG(("%s: hiding %d outputs\n",
772.29635 -+			     __FUNCTION__, config->num_output));
772.29636 -+			for (i = 0; i < config->num_output; i++) {
772.29637 -+				xf86OutputPtr output = config->output[i];
772.29638 -+				if (output->crtc != NULL)
772.29639 -+					output->funcs->dpms(output, mode);
772.29640 -+			}
772.29641 -+			sna->mode.hidden = sna->mode.front_active + 1;
772.29642 -+			sna->mode.front_active = 0;
772.29643 -+			changed = true;
772.29644 -+		}
772.29645 -+	} else {
772.29646 -+		/* Re-enable CRTC that have been forced off via other means */
772.29647 -+		if (sna->mode.hidden != 0) {
772.29648 -+			DBG(("%s: unhiding %d crtc, %d outputs\n",
772.29649 -+			     __FUNCTION__, config->num_crtc, config->num_output));
772.29650 -+			sna->mode.front_active = sna->mode.hidden - 1;
772.29651 -+			sna->mode.hidden = 0;
772.29652 -+			for (i = 0; i < config->num_crtc; i++) {
772.29653 -+				xf86CrtcPtr crtc = config->crtc[i];
772.29654 -+				if (crtc->enabled)
772.29655 -+					crtc->funcs->dpms(crtc, mode);
772.29656 -+			}
772.29657 -+
772.29658 -+			for (i = 0; i < config->num_output; i++) {
772.29659 -+				xf86OutputPtr output = config->output[i];
772.29660 -+				if (output->crtc != NULL)
772.29661 -+					output->funcs->dpms(output, mode);
772.29662 -+			}
772.29663 -+			changed = true;
772.29664 -+		}
772.29665 -+	}
772.29666 -+
772.29667 -+	DBG(("%s: hiding outputs? %d, front active? %d, changed? %d\n",
772.29668 -+	     __FUNCTION__, sna->mode.hidden, sna->mode.front_active, changed));
772.29669 -+
772.29670 -+	if (changed)
772.29671 -+		sna_crtc_config_notify(xf86ScrnToScreen(scrn));
772.29672 - }
772.29673 - 
772.29674 --static void sna_dpms_set(ScrnInfoPtr scrn, int mode, int flags)
772.29675 -+static Bool sna_save_screen(ScreenPtr screen, int mode)
772.29676 - {
772.29677 --	DBG(("%s(mode=%d, flags=%d)\n", __FUNCTION__, mode));
772.29678 --	if (!scrn->vtSema)
772.29679 --		return;
772.29680 -+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
772.29681 -+
772.29682 -+	DBG(("%s(mode=%d [unblank=%d])\n",
772.29683 -+	     __FUNCTION__, mode, xf86IsUnblank(mode)));
772.29684 - 
772.29685 --	xf86DPMSSet(scrn, mode, flags);
772.29686 --	sna_crtc_config_notify(xf86ScrnToScreen(scrn));
772.29687 -+	/* We have to unroll xf86SaveScreen() here as it is called
772.29688 -+	 * by DPMSSet() nullifying our special handling crtc->dpms()
772.29689 -+	 * in sna_dpms_set().
772.29690 -+	 */
772.29691 -+	sna_dpms_set(scrn,
772.29692 -+		     xf86IsUnblank(mode) ? DPMSModeOn : DPMSModeOff,
772.29693 -+		     0);
772.29694 -+	return TRUE;
772.29695 - }
772.29696 - 
772.29697 - static void sna_selftest(void)
772.29698 -@@ -330,107 +394,6 @@ static void sna_setup_capabilities(ScrnInfoPtr scrn, int fd)
772.29699 - #endif
772.29700 - }
772.29701 - 
772.29702 --static int
772.29703 --namecmp(const char *s1, const char *s2)
772.29704 --{
772.29705 --	char c1, c2;
772.29706 --
772.29707 --	if (!s1 || *s1 == 0) {
772.29708 --		if (!s2 || *s2 == 0)
772.29709 --			return 0;
772.29710 --		else
772.29711 --			return 1;
772.29712 --	}
772.29713 --
772.29714 --	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.29715 --		s1++;
772.29716 --
772.29717 --	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.29718 --		s2++;
772.29719 --
772.29720 --	c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.29721 --	c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.29722 --	while (c1 == c2) {
772.29723 --		if (c1 == '\0')
772.29724 --			return 0;
772.29725 --
772.29726 --		s1++;
772.29727 --		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.29728 --			s1++;
772.29729 --
772.29730 --		s2++;
772.29731 --		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.29732 --			s2++;
772.29733 --
772.29734 --		c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.29735 --		c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.29736 --	}
772.29737 --
772.29738 --	return c1 - c2;
772.29739 --}
772.29740 --
772.29741 --static Bool sna_option_cast_to_bool(struct sna *sna, int id, Bool val)
772.29742 --{
772.29743 --	const char *str = xf86GetOptValString(sna->Options, id);
772.29744 --
772.29745 --	if (str == NULL)
772.29746 --		return val;
772.29747 --
772.29748 --	if (*str == '\0')
772.29749 --		return TRUE;
772.29750 --
772.29751 --	if (namecmp(str, "1") == 0)
772.29752 --		return TRUE;
772.29753 --	if (namecmp(str, "on") == 0)
772.29754 --		return TRUE;
772.29755 --	if (namecmp(str, "true") == 0)
772.29756 --		return TRUE;
772.29757 --	if (namecmp(str, "yes") == 0)
772.29758 --		return TRUE;
772.29759 --
772.29760 --	if (namecmp(str, "0") == 0)
772.29761 --		return FALSE;
772.29762 --	if (namecmp(str, "off") == 0)
772.29763 --		return FALSE;
772.29764 --	if (namecmp(str, "false") == 0)
772.29765 --		return FALSE;
772.29766 --	if (namecmp(str, "no") == 0)
772.29767 --		return FALSE;
772.29768 --
772.29769 --	return val;
772.29770 --}
772.29771 --
772.29772 --static unsigned sna_option_cast_to_unsigned(struct sna *sna, int id, unsigned val)
772.29773 --{
772.29774 --	const char *str = xf86GetOptValString(sna->Options, id);
772.29775 --	unsigned v;
772.29776 --
772.29777 --	if (str == NULL || *str == '\0')
772.29778 --		return val;
772.29779 --
772.29780 --	if (namecmp(str, "on") == 0)
772.29781 --		return val;
772.29782 --	if (namecmp(str, "true") == 0)
772.29783 --		return val;
772.29784 --	if (namecmp(str, "yes") == 0)
772.29785 --		return val;
772.29786 --
772.29787 --	if (namecmp(str, "0") == 0)
772.29788 --		return 0;
772.29789 --	if (namecmp(str, "off") == 0)
772.29790 --		return 0;
772.29791 --	if (namecmp(str, "false") == 0)
772.29792 --		return 0;
772.29793 --	if (namecmp(str, "no") == 0)
772.29794 --		return 0;
772.29795 --
772.29796 --	v = atoi(str);
772.29797 --	if (v)
772.29798 --		return v;
772.29799 --
772.29800 --	return val;
772.29801 --}
772.29802 --
772.29803 - static Bool fb_supports_depth(int fd, int depth)
772.29804 - {
772.29805 - 	struct drm_i915_gem_create create;
772.29806 -@@ -470,16 +433,24 @@ static void setup_dri(struct sna *sna)
772.29807 - 	unsigned level;
772.29808 - 
772.29809 - 	sna->dri2.available = false;
772.29810 -+	sna->dri2.enable = false;
772.29811 - 	sna->dri3.available = false;
772.29812 -+	sna->dri3.enable = false;
772.29813 -+	sna->dri3.override = false;
772.29814 - 
772.29815 --	level = sna_option_cast_to_unsigned(sna, OPTION_DRI, ~0);
772.29816 -+	level = intel_option_cast_to_unsigned(sna->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
772.29817 - #if HAVE_DRI3
772.29818 --	if (level >= 3)
772.29819 --		sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
772.29820 -+	sna->dri3.available = !!xf86LoadSubModule(sna->scrn, "dri3");
772.29821 -+	sna->dri3.override =
772.29822 -+		!sna->dri3.available ||
772.29823 -+		xf86IsOptionSet(sna->Options, OPTION_DRI);
772.29824 -+	if (level >= 3 && sna->kgem.gen >= 040)
772.29825 -+		sna->dri3.enable = sna->dri3.available;
772.29826 - #endif
772.29827 - #if HAVE_DRI2
772.29828 -+	sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
772.29829 - 	if (level >= 2)
772.29830 --		sna->dri2.available = !!xf86LoadSubModule(sna->scrn, "dri2");
772.29831 -+		sna->dri2.enable = sna->dri2.available;
772.29832 - #endif
772.29833 - }
772.29834 - 
772.29835 -@@ -498,13 +469,13 @@ static bool enable_tear_free(struct sna *sna)
772.29836 - 	return ENABLE_TEAR_FREE;
772.29837 - }
772.29838 - 
772.29839 --static void setup_tear_free(struct sna *sna)
772.29840 -+static bool setup_tear_free(struct sna *sna)
772.29841 - {
772.29842 - 	MessageType from;
772.29843 - 	Bool enable;
772.29844 - 
772.29845 - 	if (sna->flags & SNA_LINEAR_FB)
772.29846 --		return;
772.29847 -+		return false;
772.29848 - 
772.29849 - 	if ((sna->flags & SNA_HAS_FLIP) == 0) {
772.29850 - 		from = X_PROBED;
772.29851 -@@ -518,11 +489,12 @@ static void setup_tear_free(struct sna *sna)
772.29852 - 		from = X_CONFIG;
772.29853 - 
772.29854 - 	if (enable)
772.29855 --		sna->flags |= SNA_TEAR_FREE;
772.29856 -+		sna->flags |= SNA_WANT_TEAR_FREE | SNA_TEAR_FREE;
772.29857 - 
772.29858 - done:
772.29859 - 	xf86DrvMsg(sna->scrn->scrnIndex, from, "TearFree %sabled\n",
772.29860 - 		   sna->flags & SNA_TEAR_FREE ? "en" : "dis");
772.29861 -+	return sna->flags & SNA_TEAR_FREE;
772.29862 - }
772.29863 - 
772.29864 - /**
772.29865 -@@ -612,8 +584,10 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
772.29866 - 	}
772.29867 - 
772.29868 - 	intel_detect_chipset(scrn, sna->dev);
772.29869 --	xf86DrvMsg(scrn->scrnIndex, X_PROBED, "CPU: %s\n",
772.29870 --		   sna_cpu_features_to_string(sna->cpu_features, buf));
772.29871 -+	xf86DrvMsg(scrn->scrnIndex, X_PROBED,
772.29872 -+		   "CPU: %s; using a maximum of %d threads\n",
772.29873 -+		   sna_cpu_features_to_string(sna->cpu_features, buf),
772.29874 -+		   sna_use_threads(64*1024, 64*1024, 1));
772.29875 - 
772.29876 - 	if (!xf86SetDepthBpp(scrn, 24, 0, 0,
772.29877 - 			     Support32bppFb |
772.29878 -@@ -651,18 +625,11 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
772.29879 - 	kgem_init(&sna->kgem, fd,
772.29880 - 		  xf86GetPciInfoForEntity(pEnt->index),
772.29881 - 		  sna->info->gen);
772.29882 --	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) ||
772.29883 --	    !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) {
772.29884 --		xf86DrvMsg(sna->scrn->scrnIndex, X_CONFIG,
772.29885 --			   "Disabling hardware acceleration.\n");
772.29886 --		sna->kgem.wedged = true;
772.29887 --	}
772.29888 - 
772.29889 - 	if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
772.29890 - 		sna->flags |= SNA_LINEAR_FB;
772.29891 --
772.29892 --	if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE))
772.29893 --		sna->flags |= SNA_REMOVE_OUTPUTS;
772.29894 -+	if (!sna->kgem.can_fence)
772.29895 -+		sna->flags |= SNA_LINEAR_FB;
772.29896 - 
772.29897 - 	if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
772.29898 - 		sna->flags |= SNA_NO_WAIT;
772.29899 -@@ -695,7 +662,8 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int probe)
772.29900 - 	}
772.29901 - 	scrn->currentMode = scrn->modes;
772.29902 - 
772.29903 --	setup_tear_free(sna);
772.29904 -+	if (!setup_tear_free(sna) && sna_mode_wants_tear_free(sna))
772.29905 -+		sna->kgem.needs_dirtyfb = sna->kgem.has_dirtyfb;
772.29906 - 
772.29907 - 	xf86SetGamma(scrn, zeros);
772.29908 - 	xf86SetDpi(scrn, 0, 0);
772.29909 -@@ -721,11 +689,13 @@ cleanup:
772.29910 - 	return FALSE;
772.29911 - }
772.29912 - 
772.29913 -+#if !HAVE_NOTIFY_FD
772.29914 - static bool has_shadow(struct sna *sna)
772.29915 - {
772.29916 --	if (!sna->mode.shadow_damage)
772.29917 -+	if (!sna->mode.shadow_enabled)
772.29918 - 		return false;
772.29919 - 
772.29920 -+	assert(sna->mode.shadow_damage);
772.29921 - 	if (RegionNil(DamageRegion(sna->mode.shadow_damage)))
772.29922 - 		return false;
772.29923 - 
772.29924 -@@ -748,7 +718,7 @@ sna_block_handler(BLOCKHANDLER_ARGS_DECL)
772.29925 - 	sna->BlockHandler(BLOCKHANDLER_ARGS);
772.29926 - 
772.29927 - 	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec) || has_shadow(sna))
772.29928 --		sna_accel_block_handler(sna, tv);
772.29929 -+		sna_accel_block(sna, tv);
772.29930 - }
772.29931 - 
772.29932 - static void
772.29933 -@@ -770,52 +740,102 @@ sna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
772.29934 - 
772.29935 - 	sna->WakeupHandler(WAKEUPHANDLER_ARGS);
772.29936 - 
772.29937 --	sna_accel_wakeup_handler(sna);
772.29938 --
772.29939 - 	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask)) {
772.29940 - 		sna_mode_wakeup(sna);
772.29941 - 		/* Clear the flag so that subsequent ZaphodHeads don't block  */
772.29942 - 		FD_CLR(sna->kgem.fd, (fd_set*)read_mask);
772.29943 - 	}
772.29944 - }
772.29945 -+#else
772.29946 -+static void
772.29947 -+sna_block_handler(void *data, void *_timeout)
772.29948 -+{
772.29949 -+	struct sna *sna = data;
772.29950 -+	int *timeout = _timeout;
772.29951 -+	struct timeval tv, *tvp;
772.29952 -+
772.29953 -+	DBG(("%s (timeout=%d)\n", __FUNCTION__, *timeout));
772.29954 -+	if (*timeout == 0)
772.29955 -+		return;
772.29956 -+
772.29957 -+	if (*timeout < 0) {
772.29958 -+		tvp = NULL;
772.29959 -+	} else {
772.29960 -+		tv.tv_sec = *timeout / 1000;
772.29961 -+		tv.tv_usec = (*timeout % 1000) * 1000;
772.29962 -+		tvp = &tv;
772.29963 -+	}
772.29964 -+
772.29965 -+	sna_accel_block(sna, &tvp);
772.29966 -+	if (tvp)
772.29967 -+		*timeout = tvp->tv_sec * 1000 + tvp->tv_usec / 1000;
772.29968 -+}
772.29969 -+#endif
772.29970 - 
772.29971 - #if HAVE_UDEV
772.29972 -+#include <sys/stat.h>
772.29973 -+
772.29974 - static void
772.29975 - sna_handle_uevents(int fd, void *closure)
772.29976 - {
772.29977 - 	struct sna *sna = closure;
772.29978 --	struct udev_device *dev;
772.29979 --	const char *str;
772.29980 - 	struct stat s;
772.29981 --	dev_t udev_devnum;
772.29982 -+	struct pollfd pfd;
772.29983 -+	bool hotplug = false;
772.29984 - 
772.29985 - 	DBG(("%s\n", __FUNCTION__));
772.29986 - 
772.29987 --	dev = udev_monitor_receive_device(sna->uevent_monitor);
772.29988 --	if (!dev)
772.29989 --		return;
772.29990 -+	pfd.fd = udev_monitor_get_fd(sna->uevent_monitor);
772.29991 -+	pfd.events = POLLIN;
772.29992 -+
772.29993 -+	if (fstat(sna->kgem.fd, &s))
772.29994 -+		memset(&s, 0, sizeof(s));
772.29995 -+
772.29996 -+	while (poll(&pfd, 1, 0) > 0) {
772.29997 -+		struct udev_device *dev;
772.29998 -+		dev_t devnum;
772.29999 -+
772.30000 -+		dev = udev_monitor_receive_device(sna->uevent_monitor);
772.30001 -+		if (dev == NULL)
772.30002 -+			break;
772.30003 -+
772.30004 -+		devnum = udev_device_get_devnum(dev);
772.30005 -+		if (memcmp(&s.st_rdev, &devnum, sizeof(dev_t)) == 0) {
772.30006 -+			const char *str;
772.30007 -+
772.30008 -+			str = udev_device_get_property_value(dev, "HOTPLUG");
772.30009 -+			if (str && atoi(str) == 1) {
772.30010 -+				str = udev_device_get_property_value(dev, "CONNECTOR");
772.30011 -+				if (str) {
772.30012 -+					hotplug |= sna_mode_find_hotplug_connector(sna, atoi(str));
772.30013 -+				} else {
772.30014 -+					sna->flags |= SNA_REPROBE;
772.30015 -+					hotplug = true;
772.30016 -+				}
772.30017 -+			}
772.30018 -+		}
772.30019 - 
772.30020 --	udev_devnum = udev_device_get_devnum(dev);
772.30021 --	if (fstat(sna->kgem.fd, &s) || memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t))) {
772.30022 - 		udev_device_unref(dev);
772.30023 --		return;
772.30024 - 	}
772.30025 - 
772.30026 --	str = udev_device_get_property_value(dev, "HOTPLUG");
772.30027 --	if (str && atoi(str) == 1) {
772.30028 --		ScrnInfoPtr scrn = sna->scrn;
772.30029 --
772.30030 --		DBG(("%s: hotplug event (vtSema?=%d)\n", __FUNCTION__, scrn->vtSema));
772.30031 -+	if (hotplug) {
772.30032 -+		DBG(("%s: hotplug event (vtSema?=%d)\n",
772.30033 -+		     __FUNCTION__, sna->scrn->vtSema));
772.30034 - 
772.30035 --		if (scrn->vtSema) {
772.30036 --			sna_mode_discover(sna);
772.30037 --			sna_mode_check(sna);
772.30038 --			RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
772.30039 --		} else
772.30040 -+		if (sna->scrn->vtSema)
772.30041 -+			sna_mode_discover(sna, true);
772.30042 -+		else
772.30043 - 			sna->flags |= SNA_REPROBE;
772.30044 - 	}
772.30045 -+}
772.30046 - 
772.30047 --	udev_device_unref(dev);
772.30048 -+static bool has_randr(void)
772.30049 -+{
772.30050 -+#if HAS_DIXREGISTERPRIVATEKEY
772.30051 -+	return dixPrivateKeyRegistered(rrPrivKey);
772.30052 -+#else
772.30053 -+	return *rrPrivKey;
772.30054 -+#endif
772.30055 - }
772.30056 - 
772.30057 - static void
772.30058 -@@ -833,7 +853,7 @@ sna_uevent_init(struct sna *sna)
772.30059 - 	/* RandR will be disabled if Xinerama is active, and so generating
772.30060 - 	 * RR hotplug events is then verboten.
772.30061 - 	 */
772.30062 --	if (!dixPrivateKeyRegistered(rrPrivKey))
772.30063 -+	if (!has_randr())
772.30064 - 		goto out;
772.30065 - 
772.30066 - 	u = NULL;
772.30067 -@@ -861,7 +881,8 @@ sna_uevent_init(struct sna *sna)
772.30068 - 
772.30069 - 	sna->uevent_monitor = mon;
772.30070 - out:
772.30071 --	xf86DrvMsg(sna->scrn->scrnIndex, from, "display hotplug detection %s\n",
772.30072 -+	xf86DrvMsg(sna->scrn->scrnIndex, from,
772.30073 -+		   "Display hotplug detection %s\n",
772.30074 - 		   sna->uevent_monitor ? "enabled" : "disabled");
772.30075 - 	return;
772.30076 - 
772.30077 -@@ -874,17 +895,10 @@ err_dev:
772.30078 - 
772.30079 - static bool sna_uevent_poll(struct sna *sna)
772.30080 - {
772.30081 --	struct pollfd pfd;
772.30082 --
772.30083 - 	if (sna->uevent_monitor == NULL)
772.30084 - 		return false;
772.30085 - 
772.30086 --	pfd.fd = udev_monitor_get_fd(sna->uevent_monitor);
772.30087 --	pfd.events = POLLIN;
772.30088 --
772.30089 --	while (poll(&pfd, 1, 0) > 0)
772.30090 --		sna_handle_uevents(pfd.fd, sna);
772.30091 --
772.30092 -+	sna_handle_uevents(udev_monitor_get_fd(sna->uevent_monitor), sna);
772.30093 - 	return true;
772.30094 - }
772.30095 - 
772.30096 -@@ -918,8 +932,10 @@ sna_randr_getinfo(ScreenPtr screen, Rotation *rotations)
772.30097 - {
772.30098 - 	struct sna *sna = to_sna_from_screen(screen);
772.30099 - 
772.30100 -+	DBG(("%s()\n", __FUNCTION__));
772.30101 -+
772.30102 - 	if (!sna_uevent_poll(sna))
772.30103 --		sna_mode_discover(sna);
772.30104 -+		sna_mode_discover(sna, false);
772.30105 - 
772.30106 - 	return sna->mode.rrGetInfo(screen, rotations);
772.30107 - }
772.30108 -@@ -931,8 +947,8 @@ static void sna_leave_vt(VT_FUNC_ARGS_DECL)
772.30109 - 
772.30110 - 	DBG(("%s\n", __FUNCTION__));
772.30111 - 
772.30112 --	sna_accel_leave(sna);
772.30113 - 	sna_mode_reset(sna);
772.30114 -+	sna_accel_leave(sna);
772.30115 - 
772.30116 - 	if (intel_put_master(sna->dev))
772.30117 - 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
772.30118 -@@ -948,6 +964,12 @@ static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
772.30119 - 
772.30120 - 	/* XXX Note that we will leak kernel resources if !vtSema */
772.30121 - 
772.30122 -+#if HAVE_NOTIFY_FD
772.30123 -+	RemoveBlockAndWakeupHandlers(sna_block_handler,
772.30124 -+				     (ServerWakeupHandlerProcPtr)NoopDDA,
772.30125 -+				     sna);
772.30126 -+#endif
772.30127 -+
772.30128 - 	sna_uevent_fini(sna);
772.30129 - 	sna_mode_close(sna);
772.30130 - 
772.30131 -@@ -1047,12 +1069,13 @@ static void sna_dri_init(struct sna *sna, ScreenPtr screen)
772.30132 - {
772.30133 - 	char str[128] = "";
772.30134 - 
772.30135 --	if (sna->dri2.available)
772.30136 -+	if (sna->dri2.enable)
772.30137 - 		sna->dri2.open = sna_dri2_open(sna, screen);
772.30138 - 	if (sna->dri2.open)
772.30139 - 		strcat(str, "DRI2 ");
772.30140 - 
772.30141 --	if (sna->dri3.available)
772.30142 -+	/* Load DRI3 in case DRI2 doesn't work, e.g. vgaarb */
772.30143 -+	if (sna->dri3.enable || (!sna->dri2.open && !sna->dri3.override))
772.30144 - 		sna->dri3.open = sna_dri3_open(sna, screen);
772.30145 - 	if (sna->dri3.open)
772.30146 - 		strcat(str, "DRI3 ");
772.30147 -@@ -1098,7 +1121,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
772.30148 - 	DBG(("%s\n", __FUNCTION__));
772.30149 - 
772.30150 - 	assert(sna->scrn == scrn);
772.30151 --	assert(scrn->pScreen == NULL); /* set afterwards */
772.30152 -+	assert(to_screen_from_sna(sna) == NULL || /* set afterwards */
772.30153 -+	       to_screen_from_sna(sna) == screen);
772.30154 - 
772.30155 - 	assert(sna->freed_pixmap == NULL);
772.30156 - 
772.30157 -@@ -1166,11 +1190,17 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
772.30158 - 	 * later memory should be bound when allocating, e.g rotate_mem */
772.30159 - 	scrn->vtSema = TRUE;
772.30160 - 
772.30161 -+#if !HAVE_NOTIFY_FD
772.30162 - 	sna->BlockHandler = screen->BlockHandler;
772.30163 - 	screen->BlockHandler = sna_block_handler;
772.30164 - 
772.30165 - 	sna->WakeupHandler = screen->WakeupHandler;
772.30166 - 	screen->WakeupHandler = sna_wakeup_handler;
772.30167 -+#else
772.30168 -+	RegisterBlockAndWakeupHandlers(sna_block_handler,
772.30169 -+				       (ServerWakeupHandlerProcPtr)NoopDDA,
772.30170 -+				       sna);
772.30171 -+#endif
772.30172 - 
772.30173 - 	screen->SaveScreen = sna_save_screen;
772.30174 - 	screen->CreateScreenResources = sna_create_screen_resources;
772.30175 -@@ -1190,6 +1220,8 @@ sna_screen_init(SCREEN_INIT_ARGS_DECL)
772.30176 - 				 CMAP_PALETTED_TRUECOLOR))
772.30177 - 		return FALSE;
772.30178 - 
772.30179 -+	if (!xf86CheckBoolOption(scrn->options, "dpms", TRUE))
772.30180 -+		sna->flags |= SNA_NO_DPMS;
772.30181 - 	xf86DPMSInit(screen, sna_dpms_set, 0);
772.30182 - 
772.30183 - 	sna_uevent_init(sna);
772.30184 -@@ -1244,20 +1276,15 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
772.30185 - 	if (intel_get_master(sna->dev))
772.30186 - 		return FALSE;
772.30187 - 
772.30188 -+	sna_accel_enter(sna);
772.30189 -+
772.30190 - 	if (sna->flags & SNA_REPROBE) {
772.30191 --		DBG(("%s: reporting deferred hotplug event\n",
772.30192 --		     __FUNCTION__));
772.30193 --		sna_mode_discover(sna);
772.30194 --		RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
772.30195 --		sna->flags &= ~SNA_REPROBE;
772.30196 -+		DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__));
772.30197 -+		sna_mode_discover(sna, true);
772.30198 - 	}
772.30199 - 
772.30200 --	if (!sna_set_desired_mode(sna)) {
772.30201 --		intel_put_master(sna->dev);
772.30202 --		return FALSE;
772.30203 --	}
772.30204 -+	sna_set_desired_mode(sna);
772.30205 - 
772.30206 --	sna_accel_enter(sna);
772.30207 - 	return TRUE;
772.30208 - }
772.30209 - 
772.30210 -@@ -1379,6 +1406,9 @@ static void describe_sna(ScrnInfoPtr scrn)
772.30211 - 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
772.30212 - 		   "SNA compiled: %s\n", BUILDER_DESCRIPTION);
772.30213 - #endif
772.30214 -+#if HAS_DEBUG_FULL
772.30215 -+	ErrorF("SNA compiled with full debug logging; expect to run slowly\n");
772.30216 -+#endif
772.30217 - #if !NDEBUG
772.30218 - 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
772.30219 - 		   "SNA compiled with assertions enabled\n");
772.30220 -@@ -1400,6 +1430,7 @@ static void describe_sna(ScrnInfoPtr scrn)
772.30221 - 		   "SNA compiled for use with valgrind\n");
772.30222 - 	VALGRIND_PRINTF("SNA compiled for use with valgrind\n");
772.30223 - #endif
772.30224 -+	DBG(("xf86-video-intel version: %s\n", git_version));
772.30225 - 	DBG(("pixman version: %s\n", pixman_version_string()));
772.30226 - }
772.30227 - 
772.30228 -diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
772.30229 -index a5dfb06b..6ee40336 100644
772.30230 ---- a/src/sna/sna_glyphs.c
772.30231 -+++ b/src/sna/sna_glyphs.c
772.30232 -@@ -74,7 +74,7 @@
772.30233 - #define NO_GLYPHS_VIA_MASK 0
772.30234 - #define FORCE_SMALL_MASK 0 /* -1 = never, 1 = always */
772.30235 - #define NO_GLYPHS_SLOW 0
772.30236 --#define NO_DISCARD_MASK 0
772.30237 -+#define DISCARD_MASK 0 /* -1 = never, 1 = always */
772.30238 - 
772.30239 - #define CACHE_PICTURE_SIZE 1024
772.30240 - #define GLYPH_MIN_SIZE 8
772.30241 -@@ -185,7 +185,7 @@ void sna_glyphs_close(struct sna *sna)
772.30242 -  */
772.30243 - bool sna_glyphs_create(struct sna *sna)
772.30244 - {
772.30245 --	ScreenPtr screen = sna->scrn->pScreen;
772.30246 -+	ScreenPtr screen = to_screen_from_sna(sna);
772.30247 - 	pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
772.30248 - 	unsigned int formats[] = {
772.30249 - 		PIXMAN_a8,
772.30250 -@@ -1094,6 +1094,9 @@ sna_glyph_get_image(GlyphPtr g, ScreenPtr s)
772.30251 - 
772.30252 - static inline bool use_small_mask(struct sna *sna, int16_t width, int16_t height, int depth)
772.30253 - {
772.30254 -+	if (depth < 8)
772.30255 -+		return true;
772.30256 -+
772.30257 - 	if (FORCE_SMALL_MASK)
772.30258 - 		return FORCE_SMALL_MASK > 0;
772.30259 - 
772.30260 -@@ -1156,12 +1159,6 @@ glyphs_via_mask(struct sna *sna,
772.30261 - 	src_x += box.x1 - list->xOff;
772.30262 - 	src_y += box.y1 - list->yOff;
772.30263 - 
772.30264 --	if (format->depth < 8) {
772.30265 --		format = PictureMatchFormat(screen, 8, PICT_a8);
772.30266 --		if (!format)
772.30267 --			return false;
772.30268 --	}
772.30269 --
772.30270 - 	component_alpha = NeedsComponent(format->format);
772.30271 - 	if (use_small_mask(sna, width, height, format->depth)) {
772.30272 - 		pixman_image_t *mask_image;
772.30273 -@@ -1179,7 +1176,7 @@ use_small_mask:
772.30274 - 			return false;
772.30275 - 
772.30276 - 		mask_image =
772.30277 --			pixman_image_create_bits(format->depth << 24 | format->format,
772.30278 -+			pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
772.30279 - 						 width, height,
772.30280 - 						 pixmap->devPrivate.ptr,
772.30281 - 						 pixmap->devKind);
772.30282 -@@ -1386,10 +1383,11 @@ next_image:
772.30283 - 					DBG(("%s: atlas format=%08x, mask format=%08x\n",
772.30284 - 					     __FUNCTION__,
772.30285 - 					     (int)p->atlas->format,
772.30286 --					     (int)(format->depth << 24 | format->format)));
772.30287 -+					     (int)mask->format));
772.30288 - 
772.30289 - 					memset(&tmp, 0, sizeof(tmp));
772.30290 --					if (p->atlas->format == (format->depth << 24 | format->format)) {
772.30291 -+					if (p->atlas->format == mask->format ||
772.30292 -+					    alphaless(p->atlas->format) == mask->format) {
772.30293 - 						ok = sna->render.composite(sna, PictOpAdd,
772.30294 - 									   p->atlas, NULL, mask,
772.30295 - 									   0, 0, 0, 0, 0, 0,
772.30296 -@@ -1561,6 +1559,9 @@ skip_glyph:
772.30297 - 		}
772.30298 - 	}
772.30299 - 
772.30300 -+	assert(format);
772.30301 -+	DBG(("%s: format=%08d, depth=%d\n",
772.30302 -+	     __FUNCTION__, format->format, format->depth));
772.30303 - out:
772.30304 - 	if (list_extents != stack_extents)
772.30305 - 		free(list_extents);
772.30306 -@@ -1573,24 +1574,34 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
772.30307 - 	PictFormatPtr g;
772.30308 - 	uint32_t color;
772.30309 - 
772.30310 --	if (NO_DISCARD_MASK)
772.30311 --		return false;
772.30312 -+	if (DISCARD_MASK)
772.30313 -+		return DISCARD_MASK > 0;
772.30314 - 
772.30315 - 	DBG(("%s: nlist=%d, mask=%08x, depth %d, op=%d (bounded? %d)\n",
772.30316 - 	     __FUNCTION__, nlist,
772.30317 - 	     mask ? (unsigned)mask->format : 0, mask ? mask->depth : 0,
772.30318 - 	     op, op_is_bounded(op)));
772.30319 - 
772.30320 --	if (nlist == 1 && list->len == 1)
772.30321 --		return true;
772.30322 -+	if (nlist == 1 && list->len == 1) {
772.30323 -+		if (mask == list->format)
772.30324 -+			return true;
772.30325 -+
772.30326 -+		g = list->format;
772.30327 -+		goto skip;
772.30328 -+	}
772.30329 - 
772.30330 --	if (!op_is_bounded(op))
772.30331 -+	if (!op_is_bounded(op)) {
772.30332 -+		DBG(("%s: unbounded op, not discarding\n", __FUNCTION__));
772.30333 - 		return false;
772.30334 -+	}
772.30335 - 
772.30336 - 	/* No glyphs overlap and we are not performing a mask conversion. */
772.30337 - 	g = glyphs_format(nlist, list, glyphs);
772.30338 --	if (mask == g)
772.30339 -+	if (mask == g) {
772.30340 -+		DBG(("%s: mask matches glyphs format, no conversion, so discard mask\n",
772.30341 -+		     __FUNCTION__));
772.30342 - 		return true;
772.30343 -+	}
772.30344 - 
772.30345 - 	DBG(("%s: preferred mask format %08x, depth %d\n",
772.30346 - 	     __FUNCTION__, g ? (unsigned)g->format : 0,  g ? g->depth : 0));
772.30347 -@@ -1605,18 +1616,41 @@ static bool can_discard_mask(uint8_t op, PicturePtr src, PictFormatPtr mask,
772.30348 - 
772.30349 - 			list++;
772.30350 - 		}
772.30351 -+
772.30352 -+		if (!sna_picture_is_solid(src, &color))
772.30353 -+			return false;
772.30354 -+
772.30355 -+		return color >> 24 == 0xff;
772.30356 - 	} else {
772.30357 --		if (PICT_FORMAT_A(mask->format) >= PICT_FORMAT_A(g->format))
772.30358 -+skip:
772.30359 -+		if (mask->format == g->format)
772.30360 - 			return true;
772.30361 - 
772.30362 --		if (g->depth != 1)
772.30363 --			return false;
772.30364 --	}
772.30365 -+		if (mask->format == alphaless(g->format))
772.30366 -+			return true;
772.30367 -+
772.30368 -+		if (PICT_FORMAT_TYPE(g->format) == PICT_TYPE_A &&
772.30369 -+		    PICT_FORMAT_TYPE(mask->format) != PICT_TYPE_A)
772.30370 -+			return true;
772.30371 - 
772.30372 --	if (!sna_picture_is_solid(src, &color))
772.30373 - 		return false;
772.30374 -+	}
772.30375 -+}
772.30376 - 
772.30377 --	return color >> 24 == 0xff;
772.30378 -+static uint32_t pixman_format(PictFormatPtr short_format)
772.30379 -+{
772.30380 -+	uint32_t bpp;
772.30381 -+
772.30382 -+	bpp = short_format->depth;
772.30383 -+	if (bpp <= 1)
772.30384 -+		bpp = 1;
772.30385 -+	else if (bpp <= 8)
772.30386 -+		bpp = 8;
772.30387 -+	else if (bpp <= 16)
772.30388 -+		bpp = 16;
772.30389 -+	else
772.30390 -+		bpp = 32;
772.30391 -+	return bpp << 24 | short_format->format;
772.30392 - }
772.30393 - 
772.30394 - static void
772.30395 -@@ -1756,7 +1790,7 @@ next:
772.30396 - 		if (sigtrap_get() == 0) {
772.30397 - 			if (mask_format) {
772.30398 - 				pixman_composite_glyphs(op, src_image, dst_image,
772.30399 --							mask_format->format | (mask_format->depth << 24),
772.30400 -+							pixman_format(mask_format),
772.30401 - 							src_x + src_dx + region.extents.x1 - dst_x,
772.30402 - 							src_y + src_dy + region.extents.y1 - dst_y,
772.30403 - 							region.extents.x1, region.extents.y1,
772.30404 -@@ -1815,10 +1849,10 @@ out:
772.30405 - 			     x, y,
772.30406 - 			     mask_format->depth,
772.30407 - 			     (long)mask_format->format,
772.30408 --			     (long)(mask_format->depth << 24 | mask_format->format),
772.30409 -+			     (long)pixman_format(mask_format),
772.30410 - 			     NeedsComponent(mask_format->format)));
772.30411 - 			mask_image =
772.30412 --				pixman_image_create_bits(mask_format->depth << 24 | mask_format->format,
772.30413 -+				pixman_image_create_bits(pixman_format(mask_format),
772.30414 - 							 region.extents.x2 - region.extents.x1,
772.30415 - 							 region.extents.y2 - region.extents.y1,
772.30416 - 							 NULL, 0);
772.30417 -@@ -2086,12 +2120,6 @@ glyphs_via_image(struct sna *sna,
772.30418 - 	src_x += box.x1 - list->xOff;
772.30419 - 	src_y += box.y1 - list->yOff;
772.30420 - 
772.30421 --	if (format->depth < 8) {
772.30422 --		format = PictureMatchFormat(screen, 8, PICT_a8);
772.30423 --		if (!format)
772.30424 --			return false;
772.30425 --	}
772.30426 --
772.30427 - 	DBG(("%s: small mask [format=%lx, depth=%d, size=%d], rendering glyphs to upload buffer\n",
772.30428 - 	     __FUNCTION__, (unsigned long)format->format,
772.30429 - 	     format->depth, (uint32_t)width*height*format->depth));
772.30430 -@@ -2104,7 +2132,7 @@ glyphs_via_image(struct sna *sna,
772.30431 - 		return false;
772.30432 - 
772.30433 - 	mask_image =
772.30434 --		pixman_image_create_bits(format->depth << 24 | format->format,
772.30435 -+		pixman_image_create_bits(pixmap->drawable.bitsPerPixel << 24 | format->format,
772.30436 - 					 width, height,
772.30437 - 					 pixmap->devPrivate.ptr,
772.30438 - 					 pixmap->devKind);
772.30439 -diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
772.30440 -index d6aa1294..d32bd583 100644
772.30441 ---- a/src/sna/sna_io.c
772.30442 -+++ b/src/sna/sna_io.c
772.30443 -@@ -105,8 +105,10 @@ read_boxes_inplace__cpu(struct kgem *kgem,
772.30444 - 	if (!download_inplace__cpu(kgem, dst, bo, box, n))
772.30445 - 		return false;
772.30446 - 
772.30447 -+	if (bo->tiling == I915_TILING_Y)
772.30448 -+		return false;
772.30449 -+
772.30450 - 	assert(kgem_bo_can_map__cpu(kgem, bo, false));
772.30451 --	assert(bo->tiling != I915_TILING_Y);
772.30452 - 
772.30453 - 	src = kgem_bo_map__cpu(kgem, bo);
772.30454 - 	if (src == NULL)
772.30455 -@@ -281,6 +283,9 @@ fallback:
772.30456 - 		if (box[n].y2 > extents.y2)
772.30457 - 			extents.y2 = box[n].y2;
772.30458 - 	}
772.30459 -+	if (!can_blt && sna->render.max_3d_size == 0)
772.30460 -+		goto fallback;
772.30461 -+
772.30462 - 	if (kgem_bo_can_map(kgem, src_bo)) {
772.30463 - 		/* Is it worth detiling? */
772.30464 - 		if ((extents.y2 - extents.y1 - 1) * src_bo->pitch < 4096)
772.30465 -@@ -477,6 +482,7 @@ fallback:
772.30466 - 			goto fallback;
772.30467 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.30468 - 	}
772.30469 -+	kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
772.30470 - 
772.30471 - 	tmp_nbox = nbox;
772.30472 - 	tmp_box = box;
772.30473 -@@ -539,6 +545,7 @@ fallback:
772.30474 - 				break;
772.30475 - 
772.30476 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.30477 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
772.30478 - 			tmp_box += nbox_this_time;
772.30479 - 		} while (1);
772.30480 - 	} else {
772.30481 -@@ -597,6 +604,7 @@ fallback:
772.30482 - 				break;
772.30483 - 
772.30484 - 			_kgem_set_mode(kgem, KGEM_BLT);
772.30485 -+			kgem_bcs_set_tiling(&sna->kgem, src_bo, NULL);
772.30486 - 			tmp_box += nbox_this_time;
772.30487 - 		} while (1);
772.30488 - 	}
772.30489 -@@ -666,8 +674,10 @@ write_boxes_inplace__tiled(struct kgem *kgem,
772.30490 - {
772.30491 - 	uint8_t *dst;
772.30492 - 
772.30493 -+	if (bo->tiling == I915_TILING_Y)
772.30494 -+		return false;
772.30495 -+
772.30496 - 	assert(kgem->has_wc_mmap || kgem_bo_can_map__cpu(kgem, bo, true));
772.30497 --	assert(bo->tiling != I915_TILING_Y);
772.30498 - 
772.30499 - 	if (kgem_bo_can_map__cpu(kgem, bo, true)) {
772.30500 - 		dst = kgem_bo_map__cpu(kgem, bo);
772.30501 -@@ -778,6 +788,15 @@ static bool __upload_inplace(struct kgem *kgem,
772.30502 - 	if (FORCE_INPLACE)
772.30503 - 		return FORCE_INPLACE > 0;
772.30504 - 
772.30505 -+	if (bo->exec)
772.30506 -+		return false;
772.30507 -+
772.30508 -+	if (bo->flush)
772.30509 -+		return true;
772.30510 -+
772.30511 -+	if (kgem_bo_can_map__cpu(kgem, bo, true))
772.30512 -+		return true;
772.30513 -+
772.30514 - 	/* If we are writing through the GTT, check first if we might be
772.30515 - 	 * able to almagamate a series of small writes into a single
772.30516 - 	 * operation.
772.30517 -@@ -849,6 +868,8 @@ bool sna_write_boxes(struct sna *sna, PixmapPtr dst,
772.30518 - 		if (box[n].y2 > extents.y2)
772.30519 - 			extents.y2 = box[n].y2;
772.30520 - 	}
772.30521 -+	if (!can_blt && sna->render.max_3d_size == 0)
772.30522 -+		goto fallback;
772.30523 - 
772.30524 - 	/* Try to avoid switching rings... */
772.30525 - 	if (!can_blt || kgem->ring == KGEM_RENDER ||
772.30526 -@@ -1038,6 +1059,7 @@ tile:
772.30527 - 			goto fallback;
772.30528 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.30529 - 	}
772.30530 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30531 - 
772.30532 - 	if (kgem->gen >= 0100) {
772.30533 - 		cmd |= 8;
772.30534 -@@ -1129,6 +1151,7 @@ tile:
772.30535 - 			if (nbox) {
772.30536 - 				_kgem_submit(kgem);
772.30537 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.30538 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30539 - 			}
772.30540 - 
772.30541 - 			kgem_bo_destroy(kgem, src_bo);
772.30542 -@@ -1224,6 +1247,7 @@ tile:
772.30543 - 			if (nbox) {
772.30544 - 				_kgem_submit(kgem);
772.30545 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.30546 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30547 - 			}
772.30548 - 
772.30549 - 			kgem_bo_destroy(kgem, src_bo);
772.30550 -@@ -1541,6 +1565,7 @@ tile:
772.30551 - 			goto fallback;
772.30552 - 		_kgem_set_mode(kgem, KGEM_BLT);
772.30553 - 	}
772.30554 -+	kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30555 - 
772.30556 - 	if (sna->kgem.gen >= 0100) {
772.30557 - 		cmd |= 8;
772.30558 -@@ -1636,6 +1661,7 @@ tile:
772.30559 - 			if (nbox) {
772.30560 - 				_kgem_submit(kgem);
772.30561 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.30562 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30563 - 			}
772.30564 - 
772.30565 - 			kgem_bo_destroy(kgem, src_bo);
772.30566 -@@ -1732,6 +1758,7 @@ tile:
772.30567 - 			if (nbox) {
772.30568 - 				_kgem_submit(kgem);
772.30569 - 				_kgem_set_mode(kgem, KGEM_BLT);
772.30570 -+				kgem_bcs_set_tiling(&sna->kgem, NULL, dst_bo);
772.30571 - 			}
772.30572 - 
772.30573 - 			kgem_bo_destroy(kgem, src_bo);
772.30574 -diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
772.30575 -index 6dd6fe88..2796d972 100644
772.30576 ---- a/src/sna/sna_present.c
772.30577 -+++ b/src/sna/sna_present.c
772.30578 -@@ -27,6 +27,7 @@
772.30579 - #include <sys/types.h>
772.30580 - #include <fcntl.h>
772.30581 - #include <unistd.h>
772.30582 -+#include <sys/poll.h>
772.30583 - #include <errno.h>
772.30584 - #include <xf86drm.h>
772.30585 - 
772.30586 -@@ -38,21 +39,73 @@
772.30587 - static present_screen_info_rec present_info;
772.30588 - 
772.30589 - struct sna_present_event {
772.30590 --	uint64_t event_id;
772.30591 - 	xf86CrtcPtr crtc;
772.30592 -+	struct sna *sna;
772.30593 -+	struct list link;
772.30594 -+	uint64_t *event_id;
772.30595 -+	uint64_t target_msc;
772.30596 -+	int n_event_id;
772.30597 -+	bool queued;
772.30598 - };
772.30599 - 
772.30600 -+static void sna_present_unflip(ScreenPtr screen, uint64_t event_id);
772.30601 -+static bool sna_present_queue(struct sna_present_event *info,
772.30602 -+			      uint64_t last_msc);
772.30603 -+
772.30604 - static inline struct sna_present_event *
772.30605 - to_present_event(uintptr_t  data)
772.30606 - {
772.30607 - 	return (struct sna_present_event *)(data & ~3);
772.30608 - }
772.30609 - 
772.30610 -+static struct sna_present_event *info_alloc(struct sna *sna)
772.30611 -+{
772.30612 -+	struct sna_present_event *info;
772.30613 -+
772.30614 -+	info = sna->present.freed_info;
772.30615 -+	if (info) {
772.30616 -+		sna->present.freed_info = NULL;
772.30617 -+		return info;
772.30618 -+	}
772.30619 -+
772.30620 -+	return malloc(sizeof(struct sna_present_event) + sizeof(uint64_t));
772.30621 -+}
772.30622 -+
772.30623 -+static void info_free(struct sna_present_event *info)
772.30624 -+{
772.30625 -+	struct sna *sna = info->sna;
772.30626 -+
772.30627 -+	if (sna->present.freed_info)
772.30628 -+		free(sna->present.freed_info);
772.30629 -+
772.30630 -+	sna->present.freed_info = info;
772.30631 -+}
772.30632 -+
772.30633 -+static inline bool msc_before(uint64_t msc, uint64_t target)
772.30634 -+{
772.30635 -+	return (int64_t)(msc - target) < 0;
772.30636 -+}
772.30637 -+
772.30638 - #define MARK_PRESENT(x) ((void *)((uintptr_t)(x) | 2))
772.30639 - 
772.30640 --static int pipe_from_crtc(RRCrtcPtr crtc)
772.30641 -+static inline xf86CrtcPtr unmask_crtc(xf86CrtcPtr crtc)
772.30642 -+{
772.30643 -+	return (xf86CrtcPtr)((uintptr_t)crtc & ~1);
772.30644 -+}
772.30645 -+
772.30646 -+static inline xf86CrtcPtr mark_crtc(xf86CrtcPtr crtc)
772.30647 -+{
772.30648 -+	return (xf86CrtcPtr)((uintptr_t)crtc | 1);
772.30649 -+}
772.30650 -+
772.30651 -+static inline bool has_vblank(xf86CrtcPtr crtc)
772.30652 -+{
772.30653 -+	return (uintptr_t)crtc & 1;
772.30654 -+}
772.30655 -+
772.30656 -+static inline int pipe_from_crtc(RRCrtcPtr crtc)
772.30657 - {
772.30658 --	return crtc ? sna_crtc_to_pipe(crtc->devPrivate) : -1;
772.30659 -+	return crtc ? sna_crtc_pipe(crtc->devPrivate) : -1;
772.30660 - }
772.30661 - 
772.30662 - static uint32_t pipe_select(int pipe)
772.30663 -@@ -74,6 +127,215 @@ static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, i
772.30664 - 	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
772.30665 - }
772.30666 - 
772.30667 -+static uint64_t gettime_ust64(void)
772.30668 -+{
772.30669 -+	struct timespec tv;
772.30670 -+
772.30671 -+	if (clock_gettime(CLOCK_MONOTONIC, &tv))
772.30672 -+		return GetTimeInMicros();
772.30673 -+
772.30674 -+	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
772.30675 -+}
772.30676 -+
772.30677 -+static void vblank_complete(struct sna_present_event *info,
772.30678 -+			    uint64_t ust, uint64_t msc)
772.30679 -+{
772.30680 -+	int n;
772.30681 -+
772.30682 -+	if (msc_before(msc, info->target_msc)) {
772.30683 -+		DBG(("%s: event=%d too early, now %lld, expected %lld\n",
772.30684 -+		     __FUNCTION__,
772.30685 -+		     info->event_id[0],
772.30686 -+		     (long long)msc, (long long)info->target_msc));
772.30687 -+		if (sna_present_queue(info, msc))
772.30688 -+			return;
772.30689 -+	}
772.30690 -+
772.30691 -+	DBG(("%s: %d events complete\n", __FUNCTION__, info->n_event_id));
772.30692 -+	for (n = 0; n < info->n_event_id; n++) {
772.30693 -+		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete%s\n", __FUNCTION__,
772.30694 -+		     sna_crtc_pipe(info->crtc),
772.30695 -+		     (int)(ust / 1000000), (int)(ust % 1000000),
772.30696 -+		     (long long)msc, (long long)info->target_msc,
772.30697 -+		     (long long)info->event_id[n],
772.30698 -+		     info->target_msc && msc == (uint32_t)info->target_msc ? "" : ": MISS"));
772.30699 -+		present_event_notify(info->event_id[n], ust, msc);
772.30700 -+	}
772.30701 -+	if (info->n_event_id > 1)
772.30702 -+		free(info->event_id);
772.30703 -+	list_del(&info->link);
772.30704 -+	info_free(info);
772.30705 -+}
772.30706 -+
772.30707 -+static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target)
772.30708 -+{
772.30709 -+	const DisplayModeRec *mode = &crtc->desiredMode;
772.30710 -+	const struct ust_msc *swap = sna_crtc_last_swap(crtc);
772.30711 -+	int64_t delay, subframe;
772.30712 -+
772.30713 -+	assert(mode->Clock);
772.30714 -+
772.30715 -+	delay = target - swap->msc;
772.30716 -+	assert(delay >= 0);
772.30717 -+	if (delay > 1) { /* try to use the hw vblank for the last frame */
772.30718 -+		delay--;
772.30719 -+		subframe = 0;
772.30720 -+	} else {
772.30721 -+		subframe = gettime_ust64() - swap_ust(swap);
772.30722 -+		subframe += 500;
772.30723 -+		subframe /= 1000;
772.30724 -+	}
772.30725 -+	delay *= mode->VTotal * mode->HTotal / mode->Clock;
772.30726 -+	if (subframe < delay)
772.30727 -+		delay -= subframe;
772.30728 -+	else
772.30729 -+		delay = 0;
772.30730 -+
772.30731 -+	DBG(("%s: sleep %d frames, %llu ms\n", __FUNCTION__,
772.30732 -+	     (int)(target - swap->msc), (long long)delay));
772.30733 -+	assert(delay >= 0);
772.30734 -+	return MIN(delay, INT32_MAX);
772.30735 -+}
772.30736 -+
772.30737 -+static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
772.30738 -+{
772.30739 -+	struct sna_present_event *info = data;
772.30740 -+	union drm_wait_vblank vbl;
772.30741 -+	uint64_t msc, ust;
772.30742 -+
772.30743 -+	DBG(("%s(event=%lldx%d, now=%d)\n", __FUNCTION__, (long long)info->event_id[0], info->n_event_id, now));
772.30744 -+
772.30745 -+	VG_CLEAR(vbl);
772.30746 -+	vbl.request.type = DRM_VBLANK_RELATIVE;
772.30747 -+	vbl.request.sequence = 0;
772.30748 -+	if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
772.30749 -+		ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
772.30750 -+		msc = sna_crtc_record_vblank(info->crtc, &vbl);
772.30751 -+		DBG(("%s: event=%lld, target msc=%lld, now %lld\n",
772.30752 -+		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)msc));
772.30753 -+		if (msc_before(msc, info->target_msc)) {
772.30754 -+			int delta = info->target_msc - msc;
772.30755 -+			uint32_t delay;
772.30756 -+
772.30757 -+			DBG(("%s: too early, requeuing delta=%d\n", __FUNCTION__, delta));
772.30758 -+			assert(info->target_msc - msc < 1ull<<31);
772.30759 -+			if (delta <= 2) {
772.30760 -+				vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
772.30761 -+				vbl.request.sequence = info->target_msc;
772.30762 -+				vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
772.30763 -+				if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
772.30764 -+					DBG(("%s: scheduled new vblank event for %lld\n", __FUNCTION__, (long long)info->target_msc));
772.30765 -+					info->queued = true;
772.30766 -+					if (delta == 1) {
772.30767 -+						sna_crtc_set_vblank(info->crtc);
772.30768 -+						info->crtc = mark_crtc(info->crtc);
772.30769 -+					}
772.30770 -+					free(timer);
772.30771 -+					return 0;
772.30772 -+				}
772.30773 -+			}
772.30774 -+
772.30775 -+			delay = msc_to_delay(info->crtc, info->target_msc);
772.30776 -+			if (delay) {
772.30777 -+				DBG(("%s: requeueing timer for %dms delay\n", __FUNCTION__, delay));
772.30778 -+				return delay;
772.30779 -+			}
772.30780 -+
772.30781 -+			/* As a last resort use a blocking wait.
772.30782 -+			 * Less than a millisecond for (hopefully) a rare case.
772.30783 -+			 */
772.30784 -+			DBG(("%s: blocking wait!\n", __FUNCTION__));
772.30785 -+			vbl.request.type = DRM_VBLANK_ABSOLUTE;
772.30786 -+			vbl.request.sequence = info->target_msc;
772.30787 -+			if (sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc)) == 0) {
772.30788 -+				ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
772.30789 -+				msc = sna_crtc_record_vblank(info->crtc, &vbl);
772.30790 -+			} else {
772.30791 -+				DBG(("%s: blocking wait failed, fudging\n",
772.30792 -+				     __FUNCTION__));
772.30793 -+				goto fixup;
772.30794 -+			}
772.30795 -+		}
772.30796 -+	} else {
772.30797 -+fixup:
772.30798 -+		ust = gettime_ust64();
772.30799 -+		msc = info->target_msc;
772.30800 -+		DBG(("%s: event=%lld, CRTC OFF, target msc=%lld, was %lld (off)\n",
772.30801 -+		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)sna_crtc_last_swap(info->crtc)->msc));
772.30802 -+	}
772.30803 -+
772.30804 -+	vblank_complete(info, ust, msc);
772.30805 -+	free(timer);
772.30806 -+	return 0;
772.30807 -+}
772.30808 -+
772.30809 -+static bool sna_fake_vblank(struct sna_present_event *info)
772.30810 -+{
772.30811 -+	const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
772.30812 -+	uint32_t delay;
772.30813 -+
772.30814 -+	if (msc_before(swap->msc, info->target_msc))
772.30815 -+		delay = msc_to_delay(info->crtc, info->target_msc);
772.30816 -+	else
772.30817 -+		delay = 0;
772.30818 -+
772.30819 -+	DBG(("%s(event=%lldx%d, target_msc=%lld, msc=%lld, delay=%ums)\n",
772.30820 -+	     __FUNCTION__, (long long)info->event_id[0], info->n_event_id,
772.30821 -+	     (long long)info->target_msc, (long long)swap->msc, delay));
772.30822 -+	if (delay == 0) {
772.30823 -+		uint64_t ust, msc;
772.30824 -+
772.30825 -+		if (msc_before(swap->msc, info->target_msc)) {
772.30826 -+			/* Fixup and pretend it completed immediately */
772.30827 -+			msc = info->target_msc;
772.30828 -+			ust = gettime_ust64();
772.30829 -+		} else {
772.30830 -+			msc = swap->msc;
772.30831 -+			ust = swap_ust(swap);
772.30832 -+		}
772.30833 -+
772.30834 -+		vblank_complete(info, ust, msc);
772.30835 -+		return true;
772.30836 -+	}
772.30837 -+
772.30838 -+	return TimerSet(NULL, 0, delay, sna_fake_vblank_handler, info);
772.30839 -+}
772.30840 -+
772.30841 -+static bool sna_present_queue(struct sna_present_event *info,
772.30842 -+			      uint64_t last_msc)
772.30843 -+{
772.30844 -+	union drm_wait_vblank vbl;
772.30845 -+	int delta = info->target_msc - last_msc;
772.30846 -+
772.30847 -+	DBG(("%s: target msc=%llu, seq=%u (last_msc=%llu), delta=%d\n",
772.30848 -+	     __FUNCTION__,
772.30849 -+	     (long long)info->target_msc,
772.30850 -+	     (unsigned)info->target_msc,
772.30851 -+	     (long long)last_msc,
772.30852 -+	     delta));
772.30853 -+	assert(info->target_msc - last_msc < 1ull<<31);
772.30854 -+	assert(delta >= 0);
772.30855 -+
772.30856 -+	VG_CLEAR(vbl);
772.30857 -+	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
772.30858 -+	vbl.request.sequence = info->target_msc;
772.30859 -+	vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
772.30860 -+	if (delta > 2 ||
772.30861 -+	    sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc))) {
772.30862 -+		DBG(("%s: vblank enqueue failed, faking delta=%d\n", __FUNCTION__, delta));
772.30863 -+		if (!sna_fake_vblank(info))
772.30864 -+			return false;
772.30865 -+	} else {
772.30866 -+		info->queued = true;
772.30867 -+		if (delta == 1) {
772.30868 -+			sna_crtc_set_vblank(info->crtc);
772.30869 -+			info->crtc = mark_crtc(info->crtc);
772.30870 -+		}
772.30871 -+	}
772.30872 -+
772.30873 -+	return true;
772.30874 -+}
772.30875 -+
772.30876 - static RRCrtcPtr
772.30877 - sna_present_get_crtc(WindowPtr window)
772.30878 - {
772.30879 -@@ -81,7 +343,10 @@ sna_present_get_crtc(WindowPtr window)
772.30880 - 	BoxRec box;
772.30881 - 	xf86CrtcPtr crtc;
772.30882 - 
772.30883 --	DBG(("%s\n", __FUNCTION__));
772.30884 -+	DBG(("%s: window=%ld (pixmap=%ld), box=(%d, %d)x(%d, %d)\n",
772.30885 -+	     __FUNCTION__, window->drawable.id, get_window_pixmap(window)->drawable.serialNumber,
772.30886 -+	     window->drawable.x, window->drawable.y,
772.30887 -+	     window->drawable.width, window->drawable.height));
772.30888 - 
772.30889 - 	box.x1 = window->drawable.x;
772.30890 - 	box.y1 = window->drawable.y;
772.30891 -@@ -99,26 +364,59 @@ static int
772.30892 - sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
772.30893 - {
772.30894 - 	struct sna *sna = to_sna_from_screen(crtc->pScreen);
772.30895 --	int pipe = pipe_from_crtc(crtc);
772.30896 - 	union drm_wait_vblank vbl;
772.30897 - 
772.30898 --	DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe));
772.30899 -+	DBG(("%s(pipe=%d)\n", __FUNCTION__, sna_crtc_pipe(crtc->devPrivate)));
772.30900 -+	if (sna_crtc_has_vblank(crtc->devPrivate)) {
772.30901 -+		DBG(("%s: vblank active, reusing last swap msc/ust\n",
772.30902 -+		     __FUNCTION__));
772.30903 -+		goto last;
772.30904 -+	}
772.30905 - 
772.30906 - 	VG_CLEAR(vbl);
772.30907 - 	vbl.request.type = DRM_VBLANK_RELATIVE;
772.30908 - 	vbl.request.sequence = 0;
772.30909 --	if (sna_wait_vblank(sna, &vbl, pipe) == 0) {
772.30910 -+	if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc->devPrivate)) == 0) {
772.30911 -+		struct sna_present_event *info;
772.30912 -+
772.30913 - 		*ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
772.30914 - 		*msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl);
772.30915 -+
772.30916 -+		info = info_alloc(sna);
772.30917 -+		if (info) {
772.30918 -+			info->crtc = crtc->devPrivate;
772.30919 -+			info->sna = sna;
772.30920 -+			info->target_msc = *msc + 1;
772.30921 -+			info->event_id = (uint64_t *)(info + 1);
772.30922 -+			info->n_event_id = 0;
772.30923 -+
772.30924 -+			vbl.request.type =
772.30925 -+				DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
772.30926 -+			vbl.request.sequence = info->target_msc;
772.30927 -+			vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
772.30928 -+
772.30929 -+			if (sna_wait_vblank(info->sna, &vbl,
772.30930 -+					    sna_crtc_pipe(info->crtc)) == 0) {
772.30931 -+				list_add(&info->link,
772.30932 -+					 &sna->present.vblank_queue);
772.30933 -+				info->queued = true;
772.30934 -+				sna_crtc_set_vblank(info->crtc);
772.30935 -+				info->crtc = mark_crtc(info->crtc);
772.30936 -+			} else
772.30937 -+				info_free(info);
772.30938 -+		}
772.30939 - 	} else {
772.30940 --		const struct ust_msc *swap = sna_crtc_last_swap(crtc->devPrivate);
772.30941 --		*ust = ust64(swap->tv_sec, swap->tv_usec);
772.30942 -+		const struct ust_msc *swap;
772.30943 -+last:
772.30944 -+		swap = sna_crtc_last_swap(crtc->devPrivate);
772.30945 -+		*ust = swap_ust(swap);
772.30946 - 		*msc = swap->msc;
772.30947 - 	}
772.30948 - 
772.30949 --	DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld\n", __FUNCTION__, pipe,
772.30950 -+	DBG(("%s: pipe=%d, tv=%d.%06d seq=%d msc=%lld\n", __FUNCTION__,
772.30951 -+	     sna_crtc_pipe(crtc->devPrivate),
772.30952 - 	     (int)(*ust / 1000000), (int)(*ust % 1000000),
772.30953 --	     (long long)*msc));
772.30954 -+	     vbl.reply.sequence, (long long)*msc));
772.30955 - 
772.30956 - 	return Success;
772.30957 - }
772.30958 -@@ -127,43 +425,106 @@ void
772.30959 - sna_present_vblank_handler(struct drm_event_vblank *event)
772.30960 - {
772.30961 - 	struct sna_present_event *info = to_present_event(event->user_data);
772.30962 -+	uint64_t msc;
772.30963 - 
772.30964 --	DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
772.30965 --	     sna_crtc_to_pipe(info->crtc),
772.30966 --	     event->tv_sec, event->tv_usec, event->sequence,
772.30967 --	     (long long)info->event_id));
772.30968 --	present_event_notify(info->event_id,
772.30969 --			     ust64(event->tv_sec, event->tv_usec),
772.30970 --			     sna_crtc_record_event(info->crtc, event));
772.30971 --	free(info);
772.30972 -+	if (!info->queued) {
772.30973 -+		DBG(("%s: arrived unexpectedly early (not queued)\n", __FUNCTION__));
772.30974 -+		assert(!has_vblank(info->crtc));
772.30975 -+		return;
772.30976 -+	}
772.30977 -+
772.30978 -+	if (has_vblank(info->crtc)) {
772.30979 -+		DBG(("%s: clearing immediate flag\n", __FUNCTION__));
772.30980 -+		info->crtc = unmask_crtc(info->crtc);
772.30981 -+		sna_crtc_clear_vblank(info->crtc);
772.30982 -+	}
772.30983 -+
772.30984 -+	msc = sna_crtc_record_event(info->crtc, event);
772.30985 -+
772.30986 -+	if (info->sna->mode.shadow_wait) {
772.30987 -+		DBG(("%s: recursed from TearFree\n", __FUNCTION__));
772.30988 -+		if (TimerSet(NULL, 0, 1, sna_fake_vblank_handler, info))
772.30989 -+			return;
772.30990 -+	}
772.30991 -+
772.30992 -+	vblank_complete(info, ust64(event->tv_sec, event->tv_usec), msc);
772.30993 - }
772.30994 - 
772.30995 - static int
772.30996 - sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
772.30997 - {
772.30998 - 	struct sna *sna = to_sna_from_screen(crtc->pScreen);
772.30999 --	struct sna_present_event *event;
772.31000 --	union drm_wait_vblank vbl;
772.31001 --
772.31002 --	DBG(("%s(pipe=%d, event=%lld, msc=%lld)\n",
772.31003 --	     __FUNCTION__, pipe_from_crtc(crtc),
772.31004 --	     (long long)event_id, (long long)msc));
772.31005 -+	struct sna_present_event *info, *tmp;
772.31006 -+	const struct ust_msc *swap;
772.31007 - 
772.31008 --	event = malloc(sizeof(struct sna_present_event));
772.31009 --	if (event == NULL)
772.31010 -+	if (!sna_crtc_is_on(crtc->devPrivate))
772.31011 - 		return BadAlloc;
772.31012 - 
772.31013 --	event->event_id = event_id;
772.31014 --	event->crtc = crtc->devPrivate;
772.31015 -+	swap = sna_crtc_last_swap(crtc->devPrivate);
772.31016 -+	DBG(("%s(pipe=%d, event=%lld, msc=%lld, last swap=%lld)\n",
772.31017 -+	     __FUNCTION__, sna_crtc_pipe(crtc->devPrivate),
772.31018 -+	     (long long)event_id, (long long)msc, (long long)swap->msc));
772.31019 - 
772.31020 --	VG_CLEAR(vbl);
772.31021 --	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
772.31022 --	vbl.request.sequence = msc;
772.31023 --	vbl.request.signal = (uintptr_t)MARK_PRESENT(event);
772.31024 --	if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(event->crtc))) {
772.31025 --		DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
772.31026 --		free(event);
772.31027 --		return BadMatch;
772.31028 -+	if (warn_unless((int64_t)(msc - swap->msc) >= 0)) {
772.31029 -+		DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
772.31030 -+		     sna_crtc_pipe(crtc->devPrivate),
772.31031 -+		     swap->tv_sec, swap->tv_usec,
772.31032 -+		     (long long)swap->msc, (long long)msc,
772.31033 -+		     (long long)event_id));
772.31034 -+		present_event_notify(event_id, swap_ust(swap), swap->msc);
772.31035 -+		return Success;
772.31036 -+	}
772.31037 -+	if (warn_unless(msc - swap->msc < 1ull<<31))
772.31038 -+		return BadValue;
772.31039 -+
772.31040 -+	list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
772.31041 -+		if (tmp->target_msc == msc &&
772.31042 -+		    unmask_crtc(tmp->crtc) == crtc->devPrivate) {
772.31043 -+			uint64_t *events = tmp->event_id;
772.31044 -+
772.31045 -+			if (tmp->n_event_id &&
772.31046 -+			    is_power_of_two(tmp->n_event_id)) {
772.31047 -+				events = malloc(2*sizeof(uint64_t)*tmp->n_event_id);
772.31048 -+				if (events == NULL)
772.31049 -+					return BadAlloc;
772.31050 -+
772.31051 -+				memcpy(events,
772.31052 -+				       tmp->event_id,
772.31053 -+				       tmp->n_event_id*sizeof(uint64_t));
772.31054 -+				if (tmp->n_event_id != 1)
772.31055 -+					free(tmp->event_id);
772.31056 -+				tmp->event_id = events;
772.31057 -+			}
772.31058 -+
772.31059 -+			DBG(("%s: appending event=%lld to vblank %lld x %d\n",
772.31060 -+			     __FUNCTION__, (long long)event_id, (long long)msc, tmp->n_event_id+1));
772.31061 -+			events[tmp->n_event_id++] = event_id;
772.31062 -+			return Success;
772.31063 -+		}
772.31064 -+		if ((int64_t)(tmp->target_msc - msc) > 0) {
772.31065 -+			DBG(("%s: previous target_msc=%lld invalid for coalescing\n",
772.31066 -+			     __FUNCTION__, (long long)tmp->target_msc));
772.31067 -+			break;
772.31068 -+		}
772.31069 -+	}
772.31070 -+
772.31071 -+	info = info_alloc(sna);
772.31072 -+	if (info == NULL)
772.31073 -+		return BadAlloc;
772.31074 -+
772.31075 -+	info->crtc = crtc->devPrivate;
772.31076 -+	info->sna = sna;
772.31077 -+	info->target_msc = msc;
772.31078 -+	info->event_id = (uint64_t *)(info + 1);
772.31079 -+	info->event_id[0] = event_id;
772.31080 -+	info->n_event_id = 1;
772.31081 -+	list_add_tail(&info->link, &tmp->link);
772.31082 -+	info->queued = false;
772.31083 -+
772.31084 -+	if (!sna_present_queue(info, swap->msc)) {
772.31085 -+		list_del(&info->link);
772.31086 -+		info_free(info);
772.31087 -+		return BadAlloc;
772.31088 - 	}
772.31089 - 
772.31090 - 	return Success;
772.31091 -@@ -180,14 +541,6 @@ sna_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
772.31092 - static void
772.31093 - sna_present_flush(WindowPtr window)
772.31094 - {
772.31095 --	PixmapPtr pixmap = get_window_pixmap(window);
772.31096 --	struct sna_pixmap *priv;
772.31097 --
772.31098 --	DBG(("%s(pixmap=%ld)\n", __FUNCTION__, pixmap->drawable.serialNumber));
772.31099 --
772.31100 --	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | MOVE_ASYNC_HINT | __MOVE_FORCE);
772.31101 --	if (priv && priv->gpu_bo)
772.31102 --		kgem_scanout_flush(&to_sna_from_pixmap(pixmap)->kgem, priv->gpu_bo);
772.31103 - }
772.31104 - 
772.31105 - static bool
772.31106 -@@ -201,8 +554,13 @@ check_flip__crtc(struct sna *sna,
772.31107 - 
772.31108 - 	assert(sna->scrn->vtSema);
772.31109 - 
772.31110 --	if (sna->mode.shadow_active) {
772.31111 --		DBG(("%s: shadow buffer active\n", __FUNCTION__));
772.31112 -+	if (!sna->mode.front_active) {
772.31113 -+		DBG(("%s: DPMS off, no flips\n", __FUNCTION__));
772.31114 -+		return FALSE;
772.31115 -+	}
772.31116 -+
772.31117 -+	if (sna->mode.rr_active) {
772.31118 -+		DBG(("%s: RandR transformation active\n", __FUNCTION__));
772.31119 - 		return false;
772.31120 - 	}
772.31121 - 
772.31122 -@@ -224,6 +582,11 @@ sna_present_check_flip(RRCrtcPtr crtc,
772.31123 - 	     pixmap->drawable.serialNumber,
772.31124 - 	     sync_flip));
772.31125 - 
772.31126 -+	if (!sna->scrn->vtSema) {
772.31127 -+		DBG(("%s: VT switched away, no flips\n", __FUNCTION__));
772.31128 -+		return FALSE;
772.31129 -+	}
772.31130 -+
772.31131 - 	if (sna->flags & SNA_NO_FLIP) {
772.31132 - 		DBG(("%s: flips not suported\n", __FUNCTION__));
772.31133 - 		return FALSE;
772.31134 -@@ -231,7 +594,7 @@ sna_present_check_flip(RRCrtcPtr crtc,
772.31135 - 
772.31136 - 	if (sync_flip) {
772.31137 - 		if ((sna->flags & SNA_HAS_FLIP) == 0) {
772.31138 --			DBG(("%s: async flips not suported\n", __FUNCTION__));
772.31139 -+			DBG(("%s: sync flips not suported\n", __FUNCTION__));
772.31140 - 			return FALSE;
772.31141 - 		}
772.31142 - 	} else {
772.31143 -@@ -257,24 +620,39 @@ sna_present_check_flip(RRCrtcPtr crtc,
772.31144 - 		return FALSE;
772.31145 - 	}
772.31146 - 
772.31147 --	return TRUE;
772.31148 --}
772.31149 --
772.31150 --static uint64_t gettime_ust64(void)
772.31151 --{
772.31152 --	struct timespec tv;
772.31153 -+	if (flip->pinned) {
772.31154 -+		assert(flip->gpu_bo);
772.31155 -+		if (sna->flags & SNA_LINEAR_FB) {
772.31156 -+			if (flip->gpu_bo->tiling != I915_TILING_NONE) {
772.31157 -+				DBG(("%s: pined bo, tilng=%d needs NONE\n",
772.31158 -+				     __FUNCTION__, flip->gpu_bo->tiling));
772.31159 -+				return FALSE;
772.31160 -+			}
772.31161 -+		} else {
772.31162 -+			if (!sna->kgem.can_scanout_y &&
772.31163 -+			    flip->gpu_bo->tiling == I915_TILING_Y) {
772.31164 -+				DBG(("%s: pined bo, tilng=%d and can't scanout Y\n",
772.31165 -+				     __FUNCTION__, flip->gpu_bo->tiling));
772.31166 -+				return FALSE;
772.31167 -+			}
772.31168 -+		}
772.31169 - 
772.31170 --	if (clock_gettime(CLOCK_MONOTONIC, &tv))
772.31171 --		return 0;
772.31172 -+		if (flip->gpu_bo->pitch & 63) {
772.31173 -+			DBG(("%s: pined bo, bad pitch=%d\n",
772.31174 -+			     __FUNCTION__, flip->gpu_bo->pitch));
772.31175 -+			return FALSE;
772.31176 -+		}
772.31177 -+	}
772.31178 - 
772.31179 --	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
772.31180 -+	return TRUE;
772.31181 - }
772.31182 - 
772.31183 - static Bool
772.31184 --page_flip__async(RRCrtcPtr crtc,
772.31185 --		 uint64_t event_id,
772.31186 --		 uint64_t target_msc,
772.31187 --		 struct kgem_bo *bo)
772.31188 -+flip__async(struct sna *sna,
772.31189 -+	    RRCrtcPtr crtc,
772.31190 -+	    uint64_t event_id,
772.31191 -+	    uint64_t target_msc,
772.31192 -+	    struct kgem_bo *bo)
772.31193 - {
772.31194 - 	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
772.31195 - 	     __FUNCTION__,
772.31196 -@@ -282,17 +660,17 @@ page_flip__async(RRCrtcPtr crtc,
772.31197 - 	     (long long)event_id,
772.31198 - 	     bo->handle));
772.31199 - 
772.31200 --	if (!sna_page_flip(to_sna_from_screen(crtc->pScreen), bo, NULL, NULL)) {
772.31201 -+	if (!sna_page_flip(sna, bo, NULL, NULL)) {
772.31202 - 		DBG(("%s: async pageflip failed\n", __FUNCTION__));
772.31203 - 		present_info.capabilities &= ~PresentCapabilityAsync;
772.31204 - 		return FALSE;
772.31205 - 	}
772.31206 - 
772.31207 --	DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
772.31208 -+	DBG(("%s: pipe=%d tv=%ld.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
772.31209 - 	     pipe_from_crtc(crtc),
772.31210 --	     gettime_ust64() / 1000000, gettime_ust64() % 1000000,
772.31211 --	     sna_crtc_last_swap(crtc->devPrivate)->msc,
772.31212 --	     (long long)event_id));
772.31213 -+	     (long)(gettime_ust64() / 1000000), (int)(gettime_ust64() % 1000000),
772.31214 -+	     crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL,
772.31215 -+	     (long long)target_msc, (long long)event_id));
772.31216 - 	present_event_notify(event_id, gettime_ust64(), target_msc);
772.31217 - 	return TRUE;
772.31218 - }
772.31219 -@@ -303,7 +681,12 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
772.31220 - 	struct sna_present_event *info = data;
772.31221 - 	struct ust_msc swap;
772.31222 - 
772.31223 --	DBG(("%s(sequence=%d)\n", __FUNCTION__, event->sequence));
772.31224 -+	DBG(("%s(sequence=%d): event=%lld\n", __FUNCTION__, event->sequence, (long long)info->event_id[0]));
772.31225 -+	assert(info->n_event_id == 1);
772.31226 -+	if (!info->queued) {
772.31227 -+		DBG(("%s: arrived unexpectedly early (not queued)\n", __FUNCTION__));
772.31228 -+		return;
772.31229 -+	}
772.31230 - 
772.31231 - 	if (info->crtc == NULL) {
772.31232 - 		swap.tv_sec = event->tv_sec;
772.31233 -@@ -312,22 +695,33 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
772.31234 - 	} else
772.31235 - 		swap = *sna_crtc_last_swap(info->crtc);
772.31236 - 
772.31237 --	DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
772.31238 --	     info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
772.31239 -+	DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld (target %lld), event=%lld complete%s\n", __FUNCTION__,
772.31240 -+	     info->crtc ? sna_crtc_pipe(info->crtc) : -1,
772.31241 - 	     swap.tv_sec, swap.tv_usec, (long long)swap.msc,
772.31242 --	     (long long)info->event_id));
772.31243 --	present_event_notify(info->event_id, ust64(swap.tv_sec, swap.tv_usec), swap.msc);
772.31244 --	free(info);
772.31245 -+	     (long long)info->target_msc,
772.31246 -+	     (long long)info->event_id[0],
772.31247 -+	     info->target_msc && info->target_msc == swap.msc ? "" : ": MISS"));
772.31248 -+	present_event_notify(info->event_id[0], swap_ust(&swap), swap.msc);
772.31249 -+	if (info->crtc)
772.31250 -+		sna_crtc_clear_vblank(info->crtc);
772.31251 -+
772.31252 -+	if (info->sna->present.unflip) {
772.31253 -+		DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, (long long)info->sna->present.unflip));
772.31254 -+		sna_present_unflip(xf86ScrnToScreen(info->sna->scrn),
772.31255 -+				   info->sna->present.unflip);
772.31256 -+		info->sna->present.unflip = 0;
772.31257 -+	}
772.31258 -+	info_free(info);
772.31259 - }
772.31260 - 
772.31261 - static Bool
772.31262 --page_flip(ScreenPtr screen,
772.31263 --	  RRCrtcPtr crtc,
772.31264 --	  uint64_t event_id,
772.31265 --	  struct kgem_bo *bo)
772.31266 -+flip(struct sna *sna,
772.31267 -+     RRCrtcPtr crtc,
772.31268 -+     uint64_t event_id,
772.31269 -+     uint64_t target_msc,
772.31270 -+     struct kgem_bo *bo)
772.31271 - {
772.31272 --	struct sna *sna = to_sna_from_screen(screen);
772.31273 --	struct sna_present_event *event;
772.31274 -+	struct sna_present_event *info;
772.31275 - 
772.31276 - 	DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
772.31277 - 	     __FUNCTION__,
772.31278 -@@ -335,18 +729,27 @@ page_flip(ScreenPtr screen,
772.31279 - 	     (long long)event_id,
772.31280 - 	     bo->handle));
772.31281 - 
772.31282 --	event = malloc(sizeof(struct sna_present_event));
772.31283 --	if (event == NULL)
772.31284 -+	info = info_alloc(sna);
772.31285 -+	if (info == NULL)
772.31286 - 		return FALSE;
772.31287 - 
772.31288 --	event->event_id = event_id;
772.31289 --	event->crtc = crtc ? crtc->devPrivate : NULL;
772.31290 --	if (!sna_page_flip(sna, bo, present_flip_handler, event)) {
772.31291 -+	info->crtc = crtc ? crtc->devPrivate : NULL;
772.31292 -+	info->sna = sna;
772.31293 -+	info->event_id = (uint64_t *)(info + 1);
772.31294 -+	info->event_id[0] = event_id;
772.31295 -+	info->n_event_id = 1;
772.31296 -+	info->target_msc = target_msc;
772.31297 -+	info->queued = false;
772.31298 -+
772.31299 -+	if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
772.31300 - 		DBG(("%s: pageflip failed\n", __FUNCTION__));
772.31301 --		free(event);
772.31302 -+		info_free(info);
772.31303 - 		return FALSE;
772.31304 - 	}
772.31305 - 
772.31306 -+	info->queued = true;
772.31307 -+	if (info->crtc)
772.31308 -+		sna_crtc_set_vblank(info->crtc);
772.31309 - 	return TRUE;
772.31310 - }
772.31311 - 
772.31312 -@@ -358,12 +761,48 @@ get_flip_bo(PixmapPtr pixmap)
772.31313 - 
772.31314 - 	DBG(("%s(pixmap=%ld)\n", __FUNCTION__, pixmap->drawable.serialNumber));
772.31315 - 
772.31316 --	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_FORCE);
772.31317 -+	priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ | __MOVE_SCANOUT | __MOVE_FORCE);
772.31318 - 	if (priv == NULL) {
772.31319 - 		DBG(("%s: cannot force pixmap to the GPU\n", __FUNCTION__));
772.31320 - 		return NULL;
772.31321 - 	}
772.31322 - 
772.31323 -+	if (priv->gpu_bo->scanout)
772.31324 -+		return priv->gpu_bo;
772.31325 -+
772.31326 -+	if (sna->kgem.has_llc && !wedged(sna) && !priv->pinned) {
772.31327 -+		struct kgem_bo *bo;
772.31328 -+		uint32_t tiling;
772.31329 -+
772.31330 -+		tiling = I915_TILING_NONE;
772.31331 -+		if ((sna->flags & SNA_LINEAR_FB) == 0)
772.31332 -+			tiling = I915_TILING_X;
772.31333 -+
772.31334 -+		bo = kgem_create_2d(&sna->kgem,
772.31335 -+				    pixmap->drawable.width,
772.31336 -+				    pixmap->drawable.height,
772.31337 -+				    pixmap->drawable.bitsPerPixel,
772.31338 -+				    tiling, CREATE_SCANOUT | CREATE_CACHED);
772.31339 -+		if (bo) {
772.31340 -+			BoxRec box;
772.31341 -+
772.31342 -+			box.x1 = box.y1 = 0;
772.31343 -+			box.x2 = pixmap->drawable.width;
772.31344 -+			box.y2 = pixmap->drawable.height;
772.31345 -+
772.31346 -+			if (sna->render.copy_boxes(sna, GXcopy,
772.31347 -+						   &pixmap->drawable, priv->gpu_bo, 0, 0,
772.31348 -+						   &pixmap->drawable, bo, 0, 0,
772.31349 -+						   &box, 1, 0)) {
772.31350 -+				sna_pixmap_unmap(pixmap, priv);
772.31351 -+				kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
772.31352 -+
772.31353 -+				priv->gpu_bo = bo;
772.31354 -+			} else
772.31355 -+				kgem_bo_destroy(&sna->kgem, bo);
772.31356 -+		}
772.31357 -+	}
772.31358 -+
772.31359 - 	if (sna->flags & SNA_LINEAR_FB &&
772.31360 - 	    priv->gpu_bo->tiling &&
772.31361 - 	    !sna_pixmap_change_tiling(pixmap, I915_TILING_NONE)) {
772.31362 -@@ -372,12 +811,17 @@ get_flip_bo(PixmapPtr pixmap)
772.31363 - 	}
772.31364 - 
772.31365 - 	if (priv->gpu_bo->tiling == I915_TILING_Y &&
772.31366 -+	    !sna->kgem.can_scanout_y &&
772.31367 - 	    !sna_pixmap_change_tiling(pixmap, I915_TILING_X)) {
772.31368 - 		DBG(("%s: invalid Y-tiling, cannot convert\n", __FUNCTION__));
772.31369 - 		return NULL;
772.31370 - 	}
772.31371 - 
772.31372 --	priv->pinned |= PIN_SCANOUT;
772.31373 -+	if (priv->gpu_bo->pitch & 63) {
772.31374 -+		DBG(("%s: invalid pitch, no conversion\n", __FUNCTION__));
772.31375 -+		return NULL;
772.31376 -+	}
772.31377 -+
772.31378 - 	return priv->gpu_bo;
772.31379 - }
772.31380 - 
772.31381 -@@ -388,6 +832,7 @@ sna_present_flip(RRCrtcPtr crtc,
772.31382 - 		 PixmapPtr pixmap,
772.31383 - 		 Bool sync_flip)
772.31384 - {
772.31385 -+	struct sna *sna = to_sna_from_pixmap(pixmap);
772.31386 - 	struct kgem_bo *bo;
772.31387 - 
772.31388 - 	DBG(("%s(pipe=%d, event=%lld, msc=%lld, pixmap=%ld, sync?=%d)\n",
772.31389 -@@ -397,11 +842,32 @@ sna_present_flip(RRCrtcPtr crtc,
772.31390 - 	     (long long)target_msc,
772.31391 - 	     pixmap->drawable.serialNumber, sync_flip));
772.31392 - 
772.31393 --	if (!check_flip__crtc(to_sna_from_pixmap(pixmap), crtc)) {
772.31394 -+	if (!check_flip__crtc(sna, crtc)) {
772.31395 - 		DBG(("%s: flip invalid for CRTC\n", __FUNCTION__));
772.31396 - 		return FALSE;
772.31397 - 	}
772.31398 - 
772.31399 -+	assert(sna->present.unflip == 0);
772.31400 -+
772.31401 -+	if (sna->flags & SNA_TEAR_FREE) {
772.31402 -+		DBG(("%s: disabling TearFree (was %s) in favour of Present flips\n",
772.31403 -+		     __FUNCTION__, sna->mode.shadow_enabled ? "enabled" : "disabled"));
772.31404 -+		sna->mode.shadow_enabled = false;
772.31405 -+	}
772.31406 -+	assert(!sna->mode.shadow_enabled);
772.31407 -+
772.31408 -+	if (sna->mode.flip_active) {
772.31409 -+		struct pollfd pfd;
772.31410 -+
772.31411 -+		DBG(("%s: flips still pending, stalling\n", __FUNCTION__));
772.31412 -+		pfd.fd = sna->kgem.fd;
772.31413 -+		pfd.events = POLLIN;
772.31414 -+		while (poll(&pfd, 1, 0) == 1)
772.31415 -+			sna_mode_wakeup(sna);
772.31416 -+		if (sna->mode.flip_active)
772.31417 -+			return FALSE;
772.31418 -+	}
772.31419 -+
772.31420 - 	bo = get_flip_bo(pixmap);
772.31421 - 	if (bo == NULL) {
772.31422 - 		DBG(("%s: flip invalid bo\n", __FUNCTION__));
772.31423 -@@ -409,9 +875,9 @@ sna_present_flip(RRCrtcPtr crtc,
772.31424 - 	}
772.31425 - 
772.31426 - 	if (sync_flip)
772.31427 --		return page_flip(crtc->pScreen, crtc, event_id, bo);
772.31428 -+		return flip(sna, crtc, event_id, target_msc, bo);
772.31429 - 	else
772.31430 --		return page_flip__async(crtc, event_id, target_msc, bo);
772.31431 -+		return flip__async(sna, crtc, event_id, target_msc, bo);
772.31432 - }
772.31433 - 
772.31434 - static void
772.31435 -@@ -421,29 +887,70 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id)
772.31436 - 	struct kgem_bo *bo;
772.31437 - 
772.31438 - 	DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id));
772.31439 --	if (sna->mode.front_active == 0 || sna->mode.shadow_active) {
772.31440 -+	if (sna->mode.front_active == 0 || sna->mode.rr_active) {
772.31441 - 		const struct ust_msc *swap;
772.31442 - 
772.31443 - 		DBG(("%s: no CRTC active, perform no-op flip\n", __FUNCTION__));
772.31444 - 
772.31445 - notify:
772.31446 --		swap = sna_crtc_last_swap(sna_mode_first_crtc(sna));
772.31447 --		DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
772.31448 -+		swap = sna_crtc_last_swap(sna_primary_crtc(sna));
772.31449 -+		DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld, event=%lld complete\n", __FUNCTION__,
772.31450 - 		     -1,
772.31451 - 		     swap->tv_sec, swap->tv_usec, (long long)swap->msc,
772.31452 - 		     (long long)event_id));
772.31453 --		present_event_notify(event_id,
772.31454 --				     ust64(swap->tv_sec, swap->tv_usec),
772.31455 --				     swap->msc);
772.31456 -+		present_event_notify(event_id, swap_ust(swap), swap->msc);
772.31457 -+		return;
772.31458 -+	}
772.31459 -+
772.31460 -+	assert(!sna->mode.shadow_enabled);
772.31461 -+	if (sna->mode.flip_active) {
772.31462 -+		DBG(("%s: %d outstanding flips, queueing unflip\n", __FUNCTION__, sna->mode.flip_active));
772.31463 -+		assert(sna->present.unflip == 0);
772.31464 -+		sna->present.unflip = event_id;
772.31465 - 		return;
772.31466 - 	}
772.31467 - 
772.31468 -+	if (sna->flags & SNA_TEAR_FREE) {
772.31469 -+		DBG(("%s: %s TearFree after Present flips\n",
772.31470 -+		     __FUNCTION__, sna->mode.shadow_damage != NULL ? "enabling" : "disabling"));
772.31471 -+		sna->mode.shadow_enabled = sna->mode.shadow_damage != NULL;
772.31472 -+	}
772.31473 -+
772.31474 - 	bo = get_flip_bo(screen->GetScreenPixmap(screen));
772.31475 --	if (bo == NULL || !page_flip(screen, NULL, event_id, bo)) {
772.31476 -+	if (bo == NULL) {
772.31477 -+reset_mode:
772.31478 - 		DBG(("%s: failed, trying to restore original mode\n", __FUNCTION__));
772.31479 - 		xf86SetDesiredModes(sna->scrn);
772.31480 - 		goto notify;
772.31481 - 	}
772.31482 -+
772.31483 -+	/* Are we unflipping after a failure that left our ScreenP in place? */
772.31484 -+	if (!sna_needs_page_flip(sna, bo))
772.31485 -+		goto notify;
772.31486 -+
772.31487 -+	assert(sna_pixmap(screen->GetScreenPixmap(screen))->pinned & PIN_SCANOUT);
772.31488 -+
772.31489 -+	if (sna->flags & SNA_HAS_ASYNC_FLIP) {
772.31490 -+		DBG(("%s: trying async flip restore\n", __FUNCTION__));
772.31491 -+		if (flip__async(sna, NULL, event_id, 0, bo))
772.31492 -+			return;
772.31493 -+	}
772.31494 -+
772.31495 -+	if (!flip(sna, NULL, event_id, 0, bo))
772.31496 -+		goto reset_mode;
772.31497 -+}
772.31498 -+
772.31499 -+void sna_present_cancel_flip(struct sna *sna)
772.31500 -+{
772.31501 -+	if (sna->present.unflip) {
772.31502 -+		const struct ust_msc *swap;
772.31503 -+
772.31504 -+		swap = sna_crtc_last_swap(sna_primary_crtc(sna));
772.31505 -+		present_event_notify(sna->present.unflip,
772.31506 -+				     swap_ust(swap), swap->msc);
772.31507 -+
772.31508 -+		sna->present.unflip = 0;
772.31509 -+	}
772.31510 - }
772.31511 - 
772.31512 - static present_screen_info_rec present_info = {
772.31513 -@@ -463,10 +970,13 @@ static present_screen_info_rec present_info = {
772.31514 - 
772.31515 - bool sna_present_open(struct sna *sna, ScreenPtr screen)
772.31516 - {
772.31517 -+	DBG(("%s(num_crtc=%d)\n", __FUNCTION__, sna->mode.num_real_crtc));
772.31518 -+
772.31519 - 	if (sna->mode.num_real_crtc == 0)
772.31520 - 		return false;
772.31521 - 
772.31522 - 	sna_present_update(sna);
772.31523 -+	list_init(&sna->present.vblank_queue);
772.31524 - 
772.31525 - 	return present_screen_init(screen, &present_info);
772.31526 - }
772.31527 -diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
772.31528 -index 3fbb9ecb..3e935d57 100644
772.31529 ---- a/src/sna/sna_render.c
772.31530 -+++ b/src/sna/sna_render.c
772.31531 -@@ -54,7 +54,7 @@ sna_format_for_depth(int depth)
772.31532 - {
772.31533 - 	switch (depth) {
772.31534 - 	case 1: return PICT_a1;
772.31535 --	case 4: return PICT_a4;
772.31536 -+	case 4: return PICT_x4a4;
772.31537 - 	case 8: return PICT_a8;
772.31538 - 	case 15: return PICT_x1r5g5b5;
772.31539 - 	case 16: return PICT_r5g6b5;
772.31540 -@@ -272,18 +272,6 @@ no_render_context_switch(struct kgem *kgem,
772.31541 - }
772.31542 - 
772.31543 - static void
772.31544 --no_render_retire(struct kgem *kgem)
772.31545 --{
772.31546 --	(void)kgem;
772.31547 --}
772.31548 --
772.31549 --static void
772.31550 --no_render_expire(struct kgem *kgem)
772.31551 --{
772.31552 --	(void)kgem;
772.31553 --}
772.31554 --
772.31555 --static void
772.31556 - no_render_fini(struct sna *sna)
772.31557 - {
772.31558 - 	(void)sna;
772.31559 -@@ -316,8 +304,6 @@ const char *no_render_init(struct sna *sna)
772.31560 - 	render->fini = no_render_fini;
772.31561 - 
772.31562 - 	sna->kgem.context_switch = no_render_context_switch;
772.31563 --	sna->kgem.retire = no_render_retire;
772.31564 --	sna->kgem.expire = no_render_expire;
772.31565 - 	if (sna->kgem.has_blt)
772.31566 - 		sna->kgem.ring = KGEM_BLT;
772.31567 - 
772.31568 -@@ -407,10 +393,7 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box, bool blt)
772.31569 - 		}
772.31570 - 	}
772.31571 - 
772.31572 --	if (priv->shm) {
772.31573 --		assert(!priv->flush);
772.31574 --		sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.31575 --	}
772.31576 -+	add_shm_flush(sna, priv);
772.31577 - 
772.31578 - 	DBG(("%s for box=(%d, %d), (%d, %d)\n",
772.31579 - 	     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
772.31580 -@@ -567,6 +550,7 @@ static struct kgem_bo *upload(struct sna *sna,
772.31581 - 			assert(priv->gpu_damage == NULL);
772.31582 - 			assert(priv->gpu_bo == NULL);
772.31583 - 			assert(bo->proxy != NULL);
772.31584 -+			sna_damage_all(&priv->cpu_damage, pixmap);
772.31585 - 			kgem_proxy_bo_attach(bo, &priv->gpu_bo);
772.31586 - 		}
772.31587 - 	}
772.31588 -@@ -627,10 +611,7 @@ sna_render_pixmap_bo(struct sna *sna,
772.31589 - 		    !priv->cpu_bo->snoop && priv->cpu_bo->pitch < 4096) {
772.31590 - 			DBG(("%s: CPU all damaged\n", __FUNCTION__));
772.31591 - 			channel->bo = priv->cpu_bo;
772.31592 --			if (priv->shm) {
772.31593 --				assert(!priv->flush);
772.31594 --				sna_add_flush_pixmap(sna, priv, priv->cpu_bo);
772.31595 --			}
772.31596 -+			add_shm_flush(sna, priv);
772.31597 - 			goto done;
772.31598 - 		}
772.31599 - 	}
772.31600 -@@ -1275,6 +1256,7 @@ sna_render_picture_extract(struct sna *sna,
772.31601 - 			assert(priv->gpu_damage == NULL);
772.31602 - 			assert(priv->gpu_bo == NULL);
772.31603 - 			assert(bo->proxy != NULL);
772.31604 -+			sna_damage_all(&priv->cpu_damage, pixmap);
772.31605 - 			kgem_proxy_bo_attach(bo, &priv->gpu_bo);
772.31606 - 		}
772.31607 - 	}
772.31608 -@@ -1338,6 +1320,8 @@ sna_render_picture_convolve(struct sna *sna,
772.31609 - 	 */
772.31610 - 	DBG(("%s: origin=(%d,%d) kernel=%dx%d, size=%dx%d\n",
772.31611 - 	     __FUNCTION__, x_off, y_off, cw, ch, w, h));
772.31612 -+	if (cw*ch > 32) /* too much loss of precision from quantization! */
772.31613 -+		return -1;
772.31614 - 
772.31615 - 	assert(picture->pDrawable);
772.31616 - 	assert(picture->filter == PictFilterConvolution);
772.31617 -@@ -1388,9 +1372,9 @@ sna_render_picture_convolve(struct sna *sna,
772.31618 - 			alpha = CreateSolidPicture(0, &color, &error);
772.31619 - 			if (alpha) {
772.31620 - 				sna_composite(PictOpAdd, picture, alpha, tmp,
772.31621 --					      x, y,
772.31622 -+					      x-(x_off+i), y-(y_off+j),
772.31623 -+					      0, 0,
772.31624 - 					      0, 0,
772.31625 --					      x_off+i, y_off+j,
772.31626 - 					      w, h);
772.31627 - 				FreePicture(alpha, 0);
772.31628 - 			}
772.31629 -@@ -2183,11 +2167,11 @@ copy_overlap(struct sna *sna, uint8_t alu,
772.31630 - 	ret = (sna->render.copy_boxes(sna, GXcopy,
772.31631 - 				      draw, bo, src_dx, src_dy,
772.31632 - 				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
772.31633 --				      box, n , 0) &&
772.31634 -+				      box, n, 0) &&
772.31635 - 	       sna->render.copy_boxes(sna, alu,
772.31636 - 				      &tmp->drawable, tmp_bo, -extents->x1, -extents->y1,
772.31637 - 				      draw, bo, dst_dx, dst_dy,
772.31638 --				      box, n , 0));
772.31639 -+				      box, n, 0));
772.31640 - 
772.31641 - 	screen->DestroyPixmap(tmp);
772.31642 - 	return ret;
772.31643 -@@ -2308,16 +2292,22 @@ static bool can_copy_cpu(struct sna *sna,
772.31644 - 			 struct kgem_bo *src,
772.31645 - 			 struct kgem_bo *dst)
772.31646 - {
772.31647 --	if (src->tiling != dst->tiling)
772.31648 --		return false;
772.31649 -+	DBG(("%s: tiling=%d:%d, pitch=%d:%d, can_map=%d:%d[%d]\n",
772.31650 -+	     __FUNCTION__,
772.31651 -+	     src->tiling, dst->tiling,
772.31652 -+	     src->pitch, dst->pitch,
772.31653 -+	     kgem_bo_can_map__cpu(&sna->kgem, src, false),
772.31654 -+	     kgem_bo_can_map__cpu(&sna->kgem, dst, true),
772.31655 -+	     sna->kgem.has_wc_mmap));
772.31656 - 
772.31657 --	if (src->pitch != dst->pitch)
772.31658 -+	if (src->tiling != dst->tiling)
772.31659 - 		return false;
772.31660 - 
772.31661 - 	if (!kgem_bo_can_map__cpu(&sna->kgem, src, false))
772.31662 - 		return false;
772.31663 - 
772.31664 --	if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true))
772.31665 -+	if (!kgem_bo_can_map__cpu(&sna->kgem, dst, true) &&
772.31666 -+	    !sna->kgem.has_wc_mmap)
772.31667 - 		return false;
772.31668 - 
772.31669 - 	DBG(("%s -- yes, src handle=%d, dst handle=%d\n", __FUNCTION__, src->handle, dst->handle));
772.31670 -@@ -2330,31 +2320,62 @@ memcpy_copy_boxes(struct sna *sna, uint8_t op,
772.31671 - 		  const DrawableRec *dst_draw, struct kgem_bo *dst_bo, int16_t dx, int16_t dy,
772.31672 - 		  const BoxRec *box, int n, unsigned flags)
772.31673 - {
772.31674 -+	memcpy_box_func detile = NULL;
772.31675 - 	void *dst, *src;
772.31676 --	bool clipped;
772.31677 - 
772.31678 - 	if (op != GXcopy)
772.31679 - 		return false;
772.31680 - 
772.31681 --	clipped = (n > 1 ||
772.31682 --		   box->x1 + dx > 0 ||
772.31683 --		   box->y1 + dy > 0 ||
772.31684 --		   box->x2 + dx < dst_draw->width ||
772.31685 --		   box->y2 + dy < dst_draw->height);
772.31686 -+	if (src_draw->depth != dst_draw->depth)
772.31687 -+		return false;
772.31688 - 
772.31689 - 	dst = src = NULL;
772.31690 --	if (!clipped && can_copy_cpu(sna, src_bo, dst_bo)) {
772.31691 --		dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
772.31692 -+	if (can_copy_cpu(sna, src_bo, dst_bo)) {
772.31693 -+		if (src_bo->pitch != dst_bo->pitch ||
772.31694 -+		    dx != sx || dy != sy || n > 1 ||
772.31695 -+		    box->x1 + dx > 0 ||
772.31696 -+		    box->y1 + dy > 0 ||
772.31697 -+		    box->x2 + dx < dst_draw->width ||
772.31698 -+		    box->y2 + dy < dst_draw->height) {
772.31699 -+			if (dx != sx) /* not implemented in memcpy yet */
772.31700 -+				goto use_gtt;
772.31701 -+
772.31702 -+			switch (dst_bo->tiling) {
772.31703 -+			default:
772.31704 -+			case I915_TILING_Y:
772.31705 -+				goto use_gtt;
772.31706 -+
772.31707 -+			case I915_TILING_X:
772.31708 -+				detile = sna->kgem.memcpy_between_tiled_x;
772.31709 -+				if (detile == NULL)
772.31710 -+					goto use_gtt;
772.31711 -+				break;
772.31712 -+
772.31713 -+			case I915_TILING_NONE:
772.31714 -+				break;
772.31715 -+			}
772.31716 -+		}
772.31717 -+
772.31718 -+		if (kgem_bo_can_map__cpu(&sna->kgem, dst_bo, true))
772.31719 -+			dst = kgem_bo_map__cpu(&sna->kgem, dst_bo);
772.31720 -+		else
772.31721 -+			dst = kgem_bo_map__wc(&sna->kgem, dst_bo);
772.31722 - 		src = kgem_bo_map__cpu(&sna->kgem, src_bo);
772.31723 - 	}
772.31724 - 
772.31725 - 	if (dst == NULL || src == NULL) {
772.31726 -+use_gtt:
772.31727 - 		dst = kgem_bo_map__gtt(&sna->kgem, dst_bo);
772.31728 - 		src = kgem_bo_map__gtt(&sna->kgem, src_bo);
772.31729 - 		if (dst == NULL || src == NULL)
772.31730 - 			return false;
772.31731 -+
772.31732 -+		detile = NULL;
772.31733 - 	} else {
772.31734 --		kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
772.31735 -+		if (dst == dst_bo->map__wc)
772.31736 -+			kgem_bo_sync__gtt(&sna->kgem, dst_bo);
772.31737 -+		else
772.31738 -+			kgem_bo_sync__cpu_full(&sna->kgem, dst_bo, true);
772.31739 - 		kgem_bo_sync__cpu_full(&sna->kgem, src_bo, false);
772.31740 - 	}
772.31741 - 
772.31742 -@@ -2362,7 +2383,16 @@ memcpy_copy_boxes(struct sna *sna, uint8_t op,
772.31743 - 	     __FUNCTION__, sx, sy, dx, dy, n));
772.31744 - 
772.31745 - 	if (sigtrap_get() == 0) {
772.31746 --		do {
772.31747 -+		if (detile) {
772.31748 -+			do {
772.31749 -+				detile(src, dst, dst_draw->bitsPerPixel,
772.31750 -+				       src_bo->pitch, dst_bo->pitch,
772.31751 -+				       box->x1 + sx, box->y1 + sy,
772.31752 -+				       box->x1 + dx, box->y1 + dy,
772.31753 -+				       box->x2 - box->x1, box->y2 - box->y1);
772.31754 -+				box++;
772.31755 -+			} while (--n);
772.31756 -+		} else do {
772.31757 - 			memcpy_blt(src, dst, dst_draw->bitsPerPixel,
772.31758 - 				   src_bo->pitch, dst_bo->pitch,
772.31759 - 				   box->x1 + sx, box->y1 + sy,
772.31760 -@@ -2380,4 +2410,5 @@ void
772.31761 - sna_render_mark_wedged(struct sna *sna)
772.31762 - {
772.31763 - 	sna->render.copy_boxes = memcpy_copy_boxes;
772.31764 -+	sna->render.prefer_gpu = 0;
772.31765 - }
772.31766 -diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
772.31767 -index 6e1fa480..4ba345a7 100644
772.31768 ---- a/src/sna/sna_render.h
772.31769 -+++ b/src/sna/sna_render.h
772.31770 -@@ -148,6 +148,10 @@ struct sna_composite_op {
772.31771 - 		struct {
772.31772 - 			uint32_t flags;
772.31773 - 		} gen8;
772.31774 -+
772.31775 -+		struct {
772.31776 -+			uint32_t flags;
772.31777 -+		} gen9;
772.31778 - 	} u;
772.31779 - 
772.31780 - 	void *priv;
772.31781 -@@ -238,8 +242,9 @@ struct sna_render {
772.31782 - 			  int16_t w, int16_t h,
772.31783 - 			  unsigned flags,
772.31784 - 			  struct sna_composite_op *tmp);
772.31785 --#define COMPOSITE_PARTIAL 0x1
772.31786 --#define COMPOSITE_FALLBACK 0x80000000
772.31787 -+#define COMPOSITE_PARTIAL	0x1
772.31788 -+#define COMPOSITE_UPLOAD	0x40000000
772.31789 -+#define COMPOSITE_FALLBACK	0x80000000
772.31790 - 
772.31791 - 	bool (*check_composite_spans)(struct sna *sna, uint8_t op,
772.31792 - 				      PicturePtr dst, PicturePtr src,
772.31793 -@@ -286,6 +291,8 @@ struct sna_render {
772.31794 - #define COPY_LAST 0x1
772.31795 - #define COPY_SYNC 0x2
772.31796 - #define COPY_NO_OVERLAP 0x4
772.31797 -+#define COPY_SMALL 0x8
772.31798 -+#define COPY_DRI 0x10
772.31799 - 
772.31800 - 	bool (*copy)(struct sna *sna, uint8_t alu,
772.31801 - 		     PixmapPtr src, struct kgem_bo *src_bo,
772.31802 -@@ -481,6 +488,7 @@ enum {
772.31803 - 
772.31804 - 	GEN7_WM_KERNEL_VIDEO_PLANAR,
772.31805 - 	GEN7_WM_KERNEL_VIDEO_PACKED,
772.31806 -+	GEN7_WM_KERNEL_VIDEO_RGB,
772.31807 - 	GEN7_WM_KERNEL_COUNT
772.31808 - };
772.31809 - 
772.31810 -@@ -533,12 +541,13 @@ enum {
772.31811 - 
772.31812 - 	GEN8_WM_KERNEL_VIDEO_PLANAR,
772.31813 - 	GEN8_WM_KERNEL_VIDEO_PACKED,
772.31814 -+	GEN8_WM_KERNEL_VIDEO_RGB,
772.31815 - 	GEN8_WM_KERNEL_COUNT
772.31816 - };
772.31817 - 
772.31818 - struct gen8_render_state {
772.31819 - 	unsigned gt;
772.31820 --
772.31821 -+	const struct gt_info *info;
772.31822 - 	struct kgem_bo *general_bo;
772.31823 - 
772.31824 - 	uint32_t vs_state;
772.31825 -@@ -565,6 +574,58 @@ struct gen8_render_state {
772.31826 - 	bool emit_flush;
772.31827 - };
772.31828 - 
772.31829 -+enum {
772.31830 -+	GEN9_WM_KERNEL_NOMASK = 0,
772.31831 -+	GEN9_WM_KERNEL_NOMASK_P,
772.31832 -+
772.31833 -+	GEN9_WM_KERNEL_MASK,
772.31834 -+	GEN9_WM_KERNEL_MASK_P,
772.31835 -+
772.31836 -+	GEN9_WM_KERNEL_MASKCA,
772.31837 -+	GEN9_WM_KERNEL_MASKCA_P,
772.31838 -+
772.31839 -+	GEN9_WM_KERNEL_MASKSA,
772.31840 -+	GEN9_WM_KERNEL_MASKSA_P,
772.31841 -+
772.31842 -+	GEN9_WM_KERNEL_OPACITY,
772.31843 -+	GEN9_WM_KERNEL_OPACITY_P,
772.31844 -+
772.31845 -+	GEN9_WM_KERNEL_VIDEO_PLANAR,
772.31846 -+	GEN9_WM_KERNEL_VIDEO_PACKED,
772.31847 -+	GEN9_WM_KERNEL_VIDEO_RGB,
772.31848 -+	GEN9_WM_KERNEL_COUNT
772.31849 -+};
772.31850 -+
772.31851 -+struct gen9_render_state {
772.31852 -+	unsigned gt;
772.31853 -+	const struct gt_info *info;
772.31854 -+	struct kgem_bo *general_bo;
772.31855 -+
772.31856 -+	uint32_t vs_state;
772.31857 -+	uint32_t sf_state;
772.31858 -+	uint32_t sf_mask_state;
772.31859 -+	uint32_t wm_state;
772.31860 -+	uint32_t wm_kernel[GEN9_WM_KERNEL_COUNT][3];
772.31861 -+
772.31862 -+	uint32_t cc_blend;
772.31863 -+
772.31864 -+	uint32_t drawrect_offset;
772.31865 -+	uint32_t drawrect_limit;
772.31866 -+	uint32_t blend;
772.31867 -+	uint32_t samplers;
772.31868 -+	uint32_t kernel;
772.31869 -+
772.31870 -+	uint16_t num_sf_outputs;
772.31871 -+	uint16_t ve_id;
772.31872 -+	uint16_t last_primitive;
772.31873 -+	int16_t floats_per_vertex;
772.31874 -+	uint16_t surface_table;
772.31875 -+
772.31876 -+	bool needs_invariant;
772.31877 -+	bool emit_flush;
772.31878 -+	bool ve_dirty;
772.31879 -+};
772.31880 -+
772.31881 - struct sna_static_stream {
772.31882 - 	uint32_t size, used;
772.31883 - 	uint8_t *data;
772.31884 -@@ -620,6 +681,7 @@ const char *gen5_render_init(struct sna *sna, const char *backend);
772.31885 - const char *gen6_render_init(struct sna *sna, const char *backend);
772.31886 - const char *gen7_render_init(struct sna *sna, const char *backend);
772.31887 - const char *gen8_render_init(struct sna *sna, const char *backend);
772.31888 -+const char *gen9_render_init(struct sna *sna, const char *backend);
772.31889 - 
772.31890 - void sna_render_mark_wedged(struct sna *sna);
772.31891 - 
772.31892 -diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
772.31893 -index 10fbbfe2..e162e37f 100644
772.31894 ---- a/src/sna/sna_render_inline.h
772.31895 -+++ b/src/sna/sna_render_inline.h
772.31896 -@@ -304,6 +304,12 @@ color_convert(uint32_t pixel,
772.31897 - 	return pixel;
772.31898 - }
772.31899 - 
772.31900 -+inline static uint32_t
772.31901 -+solid_color(uint32_t format, uint32_t pixel)
772.31902 -+{
772.31903 -+	return color_convert(pixel, format, PICT_a8r8g8b8);
772.31904 -+}
772.31905 -+
772.31906 - inline static bool dst_use_gpu(PixmapPtr pixmap)
772.31907 - {
772.31908 - 	struct sna_pixmap *priv = sna_pixmap(pixmap);
772.31909 -diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c
772.31910 -index 308efc0a..8e2627f7 100644
772.31911 ---- a/src/sna/sna_tiling.c
772.31912 -+++ b/src/sna/sna_tiling.c
772.31913 -@@ -369,8 +369,7 @@ sna_tiling_composite_spans_boxes(struct sna *sna,
772.31914 - 				 const BoxRec *box, int nbox, float opacity)
772.31915 - {
772.31916 - 	while (nbox--)
772.31917 --		sna_tiling_composite_spans_box(sna, op->base.priv, box++, opacity);
772.31918 --	(void)sna;
772.31919 -+		sna_tiling_composite_spans_box(sna, op, box++, opacity);
772.31920 - }
772.31921 - 
772.31922 - fastcall static void
772.31923 -@@ -581,6 +580,7 @@ sna_tiling_composite_spans(uint32_t op,
772.31924 - 	tile->rects = tile->rects_embedded;
772.31925 - 	tile->rect_count = 0;
772.31926 - 	tile->rect_size = ARRAY_SIZE(tile->rects_embedded);
772.31927 -+	COMPILE_TIME_ASSERT(sizeof(tile->rects_embedded[0]) >= sizeof(struct sna_tile_span));
772.31928 - 
772.31929 - 	tmp->box   = sna_tiling_composite_spans_box;
772.31930 - 	tmp->boxes = sna_tiling_composite_spans_boxes;
772.31931 -diff --git a/src/sna/sna_trapezoids_boxes.c b/src/sna/sna_trapezoids_boxes.c
772.31932 -index 9900e3f0..bbf83759 100644
772.31933 ---- a/src/sna/sna_trapezoids_boxes.c
772.31934 -+++ b/src/sna/sna_trapezoids_boxes.c
772.31935 -@@ -198,7 +198,7 @@ composite_aligned_boxes(struct sna *sna,
772.31936 - 	if (op == PictOpClear && sna->clear)
772.31937 - 		src = sna->clear;
772.31938 - 
772.31939 --	DBG(("%s: clipped extents (%d, %d), (%d, %d);  now offset by (%d, %d), orgin (%d, %d)\n",
772.31940 -+	DBG(("%s: clipped extents (%d, %d), (%d, %d);  now offset by (%d, %d), origin (%d, %d)\n",
772.31941 - 	     __FUNCTION__,
772.31942 - 	     clip.extents.x1, clip.extents.y1,
772.31943 - 	     clip.extents.x2, clip.extents.y2,
772.31944 -@@ -592,6 +592,8 @@ lerp32_opacity(PixmapPtr scratch,
772.31945 - 	uint32_t *ptr;
772.31946 - 	int stride, i;
772.31947 - 
772.31948 -+	sigtrap_assert_active();
772.31949 -+
772.31950 - 	ptr = (uint32_t*)((uint8_t *)scratch->devPrivate.ptr + scratch->devKind * y);
772.31951 - 	ptr += x;
772.31952 - 	stride = scratch->devKind / 4;
772.31953 -diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
772.31954 -index 37def2f9..8bc7c8a8 100644
772.31955 ---- a/src/sna/sna_trapezoids_imprecise.c
772.31956 -+++ b/src/sna/sna_trapezoids_imprecise.c
772.31957 -@@ -962,6 +962,16 @@ tor_add_trapezoid(struct tor *tor,
772.31958 - 		  const xTrapezoid *t,
772.31959 - 		  int dx, int dy)
772.31960 - {
772.31961 -+	if (!xTrapezoidValid(t)) {
772.31962 -+		__DBG(("%s: skipping invalid trapezoid: top=%d, bottom=%d, left=(%d, %d), (%d, %d), right=(%d, %d), (%d, %d)\n",
772.31963 -+		       __FUNCTION__,
772.31964 -+		       t->top, t->bottom,
772.31965 -+		       t->left.p1.x, t->left.p1.y,
772.31966 -+		       t->left.p2.x, t->left.p2.y,
772.31967 -+		       t->right.p1.x, t->right.p1.y,
772.31968 -+		       t->right.p2.x, t->right.p2.y));
772.31969 -+		return;
772.31970 -+	}
772.31971 - 	polygon_add_edge(tor->polygon, t, &t->left, 1, dx, dy);
772.31972 - 	polygon_add_edge(tor->polygon, t, &t->right, -1, dx, dy);
772.31973 - }
772.31974 -@@ -1687,31 +1697,27 @@ struct span_thread {
772.31975 - #define SPAN_THREAD_MAX_BOXES (8192/sizeof(struct sna_opacity_box))
772.31976 - struct span_thread_boxes {
772.31977 - 	const struct sna_composite_spans_op *op;
772.31978 -+	const BoxRec *clip_start, *clip_end;
772.31979 - 	int num_boxes;
772.31980 - 	struct sna_opacity_box boxes[SPAN_THREAD_MAX_BOXES];
772.31981 - };
772.31982 - 
772.31983 --static void span_thread_add_boxes(struct sna *sna, void *data,
772.31984 --				  const BoxRec *box, int count, float alpha)
772.31985 -+static void span_thread_add_box(struct sna *sna, void *data,
772.31986 -+				const BoxRec *box, float alpha)
772.31987 - {
772.31988 - 	struct span_thread_boxes *b = data;
772.31989 - 
772.31990 --	__DBG(("%s: adding %d boxes with alpha=%f\n",
772.31991 --	       __FUNCTION__, count, alpha));
772.31992 -+	__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
772.31993 - 
772.31994 --	assert(count > 0 && count <= SPAN_THREAD_MAX_BOXES);
772.31995 --	if (unlikely(b->num_boxes + count > SPAN_THREAD_MAX_BOXES)) {
772.31996 --		DBG(("%s: flushing %d boxes, adding %d\n", __FUNCTION__, b->num_boxes, count));
772.31997 --		assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
772.31998 -+	if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
772.31999 -+		DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
772.32000 - 		b->op->thread_boxes(sna, b->op, b->boxes, b->num_boxes);
772.32001 - 		b->num_boxes = 0;
772.32002 - 	}
772.32003 - 
772.32004 --	do {
772.32005 --		b->boxes[b->num_boxes].box = *box++;
772.32006 --		b->boxes[b->num_boxes].alpha = alpha;
772.32007 --		b->num_boxes++;
772.32008 --	} while (--count);
772.32009 -+	b->boxes[b->num_boxes].box = *box++;
772.32010 -+	b->boxes[b->num_boxes].alpha = alpha;
772.32011 -+	b->num_boxes++;
772.32012 - 	assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
772.32013 - }
772.32014 - 
772.32015 -@@ -1722,8 +1728,22 @@ span_thread_box(struct sna *sna,
772.32016 - 		const BoxRec *box,
772.32017 - 		int coverage)
772.32018 - {
772.32019 -+	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
772.32020 -+
772.32021 - 	__DBG(("%s: %d -> %d @ %d\n", __FUNCTION__, box->x1, box->x2, coverage));
772.32022 --	span_thread_add_boxes(sna, op, box, 1, AREA_TO_ALPHA(coverage));
772.32023 -+	if (b->num_boxes) {
772.32024 -+		struct sna_opacity_box *bb = &b->boxes[b->num_boxes-1];
772.32025 -+		if (bb->box.x1 == box->x1 &&
772.32026 -+		    bb->box.x2 == box->x2 &&
772.32027 -+		    bb->box.y2 == box->y1 &&
772.32028 -+		    bb->alpha == AREA_TO_ALPHA(coverage)) {
772.32029 -+			bb->box.y2 = box->y2;
772.32030 -+			__DBG(("%s: contracted double row: %d -> %d\n", __func__, bb->box.y1, bb->box.y2));
772.32031 -+			return;
772.32032 -+		}
772.32033 -+	}
772.32034 -+
772.32035 -+	span_thread_add_box(sna, op, box, AREA_TO_ALPHA(coverage));
772.32036 - }
772.32037 - 
772.32038 - static void
772.32039 -@@ -1733,20 +1753,28 @@ span_thread_clipped_box(struct sna *sna,
772.32040 - 			const BoxRec *box,
772.32041 - 			int coverage)
772.32042 - {
772.32043 --	pixman_region16_t region;
772.32044 -+	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
772.32045 -+	const BoxRec *c;
772.32046 - 
772.32047 - 	__DBG(("%s: %d -> %d @ %f\n", __FUNCTION__, box->x1, box->x2,
772.32048 - 	       AREA_TO_ALPHA(coverage)));
772.32049 - 
772.32050 --	pixman_region_init_rects(&region, box, 1);
772.32051 --	RegionIntersect(&region, &region, clip);
772.32052 --	if (region_num_rects(&region)) {
772.32053 --		span_thread_add_boxes(sna, op,
772.32054 --				      region_rects(&region),
772.32055 --				      region_num_rects(&region),
772.32056 --				      AREA_TO_ALPHA(coverage));
772.32057 -+	b->clip_start =
772.32058 -+		find_clip_box_for_y(b->clip_start, b->clip_end, box->y1);
772.32059 -+
772.32060 -+	c = b->clip_start;
772.32061 -+	while (c != b->clip_end) {
772.32062 -+		BoxRec clipped;
772.32063 -+
772.32064 -+		if (box->y2 <= c->y1)
772.32065 -+			break;
772.32066 -+
772.32067 -+		clipped = *box;
772.32068 -+		if (!box_intersect(&clipped, c++))
772.32069 -+			continue;
772.32070 -+
772.32071 -+		span_thread_add_box(sna, op, &clipped, AREA_TO_ALPHA(coverage));
772.32072 - 	}
772.32073 --	pixman_region_fini(&region);
772.32074 - }
772.32075 - 
772.32076 - static span_func_t
772.32077 -@@ -1777,6 +1805,16 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
772.32078 - 	return span;
772.32079 - }
772.32080 - 
772.32081 -+inline static void
772.32082 -+span_thread_boxes_init(struct span_thread_boxes *boxes,
772.32083 -+		       const struct sna_composite_spans_op *op,
772.32084 -+		       const RegionRec *clip)
772.32085 -+{
772.32086 -+	boxes->op = op;
772.32087 -+	region_get_boxes(clip, &boxes->clip_start, &boxes->clip_end);
772.32088 -+	boxes->num_boxes = 0;
772.32089 -+}
772.32090 -+
772.32091 - static void
772.32092 - span_thread(void *arg)
772.32093 - {
772.32094 -@@ -1789,8 +1827,7 @@ span_thread(void *arg)
772.32095 - 	if (!tor_init(&tor, &thread->extents, 2*thread->ntrap))
772.32096 - 		return;
772.32097 - 
772.32098 --	boxes.op = thread->op;
772.32099 --	boxes.num_boxes = 0;
772.32100 -+	span_thread_boxes_init(&boxes, thread->op, thread->clip);
772.32101 - 
772.32102 - 	y1 = thread->extents.y1 - thread->draw_y;
772.32103 - 	y2 = thread->extents.y2 - thread->draw_y;
772.32104 -@@ -2190,6 +2227,52 @@ static void _tor_blt_src(struct inplace *in, const BoxRec *box, uint8_t v)
772.32105 - 	} while (--h);
772.32106 - }
772.32107 - 
772.32108 -+struct clipped_span {
772.32109 -+	span_func_t span;
772.32110 -+	const BoxRec *clip_start, *clip_end;
772.32111 -+};
772.32112 -+
772.32113 -+static void
772.32114 -+tor_blt_clipped(struct sna *sna,
772.32115 -+		struct sna_composite_spans_op *op,
772.32116 -+		pixman_region16_t *clip,
772.32117 -+		const BoxRec *box,
772.32118 -+		int coverage)
772.32119 -+{
772.32120 -+	struct clipped_span *cs = (struct clipped_span *)clip;
772.32121 -+	const BoxRec *c;
772.32122 -+
772.32123 -+	cs->clip_start =
772.32124 -+		find_clip_box_for_y(cs->clip_start, cs->clip_end, box->y1);
772.32125 -+
772.32126 -+	c = cs->clip_start;
772.32127 -+	while (c != cs->clip_end) {
772.32128 -+		BoxRec clipped;
772.32129 -+
772.32130 -+		if (box->y2 <= c->y1)
772.32131 -+			break;
772.32132 -+
772.32133 -+		clipped = *box;
772.32134 -+		if (!box_intersect(&clipped, c++))
772.32135 -+			continue;
772.32136 -+
772.32137 -+		cs->span(sna, op, NULL, &clipped, coverage);
772.32138 -+	}
772.32139 -+}
772.32140 -+
772.32141 -+inline static span_func_t
772.32142 -+clipped_span(struct clipped_span *cs,
772.32143 -+	     span_func_t span,
772.32144 -+	     const RegionRec *clip)
772.32145 -+{
772.32146 -+	if (clip->data) {
772.32147 -+		cs->span = span;
772.32148 -+		region_get_boxes(clip, &cs->clip_start, &cs->clip_end);
772.32149 -+		span = tor_blt_clipped;
772.32150 -+	}
772.32151 -+	return span;
772.32152 -+}
772.32153 -+
772.32154 - static void
772.32155 - tor_blt_src(struct sna *sna,
772.32156 - 	    struct sna_composite_spans_op *op,
772.32157 -@@ -2203,25 +2286,6 @@ tor_blt_src(struct sna *sna,
772.32158 - }
772.32159 - 
772.32160 - static void
772.32161 --tor_blt_src_clipped(struct sna *sna,
772.32162 --		    struct sna_composite_spans_op *op,
772.32163 --		    pixman_region16_t *clip,
772.32164 --		    const BoxRec *box,
772.32165 --		    int coverage)
772.32166 --{
772.32167 --	pixman_region16_t region;
772.32168 --	int n;
772.32169 --
772.32170 --	pixman_region_init_rects(&region, box, 1);
772.32171 --	RegionIntersect(&region, &region, clip);
772.32172 --	n = region_num_rects(&region);
772.32173 --	box = region_rects(&region);
772.32174 --	while (n--)
772.32175 --		tor_blt_src(sna, op, NULL, box++, coverage);
772.32176 --	pixman_region_fini(&region);
772.32177 --}
772.32178 --
772.32179 --static void
772.32180 - tor_blt_in(struct sna *sna,
772.32181 - 	   struct sna_composite_spans_op *op,
772.32182 - 	   pixman_region16_t *clip,
772.32183 -@@ -2253,25 +2317,6 @@ tor_blt_in(struct sna *sna,
772.32184 - }
772.32185 - 
772.32186 - static void
772.32187 --tor_blt_in_clipped(struct sna *sna,
772.32188 --		   struct sna_composite_spans_op *op,
772.32189 --		   pixman_region16_t *clip,
772.32190 --		   const BoxRec *box,
772.32191 --		   int coverage)
772.32192 --{
772.32193 --	pixman_region16_t region;
772.32194 --	int n;
772.32195 --
772.32196 --	pixman_region_init_rects(&region, box, 1);
772.32197 --	RegionIntersect(&region, &region, clip);
772.32198 --	n = region_num_rects(&region);
772.32199 --	box = region_rects(&region);
772.32200 --	while (n--)
772.32201 --		tor_blt_in(sna, op, NULL, box++, coverage);
772.32202 --	pixman_region_fini(&region);
772.32203 --}
772.32204 --
772.32205 --static void
772.32206 - tor_blt_add(struct sna *sna,
772.32207 - 	    struct sna_composite_spans_op *op,
772.32208 - 	    pixman_region16_t *clip,
772.32209 -@@ -2310,25 +2355,6 @@ tor_blt_add(struct sna *sna,
772.32210 - }
772.32211 - 
772.32212 - static void
772.32213 --tor_blt_add_clipped(struct sna *sna,
772.32214 --		    struct sna_composite_spans_op *op,
772.32215 --		    pixman_region16_t *clip,
772.32216 --		    const BoxRec *box,
772.32217 --		    int coverage)
772.32218 --{
772.32219 --	pixman_region16_t region;
772.32220 --	int n;
772.32221 --
772.32222 --	pixman_region_init_rects(&region, box, 1);
772.32223 --	RegionIntersect(&region, &region, clip);
772.32224 --	n = region_num_rects(&region);
772.32225 --	box = region_rects(&region);
772.32226 --	while (n--)
772.32227 --		tor_blt_add(sna, op, NULL, box++, coverage);
772.32228 --	pixman_region_fini(&region);
772.32229 --}
772.32230 --
772.32231 --static void
772.32232 - tor_blt_lerp32(struct sna *sna,
772.32233 - 	       struct sna_composite_spans_op *op,
772.32234 - 	       pixman_region16_t *clip,
772.32235 -@@ -2343,6 +2369,7 @@ tor_blt_lerp32(struct sna *sna,
772.32236 - 	if (coverage == 0)
772.32237 - 		return;
772.32238 - 
772.32239 -+	sigtrap_assert_active();
772.32240 - 	ptr += box->y1 * stride + box->x1;
772.32241 - 
772.32242 - 	h = box->y2 - box->y1;
772.32243 -@@ -2383,25 +2410,6 @@ tor_blt_lerp32(struct sna *sna,
772.32244 - 	}
772.32245 - }
772.32246 - 
772.32247 --static void
772.32248 --tor_blt_lerp32_clipped(struct sna *sna,
772.32249 --		       struct sna_composite_spans_op *op,
772.32250 --		       pixman_region16_t *clip,
772.32251 --		       const BoxRec *box,
772.32252 --		       int coverage)
772.32253 --{
772.32254 --	pixman_region16_t region;
772.32255 --	int n;
772.32256 --
772.32257 --	pixman_region_init_rects(&region, box, 1);
772.32258 --	RegionIntersect(&region, &region, clip);
772.32259 --	n = region_num_rects(&region);
772.32260 --	box = region_rects(&region);
772.32261 --	while (n--)
772.32262 --		tor_blt_lerp32(sna, op, NULL, box++, coverage);
772.32263 --	pixman_region_fini(&region);
772.32264 --}
772.32265 --
772.32266 - struct pixman_inplace {
772.32267 - 	pixman_image_t *image, *source, *mask;
772.32268 - 	uint32_t color;
772.32269 -@@ -2431,24 +2439,6 @@ pixmask_span_solid(struct sna *sna,
772.32270 - 			       pi->dx + box->x1, pi->dy + box->y1,
772.32271 - 			       box->x2 - box->x1, box->y2 - box->y1);
772.32272 - }
772.32273 --static void
772.32274 --pixmask_span_solid__clipped(struct sna *sna,
772.32275 --			    struct sna_composite_spans_op *op,
772.32276 --			    pixman_region16_t *clip,
772.32277 --			    const BoxRec *box,
772.32278 --			    int coverage)
772.32279 --{
772.32280 --	pixman_region16_t region;
772.32281 --	int n;
772.32282 --
772.32283 --	pixman_region_init_rects(&region, box, 1);
772.32284 --	RegionIntersect(&region, &region, clip);
772.32285 --	n = region_num_rects(&region);
772.32286 --	box = region_rects(&region);
772.32287 --	while (n--)
772.32288 --		pixmask_span_solid(sna, op, NULL, box++, coverage);
772.32289 --	pixman_region_fini(&region);
772.32290 --}
772.32291 - 
772.32292 - static void
772.32293 - pixmask_span(struct sna *sna,
772.32294 -@@ -2471,24 +2461,6 @@ pixmask_span(struct sna *sna,
772.32295 - 			       pi->dx + box->x1, pi->dy + box->y1,
772.32296 - 			       box->x2 - box->x1, box->y2 - box->y1);
772.32297 - }
772.32298 --static void
772.32299 --pixmask_span__clipped(struct sna *sna,
772.32300 --		      struct sna_composite_spans_op *op,
772.32301 --		      pixman_region16_t *clip,
772.32302 --		      const BoxRec *box,
772.32303 --		      int coverage)
772.32304 --{
772.32305 --	pixman_region16_t region;
772.32306 --	int n;
772.32307 --
772.32308 --	pixman_region_init_rects(&region, box, 1);
772.32309 --	RegionIntersect(&region, &region, clip);
772.32310 --	n = region_num_rects(&region);
772.32311 --	box = region_rects(&region);
772.32312 --	while (n--)
772.32313 --		pixmask_span(sna, op, NULL, box++, coverage);
772.32314 --	pixman_region_fini(&region);
772.32315 --}
772.32316 - 
772.32317 - struct inplace_x8r8g8b8_thread {
772.32318 - 	xTrapezoid *traps;
772.32319 -@@ -2507,6 +2479,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.32320 - 	struct inplace_x8r8g8b8_thread *thread = arg;
772.32321 - 	struct tor tor;
772.32322 - 	span_func_t span;
772.32323 -+	struct clipped_span clipped;
772.32324 - 	RegionPtr clip;
772.32325 - 	int y1, y2, n;
772.32326 - 
772.32327 -@@ -2537,12 +2510,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.32328 - 		inplace.stride = pixmap->devKind;
772.32329 - 		inplace.color = thread->color;
772.32330 - 
772.32331 --		if (clip->data)
772.32332 --			span = tor_blt_lerp32_clipped;
772.32333 --		else
772.32334 --			span = tor_blt_lerp32;
772.32335 -+		span = clipped_span(&clipped, tor_blt_lerp32, clip);
772.32336 - 
772.32337 --		tor_render(NULL, &tor, (void*)&inplace, clip, span, false);
772.32338 -+		tor_render(NULL, &tor,
772.32339 -+			   (void*)&inplace, (void*)&clipped,
772.32340 -+			   span, false);
772.32341 - 	} else if (thread->is_solid) {
772.32342 - 		struct pixman_inplace pi;
772.32343 - 
772.32344 -@@ -2555,12 +2527,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.32345 - 						     1, 1, pi.bits, 0);
772.32346 - 		pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
772.32347 - 
772.32348 --		if (clip->data)
772.32349 --			span = pixmask_span_solid__clipped;
772.32350 --		else
772.32351 --			span = pixmask_span_solid;
772.32352 -+		span = clipped_span(&clipped, pixmask_span_solid, clip);
772.32353 - 
772.32354 --		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
772.32355 -+		tor_render(NULL, &tor,
772.32356 -+			   (void*)&pi, (void *)&clipped,
772.32357 -+			   span, false);
772.32358 - 
772.32359 - 		pixman_image_unref(pi.source);
772.32360 - 		pixman_image_unref(pi.image);
772.32361 -@@ -2579,12 +2550,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.32362 - 		pi.bits = pixman_image_get_data(pi.mask);
772.32363 - 		pi.op = thread->op;
772.32364 - 
772.32365 --		if (clip->data)
772.32366 --			span = pixmask_span__clipped;
772.32367 --		else
772.32368 --			span = pixmask_span;
772.32369 -+		span = clipped_span(&clipped, pixmask_span, clip);
772.32370 - 
772.32371 --		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
772.32372 -+		tor_render(NULL, &tor,
772.32373 -+			   (void*)&pi, (void *)&clipped,
772.32374 -+			   span, false);
772.32375 - 
772.32376 - 		pixman_image_unref(pi.mask);
772.32377 - 		pixman_image_unref(pi.source);
772.32378 -@@ -2698,6 +2668,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.32379 - 	if (num_threads == 1) {
772.32380 - 		struct tor tor;
772.32381 - 		span_func_t span;
772.32382 -+		struct clipped_span clipped;
772.32383 - 
772.32384 - 		if (!tor_init(&tor, &region.extents, 2*ntrap))
772.32385 - 			return true;
772.32386 -@@ -2723,17 +2694,15 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.32387 - 			inplace.stride = pixmap->devKind;
772.32388 - 			inplace.color = color;
772.32389 - 
772.32390 --			if (dst->pCompositeClip->data)
772.32391 --				span = tor_blt_lerp32_clipped;
772.32392 --			else
772.32393 --				span = tor_blt_lerp32;
772.32394 -+			span = clipped_span(&clipped, tor_blt_lerp32, dst->pCompositeClip);
772.32395 - 
772.32396 - 			DBG(("%s: render inplace op=%d, color=%08x\n",
772.32397 - 			     __FUNCTION__, op, color));
772.32398 - 
772.32399 - 			if (sigtrap_get() == 0) {
772.32400 --				tor_render(NULL, &tor, (void*)&inplace,
772.32401 --					   dst->pCompositeClip, span, false);
772.32402 -+				tor_render(NULL, &tor,
772.32403 -+					   (void*)&inplace, (void*)&clipped,
772.32404 -+					   span, false);
772.32405 - 				sigtrap_put();
772.32406 - 			}
772.32407 - 		} else if (is_solid) {
772.32408 -@@ -2748,15 +2717,12 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.32409 - 							     1, 1, pi.bits, 0);
772.32410 - 			pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
772.32411 - 
772.32412 --			if (dst->pCompositeClip->data)
772.32413 --				span = pixmask_span_solid__clipped;
772.32414 --			else
772.32415 --				span = pixmask_span_solid;
772.32416 -+			span = clipped_span(&clipped, pixmask_span_solid, dst->pCompositeClip);
772.32417 - 
772.32418 - 			if (sigtrap_get() == 0) {
772.32419 --				tor_render(NULL, &tor, (void*)&pi,
772.32420 --					   dst->pCompositeClip, span,
772.32421 --					   false);
772.32422 -+				tor_render(NULL, &tor,
772.32423 -+					   (void*)&pi, (void*)&clipped,
772.32424 -+					   span, false);
772.32425 - 				sigtrap_put();
772.32426 - 			}
772.32427 - 
772.32428 -@@ -2777,15 +2743,12 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.32429 - 			pi.bits = pixman_image_get_data(pi.mask);
772.32430 - 			pi.op = op;
772.32431 - 
772.32432 --			if (dst->pCompositeClip->data)
772.32433 --				span = pixmask_span__clipped;
772.32434 --			else
772.32435 --				span = pixmask_span;
772.32436 -+			span = clipped_span(&clipped, pixmask_span, dst->pCompositeClip);
772.32437 - 
772.32438 - 			if (sigtrap_get() == 0) {
772.32439 --				tor_render(NULL, &tor, (void*)&pi,
772.32440 --					   dst->pCompositeClip, span,
772.32441 --					   false);
772.32442 -+				tor_render(NULL, &tor,
772.32443 -+					   (void*)&pi, (void*)&clipped,
772.32444 -+					   span, false);
772.32445 - 				sigtrap_put();
772.32446 - 			}
772.32447 - 
772.32448 -@@ -2847,9 +2810,9 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.32449 - 
772.32450 - struct inplace_thread {
772.32451 - 	xTrapezoid *traps;
772.32452 --	RegionPtr clip;
772.32453 - 	span_func_t span;
772.32454 - 	struct inplace inplace;
772.32455 -+	struct clipped_span clipped;
772.32456 - 	BoxRec extents;
772.32457 - 	int dx, dy;
772.32458 - 	int draw_x, draw_y;
772.32459 -@@ -2874,8 +2837,9 @@ static void inplace_thread(void *arg)
772.32460 - 		tor_add_trapezoid(&tor, &thread->traps[n], thread->dx, thread->dy);
772.32461 - 	}
772.32462 - 
772.32463 --	tor_render(NULL, &tor, (void*)&thread->inplace,
772.32464 --		   thread->clip, thread->span, thread->unbounded);
772.32465 -+	tor_render(NULL, &tor,
772.32466 -+		   (void*)&thread->inplace, (void*)&thread->clipped,
772.32467 -+		   thread->span, thread->unbounded);
772.32468 - 
772.32469 - 	tor_fini(&tor);
772.32470 - }
772.32471 -@@ -2889,6 +2853,7 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
772.32472 - 				 bool fallback)
772.32473 - {
772.32474 - 	struct inplace inplace;
772.32475 -+	struct clipped_span clipped;
772.32476 - 	span_func_t span;
772.32477 - 	PixmapPtr pixmap;
772.32478 - 	struct sna_pixmap *priv;
772.32479 -@@ -3005,21 +2970,12 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
772.32480 - 	     region.extents.x2, region.extents.y2));
772.32481 - 
772.32482 - 	if (op == PictOpSrc) {
772.32483 --		if (dst->pCompositeClip->data)
772.32484 --			span = tor_blt_src_clipped;
772.32485 --		else
772.32486 --			span = tor_blt_src;
772.32487 -+		span = tor_blt_src;
772.32488 - 	} else if (op == PictOpIn) {
772.32489 --		if (dst->pCompositeClip->data)
772.32490 --			span = tor_blt_in_clipped;
772.32491 --		else
772.32492 --			span = tor_blt_in;
772.32493 -+		span = tor_blt_in;
772.32494 - 	} else {
772.32495 - 		assert(op == PictOpAdd);
772.32496 --		if (dst->pCompositeClip->data)
772.32497 --			span = tor_blt_add_clipped;
772.32498 --		else
772.32499 --			span = tor_blt_add;
772.32500 -+		span = tor_blt_add;
772.32501 - 	}
772.32502 - 
772.32503 - 	DBG(("%s: move-to-cpu\n", __FUNCTION__));
772.32504 -@@ -3037,6 +2993,8 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
772.32505 - 	inplace.stride = pixmap->devKind;
772.32506 - 	inplace.opacity = color >> 24;
772.32507 - 
772.32508 -+	span = clipped_span(&clipped, span, dst->pCompositeClip);
772.32509 -+
772.32510 - 	num_threads = 1;
772.32511 - 	if ((flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
772.32512 - 		num_threads = sna_use_threads(region.extents.x2 - region.extents.x1,
772.32513 -@@ -3057,8 +3015,9 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
772.32514 - 		}
772.32515 - 
772.32516 - 		if (sigtrap_get() == 0) {
772.32517 --			tor_render(NULL, &tor, (void*)&inplace,
772.32518 --				   dst->pCompositeClip, span, unbounded);
772.32519 -+			tor_render(NULL, &tor,
772.32520 -+				   (void*)&inplace, (void *)&clipped,
772.32521 -+				   span, unbounded);
772.32522 - 			sigtrap_put();
772.32523 - 		}
772.32524 - 
772.32525 -@@ -3075,8 +3034,8 @@ imprecise_trapezoid_span_inplace(struct sna *sna,
772.32526 - 		threads[0].traps = traps;
772.32527 - 		threads[0].ntrap = ntrap;
772.32528 - 		threads[0].inplace = inplace;
772.32529 -+		threads[0].clipped = clipped;
772.32530 - 		threads[0].extents = region.extents;
772.32531 --		threads[0].clip = dst->pCompositeClip;
772.32532 - 		threads[0].span = span;
772.32533 - 		threads[0].unbounded = unbounded;
772.32534 - 		threads[0].dx = dx;
772.32535 -@@ -3707,8 +3666,7 @@ tristrip_thread(void *arg)
772.32536 - 	if (!tor_init(&tor, &thread->extents, 2*thread->count))
772.32537 - 		return;
772.32538 - 
772.32539 --	boxes.op = thread->op;
772.32540 --	boxes.num_boxes = 0;
772.32541 -+	span_thread_boxes_init(&boxes, thread->op, thread->clip);
772.32542 - 
772.32543 - 	cw = 0; ccw = 1;
772.32544 - 	polygon_add_line(tor.polygon,
772.32545 -@@ -3874,7 +3832,7 @@ imprecise_tristrip_span_converter(struct sna *sna,
772.32546 - 				break;
772.32547 - 		} while (1);
772.32548 - 		polygon_add_line(tor.polygon,
772.32549 --				 &points[cw], &points[2+ccw],
772.32550 -+				 &points[cw], &points[ccw],
772.32551 - 				 dx, dy);
772.32552 - 		assert(tor.polygon->num_edges <= 2*count);
772.32553 - 
772.32554 -diff --git a/src/sna/sna_trapezoids_mono.c b/src/sna/sna_trapezoids_mono.c
772.32555 -index 808703a9..07a7867d 100644
772.32556 ---- a/src/sna/sna_trapezoids_mono.c
772.32557 -+++ b/src/sna/sna_trapezoids_mono.c
772.32558 -@@ -72,13 +72,14 @@ struct mono {
772.32559 - 	struct sna *sna;
772.32560 - 	struct sna_composite_op op;
772.32561 - 	pixman_region16_t clip;
772.32562 -+	const BoxRec *clip_start, *clip_end;
772.32563 - 
772.32564 - 	fastcall void (*span)(struct mono *, int, int, BoxPtr);
772.32565 - 
772.32566 - 	struct mono_polygon polygon;
772.32567 - };
772.32568 - 
772.32569 --#define I(x) pixman_fixed_to_int ((x) + pixman_fixed_1_minus_e/2)
772.32570 -+#define I(x) pixman_fixed_to_int((x) + pixman_fixed_1_minus_e/2)
772.32571 - 
772.32572 - static struct quorem
772.32573 - floored_muldivrem(int32_t x, int32_t a, int32_t b)
772.32574 -@@ -249,22 +250,22 @@ mono_add_line(struct mono *mono,
772.32575 - 
772.32576 - 		e->dxdy = floored_muldivrem(dx, pixman_fixed_1, dy);
772.32577 - 
772.32578 --		e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1_minus_e/2 - p1->y,
772.32579 -+		e->x = floored_muldivrem((ytop - dst_y) * pixman_fixed_1 + pixman_fixed_1/2 - p1->y,
772.32580 - 					 dx, dy);
772.32581 - 		e->x.quo += p1->x;
772.32582 - 		e->x.rem -= dy;
772.32583 - 
772.32584 - 		e->dy = dy;
772.32585 --
772.32586 --		__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
772.32587 --		       __FUNCTION__,
772.32588 --		       I(e->x.quo), e->x.quo, e->x.rem, e->dy,
772.32589 --		       e->dxdy.quo, e->dxdy.rem, e->dy));
772.32590 - 	}
772.32591 - 	e->x.quo += dst_x*pixman_fixed_1;
772.32592 -+	__DBG(("%s: initial x=%d [%d.%d/%d] + dxdy=%d.%d/%d\n",
772.32593 -+	       __FUNCTION__,
772.32594 -+	       I(e->x.quo), e->x.quo, e->x.rem, e->dy,
772.32595 -+	       e->dxdy.quo, e->dxdy.rem, e->dy));
772.32596 - 
772.32597 - 	{
772.32598 - 		struct mono_edge **ptail = &polygon->y_buckets[ytop - mono->clip.extents.y1];
772.32599 -+		assert(ytop - mono->clip.extents.y1 < mono->clip.extents.y2 - mono->clip.extents.y1);
772.32600 - 		if (*ptail)
772.32601 - 			(*ptail)->prev = e;
772.32602 - 		e->next = *ptail;
772.32603 -@@ -368,6 +369,10 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
772.32604 - 		    e->x.rem == n->x.rem &&
772.32605 - 		    e->dxdy.quo == n->dxdy.quo &&
772.32606 - 		    e->dxdy.rem == n->dxdy.rem) {
772.32607 -+			assert(e->dy == n->dy);
772.32608 -+			__DBG(("%s: discarding cancellation pair (%d.%d) + (%d.%d)\n",
772.32609 -+			       __FUNCTION__, e->x.quo, e->x.rem, e->dxdy.quo, e->dxdy.rem));
772.32610 -+
772.32611 - 			if (e->prev)
772.32612 - 				e->prev->next = n->next;
772.32613 - 			else
772.32614 -@@ -378,8 +383,11 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
772.32615 - 				break;
772.32616 - 
772.32617 - 			e = n->next;
772.32618 --		} else
772.32619 -+		} else {
772.32620 -+			__DBG(("%s: adding edge (%d.%d) + (%d.%d)/%d, height=%d\n",
772.32621 -+			       __FUNCTION__, n->x.quo, n->x.rem, n->dxdy.quo, n->dxdy.rem, n->dy, n->height_left));
772.32622 - 			e = n;
772.32623 -+		}
772.32624 - 	}
772.32625 - 
772.32626 - 	return edges;
772.32627 -@@ -474,6 +482,34 @@ mono_span__fast(struct mono *c, int x1, int x2, BoxPtr box)
772.32628 - 	c->op.box(c->sna, &c->op, box);
772.32629 - }
772.32630 - 
772.32631 -+fastcall static void
772.32632 -+mono_span__clipped(struct mono *c, int x1, int x2, BoxPtr box)
772.32633 -+{
772.32634 -+	const BoxRec *b;
772.32635 -+
772.32636 -+	__DBG(("%s [%d, %d]\n", __FUNCTION__, x1, x2));
772.32637 -+
772.32638 -+	c->clip_start =
772.32639 -+		find_clip_box_for_y(c->clip_start, c->clip_end, box->y1);
772.32640 -+
772.32641 -+	b = c->clip_start;
772.32642 -+	while (b != c->clip_end) {
772.32643 -+		BoxRec clipped;
772.32644 -+
772.32645 -+		if (box->y2 <= b->y1)
772.32646 -+			break;
772.32647 -+
772.32648 -+		clipped.x1 = x1;
772.32649 -+		clipped.x2 = x2;
772.32650 -+		clipped.y1 = box->y1;
772.32651 -+		clipped.y2 = box->y2;
772.32652 -+		if (!box_intersect(&clipped, b++))
772.32653 -+			continue;
772.32654 -+
772.32655 -+		c->op.box(c->sna, &c->op, &clipped);
772.32656 -+	}
772.32657 -+}
772.32658 -+
772.32659 - struct mono_span_thread_boxes {
772.32660 - 	const struct sna_composite_op *op;
772.32661 - #define MONO_SPAN_MAX_BOXES (8192/sizeof(BoxRec))
772.32662 -@@ -482,40 +518,45 @@ struct mono_span_thread_boxes {
772.32663 - };
772.32664 - 
772.32665 - inline static void
772.32666 --thread_mono_span_add_boxes(struct mono *c, const BoxRec *box, int count)
772.32667 -+thread_mono_span_add_box(struct mono *c, const BoxRec *box)
772.32668 - {
772.32669 - 	struct mono_span_thread_boxes *b = c->op.priv;
772.32670 - 
772.32671 --	assert(count > 0 && count <= MONO_SPAN_MAX_BOXES);
772.32672 --	if (unlikely(b->num_boxes + count > MONO_SPAN_MAX_BOXES)) {
772.32673 -+	if (unlikely(b->num_boxes == MONO_SPAN_MAX_BOXES)) {
772.32674 - 		b->op->thread_boxes(c->sna, b->op, b->boxes, b->num_boxes);
772.32675 - 		b->num_boxes = 0;
772.32676 - 	}
772.32677 - 
772.32678 --	memcpy(b->boxes + b->num_boxes, box, count*sizeof(BoxRec));
772.32679 --	b->num_boxes += count;
772.32680 -+	b->boxes[b->num_boxes++] = *box;
772.32681 - 	assert(b->num_boxes <= MONO_SPAN_MAX_BOXES);
772.32682 - }
772.32683 - 
772.32684 - fastcall static void
772.32685 - thread_mono_span_clipped(struct mono *c, int x1, int x2, BoxPtr box)
772.32686 - {
772.32687 --	pixman_region16_t region;
772.32688 -+	const BoxRec *b;
772.32689 - 
772.32690 - 	__DBG(("%s [%d, %d]\n", __FUNCTION__, x1, x2));
772.32691 - 
772.32692 --	box->x1 = x1;
772.32693 --	box->x2 = x2;
772.32694 -+	c->clip_start =
772.32695 -+		find_clip_box_for_y(c->clip_start, c->clip_end, box->y1);
772.32696 - 
772.32697 --	assert(c->clip.data);
772.32698 -+	b = c->clip_start;
772.32699 -+	while (b != c->clip_end) {
772.32700 -+		BoxRec clipped;
772.32701 -+
772.32702 -+		if (box->y2 <= b->y1)
772.32703 -+			break;
772.32704 -+
772.32705 -+		clipped.x1 = x1;
772.32706 -+		clipped.x2 = x2;
772.32707 -+		clipped.y1 = box->y1;
772.32708 -+		clipped.y2 = box->y2;
772.32709 -+		if (!box_intersect(&clipped, b++))
772.32710 -+			continue;
772.32711 - 
772.32712 --	pixman_region_init_rects(&region, box, 1);
772.32713 --	RegionIntersect(&region, &region, &c->clip);
772.32714 --	if (region_num_rects(&region))
772.32715 --		thread_mono_span_add_boxes(c,
772.32716 --					   region_rects(&region),
772.32717 --					   region_num_rects(&region));
772.32718 --	pixman_region_fini(&region);
772.32719 -+		thread_mono_span_add_box(c, &clipped);
772.32720 -+	}
772.32721 - }
772.32722 - 
772.32723 - fastcall static void
772.32724 -@@ -525,7 +566,7 @@ thread_mono_span(struct mono *c, int x1, int x2, BoxPtr box)
772.32725 - 
772.32726 - 	box->x1 = x1;
772.32727 - 	box->x2 = x2;
772.32728 --	thread_mono_span_add_boxes(c, box, 1);
772.32729 -+	thread_mono_span_add_box(c, box);
772.32730 - }
772.32731 - 
772.32732 - inline static void
772.32733 -@@ -537,6 +578,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
772.32734 - 	int winding = 0;
772.32735 - 	BoxRec box;
772.32736 - 
772.32737 -+	__DBG(("%s: y=%d, h=%d\n", __FUNCTION__, y, h));
772.32738 -+
772.32739 - 	DBG_MONO_EDGES(edge);
772.32740 - 	VALIDATE_MONO_EDGES(&c->head);
772.32741 - 
772.32742 -@@ -547,6 +590,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
772.32743 - 		struct mono_edge *next = edge->next;
772.32744 - 		int16_t xend = I(edge->x.quo);
772.32745 - 
772.32746 -+		__DBG(("%s: adding edge dir=%d [winding=%d], x=%d [%d]\n",
772.32747 -+		       __FUNCTION__, edge->dir, winding + edge->dir, xend, edge->x.quo));
772.32748 - 		if (--edge->height_left) {
772.32749 - 			if (edge->dy) {
772.32750 - 				edge->x.quo += edge->dxdy.quo;
772.32751 -@@ -555,6 +600,8 @@ mono_row(struct mono *c, int16_t y, int16_t h)
772.32752 - 					++edge->x.quo;
772.32753 - 					edge->x.rem -= edge->dy;
772.32754 - 				}
772.32755 -+				__DBG(("%s: stepped edge (%d.%d) + (%d.%d)/%d, height=%d, prev_x=%d\n",
772.32756 -+				       __FUNCTION__, edge->x.quo, edge->x.rem, edge->dxdy.quo, edge->dxdy.rem, edge->dy, edge->height_left, edge->x.quo));
772.32757 - 			}
772.32758 - 
772.32759 - 			if (edge->x.quo < prev_x) {
772.32760 -@@ -578,17 +625,22 @@ mono_row(struct mono *c, int16_t y, int16_t h)
772.32761 - 		winding += edge->dir;
772.32762 - 		if (winding == 0) {
772.32763 - 			assert(I(next->x.quo) >= xend);
772.32764 --			if (I(next->x.quo) > xend + 1) {
772.32765 -+			if (I(next->x.quo) > xend) {
772.32766 -+				__DBG(("%s: end span: %d\n", __FUNCTION__, xend));
772.32767 - 				if (xstart < c->clip.extents.x1)
772.32768 - 					xstart = c->clip.extents.x1;
772.32769 - 				if (xend > c->clip.extents.x2)
772.32770 - 					xend = c->clip.extents.x2;
772.32771 --				if (xend > xstart)
772.32772 -+				if (xend > xstart) {
772.32773 -+					__DBG(("%s: emit span [%d, %d]\n", __FUNCTION__, xstart, xend));
772.32774 - 					c->span(c, xstart, xend, &box);
772.32775 -+				}
772.32776 - 				xstart = INT16_MIN;
772.32777 - 			}
772.32778 --		} else if (xstart == INT16_MIN)
772.32779 -+		} else if (xstart == INT16_MIN) {
772.32780 -+			__DBG(("%s: starting new span: %d\n", __FUNCTION__, xend));
772.32781 - 			xstart = xend;
772.32782 -+		}
772.32783 - 
772.32784 - 		edge = next;
772.32785 - 	}
772.32786 -@@ -650,9 +702,14 @@ mono_render(struct mono *mono)
772.32787 - 	for (i = 0; i < h; i = j) {
772.32788 - 		j = i + 1;
772.32789 - 
772.32790 -+		__DBG(("%s: row=%d, new edges? %d\n", __FUNCTION__,
772.32791 -+		       i, polygon->y_buckets[i] != NULL));
772.32792 -+
772.32793 - 		if (polygon->y_buckets[i])
772.32794 - 			mono_merge_edges(mono, polygon->y_buckets[i]);
772.32795 - 
772.32796 -+		__DBG(("%s: row=%d, vertical? %d\n", __FUNCTION__,
772.32797 -+		       i, mono->is_vertical));
772.32798 - 		if (mono->is_vertical) {
772.32799 - 			struct mono_edge *e = mono->head.next;
772.32800 - 			int min_height = h - i;
772.32801 -@@ -667,6 +724,7 @@ mono_render(struct mono *mono)
772.32802 - 				j++;
772.32803 - 			if (j != i + 1)
772.32804 - 				mono_step_edges(mono, j - (i + 1));
772.32805 -+			__DBG(("%s: %d vertical rows\n", __FUNCTION__, j-i));
772.32806 - 		}
772.32807 - 
772.32808 - 		mono_row(mono, i, j-i);
772.32809 -@@ -717,6 +775,7 @@ mono_span_thread(void *arg)
772.32810 - 		if (RegionNil(&mono.clip))
772.32811 - 			return;
772.32812 - 	}
772.32813 -+	region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
772.32814 - 
772.32815 - 	boxes.op = thread->op;
772.32816 - 	boxes.num_boxes = 0;
772.32817 -@@ -891,9 +950,12 @@ mono_trapezoids_span_converter(struct sna *sna,
772.32818 - 
772.32819 - 	if (mono.clip.data == NULL && mono.op.damage == NULL)
772.32820 - 		mono.span = mono_span__fast;
772.32821 -+	else if (mono.clip.data != NULL && mono.op.damage == NULL)
772.32822 -+		mono.span = mono_span__clipped;
772.32823 - 	else
772.32824 - 		mono.span = mono_span;
772.32825 - 
772.32826 -+	region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
772.32827 - 	mono_render(&mono);
772.32828 - 	mono.op.done(mono.sna, &mono.op);
772.32829 - 	mono_fini(&mono);
772.32830 -@@ -939,6 +1001,7 @@ mono_trapezoids_span_converter(struct sna *sna,
772.32831 - 					       mono.clip.extents.x2 - mono.clip.extents.x1,
772.32832 - 					       mono.clip.extents.y2 - mono.clip.extents.y1,
772.32833 - 					       COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
772.32834 -+			region_get_boxes(&mono.clip, &mono.clip_start, &mono.clip_end);
772.32835 - 			mono_render(&mono);
772.32836 - 			mono.op.done(mono.sna, &mono.op);
772.32837 - 		}
772.32838 -@@ -974,6 +1037,7 @@ mono_inplace_fill_box(struct sna *sna,
772.32839 - 	     box->x2 - box->x1,
772.32840 - 	     box->y2 - box->y1,
772.32841 - 	     fill->color));
772.32842 -+	sigtrap_assert_active();
772.32843 - 	pixman_fill(fill->data, fill->stride, fill->bpp,
772.32844 - 		    box->x1, box->y1,
772.32845 - 		    box->x2 - box->x1,
772.32846 -@@ -995,6 +1059,7 @@ mono_inplace_fill_boxes(struct sna *sna,
772.32847 - 		     box->x2 - box->x1,
772.32848 - 		     box->y2 - box->y1,
772.32849 - 		     fill->color));
772.32850 -+		sigtrap_assert_active();
772.32851 - 		pixman_fill(fill->data, fill->stride, fill->bpp,
772.32852 - 			    box->x1, box->y1,
772.32853 - 			    box->x2 - box->x1,
772.32854 -@@ -1382,10 +1447,13 @@ mono_triangles_span_converter(struct sna *sna,
772.32855 - 		mono_render(&mono);
772.32856 - 		mono.op.done(mono.sna, &mono.op);
772.32857 - 	}
772.32858 -+	mono_fini(&mono);
772.32859 - 
772.32860 - 	if (!was_clear && !operator_is_bounded(op)) {
772.32861 - 		xPointFixed p1, p2;
772.32862 - 
772.32863 -+		DBG(("%s: performing unbounded clear\n", __FUNCTION__));
772.32864 -+
772.32865 - 		if (!mono_init(&mono, 2+3*count))
772.32866 - 			return false;
772.32867 - 
772.32868 -@@ -1431,7 +1499,6 @@ mono_triangles_span_converter(struct sna *sna,
772.32869 - 		mono_fini(&mono);
772.32870 - 	}
772.32871 - 
772.32872 --	mono_fini(&mono);
772.32873 - 	REGION_UNINIT(NULL, &mono.clip);
772.32874 - 	return true;
772.32875 - }
772.32876 -diff --git a/src/sna/sna_trapezoids_precise.c b/src/sna/sna_trapezoids_precise.c
772.32877 -index 9187ab48..242b4acb 100644
772.32878 ---- a/src/sna/sna_trapezoids_precise.c
772.32879 -+++ b/src/sna/sna_trapezoids_precise.c
772.32880 -@@ -1023,6 +1023,16 @@ tor_init(struct tor *converter, const BoxRec *box, int num_edges)
772.32881 - static void
772.32882 - tor_add_trapezoid(struct tor *tor, const xTrapezoid *t, int dx, int dy)
772.32883 - {
772.32884 -+	if (!xTrapezoidValid(t)) {
772.32885 -+		__DBG(("%s: skipping invalid trapezoid: top=%d, bottom=%d, left=(%d, %d), (%d, %d), right=(%d, %d), (%d, %d)\n",
772.32886 -+		       __FUNCTION__,
772.32887 -+		       t->top, t->bottom,
772.32888 -+		       t->left.p1.x, t->left.p1.y,
772.32889 -+		       t->left.p2.x, t->left.p2.y,
772.32890 -+		       t->right.p1.x, t->right.p1.y,
772.32891 -+		       t->right.p2.x, t->right.p2.y));
772.32892 -+		return;
772.32893 -+	}
772.32894 - 	polygon_add_edge(tor->polygon, t, &t->left, 1, dx, dy);
772.32895 - 	polygon_add_edge(tor->polygon, t, &t->right, -1, dx, dy);
772.32896 - }
772.32897 -@@ -1635,31 +1645,27 @@ struct span_thread {
772.32898 - #define SPAN_THREAD_MAX_BOXES (8192/sizeof(struct sna_opacity_box))
772.32899 - struct span_thread_boxes {
772.32900 - 	const struct sna_composite_spans_op *op;
772.32901 -+	const BoxRec *clip_start, *clip_end;
772.32902 - 	int num_boxes;
772.32903 - 	struct sna_opacity_box boxes[SPAN_THREAD_MAX_BOXES];
772.32904 - };
772.32905 - 
772.32906 --static void span_thread_add_boxes(struct sna *sna, void *data,
772.32907 --				  const BoxRec *box, int count, float alpha)
772.32908 -+static void span_thread_add_box(struct sna *sna, void *data,
772.32909 -+				const BoxRec *box, float alpha)
772.32910 - {
772.32911 - 	struct span_thread_boxes *b = data;
772.32912 - 
772.32913 --	__DBG(("%s: adding %d boxes with alpha=%f\n",
772.32914 --	       __FUNCTION__, count, alpha));
772.32915 -+	__DBG(("%s: adding box with alpha=%f\n", __FUNCTION__, alpha));
772.32916 - 
772.32917 --	assert(count > 0 && count <= SPAN_THREAD_MAX_BOXES);
772.32918 --	if (unlikely(b->num_boxes + count > SPAN_THREAD_MAX_BOXES)) {
772.32919 --		DBG(("%s: flushing %d boxes, adding %d\n", __FUNCTION__, b->num_boxes, count));
772.32920 --		assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
772.32921 -+	if (unlikely(b->num_boxes == SPAN_THREAD_MAX_BOXES)) {
772.32922 -+		DBG(("%s: flushing %d boxes\n", __FUNCTION__, b->num_boxes));
772.32923 - 		b->op->thread_boxes(sna, b->op, b->boxes, b->num_boxes);
772.32924 - 		b->num_boxes = 0;
772.32925 - 	}
772.32926 - 
772.32927 --	do {
772.32928 --		b->boxes[b->num_boxes].box = *box++;
772.32929 --		b->boxes[b->num_boxes].alpha = alpha;
772.32930 --		b->num_boxes++;
772.32931 --	} while (--count);
772.32932 -+	b->boxes[b->num_boxes].box = *box++;
772.32933 -+	b->boxes[b->num_boxes].alpha = alpha;
772.32934 -+	b->num_boxes++;
772.32935 - 	assert(b->num_boxes <= SPAN_THREAD_MAX_BOXES);
772.32936 - }
772.32937 - 
772.32938 -@@ -1670,8 +1676,22 @@ span_thread_box(struct sna *sna,
772.32939 - 		const BoxRec *box,
772.32940 - 		int coverage)
772.32941 - {
772.32942 -+	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
772.32943 -+
772.32944 - 	__DBG(("%s: %d -> %d @ %d\n", __FUNCTION__, box->x1, box->x2, coverage));
772.32945 --	span_thread_add_boxes(sna, op, box, 1, AREA_TO_FLOAT(coverage));
772.32946 -+	if (b->num_boxes) {
772.32947 -+		struct sna_opacity_box *bb = &b->boxes[b->num_boxes-1];
772.32948 -+		if (bb->box.x1 == box->x1 &&
772.32949 -+		    bb->box.x2 == box->x2 &&
772.32950 -+		    bb->box.y2 == box->y1 &&
772.32951 -+		    bb->alpha == AREA_TO_FLOAT(coverage)) {
772.32952 -+			bb->box.y2 = box->y2;
772.32953 -+			__DBG(("%s: contracted double row: %d -> %d\n", __func__, bb->box.y1, bb->box.y2));
772.32954 -+			return;
772.32955 -+		}
772.32956 -+	}
772.32957 -+
772.32958 -+	span_thread_add_box(sna, op, box, AREA_TO_FLOAT(coverage));
772.32959 - }
772.32960 - 
772.32961 - static void
772.32962 -@@ -1681,20 +1701,28 @@ span_thread_clipped_box(struct sna *sna,
772.32963 - 			const BoxRec *box,
772.32964 - 			int coverage)
772.32965 - {
772.32966 --	pixman_region16_t region;
772.32967 -+	struct span_thread_boxes *b = (struct span_thread_boxes *)op;
772.32968 -+	const BoxRec *c;
772.32969 - 
772.32970 - 	__DBG(("%s: %d -> %d @ %f\n", __FUNCTION__, box->x1, box->x2,
772.32971 - 	       AREA_TO_FLOAT(coverage)));
772.32972 - 
772.32973 --	pixman_region_init_rects(&region, box, 1);
772.32974 --	RegionIntersect(&region, &region, clip);
772.32975 --	if (region_num_rects(&region)) {
772.32976 --		span_thread_add_boxes(sna, op,
772.32977 --				      region_rects(&region),
772.32978 --				      region_num_rects(&region),
772.32979 --				      AREA_TO_FLOAT(coverage));
772.32980 -+	b->clip_start =
772.32981 -+		find_clip_box_for_y(b->clip_start, b->clip_end, box->y1);
772.32982 -+
772.32983 -+	c = b->clip_start;
772.32984 -+	while (c != b->clip_end) {
772.32985 -+		BoxRec clipped;
772.32986 -+
772.32987 -+		if (box->y2 <= c->y1)
772.32988 -+			break;
772.32989 -+
772.32990 -+		clipped = *box;
772.32991 -+		if (!box_intersect(&clipped, c++))
772.32992 -+			continue;
772.32993 -+
772.32994 -+		span_thread_add_box(sna, op, &clipped, AREA_TO_FLOAT(coverage));
772.32995 - 	}
772.32996 --	pixman_region_fini(&region);
772.32997 - }
772.32998 - 
772.32999 - static span_func_t
772.33000 -@@ -1712,7 +1740,7 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
772.33001 - 
772.33002 - 	assert(!is_mono(dst, maskFormat));
772.33003 - 	assert(tmp->thread_boxes);
772.33004 --	DBG(("%s: clipped? %d\n", __FUNCTION__, clip->data != NULL));
772.33005 -+	DBG(("%s: clipped? %d x %d\n", __FUNCTION__, clip->data != NULL, region_num_rects(clip)));
772.33006 - 	if (clip->data)
772.33007 - 		span = span_thread_clipped_box;
772.33008 - 	else
772.33009 -@@ -1721,6 +1749,17 @@ thread_choose_span(struct sna_composite_spans_op *tmp,
772.33010 - 	return span;
772.33011 - }
772.33012 - 
772.33013 -+inline static void
772.33014 -+span_thread_boxes_init(struct span_thread_boxes *boxes,
772.33015 -+		       const struct sna_composite_spans_op *op,
772.33016 -+		       const RegionRec *clip)
772.33017 -+{
772.33018 -+	boxes->op = op;
772.33019 -+	boxes->clip_start = region_rects(clip);
772.33020 -+	boxes->clip_end = boxes->clip_start + region_num_rects(clip);
772.33021 -+	boxes->num_boxes = 0;
772.33022 -+}
772.33023 -+
772.33024 - static void
772.33025 - span_thread(void *arg)
772.33026 - {
772.33027 -@@ -1733,8 +1772,7 @@ span_thread(void *arg)
772.33028 - 	if (!tor_init(&tor, &thread->extents, 2*thread->ntrap))
772.33029 - 		return;
772.33030 - 
772.33031 --	boxes.op = thread->op;
772.33032 --	boxes.num_boxes = 0;
772.33033 -+	span_thread_boxes_init(&boxes, thread->op, thread->clip);
772.33034 - 
772.33035 - 	y1 = thread->extents.y1 - thread->draw_y;
772.33036 - 	y2 = thread->extents.y2 - thread->draw_y;
772.33037 -@@ -2183,6 +2221,52 @@ static force_inline uint8_t coverage_opacity(int coverage, uint8_t opacity)
772.33038 - 	return opacity == 255 ? coverage : mul_8_8(coverage, opacity);
772.33039 - }
772.33040 - 
772.33041 -+struct clipped_span {
772.33042 -+	span_func_t span;
772.33043 -+	const BoxRec *clip_start, *clip_end;
772.33044 -+};
772.33045 -+
772.33046 -+static void
772.33047 -+tor_blt_clipped(struct sna *sna,
772.33048 -+		struct sna_composite_spans_op *op,
772.33049 -+		pixman_region16_t *clip,
772.33050 -+		const BoxRec *box,
772.33051 -+		int coverage)
772.33052 -+{
772.33053 -+	struct clipped_span *cs = (struct clipped_span *)clip;
772.33054 -+	const BoxRec *c;
772.33055 -+
772.33056 -+	cs->clip_start =
772.33057 -+		find_clip_box_for_y(cs->clip_start, cs->clip_end, box->y1);
772.33058 -+
772.33059 -+	c = cs->clip_start;
772.33060 -+	while (c != cs->clip_end) {
772.33061 -+		BoxRec clipped;
772.33062 -+
772.33063 -+		if (box->y2 <= c->y1)
772.33064 -+			break;
772.33065 -+
772.33066 -+		clipped = *box;
772.33067 -+		if (!box_intersect(&clipped, c++))
772.33068 -+			continue;
772.33069 -+
772.33070 -+		cs->span(sna, op, NULL, &clipped, coverage);
772.33071 -+	}
772.33072 -+}
772.33073 -+
772.33074 -+inline static span_func_t
772.33075 -+clipped_span(struct clipped_span *cs,
772.33076 -+	     span_func_t span,
772.33077 -+	     const RegionRec *clip)
772.33078 -+{
772.33079 -+	if (clip->data) {
772.33080 -+		cs->span = span;
772.33081 -+		region_get_boxes(clip, &cs->clip_start, &cs->clip_end);
772.33082 -+		span = tor_blt_clipped;
772.33083 -+	}
772.33084 -+	return span;
772.33085 -+}
772.33086 -+
772.33087 - static void _tor_blt_src(struct inplace *in, const BoxRec *box, uint8_t v)
772.33088 - {
772.33089 - 	uint8_t *ptr = in->ptr;
772.33090 -@@ -2218,25 +2302,6 @@ tor_blt_src(struct sna *sna,
772.33091 - }
772.33092 - 
772.33093 - static void
772.33094 --tor_blt_src_clipped(struct sna *sna,
772.33095 --		    struct sna_composite_spans_op *op,
772.33096 --		    pixman_region16_t *clip,
772.33097 --		    const BoxRec *box,
772.33098 --		    int coverage)
772.33099 --{
772.33100 --	pixman_region16_t region;
772.33101 --	int n;
772.33102 --
772.33103 --	pixman_region_init_rects(&region, box, 1);
772.33104 --	RegionIntersect(&region, &region, clip);
772.33105 --	n = region_num_rects(&region);
772.33106 --	box = region_rects(&region);
772.33107 --	while (n--)
772.33108 --		tor_blt_src(sna, op, NULL, box++, coverage);
772.33109 --	pixman_region_fini(&region);
772.33110 --}
772.33111 --
772.33112 --static void
772.33113 - tor_blt_in(struct sna *sna,
772.33114 - 	   struct sna_composite_spans_op *op,
772.33115 - 	   pixman_region16_t *clip,
772.33116 -@@ -2268,25 +2333,6 @@ tor_blt_in(struct sna *sna,
772.33117 - }
772.33118 - 
772.33119 - static void
772.33120 --tor_blt_in_clipped(struct sna *sna,
772.33121 --		   struct sna_composite_spans_op *op,
772.33122 --		   pixman_region16_t *clip,
772.33123 --		   const BoxRec *box,
772.33124 --		   int coverage)
772.33125 --{
772.33126 --	pixman_region16_t region;
772.33127 --	int n;
772.33128 --
772.33129 --	pixman_region_init_rects(&region, box, 1);
772.33130 --	RegionIntersect(&region, &region, clip);
772.33131 --	n = region_num_rects(&region);
772.33132 --	box = region_rects(&region);
772.33133 --	while (n--)
772.33134 --		tor_blt_in(sna, op, NULL, box++, coverage);
772.33135 --	pixman_region_fini(&region);
772.33136 --}
772.33137 --
772.33138 --static void
772.33139 - tor_blt_add(struct sna *sna,
772.33140 - 	    struct sna_composite_spans_op *op,
772.33141 - 	    pixman_region16_t *clip,
772.33142 -@@ -2325,25 +2371,6 @@ tor_blt_add(struct sna *sna,
772.33143 - }
772.33144 - 
772.33145 - static void
772.33146 --tor_blt_add_clipped(struct sna *sna,
772.33147 --		    struct sna_composite_spans_op *op,
772.33148 --		    pixman_region16_t *clip,
772.33149 --		    const BoxRec *box,
772.33150 --		    int coverage)
772.33151 --{
772.33152 --	pixman_region16_t region;
772.33153 --	int n;
772.33154 --
772.33155 --	pixman_region_init_rects(&region, box, 1);
772.33156 --	RegionIntersect(&region, &region, clip);
772.33157 --	n = region_num_rects(&region);
772.33158 --	box = region_rects(&region);
772.33159 --	while (n--)
772.33160 --		tor_blt_add(sna, op, NULL, box++, coverage);
772.33161 --	pixman_region_fini(&region);
772.33162 --}
772.33163 --
772.33164 --static void
772.33165 - tor_blt_lerp32(struct sna *sna,
772.33166 - 	       struct sna_composite_spans_op *op,
772.33167 - 	       pixman_region16_t *clip,
772.33168 -@@ -2358,6 +2385,7 @@ tor_blt_lerp32(struct sna *sna,
772.33169 - 	if (coverage == 0)
772.33170 - 		return;
772.33171 - 
772.33172 -+	sigtrap_assert_active();
772.33173 - 	ptr += box->y1 * stride + box->x1;
772.33174 - 
772.33175 - 	h = box->y2 - box->y1;
772.33176 -@@ -2396,25 +2424,6 @@ tor_blt_lerp32(struct sna *sna,
772.33177 - 	}
772.33178 - }
772.33179 - 
772.33180 --static void
772.33181 --tor_blt_lerp32_clipped(struct sna *sna,
772.33182 --		       struct sna_composite_spans_op *op,
772.33183 --		       pixman_region16_t *clip,
772.33184 --		       const BoxRec *box,
772.33185 --		       int coverage)
772.33186 --{
772.33187 --	pixman_region16_t region;
772.33188 --	int n;
772.33189 --
772.33190 --	pixman_region_init_rects(&region, box, 1);
772.33191 --	RegionIntersect(&region, &region, clip);
772.33192 --	n = region_num_rects(&region);
772.33193 --	box = region_rects(&region);
772.33194 --	while (n--)
772.33195 --		tor_blt_lerp32(sna, op, NULL, box++, coverage);
772.33196 --	pixman_region_fini(&region);
772.33197 --}
772.33198 --
772.33199 - struct pixman_inplace {
772.33200 - 	pixman_image_t *image, *source, *mask;
772.33201 - 	uint32_t color;
772.33202 -@@ -2442,24 +2451,6 @@ pixmask_span_solid(struct sna *sna,
772.33203 - 			       pi->dx + box->x1, pi->dy + box->y1,
772.33204 - 			       box->x2 - box->x1, box->y2 - box->y1);
772.33205 - }
772.33206 --static void
772.33207 --pixmask_span_solid__clipped(struct sna *sna,
772.33208 --			    struct sna_composite_spans_op *op,
772.33209 --			    pixman_region16_t *clip,
772.33210 --			    const BoxRec *box,
772.33211 --			    int coverage)
772.33212 --{
772.33213 --	pixman_region16_t region;
772.33214 --	int n;
772.33215 --
772.33216 --	pixman_region_init_rects(&region, box, 1);
772.33217 --	RegionIntersect(&region, &region, clip);
772.33218 --	n = region_num_rects(&region);
772.33219 --	box = region_rects(&region);
772.33220 --	while (n--)
772.33221 --		pixmask_span_solid(sna, op, NULL, box++, coverage);
772.33222 --	pixman_region_fini(&region);
772.33223 --}
772.33224 - 
772.33225 - static void
772.33226 - pixmask_span(struct sna *sna,
772.33227 -@@ -2480,24 +2471,6 @@ pixmask_span(struct sna *sna,
772.33228 - 			       pi->dx + box->x1, pi->dy + box->y1,
772.33229 - 			       box->x2 - box->x1, box->y2 - box->y1);
772.33230 - }
772.33231 --static void
772.33232 --pixmask_span__clipped(struct sna *sna,
772.33233 --		      struct sna_composite_spans_op *op,
772.33234 --		      pixman_region16_t *clip,
772.33235 --		      const BoxRec *box,
772.33236 --		      int coverage)
772.33237 --{
772.33238 --	pixman_region16_t region;
772.33239 --	int n;
772.33240 --
772.33241 --	pixman_region_init_rects(&region, box, 1);
772.33242 --	RegionIntersect(&region, &region, clip);
772.33243 --	n = region_num_rects(&region);
772.33244 --	box = region_rects(&region);
772.33245 --	while (n--)
772.33246 --		pixmask_span(sna, op, NULL, box++, coverage);
772.33247 --	pixman_region_fini(&region);
772.33248 --}
772.33249 - 
772.33250 - struct inplace_x8r8g8b8_thread {
772.33251 - 	xTrapezoid *traps;
772.33252 -@@ -2516,6 +2489,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.33253 - 	struct inplace_x8r8g8b8_thread *thread = arg;
772.33254 - 	struct tor tor;
772.33255 - 	span_func_t span;
772.33256 -+	struct clipped_span clipped;
772.33257 - 	RegionPtr clip;
772.33258 - 	int y1, y2, n;
772.33259 - 
772.33260 -@@ -2546,12 +2520,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.33261 - 		inplace.stride = pixmap->devKind;
772.33262 - 		inplace.color = thread->color;
772.33263 - 
772.33264 --		if (clip->data)
772.33265 --			span = tor_blt_lerp32_clipped;
772.33266 --		else
772.33267 --			span = tor_blt_lerp32;
772.33268 -+		span = clipped_span(&clipped, tor_blt_lerp32, clip);
772.33269 - 
772.33270 --		tor_render(NULL, &tor, (void*)&inplace, clip, span, false);
772.33271 -+		tor_render(NULL, &tor,
772.33272 -+			   (void*)&inplace, (void *)&clipped,
772.33273 -+			   span, false);
772.33274 - 	} else if (thread->is_solid) {
772.33275 - 		struct pixman_inplace pi;
772.33276 - 
772.33277 -@@ -2564,10 +2537,7 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.33278 - 						     1, 1, pi.bits, 0);
772.33279 - 		pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
772.33280 - 
772.33281 --		if (clip->data)
772.33282 --			span = pixmask_span_solid__clipped;
772.33283 --		else
772.33284 --			span = pixmask_span_solid;
772.33285 -+		span = clipped_span(&clipped, pixmask_span_solid, clip);
772.33286 - 
772.33287 - 		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
772.33288 - 
772.33289 -@@ -2588,12 +2558,11 @@ static void inplace_x8r8g8b8_thread(void *arg)
772.33290 - 		pi.bits = pixman_image_get_data(pi.mask);
772.33291 - 		pi.op = thread->op;
772.33292 - 
772.33293 --		if (clip->data)
772.33294 --			span = pixmask_span__clipped;
772.33295 --		else
772.33296 --			span = pixmask_span;
772.33297 -+		span = clipped_span(&clipped, pixmask_span, clip);
772.33298 - 
772.33299 --		tor_render(NULL, &tor, (void*)&pi, clip, span, false);
772.33300 -+		tor_render(NULL, &tor,
772.33301 -+			   (void*)&pi, (void *)&clipped,
772.33302 -+			   span, false);
772.33303 - 
772.33304 - 		pixman_image_unref(pi.mask);
772.33305 - 		pixman_image_unref(pi.source);
772.33306 -@@ -2712,6 +2681,7 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.33307 - 	if (num_threads == 1) {
772.33308 - 		struct tor tor;
772.33309 - 		span_func_t span;
772.33310 -+		struct clipped_span clipped;
772.33311 - 
772.33312 - 		if (!tor_init(&tor, &region.extents, 2*ntrap))
772.33313 - 			return true;
772.33314 -@@ -2737,17 +2707,14 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.33315 - 			inplace.stride = pixmap->devKind;
772.33316 - 			inplace.color = color;
772.33317 - 
772.33318 --			if (dst->pCompositeClip->data)
772.33319 --				span = tor_blt_lerp32_clipped;
772.33320 --			else
772.33321 --				span = tor_blt_lerp32;
772.33322 --
772.33323 -+			span = clipped_span(&clipped, tor_blt_lerp32, dst->pCompositeClip);
772.33324 - 			DBG(("%s: render inplace op=%d, color=%08x\n",
772.33325 - 			     __FUNCTION__, op, color));
772.33326 - 
772.33327 - 			if (sigtrap_get() == 0) {
772.33328 --				tor_render(NULL, &tor, (void*)&inplace,
772.33329 --					   dst->pCompositeClip, span, false);
772.33330 -+				tor_render(NULL, &tor,
772.33331 -+					   (void*)&inplace, (void*)&clipped,
772.33332 -+					   span, false);
772.33333 - 				sigtrap_put();
772.33334 - 			}
772.33335 - 		} else if (is_solid) {
772.33336 -@@ -2762,15 +2729,11 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.33337 - 							     1, 1, pi.bits, 0);
772.33338 - 			pixman_image_set_repeat(pi.source, PIXMAN_REPEAT_NORMAL);
772.33339 - 
772.33340 --			if (dst->pCompositeClip->data)
772.33341 --				span = pixmask_span_solid__clipped;
772.33342 --			else
772.33343 --				span = pixmask_span_solid;
772.33344 --
772.33345 -+			span = clipped_span(&clipped, pixmask_span_solid, dst->pCompositeClip);
772.33346 - 			if (sigtrap_get() == 0) {
772.33347 --				tor_render(NULL, &tor, (void*)&pi,
772.33348 --					   dst->pCompositeClip, span,
772.33349 --					   false);
772.33350 -+				tor_render(NULL, &tor,
772.33351 -+					   (void*)&pi, (void*)&clipped,
772.33352 -+					    span, false);
772.33353 - 				sigtrap_put();
772.33354 - 			}
772.33355 - 
772.33356 -@@ -2791,15 +2754,11 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.33357 - 			pi.bits = pixman_image_get_data(pi.mask);
772.33358 - 			pi.op = op;
772.33359 - 
772.33360 --			if (dst->pCompositeClip->data)
772.33361 --				span = pixmask_span__clipped;
772.33362 --			else
772.33363 --				span = pixmask_span;
772.33364 --
772.33365 -+			span = clipped_span(&clipped, pixmask_span, dst->pCompositeClip);
772.33366 - 			if (sigtrap_get() == 0) {
772.33367 --				tor_render(NULL, &tor, (void*)&pi,
772.33368 --					   dst->pCompositeClip, span,
772.33369 --					   false);
772.33370 -+				tor_render(NULL, &tor,
772.33371 -+					   (void*)&pi, (void *)&clipped,
772.33372 -+					   span, false);
772.33373 - 				sigtrap_put();
772.33374 - 			}
772.33375 - 
772.33376 -@@ -2861,9 +2820,9 @@ trapezoid_span_inplace__x8r8g8b8(CARD8 op,
772.33377 - 
772.33378 - struct inplace_thread {
772.33379 - 	xTrapezoid *traps;
772.33380 --	RegionPtr clip;
772.33381 - 	span_func_t span;
772.33382 - 	struct inplace inplace;
772.33383 -+	struct clipped_span clipped;
772.33384 - 	BoxRec extents;
772.33385 - 	int dx, dy;
772.33386 - 	int draw_x, draw_y;
772.33387 -@@ -2888,8 +2847,9 @@ static void inplace_thread(void *arg)
772.33388 - 		tor_add_trapezoid(&tor, &thread->traps[n], thread->dx, thread->dy);
772.33389 - 	}
772.33390 - 
772.33391 --	tor_render(NULL, &tor, (void*)&thread->inplace,
772.33392 --		   thread->clip, thread->span, thread->unbounded);
772.33393 -+	tor_render(NULL, &tor, 
772.33394 -+		   (void*)&thread->inplace, (void*)&thread->clipped,
772.33395 -+		   thread->span, thread->unbounded);
772.33396 - 
772.33397 - 	tor_fini(&tor);
772.33398 - }
772.33399 -@@ -2903,6 +2863,7 @@ precise_trapezoid_span_inplace(struct sna *sna,
772.33400 - 			       bool fallback)
772.33401 - {
772.33402 - 	struct inplace inplace;
772.33403 -+	struct clipped_span clipped;
772.33404 - 	span_func_t span;
772.33405 - 	PixmapPtr pixmap;
772.33406 - 	struct sna_pixmap *priv;
772.33407 -@@ -3020,21 +2981,12 @@ precise_trapezoid_span_inplace(struct sna *sna,
772.33408 - 	     dst->pCompositeClip->data != NULL));
772.33409 - 
772.33410 - 	if (op == PictOpSrc) {
772.33411 --		if (dst->pCompositeClip->data)
772.33412 --			span = tor_blt_src_clipped;
772.33413 --		else
772.33414 --			span = tor_blt_src;
772.33415 -+		span = tor_blt_src;
772.33416 - 	} else if (op == PictOpIn) {
772.33417 --		if (dst->pCompositeClip->data)
772.33418 --			span = tor_blt_in_clipped;
772.33419 --		else
772.33420 --			span = tor_blt_in;
772.33421 -+		span = tor_blt_in;
772.33422 - 	} else {
772.33423 - 		assert(op == PictOpAdd);
772.33424 --		if (dst->pCompositeClip->data)
772.33425 --			span = tor_blt_add_clipped;
772.33426 --		else
772.33427 --			span = tor_blt_add;
772.33428 -+		span = tor_blt_add;
772.33429 - 	}
772.33430 - 
772.33431 - 	DBG(("%s: move-to-cpu(dst)\n", __FUNCTION__));
772.33432 -@@ -3052,6 +3004,8 @@ precise_trapezoid_span_inplace(struct sna *sna,
772.33433 - 	inplace.stride = pixmap->devKind;
772.33434 - 	inplace.opacity = color >> 24;
772.33435 - 
772.33436 -+	span = clipped_span(&clipped, span, dst->pCompositeClip);
772.33437 -+
772.33438 - 	num_threads = 1;
772.33439 - 	if (!NO_GPU_THREADS &&
772.33440 - 	    (flags & COMPOSITE_SPANS_RECTILINEAR) == 0)
772.33441 -@@ -3074,8 +3028,9 @@ precise_trapezoid_span_inplace(struct sna *sna,
772.33442 - 		}
772.33443 - 
772.33444 - 		if (sigtrap_get() == 0) {
772.33445 --			tor_render(NULL, &tor, (void*)&inplace,
772.33446 --				   dst->pCompositeClip, span, unbounded);
772.33447 -+			tor_render(NULL, &tor,
772.33448 -+				   (void*)&inplace, (void *)&clipped,
772.33449 -+				   span, unbounded);
772.33450 - 			sigtrap_put();
772.33451 - 		}
772.33452 - 
772.33453 -@@ -3093,7 +3048,7 @@ precise_trapezoid_span_inplace(struct sna *sna,
772.33454 - 		threads[0].ntrap = ntrap;
772.33455 - 		threads[0].inplace = inplace;
772.33456 - 		threads[0].extents = region.extents;
772.33457 --		threads[0].clip = dst->pCompositeClip;
772.33458 -+		threads[0].clipped = clipped;
772.33459 - 		threads[0].span = span;
772.33460 - 		threads[0].unbounded = unbounded;
772.33461 - 		threads[0].dx = dx;
772.33462 -@@ -3316,8 +3271,7 @@ tristrip_thread(void *arg)
772.33463 - 	if (!tor_init(&tor, &thread->extents, 2*thread->count))
772.33464 - 		return;
772.33465 - 
772.33466 --	boxes.op = thread->op;
772.33467 --	boxes.num_boxes = 0;
772.33468 -+	span_thread_boxes_init(&boxes, thread->op, thread->clip);
772.33469 - 
772.33470 - 	cw = 0; ccw = 1;
772.33471 - 	polygon_add_line(tor.polygon,
772.33472 -diff --git a/src/sna/sna_video.c b/src/sna/sna_video.c
772.33473 -index ed0e7b31..e2b11c31 100644
772.33474 ---- a/src/sna/sna_video.c
772.33475 -+++ b/src/sna/sna_video.c
772.33476 -@@ -591,6 +591,72 @@ use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */
772.33477 - 	return true;
772.33478 - }
772.33479 - 
772.33480 -+void sna_video_fill_colorkey(struct sna_video *video,
772.33481 -+			     const RegionRec *clip)
772.33482 -+{
772.33483 -+	struct sna *sna = video->sna;
772.33484 -+	PixmapPtr front = sna->front;
772.33485 -+	struct kgem_bo *bo = __sna_pixmap_get_bo(front);
772.33486 -+	uint8_t *dst, *tmp;
772.33487 -+	int w, width;
772.33488 -+
772.33489 -+	if (video->AlwaysOnTop || RegionEqual(&video->clip, (RegionPtr)clip))
772.33490 -+		return;
772.33491 -+
772.33492 -+	assert(bo);
772.33493 -+	if (!wedged(sna) &&
772.33494 -+	    sna_blt_fill_boxes(sna, GXcopy, bo,
772.33495 -+			       front->drawable.bitsPerPixel,
772.33496 -+			       video->color_key,
772.33497 -+			       region_rects(clip),
772.33498 -+			       region_num_rects(clip))) {
772.33499 -+		RegionCopy(&video->clip, (RegionPtr)clip);
772.33500 -+		return;
772.33501 -+	}
772.33502 -+
772.33503 -+	dst = kgem_bo_map__gtt(&sna->kgem, bo);
772.33504 -+	if (dst == NULL)
772.33505 -+		return;
772.33506 -+
772.33507 -+	w = front->drawable.bitsPerPixel/8;
772.33508 -+	width = (clip->extents.x2 - clip->extents.x1) * w;
772.33509 -+	tmp = malloc(width);
772.33510 -+	if (tmp == NULL)
772.33511 -+		return;
772.33512 -+
772.33513 -+	memcpy(tmp, &video->color_key, w);
772.33514 -+	while (2 * w < width) {
772.33515 -+		memcpy(tmp + w, tmp, w);
772.33516 -+		w *= 2;
772.33517 -+	}
772.33518 -+	if (w < width)
772.33519 -+		memcpy(tmp + w, tmp, width - w);
772.33520 -+
772.33521 -+	if (sigtrap_get() == 0) {
772.33522 -+		const BoxRec *box = region_rects(clip);
772.33523 -+		int n = region_num_rects(clip);
772.33524 -+
772.33525 -+		w = front->drawable.bitsPerPixel/8;
772.33526 -+		do {
772.33527 -+			int y = box->y1;
772.33528 -+			uint8_t *row = dst + y*bo->pitch + w*box->x1;
772.33529 -+
772.33530 -+			width = (box->x2 - box->x1) * w;
772.33531 -+			while (y < box->y2) {
772.33532 -+				memcpy(row, tmp, width);
772.33533 -+				row += bo->pitch;
772.33534 -+				y++;
772.33535 -+			}
772.33536 -+			box++;
772.33537 -+		} while (--n);
772.33538 -+		sigtrap_put();
772.33539 -+
772.33540 -+		RegionCopy(&video->clip, (RegionPtr)clip);
772.33541 -+	}
772.33542 -+
772.33543 -+	free(tmp);
772.33544 -+}
772.33545 -+
772.33546 - XvAdaptorPtr sna_xv_adaptor_alloc(struct sna *sna)
772.33547 - {
772.33548 - 	XvAdaptorPtr new_adaptors;
772.33549 -diff --git a/src/sna/sna_video.h b/src/sna/sna_video.h
772.33550 -index f21605fc..39cb725f 100644
772.33551 ---- a/src/sna/sna_video.h
772.33552 -+++ b/src/sna/sna_video.h
772.33553 -@@ -72,6 +72,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE.
772.33554 - struct sna_video {
772.33555 - 	struct sna *sna;
772.33556 - 
772.33557 -+	int idx; /* XXX expose struct plane instead? */
772.33558 -+
772.33559 - 	int brightness;
772.33560 - 	int contrast;
772.33561 - 	int saturation;
772.33562 -@@ -193,6 +195,9 @@ bool
772.33563 - sna_video_copy_data(struct sna_video *video,
772.33564 - 		    struct sna_video_frame *frame,
772.33565 - 		    const uint8_t *buf);
772.33566 -+void
772.33567 -+sna_video_fill_colorkey(struct sna_video *video,
772.33568 -+			const RegionRec *clip);
772.33569 - 
772.33570 - void sna_video_buffer_fini(struct sna_video *video);
772.33571 - 
772.33572 -@@ -210,4 +215,26 @@ sna_window_set_port(WindowPtr window, XvPortPtr port)
772.33573 - 	((void **)__get_private(window, sna_window_key))[2] = port;
772.33574 - }
772.33575 - 
772.33576 -+static inline int offset_and_clip(int x, int dx)
772.33577 -+{
772.33578 -+	x += dx;
772.33579 -+	if (x <= 0)
772.33580 -+		return 0;
772.33581 -+	if (x >= MAXSHORT)
772.33582 -+		return MAXSHORT;
772.33583 -+	return x;
772.33584 -+}
772.33585 -+
772.33586 -+static inline void init_video_region(RegionRec *region,
772.33587 -+				     DrawablePtr draw,
772.33588 -+				     int drw_x, int drw_y,
772.33589 -+				     int drw_w, int drw_h)
772.33590 -+{
772.33591 -+	region->extents.x1 = offset_and_clip(draw->x, drw_x);
772.33592 -+	region->extents.y1 = offset_and_clip(draw->y, drw_y);
772.33593 -+	region->extents.x2 = offset_and_clip(draw->x, drw_x + drw_w);
772.33594 -+	region->extents.y2 = offset_and_clip(draw->y, drw_y + drw_h);
772.33595 -+	region->data = NULL;
772.33596 -+}
772.33597 -+
772.33598 - #endif /* SNA_VIDEO_H */
772.33599 -diff --git a/src/sna/sna_video_overlay.c b/src/sna/sna_video_overlay.c
772.33600 -index ac81f1a0..9bc5ce40 100644
772.33601 ---- a/src/sna/sna_video_overlay.c
772.33602 -+++ b/src/sna/sna_video_overlay.c
772.33603 -@@ -130,7 +130,7 @@ static int sna_video_overlay_stop(ddStopVideo_ARGS)
772.33604 - 
772.33605 - 	DBG(("%s()\n", __FUNCTION__));
772.33606 - 
772.33607 --	REGION_EMPTY(scrn->pScreen, &video->clip);
772.33608 -+	REGION_EMPTY(to_screen_from_sna(sna), &video->clip);
772.33609 - 
772.33610 - 	request.flags = 0;
772.33611 - 	(void)drmIoctl(sna->kgem.fd,
772.33612 -@@ -474,15 +474,13 @@ sna_video_overlay_put_image(ddPutImage_ARGS)
772.33613 - 	if (src_h >= (drw_h * 8))
772.33614 - 		drw_h = src_h / 7;
772.33615 - 
772.33616 --	clip.extents.x1 = draw->x + drw_x;
772.33617 --	clip.extents.y1 = draw->y + drw_y;
772.33618 --	clip.extents.x2 = clip.extents.x1 + drw_w;
772.33619 --	clip.extents.y2 = clip.extents.y1 + drw_h;
772.33620 --	clip.data = NULL;
772.33621 -+	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
772.33622 - 
772.33623 - 	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
772.33624 --	if (!video->AlwaysOnTop)
772.33625 -+	if (!video->AlwaysOnTop) {
772.33626 -+		ValidateGC(draw, gc);
772.33627 - 		RegionIntersect(&clip, &clip, gc->pCompositeClip);
772.33628 -+	}
772.33629 - 	if (box_empty(&clip.extents))
772.33630 - 		goto invisible;
772.33631 - 
772.33632 -@@ -551,15 +549,7 @@ sna_video_overlay_put_image(ddPutImage_ARGS)
772.33633 - 	ret = Success;
772.33634 - 	if (sna_video_overlay_show
772.33635 - 	    (sna, video, &frame, crtc, &dstBox, src_w, src_h, drw_w, drw_h)) {
772.33636 --		//xf86XVFillKeyHelperDrawable(draw, video->color_key, &clip);
772.33637 --		if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
772.33638 --		    sna_blt_fill_boxes(sna, GXcopy,
772.33639 --				       __sna_pixmap_get_bo(sna->front),
772.33640 --				       sna->front->drawable.bitsPerPixel,
772.33641 --				       video->color_key,
772.33642 --				       region_rects(&clip),
772.33643 --				       region_num_rects(&clip)))
772.33644 --			RegionCopy(&video->clip, &clip);
772.33645 -+		sna_video_fill_colorkey(video, &clip);
772.33646 - 		sna_window_set_port((WindowPtr)draw, port);
772.33647 - 	} else {
772.33648 - 		DBG(("%s: failed to show video frame\n", __FUNCTION__));
772.33649 -diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
772.33650 -index 92230f97..69bfdfd2 100644
772.33651 ---- a/src/sna/sna_video_sprite.c
772.33652 -+++ b/src/sna/sna_video_sprite.c
772.33653 -@@ -47,6 +47,8 @@
772.33654 - #define DRM_FORMAT_YUYV         fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
772.33655 - #define DRM_FORMAT_UYVY         fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
772.33656 - 
772.33657 -+#define has_hw_scaling(sna) ((sna)->kgem.gen < 071)
772.33658 -+
772.33659 - #define LOCAL_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct local_mode_set_plane)
772.33660 - struct local_mode_set_plane {
772.33661 - 	uint32_t plane_id;
772.33662 -@@ -81,19 +83,17 @@ static int sna_video_sprite_stop(ddStopVideo_ARGS)
772.33663 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(video->sna->scrn);
772.33664 - 	int i;
772.33665 - 
772.33666 --	for (i = 0; i < config->num_crtc; i++) {
772.33667 -+	for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
772.33668 - 		xf86CrtcPtr crtc = config->crtc[i];
772.33669 - 		int pipe;
772.33670 - 
772.33671 --		if (sna_crtc_id(crtc) == 0)
772.33672 --			break;
772.33673 --
772.33674 --		pipe = sna_crtc_to_pipe(crtc);
772.33675 -+		pipe = sna_crtc_pipe(crtc);
772.33676 -+		assert(pipe < ARRAY_SIZE(video->bo));
772.33677 - 		if (video->bo[pipe] == NULL)
772.33678 - 			continue;
772.33679 - 
772.33680 - 		memset(&s, 0, sizeof(s));
772.33681 --		s.plane_id = sna_crtc_to_sprite(crtc);
772.33682 -+		s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
772.33683 - 		if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
772.33684 - 			xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
772.33685 - 				   "failed to disable plane\n");
772.33686 -@@ -153,7 +153,7 @@ static int sna_video_sprite_best_size(ddQueryBestSize_ARGS)
772.33687 - 	struct sna_video *video = port->devPriv.ptr;
772.33688 - 	struct sna *sna = video->sna;
772.33689 - 
772.33690 --	if (sna->kgem.gen >= 075) {
772.33691 -+	if (!has_hw_scaling(sna) && !sna->render.video) {
772.33692 - 		*p_w = vid_w;
772.33693 - 		*p_h = vid_h;
772.33694 - 	} else {
772.33695 -@@ -221,12 +221,12 @@ sna_video_sprite_show(struct sna *sna,
772.33696 - 		      BoxPtr dstBox)
772.33697 - {
772.33698 - 	struct local_mode_set_plane s;
772.33699 --	int pipe = sna_crtc_to_pipe(crtc);
772.33700 -+	int pipe = sna_crtc_pipe(crtc);
772.33701 - 
772.33702 - 	/* XXX handle video spanning multiple CRTC */
772.33703 - 
772.33704 - 	VG_CLEAR(s);
772.33705 --	s.plane_id = sna_crtc_to_sprite(crtc);
772.33706 -+	s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
772.33707 - 
772.33708 - #define DRM_I915_SET_SPRITE_COLORKEY 0x2b
772.33709 - #define LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct local_intel_sprite_colorkey)
772.33710 -@@ -263,9 +263,6 @@ sna_video_sprite_show(struct sna *sna,
772.33711 - 		video->color_key_changed &= ~(1 << pipe);
772.33712 - 	}
772.33713 - 
772.33714 --	if (video->bo[pipe] == frame->bo)
772.33715 --		return true;
772.33716 --
772.33717 - 	update_dst_box_to_crtc_coords(sna, crtc, dstBox);
772.33718 - 	if (frame->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
772.33719 - 		int tmp = frame->width;
772.33720 -@@ -283,15 +280,30 @@ sna_video_sprite_show(struct sna *sna,
772.33721 - 			uint32_t handles[4];
772.33722 - 			uint32_t pitches[4]; /* pitch for each plane */
772.33723 - 			uint32_t offsets[4]; /* offset of each plane */
772.33724 -+			uint64_t modifiers[4];
772.33725 - 		} f;
772.33726 - 		bool purged = true;
772.33727 - 
772.33728 - 		memset(&f, 0, sizeof(f));
772.33729 - 		f.width = frame->width;
772.33730 - 		f.height = frame->height;
772.33731 -+		f.flags = 1 << 1; /* +modifiers */
772.33732 - 		f.handles[0] = frame->bo->handle;
772.33733 - 		f.pitches[0] = frame->pitch[0];
772.33734 - 
772.33735 -+		switch (frame->bo->tiling) {
772.33736 -+		case I915_TILING_NONE:
772.33737 -+			break;
772.33738 -+		case I915_TILING_X:
772.33739 -+			/* I915_FORMAT_MOD_X_TILED */
772.33740 -+			f.modifiers[0] = (uint64_t)1 << 56 | 1;
772.33741 -+			break;
772.33742 -+		case I915_TILING_Y:
772.33743 -+			/* I915_FORMAT_MOD_X_TILED */
772.33744 -+			f.modifiers[0] = (uint64_t)1 << 56 | 2;
772.33745 -+			break;
772.33746 -+		}
772.33747 -+
772.33748 - 		switch (frame->id) {
772.33749 - 		case FOURCC_RGB565:
772.33750 - 			f.pixel_format = DRM_FORMAT_RGB565;
772.33751 -@@ -360,7 +372,7 @@ sna_video_sprite_show(struct sna *sna,
772.33752 - 		return false;
772.33753 - 	}
772.33754 - 
772.33755 --	frame->bo->domain = DOMAIN_NONE;
772.33756 -+	__kgem_bo_clear_dirty(frame->bo);
772.33757 - 
772.33758 - 	if (video->bo[pipe])
772.33759 - 		kgem_bo_destroy(&sna->kgem, video->bo[pipe]);
772.33760 -@@ -374,17 +386,17 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
772.33761 - 	struct sna *sna = video->sna;
772.33762 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.33763 - 	RegionRec clip;
772.33764 -+	BoxRec draw_extents;
772.33765 - 	int ret, i;
772.33766 - 
772.33767 --	clip.extents.x1 = draw->x + drw_x;
772.33768 --	clip.extents.y1 = draw->y + drw_y;
772.33769 --	clip.extents.x2 = clip.extents.x1 + drw_w;
772.33770 --	clip.extents.y2 = clip.extents.y1 + drw_h;
772.33771 --	clip.data = NULL;
772.33772 -+	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
772.33773 -+	draw_extents = clip.extents;
772.33774 - 
772.33775 - 	DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop));
772.33776 --	if (!video->AlwaysOnTop)
772.33777 -+	if (!video->AlwaysOnTop) {
772.33778 -+		ValidateGC(draw, gc);
772.33779 - 		RegionIntersect(&clip, &clip, gc->pCompositeClip);
772.33780 -+	}
772.33781 - 
772.33782 - 	DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n",
772.33783 - 	     __FUNCTION__,
772.33784 -@@ -402,19 +414,17 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
772.33785 - 		goto err;
772.33786 - 	}
772.33787 - 
772.33788 --	for (i = 0; i < config->num_crtc; i++) {
772.33789 -+	for (i = 0; i < video->sna->mode.num_real_crtc; i++) {
772.33790 - 		xf86CrtcPtr crtc = config->crtc[i];
772.33791 - 		struct sna_video_frame frame;
772.33792 -+		BoxRec dst = draw_extents;
772.33793 - 		int pipe;
772.33794 - 		INT32 x1, x2, y1, y2;
772.33795 --		BoxRec dst;
772.33796 - 		RegionRec reg;
772.33797 - 		Rotation rotation;
772.33798 -+		bool cache_bo;
772.33799 - 
772.33800 --		if (sna_crtc_id(crtc) == 0)
772.33801 --			break;
772.33802 --
772.33803 --		pipe = sna_crtc_to_pipe(crtc);
772.33804 -+		pipe = sna_crtc_pipe(crtc);
772.33805 - 
772.33806 - 		sna_video_frame_init(video, format->id, width, height, &frame);
772.33807 - 
772.33808 -@@ -423,10 +433,11 @@ static int sna_video_sprite_put_image(ddPutImage_ARGS)
772.33809 - 		RegionIntersect(&reg, &reg, &clip);
772.33810 - 		if (RegionNil(&reg)) {
772.33811 - off:
772.33812 -+			assert(pipe < ARRAY_SIZE(video->bo));
772.33813 - 			if (video->bo[pipe]) {
772.33814 - 				struct local_mode_set_plane s;
772.33815 - 				memset(&s, 0, sizeof(s));
772.33816 --				s.plane_id = sna_crtc_to_sprite(crtc);
772.33817 -+				s.plane_id = sna_crtc_to_sprite(crtc, video->idx);
772.33818 - 				if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s))
772.33819 - 					xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR,
772.33820 - 						   "failed to disable plane\n");
772.33821 -@@ -440,8 +451,6 @@ off:
772.33822 - 		y1 = src_y;
772.33823 - 		y2 = src_y + src_h;
772.33824 - 
772.33825 --		dst = clip.extents;
772.33826 --
772.33827 - 		ret = xf86XVClipVideoHelper(&dst, &x1, &x2, &y1, &y2,
772.33828 - 					    &reg, frame.width, frame.height);
772.33829 - 		RegionUninit(&reg);
772.33830 -@@ -465,8 +474,8 @@ off:
772.33831 - 
772.33832 - 		/* if sprite can't handle rotation natively, store it for the copy func */
772.33833 - 		rotation = RR_Rotate_0;
772.33834 --		if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) {
772.33835 --			sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0);
772.33836 -+		if (!sna_crtc_set_sprite_rotation(crtc, video->idx, crtc->rotation)) {
772.33837 -+			sna_crtc_set_sprite_rotation(crtc, video->idx, RR_Rotate_0);
772.33838 - 			rotation = crtc->rotation;
772.33839 - 		}
772.33840 - 		sna_video_frame_set_rotation(video, &frame, rotation);
772.33841 -@@ -496,6 +505,8 @@ off:
772.33842 - 			frame.image.y1 = 0;
772.33843 - 			frame.image.x2 = frame.width;
772.33844 - 			frame.image.y2 = frame.height;
772.33845 -+
772.33846 -+			cache_bo = false;
772.33847 - 		} else {
772.33848 - 			frame.bo = sna_video_buffer(video, &frame);
772.33849 - 			if (frame.bo == NULL) {
772.33850 -@@ -509,6 +520,60 @@ off:
772.33851 - 				ret = BadAlloc;
772.33852 - 				goto err;
772.33853 - 			}
772.33854 -+
772.33855 -+			cache_bo = true;
772.33856 -+		}
772.33857 -+
772.33858 -+		if (!has_hw_scaling(sna) && sna->render.video &&
772.33859 -+		    !((frame.src.x2 - frame.src.x1) == (dst.x2 - dst.x1) &&
772.33860 -+		      (frame.src.y2 - frame.src.y1) == (dst.y2 - dst.y1))) {
772.33861 -+			ScreenPtr screen = to_screen_from_sna(sna);
772.33862 -+			PixmapPtr scaled;
772.33863 -+			RegionRec r;
772.33864 -+
772.33865 -+			r.extents.x1 = r.extents.y1 = 0;
772.33866 -+			r.extents.x2 = dst.x2 - dst.x1;
772.33867 -+			r.extents.y2 = dst.y2 - dst.y1;
772.33868 -+			r.data = NULL;
772.33869 -+
772.33870 -+			DBG(("%s: scaling from (%d, %d) to (%d, %d)\n",
772.33871 -+			     __FUNCTION__,
772.33872 -+			     frame.src.x2 - frame.src.x1,
772.33873 -+			     frame.src.y2 - frame.src.y1,
772.33874 -+			     r.extents.x2, r.extents.y2));
772.33875 -+
772.33876 -+			scaled = screen->CreatePixmap(screen,
772.33877 -+						      r.extents.x2,
772.33878 -+						      r.extents.y2,
772.33879 -+						      24,
772.33880 -+						      CREATE_PIXMAP_USAGE_SCRATCH);
772.33881 -+			if (scaled == NULL) {
772.33882 -+				ret = BadAlloc;
772.33883 -+				goto err;
772.33884 -+			}
772.33885 -+
772.33886 -+			if (!sna->render.video(sna, video, &frame, &r, scaled)) {
772.33887 -+				screen->DestroyPixmap(scaled);
772.33888 -+				ret = BadAlloc;
772.33889 -+				goto err;
772.33890 -+			}
772.33891 -+
772.33892 -+			if (cache_bo)
772.33893 -+				sna_video_buffer_fini(video);
772.33894 -+			else
772.33895 -+				kgem_bo_destroy(&sna->kgem, frame.bo);
772.33896 -+
772.33897 -+			frame.bo = kgem_bo_reference(__sna_pixmap_get_bo(scaled));
772.33898 -+			kgem_bo_submit(&sna->kgem, frame.bo);
772.33899 -+
772.33900 -+			frame.id = FOURCC_RGB888;
772.33901 -+			frame.src = frame.image = r.extents;
772.33902 -+			frame.width = frame.image.x2;
772.33903 -+			frame.height = frame.image.y2;
772.33904 -+			frame.pitch[0] = frame.bo->pitch;
772.33905 -+
772.33906 -+			screen->DestroyPixmap(scaled);
772.33907 -+			cache_bo = false;
772.33908 - 		}
772.33909 - 
772.33910 - 		ret = Success;
772.33911 -@@ -517,24 +582,16 @@ off:
772.33912 - 			ret = BadAlloc;
772.33913 - 		}
772.33914 - 
772.33915 --		frame.bo->domain = DOMAIN_NONE;
772.33916 --		if (xvmc_passthrough(format->id))
772.33917 --			kgem_bo_destroy(&sna->kgem, frame.bo);
772.33918 --		else
772.33919 -+		if (cache_bo)
772.33920 - 			sna_video_buffer_fini(video);
772.33921 -+		else
772.33922 -+			kgem_bo_destroy(&sna->kgem, frame.bo);
772.33923 - 
772.33924 - 		if (ret != Success)
772.33925 - 			goto err;
772.33926 - 	}
772.33927 - 
772.33928 --	if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) &&
772.33929 --	    sna_blt_fill_boxes(sna, GXcopy,
772.33930 --			       __sna_pixmap_get_bo(sna->front),
772.33931 --			       sna->front->drawable.bitsPerPixel,
772.33932 --			       video->color_key,
772.33933 --			       region_rects(&clip),
772.33934 --			       region_num_rects(&clip)))
772.33935 --		RegionCopy(&video->clip, &clip);
772.33936 -+	sna_video_fill_colorkey(video, &clip);
772.33937 - 	sna_window_set_port((WindowPtr)draw, port);
772.33938 - 
772.33939 - 	return Success;
772.33940 -@@ -606,25 +663,28 @@ static int sna_video_sprite_color_key(struct sna *sna)
772.33941 - 	return color_key & ((1 << scrn->depth) - 1);
772.33942 - }
772.33943 - 
772.33944 --static bool sna_video_has_sprites(struct sna *sna)
772.33945 -+static int sna_video_has_sprites(struct sna *sna)
772.33946 - {
772.33947 - 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
772.33948 -+	unsigned min;
772.33949 - 	int i;
772.33950 - 
772.33951 - 	DBG(("%s: num_crtc=%d\n", __FUNCTION__, sna->mode.num_real_crtc));
772.33952 - 
772.33953 - 	if (sna->mode.num_real_crtc == 0)
772.33954 --		return false;
772.33955 -+		return 0;
772.33956 - 
772.33957 -+	min = -1;
772.33958 - 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
772.33959 --		if (!sna_crtc_to_sprite(config->crtc[i])) {
772.33960 --			DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(config->crtc[i])));
772.33961 --			return false;
772.33962 --		}
772.33963 -+		unsigned count =  sna_crtc_count_sprites(config->crtc[i]);
772.33964 -+		DBG(("%s: %d sprites found on pipe %d\n", __FUNCTION__,
772.33965 -+		     count, sna_crtc_pipe(config->crtc[i])));
772.33966 -+		if (count < min)
772.33967 -+			min = count;
772.33968 - 	}
772.33969 - 
772.33970 --	DBG(("%s: yes\n", __FUNCTION__));
772.33971 --	return true;
772.33972 -+	DBG(("%s: min=%d\n", __FUNCTION__, min));
772.33973 -+	return min;
772.33974 - }
772.33975 - 
772.33976 - void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
772.33977 -@@ -632,16 +692,18 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
772.33978 - 	XvAdaptorPtr adaptor;
772.33979 - 	struct sna_video *video;
772.33980 - 	XvPortPtr port;
772.33981 -+	int count, i;
772.33982 - 
772.33983 --	if (!sna_video_has_sprites(sna))
772.33984 -+	count = sna_video_has_sprites(sna);
772.33985 -+	if (!count)
772.33986 - 		return;
772.33987 - 
772.33988 - 	adaptor = sna_xv_adaptor_alloc(sna);
772.33989 - 	if (!adaptor)
772.33990 - 		return;
772.33991 - 
772.33992 --	video = calloc(1, sizeof(*video));
772.33993 --	port = calloc(1, sizeof(*port));
772.33994 -+	video = calloc(count, sizeof(*video));
772.33995 -+	port = calloc(count, sizeof(*port));
772.33996 - 	if (video == NULL || port == NULL) {
772.33997 - 		free(video);
772.33998 - 		free(port);
772.33999 -@@ -686,36 +748,43 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen)
772.34000 - 	adaptor->ddPutImage = sna_video_sprite_put_image;
772.34001 - 	adaptor->ddQueryImageAttributes = sna_video_sprite_query;
772.34002 - 
772.34003 --	adaptor->nPorts = 1;
772.34004 -+	adaptor->nPorts = count;
772.34005 - 	adaptor->pPorts = port;
772.34006 - 
772.34007 --	adaptor->base_id = port->id = FakeClientID(0);
772.34008 --	AddResource(port->id, XvGetRTPort(), port);
772.34009 --	port->pAdaptor = adaptor;
772.34010 --	port->pNotify =  NULL;
772.34011 --	port->pDraw =  NULL;
772.34012 --	port->client =  NULL;
772.34013 --	port->grab.client =  NULL;
772.34014 --	port->time = currentTime;
772.34015 --	port->devPriv.ptr = video;
772.34016 --
772.34017 --	video->sna = sna;
772.34018 --	video->alignment = 64;
772.34019 --	video->color_key = sna_video_sprite_color_key(sna);
772.34020 --	video->color_key_changed = ~0;
772.34021 --	video->has_color_key = true;
772.34022 --	video->brightness = -19;	/* (255/219) * -16 */
772.34023 --	video->contrast = 75;	/* 255/219 * 64 */
772.34024 --	video->saturation = 146;	/* 128/112 * 128 */
772.34025 --	video->desired_crtc = NULL;
772.34026 --	video->gamma5 = 0xc0c0c0;
772.34027 --	video->gamma4 = 0x808080;
772.34028 --	video->gamma3 = 0x404040;
772.34029 --	video->gamma2 = 0x202020;
772.34030 --	video->gamma1 = 0x101010;
772.34031 --	video->gamma0 = 0x080808;
772.34032 --	RegionNull(&video->clip);
772.34033 --	video->SyncToVblank = 1;
772.34034 -+	for (i = 0; i < count; i++) {
772.34035 -+		port->id = FakeClientID(0);
772.34036 -+		AddResource(port->id, XvGetRTPort(), port);
772.34037 -+		port->pAdaptor = adaptor;
772.34038 -+		port->pNotify =  NULL;
772.34039 -+		port->pDraw =  NULL;
772.34040 -+		port->client =  NULL;
772.34041 -+		port->grab.client =  NULL;
772.34042 -+		port->time = currentTime;
772.34043 -+		port->devPriv.ptr = video;
772.34044 -+
772.34045 -+		video->sna = sna;
772.34046 -+		video->idx = i;
772.34047 -+		video->alignment = 64;
772.34048 -+		video->color_key = sna_video_sprite_color_key(sna);
772.34049 -+		video->color_key_changed = ~0;
772.34050 -+		video->has_color_key = true;
772.34051 -+		video->brightness = -19;	/* (255/219) * -16 */
772.34052 -+		video->contrast = 75;	/* 255/219 * 64 */
772.34053 -+		video->saturation = 146;	/* 128/112 * 128 */
772.34054 -+		video->desired_crtc = NULL;
772.34055 -+		video->gamma5 = 0xc0c0c0;
772.34056 -+		video->gamma4 = 0x808080;
772.34057 -+		video->gamma3 = 0x404040;
772.34058 -+		video->gamma2 = 0x202020;
772.34059 -+		video->gamma1 = 0x101010;
772.34060 -+		video->gamma0 = 0x080808;
772.34061 -+		RegionNull(&video->clip);
772.34062 -+		video->SyncToVblank = 1;
772.34063 -+
772.34064 -+		port++;
772.34065 -+		video++;
772.34066 -+	}
772.34067 -+	adaptor->base_id = adaptor->pPorts[0].id;
772.34068 - 
772.34069 - 	xvColorKey = MAKE_ATOM("XV_COLORKEY");
772.34070 - 	xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP");
772.34071 -diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
772.34072 -index 95011939..3cce5cf1 100644
772.34073 ---- a/src/sna/sna_video_textured.c
772.34074 -+++ b/src/sna/sna_video_textured.c
772.34075 -@@ -48,7 +48,12 @@ static const XvAttributeRec Attributes[] = {
772.34076 - 	//{XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"},
772.34077 - };
772.34078 - 
772.34079 --static const XvImageRec Images[] = {
772.34080 -+static const XvImageRec gen2_Images[] = {
772.34081 -+	XVIMAGE_YUY2,
772.34082 -+	XVIMAGE_UYVY,
772.34083 -+};
772.34084 -+
772.34085 -+static const XvImageRec gen3_Images[] = {
772.34086 - 	XVIMAGE_YUY2,
772.34087 - 	XVIMAGE_YV12,
772.34088 - 	XVIMAGE_I420,
772.34089 -@@ -149,15 +154,16 @@ sna_video_textured_put_image(ddPutImage_ARGS)
772.34090 - 	BoxRec dstBox;
772.34091 - 	RegionRec clip;
772.34092 - 	xf86CrtcPtr crtc;
772.34093 -+	int16_t dx, dy;
772.34094 - 	bool flush = false;
772.34095 - 	bool ret;
772.34096 - 
772.34097 --	clip.extents.x1 = draw->x + drw_x;
772.34098 --	clip.extents.y1 = draw->y + drw_y;
772.34099 --	clip.extents.x2 = clip.extents.x1 + drw_w;
772.34100 --	clip.extents.y2 = clip.extents.y1 + drw_h;
772.34101 --	clip.data = NULL;
772.34102 -+	if (wedged(sna))
772.34103 -+		return BadAlloc;
772.34104 - 
772.34105 -+	init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h);
772.34106 -+
772.34107 -+	ValidateGC(draw, gc);
772.34108 - 	RegionIntersect(&clip, &clip, gc->pCompositeClip);
772.34109 - 	if (!RegionNotEmpty(&clip))
772.34110 - 		return Success;
772.34111 -@@ -181,6 +187,9 @@ sna_video_textured_put_image(ddPutImage_ARGS)
772.34112 - 				   &clip))
772.34113 - 		return Success;
772.34114 - 
772.34115 -+	if (get_drawable_deltas(draw, pixmap, &dx, &dy))
772.34116 -+		RegionTranslate(&clip, dx, dy);
772.34117 -+
772.34118 - 	flags = MOVE_WRITE | __MOVE_FORCE;
772.34119 - 	if (clip.data)
772.34120 - 		flags |= MOVE_READ;
772.34121 -@@ -234,7 +243,7 @@ sna_video_textured_put_image(ddPutImage_ARGS)
772.34122 - 		DBG(("%s: failed to render video\n", __FUNCTION__));
772.34123 - 		ret = BadAlloc;
772.34124 - 	} else
772.34125 --		DamageDamageRegion(draw, &clip);
772.34126 -+		DamageDamageRegion(&pixmap->drawable, &clip);
772.34127 - 
772.34128 - 	kgem_bo_destroy(&sna->kgem, frame.bo);
772.34129 - 
772.34130 -@@ -316,7 +325,7 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
772.34131 - 
772.34132 - 	if (!sna->render.video) {
772.34133 - 		xf86DrvMsg(sna->scrn->scrnIndex, X_INFO,
772.34134 --			   "Textured video not supported on this hardware\n");
772.34135 -+			   "Textured video not supported on this hardware or backend\n");
772.34136 - 		return;
772.34137 - 	}
772.34138 - 
772.34139 -@@ -362,8 +371,13 @@ void sna_video_textured_setup(struct sna *sna, ScreenPtr screen)
772.34140 - 						 ARRAY_SIZE(Formats));
772.34141 - 	adaptor->nAttributes = ARRAY_SIZE(Attributes);
772.34142 - 	adaptor->pAttributes = (XvAttributeRec *)Attributes;
772.34143 --	adaptor->nImages = ARRAY_SIZE(Images);
772.34144 --	adaptor->pImages = (XvImageRec *)Images;
772.34145 -+	if (sna->kgem.gen < 030) {
772.34146 -+		adaptor->nImages = ARRAY_SIZE(gen2_Images);
772.34147 -+		adaptor->pImages = (XvImageRec *)gen2_Images;
772.34148 -+	} else {
772.34149 -+		adaptor->nImages = ARRAY_SIZE(gen3_Images);
772.34150 -+		adaptor->pImages = (XvImageRec *)gen3_Images;
772.34151 -+	}
772.34152 - #if XORG_XV_VERSION < 2
772.34153 - 	adaptor->ddAllocatePort = sna_xv_alloc_port;
772.34154 - 	adaptor->ddFreePort = sna_xv_free_port;
772.34155 -diff --git a/src/sna/xassert.h b/src/sna/xassert.h
772.34156 -index 1bcfd080..e648e4bc 100644
772.34157 ---- a/src/sna/xassert.h
772.34158 -+++ b/src/sna/xassert.h
772.34159 -@@ -43,6 +43,28 @@
772.34160 - 	xorg_backtrace(); \
772.34161 - 	FatalError("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
772.34162 - } while (0)
772.34163 -+
772.34164 -+#define warn_unless(E) \
772.34165 -+({ \
772.34166 -+	bool fail = !(E); \
772.34167 -+	if (unlikely(fail)) { \
772.34168 -+		static int __warn_once__; \
772.34169 -+		if (!__warn_once__) { \
772.34170 -+			xorg_backtrace(); \
772.34171 -+			ErrorF("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
772.34172 -+			__warn_once__ = 1; \
772.34173 -+		} \
772.34174 -+	} \
772.34175 -+	unlikely(fail); \
772.34176 -+})
772.34177 -+
772.34178 -+#define dbg(EXPR) EXPR
772.34179 -+
772.34180 -+#else
772.34181 -+
772.34182 -+#define warn_unless(E) ({ bool fail = !(E); unlikely(fail); })
772.34183 -+#define dbg(EXPR)
772.34184 -+
772.34185 - #endif
772.34186 - 
772.34187 - #endif /* __XASSERT_H__ */
772.34188 -diff --git a/src/uxa/i830_reg.h b/src/uxa/i830_reg.h
772.34189 -index d8306bcd..ba39d82c 100644
772.34190 ---- a/src/uxa/i830_reg.h
772.34191 -+++ b/src/uxa/i830_reg.h
772.34192 -@@ -65,6 +65,12 @@
772.34193 - #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA	(0)
772.34194 - #define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB	(0x1<<20)
772.34195 - 
772.34196 -+#define MI_LOAD_REGISTER_IMM		(0x22<<23 | (3-2))
772.34197 -+
772.34198 -+#define BCS_SWCTRL                      0x22200
772.34199 -+# define BCS_SWCTRL_SRC_Y               (1 << 0)
772.34200 -+# define BCS_SWCTRL_DST_Y               (1 << 1)
772.34201 -+
772.34202 - /* BLT commands */
772.34203 - #define COLOR_BLT_CMD		((2<<29)|(0x40<<22)|(0x3))
772.34204 - #define COLOR_BLT_WRITE_ALPHA	(1<<21)
772.34205 -diff --git a/src/uxa/i965_video.c b/src/uxa/i965_video.c
772.34206 -index 68e6fd38..438ab909 100644
772.34207 ---- a/src/uxa/i965_video.c
772.34208 -+++ b/src/uxa/i965_video.c
772.34209 -@@ -37,7 +37,6 @@
772.34210 - #include "fourcc.h"
772.34211 - 
772.34212 - #include "intel.h"
772.34213 --#include "intel_xvmc.h"
772.34214 - #include "intel_uxa.h"
772.34215 - #include "i830_reg.h"
772.34216 - #include "i965_reg.h"
772.34217 -diff --git a/src/uxa/intel.h b/src/uxa/intel.h
772.34218 -index 1b7e5339..a5e77af4 100644
772.34219 ---- a/src/uxa/intel.h
772.34220 -+++ b/src/uxa/intel.h
772.34221 -@@ -121,7 +121,6 @@ typedef struct intel_screen_private {
772.34222 - 
772.34223 - 	void *modes;
772.34224 - 	drm_intel_bo *front_buffer, *back_buffer;
772.34225 --	unsigned int back_name;
772.34226 - 	long front_pitch, front_tiling;
772.34227 - 
772.34228 - 	dri_bufmgr *bufmgr;
772.34229 -@@ -169,6 +168,7 @@ typedef struct intel_screen_private {
772.34230 - 	const struct intel_device_info *info;
772.34231 - 
772.34232 - 	unsigned int BR[20];
772.34233 -+	unsigned int BR_tiling[2];
772.34234 - 
772.34235 - 	CloseScreenProcPtr CloseScreen;
772.34236 - 
772.34237 -@@ -196,7 +196,9 @@ typedef struct intel_screen_private {
772.34238 - 
772.34239 - 	int colorKey;
772.34240 - 	XF86VideoAdaptorPtr adaptor;
772.34241 -+#if !HAVE_NOTIFY_FD
772.34242 - 	ScreenBlockHandlerProcPtr BlockHandler;
772.34243 -+#endif
772.34244 - 	Bool overlayOn;
772.34245 - 
772.34246 - 	struct {
772.34247 -@@ -285,8 +287,6 @@ typedef struct intel_screen_private {
772.34248 - 	Bool has_kernel_flush;
772.34249 - 	Bool needs_flush;
772.34250 - 
772.34251 --	struct _DRI2FrameEvent *pending_flip[MAX_PIPES];
772.34252 --
772.34253 - 	/* Broken-out options. */
772.34254 - 	OptionInfoPtr Options;
772.34255 - 
772.34256 -@@ -368,6 +368,7 @@ typedef void (*intel_drm_abort_proc)(ScrnInfoPtr scrn,
772.34257 - 
772.34258 - extern uint32_t intel_drm_queue_alloc(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data, intel_drm_handler_proc handler, intel_drm_abort_proc abort);
772.34259 - extern void intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data);
772.34260 -+extern void intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq);
772.34261 - 
772.34262 - extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc);
772.34263 - extern int intel_crtc_id(xf86CrtcPtr crtc);
772.34264 -@@ -408,7 +409,6 @@ typedef struct _DRI2FrameEvent {
772.34265 - 	ClientPtr client;
772.34266 - 	enum DRI2FrameEventType type;
772.34267 - 	int frame;
772.34268 --	int pipe;
772.34269 - 
772.34270 - 	struct list drawable_resource, client_resource;
772.34271 - 
772.34272 -@@ -418,7 +418,12 @@ typedef struct _DRI2FrameEvent {
772.34273 - 	DRI2BufferPtr front;
772.34274 - 	DRI2BufferPtr back;
772.34275 - 
772.34276 --	struct _DRI2FrameEvent *chain;
772.34277 -+	/* current scanout for triple buffer */
772.34278 -+	int old_width;
772.34279 -+	int old_height;
772.34280 -+	int old_pitch;
772.34281 -+	int old_tiling;
772.34282 -+	dri_bo *old_buffer;
772.34283 - } DRI2FrameEventRec, *DRI2FrameEventPtr;
772.34284 - 
772.34285 - extern Bool intel_do_pageflip(intel_screen_private *intel,
772.34286 -@@ -456,10 +461,6 @@ extern xf86CrtcPtr intel_covering_crtc(ScrnInfoPtr scrn, BoxPtr box,
772.34287 - 
772.34288 - Bool I830DRI2ScreenInit(ScreenPtr pScreen);
772.34289 - void I830DRI2CloseScreen(ScreenPtr pScreen);
772.34290 --void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
772.34291 --			       unsigned int tv_usec, DRI2FrameEventPtr flip_info);
772.34292 --void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
772.34293 --			      unsigned int tv_usec, DRI2FrameEventPtr flip_info);
772.34294 - 
772.34295 - /* intel_dri3.c */
772.34296 - Bool intel_dri3_screen_init(ScreenPtr screen);
772.34297 -diff --git a/src/uxa/intel_batchbuffer.c b/src/uxa/intel_batchbuffer.c
772.34298 -index a29e4434..114c6026 100644
772.34299 ---- a/src/uxa/intel_batchbuffer.c
772.34300 -+++ b/src/uxa/intel_batchbuffer.c
772.34301 -@@ -245,6 +245,17 @@ void intel_batch_submit(ScrnInfoPtr scrn)
772.34302 - 	if (intel->batch_used == 0)
772.34303 - 		return;
772.34304 - 
772.34305 -+	if (intel->current_batch == I915_EXEC_BLT &&
772.34306 -+	    INTEL_INFO(intel)->gen >= 060) {
772.34307 -+		OUT_BATCH(MI_FLUSH_DW);
772.34308 -+		OUT_BATCH(0);
772.34309 -+		OUT_BATCH(0);
772.34310 -+		OUT_BATCH(0);
772.34311 -+		OUT_BATCH(MI_LOAD_REGISTER_IMM);
772.34312 -+		OUT_BATCH(BCS_SWCTRL);
772.34313 -+		OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16);
772.34314 -+	}
772.34315 -+
772.34316 - 	/* Mark the end of the batchbuffer. */
772.34317 - 	OUT_BATCH(MI_BATCH_BUFFER_END);
772.34318 - 	/* Emit a padding dword if we aren't going to be quad-word aligned. */
772.34319 -diff --git a/src/uxa/intel_batchbuffer.h b/src/uxa/intel_batchbuffer.h
772.34320 -index e5fb8d08..e71ffd19 100644
772.34321 ---- a/src/uxa/intel_batchbuffer.h
772.34322 -+++ b/src/uxa/intel_batchbuffer.h
772.34323 -@@ -30,7 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
772.34324 - #ifndef _INTEL_BATCHBUFFER_H
772.34325 - #define _INTEL_BATCHBUFFER_H
772.34326 - 
772.34327 --#define BATCH_RESERVED		16
772.34328 -+#define BATCH_RESERVED		64
772.34329 - 
772.34330 - 
772.34331 - void intel_batch_init(ScrnInfoPtr scrn);
772.34332 -@@ -202,6 +202,23 @@ do {									\
772.34333 - 
772.34334 - #define BEGIN_BATCH(n)	__BEGIN_BATCH(n,RENDER_BATCH)
772.34335 - #define BEGIN_BATCH_BLT(n)	__BEGIN_BATCH(n,BLT_BATCH)
772.34336 -+#define BEGIN_BATCH_BLT_TILED(n) \
772.34337 -+do { \
772.34338 -+	if (INTEL_INFO(intel)->gen < 060) { \
772.34339 -+		__BEGIN_BATCH(n, BLT_BATCH); \
772.34340 -+	} else { \
772.34341 -+		__BEGIN_BATCH(n+7, BLT_BATCH); \
772.34342 -+		OUT_BATCH(MI_FLUSH_DW); \
772.34343 -+		OUT_BATCH(0); \
772.34344 -+		OUT_BATCH(0); \
772.34345 -+		OUT_BATCH(0); \
772.34346 -+		OUT_BATCH(MI_LOAD_REGISTER_IMM); \
772.34347 -+		OUT_BATCH(BCS_SWCTRL); \
772.34348 -+		OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16 | \
772.34349 -+			  ((intel->BR_tiling[0] == I915_TILING_Y) ? BCS_SWCTRL_DST_Y : 0) | \
772.34350 -+			  ((intel->BR_tiling[1] == I915_TILING_Y) ? BCS_SWCTRL_SRC_Y : 0)); \
772.34351 -+	} \
772.34352 -+} while (0)
772.34353 - 
772.34354 - #define ADVANCE_BATCH() do {						\
772.34355 - 	if (intel->batch_emitting == 0)					\
772.34356 -diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
772.34357 -index 7b4d4e0c..809cda1d 100644
772.34358 ---- a/src/uxa/intel_display.c
772.34359 -+++ b/src/uxa/intel_display.c
772.34360 -@@ -89,11 +89,11 @@ struct intel_mode {
772.34361 - 	struct list outputs;
772.34362 - 	struct list crtcs;
772.34363 - 
772.34364 --	void *pageflip_data;
772.34365 --	intel_pageflip_handler_proc pageflip_handler;
772.34366 --	intel_pageflip_abort_proc pageflip_abort;
772.34367 --
772.34368 --	Bool delete_dp_12_displays;
772.34369 -+	struct {
772.34370 -+		intel_pageflip_handler_proc handler;
772.34371 -+		intel_pageflip_abort_proc abort;
772.34372 -+		void *data;
772.34373 -+	} pageflip;
772.34374 - };
772.34375 - 
772.34376 - struct intel_pageflip {
772.34377 -@@ -114,7 +114,6 @@ struct intel_crtc {
772.34378 - 	struct list link;
772.34379 - 	PixmapPtr scanout_pixmap;
772.34380 - 	uint32_t scanout_fb_id;
772.34381 --	int32_t vblank_offset;
772.34382 - 	uint32_t msc_prev;
772.34383 - 	uint64_t msc_high;
772.34384 - };
772.34385 -@@ -193,7 +192,7 @@ intel_output_backlight_init(xf86OutputPtr output)
772.34386 - 
772.34387 - 	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
772.34388 - 	if (str != NULL) {
772.34389 --		if (backlight_exists(str) != BL_NONE) {
772.34390 -+		if (backlight_exists(str)) {
772.34391 - 			intel_output->backlight_active_level =
772.34392 - 				backlight_open(&intel_output->backlight,
772.34393 - 					       strdup(str));
772.34394 -@@ -689,9 +688,11 @@ intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
772.34395 - 	}
772.34396 - 
772.34397 - 	bo = intel_get_pixmap_bo(ppix);
772.34398 --	if (intel->front_buffer) {
772.34399 --		ErrorF("have front buffer\n");
772.34400 --	}
772.34401 -+	if (!bo)
772.34402 -+		return FALSE;
772.34403 -+
772.34404 -+	if (intel->front_buffer)
772.34405 -+		return FALSE;
772.34406 - 
772.34407 - 	drm_intel_bo_disable_reuse(bo);
772.34408 - 
772.34409 -@@ -867,6 +868,48 @@ intel_output_attach_edid(xf86OutputPtr output)
772.34410 - 	xf86OutputSetEDID(output, mon);
772.34411 - }
772.34412 - 
772.34413 -+static void
772.34414 -+intel_output_attach_tile(xf86OutputPtr output)
772.34415 -+{
772.34416 -+#if XF86_OUTPUT_VERSION >= 3
772.34417 -+	struct intel_output *intel_output = output->driver_private;
772.34418 -+	drmModeConnectorPtr koutput = intel_output->mode_output;
772.34419 -+	struct intel_mode *mode = intel_output->mode;
772.34420 -+	drmModePropertyBlobPtr blob = NULL;
772.34421 -+	struct xf86CrtcTileInfo tile_info, *set = NULL;
772.34422 -+	int i;
772.34423 -+
772.34424 -+	for (i = 0; koutput && i < koutput->count_props; i++) {
772.34425 -+		drmModePropertyPtr props;
772.34426 -+
772.34427 -+		props = drmModeGetProperty(mode->fd, koutput->props[i]);
772.34428 -+		if (!props)
772.34429 -+			continue;
772.34430 -+
772.34431 -+		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
772.34432 -+			drmModeFreeProperty(props);
772.34433 -+			continue;
772.34434 -+		}
772.34435 -+
772.34436 -+		if (!strcmp(props->name, "TILE")) {
772.34437 -+			blob = drmModeGetPropertyBlob(mode->fd,
772.34438 -+						      koutput->prop_values[i]);
772.34439 -+		}
772.34440 -+		drmModeFreeProperty(props);
772.34441 -+	}
772.34442 -+
772.34443 -+	if (blob) {
772.34444 -+		if (xf86OutputParseKMSTile(blob->data,
772.34445 -+					   blob->length,
772.34446 -+					   &tile_info))
772.34447 -+			set = &tile_info;
772.34448 -+		drmModeFreePropertyBlob(blob);
772.34449 -+	}
772.34450 -+
772.34451 -+	xf86OutputSetTile(output, set);
772.34452 -+#endif
772.34453 -+}
772.34454 -+
772.34455 - static DisplayModePtr
772.34456 - intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
772.34457 - {
772.34458 -@@ -922,6 +965,7 @@ intel_output_get_modes(xf86OutputPtr output)
772.34459 - 	int i;
772.34460 - 
772.34461 - 	intel_output_attach_edid(output);
772.34462 -+	intel_output_attach_tile(output);
772.34463 - 
772.34464 - 	if (!koutput)
772.34465 - 		return Modes;
772.34466 -@@ -1492,6 +1536,7 @@ intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_
772.34467 - 			intel_output = output->driver_private;
772.34468 - 			intel_output->output_id = mode_res->connectors[num];
772.34469 - 			intel_output->mode_output = koutput;
772.34470 -+			RROutputChanged(output->randr_output, TRUE);
772.34471 - 			return;
772.34472 - 		}
772.34473 - 	}
772.34474 -@@ -1650,9 +1695,6 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data);
772.34475 - static void
772.34476 - intel_pageflip_complete(struct intel_mode *mode);
772.34477 - 
772.34478 --static void
772.34479 --intel_drm_abort_seq (ScrnInfoPtr scrn, uint32_t seq);
772.34480 --
772.34481 - Bool
772.34482 - intel_do_pageflip(intel_screen_private *intel,
772.34483 - 		  dri_bo *new_front,
772.34484 -@@ -1671,23 +1713,30 @@ intel_do_pageflip(intel_screen_private *intel,
772.34485 - 	uint32_t new_fb_id;
772.34486 - 	uint32_t flags;
772.34487 - 	uint32_t seq;
772.34488 -+	int err = 0;
772.34489 - 	int i;
772.34490 - 
772.34491 - 	/*
772.34492 -+	 * We only have a single length queue in the kernel, so any
772.34493 -+	 * attempts to schedule a second flip before processing the first
772.34494 -+	 * is a bug. Punt it back to the caller.
772.34495 -+	 */
772.34496 -+	if (mode->flip_count)
772.34497 -+		return FALSE;
772.34498 -+
772.34499 -+	/*
772.34500 - 	 * Create a new handle for the back buffer
772.34501 - 	 */
772.34502 - 	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
772.34503 - 			 scrn->depth, scrn->bitsPerPixel, pitch,
772.34504 --			 new_front->handle, &new_fb_id))
772.34505 -+			 new_front->handle, &new_fb_id)) {
772.34506 -+		err = errno;
772.34507 - 		goto error_out;
772.34508 -+	}
772.34509 - 
772.34510 - 	drm_intel_bo_disable_reuse(new_front);
772.34511 -         intel_flush(intel);
772.34512 - 
772.34513 --	mode->pageflip_data = pageflip_data;
772.34514 --	mode->pageflip_handler = pageflip_handler;
772.34515 --	mode->pageflip_abort = pageflip_abort;
772.34516 --
772.34517 - 	/*
772.34518 - 	 * Queue flips on all enabled CRTCs
772.34519 - 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
772.34520 -@@ -1699,6 +1748,7 @@ intel_do_pageflip(intel_screen_private *intel,
772.34521 - 	 */
772.34522 - 	mode->fe_msc = 0;
772.34523 - 	mode->fe_usec = 0;
772.34524 -+	memset(&mode->pageflip, 0, sizeof(mode->pageflip));
772.34525 - 
772.34526 - 	flags = DRM_MODE_PAGE_FLIP_EVENT;
772.34527 - 	if (async)
772.34528 -@@ -1711,8 +1761,7 @@ intel_do_pageflip(intel_screen_private *intel,
772.34529 - 
772.34530 - 		flip = calloc(1, sizeof(struct intel_pageflip));
772.34531 - 		if (flip == NULL) {
772.34532 --			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
772.34533 --				   "flip queue: carrier alloc failed.\n");
772.34534 -+			err = errno;
772.34535 - 			goto error_undo;
772.34536 - 		}
772.34537 - 
772.34538 -@@ -1724,33 +1773,30 @@ intel_do_pageflip(intel_screen_private *intel,
772.34539 - 
772.34540 - 		seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
772.34541 - 		if (!seq) {
772.34542 -+			err = errno;
772.34543 - 			free(flip);
772.34544 - 			goto error_undo;
772.34545 - 		}
772.34546 - 
772.34547 --again:
772.34548 -+		mode->flip_count++;
772.34549 -+
772.34550 - 		if (drmModePageFlip(mode->fd,
772.34551 - 				    crtc_id(crtc),
772.34552 - 				    new_fb_id,
772.34553 - 				    flags, (void *)(uintptr_t)seq)) {
772.34554 --			if (intel_mode_read_drm_events(intel)) {
772.34555 --				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
772.34556 --					   "flip queue retry\n");
772.34557 --				goto again;
772.34558 --			}
772.34559 --			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
772.34560 --				   "flip queue failed: %s\n", strerror(errno));
772.34561 --			if (seq)
772.34562 --				intel_drm_abort_seq(scrn, seq);
772.34563 --			free(flip);
772.34564 -+			err = errno;
772.34565 -+			intel_drm_abort_seq(scrn, seq);
772.34566 - 			goto error_undo;
772.34567 - 		}
772.34568 --		mode->flip_count++;
772.34569 - 	}
772.34570 - 
772.34571 - 	mode->old_fb_id = mode->fb_id;
772.34572 - 	mode->fb_id = new_fb_id;
772.34573 - 
772.34574 -+	mode->pageflip.data = pageflip_data;
772.34575 -+	mode->pageflip.handler = pageflip_handler;
772.34576 -+	mode->pageflip.abort = pageflip_abort;
772.34577 -+
772.34578 - 	if (!mode->flip_count)
772.34579 - 		intel_pageflip_complete(mode);
772.34580 - 
772.34581 -@@ -1765,7 +1811,7 @@ error_undo:
772.34582 - 
772.34583 - error_out:
772.34584 - 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
772.34585 --		   strerror(errno));
772.34586 -+		   strerror(err));
772.34587 - 
772.34588 - 	mode->flip_count = 0;
772.34589 - 	return FALSE;
772.34590 -@@ -1839,7 +1885,7 @@ intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), v
772.34591 - /*
772.34592 -  * Abort by drm queue sequence number
772.34593 -  */
772.34594 --static void
772.34595 -+void
772.34596 - intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
772.34597 - {
772.34598 - 	struct intel_drm_queue *q;
772.34599 -@@ -1911,7 +1957,6 @@ intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
772.34600 - {
772.34601 - 	struct intel_crtc *intel_crtc = crtc->driver_private;
772.34602 - 
772.34603 --        sequence += intel_crtc->vblank_offset;
772.34604 -         if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000)
772.34605 -                 intel_crtc->msc_high += 0x100000000L;
772.34606 -         intel_crtc->msc_prev = sequence;
772.34607 -@@ -1935,37 +1980,10 @@ intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64
772.34608 -         return 0;
772.34609 - }
772.34610 - 
772.34611 --/*
772.34612 -- * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number,
772.34613 -- * removing the high 32 bits and subtracting out the vblank_offset term.
772.34614 -- *
772.34615 -- * This also updates the vblank_offset when it notices that the value should
772.34616 -- * change.
772.34617 -- */
772.34618 --
772.34619 --#define MAX_VBLANK_OFFSET       1000
772.34620 --
772.34621 - uint32_t
772.34622 - intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
772.34623 - {
772.34624 --	struct intel_crtc *intel_crtc = crtc->driver_private;
772.34625 --        uint64_t msc, ust;
772.34626 --
772.34627 --	if (intel_get_crtc_msc_ust(scrn, crtc, &msc, &ust) == 0) {
772.34628 --		int64_t diff = expect - msc;
772.34629 --
772.34630 --		/* We're way off here, assume that the kernel has lost its mind
772.34631 --		 * and smack the vblank back to something sensible
772.34632 --		 */
772.34633 --		if (diff < -MAX_VBLANK_OFFSET || diff > MAX_VBLANK_OFFSET) {
772.34634 --			intel_crtc->vblank_offset += (int32_t) diff;
772.34635 --			if (intel_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
772.34636 --			    intel_crtc->vblank_offset < MAX_VBLANK_OFFSET)
772.34637 --				intel_crtc->vblank_offset = 0;
772.34638 --		}
772.34639 --	}
772.34640 --
772.34641 --        return (uint32_t) (expect - intel_crtc->vblank_offset);
772.34642 -+        return (uint32_t)expect;
772.34643 - }
772.34644 - 
772.34645 - /*
772.34646 -@@ -1998,14 +2016,13 @@ intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *use
772.34647 - static void
772.34648 - intel_pageflip_complete(struct intel_mode *mode)
772.34649 - {
772.34650 --	/* Release framebuffer */
772.34651 --	drmModeRmFB(mode->fd, mode->old_fb_id);
772.34652 --
772.34653 --	if (!mode->pageflip_handler)
772.34654 -+	if (!mode->pageflip.handler)
772.34655 - 		return;
772.34656 - 
772.34657 --	mode->pageflip_handler(mode->fe_msc, mode->fe_usec,
772.34658 --			       mode->pageflip_data);
772.34659 -+	/* Release framebuffer */
772.34660 -+	drmModeRmFB(mode->fd, mode->old_fb_id);
772.34661 -+	mode->pageflip.handler(mode->fe_msc, mode->fe_usec,
772.34662 -+			       mode->pageflip.data);
772.34663 - }
772.34664 - 
772.34665 - /*
772.34666 -@@ -2045,6 +2062,7 @@ intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
772.34667 - 
772.34668 - 	if (!mode)
772.34669 - 		return;
772.34670 -+
772.34671 - 	intel_pageflip_complete(mode);
772.34672 - }
772.34673 - 
772.34674 -@@ -2060,18 +2078,18 @@ intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
772.34675 - 	if (!mode)
772.34676 - 		return;
772.34677 - 
772.34678 --	/* Release framebuffer */
772.34679 --	drmModeRmFB(mode->fd, mode->old_fb_id);
772.34680 --
772.34681 --	if (!mode->pageflip_abort)
772.34682 -+	if (!mode->pageflip.abort)
772.34683 - 		return;
772.34684 - 
772.34685 --	mode->pageflip_abort(mode->pageflip_data);
772.34686 -+	/* Release framebuffer */
772.34687 -+	drmModeRmFB(mode->fd, mode->old_fb_id);
772.34688 -+	mode->pageflip.abort(mode->pageflip.data);
772.34689 - }
772.34690 - 
772.34691 - /*
772.34692 -  * Check for pending DRM events and process them.
772.34693 -  */
772.34694 -+#if !HAVE_NOTIFY_FD
772.34695 - static void
772.34696 - drm_wakeup_handler(pointer data, int err, pointer p)
772.34697 - {
772.34698 -@@ -2086,6 +2104,14 @@ drm_wakeup_handler(pointer data, int err, pointer p)
772.34699 - 	if (FD_ISSET(mode->fd, read_mask))
772.34700 - 		drmHandleEvent(mode->fd, &mode->event_context);
772.34701 - }
772.34702 -+#else
772.34703 -+static void
772.34704 -+drm_notify_fd(int fd, int ready, void *data)
772.34705 -+{
772.34706 -+	struct intel_mode *mode = data;
772.34707 -+	drmHandleEvent(mode->fd, &mode->event_context);
772.34708 -+}
772.34709 -+#endif
772.34710 - 
772.34711 - /*
772.34712 -  * If there are any available, read drm_events
772.34713 -@@ -2231,10 +2257,6 @@ Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
772.34714 - 		intel->use_pageflipping = TRUE;
772.34715 - 	}
772.34716 - 
772.34717 --	if (xf86ReturnOptValBool(intel->Options, OPTION_DELETE_DP12, FALSE)) {
772.34718 --		mode->delete_dp_12_displays = TRUE;
772.34719 --	}
772.34720 --
772.34721 - 	intel->modes = mode;
772.34722 - 	drmModeFreeResources(mode_res);
772.34723 - 	return TRUE;
772.34724 -@@ -2250,9 +2272,11 @@ intel_mode_init(struct intel_screen_private *intel)
772.34725 - 	 * registration within ScreenInit and not PreInit.
772.34726 - 	 */
772.34727 - 	mode->flip_count = 0;
772.34728 --	AddGeneralSocket(mode->fd);
772.34729 -+	SetNotifyFd(mode->fd, drm_notify_fd, X_NOTIFY_READ, mode);
772.34730 -+#if !HAVE_NOTIFY_FD
772.34731 - 	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
772.34732 - 				       drm_wakeup_handler, mode);
772.34733 -+#endif
772.34734 - }
772.34735 - 
772.34736 - void
772.34737 -@@ -2276,9 +2300,11 @@ intel_mode_close(intel_screen_private *intel)
772.34738 - 
772.34739 -         intel_drm_abort_scrn(intel->scrn);
772.34740 - 
772.34741 -+#if !HAVE_NOTIFY_FD
772.34742 - 	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
772.34743 - 				     drm_wakeup_handler, mode);
772.34744 --	RemoveGeneralSocket(mode->fd);
772.34745 -+#endif
772.34746 -+	RemoveNotifyFd(mode->fd);
772.34747 - }
772.34748 - 
772.34749 - void
772.34750 -@@ -2498,12 +2524,11 @@ intel_mode_hotplug(struct intel_screen_private *intel)
772.34751 - 	int i, j;
772.34752 - 	Bool found;
772.34753 - 	Bool changed = FALSE;
772.34754 --	struct intel_mode *mode = intel->modes;
772.34755 -+
772.34756 - 	mode_res = drmModeGetResources(intel->drmSubFD);
772.34757 - 	if (!mode_res)
772.34758 - 		goto out;
772.34759 - 
772.34760 --restart_destroy:
772.34761 - 	for (i = 0; i < config->num_output; i++) {
772.34762 - 		xf86OutputPtr output = config->output[i];
772.34763 - 		struct intel_output *intel_output;
772.34764 -@@ -2522,13 +2547,9 @@ restart_destroy:
772.34765 - 		drmModeFreeConnector(intel_output->mode_output);
772.34766 - 		intel_output->mode_output = NULL;
772.34767 - 		intel_output->output_id = -1;
772.34768 -+		RROutputChanged(output->randr_output, TRUE);
772.34769 - 
772.34770 - 		changed = TRUE;
772.34771 --		if (mode->delete_dp_12_displays) {
772.34772 --			RROutputDestroy(output->randr_output);
772.34773 --			xf86OutputDestroy(output);
772.34774 --			goto restart_destroy;
772.34775 --		}
772.34776 - 	}
772.34777 - 
772.34778 - 	/* find new output ids we don't have outputs for */
772.34779 -@@ -2552,10 +2573,8 @@ restart_destroy:
772.34780 - 		intel_output_init(scrn, intel->modes, mode_res, i, 1);
772.34781 - 	}
772.34782 - 
772.34783 --	if (changed) {
772.34784 --		RRSetChanged(xf86ScrnToScreen(scrn));
772.34785 -+	if (changed)
772.34786 - 		RRTellChanged(xf86ScrnToScreen(scrn));
772.34787 --	}
772.34788 - 
772.34789 - 	drmModeFreeResources(mode_res);
772.34790 - out:
772.34791 -diff --git a/src/uxa/intel_dri.c b/src/uxa/intel_dri.c
772.34792 -index f61c6210..524826d2 100644
772.34793 ---- a/src/uxa/intel_dri.c
772.34794 -+++ b/src/uxa/intel_dri.c
772.34795 -@@ -81,6 +81,47 @@ static DevPrivateKeyRec i830_client_key;
772.34796 - static int i830_client_key;
772.34797 - #endif
772.34798 - 
772.34799 -+static void I830DRI2FlipEventHandler(unsigned int frame,
772.34800 -+				     unsigned int tv_sec,
772.34801 -+				     unsigned int tv_usec,
772.34802 -+				     DRI2FrameEventPtr flip_info);
772.34803 -+
772.34804 -+static void I830DRI2FrameEventHandler(unsigned int frame,
772.34805 -+				      unsigned int tv_sec,
772.34806 -+				      unsigned int tv_usec,
772.34807 -+				      DRI2FrameEventPtr swap_info);
772.34808 -+
772.34809 -+static void
772.34810 -+i830_dri2_del_frame_event(DRI2FrameEventPtr info);
772.34811 -+
772.34812 -+static uint32_t pipe_select(int pipe)
772.34813 -+{
772.34814 -+	if (pipe > 1)
772.34815 -+		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
772.34816 -+	else if (pipe > 0)
772.34817 -+		return DRM_VBLANK_SECONDARY;
772.34818 -+	else
772.34819 -+		return 0;
772.34820 -+}
772.34821 -+
772.34822 -+static void
772.34823 -+intel_dri2_vblank_handler(ScrnInfoPtr scrn,
772.34824 -+                          xf86CrtcPtr crtc,
772.34825 -+                          uint64_t msc,
772.34826 -+                          uint64_t usec,
772.34827 -+                          void *data)
772.34828 -+{
772.34829 -+        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, data);
772.34830 -+}
772.34831 -+
772.34832 -+static void
772.34833 -+intel_dri2_vblank_abort(ScrnInfoPtr scrn,
772.34834 -+                        xf86CrtcPtr crtc,
772.34835 -+                        void *data)
772.34836 -+{
772.34837 -+        i830_dri2_del_frame_event(data);
772.34838 -+}
772.34839 -+
772.34840 - static uint32_t pixmap_flink(PixmapPtr pixmap)
772.34841 - {
772.34842 - 	struct intel_uxa_pixmap *priv = intel_uxa_get_pixmap_private(pixmap);
772.34843 -@@ -135,9 +176,6 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
772.34844 - 		pixmap = NULL;
772.34845 - 		if (attachments[i] == DRI2BufferFrontLeft) {
772.34846 - 			pixmap = get_front_buffer(drawable);
772.34847 --
772.34848 --			if (pixmap == NULL)
772.34849 --				drawable = &(get_drawable_pixmap(drawable)->drawable);
772.34850 - 		} else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) {
772.34851 - 			pixmap = pDepthPixmap;
772.34852 - 			pixmap->refcnt++;
772.34853 -@@ -246,11 +284,8 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
772.34854 - 	}
772.34855 - 
772.34856 - 	pixmap = NULL;
772.34857 --	if (attachment == DRI2BufferFrontLeft) {
772.34858 -+	if (attachment == DRI2BufferFrontLeft)
772.34859 - 		pixmap = get_front_buffer(drawable);
772.34860 --		if (pixmap == NULL)
772.34861 --			drawable = &(get_drawable_pixmap(drawable)->drawable);
772.34862 --	}
772.34863 - 
772.34864 - 	if (pixmap == NULL) {
772.34865 - 		unsigned int hint = INTEL_CREATE_PIXMAP_DRI2;
772.34866 -@@ -673,6 +708,20 @@ i830_dri2_del_frame_event(DRI2FrameEventPtr info)
772.34867 - 	if (info->back)
772.34868 - 		I830DRI2DestroyBuffer(NULL, info->back);
772.34869 - 
772.34870 -+	if (info->old_buffer) {
772.34871 -+		/* Check that the old buffer still matches the front buffer
772.34872 -+		 * in case a mode change occurred before we woke up.
772.34873 -+		 */
772.34874 -+		if (info->intel->back_buffer == NULL &&
772.34875 -+		    info->old_width  == info->intel->scrn->virtualX &&
772.34876 -+		    info->old_height == info->intel->scrn->virtualY &&
772.34877 -+		    info->old_pitch  == info->intel->front_pitch &&
772.34878 -+		    info->old_tiling == info->intel->front_tiling)
772.34879 -+			info->intel->back_buffer = info->old_buffer;
772.34880 -+		else
772.34881 -+			dri_bo_unreference(info->old_buffer);
772.34882 -+	}
772.34883 -+
772.34884 - 	free(info);
772.34885 - }
772.34886 - 
772.34887 -@@ -708,16 +757,14 @@ static void
772.34888 - I830DRI2ExchangeBuffers(struct intel_screen_private *intel, DRI2BufferPtr front, DRI2BufferPtr back)
772.34889 - {
772.34890 - 	I830DRI2BufferPrivatePtr front_priv, back_priv;
772.34891 --	int tmp;
772.34892 - 	struct intel_uxa_pixmap *new_front;
772.34893 - 
772.34894 - 	front_priv = front->driverPrivate;
772.34895 - 	back_priv = back->driverPrivate;
772.34896 - 
772.34897 - 	/* Swap BO names so DRI works */
772.34898 --	tmp = front->name;
772.34899 - 	front->name = back->name;
772.34900 --	back->name = tmp;
772.34901 -+	back->name = pixmap_flink(front_priv->pixmap);
772.34902 - 
772.34903 - 	/* Swap pixmap bos */
772.34904 - 	new_front = intel_exchange_pixmap_buffers(intel,
772.34905 -@@ -753,87 +800,30 @@ I830DRI2FlipAbort(void *pageflip_data)
772.34906 -         i830_dri2_del_frame_event(info);
772.34907 - }
772.34908 - 
772.34909 --/*
772.34910 -- * Our internal swap routine takes care of actually exchanging, blitting, or
772.34911 -- * flipping buffers as necessary.
772.34912 -- */
772.34913 - static Bool
772.34914 --I830DRI2ScheduleFlip(struct intel_screen_private *intel,
772.34915 --		     DrawablePtr draw,
772.34916 --		     DRI2FrameEventPtr info)
772.34917 -+allocate_back_buffer(struct intel_screen_private *intel)
772.34918 - {
772.34919 --	I830DRI2BufferPrivatePtr priv = info->back->driverPrivate;
772.34920 --	drm_intel_bo *new_back, *old_back;
772.34921 --	int tmp_name;
772.34922 --
772.34923 --	if (!intel->use_triple_buffer) {
772.34924 --		info->type = DRI2_SWAP;
772.34925 --		if (!intel_do_pageflip(intel,
772.34926 --				       get_pixmap_bo(priv),
772.34927 --				       info->pipe, FALSE, info,
772.34928 --                                       I830DRI2FlipComplete,
772.34929 --                                       I830DRI2FlipAbort))
772.34930 --			return FALSE;
772.34931 --
772.34932 --		I830DRI2ExchangeBuffers(intel, info->front, info->back);
772.34933 --		return TRUE;
772.34934 --	}
772.34935 -+	drm_intel_bo *bo;
772.34936 -+	int pitch;
772.34937 -+	uint32_t tiling;
772.34938 - 
772.34939 --	if (intel->pending_flip[info->pipe]) {
772.34940 --		assert(intel->pending_flip[info->pipe]->chain == NULL);
772.34941 --		intel->pending_flip[info->pipe]->chain = info;
772.34942 -+	if (intel->back_buffer)
772.34943 - 		return TRUE;
772.34944 --	}
772.34945 - 
772.34946 --	if (intel->back_buffer == NULL) {
772.34947 --		new_back = drm_intel_bo_alloc(intel->bufmgr, "front buffer",
772.34948 --					      intel->front_buffer->size, 0);
772.34949 --		if (new_back == NULL)
772.34950 --			return FALSE;
772.34951 --
772.34952 --		if (intel->front_tiling != I915_TILING_NONE) {
772.34953 --			uint32_t tiling = intel->front_tiling;
772.34954 --			drm_intel_bo_set_tiling(new_back, &tiling, intel->front_pitch);
772.34955 --			if (tiling != intel->front_tiling) {
772.34956 --				drm_intel_bo_unreference(new_back);
772.34957 --				return FALSE;
772.34958 --			}
772.34959 --		}
772.34960 --
772.34961 --		drm_intel_bo_disable_reuse(new_back);
772.34962 --		dri_bo_flink(new_back, &intel->back_name);
772.34963 --	} else {
772.34964 --		new_back = intel->back_buffer;
772.34965 --		intel->back_buffer = NULL;
772.34966 --	}
772.34967 -+	bo = intel_allocate_framebuffer(intel->scrn,
772.34968 -+					intel->scrn->virtualX,
772.34969 -+					intel->scrn->virtualY,
772.34970 -+					intel->cpp,
772.34971 -+					&pitch, &tiling);
772.34972 -+	if (bo == NULL)
772.34973 -+		return FALSE;
772.34974 - 
772.34975 --	old_back = get_pixmap_bo(priv);
772.34976 --	if (!intel_do_pageflip(intel, old_back, info->pipe, FALSE, info, I830DRI2FlipComplete, I830DRI2FlipAbort)) {
772.34977 --		intel->back_buffer = new_back;
772.34978 -+	if (pitch != intel->front_pitch || tiling != intel->front_tiling) {
772.34979 -+		drm_intel_bo_unreference(bo);
772.34980 - 		return FALSE;
772.34981 - 	}
772.34982 --	info->type = DRI2_SWAP_CHAIN;
772.34983 --	intel->pending_flip[info->pipe] = info;
772.34984 --
772.34985 --	priv = info->front->driverPrivate;
772.34986 --
772.34987 --	/* Exchange the current front-buffer with the fresh bo */
772.34988 --
772.34989 --	intel->back_buffer = intel->front_buffer;
772.34990 --	drm_intel_bo_reference(intel->back_buffer);
772.34991 --	intel_set_pixmap_bo(priv->pixmap, new_back);
772.34992 --	drm_intel_bo_unreference(new_back);
772.34993 --
772.34994 --	tmp_name = info->front->name;
772.34995 --	info->front->name = intel->back_name;
772.34996 --	intel->back_name = tmp_name;
772.34997 - 
772.34998 --	/* Then flip DRI2 pointers and update the screen pixmap */
772.34999 --	I830DRI2ExchangeBuffers(intel, info->front, info->back);
772.35000 --	DRI2SwapComplete(info->client, draw, 0, 0, 0,
772.35001 --			 DRI2_EXCHANGE_COMPLETE,
772.35002 --			 info->event_complete,
772.35003 --			 info->event_data);
772.35004 -+	intel->back_buffer = bo;
772.35005 - 	return TRUE;
772.35006 - }
772.35007 - 
772.35008 -@@ -889,8 +879,88 @@ can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
772.35009 - 	return TRUE;
772.35010 - }
772.35011 - 
772.35012 --void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
772.35013 --			       unsigned int tv_usec, DRI2FrameEventPtr swap_info)
772.35014 -+static Bool
772.35015 -+queue_flip(struct intel_screen_private *intel,
772.35016 -+	   DrawablePtr draw,
772.35017 -+	   DRI2FrameEventPtr info)
772.35018 -+{
772.35019 -+	xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
772.35020 -+	I830DRI2BufferPrivatePtr priv = info->back->driverPrivate;
772.35021 -+	drm_intel_bo *old_back = get_pixmap_bo(priv);
772.35022 -+
772.35023 -+	if (crtc == NULL)
772.35024 -+		return FALSE;
772.35025 -+
772.35026 -+	if (!can_exchange(draw, info->front, info->back))
772.35027 -+		return FALSE;
772.35028 -+
772.35029 -+	if (!intel_do_pageflip(intel, old_back,
772.35030 -+			       intel_crtc_to_pipe(crtc),
772.35031 -+			       FALSE, info,
772.35032 -+			       I830DRI2FlipComplete, I830DRI2FlipAbort))
772.35033 -+		return FALSE;
772.35034 -+
772.35035 -+#if DRI2INFOREC_VERSION >= 6
772.35036 -+	if (intel->use_triple_buffer && allocate_back_buffer(intel)) {
772.35037 -+		info->old_width  = intel->scrn->virtualX;
772.35038 -+		info->old_height = intel->scrn->virtualY;
772.35039 -+		info->old_pitch  = intel->front_pitch;
772.35040 -+		info->old_tiling = intel->front_tiling;
772.35041 -+		info->old_buffer = intel->front_buffer;
772.35042 -+		dri_bo_reference(info->old_buffer);
772.35043 -+
772.35044 -+		priv = info->front->driverPrivate;
772.35045 -+		intel_set_pixmap_bo(priv->pixmap, intel->back_buffer);
772.35046 -+
772.35047 -+		dri_bo_unreference(intel->back_buffer);
772.35048 -+		intel->back_buffer = NULL;
772.35049 -+
772.35050 -+		DRI2SwapLimit(draw, 2);
772.35051 -+	} else
772.35052 -+		DRI2SwapLimit(draw, 1);
772.35053 -+#endif
772.35054 -+
772.35055 -+	/* Then flip DRI2 pointers and update the screen pixmap */
772.35056 -+	I830DRI2ExchangeBuffers(intel, info->front, info->back);
772.35057 -+	return TRUE;
772.35058 -+}
772.35059 -+
772.35060 -+static Bool
772.35061 -+queue_swap(struct intel_screen_private *intel,
772.35062 -+	   DrawablePtr draw,
772.35063 -+	   DRI2FrameEventPtr info)
772.35064 -+{
772.35065 -+	xf86CrtcPtr crtc = I830DRI2DrawableCrtc(draw);
772.35066 -+	drmVBlank vbl;
772.35067 -+
772.35068 -+	if (crtc == NULL)
772.35069 -+		return FALSE;
772.35070 -+
772.35071 -+	vbl.request.type =
772.35072 -+		DRM_VBLANK_RELATIVE |
772.35073 -+		DRM_VBLANK_EVENT |
772.35074 -+		pipe_select(intel_crtc_to_pipe(crtc));
772.35075 -+	vbl.request.sequence = 1;
772.35076 -+	vbl.request.signal =
772.35077 -+		intel_drm_queue_alloc(intel->scrn, crtc, info,
772.35078 -+				      intel_dri2_vblank_handler,
772.35079 -+				      intel_dri2_vblank_abort);
772.35080 -+	if (vbl.request.signal == 0)
772.35081 -+		return FALSE;
772.35082 -+
772.35083 -+	info->type = DRI2_SWAP;
772.35084 -+	if (drmWaitVBlank(intel->drmSubFD, &vbl)) {
772.35085 -+		intel_drm_abort_seq(intel->scrn, vbl.request.signal);
772.35086 -+		return FALSE;
772.35087 -+	}
772.35088 -+
772.35089 -+	return TRUE;
772.35090 -+}
772.35091 -+
772.35092 -+static void I830DRI2FrameEventHandler(unsigned int frame,
772.35093 -+				      unsigned int tv_sec,
772.35094 -+				      unsigned int tv_usec,
772.35095 -+				      DRI2FrameEventPtr swap_info)
772.35096 - {
772.35097 - 	intel_screen_private *intel = swap_info->intel;
772.35098 - 	DrawablePtr drawable;
772.35099 -@@ -906,24 +976,22 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
772.35100 - 		return;
772.35101 - 	}
772.35102 - 
772.35103 --
772.35104 - 	switch (swap_info->type) {
772.35105 - 	case DRI2_FLIP:
772.35106 - 		/* If we can still flip... */
772.35107 --		if (can_exchange(drawable, swap_info->front, swap_info->back) &&
772.35108 --		    I830DRI2ScheduleFlip(intel, drawable, swap_info))
772.35109 --			return;
772.35110 --
772.35111 --		/* else fall through to exchange/blit */
772.35112 --	case DRI2_SWAP: {
772.35113 --		I830DRI2FallbackBlitSwap(drawable,
772.35114 --					 swap_info->front, swap_info->back);
772.35115 --		DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
772.35116 --				 DRI2_BLIT_COMPLETE,
772.35117 --				 swap_info->client ? swap_info->event_complete : NULL,
772.35118 --				 swap_info->event_data);
772.35119 --		break;
772.35120 --	}
772.35121 -+		if (!queue_flip(intel, drawable, swap_info) &&
772.35122 -+		    !queue_swap(intel, drawable, swap_info)) {
772.35123 -+		case DRI2_SWAP:
772.35124 -+			I830DRI2FallbackBlitSwap(drawable,
772.35125 -+						 swap_info->front, swap_info->back);
772.35126 -+			DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
772.35127 -+					 DRI2_BLIT_COMPLETE,
772.35128 -+					 swap_info->client ? swap_info->event_complete : NULL,
772.35129 -+					 swap_info->event_data);
772.35130 -+			break;
772.35131 -+		}
772.35132 -+		return;
772.35133 -+
772.35134 - 	case DRI2_WAITMSC:
772.35135 - 		if (swap_info->client)
772.35136 - 			DRI2WaitMSCComplete(swap_info->client, drawable,
772.35137 -@@ -939,12 +1007,13 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
772.35138 - 	i830_dri2_del_frame_event(swap_info);
772.35139 - }
772.35140 - 
772.35141 --void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
772.35142 --			      unsigned int tv_usec, DRI2FrameEventPtr flip_info)
772.35143 -+static void I830DRI2FlipEventHandler(unsigned int frame,
772.35144 -+				     unsigned int tv_sec,
772.35145 -+				     unsigned int tv_usec,
772.35146 -+				     DRI2FrameEventPtr flip_info)
772.35147 - {
772.35148 - 	struct intel_screen_private *intel = flip_info->intel;
772.35149 - 	DrawablePtr drawable;
772.35150 --	DRI2FrameEventPtr chain;
772.35151 - 
772.35152 - 	drawable = NULL;
772.35153 - 	if (flip_info->drawable_id)
772.35154 -@@ -954,6 +1023,7 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
772.35155 - 
772.35156 - 	/* We assume our flips arrive in order, so we don't check the frame */
772.35157 - 	switch (flip_info->type) {
772.35158 -+	case DRI2_FLIP:
772.35159 - 	case DRI2_SWAP:
772.35160 - 		if (!drawable)
772.35161 - 			break;
772.35162 -@@ -984,35 +1054,6 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
772.35163 - 				 flip_info->event_data);
772.35164 - 		break;
772.35165 - 
772.35166 --	case DRI2_SWAP_CHAIN:
772.35167 --		assert(intel->pending_flip[flip_info->pipe] == flip_info);
772.35168 --		intel->pending_flip[flip_info->pipe] = NULL;
772.35169 --
772.35170 --		chain = flip_info->chain;
772.35171 --		if (chain) {
772.35172 --			DrawablePtr chain_drawable = NULL;
772.35173 --			if (chain->drawable_id)
772.35174 --				 dixLookupDrawable(&chain_drawable,
772.35175 --						   chain->drawable_id,
772.35176 --						   serverClient,
772.35177 --						   M_ANY, DixWriteAccess);
772.35178 --			if (chain_drawable == NULL) {
772.35179 --				i830_dri2_del_frame_event(chain);
772.35180 --			} else if (!can_exchange(chain_drawable, chain->front, chain->back) ||
772.35181 --				   !I830DRI2ScheduleFlip(intel, chain_drawable, chain)) {
772.35182 --				I830DRI2FallbackBlitSwap(chain_drawable,
772.35183 --							 chain->front,
772.35184 --							 chain->back);
772.35185 --
772.35186 --				DRI2SwapComplete(chain->client, chain_drawable, frame, tv_sec, tv_usec,
772.35187 --						 DRI2_BLIT_COMPLETE,
772.35188 --						 chain->client ? chain->event_complete : NULL,
772.35189 --						 chain->event_data);
772.35190 --				i830_dri2_del_frame_event(chain);
772.35191 --			}
772.35192 --		}
772.35193 --		break;
772.35194 --
772.35195 - 	default:
772.35196 - 		xf86DrvMsg(intel->scrn->scrnIndex, X_WARNING,
772.35197 - 			   "%s: unknown vblank event received\n", __func__);
772.35198 -@@ -1023,38 +1064,6 @@ void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
772.35199 - 	i830_dri2_del_frame_event(flip_info);
772.35200 - }
772.35201 - 
772.35202 --static uint32_t pipe_select(int pipe)
772.35203 --{
772.35204 --	if (pipe > 1)
772.35205 --		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
772.35206 --	else if (pipe > 0)
772.35207 --		return DRM_VBLANK_SECONDARY;
772.35208 --	else
772.35209 --		return 0;
772.35210 --}
772.35211 --
772.35212 --static void
772.35213 --intel_dri2_vblank_handler(ScrnInfoPtr scrn,
772.35214 --                          xf86CrtcPtr crtc,
772.35215 --                          uint64_t msc,
772.35216 --                          uint64_t usec,
772.35217 --                          void *data)
772.35218 --{
772.35219 --        DRI2FrameEventPtr swap_info = data;
772.35220 --
772.35221 --        I830DRI2FrameEventHandler((uint32_t) msc, usec / 1000000, usec % 1000000, swap_info);
772.35222 --}
772.35223 --
772.35224 --static void
772.35225 --intel_dri2_vblank_abort(ScrnInfoPtr scrn,
772.35226 --                        xf86CrtcPtr crtc,
772.35227 --                        void *data)
772.35228 --{
772.35229 --        DRI2FrameEventPtr swap_info = data;
772.35230 --
772.35231 --        i830_dri2_del_frame_event(swap_info);
772.35232 --}
772.35233 --
772.35234 - /*
772.35235 -  * ScheduleSwap is responsible for requesting a DRM vblank event for the
772.35236 -  * appropriate frame.
772.35237 -@@ -1089,7 +1098,6 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35238 -         int pipe = crtc ? intel_crtc_to_pipe(crtc) : -1;
772.35239 -         int flip = 0;
772.35240 - 	DRI2FrameEventPtr swap_info = NULL;
772.35241 --	enum DRI2FrameEventType swap_type = DRI2_SWAP;
772.35242 - 	uint64_t current_msc, current_ust;
772.35243 -         uint64_t request_msc;
772.35244 -         uint32_t seq;
772.35245 -@@ -1109,7 +1117,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35246 - 	swap_info->event_data = data;
772.35247 - 	swap_info->front = front;
772.35248 - 	swap_info->back = back;
772.35249 --	swap_info->pipe = pipe;
772.35250 -+	swap_info->type = DRI2_SWAP;
772.35251 - 
772.35252 - 	if (!i830_dri2_add_frame_event(swap_info)) {
772.35253 - 	    free(swap_info);
772.35254 -@@ -1124,20 +1132,27 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35255 - 	if (ret)
772.35256 - 	    goto blit_fallback;
772.35257 - 
772.35258 --	/* Flips need to be submitted one frame before */
772.35259 -+	/*
772.35260 -+	 * If we can, schedule the flip directly from here rather
772.35261 -+	 * than waiting for an event from the kernel for the current
772.35262 -+	 * (or a past) MSC.
772.35263 -+	 */
772.35264 -+	if (divisor == 0 &&
772.35265 -+	    current_msc >= *target_msc &&
772.35266 -+	    queue_flip(intel, draw, swap_info))
772.35267 -+		return TRUE;
772.35268 -+
772.35269 - 	if (can_exchange(draw, front, back)) {
772.35270 --	    swap_type = DRI2_FLIP;
772.35271 --	    flip = 1;
772.35272 -+		swap_info->type = DRI2_FLIP;
772.35273 -+		/* Flips need to be submitted one frame before */
772.35274 -+		if (*target_msc > 0)
772.35275 -+			--*target_msc;
772.35276 -+		flip = 1;
772.35277 - 	}
772.35278 - 
772.35279 --	swap_info->type = swap_type;
772.35280 --
772.35281 --	/* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
772.35282 --	 * Do it early, so handling of different timing constraints
772.35283 --	 * for divisor, remainder and msc vs. target_msc works.
772.35284 --	 */
772.35285 --	if (*target_msc > 0)
772.35286 --		*target_msc -= flip;
772.35287 -+#if DRI2INFOREC_VERSION >= 6
772.35288 -+	DRI2SwapLimit(draw, 1);
772.35289 -+#endif
772.35290 - 
772.35291 - 	/*
772.35292 - 	 * If divisor is zero, or current_msc is smaller than target_msc
772.35293 -@@ -1145,15 +1160,6 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35294 - 	 * the swap.
772.35295 - 	 */
772.35296 - 	if (divisor == 0 || current_msc < *target_msc) {
772.35297 --		/*
772.35298 --		 * If we can, schedule the flip directly from here rather
772.35299 --		 * than waiting for an event from the kernel for the current
772.35300 --		 * (or a past) MSC.
772.35301 --		 */
772.35302 --		if (flip && divisor == 0 && current_msc >= *target_msc &&
772.35303 --		    I830DRI2ScheduleFlip(intel, draw, swap_info))
772.35304 --			return TRUE;
772.35305 --
772.35306 - 		vbl.request.type =
772.35307 - 			DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | pipe_select(pipe);
772.35308 - 
772.35309 -@@ -1168,7 +1174,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35310 - 		 * current_msc to ensure we return a reasonable value back
772.35311 - 		 * to the caller. This makes swap_interval logic more robust.
772.35312 - 		 */
772.35313 --		if (current_msc >= *target_msc)
772.35314 -+		if (current_msc > *target_msc)
772.35315 - 			*target_msc = current_msc;
772.35316 - 
772.35317 -                 seq = intel_drm_queue_alloc(scrn, crtc, swap_info, intel_dri2_vblank_handler, intel_dri2_vblank_abort);
772.35318 -@@ -1183,6 +1189,8 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
772.35319 - 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
772.35320 - 				   "divisor 0 get vblank counter failed: %s\n",
772.35321 - 				   strerror(errno));
772.35322 -+			intel_drm_abort_seq(intel->scrn, seq);
772.35323 -+			swap_info = NULL;
772.35324 - 			goto blit_fallback;
772.35325 - 		}
772.35326 - 
772.35327 -@@ -1332,7 +1340,6 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
772.35328 - 
772.35329 - 	if (!i830_dri2_add_frame_event(wait_info)) {
772.35330 - 	    free(wait_info);
772.35331 --	    wait_info = NULL;
772.35332 - 	    goto out_complete;
772.35333 - 	}
772.35334 - 
772.35335 -@@ -1374,7 +1381,8 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
772.35336 - 					   strerror(errno));
772.35337 - 				limit--;
772.35338 - 			}
772.35339 --			goto out_free;
772.35340 -+			intel_drm_abort_seq(intel->scrn, seq);
772.35341 -+			goto out_complete;
772.35342 - 		}
772.35343 - 
772.35344 - 		wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
772.35345 -@@ -1417,7 +1425,8 @@ I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
772.35346 - 				   strerror(errno));
772.35347 - 			limit--;
772.35348 - 		}
772.35349 --		goto out_free;
772.35350 -+		intel_drm_abort_seq(intel->scrn, seq);
772.35351 -+		goto out_complete;
772.35352 - 	}
772.35353 - 
772.35354 - 	wait_info->frame = intel_sequence_to_crtc_msc(crtc, vbl.reply.sequence);
772.35355 -@@ -1440,13 +1449,92 @@ static int has_i830_dri(void)
772.35356 - 	return access(DRI_DRIVER_PATH "/i830_dri.so", R_OK) == 0;
772.35357 - }
772.35358 - 
772.35359 --static const char *dri_driver_name(intel_screen_private *intel)
772.35360 -+static int
772.35361 -+namecmp(const char *s1, const char *s2)
772.35362 -+{
772.35363 -+	char c1, c2;
772.35364 -+
772.35365 -+	if (!s1 || *s1 == 0) {
772.35366 -+		if (!s2 || *s2 == 0)
772.35367 -+			return 0;
772.35368 -+		else
772.35369 -+			return 1;
772.35370 -+	}
772.35371 -+
772.35372 -+	while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.35373 -+		s1++;
772.35374 -+
772.35375 -+	while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.35376 -+		s2++;
772.35377 -+
772.35378 -+	c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.35379 -+	c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.35380 -+	while (c1 == c2) {
772.35381 -+		if (c1 == '\0')
772.35382 -+			return 0;
772.35383 -+
772.35384 -+		s1++;
772.35385 -+		while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
772.35386 -+			s1++;
772.35387 -+
772.35388 -+		s2++;
772.35389 -+		while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
772.35390 -+			s2++;
772.35391 -+
772.35392 -+		c1 = isupper(*s1) ? tolower(*s1) : *s1;
772.35393 -+		c2 = isupper(*s2) ? tolower(*s2) : *s2;
772.35394 -+	}
772.35395 -+
772.35396 -+	return c1 - c2;
772.35397 -+}
772.35398 -+
772.35399 -+static Bool is_level(const char **str)
772.35400 -+{
772.35401 -+	const char *s = *str;
772.35402 -+	char *end;
772.35403 -+	unsigned val;
772.35404 -+
772.35405 -+	if (s == NULL || *s == '\0')
772.35406 -+		return TRUE;
772.35407 -+
772.35408 -+	if (namecmp(s, "on") == 0)
772.35409 -+		return TRUE;
772.35410 -+	if (namecmp(s, "true") == 0)
772.35411 -+		return TRUE;
772.35412 -+	if (namecmp(s, "yes") == 0)
772.35413 -+		return TRUE;
772.35414 -+
772.35415 -+	if (namecmp(s, "0") == 0)
772.35416 -+		return TRUE;
772.35417 -+	if (namecmp(s, "off") == 0)
772.35418 -+		return TRUE;
772.35419 -+	if (namecmp(s, "false") == 0)
772.35420 -+		return TRUE;
772.35421 -+	if (namecmp(s, "no") == 0)
772.35422 -+		return TRUE;
772.35423 -+
772.35424 -+	val = strtoul(s, &end, 0);
772.35425 -+	if (val && *end == '\0')
772.35426 -+		return TRUE;
772.35427 -+	if (val && *end == ':')
772.35428 -+		*str = end + 1;
772.35429 -+	return FALSE;
772.35430 -+}
772.35431 -+
772.35432 -+static const char *options_get_dri(intel_screen_private *intel)
772.35433 - {
772.35434 - #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.35435 --	const char *s = xf86GetOptValString(intel->Options, OPTION_DRI);
772.35436 --	Bool dummy;
772.35437 -+	return xf86GetOptValString(intel->Options, OPTION_DRI);
772.35438 -+#else
772.35439 -+	return NULL;
772.35440 -+#endif
772.35441 -+}
772.35442 - 
772.35443 --	if (s == NULL || xf86getBoolValue(&dummy, s)) {
772.35444 -+static const char *dri_driver_name(intel_screen_private *intel)
772.35445 -+{
772.35446 -+	const char *s = options_get_dri(intel);
772.35447 -+
772.35448 -+	if (is_level(&s)) {
772.35449 - 		if (INTEL_INFO(intel)->gen < 030)
772.35450 - 			return has_i830_dri() ? "i830" : "i915";
772.35451 - 		else if (INTEL_INFO(intel)->gen < 040)
772.35452 -@@ -1456,14 +1544,6 @@ static const char *dri_driver_name(intel_screen_private *intel)
772.35453 - 	}
772.35454 - 
772.35455 - 	return s;
772.35456 --#else
772.35457 --	if (INTEL_INFO(intel)->gen < 030)
772.35458 --		return has_i830_dri() ? "i830" : "i915";
772.35459 --	else if (INTEL_INFO(intel)->gen < 040)
772.35460 --		return "i915";
772.35461 --	else
772.35462 --		return "i965";
772.35463 --#endif
772.35464 - }
772.35465 - 
772.35466 - Bool I830DRI2ScreenInit(ScreenPtr screen)
772.35467 -@@ -1544,7 +1624,7 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
772.35468 - 	info.numDrivers = 2;
772.35469 - 	info.driverNames = driverNames;
772.35470 - 	driverNames[0] = info.driverName;
772.35471 --	driverNames[1] = info.driverName;
772.35472 -+	driverNames[1] = "va_gl";
772.35473 - #endif
772.35474 - 
772.35475 - 	return DRI2ScreenInit(screen, &info);
772.35476 -diff --git a/src/uxa/intel_driver.c b/src/uxa/intel_driver.c
772.35477 -index 2793da5d..3703c412 100644
772.35478 ---- a/src/uxa/intel_driver.c
772.35479 -+++ b/src/uxa/intel_driver.c
772.35480 -@@ -237,24 +237,17 @@ static Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
772.35481 - 	return TRUE;
772.35482 - }
772.35483 - 
772.35484 --static Bool intel_option_cast_string_to_bool(intel_screen_private *intel,
772.35485 --					     int id, Bool val)
772.35486 --{
772.35487 --#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,99,901,0)
772.35488 --	xf86getBoolValue(&val, xf86GetOptValString(intel->Options, id));
772.35489 --	return val;
772.35490 --#else
772.35491 --	return val;
772.35492 --#endif
772.35493 --}
772.35494 --
772.35495 - static void intel_check_dri_option(ScrnInfoPtr scrn)
772.35496 - {
772.35497 - 	intel_screen_private *intel = intel_get_screen_private(scrn);
772.35498 -+	unsigned level;
772.35499 - 
772.35500 - 	intel->dri2 = intel->dri3 = DRI_NONE;
772.35501 --	if (!intel_option_cast_string_to_bool(intel, OPTION_DRI, TRUE))
772.35502 --		intel->dri2 = intel->dri3 = DRI_DISABLED;
772.35503 -+	level = intel_option_cast_to_unsigned(intel->Options, OPTION_DRI, DEFAULT_DRI_LEVEL);
772.35504 -+	if (level < 3 || INTEL_INFO(intel)->gen < 040)
772.35505 -+		intel->dri3 = DRI_DISABLED;
772.35506 -+	if (level < 2)
772.35507 -+		intel->dri2 = DRI_DISABLED;
772.35508 - 
772.35509 - 	if (scrn->depth != 16 && scrn->depth != 24 && scrn->depth != 30) {
772.35510 - 		xf86DrvMsg(scrn->scrnIndex, X_CONFIG,
772.35511 -@@ -371,8 +364,8 @@ static Bool can_accelerate_blt(struct intel_screen_private *intel)
772.35512 - 	if (INTEL_INFO(intel)->gen == -1)
772.35513 - 		return FALSE;
772.35514 - 
772.35515 --	if (xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_DISABLE, FALSE) ||
772.35516 --	    !intel_option_cast_string_to_bool(intel, OPTION_ACCEL_METHOD, TRUE)) {
772.35517 -+	if (!xf86ReturnOptValBool(intel->Options, OPTION_ACCEL_ENABLE, TRUE) ||
772.35518 -+	    !intel_option_cast_to_bool(intel->Options, OPTION_ACCEL_METHOD, TRUE)) {
772.35519 - 		xf86DrvMsg(intel->scrn->scrnIndex, X_CONFIG,
772.35520 - 			   "Disabling hardware acceleration.\n");
772.35521 - 		return FALSE;
772.35522 -@@ -659,8 +652,9 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
772.35523 - }
772.35524 - 
772.35525 - static void
772.35526 --intel_dirty_update(ScreenPtr screen)
772.35527 -+intel_dirty_update(intel_screen_private *intel)
772.35528 - {
772.35529 -+	ScreenPtr screen = xf86ScrnToScreen(intel->scrn);
772.35530 - 	RegionPtr region;
772.35531 - 	PixmapDirtyUpdatePtr ent;
772.35532 - 
772.35533 -@@ -677,6 +671,7 @@ intel_dirty_update(ScreenPtr screen)
772.35534 - }
772.35535 - #endif
772.35536 - 
772.35537 -+#if !HAVE_NOTIFY_FD
772.35538 - static void
772.35539 - I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
772.35540 - {
772.35541 -@@ -694,9 +689,22 @@ I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
772.35542 - 	intel_uxa_block_handler(intel);
772.35543 - 	intel_video_block_handler(intel);
772.35544 - #ifdef INTEL_PIXMAP_SHARING
772.35545 --	intel_dirty_update(screen);
772.35546 -+	intel_dirty_update(intel);
772.35547 - #endif
772.35548 - }
772.35549 -+#else
772.35550 -+static void
772.35551 -+I830BlockHandler(void *data, void *timeout)
772.35552 -+{
772.35553 -+	intel_screen_private *intel = data;
772.35554 -+
772.35555 -+	intel_uxa_block_handler(intel);
772.35556 -+	intel_video_block_handler(intel);
772.35557 -+#ifdef INTEL_PIXMAP_SHARING
772.35558 -+	intel_dirty_update(intel);
772.35559 -+#endif
772.35560 -+}
772.35561 -+#endif
772.35562 - 
772.35563 - static Bool
772.35564 - intel_init_initial_framebuffer(ScrnInfoPtr scrn)
772.35565 -@@ -735,6 +743,8 @@ intel_flush_callback(CallbackListPtr *list,
772.35566 - }
772.35567 - 
772.35568 - #if HAVE_UDEV
772.35569 -+#include <sys/stat.h>
772.35570 -+
772.35571 - static void
772.35572 - I830HandleUEvents(int fd, void *closure)
772.35573 - {
772.35574 -@@ -771,6 +781,15 @@ I830HandleUEvents(int fd, void *closure)
772.35575 - 	udev_device_unref(dev);
772.35576 - }
772.35577 - 
772.35578 -+static int has_randr(void)
772.35579 -+{
772.35580 -+#if HAS_DIXREGISTERPRIVATEKEY
772.35581 -+	return dixPrivateKeyRegistered(rrPrivKey);
772.35582 -+#else
772.35583 -+	return *rrPrivKey;
772.35584 -+#endif
772.35585 -+}
772.35586 -+
772.35587 - static void
772.35588 - I830UeventInit(ScrnInfoPtr scrn)
772.35589 - {
772.35590 -@@ -780,6 +799,10 @@ I830UeventInit(ScrnInfoPtr scrn)
772.35591 - 	Bool hotplug;
772.35592 - 	MessageType from = X_CONFIG;
772.35593 - 
772.35594 -+	/* Without RR, nothing we can do here */
772.35595 -+	if (!has_randr())
772.35596 -+		return;
772.35597 -+
772.35598 - 	if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
772.35599 - 		from = X_DEFAULT;
772.35600 - 		hotplug = TRUE;
772.35601 -@@ -939,8 +962,14 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL)
772.35602 - 			   "Hardware cursor initialization failed\n");
772.35603 - 	}
772.35604 - 
772.35605 -+#if !HAVE_NOTIFY_FD
772.35606 - 	intel->BlockHandler = screen->BlockHandler;
772.35607 - 	screen->BlockHandler = I830BlockHandler;
772.35608 -+#else
772.35609 -+	RegisterBlockAndWakeupHandlers(I830BlockHandler,
772.35610 -+				       (ServerWakeupHandlerProcPtr)NoopDDA,
772.35611 -+				       intel);
772.35612 -+#endif
772.35613 - 
772.35614 - #ifdef INTEL_PIXMAP_SHARING
772.35615 - 	screen->StartPixmapTracking = PixmapStartDirtyTracking;
772.35616 -@@ -1164,8 +1193,6 @@ static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
772.35617 - 
772.35618 - 	intel_sync_close(screen);
772.35619 - 
772.35620 --	xf86GARTCloseScreen(scrn->scrnIndex);
772.35621 --
772.35622 - 	scrn->vtSema = FALSE;
772.35623 - 	return TRUE;
772.35624 - }
772.35625 -diff --git a/src/uxa/intel_hwmc.c b/src/uxa/intel_hwmc.c
772.35626 -index 829cb8e0..78540600 100644
772.35627 ---- a/src/uxa/intel_hwmc.c
772.35628 -+++ b/src/uxa/intel_hwmc.c
772.35629 -@@ -193,7 +193,7 @@ Bool intel_xvmc_adaptor_init(ScreenPtr pScreen)
772.35630 - 	intel_screen_private *intel = intel_get_screen_private(scrn);
772.35631 - 	struct pci_device *pci;
772.35632 - 	static XF86MCAdaptorRec *pAdapt;
772.35633 --	char *name;
772.35634 -+	const char *name;
772.35635 - 	char buf[64];
772.35636 - 
772.35637 - 	if (!intel->XvMCEnabled)
772.35638 -diff --git a/src/uxa/intel_memory.c b/src/uxa/intel_memory.c
772.35639 -index 0c6cf30c..b2d7a367 100644
772.35640 ---- a/src/uxa/intel_memory.c
772.35641 -+++ b/src/uxa/intel_memory.c
772.35642 -@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
772.35643 -  * This is the video memory allocator.  Our memory allocation is different from
772.35644 -  * other graphics chips, where you have a fixed amount of graphics memory
772.35645 -  * available that you want to put to the best use.  Instead, we have almost no
772.35646 -- * memory pre-allocated, and we have to choose an appropriate amount of sytem
772.35647 -+ * memory pre-allocated, and we have to choose an appropriate amount of system
772.35648 -  * memory to use.
772.35649 -  *
772.35650 -  * The allocations we might do:
772.35651 -diff --git a/src/uxa/intel_present.c b/src/uxa/intel_present.c
772.35652 -index d20043f3..ac028edd 100644
772.35653 ---- a/src/uxa/intel_present.c
772.35654 -+++ b/src/uxa/intel_present.c
772.35655 -@@ -244,6 +244,7 @@ intel_present_check_flip(RRCrtcPtr              crtc,
772.35656 - 	ScrnInfoPtr             scrn = xf86ScreenToScrn(screen);
772.35657 - 	intel_screen_private    *intel = intel_get_screen_private(scrn);
772.35658 -         dri_bo                  *bo;
772.35659 -+	uint32_t		tiling, swizzle;
772.35660 - 
772.35661 - 	if (!scrn->vtSema)
772.35662 - 		return FALSE;
772.35663 -@@ -266,6 +267,12 @@ intel_present_check_flip(RRCrtcPtr              crtc,
772.35664 -         if (!bo)
772.35665 -                 return FALSE;
772.35666 - 
772.35667 -+	if (drm_intel_bo_get_tiling(bo, &tiling, &swizzle))
772.35668 -+		return FALSE;
772.35669 -+
772.35670 -+	if (tiling == I915_TILING_Y)
772.35671 -+		return FALSE;
772.35672 -+
772.35673 - 	return TRUE;
772.35674 - }
772.35675 - 
772.35676 -@@ -343,29 +350,33 @@ intel_present_unflip(ScreenPtr screen, uint64_t event_id)
772.35677 - {
772.35678 - 	ScrnInfoPtr                             scrn = xf86ScreenToScrn(screen);
772.35679 - 	intel_screen_private                    *intel = intel_get_screen_private(scrn);
772.35680 --	struct intel_present_vblank_event       *event;
772.35681 - 	PixmapPtr                               pixmap = screen->GetScreenPixmap(screen);
772.35682 -+	struct intel_present_vblank_event       *event = NULL;
772.35683 - 	dri_bo                                  *bo;
772.35684 --	Bool                                    ret;
772.35685 - 
772.35686 - 	if (!intel_present_check_flip(NULL, screen->root, pixmap, true))
772.35687 --		return;
772.35688 -+		goto fail;
772.35689 - 
772.35690 - 	bo = intel_get_pixmap_bo(pixmap);
772.35691 - 	if (!bo)
772.35692 --		return;
772.35693 -+		goto fail;
772.35694 - 
772.35695 - 	event = calloc(1, sizeof(struct intel_present_vblank_event));
772.35696 - 	if (!event)
772.35697 --		return;
772.35698 -+		goto fail;
772.35699 - 
772.35700 - 	event->event_id = event_id;
772.35701 - 
772.35702 --	ret = intel_do_pageflip(intel, bo, -1, FALSE, event, intel_present_flip_event, intel_present_flip_abort);
772.35703 --	if (!ret) {
772.35704 --		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
772.35705 --			   "present unflip failed\n");
772.35706 --	}
772.35707 -+	if (!intel_do_pageflip(intel, bo, -1, FALSE, event,
772.35708 -+			       intel_present_flip_event,
772.35709 -+			       intel_present_flip_abort))
772.35710 -+		goto fail;
772.35711 -+
772.35712 -+	return;
772.35713 -+fail:
772.35714 -+	xf86SetDesiredModes(scrn);
772.35715 -+	present_event_notify(event_id, 0, 0);
772.35716 -+	free(event);
772.35717 - }
772.35718 - 
772.35719 - static present_screen_info_rec intel_present_screen_info = {
772.35720 -diff --git a/src/uxa/intel_uxa.c b/src/uxa/intel_uxa.c
772.35721 -index 590ff5d1..ec32a723 100644
772.35722 ---- a/src/uxa/intel_uxa.c
772.35723 -+++ b/src/uxa/intel_uxa.c
772.35724 -@@ -176,6 +176,24 @@ intel_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask)
772.35725 - 	return TRUE;
772.35726 - }
772.35727 - 
772.35728 -+static Bool
772.35729 -+intel_uxa_check_bo_tiling(intel_screen_private *intel,
772.35730 -+			  PixmapPtr pixmap,
772.35731 -+			  unsigned *tiling_out)
772.35732 -+{
772.35733 -+	struct intel_uxa_pixmap *priv;
772.35734 -+
772.35735 -+	priv = intel_uxa_get_pixmap_private(pixmap);
772.35736 -+	if (!priv)
772.35737 -+		return FALSE;
772.35738 -+
772.35739 -+	if (priv->tiling == I915_TILING_Y && INTEL_INFO(intel)->gen < 060)
772.35740 -+		return FALSE;
772.35741 -+
772.35742 -+	*tiling_out = priv->tiling;
772.35743 -+	return TRUE;
772.35744 -+}
772.35745 -+
772.35746 - /**
772.35747 -  * Sets up hardware state for a series of solid fills.
772.35748 -  */
772.35749 -@@ -189,6 +207,9 @@ intel_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
772.35750 - 		intel_uxa_get_pixmap_bo(pixmap),
772.35751 - 	};
772.35752 - 
772.35753 -+	if (!intel_uxa_check_bo_tiling(intel, pixmap, &intel->BR_tiling[0]))
772.35754 -+		return FALSE;
772.35755 -+
772.35756 - 	if (!intel_uxa_check_pitch_2d(pixmap))
772.35757 - 		return FALSE;
772.35758 - 
772.35759 -@@ -236,7 +257,7 @@ static void intel_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
772.35760 - 
772.35761 - 	{
772.35762 - 		int len = INTEL_INFO(intel)->gen >= 0100 ? 7 : 6;
772.35763 --		BEGIN_BATCH_BLT(len);
772.35764 -+		BEGIN_BATCH_BLT_TILED(len);
772.35765 - 
772.35766 - 		cmd = XY_COLOR_BLT_CMD | (len - 2);
772.35767 - 
772.35768 -@@ -310,6 +331,10 @@ intel_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
772.35769 - 		intel_uxa_get_pixmap_bo(dest),
772.35770 - 	};
772.35771 - 
772.35772 -+	if (!intel_uxa_check_bo_tiling(intel, dest, &intel->BR_tiling[0]) ||
772.35773 -+	    !intel_uxa_check_bo_tiling(intel, source, &intel->BR_tiling[1]))
772.35774 -+		return FALSE;
772.35775 -+
772.35776 - 	if (!intel_uxa_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
772.35777 - 		return FALSE;
772.35778 - 
772.35779 -@@ -375,7 +400,7 @@ intel_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
772.35780 - 
772.35781 - 	{
772.35782 - 		int len = INTEL_INFO(intel)->gen >= 0100 ? 10 : 8;
772.35783 --		BEGIN_BATCH_BLT(len);
772.35784 -+		BEGIN_BATCH_BLT_TILED(len);
772.35785 - 
772.35786 - 		cmd = XY_SRC_COPY_BLT_CMD | (len - 2);
772.35787 - 
772.35788 -@@ -1068,7 +1093,7 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
772.35789 - 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
772.35790 - 	PixmapPtr pixmap;
772.35791 - 	intel_screen_private *intel = intel_get_screen_private(scrn);
772.35792 --	dri_bo *bo = intel->front_buffer;
772.35793 -+	dri_bo *bo = intel->front_buffer, *old_bo;
772.35794 - 	int old_width, old_height, old_pitch;
772.35795 - 
772.35796 - 	if (!uxa_resources_init(screen))
772.35797 -@@ -1081,6 +1106,7 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
772.35798 - 	old_width = pixmap->drawable.width;
772.35799 - 	old_height = pixmap->drawable.height;
772.35800 - 	old_pitch = pixmap->devKind;
772.35801 -+	old_bo = intel_uxa_get_pixmap_bo(pixmap);
772.35802 - 
772.35803 - 	if (!screen->ModifyPixmapHeader(pixmap,
772.35804 - 					scrn->virtualX,
772.35805 -@@ -1102,6 +1128,9 @@ Bool intel_uxa_create_screen_resources(ScreenPtr screen)
772.35806 - err:
772.35807 - 	screen->ModifyPixmapHeader(pixmap,
772.35808 - 				   old_width, old_height, -1, -1, old_pitch, NULL);
772.35809 -+	if (old_bo)
772.35810 -+		intel_uxa_set_pixmap_bo(pixmap, old_bo);
772.35811 -+
772.35812 - 	return FALSE;
772.35813 - }
772.35814 - 
772.35815 -diff --git a/test/Makefile.am b/test/Makefile.am
772.35816 -index 66ed8ebb..12b5d5d8 100644
772.35817 ---- a/test/Makefile.am
772.35818 -+++ b/test/Makefile.am
772.35819 -@@ -5,6 +5,7 @@ stress_TESTS = \
772.35820 - 	basic-rectangle \
772.35821 - 	basic-string \
772.35822 - 	basic-copyarea \
772.35823 -+	basic-copyplane \
772.35824 - 	basic-copyarea-size \
772.35825 - 	basic-putimage \
772.35826 - 	basic-lines \
772.35827 -@@ -12,8 +13,10 @@ stress_TESTS = \
772.35828 - 	DrawSegments \
772.35829 - 	cursor-test \
772.35830 - 	render-fill \
772.35831 -+	render-glyphs \
772.35832 - 	render-trapezoid \
772.35833 - 	render-trapezoid-image \
772.35834 -+	render-triangle \
772.35835 - 	render-fill-copy \
772.35836 - 	render-composite-solid \
772.35837 - 	render-composite-solid-mask \
772.35838 -@@ -25,9 +28,16 @@ stress_TESTS = \
772.35839 - 	shm-test \
772.35840 - 	$(NULL)
772.35841 - 
772.35842 -+if X11_VM
772.35843 -+stress_TESTS += \
772.35844 -+	xvidmode \
772.35845 -+	$(NULL)
772.35846 -+endif
772.35847 -+
772.35848 - if DRI2
772.35849 - stress_TESTS += \
772.35850 - 	dri2-race \
772.35851 -+	dri2-speed \
772.35852 - 	dri2-swap \
772.35853 - 	dri2-test \
772.35854 - 	$(NULL)
772.35855 -@@ -36,8 +46,11 @@ endif
772.35856 - if X11_DRI3
772.35857 - stress_TESTS += \
772.35858 - 	dri3-test \
772.35859 -+	present-race \
772.35860 -+	present-speed \
772.35861 - 	present-test \
772.35862 - 	$(NULL)
772.35863 -+present_speed_CFLAGS = ${AM_CFLAGS} -pthread
772.35864 - endif
772.35865 - check_PROGRAMS = $(stress_TESTS)
772.35866 - 
772.35867 -diff --git a/test/basic-copyplane.c b/test/basic-copyplane.c
772.35868 -new file mode 100644
772.35869 -index 00000000..f049b82b
772.35870 ---- /dev/null
772.35871 -+++ b/test/basic-copyplane.c
772.35872 -@@ -0,0 +1,99 @@
772.35873 -+#include <stdint.h>
772.35874 -+#include <stdio.h>
772.35875 -+#include <stdlib.h>
772.35876 -+
772.35877 -+#include <X11/Xutil.h> /* for XDestroyImage */
772.35878 -+#include <pixman.h> /* for pixman blt functions */
772.35879 -+
772.35880 -+#include "test.h"
772.35881 -+
772.35882 -+static uint8_t clock_bits[] = {0x3C, 0x5E, 0xEF, 0xF7, 0x87, 0xFF, 0x7E, 0x3C};
772.35883 -+
772.35884 -+/* https://bugs.freedesktop.org/show_bug.cgi?id=91499 */
772.35885 -+static void draw_clock(struct test_display *t, Drawable d,
772.35886 -+		       uint8_t alu, int x, int y, uint32_t fg, uint32_t bg)
772.35887 -+{
772.35888 -+	Pixmap pixmap;
772.35889 -+	XGCValues val;
772.35890 -+	GC gc;
772.35891 -+
772.35892 -+	val.graphics_exposures = 0;
772.35893 -+	val.function = alu;
772.35894 -+	val.foreground = fg;
772.35895 -+	val.background = fg;
772.35896 -+
772.35897 -+	gc = XCreateGC(t->dpy, d,
772.35898 -+		       GCGraphicsExposures | GCForeground | GCBackground | GCFunction,
772.35899 -+		       &val);
772.35900 -+	pixmap = XCreateBitmapFromData(t->dpy, d, (char *)clock_bits, 8, 8);
772.35901 -+
772.35902 -+	XCopyPlane(t->dpy, pixmap, d, gc, 0, 0, 8, 8, x, y, 1);
772.35903 -+
772.35904 -+	XFreePixmap(t->dpy, pixmap);
772.35905 -+	XFreeGC(t->dpy, gc);
772.35906 -+}
772.35907 -+
772.35908 -+static void clear(struct test_display *dpy, struct test_target *tt)
772.35909 -+{
772.35910 -+	XRenderColor render_color = {0};
772.35911 -+	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
772.35912 -+			     0, 0, tt->width, tt->height);
772.35913 -+}
772.35914 -+
772.35915 -+static void clock_tests(struct test *t, int reps, int sets, enum target target)
772.35916 -+{
772.35917 -+	struct test_target out, ref;
772.35918 -+	int r, s;
772.35919 -+
772.35920 -+	printf("Testing clock (%s): ", test_target_name(target));
772.35921 -+	fflush(stdout);
772.35922 -+
772.35923 -+	test_target_create_render(&t->out, target, &out);
772.35924 -+	clear(&t->out, &out);
772.35925 -+
772.35926 -+	test_target_create_render(&t->ref, target, &ref);
772.35927 -+	clear(&t->ref, &ref);
772.35928 -+
772.35929 -+	for (s = 0; s < sets; s++) {
772.35930 -+		for (r = 0; r < reps; r++) {
772.35931 -+			int x = rand() % (out.width - 8);
772.35932 -+			int y = rand() % (out.height - 8);
772.35933 -+			uint8_t alu = rand() % (GXset + 1);
772.35934 -+			uint32_t bg = rand();
772.35935 -+			uint32_t fg = rand();
772.35936 -+
772.35937 -+			draw_clock(&t->out, out.draw, alu, x, y, fg, bg);
772.35938 -+			draw_clock(&t->ref, ref.draw, alu, x, y, fg, bg);
772.35939 -+		}
772.35940 -+
772.35941 -+		test_compare(t,
772.35942 -+			     out.draw, out.format,
772.35943 -+			     ref.draw, ref.format,
772.35944 -+			     0, 0, out.width, out.height,
772.35945 -+			     "");
772.35946 -+	}
772.35947 -+
772.35948 -+	printf("passed [%d iterations x %d]\n", reps, sets);
772.35949 -+
772.35950 -+	test_target_destroy_render(&t->out, &out);
772.35951 -+	test_target_destroy_render(&t->ref, &ref);
772.35952 -+}
772.35953 -+
772.35954 -+int main(int argc, char **argv)
772.35955 -+{
772.35956 -+	struct test test;
772.35957 -+	int i;
772.35958 -+
772.35959 -+	test_init(&test, argc, argv);
772.35960 -+
772.35961 -+	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
772.35962 -+		int reps = REPS(i), sets = SETS(i);
772.35963 -+		enum target t;
772.35964 -+
772.35965 -+		for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
772.35966 -+			clock_tests(&test, reps, sets, t);
772.35967 -+		}
772.35968 -+	}
772.35969 -+
772.35970 -+	return 0;
772.35971 -+}
772.35972 -diff --git a/test/dri2-race.c b/test/dri2-race.c
772.35973 -index 8862c84c..ece624f6 100644
772.35974 ---- a/test/dri2-race.c
772.35975 -+++ b/test/dri2-race.c
772.35976 -@@ -5,6 +5,11 @@
772.35977 - #include <X11/Xlib.h>
772.35978 - #include <X11/Xutil.h>
772.35979 - #include <X11/extensions/Xfixes.h>
772.35980 -+#include <X11/extensions/Xcomposite.h>
772.35981 -+#include <X11/Xlib-xcb.h>
772.35982 -+#include <xcb/xcb.h>
772.35983 -+#include <xcb/xcbext.h>
772.35984 -+#include <xcb/dri2.h>
772.35985 - #include <unistd.h>
772.35986 - #include <fcntl.h>
772.35987 - #include <string.h>
772.35988 -@@ -12,11 +17,49 @@
772.35989 - 
772.35990 - #include <xf86drm.h>
772.35991 - #include <drm.h>
772.35992 -+#include <setjmp.h>
772.35993 - 
772.35994 - #include "dri2.h"
772.35995 - 
772.35996 - #define COUNT 60
772.35997 - 
772.35998 -+#define N_DIVISORS 3
772.35999 -+static const int divisors[N_DIVISORS] = { 0, 1, 16 };
772.36000 -+
772.36001 -+static jmp_buf error_handler[4];
772.36002 -+static int have_error_handler;
772.36003 -+
772.36004 -+#define error_get() \
772.36005 -+	setjmp(error_handler[have_error_handler++])
772.36006 -+
772.36007 -+#define error_put() \
772.36008 -+	have_error_handler--
772.36009 -+
772.36010 -+static int (*saved_io_error)(Display *dpy);
772.36011 -+
772.36012 -+static int io_error(Display *dpy)
772.36013 -+{
772.36014 -+	if (have_error_handler)
772.36015 -+		longjmp(error_handler[--have_error_handler], 0);
772.36016 -+
772.36017 -+	return saved_io_error(dpy);
772.36018 -+}
772.36019 -+
772.36020 -+static int x_error(Display *dpy, XErrorEvent *e)
772.36021 -+{
772.36022 -+	return Success;
772.36023 -+}
772.36024 -+
772.36025 -+static uint32_t upper_32_bits(uint64_t val)
772.36026 -+{
772.36027 -+	return val >> 32;
772.36028 -+}
772.36029 -+
772.36030 -+static uint32_t lower_32_bits(uint64_t val)
772.36031 -+{
772.36032 -+	return val & 0xffffffff;
772.36033 -+}
772.36034 -+
772.36035 - static int dri2_open(Display *dpy)
772.36036 - {
772.36037 - 	drm_auth_t auth;
772.36038 -@@ -41,45 +84,701 @@ static int dri2_open(Display *dpy)
772.36039 - 	return fd;
772.36040 - }
772.36041 - 
772.36042 --static void run(Display *dpy, int width, int height,
772.36043 --		unsigned int *attachments, int nattachments,
772.36044 --		const char *name)
772.36045 -+static void swap_buffers(Display *dpy, Window win, int divisor,
772.36046 -+			 unsigned int *attachments, int nattachments)
772.36047 -+{
772.36048 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.36049 -+	unsigned int seq[2];
772.36050 -+
772.36051 -+	seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
772.36052 -+						 0, 0, 0, divisor, 0, 0).sequence;
772.36053 -+
772.36054 -+
772.36055 -+	seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
772.36056 -+						nattachments, nattachments,
772.36057 -+						attachments).sequence;
772.36058 -+
772.36059 -+	xcb_flush(c);
772.36060 -+	xcb_discard_reply(c, seq[0]);
772.36061 -+	xcb_discard_reply(c, seq[1]);
772.36062 -+}
772.36063 -+
772.36064 -+#define COMPOSITE 1
772.36065 -+
772.36066 -+static int has_composite(Display *dpy)
772.36067 -+{
772.36068 -+	Display *dummy = NULL;
772.36069 -+	int event, error;
772.36070 -+	int major = -1, minor = -1;
772.36071 -+
772.36072 -+	if (dpy == NULL)
772.36073 -+		dummy = dpy = XOpenDisplay(NULL);
772.36074 -+
772.36075 -+	if (XCompositeQueryExtension(dpy, &event, &error))
772.36076 -+		XCompositeQueryVersion(dpy, &major, &minor);
772.36077 -+
772.36078 -+	if (dummy)
772.36079 -+		XCloseDisplay(dummy);
772.36080 -+
772.36081 -+	return major > 0 || minor >= 4;
772.36082 -+}
772.36083 -+
772.36084 -+static void race_window(Display *dpy, int width, int height,
772.36085 -+			unsigned int *attachments, int nattachments,
772.36086 -+			unsigned flags, const char *name)
772.36087 - {
772.36088 - 	Window win;
772.36089 - 	XSetWindowAttributes attr;
772.36090 --	int count, loop;
772.36091 -+	int count, loop, n;
772.36092 - 	DRI2Buffer *buffers;
772.36093 - 
772.36094 -+	if (flags & COMPOSITE && !has_composite(dpy))
772.36095 -+		return;
772.36096 -+
772.36097 -+	printf("%s(%s)\n", __func__, name);
772.36098 -+
772.36099 - 	/* Be nasty and install a fullscreen window on top so that we
772.36100 - 	 * can guarantee we do not get clipped by children.
772.36101 - 	 */
772.36102 - 	attr.override_redirect = 1;
772.36103 --	loop = 100;
772.36104 --	do {
772.36105 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36106 -+		loop = 256 >> ffs(divisors[n]);
772.36107 -+		printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop);
772.36108 -+		fflush(stdout);
772.36109 -+		do {
772.36110 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36111 -+					0, 0, width, height, 0,
772.36112 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36113 -+					InputOutput,
772.36114 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36115 -+					CWOverrideRedirect, &attr);
772.36116 -+			if (flags & COMPOSITE)
772.36117 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36118 -+			XMapWindow(dpy, win);
772.36119 -+
772.36120 -+			DRI2CreateDrawable(dpy, win);
772.36121 -+
772.36122 -+			buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.36123 -+					attachments, nattachments, &count);
772.36124 -+			if (count != nattachments)
772.36125 -+				return;
772.36126 -+
772.36127 -+			free(buffers);
772.36128 -+			for (count = 0; count < loop; count++)
772.36129 -+				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
772.36130 -+			XDestroyWindow(dpy, win);
772.36131 -+			printf("."); fflush(stdout);
772.36132 -+		} while (--loop);
772.36133 -+		printf("*\n");
772.36134 -+	}
772.36135 -+
772.36136 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36137 -+		loop = 256 >> ffs(divisors[n]);
772.36138 -+		printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop);
772.36139 -+		fflush(stdout);
772.36140 -+		do {
772.36141 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36142 -+					0, 0, width, height, 0,
772.36143 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36144 -+					InputOutput,
772.36145 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36146 -+					CWOverrideRedirect, &attr);
772.36147 -+			if (flags & COMPOSITE)
772.36148 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36149 -+			XMapWindow(dpy, win);
772.36150 -+
772.36151 -+			DRI2CreateDrawable(dpy, win);
772.36152 -+
772.36153 -+			buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.36154 -+					attachments, nattachments, &count);
772.36155 -+			if (count != nattachments)
772.36156 -+				return;
772.36157 -+
772.36158 -+			free(buffers);
772.36159 -+			for (count = 0; count < loop; count++)
772.36160 -+				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
772.36161 -+			XDestroyWindow(dpy, win);
772.36162 -+			printf("."); fflush(stdout);
772.36163 -+		} while (--loop);
772.36164 -+		printf("*\n");
772.36165 -+	}
772.36166 -+
772.36167 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36168 -+		loop = 256 >> ffs(divisors[n]);
772.36169 -+		printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop);
772.36170 -+		fflush(stdout);
772.36171 -+		do {
772.36172 -+			uint64_t ignore, msc;
772.36173 -+			xcb_connection_t *c = XGetXCBConnection(dpy);
772.36174 -+
772.36175 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36176 -+					0, 0, width, height, 0,
772.36177 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36178 -+					InputOutput,
772.36179 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36180 -+					CWOverrideRedirect, &attr);
772.36181 -+			if (flags & COMPOSITE)
772.36182 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36183 -+			XMapWindow(dpy, win);
772.36184 -+
772.36185 -+			DRI2CreateDrawable(dpy, win);
772.36186 -+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
772.36187 -+			msc++;
772.36188 -+			for (count = 0; count < loop; count++) {
772.36189 -+				xcb_discard_reply(c,
772.36190 -+						xcb_dri2_wait_msc(c, win,
772.36191 -+							upper_32_bits(msc),
772.36192 -+							lower_32_bits(msc),
772.36193 -+							0, 0, 0, 0).sequence);
772.36194 -+				msc += divisors[n];
772.36195 -+			}
772.36196 -+			XFlush(dpy);
772.36197 -+			XDestroyWindow(dpy, win);
772.36198 -+			printf("."); fflush(stdout);
772.36199 -+		} while (--loop);
772.36200 -+		printf("*\n");
772.36201 -+	}
772.36202 -+
772.36203 -+	XSync(dpy, 1);
772.36204 -+	sleep(2);
772.36205 -+	XSync(dpy, 1);
772.36206 -+}
772.36207 -+
772.36208 -+static int rand_size(int max)
772.36209 -+{
772.36210 -+	return 1 + (rand() % (max - 1));
772.36211 -+}
772.36212 -+
772.36213 -+static void race_resize(Display *dpy, int width, int height,
772.36214 -+			unsigned int *attachments, int nattachments,
772.36215 -+			unsigned flags, const char *name)
772.36216 -+{
772.36217 -+	Window win;
772.36218 -+	XSetWindowAttributes attr;
772.36219 -+	int count, loop, n;
772.36220 -+	DRI2Buffer *buffers;
772.36221 -+
772.36222 -+	if (flags & COMPOSITE && !has_composite(dpy))
772.36223 -+		return;
772.36224 -+
772.36225 -+	printf("%s(%s)\n", __func__, name);
772.36226 -+
772.36227 -+	attr.override_redirect = 1;
772.36228 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36229 -+		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36230 -+				    0, 0, width, height, 0,
772.36231 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36232 -+				    InputOutput,
772.36233 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36234 -+				    CWOverrideRedirect, &attr);
772.36235 -+		if (flags & COMPOSITE)
772.36236 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36237 -+		XMapWindow(dpy, win);
772.36238 -+
772.36239 -+		DRI2CreateDrawable(dpy, win);
772.36240 -+
772.36241 -+		loop = 256 >> ffs(divisors[n]);
772.36242 -+		printf("DRI2SwapBuffers(divisor=%d), loop=%d", divisors[n], loop);
772.36243 -+		fflush(stdout);
772.36244 -+		do {
772.36245 -+			int w, h;
772.36246 -+
772.36247 -+			buffers = DRI2GetBuffers(dpy, win, &w, &h,
772.36248 -+					attachments, nattachments, &count);
772.36249 -+			if (count != nattachments)
772.36250 -+				return;
772.36251 -+
772.36252 -+			free(buffers);
772.36253 -+			for (count = 0; count < loop; count++)
772.36254 -+				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
772.36255 -+			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
772.36256 -+			printf("."); fflush(stdout);
772.36257 -+		} while (--loop);
772.36258 -+		XDestroyWindow(dpy, win);
772.36259 -+		XSync(dpy, True);
772.36260 -+		printf("*\n");
772.36261 -+	}
772.36262 -+
772.36263 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36264 - 		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36265 - 				    0, 0, width, height, 0,
772.36266 - 				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36267 - 				    InputOutput,
772.36268 - 				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36269 - 				    CWOverrideRedirect, &attr);
772.36270 -+		if (flags & COMPOSITE)
772.36271 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36272 - 		XMapWindow(dpy, win);
772.36273 - 
772.36274 - 		DRI2CreateDrawable(dpy, win);
772.36275 - 
772.36276 --		buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.36277 --					 attachments, nattachments, &count);
772.36278 --		if (count != nattachments)
772.36279 --			return;
772.36280 -+		loop = 256 >> ffs(divisors[n]);
772.36281 -+		printf("xcb_dri2_swap_buffers(divisor=%d), loops=%d", divisors[n], loop);
772.36282 -+		fflush(stdout);
772.36283 -+		do {
772.36284 -+			int w, h;
772.36285 -+
772.36286 -+			buffers = DRI2GetBuffers(dpy, win, &w, &h,
772.36287 -+					attachments, nattachments, &count);
772.36288 -+			if (count != nattachments)
772.36289 -+				return;
772.36290 - 
772.36291 --		free(buffers);
772.36292 --		for (count = 0; count < loop; count++)
772.36293 --			DRI2SwapBuffers(dpy, win, 0, 0, 0);
772.36294 -+			free(buffers);
772.36295 -+			for (count = 0; count < loop; count++)
772.36296 -+				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
772.36297 -+			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
772.36298 -+			printf("."); fflush(stdout);
772.36299 -+		} while (--loop);
772.36300 - 		XDestroyWindow(dpy, win);
772.36301 --	} while (--loop);
772.36302 -+		XSync(dpy, True);
772.36303 -+		printf("*\n");
772.36304 -+	}
772.36305 -+
772.36306 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36307 -+		win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36308 -+				    0, 0, width, height, 0,
772.36309 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36310 -+				    InputOutput,
772.36311 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36312 -+				    CWOverrideRedirect, &attr);
772.36313 -+		if (flags & COMPOSITE)
772.36314 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36315 -+		XMapWindow(dpy, win);
772.36316 -+
772.36317 -+		DRI2CreateDrawable(dpy, win);
772.36318 -+
772.36319 -+		loop = 256 >> ffs(divisors[n]);
772.36320 -+		printf("DRI2WaitMsc(divisor=%d), loop=%d", divisors[n], loop);
772.36321 -+		fflush(stdout);
772.36322 -+		do {
772.36323 -+			uint64_t ignore, msc;
772.36324 -+			xcb_connection_t *c = XGetXCBConnection(dpy);
772.36325 -+
772.36326 -+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
772.36327 -+			msc++;
772.36328 -+			for (count = 0; count < loop; count++) {
772.36329 -+				xcb_discard_reply(c,
772.36330 -+						xcb_dri2_wait_msc(c, win,
772.36331 -+							upper_32_bits(msc),
772.36332 -+							lower_32_bits(msc),
772.36333 -+							0, 0, 0, 0).sequence);
772.36334 -+				msc += divisors[n];
772.36335 -+			}
772.36336 -+			XFlush(dpy);
772.36337 -+			XResizeWindow(dpy, win, rand_size(width), rand_size(height));
772.36338 -+			printf("."); fflush(stdout);
772.36339 -+		} while (--loop);
772.36340 -+		XDestroyWindow(dpy, win);
772.36341 -+		XSync(dpy, True);
772.36342 -+		printf("*\n");
772.36343 -+	}
772.36344 -+
772.36345 -+	XSync(dpy, 1);
772.36346 -+	sleep(2);
772.36347 -+	XSync(dpy, 1);
772.36348 -+}
772.36349 -+
772.36350 -+static void race_manager(Display *dpy, int width, int height,
772.36351 -+			 unsigned int *attachments, int nattachments,
772.36352 -+			 unsigned flags, const char *name)
772.36353 -+{
772.36354 -+	Display *mgr = XOpenDisplay(NULL);
772.36355 -+	Window win;
772.36356 -+	XSetWindowAttributes attr;
772.36357 -+	int count, loop, n;
772.36358 -+	DRI2Buffer *buffers;
772.36359 -+
772.36360 -+	if (flags & COMPOSITE && !has_composite(dpy))
772.36361 -+		return;
772.36362 -+
772.36363 -+	printf("%s(%s)\n", __func__, name);
772.36364 -+
772.36365 -+	/* Be nasty and install a fullscreen window on top so that we
772.36366 -+	 * can guarantee we do not get clipped by children.
772.36367 -+	 */
772.36368 -+	attr.override_redirect = 1;
772.36369 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36370 -+		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
772.36371 -+		fflush(stdout);
772.36372 -+		loop = 256 >> ffs(divisors[n]);
772.36373 -+		do {
772.36374 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36375 -+					0, 0, width, height, 0,
772.36376 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36377 -+					InputOutput,
772.36378 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36379 -+					CWOverrideRedirect, &attr);
772.36380 -+			if (flags & COMPOSITE)
772.36381 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36382 -+			XMapWindow(dpy, win);
772.36383 -+
772.36384 -+			DRI2CreateDrawable(dpy, win);
772.36385 -+
772.36386 -+			buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.36387 -+					attachments, nattachments, &count);
772.36388 -+			if (count != nattachments)
772.36389 -+				return;
772.36390 -+
772.36391 -+			free(buffers);
772.36392 -+			for (count = 0; count < loop; count++)
772.36393 -+				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
772.36394 -+			XFlush(dpy);
772.36395 -+			XDestroyWindow(mgr, win);
772.36396 -+			XFlush(mgr);
772.36397 -+			printf("."); fflush(stdout);
772.36398 -+		} while (--loop);
772.36399 -+		printf("*\n");
772.36400 -+	}
772.36401 -+
772.36402 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36403 -+		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
772.36404 -+		fflush(stdout);
772.36405 -+		loop = 256 >> ffs(divisors[n]);
772.36406 -+		do {
772.36407 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36408 -+					0, 0, width, height, 0,
772.36409 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36410 -+					InputOutput,
772.36411 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36412 -+					CWOverrideRedirect, &attr);
772.36413 -+			if (flags & COMPOSITE)
772.36414 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36415 -+			XMapWindow(dpy, win);
772.36416 -+
772.36417 -+			DRI2CreateDrawable(dpy, win);
772.36418 -+
772.36419 -+			buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.36420 -+					attachments, nattachments, &count);
772.36421 -+			if (count != nattachments)
772.36422 -+				return;
772.36423 -+
772.36424 -+			free(buffers);
772.36425 -+			for (count = 0; count < loop; count++)
772.36426 -+				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
772.36427 -+			XFlush(dpy);
772.36428 -+			XDestroyWindow(mgr, win);
772.36429 -+			XFlush(mgr);
772.36430 -+			printf("."); fflush(stdout);
772.36431 -+		} while (--loop);
772.36432 -+		printf("*\n");
772.36433 -+	}
772.36434 -+
772.36435 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36436 -+		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
772.36437 -+		fflush(stdout);
772.36438 -+		loop = 256 >> ffs(divisors[n]);
772.36439 -+		do {
772.36440 -+			uint64_t ignore, msc;
772.36441 -+			xcb_connection_t *c = XGetXCBConnection(dpy);
772.36442 -+
772.36443 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36444 -+					0, 0, width, height, 0,
772.36445 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36446 -+					InputOutput,
772.36447 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36448 -+					CWOverrideRedirect, &attr);
772.36449 -+			if (flags & COMPOSITE)
772.36450 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36451 -+			XMapWindow(dpy, win);
772.36452 -+
772.36453 -+			DRI2CreateDrawable(dpy, win);
772.36454 -+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
772.36455 -+			msc++;
772.36456 -+			for (count = 0; count < loop; count++) {
772.36457 -+				xcb_discard_reply(c,
772.36458 -+						xcb_dri2_wait_msc(c, win,
772.36459 -+							upper_32_bits(msc),
772.36460 -+							lower_32_bits(msc),
772.36461 -+							0, 0, 0, 0).sequence);
772.36462 -+				msc += divisors[n];
772.36463 -+			}
772.36464 -+			XFlush(dpy);
772.36465 -+			XDestroyWindow(mgr, win);
772.36466 -+			XFlush(mgr);
772.36467 -+			printf("."); fflush(stdout);
772.36468 -+		} while (--loop);
772.36469 -+		printf("*\n");
772.36470 -+	}
772.36471 - 
772.36472 - 	XSync(dpy, 1);
772.36473 -+	XSync(mgr, 1);
772.36474 - 	sleep(2);
772.36475 - 	XSync(dpy, 1);
772.36476 -+	XSync(mgr, 1);
772.36477 -+
772.36478 -+	XCloseDisplay(mgr);
772.36479 -+}
772.36480 -+
772.36481 -+static void race_close(int width, int height,
772.36482 -+		       unsigned int *attachments, int nattachments,
772.36483 -+		       unsigned flags, const char *name)
772.36484 -+{
772.36485 -+	XSetWindowAttributes attr;
772.36486 -+	int count, loop, n;
772.36487 -+
772.36488 -+	if (flags & COMPOSITE && !has_composite(NULL))
772.36489 -+		return;
772.36490 -+
772.36491 -+	printf("%s(%s)\n", __func__, name);
772.36492 -+
772.36493 -+	/* Be nasty and install a fullscreen window on top so that we
772.36494 -+	 * can guarantee we do not get clipped by children.
772.36495 -+	 */
772.36496 -+	attr.override_redirect = 1;
772.36497 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36498 -+		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
772.36499 -+		fflush(stdout);
772.36500 -+		loop = 256 >> ffs(divisors[n]);
772.36501 -+		do {
772.36502 -+			Display *dpy = XOpenDisplay(NULL);
772.36503 -+			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36504 -+					0, 0, width, height, 0,
772.36505 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36506 -+					InputOutput,
772.36507 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36508 -+					CWOverrideRedirect, &attr);
772.36509 -+			if (flags & COMPOSITE)
772.36510 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36511 -+			XMapWindow(dpy, win);
772.36512 -+
772.36513 -+			DRI2CreateDrawable(dpy, win);
772.36514 -+			free(DRI2GetBuffers(dpy, win, &width, &height,
772.36515 -+						attachments, nattachments, &count));
772.36516 -+			if (count != nattachments)
772.36517 -+				return;
772.36518 -+
772.36519 -+			for (count = 0; count < loop; count++)
772.36520 -+				DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
772.36521 -+			XCloseDisplay(dpy);
772.36522 -+			printf("."); fflush(stdout);
772.36523 -+		} while (--loop);
772.36524 -+		printf("*\n");
772.36525 -+	}
772.36526 -+
772.36527 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36528 -+		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
772.36529 -+		fflush(stdout);
772.36530 -+		loop = 256 >> ffs(divisors[n]);
772.36531 -+		do {
772.36532 -+			Display *dpy = XOpenDisplay(NULL);
772.36533 -+			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36534 -+					0, 0, width, height, 0,
772.36535 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36536 -+					InputOutput,
772.36537 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36538 -+					CWOverrideRedirect, &attr);
772.36539 -+			if (flags & COMPOSITE)
772.36540 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36541 -+			XMapWindow(dpy, win);
772.36542 -+
772.36543 -+			DRI2CreateDrawable(dpy, win);
772.36544 -+			free(DRI2GetBuffers(dpy, win, &width, &height,
772.36545 -+						attachments, nattachments, &count));
772.36546 -+			if (count != nattachments)
772.36547 -+				return;
772.36548 -+
772.36549 -+			for (count = 0; count < loop; count++)
772.36550 -+				swap_buffers(dpy, win, divisors[n], attachments, nattachments);
772.36551 -+			XCloseDisplay(dpy);
772.36552 -+			printf("."); fflush(stdout);
772.36553 -+		} while (--loop);
772.36554 -+		printf("*\n");
772.36555 -+	}
772.36556 -+
772.36557 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36558 -+		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
772.36559 -+		fflush(stdout);
772.36560 -+		loop = 256 >> ffs(divisors[n]);
772.36561 -+		do {
772.36562 -+			uint64_t ignore, msc;
772.36563 -+			Display *dpy = XOpenDisplay(NULL);
772.36564 -+			xcb_connection_t *c = XGetXCBConnection(dpy);
772.36565 -+			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36566 -+					0, 0, width, height, 0,
772.36567 -+					DefaultDepth(dpy, DefaultScreen(dpy)),
772.36568 -+					InputOutput,
772.36569 -+					DefaultVisual(dpy, DefaultScreen(dpy)),
772.36570 -+					CWOverrideRedirect, &attr);
772.36571 -+			if (flags & COMPOSITE)
772.36572 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36573 -+			XMapWindow(dpy, win);
772.36574 -+
772.36575 -+			DRI2CreateDrawable(dpy, win);
772.36576 -+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
772.36577 -+			msc++;
772.36578 -+			for (count = 0; count < loop; count++) {
772.36579 -+				xcb_discard_reply(c,
772.36580 -+						xcb_dri2_wait_msc(c, win,
772.36581 -+							upper_32_bits(msc),
772.36582 -+							lower_32_bits(msc),
772.36583 -+							0, 0, 0, 0).sequence);
772.36584 -+				msc += divisors[n];
772.36585 -+			}
772.36586 -+			XFlush(dpy);
772.36587 -+			XCloseDisplay(dpy);
772.36588 -+			printf("."); fflush(stdout);
772.36589 -+		} while (--loop);
772.36590 -+		printf("*\n");
772.36591 -+	}
772.36592 -+}
772.36593 -+
772.36594 -+static void race_client(int width, int height,
772.36595 -+			unsigned int *attachments, int nattachments,
772.36596 -+			unsigned flags, const char *name)
772.36597 -+{
772.36598 -+	Display *mgr = XOpenDisplay(NULL);
772.36599 -+	XSetWindowAttributes attr;
772.36600 -+	int count, loop, n;
772.36601 -+
772.36602 -+	if (flags & COMPOSITE && !has_composite(NULL))
772.36603 -+		return;
772.36604 -+
772.36605 -+	printf("%s(%s)\n", __func__, name);
772.36606 -+
772.36607 -+	/* Be nasty and install a fullscreen window on top so that we
772.36608 -+	 * can guarantee we do not get clipped by children.
772.36609 -+	 */
772.36610 -+	attr.override_redirect = 1;
772.36611 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36612 -+		printf("DRI2SwapBuffers(divisor=%d)", divisors[n]);
772.36613 -+		fflush(stdout);
772.36614 -+		loop = 256 >> ffs(divisors[n]);
772.36615 -+		do {
772.36616 -+			Display *dpy = XOpenDisplay(NULL);
772.36617 -+			Window win;
772.36618 -+
772.36619 -+			if (error_get()) {
772.36620 -+				XCloseDisplay(dpy);
772.36621 -+				printf("+"); fflush(stdout);
772.36622 -+				continue;
772.36623 -+			}
772.36624 -+
772.36625 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36626 -+					    0, 0, width, height, 0,
772.36627 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36628 -+					    InputOutput,
772.36629 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36630 -+					    CWOverrideRedirect, &attr);
772.36631 -+			if (flags & COMPOSITE)
772.36632 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36633 -+			XMapWindow(dpy, win);
772.36634 -+
772.36635 -+			DRI2CreateDrawable(dpy, win);
772.36636 -+			free(DRI2GetBuffers(dpy, win, &width, &height,
772.36637 -+					    attachments, nattachments, &count));
772.36638 -+			if (count == nattachments) {
772.36639 -+				for (count = 0; count < loop; count++)
772.36640 -+					DRI2SwapBuffers(dpy, win, 0, divisors[n], count & (divisors[n]-1));
772.36641 -+			}
772.36642 -+
772.36643 -+			XFlush(dpy);
772.36644 -+			XKillClient(mgr, win);
772.36645 -+			XFlush(mgr);
772.36646 -+
772.36647 -+			XCloseDisplay(dpy);
772.36648 -+			printf("."); fflush(stdout);
772.36649 -+
772.36650 -+			error_put();
772.36651 -+		} while (--loop);
772.36652 -+		printf("*\n");
772.36653 -+	}
772.36654 -+
772.36655 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36656 -+		printf("xcb_dri2_swap_buffers(divisor=%d)", divisors[n]);
772.36657 -+		fflush(stdout);
772.36658 -+		loop = 256 >> ffs(divisors[n]);
772.36659 -+		do {
772.36660 -+			Display *dpy = XOpenDisplay(NULL);
772.36661 -+			Window win;
772.36662 -+
772.36663 -+			if (error_get()) {
772.36664 -+				XCloseDisplay(dpy);
772.36665 -+				printf("+"); fflush(stdout);
772.36666 -+				continue;
772.36667 -+			}
772.36668 -+
772.36669 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36670 -+					    0, 0, width, height, 0,
772.36671 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36672 -+					    InputOutput,
772.36673 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36674 -+					    CWOverrideRedirect, &attr);
772.36675 -+			if (flags & COMPOSITE)
772.36676 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36677 -+			XMapWindow(dpy, win);
772.36678 -+
772.36679 -+			DRI2CreateDrawable(dpy, win);
772.36680 -+			free(DRI2GetBuffers(dpy, win, &width, &height,
772.36681 -+					    attachments, nattachments, &count));
772.36682 -+			if (count == nattachments) {
772.36683 -+				for (count = 0; count < loop; count++)
772.36684 -+					swap_buffers(dpy, win, divisors[n], attachments, nattachments);
772.36685 -+			}
772.36686 -+
772.36687 -+			XFlush(dpy);
772.36688 -+			XKillClient(mgr, win);
772.36689 -+			XFlush(mgr);
772.36690 -+
772.36691 -+			XCloseDisplay(dpy);
772.36692 -+			printf("."); fflush(stdout);
772.36693 -+
772.36694 -+			error_put();
772.36695 -+		} while (--loop);
772.36696 -+		printf("*\n");
772.36697 -+	}
772.36698 -+
772.36699 -+	for (n = 0; n < N_DIVISORS; n++) {
772.36700 -+		printf("DRI2WaitMsc(divisor=%d)", divisors[n]);
772.36701 -+		fflush(stdout);
772.36702 -+		loop = 256 >> ffs(divisors[n]);
772.36703 -+		do {
772.36704 -+			Display *dpy = XOpenDisplay(NULL);
772.36705 -+			uint64_t ignore, msc;
772.36706 -+			xcb_connection_t *c;
772.36707 -+			Window win;
772.36708 -+
772.36709 -+			if (error_get()) {
772.36710 -+				XCloseDisplay(dpy);
772.36711 -+				printf("+"); fflush(stdout);
772.36712 -+				continue;
772.36713 -+			}
772.36714 -+
772.36715 -+			win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.36716 -+					    0, 0, width, height, 0,
772.36717 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.36718 -+					    InputOutput,
772.36719 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.36720 -+					    CWOverrideRedirect, &attr);
772.36721 -+			if (flags & COMPOSITE)
772.36722 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.36723 -+			XMapWindow(dpy, win);
772.36724 -+
772.36725 -+			DRI2CreateDrawable(dpy, win);
772.36726 -+			DRI2GetMSC(dpy, win, &ignore, &msc, &ignore);
772.36727 -+			c = XGetXCBConnection(dpy);
772.36728 -+			msc++;
772.36729 -+			for (count = 0; count < loop; count++) {
772.36730 -+				xcb_discard_reply(c,
772.36731 -+						  xcb_dri2_wait_msc(c, win,
772.36732 -+								    upper_32_bits(msc),
772.36733 -+								    lower_32_bits(msc),
772.36734 -+								    0, 0, 0, 0).sequence);
772.36735 -+				msc += divisors[n];
772.36736 -+			}
772.36737 -+
772.36738 -+			XFlush(dpy);
772.36739 -+			XKillClient(mgr, win);
772.36740 -+			XFlush(mgr);
772.36741 -+
772.36742 -+			XCloseDisplay(dpy);
772.36743 -+			printf("."); fflush(stdout);
772.36744 -+
772.36745 -+			error_put();
772.36746 -+		} while (--loop);
772.36747 -+		printf("*\n");
772.36748 -+	}
772.36749 -+
772.36750 -+	XCloseDisplay(mgr);
772.36751 - }
772.36752 - 
772.36753 - int main(void)
772.36754 -@@ -91,7 +790,10 @@ int main(void)
772.36755 - 		DRI2BufferFrontLeft,
772.36756 - 	};
772.36757 - 
772.36758 --	dpy = XOpenDisplay (NULL);
772.36759 -+	saved_io_error = XSetIOErrorHandler(io_error);
772.36760 -+	XSetErrorHandler(x_error);
772.36761 -+
772.36762 -+	dpy = XOpenDisplay(NULL);
772.36763 - 	if (dpy == NULL)
772.36764 - 		return 77;
772.36765 - 
772.36766 -@@ -101,13 +803,52 @@ int main(void)
772.36767 - 
772.36768 - 	width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
772.36769 - 	height = HeightOfScreen(DefaultScreenOfDisplay(dpy));
772.36770 --	run(dpy, width, height, attachments, 1, "fullscreen");
772.36771 --	run(dpy, width, height, attachments, 2, "fullscreen (with front)");
772.36772 -+	race_window(dpy, width, height, attachments, 1, 0, "fullscreen");
772.36773 -+	race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen");
772.36774 -+	race_window(dpy, width, height, attachments, 2, 0, "fullscreen (with front)");
772.36775 -+	race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
772.36776 -+
772.36777 -+	race_resize(dpy, width, height, attachments, 1, 0, "");
772.36778 -+	race_resize(dpy, width, height, attachments, 1, COMPOSITE, "composite");
772.36779 -+	race_resize(dpy, width, height, attachments, 2, 0, "with front");
772.36780 -+	race_resize(dpy, width, height, attachments, 2, COMPOSITE, "composite with front");
772.36781 -+
772.36782 -+	race_manager(dpy, width, height, attachments, 1, 0, "fullscreen");
772.36783 -+	race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite fullscreen");
772.36784 -+	race_manager(dpy, width, height, attachments, 2, 0, "fullscreen (with front)");
772.36785 -+	race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
772.36786 -+
772.36787 -+	race_close(width, height, attachments, 1, 0, "fullscreen");
772.36788 -+	race_close(width, height, attachments, 1, COMPOSITE, "composite fullscreen");
772.36789 -+	race_close(width, height, attachments, 2, 0, "fullscreen (with front)");
772.36790 -+	race_close(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
772.36791 -+
772.36792 -+	race_client(width, height, attachments, 1, 0, "fullscreen");
772.36793 -+	race_client(width, height, attachments, 1, COMPOSITE, "composite fullscreen");
772.36794 -+	race_client(width, height, attachments, 2, 0, "fullscreen (with front)");
772.36795 -+	race_client(width, height, attachments, 2, COMPOSITE, "composite fullscreen (with front)");
772.36796 - 
772.36797 - 	width /= 2;
772.36798 - 	height /= 2;
772.36799 --	run(dpy, width, height, attachments, 1, "windowed");
772.36800 --	run(dpy, width, height, attachments, 2, "windowed (with front)");
772.36801 -+	race_window(dpy, width, height, attachments, 1, 0, "windowed");
772.36802 -+	race_window(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed");
772.36803 -+	race_window(dpy, width, height, attachments, 2, 0, "windowed (with front)");
772.36804 -+	race_window(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
772.36805 -+
772.36806 -+	race_manager(dpy, width, height, attachments, 1, 0, "windowed");
772.36807 -+	race_manager(dpy, width, height, attachments, 1, COMPOSITE, "composite windowed");
772.36808 -+	race_manager(dpy, width, height, attachments, 2, 0, "windowed (with front)");
772.36809 -+	race_manager(dpy, width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
772.36810 -+
772.36811 -+	race_close(width, height, attachments, 1, 0, "windowed");
772.36812 -+	race_close(width, height, attachments, 1, COMPOSITE, "composite windowed");
772.36813 -+	race_close(width, height, attachments, 2, 0, "windowed (with front)");
772.36814 -+	race_close(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
772.36815 -+
772.36816 -+	race_client(width, height, attachments, 1, 0, "windowed");
772.36817 -+	race_client(width, height, attachments, 1, COMPOSITE, "composite windowed");
772.36818 -+	race_client(width, height, attachments, 2, 0, "windowed (with front)");
772.36819 -+	race_client(width, height, attachments, 2, COMPOSITE, "composite windowed (with front)");
772.36820 - 
772.36821 - 	return 0;
772.36822 - }
772.36823 -diff --git a/test/dri2-speed.c b/test/dri2-speed.c
772.36824 -new file mode 100644
772.36825 -index 00000000..87b9d0b6
772.36826 ---- /dev/null
772.36827 -+++ b/test/dri2-speed.c
772.36828 -@@ -0,0 +1,342 @@
772.36829 -+/*
772.36830 -+ * Copyright (c) 2015 Intel Corporation
772.36831 -+ *
772.36832 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.36833 -+ * copy of this software and associated documentation files (the "Software"),
772.36834 -+ * to deal in the Software without restriction, including without limitation
772.36835 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.36836 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.36837 -+ * Software is furnished to do so, subject to the following conditions:
772.36838 -+ *
772.36839 -+ * The above copyright notice and this permission notice (including the next
772.36840 -+ * paragraph) shall be included in all copies or substantial portions of the
772.36841 -+ * Software.
772.36842 -+ *
772.36843 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.36844 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.36845 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.36846 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.36847 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772.36848 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
772.36849 -+ * SOFTWARE.
772.36850 -+ *
772.36851 -+ */
772.36852 -+
772.36853 -+#ifdef HAVE_CONFIG_H
772.36854 -+#include "config.h"
772.36855 -+#endif
772.36856 -+
772.36857 -+#include <X11/Xlib.h>
772.36858 -+#include <X11/Xatom.h>
772.36859 -+#include <X11/Xlib-xcb.h>
772.36860 -+#include <X11/Xutil.h>
772.36861 -+#include <X11/Xlibint.h>
772.36862 -+#include <X11/extensions/dpms.h>
772.36863 -+#include <X11/extensions/randr.h>
772.36864 -+#include <X11/extensions/Xcomposite.h>
772.36865 -+#include <X11/extensions/Xdamage.h>
772.36866 -+#include <X11/extensions/Xrandr.h>
772.36867 -+#include <xcb/xcb.h>
772.36868 -+#include <xcb/dri2.h>
772.36869 -+#include <xf86drm.h>
772.36870 -+
772.36871 -+#include <stdio.h>
772.36872 -+#include <string.h>
772.36873 -+#include <fcntl.h>
772.36874 -+#include <unistd.h>
772.36875 -+#include <assert.h>
772.36876 -+#include <errno.h>
772.36877 -+#include <setjmp.h>
772.36878 -+#include <signal.h>
772.36879 -+
772.36880 -+#include "dri2.h"
772.36881 -+
772.36882 -+static int _x_error_occurred;
772.36883 -+
772.36884 -+static int
772.36885 -+_check_error_handler(Display     *display,
772.36886 -+		     XErrorEvent *event)
772.36887 -+{
772.36888 -+	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
772.36889 -+	       DisplayString(display),
772.36890 -+	       event->serial,
772.36891 -+	       event->error_code,
772.36892 -+	       event->request_code,
772.36893 -+	       event->minor_code);
772.36894 -+	_x_error_occurred++;
772.36895 -+	return False; /* ignored */
772.36896 -+}
772.36897 -+
772.36898 -+static double elapsed(const struct timespec *start,
772.36899 -+		      const struct timespec *end)
772.36900 -+{
772.36901 -+	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
772.36902 -+}
772.36903 -+
772.36904 -+static void run(Display *dpy, Window win, const char *name)
772.36905 -+{
772.36906 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.36907 -+	struct timespec start, end;
772.36908 -+	int n, completed = 0;
772.36909 -+
772.36910 -+	_x_error_occurred = 0;
772.36911 -+
772.36912 -+	clock_gettime(CLOCK_MONOTONIC, &start);
772.36913 -+	do {
772.36914 -+		for (n = 0; n < 1000; n++) {
772.36915 -+			unsigned int attachments[] = { DRI2BufferBackLeft };
772.36916 -+			unsigned int seq[2];
772.36917 -+
772.36918 -+			seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
772.36919 -+								 0, 0, 0, 0, 0, 0).sequence;
772.36920 -+
772.36921 -+
772.36922 -+			seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
772.36923 -+								1, 1, attachments).sequence;
772.36924 -+
772.36925 -+			xcb_flush(c);
772.36926 -+			xcb_discard_reply(c, seq[0]);
772.36927 -+			xcb_discard_reply(c, seq[1]);
772.36928 -+			completed++;
772.36929 -+		}
772.36930 -+		clock_gettime(CLOCK_MONOTONIC, &end);
772.36931 -+	} while (end.tv_sec < start.tv_sec + 10);
772.36932 -+
772.36933 -+	XSync(dpy, True);
772.36934 -+	if (_x_error_occurred)
772.36935 -+		abort();
772.36936 -+
772.36937 -+	printf("%s: Completed %d swaps in %.1fs, %.3fus each (%.1f FPS)\n",
772.36938 -+	       name, completed, elapsed(&start, &end) / 1000000,
772.36939 -+	       elapsed(&start, &end) / completed,
772.36940 -+	       completed / (elapsed(&start, &end) / 1000000));
772.36941 -+}
772.36942 -+
772.36943 -+static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
772.36944 -+{
772.36945 -+	XRRScreenResources *res;
772.36946 -+
772.36947 -+	res = XRRGetScreenResourcesCurrent(dpy, window);
772.36948 -+	if (res == NULL)
772.36949 -+		res = XRRGetScreenResources(dpy, window);
772.36950 -+
772.36951 -+	return res;
772.36952 -+}
772.36953 -+
772.36954 -+static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
772.36955 -+{
772.36956 -+	int i;
772.36957 -+
772.36958 -+	for (i = 0; i < res->nmode; i++) {
772.36959 -+		if (res->modes[i].id == id)
772.36960 -+			return &res->modes[i];
772.36961 -+	}
772.36962 -+
772.36963 -+	return NULL;
772.36964 -+}
772.36965 -+
772.36966 -+static int dri2_open(Display *dpy)
772.36967 -+{
772.36968 -+	drm_auth_t auth;
772.36969 -+	char *driver, *device;
772.36970 -+	int fd;
772.36971 -+
772.36972 -+	if (!DRI2Connect(dpy, DefaultRootWindow(dpy), &driver, &device))
772.36973 -+		return -1;
772.36974 -+
772.36975 -+	printf ("Connecting to %s driver on %s\n", driver, device);
772.36976 -+
772.36977 -+	fd = open(device, O_RDWR);
772.36978 -+	if (fd < 0)
772.36979 -+		return -1;
772.36980 -+
772.36981 -+	if (drmIoctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
772.36982 -+		return -1;
772.36983 -+
772.36984 -+	if (!DRI2Authenticate(dpy, DefaultRootWindow(dpy), auth.magic))
772.36985 -+		return -1;
772.36986 -+
772.36987 -+	return fd;
772.36988 -+}
772.36989 -+
772.36990 -+static void fullscreen(Display *dpy, Window win)
772.36991 -+{
772.36992 -+	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
772.36993 -+	XChangeProperty(dpy, win,
772.36994 -+			XInternAtom(dpy, "_NET_WM_STATE", False),
772.36995 -+			XA_ATOM, 32, PropModeReplace,
772.36996 -+			(unsigned char *)&atom, 1);
772.36997 -+}
772.36998 -+
772.36999 -+static int has_composite(Display *dpy)
772.37000 -+{
772.37001 -+	int event, error;
772.37002 -+	int major, minor;
772.37003 -+
772.37004 -+	if (!XDamageQueryExtension (dpy, &event, &error))
772.37005 -+		return 0;
772.37006 -+
772.37007 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
772.37008 -+		return 0;
772.37009 -+
772.37010 -+	XCompositeQueryVersion(dpy, &major, &minor);
772.37011 -+
772.37012 -+	return major > 0 || minor >= 4;
772.37013 -+}
772.37014 -+
772.37015 -+int main(void)
772.37016 -+{
772.37017 -+	Display *dpy;
772.37018 -+	Window root, win;
772.37019 -+	XRRScreenResources *res;
772.37020 -+	XRRCrtcInfo **original_crtc;
772.37021 -+	XSetWindowAttributes attr;
772.37022 -+	int i, j, fd;
772.37023 -+
772.37024 -+	attr.override_redirect = 1;
772.37025 -+
772.37026 -+	dpy = XOpenDisplay(NULL);
772.37027 -+	if (dpy == NULL)
772.37028 -+		return 77;
772.37029 -+
772.37030 -+	fd = dri2_open(dpy);
772.37031 -+	if (fd < 0)
772.37032 -+		return 77;
772.37033 -+
772.37034 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.37035 -+		DPMSDisable(dpy);
772.37036 -+
772.37037 -+	root = DefaultRootWindow(dpy);
772.37038 -+
772.37039 -+	signal(SIGALRM, SIG_IGN);
772.37040 -+	XSetErrorHandler(_check_error_handler);
772.37041 -+
772.37042 -+	res = NULL;
772.37043 -+	if (XRRQueryVersion(dpy, &i, &i))
772.37044 -+		res = _XRRGetScreenResourcesCurrent(dpy, root);
772.37045 -+	if (res == NULL)
772.37046 -+		return 77;
772.37047 -+
772.37048 -+	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
772.37049 -+	for (i = 0; i < res->ncrtc; i++)
772.37050 -+		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
772.37051 -+
772.37052 -+	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
772.37053 -+	for (i = 0; i < res->ncrtc; i++)
772.37054 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.37055 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
772.37056 -+
772.37057 -+	DRI2CreateDrawable(dpy, root);
772.37058 -+	DRI2SwapInterval(dpy, root, 0);
772.37059 -+	run(dpy, root, "off");
772.37060 -+	XSync(dpy, True);
772.37061 -+
772.37062 -+	for (i = 0; i < res->noutput; i++) {
772.37063 -+		XRROutputInfo *output;
772.37064 -+		XRRModeInfo *mode;
772.37065 -+
772.37066 -+		output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
772.37067 -+		if (output == NULL)
772.37068 -+			continue;
772.37069 -+
772.37070 -+		mode = NULL;
772.37071 -+		if (res->nmode)
772.37072 -+			mode = lookup_mode(res, output->modes[0]);
772.37073 -+
772.37074 -+		for (j = 0; mode && j < 2*output->ncrtc; j++) {
772.37075 -+			int c = j;
772.37076 -+			if (c >= output->ncrtc)
772.37077 -+				c = 2*output->ncrtc - j - 1;
772.37078 -+
772.37079 -+			printf("[%d, %d] -- OUTPUT:%ld, CRTC:%ld: %dx%d\n",
772.37080 -+			       i, c, (long)res->outputs[i], (long)output->crtcs[c],
772.37081 -+			       mode->width, mode->height);
772.37082 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
772.37083 -+					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
772.37084 -+
772.37085 -+			run(dpy, root, "root");
772.37086 -+			XSync(dpy, True);
772.37087 -+
772.37088 -+			win = XCreateWindow(dpy, root,
772.37089 -+					    0, 0, mode->width, mode->height, 0,
772.37090 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37091 -+					    InputOutput,
772.37092 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37093 -+					    CWOverrideRedirect, &attr);
772.37094 -+			DRI2CreateDrawable(dpy, win);
772.37095 -+			DRI2SwapInterval(dpy, win, 0);
772.37096 -+			fullscreen(dpy, win);
772.37097 -+			XMapWindow(dpy, win);
772.37098 -+			run(dpy, win, "fullscreen");
772.37099 -+			XDestroyWindow(dpy, win);
772.37100 -+			XSync(dpy, True);
772.37101 -+
772.37102 -+			win = XCreateWindow(dpy, root,
772.37103 -+					    0, 0, mode->width, mode->height, 0,
772.37104 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37105 -+					    InputOutput,
772.37106 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37107 -+					    CWOverrideRedirect, &attr);
772.37108 -+			DRI2CreateDrawable(dpy, win);
772.37109 -+			DRI2SwapInterval(dpy, win, 0);
772.37110 -+			XMapWindow(dpy, win);
772.37111 -+			run(dpy, win, "windowed");
772.37112 -+			XDestroyWindow(dpy, win);
772.37113 -+			XSync(dpy, True);
772.37114 -+
772.37115 -+			if (has_composite(dpy)) {
772.37116 -+				Damage damage;
772.37117 -+
772.37118 -+				_x_error_occurred = 0;
772.37119 -+				win = XCreateWindow(dpy, root,
772.37120 -+						    0, 0, mode->width, mode->height, 0,
772.37121 -+						    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37122 -+						    InputOutput,
772.37123 -+						    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37124 -+						    CWOverrideRedirect, &attr);
772.37125 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.37126 -+				damage = XDamageCreate(dpy, win, XDamageReportRawRectangles);
772.37127 -+				DRI2CreateDrawable(dpy, win);
772.37128 -+				DRI2SwapInterval(dpy, win, 0);
772.37129 -+				XMapWindow(dpy, win);
772.37130 -+				XSync(dpy, True);
772.37131 -+				if (!_x_error_occurred)
772.37132 -+					run(dpy, win, "composited");
772.37133 -+				XDamageDestroy(dpy, damage);
772.37134 -+				XDestroyWindow(dpy, win);
772.37135 -+				XSync(dpy, True);
772.37136 -+			}
772.37137 -+
772.37138 -+			win = XCreateWindow(dpy, root,
772.37139 -+					    0, 0, mode->width/2, mode->height/2, 0,
772.37140 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37141 -+					    InputOutput,
772.37142 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37143 -+					    CWOverrideRedirect, &attr);
772.37144 -+			DRI2CreateDrawable(dpy, win);
772.37145 -+			DRI2SwapInterval(dpy, win, 0);
772.37146 -+			XMapWindow(dpy, win);
772.37147 -+			run(dpy, win, "half");
772.37148 -+			XDestroyWindow(dpy, win);
772.37149 -+			XSync(dpy, True);
772.37150 -+
772.37151 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
772.37152 -+					 0, 0, None, RR_Rotate_0, NULL, 0);
772.37153 -+		}
772.37154 -+
772.37155 -+		XRRFreeOutputInfo(output);
772.37156 -+	}
772.37157 -+
772.37158 -+	for (i = 0; i < res->ncrtc; i++)
772.37159 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.37160 -+				 original_crtc[i]->x,
772.37161 -+				 original_crtc[i]->y,
772.37162 -+				 original_crtc[i]->mode,
772.37163 -+				 original_crtc[i]->rotation,
772.37164 -+				 original_crtc[i]->outputs,
772.37165 -+				 original_crtc[i]->noutput);
772.37166 -+
772.37167 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.37168 -+		DPMSEnable(dpy);
772.37169 -+	return 0;
772.37170 -+}
772.37171 -diff --git a/test/dri2-test.c b/test/dri2-test.c
772.37172 -index dd4179f3..bdf01f38 100644
772.37173 ---- a/test/dri2-test.c
772.37174 -+++ b/test/dri2-test.c
772.37175 -@@ -6,6 +6,10 @@
772.37176 - #include <X11/Xutil.h>
772.37177 - #include <X11/extensions/Xfixes.h>
772.37178 - #include <X11/extensions/Xrandr.h>
772.37179 -+#include <X11/Xlib-xcb.h>
772.37180 -+#include <xcb/xcb.h>
772.37181 -+#include <xcb/xcbext.h>
772.37182 -+#include <xcb/dri2.h>
772.37183 - #include <unistd.h>
772.37184 - #include <fcntl.h>
772.37185 - #include <string.h>
772.37186 -@@ -18,6 +22,8 @@
772.37187 - 
772.37188 - #define COUNT 60
772.37189 - 
772.37190 -+static int prime[] = { 0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29, 31, 37, 41, 43, 47, 51, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 };
772.37191 -+
772.37192 - static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
772.37193 - {
772.37194 - 	XRRScreenResources *res;
772.37195 -@@ -101,16 +107,41 @@ static uint64_t check_msc(Display *dpy, Window win, uint64_t last_msc)
772.37196 - 	return current_msc;
772.37197 - }
772.37198 - 
772.37199 -+static void wait_next_vblank(Display *dpy, Window win)
772.37200 -+{
772.37201 -+	uint64_t msc, ust, sbc;
772.37202 -+	DRI2WaitMSC(dpy, win, 0, 1, 0, &ust, &msc, &sbc);
772.37203 -+}
772.37204 -+
772.37205 -+static void swap_buffers(xcb_connection_t *c, Window win,
772.37206 -+		unsigned int *attachments, int nattachments)
772.37207 -+{
772.37208 -+	unsigned int seq[2];
772.37209 -+
772.37210 -+	seq[0] = xcb_dri2_swap_buffers_unchecked(c, win,
772.37211 -+						 0, 0, 0, 0, 0, 0).sequence;
772.37212 -+
772.37213 -+
772.37214 -+	seq[1] = xcb_dri2_get_buffers_unchecked(c, win,
772.37215 -+						nattachments, nattachments,
772.37216 -+						attachments).sequence;
772.37217 -+
772.37218 -+	xcb_flush(c);
772.37219 -+	xcb_discard_reply(c, seq[0]);
772.37220 -+	xcb_discard_reply(c, seq[1]);
772.37221 -+}
772.37222 -+
772.37223 - static void run(Display *dpy, int width, int height,
772.37224 - 		unsigned int *attachments, int nattachments,
772.37225 - 		const char *name)
772.37226 - {
772.37227 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37228 - 	Window win;
772.37229 - 	XSetWindowAttributes attr;
772.37230 --	int count;
772.37231 - 	DRI2Buffer *buffers;
772.37232 - 	struct timespec start, end;
772.37233 --	uint64_t msc;
772.37234 -+	uint64_t start_msc, end_msc;
772.37235 -+	int modulus, remainder, count;
772.37236 - 
772.37237 - 	/* Be nasty and install a fullscreen window on top so that we
772.37238 - 	 * can guarantee we do not get clipped by children.
772.37239 -@@ -125,42 +156,99 @@ static void run(Display *dpy, int width, int height,
772.37240 - 	XMapWindow(dpy, win);
772.37241 - 
772.37242 - 	DRI2CreateDrawable(dpy, win);
772.37243 --	msc = check_msc(dpy, win, 0);
772.37244 -+	DRI2SwapInterval(dpy, win, 1);
772.37245 -+	start_msc = check_msc(dpy, win, 0);
772.37246 - 
772.37247 - 	buffers = DRI2GetBuffers(dpy, win, &width, &height,
772.37248 - 				 attachments, nattachments, &count);
772.37249 - 	if (count != nattachments)
772.37250 - 		return;
772.37251 - 
772.37252 --	msc = check_msc(dpy, win, msc);
772.37253 -+	swap_buffers(c, win, attachments, nattachments);
772.37254 -+	start_msc = check_msc(dpy, win, start_msc);
772.37255 - 	clock_gettime(CLOCK_MONOTONIC, &start);
772.37256 - 	for (count = 0; count < COUNT; count++)
772.37257 --		DRI2SwapBuffers(dpy, win, 0, 0, 0);
772.37258 --	msc = check_msc(dpy, win, msc);
772.37259 -+		swap_buffers(c, win, attachments, nattachments);
772.37260 -+	end_msc = check_msc(dpy, win, start_msc);
772.37261 - 	clock_gettime(CLOCK_MONOTONIC, &end);
772.37262 --	printf("%d %s (%dx%d) swaps in %fs.\n",
772.37263 --	       count, name, width, height, elapsed(&start, &end));
772.37264 -+	printf("%d [%ld] %s (%dx%d) swaps in %fs.\n",
772.37265 -+	       count, (long)(end_msc - start_msc),
772.37266 -+	       name, width, height, elapsed(&start, &end));
772.37267 - 
772.37268 --	msc = check_msc(dpy, win, msc);
772.37269 -+	swap_buffers(c, win, attachments, nattachments);
772.37270 -+	start_msc = check_msc(dpy, win, end_msc);
772.37271 - 	clock_gettime(CLOCK_MONOTONIC, &start);
772.37272 - 	for (count = 0; count < COUNT; count++)
772.37273 - 		dri2_copy_swap(dpy, win, width, height, nattachments == 2);
772.37274 --	msc = check_msc(dpy, win, msc);
772.37275 -+	end_msc = check_msc(dpy, win, start_msc);
772.37276 - 	clock_gettime(CLOCK_MONOTONIC, &end);
772.37277 - 
772.37278 --	printf("%d %s (%dx%d) blits in %fs.\n",
772.37279 --	       count, name, width, height, elapsed(&start, &end));
772.37280 -+	printf("%d [%ld] %s (%dx%d) blits in %fs.\n",
772.37281 -+	       count, (long)(end_msc - start_msc),
772.37282 -+	       name, width, height, elapsed(&start, &end));
772.37283 - 
772.37284 - 	DRI2SwapInterval(dpy, win, 0);
772.37285 -+	wait_next_vblank(dpy, win);
772.37286 -+
772.37287 -+	swap_buffers(c, win, attachments, nattachments);
772.37288 -+	start_msc = check_msc(dpy, win, end_msc);
772.37289 -+	clock_gettime(CLOCK_MONOTONIC, &start);
772.37290 -+	for (count = 0; count < COUNT; count++)
772.37291 -+		swap_buffers(c, win, attachments, nattachments);
772.37292 -+	end_msc = check_msc(dpy, win, start_msc);
772.37293 -+	clock_gettime(CLOCK_MONOTONIC, &end);
772.37294 -+	printf("%d [%ld] %s (%dx%d) vblank=0 swaps in %fs.\n",
772.37295 -+	       count, (long)(end_msc - start_msc),
772.37296 -+	       name, width, height, elapsed(&start, &end));
772.37297 - 
772.37298 --	msc = check_msc(dpy, win, msc);
772.37299 -+	start_msc = check_msc(dpy, win, end_msc);
772.37300 - 	clock_gettime(CLOCK_MONOTONIC, &start);
772.37301 - 	for (count = 0; count < COUNT; count++)
772.37302 --		DRI2SwapBuffers(dpy, win, 0, 0, 0);
772.37303 --	msc = check_msc(dpy, win, msc);
772.37304 -+		wait_next_vblank(dpy, win);
772.37305 -+	end_msc = check_msc(dpy, win, start_msc);
772.37306 - 	clock_gettime(CLOCK_MONOTONIC, &end);
772.37307 --	printf("%d %s (%dx%d) vblank=0 swaps in %fs.\n",
772.37308 --	       count, name, width, height, elapsed(&start, &end));
772.37309 -+	printf("%d [%ld] %s waits in %fs.\n",
772.37310 -+	       count, (long)(end_msc - start_msc),
772.37311 -+	       name, elapsed(&start, &end));
772.37312 -+
772.37313 -+	printf("Testing past & future waits\n");
772.37314 -+	for (modulus = 1; modulus <= 128; modulus <<= 1) {
772.37315 -+		for (count = 0;  prime[count] < modulus; count++) {
772.37316 -+			uint64_t msc, ust, sbc;
772.37317 -+			uint64_t target;
772.37318 -+
772.37319 -+			remainder = prime[count];
772.37320 -+
772.37321 -+			DRI2WaitMSC(dpy, win, 0, 1, 0, &ust, &msc, &sbc);
772.37322 -+
772.37323 -+			target = msc + modulus + 1;
772.37324 -+			target &= -modulus;
772.37325 -+			target += remainder;
772.37326 -+
772.37327 -+			DRI2WaitMSC(dpy, win, target, modulus, remainder,
772.37328 -+				    &ust, &msc, &sbc);
772.37329 -+			if (msc != target) {
772.37330 -+				printf("Missed future MSC (%d, %d): expected=%lld, found=%lld\n",
772.37331 -+				       modulus, remainder,
772.37332 -+				       (long long)target, (long long)msc);
772.37333 -+			}
772.37334 -+
772.37335 -+			target = msc;
772.37336 -+			target &= -modulus;
772.37337 -+			target += remainder;
772.37338 -+			if (target <= msc)
772.37339 -+				target += modulus;
772.37340 -+
772.37341 -+			DRI2WaitMSC(dpy, win, msc, modulus, remainder,
772.37342 -+				    &ust, &msc, &sbc);
772.37343 -+
772.37344 -+			if (msc != target) {
772.37345 -+				printf("Missed past MSC (%d, %d): expected=%lld, found=%lld\n",
772.37346 -+				       modulus, remainder,
772.37347 -+				       (long long)target, (long long)msc);
772.37348 -+			}
772.37349 -+		}
772.37350 -+	}
772.37351 - 
772.37352 - 	XDestroyWindow(dpy, win);
772.37353 - 	free(buffers);
772.37354 -diff --git a/test/dri3-test.c b/test/dri3-test.c
772.37355 -index c66da313..78e105a8 100644
772.37356 ---- a/test/dri3-test.c
772.37357 -+++ b/test/dri3-test.c
772.37358 -@@ -93,14 +93,9 @@ static const struct pci_id_match ids[] = {
772.37359 - 	INTEL_IVB_D_IDS(070),
772.37360 - 	INTEL_IVB_M_IDS(070),
772.37361 - 
772.37362 --	INTEL_HSW_D_IDS(075),
772.37363 --	INTEL_HSW_M_IDS(075),
772.37364 --
772.37365 --	INTEL_VLV_D_IDS(071),
772.37366 --	INTEL_VLV_M_IDS(071),
772.37367 --
772.37368 --	INTEL_BDW_D_IDS(0100),
772.37369 --	INTEL_BDW_M_IDS(0100),
772.37370 -+	INTEL_HSW_IDS(075),
772.37371 -+	INTEL_VLV_IDS(071),
772.37372 -+	INTEL_BDW_IDS(0100),
772.37373 - };
772.37374 - 
772.37375 - static int i915_gen(int device)
772.37376 -@@ -1020,6 +1015,67 @@ fail:
772.37377 - 	return 1;
772.37378 - }
772.37379 - 
772.37380 -+static int gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
772.37381 -+{
772.37382 -+	struct drm_i915_gem_set_tiling set_tiling;
772.37383 -+
772.37384 -+	set_tiling.handle = handle;
772.37385 -+	set_tiling.tiling_mode = tiling;
772.37386 -+	set_tiling.stride = stride;
772.37387 -+
772.37388 -+	return drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0;
772.37389 -+}
772.37390 -+
772.37391 -+static int test_tiling(Display *dpy, int device)
772.37392 -+{
772.37393 -+	Window root = RootWindow(dpy, DefaultScreen(dpy));
772.37394 -+	const int tiling[] = { I915_TILING_NONE, I915_TILING_X, I915_TILING_Y };
772.37395 -+	int line = -1;
772.37396 -+	int t;
772.37397 -+
772.37398 -+	_x_error_occurred = 0;
772.37399 -+
772.37400 -+	for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) {
772.37401 -+		uint32_t src;
772.37402 -+		int src_fd;
772.37403 -+		Pixmap src_pix;
772.37404 -+
772.37405 -+		src = gem_create(device, 4*4096);
772.37406 -+		if (!src) {
772.37407 -+			line = __LINE__;
772.37408 -+			goto fail;
772.37409 -+		}
772.37410 -+
772.37411 -+		gem_set_tiling(device, src, tiling[t], 512);
772.37412 -+
772.37413 -+		src_fd = gem_export(device, src);
772.37414 -+		if (src_fd < 0) {
772.37415 -+			line = __LINE__;
772.37416 -+			goto fail;
772.37417 -+		}
772.37418 -+
772.37419 -+		src_pix = dri3_create_pixmap(dpy, root,
772.37420 -+					     128, 32, 32,
772.37421 -+					     src_fd, 32, 512, 4*4096);
772.37422 -+		XSync(dpy, True);
772.37423 -+		if (_x_error_occurred) {
772.37424 -+			line = __LINE__;
772.37425 -+			goto fail;
772.37426 -+		}
772.37427 -+		XFreePixmap(dpy, src_pix);
772.37428 -+		_x_error_occurred = 0;
772.37429 -+
772.37430 -+		close(src_fd);
772.37431 -+		gem_close(device, src);
772.37432 -+	}
772.37433 -+
772.37434 -+	return 0;
772.37435 -+
772.37436 -+fail:
772.37437 -+	printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line);
772.37438 -+	return 1;
772.37439 -+}
772.37440 -+
772.37441 - static int
772.37442 - _check_error_handler(Display     *display,
772.37443 - 		     XErrorEvent *event)
772.37444 -@@ -1060,6 +1116,7 @@ int main(void)
772.37445 - 
772.37446 - 	error += test_bad_size(dpy, device);
772.37447 - 	error += test_bad_pitch(dpy, device);
772.37448 -+	error += test_tiling(dpy, device);
772.37449 - 
772.37450 - 	error += test_shm(dpy, device, 400, 300);
772.37451 - 	error += test_shm(dpy, device, 300, 400);
772.37452 -diff --git a/test/dri3.c b/test/dri3.c
772.37453 -index 45f3285c..e5644629 100644
772.37454 ---- a/test/dri3.c
772.37455 -+++ b/test/dri3.c
772.37456 -@@ -29,6 +29,7 @@
772.37457 - #include <xcb/dri3.h>
772.37458 - #include <xcb/sync.h>
772.37459 - #include <unistd.h>
772.37460 -+#include <stdlib.h>
772.37461 - 
772.37462 - #include "dri3.h"
772.37463 - 
772.37464 -@@ -109,12 +110,45 @@ void dri3_fence_free(Display *dpy, struct dri3_fence *fence)
772.37465 - 	xcb_sync_destroy_fence(c, fence->xid);
772.37466 - }
772.37467 - 
772.37468 -+static void dri3_query_version(xcb_connection_t *c, int *major, int *minor)
772.37469 -+{
772.37470 -+	xcb_dri3_query_version_reply_t *reply;
772.37471 -+
772.37472 -+	reply = xcb_dri3_query_version_reply(c,
772.37473 -+					     xcb_dri3_query_version(c,
772.37474 -+								    XCB_DRI3_MAJOR_VERSION,
772.37475 -+								    XCB_DRI3_MINOR_VERSION),
772.37476 -+					     NULL);
772.37477 -+	if (reply != NULL) {
772.37478 -+		*major = reply->major_version;
772.37479 -+		*minor = reply->minor_version;
772.37480 -+		free(reply);
772.37481 -+	}
772.37482 -+}
772.37483 -+
772.37484 -+static int dri3_exists(xcb_connection_t *c)
772.37485 -+{
772.37486 -+	const xcb_query_extension_reply_t *ext;
772.37487 -+	int major, minor;
772.37488 -+
772.37489 -+	major = minor = -1;
772.37490 -+
772.37491 -+	ext = xcb_get_extension_data(c, &xcb_dri3_id);
772.37492 -+	if (ext != NULL && ext->present)
772.37493 -+		dri3_query_version(c, &major, &minor);
772.37494 -+
772.37495 -+	return major >= 0;
772.37496 -+}
772.37497 -+
772.37498 - int dri3_open__full(Display *dpy, Window root, unsigned provider)
772.37499 - {
772.37500 - 	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37501 - 	xcb_dri3_open_cookie_t cookie;
772.37502 - 	xcb_dri3_open_reply_t *reply;
772.37503 - 
772.37504 -+	if (!dri3_exists(c))
772.37505 -+		return -1;
772.37506 -+
772.37507 - 	cookie = xcb_dri3_open(c, root, provider);
772.37508 - 	reply = xcb_dri3_open_reply(c, cookie, NULL);
772.37509 - 
772.37510 -diff --git a/test/present-race.c b/test/present-race.c
772.37511 -new file mode 100644
772.37512 -index 00000000..b2b6aa2b
772.37513 ---- /dev/null
772.37514 -+++ b/test/present-race.c
772.37515 -@@ -0,0 +1,484 @@
772.37516 -+/*
772.37517 -+ * Copyright (c) 2014 Intel Corporation
772.37518 -+ *
772.37519 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.37520 -+ * copy of this software and associated documentation files (the "Software"),
772.37521 -+ * to deal in the Software without restriction, including without limitation
772.37522 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.37523 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.37524 -+ * Software is furnished to do so, subject to the following conditions:
772.37525 -+ *
772.37526 -+ * The above copyright notice and this permission notice (including the next
772.37527 -+ * paragraph) shall be included in all copies or substantial portions of the
772.37528 -+ * Software.
772.37529 -+ *
772.37530 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.37531 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.37532 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.37533 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.37534 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772.37535 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
772.37536 -+ * SOFTWARE.
772.37537 -+ *
772.37538 -+ */
772.37539 -+
772.37540 -+#ifdef HAVE_CONFIG_H
772.37541 -+#include "config.h"
772.37542 -+#endif
772.37543 -+
772.37544 -+#include <X11/Xlib.h>
772.37545 -+#include <X11/Xlib-xcb.h>
772.37546 -+#include <X11/xshmfence.h>
772.37547 -+#include <X11/Xutil.h>
772.37548 -+#include <X11/Xlibint.h>
772.37549 -+#include <X11/extensions/dpms.h>
772.37550 -+#include <X11/extensions/randr.h>
772.37551 -+#include <X11/extensions/Xcomposite.h>
772.37552 -+#include <X11/extensions/Xrandr.h>
772.37553 -+#include <X11/extensions/Xrender.h>
772.37554 -+#include <X11/extensions/XShm.h>
772.37555 -+#if HAVE_X11_EXTENSIONS_SHMPROTO_H
772.37556 -+#include <X11/extensions/shmproto.h>
772.37557 -+#elif HAVE_X11_EXTENSIONS_SHMSTR_H
772.37558 -+#include <X11/extensions/shmstr.h>
772.37559 -+#else
772.37560 -+#error Failed to find the right header for X11 MIT-SHM protocol definitions
772.37561 -+#endif
772.37562 -+#include <xcb/xcb.h>
772.37563 -+#include <xcb/present.h>
772.37564 -+#include <xcb/xfixes.h>
772.37565 -+#include <xcb/dri3.h>
772.37566 -+#include <xf86drm.h>
772.37567 -+#include <i915_drm.h>
772.37568 -+
772.37569 -+#include <stdio.h>
772.37570 -+#include <string.h>
772.37571 -+#include <fcntl.h>
772.37572 -+#include <unistd.h>
772.37573 -+#include <assert.h>
772.37574 -+#include <errno.h>
772.37575 -+#include <setjmp.h>
772.37576 -+#include <signal.h>
772.37577 -+
772.37578 -+#include <sys/mman.h>
772.37579 -+#include <sys/ipc.h>
772.37580 -+#include <sys/shm.h>
772.37581 -+#include <pciaccess.h>
772.37582 -+
772.37583 -+#include "dri3.h"
772.37584 -+
772.37585 -+static int _x_error_occurred;
772.37586 -+static uint32_t stamp;
772.37587 -+
772.37588 -+static int
772.37589 -+_check_error_handler(Display     *display,
772.37590 -+		     XErrorEvent *event)
772.37591 -+{
772.37592 -+	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
772.37593 -+	       DisplayString(display),
772.37594 -+	       event->serial,
772.37595 -+	       event->error_code,
772.37596 -+	       event->request_code,
772.37597 -+	       event->minor_code);
772.37598 -+	_x_error_occurred++;
772.37599 -+	return False; /* ignored */
772.37600 -+}
772.37601 -+
772.37602 -+static int has_composite(Display *dpy)
772.37603 -+{
772.37604 -+	int event, error;
772.37605 -+	int major, minor;
772.37606 -+
772.37607 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
772.37608 -+		return 0;
772.37609 -+
772.37610 -+	XCompositeQueryVersion(dpy, &major, &minor);
772.37611 -+
772.37612 -+	return major > 0 || minor >= 4;
772.37613 -+}
772.37614 -+
772.37615 -+static void *setup_msc(Display *dpy, Window win)
772.37616 -+{
772.37617 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37618 -+	xcb_void_cookie_t cookie;
772.37619 -+	uint32_t id = xcb_generate_id(c);
772.37620 -+	xcb_generic_error_t *error;
772.37621 -+	void *q;
772.37622 -+
772.37623 -+	cookie = xcb_present_select_input_checked(c, id, win, XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
772.37624 -+	q = xcb_register_for_special_xge(c, &xcb_present_id, id, &stamp);
772.37625 -+
772.37626 -+	error = xcb_request_check(c, cookie);
772.37627 -+	assert(error == NULL);
772.37628 -+
772.37629 -+	return q;
772.37630 -+}
772.37631 -+
772.37632 -+static void teardown_msc(Display *dpy, void *q)
772.37633 -+{
772.37634 -+	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
772.37635 -+}
772.37636 -+
772.37637 -+static uint64_t wait_vblank(Display *dpy, Window win)
772.37638 -+{
772.37639 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37640 -+	static uint32_t serial = 1;
772.37641 -+	uint64_t msc = 0;
772.37642 -+	int complete = 0;
772.37643 -+	void *q;
772.37644 -+
772.37645 -+	if (win == 0)
772.37646 -+		win = DefaultRootWindow(dpy);
772.37647 -+
772.37648 -+	q = setup_msc(dpy, win);
772.37649 -+
772.37650 -+	xcb_present_notify_msc(c, win, serial ^ 0xdeadbeef, 0, 1, 0);
772.37651 -+	xcb_flush(c);
772.37652 -+
772.37653 -+	do {
772.37654 -+		xcb_present_complete_notify_event_t *ce;
772.37655 -+		xcb_generic_event_t *ev;
772.37656 -+
772.37657 -+		ev = xcb_wait_for_special_event(c, q);
772.37658 -+		if (ev == NULL)
772.37659 -+			break;
772.37660 -+
772.37661 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.37662 -+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
772.37663 -+		    ce->serial == (serial ^ 0xdeadbeef)) {
772.37664 -+			msc = ce->msc;
772.37665 -+			complete = 1;
772.37666 -+		}
772.37667 -+		free(ev);
772.37668 -+	} while (!complete);
772.37669 -+
772.37670 -+	if (++serial == 0)
772.37671 -+		serial = 1;
772.37672 -+
772.37673 -+	teardown_msc(dpy, q);
772.37674 -+
772.37675 -+	return msc;
772.37676 -+}
772.37677 -+
772.37678 -+static int test_basic(Display *dpy, int dummy)
772.37679 -+{
772.37680 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37681 -+	XSetWindowAttributes attr;
772.37682 -+	Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
772.37683 -+	Pixmap pixmap;
772.37684 -+	struct dri3_fence fence;
772.37685 -+	Window root, win;
772.37686 -+	unsigned int width, height;
772.37687 -+	unsigned border, depth;
772.37688 -+	int x, y, ret = 1;
772.37689 -+	const char *phase;
772.37690 -+	uint64_t msc;
772.37691 -+
772.37692 -+	root = DefaultRootWindow(dpy);
772.37693 -+	XGetGeometry(dpy, root,
772.37694 -+		     &win, &x, &y,
772.37695 -+		     &width, &height, &border, &depth);
772.37696 -+
772.37697 -+	_x_error_occurred = 0;
772.37698 -+	attr.override_redirect = 1;
772.37699 -+	switch (dummy) {
772.37700 -+	case 0:
772.37701 -+		win = root;
772.37702 -+		phase = "root";
772.37703 -+		break;
772.37704 -+	case 1:
772.37705 -+		win = XCreateWindow(dpy, root,
772.37706 -+				    0, 0, width, height, 0, depth,
772.37707 -+				    InputOutput, visual,
772.37708 -+				    CWOverrideRedirect, &attr);
772.37709 -+		phase = "fullscreen";
772.37710 -+		break;
772.37711 -+	case 2:
772.37712 -+		width /= 2;
772.37713 -+		height /= 2;
772.37714 -+		win = XCreateWindow(dpy, root,
772.37715 -+				    0, 0, width, height, 0, depth,
772.37716 -+				    InputOutput, visual,
772.37717 -+				    CWOverrideRedirect, &attr);
772.37718 -+		phase = "window";
772.37719 -+		break;
772.37720 -+	case 3:
772.37721 -+		if (!has_composite(dpy))
772.37722 -+			return 0;
772.37723 -+
772.37724 -+		win = XCreateWindow(dpy, root,
772.37725 -+				    0, 0, width, height, 0,
772.37726 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37727 -+				    InputOutput,
772.37728 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37729 -+				    CWOverrideRedirect, &attr);
772.37730 -+		XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.37731 -+		phase = "composite";
772.37732 -+		break;
772.37733 -+
772.37734 -+	default:
772.37735 -+		phase = "broken";
772.37736 -+		win = root;
772.37737 -+		abort();
772.37738 -+		break;
772.37739 -+	}
772.37740 -+
772.37741 -+	XMapWindow(dpy, win);
772.37742 -+	XSync(dpy, True);
772.37743 -+	if (_x_error_occurred)
772.37744 -+		return 1;
772.37745 -+
772.37746 -+	if (dri3_create_fence(dpy, win, &fence))
772.37747 -+		return 0;
772.37748 -+
772.37749 -+	printf("%s: Testing basic flip: %dx%d\n", phase, width, height);
772.37750 -+	fflush(stdout);
772.37751 -+	_x_error_occurred = 0;
772.37752 -+
772.37753 -+	xshmfence_reset(fence.addr);
772.37754 -+	msc = wait_vblank(dpy, win);
772.37755 -+
772.37756 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.37757 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.37758 -+			   0, /* valid */
772.37759 -+			   0, /* update */
772.37760 -+			   0, /* x_off */
772.37761 -+			   0, /* y_off */
772.37762 -+			   None,
772.37763 -+			   None, /* wait fence */
772.37764 -+			   fence.xid,
772.37765 -+			   XCB_PRESENT_OPTION_NONE,
772.37766 -+			   (msc + 64) & -64, /* target msc */
772.37767 -+			   64, /* divisor */
772.37768 -+			   32, /* remainder */
772.37769 -+			   0, NULL);
772.37770 -+	XFreePixmap(dpy, pixmap);
772.37771 -+
772.37772 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.37773 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.37774 -+			   0, /* valid */
772.37775 -+			   0, /* update */
772.37776 -+			   0, /* x_off */
772.37777 -+			   0, /* y_off */
772.37778 -+			   None,
772.37779 -+			   None, /* wait fence */
772.37780 -+			   None, /* sync fence */
772.37781 -+			   XCB_PRESENT_OPTION_NONE,
772.37782 -+			   (msc + 64) & -64, /* target msc */
772.37783 -+			   64, /* divisor */
772.37784 -+			   48, /* remainder */
772.37785 -+			   0, NULL);
772.37786 -+	XFreePixmap(dpy, pixmap);
772.37787 -+	XDestroyWindow(dpy, win);
772.37788 -+	XFlush(dpy);
772.37789 -+
772.37790 -+	ret = !!xshmfence_await(fence.addr);
772.37791 -+	dri3_fence_free(dpy, &fence);
772.37792 -+
772.37793 -+	XSync(dpy, True);
772.37794 -+	ret += !!_x_error_occurred;
772.37795 -+
772.37796 -+	return ret;
772.37797 -+}
772.37798 -+
772.37799 -+static int test_race(Display *dpy, int dummy)
772.37800 -+{
772.37801 -+	Display *mgr = XOpenDisplay(NULL);
772.37802 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37803 -+	XSetWindowAttributes attr;
772.37804 -+	Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
772.37805 -+	Pixmap pixmap;
772.37806 -+	struct dri3_fence fence;
772.37807 -+	Window root, win;
772.37808 -+	unsigned int width, height;
772.37809 -+	unsigned border, depth;
772.37810 -+	int x, y, ret = 1;
772.37811 -+	const char *phase;
772.37812 -+	uint64_t msc;
772.37813 -+
772.37814 -+	root = DefaultRootWindow(dpy);
772.37815 -+	XGetGeometry(dpy, root,
772.37816 -+		     &win, &x, &y,
772.37817 -+		     &width, &height, &border, &depth);
772.37818 -+
772.37819 -+	_x_error_occurred = 0;
772.37820 -+	attr.override_redirect = 1;
772.37821 -+	switch (dummy) {
772.37822 -+	case 0:
772.37823 -+		win = root;
772.37824 -+		phase = "root";
772.37825 -+		break;
772.37826 -+	case 1:
772.37827 -+		win = XCreateWindow(dpy, root,
772.37828 -+				    0, 0, width, height, 0, depth,
772.37829 -+				    InputOutput, visual,
772.37830 -+				    CWOverrideRedirect, &attr);
772.37831 -+		phase = "fullscreen";
772.37832 -+		break;
772.37833 -+	case 2:
772.37834 -+		width /= 2;
772.37835 -+		height /= 2;
772.37836 -+		win = XCreateWindow(dpy, root,
772.37837 -+				    0, 0, width, height, 0, depth,
772.37838 -+				    InputOutput, visual,
772.37839 -+				    CWOverrideRedirect, &attr);
772.37840 -+		phase = "window";
772.37841 -+		break;
772.37842 -+	case 3:
772.37843 -+		if (!has_composite(dpy))
772.37844 -+			return 0;
772.37845 -+
772.37846 -+		win = XCreateWindow(dpy, root,
772.37847 -+				    0, 0, width, height, 0,
772.37848 -+				    DefaultDepth(dpy, DefaultScreen(dpy)),
772.37849 -+				    InputOutput,
772.37850 -+				    DefaultVisual(dpy, DefaultScreen(dpy)),
772.37851 -+				    CWOverrideRedirect, &attr);
772.37852 -+		XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.37853 -+		phase = "composite";
772.37854 -+		break;
772.37855 -+
772.37856 -+	default:
772.37857 -+		phase = "broken";
772.37858 -+		win = root;
772.37859 -+		abort();
772.37860 -+		break;
772.37861 -+	}
772.37862 -+
772.37863 -+	XMapWindow(dpy, win);
772.37864 -+	XSync(dpy, True);
772.37865 -+	if (_x_error_occurred)
772.37866 -+		return 1;
772.37867 -+
772.37868 -+	if (dri3_create_fence(dpy, win, &fence))
772.37869 -+		return 0;
772.37870 -+
772.37871 -+	printf("%s: Testing race with manager: %dx%d\n", phase, width, height);
772.37872 -+	fflush(stdout);
772.37873 -+	_x_error_occurred = 0;
772.37874 -+
772.37875 -+	xshmfence_reset(fence.addr);
772.37876 -+	msc = wait_vblank(dpy, win);
772.37877 -+
772.37878 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.37879 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.37880 -+			   0, /* valid */
772.37881 -+			   0, /* update */
772.37882 -+			   0, /* x_off */
772.37883 -+			   0, /* y_off */
772.37884 -+			   None,
772.37885 -+			   None, /* wait fence */
772.37886 -+			   fence.xid,
772.37887 -+			   XCB_PRESENT_OPTION_NONE,
772.37888 -+			   (msc + 64) & -64, /* target msc */
772.37889 -+			   64, /* divisor */
772.37890 -+			   32, /* remainder */
772.37891 -+			   0, NULL);
772.37892 -+	XFreePixmap(dpy, pixmap);
772.37893 -+
772.37894 -+	XFlush(dpy);
772.37895 -+	XDestroyWindow(mgr, win);
772.37896 -+	XFlush(mgr);
772.37897 -+
772.37898 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.37899 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.37900 -+			   0, /* valid */
772.37901 -+			   0, /* update */
772.37902 -+			   0, /* x_off */
772.37903 -+			   0, /* y_off */
772.37904 -+			   None,
772.37905 -+			   None, /* wait fence */
772.37906 -+			   None, /* sync fence */
772.37907 -+			   XCB_PRESENT_OPTION_NONE,
772.37908 -+			   (msc + 64) & -64, /* target msc */
772.37909 -+			   64, /* divisor */
772.37910 -+			   48, /* remainder */
772.37911 -+			   0, NULL);
772.37912 -+	XFreePixmap(dpy, pixmap);
772.37913 -+	XFlush(dpy);
772.37914 -+
772.37915 -+	ret = !!xshmfence_await(fence.addr);
772.37916 -+	dri3_fence_free(dpy, &fence);
772.37917 -+
772.37918 -+	XSync(dpy, True);
772.37919 -+	ret += !!_x_error_occurred;
772.37920 -+
772.37921 -+	XCloseDisplay(mgr);
772.37922 -+
772.37923 -+	return ret;
772.37924 -+}
772.37925 -+
772.37926 -+static int has_present(Display *dpy)
772.37927 -+{
772.37928 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.37929 -+	xcb_generic_error_t *error = NULL;
772.37930 -+	void *reply;
772.37931 -+
772.37932 -+	reply = xcb_xfixes_query_version_reply(c,
772.37933 -+					       xcb_xfixes_query_version(c,
772.37934 -+									XCB_XFIXES_MAJOR_VERSION,
772.37935 -+									XCB_XFIXES_MINOR_VERSION),
772.37936 -+					       &error);
772.37937 -+	free(reply);
772.37938 -+	free(error);
772.37939 -+	if (reply == NULL) {
772.37940 -+		fprintf(stderr, "XFixes not supported on %s\n", DisplayString(dpy));
772.37941 -+		return 0;
772.37942 -+	}
772.37943 -+
772.37944 -+	reply = xcb_dri3_query_version_reply(c,
772.37945 -+					     xcb_dri3_query_version(c,
772.37946 -+								    XCB_DRI3_MAJOR_VERSION,
772.37947 -+								    XCB_DRI3_MINOR_VERSION),
772.37948 -+					     &error);
772.37949 -+	free(reply);
772.37950 -+	free(error);
772.37951 -+	if (reply == NULL) {
772.37952 -+		fprintf(stderr, "DRI3 not supported on %s\n", DisplayString(dpy));
772.37953 -+		return 0;
772.37954 -+	}
772.37955 -+
772.37956 -+	reply = xcb_present_query_version_reply(c,
772.37957 -+						xcb_present_query_version(c,
772.37958 -+									  XCB_PRESENT_MAJOR_VERSION,
772.37959 -+									  XCB_PRESENT_MINOR_VERSION),
772.37960 -+						&error);
772.37961 -+
772.37962 -+	free(reply);
772.37963 -+	free(error);
772.37964 -+	if (reply == NULL) {
772.37965 -+		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
772.37966 -+		return 0;
772.37967 -+	}
772.37968 -+
772.37969 -+	return 1;
772.37970 -+}
772.37971 -+
772.37972 -+int main(void)
772.37973 -+{
772.37974 -+	Display *dpy;
772.37975 -+	int dummy;
772.37976 -+	int error = 0;
772.37977 -+
772.37978 -+	dpy = XOpenDisplay(NULL);
772.37979 -+	if (dpy == NULL)
772.37980 -+		return 77;
772.37981 -+
772.37982 -+	if (!has_present(dpy))
772.37983 -+		return 77;
772.37984 -+
772.37985 -+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
772.37986 -+		DPMSDisable(dpy);
772.37987 -+
772.37988 -+	signal(SIGALRM, SIG_IGN);
772.37989 -+	XSetErrorHandler(_check_error_handler);
772.37990 -+
772.37991 -+	for (dummy = 0; dummy <= 3; dummy++) {
772.37992 -+		error += test_basic(dpy, dummy);
772.37993 -+		error += test_race(dpy, dummy);
772.37994 -+	}
772.37995 -+
772.37996 -+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
772.37997 -+		DPMSEnable(dpy);
772.37998 -+	return !!error;
772.37999 -+}
772.38000 -diff --git a/test/present-speed.c b/test/present-speed.c
772.38001 -new file mode 100644
772.38002 -index 00000000..eccde931
772.38003 ---- /dev/null
772.38004 -+++ b/test/present-speed.c
772.38005 -@@ -0,0 +1,1015 @@
772.38006 -+/*
772.38007 -+ * Copyright (c) 2015 Intel Corporation
772.38008 -+ *
772.38009 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.38010 -+ * copy of this software and associated documentation files (the "Software"),
772.38011 -+ * to deal in the Software without restriction, including without limitation
772.38012 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.38013 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.38014 -+ * Software is furnished to do so, subject to the following conditions:
772.38015 -+ *
772.38016 -+ * The above copyright notice and this permission notice (including the next
772.38017 -+ * paragraph) shall be included in all copies or substantial portions of the
772.38018 -+ * Software.
772.38019 -+ *
772.38020 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.38021 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.38022 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.38023 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.38024 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772.38025 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
772.38026 -+ * SOFTWARE.
772.38027 -+ *
772.38028 -+ */
772.38029 -+
772.38030 -+#ifdef HAVE_CONFIG_H
772.38031 -+#include "config.h"
772.38032 -+#endif
772.38033 -+
772.38034 -+#include <X11/Xlib.h>
772.38035 -+#include <X11/Xatom.h>
772.38036 -+#include <X11/Xlib-xcb.h>
772.38037 -+#include <X11/xshmfence.h>
772.38038 -+#include <X11/Xutil.h>
772.38039 -+#include <X11/Xlibint.h>
772.38040 -+#include <X11/extensions/Xcomposite.h>
772.38041 -+#include <X11/extensions/Xdamage.h>
772.38042 -+#include <X11/extensions/dpms.h>
772.38043 -+#include <X11/extensions/randr.h>
772.38044 -+#include <X11/extensions/Xrandr.h>
772.38045 -+#include <xcb/xcb.h>
772.38046 -+#include <xcb/present.h>
772.38047 -+#include <xcb/dri3.h>
772.38048 -+#include <xcb/xfixes.h>
772.38049 -+#include <xf86drm.h>
772.38050 -+#include <i915_drm.h>
772.38051 -+
772.38052 -+#include <stdio.h>
772.38053 -+#include <string.h>
772.38054 -+#include <fcntl.h>
772.38055 -+#include <unistd.h>
772.38056 -+#include <assert.h>
772.38057 -+#include <errno.h>
772.38058 -+#include <setjmp.h>
772.38059 -+#include <signal.h>
772.38060 -+#include <sys/wait.h>
772.38061 -+
772.38062 -+#include "dri3.h"
772.38063 -+
772.38064 -+static int _x_error_occurred;
772.38065 -+static uint32_t stamp;
772.38066 -+
772.38067 -+struct list {
772.38068 -+    struct list *next, *prev;
772.38069 -+};
772.38070 -+
772.38071 -+static void
772.38072 -+list_init(struct list *list)
772.38073 -+{
772.38074 -+    list->next = list->prev = list;
772.38075 -+}
772.38076 -+
772.38077 -+static inline void
772.38078 -+__list_add(struct list *entry,
772.38079 -+	    struct list *prev,
772.38080 -+	    struct list *next)
772.38081 -+{
772.38082 -+    next->prev = entry;
772.38083 -+    entry->next = next;
772.38084 -+    entry->prev = prev;
772.38085 -+    prev->next = entry;
772.38086 -+}
772.38087 -+
772.38088 -+static inline void
772.38089 -+list_add(struct list *entry, struct list *head)
772.38090 -+{
772.38091 -+    __list_add(entry, head, head->next);
772.38092 -+}
772.38093 -+
772.38094 -+static inline void
772.38095 -+__list_del(struct list *prev, struct list *next)
772.38096 -+{
772.38097 -+	next->prev = prev;
772.38098 -+	prev->next = next;
772.38099 -+}
772.38100 -+
772.38101 -+static inline void
772.38102 -+_list_del(struct list *entry)
772.38103 -+{
772.38104 -+    __list_del(entry->prev, entry->next);
772.38105 -+}
772.38106 -+
772.38107 -+static inline void
772.38108 -+list_move(struct list *list, struct list *head)
772.38109 -+{
772.38110 -+	if (list->prev != head) {
772.38111 -+		_list_del(list);
772.38112 -+		list_add(list, head);
772.38113 -+	}
772.38114 -+}
772.38115 -+
772.38116 -+#define __container_of(ptr, sample, member)				\
772.38117 -+    (void *)((char *)(ptr) - ((char *)&(sample)->member - (char *)(sample)))
772.38118 -+
772.38119 -+#define list_for_each_entry(pos, head, member)				\
772.38120 -+    for (pos = __container_of((head)->next, pos, member);		\
772.38121 -+	 &pos->member != (head);					\
772.38122 -+	 pos = __container_of(pos->member.next, pos, member))
772.38123 -+
772.38124 -+static int
772.38125 -+_check_error_handler(Display     *display,
772.38126 -+		     XErrorEvent *event)
772.38127 -+{
772.38128 -+	if (_x_error_occurred < 0)
772.38129 -+		return True;
772.38130 -+
772.38131 -+	printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n",
772.38132 -+	       DisplayString(display),
772.38133 -+	       event->serial,
772.38134 -+	       event->error_code,
772.38135 -+	       event->request_code,
772.38136 -+	       event->minor_code);
772.38137 -+	_x_error_occurred++;
772.38138 -+	return False; /* ignored */
772.38139 -+}
772.38140 -+
772.38141 -+static double elapsed(const struct timespec *start,
772.38142 -+		      const struct timespec *end)
772.38143 -+{
772.38144 -+	return 1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000;
772.38145 -+}
772.38146 -+
772.38147 -+struct buffer {
772.38148 -+	struct list link;
772.38149 -+	Pixmap pixmap;
772.38150 -+	struct dri3_fence fence;
772.38151 -+	int fd;
772.38152 -+	int busy;
772.38153 -+	int id;
772.38154 -+};
772.38155 -+
772.38156 -+#define DRI3 1
772.38157 -+#define NOCOPY 2
772.38158 -+#define ASYNC 4
772.38159 -+static void run(Display *dpy, Window win, const char *name, unsigned options)
772.38160 -+{
772.38161 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.38162 -+	struct timespec start, end;
772.38163 -+#define N_BACK 8
772.38164 -+	char test_name[128];
772.38165 -+	struct buffer buffer[N_BACK];
772.38166 -+	struct list mru;
772.38167 -+	Window root;
772.38168 -+	unsigned int width, height;
772.38169 -+	unsigned border, depth;
772.38170 -+	unsigned present_flags = 0;
772.38171 -+	xcb_xfixes_region_t update = 0;
772.38172 -+	int completed = 0;
772.38173 -+	int queued = 0;
772.38174 -+	uint32_t eid = 0;
772.38175 -+	void *Q = NULL;
772.38176 -+	int i, n;
772.38177 -+
772.38178 -+	list_init(&mru);
772.38179 -+
772.38180 -+	XGetGeometry(dpy, win,
772.38181 -+		     &root, &i, &n, &width, &height, &border, &depth);
772.38182 -+
772.38183 -+	_x_error_occurred = 0;
772.38184 -+
772.38185 -+	for (n = 0; n < N_BACK; n++) {
772.38186 -+		buffer[n].pixmap = xcb_generate_id(c);
772.38187 -+		xcb_create_pixmap(c, depth, buffer[n].pixmap, win,
772.38188 -+				  width, height);
772.38189 -+		buffer[n].fence.xid = 0;
772.38190 -+		buffer[n].fd = -1;
772.38191 -+		buffer[n].id = n;
772.38192 -+		if (options & DRI3) {
772.38193 -+			xcb_dri3_buffer_from_pixmap_reply_t *reply;
772.38194 -+			int *fds;
772.38195 -+
772.38196 -+			if (dri3_create_fence(dpy, win, &buffer[n].fence))
772.38197 -+				return;
772.38198 -+
772.38199 -+			reply = xcb_dri3_buffer_from_pixmap_reply (c,
772.38200 -+								   xcb_dri3_buffer_from_pixmap(c, buffer[n].pixmap),
772.38201 -+								   NULL);
772.38202 -+			if (reply == NULL)
772.38203 -+				return;
772.38204 -+
772.38205 -+			fds = xcb_dri3_buffer_from_pixmap_reply_fds (c, reply);
772.38206 -+			buffer[n].fd = fds[0];
772.38207 -+			free(reply);
772.38208 -+
772.38209 -+			/* start idle */
772.38210 -+			xshmfence_trigger(buffer[n].fence.addr);
772.38211 -+		}
772.38212 -+		buffer[n].busy = 0;
772.38213 -+		list_add(&buffer[n].link, &mru);
772.38214 -+	}
772.38215 -+	if (options & ASYNC)
772.38216 -+		present_flags |= XCB_PRESENT_OPTION_ASYNC;
772.38217 -+	if (options & NOCOPY) {
772.38218 -+		update = xcb_generate_id(c);
772.38219 -+		xcb_xfixes_create_region(c, update, 0, NULL);
772.38220 -+		present_flags |= XCB_PRESENT_OPTION_COPY;
772.38221 -+	}
772.38222 -+
772.38223 -+	if (!(options & DRI3)) {
772.38224 -+		eid = xcb_generate_id(c);
772.38225 -+		xcb_present_select_input(c, eid, win,
772.38226 -+					 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
772.38227 -+					 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
772.38228 -+		Q = xcb_register_for_special_xge(c, &xcb_present_id, eid, &stamp);
772.38229 -+	}
772.38230 -+
772.38231 -+	clock_gettime(CLOCK_MONOTONIC, &start);
772.38232 -+	do {
772.38233 -+		for (n = 0; n < 1000; n++) {
772.38234 -+			struct buffer *tmp, *b = NULL;
772.38235 -+retry:
772.38236 -+			list_for_each_entry(tmp, &mru, link) {
772.38237 -+				if (tmp->fence.xid)
772.38238 -+					tmp->busy = !xshmfence_query(tmp->fence.addr);
772.38239 -+				if (!tmp->busy) {
772.38240 -+					b = tmp;
772.38241 -+					break;
772.38242 -+				}
772.38243 -+			}
772.38244 -+			if (options & DRI3) {
772.38245 -+				if (b == NULL)
772.38246 -+					goto retry;
772.38247 -+
772.38248 -+				xshmfence_reset(b->fence.addr);
772.38249 -+				queued--;
772.38250 -+				completed++;
772.38251 -+			} else while (b == NULL) {
772.38252 -+				xcb_present_generic_event_t *ev;
772.38253 -+
772.38254 -+				ev = (xcb_present_generic_event_t *)
772.38255 -+					xcb_wait_for_special_event(c, Q);
772.38256 -+				if (ev == NULL)
772.38257 -+					abort();
772.38258 -+
772.38259 -+				do {
772.38260 -+					switch (ev->evtype) {
772.38261 -+					case XCB_PRESENT_COMPLETE_NOTIFY:
772.38262 -+						completed++;
772.38263 -+						queued--;
772.38264 -+						break;
772.38265 -+
772.38266 -+					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
772.38267 -+						{
772.38268 -+							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
772.38269 -+							assert(ie->serial < N_BACK);
772.38270 -+							buffer[ie->serial].busy = 0;
772.38271 -+							if (b == NULL)
772.38272 -+								b = &buffer[ie->serial];
772.38273 -+							break;
772.38274 -+						}
772.38275 -+					}
772.38276 -+					free(ev);
772.38277 -+				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
772.38278 -+			}
772.38279 -+
772.38280 -+			b->busy = (options & NOCOPY) == 0;
772.38281 -+			xcb_present_pixmap(c, win, b->pixmap, b->id,
772.38282 -+					   0, /* valid */
772.38283 -+					   update, /* update */
772.38284 -+					   0, /* x_off */
772.38285 -+					   0, /* y_off */
772.38286 -+					   None,
772.38287 -+					   None, /* wait fence */
772.38288 -+					   b->fence.xid,
772.38289 -+					   present_flags,
772.38290 -+					   0, /* target msc */
772.38291 -+					   0, /* divisor */
772.38292 -+					   0, /* remainder */
772.38293 -+					   0, NULL);
772.38294 -+			list_move(&b->link, &mru);
772.38295 -+			queued++;
772.38296 -+			xcb_flush(c);
772.38297 -+		}
772.38298 -+		clock_gettime(CLOCK_MONOTONIC, &end);
772.38299 -+	} while (end.tv_sec < start.tv_sec + 10);
772.38300 -+
772.38301 -+	if (options & DRI3) {
772.38302 -+		struct buffer *b;
772.38303 -+		XID pixmap;
772.38304 -+
772.38305 -+		pixmap = xcb_generate_id(c);
772.38306 -+		xcb_create_pixmap(c, depth, pixmap, win, width, height);
772.38307 -+		xcb_present_pixmap(c, win, pixmap, 0xdeadbeef,
772.38308 -+				   0, /* valid */
772.38309 -+				   None, /* update */
772.38310 -+				   0, /* x_off */
772.38311 -+				   0, /* y_off */
772.38312 -+				   None,
772.38313 -+				   None, /* wait fence */
772.38314 -+				   None,
772.38315 -+				   0,
772.38316 -+				   0, /* target msc */
772.38317 -+				   0, /* divisor */
772.38318 -+				   0, /* remainder */
772.38319 -+				   0, NULL);
772.38320 -+		xcb_flush(c);
772.38321 -+
772.38322 -+		list_for_each_entry(b, &mru, link)
772.38323 -+			xshmfence_await(b->fence.addr);
772.38324 -+
772.38325 -+		xcb_free_pixmap(c, pixmap);
772.38326 -+		completed += queued;
772.38327 -+	} else while (queued) {
772.38328 -+		xcb_present_generic_event_t *ev;
772.38329 -+
772.38330 -+		ev = (xcb_present_generic_event_t *)
772.38331 -+			xcb_wait_for_special_event(c, Q);
772.38332 -+		if (ev == NULL)
772.38333 -+			abort();
772.38334 -+
772.38335 -+		do {
772.38336 -+			switch (ev->evtype) {
772.38337 -+			case XCB_PRESENT_COMPLETE_NOTIFY:
772.38338 -+				completed++;
772.38339 -+				queued--;
772.38340 -+				break;
772.38341 -+
772.38342 -+			case XCB_PRESENT_EVENT_IDLE_NOTIFY:
772.38343 -+				break;
772.38344 -+			}
772.38345 -+			free(ev);
772.38346 -+		} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, Q)));
772.38347 -+	}
772.38348 -+	clock_gettime(CLOCK_MONOTONIC, &end);
772.38349 -+
772.38350 -+	if (update)
772.38351 -+		xcb_xfixes_destroy_region(c, update);
772.38352 -+	for (n = 0; n < N_BACK; n++) {
772.38353 -+		if (buffer[n].fence.xid)
772.38354 -+			dri3_fence_free(dpy, &buffer[n].fence);
772.38355 -+		if (buffer[n].fd != -1)
772.38356 -+			close(buffer[n].fd);
772.38357 -+		xcb_free_pixmap(c, buffer[n].pixmap);
772.38358 -+	}
772.38359 -+
772.38360 -+	if (Q) {
772.38361 -+		xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence);
772.38362 -+		XSync(dpy, True);
772.38363 -+		xcb_unregister_for_special_event(c, Q);
772.38364 -+	}
772.38365 -+
772.38366 -+	test_name[0] = '\0';
772.38367 -+	if (options) {
772.38368 -+		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
772.38369 -+			 options & NOCOPY ? " no-copy" : "",
772.38370 -+			 options & DRI3 ? " dri3" : "",
772.38371 -+			 options & ASYNC ? " async" : "");
772.38372 -+	}
772.38373 -+	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
772.38374 -+	       name, test_name,
772.38375 -+	       completed, elapsed(&start, &end) / 1000000,
772.38376 -+	       elapsed(&start, &end) / completed,
772.38377 -+	       completed / (elapsed(&start, &end) / 1000000));
772.38378 -+}
772.38379 -+
772.38380 -+struct perpixel {
772.38381 -+	Window win;
772.38382 -+	struct buffer buffer[N_BACK];
772.38383 -+	struct list mru;
772.38384 -+	uint32_t eid;
772.38385 -+	void *Q;
772.38386 -+	int queued;
772.38387 -+};
772.38388 -+
772.38389 -+static void perpixel(Display *dpy,
772.38390 -+		     int max_width, int max_height, unsigned options)
772.38391 -+{
772.38392 -+	//const int sz = max_width * max_height;
772.38393 -+	const int sz = 1048;
772.38394 -+	struct perpixel *pp;
772.38395 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.38396 -+	struct timespec start, end;
772.38397 -+	char test_name[128];
772.38398 -+	unsigned present_flags = 0;
772.38399 -+	xcb_xfixes_region_t update = 0;
772.38400 -+	int completed = 0;
772.38401 -+	int i, n;
772.38402 -+
772.38403 -+	pp = calloc(sz, sizeof(*pp));
772.38404 -+	if (!pp)
772.38405 -+		return;
772.38406 -+
772.38407 -+	for (i = 0; i < sz; i++) {
772.38408 -+		XSetWindowAttributes attr = { .override_redirect = 1 };
772.38409 -+		int depth = DefaultDepth(dpy, DefaultScreen(dpy));
772.38410 -+		pp[i].win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.38411 -+					  i % max_width, i / max_width, 1, 1, 0, depth,
772.38412 -+					  InputOutput,
772.38413 -+					  DefaultVisual(dpy, DefaultScreen(dpy)),
772.38414 -+					  CWOverrideRedirect, &attr);
772.38415 -+		XMapWindow(dpy, pp[i].win);
772.38416 -+		list_init(&pp[i].mru);
772.38417 -+		for (n = 0; n < N_BACK; n++) {
772.38418 -+			pp[i].buffer[n].pixmap = xcb_generate_id(c);
772.38419 -+			xcb_create_pixmap(c, depth, pp[i].buffer[n].pixmap,
772.38420 -+					  pp[i].win, 1, 1);
772.38421 -+			pp[i].buffer[n].fence.xid = 0;
772.38422 -+			pp[i].buffer[n].fd = -1;
772.38423 -+			pp[i].buffer[n].id = n;
772.38424 -+			if (options & DRI3) {
772.38425 -+				xcb_dri3_buffer_from_pixmap_reply_t *reply;
772.38426 -+				int *fds;
772.38427 -+
772.38428 -+				if (dri3_create_fence(dpy, pp[i].win, &pp[i].buffer[n].fence))
772.38429 -+					return;
772.38430 -+
772.38431 -+				reply = xcb_dri3_buffer_from_pixmap_reply(c,
772.38432 -+									  xcb_dri3_buffer_from_pixmap(c, pp[i].buffer[n].pixmap),
772.38433 -+									  NULL);
772.38434 -+				if (reply == NULL)
772.38435 -+					return;
772.38436 -+
772.38437 -+				fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, reply);
772.38438 -+				pp[i].buffer[n].fd = fds[0];
772.38439 -+				free(reply);
772.38440 -+
772.38441 -+				/* start idle */
772.38442 -+				xshmfence_trigger(pp[i].buffer[n].fence.addr);
772.38443 -+			}
772.38444 -+			pp[i].buffer[n].busy = 0;
772.38445 -+			list_add(&pp[i].buffer[n].link, &pp[i].mru);
772.38446 -+		}
772.38447 -+
772.38448 -+		if (!(options & DRI3)) {
772.38449 -+			pp[i].eid = xcb_generate_id(c);
772.38450 -+			xcb_present_select_input(c, pp[i].eid, pp[i].win,
772.38451 -+						 (options & NOCOPY ? 0 : XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY) |
772.38452 -+						 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
772.38453 -+			pp[i].Q = xcb_register_for_special_xge(c, &xcb_present_id, pp[i].eid, &stamp);
772.38454 -+		}
772.38455 -+		pp[i].queued = 0;
772.38456 -+	}
772.38457 -+
772.38458 -+	XSync(dpy, True);
772.38459 -+	_x_error_occurred = 0;
772.38460 -+
772.38461 -+	if (options & ASYNC)
772.38462 -+		present_flags |= XCB_PRESENT_OPTION_ASYNC;
772.38463 -+	if (options & NOCOPY) {
772.38464 -+		update = xcb_generate_id(c);
772.38465 -+		xcb_xfixes_create_region(c, update, 0, NULL);
772.38466 -+		present_flags |= XCB_PRESENT_OPTION_COPY;
772.38467 -+	}
772.38468 -+
772.38469 -+	clock_gettime(CLOCK_MONOTONIC, &start);
772.38470 -+	do {
772.38471 -+		for (i = 0; i < sz; i++) {
772.38472 -+			struct buffer *tmp, *b = NULL;
772.38473 -+retry:
772.38474 -+			list_for_each_entry(tmp, &pp[i].mru, link) {
772.38475 -+				if (tmp->fence.xid)
772.38476 -+					tmp->busy = !xshmfence_query(tmp->fence.addr);
772.38477 -+				if (!tmp->busy) {
772.38478 -+					b = tmp;
772.38479 -+					break;
772.38480 -+				}
772.38481 -+			}
772.38482 -+			if (options & DRI3) {
772.38483 -+				if (b == NULL)
772.38484 -+					goto retry;
772.38485 -+
772.38486 -+				xshmfence_reset(b->fence.addr);
772.38487 -+				pp[i].queued--;
772.38488 -+				completed++;
772.38489 -+			} else while (b == NULL) {
772.38490 -+				xcb_present_generic_event_t *ev;
772.38491 -+
772.38492 -+				ev = (xcb_present_generic_event_t *)
772.38493 -+					xcb_wait_for_special_event(c, pp[i].Q);
772.38494 -+				if (ev == NULL)
772.38495 -+					abort();
772.38496 -+
772.38497 -+				do {
772.38498 -+					switch (ev->evtype) {
772.38499 -+					case XCB_PRESENT_COMPLETE_NOTIFY:
772.38500 -+						completed++;
772.38501 -+						pp[i].queued--;
772.38502 -+						break;
772.38503 -+
772.38504 -+					case XCB_PRESENT_EVENT_IDLE_NOTIFY:
772.38505 -+						{
772.38506 -+							xcb_present_idle_notify_event_t *ie = (xcb_present_idle_notify_event_t *)ev;
772.38507 -+							assert(ie->serial < N_BACK);
772.38508 -+							pp[i].buffer[ie->serial].busy = 0;
772.38509 -+							if (b == NULL)
772.38510 -+								b = &pp[i].buffer[ie->serial];
772.38511 -+							break;
772.38512 -+						}
772.38513 -+					}
772.38514 -+					free(ev);
772.38515 -+				} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
772.38516 -+			}
772.38517 -+
772.38518 -+			b->busy = (options & NOCOPY) == 0;
772.38519 -+			xcb_present_pixmap(c, pp[i].win, b->pixmap, b->id,
772.38520 -+					   0, /* valid */
772.38521 -+					   update, /* update */
772.38522 -+					   0, /* x_off */
772.38523 -+					   0, /* y_off */
772.38524 -+					   None,
772.38525 -+					   None, /* wait fence */
772.38526 -+					   b->fence.xid,
772.38527 -+					   present_flags,
772.38528 -+					   0, /* target msc */
772.38529 -+					   0, /* divisor */
772.38530 -+					   0, /* remainder */
772.38531 -+					   0, NULL);
772.38532 -+			list_move(&b->link, &pp[i].mru);
772.38533 -+			pp[i].queued++;
772.38534 -+		}
772.38535 -+		xcb_flush(c);
772.38536 -+		clock_gettime(CLOCK_MONOTONIC, &end);
772.38537 -+	} while (end.tv_sec < start.tv_sec + 10);
772.38538 -+
772.38539 -+	for (i = 0; i < sz; i++) {
772.38540 -+		if (options & DRI3) {
772.38541 -+			int depth = DefaultDepth(dpy, DefaultScreen(dpy));
772.38542 -+			struct buffer *b;
772.38543 -+			XID pixmap;
772.38544 -+
772.38545 -+			pixmap = xcb_generate_id(c);
772.38546 -+			xcb_create_pixmap(c, depth, pixmap, pp[i].win, 1, 1);
772.38547 -+			xcb_present_pixmap(c, pp[i].win, pixmap, 0xdeadbeef,
772.38548 -+					   0, /* valid */
772.38549 -+					   None, /* update */
772.38550 -+					   0, /* x_off */
772.38551 -+					   0, /* y_off */
772.38552 -+					   None,
772.38553 -+					   None, /* wait fence */
772.38554 -+					   None,
772.38555 -+					   0,
772.38556 -+					   0, /* target msc */
772.38557 -+					   0, /* divisor */
772.38558 -+					   0, /* remainder */
772.38559 -+					   0, NULL);
772.38560 -+			xcb_flush(c);
772.38561 -+
772.38562 -+			list_for_each_entry(b, &pp[i].mru, link)
772.38563 -+				xshmfence_await(b->fence.addr);
772.38564 -+
772.38565 -+			xcb_free_pixmap(c, pixmap);
772.38566 -+			completed += pp[i].queued;
772.38567 -+		} else while (pp[i].queued) {
772.38568 -+			xcb_present_generic_event_t *ev;
772.38569 -+
772.38570 -+			ev = (xcb_present_generic_event_t *)
772.38571 -+				xcb_wait_for_special_event(c, pp[i].Q);
772.38572 -+			if (ev == NULL)
772.38573 -+				abort();
772.38574 -+
772.38575 -+			do {
772.38576 -+				switch (ev->evtype) {
772.38577 -+				case XCB_PRESENT_COMPLETE_NOTIFY:
772.38578 -+					completed++;
772.38579 -+					pp[i].queued--;
772.38580 -+					break;
772.38581 -+
772.38582 -+				case XCB_PRESENT_EVENT_IDLE_NOTIFY:
772.38583 -+					break;
772.38584 -+				}
772.38585 -+				free(ev);
772.38586 -+			} while ((ev = (xcb_present_generic_event_t *)xcb_poll_for_special_event(c, pp[i].Q)));
772.38587 -+		}
772.38588 -+	}
772.38589 -+	clock_gettime(CLOCK_MONOTONIC, &end);
772.38590 -+
772.38591 -+	if (update)
772.38592 -+		xcb_xfixes_destroy_region(c, update);
772.38593 -+
772.38594 -+	for (i = 0; i < sz; i++) {
772.38595 -+		for (n = 0; n < N_BACK; n++) {
772.38596 -+			if (pp[i].buffer[n].fence.xid)
772.38597 -+				dri3_fence_free(dpy, &pp[i].buffer[n].fence);
772.38598 -+			if (pp[i].buffer[n].fd != -1)
772.38599 -+				close(pp[i].buffer[n].fd);
772.38600 -+			xcb_free_pixmap(c, pp[i].buffer[n].pixmap);
772.38601 -+		}
772.38602 -+
772.38603 -+		if (pp[i].Q) {
772.38604 -+			xcb_discard_reply(c, xcb_present_select_input_checked(c, pp[i].eid, pp[i].win, 0).sequence);
772.38605 -+			XSync(dpy, True);
772.38606 -+			xcb_unregister_for_special_event(c, pp[i].Q);
772.38607 -+		}
772.38608 -+
772.38609 -+		XDestroyWindow(dpy, pp[i].win);
772.38610 -+	}
772.38611 -+	free(pp);
772.38612 -+
772.38613 -+	test_name[0] = '\0';
772.38614 -+	if (options) {
772.38615 -+		snprintf(test_name, sizeof(test_name), "(%s%s%s )",
772.38616 -+			 options & NOCOPY ? " no-copy" : "",
772.38617 -+			 options & DRI3 ? " dri3" : "",
772.38618 -+			 options & ASYNC ? " async" : "");
772.38619 -+	}
772.38620 -+	printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n",
772.38621 -+	       __func__, test_name,
772.38622 -+	       completed, elapsed(&start, &end) / 1000000,
772.38623 -+	       elapsed(&start, &end) / completed,
772.38624 -+	       completed / (elapsed(&start, &end) / 1000000));
772.38625 -+}
772.38626 -+
772.38627 -+static int isqrt(int x)
772.38628 -+{
772.38629 -+	int i;
772.38630 -+
772.38631 -+	for (i = 2; i*i < x; i++)
772.38632 -+		;
772.38633 -+	return i;
772.38634 -+}
772.38635 -+
772.38636 -+struct sibling {
772.38637 -+	pthread_t thread;
772.38638 -+	Display *dpy;
772.38639 -+	int x, y;
772.38640 -+	int width, height;
772.38641 -+	unsigned options;
772.38642 -+};
772.38643 -+
772.38644 -+static void *sibling(void *arg)
772.38645 -+{
772.38646 -+	struct sibling *s = arg;
772.38647 -+	XSetWindowAttributes attr = { .override_redirect = 1 };
772.38648 -+	Window win = XCreateWindow(s->dpy, DefaultRootWindow(s->dpy),
772.38649 -+				   s->x, s->y, s->width, s->height, 0,
772.38650 -+				   DefaultDepth(s->dpy, DefaultScreen(s->dpy)),
772.38651 -+				   InputOutput,
772.38652 -+				   DefaultVisual(s->dpy, DefaultScreen(s->dpy)),
772.38653 -+				   CWOverrideRedirect, &attr);
772.38654 -+	XMapWindow(s->dpy, win);
772.38655 -+	run(s->dpy, win, "sibling", s->options);
772.38656 -+	return NULL;
772.38657 -+}
772.38658 -+
772.38659 -+static void siblings(Display *dpy,
772.38660 -+		     int max_width, int max_height, int ncpus, unsigned options)
772.38661 -+{
772.38662 -+	int sq_ncpus = isqrt(ncpus);
772.38663 -+	int width = max_width / sq_ncpus;
772.38664 -+	int height = max_height/ sq_ncpus;
772.38665 -+	struct sibling s[ncpus];
772.38666 -+	int child;
772.38667 -+
772.38668 -+	if (ncpus <= 1)
772.38669 -+		return;
772.38670 -+
772.38671 -+	for (child = 0; child < ncpus; child++) {
772.38672 -+		s[child].dpy = dpy;
772.38673 -+		s[child].x = (child % sq_ncpus) * width;
772.38674 -+		s[child].y = (child / sq_ncpus) * height;
772.38675 -+		s[child].width = width;
772.38676 -+		s[child].height = height;
772.38677 -+		s[child].options = options;
772.38678 -+		pthread_create(&s[child].thread, NULL, sibling, &s[child]);
772.38679 -+	}
772.38680 -+
772.38681 -+	for (child = 0; child < ncpus; child++)
772.38682 -+		pthread_join(s[child].thread, NULL);
772.38683 -+}
772.38684 -+
772.38685 -+static void cousins(int max_width, int max_height, int ncpus, unsigned options)
772.38686 -+{
772.38687 -+	int sq_ncpus = isqrt(ncpus);
772.38688 -+	int width = max_width / sq_ncpus;
772.38689 -+	int height = max_height/ sq_ncpus;
772.38690 -+	int child;
772.38691 -+
772.38692 -+	if (ncpus <= 1)
772.38693 -+		return;
772.38694 -+
772.38695 -+	for (child = 0; child < ncpus; child++) {
772.38696 -+		for (; fork() == 0; exit(0)) {
772.38697 -+			int x = (child % sq_ncpus) * width;
772.38698 -+			int y = (child / sq_ncpus) * height;
772.38699 -+			XSetWindowAttributes attr = { .override_redirect = 1 };
772.38700 -+			Display *dpy = XOpenDisplay(NULL);
772.38701 -+			Window win = XCreateWindow(dpy, DefaultRootWindow(dpy),
772.38702 -+						   x, y, width, height, 0,
772.38703 -+						   DefaultDepth(dpy, DefaultScreen(dpy)),
772.38704 -+						   InputOutput,
772.38705 -+						   DefaultVisual(dpy, DefaultScreen(dpy)),
772.38706 -+						   CWOverrideRedirect, &attr);
772.38707 -+			XMapWindow(dpy, win);
772.38708 -+			run(dpy, win, "cousin", options);
772.38709 -+		}
772.38710 -+	}
772.38711 -+
772.38712 -+	while (child) {
772.38713 -+		int status = -1;
772.38714 -+		pid_t pid = wait(&status);
772.38715 -+		if (pid == -1)
772.38716 -+			continue;
772.38717 -+		child--;
772.38718 -+	}
772.38719 -+}
772.38720 -+
772.38721 -+static int has_present(Display *dpy)
772.38722 -+{
772.38723 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.38724 -+	xcb_generic_error_t *error = NULL;
772.38725 -+	void *reply;
772.38726 -+
772.38727 -+	reply = xcb_present_query_version_reply(c,
772.38728 -+						xcb_present_query_version(c,
772.38729 -+									  XCB_PRESENT_MAJOR_VERSION,
772.38730 -+									  XCB_PRESENT_MINOR_VERSION),
772.38731 -+						&error);
772.38732 -+
772.38733 -+	free(reply);
772.38734 -+	free(error);
772.38735 -+	if (reply == NULL) {
772.38736 -+		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
772.38737 -+		return 0;
772.38738 -+	}
772.38739 -+
772.38740 -+	return 1;
772.38741 -+}
772.38742 -+
772.38743 -+static int has_composite(Display *dpy)
772.38744 -+{
772.38745 -+	int event, error;
772.38746 -+	int major, minor;
772.38747 -+
772.38748 -+	if (!XDamageQueryExtension (dpy, &event, &error))
772.38749 -+		return 0;
772.38750 -+
772.38751 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
772.38752 -+		return 0;
772.38753 -+
772.38754 -+	XCompositeQueryVersion(dpy, &major, &minor);
772.38755 -+
772.38756 -+	return major > 0 || minor >= 4;
772.38757 -+}
772.38758 -+
772.38759 -+static int dri3_query_version(Display *dpy, int *major, int *minor)
772.38760 -+{
772.38761 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.38762 -+	xcb_dri3_query_version_reply_t *reply;
772.38763 -+	xcb_generic_error_t *error;
772.38764 -+
772.38765 -+	*major = *minor = -1;
772.38766 -+
772.38767 -+	reply = xcb_dri3_query_version_reply(c,
772.38768 -+					     xcb_dri3_query_version(c,
772.38769 -+								    XCB_DRI3_MAJOR_VERSION,
772.38770 -+								    XCB_DRI3_MINOR_VERSION),
772.38771 -+					     &error);
772.38772 -+	free(error);
772.38773 -+	if (reply == NULL)
772.38774 -+		return -1;
772.38775 -+
772.38776 -+	*major = reply->major_version;
772.38777 -+	*minor = reply->minor_version;
772.38778 -+	free(reply);
772.38779 -+
772.38780 -+	return 0;
772.38781 -+}
772.38782 -+
772.38783 -+static int has_dri3(Display *dpy)
772.38784 -+{
772.38785 -+	const xcb_query_extension_reply_t *ext;
772.38786 -+	int major, minor;
772.38787 -+
772.38788 -+	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
772.38789 -+	if (ext == NULL || !ext->present)
772.38790 -+		return 0;
772.38791 -+
772.38792 -+	if (dri3_query_version(dpy, &major, &minor) < 0)
772.38793 -+		return 0;
772.38794 -+
772.38795 -+	return major >= 0;
772.38796 -+}
772.38797 -+
772.38798 -+static int has_xfixes(Display *dpy)
772.38799 -+{
772.38800 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.38801 -+	const xcb_query_extension_reply_t *ext;
772.38802 -+	void *reply;
772.38803 -+
772.38804 -+	ext = xcb_get_extension_data(c, &xcb_xfixes_id);
772.38805 -+	if (ext == NULL || !ext->present)
772.38806 -+		return 0;
772.38807 -+
772.38808 -+	reply = xcb_xfixes_query_version_reply(c,
772.38809 -+					       xcb_xfixes_query_version(c,
772.38810 -+									XCB_XFIXES_MAJOR_VERSION,
772.38811 -+									XCB_XFIXES_MINOR_VERSION),
772.38812 -+					       NULL);
772.38813 -+	free(reply);
772.38814 -+
772.38815 -+	return reply != NULL;
772.38816 -+}
772.38817 -+
772.38818 -+static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
772.38819 -+{
772.38820 -+	XRRScreenResources *res;
772.38821 -+
772.38822 -+	res = XRRGetScreenResourcesCurrent(dpy, window);
772.38823 -+	if (res == NULL)
772.38824 -+		res = XRRGetScreenResources(dpy, window);
772.38825 -+
772.38826 -+	return res;
772.38827 -+}
772.38828 -+
772.38829 -+static XRRModeInfo *lookup_mode(XRRScreenResources *res, int id)
772.38830 -+{
772.38831 -+	int i;
772.38832 -+
772.38833 -+	for (i = 0; i < res->nmode; i++) {
772.38834 -+		if (res->modes[i].id == id)
772.38835 -+			return &res->modes[i];
772.38836 -+	}
772.38837 -+
772.38838 -+	return NULL;
772.38839 -+}
772.38840 -+
772.38841 -+static void fullscreen(Display *dpy, Window win)
772.38842 -+{
772.38843 -+	Atom atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
772.38844 -+	XChangeProperty(dpy, win,
772.38845 -+			XInternAtom(dpy, "_NET_WM_STATE", False),
772.38846 -+			XA_ATOM, 32, PropModeReplace,
772.38847 -+			(unsigned char *)&atom, 1);
772.38848 -+}
772.38849 -+
772.38850 -+static void loop(Display *dpy, XRRScreenResources *res, unsigned options)
772.38851 -+{
772.38852 -+	Window root = DefaultRootWindow(dpy);
772.38853 -+	Window win;
772.38854 -+	XSetWindowAttributes attr;
772.38855 -+	int i, j;
772.38856 -+
772.38857 -+	attr.override_redirect = 1;
772.38858 -+
772.38859 -+	run(dpy, root, "off", options);
772.38860 -+	XSync(dpy, True);
772.38861 -+
772.38862 -+	for (i = 0; i < res->noutput; i++) {
772.38863 -+		XRROutputInfo *output;
772.38864 -+		XRRModeInfo *mode;
772.38865 -+
772.38866 -+		output = XRRGetOutputInfo(dpy, res, res->outputs[i]);
772.38867 -+		if (output == NULL)
772.38868 -+			continue;
772.38869 -+
772.38870 -+		mode = NULL;
772.38871 -+		if (res->nmode)
772.38872 -+			mode = lookup_mode(res, output->modes[0]);
772.38873 -+
772.38874 -+		for (j = 0; mode && j < 2*output->ncrtc; j++) {
772.38875 -+			int c = j;
772.38876 -+			if (c >= output->ncrtc)
772.38877 -+				c = 2*output->ncrtc - j - 1;
772.38878 -+
772.38879 -+			printf("[%d, %d] -- OUTPUT:%ld, CRTC:%ld: %dx%d\n",
772.38880 -+			       i, c, (long)res->outputs[i], (long)output->crtcs[c],
772.38881 -+			       mode->width, mode->height);
772.38882 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
772.38883 -+					 0, 0, output->modes[0], RR_Rotate_0, &res->outputs[i], 1);
772.38884 -+
772.38885 -+			run(dpy, root, "root", options);
772.38886 -+			XSync(dpy, True);
772.38887 -+
772.38888 -+			win = XCreateWindow(dpy, root,
772.38889 -+					    0, 0, mode->width, mode->height, 0,
772.38890 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.38891 -+					    InputOutput,
772.38892 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.38893 -+					    CWOverrideRedirect, &attr);
772.38894 -+			fullscreen(dpy, win);
772.38895 -+			XMapWindow(dpy, win);
772.38896 -+			run(dpy, win, "fullscreen", options);
772.38897 -+			XDestroyWindow(dpy, win);
772.38898 -+			XSync(dpy, True);
772.38899 -+
772.38900 -+			win = XCreateWindow(dpy, root,
772.38901 -+					    0, 0, mode->width, mode->height, 0,
772.38902 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.38903 -+					    InputOutput,
772.38904 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.38905 -+					    CWOverrideRedirect, &attr);
772.38906 -+			XMapWindow(dpy, win);
772.38907 -+			run(dpy, win, "windowed", options);
772.38908 -+			XDestroyWindow(dpy, win);
772.38909 -+			XSync(dpy, True);
772.38910 -+
772.38911 -+			if (has_composite(dpy)) {
772.38912 -+				Damage damage;
772.38913 -+
772.38914 -+				_x_error_occurred = 0;
772.38915 -+				win = XCreateWindow(dpy, root,
772.38916 -+						    0, 0, mode->width, mode->height, 0,
772.38917 -+						    DefaultDepth(dpy, DefaultScreen(dpy)),
772.38918 -+						    InputOutput,
772.38919 -+						    DefaultVisual(dpy, DefaultScreen(dpy)),
772.38920 -+						    CWOverrideRedirect, &attr);
772.38921 -+				XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.38922 -+				damage = XDamageCreate(dpy, win, XDamageReportNonEmpty);
772.38923 -+				XMapWindow(dpy, win);
772.38924 -+				XSync(dpy, True);
772.38925 -+				if (!_x_error_occurred)
772.38926 -+					run(dpy, win, "composited", options);
772.38927 -+				XDamageDestroy(dpy, damage);
772.38928 -+				XDestroyWindow(dpy, win);
772.38929 -+				XSync(dpy, True);
772.38930 -+			}
772.38931 -+
772.38932 -+			win = XCreateWindow(dpy, root,
772.38933 -+					    0, 0, mode->width/2, mode->height/2, 0,
772.38934 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.38935 -+					    InputOutput,
772.38936 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.38937 -+					    CWOverrideRedirect, &attr);
772.38938 -+			XMapWindow(dpy, win);
772.38939 -+			run(dpy, win, "half", options);
772.38940 -+			XDestroyWindow(dpy, win);
772.38941 -+			XSync(dpy, True);
772.38942 -+
772.38943 -+			perpixel(dpy, mode->width, mode->height, options);
772.38944 -+
772.38945 -+			siblings(dpy, mode->width, mode->height,
772.38946 -+				 sysconf(_SC_NPROCESSORS_ONLN),
772.38947 -+				 options);
772.38948 -+
772.38949 -+			cousins(mode->width, mode->height,
772.38950 -+				sysconf(_SC_NPROCESSORS_ONLN),
772.38951 -+				options);
772.38952 -+
772.38953 -+			XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime,
772.38954 -+					 0, 0, None, RR_Rotate_0, NULL, 0);
772.38955 -+		}
772.38956 -+
772.38957 -+		XRRFreeOutputInfo(output);
772.38958 -+	}
772.38959 -+
772.38960 -+}
772.38961 -+
772.38962 -+int main(void)
772.38963 -+{
772.38964 -+	Display *dpy;
772.38965 -+	XRRScreenResources *res;
772.38966 -+	XRRCrtcInfo **original_crtc;
772.38967 -+	int i;
772.38968 -+
772.38969 -+	XInitThreads();
772.38970 -+
772.38971 -+	dpy = XOpenDisplay(NULL);
772.38972 -+	if (dpy == NULL)
772.38973 -+		return 77;
772.38974 -+
772.38975 -+	if (!has_present(dpy))
772.38976 -+		return 77;
772.38977 -+
772.38978 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.38979 -+		DPMSDisable(dpy);
772.38980 -+
772.38981 -+	signal(SIGALRM, SIG_IGN);
772.38982 -+	XSetErrorHandler(_check_error_handler);
772.38983 -+
772.38984 -+	res = NULL;
772.38985 -+	if (XRRQueryVersion(dpy, &i, &i))
772.38986 -+		res = _XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
772.38987 -+	if (res == NULL)
772.38988 -+		return 77;
772.38989 -+
772.38990 -+	original_crtc = malloc(sizeof(XRRCrtcInfo *)*res->ncrtc);
772.38991 -+	for (i = 0; i < res->ncrtc; i++)
772.38992 -+		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
772.38993 -+
772.38994 -+	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
772.38995 -+	for (i = 0; i < res->ncrtc; i++)
772.38996 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.38997 -+				 0, 0, None, RR_Rotate_0, NULL, 0);
772.38998 -+
772.38999 -+	loop(dpy, res, 0);
772.39000 -+	loop(dpy, res, ASYNC);
772.39001 -+	if (has_xfixes(dpy))
772.39002 -+		loop(dpy, res, NOCOPY);
772.39003 -+	if (has_dri3(dpy)) {
772.39004 -+		loop(dpy, res, DRI3);
772.39005 -+		loop(dpy, res, DRI3 | ASYNC);
772.39006 -+	}
772.39007 -+
772.39008 -+	for (i = 0; i < res->ncrtc; i++)
772.39009 -+		XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime,
772.39010 -+				 original_crtc[i]->x,
772.39011 -+				 original_crtc[i]->y,
772.39012 -+				 original_crtc[i]->mode,
772.39013 -+				 original_crtc[i]->rotation,
772.39014 -+				 original_crtc[i]->outputs,
772.39015 -+				 original_crtc[i]->noutput);
772.39016 -+
772.39017 -+	if (DPMSQueryExtension(dpy, &i, &i))
772.39018 -+		DPMSEnable(dpy);
772.39019 -+	return 0;
772.39020 -+}
772.39021 -diff --git a/test/present-test.c b/test/present-test.c
772.39022 -index 6b562eb0..5a12a24f 100644
772.39023 ---- a/test/present-test.c
772.39024 -+++ b/test/present-test.c
772.39025 -@@ -31,7 +31,9 @@
772.39026 - #include <X11/xshmfence.h>
772.39027 - #include <X11/Xutil.h>
772.39028 - #include <X11/Xlibint.h>
772.39029 -+#include <X11/extensions/dpms.h>
772.39030 - #include <X11/extensions/randr.h>
772.39031 -+#include <X11/extensions/Xcomposite.h>
772.39032 - #include <X11/extensions/Xrandr.h>
772.39033 - #include <X11/extensions/Xrender.h>
772.39034 - #include <X11/extensions/XShm.h>
772.39035 -@@ -44,6 +46,8 @@
772.39036 - #endif
772.39037 - #include <xcb/xcb.h>
772.39038 - #include <xcb/present.h>
772.39039 -+#include <xcb/xfixes.h>
772.39040 -+#include <xcb/dri3.h>
772.39041 - #include <xf86drm.h>
772.39042 - #include <i915_drm.h>
772.39043 - 
772.39044 -@@ -134,12 +138,14 @@ static void *setup_msc(Display *dpy,  Window win)
772.39045 - 	return q;
772.39046 - }
772.39047 - 
772.39048 --static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
772.39049 -+static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc, uint64_t *ust)
772.39050 - {
772.39051 - 	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39052 -+	static uint32_t serial = 1;
772.39053 - 	uint64_t msc = 0;
772.39054 -+	int complete = 0;
772.39055 - 
772.39056 --	xcb_present_notify_msc(c, win, 0, 0, 0, 0);
772.39057 -+	xcb_present_notify_msc(c, win, serial ^ 0xcc00ffee, 0, 0, 0);
772.39058 - 	xcb_flush(c);
772.39059 - 
772.39060 - 	do {
772.39061 -@@ -151,82 +157,1268 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
772.39062 - 			break;
772.39063 - 
772.39064 - 		ce = (xcb_present_complete_notify_event_t *)ev;
772.39065 --		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
772.39066 -+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
772.39067 -+		    ce->serial == (serial ^ 0xcc00ffee)) {
772.39068 -+			msc = ce->msc;
772.39069 -+			if (ust)
772.39070 -+				*ust = ce->ust;
772.39071 -+			complete = 1;
772.39072 -+		}
772.39073 -+		free(ev);
772.39074 -+	} while (!complete);
772.39075 -+
772.39076 -+	if ((int64_t)(msc - last_msc) < 0) {
772.39077 -+		printf("Invalid MSC: was %llu, now %llu\n",
772.39078 -+		       (long long)last_msc, (long long)msc);
772.39079 -+	}
772.39080 -+
772.39081 -+	if (++serial == 0)
772.39082 -+		serial = 1;
772.39083 -+
772.39084 -+	return msc;
772.39085 -+}
772.39086 -+
772.39087 -+static uint64_t wait_vblank(Display *dpy, Window win, void *q)
772.39088 -+{
772.39089 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39090 -+	static uint32_t serial = 1;
772.39091 -+	uint64_t msc = 0;
772.39092 -+	int complete = 0;
772.39093 -+
772.39094 -+	xcb_present_notify_msc(c, win, serial ^ 0xdeadbeef, 0, 1, 0);
772.39095 -+	xcb_flush(c);
772.39096 -+
772.39097 -+	do {
772.39098 -+		xcb_present_complete_notify_event_t *ce;
772.39099 -+		xcb_generic_event_t *ev;
772.39100 -+
772.39101 -+		ev = xcb_wait_for_special_event(c, q);
772.39102 -+		if (ev == NULL)
772.39103 -+			break;
772.39104 -+
772.39105 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39106 -+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
772.39107 -+		    ce->serial == (serial ^ 0xdeadbeef)) {
772.39108 - 			msc = ce->msc;
772.39109 -+			complete = 1;
772.39110 -+		}
772.39111 -+		free(ev);
772.39112 -+	} while (!complete);
772.39113 -+
772.39114 -+	if (++serial == 0)
772.39115 -+		serial = 1;
772.39116 -+
772.39117 -+	return msc;
772.39118 -+}
772.39119 -+
772.39120 -+static uint64_t msc_interval(Display *dpy, Window win, void *q)
772.39121 -+{
772.39122 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39123 -+	uint64_t msc, ust;
772.39124 -+	int complete = 0;
772.39125 -+
772.39126 -+	msc = check_msc(dpy, win, q, 0, NULL);
772.39127 -+
772.39128 -+	xcb_present_notify_msc(c, win, 0xc0ffee00, msc, 0, 0);
772.39129 -+	xcb_present_notify_msc(c, win, 0xc0ffee01, msc + 10, 0, 0);
772.39130 -+	xcb_flush(c);
772.39131 -+
772.39132 -+	ust = msc = 0;
772.39133 -+	do {
772.39134 -+		xcb_present_complete_notify_event_t *ce;
772.39135 -+		xcb_generic_event_t *ev;
772.39136 -+
772.39137 -+		ev = xcb_wait_for_special_event(c, q);
772.39138 -+		if (ev == NULL)
772.39139 -+			break;
772.39140 -+
772.39141 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39142 -+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
772.39143 -+		    ce->serial == 0xc0ffee00) {
772.39144 -+			msc -= ce->msc;
772.39145 -+			ust -= ce->ust;
772.39146 -+			complete++;
772.39147 -+		}
772.39148 -+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
772.39149 -+		    ce->serial == 0xc0ffee01) {
772.39150 -+			msc += ce->msc;
772.39151 -+			ust += ce->ust;
772.39152 -+			complete++;
772.39153 -+		}
772.39154 -+		free(ev);
772.39155 -+	} while (complete != 2);
772.39156 -+
772.39157 -+	printf("10 frame interval: msc=%lld, ust=%lld\n",
772.39158 -+	       (long long)msc, (long long)ust);
772.39159 -+	XSync(dpy, True);
772.39160 -+	if (msc == 0)
772.39161 -+		return 0;
772.39162 -+
772.39163 -+	return (ust + msc/2) / msc;
772.39164 -+}
772.39165 -+
772.39166 -+static void teardown_msc(Display *dpy, void *q)
772.39167 -+{
772.39168 -+	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
772.39169 -+}
772.39170 -+
772.39171 -+static int test_whole(Display *dpy, Window win, const char *phase)
772.39172 -+{
772.39173 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39174 -+	Pixmap pixmap;
772.39175 -+	struct dri3_fence fence;
772.39176 -+	Window root;
772.39177 -+	unsigned int width, height;
772.39178 -+	unsigned border, depth;
772.39179 -+	int x, y, ret = 1;
772.39180 -+
772.39181 -+	XGetGeometry(dpy, win,
772.39182 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39183 -+
772.39184 -+	if (dri3_create_fence(dpy, win, &fence))
772.39185 -+		return 0;
772.39186 -+
772.39187 -+	printf("%s: Testing simple flip: %dx%d\n", phase, width, height);
772.39188 -+	_x_error_occurred = 0;
772.39189 -+
772.39190 -+	xshmfence_reset(fence.addr);
772.39191 -+
772.39192 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39193 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.39194 -+			   0, /* valid */
772.39195 -+			   0, /* update */
772.39196 -+			   0, /* x_off */
772.39197 -+			   0, /* y_off */
772.39198 -+			   None,
772.39199 -+			   None, /* wait fence */
772.39200 -+			   fence.xid,
772.39201 -+			   XCB_PRESENT_OPTION_NONE,
772.39202 -+			   0, /* target msc */
772.39203 -+			   0, /* divisor */
772.39204 -+			   0, /* remainder */
772.39205 -+			   0, NULL);
772.39206 -+	XFreePixmap(dpy, pixmap);
772.39207 -+
772.39208 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39209 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.39210 -+			   0, /* valid */
772.39211 -+			   0, /* update */
772.39212 -+			   0, /* x_off */
772.39213 -+			   0, /* y_off */
772.39214 -+			   None,
772.39215 -+			   None, /* wait fence */
772.39216 -+			   None, /* sync fence */
772.39217 -+			   XCB_PRESENT_OPTION_NONE,
772.39218 -+			   0, /* target msc */
772.39219 -+			   0, /* divisor */
772.39220 -+			   0, /* remainder */
772.39221 -+			   0, NULL);
772.39222 -+	XFreePixmap(dpy, pixmap);
772.39223 -+	XFlush(dpy);
772.39224 -+
772.39225 -+	ret = !!xshmfence_await(fence.addr);
772.39226 -+	dri3_fence_free(dpy, &fence);
772.39227 -+
772.39228 -+	XSync(dpy, True);
772.39229 -+	ret += !!_x_error_occurred;
772.39230 -+
772.39231 -+	return ret;
772.39232 -+}
772.39233 -+
772.39234 -+static uint64_t flush_flips(Display *dpy, Window win, Pixmap pixmap, void *Q, uint64_t *ust)
772.39235 -+{
772.39236 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39237 -+	uint64_t msc;
772.39238 -+	int complete;
772.39239 -+
772.39240 -+	msc = check_msc(dpy, win, Q, 0, NULL);
772.39241 -+	xcb_present_pixmap(c, win, pixmap,
772.39242 -+			   0xdeadbeef, /* serial */
772.39243 -+			   0, /* valid */
772.39244 -+			   0, /* update */
772.39245 -+			   0, /* x_off */
772.39246 -+			   0, /* y_off */
772.39247 -+			   None,
772.39248 -+			   None, /* wait fence */
772.39249 -+			   None,
772.39250 -+			   XCB_PRESENT_OPTION_NONE,
772.39251 -+			   msc + 60, /* target msc */
772.39252 -+			   0, /* divisor */
772.39253 -+			   0, /* remainder */
772.39254 -+			   0, NULL);
772.39255 -+	xcb_flush(c);
772.39256 -+	complete = 0;
772.39257 -+	do {
772.39258 -+		xcb_present_complete_notify_event_t *ce;
772.39259 -+		xcb_generic_event_t *ev;
772.39260 -+
772.39261 -+		ev = xcb_wait_for_special_event(c, Q);
772.39262 -+		if (ev == NULL)
772.39263 -+			break;
772.39264 -+
772.39265 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39266 -+		complete = (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP &&
772.39267 -+			    ce->serial == 0xdeadbeef);
772.39268 -+		free(ev);
772.39269 -+	} while (!complete);
772.39270 -+	XSync(dpy, True);
772.39271 -+
772.39272 -+	return check_msc(dpy, win, Q, msc, ust);
772.39273 -+}
772.39274 -+
772.39275 -+static int test_double(Display *dpy, Window win, const char *phase, void *Q)
772.39276 -+{
772.39277 -+#define COUNT (15*60)
772.39278 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39279 -+	Pixmap pixmap;
772.39280 -+	Window root;
772.39281 -+	unsigned int width, height;
772.39282 -+	unsigned border, depth;
772.39283 -+	int x, y, n, ret;
772.39284 -+	struct {
772.39285 -+		uint64_t msc, ust;
772.39286 -+	} frame[COUNT+1];
772.39287 -+	int offset = 0;
772.39288 -+
772.39289 -+	XGetGeometry(dpy, win,
772.39290 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39291 -+
772.39292 -+	printf("%s: Testing flip double buffering: %dx%d\n", phase, width, height);
772.39293 -+	_x_error_occurred = 0;
772.39294 -+
772.39295 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39296 -+	flush_flips(dpy, win, pixmap, Q, NULL);
772.39297 -+	for (n = 0; n <= COUNT; n++) {
772.39298 -+		int complete;
772.39299 -+
772.39300 -+		xcb_present_pixmap(c, win, pixmap, n,
772.39301 -+				   0, /* valid */
772.39302 -+				   0, /* update */
772.39303 -+				   0, /* x_off */
772.39304 -+				   0, /* y_off */
772.39305 -+				   None,
772.39306 -+				   None, /* wait fence */
772.39307 -+				   None,
772.39308 -+				   XCB_PRESENT_OPTION_NONE,
772.39309 -+				   0, /* target msc */
772.39310 -+				   0, /* divisor */
772.39311 -+				   0, /* remainder */
772.39312 -+				   0, NULL);
772.39313 -+		xcb_flush(c);
772.39314 -+
772.39315 -+		complete = 0;
772.39316 -+		do {
772.39317 -+			xcb_present_complete_notify_event_t *ce;
772.39318 -+			xcb_generic_event_t *ev;
772.39319 -+
772.39320 -+			ev = xcb_wait_for_special_event(c, Q);
772.39321 -+			if (ev == NULL)
772.39322 -+				break;
772.39323 -+
772.39324 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.39325 -+			if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP &&
772.39326 -+			    ce->serial == n) {
772.39327 -+				frame[n].msc = ce->msc;
772.39328 -+				frame[n].ust = ce->ust;
772.39329 -+				complete = 1;
772.39330 -+			}
772.39331 -+			free(ev);
772.39332 -+		} while (!complete);
772.39333 -+	}
772.39334 -+	XFreePixmap(dpy, pixmap);
772.39335 -+
772.39336 -+	XSync(dpy, True);
772.39337 -+	ret = !!_x_error_occurred;
772.39338 -+
772.39339 -+	if (frame[COUNT].msc - frame[0].msc != COUNT) {
772.39340 -+		printf("Expected %d frames interval, %d elapsed instead\n",
772.39341 -+		       COUNT, (int)(frame[COUNT].msc - frame[0].msc));
772.39342 -+		for (n = 0; n <= COUNT; n++) {
772.39343 -+			if (frame[n].msc - frame[0].msc != n + offset) {
772.39344 -+				printf("frame[%d]: msc=%03lld, ust=%lld\n", n,
772.39345 -+				       (long long)(frame[n].msc - frame[0].msc),
772.39346 -+				       (long long)(frame[n].ust - frame[0].ust));
772.39347 -+				offset = frame[n].msc - frame[0].msc - n;
772.39348 -+				ret++;
772.39349 -+			}
772.39350 -+		}
772.39351 -+	}
772.39352 -+
772.39353 -+	return ret;
772.39354 -+}
772.39355 -+
772.39356 -+static int test_future(Display *dpy, Window win, const char *phase, void *Q)
772.39357 -+{
772.39358 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39359 -+	Pixmap pixmap;
772.39360 -+	struct dri3_fence fence;
772.39361 -+	Window root;
772.39362 -+	unsigned int width, height;
772.39363 -+	unsigned border, depth;
772.39364 -+	int x, y, ret = 0, n;
772.39365 -+	uint64_t msc, ust;
772.39366 -+	int complete, count;
772.39367 -+	int early = 0, late = 0;
772.39368 -+	int earliest = 0, latest = 0;
772.39369 -+	uint64_t interval;
772.39370 -+
772.39371 -+	XGetGeometry(dpy, win,
772.39372 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39373 -+
772.39374 -+	if (dri3_create_fence(dpy, win, &fence))
772.39375 -+		return 0;
772.39376 -+
772.39377 -+	printf("%s: Testing flips into the future: %dx%d\n", phase, width, height);
772.39378 -+	_x_error_occurred = 0;
772.39379 -+
772.39380 -+	interval = msc_interval(dpy, win, Q);
772.39381 -+	if (interval == 0) {
772.39382 -+		printf("Zero delay between frames\n");
772.39383 -+		return 1;
772.39384 -+	}
772.39385 -+
772.39386 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39387 -+	msc = flush_flips(dpy, win, pixmap, Q, &ust);
772.39388 -+	for (n = 1; n <= 10; n++)
772.39389 -+		xcb_present_pixmap(c, win, pixmap,
772.39390 -+				   n, /* serial */
772.39391 -+				   0, /* valid */
772.39392 -+				   0, /* update */
772.39393 -+				   0, /* x_off */
772.39394 -+				   0, /* y_off */
772.39395 -+				   None,
772.39396 -+				   None, /* wait fence */
772.39397 -+				   None,
772.39398 -+				   XCB_PRESENT_OPTION_NONE,
772.39399 -+				   msc + 60 + n*15*60, /* target msc */
772.39400 -+				   0, /* divisor */
772.39401 -+				   0, /* remainder */
772.39402 -+				   0, NULL);
772.39403 -+	xcb_present_pixmap(c, win, pixmap,
772.39404 -+			   0xdeadbeef, /* serial */
772.39405 -+			   0, /* valid */
772.39406 -+			   0, /* update */
772.39407 -+			   0, /* x_off */
772.39408 -+			   0, /* y_off */
772.39409 -+			   None,
772.39410 -+			   None, /* wait fence */
772.39411 -+			   None,
772.39412 -+			   XCB_PRESENT_OPTION_NONE,
772.39413 -+			   msc + 60 + n*15*60, /* target msc */
772.39414 -+			   0, /* divisor */
772.39415 -+			   0, /* remainder */
772.39416 -+			   0, NULL);
772.39417 -+	xcb_flush(c);
772.39418 -+
772.39419 -+	complete = 0;
772.39420 -+	count = 0;
772.39421 -+	do {
772.39422 -+		xcb_present_complete_notify_event_t *ce;
772.39423 -+		xcb_generic_event_t *ev;
772.39424 -+
772.39425 -+		ev = xcb_wait_for_special_event(c, Q);
772.39426 -+		if (ev == NULL)
772.39427 -+			break;
772.39428 -+
772.39429 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39430 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
772.39431 -+
772.39432 -+		if (ce->serial == 0xdeadbeef) {
772.39433 -+			int64_t time;
772.39434 -+
772.39435 -+			time = ce->ust - (ust + (60 + 15*60*n) * interval);
772.39436 -+			if (time < -(int64_t)interval) {
772.39437 -+				fprintf(stderr,
772.39438 -+					"\tflips completed too early by %lldms\n",
772.39439 -+					(long long)(-time / 1000));
772.39440 -+			} else if (time > (int64_t)interval) {
772.39441 -+				fprintf(stderr,
772.39442 -+					"\tflips completed too late by %lldms\n",
772.39443 -+					(long long)(time / 1000));
772.39444 -+			}
772.39445 -+			complete = 1;
772.39446 -+		} else {
772.39447 -+			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
772.39448 -+			if (diff < 0) {
772.39449 -+				if (-diff > earliest) {
772.39450 -+					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
772.39451 -+					earliest = -diff;
772.39452 -+				}
772.39453 -+				early++;
772.39454 -+				ret++;
772.39455 -+			} else if (diff > 0) {
772.39456 -+				if (diff > latest) {
772.39457 -+					fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
772.39458 -+					latest = diff;
772.39459 -+				}
772.39460 -+				late++;
772.39461 -+				ret++;
772.39462 -+			}
772.39463 -+			count++;
772.39464 -+		}
772.39465 -+		free(ev);
772.39466 -+	} while (!complete);
772.39467 -+
772.39468 -+	if (early)
772.39469 -+		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
772.39470 -+	if (late)
772.39471 -+		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
772.39472 -+
772.39473 -+	if (count != 10) {
772.39474 -+		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", 10 - count);
772.39475 -+		ret++;
772.39476 -+
772.39477 -+		do {
772.39478 -+			xcb_present_complete_notify_event_t *ce;
772.39479 -+			xcb_generic_event_t *ev;
772.39480 -+
772.39481 -+			ev = xcb_wait_for_special_event(c, Q);
772.39482 -+			if (ev == NULL)
772.39483 -+				break;
772.39484 -+
772.39485 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.39486 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
772.39487 -+			free(ev);
772.39488 -+		} while (++count != 10);
772.39489 -+	}
772.39490 -+
772.39491 -+	ret += !!_x_error_occurred;
772.39492 -+
772.39493 -+	return ret;
772.39494 -+}
772.39495 -+
772.39496 -+static int test_exhaustion(Display *dpy, Window win, const char *phase, void *Q)
772.39497 -+{
772.39498 -+#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
772.39499 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39500 -+	Pixmap pixmap;
772.39501 -+	struct dri3_fence fence[2];
772.39502 -+	Window root;
772.39503 -+	xcb_xfixes_region_t region;
772.39504 -+	unsigned int width, height;
772.39505 -+	unsigned border, depth;
772.39506 -+	int x, y, ret = 0, n;
772.39507 -+	uint64_t target, final;
772.39508 -+
772.39509 -+	XGetGeometry(dpy, win,
772.39510 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39511 -+
772.39512 -+	if (dri3_create_fence(dpy, win, &fence[0]) ||
772.39513 -+	    dri3_create_fence(dpy, win, &fence[1]))
772.39514 -+		return 0;
772.39515 -+
772.39516 -+	printf("%s: Testing flips with long vblank queues: %dx%d\n", phase, width, height);
772.39517 -+	_x_error_occurred = 0;
772.39518 -+
772.39519 -+	region = xcb_generate_id(c);
772.39520 -+	xcb_xfixes_create_region(c, region, 0, NULL);
772.39521 -+
772.39522 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39523 -+	xshmfence_reset(fence[0].addr);
772.39524 -+	xshmfence_reset(fence[1].addr);
772.39525 -+	target = check_msc(dpy, win, Q, 0, NULL);
772.39526 -+	for (n = N_VBLANKS; n--; )
772.39527 -+		xcb_present_pixmap(c, win, pixmap, 0,
772.39528 -+				   0, /* valid */
772.39529 -+				   region, /* update */
772.39530 -+				   0, /* x_off */
772.39531 -+				   0, /* y_off */
772.39532 -+				   None,
772.39533 -+				   None, /* wait fence */
772.39534 -+				   None,
772.39535 -+				   XCB_PRESENT_OPTION_NONE,
772.39536 -+				   target + N_VBLANKS, /* target msc */
772.39537 -+				   1, /* divisor */
772.39538 -+				   0, /* remainder */
772.39539 -+				   0, NULL);
772.39540 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.39541 -+			   region, /* valid */
772.39542 -+			   region, /* update */
772.39543 -+			   0, /* x_off */
772.39544 -+			   0, /* y_off */
772.39545 -+			   None,
772.39546 -+			   None, /* wait fence */
772.39547 -+			   fence[0].xid,
772.39548 -+			   XCB_PRESENT_OPTION_NONE,
772.39549 -+			   target, /* target msc */
772.39550 -+			   0, /* divisor */
772.39551 -+			   0, /* remainder */
772.39552 -+			   0, NULL);
772.39553 -+	for (n = 1; n < N_VBLANKS; n++)
772.39554 -+		xcb_present_pixmap(c, win, pixmap, 0,
772.39555 -+				   region, /* valid */
772.39556 -+				   region, /* update */
772.39557 -+				   0, /* x_off */
772.39558 -+				   0, /* y_off */
772.39559 -+				   None,
772.39560 -+				   None, /* wait fence */
772.39561 -+				   None,
772.39562 -+				   XCB_PRESENT_OPTION_NONE,
772.39563 -+				   target + n, /* target msc */
772.39564 -+				   0, /* divisor */
772.39565 -+				   0, /* remainder */
772.39566 -+				   0, NULL);
772.39567 -+	xcb_present_pixmap(c, win, pixmap, 0,
772.39568 -+			   region, /* valid */
772.39569 -+			   region, /* update */
772.39570 -+			   0, /* x_off */
772.39571 -+			   0, /* y_off */
772.39572 -+			   None,
772.39573 -+			   None, /* wait fence */
772.39574 -+			   fence[1].xid,
772.39575 -+			   XCB_PRESENT_OPTION_NONE,
772.39576 -+			   target + N_VBLANKS, /* target msc */
772.39577 -+			   0, /* divisor */
772.39578 -+			   0, /* remainder */
772.39579 -+			   0, NULL);
772.39580 -+	xcb_flush(c);
772.39581 -+
772.39582 -+	ret += !!xshmfence_await(fence[0].addr);
772.39583 -+	final = check_msc(dpy, win, Q, 0, NULL);
772.39584 -+	if (final < target) {
772.39585 -+		printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
772.39586 -+		       (long long)final, (long long)target);
772.39587 -+		ret++;
772.39588 -+	} else if (final > target + 1) {
772.39589 -+		printf("\tFirst flip too late, MSC was %llu, expected %llu\n",
772.39590 -+		       (long long)final, (long long)target);
772.39591 -+		ret++;
772.39592 -+	}
772.39593 -+
772.39594 -+	ret += !!xshmfence_await(fence[1].addr);
772.39595 -+	final = check_msc(dpy, win, Q, 0, NULL);
772.39596 -+	if (final < target + N_VBLANKS) {
772.39597 -+		printf("\tLast flip too early, MSC was %llu, expected %llu\n",
772.39598 -+		       (long long)final, (long long)(target + N_VBLANKS));
772.39599 -+		ret++;
772.39600 -+	} else if (final > target + N_VBLANKS + 1) {
772.39601 -+		printf("\tLast flip too late, MSC was %llu, expected %llu\n",
772.39602 -+		       (long long)final, (long long)(target + N_VBLANKS));
772.39603 -+		ret++;
772.39604 -+	}
772.39605 -+
772.39606 -+	flush_flips(dpy, win, pixmap, Q, NULL);
772.39607 -+
772.39608 -+	XFreePixmap(dpy, pixmap);
772.39609 -+	xcb_xfixes_destroy_region(c, region);
772.39610 -+	dri3_fence_free(dpy, &fence[1]);
772.39611 -+	dri3_fence_free(dpy, &fence[0]);
772.39612 -+
772.39613 -+	XSync(dpy, True);
772.39614 -+	ret += !!_x_error_occurred;
772.39615 -+
772.39616 -+	return ret;
772.39617 -+#undef N_VBLANKS
772.39618 -+}
772.39619 -+
772.39620 -+static int test_accuracy(Display *dpy, Window win, const char *phase, void *Q)
772.39621 -+{
772.39622 -+#define N_VBLANKS (60 * 120) /* ~2 minutes */
772.39623 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39624 -+	Pixmap pixmap;
772.39625 -+	Window root;
772.39626 -+	unsigned int width, height;
772.39627 -+	unsigned border, depth;
772.39628 -+	int x, y, ret = 0, n;
772.39629 -+	uint64_t target;
772.39630 -+	int early = 0, late = 0;
772.39631 -+	int earliest = 0, latest = 0;
772.39632 -+	int complete, count;
772.39633 -+
772.39634 -+	XGetGeometry(dpy, win,
772.39635 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39636 -+
772.39637 -+	printf("%s: Testing flip accuracy: %dx%d\n", phase, width, height);
772.39638 -+	_x_error_occurred = 0;
772.39639 -+
772.39640 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39641 -+	target = flush_flips(dpy, win, pixmap, Q, NULL);
772.39642 -+	for (n = 0; n <= N_VBLANKS; n++)
772.39643 -+		xcb_present_pixmap(c, win, pixmap,
772.39644 -+				   n, /* serial */
772.39645 -+				   0, /* valid */
772.39646 -+				   0, /* update */
772.39647 -+				   0, /* x_off */
772.39648 -+				   0, /* y_off */
772.39649 -+				   None,
772.39650 -+				   None, /* wait fence */
772.39651 -+				   None,
772.39652 -+				   XCB_PRESENT_OPTION_NONE,
772.39653 -+				   target + 60 + n, /* target msc */
772.39654 -+				   0, /* divisor */
772.39655 -+				   0, /* remainder */
772.39656 -+				   0, NULL);
772.39657 -+	xcb_present_pixmap(c, win, pixmap,
772.39658 -+			   0xdeadbeef, /* serial */
772.39659 -+			   0, /* valid */
772.39660 -+			   0, /* update */
772.39661 -+			   0, /* x_off */
772.39662 -+			   0, /* y_off */
772.39663 -+			   None,
772.39664 -+			   None, /* wait fence */
772.39665 -+			   None,
772.39666 -+			   XCB_PRESENT_OPTION_NONE,
772.39667 -+			   target + 60 + n, /* target msc */
772.39668 -+			   0, /* divisor */
772.39669 -+			   0, /* remainder */
772.39670 -+			   0, NULL);
772.39671 -+	xcb_flush(c);
772.39672 -+
772.39673 -+	complete = 0;
772.39674 -+	count = 0;
772.39675 -+	do {
772.39676 -+		xcb_present_complete_notify_event_t *ce;
772.39677 -+		xcb_generic_event_t *ev;
772.39678 -+
772.39679 -+		ev = xcb_wait_for_special_event(c, Q);
772.39680 -+		if (ev == NULL)
772.39681 -+			break;
772.39682 -+
772.39683 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39684 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
772.39685 -+
772.39686 -+		if (ce->serial != 0xdeadbeef) {
772.39687 -+			int diff = (int64_t)(ce->msc - (target + ce->serial + 60));
772.39688 -+			if (diff < 0) {
772.39689 -+				if (-diff > earliest) {
772.39690 -+					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
772.39691 -+					earliest = -diff;
772.39692 -+				}
772.39693 -+				early++;
772.39694 -+				ret++;
772.39695 -+			} else if (diff > 0) {
772.39696 -+				if (diff > latest) {
772.39697 -+					fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
772.39698 -+					latest = diff;
772.39699 -+				}
772.39700 -+				late++;
772.39701 -+				ret++;
772.39702 -+			}
772.39703 -+			count++;
772.39704 -+		} else
772.39705 -+			complete = 1;
772.39706 - 		free(ev);
772.39707 --	} while (msc == 0);
772.39708 -+	} while (!complete);
772.39709 -+
772.39710 -+	if (early)
772.39711 -+		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
772.39712 -+	if (late)
772.39713 -+		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
772.39714 -+
772.39715 -+	if (count != N_VBLANKS+1) {
772.39716 -+		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", N_VBLANKS+1 - count);
772.39717 -+		ret++;
772.39718 -+		do {
772.39719 -+			xcb_present_complete_notify_event_t *ce;
772.39720 -+			xcb_generic_event_t *ev;
772.39721 -+
772.39722 -+			ev = xcb_wait_for_special_event(c, Q);
772.39723 -+			if (ev == NULL)
772.39724 -+				break;
772.39725 -+
772.39726 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.39727 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
772.39728 -+			free(ev);
772.39729 -+		} while (++count != N_VBLANKS+1);
772.39730 -+	}
772.39731 -+
772.39732 -+	XFreePixmap(dpy, pixmap);
772.39733 -+
772.39734 -+	XSync(dpy, True);
772.39735 -+	ret += !!_x_error_occurred;
772.39736 -+
772.39737 -+	return ret;
772.39738 -+#undef N_VBLANKS
772.39739 -+}
772.39740 -+
772.39741 -+static int test_modulus(Display *dpy, Window win, const char *phase, void *Q)
772.39742 -+{
772.39743 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39744 -+	Pixmap pixmap;
772.39745 -+	Window root;
772.39746 -+	unsigned int width, height;
772.39747 -+	unsigned border, depth;
772.39748 -+	xcb_xfixes_region_t region;
772.39749 -+	int x, y, ret = 0;
772.39750 -+	uint64_t target;
772.39751 -+	int early = 0, late = 0;
772.39752 -+	int earliest = 0, latest = 0;
772.39753 -+	int complete, expect, count;
772.39754 -+
772.39755 -+	XGetGeometry(dpy, win,
772.39756 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.39757 -+
772.39758 -+	printf("%s: Testing flip modulus: %dx%d\n", phase, width, height);
772.39759 -+	_x_error_occurred = 0;
772.39760 -+
772.39761 -+	region = xcb_generate_id(c);
772.39762 -+	xcb_xfixes_create_region(c, region, 0, NULL);
772.39763 -+
772.39764 -+	pixmap = XCreatePixmap(dpy, win, width, height, depth);
772.39765 -+	target = flush_flips(dpy, win, pixmap, Q, NULL);
772.39766 -+	expect = 0;
772.39767 -+	for (x = 1; x <= 7; x++) {
772.39768 -+		for (y = 0; y < x; y++) {
772.39769 -+			xcb_present_pixmap(c, win, pixmap,
772.39770 -+					   y << 16 | x, /* serial */
772.39771 -+					   region, /* valid */
772.39772 -+					   region, /* update */
772.39773 -+					   0, /* x_off */
772.39774 -+					   0, /* y_off */
772.39775 -+					   None,
772.39776 -+					   None, /* wait fence */
772.39777 -+					   None,
772.39778 -+					   XCB_PRESENT_OPTION_NONE,
772.39779 -+					   0, /* target msc */
772.39780 -+					   x, /* divisor */
772.39781 -+					   y, /* remainder */
772.39782 -+					   0, NULL);
772.39783 -+			expect++;
772.39784 -+		}
772.39785 -+	}
772.39786 -+	xcb_present_pixmap(c, win, pixmap,
772.39787 -+			   0xdeadbeef, /* serial */
772.39788 -+			   0, /* valid */
772.39789 -+			   0, /* update */
772.39790 -+			   0, /* x_off */
772.39791 -+			   0, /* y_off */
772.39792 -+			   None,
772.39793 -+			   None, /* wait fence */
772.39794 -+			   None,
772.39795 -+			   XCB_PRESENT_OPTION_NONE,
772.39796 -+			   target + 2*x, /* target msc */
772.39797 -+			   0, /* divisor */
772.39798 -+			   0, /* remainder */
772.39799 -+			   0, NULL);
772.39800 -+	xcb_flush(c);
772.39801 -+
772.39802 -+	complete = 0;
772.39803 -+	count = 0;
772.39804 -+	do {
772.39805 -+		xcb_present_complete_notify_event_t *ce;
772.39806 -+		xcb_generic_event_t *ev;
772.39807 -+
772.39808 -+		ev = xcb_wait_for_special_event(c, Q);
772.39809 -+		if (ev == NULL)
772.39810 -+			break;
772.39811 -+
772.39812 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39813 -+		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
772.39814 -+			break;
772.39815 -+
772.39816 -+		assert(ce->serial);
772.39817 -+		if (ce->serial != 0xdeadbeef) {
772.39818 -+			uint64_t msc;
772.39819 -+			int diff;
772.39820 -+
772.39821 -+			x = ce->serial & 0xffff;
772.39822 -+			y = ce->serial >> 16;
772.39823 -+
772.39824 -+			msc = target;
772.39825 -+			msc -= target % x;
772.39826 -+			msc += y;
772.39827 -+			if (msc <= target)
772.39828 -+				msc += x;
772.39829 -+
772.39830 -+			diff = (int64_t)(ce->msc - msc);
772.39831 -+			if (diff < 0) {
772.39832 -+				if (-diff > earliest) {
772.39833 -+					fprintf(stderr, "\tframe (%d, %d) displayed early by %d frames\n", y, x, -diff);
772.39834 -+					earliest = -diff;
772.39835 -+				}
772.39836 -+				early++;
772.39837 -+				ret++;
772.39838 -+			} else if (diff > 0) {
772.39839 -+				if (diff > latest) {
772.39840 -+					fprintf(stderr, "\tframe (%d, %d) displayed late by %d frames\n", y, x, diff);
772.39841 -+					latest = diff;
772.39842 -+				}
772.39843 -+				late++;
772.39844 -+				ret++;
772.39845 -+			}
772.39846 -+			count++;
772.39847 -+		} else
772.39848 -+			complete = 1;
772.39849 -+		free(ev);
772.39850 -+	} while (!complete);
772.39851 -+
772.39852 -+	if (early)
772.39853 -+		printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
772.39854 -+	if (late)
772.39855 -+		printf("\t%d frames shown too late (worst %d)!\n", late, latest);
772.39856 -+
772.39857 -+	if (count != expect) {
772.39858 -+		fprintf(stderr, "Sentinel frame received too early! %d frames outstanding\n", expect - count);
772.39859 -+		ret++;
772.39860 -+		do {
772.39861 -+			xcb_present_complete_notify_event_t *ce;
772.39862 -+			xcb_generic_event_t *ev;
772.39863 -+
772.39864 -+			ev = xcb_wait_for_special_event(c, Q);
772.39865 -+			if (ev == NULL)
772.39866 -+				break;
772.39867 -+
772.39868 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.39869 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.39870 -+			free(ev);
772.39871 -+		} while (++count != expect);
772.39872 -+	}
772.39873 -+
772.39874 -+	XFreePixmap(dpy, pixmap);
772.39875 -+	xcb_xfixes_destroy_region(c, region);
772.39876 -+
772.39877 -+	XSync(dpy, True);
772.39878 -+	ret += !!_x_error_occurred;
772.39879 -+
772.39880 -+	return ret;
772.39881 -+}
772.39882 -+
772.39883 -+static int test_future_msc(Display *dpy, void *Q)
772.39884 -+{
772.39885 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.39886 -+	Window root = DefaultRootWindow(dpy);
772.39887 -+	int ret = 0, n;
772.39888 -+	uint64_t msc, ust;
772.39889 -+	int complete, count;
772.39890 -+	int early = 0, late = 0;
772.39891 -+	int earliest = 0, latest = 0;
772.39892 -+	uint64_t interval;
772.39893 -+
772.39894 -+	printf("Testing notifies into the future\n");
772.39895 -+	_x_error_occurred = 0;
772.39896 -+
772.39897 -+	interval = msc_interval(dpy, root, Q);
772.39898 -+	if (interval == 0) {
772.39899 -+		printf("Zero delay between frames\n");
772.39900 -+		return 1;
772.39901 -+	}
772.39902 -+	msc = check_msc(dpy, root, Q, 0, &ust);
772.39903 -+	printf("Initial msc=%llx, interval between frames %lldus\n",
772.39904 -+	       (long long)msc, (long long)interval);
772.39905 -+
772.39906 -+	for (n = 1; n <= 10; n++)
772.39907 -+		xcb_present_notify_msc(c, root, n, msc + 60 + n*15*60, 0, 0);
772.39908 -+	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n*15*60, 0, 0);
772.39909 -+	xcb_flush(c);
772.39910 -+
772.39911 -+	complete = 0;
772.39912 -+	count = 0;
772.39913 -+	do {
772.39914 -+		xcb_present_complete_notify_event_t *ce;
772.39915 -+		xcb_generic_event_t *ev;
772.39916 -+
772.39917 -+		ev = xcb_wait_for_special_event(c, Q);
772.39918 -+		if (ev == NULL)
772.39919 -+			break;
772.39920 -+
772.39921 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.39922 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.39923 -+
772.39924 -+		if (ce->serial == 0xdeadbeef) {
772.39925 -+			int64_t time, tolerance;
772.39926 -+
772.39927 -+			tolerance = 60 + 15*60*n/10;
772.39928 -+			if (tolerance < interval)
772.39929 -+				tolerance = interval;
772.39930 -+
772.39931 -+			time = ce->ust - (ust + (60 + 15*60*n) * interval);
772.39932 -+			if (time < -(int64_t)tolerance) {
772.39933 -+				fprintf(stderr,
772.39934 -+					"\tnotifies completed too early by %lldms, tolerance %lldus\n",
772.39935 -+					(long long)(-time / 1000), (long long)tolerance);
772.39936 -+			} else if (time > (int64_t)tolerance) {
772.39937 -+				fprintf(stderr,
772.39938 -+					"\tnotifies completed too late by %lldms, tolerance %lldus\n",
772.39939 -+					(long long)(time / 1000), (long long)tolerance);
772.39940 -+			}
772.39941 -+			complete = 1;
772.39942 -+		} else {
772.39943 -+			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
772.39944 -+
772.39945 -+			if (ce->serial != count + 1) {
772.39946 -+				fprintf(stderr, "vblank received out of order! expected %d, received %d\n",
772.39947 -+					count + 1, (int)ce->serial);
772.39948 -+				ret++;
772.39949 -+			}
772.39950 -+			count++;
772.39951 -+
772.39952 -+			if (diff < 0) {
772.39953 -+				if (-diff > earliest) {
772.39954 -+					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
772.39955 -+					earliest = -diff;
772.39956 -+				}
772.39957 -+				early++;
772.39958 -+				ret++;
772.39959 -+			} else if (diff > 0) {
772.39960 -+				if (diff > latest) {
772.39961 -+					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
772.39962 -+					latest = diff;
772.39963 -+				}
772.39964 -+				late++;
772.39965 -+				ret++;
772.39966 -+			}
772.39967 -+		}
772.39968 -+		free(ev);
772.39969 -+	} while (!complete);
772.39970 -+
772.39971 -+	if (early)
772.39972 -+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
772.39973 -+	if (late)
772.39974 -+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
772.39975 -+
772.39976 -+	if (count != 10) {
772.39977 -+		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", 10 - count);
772.39978 -+		ret++;
772.39979 -+		do {
772.39980 -+			xcb_present_complete_notify_event_t *ce;
772.39981 -+			xcb_generic_event_t *ev;
772.39982 -+
772.39983 -+			ev = xcb_wait_for_special_event(c, Q);
772.39984 -+			if (ev == NULL)
772.39985 -+				break;
772.39986 -+
772.39987 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.39988 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.39989 -+			free(ev);
772.39990 -+		} while (++count != 10);
772.39991 -+	}
772.39992 -+
772.39993 -+	XSync(dpy, True);
772.39994 -+	ret += !!_x_error_occurred;
772.39995 -+
772.39996 -+	return ret;
772.39997 -+}
772.39998 -+
772.39999 -+static int test_wrap_msc(Display *dpy)
772.40000 -+{
772.40001 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.40002 -+	Window root, win;
772.40003 -+	int x, y;
772.40004 -+	unsigned int width, height;
772.40005 -+	unsigned border, depth;
772.40006 -+	XSetWindowAttributes attr;
772.40007 -+	int ret = 0, n;
772.40008 -+	uint64_t msc, ust;
772.40009 -+	int complete;
772.40010 -+	uint64_t interval;
772.40011 -+	void *Q;
772.40012 -+
772.40013 -+	XGetGeometry(dpy, DefaultRootWindow(dpy),
772.40014 -+		     &root, &x, &y, &width, &height, &border, &depth);
772.40015 -+
772.40016 -+	attr.override_redirect = 1;
772.40017 -+	win = XCreateWindow(dpy, root,
772.40018 -+			    0, 0, width, height, 0, depth,
772.40019 -+			    InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
772.40020 -+			    CWOverrideRedirect, &attr);
772.40021 -+	XMapWindow(dpy, win);
772.40022 -+	XSync(dpy, True);
772.40023 -+	if (_x_error_occurred)
772.40024 -+		return 1;
772.40025 - 
772.40026 --	if (msc < last_msc) {
772.40027 --		printf("Invalid MSC: was %llu, now %llu\n",
772.40028 --		       (long long)last_msc, (long long)msc);
772.40029 -+	printf("Testing wraparound notifies\n");
772.40030 -+	_x_error_occurred = 0;
772.40031 -+
772.40032 -+	Q = setup_msc(dpy, win);
772.40033 -+	interval = msc_interval(dpy, win, Q);
772.40034 -+	if (interval == 0) {
772.40035 -+		printf("Zero delay between frames\n");
772.40036 -+		return 1;
772.40037 - 	}
772.40038 -+	msc = check_msc(dpy, win, Q, 0, &ust);
772.40039 -+	printf("Initial msc=%llx, interval between frames %lldus\n",
772.40040 -+	       (long long)msc, (long long)interval);
772.40041 -+
772.40042 -+	for (n = 1; n <= 10; n++)
772.40043 -+		xcb_present_notify_msc(c, win, n,
772.40044 -+				       msc + ((long long)n<<32) + n,
772.40045 -+				       0, 0);
772.40046 -+	for (n = 1; n <= 10; n++)
772.40047 -+		xcb_present_notify_msc(c, win, -n,
772.40048 -+				       0, (long long)n << 32, 0);
772.40049 -+	xcb_present_notify_msc(c, win, 0xdeadbeef, msc + 60*10, 0, 0);
772.40050 -+	xcb_flush(c);
772.40051 - 
772.40052 --	return msc;
772.40053 -+	complete = 0;
772.40054 -+	do {
772.40055 -+		xcb_present_complete_notify_event_t *ce;
772.40056 -+		xcb_generic_event_t *ev;
772.40057 -+
772.40058 -+		ev = xcb_wait_for_special_event(c, Q);
772.40059 -+		if (ev == NULL)
772.40060 -+			break;
772.40061 -+
772.40062 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.40063 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40064 -+
772.40065 -+		if (ce->serial == 0xdeadbeef) {
772.40066 -+			complete = 1;
772.40067 -+		} else {
772.40068 -+			fprintf(stderr,
772.40069 -+				"\tnotify %d recieved at +%llu\n",
772.40070 -+				ce->serial, ce->msc - msc);
772.40071 -+			ret++;
772.40072 -+		}
772.40073 -+		free(ev);
772.40074 -+	} while (!complete);
772.40075 -+
772.40076 -+	teardown_msc(dpy, Q);
772.40077 -+	XDestroyWindow(dpy, win);
772.40078 -+	XSync(dpy, True);
772.40079 -+
772.40080 -+	return ret;
772.40081 - }
772.40082 - 
772.40083 --static void teardown_msc(Display *dpy, void *q)
772.40084 -+static int test_exhaustion_msc(Display *dpy, void *Q)
772.40085 - {
772.40086 --	xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
772.40087 -+#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
772.40088 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.40089 -+	Window root = DefaultRootWindow(dpy);
772.40090 -+	int ret = 0, n, complete;
772.40091 -+	int earliest = 0, early = 0;
772.40092 -+	int latest = 0, late = 0;
772.40093 -+	uint64_t msc;
772.40094 -+
772.40095 -+	printf("Testing notifies with long queues\n");
772.40096 -+	_x_error_occurred = 0;
772.40097 -+
772.40098 -+	msc = check_msc(dpy, root, Q, 0, NULL);
772.40099 -+	for (n = N_VBLANKS; n--; )
772.40100 -+		xcb_present_notify_msc(c, root, N_VBLANKS, msc + N_VBLANKS, 0, 0);
772.40101 -+	for (n = 1; n <= N_VBLANKS ; n++)
772.40102 -+		xcb_present_notify_msc(c, root, n, msc + n, 0, 0);
772.40103 -+	xcb_flush(c);
772.40104 -+
772.40105 -+	complete = 2*N_VBLANKS;
772.40106 -+	do {
772.40107 -+		xcb_present_complete_notify_event_t *ce;
772.40108 -+		xcb_generic_event_t *ev;
772.40109 -+		int diff;
772.40110 -+
772.40111 -+		ev = xcb_wait_for_special_event(c, Q);
772.40112 -+		if (ev == NULL)
772.40113 -+			break;
772.40114 -+
772.40115 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.40116 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40117 -+
772.40118 -+		diff = (int64_t)(ce->msc - msc - ce->serial);
772.40119 -+		if (diff < 0) {
772.40120 -+			if (-diff > earliest) {
772.40121 -+				fprintf(stderr, "\tnotify %d early by %d msc\n",(int)ce->serial, -diff);
772.40122 -+				earliest = -diff;
772.40123 -+			}
772.40124 -+			early++;
772.40125 -+			ret++;
772.40126 -+		} else if (diff > 0) {
772.40127 -+			if (diff > latest) {
772.40128 -+				fprintf(stderr, "\tnotify %d late by %d msc\n", (int)ce->serial, diff);
772.40129 -+				latest = diff;
772.40130 -+			}
772.40131 -+			late++;
772.40132 -+			ret++;
772.40133 -+		}
772.40134 -+		free(ev);
772.40135 -+	} while (--complete);
772.40136 -+
772.40137 -+	if (early)
772.40138 -+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
772.40139 -+	if (late)
772.40140 -+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
772.40141 -+
772.40142 -+	XSync(dpy, True);
772.40143 -+	ret += !!_x_error_occurred;
772.40144 -+
772.40145 -+	return ret;
772.40146 -+#undef N_VBLANKS
772.40147 - }
772.40148 --static int test_whole(Display *dpy)
772.40149 -+
772.40150 -+static int test_accuracy_msc(Display *dpy, void *Q)
772.40151 - {
772.40152 --	Pixmap pixmap;
772.40153 --	struct dri3_fence fence;
772.40154 --	Window root;
772.40155 --	unsigned int width, height;
772.40156 --	unsigned border, depth;
772.40157 --	int x, y, ret = 1;
772.40158 -+#define N_VBLANKS (60 * 120) /* ~2 minutes */
772.40159 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.40160 -+	Window root = DefaultRootWindow(dpy);
772.40161 -+	int ret = 0, n;
772.40162 -+	uint64_t msc;
772.40163 -+	int early = 0, late = 0;
772.40164 -+	int earliest = 0, latest = 0;
772.40165 -+	int complete, count;
772.40166 - 
772.40167 --	XGetGeometry(dpy, DefaultRootWindow(dpy),
772.40168 --		     &root, &x, &y, &width, &height, &border, &depth);
772.40169 -+	printf("Testing notify accuracy\n");
772.40170 -+	_x_error_occurred = 0;
772.40171 - 
772.40172 --	if (dri3_create_fence(dpy, root, &fence))
772.40173 --		return 0;
772.40174 -+	msc = check_msc(dpy, root, Q, 0, NULL);
772.40175 -+	for (n = 0; n <= N_VBLANKS; n++)
772.40176 -+		xcb_present_notify_msc(c, root, n, msc + 60 + n, 0, 0);
772.40177 -+	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n, 0, 0);
772.40178 -+	xcb_flush(c);
772.40179 -+
772.40180 -+	complete = 0;
772.40181 -+	count = 0;
772.40182 -+	do {
772.40183 -+		xcb_present_complete_notify_event_t *ce;
772.40184 -+		xcb_generic_event_t *ev;
772.40185 -+
772.40186 -+		ev = xcb_wait_for_special_event(c, Q);
772.40187 -+		if (ev == NULL)
772.40188 -+			break;
772.40189 -+
772.40190 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.40191 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40192 -+
772.40193 -+		if (ce->serial != 0xdeadbeef) {
772.40194 -+			int diff = (int64_t)(ce->msc - (msc + ce->serial + 60));
772.40195 -+			if (diff < 0) {
772.40196 -+				if (-diff > earliest) {
772.40197 -+					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
772.40198 -+					earliest = -diff;
772.40199 -+				}
772.40200 -+				early++;
772.40201 -+				ret++;
772.40202 -+			} else if (diff > 0) {
772.40203 -+				if (diff > latest) {
772.40204 -+					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
772.40205 -+					latest = diff;
772.40206 -+				}
772.40207 -+				late++;
772.40208 -+				ret++;
772.40209 -+			}
772.40210 -+			count++;
772.40211 -+		} else
772.40212 -+			complete = 1;
772.40213 -+		free(ev);
772.40214 -+	} while (!complete);
772.40215 -+
772.40216 -+	if (early)
772.40217 -+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
772.40218 -+	if (late)
772.40219 -+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
772.40220 -+
772.40221 -+	if (count != N_VBLANKS+1) {
772.40222 -+		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", N_VBLANKS+1 - count);
772.40223 -+		ret++;
772.40224 -+		do {
772.40225 -+			xcb_present_complete_notify_event_t *ce;
772.40226 -+			xcb_generic_event_t *ev;
772.40227 -+
772.40228 -+			ev = xcb_wait_for_special_event(c, Q);
772.40229 -+			if (ev == NULL)
772.40230 -+				break;
772.40231 -+
772.40232 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.40233 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40234 -+			free(ev);
772.40235 -+		} while (++count != N_VBLANKS+1);
772.40236 -+	}
772.40237 -+
772.40238 -+	XSync(dpy, True);
772.40239 -+	ret += !!_x_error_occurred;
772.40240 -+
772.40241 -+	return ret;
772.40242 -+#undef N_VBLANKS
772.40243 -+}
772.40244 - 
772.40245 --	printf("Testing whole screen flip: %dx%d\n", width, height);
772.40246 -+static int test_modulus_msc(Display *dpy, void *Q)
772.40247 -+{
772.40248 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.40249 -+	Window root = DefaultRootWindow(dpy);
772.40250 -+	xcb_present_complete_notify_event_t *ce;
772.40251 -+	xcb_generic_event_t *ev;
772.40252 -+	int x, y, ret = 0;
772.40253 -+	uint64_t target;
772.40254 -+	int early = 0, late = 0;
772.40255 -+	int earliest = 0, latest = 0;
772.40256 -+	int complete, count, expect;
772.40257 -+
772.40258 -+	printf("Testing notify modulus\n");
772.40259 - 	_x_error_occurred = 0;
772.40260 - 
772.40261 --	xshmfence_reset(fence.addr);
772.40262 -+	target = wait_vblank(dpy, root, Q);
772.40263 - 
772.40264 --	pixmap = XCreatePixmap(dpy, root, width, height, depth);
772.40265 --	xcb_present_pixmap(XGetXCBConnection(dpy),
772.40266 --			   root, pixmap,
772.40267 --			   0, /* sbc */
772.40268 --			   0, /* valid */
772.40269 --			   0, /* update */
772.40270 --			   0, /* x_off */
772.40271 --			   0, /* y_off */
772.40272 --			   None,
772.40273 --			   None, /* wait fence */
772.40274 --			   fence.xid,
772.40275 --			   XCB_PRESENT_OPTION_NONE,
772.40276 --			   0, /* target msc */
772.40277 --			   0, /* divisor */
772.40278 --			   0, /* remainder */
772.40279 --			   0, NULL);
772.40280 --	XFreePixmap(dpy, pixmap);
772.40281 -+	expect = 0;
772.40282 -+	xcb_present_notify_msc(c, root, 0, 0, 0, 0);
772.40283 -+	for (x = 1; x <= 19; x++) {
772.40284 -+		for (y = 0; y < x; y++) {
772.40285 -+			xcb_present_notify_msc(c, root, y << 16 | x, 0, x, y);
772.40286 -+			expect++;
772.40287 -+		}
772.40288 -+	}
772.40289 -+	xcb_present_notify_msc(c, root, 0xdeadbeef, target + 2*x, 0, 0);
772.40290 -+	xcb_flush(c);
772.40291 - 
772.40292 --	pixmap = XCreatePixmap(dpy, root, width, height, depth);
772.40293 --	xcb_present_pixmap(XGetXCBConnection(dpy),
772.40294 --			   root, pixmap,
772.40295 --			   0, /* sbc */
772.40296 --			   0, /* valid */
772.40297 --			   0, /* update */
772.40298 --			   0, /* x_off */
772.40299 --			   0, /* y_off */
772.40300 --			   None,
772.40301 --			   None, /* wait fence */
772.40302 --			   None, /* sync fence */
772.40303 --			   XCB_PRESENT_OPTION_NONE,
772.40304 --			   0, /* target msc */
772.40305 --			   0, /* divisor */
772.40306 --			   0, /* remainder */
772.40307 --			   0, NULL);
772.40308 --	XFreePixmap(dpy, pixmap);
772.40309 --	XFlush(dpy);
772.40310 -+	ev = xcb_wait_for_special_event(c, Q);
772.40311 -+	if (ev) {
772.40312 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.40313 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40314 -+		assert(ce->serial == 0);
772.40315 -+		assert(target == ce->msc);
772.40316 -+		target = ce->msc;
772.40317 -+	}
772.40318 - 
772.40319 --	ret = !!xshmfence_await(fence.addr);
772.40320 --	dri3_fence_free(dpy, &fence);
772.40321 -+	complete = 0;
772.40322 -+	count = 0;
772.40323 -+	do {
772.40324 -+		ev = xcb_wait_for_special_event(c, Q);
772.40325 -+		if (ev == NULL)
772.40326 -+			break;
772.40327 -+
772.40328 -+		ce = (xcb_present_complete_notify_event_t *)ev;
772.40329 -+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40330 -+
772.40331 -+		assert(ce->serial);
772.40332 -+		if (ce->serial != 0xdeadbeef) {
772.40333 -+			uint64_t msc;
772.40334 -+			int diff;
772.40335 -+
772.40336 -+			x = ce->serial & 0xffff;
772.40337 -+			y = ce->serial >> 16;
772.40338 -+
772.40339 -+			msc = target;
772.40340 -+			msc -= target % x;
772.40341 -+			msc += y;
772.40342 -+			if (msc <= target)
772.40343 -+				msc += x;
772.40344 -+
772.40345 -+			diff = (int64_t)(ce->msc - msc);
772.40346 -+			if (diff < 0) {
772.40347 -+				if (-diff > earliest) {
772.40348 -+					fprintf(stderr, "\tnotify (%d, %d) early by %d msc (target %lld, reported %lld)\n", y, x, -diff, (long long)msc, (long long)ce->msc);
772.40349 -+					earliest = -diff;
772.40350 -+				}
772.40351 -+				early++;
772.40352 -+				ret++;
772.40353 -+			} else if (diff > 0) {
772.40354 -+				if (diff > latest) {
772.40355 -+					fprintf(stderr, "\tnotify (%d, %d) late by %d msc (target %lld, reported %lld)\n", y, x, diff, (long long)msc, (long long)ce->msc);
772.40356 -+					latest = diff;
772.40357 -+				}
772.40358 -+				late++;
772.40359 -+				ret++;
772.40360 -+			}
772.40361 -+			count++;
772.40362 -+		} else
772.40363 -+			complete = 1;
772.40364 -+		free(ev);
772.40365 -+	} while (!complete);
772.40366 -+
772.40367 -+	if (early)
772.40368 -+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
772.40369 -+	if (late)
772.40370 -+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
772.40371 -+
772.40372 -+	if (count != expect) {
772.40373 -+		fprintf(stderr, "Sentinel vblank received too early! %d waits outstanding\n", expect - count);
772.40374 -+		ret++;
772.40375 -+		do {
772.40376 -+			ev = xcb_wait_for_special_event(c, Q);
772.40377 -+			if (ev == NULL)
772.40378 -+				break;
772.40379 -+
772.40380 -+			ce = (xcb_present_complete_notify_event_t *)ev;
772.40381 -+			assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
772.40382 -+			free(ev);
772.40383 -+		} while (++count != expect);
772.40384 -+	}
772.40385 - 
772.40386 - 	XSync(dpy, True);
772.40387 - 	ret += !!_x_error_occurred;
772.40388 -@@ -279,8 +1471,6 @@ static int for_each_crtc(Display *dpy,
772.40389 - 	for (i = 0; i < res->ncrtc; i++)
772.40390 - 		original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
772.40391 - 
772.40392 --	printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
772.40393 --
772.40394 - 	for (i = 0; i < res->noutput; i++) {
772.40395 - 		XRROutputInfo *output;
772.40396 - 		XRRModeInfo *mode;
772.40397 -@@ -322,7 +1512,7 @@ static int for_each_crtc(Display *dpy,
772.40398 - 	free(original_crtc);
772.40399 - 	XRRFreeScreenResources(res);
772.40400 - 
772.40401 --	return j;
772.40402 -+	return err;
772.40403 - }
772.40404 - 
772.40405 - struct test_crtc {
772.40406 -@@ -335,6 +1525,7 @@ struct test_crtc {
772.40407 - 	uint64_t msc;
772.40408 - };
772.40409 - #define SYNC 0x1
772.40410 -+#define FUTURE 0x2
772.40411 - 
772.40412 - static int __test_crtc(Display *dpy, RRCrtc crtc,
772.40413 - 		       int width, int height,
772.40414 -@@ -344,7 +1535,7 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
772.40415 - 	Pixmap pixmap;
772.40416 - 	int err = 0;
772.40417 - 
772.40418 --	test->msc = check_msc(dpy, test->win, test->queue, test->msc);
772.40419 -+	test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
772.40420 - 
772.40421 - 	if (test->flags & SYNC)
772.40422 - 		xshmfence_reset(test->fence.addr);
772.40423 -@@ -361,16 +1552,14 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
772.40424 - 			   None, /* wait fence */
772.40425 - 			   test->flags & SYNC ? test->fence.xid : None,
772.40426 - 			   XCB_PRESENT_OPTION_NONE,
772.40427 --			   0, /* target msc */
772.40428 -+			   test->msc, /* target msc */
772.40429 - 			   1, /* divisor */
772.40430 - 			   0, /* remainder */
772.40431 - 			   0, NULL);
772.40432 --	XFreePixmap(dpy, pixmap);
772.40433 --
772.40434 - 	if (test->flags & SYNC) {
772.40435 --		pixmap = XCreatePixmap(dpy, test->win, width, height, test->depth);
772.40436 -+		Pixmap tmp = XCreatePixmap(dpy, test->win, width, height, test->depth);
772.40437 - 		xcb_present_pixmap(XGetXCBConnection(dpy),
772.40438 --				   test->win, pixmap,
772.40439 -+				   test->win, tmp,
772.40440 - 				   1, /* sbc */
772.40441 - 				   0, /* valid */
772.40442 - 				   0, /* update */
772.40443 -@@ -380,16 +1569,17 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
772.40444 - 				   None, /* wait fence */
772.40445 - 				   None, /* sync fence */
772.40446 - 				   XCB_PRESENT_OPTION_NONE,
772.40447 --				   1, /* target msc */
772.40448 -+				   test->msc + (test->flags & FUTURE ? 5 * 16 : 1), /* target msc */
772.40449 - 				   1, /* divisor */
772.40450 - 				   0, /* remainder */
772.40451 - 				   0, NULL);
772.40452 --		XFreePixmap(dpy, pixmap);
772.40453 -+		XFreePixmap(dpy, tmp);
772.40454 - 		XFlush(dpy);
772.40455 - 		err += !!xshmfence_await(test->fence.addr);
772.40456 - 	}
772.40457 -+	XFreePixmap(dpy, pixmap);
772.40458 - 
772.40459 --	test->msc = check_msc(dpy, test->win, test->queue, test->msc);
772.40460 -+	test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
772.40461 - 	return err;
772.40462 - }
772.40463 - 
772.40464 -@@ -410,15 +1600,23 @@ static int test_crtc(Display *dpy, void *queue, uint64_t last_msc)
772.40465 - 
772.40466 - 	printf("Testing each crtc, without waiting for each flip\n");
772.40467 - 	test.flags = 0;
772.40468 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40469 - 	err += for_each_crtc(dpy, __test_crtc, &test);
772.40470 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40471 - 
772.40472 - 	printf("Testing each crtc, waiting for flips to complete\n");
772.40473 - 	test.flags = SYNC;
772.40474 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40475 - 	err += for_each_crtc(dpy, __test_crtc, &test);
772.40476 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40477 - 
772.40478 --	test.msc = check_msc(dpy, test.win, test.queue, test.msc);
772.40479 --	dri3_fence_free(dpy, &test.fence);
772.40480 -+	printf("Testing each crtc, with future flips\n");
772.40481 -+	test.flags = FUTURE | SYNC;
772.40482 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40483 -+	err += for_each_crtc(dpy, __test_crtc, &test);
772.40484 -+	test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
772.40485 - 
772.40486 -+	dri3_fence_free(dpy, &test.fence);
772.40487 - 	XSync(dpy, True);
772.40488 - 	err += !!_x_error_occurred;
772.40489 - 
772.40490 -@@ -536,6 +1734,31 @@ static int gem_set_caching(int fd, uint32_t handle, int caching)
772.40491 - 	return drmIoctl(fd, LOCAL_IOCTL_I915_GEM_SET_CACHING, &arg) == 0;
772.40492 - }
772.40493 - 
772.40494 -+static int gem_set_tiling(int fd, uint32_t handle, int tiling, int stride)
772.40495 -+{
772.40496 -+	struct drm_i915_gem_set_tiling set_tiling;
772.40497 -+	int err;
772.40498 -+
772.40499 -+restart:
772.40500 -+	set_tiling.handle = handle;
772.40501 -+	set_tiling.tiling_mode = tiling;
772.40502 -+	set_tiling.stride = stride;
772.40503 -+
772.40504 -+	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0)
772.40505 -+		return 1;
772.40506 -+
772.40507 -+	err = errno;
772.40508 -+	if (err == EINTR)
772.40509 -+		goto restart;
772.40510 -+
772.40511 -+	if (err == EAGAIN) {
772.40512 -+		sched_yield();
772.40513 -+		goto restart;
772.40514 -+	}
772.40515 -+
772.40516 -+	return 0;
772.40517 -+}
772.40518 -+
772.40519 - static int gem_export(int fd, uint32_t handle)
772.40520 - {
772.40521 - 	struct drm_prime_handle args;
772.40522 -@@ -557,6 +1780,126 @@ static void gem_close(int fd, uint32_t handle)
772.40523 - 	(void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
772.40524 - }
772.40525 - 
772.40526 -+static int test_dri3_tiling(Display *dpy)
772.40527 -+{
772.40528 -+	Window win = DefaultRootWindow(dpy);
772.40529 -+	const int tiling[] = { I915_TILING_NONE, I915_TILING_X, I915_TILING_Y };
772.40530 -+	Window root;
772.40531 -+	unsigned int width, height;
772.40532 -+	unsigned border, depth, bpp;
772.40533 -+	unsigned stride, size;
772.40534 -+	void *Q;
772.40535 -+	int x, y;
772.40536 -+	int device;
772.40537 -+	int line = -1;
772.40538 -+	int t;
772.40539 -+
772.40540 -+	device = dri3_open(dpy);
772.40541 -+	if (device < 0)
772.40542 -+		return 0;
772.40543 -+
772.40544 -+	if (!is_intel(device))
772.40545 -+		return 0;
772.40546 -+
772.40547 -+	printf("Opened Intel DRI3 device\n");
772.40548 -+
772.40549 -+	XGetGeometry(dpy, win, &root, &x, &y,
772.40550 -+		     &width, &height, &border, &depth);
772.40551 -+
772.40552 -+	switch (depth) {
772.40553 -+	case 8: bpp = 8; break;
772.40554 -+	case 15: case 16: bpp = 16; break;
772.40555 -+	case 24: case 32: bpp = 32; break;
772.40556 -+	default: return 0;
772.40557 -+	}
772.40558 -+
772.40559 -+	stride = ALIGN(width * bpp/8, 512);
772.40560 -+	size = PAGE_ALIGN(stride * ALIGN(height, 32));
772.40561 -+	printf("Creating DRI3 %dx%d (source stride=%d, size=%d) for GTT\n",
772.40562 -+	       width, height, stride, size);
772.40563 -+
772.40564 -+	_x_error_occurred = 0;
772.40565 -+	Q = setup_msc(dpy, root);
772.40566 -+
772.40567 -+	for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) {
772.40568 -+		uint64_t msc;
772.40569 -+		uint32_t src;
772.40570 -+		int src_fd;
772.40571 -+		Pixmap src_pix;
772.40572 -+
772.40573 -+		src = gem_create(device, size);
772.40574 -+		if (!src) {
772.40575 -+			line = __LINE__;
772.40576 -+			goto fail;
772.40577 -+		}
772.40578 -+
772.40579 -+		gem_set_tiling(device, src, tiling[t], stride);
772.40580 -+
772.40581 -+		src_fd = gem_export(device, src);
772.40582 -+		if (src_fd < 0) {
772.40583 -+			line = __LINE__;
772.40584 -+			goto fail;
772.40585 -+		}
772.40586 -+
772.40587 -+		src_pix = dri3_create_pixmap(dpy, root,
772.40588 -+					     width, height, depth,
772.40589 -+					     src_fd, bpp, stride, size);
772.40590 -+
772.40591 -+		msc = wait_vblank(dpy, root, Q);
772.40592 -+
772.40593 -+		xcb_present_pixmap(XGetXCBConnection(dpy),
772.40594 -+				   win, src_pix,
772.40595 -+				   0, /* sbc */
772.40596 -+				   0, /* valid */
772.40597 -+				   0, /* update */
772.40598 -+				   0, /* x_off */
772.40599 -+				   0, /* y_off */
772.40600 -+				   None,
772.40601 -+				   None, /* wait fence */
772.40602 -+				   None,
772.40603 -+				   XCB_PRESENT_OPTION_NONE,
772.40604 -+				   msc + 2, /* target msc */
772.40605 -+				   1, /* divisor */
772.40606 -+				   0, /* remainder */
772.40607 -+				   0, NULL);
772.40608 -+
772.40609 -+		xcb_present_pixmap(XGetXCBConnection(dpy),
772.40610 -+				   win, src_pix,
772.40611 -+				   0, /* sbc */
772.40612 -+				   0, /* valid */
772.40613 -+				   0, /* update */
772.40614 -+				   0, /* x_off */
772.40615 -+				   0, /* y_off */
772.40616 -+				   None,
772.40617 -+				   None, /* wait fence */
772.40618 -+				   None,
772.40619 -+				   XCB_PRESENT_OPTION_NONE,
772.40620 -+				   msc + 3, /* target msc */
772.40621 -+				   1, /* divisor */
772.40622 -+				   0, /* remainder */
772.40623 -+				   0, NULL);
772.40624 -+
772.40625 -+		XSync(dpy, True);
772.40626 -+		if (_x_error_occurred) {
772.40627 -+			line = __LINE__;
772.40628 -+			goto fail;
772.40629 -+		}
772.40630 -+		XFreePixmap(dpy, src_pix);
772.40631 -+		_x_error_occurred = 0;
772.40632 -+
772.40633 -+		close(src_fd);
772.40634 -+		gem_close(device, src);
772.40635 -+	}
772.40636 -+
772.40637 -+	teardown_msc(dpy, Q);
772.40638 -+	return 0;
772.40639 -+
772.40640 -+fail:
772.40641 -+	printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line);
772.40642 -+	teardown_msc(dpy, Q);
772.40643 -+	return 1;
772.40644 -+}
772.40645 -+
772.40646 - static int test_dri3(Display *dpy)
772.40647 - {
772.40648 - 	Window win = DefaultRootWindow(dpy);
772.40649 -@@ -670,8 +2013,32 @@ fail:
772.40650 - static int has_present(Display *dpy)
772.40651 - {
772.40652 - 	xcb_connection_t *c = XGetXCBConnection(dpy);
772.40653 --	xcb_present_query_version_reply_t *reply;
772.40654 - 	xcb_generic_error_t *error = NULL;
772.40655 -+	void *reply;
772.40656 -+
772.40657 -+	reply = xcb_xfixes_query_version_reply(c,
772.40658 -+					       xcb_xfixes_query_version(c,
772.40659 -+									XCB_XFIXES_MAJOR_VERSION,
772.40660 -+									XCB_XFIXES_MINOR_VERSION),
772.40661 -+					       &error);
772.40662 -+	free(reply);
772.40663 -+	free(error);
772.40664 -+	if (reply == NULL) {
772.40665 -+		fprintf(stderr, "XFixes not supported on %s\n", DisplayString(dpy));
772.40666 -+		return 0;
772.40667 -+	}
772.40668 -+
772.40669 -+	reply = xcb_dri3_query_version_reply(c,
772.40670 -+					     xcb_dri3_query_version(c,
772.40671 -+								    XCB_DRI3_MAJOR_VERSION,
772.40672 -+								    XCB_DRI3_MINOR_VERSION),
772.40673 -+					     &error);
772.40674 -+	free(reply);
772.40675 -+	free(error);
772.40676 -+	if (reply == NULL) {
772.40677 -+		fprintf(stderr, "DRI3 not supported on %s\n", DisplayString(dpy));
772.40678 -+		return 0;
772.40679 -+	}
772.40680 - 
772.40681 - 	reply = xcb_present_query_version_reply(c,
772.40682 - 						xcb_present_query_version(c,
772.40683 -@@ -681,14 +2048,32 @@ static int has_present(Display *dpy)
772.40684 - 
772.40685 - 	free(reply);
772.40686 - 	free(error);
772.40687 -+	if (reply == NULL) {
772.40688 -+		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
772.40689 -+		return 0;
772.40690 -+	}
772.40691 -+
772.40692 -+	return 1;
772.40693 -+}
772.40694 -+
772.40695 -+static int has_composite(Display *dpy)
772.40696 -+{
772.40697 -+	int event, error;
772.40698 -+	int major, minor;
772.40699 -+
772.40700 -+	if (!XCompositeQueryExtension(dpy, &event, &error))
772.40701 -+		return 0;
772.40702 -+
772.40703 -+	XCompositeQueryVersion(dpy, &major, &minor);
772.40704 - 
772.40705 --	return reply != NULL;
772.40706 -+	return major > 0 || minor >= 4;
772.40707 - }
772.40708 - 
772.40709 - int main(void)
772.40710 - {
772.40711 - 	Display *dpy;
772.40712 - 	Window root;
772.40713 -+	int dummy;
772.40714 - 	int error = 0;
772.40715 - 	uint64_t last_msc;
772.40716 - 	void *queue;
772.40717 -@@ -700,27 +2085,135 @@ int main(void)
772.40718 - 	if (!has_present(dpy))
772.40719 - 		return 77;
772.40720 - 
772.40721 -+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
772.40722 -+		DPMSDisable(dpy);
772.40723 -+
772.40724 - 	root = DefaultRootWindow(dpy);
772.40725 - 
772.40726 - 	signal(SIGALRM, SIG_IGN);
772.40727 - 	XSetErrorHandler(_check_error_handler);
772.40728 - 
772.40729 - 	queue = setup_msc(dpy, root);
772.40730 --	last_msc = check_msc(dpy, root, queue, 0);
772.40731 -+	last_msc = check_msc(dpy, root, queue, 0, NULL);
772.40732 -+
772.40733 -+	error += test_future_msc(dpy, queue);
772.40734 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40735 -+
772.40736 -+	error += test_wrap_msc(dpy);
772.40737 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40738 -+
772.40739 -+	error += test_accuracy_msc(dpy, queue);
772.40740 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40741 -+
772.40742 -+	error += test_modulus_msc(dpy, queue);
772.40743 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40744 -+
772.40745 -+	error += test_exhaustion_msc(dpy, queue);
772.40746 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40747 -+
772.40748 -+	for (dummy = 0; dummy <= 3; dummy++) {
772.40749 -+		Window win;
772.40750 -+		uint64_t msc = 0;
772.40751 -+		XSetWindowAttributes attr;
772.40752 -+		Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
772.40753 -+		unsigned int width, height;
772.40754 -+		unsigned border, depth;
772.40755 -+		const char *phase;
772.40756 -+		int x, y;
772.40757 -+		void *Q;
772.40758 -+
772.40759 -+		attr.override_redirect = 1;
772.40760 -+
772.40761 -+		XGetGeometry(dpy, root, &win, &x, &y,
772.40762 -+			     &width, &height, &border, &depth);
772.40763 -+
772.40764 -+		_x_error_occurred = 0;
772.40765 -+		switch (dummy) {
772.40766 -+		case 0:
772.40767 -+			win = root;
772.40768 -+			phase = "root";
772.40769 -+			break;
772.40770 -+		case 1:
772.40771 -+			win = XCreateWindow(dpy, root,
772.40772 -+					    0, 0, width, height, 0, depth,
772.40773 -+					    InputOutput, visual,
772.40774 -+					    CWOverrideRedirect, &attr);
772.40775 -+			phase = "fullscreen";
772.40776 -+			break;
772.40777 -+		case 2:
772.40778 -+			win = XCreateWindow(dpy, root,
772.40779 -+					    0, 0, width/2, height/2, 0, depth,
772.40780 -+					    InputOutput, visual,
772.40781 -+					    CWOverrideRedirect, &attr);
772.40782 -+			phase = "window";
772.40783 -+			break;
772.40784 -+		case 3:
772.40785 -+			if (!has_composite(dpy))
772.40786 -+				continue;
772.40787 -+
772.40788 -+			win = XCreateWindow(dpy, root,
772.40789 -+					    0, 0, width, height, 0,
772.40790 -+					    DefaultDepth(dpy, DefaultScreen(dpy)),
772.40791 -+					    InputOutput,
772.40792 -+					    DefaultVisual(dpy, DefaultScreen(dpy)),
772.40793 -+					    CWOverrideRedirect, &attr);
772.40794 -+			XCompositeRedirectWindow(dpy, win, CompositeRedirectManual);
772.40795 -+			phase = "composite";
772.40796 -+			break;
772.40797 -+
772.40798 -+		default:
772.40799 -+			phase = "broken";
772.40800 -+			win = root;
772.40801 -+			abort();
772.40802 -+			break;
772.40803 -+		}
772.40804 -+
772.40805 -+		XMapWindow(dpy, win);
772.40806 -+		XSync(dpy, True);
772.40807 -+		if (_x_error_occurred)
772.40808 -+			continue;
772.40809 -+
772.40810 -+		Q = setup_msc(dpy, win);
772.40811 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40812 - 
772.40813 --	error += test_whole(dpy);
772.40814 --	last_msc = check_msc(dpy, root, queue, last_msc);
772.40815 -+		error += test_whole(dpy, win, phase);
772.40816 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40817 -+
772.40818 -+		error += test_double(dpy, win, phase, Q);
772.40819 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40820 -+
772.40821 -+		error += test_future(dpy, win, phase, Q);
772.40822 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40823 -+
772.40824 -+		error += test_accuracy(dpy, win, phase, Q);
772.40825 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40826 -+
772.40827 -+		error += test_modulus(dpy, win, phase, Q);
772.40828 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40829 -+
772.40830 -+		error += test_exhaustion(dpy, win, phase, Q);
772.40831 -+		msc = check_msc(dpy, win, Q, msc, NULL);
772.40832 -+
772.40833 -+		teardown_msc(dpy, Q);
772.40834 -+		if (win != root)
772.40835 -+			XDestroyWindow(dpy, win);
772.40836 -+	}
772.40837 - 
772.40838 - 	error += test_crtc(dpy, queue, last_msc);
772.40839 --	last_msc = check_msc(dpy, root, queue, last_msc);
772.40840 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40841 - 
772.40842 - 	error += test_shm(dpy);
772.40843 --	last_msc = check_msc(dpy, root, queue, last_msc);
772.40844 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40845 - 
772.40846 - 	error += test_dri3(dpy);
772.40847 --	last_msc = check_msc(dpy, root, queue, last_msc);
772.40848 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40849 -+
772.40850 -+	error += test_dri3_tiling(dpy);
772.40851 -+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
772.40852 - 
772.40853 - 	teardown_msc(dpy, queue);
772.40854 - 
772.40855 -+	if (DPMSQueryExtension(dpy, &dummy, &dummy))
772.40856 -+		DPMSEnable(dpy);
772.40857 - 	return !!error;
772.40858 - }
772.40859 -diff --git a/test/render-glyphs.c b/test/render-glyphs.c
772.40860 -new file mode 100644
772.40861 -index 00000000..8822e36a
772.40862 ---- /dev/null
772.40863 -+++ b/test/render-glyphs.c
772.40864 -@@ -0,0 +1,441 @@
772.40865 -+#include <stdint.h>
772.40866 -+#include <stdio.h>
772.40867 -+#include <stdlib.h>
772.40868 -+#include <stdbool.h>
772.40869 -+#include <stdarg.h>
772.40870 -+#include <string.h>
772.40871 -+
772.40872 -+#include <X11/Xutil.h> /* for XDestroyImage */
772.40873 -+#include <pixman.h> /* for pixman blt functions */
772.40874 -+
772.40875 -+#include "test.h"
772.40876 -+
772.40877 -+static const XRenderColor colors[] = {
772.40878 -+	/* red, green, blue, alpha */
772.40879 -+	{ 0 },
772.40880 -+	{ 0, 0, 0, 0xffff },
772.40881 -+	{ 0xffff, 0, 0, 0xffff },
772.40882 -+	{ 0, 0xffff, 0, 0xffff },
772.40883 -+	{ 0, 0, 0xffff, 0xffff },
772.40884 -+	{ 0xffff, 0xffff, 0xffff, 0xffff },
772.40885 -+};
772.40886 -+
772.40887 -+static struct clip {
772.40888 -+	void *func;
772.40889 -+} clips[] = {
772.40890 -+	{ NULL },
772.40891 -+};
772.40892 -+
772.40893 -+static int _x_error_occurred;
772.40894 -+
772.40895 -+static int
772.40896 -+_check_error_handler(Display     *display,
772.40897 -+		     XErrorEvent *event)
772.40898 -+{
772.40899 -+	_x_error_occurred = 1;
772.40900 -+	return False; /* ignored */
772.40901 -+}
772.40902 -+
772.40903 -+static void clear(struct test_display *dpy,
772.40904 -+		  struct test_target *tt,
772.40905 -+		  const XRenderColor *c)
772.40906 -+{
772.40907 -+	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, c,
772.40908 -+			     0, 0, tt->width, tt->height);
772.40909 -+}
772.40910 -+
772.40911 -+static bool check_op(struct test_display *dpy, int op, struct test_target *tt)
772.40912 -+{
772.40913 -+	XRenderColor render_color = {0};
772.40914 -+
772.40915 -+	XSync(dpy->dpy, True);
772.40916 -+	_x_error_occurred = 0;
772.40917 -+
772.40918 -+	XRenderFillRectangle(dpy->dpy, op,
772.40919 -+			     tt->picture, &render_color,
772.40920 -+			     0, 0, 0, 0);
772.40921 -+
772.40922 -+	XSync(dpy->dpy, True);
772.40923 -+	return _x_error_occurred == 0;
772.40924 -+}
772.40925 -+
772.40926 -+struct glyph_iter {
772.40927 -+	enum {
772.40928 -+		GLYPHS, OP, DST, SRC, MASK, CLIP,
772.40929 -+	} stage;
772.40930 -+
772.40931 -+	int glyph_format;
772.40932 -+	int op;
772.40933 -+	int dst_color;
772.40934 -+	int src_color;
772.40935 -+	int mask_format;
772.40936 -+	int clip;
772.40937 -+
772.40938 -+	struct {
772.40939 -+		struct test_display *dpy;
772.40940 -+		struct test_target tt;
772.40941 -+		GlyphSet glyphset;
772.40942 -+		Picture src;
772.40943 -+		XRenderPictFormat *mask_format;
772.40944 -+	} ref, out;
772.40945 -+};
772.40946 -+
772.40947 -+static void glyph_iter_init(struct glyph_iter *gi,
772.40948 -+			    struct test *t, enum target target)
772.40949 -+{
772.40950 -+	memset(gi, 0, sizeof(*gi));
772.40951 -+
772.40952 -+	gi->out.dpy = &t->out;
772.40953 -+	test_target_create_render(&t->out, target, &gi->out.tt);
772.40954 -+
772.40955 -+	gi->ref.dpy = &t->ref;
772.40956 -+	test_target_create_render(&t->ref, target, &gi->ref.tt);
772.40957 -+
772.40958 -+	gi->stage = GLYPHS;
772.40959 -+	gi->glyph_format = -1;
772.40960 -+	gi->op = -1;
772.40961 -+	gi->dst_color = -1;
772.40962 -+	gi->src_color = -1;
772.40963 -+	gi->mask_format = -1;
772.40964 -+	gi->clip = -1;
772.40965 -+}
772.40966 -+
772.40967 -+static void render_clear(char *image, int image_size, int bpp)
772.40968 -+{
772.40969 -+	memset(image, 0, image_size);
772.40970 -+}
772.40971 -+
772.40972 -+static void render_black(char *image, int image_size, int bpp)
772.40973 -+{
772.40974 -+	if (bpp == 4) {
772.40975 -+		uint32_t *p = (uint32_t *)image;
772.40976 -+		image_size /= 4;
772.40977 -+		while (image_size--)
772.40978 -+			*p++ = 0x000000ff;
772.40979 -+	} else
772.40980 -+		memset(image, 0x55, image_size);
772.40981 -+}
772.40982 -+
772.40983 -+static void render_green(char *image, int image_size, int bpp)
772.40984 -+{
772.40985 -+	if (bpp == 4) {
772.40986 -+		uint32_t *p = (uint32_t *)image;
772.40987 -+		image_size /= 4;
772.40988 -+		while (image_size--)
772.40989 -+			*p++ = 0xffff0000;
772.40990 -+	} else
772.40991 -+		memset(image, 0xaa, image_size);
772.40992 -+}
772.40993 -+
772.40994 -+static void render_white(char *image, int image_size, int bpp)
772.40995 -+{
772.40996 -+	memset(image, 0xff, image_size);
772.40997 -+}
772.40998 -+
772.40999 -+static GlyphSet create_glyphs(Display *dpy, int format_id)
772.41000 -+{
772.41001 -+#define N_GLYPHS 4
772.41002 -+	XRenderPictFormat *format;
772.41003 -+	XGlyphInfo glyph = { 8, 8, 0, 0, 8, 0 };
772.41004 -+	char image[4*8*8];
772.41005 -+	GlyphSet glyphset;
772.41006 -+	Glyph gid;
772.41007 -+	int image_size;
772.41008 -+	int bpp;
772.41009 -+	int n;
772.41010 -+
772.41011 -+	format = XRenderFindStandardFormat(dpy, format_id);
772.41012 -+	if (format == NULL)
772.41013 -+		return 0;
772.41014 -+
772.41015 -+	switch (format_id) {
772.41016 -+	case PictStandardARGB32:
772.41017 -+	case PictStandardRGB24:
772.41018 -+		image_size = 4 * 8 * 8;
772.41019 -+		bpp = 4;
772.41020 -+		break;
772.41021 -+	case PictStandardA8:
772.41022 -+	case PictStandardA4:
772.41023 -+		image_size = 8 * 8;
772.41024 -+		bpp = 1;
772.41025 -+		break;
772.41026 -+	case PictStandardA1:
772.41027 -+		image_size = 8;
772.41028 -+		bpp = 0;
772.41029 -+		break;
772.41030 -+	default:
772.41031 -+		return 0;
772.41032 -+	}
772.41033 -+
772.41034 -+	glyphset = XRenderCreateGlyphSet(dpy, format);
772.41035 -+	for (n = 0; n < N_GLYPHS; n++) {
772.41036 -+		gid = n;
772.41037 -+
772.41038 -+		switch (n) {
772.41039 -+		case 0: render_clear(image, image_size, bpp); break;
772.41040 -+		case 1: render_black(image, image_size, bpp); break;
772.41041 -+		case 2: render_green(image, image_size, bpp); break;
772.41042 -+		case 3: render_white(image, image_size, bpp); break;
772.41043 -+		}
772.41044 -+
772.41045 -+		XRenderAddGlyphs(dpy, glyphset,
772.41046 -+				 &gid, &glyph, 1, image, image_size);
772.41047 -+	}
772.41048 -+
772.41049 -+	return glyphset;
772.41050 -+}
772.41051 -+
772.41052 -+static const char *glyph_name(int n)
772.41053 -+{
772.41054 -+	switch (n) {
772.41055 -+	case 0: return "clear";
772.41056 -+	case 1: return "black";
772.41057 -+	case 2: return "green";
772.41058 -+	case 3: return "white";
772.41059 -+	default: return "unknown";
772.41060 -+	}
772.41061 -+}
772.41062 -+
772.41063 -+static bool glyph_iter_next(struct glyph_iter *gi)
772.41064 -+{
772.41065 -+restart:
772.41066 -+	if (gi->stage == GLYPHS) {
772.41067 -+		if (++gi->glyph_format == PictStandardNUM)
772.41068 -+			return false;
772.41069 -+
772.41070 -+		if (gi->out.glyphset)
772.41071 -+			XRenderFreeGlyphSet(gi->out.dpy->dpy,
772.41072 -+					    gi->out.glyphset);
772.41073 -+		gi->out.glyphset = create_glyphs(gi->out.dpy->dpy,
772.41074 -+					       gi->glyph_format);
772.41075 -+
772.41076 -+		if (gi->ref.glyphset)
772.41077 -+			XRenderFreeGlyphSet(gi->ref.dpy->dpy,
772.41078 -+					    gi->ref.glyphset);
772.41079 -+		gi->ref.glyphset = create_glyphs(gi->ref.dpy->dpy,
772.41080 -+					       gi->glyph_format);
772.41081 -+
772.41082 -+		gi->stage++;
772.41083 -+	}
772.41084 -+
772.41085 -+	if (gi->stage == OP) {
772.41086 -+		do {
772.41087 -+			if (++gi->op == 255)
772.41088 -+				goto reset_op;
772.41089 -+		} while (!check_op(gi->out.dpy, gi->op, &gi->out.tt) ||
772.41090 -+			 !check_op(gi->ref.dpy, gi->op, &gi->ref.tt));
772.41091 -+
772.41092 -+		gi->stage++;
772.41093 -+	}
772.41094 -+
772.41095 -+	if (gi->stage == DST) {
772.41096 -+		if (++gi->dst_color == ARRAY_SIZE(colors))
772.41097 -+			goto reset_dst;
772.41098 -+
772.41099 -+		gi->stage++;
772.41100 -+	}
772.41101 -+
772.41102 -+	if (gi->stage == SRC) {
772.41103 -+		if (++gi->src_color == ARRAY_SIZE(colors))
772.41104 -+			goto reset_src;
772.41105 -+
772.41106 -+		if (gi->ref.src)
772.41107 -+			XRenderFreePicture(gi->ref.dpy->dpy, gi->ref.src);
772.41108 -+		gi->ref.src = XRenderCreateSolidFill(gi->ref.dpy->dpy,
772.41109 -+						     &colors[gi->src_color]);
772.41110 -+
772.41111 -+		if (gi->out.src)
772.41112 -+			XRenderFreePicture(gi->out.dpy->dpy, gi->out.src);
772.41113 -+		gi->out.src = XRenderCreateSolidFill(gi->out.dpy->dpy,
772.41114 -+						     &colors[gi->src_color]);
772.41115 -+
772.41116 -+		gi->stage++;
772.41117 -+	}
772.41118 -+
772.41119 -+	if (gi->stage == MASK) {
772.41120 -+		if (++gi->mask_format > PictStandardNUM)
772.41121 -+			goto reset_mask;
772.41122 -+
772.41123 -+		if (gi->mask_format == PictStandardRGB24)
772.41124 -+			gi->mask_format++;
772.41125 -+
772.41126 -+		if (gi->mask_format < PictStandardNUM) {
772.41127 -+			gi->out.mask_format = XRenderFindStandardFormat(gi->out.dpy->dpy,
772.41128 -+									gi->mask_format);
772.41129 -+			gi->ref.mask_format = XRenderFindStandardFormat(gi->ref.dpy->dpy,
772.41130 -+									gi->mask_format);
772.41131 -+		} else {
772.41132 -+			gi->out.mask_format = NULL;
772.41133 -+			gi->ref.mask_format = NULL;
772.41134 -+		}
772.41135 -+
772.41136 -+		gi->stage++;
772.41137 -+	}
772.41138 -+
772.41139 -+	if (gi->stage == CLIP) {
772.41140 -+		if (++gi->clip == ARRAY_SIZE(clips))
772.41141 -+			goto reset_clip;
772.41142 -+
772.41143 -+		gi->stage++;
772.41144 -+	}
772.41145 -+
772.41146 -+	gi->stage--;
772.41147 -+	return true;
772.41148 -+
772.41149 -+reset_op:
772.41150 -+	gi->op = -1;
772.41151 -+reset_dst:
772.41152 -+	gi->dst_color = -1;
772.41153 -+reset_src:
772.41154 -+	gi->src_color = -1;
772.41155 -+reset_mask:
772.41156 -+	gi->mask_format = -1;
772.41157 -+reset_clip:
772.41158 -+	gi->clip = -1;
772.41159 -+	gi->stage--;
772.41160 -+	goto restart;
772.41161 -+}
772.41162 -+
772.41163 -+static void glyph_iter_fini(struct glyph_iter *gi)
772.41164 -+{
772.41165 -+	if (gi->out.glyphset)
772.41166 -+		XRenderFreeGlyphSet (gi->out.dpy->dpy, gi->out.glyphset);
772.41167 -+	if (gi->ref.glyphset)
772.41168 -+		XRenderFreeGlyphSet (gi->ref.dpy->dpy, gi->ref.glyphset);
772.41169 -+
772.41170 -+	test_target_destroy_render(gi->out.dpy, &gi->out.tt);
772.41171 -+	test_target_destroy_render(gi->ref.dpy, &gi->ref.tt);
772.41172 -+}
772.41173 -+
772.41174 -+static const char *stdformat_to_str(int id)
772.41175 -+{
772.41176 -+	switch (id) {
772.41177 -+	case PictStandardARGB32: return "ARGB32";
772.41178 -+	case PictStandardRGB24: return "RGB24";
772.41179 -+	case PictStandardA8: return "A8";
772.41180 -+	case PictStandardA4: return "A4";
772.41181 -+	case PictStandardA1: return "A1";
772.41182 -+	default: return "none";
772.41183 -+	}
772.41184 -+}
772.41185 -+
772.41186 -+static char *glyph_iter_to_string(struct glyph_iter *gi,
772.41187 -+				  const char *format,
772.41188 -+				  ...)
772.41189 -+{
772.41190 -+	static char buf[100];
772.41191 -+	va_list ap;
772.41192 -+	int len;
772.41193 -+
772.41194 -+	len = sprintf(buf, "glyphs=%s, op=%d, dst=%08x, src=%08x, mask=%s",
772.41195 -+		      stdformat_to_str(gi->glyph_format), gi->op,
772.41196 -+		      xrender_color(&colors[gi->dst_color]),
772.41197 -+		      xrender_color(&colors[gi->src_color]),
772.41198 -+		      stdformat_to_str(gi->mask_format));
772.41199 -+
772.41200 -+	if (format) {
772.41201 -+		buf[len++] = ' ';
772.41202 -+		va_start(ap, format);
772.41203 -+		vsprintf(buf+len, format, ap);
772.41204 -+		va_end(ap);
772.41205 -+	}
772.41206 -+
772.41207 -+	return buf;
772.41208 -+}
772.41209 -+
772.41210 -+static void single(struct test *t, enum target target)
772.41211 -+{
772.41212 -+	struct glyph_iter gi;
772.41213 -+	int n;
772.41214 -+
772.41215 -+	printf("Testing single glyph (%s): ", test_target_name(target));
772.41216 -+	fflush(stdout);
772.41217 -+
772.41218 -+	glyph_iter_init(&gi, t, target);
772.41219 -+	while (glyph_iter_next(&gi)) {
772.41220 -+		XGlyphElt8 elt;
772.41221 -+		char id[N_GLYPHS];
772.41222 -+
772.41223 -+		for (n = 0; n < N_GLYPHS; n++) {
772.41224 -+			id[n] = n;
772.41225 -+
772.41226 -+			elt.chars = &id[n];
772.41227 -+			elt.nchars = 1;
772.41228 -+			elt.xOff = 0;
772.41229 -+			elt.yOff = 0;
772.41230 -+
772.41231 -+			clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
772.41232 -+			elt.glyphset = gi.out.glyphset;
772.41233 -+			XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
772.41234 -+					       gi.out.src,
772.41235 -+					       gi.out.tt.picture,
772.41236 -+					       gi.out.mask_format,
772.41237 -+					       0, 0,
772.41238 -+					       0, 8,
772.41239 -+					       &elt, 1);
772.41240 -+
772.41241 -+			clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
772.41242 -+			elt.glyphset = gi.ref.glyphset;
772.41243 -+			XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
772.41244 -+					       gi.ref.src,
772.41245 -+					       gi.ref.tt.picture,
772.41246 -+					       gi.ref.mask_format,
772.41247 -+					       0, 0,
772.41248 -+					       0, 8,
772.41249 -+					       &elt, 1);
772.41250 -+			test_compare(t,
772.41251 -+				     gi.out.tt.draw, gi.out.tt.format,
772.41252 -+				     gi.ref.tt.draw, gi.ref.tt.format,
772.41253 -+				     0, 0, gi.out.tt.width, gi.out.tt.height,
772.41254 -+				     glyph_iter_to_string(&gi,
772.41255 -+							  "glyph=%s",
772.41256 -+							  glyph_name(n)));
772.41257 -+		}
772.41258 -+
772.41259 -+		elt.chars = &id[0];
772.41260 -+		elt.nchars = n;
772.41261 -+		clear(gi.out.dpy, &gi.out.tt, &colors[gi.dst_color]);
772.41262 -+		elt.glyphset = gi.out.glyphset;
772.41263 -+		XRenderCompositeText8 (gi.out.dpy->dpy, gi.op,
772.41264 -+				       gi.out.src,
772.41265 -+				       gi.out.tt.picture,
772.41266 -+				       gi.out.mask_format,
772.41267 -+				       0, 0,
772.41268 -+				       0, 8,
772.41269 -+				       &elt, 1);
772.41270 -+
772.41271 -+		clear(gi.ref.dpy, &gi.ref.tt, &colors[gi.dst_color]);
772.41272 -+		elt.glyphset = gi.ref.glyphset;
772.41273 -+		XRenderCompositeText8 (gi.ref.dpy->dpy, gi.op,
772.41274 -+				       gi.ref.src,
772.41275 -+				       gi.ref.tt.picture,
772.41276 -+				       gi.ref.mask_format,
772.41277 -+				       0, 0,
772.41278 -+				       0, 8,
772.41279 -+				       &elt, 1);
772.41280 -+		test_compare(t,
772.41281 -+			     gi.out.tt.draw, gi.out.tt.format,
772.41282 -+			     gi.ref.tt.draw, gi.ref.tt.format,
772.41283 -+			     0, 0, gi.out.tt.width, gi.out.tt.height,
772.41284 -+			     glyph_iter_to_string(&gi, "all"));
772.41285 -+	}
772.41286 -+	glyph_iter_fini(&gi);
772.41287 -+}
772.41288 -+
772.41289 -+int main(int argc, char **argv)
772.41290 -+{
772.41291 -+	struct test test;
772.41292 -+	int t;
772.41293 -+
772.41294 -+	test_init(&test, argc, argv);
772.41295 -+	XSetErrorHandler(_check_error_handler);
772.41296 -+
772.41297 -+	for (t = TARGET_FIRST; t <= TARGET_LAST; t++) {
772.41298 -+		single(&test, t);
772.41299 -+		//overlapping(&test, t);
772.41300 -+		//gap(&test, t);
772.41301 -+		//mixed(&test, t);
772.41302 -+	}
772.41303 -+
772.41304 -+	return 0;
772.41305 -+}
772.41306 -diff --git a/test/render-trapezoid.c b/test/render-trapezoid.c
772.41307 -index cd990143..f15a78e3 100644
772.41308 ---- a/test/render-trapezoid.c
772.41309 -+++ b/test/render-trapezoid.c
772.41310 -@@ -403,16 +403,141 @@ static void trap_tests(struct test *t,
772.41311 - 	free(traps);
772.41312 - }
772.41313 - 
772.41314 -+enum edge {
772.41315 -+	EDGE_SHARP = PolyEdgeSharp,
772.41316 -+	EDGE_SMOOTH,
772.41317 -+};
772.41318 -+
772.41319 -+static const char *edge_name(enum edge edge)
772.41320 -+{
772.41321 -+	switch (edge) {
772.41322 -+	default:
772.41323 -+	case EDGE_SHARP: return "sharp";
772.41324 -+	case EDGE_SMOOTH: return "smooth";
772.41325 -+	}
772.41326 -+}
772.41327 -+
772.41328 -+static void set_edge(Display *dpy, Picture p, enum edge edge)
772.41329 -+{
772.41330 -+	XRenderPictureAttributes a;
772.41331 -+
772.41332 -+	a.poly_edge = edge;
772.41333 -+	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
772.41334 -+}
772.41335 -+
772.41336 -+static void edge_test(struct test *t,
772.41337 -+		      enum mask mask,
772.41338 -+		      enum edge edge,
772.41339 -+		      enum target target)
772.41340 -+{
772.41341 -+	struct test_target out, ref;
772.41342 -+	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
772.41343 -+	Picture src_ref, src_out;
772.41344 -+	XTrapezoid trap;
772.41345 -+	int left_or_right, p;
772.41346 -+
772.41347 -+	test_target_create_render(&t->out, target, &out);
772.41348 -+	set_edge(t->out.dpy, out.picture, edge);
772.41349 -+	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
772.41350 -+
772.41351 -+	test_target_create_render(&t->ref, target, &ref);
772.41352 -+	set_edge(t->ref.dpy, ref.picture, edge);
772.41353 -+	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
772.41354 -+
772.41355 -+	printf("Testing edges (with mask %s and %s edges) (%s): ",
772.41356 -+	       mask_name(mask),
772.41357 -+	       edge_name(edge),
772.41358 -+	       test_target_name(target));
772.41359 -+	fflush(stdout);
772.41360 -+
772.41361 -+	for (left_or_right = 0; left_or_right <= 1; left_or_right++) {
772.41362 -+		for (p = -64; p <= out.width + 64; p++) {
772.41363 -+			char buf[80];
772.41364 -+
772.41365 -+			if (left_or_right) {
772.41366 -+				trap.left.p1.x = 0;
772.41367 -+				trap.left.p1.y = 0;
772.41368 -+				trap.left.p2.x = 0;
772.41369 -+				trap.left.p2.y = out.height << 16;
772.41370 -+
772.41371 -+				trap.right.p1.x = p << 16;
772.41372 -+				trap.right.p1.y = 0;
772.41373 -+				trap.right.p2.x = out.width << 16;
772.41374 -+				trap.right.p2.y = out.height << 16;
772.41375 -+			} else {
772.41376 -+				trap.right.p1.x = out.width << 16;
772.41377 -+				trap.right.p1.y = 0;
772.41378 -+				trap.right.p2.x = out.width << 16;
772.41379 -+				trap.right.p2.y = out.height << 16;
772.41380 -+
772.41381 -+				trap.left.p1.x = 0;
772.41382 -+				trap.left.p1.y = 0;
772.41383 -+				trap.left.p2.x = p << 16;
772.41384 -+				trap.left.p2.y = out.height << 16;
772.41385 -+			}
772.41386 -+
772.41387 -+			trap.top = 0;
772.41388 -+			trap.bottom = out.height << 16;
772.41389 -+
772.41390 -+			sprintf(buf,
772.41391 -+				"trap=((%d, %d), (%d, %d)), ((%d, %d), (%d, %d))\n",
772.41392 -+				trap.left.p1.x >> 16, trap.left.p1.y >> 16,
772.41393 -+				trap.left.p2.x >> 16, trap.left.p2.y >> 16,
772.41394 -+				trap.right.p1.x >> 16, trap.right.p1.y >> 16,
772.41395 -+				trap.right.p2.x >> 16, trap.right.p2.y >> 16);
772.41396 -+
772.41397 -+			clear(&t->out, &out);
772.41398 -+			XRenderCompositeTrapezoids(t->out.dpy,
772.41399 -+						   PictOpSrc,
772.41400 -+						   src_out,
772.41401 -+						   out.picture,
772.41402 -+						   mask_format(t->out.dpy, mask),
772.41403 -+						   0, 0,
772.41404 -+						   &trap, 1);
772.41405 -+
772.41406 -+			clear(&t->ref, &ref);
772.41407 -+			XRenderCompositeTrapezoids(t->ref.dpy,
772.41408 -+						   PictOpSrc,
772.41409 -+						   src_ref,
772.41410 -+						   ref.picture,
772.41411 -+						   mask_format(t->ref.dpy, mask),
772.41412 -+						   0, 0,
772.41413 -+						   &trap, 1);
772.41414 -+
772.41415 -+			test_compare(t,
772.41416 -+				     out.draw, out.format,
772.41417 -+				     ref.draw, ref.format,
772.41418 -+				     0, 0, out.width, out.height,
772.41419 -+				     buf);
772.41420 -+		}
772.41421 -+	}
772.41422 -+
772.41423 -+	XRenderFreePicture(t->out.dpy, src_out);
772.41424 -+	test_target_destroy_render(&t->out, &out);
772.41425 -+
772.41426 -+	XRenderFreePicture(t->ref.dpy, src_ref);
772.41427 -+	test_target_destroy_render(&t->ref, &ref);
772.41428 -+
772.41429 -+	printf("pass\n");
772.41430 -+}
772.41431 -+
772.41432 - int main(int argc, char **argv)
772.41433 - {
772.41434 - 	struct test test;
772.41435 - 	int i, dx, dy;
772.41436 - 	enum target target;
772.41437 - 	enum mask mask;
772.41438 -+	enum edge edge;
772.41439 - 	enum trapezoid trapezoid;
772.41440 - 
772.41441 - 	test_init(&test, argc, argv);
772.41442 - 
772.41443 -+	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
772.41444 -+		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
772.41445 -+			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
772.41446 -+				edge_test(&test, mask, edge, target);
772.41447 -+	}
772.41448 -+
772.41449 - 	for (i = 0; i <= DEFAULT_ITERATIONS; i++) {
772.41450 - 		int reps = REPS(i), sets = SETS(i);
772.41451 - 
772.41452 -diff --git a/test/render-triangle.c b/test/render-triangle.c
772.41453 -new file mode 100644
772.41454 -index 00000000..165834ce
772.41455 ---- /dev/null
772.41456 -+++ b/test/render-triangle.c
772.41457 -@@ -0,0 +1,180 @@
772.41458 -+#include <stdint.h>
772.41459 -+#include <stdio.h>
772.41460 -+#include <stdlib.h>
772.41461 -+
772.41462 -+#include "test.h"
772.41463 -+
772.41464 -+enum edge {
772.41465 -+	EDGE_SHARP = PolyEdgeSharp,
772.41466 -+	EDGE_SMOOTH,
772.41467 -+};
772.41468 -+
772.41469 -+static void set_edge(Display *dpy, Picture p, enum edge edge)
772.41470 -+{
772.41471 -+	XRenderPictureAttributes a;
772.41472 -+
772.41473 -+	a.poly_edge = edge;
772.41474 -+	XRenderChangePicture(dpy, p, CPPolyEdge, &a);
772.41475 -+}
772.41476 -+
772.41477 -+static XRenderPictFormat *mask_format(Display *dpy, enum mask mask)
772.41478 -+{
772.41479 -+	switch (mask) {
772.41480 -+	default:
772.41481 -+	case MASK_NONE: return NULL;
772.41482 -+	case MASK_A1: return XRenderFindStandardFormat(dpy, PictStandardA1);
772.41483 -+	case MASK_A8: return XRenderFindStandardFormat(dpy, PictStandardA8);
772.41484 -+	}
772.41485 -+}
772.41486 -+
772.41487 -+static const char *mask_name(enum mask mask)
772.41488 -+{
772.41489 -+	switch (mask) {
772.41490 -+	default:
772.41491 -+	case MASK_NONE: return "none";
772.41492 -+	case MASK_A1: return "a1";
772.41493 -+	case MASK_A8: return "a8";
772.41494 -+	}
772.41495 -+}
772.41496 -+
772.41497 -+static const char *edge_name(enum edge edge)
772.41498 -+{
772.41499 -+	switch (edge) {
772.41500 -+	default:
772.41501 -+	case EDGE_SHARP: return "sharp";
772.41502 -+	case EDGE_SMOOTH: return "smooth";
772.41503 -+	}
772.41504 -+}
772.41505 -+
772.41506 -+static void clear(struct test_display *dpy, struct test_target *tt)
772.41507 -+{
772.41508 -+	XRenderColor render_color = {0};
772.41509 -+	XRenderFillRectangle(dpy->dpy, PictOpClear, tt->picture, &render_color,
772.41510 -+			     0, 0, tt->width, tt->height);
772.41511 -+}
772.41512 -+
772.41513 -+static void step_to_point(int step, int width, int height, XPointFixed *p)
772.41514 -+{
772.41515 -+	do {
772.41516 -+		p->x = (step - 64) << 16;
772.41517 -+		p->y = -64 << 16;
772.41518 -+
772.41519 -+		step -= width - 128;
772.41520 -+		if (step <= 0)
772.41521 -+			return;
772.41522 -+
772.41523 -+		p->x = (width + 64) << 16;
772.41524 -+		p->y = (step - 64) << 16;
772.41525 -+		step -= height - 128;
772.41526 -+
772.41527 -+		if (step <= 0)
772.41528 -+			return;
772.41529 -+
772.41530 -+		p->x = (width + 64 - step) << 16;
772.41531 -+		p->y = (height + 64) << 16;
772.41532 -+		step -= width - 128;
772.41533 -+
772.41534 -+		if (step <= 0)
772.41535 -+			return;
772.41536 -+
772.41537 -+		p->x = -64 << 16;
772.41538 -+		p->y = (height + 64 - step) << 16;
772.41539 -+		step -= height - 128;
772.41540 -+	} while (step > 0);
772.41541 -+}
772.41542 -+
772.41543 -+static void edge_test(struct test *t,
772.41544 -+		      enum mask mask,
772.41545 -+		      enum edge edge,
772.41546 -+		      enum target target)
772.41547 -+{
772.41548 -+	struct test_target out, ref;
772.41549 -+	XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
772.41550 -+	Picture src_ref, src_out;
772.41551 -+	XTriangle tri;
772.41552 -+	unsigned step, max;
772.41553 -+
772.41554 -+	test_target_create_render(&t->out, target, &out);
772.41555 -+	set_edge(t->out.dpy, out.picture, edge);
772.41556 -+	src_out = XRenderCreateSolidFill(t->out.dpy, &white);
772.41557 -+
772.41558 -+	test_target_create_render(&t->ref, target, &ref);
772.41559 -+	set_edge(t->ref.dpy, ref.picture, edge);
772.41560 -+	src_ref = XRenderCreateSolidFill(t->ref.dpy, &white);
772.41561 -+
772.41562 -+	printf("Testing edges (with mask %s and %s edges) (%s): ",
772.41563 -+	       mask_name(mask),
772.41564 -+	       edge_name(edge),
772.41565 -+	       test_target_name(target));
772.41566 -+	fflush(stdout);
772.41567 -+
772.41568 -+	max = 2*(out.width + 128 + out.height+128);
772.41569 -+	step = 0;
772.41570 -+	for (step = 0; step <= max; step++) {
772.41571 -+		char buf[80];
772.41572 -+
772.41573 -+		step_to_point(step, out.width, out.height, &tri.p1);
772.41574 -+		step_to_point(step + out.width + 128,
772.41575 -+			      out.width, out.height,
772.41576 -+			      &tri.p2);
772.41577 -+		step_to_point(step + out.height + 128 + 2*(out.width + 128),
772.41578 -+			      out.width, out.height,
772.41579 -+			      &tri.p3);
772.41580 -+
772.41581 -+		sprintf(buf,
772.41582 -+			"tri=((%d, %d), (%d, %d), (%d, %d))\n",
772.41583 -+			tri.p1.x >> 16, tri.p1.y >> 16,
772.41584 -+			tri.p2.x >> 16, tri.p2.y >> 16,
772.41585 -+			tri.p3.x >> 16, tri.p3.y >> 16);
772.41586 -+
772.41587 -+		clear(&t->out, &out);
772.41588 -+		XRenderCompositeTriangles(t->out.dpy,
772.41589 -+					  PictOpSrc,
772.41590 -+					  src_out,
772.41591 -+					  out.picture,
772.41592 -+					  mask_format(t->out.dpy, mask),
772.41593 -+					  0, 0,
772.41594 -+					  &tri, 1);
772.41595 -+
772.41596 -+		clear(&t->ref, &ref);
772.41597 -+		XRenderCompositeTriangles(t->ref.dpy,
772.41598 -+					  PictOpSrc,
772.41599 -+					  src_ref,
772.41600 -+					  ref.picture,
772.41601 -+					  mask_format(t->ref.dpy, mask),
772.41602 -+					  0, 0,
772.41603 -+					  &tri, 1);
772.41604 -+
772.41605 -+		test_compare(t,
772.41606 -+			     out.draw, out.format,
772.41607 -+			     ref.draw, ref.format,
772.41608 -+			     0, 0, out.width, out.height,
772.41609 -+			     buf);
772.41610 -+	}
772.41611 -+
772.41612 -+	XRenderFreePicture(t->out.dpy, src_out);
772.41613 -+	test_target_destroy_render(&t->out, &out);
772.41614 -+
772.41615 -+	XRenderFreePicture(t->ref.dpy, src_ref);
772.41616 -+	test_target_destroy_render(&t->ref, &ref);
772.41617 -+
772.41618 -+	printf("pass\n");
772.41619 -+}
772.41620 -+
772.41621 -+int main(int argc, char **argv)
772.41622 -+{
772.41623 -+	struct test test;
772.41624 -+	enum target target;
772.41625 -+	enum mask mask;
772.41626 -+	enum edge edge;
772.41627 -+
772.41628 -+	test_init(&test, argc, argv);
772.41629 -+
772.41630 -+	for (target = TARGET_FIRST; target <= TARGET_LAST; target++) {
772.41631 -+		for (mask = MASK_NONE; mask <= MASK_A8; mask++)
772.41632 -+			for (edge = EDGE_SHARP; edge <= EDGE_SMOOTH; edge++)
772.41633 -+				edge_test(&test, mask, edge, target);
772.41634 -+	}
772.41635 -+
772.41636 -+	return 0;
772.41637 -+}
772.41638 -diff --git a/test/test.h b/test/test.h
772.41639 -index a3ef979d..9eec1cf9 100644
772.41640 ---- a/test/test.h
772.41641 -+++ b/test/test.h
772.41642 -@@ -107,6 +107,15 @@ static inline uint32_t color(uint8_t red, uint8_t green, uint8_t blue, uint8_t a
772.41643 - 	return alpha << 24 | ra >> 8 << 16 | ga >> 8 << 8 | ba >> 8;
772.41644 - }
772.41645 - 
772.41646 -+static inline uint32_t xrender_color(const XRenderColor *c)
772.41647 -+{
772.41648 -+	uint32_t ra = c->red * c->alpha;
772.41649 -+	uint32_t ga = c->green * c->alpha;
772.41650 -+	uint32_t ba = c->blue * c->alpha;
772.41651 -+
772.41652 -+	return c->alpha >> 8 << 24 | ra >> 24 << 16 | ga >> 24 << 8 | ba >> 24;
772.41653 -+}
772.41654 -+
772.41655 - void test_timer_start(struct test_display *t, struct timespec *tv);
772.41656 - double test_timer_stop(struct test_display *t, struct timespec *tv);
772.41657 - 
772.41658 -diff --git a/test/test_image.c b/test/test_image.c
772.41659 -index d15a8af8..1c076990 100644
772.41660 ---- a/test/test_image.c
772.41661 -+++ b/test/test_image.c
772.41662 -@@ -197,13 +197,10 @@ void test_compare(struct test *t,
772.41663 - 		  const char *info)
772.41664 - {
772.41665 - 	XImage out_image, ref_image;
772.41666 --	Pixmap tmp;
772.41667 --	char *out, *ref;
772.41668 -+	uint32_t *out, *ref;
772.41669 - 	char buf[600];
772.41670 - 	uint32_t mask;
772.41671 - 	int i, j;
772.41672 --	XGCValues gcv;
772.41673 --	GC gc;
772.41674 - 
772.41675 - 	if (w * h * 4 > t->out.max_shm_size)
772.41676 - 		return test_compare_fallback(t,
772.41677 -@@ -214,37 +211,24 @@ void test_compare(struct test *t,
772.41678 - 	test_init_image(&out_image, &t->out.shm, out_format, w, h);
772.41679 - 	test_init_image(&ref_image, &t->ref.shm, ref_format, w, h);
772.41680 - 
772.41681 --	gcv.graphics_exposures = 0;
772.41682 --
772.41683 - 	die_unless(out_image.depth == ref_image.depth);
772.41684 - 	die_unless(out_image.bits_per_pixel == ref_image.bits_per_pixel);
772.41685 - 	die_unless(out_image.bits_per_pixel == 32);
772.41686 - 
772.41687 --	mask = depth_mask(out_image.depth);
772.41688 -+	XShmGetImage(t->out.dpy, out_draw, &out_image, x, y, AllPlanes);
772.41689 -+	out = (uint32_t *)out_image.data;
772.41690 - 
772.41691 --	tmp = XCreatePixmap(t->out.dpy, out_draw, w, h, out_image.depth);
772.41692 --	gc = XCreateGC(t->out.dpy, tmp, GCGraphicsExposures, &gcv);
772.41693 --	XCopyArea(t->out.dpy, out_draw, tmp, gc, x, y, w, h, 0, 0);
772.41694 --	XShmGetImage(t->out.dpy, tmp, &out_image, 0, 0, AllPlanes);
772.41695 --	XFreeGC(t->out.dpy, gc);
772.41696 --	XFreePixmap(t->out.dpy, tmp);
772.41697 --	out = out_image.data;
772.41698 --
772.41699 --	tmp = XCreatePixmap(t->ref.dpy, ref_draw, w, h, ref_image.depth);
772.41700 --	gc = XCreateGC(t->ref.dpy, tmp, GCGraphicsExposures, &gcv);
772.41701 --	XCopyArea(t->ref.dpy, ref_draw, tmp, gc, x, y, w, h, 0, 0);
772.41702 --	XShmGetImage(t->ref.dpy, tmp, &ref_image, 0, 0, AllPlanes);
772.41703 --	XFreeGC(t->ref.dpy, gc);
772.41704 --	XFreePixmap(t->ref.dpy, tmp);
772.41705 --	ref = ref_image.data;
772.41706 -+	XShmGetImage(t->ref.dpy, ref_draw, &ref_image, x, y, AllPlanes);
772.41707 -+	ref = (uint32_t *)ref_image.data;
772.41708 - 
772.41709 - 	/* Start with an exact comparison. However, one quicky desires
772.41710 - 	 * a fuzzy comparator to hide hardware inaccuracies...
772.41711 - 	 */
772.41712 -+	mask = depth_mask(out_image.depth);
772.41713 - 	for (j = 0; j < h; j++) {
772.41714 - 		for (i = 0; i < w; i++) {
772.41715 --			uint32_t a = ((uint32_t *)out)[i] & mask;
772.41716 --			uint32_t b = ((uint32_t *)ref)[i] & mask;
772.41717 -+			uint32_t a = out[i] & mask;
772.41718 -+			uint32_t b = ref[i] & mask;
772.41719 - 			if (a != b && pixel_difference(a, b) > MAX_DELTA) {
772.41720 - 				show_pixels(buf,
772.41721 - 					    &out_image, &ref_image,
772.41722 -@@ -255,8 +239,8 @@ void test_compare(struct test *t,
772.41723 - 				    x,i, y,j, a, b, pixel_difference(a, b), buf, info);
772.41724 - 			}
772.41725 - 		}
772.41726 --		out += out_image.bytes_per_line;
772.41727 --		ref += ref_image.bytes_per_line;
772.41728 -+		out = (uint32_t *)((char *)out + out_image.bytes_per_line);
772.41729 -+		ref = (uint32_t *)((char *)ref + ref_image.bytes_per_line);
772.41730 - 	}
772.41731 - }
772.41732 - 
772.41733 -diff --git a/test/xvidmode.c b/test/xvidmode.c
772.41734 -new file mode 100644
772.41735 -index 00000000..5cde8286
772.41736 ---- /dev/null
772.41737 -+++ b/test/xvidmode.c
772.41738 -@@ -0,0 +1,54 @@
772.41739 -+#include <stdlib.h>
772.41740 -+#include <stdio.h>
772.41741 -+#include <string.h>
772.41742 -+#include <X11/Xlib.h>
772.41743 -+#include <X11/extensions/xf86vmode.h>
772.41744 -+
772.41745 -+int main(void)
772.41746 -+{
772.41747 -+	Display *dpy;
772.41748 -+	XF86VidModeModeLine current;
772.41749 -+	XF86VidModeModeInfo **modes;
772.41750 -+	int num_modes, i;
772.41751 -+	int saved_mode = -1;
772.41752 -+	int dotclock;
772.41753 -+
772.41754 -+	dpy = XOpenDisplay(NULL);
772.41755 -+	if (dpy == NULL)
772.41756 -+		dpy = XOpenDisplay(":0");
772.41757 -+
772.41758 -+	XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &dotclock, &current);
772.41759 -+	XF86VidModeGetAllModeLines(dpy, XDefaultScreen(dpy),
772.41760 -+				   &num_modes, &modes);
772.41761 -+	for (i = 0; i < num_modes; i++) {
772.41762 -+		int this;
772.41763 -+
772.41764 -+		this = (current.hdisplay == modes[i]->hdisplay &&
772.41765 -+			current.vdisplay == modes[i]->vdisplay &&
772.41766 -+			dotclock == modes[i]->dotclock);
772.41767 -+		if (this && saved_mode == -1)
772.41768 -+			saved_mode = i;
772.41769 -+
772.41770 -+		printf("[%d] %dx%d%s\n",
772.41771 -+		       i,
772.41772 -+		       modes[i]->hdisplay,
772.41773 -+		       modes[i]->vdisplay,
772.41774 -+		       this ? "*" : "");
772.41775 -+	}
772.41776 -+
772.41777 -+	for (i = 0; i < num_modes; i++) {
772.41778 -+		printf("Switching to mode %dx%d\n",
772.41779 -+		       modes[i]->hdisplay,
772.41780 -+		       modes[i]->vdisplay);
772.41781 -+		XF86VidModeSwitchToMode(dpy, XDefaultScreen(dpy), modes[i]);
772.41782 -+		XSync(dpy, True);
772.41783 -+	}
772.41784 -+
772.41785 -+	if (saved_mode != -1) {
772.41786 -+		XF86VidModeSwitchToMode(dpy, XDefaultScreen(dpy),
772.41787 -+					modes[saved_mode]);
772.41788 -+		XFlush(dpy);
772.41789 -+	}
772.41790 -+
772.41791 -+	return 0;
772.41792 -+}
772.41793 -diff --git a/tools/Makefile.am b/tools/Makefile.am
772.41794 -index b5de2c96..92df266b 100644
772.41795 ---- a/tools/Makefile.am
772.41796 -+++ b/tools/Makefile.am
772.41797 -@@ -26,13 +26,30 @@ AM_CFLAGS = \
772.41798 - drivermandir = $(DRIVER_MAN_DIR)
772.41799 - policydir = $(datarootdir)/polkit-1/actions
772.41800 - 
772.41801 -+bin_PROGRAMS =
772.41802 -+noinst_PROGRAMS =
772.41803 -+libexec_PROGRAMS =
772.41804 -+
772.41805 - if BUILD_TOOLS
772.41806 --bin_PROGRAMS = intel-virtual-output
772.41807 -+bin_PROGRAMS += intel-virtual-output
772.41808 - driverman_DATA = intel-virtual-output.$(DRIVER_MAN_SUFFIX)
772.41809 - endif
772.41810 - 
772.41811 -+if BUILD_TOOL_CURSOR
772.41812 -+noinst_PROGRAMS += cursor
772.41813 -+cursor_CFLAGS = $(TOOL_CURSOR_CFLAGS)
772.41814 -+cursor_LDADD = $(TOOL_CURSOR_LIBS)
772.41815 -+endif
772.41816 -+
772.41817 -+if X11_DRI3
772.41818 -+noinst_PROGRAMS += dri3info
772.41819 -+dri3info_SOURCES = dri3info.c
772.41820 -+dri3info_CFLAGS = $(X11_DRI3_CFLAGS) $(DRI_CFLAGS)
772.41821 -+dri3info_LDADD = $(X11_DRI3_LIBS) $(DRI_LIBS)
772.41822 -+endif
772.41823 -+
772.41824 - if BUILD_BACKLIGHT_HELPER
772.41825 --libexec_PROGRAMS = xf86-video-intel-backlight-helper
772.41826 -+libexec_PROGRAMS += xf86-video-intel-backlight-helper
772.41827 - nodist_policy_DATA = org.x.xf86-video-intel.backlight-helper.policy
772.41828 - 
772.41829 - backlight_helper = $(libexecdir)/xf86-video-intel-backlight-helper
772.41830 -diff --git a/tools/backlight_helper.c b/tools/backlight_helper.c
772.41831 -index 8b2667dc..aadb8fac 100644
772.41832 ---- a/tools/backlight_helper.c
772.41833 -+++ b/tools/backlight_helper.c
772.41834 -@@ -1,3 +1,7 @@
772.41835 -+#ifdef HAVE_CONFIG_H
772.41836 -+#include "config.h"
772.41837 -+#endif
772.41838 -+
772.41839 - #include <stdio.h>
772.41840 - #include <string.h>
772.41841 - #include <stdarg.h>
772.41842 -@@ -9,6 +13,12 @@
772.41843 - #include <sys/types.h>
772.41844 - #include <sys/stat.h>
772.41845 - 
772.41846 -+#if MAJOR_IN_MKDEV
772.41847 -+#include <sys/mkdev.h>
772.41848 -+#elif MAJOR_IN_SYSMACROS
772.41849 -+#include <sys/sysmacros.h>
772.41850 -+#endif
772.41851 -+
772.41852 - #define DBG 0
772.41853 - 
772.41854 - #if defined(__GNUC__) && (__GNUC__ > 3)
772.41855 -diff --git a/tools/cursor.c b/tools/cursor.c
772.41856 -new file mode 100644
772.41857 -index 00000000..6a2438ad
772.41858 ---- /dev/null
772.41859 -+++ b/tools/cursor.c
772.41860 -@@ -0,0 +1,127 @@
772.41861 -+/*
772.41862 -+ * Copyright © 2015 Intel Corporation
772.41863 -+ *
772.41864 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.41865 -+ * copy of this software and associated documentation files (the "Software"),
772.41866 -+ * to deal in the Software without restriction, including without limitation
772.41867 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.41868 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.41869 -+ * Software is furnished to do so, subject to the following conditions:
772.41870 -+ *
772.41871 -+ * The above copyright notice and this permission notice (including the next
772.41872 -+ * paragraph) shall be included in all copies or substantial portions of the
772.41873 -+ * Software.
772.41874 -+ *
772.41875 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.41876 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.41877 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.41878 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.41879 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
772.41880 -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
772.41881 -+ * IN THE SOFTWARE.
772.41882 -+ *
772.41883 -+ */
772.41884 -+
772.41885 -+#ifdef HAVE_CONFIG_H
772.41886 -+#include "config.h"
772.41887 -+#endif
772.41888 -+
772.41889 -+#include <X11/Xlib.h>
772.41890 -+#include <X11/extensions/Xfixes.h>
772.41891 -+
772.41892 -+#include <stdint.h>
772.41893 -+#include <stdio.h>
772.41894 -+#include <stdlib.h>
772.41895 -+#include <png.h>
772.41896 -+
772.41897 -+int main(int argc, char **argv)
772.41898 -+{
772.41899 -+	Display *dpy;
772.41900 -+	XFixesCursorImage *cur;
772.41901 -+	unsigned long *src; /* XXX deep sigh */
772.41902 -+	unsigned x, y;
772.41903 -+	png_struct *png;
772.41904 -+	png_info *info;
772.41905 -+	png_byte **rows;
772.41906 -+	FILE *file;
772.41907 -+
772.41908 -+	dpy = XOpenDisplay(NULL);
772.41909 -+	if (dpy == NULL)
772.41910 -+		return 1;
772.41911 -+
772.41912 -+	if (!XFixesQueryExtension(dpy, (int *)&x, (int *)&y))
772.41913 -+		return 1;
772.41914 -+
772.41915 -+	cur = XFixesGetCursorImage(dpy);
772.41916 -+	if (cur == NULL)
772.41917 -+		return 1;
772.41918 -+
772.41919 -+	printf("Cursor on display '%s': %dx%d, (hotspot %dx%d)\n",
772.41920 -+	       DisplayString(dpy),
772.41921 -+	       cur->width, cur->height,
772.41922 -+	       cur->xhot, cur->yhot);
772.41923 -+
772.41924 -+	if (1) {
772.41925 -+		int x, y;
772.41926 -+
772.41927 -+		src = cur->pixels;
772.41928 -+		for (y = 0; y < cur->height; y++) {
772.41929 -+			for (x = 0; x < cur->width; x++) {
772.41930 -+				if (x == cur->xhot && y == cur->yhot)
772.41931 -+					printf("+");
772.41932 -+				else
772.41933 -+					printf("%c", *src ? *src >> 24 >= 127 ? 'x' : '.' : ' ');
772.41934 -+				src++;
772.41935 -+			}
772.41936 -+			printf("\n");
772.41937 -+		}
772.41938 -+	}
772.41939 -+
772.41940 -+	file = fopen("cursor.png", "wb");
772.41941 -+	if (file == NULL)
772.41942 -+		return 2;
772.41943 -+
772.41944 -+	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
772.41945 -+	info = png_create_info_struct(png);
772.41946 -+	png_init_io(png, file);
772.41947 -+	png_set_IHDR(png, info,
772.41948 -+		     cur->width, cur->height, 8,
772.41949 -+		     PNG_COLOR_TYPE_RGB_ALPHA,
772.41950 -+		     PNG_INTERLACE_NONE,
772.41951 -+		     PNG_COMPRESSION_TYPE_DEFAULT,
772.41952 -+		     PNG_FILTER_TYPE_DEFAULT);
772.41953 -+	png_write_info(png, info);
772.41954 -+
772.41955 -+	src = cur->pixels;
772.41956 -+	rows = malloc(cur->height*sizeof(png_byte*));
772.41957 -+	if (rows == NULL)
772.41958 -+		return 3;
772.41959 -+
772.41960 -+	for (y = 0; y < cur->height; y++) {
772.41961 -+		rows[y] = malloc(cur->width * 4);
772.41962 -+		for (x = 0; x < cur->width; x++) {
772.41963 -+			uint32_t p = *src++;
772.41964 -+			uint8_t r = p >> 0;
772.41965 -+			uint8_t g = p >> 8;
772.41966 -+			uint8_t b = p >> 16;
772.41967 -+			uint8_t a = p >> 24;
772.41968 -+
772.41969 -+			if (a > 0x00 && a < 0xff) {
772.41970 -+				r = (r * 0xff + a /2) / a;
772.41971 -+				g = (g * 0xff + a /2) / a;
772.41972 -+				b = (b * 0xff + a /2) / a;
772.41973 -+			}
772.41974 -+
772.41975 -+			rows[y][4*x + 0] = b;
772.41976 -+			rows[y][4*x + 1] = g;
772.41977 -+			rows[y][4*x + 2] = r;
772.41978 -+			rows[y][4*x + 3] = a;
772.41979 -+		}
772.41980 -+	}
772.41981 -+
772.41982 -+	png_write_image(png, rows);
772.41983 -+	png_write_end(png, NULL);
772.41984 -+	fclose(file);
772.41985 -+
772.41986 -+	return 0;
772.41987 -+}
772.41988 -diff --git a/tools/dri3info.c b/tools/dri3info.c
772.41989 -new file mode 100644
772.41990 -index 00000000..0c33fc5a
772.41991 ---- /dev/null
772.41992 -+++ b/tools/dri3info.c
772.41993 -@@ -0,0 +1,329 @@
772.41994 -+/*
772.41995 -+ * Copyright (c) 2015 Intel Corporation
772.41996 -+ *
772.41997 -+ * Permission is hereby granted, free of charge, to any person obtaining a
772.41998 -+ * copy of this software and associated documentation files (the "Software"),
772.41999 -+ * to deal in the Software without restriction, including without limitation
772.42000 -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
772.42001 -+ * and/or sell copies of the Software, and to permit persons to whom the
772.42002 -+ * Software is furnished to do so, subject to the following conditions:
772.42003 -+ *
772.42004 -+ * The above copyright notice and this permission notice (including the next
772.42005 -+ * paragraph) shall be included in all copies or substantial portions of the
772.42006 -+ * Software.
772.42007 -+ *
772.42008 -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
772.42009 -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
772.42010 -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
772.42011 -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
772.42012 -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
772.42013 -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
772.42014 -+ * SOFTWARE.
772.42015 -+ *
772.42016 -+ * To compile standalone: gcc -o dri3info dri3info.c `pkg-config --cflags --libs xcb-dri3 x11-xcb xrandr xxf86vm libdrm`
772.42017 -+ */
772.42018 -+
772.42019 -+#include <X11/Xlib.h>
772.42020 -+#include <X11/Xlib-xcb.h>
772.42021 -+#include <xcb/xcb.h>
772.42022 -+#include <xcb/dri3.h>
772.42023 -+#include <unistd.h>
772.42024 -+#include <stdio.h>
772.42025 -+#include <stdlib.h>
772.42026 -+#include <stdint.h>
772.42027 -+#include <string.h>
772.42028 -+#include <sys/stat.h>
772.42029 -+#include <drm.h>
772.42030 -+#include <xf86drm.h>
772.42031 -+
772.42032 -+#include <X11/extensions/Xrandr.h>
772.42033 -+#include <X11/extensions/xf86vmode.h>
772.42034 -+
772.42035 -+static int dri3_query_version(Display *dpy, int *major, int *minor)
772.42036 -+{
772.42037 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.42038 -+	xcb_dri3_query_version_reply_t *reply;
772.42039 -+	xcb_generic_error_t *error;
772.42040 -+
772.42041 -+	*major = *minor = -1;
772.42042 -+
772.42043 -+	reply = xcb_dri3_query_version_reply(c,
772.42044 -+					     xcb_dri3_query_version(c,
772.42045 -+								    XCB_DRI3_MAJOR_VERSION,
772.42046 -+								    XCB_DRI3_MINOR_VERSION),
772.42047 -+					     &error);
772.42048 -+	free(error);
772.42049 -+	if (reply == NULL)
772.42050 -+		return -1;
772.42051 -+
772.42052 -+	*major = reply->major_version;
772.42053 -+	*minor = reply->minor_version;
772.42054 -+	free(reply);
772.42055 -+
772.42056 -+	return 0;
772.42057 -+}
772.42058 -+
772.42059 -+static int dri3_exists(Display *dpy)
772.42060 -+{
772.42061 -+	const xcb_query_extension_reply_t *ext;
772.42062 -+	int major, minor;
772.42063 -+
772.42064 -+	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
772.42065 -+	if (ext == NULL || !ext->present)
772.42066 -+		return 0;
772.42067 -+
772.42068 -+	if (dri3_query_version(dpy, &major, &minor) < 0)
772.42069 -+		return 0;
772.42070 -+
772.42071 -+	return major >= 0;
772.42072 -+}
772.42073 -+
772.42074 -+static int dri3_open(Display *dpy)
772.42075 -+{
772.42076 -+	xcb_connection_t *c = XGetXCBConnection(dpy);
772.42077 -+	xcb_dri3_open_cookie_t cookie;
772.42078 -+	xcb_dri3_open_reply_t *reply;
772.42079 -+
772.42080 -+	if (!dri3_exists(dpy))
772.42081 -+		return -1;
772.42082 -+
772.42083 -+	cookie = xcb_dri3_open(c, RootWindow(dpy, DefaultScreen(dpy)), None);
772.42084 -+	reply = xcb_dri3_open_reply(c, cookie, NULL);
772.42085 -+
772.42086 -+	if (!reply)
772.42087 -+		return -1;
772.42088 -+
772.42089 -+	if (reply->nfd != 1)
772.42090 -+		return -1;
772.42091 -+
772.42092 -+	return xcb_dri3_open_reply_fds(c, reply)[0];
772.42093 -+}
772.42094 -+
772.42095 -+static void get_device_path(int fd, char *buf, int len)
772.42096 -+{
772.42097 -+	struct stat remote, local;
772.42098 -+	int i;
772.42099 -+
772.42100 -+	if (fstat(fd, &remote))
772.42101 -+		goto out;
772.42102 -+
772.42103 -+	for (i = 0; i < 16; i++) {
772.42104 -+		snprintf(buf, len, "/dev/dri/card%d", i);
772.42105 -+		if (stat(buf, &local))
772.42106 -+			continue;
772.42107 -+
772.42108 -+		if (local.st_mode == remote.st_mode &&
772.42109 -+		    local.st_rdev == remote.st_rdev)
772.42110 -+			return;
772.42111 -+
772.42112 -+		snprintf(buf, len, "/dev/dri/renderD%d", i + 128);
772.42113 -+		if (stat(buf, &local))
772.42114 -+			continue;
772.42115 -+
772.42116 -+		if (local.st_mode == remote.st_mode &&
772.42117 -+		    local.st_rdev == remote.st_rdev)
772.42118 -+			return;
772.42119 -+	}
772.42120 -+
772.42121 -+out:
772.42122 -+	strncpy(buf, "unknown path", len);
772.42123 -+}
772.42124 -+
772.42125 -+static void get_driver_name(int fd, char *name, int len)
772.42126 -+{
772.42127 -+	drm_version_t version;
772.42128 -+
772.42129 -+	memset(name, 0, len);
772.42130 -+	memset(&version, 0, sizeof(version));
772.42131 -+	version.name_len = len;
772.42132 -+	version.name = name;
772.42133 -+
772.42134 -+	(void)drmIoctl(fd, DRM_IOCTL_VERSION, &version);
772.42135 -+}
772.42136 -+
772.42137 -+static int compute_refresh_rate_from_mode(long n, long d, unsigned flags,
772.42138 -+					   int32_t *numerator,
772.42139 -+					   int32_t *denominator)
772.42140 -+{
772.42141 -+	int i;
772.42142 -+
772.42143 -+	/* The mode flags are only defined privately to the Xserver (in xf86str.h)
772.42144 -+	 * but they at least bit compatible between VidMode, RandR and DRM.
772.42145 -+	 */
772.42146 -+# define V_INTERLACE 0x010
772.42147 -+# define V_DBLSCAN   0x020
772.42148 -+
772.42149 -+	if (flags & V_INTERLACE)
772.42150 -+		n *= 2;
772.42151 -+	else if (flags & V_DBLSCAN)
772.42152 -+		d *= 2;
772.42153 -+
772.42154 -+	/* The OML_sync_control spec requires that if the refresh rate is a
772.42155 -+	 * whole number, that the returned numerator be equal to the refresh
772.42156 -+	 * rate and the denominator be 1.
772.42157 -+	 */
772.42158 -+
772.42159 -+	if (n % d == 0) {
772.42160 -+		n /= d;
772.42161 -+		d = 1;
772.42162 -+	}
772.42163 -+	else {
772.42164 -+		static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
772.42165 -+
772.42166 -+		/* This is a poor man's way to reduce a fraction.  It's far from
772.42167 -+		 * perfect, but it will work well enough for this situation.
772.42168 -+		 */
772.42169 -+
772.42170 -+		for (i = 0; f[i] != 0; i++) {
772.42171 -+			while (n % f[i] == 0 && d % f[i] == 0) {
772.42172 -+				d /= f[i];
772.42173 -+				n /= f[i];
772.42174 -+			}
772.42175 -+		}
772.42176 -+	}
772.42177 -+
772.42178 -+	*numerator = n;
772.42179 -+	*denominator = d;
772.42180 -+	return 1;
772.42181 -+}
772.42182 -+
772.42183 -+static int RRGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
772.42184 -+{
772.42185 -+	int ret = 0;
772.42186 -+	Window root = RootWindow(dpy, DefaultScreen(dpy));
772.42187 -+	XRRScreenResources *res;
772.42188 -+	int rr_event, rr_error;
772.42189 -+	RROutput primary;
772.42190 -+	RRMode mode = 0;
772.42191 -+	int n;
772.42192 -+
772.42193 -+	if (!XRRQueryExtension(dpy, &rr_event, &rr_error))
772.42194 -+		return ret;
772.42195 -+
772.42196 -+	res = XRRGetScreenResourcesCurrent(dpy, root);
772.42197 -+	if (res == NULL)
772.42198 -+		return ret;
772.42199 -+
772.42200 -+	/* Use the primary output if specified, otherwise
772.42201 -+	 * use the mode on the first enabled crtc.
772.42202 -+	 */
772.42203 -+	primary = XRRGetOutputPrimary(dpy, root);
772.42204 -+	if (primary) {
772.42205 -+		XRROutputInfo *output;
772.42206 -+
772.42207 -+		output = XRRGetOutputInfo(dpy, res, primary);
772.42208 -+		if (output != NULL) {
772.42209 -+			if (output->crtc) {
772.42210 -+				XRRCrtcInfo *crtc;
772.42211 -+
772.42212 -+				crtc = XRRGetCrtcInfo(dpy, res, output->crtc);
772.42213 -+				if (crtc) {
772.42214 -+					mode = crtc->mode;
772.42215 -+					XRRFreeCrtcInfo(crtc);
772.42216 -+				}
772.42217 -+			}
772.42218 -+			XRRFreeOutputInfo(output);
772.42219 -+		}
772.42220 -+	}
772.42221 -+
772.42222 -+	for (n = 0; mode == 0 && n < res->ncrtc; n++) {
772.42223 -+		XRRCrtcInfo *crtc;
772.42224 -+
772.42225 -+		crtc = XRRGetCrtcInfo(dpy, res, res->crtcs[n]);
772.42226 -+		if (crtc) {
772.42227 -+			mode = crtc->mode;
772.42228 -+			XRRFreeCrtcInfo(crtc);
772.42229 -+		}
772.42230 -+	}
772.42231 -+
772.42232 -+	for (n = 0; n < res->nmode; n++) {
772.42233 -+		if (res->modes[n].id == mode) {
772.42234 -+			ret = compute_refresh_rate_from_mode(res->modes[n].dotClock,
772.42235 -+							     res->modes[n].hTotal*res->modes[n].vTotal,
772.42236 -+							     res->modes[n].modeFlags,
772.42237 -+							     numerator, denominator);
772.42238 -+			break;
772.42239 -+		}
772.42240 -+	}
772.42241 -+
772.42242 -+	XRRFreeScreenResources(res);
772.42243 -+	return ret;
772.42244 -+}
772.42245 -+
772.42246 -+static int VMGetMscRate(Display *dpy, int32_t *numerator, int32_t *denominator)
772.42247 -+{
772.42248 -+	XF86VidModeModeLine mode_line;
772.42249 -+	int dot_clock;
772.42250 -+	int i;
772.42251 -+
772.42252 -+	if (XF86VidModeQueryVersion(dpy, &i, &i) &&
772.42253 -+	    XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &dot_clock, &mode_line))
772.42254 -+		return compute_refresh_rate_from_mode(dot_clock * 1000,
772.42255 -+						      mode_line.vtotal * mode_line.htotal,
772.42256 -+						      mode_line.flags,
772.42257 -+						      numerator, denominator);
772.42258 -+
772.42259 -+	return 0;
772.42260 -+}
772.42261 -+
772.42262 -+static int get_refresh_rate(Display *dpy,
772.42263 -+			     int32_t *numerator,
772.42264 -+			     int32_t *denominator)
772.42265 -+{
772.42266 -+	if (RRGetMscRate(dpy, numerator, denominator))
772.42267 -+		return 1;
772.42268 -+
772.42269 -+	if (VMGetMscRate(dpy, numerator, denominator))
772.42270 -+		return 1;
772.42271 -+
772.42272 -+	return 0;
772.42273 -+}
772.42274 -+
772.42275 -+static void info(const char *dpyname)
772.42276 -+{
772.42277 -+	Display *dpy;
772.42278 -+	int device;
772.42279 -+	int32_t numerator, denominator;
772.42280 -+
772.42281 -+	dpy = XOpenDisplay(dpyname);
772.42282 -+	if (dpy == NULL) {
772.42283 -+		printf("Unable to connect to display '%s'\n",
772.42284 -+		       dpyname ?: getenv("DISPLAY") ?: "unset");
772.42285 -+		return;
772.42286 -+	}
772.42287 -+
772.42288 -+	printf("Display '%s'\n", DisplayString(dpy));
772.42289 -+	device = dri3_open(dpy);
772.42290 -+	if (device < 0) {
772.42291 -+		printf("\tUnable to connect to DRI3\n");
772.42292 -+	} else {
772.42293 -+		char device_path[1024];
772.42294 -+		char driver_name[1024];
772.42295 -+
772.42296 -+		get_device_path(device, device_path, sizeof(device_path));
772.42297 -+		get_driver_name(device, driver_name, sizeof(driver_name));
772.42298 -+
772.42299 -+		printf("Connected to DRI3, using fd %d which matches %s, driver %s\n",
772.42300 -+		       device, device_path, driver_name);
772.42301 -+		close(device);
772.42302 -+	}
772.42303 -+
772.42304 -+	if (get_refresh_rate(dpy, &numerator, &denominator))
772.42305 -+		printf("\tPrimary refresh rate: %d/%d (%.1fHz)\n",
772.42306 -+		       numerator, denominator, numerator/(float)denominator);
772.42307 -+
772.42308 -+	XCloseDisplay(dpy);
772.42309 -+}
772.42310 -+
772.42311 -+int main(int argc, char **argv)
772.42312 -+{
772.42313 -+	int i;
772.42314 -+
772.42315 -+	if (argc > 1) {
772.42316 -+		for (i = 1; i < argc; i++)
772.42317 -+			info(argv[i]);
772.42318 -+	} else
772.42319 -+		info(NULL);
772.42320 -+
772.42321 -+	return 0;
772.42322 -+}
772.42323 -diff --git a/tools/virtual.c b/tools/virtual.c
772.42324 -index 8e2b4a22..fc8db2b9 100644
772.42325 ---- a/tools/virtual.c
772.42326 -+++ b/tools/virtual.c
772.42327 -@@ -31,6 +31,7 @@
772.42328 - 
772.42329 - #include <X11/Xlibint.h>
772.42330 - #include <X11/extensions/record.h>
772.42331 -+#include <X11/extensions/scrnsaver.h>
772.42332 - #include <X11/extensions/XShm.h>
772.42333 - #if HAVE_X11_EXTENSIONS_SHMPROTO_H
772.42334 - #include <X11/extensions/shmproto.h>
772.42335 -@@ -79,13 +80,15 @@ static int verbose;
772.42336 - #define DRAW 0x8
772.42337 - #define DAMAGE 0x10
772.42338 - #define CURSOR 0x20
772.42339 --#define POLL 0x40
772.42340 -+#define SCREEN 0x40
772.42341 -+#define POLL 0x80
772.42342 - 
772.42343 - struct display {
772.42344 - 	Display *dpy;
772.42345 - 	struct clone *clone;
772.42346 - 	struct context *ctx;
772.42347 - 
772.42348 -+	int saver_event, saver_error, saver_active;
772.42349 - 	int damage_event, damage_error;
772.42350 - 	int xfixes_event, xfixes_error;
772.42351 - 	int rr_event, rr_error, rr_active;
772.42352 -@@ -98,6 +101,7 @@ struct display {
772.42353 - 	int width;
772.42354 - 	int height;
772.42355 - 	int depth;
772.42356 -+	int active;
772.42357 - 
772.42358 - 	XRenderPictFormat *root_format;
772.42359 - 	XRenderPictFormat *rgb16_format;
772.42360 -@@ -111,7 +115,7 @@ struct display {
772.42361 - 	Cursor invisible_cursor;
772.42362 - 	Cursor visible_cursor;
772.42363 - 
772.42364 --	XcursorImage cursor_image;
772.42365 -+	XcursorImage cursor_image; /* first only */
772.42366 - 	int cursor_serial;
772.42367 - 	int cursor_x;
772.42368 - 	int cursor_y;
772.42369 -@@ -123,6 +127,13 @@ struct display {
772.42370 - 	int send;
772.42371 - 	int skip_clone;
772.42372 - 	int skip_frame;
772.42373 -+
772.42374 -+	struct {
772.42375 -+		int timeout;
772.42376 -+		int interval;
772.42377 -+		int prefer_blank;
772.42378 -+		int allow_exp;
772.42379 -+	} saver;
772.42380 - };
772.42381 - 
772.42382 - struct output {
772.42383 -@@ -145,6 +156,7 @@ struct output {
772.42384 - 	XRenderPictFormat *use_render;
772.42385 - 
772.42386 - 	int x, y;
772.42387 -+	int width, height;
772.42388 - 	XRRModeInfo mode;
772.42389 - 	Rotation rotation;
772.42390 - };
772.42391 -@@ -218,6 +230,13 @@ static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Wi
772.42392 - static int _x_error_occurred;
772.42393 - 
772.42394 - static int
772.42395 -+_io_error_handler(Display *display)
772.42396 -+{
772.42397 -+	fprintf(stderr, "XIO error on display %s\n", DisplayString(display));
772.42398 -+	abort();
772.42399 -+}
772.42400 -+
772.42401 -+static int
772.42402 - _check_error_handler(Display     *display,
772.42403 - 		     XErrorEvent *event)
772.42404 - {
772.42405 -@@ -243,6 +262,10 @@ can_use_shm(Display *dpy,
772.42406 - 	XExtCodes *codes;
772.42407 - 	int major, minor, has_shm, has_pixmap;
772.42408 - 
772.42409 -+	*shm_event = 0;
772.42410 -+	*shm_opcode = 0;
772.42411 -+	*shm_pixmap = 0;
772.42412 -+
772.42413 - 	if (!XShmQueryExtension(dpy))
772.42414 - 		return 0;
772.42415 - 
772.42416 -@@ -320,6 +343,7 @@ can_use_shm(Display *dpy,
772.42417 - #include <X11/Xlib-xcb.h>
772.42418 - #include <X11/xshmfence.h>
772.42419 - #include <xcb/xcb.h>
772.42420 -+#include <xcb/xcbext.h>
772.42421 - #include <xcb/dri3.h>
772.42422 - #include <xcb/sync.h>
772.42423 - static Pixmap dri3_create_pixmap(Display *dpy,
772.42424 -@@ -357,6 +381,7 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
772.42425 - {
772.42426 - 	xcb_connection_t *c = XGetXCBConnection(dpy);
772.42427 - 	xcb_dri3_query_version_reply_t *reply;
772.42428 -+	xcb_generic_error_t *error;
772.42429 - 
772.42430 - 	*major = *minor = -1;
772.42431 - 
772.42432 -@@ -364,7 +389,8 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
772.42433 - 					     xcb_dri3_query_version(c,
772.42434 - 								    XCB_DRI3_MAJOR_VERSION,
772.42435 - 								    XCB_DRI3_MINOR_VERSION),
772.42436 --					     NULL);
772.42437 -+					     &error);
772.42438 -+	free(error);
772.42439 - 	if (reply == NULL)
772.42440 - 		return -1;
772.42441 - 
772.42442 -@@ -377,8 +403,13 @@ static int dri3_query_version(Display *dpy, int *major, int *minor)
772.42443 - 
772.42444 - static int dri3_exists(Display *dpy)
772.42445 - {
772.42446 -+	const xcb_query_extension_reply_t *ext;
772.42447 - 	int major, minor;
772.42448 - 
772.42449 -+	ext = xcb_get_extension_data(XGetXCBConnection(dpy), &xcb_dri3_id);
772.42450 -+	if (ext == NULL || !ext->present)
772.42451 -+		return 0;
772.42452 -+
772.42453 - 	if (dri3_query_version(dpy, &major, &minor) < 0)
772.42454 - 		return 0;
772.42455 - 
772.42456 -@@ -809,6 +840,10 @@ static int clone_update_modes__fixed(struct clone *clone)
772.42457 - 	RRMode id;
772.42458 - 	int i, j, ret = ENOENT;
772.42459 - 
772.42460 -+	DBG(X11, ("%s-%s cloning modes fixed %dx%d\n",
772.42461 -+	     DisplayString(clone->dst.dpy), clone->dst.name,
772.42462 -+	     clone->dst.width, clone->dst.height));
772.42463 -+
772.42464 - 	assert(clone->src.rr_output);
772.42465 - 
772.42466 - 	res = _XRRGetScreenResourcesCurrent(clone->src.dpy, clone->src.window);
772.42467 -@@ -837,8 +872,8 @@ static int clone_update_modes__fixed(struct clone *clone)
772.42468 - 
772.42469 - 	/* Create matching mode for the real output on the virtual */
772.42470 - 	memset(&mode, 0, sizeof(mode));
772.42471 --	mode.width = clone->width;
772.42472 --	mode.height = clone->height;
772.42473 -+	mode.width = clone->dst.width;
772.42474 -+	mode.height = clone->dst.height;
772.42475 - 	mode.nameLength = sprintf(mode_name, "FAKE-%dx%d", mode.width, mode.height);
772.42476 - 	mode.name = mode_name;
772.42477 - 
772.42478 -@@ -942,6 +977,35 @@ out:
772.42479 - 	return rr_output;
772.42480 - }
772.42481 - 
772.42482 -+static int check_virtual(struct display *display)
772.42483 -+{
772.42484 -+	XRRScreenResources *res;
772.42485 -+	int found = -ENOENT;
772.42486 -+	int i;
772.42487 -+
772.42488 -+	res = _XRRGetScreenResourcesCurrent(display->dpy, display->root);
772.42489 -+	if (res == NULL)
772.42490 -+		return -ENOMEM;
772.42491 -+
772.42492 -+	for (i = 0; found == -ENOENT && i < res->noutput; i++) {
772.42493 -+		XRROutputInfo *output;
772.42494 -+
772.42495 -+		output = XRRGetOutputInfo(display->dpy, res, res->outputs[i]);
772.42496 -+		if (output == NULL)
772.42497 -+			continue;
772.42498 -+
772.42499 -+		if (strcmp(output->name, "VIRTUAL1") == 0)
772.42500 -+			found = 0;
772.42501 -+
772.42502 -+		XRRFreeOutputInfo(output);
772.42503 -+	}
772.42504 -+	XRRFreeScreenResources(res);
772.42505 -+
772.42506 -+	DBG(XRR, ("%s(%s): has VIRTUAL1? %d\n",
772.42507 -+		  __func__, DisplayString(display->dpy), found));
772.42508 -+	return found;
772.42509 -+}
772.42510 -+
772.42511 - static int stride_for_depth(int width, int depth)
772.42512 - {
772.42513 - 	if (depth == 24)
772.42514 -@@ -1082,20 +1146,20 @@ static int clone_init_xfer(struct clone *clone)
772.42515 - 		width = 0;
772.42516 - 		height = 0;
772.42517 - 	} else if (clone->dri3.xid) {
772.42518 --		width = clone->dst.display->width;
772.42519 --		height = clone->dst.display->height;
772.42520 -+		width = clone->dst.width;
772.42521 -+		height = clone->dst.height;
772.42522 - 	} else {
772.42523 - 		width = mode_width(&clone->src.mode, clone->src.rotation);
772.42524 - 		height = mode_height(&clone->src.mode, clone->src.rotation);
772.42525 - 	}
772.42526 - 
772.42527 -+	DBG(DRAW, ("%s-%s create xfer, %dx%d (currently %dx%d)\n",
772.42528 -+	     DisplayString(clone->dst.dpy), clone->dst.name,
772.42529 -+	     width, height, clone->width, clone->height));
772.42530 -+
772.42531 - 	if (width == clone->width && height == clone->height)
772.42532 - 		return 0;
772.42533 - 
772.42534 --	DBG(DRAW, ("%s-%s create xfer, %dx%d\n",
772.42535 --	     DisplayString(clone->dst.dpy), clone->dst.name,
772.42536 --	     width, height));
772.42537 --
772.42538 - 	if (clone->shm.shmaddr) {
772.42539 - 		if (clone->src.use_shm)
772.42540 - 			XShmDetach(clone->src.dpy, &clone->src.shm);
772.42541 -@@ -1225,6 +1289,56 @@ static void clone_update(struct clone *clone)
772.42542 - 	clone->rr_update = 0;
772.42543 - }
772.42544 - 
772.42545 -+static void screensaver_save(struct display *display)
772.42546 -+{
772.42547 -+	display->saver_active =
772.42548 -+		XScreenSaverQueryExtension(display->dpy,
772.42549 -+					   &display->saver_event,
772.42550 -+					   &display->saver_error);
772.42551 -+	DBG(SCREEN,
772.42552 -+	    ("%s screen saver active? %d [event=%d, error=%d]\n",
772.42553 -+	     DisplayString(display->dpy),
772.42554 -+	     display->saver_active,
772.42555 -+	     display->saver_event,
772.42556 -+	     display->saver_error));
772.42557 -+
772.42558 -+	XGetScreenSaver(display->dpy,
772.42559 -+			&display->saver.timeout,
772.42560 -+			&display->saver.interval,
772.42561 -+			&display->saver.prefer_blank,
772.42562 -+			&display->saver.allow_exp);
772.42563 -+
772.42564 -+	DBG(SCREEN,
772.42565 -+	    ("%s saving screen saver defaults: timeout=%d interval=%d prefer_blank=%d allow_exp=%d\n",
772.42566 -+	     DisplayString(display->dpy),
772.42567 -+	     display->saver.timeout,
772.42568 -+	     display->saver.interval,
772.42569 -+	     display->saver.prefer_blank,
772.42570 -+	     display->saver.allow_exp));
772.42571 -+}
772.42572 -+
772.42573 -+static void screensaver_disable(struct display *display)
772.42574 -+{
772.42575 -+	DBG(SCREEN,
772.42576 -+	    ("%s disabling screen saver\n", DisplayString(display->dpy)));
772.42577 -+
772.42578 -+	XSetScreenSaver(display->dpy, 0, 0, DefaultBlanking, DefaultExposures);
772.42579 -+	display_mark_flush(display);
772.42580 -+}
772.42581 -+
772.42582 -+static void screensaver_restore(struct display *display)
772.42583 -+{
772.42584 -+	DBG(SCREEN,
772.42585 -+	    ("%s restoring screen saver\n", DisplayString(display->dpy)));
772.42586 -+
772.42587 -+	XSetScreenSaver(display->dpy,
772.42588 -+			display->saver.timeout,
772.42589 -+			display->saver.interval,
772.42590 -+			display->saver.prefer_blank,
772.42591 -+			display->saver.allow_exp);
772.42592 -+	display_mark_flush(display);
772.42593 -+}
772.42594 -+
772.42595 - static int context_update(struct context *ctx)
772.42596 - {
772.42597 - 	Display *dpy = ctx->display->dpy;
772.42598 -@@ -1325,8 +1439,19 @@ static int context_update(struct context *ctx)
772.42599 - 		struct clone *clone;
772.42600 - 		int x1, x2, y1, y2;
772.42601 - 
772.42602 --		if (display->rr_active == 0)
772.42603 -+		if (display->rr_active == 0) {
772.42604 -+			for (clone = display->clone; clone; clone = clone->next) {
772.42605 -+				struct output *output = &clone->src;
772.42606 -+				if (output->mode.id) {
772.42607 -+					clone->dst.mode.id = -1;
772.42608 -+					clone->dst.rr_crtc = -1;
772.42609 -+				} else {
772.42610 -+					clone->dst.mode.id = 0;
772.42611 -+					clone->dst.rr_crtc = 0;
772.42612 -+				}
772.42613 -+			}
772.42614 - 			continue;
772.42615 -+		}
772.42616 - 
772.42617 - 		x1 = y1 = INT_MAX;
772.42618 - 		x2 = y2 = INT_MIN;
772.42619 -@@ -1570,6 +1695,13 @@ ungrab:
772.42620 - 		XUngrabServer(display->dpy);
772.42621 - 	}
772.42622 - 
772.42623 -+	for (n = 1; n < ctx->ndisplay; n++) {
772.42624 -+		struct display *display = &ctx->display[n];
772.42625 -+
772.42626 -+		display->active = 0;
772.42627 -+		screensaver_restore(display);
772.42628 -+	}
772.42629 -+
772.42630 - 	ctx->active = NULL;
772.42631 - 	for (n = 0; n < ctx->nclone; n++) {
772.42632 - 		struct clone *clone = &ctx->clones[n];
772.42633 -@@ -1580,7 +1712,10 @@ ungrab:
772.42634 - 			continue;
772.42635 - 
772.42636 - 		DBG(XRR, ("%s-%s: added to active list\n",
772.42637 --		     DisplayString(clone->dst.display->dpy), clone->dst.name));
772.42638 -+			  DisplayString(clone->dst.display->dpy), clone->dst.name));
772.42639 -+
772.42640 -+		if (clone->dst.display->active++ == 0)
772.42641 -+			screensaver_disable(clone->dst.display);
772.42642 - 
772.42643 - 		clone->active = ctx->active;
772.42644 - 		ctx->active = clone;
772.42645 -@@ -1599,14 +1734,17 @@ static Cursor display_load_invisible_cursor(struct display *display)
772.42646 - 
772.42647 - static Cursor display_get_visible_cursor(struct display *display)
772.42648 - {
772.42649 --	if (display->cursor_serial != display->cursor_image.size) {
772.42650 --		DBG(CURSOR, ("%s updating cursor\n", DisplayString(display->dpy)));
772.42651 -+	struct display *first = display->ctx->display;
772.42652 -+
772.42653 -+	if (display->cursor_serial != first->cursor_serial) {
772.42654 -+		DBG(CURSOR, ("%s updating cursor %dx%d, serial %d\n",
772.42655 -+		    DisplayString(display->dpy), first->cursor_image.width, first->cursor_image.height, first->cursor_serial));
772.42656 - 
772.42657 - 		if (display->visible_cursor)
772.42658 - 			XFreeCursor(display->dpy, display->visible_cursor);
772.42659 - 
772.42660 --		display->visible_cursor = XcursorImageLoadCursor(display->dpy, &display->cursor_image);
772.42661 --		display->cursor_serial = display->cursor_image.size;
772.42662 -+		display->visible_cursor = XcursorImageLoadCursor(display->dpy, &first->cursor_image);
772.42663 -+		display->cursor_serial = first->cursor_serial;
772.42664 - 	}
772.42665 - 
772.42666 - 	return display->visible_cursor;
772.42667 -@@ -1629,7 +1767,7 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
772.42668 - 	display->cursor_image.height = cur->height;
772.42669 - 	display->cursor_image.xhot = cur->xhot;
772.42670 - 	display->cursor_image.yhot = cur->yhot;
772.42671 --	display->cursor_image.size++;
772.42672 -+	display->cursor_serial++;
772.42673 - 
772.42674 - 	n = cur->width*cur->height;
772.42675 - 	src = cur->pixels;
772.42676 -@@ -1637,11 +1775,24 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
772.42677 - 	while (n--)
772.42678 - 		*dst++ = *src++;
772.42679 - 
772.42680 --	DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
772.42681 --	display->cursor_moved++;
772.42682 --	if (display->cursor != display->invisible_cursor) {
772.42683 --		display->cursor_visible++;
772.42684 --		context_enable_timer(display->ctx);
772.42685 -+	if (verbose & CURSOR) {
772.42686 -+		int x, y;
772.42687 -+
772.42688 -+		printf("%s cursor image %dx%d, serial %d:\n",
772.42689 -+		       DisplayString(display->dpy),
772.42690 -+		       cur->width, cur->height,
772.42691 -+		       display->cursor_serial);
772.42692 -+		dst = display->cursor_image.pixels;
772.42693 -+		for (y = 0; y < cur->height; y++) {
772.42694 -+			for (x = 0; x < cur->width; x++) {
772.42695 -+				if (x == cur->xhot && y == cur->yhot)
772.42696 -+					printf("+");
772.42697 -+				else
772.42698 -+					printf("%c", *dst ? *dst >> 24 >= 127 ? 'x' : '.' : ' ');
772.42699 -+				dst++;
772.42700 -+			}
772.42701 -+			printf("\n");
772.42702 -+		}
772.42703 - 	}
772.42704 - }
772.42705 - 
772.42706 -@@ -1685,6 +1836,8 @@ static void display_flush_cursor(struct display *display)
772.42707 - 	if (cursor == None)
772.42708 - 		cursor = display->invisible_cursor;
772.42709 - 	if (cursor != display->cursor) {
772.42710 -+		DBG(CURSOR, ("%s setting cursor shape %lx\n",
772.42711 -+		    DisplayString(display->dpy), (long)cursor));
772.42712 - 		XDefineCursor(display->dpy, display->root, cursor);
772.42713 - 		display->cursor = cursor;
772.42714 - 	}
772.42715 -@@ -1762,6 +1915,8 @@ static void get_src(struct clone *c, const XRectangle *clip)
772.42716 - 	c->image.obdata = (char *)&c->src.shm;
772.42717 - 
772.42718 - 	if (c->src.use_render) {
772.42719 -+		DBG(DRAW, ("%s-%s get_src via XRender\n",
772.42720 -+			   DisplayString(c->dst.dpy), c->dst.name));
772.42721 - 		XRenderComposite(c->src.dpy, PictOpSrc,
772.42722 - 				 c->src.win_picture, 0, c->src.pix_picture,
772.42723 - 				 clip->x, clip->y,
772.42724 -@@ -1782,16 +1937,22 @@ static void get_src(struct clone *c, const XRectangle *clip)
772.42725 - 				     &c->image, 0, 0);
772.42726 - 		}
772.42727 - 	} else if (c->src.pixmap) {
772.42728 -+		DBG(DRAW, ("%s-%s get_src XCopyArea (SHM/DRI3)\n",
772.42729 -+			   DisplayString(c->dst.dpy), c->dst.name));
772.42730 - 		XCopyArea(c->src.dpy, c->src.window, c->src.pixmap, c->src.gc,
772.42731 - 			  clip->x, clip->y,
772.42732 - 			  clip->width, clip->height,
772.42733 - 			  0, 0);
772.42734 - 		XSync(c->src.dpy, False);
772.42735 - 	} else if (c->src.use_shm) {
772.42736 -+		DBG(DRAW, ("%s-%s get_src XShmGetImage\n",
772.42737 -+			   DisplayString(c->dst.dpy), c->dst.name));
772.42738 - 		ximage_prepare(&c->image, clip->width, clip->height);
772.42739 - 		XShmGetImage(c->src.dpy, c->src.window, &c->image,
772.42740 - 			     clip->x, clip->y, AllPlanes);
772.42741 - 	} else {
772.42742 -+		DBG(DRAW, ("%s-%s get_src XGetSubImage (slow)\n",
772.42743 -+			   DisplayString(c->dst.dpy), c->dst.name));
772.42744 - 		ximage_prepare(&c->image, c->width, c->height);
772.42745 - 		XGetSubImage(c->src.dpy, c->src.window,
772.42746 - 			     clip->x, clip->y, clip->width, clip->height,
772.42747 -@@ -1838,7 +1999,7 @@ static void put_dst(struct clone *c, const XRectangle *clip)
772.42748 - 				 clip->width, clip->height);
772.42749 - 		c->dst.display->send |= c->dst.use_shm;
772.42750 - 	} else if (c->dst.pixmap) {
772.42751 --		DBG(DRAW, ("%s-%s using SHM pixmap\n",
772.42752 -+		DBG(DRAW, ("%s-%s using SHM or DRI3 pixmap\n",
772.42753 - 		     DisplayString(c->dst.dpy), c->dst.name));
772.42754 - 		c->dst.serial = NextRequest(c->dst.dpy);
772.42755 - 		XCopyArea(c->dst.dpy, c->dst.pixmap, c->dst.window, c->dst.gc,
772.42756 -@@ -1870,6 +2031,9 @@ static int clone_paint(struct clone *c)
772.42757 - {
772.42758 - 	XRectangle clip;
772.42759 - 
772.42760 -+	if (c->width == 0 || c->height == 0)
772.42761 -+		return 0;
772.42762 -+
772.42763 - 	DBG(DRAW, ("%s-%s paint clone, damaged (%d, %d), (%d, %d) [(%d, %d), (%d,  %d)]\n",
772.42764 - 	     DisplayString(c->dst.dpy), c->dst.name,
772.42765 - 	     c->damaged.x1, c->damaged.y1,
772.42766 -@@ -1944,6 +2108,10 @@ static int clone_paint(struct clone *c)
772.42767 - 		clip.height = c->damaged.y2 - c->damaged.y1;
772.42768 - 		get_src(c, &clip);
772.42769 - 
772.42770 -+		DBG(DRAW, ("%s-%s target offset %dx%d\n",
772.42771 -+			   DisplayString(c->dst.dpy), c->dst.name,
772.42772 -+			   c->dst.x - c->src.x, c->dst.y - c->src.y));
772.42773 -+
772.42774 - 		clip.x += c->dst.x - c->src.x;
772.42775 - 		clip.y += c->dst.y - c->src.y;
772.42776 - 		put_dst(c, &clip);
772.42777 -@@ -1969,8 +2137,9 @@ static void clone_damage(struct clone *c, const XRectangle *rec)
772.42778 - 	if ((v = (int)rec->y + rec->height) > c->damaged.y2)
772.42779 - 		c->damaged.y2 = v;
772.42780 - 
772.42781 --	DBG(DAMAGE, ("%s-%s damaged: (%d, %d), (%d, %d)\n",
772.42782 -+	DBG(DAMAGE, ("%s-%s damaged: +(%d,%d)x(%d, %d) -> (%d, %d), (%d, %d)\n",
772.42783 - 	     DisplayString(c->dst.display->dpy), c->dst.name,
772.42784 -+	     rec->x, rec->y, rec->width, rec->height,
772.42785 - 	     c->damaged.x1, c->damaged.y1,
772.42786 - 	     c->damaged.x2, c->damaged.y2));
772.42787 - }
772.42788 -@@ -2252,6 +2421,8 @@ static int clone_init_depth(struct clone *clone)
772.42789 - 	if (ret)
772.42790 - 		return ret;
772.42791 - 
772.42792 -+	clone->depth = depth;
772.42793 -+
772.42794 - 	DBG(X11, ("%s-%s using depth %d, requires xrender for src? %d, for dst? %d\n",
772.42795 - 	     DisplayString(clone->dst.dpy), clone->dst.name,
772.42796 - 	     clone->depth,
772.42797 -@@ -2312,6 +2483,8 @@ static int add_display(struct context *ctx, Display *dpy)
772.42798 - 	display->depth = DefaultDepth(dpy, DefaultScreen(dpy));
772.42799 - 	display->visual = DefaultVisual(dpy, DefaultScreen(dpy));
772.42800 - 
772.42801 -+	XSelectInput(dpy, display->root, ExposureMask);
772.42802 -+
772.42803 - 	display->has_shm = can_use_shm(dpy, display->root,
772.42804 - 				       &display->shm_event,
772.42805 - 				       &display->shm_opcode,
772.42806 -@@ -2323,6 +2496,8 @@ static int add_display(struct context *ctx, Display *dpy)
772.42807 - 	     display->shm_opcode,
772.42808 - 	     display->has_shm_pixmap));
772.42809 - 
772.42810 -+	screensaver_save(display);
772.42811 -+
772.42812 - 	display->rr_active = XRRQueryExtension(dpy, &display->rr_event, &display->rr_error);
772.42813 - 	DBG(X11, ("%s: randr_active?=%d, event=%d, error=%d\n",
772.42814 - 	     DisplayString(dpy),
772.42815 -@@ -2592,6 +2767,11 @@ static int last_display_add_clones__randr(struct context *ctx)
772.42816 - 			return ret;
772.42817 - 		}
772.42818 - 
772.42819 -+		clone->dst.x = 0;
772.42820 -+		clone->dst.y = 0;
772.42821 -+		clone->dst.width = display->width;
772.42822 -+		clone->dst.height = display->height;
772.42823 -+
772.42824 - 		ret = clone_update_modes__randr(clone);
772.42825 - 		if (ret) {
772.42826 - 			fprintf(stderr, "Failed to clone output \"%s\" from display \"%s\"\n",
772.42827 -@@ -2668,8 +2848,8 @@ static int last_display_add_clones__xinerama(struct context *ctx)
772.42828 - 		}
772.42829 - 
772.42830 - 		/* Replace the modes on the local VIRTUAL output with the remote Screen */
772.42831 --		clone->width = xi[n].width;
772.42832 --		clone->height = xi[n].height;
772.42833 -+		clone->dst.width = xi[n].width;
772.42834 -+		clone->dst.height = xi[n].height;
772.42835 - 		clone->dst.x = xi[n].x_org;
772.42836 - 		clone->dst.y = xi[n].y_org;
772.42837 - 		clone->dst.rr_crtc = -1;
772.42838 -@@ -2698,64 +2878,67 @@ static int last_display_add_clones__display(struct context *ctx)
772.42839 - 	Display *dpy = display->dpy;
772.42840 - 	struct clone *clone;
772.42841 - 	Screen *scr;
772.42842 -+	int count, s;
772.42843 - 	char buf[80];
772.42844 - 	int ret;
772.42845 - 	RROutput id;
772.42846 - 
772.42847 -+	count = ScreenCount(dpy);
772.42848 -+	DBG(X11, ("%s(%s) - %d screens\n", __func__, DisplayString(dpy), count));
772.42849 -+	for (s = 0; s < count; s++) {
772.42850 -+		clone = add_clone(ctx);
772.42851 -+		if (clone == NULL)
772.42852 -+			return -ENOMEM;
772.42853 - 
772.42854 --	DBG(X11, ("%s(%s)\n", __func__, DisplayString(dpy)));
772.42855 --	clone = add_clone(ctx);
772.42856 --	if (clone == NULL)
772.42857 --		return -ENOMEM;
772.42858 -+		clone->depth = 24;
772.42859 -+		clone->next = display->clone;
772.42860 -+		display->clone = clone;
772.42861 - 
772.42862 --	clone->depth = 24;
772.42863 --	clone->next = display->clone;
772.42864 --	display->clone = clone;
772.42865 -+		id = claim_virtual(ctx->display, buf, ctx->nclone);
772.42866 -+		if (id == 0) {
772.42867 -+			fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
772.42868 -+				buf, DisplayString(dpy));
772.42869 -+		}
772.42870 -+		ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
772.42871 -+		if (ret) {
772.42872 -+			fprintf(stderr, "Failed to add display \"%s\"\n",
772.42873 -+				DisplayString(ctx->display->dpy));
772.42874 -+			return ret;
772.42875 -+		}
772.42876 - 
772.42877 --	id = claim_virtual(ctx->display, buf, ctx->nclone);
772.42878 --	if (id == 0) {
772.42879 --		fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
772.42880 --			buf, DisplayString(dpy));
772.42881 --	}
772.42882 --	ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
772.42883 --	if (ret) {
772.42884 --		fprintf(stderr, "Failed to add display \"%s\"\n",
772.42885 --			DisplayString(ctx->display->dpy));
772.42886 --		return ret;
772.42887 --	}
772.42888 -+		sprintf(buf, "SCREEN%d", s);
772.42889 -+		ret = clone_output_init(clone, &clone->dst, display, buf, 0);
772.42890 -+		if (ret) {
772.42891 -+			fprintf(stderr, "Failed to add display \"%s\"\n",
772.42892 -+				DisplayString(dpy));
772.42893 -+			return ret;
772.42894 -+		}
772.42895 - 
772.42896 --	sprintf(buf, "WHOLE");
772.42897 --	ret = clone_output_init(clone, &clone->dst, display, buf, 0);
772.42898 --	if (ret) {
772.42899 --		fprintf(stderr, "Failed to add display \"%s\"\n",
772.42900 --			DisplayString(dpy));
772.42901 --		return ret;
772.42902 --	}
772.42903 -+		ret = clone_init_depth(clone);
772.42904 -+		if (ret) {
772.42905 -+			fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
772.42906 -+				DisplayString(dpy));
772.42907 -+			return ret;
772.42908 -+		}
772.42909 - 
772.42910 --	ret = clone_init_depth(clone);
772.42911 --	if (ret) {
772.42912 --		fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
772.42913 --			DisplayString(dpy));
772.42914 --		return ret;
772.42915 --	}
772.42916 -+		/* Replace the modes on the local VIRTUAL output with the remote Screen */
772.42917 -+		scr = ScreenOfDisplay(dpy, s);
772.42918 -+		clone->dst.width = scr->width;
772.42919 -+		clone->dst.height = scr->height;
772.42920 -+		clone->dst.x = 0;
772.42921 -+		clone->dst.y = 0;
772.42922 -+		clone->dst.rr_crtc = -1;
772.42923 -+		ret = clone_update_modes__fixed(clone);
772.42924 -+		if (ret) {
772.42925 -+			fprintf(stderr, "Failed to clone display \"%s\"\n",
772.42926 -+				DisplayString(dpy));
772.42927 -+			return ret;
772.42928 -+		}
772.42929 - 
772.42930 --	/* Replace the modes on the local VIRTUAL output with the remote Screen */
772.42931 --	scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
772.42932 --	clone->width = scr->width;
772.42933 --	clone->height = scr->height;
772.42934 --	clone->dst.x = 0;
772.42935 --	clone->dst.y = 0;
772.42936 --	clone->dst.rr_crtc = -1;
772.42937 --	ret = clone_update_modes__fixed(clone);
772.42938 --	if (ret) {
772.42939 --		fprintf(stderr, "Failed to clone display \"%s\"\n",
772.42940 --			DisplayString(dpy));
772.42941 --		return ret;
772.42942 -+		clone->active = ctx->active;
772.42943 -+		ctx->active = clone;
772.42944 - 	}
772.42945 - 
772.42946 --	clone->active = ctx->active;
772.42947 --	ctx->active = clone;
772.42948 --
772.42949 - 	return 0;
772.42950 - }
772.42951 - 
772.42952 -@@ -3168,6 +3351,33 @@ static void context_cleanup(struct context *ctx)
772.42953 - 	XCloseDisplay(dpy);
772.42954 - }
772.42955 - 
772.42956 -+static void update_cursor_image(struct context *ctx)
772.42957 -+{
772.42958 -+	XFixesCursorImage *cur;
772.42959 -+	int i;
772.42960 -+
772.42961 -+	DBG(CURSOR, ("%s cursor changed\n",
772.42962 -+		     DisplayString(ctx->display->dpy)));
772.42963 -+
772.42964 -+	cur = XFixesGetCursorImage(ctx->display->dpy);
772.42965 -+	if (cur == NULL)
772.42966 -+		return;
772.42967 -+
772.42968 -+	display_load_visible_cursor(&ctx->display[0], cur);
772.42969 -+	for (i = 1; i < ctx->ndisplay; i++) {
772.42970 -+		struct display *display = &ctx->display[i];
772.42971 -+
772.42972 -+		DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
772.42973 -+		display->cursor_moved++;
772.42974 -+		if (display->cursor != display->invisible_cursor) {
772.42975 -+			display->cursor_visible++;
772.42976 -+			context_enable_timer(display->ctx);
772.42977 -+		}
772.42978 -+	}
772.42979 -+
772.42980 -+	XFree(cur);
772.42981 -+}
772.42982 -+
772.42983 - static int done;
772.42984 - 
772.42985 - static void signal_handler(int sig)
772.42986 -@@ -3182,6 +3392,7 @@ int main(int argc, char **argv)
772.42987 - 	uint64_t count;
772.42988 - 	int daemonize = 1, bumblebee = 0, siblings = 0, singleton = 1;
772.42989 - 	int i, ret, open, fail;
772.42990 -+	int idle;
772.42991 - 
772.42992 - 	signal(SIGPIPE, SIG_IGN);
772.42993 - 
772.42994 -@@ -3228,6 +3439,7 @@ int main(int argc, char **argv)
772.42995 - 		return -ret;
772.42996 - 
772.42997 - 	XSetErrorHandler(_check_error_handler);
772.42998 -+	XSetIOErrorHandler(_io_error_handler);
772.42999 - 
772.43000 - 	ret = add_fd(&ctx, display_open(&ctx, src_name));
772.43001 - 	if (ret) {
772.43002 -@@ -3237,6 +3449,13 @@ int main(int argc, char **argv)
772.43003 - 		goto out;
772.43004 - 	}
772.43005 - 
772.43006 -+	ret = check_virtual(ctx.display);
772.43007 -+	if (ret) {
772.43008 -+		fprintf(stderr, "No VIRTUAL outputs on \"%s\".\n",
772.43009 -+			DisplayString(ctx.display->dpy));
772.43010 -+		goto out;
772.43011 -+	}
772.43012 -+
772.43013 - 	if (singleton) {
772.43014 - 		XSelectInput(ctx.display->dpy, ctx.display->root, PropertyChangeMask);
772.43015 - 		if (first_display_has_singleton(&ctx)) {
772.43016 -@@ -3291,6 +3510,11 @@ int main(int argc, char **argv)
772.43017 - 	if (ret)
772.43018 - 		goto out;
772.43019 - 
772.43020 -+	if (ctx.display->saver_active)
772.43021 -+		XScreenSaverSelectInput(ctx.display->dpy,
772.43022 -+					ctx.display->root,
772.43023 -+					ScreenSaverNotifyMask);
772.43024 -+
772.43025 - 	if ((ctx.display->rr_event | ctx.display->rr_error) == 0) {
772.43026 - 		fprintf(stderr, "RandR extension not supported by %s\n", DisplayString(ctx.display->dpy));
772.43027 - 		ret = EINVAL;
772.43028 -@@ -3348,25 +3572,60 @@ int main(int argc, char **argv)
772.43029 - 	signal(SIGTERM, signal_handler);
772.43030 - 
772.43031 - 	ctx.command_continuation = 0;
772.43032 -+	update_cursor_image(&ctx);
772.43033 -+
772.43034 -+	idle = 0;
772.43035 - 	while (!done) {
772.43036 - 		XEvent e;
772.43037 - 		int reconfigure = 0;
772.43038 - 		int rr_update = 0;
772.43039 - 
772.43040 --		DBG(POLL, ("polling - enable timer? %d, nfd=%d, ndisplay=%d\n", ctx.timer_active, ctx.nfd, ctx.ndisplay));
772.43041 --		ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
772.43042 --		if (ret <= 0)
772.43043 --			break;
772.43044 -+		if (idle) {
772.43045 -+			DBG(POLL, ("polling - enable timer? %d, nfd=%d, ndisplay=%d\n", ctx.timer_active, ctx.nfd, ctx.ndisplay));
772.43046 -+			ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
772.43047 -+			if (ret <= 0)
772.43048 -+				break;
772.43049 -+
772.43050 -+			DBG(POLL, ("poll reports %d fd awake\n", ret));
772.43051 -+		}
772.43052 -+		idle = 1;
772.43053 - 
772.43054 - 		/* pfd[0] is the timer, pfd[1] is the local display, pfd[2] is the mouse, pfd[3+] are the remotes */
772.43055 - 
772.43056 --		DBG(POLL, ("poll reports %d fd awake\n", ret));
772.43057 - 		if (ctx.pfd[1].revents || XPending(ctx.display[0].dpy)) {
772.43058 - 			DBG(POLL,("%s woken up\n", DisplayString(ctx.display[0].dpy)));
772.43059 -+			ctx.pfd[1].revents = 0;
772.43060 -+			idle = 0;
772.43061 -+
772.43062 - 			do {
772.43063 - 				XNextEvent(ctx.display->dpy, &e);
772.43064 - 
772.43065 --				if (e.type == ctx.display->damage_event + XDamageNotify ) {
772.43066 -+				DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[0].dpy), e.type));
772.43067 -+
772.43068 -+				if (e.type == ctx.display->saver_event + ScreenSaverNotify) {
772.43069 -+					const XScreenSaverNotifyEvent *se = (const XScreenSaverNotifyEvent *)&e;
772.43070 -+					DBG(SCREEN,
772.43071 -+					    ("%s screen saver: state=%d, kind=%d, forced=%d\n",
772.43072 -+					     DisplayString(ctx.display->dpy),
772.43073 -+					     se->state, se->kind, se->forced));
772.43074 -+					for (i = 1; i < ctx.ndisplay; i++) {
772.43075 -+						struct display *display = &ctx.display[i];
772.43076 -+
772.43077 -+						if (!display->active)
772.43078 -+							continue;
772.43079 -+
772.43080 -+						DBG(SCREEN,
772.43081 -+						    ("%s %s screen saver\n",
772.43082 -+						     DisplayString(display->dpy),
772.43083 -+						     se->state == ScreenSaverOn ? "activating" : "resetting\n"));
772.43084 -+
772.43085 -+						if (se->state == ScreenSaverOn)
772.43086 -+							XActivateScreenSaver(display->dpy);
772.43087 -+						else
772.43088 -+							XResetScreenSaver(display->dpy);
772.43089 -+						XFlush(display->dpy);
772.43090 -+					}
772.43091 -+				} else if (e.type == ctx.display->damage_event + XDamageNotify) {
772.43092 - 					const XDamageNotifyEvent *de = (const XDamageNotifyEvent *)&e;
772.43093 - 					struct clone *clone;
772.43094 - 
772.43095 -@@ -3380,19 +3639,7 @@ int main(int argc, char **argv)
772.43096 - 					if (ctx.active)
772.43097 - 						context_enable_timer(&ctx);
772.43098 - 				} else if (e.type == ctx.display->xfixes_event + XFixesCursorNotify) {
772.43099 --					XFixesCursorImage *cur;
772.43100 --
772.43101 --					DBG(CURSOR, ("%s cursor changed\n",
772.43102 --					     DisplayString(ctx.display->dpy)));
772.43103 --
772.43104 --					cur = XFixesGetCursorImage(ctx.display->dpy);
772.43105 --					if (cur == NULL)
772.43106 --						continue;
772.43107 --
772.43108 --					for (i = 1; i < ctx.ndisplay; i++)
772.43109 --						display_load_visible_cursor(&ctx.display[i], cur);
772.43110 --
772.43111 --					XFree(cur);
772.43112 -+					update_cursor_image(&ctx);
772.43113 - 				} else if (e.type == ctx.display->rr_event + RRScreenChangeNotify) {
772.43114 - 					DBG(XRR, ("%s screen changed (reconfigure pending? %d)\n",
772.43115 - 					     DisplayString(ctx.display->dpy), reconfigure));
772.43116 -@@ -3426,13 +3673,41 @@ int main(int argc, char **argv)
772.43117 - 			if (ctx.pfd[i+2].revents == 0 && !XPending(ctx.display[i].dpy))
772.43118 - 				continue;
772.43119 - 
772.43120 -+			ctx.pfd[i+2].revents = 0;
772.43121 -+			idle = 0;
772.43122 -+
772.43123 - 			DBG(POLL, ("%s woken up\n", DisplayString(ctx.display[i].dpy)));
772.43124 - 			do {
772.43125 - 				XNextEvent(ctx.display[i].dpy, &e);
772.43126 - 
772.43127 - 				DBG(POLL, ("%s received event %d\n", DisplayString(ctx.display[i].dpy), e.type));
772.43128 --				if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) {
772.43129 --					XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
772.43130 -+				if (e.type == Expose) {
772.43131 -+					const XExposeEvent *xe = (XExposeEvent *)&e;
772.43132 -+					struct clone *clone;
772.43133 -+					int damaged = 0;
772.43134 -+
772.43135 -+					DBG(DAMAGE, ("%s exposed: (%d, %d)x(%d, %d)\n",
772.43136 -+					     DisplayString(ctx.display[i].dpy),
772.43137 -+					     xe->x, xe->y, xe->width, xe->height));
772.43138 -+
772.43139 -+					for (clone = ctx.active; clone; clone = clone->active) {
772.43140 -+						XRectangle r;
772.43141 -+
772.43142 -+						if (clone->dst.display != &ctx.display[i])
772.43143 -+							continue;
772.43144 -+
772.43145 -+						r.x = clone->src.x + xe->x;
772.43146 -+						r.y = clone->src.y + xe->y;
772.43147 -+						r.width  = xe->width;
772.43148 -+						r.height = xe->height;
772.43149 -+						clone_damage(clone, &r);
772.43150 -+						damaged++;
772.43151 -+					}
772.43152 -+
772.43153 -+					if (damaged)
772.43154 -+						context_enable_timer(&ctx);
772.43155 -+				} else if (ctx.display[i].rr_active && e.type == ctx.display[i].rr_event + RRNotify) {
772.43156 -+					const XRRNotifyEvent *re = (XRRNotifyEvent *)&e;
772.43157 - 
772.43158 - 					DBG(XRR, ("%s received RRNotify, type %d\n", DisplayString(ctx.display[i].dpy), re->subtype));
772.43159 - 					if (re->subtype == RRNotify_OutputChange) {
772.43160 -@@ -3480,6 +3755,7 @@ int main(int argc, char **argv)
772.43161 - 
772.43162 - 			DBG(TIMER, ("%s timer still active? %d\n", DisplayString(ctx.display->dpy), ret != 0));
772.43163 - 			ctx.timer_active = ret != 0;
772.43164 -+			idle = 0;
772.43165 - 		}
772.43166 - 	}
772.43167 - 
   773.1 --- a/xorg-xf86-video-intel/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   773.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   773.3 @@ -1,3 +0,0 @@
   773.4 -# from Alpine Linux: patch git20170325
   773.5 -# https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-intel
   773.6 -git.patch
   774.1 --- a/xorg-xf86-video-mach64/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   774.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   774.3 @@ -1,1 +0,0 @@
   774.4 -../xorg/.icon.png
   774.5 \ No newline at end of file
   775.1 --- a/xorg-xf86-video-mach64/receipt	Thu Dec 13 00:46:54 2018 +0200
   775.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   775.3 @@ -1,28 +0,0 @@
   775.4 -# SliTaz package receipt v2.
   775.5 -
   775.6 -PACKAGE="xorg-xf86-video-mach64"
   775.7 -VERSION="6.9.6"
   775.8 -CATEGORY="x-window"
   775.9 -SHORT_DESC="Xorg driver for ATI MACH 64 cards"
  775.10 -MAINTAINER="pascal.bellard@slitaz.org"
  775.11 -LICENSE="MIT"
  775.12 -WEB_SITE="https://www.x.org/wiki/"
  775.13 -REPOLOGY="xdrv:mach64"
  775.14 -
  775.15 -TARBALL="xf86-video-mach64-$VERSION.tar.bz2"
  775.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  775.17 -
  775.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev"
  775.19 -
  775.20 -compile_rules() {
  775.21 -	./configure $CONFIGURE_ARGS &&
  775.22 -	fix libtool &&
  775.23 -	make &&
  775.24 -	make install
  775.25 -}
  775.26 -
  775.27 -genpkg_rules() {
  775.28 -	copy @std
  775.29 -	DEPENDS="xorg-server"
  775.30 -	TAGS="xorg display"
  775.31 -}
   776.1 --- a/xorg-xf86-video-neomagic/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   776.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   776.3 @@ -1,1 +0,0 @@
   776.4 -../xorg/.icon.png
   776.5 \ No newline at end of file
   777.1 --- a/xorg-xf86-video-neomagic/receipt	Thu Dec 13 00:46:54 2018 +0200
   777.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   777.3 @@ -1,29 +0,0 @@
   777.4 -# SliTaz package receipt v2.
   777.5 -
   777.6 -PACKAGE="xorg-xf86-video-neomagic"
   777.7 -VERSION="1.2.9"
   777.8 -CATEGORY="x-window"
   777.9 -SHORT_DESC="Xorg driver for the Neomagic graphics chipsets found in many \
  777.10 -laptop computers"
  777.11 -MAINTAINER="devel@slitaz.org"
  777.12 -LICENSE="MIT"
  777.13 -WEB_SITE="https://www.x.org/wiki/neomagic/"
  777.14 -REPOLOGY="xdrv:neomagic"
  777.15 -
  777.16 -TARBALL="xf86-video-neomagic-$VERSION.tar.bz2"
  777.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  777.18 -
  777.19 -BUILD_DEPENDS="xorg-server-dev xorg-xorgproto"
  777.20 -
  777.21 -compile_rules() {
  777.22 -	./configure $CONFIGURE_ARGS &&
  777.23 -	fix libtool &&
  777.24 -	make &&
  777.25 -	make install
  777.26 -}
  777.27 -
  777.28 -genpkg_rules() {
  777.29 -	copy @std
  777.30 -	DEPENDS="xorg-server"
  777.31 -	TAGS="xorg display"
  777.32 -}
   778.1 --- a/xorg-xf86-video-nouveau/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   778.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   778.3 @@ -1,1 +0,0 @@
   778.4 -../xorg/.icon.png
   778.5 \ No newline at end of file
   779.1 --- a/xorg-xf86-video-nouveau/receipt	Thu Dec 13 00:46:54 2018 +0200
   779.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   779.3 @@ -1,29 +0,0 @@
   779.4 -# SliTaz package receipt v2.
   779.5 -
   779.6 -PACKAGE="xorg-xf86-video-nouveau"
   779.7 -VERSION="1.0.15"
   779.8 -CATEGORY="x-window"
   779.9 -SHORT_DESC="Xorg driver for NVIDIA video cards"
  779.10 -MAINTAINER="devl547@gmail.com"
  779.11 -LICENSE="GPL"
  779.12 -WEB_SITE="https://nouveau.freedesktop.org/wiki/"
  779.13 -REPOLOGY="xdrv:nouveau"
  779.14 -
  779.15 -TARBALL="xf86-video-nouveau-$VERSION.tar.bz2"
  779.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  779.17 -
  779.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-libXrandr-dev \
  779.19 -xorg-libXrender-dev xorg-libXv-dev eudev-dev"
  779.20 -
  779.21 -compile_rules() {
  779.22 -	./configure $CONFIGURE_ARGS &&
  779.23 -	fix libtool &&
  779.24 -	make &&
  779.25 -	make install
  779.26 -}
  779.27 -
  779.28 -genpkg_rules() {
  779.29 -	copy @std
  779.30 -	DEPENDS="eudev libdrm libdrm-nouveau"
  779.31 -	TAGS="xorg display"
  779.32 -}
   780.1 --- a/xorg-xf86-video-nv/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   780.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   780.3 @@ -1,1 +0,0 @@
   780.4 -../xorg/.icon.png
   780.5 \ No newline at end of file
   781.1 --- a/xorg-xf86-video-nv/receipt	Thu Dec 13 00:46:54 2018 +0200
   781.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   781.3 @@ -1,28 +0,0 @@
   781.4 -# SliTaz package receipt v2.
   781.5 -
   781.6 -PACKAGE="xorg-xf86-video-nv"
   781.7 -VERSION="2.1.21"
   781.8 -CATEGORY="x-window"
   781.9 -SHORT_DESC="Xorg driver for NVIDIA video cards"
  781.10 -MAINTAINER="devel@slitaz.org"
  781.11 -LICENSE="MIT"
  781.12 -WEB_SITE="https://www.x.org/wiki/"
  781.13 -REPOLOGY="xdrv:nv"
  781.14 -
  781.15 -TARBALL="xf86-video-nv-$VERSION.tar.bz2"
  781.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  781.17 -
  781.18 -BUILD_DEPENDS="xorg-server-dev"
  781.19 -
  781.20 -compile_rules() {
  781.21 -	./configure $CONFIGURE_ARGS &&
  781.22 -	fix libtool &&
  781.23 -	make &&
  781.24 -	make install
  781.25 -}
  781.26 -
  781.27 -genpkg_rules() {
  781.28 -	copy @std
  781.29 -	DEPENDS="xorg-server"
  781.30 -	TAGS="xorg display"
  781.31 -}
   782.1 --- a/xorg-xf86-video-omap/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   782.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   782.3 @@ -1,1 +0,0 @@
   782.4 -../xorg/.icon.png
   782.5 \ No newline at end of file
   783.1 --- a/xorg-xf86-video-omap/receipt	Thu Dec 13 00:46:54 2018 +0200
   783.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   783.3 @@ -1,28 +0,0 @@
   783.4 -# SliTaz package receipt v2.
   783.5 -
   783.6 -PACKAGE="xorg-xf86-video-omap"
   783.7 -VERSION="0.4.5"
   783.8 -CATEGORY="x-window"
   783.9 -SHORT_DESC="Xorg driver for OMAP SoCs"
  783.10 -MAINTAINER="al.bobylev@gmail.com"
  783.11 -LICENSE="MIT"
  783.12 -WEB_SITE="https://www.x.org/wiki/"
  783.13 -REPOLOGY="xdrv:omap"
  783.14 -
  783.15 -TARBALL="xf86-video-omap-$VERSION.tar.bz2"
  783.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  783.17 -
  783.18 -BUILD_DEPENDS="xorg-server-dev eudev-dev"
  783.19 -
  783.20 -compile_rules() {
  783.21 -	./configure $CONFIGURE_ARGS &&
  783.22 -	fix libtool &&
  783.23 -	make &&
  783.24 -	make install
  783.25 -}
  783.26 -
  783.27 -genpkg_rules() {
  783.28 -	copy @std
  783.29 -	DEPENDS="xorg-server libdrm libdrm-omap"
  783.30 -	TAGS="xorg display"
  783.31 -}
   784.1 --- a/xorg-xf86-video-openchrome/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   784.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   784.3 @@ -1,1 +0,0 @@
   784.4 -../xorg/.icon.png
   784.5 \ No newline at end of file
   785.1 --- a/xorg-xf86-video-openchrome/receipt	Thu Dec 13 00:46:54 2018 +0200
   785.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   785.3 @@ -1,30 +0,0 @@
   785.4 -# SliTaz package receipt v2.
   785.5 -
   785.6 -PACKAGE="xorg-xf86-video-openchrome"
   785.7 -VERSION="0.6.0"
   785.8 -CATEGORY="x-window"
   785.9 -SHORT_DESC="Xorg driver for VIA chipsets that have an integrated Unichrome \
  785.10 -graphics engine"
  785.11 -MAINTAINER="al.bobylev@gmail.com"
  785.12 -LICENSE="MIT"
  785.13 -WEB_SITE="https://www.x.org/wiki/"
  785.14 -REPOLOGY="xdrv:openchrome"
  785.15 -
  785.16 -TARBALL="xf86-video-openchrome-$VERSION.tar.bz2"
  785.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  785.18 -
  785.19 -BUILD_DEPENDS="xorg-server-dev xorg-libXvMC-dev"
  785.20 -
  785.21 -compile_rules() {
  785.22 -	./configure $CONFIGURE_ARGS &&
  785.23 -	fix libtool &&
  785.24 -	make &&
  785.25 -	make install
  785.26 -}
  785.27 -
  785.28 -genpkg_rules() {
  785.29 -	copy @std
  785.30 -	DEPENDS="xorg-server eudev libdrm xorg-libX11 xorg-libXext \
  785.31 -	xorg-libXv xorg-libXvMC"
  785.32 -	TAGS="xorg display"
  785.33 -}
   786.1 --- a/xorg-xf86-video-qxl/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   786.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   786.3 @@ -1,1 +0,0 @@
   786.4 -../xorg/.icon.png
   786.5 \ No newline at end of file
   787.1 --- a/xorg-xf86-video-qxl/receipt	Thu Dec 13 00:46:54 2018 +0200
   787.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   787.3 @@ -1,29 +0,0 @@
   787.4 -# SliTaz package receipt v2.
   787.5 -
   787.6 -PACKAGE="xorg-xf86-video-qxl"
   787.7 -VERSION="0.1.5"
   787.8 -CATEGORY="x-window"
   787.9 -SHORT_DESC="Xorg driver for QXL virtual GPU"
  787.10 -MAINTAINER="al.bobylev@gmail.com"
  787.11 -LICENSE="MIT"
  787.12 -WEB_SITE="https://www.x.org/wiki/"
  787.13 -REPOLOGY="xdrv:qxl"
  787.14 -
  787.15 -TARBALL="xf86-video-qxl-$VERSION.tar.bz2"
  787.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  787.17 -
  787.18 -BUILD_DEPENDS="xorg-server-dev xorg-libXfont2-dev xorg-xorgproto \
  787.19 -spice-protocol"
  787.20 -
  787.21 -compile_rules() {
  787.22 -	./configure $CONFIGURE_ARGS &&
  787.23 -	fix libtool &&
  787.24 -	make &&
  787.25 -	make install
  787.26 -}
  787.27 -
  787.28 -genpkg_rules() {
  787.29 -	copy @std
  787.30 -	DEPENDS="xorg-server eudev"
  787.31 -	TAGS="xorg display"
  787.32 -}
   788.1 --- a/xorg-xf86-video-r128/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   788.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   788.3 @@ -1,1 +0,0 @@
   788.4 -../xorg/.icon.png
   788.5 \ No newline at end of file
   789.1 --- a/xorg-xf86-video-r128/receipt	Thu Dec 13 00:46:54 2018 +0200
   789.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   789.3 @@ -1,28 +0,0 @@
   789.4 -# SliTaz package receipt v2.
   789.5 -
   789.6 -PACKAGE="xorg-xf86-video-r128"
   789.7 -VERSION="6.11.0"
   789.8 -CATEGORY="x-window"
   789.9 -SHORT_DESC="Xorg driver for ATI Rage 128 based video cards"
  789.10 -MAINTAINER="al.bobylev@gmail.com"
  789.11 -LICENSE="MIT"
  789.12 -WEB_SITE="https://www.x.org/wiki/"
  789.13 -REPOLOGY="xdrv:r128"
  789.14 -
  789.15 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  789.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  789.17 -
  789.18 -BUILD_DEPENDS="xorg-server-dev"
  789.19 -
  789.20 -compile_rules() {
  789.21 -	./configure $CONFIGURE_ARGS &&
  789.22 -	fix libtool &&
  789.23 -	make &&
  789.24 -	make install
  789.25 -}
  789.26 -
  789.27 -genpkg_rules() {
  789.28 -	copy @std
  789.29 -	DEPENDS="xorg-server"
  789.30 -	TAGS="xorg display"
  789.31 -}
   790.1 --- a/xorg-xf86-video-rendition/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   790.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   790.3 @@ -1,1 +0,0 @@
   790.4 -../xorg/.icon.png
   790.5 \ No newline at end of file
   791.1 --- a/xorg-xf86-video-rendition/receipt	Thu Dec 13 00:46:54 2018 +0200
   791.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   791.3 @@ -1,28 +0,0 @@
   791.4 -# SliTaz package receipt v2.
   791.5 -
   791.6 -PACKAGE="xorg-xf86-video-rendition"
   791.7 -VERSION="4.2.7"
   791.8 -CATEGORY="x-window"
   791.9 -SHORT_DESC="Xorg driver for Rendition/Micron based video cards"
  791.10 -MAINTAINER="al.bobylev@gmail.com"
  791.11 -LICENSE="MIT"
  791.12 -WEB_SITE="https://www.x.org/wiki/"
  791.13 -REPOLOGY="xdrv:rendition"
  791.14 -
  791.15 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  791.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  791.17 -
  791.18 -BUILD_DEPENDS="xorg-server-dev"
  791.19 -
  791.20 -compile_rules() {
  791.21 -	./configure $CONFIGURE_ARGS &&
  791.22 -	fix libtool &&
  791.23 -	make &&
  791.24 -	make install
  791.25 -}
  791.26 -
  791.27 -genpkg_rules() {
  791.28 -	copy @std
  791.29 -	DEPENDS="xorg-server"
  791.30 -	TAGS="xorg display"
  791.31 -}
   792.1 --- a/xorg-xf86-video-s3virge/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   792.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   792.3 @@ -1,1 +0,0 @@
   792.4 -../xorg/.icon.png
   792.5 \ No newline at end of file
   793.1 --- a/xorg-xf86-video-s3virge/receipt	Thu Dec 13 00:46:54 2018 +0200
   793.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   793.3 @@ -1,28 +0,0 @@
   793.4 -# SliTaz package receipt v2.
   793.5 -
   793.6 -PACKAGE="xorg-xf86-video-s3virge"
   793.7 -VERSION="1.10.7"
   793.8 -CATEGORY="x-window"
   793.9 -SHORT_DESC="Xorg driver for Trident S3 virge cards"
  793.10 -MAINTAINER="pascal.bellard@slitaz.org"
  793.11 -LICENSE="MIT"
  793.12 -WEB_SITE="https://www.x.org/wiki/s3virge/"
  793.13 -REPOLOGY="xdrv:s3virge"
  793.14 -
  793.15 -TARBALL="xf86-video-s3virge-$VERSION.tar.bz2"
  793.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  793.17 -
  793.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev"
  793.19 -
  793.20 -compile_rules() {
  793.21 -	./configure $CONFIGURE_ARGS &&
  793.22 -	fix libtool &&
  793.23 -	make &&
  793.24 -	make install
  793.25 -}
  793.26 -
  793.27 -genpkg_rules() {
  793.28 -	copy @std
  793.29 -	DEPENDS="xorg-server"
  793.30 -	TAGS="xorg display"
  793.31 -}
   794.1 --- a/xorg-xf86-video-s3virge/stuff/patches/check-max-value.patch	Thu Dec 13 00:46:54 2018 +0200
   794.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   794.3 @@ -1,24 +0,0 @@
   794.4 ---- a/src/s3v_driver.c
   794.5 -+++ b/src/s3v_driver.c
   794.6 -@@ -1212,8 +1212,6 @@
   794.7 -     /* todo -  The virge limit is 2048 vertical & horizontal */
   794.8 -     /* pixels, not clock register settings. */
   794.9 - 			 	/* true for all ViRGE? */
  794.10 --  pScrn->maxHValue = 2048;
  794.11 --  pScrn->maxVValue = 2048;
  794.12 - 
  794.13 -     				/* Lower depths default to config file */
  794.14 -   pScrn->virtualX = pScrn->display->virtualX;
  794.15 -@@ -2566,6 +2564,12 @@
  794.16 -     if ((pScrn->bitsPerPixel + 7)/8 * mode->HDisplay > 4095)
  794.17 - 	return MODE_VIRTUAL_X;
  794.18 - 
  794.19 -+    if (mode->HTotal > 2048)
  794.20 -+        return MODE_BAD_HVALUE;
  794.21 -+
  794.22 -+    if (mode->VTotal > 2048)
  794.23 -+        return MODE_BAD_VVALUE;
  794.24 -+        
  794.25 -     return MODE_OK;
  794.26 - }
  794.27 - 
   795.1 --- a/xorg-xf86-video-s3virge/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   795.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   795.3 @@ -1,2 +0,0 @@
   795.4 -# From Alpine Linux: https://git.alpinelinux.org/cgit/aports/tree/main/xf86-video-s3virge
   795.5 -check-max-value.patch
   796.1 --- a/xorg-xf86-video-savage/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   796.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   796.3 @@ -1,1 +0,0 @@
   796.4 -../xorg/.icon.png
   796.5 \ No newline at end of file
   797.1 --- a/xorg-xf86-video-savage/receipt	Thu Dec 13 00:46:54 2018 +0200
   797.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   797.3 @@ -1,28 +0,0 @@
   797.4 -# SliTaz package receipt v2.
   797.5 -
   797.6 -PACKAGE="xorg-xf86-video-savage"
   797.7 -VERSION="2.3.9"
   797.8 -CATEGORY="x-window"
   797.9 -SHORT_DESC="Xorg driver for the S3 Savage family video accelerator chips"
  797.10 -MAINTAINER="pascal.bellard@slitaz.org"
  797.11 -LICENSE="MIT"
  797.12 -WEB_SITE="https://www.x.org/wiki/savage/"
  797.13 -REPOLOGY="xdrv:savage"
  797.14 -
  797.15 -TARBALL="xf86-video-savage-$VERSION.tar.bz2"
  797.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  797.17 -
  797.18 -BUILD_DEPENDS="xorg-server-dev"
  797.19 -
  797.20 -compile_rules() {
  797.21 -	./configure $CONFIGURE_ARGS &&
  797.22 -	fix libtool &&
  797.23 -	make &&
  797.24 -	make install
  797.25 -}
  797.26 -
  797.27 -genpkg_rules() {
  797.28 -	copy @std
  797.29 -	DEPENDS="xorg-server"
  797.30 -	TAGS="xorg display"
  797.31 -}
   798.1 --- a/xorg-xf86-video-siliconmotion/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   798.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   798.3 @@ -1,1 +0,0 @@
   798.4 -../xorg/.icon.png
   798.5 \ No newline at end of file
   799.1 --- a/xorg-xf86-video-siliconmotion/receipt	Thu Dec 13 00:46:54 2018 +0200
   799.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   799.3 @@ -1,28 +0,0 @@
   799.4 -# SliTaz package receipt v2.
   799.5 -
   799.6 -PACKAGE="xorg-xf86-video-siliconmotion"
   799.7 -VERSION="1.7.9"
   799.8 -CATEGORY="x-window"
   799.9 -SHORT_DESC="Xorg driver for Silicon Motion based video cards"
  799.10 -MAINTAINER="al.bobylev@gmail.com"
  799.11 -LICENSE="MIT"
  799.12 -WEB_SITE="https://www.x.org/wiki/"
  799.13 -REPOLOGY="xdrv:siliconmotion"
  799.14 -
  799.15 -TARBALL="xf86-video-siliconmotion-$VERSION.tar.bz2"
  799.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  799.17 -
  799.18 -BUILD_DEPENDS="xorg-server-dev"
  799.19 -
  799.20 -compile_rules() {
  799.21 -	./configure $CONFIGURE_ARGS &&
  799.22 -	fix libtool &&
  799.23 -	make &&
  799.24 -	make install
  799.25 -}
  799.26 -
  799.27 -genpkg_rules() {
  799.28 -	copy @std
  799.29 -	DEPENDS="xorg-server"
  799.30 -	TAGS="xorg display"
  799.31 -}
   800.1 --- a/xorg-xf86-video-sis/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   800.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   800.3 @@ -1,1 +0,0 @@
   800.4 -../xorg/.icon.png
   800.5 \ No newline at end of file
   801.1 --- a/xorg-xf86-video-sis/receipt	Thu Dec 13 00:46:54 2018 +0200
   801.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   801.3 @@ -1,29 +0,0 @@
   801.4 -# SliTaz package receipt v2.
   801.5 -
   801.6 -PACKAGE="xorg-xf86-video-sis"
   801.7 -VERSION="0.10.9"
   801.8 -CATEGORY="x-window"
   801.9 -SHORT_DESC="Xorg driver for SiS (Silicon Integrated Systems) and XGI video \
  801.10 -chips"
  801.11 -MAINTAINER="pascal.bellard@slitaz.org"
  801.12 -LICENSE="MIT"
  801.13 -WEB_SITE="https://www.x.org/wiki/sis/"
  801.14 -REPOLOGY="xdrv:sis"
  801.15 -
  801.16 -TARBALL="xf86-video-sis-$VERSION.tar.bz2"
  801.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  801.18 -
  801.19 -BUILD_DEPENDS="xorg-server-dev xorg-xorgproto"
  801.20 -
  801.21 -compile_rules() {
  801.22 -	./configure $CONFIGURE_ARGS &&
  801.23 -	fix libtool &&
  801.24 -	make &&
  801.25 -	make install
  801.26 -}
  801.27 -
  801.28 -genpkg_rules() {
  801.29 -	copy @std
  801.30 -	DEPENDS="xorg-server"
  801.31 -	TAGS="xorg display"
  801.32 -}
   802.1 --- a/xorg-xf86-video-sisusb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   802.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   802.3 @@ -1,1 +0,0 @@
   802.4 -../xorg/.icon.png
   802.5 \ No newline at end of file
   803.1 --- a/xorg-xf86-video-sisusb/receipt	Thu Dec 13 00:46:54 2018 +0200
   803.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   803.3 @@ -1,29 +0,0 @@
   803.4 -# SliTaz package receipt v2.
   803.5 -
   803.6 -PACKAGE="xorg-xf86-video-sisusb"
   803.7 -VERSION="0.9.7"
   803.8 -CATEGORY="x-window"
   803.9 -SHORT_DESC="Xorg driver for SiS (Silicon Integrated Systems) video chips that \
  803.10 -are connected via a Net2280-based USB dongle"
  803.11 -MAINTAINER="al.bobylev@gmail.com"
  803.12 -LICENSE="MIT"
  803.13 -WEB_SITE="https://www.x.org/wiki/"
  803.14 -REPOLOGY="xdrv:sisusb"
  803.15 -
  803.16 -TARBALL="xf86-video-sisusb-$VERSION.tar.bz2"
  803.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  803.18 -
  803.19 -BUILD_DEPENDS="xorg-server-dev"
  803.20 -
  803.21 -compile_rules() {
  803.22 -	./configure $CONFIGURE_ARGS &&
  803.23 -	fix libtool &&
  803.24 -	make &&
  803.25 -	make install
  803.26 -}
  803.27 -
  803.28 -genpkg_rules() {
  803.29 -	copy @std
  803.30 -	DEPENDS="xorg-server"
  803.31 -	TAGS="xorg display"
  803.32 -}
   804.1 --- a/xorg-xf86-video-suncg14/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   804.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   804.3 @@ -1,1 +0,0 @@
   804.4 -../xorg/.icon.png
   804.5 \ No newline at end of file
   805.1 --- a/xorg-xf86-video-suncg14/receipt	Thu Dec 13 00:46:54 2018 +0200
   805.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   805.3 @@ -1,28 +0,0 @@
   805.4 -# SliTaz package receipt v2.
   805.5 -
   805.6 -PACKAGE="xorg-xf86-video-suncg14"
   805.7 -VERSION="1.1.2"
   805.8 -CATEGORY="x-window"
   805.9 -SHORT_DESC="Xorg driver for Sun CG14 video cards"
  805.10 -MAINTAINER="al.bobylev@gmail.com"
  805.11 -LICENSE="MIT"
  805.12 -WEB_SITE="https://www.x.org/wiki/"
  805.13 -REPOLOGY="xdrv:suncg14"
  805.14 -
  805.15 -TARBALL="xf86-video-suncg14-$VERSION.tar.bz2"
  805.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  805.17 -
  805.18 -BUILD_DEPENDS="xorg-server-dev"
  805.19 -
  805.20 -compile_rules() {
  805.21 -	./configure $CONFIGURE_ARGS &&
  805.22 -	fix libtool &&
  805.23 -	make &&
  805.24 -	make install
  805.25 -}
  805.26 -
  805.27 -genpkg_rules() {
  805.28 -	copy @std
  805.29 -	DEPENDS="xorg-server"
  805.30 -	TAGS="xorg display"
  805.31 -}
   806.1 --- a/xorg-xf86-video-suncg3/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   806.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   806.3 @@ -1,1 +0,0 @@
   806.4 -../xorg/.icon.png
   806.5 \ No newline at end of file
   807.1 --- a/xorg-xf86-video-suncg3/receipt	Thu Dec 13 00:46:54 2018 +0200
   807.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   807.3 @@ -1,28 +0,0 @@
   807.4 -# SliTaz package receipt v2.
   807.5 -
   807.6 -PACKAGE="xorg-xf86-video-suncg3"
   807.7 -VERSION="1.1.2"
   807.8 -CATEGORY="x-window"
   807.9 -SHORT_DESC="Xorg driver for Sun CG3 video cards"
  807.10 -MAINTAINER="al.bobylev@gmail.com"
  807.11 -LICENSE="MIT"
  807.12 -WEB_SITE="https://www.x.org/wiki/"
  807.13 -REPOLOGY="xdrv:suncg3"
  807.14 -
  807.15 -TARBALL="xf86-video-suncg3-$VERSION.tar.bz2"
  807.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  807.17 -
  807.18 -BUILD_DEPENDS="xorg-server-dev"
  807.19 -
  807.20 -compile_rules() {
  807.21 -	./configure $CONFIGURE_ARGS &&
  807.22 -	fix libtool &&
  807.23 -	make &&
  807.24 -	make install
  807.25 -}
  807.26 -
  807.27 -genpkg_rules() {
  807.28 -	copy @std
  807.29 -	DEPENDS="xorg-server"
  807.30 -	TAGS="xorg display"
  807.31 -}
   808.1 --- a/xorg-xf86-video-suncg6/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   808.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   808.3 @@ -1,1 +0,0 @@
   808.4 -../xorg/.icon.png
   808.5 \ No newline at end of file
   809.1 --- a/xorg-xf86-video-suncg6/receipt	Thu Dec 13 00:46:54 2018 +0200
   809.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   809.3 @@ -1,29 +0,0 @@
   809.4 -# SliTaz package receipt v2.
   809.5 -
   809.6 -PACKAGE="xorg-xf86-video-suncg6"
   809.7 -VERSION="1.1.2"
   809.8 -CATEGORY="x-window"
   809.9 -SHORT_DESC="Xorg driver for Sun GX and Turbo GX (also known as cgsix) video \
  809.10 -cards"
  809.11 -MAINTAINER="al.bobylev@gmail.com"
  809.12 -LICENSE="MIT"
  809.13 -WEB_SITE="https://www.x.org/wiki/"
  809.14 -REPOLOGY="xdrv:suncg6"
  809.15 -
  809.16 -TARBALL="xf86-video-suncg6-$VERSION.tar.bz2"
  809.17 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  809.18 -
  809.19 -BUILD_DEPENDS="xorg-server-dev"
  809.20 -
  809.21 -compile_rules() {
  809.22 -	./configure $CONFIGURE_ARGS &&
  809.23 -	fix libtool &&
  809.24 -	make &&
  809.25 -	make install
  809.26 -}
  809.27 -
  809.28 -genpkg_rules() {
  809.29 -	copy @std
  809.30 -	DEPENDS="xorg-server"
  809.31 -	TAGS="xorg display"
  809.32 -}
   810.1 --- a/xorg-xf86-video-sunffb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   810.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   810.3 @@ -1,1 +0,0 @@
   810.4 -../xorg/.icon.png
   810.5 \ No newline at end of file
   811.1 --- a/xorg-xf86-video-sunffb/receipt	Thu Dec 13 00:46:54 2018 +0200
   811.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   811.3 @@ -1,28 +0,0 @@
   811.4 -# SliTaz package receipt v2.
   811.5 -
   811.6 -PACKAGE="xorg-xf86-video-sunffb"
   811.7 -VERSION="1.2.2"
   811.8 -CATEGORY="x-window"
   811.9 -SHORT_DESC="Xorg driver for Sun Creator, Creator 3D and Elite 3D video cards"
  811.10 -MAINTAINER="al.bobylev@gmail.com"
  811.11 -LICENSE="MIT"
  811.12 -WEB_SITE="https://www.x.org/wiki/"
  811.13 -REPOLOGY="xdrv:sunffb"
  811.14 -
  811.15 -TARBALL="xf86-video-sunffb-$VERSION.tar.bz2"
  811.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  811.17 -
  811.18 -BUILD_DEPENDS="xorg-server-dev"
  811.19 -
  811.20 -compile_rules() {
  811.21 -	./configure $CONFIGURE_ARGS &&
  811.22 -	fix libtool &&
  811.23 -	make &&
  811.24 -	make install
  811.25 -}
  811.26 -
  811.27 -genpkg_rules() {
  811.28 -	copy @std
  811.29 -	DEPENDS="xorg-server"
  811.30 -	TAGS="xorg display"
  811.31 -}
   812.1 --- a/xorg-xf86-video-sunleo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   812.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   812.3 @@ -1,1 +0,0 @@
   812.4 -../xorg/.icon.png
   812.5 \ No newline at end of file
   813.1 --- a/xorg-xf86-video-sunleo/receipt	Thu Dec 13 00:46:54 2018 +0200
   813.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   813.3 @@ -1,28 +0,0 @@
   813.4 -# SliTaz package receipt v2.
   813.5 -
   813.6 -PACKAGE="xorg-xf86-video-sunleo"
   813.7 -VERSION="1.2.2"
   813.8 -CATEGORY="x-window"
   813.9 -SHORT_DESC="Xorg driver for Sun Leo (ZX) video cards"
  813.10 -MAINTAINER="al.bobylev@gmail.com"
  813.11 -LICENSE="MIT"
  813.12 -WEB_SITE="https://www.x.org/wiki/"
  813.13 -REPOLOGY="xdrv:sunleo"
  813.14 -
  813.15 -TARBALL="xf86-video-sunleo-$VERSION.tar.bz2"
  813.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  813.17 -
  813.18 -BUILD_DEPENDS="xorg-server-dev xorg-libXfont2-dev"
  813.19 -
  813.20 -compile_rules() {
  813.21 -	./configure $CONFIGURE_ARGS &&
  813.22 -	fix libtool &&
  813.23 -	make &&
  813.24 -	make install
  813.25 -}
  813.26 -
  813.27 -genpkg_rules() {
  813.28 -	copy @std
  813.29 -	DEPENDS="xorg-server"
  813.30 -	TAGS="xorg display"
  813.31 -}
   814.1 --- a/xorg-xf86-video-suntcx/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   814.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   814.3 @@ -1,1 +0,0 @@
   814.4 -../xorg/.icon.png
   814.5 \ No newline at end of file
   815.1 --- a/xorg-xf86-video-suntcx/receipt	Thu Dec 13 00:46:54 2018 +0200
   815.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   815.3 @@ -1,28 +0,0 @@
   815.4 -# SliTaz package receipt v2.
   815.5 -
   815.6 -PACKAGE="xorg-xf86-video-suntcx"
   815.7 -VERSION="1.1.2"
   815.8 -CATEGORY="x-window"
   815.9 -SHORT_DESC="Xorg driver for Sun TCX video cards"
  815.10 -MAINTAINER="al.bobylev@gmail.com"
  815.11 -LICENSE="MIT"
  815.12 -WEB_SITE="https://www.x.org/wiki/"
  815.13 -REPOLOGY="xdrv:suntcx"
  815.14 -
  815.15 -TARBALL="xf86-video-suntcx-$VERSION.tar.bz2"
  815.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  815.17 -
  815.18 -BUILD_DEPENDS="xorg-server-dev"
  815.19 -
  815.20 -compile_rules() {
  815.21 -	./configure $CONFIGURE_ARGS &&
  815.22 -	fix libtool &&
  815.23 -	make &&
  815.24 -	make install
  815.25 -}
  815.26 -
  815.27 -genpkg_rules() {
  815.28 -	copy @std
  815.29 -	DEPENDS="xorg-server"
  815.30 -	TAGS="xorg display"
  815.31 -}
   816.1 --- a/xorg-xf86-video-tdfx/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   816.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   816.3 @@ -1,1 +0,0 @@
   816.4 -../xorg/.icon.png
   816.5 \ No newline at end of file
   817.1 --- a/xorg-xf86-video-tdfx/receipt	Thu Dec 13 00:46:54 2018 +0200
   817.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   817.3 @@ -1,28 +0,0 @@
   817.4 -# SliTaz package receipt v2.
   817.5 -
   817.6 -PACKAGE="xorg-xf86-video-tdfx"
   817.7 -VERSION="1.4.7"
   817.8 -CATEGORY="x-window"
   817.9 -SHORT_DESC="Xorg driver for 3Dfx video cards"
  817.10 -MAINTAINER="al.bobylev@gmail.com"
  817.11 -LICENSE="MIT"
  817.12 -WEB_SITE="https://www.x.org/wiki/"
  817.13 -REPOLOGY="xdrv:tdfx"
  817.14 -
  817.15 -TARBALL="xf86-video-tdfx-$VERSION.tar.bz2"
  817.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  817.17 -
  817.18 -BUILD_DEPENDS="xorg-server-dev"
  817.19 -
  817.20 -compile_rules() {
  817.21 -	./configure $CONFIGURE_ARGS &&
  817.22 -	fix libtool &&
  817.23 -	make &&
  817.24 -	make install
  817.25 -}
  817.26 -
  817.27 -genpkg_rules() {
  817.28 -	copy @std
  817.29 -	DEPENDS="xorg-server"
  817.30 -	TAGS="xorg display"
  817.31 -}
   818.1 --- a/xorg-xf86-video-trident/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   818.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   818.3 @@ -1,1 +0,0 @@
   818.4 -../xorg/.icon.png
   818.5 \ No newline at end of file
   819.1 --- a/xorg-xf86-video-trident/receipt	Thu Dec 13 00:46:54 2018 +0200
   819.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   819.3 @@ -1,28 +0,0 @@
   819.4 -# SliTaz package receipt v2.
   819.5 -
   819.6 -PACKAGE="xorg-xf86-video-trident"
   819.7 -VERSION="1.3.8"
   819.8 -CATEGORY="x-window"
   819.9 -SHORT_DESC="Xorg driver for Trident video cards"
  819.10 -MAINTAINER="devel@slitaz.org"
  819.11 -LICENSE="MIT"
  819.12 -WEB_SITE="https://www.x.org/wiki/trident/"
  819.13 -REPOLOGY="xdrv:trident"
  819.14 -
  819.15 -TARBALL="xf86-video-trident-$VERSION.tar.bz2"
  819.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  819.17 -
  819.18 -BUILD_DEPENDS="xorg-server-dev xorg-xorgproto"
  819.19 -
  819.20 -compile_rules() {
  819.21 -	./configure $CONFIGURE_ARGS &&
  819.22 -	fix libtool &&
  819.23 -	make &&
  819.24 -	make install
  819.25 -}
  819.26 -
  819.27 -genpkg_rules() {
  819.28 -	copy @std
  819.29 -	DEPENDS="xorg-server"
  819.30 -	TAGS="xorg display"
  819.31 -}
   820.1 --- a/xorg-xf86-video-vesa/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   820.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   820.3 @@ -1,1 +0,0 @@
   820.4 -../xorg/.icon.png
   820.5 \ No newline at end of file
   821.1 --- a/xorg-xf86-video-vesa/receipt	Thu Dec 13 00:46:54 2018 +0200
   821.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   821.3 @@ -1,29 +0,0 @@
   821.4 -# SliTaz package receipt v2.
   821.5 -
   821.6 -PACKAGE="xorg-xf86-video-vesa"
   821.7 -VERSION="2.4.0"
   821.8 -CATEGORY="x-window"
   821.9 -SHORT_DESC="Xorg driver for generic VESA video cards"
  821.10 -MAINTAINER="devel@slitaz.org"
  821.11 -LICENSE="MIT"
  821.12 -WEB_SITE="https://www.x.org/wiki/vesa/"
  821.13 -REPOLOGY="xdrv:vesa"
  821.14 -
  821.15 -TARBALL="xf86-video-vesa-$VERSION.tar.bz2"
  821.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  821.17 -
  821.18 -BUILD_DEPENDS="xorg-server-dev"
  821.19 -
  821.20 -compile_rules() {
  821.21 -	./configure $CONFIGURE_ARGS &&
  821.22 -	fix libtool &&
  821.23 -	make &&
  821.24 -	make install
  821.25 -}
  821.26 -
  821.27 -genpkg_rules() {
  821.28 -	copy @std
  821.29 -	# We can use xorg-server-light with evdev and vesa driver.
  821.30 -	#DEPENDS="xorg-server"
  821.31 -	TAGS="xorg display"
  821.32 -}
   822.1 --- a/xorg-xf86-video-vmware/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   822.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   822.3 @@ -1,1 +0,0 @@
   822.4 -../xorg/.icon.png
   822.5 \ No newline at end of file
   823.1 --- a/xorg-xf86-video-vmware/receipt	Thu Dec 13 00:46:54 2018 +0200
   823.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   823.3 @@ -1,29 +0,0 @@
   823.4 -# SliTaz package receipt v2.
   823.5 -
   823.6 -PACKAGE="xorg-xf86-video-vmware"
   823.7 -VERSION="13.3.0"
   823.8 -CATEGORY="x-window"
   823.9 -SHORT_DESC="Xorg driver for VMware virtual video cards"
  823.10 -MAINTAINER="devel@slitaz.org"
  823.11 -LICENSE="MIT"
  823.12 -WEB_SITE="https://www.x.org/wiki/vmware/"
  823.13 -REPOLOGY="xdrv:vmware"
  823.14 -
  823.15 -TARBALL="xf86-video-vmware-$VERSION.tar.bz2"
  823.16 -WGET_URL="$XORG_MIRROR/driver/$TARBALL"
  823.17 -
  823.18 -BUILD_DEPENDS="xorg-util-macros xorg-server-dev xorg-libXrandr-dev \
  823.19 -xorg-libXrender-dev xorg-libXinerama-dev xorg-libXv-dev xorg-xorgproto \
  823.20 -libgcrypt-dev expat-dev eudev-dev"
  823.21 -
  823.22 -compile_rules() {
  823.23 -	./configure $CONFIGURE_ARGS &&
  823.24 -	fix libtool &&
  823.25 -	make &&
  823.26 -	make install
  823.27 -}
  823.28 -
  823.29 -genpkg_rules() {
  823.30 -	copy @std
  823.31 -	DEPENDS="eudev libdrm mesa-libxatracker"
  823.32 -}
   824.1 --- a/xorg-xfd/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   824.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   824.3 @@ -1,1 +0,0 @@
   824.4 -../xorg/.icon.png
   824.5 \ No newline at end of file
   825.1 --- a/xorg-xfd/receipt	Thu Dec 13 00:46:54 2018 +0200
   825.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   825.3 @@ -1,28 +0,0 @@
   825.4 -# SliTaz package receipt v2.
   825.5 -
   825.6 -PACKAGE="xorg-xfd"
   825.7 -VERSION="1.1.2"
   825.8 -CATEGORY="x-window"
   825.9 -SHORT_DESC="Display all the characters in an X font"
  825.10 -MAINTAINER="al.bobylev@gmail.com"
  825.11 -LICENSE="MIT"
  825.12 -WEB_SITE="https://www.x.org/wiki/"
  825.13 -REPOLOGY="xfd"
  825.14 -
  825.15 -TARBALL="xfd-$VERSION.tar.bz2"
  825.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  825.17 -
  825.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev fontconfig-dev xorg-libXft-dev \
  825.19 -xorg-libXrender-dev xorg-libXmu-dev xorg-xorgproto gettext-dev"
  825.20 -
  825.21 -compile_rules() {
  825.22 -	./configure $CONFIGURE_ARGS &&
  825.23 -	make &&
  825.24 -	make install
  825.25 -}
  825.26 -
  825.27 -genpkg_rules() {
  825.28 -	copy @std
  825.29 -	DEPENDS="fontconfig freetype xorg-libX11 xorg-libXaw xorg-libXft \
  825.30 -	xorg-libXmu xorg-libXrender xorg-libXt"
  825.31 -}
   826.1 --- a/xorg-xfontsel/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   826.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   826.3 @@ -1,1 +0,0 @@
   826.4 -../xorg/.icon.png
   826.5 \ No newline at end of file
   827.1 --- a/xorg-xfontsel/receipt	Thu Dec 13 00:46:54 2018 +0200
   827.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   827.3 @@ -1,28 +0,0 @@
   827.4 -# SliTaz package receipt v2.
   827.5 -
   827.6 -PACKAGE="xorg-xfontsel"
   827.7 -VERSION="1.0.6"
   827.8 -CATEGORY="x-window"
   827.9 -SHORT_DESC="Point and click selection of X11 font names"
  827.10 -MAINTAINER="devel@slitaz.org"
  827.11 -LICENSE="MIT"
  827.12 -WEB_SITE="https://www.x.org/wiki/"
  827.13 -REPOLOGY="xfontsel"
  827.14 -
  827.15 -TARBALL="xfontsel-$VERSION.tar.bz2"
  827.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  827.17 -
  827.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev"
  827.19 -
  827.20 -compile_rules() {
  827.21 -	./configure $CONFIGURE_ARGS &&
  827.22 -	make &&
  827.23 -	make install
  827.24 -}
  827.25 -
  827.26 -genpkg_rules() {
  827.27 -	copy @std
  827.28 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  827.29 -	CONFIG_FILES="/etc/X11/app-defaults/XFontSel"
  827.30 -	TAGS="utility xorg fonts"
  827.31 -}
   828.1 --- a/xorg-xfs/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   828.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   828.3 @@ -1,1 +0,0 @@
   828.4 -../xorg/.icon.png
   828.5 \ No newline at end of file
   829.1 --- a/xorg-xfs/receipt	Thu Dec 13 00:46:54 2018 +0200
   829.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   829.3 @@ -1,30 +0,0 @@
   829.4 -# SliTaz package receipt v2.
   829.5 -
   829.6 -PACKAGE="xorg-xfs"
   829.7 -VERSION="1.2.0"
   829.8 -CATEGORY="x-window"
   829.9 -SHORT_DESC="X Font Server"
  829.10 -MAINTAINER="al.bobylev@gmail.com"
  829.11 -LICENSE="MIT"
  829.12 -WEB_SITE="https://www.x.org/wiki/"
  829.13 -REPOLOGY="xfs"
  829.14 -
  829.15 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  829.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  829.17 -
  829.18 -BUILD_DEPENDS="xorg-util-macros xorg-font-util-dev xorg-xorgproto \
  829.19 -xorg-libXfont2-dev xorg-xtrans"
  829.20 -
  829.21 -compile_rules() {
  829.22 -	touch /root/missing /missing
  829.23 -
  829.24 -	./configure $CONFIGURE_ARGS &&
  829.25 -	make &&
  829.26 -	make install
  829.27 -}
  829.28 -
  829.29 -genpkg_rules() {
  829.30 -	copy @std
  829.31 -	DEPENDS="xorg-libXfont2"
  829.32 -	CONFIG_FILES="/etc/X11/fs/config"
  829.33 -}
   830.1 --- a/xorg-xfsinfo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   830.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   830.3 @@ -1,1 +0,0 @@
   830.4 -../xorg/.icon.png
   830.5 \ No newline at end of file
   831.1 --- a/xorg-xfsinfo/receipt	Thu Dec 13 00:46:54 2018 +0200
   831.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   831.3 @@ -1,28 +0,0 @@
   831.4 -# SliTaz package receipt v2.
   831.5 -
   831.6 -PACKAGE="xorg-xfsinfo"
   831.7 -VERSION="1.0.5"
   831.8 -CATEGORY="x-window"
   831.9 -SHORT_DESC="X font server information utility"
  831.10 -MAINTAINER="al.bobylev@gmail.com"
  831.11 -LICENSE="MIT"
  831.12 -WEB_SITE="https://www.x.org/wiki/"
  831.13 -REPOLOGY="xfsinfo"
  831.14 -
  831.15 -TARBALL="xfsinfo-$VERSION.tar.bz2"
  831.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  831.17 -
  831.18 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-libFS-dev"
  831.19 -
  831.20 -compile_rules() {
  831.21 -	touch /root/missing
  831.22 -
  831.23 -	./configure $CONFIGURE_ARGS &&
  831.24 -	make &&
  831.25 -	make install
  831.26 -}
  831.27 -
  831.28 -genpkg_rules() {
  831.29 -	copy @std
  831.30 -	DEPENDS="xorg-libFS"
  831.31 -}
   832.1 --- a/xorg-xgamma/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   832.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   832.3 @@ -1,1 +0,0 @@
   832.4 -../xorg/.icon.png
   832.5 \ No newline at end of file
   833.1 --- a/xorg-xgamma/receipt	Thu Dec 13 00:46:54 2018 +0200
   833.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   833.3 @@ -1,28 +0,0 @@
   833.4 -# SliTaz package receipt v2.
   833.5 -
   833.6 -PACKAGE="xorg-xgamma"
   833.7 -VERSION="1.0.6"
   833.8 -CATEGORY="x-window"
   833.9 -SHORT_DESC="Alter a monitor's gamma correction through the X server"
  833.10 -MAINTAINER="al.bobylev@gmail.com"
  833.11 -LICENSE="MIT"
  833.12 -WEB_SITE="https://www.x.org/wiki/"
  833.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  833.14 -REPOLOGY="xgamma"
  833.15 -
  833.16 -TARBALL="xgamma-$VERSION.tar.bz2"
  833.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  833.18 -
  833.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXxf86vm-dev xorg-xorgproto"
  833.20 -
  833.21 -compile_rules() {
  833.22 -	./configure $CONFIGURE_ARGS &&
  833.23 -	fix libtool &&
  833.24 -	make &&
  833.25 -	make install
  833.26 -}
  833.27 -
  833.28 -genpkg_rules() {
  833.29 -	copy @std
  833.30 -	DEPENDS="xorg-libX11 xorg-libXxf86vm"
  833.31 -}
   834.1 --- a/xorg-xhost/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   834.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   834.3 @@ -1,1 +0,0 @@
   834.4 -../xorg/.icon.png
   834.5 \ No newline at end of file
   835.1 --- a/xorg-xhost/receipt	Thu Dec 13 00:46:54 2018 +0200
   835.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   835.3 @@ -1,28 +0,0 @@
   835.4 -# SliTaz package receipt v2.
   835.5 -
   835.6 -PACKAGE="xorg-xhost"
   835.7 -VERSION="1.0.7"
   835.8 -CATEGORY="x-window"
   835.9 -SHORT_DESC="Server access control program for X"
  835.10 -MAINTAINER="pascal.bellard@slitaz.org"
  835.11 -LICENSE="MIT"
  835.12 -WEB_SITE="https://www.x.org/wiki/"
  835.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  835.14 -REPOLOGY="xhost"
  835.15 -
  835.16 -TARBALL="xhost-$VERSION.tar.bz2"
  835.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  835.18 -
  835.19 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-libX11-dev xorg-libXmu-dev"
  835.20 -
  835.21 -compile_rules() {
  835.22 -	./configure $CONFIGURE_ARGS &&
  835.23 -	fix libtool &&
  835.24 -	make &&
  835.25 -	make install
  835.26 -}
  835.27 -
  835.28 -genpkg_rules() {
  835.29 -	copy @std
  835.30 -	DEPENDS="xorg-libX11 xorg-libXmu"
  835.31 -}
   836.1 --- a/xorg-xinit/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   836.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   836.3 @@ -1,1 +0,0 @@
   836.4 -../xorg/.icon.png
   836.5 \ No newline at end of file
   837.1 --- a/xorg-xinit/receipt	Thu Dec 13 00:46:54 2018 +0200
   837.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   837.3 @@ -1,33 +0,0 @@
   837.4 -# SliTaz package receipt v2.
   837.5 -
   837.6 -PACKAGE="xorg-xinit"
   837.7 -VERSION="1.4.0"
   837.8 -CATEGORY="x-window"
   837.9 -SHORT_DESC="X Window System initializer (includes startx)"
  837.10 -MAINTAINER="devel@slitaz.org"
  837.11 -LICENSE="MIT"
  837.12 -WEB_SITE="https://www.x.org/wiki/"
  837.13 -REPOLOGY="xinit"
  837.14 -
  837.15 -TARBALL="xinit-$VERSION.tar.bz2"
  837.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  837.17 -
  837.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXmu-dev"
  837.19 -
  837.20 -compile_rules() {
  837.21 -	sed -i '/$serverargs $vtarg/ s/serverargs/: #&/' startx.cpp
  837.22 -
  837.23 -	./configure \
  837.24 -		--with-xinitdir=/etc/X11/xinit \
  837.25 -		$CONFIGURE_ARGS &&
  837.26 -	make &&
  837.27 -	make install || return 1
  837.28 -
  837.29 -	cp $stuff/xserverrc $install/etc/X11/xinit/xserverrc
  837.30 -}
  837.31 -
  837.32 -genpkg_rules() {
  837.33 -	copy @std
  837.34 -	DEPENDS="xorg-libX11   openssl xorg-xauth"
  837.35 -	TAGS="utility xorg"
  837.36 -}
   838.1 --- a/xorg-xinit/stuff/patches/06_move_serverauthfile_into_tmp.diff	Thu Dec 13 00:46:54 2018 +0200
   838.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   838.3 @@ -1,20 +0,0 @@
   838.4 -Move startx auth files in /tmp so they are removed on reboot.
   838.5 -http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=357736
   838.6 -The trap patch didn't seem to work on reboot.
   838.7 ----
   838.8 - startx.cpp |    2 +-
   838.9 - 1 file changed, 1 insertion(+), 1 deletion(-)
  838.10 -
  838.11 -Index: xinit/startx.cpp
  838.12 -===================================================================
  838.13 ---- xinit.orig/startx.cpp
  838.14 -+++ xinit/startx.cpp
  838.15 -@@ -273,7 +273,7 @@
  838.16 -     dummy=0
  838.17 - 
  838.18 -     XCOMM create a file with auth information for the server. ':0' is a dummy.
  838.19 --    xserverauthfile=$HOME/.serverauth.$$
  838.20 -+    xserverauthfile=`mktemp -p /tmp serverauth.XXXXXXXXXX`
  838.21 -     trap "rm -f '$xserverauthfile'" HUP INT QUIT ILL TRAP KILL BUS TERM
  838.22 -     xauth -q -f "$xserverauthfile" << EOF
  838.23 - add :$dummy . $mcookie
   839.1 --- a/xorg-xinit/stuff/patches/series	Thu Dec 13 00:46:54 2018 +0200
   839.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   839.3 @@ -1,1 +0,0 @@
   839.4 -06_move_serverauthfile_into_tmp.diff
   840.1 --- a/xorg-xinit/stuff/xserverrc	Thu Dec 13 00:46:54 2018 +0200
   840.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   840.3 @@ -1,1 +0,0 @@
   840.4 -exec /usr/bin/X -nolisten tcp +bs
   841.1 --- a/xorg-xinput/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   841.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   841.3 @@ -1,1 +0,0 @@
   841.4 -../xorg/.icon.png
   841.5 \ No newline at end of file
   842.1 --- a/xorg-xinput/receipt	Thu Dec 13 00:46:54 2018 +0200
   842.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   842.3 @@ -1,29 +0,0 @@
   842.4 -# SliTaz package receipt v2.
   842.5 -
   842.6 -PACKAGE="xorg-xinput"
   842.7 -VERSION="1.6.2"
   842.8 -CATEGORY="x-window"
   842.9 -SHORT_DESC="Utility to configure and test X input devices"
  842.10 -MAINTAINER="devel@slitaz.org"
  842.11 -LICENSE="MIT"
  842.12 -WEB_SITE="https://www.x.org/wiki/"
  842.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  842.14 -REPOLOGY="xinput"
  842.15 -
  842.16 -TARBALL="xinput-$VERSION.tar.bz2"
  842.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  842.18 -
  842.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXext-dev \
  842.20 -xorg-libXi-dev xorg-xorgproto xorg-libXrandr-dev xorg-libXinerama-dev"
  842.21 -
  842.22 -compile_rules() {
  842.23 -	./configure $CONFIGURE_ARGS &&
  842.24 -	fix libtool &&
  842.25 -	make &&
  842.26 -	make install
  842.27 -}
  842.28 -
  842.29 -genpkg_rules() {
  842.30 -	copy @std
  842.31 -	DEPENDS="xorg-libX11 xorg-libXi xorg-libXinerama xorg-libXrandr"
  842.32 -}
   843.1 --- a/xorg-xkbcomp/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   843.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   843.3 @@ -1,1 +0,0 @@
   843.4 -../xorg/.icon.png
   843.5 \ No newline at end of file
   844.1 --- a/xorg-xkbcomp/receipt	Thu Dec 13 00:46:54 2018 +0200
   844.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   844.3 @@ -1,38 +0,0 @@
   844.4 -# SliTaz package receipt v2.
   844.5 -
   844.6 -PACKAGE="xorg-xkbcomp"
   844.7 -VERSION="1.4.2"
   844.8 -CATEGORY="x-window"
   844.9 -SHORT_DESC="Compile XKB keyboard description"
  844.10 -MAINTAINER="devel@slitaz.org"
  844.11 -LICENSE="MIT"
  844.12 -WEB_SITE="https://www.x.org/wiki/"
  844.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  844.14 -REPOLOGY="xkbcomp"
  844.15 -
  844.16 -TARBALL="xkbcomp-$VERSION.tar.bz2"
  844.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  844.18 -
  844.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libxkbfile-dev xorg-xorgproto"
  844.20 -SPLIT="$PACKAGE-dev"
  844.21 -
  844.22 -compile_rules() {
  844.23 -	./configure $CONFIGURE_ARGS &&
  844.24 -	fix libtool &&
  844.25 -	make &&
  844.26 -	make install
  844.27 -}
  844.28 -
  844.29 -genpkg_rules() {
  844.30 -	case $PACKAGE in
  844.31 -		*-xkbcomp)
  844.32 -			copy @std
  844.33 -			DEPENDS="xorg-libX11 xorg-libxkbfile"
  844.34 -			;;
  844.35 -		*-dev)
  844.36 -			copy @dev
  844.37 -			DEPENDS="xorg-xkbcomp \
  844.38 -			xorg-libX11-dev xorg-libxkbfile-dev xorg-xorgproto"
  844.39 -			;;
  844.40 -	esac
  844.41 -}
   845.1 --- a/xorg-xkbevd/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   845.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   845.3 @@ -1,1 +0,0 @@
   845.4 -../xorg/.icon.png
   845.5 \ No newline at end of file
   846.1 --- a/xorg-xkbevd/receipt	Thu Dec 13 00:46:54 2018 +0200
   846.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   846.3 @@ -1,28 +0,0 @@
   846.4 -# SliTaz package receipt v2.
   846.5 -
   846.6 -PACKAGE="xorg-xkbevd"
   846.7 -VERSION="1.1.4"
   846.8 -CATEGORY="x-window"
   846.9 -SHORT_DESC="XKB event daemon"
  846.10 -MAINTAINER="al.bobylev@gmail.com"
  846.11 -LICENSE="MIT"
  846.12 -WEB_SITE="https://www.x.org/wiki/"
  846.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  846.14 -REPOLOGY="xkbevd"
  846.15 -
  846.16 -TARBALL="xkbevd-$VERSION.tar.bz2"
  846.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  846.18 -
  846.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxkbfile-dev xorg-libX11-dev"
  846.20 -
  846.21 -compile_rules() {
  846.22 -	./configure $CONFIGURE_ARGS &&
  846.23 -	fix libtool &&
  846.24 -	make &&
  846.25 -	make install
  846.26 -}
  846.27 -
  846.28 -genpkg_rules() {
  846.29 -	copy @std
  846.30 -	DEPENDS="xorg-libX11 xorg-libxkbfile"
  846.31 -}
   847.1 --- a/xorg-xkbprint/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   847.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   847.3 @@ -1,1 +0,0 @@
   847.4 -../xorg/.icon.png
   847.5 \ No newline at end of file
   848.1 --- a/xorg-xkbprint/receipt	Thu Dec 13 00:46:54 2018 +0200
   848.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   848.3 @@ -1,26 +0,0 @@
   848.4 -# SliTaz package receipt v2.
   848.5 -
   848.6 -PACKAGE="xorg-xkbprint"
   848.7 -VERSION="1.0.4"
   848.8 -CATEGORY="x-window"
   848.9 -SHORT_DESC="Print an XKB keyboard description"
  848.10 -MAINTAINER="al.bobylev@gmail.com"
  848.11 -LICENSE="MIT"
  848.12 -WEB_SITE="https://www.x.org/wiki/"
  848.13 -REPOLOGY="xkbprint"
  848.14 -
  848.15 -TARBALL="xkbprint-$VERSION.tar.bz2"
  848.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  848.17 -
  848.18 -BUILD_DEPENDS="xorg-util-macros xorg-libxkbfile-dev xorg-libX11-dev xorg-xorgproto"
  848.19 -
  848.20 -compile_rules() {
  848.21 -	./configure $CONFIGURE_ARGS &&
  848.22 -	make &&
  848.23 -	make install
  848.24 -}
  848.25 -
  848.26 -genpkg_rules() {
  848.27 -	copy @std
  848.28 -	DEPENDS="xorg-libX11 xorg-libxkbfile"
  848.29 -}
   849.1 --- a/xorg-xkbutils/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   849.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   849.3 @@ -1,1 +0,0 @@
   849.4 -../xorg/.icon.png
   849.5 \ No newline at end of file
   850.1 --- a/xorg-xkbutils/receipt	Thu Dec 13 00:46:54 2018 +0200
   850.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   850.3 @@ -1,29 +0,0 @@
   850.4 -# SliTaz package receipt v2.
   850.5 -
   850.6 -PACKAGE="xorg-xkbutils"
   850.7 -VERSION="1.0.4"
   850.8 -CATEGORY="x-window"
   850.9 -SHORT_DESC="Xorg keyboard utilities"
  850.10 -MAINTAINER="devel@slitaz.org"
  850.11 -LICENSE="MIT"
  850.12 -WEB_SITE="https://www.x.org/wiki/"
  850.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  850.14 -REPOLOGY="xkbutils"
  850.15 -
  850.16 -TARBALL="xkbutils-$VERSION.tar.bz2"
  850.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  850.18 -
  850.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXt-dev \
  850.20 -xorg-libX11-dev xorg-xorgproto"
  850.21 -
  850.22 -compile_rules() {
  850.23 -	./configure $CONFIGURE_ARGS &&
  850.24 -	fix libtool &&
  850.25 -	make &&
  850.26 -	make install
  850.27 -}
  850.28 -
  850.29 -genpkg_rules() {
  850.30 -	copy @std
  850.31 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXt"
  850.32 -}
   851.1 --- a/xorg-xkeyboard-config/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   851.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   851.3 @@ -1,1 +0,0 @@
   851.4 -../xorg/.icon.png
   851.5 \ No newline at end of file
   852.1 --- a/xorg-xkeyboard-config/receipt	Thu Dec 13 00:46:54 2018 +0200
   852.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   852.3 @@ -1,27 +0,0 @@
   852.4 -# SliTaz package receipt v2.
   852.5 -
   852.6 -PACKAGE="xorg-xkeyboard-config"
   852.7 -VERSION="2.25"
   852.8 -CATEGORY="x-window"
   852.9 -SHORT_DESC="Keyboard configuration database for the X Window System"
  852.10 -MAINTAINER="devel@slitaz.org"
  852.11 -LICENSE="MIT"
  852.12 -WEB_SITE="https://www.x.org/wiki/"
  852.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xkeyboard-config.html"
  852.14 -HOST_ARCH="any"
  852.15 -REPOLOGY="xkeyboard-config"
  852.16 -
  852.17 -TARBALL="xkeyboard-config-$VERSION.tar.bz2"
  852.18 -WGET_URL="$XORG_MIRROR/data/xkeyboard-config/$TARBALL"
  852.19 -
  852.20 -BUILD_DEPENDS="libxslt xorg-xorgproto xorg-libX11-dev intltool"
  852.21 -SPLIT="$PACKAGE-dev"
  852.22 -
  852.23 -compile_rules() {
  852.24 -	./configure \
  852.25 -		--with-xkb-base=/usr/share/X11/xkb \
  852.26 -		--with-xkb-rules-symlink=xorg \
  852.27 -		$CONFIGURE_ARGS &&
  852.28 -	make &&
  852.29 -	make install
  852.30 -}
   853.1 --- a/xorg-xkill/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   853.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   853.3 @@ -1,1 +0,0 @@
   853.4 -../xorg/.icon.png
   853.5 \ No newline at end of file
   854.1 --- a/xorg-xkill/receipt	Thu Dec 13 00:46:54 2018 +0200
   854.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   854.3 @@ -1,27 +0,0 @@
   854.4 -# SliTaz package receipt v2.
   854.5 -
   854.6 -PACKAGE="xorg-xkill"
   854.7 -VERSION="1.0.5"
   854.8 -CATEGORY="x-window"
   854.9 -SHORT_DESC="Kill a client by its X resource"
  854.10 -MAINTAINER="devel@slitaz.org"
  854.11 -LICENSE="MIT"
  854.12 -WEB_SITE="https://www.x.org/wiki/"
  854.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  854.14 -REPOLOGY="xkill"
  854.15 -
  854.16 -TARBALL="xkill-$VERSION.tar.bz2"
  854.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  854.18 -
  854.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXmu-dev xorg-xorgproto"
  854.20 -
  854.21 -compile_rules() {
  854.22 -	./configure $CONFIGURE_ARGS &&
  854.23 -	make &&
  854.24 -	make install
  854.25 -}
  854.26 -
  854.27 -genpkg_rules() {
  854.28 -	copy @std
  854.29 -	DEPENDS="xorg-libX11 xorg-libXmu"
  854.30 -}
   855.1 --- a/xorg-xload/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   855.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   855.3 @@ -1,1 +0,0 @@
   855.4 -../xorg/.icon.png
   855.5 \ No newline at end of file
   856.1 --- a/xorg-xload/receipt	Thu Dec 13 00:46:54 2018 +0200
   856.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   856.3 @@ -1,29 +0,0 @@
   856.4 -# SliTaz package receipt v2.
   856.5 -
   856.6 -PACKAGE="xorg-xload"
   856.7 -VERSION="1.1.3"
   856.8 -CATEGORY="x-window"
   856.9 -SHORT_DESC="System load average display for X"
  856.10 -MAINTAINER="devel@slitaz.org"
  856.11 -LICENSE="MIT"
  856.12 -WEB_SITE="https://www.x.org/wiki/"
  856.13 -REPOLOGY="xload"
  856.14 -
  856.15 -TARBALL="xload-$VERSION.tar.bz2"
  856.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  856.17 -
  856.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev gettext-dev"
  856.19 -
  856.20 -compile_rules() {
  856.21 -	touch /root/missing /missing
  856.22 -
  856.23 -	./configure $CONFIGURE_ARGS &&
  856.24 -	make &&
  856.25 -	make install
  856.26 -}
  856.27 -
  856.28 -genpkg_rules() {
  856.29 -	copy @std
  856.30 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  856.31 -	CONFIG_FILES="/etc/X11/app-defaults/XLoad"
  856.32 -}
   857.1 --- a/xorg-xload/stuff/xorg-xload.desktop	Thu Dec 13 00:46:54 2018 +0200
   857.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   857.3 @@ -1,7 +0,0 @@
   857.4 -[Desktop Entry]
   857.5 -Type=Application
   857.6 -Name=Xload Monitor
   857.7 -Name[fr]=Moniteur Xload
   857.8 -Exec=xload -nolabel -bg black -fg lightblue -hl orange
   857.9 -Icon=applications-other
  857.10 -Categories=System;
   858.1 --- a/xorg-xlsatoms/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   858.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   858.3 @@ -1,1 +0,0 @@
   858.4 -../xorg/.icon.png
   858.5 \ No newline at end of file
   859.1 --- a/xorg-xlsatoms/receipt	Thu Dec 13 00:46:54 2018 +0200
   859.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   859.3 @@ -1,28 +0,0 @@
   859.4 -# SliTaz package receipt v2.
   859.5 -
   859.6 -PACKAGE="xorg-xlsatoms"
   859.7 -VERSION="1.1.2"
   859.8 -CATEGORY="x-window"
   859.9 -SHORT_DESC="List interned atoms defined on server"
  859.10 -MAINTAINER="al.bobylev@gmail.com"
  859.11 -LICENSE="MIT"
  859.12 -WEB_SITE="https://www.x.org/wiki/"
  859.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  859.14 -REPOLOGY="xlsatoms"
  859.15 -
  859.16 -TARBALL="xlsatoms-$VERSION.tar.bz2"
  859.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  859.18 -
  859.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxcb-dev"
  859.20 -
  859.21 -compile_rules() {
  859.22 -	./configure $CONFIGURE_ARGS &&
  859.23 -	fix libtool &&
  859.24 -	make &&
  859.25 -	make install
  859.26 -}
  859.27 -
  859.28 -genpkg_rules() {
  859.29 -	copy @std
  859.30 -	DEPENDS="xorg-libxcb"
  859.31 -}
   860.1 --- a/xorg-xlsclients/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   860.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   860.3 @@ -1,1 +0,0 @@
   860.4 -../xorg/.icon.png
   860.5 \ No newline at end of file
   861.1 --- a/xorg-xlsclients/receipt	Thu Dec 13 00:46:54 2018 +0200
   861.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   861.3 @@ -1,30 +0,0 @@
   861.4 -# SliTaz package receipt v2.
   861.5 -
   861.6 -PACKAGE="xorg-xlsclients"
   861.7 -VERSION="1.1.4"
   861.8 -CATEGORY="x-window"
   861.9 -SHORT_DESC="List client applications running on a display"
  861.10 -MAINTAINER="al.bobylev@gmail.com"
  861.11 -LICENSE="MIT"
  861.12 -WEB_SITE="https://www.x.org/wiki/"
  861.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  861.14 -REPOLOGY="xlsclients"
  861.15 -
  861.16 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  861.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  861.18 -
  861.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxcb-dev"
  861.20 -
  861.21 -compile_rules() {
  861.22 -	touch /root/missing /missing
  861.23 -
  861.24 -	./configure $CONFIGURE_ARGS &&
  861.25 -	fix libtool &&
  861.26 -	make &&
  861.27 -	make install
  861.28 -}
  861.29 -
  861.30 -genpkg_rules() {
  861.31 -	copy @std
  861.32 -	DEPENDS="xorg-libxcb"
  861.33 -}
   862.1 --- a/xorg-xlsfonts/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   862.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   862.3 @@ -1,1 +0,0 @@
   862.4 -../xorg/.icon.png
   862.5 \ No newline at end of file
   863.1 --- a/xorg-xlsfonts/receipt	Thu Dec 13 00:46:54 2018 +0200
   863.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   863.3 @@ -1,26 +0,0 @@
   863.4 -# SliTaz package receipt v2.
   863.5 -
   863.6 -PACKAGE="xorg-xlsfonts"
   863.7 -VERSION="1.0.6"
   863.8 -CATEGORY="x-window"
   863.9 -SHORT_DESC="List X fonts available on X server"
  863.10 -MAINTAINER="al.bobylev@gmail.com"
  863.11 -LICENSE="MIT"
  863.12 -WEB_SITE="https://www.x.org/wiki/"
  863.13 -REPOLOGY="xlsfonts"
  863.14 -
  863.15 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  863.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  863.17 -
  863.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto"
  863.19 -
  863.20 -compile_rules() {
  863.21 -	./configure $CONFIGURE_ARGS &&
  863.22 -	make &&
  863.23 -	make install
  863.24 -}
  863.25 -
  863.26 -genpkg_rules() {
  863.27 -	copy @std
  863.28 -	DEPENDS="xorg-libX11"
  863.29 -}
   864.1 --- a/xorg-xmag/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   864.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   864.3 @@ -1,1 +0,0 @@
   864.4 -../xorg/.icon.png
   864.5 \ No newline at end of file
   865.1 --- a/xorg-xmag/receipt	Thu Dec 13 00:46:54 2018 +0200
   865.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   865.3 @@ -1,28 +0,0 @@
   865.4 -# SliTaz package receipt v2.
   865.5 -
   865.6 -PACKAGE="xorg-xmag"
   865.7 -VERSION="1.0.6"
   865.8 -CATEGORY="x-window"
   865.9 -SHORT_DESC="Magnify parts of the screen"
  865.10 -MAINTAINER="al.bobylev@gmail.com"
  865.11 -LICENSE="MIT"
  865.12 -WEB_SITE="https://www.x.org/wiki/"
  865.13 -REPOLOGY="xmag"
  865.14 -
  865.15 -TARBALL="xmag-$VERSION.tar.bz2"
  865.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  865.17 -
  865.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev xorg-libXmu-dev xorg-libXt-dev \
  865.19 -xorg-libX11-dev"
  865.20 -
  865.21 -compile_rules() {
  865.22 -	./configure $CONFIGURE_ARGS &&
  865.23 -	make &&
  865.24 -	make install
  865.25 -}
  865.26 -
  865.27 -genpkg_rules() {
  865.28 -	copy @std
  865.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt"
  865.30 -	CONFIG_FILES="/etc/X11/app-defaults/Xmag"
  865.31 -}
   866.1 --- a/xorg-xmessage/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   866.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   866.3 @@ -1,1 +0,0 @@
   866.4 -../xorg/.icon.png
   866.5 \ No newline at end of file
   867.1 --- a/xorg-xmessage/receipt	Thu Dec 13 00:46:54 2018 +0200
   867.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   867.3 @@ -1,29 +0,0 @@
   867.4 -# SliTaz package receipt v2.
   867.5 -
   867.6 -PACKAGE="xorg-xmessage"
   867.7 -VERSION="1.0.5"
   867.8 -CATEGORY="x-window"
   867.9 -SHORT_DESC="Display a message or query in a window"
  867.10 -MAINTAINER="devel@slitaz.org"
  867.11 -LICENSE="MIT"
  867.12 -WEB_SITE="https://www.x.org/wiki/"
  867.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  867.14 -REPOLOGY="xmessage"
  867.15 -
  867.16 -TARBALL="xmessage-$VERSION.tar.bz2"
  867.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  867.18 -
  867.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXaw-dev"
  867.20 -
  867.21 -compile_rules() {
  867.22 -	./configure $CONFIGURE_ARGS &&
  867.23 -	make &&
  867.24 -	make install
  867.25 -}
  867.26 -
  867.27 -genpkg_rules() {
  867.28 -	copy @std
  867.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXt"
  867.30 -	CONFIG_FILES="/etc/X11/app-defaults/Xmessage \
  867.31 -	/etc/X11/app-defaults/Xmessage-color"
  867.32 -}
   868.1 --- a/xorg-xmodmap/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   868.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   868.3 @@ -1,1 +0,0 @@
   868.4 -../xorg/.icon.png
   868.5 \ No newline at end of file
   869.1 --- a/xorg-xmodmap/receipt	Thu Dec 13 00:46:54 2018 +0200
   869.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   869.3 @@ -1,28 +0,0 @@
   869.4 -# SliTaz package receipt v2.
   869.5 -
   869.6 -PACKAGE="xorg-xmodmap"
   869.7 -VERSION="1.0.9"
   869.8 -CATEGORY="x-window"
   869.9 -SHORT_DESC="Utility for modifying keymaps and button mappings"
  869.10 -MAINTAINER="devel@slitaz.org"
  869.11 -LICENSE="MIT"
  869.12 -WEB_SITE="https://www.x.org/wiki/"
  869.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  869.14 -REPOLOGY="xmodmap"
  869.15 -
  869.16 -TARBALL="xmodmap-$VERSION.tar.bz2"
  869.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  869.18 -
  869.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto"
  869.20 -
  869.21 -compile_rules() {
  869.22 -	./configure $CONFIGURE_ARGS &&
  869.23 -	fix libtool &&
  869.24 -	make &&
  869.25 -	make install
  869.26 -}
  869.27 -
  869.28 -genpkg_rules() {
  869.29 -	copy @std
  869.30 -	DEPENDS="xorg-libX11"
  869.31 -}
   870.1 --- a/xorg-xorgproto/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   870.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   870.3 @@ -1,1 +0,0 @@
   870.4 -../xorg/.icon.png
   870.5 \ No newline at end of file
   871.1 --- a/xorg-xorgproto/receipt	Thu Dec 13 00:46:54 2018 +0200
   871.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   871.3 @@ -1,35 +0,0 @@
   871.4 -# SliTaz package receipt v2.
   871.5 -
   871.6 -PACKAGE="xorg-xorgproto"
   871.7 -VERSION="2018.4"
   871.8 -CATEGORY="x-window"
   871.9 -SHORT_DESC="X.Org combined protocol headers"
  871.10 -MAINTAINER="al.bobylev@gmail.com"
  871.11 -LICENSE="MIT"
  871.12 -WEB_SITE="https://github.com/freedesktop/xorg-xorgproto"
  871.13 -HOST_ARCH="any"
  871.14 -REPOLOGY="xorgproto"
  871.15 -
  871.16 -TARBALL="xorgproto-$VERSION.tar.gz"
  871.17 -WGET_URL="https://github.com/freedesktop/xorg-xorgproto/archive/$TARBALL"
  871.18 -
  871.19 -BUILD_DEPENDS="meson ninja"
  871.20 -
  871.21 -compile_rules() {
  871.22 -	mkdir build
  871.23 -	cd    build
  871.24 -	meson-wrapper \
  871.25 -		--datadir=/usr/lib \
  871.26 -		-Dlegacy=true &&
  871.27 -	ninja &&
  871.28 -	ninja install
  871.29 -}
  871.30 -
  871.31 -genpkg_rules() {
  871.32 -	copy @dev
  871.33 -	rm \
  871.34 -		$fs/usr/include/X11/extensions/apple* \
  871.35 -		$fs/usr/include/X11/extensions/windows* \
  871.36 -		$fs/usr/lib/pkgconfig/apple* \
  871.37 -		$fs/usr/lib/pkgconfig/windows*
  871.38 -}
   872.1 --- a/xorg-xpr/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   872.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   872.3 @@ -1,1 +0,0 @@
   872.4 -../xorg/.icon.png
   872.5 \ No newline at end of file
   873.1 --- a/xorg-xpr/receipt	Thu Dec 13 00:46:54 2018 +0200
   873.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   873.3 @@ -1,28 +0,0 @@
   873.4 -# SliTaz package receipt v2.
   873.5 -
   873.6 -PACKAGE="xorg-xpr"
   873.7 -VERSION="1.0.5"
   873.8 -CATEGORY="x-window"
   873.9 -SHORT_DESC="Print an X window dump from xwd"
  873.10 -MAINTAINER="al.bobylev@gmail.com"
  873.11 -LICENSE="MIT"
  873.12 -WEB_SITE="https://www.x.org/wiki/"
  873.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  873.14 -REPOLOGY="xpr"
  873.15 -
  873.16 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  873.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  873.18 -
  873.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXmu-dev xorg-libX11-dev xorg-xorgproto"
  873.20 -
  873.21 -compile_rules() {
  873.22 -	./configure $CONFIGURE_ARGS &&
  873.23 -	fix libtool &&
  873.24 -	make &&
  873.25 -	make install
  873.26 -}
  873.27 -
  873.28 -genpkg_rules() {
  873.29 -	copy @std
  873.30 -	DEPENDS="xorg-libX11 xorg-libXmu"
  873.31 -}
   874.1 --- a/xorg-xprop/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   874.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   874.3 @@ -1,1 +0,0 @@
   874.4 -../xorg/.icon.png
   874.5 \ No newline at end of file
   875.1 --- a/xorg-xprop/receipt	Thu Dec 13 00:46:54 2018 +0200
   875.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   875.3 @@ -1,27 +0,0 @@
   875.4 -# SliTaz package receipt v2.
   875.5 -
   875.6 -PACKAGE="xorg-xprop"
   875.7 -VERSION="1.2.3"
   875.8 -CATEGORY="x-window"
   875.9 -SHORT_DESC="Property displayer for X"
  875.10 -MAINTAINER="devel@slitaz.org"
  875.11 -LICENSE="MIT"
  875.12 -WEB_SITE="https://www.x.org/wiki/"
  875.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  875.14 -REPOLOGY="xprop"
  875.15 -
  875.16 -TARBALL="xprop-$VERSION.tar.bz2"
  875.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  875.18 -
  875.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto"
  875.20 -
  875.21 -compile_rules() {
  875.22 -	./configure $CONFIGURE_ARGS &&
  875.23 -	make &&
  875.24 -	make install
  875.25 -}
  875.26 -
  875.27 -genpkg_rules() {
  875.28 -	copy @std
  875.29 -	DEPENDS="xorg-libX11"
  875.30 -}
   876.1 --- a/xorg-xrandr/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   876.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   876.3 @@ -1,1 +0,0 @@
   876.4 -../xorg/.icon.png
   876.5 \ No newline at end of file
   877.1 --- a/xorg-xrandr/receipt	Thu Dec 13 00:46:54 2018 +0200
   877.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   877.3 @@ -1,29 +0,0 @@
   877.4 -# SliTaz package receipt v2.
   877.5 -
   877.6 -PACKAGE="xorg-xrandr"
   877.7 -VERSION="1.5.0"
   877.8 -CATEGORY="x-window"
   877.9 -SHORT_DESC="Primitive command line interface to RandR extension"
  877.10 -MAINTAINER="devel@slitaz.org"
  877.11 -LICENSE="MIT"
  877.12 -WEB_SITE="https://www.x.org/wiki/"
  877.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  877.14 -REPOLOGY="xrandr"
  877.15 -
  877.16 -TARBALL="xrandr-$VERSION.tar.bz2"
  877.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  877.18 -
  877.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXrandr-dev xorg-libXrender-dev \
  877.20 -xorg-libX11-dev xorg-xorgproto"
  877.21 -
  877.22 -compile_rules() {
  877.23 -	./configure $CONFIGURE_ARGS &&
  877.24 -	fix libtool &&
  877.25 -	make &&
  877.26 -	make install
  877.27 -}
  877.28 -
  877.29 -genpkg_rules() {
  877.30 -	copy @std
  877.31 -	DEPENDS="xorg-libX11 xorg-libXrandr"
  877.32 -}
   878.1 --- a/xorg-xrdb/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   878.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   878.3 @@ -1,1 +0,0 @@
   878.4 -../xorg/.icon.png
   878.5 \ No newline at end of file
   879.1 --- a/xorg-xrdb/receipt	Thu Dec 13 00:46:54 2018 +0200
   879.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   879.3 @@ -1,29 +0,0 @@
   879.4 -# SliTaz package receipt v2.
   879.5 -
   879.6 -PACKAGE="xorg-xrdb"
   879.7 -VERSION="1.1.1"
   879.8 -CATEGORY="x-window"
   879.9 -SHORT_DESC="X server resource database utility"
  879.10 -MAINTAINER="devel@slitaz.org"
  879.11 -LICENSE="MIT"
  879.12 -WEB_SITE="https://www.x.org/wiki/"
  879.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  879.14 -REPOLOGY="xrdb"
  879.15 -
  879.16 -TARBALL="xrdb-$VERSION.tar.bz2"
  879.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  879.18 -
  879.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXmu-dev xorg-libX11-dev xorg-xorgproto"
  879.20 -
  879.21 -compile_rules() {
  879.22 -	touch /root/missing /missing
  879.23 -
  879.24 -	./configure $CONFIGURE_ARGS &&
  879.25 -	make &&
  879.26 -	make install
  879.27 -}
  879.28 -
  879.29 -genpkg_rules() {
  879.30 -	copy @std
  879.31 -	DEPENDS="xorg-libX11 xorg-libXmu"
  879.32 -}
   880.1 --- a/xorg-xrefresh/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   880.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   880.3 @@ -1,1 +0,0 @@
   880.4 -../xorg/.icon.png
   880.5 \ No newline at end of file
   881.1 --- a/xorg-xrefresh/receipt	Thu Dec 13 00:46:54 2018 +0200
   881.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   881.3 @@ -1,28 +0,0 @@
   881.4 -# SliTaz package receipt v2.
   881.5 -
   881.6 -PACKAGE="xorg-xrefresh"
   881.7 -VERSION="1.0.6"
   881.8 -CATEGORY="x-window"
   881.9 -SHORT_DESC="Refresh all or part of an X screen"
  881.10 -MAINTAINER="al.bobylev@gmail.com"
  881.11 -LICENSE="MIT"
  881.12 -WEB_SITE="https://www.x.org/wiki/"
  881.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  881.14 -REPOLOGY="xrefresh"
  881.15 -
  881.16 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  881.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  881.18 -
  881.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto"
  881.20 -
  881.21 -compile_rules() {
  881.22 -	./configure $CONFIGURE_ARGS &&
  881.23 -	fix libtool &&
  881.24 -	make &&
  881.25 -	make install
  881.26 -}
  881.27 -
  881.28 -genpkg_rules() {
  881.29 -	copy @std
  881.30 -	DEPENDS="xorg-libX11"
  881.31 -}
   882.1 --- a/xorg-xset/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   882.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   882.3 @@ -1,1 +0,0 @@
   882.4 -../xorg/.icon.png
   882.5 \ No newline at end of file
   883.1 --- a/xorg-xset/receipt	Thu Dec 13 00:46:54 2018 +0200
   883.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   883.3 @@ -1,36 +0,0 @@
   883.4 -# SliTaz package receipt v2.
   883.5 -
   883.6 -PACKAGE="xorg-xset"
   883.7 -VERSION="1.2.4"
   883.8 -CATEGORY="x-window"
   883.9 -SHORT_DESC="User preference utility for X"
  883.10 -MAINTAINER="paul@slitaz.org"
  883.11 -LICENSE="MIT"
  883.12 -WEB_SITE="https://www.x.org/wiki/"
  883.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  883.14 -REPOLOGY="xset"
  883.15 -
  883.16 -TARBALL="xset-$VERSION.tar.bz2"
  883.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  883.18 -
  883.19 -BUILD_DEPENDS="xorg-util-macros xorg-xorgproto xorg-libXmu-dev \
  883.20 -xorg-libXxf86misc-dev xorg-libXfontcache-dev"
  883.21 -
  883.22 -compile_rules() {
  883.23 -	touch /root/missing /missing
  883.24 -
  883.25 -	./configure $CONFIGURE_ARGS &&
  883.26 -	fix libtool &&
  883.27 -	make &&
  883.28 -	make install || return 1
  883.29 -
  883.30 -	cp -a $stuff/*.sh $install/usr/bin/
  883.31 -	chown -R root:root $install
  883.32 -}
  883.33 -
  883.34 -genpkg_rules() {
  883.35 -	copy @std
  883.36 -	DEPENDS="xorg-libX11 xorg-libXext xorg-libXfontcache xorg-libXmu \
  883.37 -	xorg-libXxf86misc"
  883.38 -	SUGGESTED="yad"
  883.39 -}
   884.1 --- a/xorg-xset/stuff/xorg-xset.desktop	Thu Dec 13 00:46:54 2018 +0200
   884.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   884.3 @@ -1,11 +0,0 @@
   884.4 -[Desktop Entry]
   884.5 -Type=Application
   884.6 -Name=Set screensaver timeout
   884.7 -Comment=0(always on), Default settings: 10 min (600 sec)
   884.8 -Name[fr]=Règle l'économiseur d'écran
   884.9 -Comment[fr]=0(écran toujours allumé), Par défaut 10 min (600 s)
  884.10 -Name[ru]=Время отключения монитора
  884.11 -Comment[ru]=0(не выключать), По умолчанию: 10 мин.(600 ceк.)
  884.12 -Icon=preferences-desktop-screensaver
  884.13 -Exec=xset-screensaver.sh
  884.14 -Categories=GTK;Settings;HardwareSettings;
   885.1 --- a/xorg-xset/stuff/xset-screensaver.sh	Thu Dec 13 00:46:54 2018 +0200
   885.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   885.3 @@ -1,49 +0,0 @@
   885.4 -#!/bin/sh
   885.5 -#
   885.6 -[ -z $(which yad) ] && exec yad && exit 0
   885.7 -
   885.8 -case $(id -u) in
   885.9 -	0) path=/etc/xdg ;;
  885.10 -	*) path=${XDG_CONFIG_HOME:-$HOME/.config}
  885.11 -		[ -f "$path/autostart" ] && mv $path/autostart $path/autostart.bak
  885.12 -		[ -d "$path/autostart" ] || mkdir -p $path/autostart ;;
  885.13 -esac
  885.14 -
  885.15 -AutostartFile="$path/autostart/xset-screensaver.desktop"
  885.16 -launcher='/usr/share/applications/xorg-xset.desktop' # Must be same as package name
  885.17 -
  885.18 -exec_d()
  885.19 -{
  885.20 -	cmd=$(cat $AutostartFile | grep Exec | sed 's/Exec=//') ; $cmd
  885.21 -}
  885.22 -
  885.23 -[ -f $AutostartFile ] && exec_d
  885.24 -
  885.25 -case $LC_ALL in
  885.26 -	C|POSIX|en*) lang='=' ;;
  885.27 -	*) lang='\['${LC_ALL%_*}
  885.28 -	grep -q '\['${LC_ALL%_*} $launcher || lang='=' ;;
  885.29 -esac
  885.30 -
  885.31 -
  885.32 -
  885.33 -val=$(yad --title="$(cat $launcher | grep Name$lang | cut -d'=' -f2)" \
  885.34 -	--scale --max-value=18000 --mark="1h.":3600 --buttons-layout=spread \
  885.35 -	--mark="$(cat $launcher | grep Comment$lang | cut -d'=' -f2 | cut -d',' -f1)":0 \
  885.36 -	--mark="120min.(2h.)":7200 --mark="180min.(3h.)":10800 \
  885.37 -	--mark="240min.(4h.)":14400 --mark="300min.(5h.)":18000 \
  885.38 -	--page=1800 --step=60 --geometry=630x42+10+100 \
  885.39 -	--value=$(xset q | grep timeout | cut -d' ' -f5) \
  885.40 -	--window-icon="preferences-desktop-screensaver" )
  885.41 -
  885.42 -[ -z $val ] || cat > $AutostartFile <<EOT
  885.43 -[Desktop Entry]
  885.44 -Type=Application
  885.45 -Name=xset screensaver timeout
  885.46 -Exec=xset dpms $val $val $val s $val $val
  885.47 -EOT
  885.48 -
  885.49 -exec_d
  885.50 -
  885.51 -# Notes: 'xset s' max val is 32767, 'xset dpms' limit is unknown
  885.52 -exit 0
   886.1 --- a/xorg-xsetmode/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   886.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   886.3 @@ -1,1 +0,0 @@
   886.4 -../xorg/.icon.png
   886.5 \ No newline at end of file
   887.1 --- a/xorg-xsetmode/receipt	Thu Dec 13 00:46:54 2018 +0200
   887.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   887.3 @@ -1,26 +0,0 @@
   887.4 -# SliTaz package receipt v2.
   887.5 -
   887.6 -PACKAGE="xorg-xsetmode"
   887.7 -VERSION="1.0.0"
   887.8 -CATEGORY="x-window"
   887.9 -SHORT_DESC="Set the mode for an X Input device"
  887.10 -MAINTAINER="al.bobylev@gmail.com"
  887.11 -LICENSE="MIT"
  887.12 -WEB_SITE="https://www.x.org/wiki/"
  887.13 -REPOLOGY="xsetmode"
  887.14 -
  887.15 -TARBALL="xsetmode-$VERSION.tar.bz2"
  887.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  887.17 -
  887.18 -BUILD_DEPENDS="xorg-libXi-dev xorg-libX11-dev"
  887.19 -
  887.20 -compile_rules() {
  887.21 -	./configure $CONFIGURE_ARGS &&
  887.22 -	make &&
  887.23 -	make install
  887.24 -}
  887.25 -
  887.26 -genpkg_rules() {
  887.27 -	copy @std
  887.28 -	DEPENDS="xorg-libX11 xorg-libXi"
  887.29 -}
   888.1 --- a/xorg-xsetpointer/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   888.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   888.3 @@ -1,1 +0,0 @@
   888.4 -../xorg/.icon.png
   888.5 \ No newline at end of file
   889.1 --- a/xorg-xsetpointer/receipt	Thu Dec 13 00:46:54 2018 +0200
   889.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   889.3 @@ -1,26 +0,0 @@
   889.4 -# SliTaz package receipt v2.
   889.5 -
   889.6 -PACKAGE="xorg-xsetpointer"
   889.7 -VERSION="1.0.1"
   889.8 -CATEGORY="x-window"
   889.9 -SHORT_DESC="Set an X Input device as the main pointer"
  889.10 -MAINTAINER="al.bobylev@gmail.com"
  889.11 -LICENSE="MIT"
  889.12 -WEB_SITE="https://www.x.org/wiki/"
  889.13 -REPOLOGY="xsetpointer"
  889.14 -
  889.15 -TARBALL="xsetpointer-$VERSION.tar.bz2"
  889.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  889.17 -
  889.18 -BUILD_DEPENDS="xorg-libXi-dev xorg-libX11-dev xorg-xorgproto"
  889.19 -
  889.20 -compile_rules() {
  889.21 -	./configure $CONFIGURE_ARGS &&
  889.22 -	make &&
  889.23 -	make install
  889.24 -}
  889.25 -
  889.26 -genpkg_rules() {
  889.27 -	copy @std
  889.28 -	DEPENDS="xorg-libX11 xorg-libXi"
  889.29 -}
   890.1 --- a/xorg-xsetroot/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   890.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   890.3 @@ -1,1 +0,0 @@
   890.4 -../xorg/.icon.png
   890.5 \ No newline at end of file
   891.1 --- a/xorg-xsetroot/receipt	Thu Dec 13 00:46:54 2018 +0200
   891.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   891.3 @@ -1,29 +0,0 @@
   891.4 -# SliTaz package receipt v2.
   891.5 -
   891.6 -PACKAGE="xorg-xsetroot"
   891.7 -VERSION="1.1.2"
   891.8 -CATEGORY="x-window"
   891.9 -SHORT_DESC="Root window parameter setting utility for X"
  891.10 -MAINTAINER="devel@slitaz.org"
  891.11 -LICENSE="MIT"
  891.12 -WEB_SITE="https://www.x.org/wiki/"
  891.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  891.14 -REPOLOGY="xsetroot"
  891.15 -
  891.16 -TARBALL="xsetroot-$VERSION.tar.bz2"
  891.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  891.18 -
  891.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXmu-dev xorg-libX11-dev \
  891.20 -xorg-xbitmaps xorg-libXcursor-dev xorg-xorgproto"
  891.21 -
  891.22 -compile_rules() {
  891.23 -	./configure $CONFIGURE_ARGS &&
  891.24 -	fix libtool &&
  891.25 -	make &&
  891.26 -	make install
  891.27 -}
  891.28 -
  891.29 -genpkg_rules() {
  891.30 -	copy @std
  891.31 -	DEPENDS="xorg-libX11 xorg-libXcursor xorg-libXmu"
  891.32 -}
   892.1 --- a/xorg-xsm/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   892.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   892.3 @@ -1,1 +0,0 @@
   892.4 -../xorg/.icon.png
   892.5 \ No newline at end of file
   893.1 --- a/xorg-xsm/receipt	Thu Dec 13 00:46:54 2018 +0200
   893.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   893.3 @@ -1,28 +0,0 @@
   893.4 -# SliTaz package receipt v2.
   893.5 -
   893.6 -PACKAGE="xorg-xsm"
   893.7 -VERSION="1.0.4"
   893.8 -CATEGORY="x-window"
   893.9 -SHORT_DESC="X Session Manager"
  893.10 -MAINTAINER="al.bobylev@gmail.com"
  893.11 -LICENSE="MIT"
  893.12 -WEB_SITE="https://www.x.org/wiki/"
  893.13 -REPOLOGY="xsm"
  893.14 -
  893.15 -TARBALL="xsm-$VERSION.tar.bz2"
  893.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  893.17 -
  893.18 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-libXt-dev xorg-libICE-dev \
  893.19 -xorg-libSM-dev xorg-libXaw-dev"
  893.20 -
  893.21 -compile_rules() {
  893.22 -	./configure $CONFIGURE_ARGS &&
  893.23 -	make &&
  893.24 -	make install
  893.25 -}
  893.26 -
  893.27 -genpkg_rules() {
  893.28 -	copy @std
  893.29 -	DEPENDS="xorg-libICE xorg-libSM xorg-libX11 xorg-libXaw xorg-libXt"
  893.30 -	CONFIG_FILES="/etc/X11/app-defaults/XSm /etc/X11/xsm/system.xsm"
  893.31 -}
   894.1 --- a/xorg-xtrans/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   894.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   894.3 @@ -1,1 +0,0 @@
   894.4 -../xorg/.icon.png
   894.5 \ No newline at end of file
   895.1 --- a/xorg-xtrans/receipt	Thu Dec 13 00:46:54 2018 +0200
   895.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   895.3 @@ -1,28 +0,0 @@
   895.4 -# SliTaz package receipt v2.
   895.5 -
   895.6 -PACKAGE="xorg-xtrans"
   895.7 -VERSION="1.3.5"
   895.8 -CATEGORY="development"
   895.9 -SHORT_DESC="X Network Transport layer shared code"
  895.10 -MAINTAINER="devel@slitaz.org"
  895.11 -LICENSE="other"
  895.12 -WEB_SITE="https://www.x.org/wiki/"
  895.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  895.14 -HOST_ARCH="any"
  895.15 -REPOLOGY="xtrans"
  895.16 -
  895.17 -TARBALL="xtrans-$VERSION.tar.bz2"
  895.18 -WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  895.19 -
  895.20 -BUILD_DEPENDS="xorg-util-macros"
  895.21 -
  895.22 -compile_rules() {
  895.23 -	./configure $CONFIGURE_ARGS &&
  895.24 -	make &&
  895.25 -	make install
  895.26 -}
  895.27 -
  895.28 -genpkg_rules() {
  895.29 -	copy @dev
  895.30 -	DEPENDS="xorg-xorgproto"
  895.31 -}
   896.1 --- a/xorg-xvidtune/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   896.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   896.3 @@ -1,1 +0,0 @@
   896.4 -../xorg/.icon.png
   896.5 \ No newline at end of file
   897.1 --- a/xorg-xvidtune/receipt	Thu Dec 13 00:46:54 2018 +0200
   897.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   897.3 @@ -1,28 +0,0 @@
   897.4 -# SliTaz package receipt v2.
   897.5 -
   897.6 -PACKAGE="xorg-xvidtune"
   897.7 -VERSION="1.0.3"
   897.8 -CATEGORY="x-window"
   897.9 -SHORT_DESC="Video mode tuner for Xorg"
  897.10 -MAINTAINER="al.bobylev@gmail.com"
  897.11 -LICENSE="MIT"
  897.12 -WEB_SITE="https://www.x.org/wiki/"
  897.13 -REPOLOGY="xvidtune"
  897.14 -
  897.15 -TARBALL="xvidtune-$VERSION.tar.bz2"
  897.16 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  897.17 -
  897.18 -BUILD_DEPENDS="xorg-util-macros xorg-libXxf86vm-dev xorg-libXt-dev \
  897.19 -xorg-libXaw-dev xorg-libXmu-dev xorg-libX11-dev"
  897.20 -
  897.21 -compile_rules() {
  897.22 -	./configure $CONFIGURE_ARGS &&
  897.23 -	make &&
  897.24 -	make install
  897.25 -}
  897.26 -
  897.27 -genpkg_rules() {
  897.28 -	copy @std
  897.29 -	DEPENDS="xorg-libX11 xorg-libXaw xorg-libXmu xorg-libXt xorg-libXxf86vm"
  897.30 -	CONFIG_FILES="/etc/X11/app-defaults/Xvidtune"
  897.31 -}
   898.1 --- a/xorg-xvinfo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   898.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   898.3 @@ -1,1 +0,0 @@
   898.4 -../xorg/.icon.png
   898.5 \ No newline at end of file
   899.1 --- a/xorg-xvinfo/receipt	Thu Dec 13 00:46:54 2018 +0200
   899.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   899.3 @@ -1,28 +0,0 @@
   899.4 -# SliTaz package receipt v2.
   899.5 -
   899.6 -PACKAGE="xorg-xvinfo"
   899.7 -VERSION="1.1.3"
   899.8 -CATEGORY="x-window"
   899.9 -SHORT_DESC="Print out X-Video extension adaptor information"
  899.10 -MAINTAINER="al.bobylev@gmail.com"
  899.11 -LICENSE="MIT"
  899.12 -WEB_SITE="https://www.x.org/wiki/"
  899.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  899.14 -REPOLOGY="xvinfo"
  899.15 -
  899.16 -TARBALL="xvinfo-$VERSION.tar.bz2"
  899.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  899.18 -
  899.19 -BUILD_DEPENDS="xorg-util-macros xorg-libXv-dev xorg-libX11-dev xorg-xorgproto"
  899.20 -
  899.21 -compile_rules() {
  899.22 -	./configure $CONFIGURE_ARGS &&
  899.23 -	fix libtool &&
  899.24 -	make &&
  899.25 -	make install
  899.26 -}
  899.27 -
  899.28 -genpkg_rules() {
  899.29 -	copy @std
  899.30 -	DEPENDS="xorg-libX11 xorg-libXv"
  899.31 -}
   900.1 --- a/xorg-xwd/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   900.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   900.3 @@ -1,1 +0,0 @@
   900.4 -../xorg/.icon.png
   900.5 \ No newline at end of file
   901.1 --- a/xorg-xwd/receipt	Thu Dec 13 00:46:54 2018 +0200
   901.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   901.3 @@ -1,28 +0,0 @@
   901.4 -# SliTaz package receipt v2.
   901.5 -
   901.6 -PACKAGE="xorg-xwd"
   901.7 -VERSION="1.0.7"
   901.8 -CATEGORY="x-window"
   901.9 -SHORT_DESC="Dump current contents of X window or screen to file"
  901.10 -MAINTAINER="al.bobylev@gmail.com"
  901.11 -LICENSE="MIT"
  901.12 -WEB_SITE="https://www.x.org/wiki/"
  901.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  901.14 -REPOLOGY="xwd"
  901.15 -
  901.16 -TARBALL="xwd-$VERSION.tar.bz2"
  901.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  901.18 -
  901.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto xorg-libxkbfile-dev"
  901.20 -
  901.21 -compile_rules() {
  901.22 -	./configure $CONFIGURE_ARGS &&
  901.23 -	fix libtool &&
  901.24 -	make &&
  901.25 -	make install
  901.26 -}
  901.27 -
  901.28 -genpkg_rules() {
  901.29 -	copy @std
  901.30 -	DEPENDS="xorg-libX11 xorg-libxkbfile"
  901.31 -}
   902.1 --- a/xorg-xwininfo/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   902.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   902.3 @@ -1,1 +0,0 @@
   902.4 -../xorg/.icon.png
   902.5 \ No newline at end of file
   903.1 --- a/xorg-xwininfo/receipt	Thu Dec 13 00:46:54 2018 +0200
   903.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   903.3 @@ -1,29 +0,0 @@
   903.4 -# SliTaz package receipt v2.
   903.5 -
   903.6 -PACKAGE="xorg-xwininfo"
   903.7 -VERSION="1.1.4"
   903.8 -CATEGORY="x-window"
   903.9 -SHORT_DESC="Window information utility for X"
  903.10 -MAINTAINER="devel@slitaz.org"
  903.11 -LICENSE="MIT"
  903.12 -WEB_SITE="https://www.x.org/wiki/"
  903.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  903.14 -REPOLOGY="xwininfo"
  903.15 -
  903.16 -TARBALL="xwininfo-$VERSION.tar.bz2"
  903.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  903.18 -
  903.19 -BUILD_DEPENDS="xorg-util-macros xorg-libxcb-dev xorg-libX11-dev"
  903.20 -
  903.21 -compile_rules() {
  903.22 -	./configure $CONFIGURE_ARGS &&
  903.23 -	fix libtool &&
  903.24 -	make &&
  903.25 -	make install
  903.26 -}
  903.27 -
  903.28 -genpkg_rules() {
  903.29 -	copy @std
  903.30 -	DEPENDS="xorg-libxcb"
  903.31 -	TAGS="util xorg windows"
  903.32 -}
   904.1 --- a/xorg-xwud/.icon.png	Thu Dec 13 00:46:54 2018 +0200
   904.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   904.3 @@ -1,1 +0,0 @@
   904.4 -../xorg/.icon.png
   904.5 \ No newline at end of file
   905.1 --- a/xorg-xwud/receipt	Thu Dec 13 00:46:54 2018 +0200
   905.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   905.3 @@ -1,28 +0,0 @@
   905.4 -# SliTaz package receipt v2.
   905.5 -
   905.6 -PACKAGE="xorg-xwud"
   905.7 -VERSION="1.0.5"
   905.8 -CATEGORY="x-window"
   905.9 -SHORT_DESC="Display an X window dump from xwd"
  905.10 -MAINTAINER="al.bobylev@gmail.com"
  905.11 -LICENSE="MIT"
  905.12 -WEB_SITE="https://www.x.org/wiki/"
  905.13 -LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  905.14 -REPOLOGY="xwud"
  905.15 -
  905.16 -TARBALL="${PACKAGE#*-}-$VERSION.tar.bz2"
  905.17 -WGET_URL="$XORG_MIRROR/app/$TARBALL"
  905.18 -
  905.19 -BUILD_DEPENDS="xorg-util-macros xorg-libX11-dev xorg-xorgproto"
  905.20 -
  905.21 -compile_rules() {
  905.22 -	./configure $CONFIGURE_ARGS &&
  905.23 -	fix libtool &&
  905.24 -	make &&
  905.25 -	make install
  905.26 -}
  905.27 -
  905.28 -genpkg_rules() {
  905.29 -	copy @std
  905.30 -	DEPENDS="xorg-libX11"
  905.31 -}
   906.1 --- a/xorg/receipt	Thu Dec 13 00:46:54 2018 +0200
   906.2 +++ b/xorg/receipt	Thu Dec 20 17:55:43 2018 +0200
   906.3 @@ -12,33 +12,19 @@
   906.4  
   906.5  SPLIT="$PACKAGE-dev $PACKAGE-dev-proto"
   906.6  
   906.7 -genpkg_rules() {
   906.8 -	case $PACKAGE in
   906.9 -		xorg)
  906.10 -			CAT="meta|meta-package to install all Xorg modules"
  906.11 -			DEPENDS="xorg-xauth xorg-base-fonts xorg-libICE xorg-libpciaccess \
  906.12 -			xorg-libSM xorg-libX11 xorg-libXau xorg-libXcomposite \
  906.13 -			xorg-libXcursor xorg-libXdamage xorg-libXdmcp xorg-libXext \
  906.14 -			xorg-libXfixes xorg-libXfont xorg-libXft xorg-libXi \
  906.15 -			xorg-libXinerama xorg-libxkbfile xorg-libXmu xorg-libXpm \
  906.16 -			xorg-libXrandr xorg-libXrender xorg-libXScrnSaver xorg-libXt \
  906.17 -			xorg-libXtst xorg-libXxf86vm xorg-xkbcomp xorg-xkeyboard-config"
  906.18 -			;;
  906.19 -		xorg-dev)
  906.20 -			CAT="meta|meta-package to install all Xorg devel packages"
  906.21 -			DEPENDS="xorg-libXdmcp-dev xorg-libXau-dev xorg-libX11-dev \
  906.22 -			xorg-libXext-dev xorg-libXrender-dev xorg-libXrandr-dev \
  906.23 -			xorg-libXfixes-dev xorg-libfontenc-dev xorg-libXfont-dev \
  906.24 -			xorg-libXft-dev xorg-libXcomposite-dev xorg-libxkbfile-dev \
  906.25 -			xorg-libICE-dev xorg-libSM-dev xorg-libXt-dev xorg-libXinerama-dev \
  906.26 -			xorg-libXmu-dev xorg-libXpm-dev xorg-libXaw-dev xorg-libXt-dev \
  906.27 -			xorg-libXtst-dev xorg-libXcursor-dev xorg-libXdamage-dev \
  906.28 -			xorg-libXi-dev"
  906.29 -			;;
  906.30 -		xorg-dev-proto)
  906.31 -			CAT="meta|meta-package to install all Xorg protocols"
  906.32 -			DEPENDS="xorg-xorgproto \
  906.33 -			xorg-util-macros"
  906.34 -			;;
  906.35 -	esac
  906.36 -}
  906.37 +DEPENDS_std="xauth font-misc-misc-base libice libpciaccess libsm libx11 libxau \
  906.38 +libxcomposite libxcursor libxdamage libxdmcp libxext libxfixes libxfont libxft \
  906.39 +libxi libxinerama libxkbfile libxmu libxpm libxrandr libxrender libxscrnsaver \
  906.40 +libxt libxtst libxxf86vm xkbcomp xkeyboard-config"
  906.41 +DEPENDS_dev="libxdmcp-dev libxau-dev libx11-dev libxext-dev libxrender-dev \
  906.42 +libxrandr-dev libxfixes-dev libfontenc-dev xorg-libxfont-dev libxft-dev \
  906.43 +libxcomposite-dev libxkbfile-dev libice-dev libsm-dev libxt-dev \
  906.44 +libxinerama-dev libxmu-dev libxpm-dev libxaw-dev libxtst-dev libxcursor-dev \
  906.45 +libxdamage-dev libxi-dev"
  906.46 +DEPENDS_dev_proto="xorgproto util-macros"
  906.47 +
  906.48 +CAT_std="meta|meta-package to install all Xorg modules"
  906.49 +CAT_dev="meta|meta-package to install all Xorg devel packages"
  906.50 +CAT_dev_proto="meta|meta-package to install all Xorg protocols"
  906.51 +
  906.52 +TAGS="Xorg"
   907.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   907.2 +++ b/xorgproto/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   907.3 @@ -0,0 +1,1 @@
   907.4 +../xorg/.icon.png
   907.5 \ No newline at end of file
   908.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   908.2 +++ b/xorgproto/receipt	Thu Dec 20 17:55:43 2018 +0200
   908.3 @@ -0,0 +1,37 @@
   908.4 +# SliTaz package receipt v2.
   908.5 +
   908.6 +PACKAGE="xorgproto"
   908.7 +VERSION="2018.4"
   908.8 +CATEGORY="x-window"
   908.9 +SHORT_DESC="X.Org combined protocol headers"
  908.10 +MAINTAINER="al.bobylev@gmail.com"
  908.11 +LICENSE="MIT"
  908.12 +WEB_SITE="https://github.com/freedesktop/xorg-xorgproto"
  908.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xorgproto.html"
  908.14 +HOST_ARCH="any"
  908.15 +
  908.16 +TARBALL="$PACKAGE-$VERSION.tar.gz"
  908.17 +WGET_URL="https://github.com/freedesktop/xorg-xorgproto/archive/$TARBALL"
  908.18 +TARBALL_SHA1="f0870dfbaa9cccac5d0acbf61ea76196b20b5ad8"
  908.19 +
  908.20 +BUILD_DEPENDS="meson ninja"
  908.21 +
  908.22 +COPY="@dev"
  908.23 +
  908.24 +compile_rules() {
  908.25 +	mkdir build
  908.26 +	cd    build
  908.27 +	# legacy=true will install these additional .pc's:
  908.28 +	# evieproto, fontcacheproto, lg3dproto, printproto, xcalibrateproto, xf86rushproto
  908.29 +	meson-wrapper \
  908.30 +		--datadir=/usr/lib \
  908.31 +		-Dlegacy=true &&
  908.32 +	ninja &&
  908.33 +	ninja install || return 1
  908.34 +
  908.35 +	cook_pick_docs ../[^m]*.txt ../PM_spec
  908.36 +}
  908.37 +
  908.38 +TAGS="Xorg"
  908.39 +
  908.40 +PROVIDE="xorg-xorgproto"
   909.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   909.2 +++ b/xpr/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   909.3 @@ -0,0 +1,1 @@
   909.4 +../xorg/.icon.png
   909.5 \ No newline at end of file
   910.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   910.2 +++ b/xpr/receipt	Thu Dec 20 17:55:43 2018 +0200
   910.3 @@ -0,0 +1,27 @@
   910.4 +# SliTaz package receipt v2.
   910.5 +
   910.6 +PACKAGE="xpr"
   910.7 +VERSION="1.0.5"
   910.8 +CATEGORY="x-window"
   910.9 +SHORT_DESC="Print an X window dump from xwd"
  910.10 +MAINTAINER="al.bobylev@gmail.com"
  910.11 +LICENSE="MIT"
  910.12 +WEB_SITE="https://www.x.org/wiki/"
  910.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  910.14 +
  910.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  910.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  910.17 +TARBALL_SHA1="0632c7d8632ac9d23f285811aaea805a2956e155"
  910.18 +
  910.19 +BUILD_DEPENDS="util-macros libxmu-dev libx11-dev xorgproto"
  910.20 +DEPENDS="libx11 libxmu"
  910.21 +
  910.22 +compile_rules() {
  910.23 +	./configure $CONFIGURE_ARGS &&
  910.24 +	make &&
  910.25 +	make install
  910.26 +}
  910.27 +
  910.28 +TAGS="Xorg"
  910.29 +
  910.30 +PROVIDE="xorg-xpr"
   911.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   911.2 +++ b/xprop/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   911.3 @@ -0,0 +1,1 @@
   911.4 +../xorg/.icon.png
   911.5 \ No newline at end of file
   912.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   912.2 +++ b/xprop/receipt	Thu Dec 20 17:55:43 2018 +0200
   912.3 @@ -0,0 +1,27 @@
   912.4 +# SliTaz package receipt v2.
   912.5 +
   912.6 +PACKAGE="xprop"
   912.7 +VERSION="1.2.3"
   912.8 +CATEGORY="x-window"
   912.9 +SHORT_DESC="Property displayer for X"
  912.10 +MAINTAINER="devel@slitaz.org"
  912.11 +LICENSE="MIT"
  912.12 +WEB_SITE="https://www.x.org/wiki/"
  912.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  912.14 +
  912.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  912.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  912.17 +TARBALL_SHA1="77062c08a23cfca76824b7e8f9860678255d6b1a"
  912.18 +
  912.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto"
  912.20 +DEPENDS="libx11"
  912.21 +
  912.22 +compile_rules() {
  912.23 +	./configure $CONFIGURE_ARGS &&
  912.24 +	make &&
  912.25 +	make install
  912.26 +}
  912.27 +
  912.28 +TAGS="Xorg"
  912.29 +
  912.30 +PROVIDE="xorg-xprop"
   913.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   913.2 +++ b/xrandr/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   913.3 @@ -0,0 +1,1 @@
   913.4 +../xorg/.icon.png
   913.5 \ No newline at end of file
   914.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   914.2 +++ b/xrandr/receipt	Thu Dec 20 17:55:43 2018 +0200
   914.3 @@ -0,0 +1,27 @@
   914.4 +# SliTaz package receipt v2.
   914.5 +
   914.6 +PACKAGE="xrandr"
   914.7 +VERSION="1.5.0"
   914.8 +CATEGORY="x-window"
   914.9 +SHORT_DESC="Primitive command line interface to RandR extension"
  914.10 +MAINTAINER="devel@slitaz.org"
  914.11 +LICENSE="MIT"
  914.12 +WEB_SITE="https://www.x.org/wiki/"
  914.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  914.14 +
  914.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  914.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  914.17 +TARBALL_SHA1="f402b2ed85817c2e111afafd6f5d0657328be2fa"
  914.18 +
  914.19 +BUILD_DEPENDS="util-macros libxrandr-dev libxrender-dev libx11-dev xorgproto"
  914.20 +DEPENDS="libx11 libxrandr"
  914.21 +
  914.22 +compile_rules() {
  914.23 +	./configure $CONFIGURE_ARGS &&
  914.24 +	make &&
  914.25 +	make install
  914.26 +}
  914.27 +
  914.28 +TAGS="Xorg"
  914.29 +
  914.30 +PROVIDE="xorg-xrandr"
   915.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   915.2 +++ b/xrdb/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   915.3 @@ -0,0 +1,1 @@
   915.4 +../xorg/.icon.png
   915.5 \ No newline at end of file
   916.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   916.2 +++ b/xrdb/receipt	Thu Dec 20 17:55:43 2018 +0200
   916.3 @@ -0,0 +1,29 @@
   916.4 +# SliTaz package receipt v2.
   916.5 +
   916.6 +PACKAGE="xrdb"
   916.7 +VERSION="1.1.1"
   916.8 +CATEGORY="x-window"
   916.9 +SHORT_DESC="X server resource database utility"
  916.10 +MAINTAINER="devel@slitaz.org"
  916.11 +LICENSE="MIT"
  916.12 +WEB_SITE="https://www.x.org/wiki/"
  916.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  916.14 +
  916.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  916.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  916.17 +TARBALL_SHA1="0d6b1cae357574d565d6e6bc10f6ccf073e1b9dd"
  916.18 +
  916.19 +BUILD_DEPENDS="util-macros libxmu-dev libx11-dev xorgproto"
  916.20 +DEPENDS="libx11 libxmu"
  916.21 +
  916.22 +compile_rules() {
  916.23 +	touch /root/missing /missing
  916.24 +
  916.25 +	./configure $CONFIGURE_ARGS &&
  916.26 +	make &&
  916.27 +	make install
  916.28 +}
  916.29 +
  916.30 +TAGS="Xorg"
  916.31 +
  916.32 +PROVIDE="xorg-xrdb"
   917.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   917.2 +++ b/xrefresh/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   917.3 @@ -0,0 +1,1 @@
   917.4 +../xorg/.icon.png
   917.5 \ No newline at end of file
   918.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   918.2 +++ b/xrefresh/receipt	Thu Dec 20 17:55:43 2018 +0200
   918.3 @@ -0,0 +1,27 @@
   918.4 +# SliTaz package receipt v2.
   918.5 +
   918.6 +PACKAGE="xrefresh"
   918.7 +VERSION="1.0.6"
   918.8 +CATEGORY="x-window"
   918.9 +SHORT_DESC="Refresh all or part of an X screen"
  918.10 +MAINTAINER="al.bobylev@gmail.com"
  918.11 +LICENSE="MIT"
  918.12 +WEB_SITE="https://www.x.org/wiki/"
  918.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  918.14 +
  918.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  918.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  918.17 +TARBALL_SHA1="11eb5b3f905631281d2cedd86a0b666bab0d9bdc"
  918.18 +
  918.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto"
  918.20 +DEPENDS="libx11"
  918.21 +
  918.22 +compile_rules() {
  918.23 +	./configure $CONFIGURE_ARGS &&
  918.24 +	make &&
  918.25 +	make install
  918.26 +}
  918.27 +
  918.28 +TAGS="Xorg"
  918.29 +
  918.30 +PROVIDE="xorg-xrefresh"
   919.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   919.2 +++ b/xset/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   919.3 @@ -0,0 +1,1 @@
   919.4 +../xorg/.icon.png
   919.5 \ No newline at end of file
   920.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   920.2 +++ b/xset/receipt	Thu Dec 20 17:55:43 2018 +0200
   920.3 @@ -0,0 +1,35 @@
   920.4 +# SliTaz package receipt v2.
   920.5 +
   920.6 +PACKAGE="xset"
   920.7 +VERSION="1.2.4"
   920.8 +CATEGORY="x-window"
   920.9 +SHORT_DESC="User preference utility for X"
  920.10 +MAINTAINER="paul@slitaz.org"
  920.11 +LICENSE="MIT"
  920.12 +WEB_SITE="https://www.x.org/wiki/"
  920.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  920.14 +
  920.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  920.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  920.17 +TARBALL_SHA1="41a857f30ff5bb0dfbda1549bb703984344ea228"
  920.18 +
  920.19 +BUILD_DEPENDS="util-macros xorgproto libxmu-dev libxxf86misc-dev \
  920.20 +libxfontcache-dev"
  920.21 +DEPENDS="libx11 libxext libxfontcache libxmu libxxf86misc"
  920.22 +
  920.23 +SUGGESTED="yad"
  920.24 +
  920.25 +compile_rules() {
  920.26 +	touch /root/missing /missing
  920.27 +
  920.28 +	./configure $CONFIGURE_ARGS &&
  920.29 +	make &&
  920.30 +	make install || return 1
  920.31 +
  920.32 +	cp -a $stuff/*.sh $install/usr/bin/
  920.33 +	chown -R 0:0 $install
  920.34 +}
  920.35 +
  920.36 +TAGS="Xorg"
  920.37 +
  920.38 +PROVIDE="xorg-xset"
   921.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   921.2 +++ b/xset/stuff/xorg-xset.desktop	Thu Dec 20 17:55:43 2018 +0200
   921.3 @@ -0,0 +1,11 @@
   921.4 +[Desktop Entry]
   921.5 +Type=Application
   921.6 +Name=Set screensaver timeout
   921.7 +Comment=0(always on), Default settings: 10 min (600 sec)
   921.8 +Name[fr]=Règle l'économiseur d'écran
   921.9 +Comment[fr]=0(écran toujours allumé), Par défaut 10 min (600 s)
  921.10 +Name[ru]=Время отключения монитора
  921.11 +Comment[ru]=0(не выключать), По умолчанию: 10 мин.(600 ceк.)
  921.12 +Icon=preferences-desktop-screensaver
  921.13 +Exec=xset-screensaver.sh
  921.14 +Categories=GTK;Settings;HardwareSettings;
   922.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   922.2 +++ b/xset/stuff/xset-screensaver.sh	Thu Dec 20 17:55:43 2018 +0200
   922.3 @@ -0,0 +1,49 @@
   922.4 +#!/bin/sh
   922.5 +#
   922.6 +[ -z $(which yad) ] && exec yad && exit 0
   922.7 +
   922.8 +case $(id -u) in
   922.9 +	0) path=/etc/xdg ;;
  922.10 +	*) path=${XDG_CONFIG_HOME:-$HOME/.config}
  922.11 +		[ -f "$path/autostart" ] && mv $path/autostart $path/autostart.bak
  922.12 +		[ -d "$path/autostart" ] || mkdir -p $path/autostart ;;
  922.13 +esac
  922.14 +
  922.15 +AutostartFile="$path/autostart/xset-screensaver.desktop"
  922.16 +launcher='/usr/share/applications/xorg-xset.desktop' # Must be same as package name
  922.17 +
  922.18 +exec_d()
  922.19 +{
  922.20 +	cmd=$(cat $AutostartFile | grep Exec | sed 's/Exec=//') ; $cmd
  922.21 +}
  922.22 +
  922.23 +[ -f $AutostartFile ] && exec_d
  922.24 +
  922.25 +case $LC_ALL in
  922.26 +	C|POSIX|en*) lang='=' ;;
  922.27 +	*) lang='\['${LC_ALL%_*}
  922.28 +	grep -q '\['${LC_ALL%_*} $launcher || lang='=' ;;
  922.29 +esac
  922.30 +
  922.31 +
  922.32 +
  922.33 +val=$(yad --title="$(cat $launcher | grep Name$lang | cut -d'=' -f2)" \
  922.34 +	--scale --max-value=18000 --mark="1h.":3600 --buttons-layout=spread \
  922.35 +	--mark="$(cat $launcher | grep Comment$lang | cut -d'=' -f2 | cut -d',' -f1)":0 \
  922.36 +	--mark="120min.(2h.)":7200 --mark="180min.(3h.)":10800 \
  922.37 +	--mark="240min.(4h.)":14400 --mark="300min.(5h.)":18000 \
  922.38 +	--page=1800 --step=60 --geometry=630x42+10+100 \
  922.39 +	--value=$(xset q | grep timeout | cut -d' ' -f5) \
  922.40 +	--window-icon="preferences-desktop-screensaver" )
  922.41 +
  922.42 +[ -z $val ] || cat > $AutostartFile <<EOT
  922.43 +[Desktop Entry]
  922.44 +Type=Application
  922.45 +Name=xset screensaver timeout
  922.46 +Exec=xset dpms $val $val $val s $val $val
  922.47 +EOT
  922.48 +
  922.49 +exec_d
  922.50 +
  922.51 +# Notes: 'xset s' max val is 32767, 'xset dpms' limit is unknown
  922.52 +exit 0
   923.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   923.2 +++ b/xsetmode/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   923.3 @@ -0,0 +1,1 @@
   923.4 +../xorg/.icon.png
   923.5 \ No newline at end of file
   924.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   924.2 +++ b/xsetmode/receipt	Thu Dec 20 17:55:43 2018 +0200
   924.3 @@ -0,0 +1,26 @@
   924.4 +# SliTaz package receipt v2.
   924.5 +
   924.6 +PACKAGE="xsetmode"
   924.7 +VERSION="1.0.0"
   924.8 +CATEGORY="x-window"
   924.9 +SHORT_DESC="Set the mode for an X Input device"
  924.10 +MAINTAINER="al.bobylev@gmail.com"
  924.11 +LICENSE="MIT"
  924.12 +WEB_SITE="https://www.x.org/wiki/"
  924.13 +
  924.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  924.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  924.16 +TARBALL_SHA1="add4e6a91c9d0e7d1a80b3534c64d6b7bf633ea0"
  924.17 +
  924.18 +BUILD_DEPENDS="libxi-dev libx11-dev"
  924.19 +DEPENDS="libx11 libxi"
  924.20 +
  924.21 +compile_rules() {
  924.22 +	./configure $CONFIGURE_ARGS &&
  924.23 +	make &&
  924.24 +	make install
  924.25 +}
  924.26 +
  924.27 +TAGS="Xorg"
  924.28 +
  924.29 +PROVIDE="xorg-xsetmode"
   925.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   925.2 +++ b/xsetpointer/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   925.3 @@ -0,0 +1,1 @@
   925.4 +../xorg/.icon.png
   925.5 \ No newline at end of file
   926.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   926.2 +++ b/xsetpointer/receipt	Thu Dec 20 17:55:43 2018 +0200
   926.3 @@ -0,0 +1,26 @@
   926.4 +# SliTaz package receipt v2.
   926.5 +
   926.6 +PACKAGE="xsetpointer"
   926.7 +VERSION="1.0.1"
   926.8 +CATEGORY="x-window"
   926.9 +SHORT_DESC="Set an X Input device as the main pointer"
  926.10 +MAINTAINER="al.bobylev@gmail.com"
  926.11 +LICENSE="MIT"
  926.12 +WEB_SITE="https://www.x.org/wiki/"
  926.13 +
  926.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  926.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  926.16 +TARBALL_SHA1="a8b01c6f27625a6f6943f9be17b1e5511f69d710"
  926.17 +
  926.18 +BUILD_DEPENDS="libxi-dev libx11-dev xorgproto"
  926.19 +DEPENDS="libx11 libxi"
  926.20 +
  926.21 +compile_rules() {
  926.22 +	./configure $CONFIGURE_ARGS &&
  926.23 +	make &&
  926.24 +	make install
  926.25 +}
  926.26 +
  926.27 +TAGS="Xorg"
  926.28 +
  926.29 +PROVIDE="xorg-xsetpointer"
   927.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   927.2 +++ b/xsetroot/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   927.3 @@ -0,0 +1,1 @@
   927.4 +../xorg/.icon.png
   927.5 \ No newline at end of file
   928.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   928.2 +++ b/xsetroot/receipt	Thu Dec 20 17:55:43 2018 +0200
   928.3 @@ -0,0 +1,32 @@
   928.4 +# SliTaz package receipt v2.
   928.5 +
   928.6 +PACKAGE="xsetroot"
   928.7 +VERSION="1.1.2"
   928.8 +CATEGORY="x-window"
   928.9 +SHORT_DESC="Root window parameter setting utility for X"
  928.10 +MAINTAINER="devel@slitaz.org"
  928.11 +LICENSE="MIT"
  928.12 +WEB_SITE="https://www.x.org/wiki/"
  928.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  928.14 +
  928.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  928.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  928.17 +TARBALL_SHA1="42ab81761823b44974feab86477007c49dbace50"
  928.18 +
  928.19 +BUILD_DEPENDS="util-macros libxmu-dev libx11-dev xbitmaps libxcursor-dev \
  928.20 +xorgproto"
  928.21 +DEPENDS="libx11 libxcursor libxmu"
  928.22 +
  928.23 +compile_rules() {
  928.24 +	./configure $CONFIGURE_ARGS &&
  928.25 +	make &&
  928.26 +	make install
  928.27 +}
  928.28 +
  928.29 +genpkg_rules() {
  928.30 +	copy @std
  928.31 +}
  928.32 +
  928.33 +TAGS="Xorg"
  928.34 +
  928.35 +PROVIDE="xorg-xsetroot"
   929.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   929.2 +++ b/xsm/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   929.3 @@ -0,0 +1,1 @@
   929.4 +../xorg/.icon.png
   929.5 \ No newline at end of file
   930.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   930.2 +++ b/xsm/receipt	Thu Dec 20 17:55:43 2018 +0200
   930.3 @@ -0,0 +1,28 @@
   930.4 +# SliTaz package receipt v2.
   930.5 +
   930.6 +PACKAGE="xsm"
   930.7 +VERSION="1.0.4"
   930.8 +CATEGORY="x-window"
   930.9 +SHORT_DESC="X Session Manager"
  930.10 +MAINTAINER="al.bobylev@gmail.com"
  930.11 +LICENSE="MIT"
  930.12 +WEB_SITE="https://www.x.org/wiki/"
  930.13 +
  930.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  930.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  930.16 +TARBALL_SHA1="dd41234e276fe8b2d0a853879568f73b6d98812a"
  930.17 +
  930.18 +BUILD_DEPENDS="util-macros libx11-dev libxt-dev libice-dev libsm-dev libxaw-dev"
  930.19 +DEPENDS="libice libsm libx11 libxaw libxt"
  930.20 +
  930.21 +CONFIG_FILES="/etc/X11/app-defaults/XSm /etc/X11/xsm/system.xsm"
  930.22 +
  930.23 +compile_rules() {
  930.24 +	./configure $CONFIGURE_ARGS &&
  930.25 +	make &&
  930.26 +	make install
  930.27 +}
  930.28 +
  930.29 +TAGS="Xorg"
  930.30 +
  930.31 +PROVIDE="xorg-xsm"
   931.1 Binary file xterm/.icon.png has changed
   932.1 --- a/xterm/receipt	Thu Dec 13 00:46:54 2018 +0200
   932.2 +++ b/xterm/receipt	Thu Dec 20 17:55:43 2018 +0200
   932.3 @@ -1,29 +1,40 @@
   932.4  # SliTaz package receipt v2.
   932.5  
   932.6  PACKAGE="xterm"
   932.7 -VERSION="330"
   932.8 +VERSION="340"
   932.9  CATEGORY="utilities"
  932.10  SHORT_DESC="X terminal emulator"
  932.11  MAINTAINER="devel@slitaz.org"
  932.12  LICENSE="MIT"
  932.13  WEB_SITE="http://invisible-island.net/xterm/"
  932.14 -COOKOPTS="!pixmaps"
  932.15 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/xterm.html"
  932.16  
  932.17  TARBALL="$PACKAGE-$VERSION.tgz"
  932.18 -WGET_URL="ftp://ftp.invisible-island.net/xterm/$TARBALL"
  932.19 +WGET_URL="http://invisible-mirror.net/archives/xterm/$TARBALL"
  932.20 +TARBALL_SHA1="3b36f08e2af569695a2f04da59b50ddb14c9a895"
  932.21  
  932.22 -BUILD_DEPENDS="ncurses-dev xorg-libXpm-dev xorg-libXinerama-dev \
  932.23 -xorg-libXaw3d-dev xorg-libXcursor-dev freetype-dev expat-dev fontconfig-dev \
  932.24 -xorg-libXft-dev xorg-libXt-dev"
  932.25 +BUILD_DEPENDS="ncurses-dev libxpm-dev libxinerama-dev libxaw3d-dev \
  932.26 +libxcursor-dev freetype-dev expat-dev fontconfig-dev libxft-dev libxt-dev"
  932.27 +DEPENDS="fontconfig ncurses libice libx11 libxaw3d libxft libxinerama libxmu \
  932.28 +libxpm libxt"
  932.29 +
  932.30 +COPY="xterm resize XTerm XTerm-color *.png *.desktop"
  932.31 +TAGS="terminal"
  932.32 +
  932.33 +COOKOPTS="!pixmaps"
  932.34  
  932.35  compile_rules() {
  932.36  	export LDFLAGS="$LDFLAGS -Wl,--copy-dt-needed-entries"
  932.37 +	sed -i '/v0/{n;s/new:/new:kb=^?:/}' termcap
  932.38 +	printf '\tkbs=\\177,\n' >> terminfo
  932.39 +
  932.40 +	TERMINFO=/usr/share/terminfo \
  932.41  	./configure \
  932.42  		--with-icon-symlink \
  932.43  		--disable-desktop \
  932.44  		--with-x \
  932.45  		--with-Xaw3d \
  932.46 -		--with-app-defaults=/usr/share/X11/app-defaults \
  932.47 +		--with-app-defaults=/etc/X11/app-defaults \
  932.48  		--enable-wide-chars \
  932.49  		--enable-freetype \
  932.50  		--enable-doublechars \
  932.51 @@ -61,10 +72,3 @@
  932.52  testsuite() {
  932.53  	readelf -h $install/usr/bin/xterm
  932.54  }
  932.55 -
  932.56 -genpkg_rules() {
  932.57 -	copy xterm resize XTerm XTerm-color *.png
  932.58 -	TAGS="terminal"
  932.59 -	DEPENDS="fontconfig ncurses xorg-libICE xorg-libX11 xorg-libXaw3d \
  932.60 -	xorg-libXft xorg-libXinerama xorg-libXmu xorg-libXpm xorg-libXt"
  932.61 -}
   933.1 --- a/xterm/stuff/xterm.desktop	Thu Dec 13 00:46:54 2018 +0200
   933.2 +++ b/xterm/stuff/xterm.desktop	Thu Dec 20 17:55:43 2018 +0200
   933.3 @@ -1,8 +1,7 @@
   933.4  [Desktop Entry]
   933.5  Type=Application
   933.6 -Name=XTerm Terminal
   933.7 -Name[fr]=Terminal Xterm
   933.8 -Name[ru]=Терминал XTerm
   933.9 +Name=XTerm
  933.10 +Comment=Standard terminal emulator for the X window system
  933.11  Exec=xterm -ls
  933.12 -Icon=utilities-terminal
  933.13 +Icon=xterm
  933.14  Categories=System;TerminalEmulator;
   934.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   934.2 +++ b/xtrans/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   934.3 @@ -0,0 +1,1 @@
   934.4 +../xorg/.icon.png
   934.5 \ No newline at end of file
   935.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   935.2 +++ b/xtrans/receipt	Thu Dec 20 17:55:43 2018 +0200
   935.3 @@ -0,0 +1,28 @@
   935.4 +# SliTaz package receipt v2.
   935.5 +
   935.6 +PACKAGE="xtrans"
   935.7 +VERSION="1.3.5"
   935.8 +CATEGORY="development"
   935.9 +SHORT_DESC="X Network Transport layer shared code"
  935.10 +MAINTAINER="devel@slitaz.org"
  935.11 +LICENSE="other"
  935.12 +WEB_SITE="https://www.x.org/wiki/"
  935.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7lib.html"
  935.14 +HOST_ARCH="any"
  935.15 +
  935.16 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  935.17 +WGET_URL="$XORG_MIRROR/lib/$TARBALL"
  935.18 +TARBALL_SHA1="2d3ae1839d841f568bc481c6116af7d2a9f9ba59"
  935.19 +
  935.20 +COPY="@dev"
  935.21 +DEPENDS="xorgproto"
  935.22 +
  935.23 +compile_rules() {
  935.24 +	./configure $CONFIGURE_ARGS &&
  935.25 +	make &&
  935.26 +	make install
  935.27 +}
  935.28 +
  935.29 +TAGS="Xorg"
  935.30 +
  935.31 +PROVIDE="xorg-xtrans"
   936.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   936.2 +++ b/xvidtune/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   936.3 @@ -0,0 +1,1 @@
   936.4 +../xorg/.icon.png
   936.5 \ No newline at end of file
   937.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   937.2 +++ b/xvidtune/receipt	Thu Dec 20 17:55:43 2018 +0200
   937.3 @@ -0,0 +1,29 @@
   937.4 +# SliTaz package receipt v2.
   937.5 +
   937.6 +PACKAGE="xvidtune"
   937.7 +VERSION="1.0.3"
   937.8 +CATEGORY="x-window"
   937.9 +SHORT_DESC="Video mode tuner for Xorg"
  937.10 +MAINTAINER="al.bobylev@gmail.com"
  937.11 +LICENSE="MIT"
  937.12 +WEB_SITE="https://www.x.org/wiki/"
  937.13 +
  937.14 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  937.15 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  937.16 +TARBALL_SHA1="5ed9967f61cb7f6698fc6da6a2ca7afc5305468d"
  937.17 +
  937.18 +BUILD_DEPENDS="util-macros libxxf86vm-dev libxt-dev libxaw-dev libxmu-dev \
  937.19 +libx11-dev"
  937.20 +DEPENDS="libx11 libxaw libxmu libxt libxxf86vm"
  937.21 +
  937.22 +CONFIG_FILES="/etc/X11/app-defaults/Xvidtune"
  937.23 +
  937.24 +compile_rules() {
  937.25 +	./configure $CONFIGURE_ARGS &&
  937.26 +	make &&
  937.27 +	make install
  937.28 +}
  937.29 +
  937.30 +TAGS="Xorg"
  937.31 +
  937.32 +PROVIDE="xorg-xvidtune"
   938.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   938.2 +++ b/xvinfo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   938.3 @@ -0,0 +1,1 @@
   938.4 +../xorg/.icon.png
   938.5 \ No newline at end of file
   939.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   939.2 +++ b/xvinfo/receipt	Thu Dec 20 17:55:43 2018 +0200
   939.3 @@ -0,0 +1,27 @@
   939.4 +# SliTaz package receipt v2.
   939.5 +
   939.6 +PACKAGE="xvinfo"
   939.7 +VERSION="1.1.3"
   939.8 +CATEGORY="x-window"
   939.9 +SHORT_DESC="Print out X-Video extension adaptor information"
  939.10 +MAINTAINER="al.bobylev@gmail.com"
  939.11 +LICENSE="MIT"
  939.12 +WEB_SITE="https://www.x.org/wiki/"
  939.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  939.14 +
  939.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  939.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  939.17 +TARBALL_SHA1="08ff744f7735317fd2fe1b0d2feba8c34cc2e5eb"
  939.18 +
  939.19 +BUILD_DEPENDS="util-macros libxv-dev libx11-dev xorgproto"
  939.20 +DEPENDS="libx11 libxv"
  939.21 +
  939.22 +compile_rules() {
  939.23 +	./configure $CONFIGURE_ARGS &&
  939.24 +	make &&
  939.25 +	make install
  939.26 +}
  939.27 +
  939.28 +TAGS="Xorg"
  939.29 +
  939.30 +PROVIDE="xorg-xvinfo"
   940.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   940.2 +++ b/xwd/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   940.3 @@ -0,0 +1,1 @@
   940.4 +../xorg/.icon.png
   940.5 \ No newline at end of file
   941.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   941.2 +++ b/xwd/receipt	Thu Dec 20 17:55:43 2018 +0200
   941.3 @@ -0,0 +1,27 @@
   941.4 +# SliTaz package receipt v2.
   941.5 +
   941.6 +PACKAGE="xwd"
   941.7 +VERSION="1.0.7"
   941.8 +CATEGORY="x-window"
   941.9 +SHORT_DESC="Dump current contents of X window or screen to file"
  941.10 +MAINTAINER="al.bobylev@gmail.com"
  941.11 +LICENSE="MIT"
  941.12 +WEB_SITE="https://www.x.org/wiki/"
  941.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  941.14 +
  941.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  941.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  941.17 +TARBALL_SHA1="65ce0617be29687cf6082c3a0e85d15a0dcccda9"
  941.18 +
  941.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto libxkbfile-dev"
  941.20 +DEPENDS="libx11 libxkbfile"
  941.21 +
  941.22 +compile_rules() {
  941.23 +	./configure $CONFIGURE_ARGS &&
  941.24 +	make &&
  941.25 +	make install
  941.26 +}
  941.27 +
  941.28 +TAGS="Xorg"
  941.29 +
  941.30 +PROVIDE="xorg-xwd"
   942.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   942.2 +++ b/xwininfo/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   942.3 @@ -0,0 +1,1 @@
   942.4 +../xorg/.icon.png
   942.5 \ No newline at end of file
   943.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   943.2 +++ b/xwininfo/receipt	Thu Dec 20 17:55:43 2018 +0200
   943.3 @@ -0,0 +1,27 @@
   943.4 +# SliTaz package receipt v2.
   943.5 +
   943.6 +PACKAGE="xwininfo"
   943.7 +VERSION="1.1.4"
   943.8 +CATEGORY="x-window"
   943.9 +SHORT_DESC="Window information utility for X"
  943.10 +MAINTAINER="devel@slitaz.org"
  943.11 +LICENSE="MIT"
  943.12 +WEB_SITE="https://www.x.org/wiki/"
  943.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  943.14 +
  943.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  943.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  943.17 +TARBALL_SHA1="7364e79d1de7bb612dd98c336c649648c6c081ca"
  943.18 +
  943.19 +BUILD_DEPENDS="util-macros libxcb-dev libx11-dev"
  943.20 +DEPENDS="libxcb"
  943.21 +
  943.22 +compile_rules() {
  943.23 +	./configure $CONFIGURE_ARGS &&
  943.24 +	make &&
  943.25 +	make install
  943.26 +}
  943.27 +
  943.28 +TAGS="Xorg"
  943.29 +
  943.30 +PROVIDE="xorg-xwininfo"
   944.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   944.2 +++ b/xwud/.icon.png	Thu Dec 20 17:55:43 2018 +0200
   944.3 @@ -0,0 +1,1 @@
   944.4 +../xorg/.icon.png
   944.5 \ No newline at end of file
   945.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   945.2 +++ b/xwud/receipt	Thu Dec 20 17:55:43 2018 +0200
   945.3 @@ -0,0 +1,27 @@
   945.4 +# SliTaz package receipt v2.
   945.5 +
   945.6 +PACKAGE="xwud"
   945.7 +VERSION="1.0.5"
   945.8 +CATEGORY="x-window"
   945.9 +SHORT_DESC="Display an X window dump from xwd"
  945.10 +MAINTAINER="al.bobylev@gmail.com"
  945.11 +LICENSE="MIT"
  945.12 +WEB_SITE="https://www.x.org/wiki/"
  945.13 +LFS="http://www.linuxfromscratch.org/blfs/view/svn/x/x7app.html"
  945.14 +
  945.15 +TARBALL="$PACKAGE-$VERSION.tar.bz2"
  945.16 +WGET_URL="$XORG_MIRROR/app/$TARBALL"
  945.17 +TARBALL_SHA1="a85d84a1b81f8e667ea6ac126d447590c93eb079"
  945.18 +
  945.19 +BUILD_DEPENDS="util-macros libx11-dev xorgproto"
  945.20 +DEPENDS="libx11"
  945.21 +
  945.22 +compile_rules() {
  945.23 +	./configure $CONFIGURE_ARGS &&
  945.24 +	make &&
  945.25 +	make install
  945.26 +}
  945.27 +
  945.28 +TAGS="Xorg"
  945.29 +
  945.30 +PROVIDE="xorg-xwud"
   946.1 --- a/yaml/receipt	Thu Dec 13 00:46:54 2018 +0200
   946.2 +++ b/yaml/receipt	Thu Dec 20 17:55:43 2018 +0200
   946.3 @@ -1,7 +1,7 @@
   946.4  # SliTaz package receipt v2.
   946.5  
   946.6  PACKAGE="yaml"
   946.7 -VERSION="0.1.7"
   946.8 +VERSION="0.2.1"
   946.9  CATEGORY="system-tools"
  946.10  SHORT_DESC="YAML 1.1 parser and emitter written in C"
  946.11  MAINTAINER="devel@slitaz.org"
  946.12 @@ -11,6 +11,7 @@
  946.13  
  946.14  TARBALL="$PACKAGE-$VERSION.tar.gz"
  946.15  WGET_URL="http://pyyaml.org/download/libyaml/$TARBALL"
  946.16 +TARBALL_SHA1="125a3113681f06320dcdfde48bab47cba9031263"
  946.17  
  946.18  SPLIT="$PACKAGE-dev"
  946.19  
  946.20 @@ -22,10 +23,3 @@
  946.21  	make &&
  946.22  	make install
  946.23  }
  946.24 -
  946.25 -genpkg_rules() {
  946.26 -	case $PACKAGE in
  946.27 -		yaml)  copy @std;;
  946.28 -		*-dev) copy @dev;;
  946.29 -	esac
  946.30 -}