summaryrefslogtreecommitdiff
path: root/xserver/exa
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2010-07-27 19:02:39 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2010-07-27 19:02:39 +0000
commit269d40cbcc43b41f621ca6d91c182952f60ec48e (patch)
tree872f2fddd3f2207e57a28595e73886713ce4a77a /xserver/exa
parent917a2249b787451cad3f9697872aeccfd0da3324 (diff)
Update to xserver 1.8. Tested by many. Ok oga@, todd@.
Diffstat (limited to 'xserver/exa')
-rw-r--r--xserver/exa/Makefile.am7
-rw-r--r--xserver/exa/Makefile.in112
-rw-r--r--xserver/exa/exa.c929
-rw-r--r--xserver/exa/exa.h121
-rw-r--r--xserver/exa/exa_accel.c382
-rw-r--r--xserver/exa/exa_classic.c267
-rw-r--r--xserver/exa/exa_driver.c225
-rw-r--r--xserver/exa/exa_glyphs.c363
-rw-r--r--xserver/exa/exa_migration_classic.c (renamed from xserver/exa/exa_migration.c)199
-rw-r--r--xserver/exa/exa_migration_mixed.c261
-rw-r--r--xserver/exa/exa_mixed.c291
-rw-r--r--xserver/exa/exa_offscreen.c226
-rw-r--r--xserver/exa/exa_priv.h274
-rw-r--r--xserver/exa/exa_render.c549
-rw-r--r--xserver/exa/exa_unaccel.c596
15 files changed, 3421 insertions, 1381 deletions
diff --git a/xserver/exa/Makefile.am b/xserver/exa/Makefile.am
index 2b3f1e416..8b759cd76 100644
--- a/xserver/exa/Makefile.am
+++ b/xserver/exa/Makefile.am
@@ -17,11 +17,14 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
libexa_la_SOURCES = \
exa.c \
exa.h \
+ exa_classic.c \
+ exa_migration_classic.c \
+ exa_driver.c \
+ exa_mixed.c \
+ exa_migration_mixed.c \
exa_accel.c \
exa_glyphs.c \
- exa_migration.c \
exa_offscreen.c \
exa_render.c \
exa_priv.h \
exa_unaccel.c
-
diff --git a/xserver/exa/Makefile.in b/xserver/exa/Makefile.in
index fbcf99abf..eb93398ad 100644
--- a/xserver/exa/Makefile.in
+++ b/xserver/exa/Makefile.in
@@ -41,8 +41,8 @@ subdir = exa
DIST_COMMON = $(am__sdk_HEADERS_DIST) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/configure.ac
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \
+ $(top_srcdir)/m4/dolt.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(install_sh) -d
@@ -52,14 +52,16 @@ CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
$(top_builddir)/include/xorg-config.h \
$(top_builddir)/include/xkb-config.h \
$(top_builddir)/include/xwin-config.h \
- $(top_builddir)/include/kdrive-config.h
+ $(top_builddir)/include/kdrive-config.h \
+ $(top_builddir)/include/version-config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libexa_la_LIBADD =
-am_libexa_la_OBJECTS = exa.lo exa_accel.lo exa_glyphs.lo \
- exa_migration.lo exa_offscreen.lo exa_render.lo exa_unaccel.lo
+am_libexa_la_OBJECTS = exa.lo exa_classic.lo exa_migration_classic.lo \
+ exa_driver.lo exa_mixed.lo exa_migration_mixed.lo exa_accel.lo \
+ exa_glyphs.lo exa_offscreen.lo exa_render.lo exa_unaccel.lo
libexa_la_OBJECTS = $(am_libexa_la_OBJECTS)
-DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@@ -95,12 +97,13 @@ ALPHA_VIDEO_TRUE = @ALPHA_VIDEO_TRUE@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
-APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@
APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@
APP_MAN_DIR = @APP_MAN_DIR@
APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
AR = @AR@
+ARM_BACKTRACE_CFLAGS = @ARM_BACKTRACE_CFLAGS@
ARM_VIDEO_FALSE = @ARM_VIDEO_FALSE@
ARM_VIDEO_TRUE = @ARM_VIDEO_TRUE@
AS = @AS@
@@ -128,6 +131,7 @@ CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CHANGELOG_CMD = @CHANGELOG_CMD@
COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
COMPOSITE_FALSE = @COMPOSITE_FALSE@
COMPOSITE_TRUE = @COMPOSITE_TRUE@
@@ -137,8 +141,11 @@ CONFIG_HAL_FALSE = @CONFIG_HAL_FALSE@
CONFIG_HAL_TRUE = @CONFIG_HAL_TRUE@
CONFIG_NEED_DBUS_FALSE = @CONFIG_NEED_DBUS_FALSE@
CONFIG_NEED_DBUS_TRUE = @CONFIG_NEED_DBUS_TRUE@
+CONFIG_UDEV_FALSE = @CONFIG_UDEV_FALSE@
+CONFIG_UDEV_TRUE = @CONFIG_UDEV_TRUE@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+CWARNFLAGS = @CWARNFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
@@ -152,6 +159,7 @@ DBUS_LIBS = @DBUS_LIBS@
DEBUG_FALSE = @DEBUG_FALSE@
DEBUG_TRUE = @DEBUG_TRUE@
DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@
+DEFAULT_LOGDIR = @DEFAULT_LOGDIR@
DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@
DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@
DEFS = @DEFS@
@@ -161,7 +169,9 @@ DGA_FALSE = @DGA_FALSE@
DGA_LIBS = @DGA_LIBS@
DGA_TRUE = @DGA_TRUE@
DIX_CFLAGS = @DIX_CFLAGS@
+DIX_LIB = @DIX_LIB@
DLLTOOL = @DLLTOOL@
+DLOPEN_LIBS = @DLOPEN_LIBS@
DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@
DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@
DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@
@@ -177,6 +187,7 @@ DMX_BUILD_USB_TRUE = @DMX_BUILD_USB_TRUE@
DMX_FALSE = @DMX_FALSE@
DMX_TRUE = @DMX_TRUE@
DOLT_BASH = @DOLT_BASH@
+DOXYGEN = @DOXYGEN@
DPMSExtension_FALSE = @DPMSExtension_FALSE@
DPMSExtension_TRUE = @DPMSExtension_TRUE@
DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
@@ -189,8 +200,10 @@ DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@
DRIPROTO_LIBS = @DRIPROTO_LIBS@
DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRI_CFLAGS = @DRI_CFLAGS@
DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
DRI_FALSE = @DRI_FALSE@
+DRI_LIBS = @DRI_LIBS@
DRI_TRUE = @DRI_TRUE@
DSYMUTIL = @DSYMUTIL@
DTRACE = @DTRACE@
@@ -206,8 +219,17 @@ FBDEVHW_TRUE = @FBDEVHW_TRUE@
FFLAGS = @FFLAGS@
FILE_MAN_DIR = @FILE_MAN_DIR@
FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+FONT100DPIDIR = @FONT100DPIDIR@
+FONT75DPIDIR = @FONT75DPIDIR@
+FONTMISCDIR = @FONTMISCDIR@
+FONTOTFDIR = @FONTOTFDIR@
+FONTROOTDIR = @FONTROOTDIR@
+FONTTTFDIR = @FONTTTFDIR@
+FONTTYPE1DIR = @FONTTYPE1DIR@
FREEBSD_KLDLOAD_FALSE = @FREEBSD_KLDLOAD_FALSE@
FREEBSD_KLDLOAD_TRUE = @FREEBSD_KLDLOAD_TRUE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
GLX_DEFINES = @GLX_DEFINES@
GLX_FALSE = @GLX_FALSE@
@@ -217,18 +239,17 @@ GL_LIBS = @GL_LIBS@
GREP = @GREP@
HAL_CFLAGS = @HAL_CFLAGS@
HAL_LIBS = @HAL_LIBS@
-HAVE_AGL_FRAMEWORK_FALSE = @HAVE_AGL_FRAMEWORK_FALSE@
-HAVE_AGL_FRAMEWORK_TRUE = @HAVE_AGL_FRAMEWORK_TRUE@
HAVE_DBUS_FALSE = @HAVE_DBUS_FALSE@
HAVE_DBUS_TRUE = @HAVE_DBUS_TRUE@
-HAVE_XPLUGIN_FALSE = @HAVE_XPLUGIN_FALSE@
-HAVE_XPLUGIN_TRUE = @HAVE_XPLUGIN_TRUE@
+HAVE_DOXYGEN_FALSE = @HAVE_DOXYGEN_FALSE@
+HAVE_DOXYGEN_TRUE = @HAVE_DOXYGEN_TRUE@
HP300_VIDEO_FALSE = @HP300_VIDEO_FALSE@
HP300_VIDEO_TRUE = @HP300_VIDEO_TRUE@
HPPA_VIDEO_FALSE = @HPPA_VIDEO_FALSE@
HPPA_VIDEO_TRUE = @HPPA_VIDEO_TRUE@
I386_VIDEO_FALSE = @I386_VIDEO_FALSE@
I386_VIDEO_TRUE = @I386_VIDEO_TRUE@
+INSTALL_CMD = @INSTALL_CMD@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_LIBXF86CONFIG_FALSE = @INSTALL_LIBXF86CONFIG_FALSE@
INSTALL_LIBXF86CONFIG_TRUE = @INSTALL_LIBXF86CONFIG_TRUE@
@@ -237,6 +258,8 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_SETUID_FALSE = @INSTALL_SETUID_FALSE@
INSTALL_SETUID_TRUE = @INSTALL_SETUID_TRUE@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INT10MODULE_FALSE = @INT10MODULE_FALSE@
+INT10MODULE_TRUE = @INT10MODULE_TRUE@
INT10_STUB_FALSE = @INT10_STUB_FALSE@
INT10_STUB_TRUE = @INT10_STUB_TRUE@
INT10_VM86_FALSE = @INT10_VM86_FALSE@
@@ -249,20 +272,23 @@ KDRIVELINUX_FALSE = @KDRIVELINUX_FALSE@
KDRIVELINUX_TRUE = @KDRIVELINUX_TRUE@
KDRIVEOPENBSD_FALSE = @KDRIVEOPENBSD_FALSE@
KDRIVEOPENBSD_TRUE = @KDRIVEOPENBSD_TRUE@
-KDRIVEVESA_FALSE = @KDRIVEVESA_FALSE@
-KDRIVEVESA_TRUE = @KDRIVEVESA_TRUE@
KDRIVEWSCONS_FALSE = @KDRIVEWSCONS_FALSE@
KDRIVEWSCONS_TRUE = @KDRIVEWSCONS_TRUE@
KDRIVE_CFLAGS = @KDRIVE_CFLAGS@
+KDRIVE_EVDEV_FALSE = @KDRIVE_EVDEV_FALSE@
+KDRIVE_EVDEV_TRUE = @KDRIVE_EVDEV_TRUE@
KDRIVE_FALSE = @KDRIVE_FALSE@
-KDRIVE_HW_FALSE = @KDRIVE_HW_FALSE@
-KDRIVE_HW_TRUE = @KDRIVE_HW_TRUE@
KDRIVE_INCS = @KDRIVE_INCS@
+KDRIVE_KBD_FALSE = @KDRIVE_KBD_FALSE@
+KDRIVE_KBD_TRUE = @KDRIVE_KBD_TRUE@
KDRIVE_LIBS = @KDRIVE_LIBS@
KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@
+KDRIVE_MOUSE_FALSE = @KDRIVE_MOUSE_FALSE@
+KDRIVE_MOUSE_TRUE = @KDRIVE_MOUSE_TRUE@
KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@
KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@
KDRIVE_TRUE = @KDRIVE_TRUE@
+LAUNCHD_ID_PREFIX = @LAUNCHD_ID_PREFIX@
LDFLAGS = @LDFLAGS@
LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@
LEX = @LEX@
@@ -291,12 +317,12 @@ LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAIN_LIB = @MAIN_LIB@
MAKEINFO = @MAKEINFO@
MAKE_HTML = @MAKE_HTML@
MAKE_PDF = @MAKE_PDF@
MAKE_PS = @MAKE_PS@
MAKE_TEXT = @MAKE_TEXT@
-MESA_SOURCE = @MESA_SOURCE@
MISC_MAN_DIR = @MISC_MAN_DIR@
MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
MITSHM_FALSE = @MITSHM_FALSE@
@@ -315,6 +341,9 @@ OBJCFLAGS = @OBJCFLAGS@
OBJCLINK = @OBJCLINK@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OS_LIB = @OS_LIB@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -343,10 +372,14 @@ SCREENSAVER_TRUE = @SCREENSAVER_TRUE@
SECURE_RPC_FALSE = @SECURE_RPC_FALSE@
SECURE_RPC_TRUE = @SECURE_RPC_TRUE@
SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@
SET_MAKE = @SET_MAKE@
SGI_VIDEO_FALSE = @SGI_VIDEO_FALSE@
SGI_VIDEO_TRUE = @SGI_VIDEO_TRUE@
+SHA1_CFLAGS = @SHA1_CFLAGS@
+SHA1_LIBS = @SHA1_LIBS@
SHELL = @SHELL@
# Override these since EXA doesn't need them and the needed files aren't
@@ -355,25 +388,38 @@ SOLARIS_ASM_CFLAGS = ""
SOLARIS_ASM_INLINE_FALSE = @SOLARIS_ASM_INLINE_FALSE@
SOLARIS_ASM_INLINE_TRUE = @SOLARIS_ASM_INLINE_TRUE@
SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@
-SOLARIS_USL_CONSOLE_FALSE = @SOLARIS_USL_CONSOLE_FALSE@
-SOLARIS_USL_CONSOLE_TRUE = @SOLARIS_USL_CONSOLE_TRUE@
+SOLARIS_VT_FALSE = @SOLARIS_VT_FALSE@
+SOLARIS_VT_TRUE = @SOLARIS_VT_TRUE@
SPARC64_VIDEO_FALSE = @SPARC64_VIDEO_FALSE@
SPARC64_VIDEO_TRUE = @SPARC64_VIDEO_TRUE@
+SPECIAL_DTRACE_OBJECTS_FALSE = @SPECIAL_DTRACE_OBJECTS_FALSE@
+SPECIAL_DTRACE_OBJECTS_TRUE = @SPECIAL_DTRACE_OBJECTS_TRUE@
STANDALONE_XPBPROXY_FALSE = @STANDALONE_XPBPROXY_FALSE@
STANDALONE_XPBPROXY_TRUE = @STANDALONE_XPBPROXY_TRUE@
STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
TSLIB_CFLAGS = @TSLIB_CFLAGS@
TSLIB_FALSE = @TSLIB_FALSE@
TSLIB_LIBS = @TSLIB_LIBS@
TSLIB_TRUE = @TSLIB_TRUE@
+UDEV_CFLAGS = @UDEV_CFLAGS@
+UDEV_LIBS = @UDEV_LIBS@
+UNITTESTS_FALSE = @UNITTESTS_FALSE@
+UNITTESTS_TRUE = @UNITTESTS_TRUE@
UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
-VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@
-VENDOR_NAME = @VENDOR_NAME@
+VBE_FALSE = @VBE_FALSE@
+VBE_TRUE = @VBE_TRUE@
VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
-VENDOR_RELEASE = @VENDOR_RELEASE@
VERSION = @VERSION@
+VGAHW_FALSE = @VGAHW_FALSE@
+VGAHW_TRUE = @VGAHW_TRUE@
+WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@
+WINDOWSWM_LIBS = @WINDOWSWM_LIBS@
+WINDRES = @WINDRES@
X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
+XAA_FALSE = @XAA_FALSE@
+XAA_TRUE = @XAA_TRUE@
XACE_FALSE = @XACE_FALSE@
XACE_TRUE = @XACE_TRUE@
XCALIBRATE_FALSE = @XCALIBRATE_FALSE@
@@ -398,6 +444,7 @@ XEPHYR_LIBS = @XEPHYR_LIBS@
XEPHYR_TRUE = @XEPHYR_TRUE@
XF86BIGFONT_FALSE = @XF86BIGFONT_FALSE@
XF86BIGFONT_TRUE = @XF86BIGFONT_TRUE@
+XF86CONFIGDIR = @XF86CONFIGDIR@
XF86CONFIGFILE = @XF86CONFIGFILE@
XF86UTILS_FALSE = @XF86UTILS_FALSE@
XF86UTILS_TRUE = @XF86UTILS_TRUE@
@@ -440,15 +487,14 @@ XORG_TRUE = @XORG_TRUE@
XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@
XPBPROXY_LIBS = @XPBPROXY_LIBS@
XQUARTZ_FALSE = @XQUARTZ_FALSE@
+XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@
+XQUARTZ_SPARKLE_FALSE = @XQUARTZ_SPARKLE_FALSE@
+XQUARTZ_SPARKLE_TRUE = @XQUARTZ_SPARKLE_TRUE@
XQUARTZ_TRUE = @XQUARTZ_TRUE@
XREGISTRY_FALSE = @XREGISTRY_FALSE@
XREGISTRY_TRUE = @XREGISTRY_TRUE@
XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@
-XSDLSERVER_FALSE = @XSDLSERVER_FALSE@
-XSDLSERVER_TRUE = @XSDLSERVER_TRUE@
-XSDL_INCS = @XSDL_INCS@
-XSDL_LIBS = @XSDL_LIBS@
XSELINUX_FALSE = @XSELINUX_FALSE@
XSELINUX_TRUE = @XSELINUX_TRUE@
XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@
@@ -496,10 +542,10 @@ X_PRIVSEP_FALSE = @X_PRIVSEP_FALSE@
X_PRIVSEP_TRUE = @X_PRIVSEP_TRUE@
YACC = @YACC@
YFLAGS = @YFLAGS@
+__XCONFIGDIR__ = @__XCONFIGDIR__@
__XCONFIGFILE__ = @__XCONFIGFILE__@
abi_ansic = @abi_ansic@
abi_extension = @abi_extension@
-abi_font = @abi_font@
abi_videodrv = @abi_videodrv@
abi_xinput = @abi_xinput@
ac_ct_CC = @ac_ct_CC@
@@ -554,7 +600,9 @@ psdir = @psdir@
sbindir = @sbindir@
sdkdir = @sdkdir@
sharedstatedir = @sharedstatedir@
+symbol_visibility = @symbol_visibility@
sysconfdir = @sysconfdir@
+sysconfigdir = @sysconfigdir@
target_alias = @target_alias@
noinst_LTLIBRARIES = libexa.la
@XORG_TRUE@sdk_HEADERS = exa.h
@@ -566,9 +614,13 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
libexa_la_SOURCES = \
exa.c \
exa.h \
+ exa_classic.c \
+ exa_migration_classic.c \
+ exa_driver.c \
+ exa_mixed.c \
+ exa_migration_mixed.c \
exa_accel.c \
exa_glyphs.c \
- exa_migration.c \
exa_offscreen.c \
exa_render.c \
exa_priv.h \
@@ -627,8 +679,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_accel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_classic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_driver.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_glyphs.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_migration.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_migration_classic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_migration_mixed.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_mixed.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_offscreen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_render.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_unaccel.Plo@am__quote@
diff --git a/xserver/exa/exa.c b/xserver/exa/exa.c
index 270810766..590d9a500 100644
--- a/xserver/exa/exa.c
+++ b/xserver/exa/exa.c
@@ -41,22 +41,13 @@ static int exaScreenPrivateKeyIndex;
DevPrivateKey exaScreenPrivateKey = &exaScreenPrivateKeyIndex;
static int exaPixmapPrivateKeyIndex;
DevPrivateKey exaPixmapPrivateKey = &exaPixmapPrivateKeyIndex;
+static int exaGCPrivateKeyIndex;
+DevPrivateKey exaGCPrivateKey = &exaGCPrivateKeyIndex;
#ifdef MITSHM
static ShmFuncs exaShmFuncs = { NULL, NULL };
#endif
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
- return pExaPixmap->fb_ptr;
- else
- return pExaPixmap->sys_ptr;
-}
-
/**
* exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
* the beginning of the given pixmap.
@@ -71,9 +62,9 @@ unsigned long
exaGetPixmapOffset(PixmapPtr pPix)
{
ExaScreenPriv (pPix->drawable.pScreen);
+ ExaPixmapPriv (pPix);
- return ((unsigned long)ExaGetPixmapAddress(pPix) -
- (unsigned long)pExaScr->info->memoryBase);
+ return (CARD8 *)pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
}
void *
@@ -129,7 +120,7 @@ exaGetDrawablePixmap(DrawablePtr pDrawable)
return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
else
return (PixmapPtr) pDrawable;
-}
+}
/**
* Sets the offsets to add to coordinates to make them address the same bits in
@@ -159,14 +150,9 @@ exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
void
exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
{
- ExaPixmapPriv(pPix);
BoxRec box;
- RegionPtr pDamageReg;
RegionRec region;
- if (!pExaPixmap || !pExaPixmap->pDamage)
- return;
-
box.x1 = max(x1, 0);
box.y1 = max(y1, 0);
box.x2 = min(x2, pPix->drawable.width);
@@ -175,46 +161,12 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
if (box.x1 >= box.x2 || box.y1 >= box.y2)
return;
- pDamageReg = DamageRegion(pExaPixmap->pDamage);
-
REGION_INIT(pScreen, &region, &box, 1);
- REGION_UNION(pScreen, pDamageReg, pDamageReg, &region);
+ DamageRegionAppend(&pPix->drawable, &region);
+ DamageRegionProcessPending(&pPix->drawable);
REGION_UNINIT(pScreen, &region);
}
-static Bool
-exaDestroyPixmap (PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
-
- if (pPixmap->refcnt == 1)
- {
- ExaPixmapPriv (pPixmap);
-
- if (pExaPixmap->driverPriv) {
- pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
- pExaPixmap->driverPriv = NULL;
- }
-
- if (pExaPixmap->area)
- {
- DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
- (void*)pPixmap->drawable.id,
- ExaGetPixmapPriv(pPixmap)->area->offset,
- pPixmap->drawable.width,
- pPixmap->drawable.height));
- /* Free the offscreen area */
- exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- }
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
- }
- return fbDestroyPixmap (pPixmap);
-}
-
static int
exaLog2(int val)
{
@@ -227,14 +179,14 @@ exaLog2(int val)
return bits - 1;
}
-static void
+void
exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
pExaPixmap->accel_blocked = 0;
if (pExaScr->info->maxPitchPixels) {
- int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8;
+ int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
if (pExaPixmap->fb_pitch > max_pitch)
pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
@@ -251,226 +203,66 @@ exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
}
-static void
+void
exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
- pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8;
+ pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
else
- pExaPixmap->fb_pitch = w * bpp / 8;
+ pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
pExaScr->info->pixmapPitchAlign);
}
/**
- * exaCreatePixmap() creates a new pixmap.
- *
- * If width and height are 0, this won't be a full-fledged pixmap and it will
- * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
- * ModifyPixmapHeader() would break migration. These types of pixmaps are used
- * for scratch pixmaps, or to represent the visible screen.
+ * Returns TRUE if the pixmap is not movable. This is the case where it's a
+ * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
+ * some X Server internal component (the score says it's pinned).
*/
-static PixmapPtr
-exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- int driver_alloc = 0;
- int bpp;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- if (!pExaScr->info->CreatePixmap) {
- pPixmap = fbCreatePixmap (pScreen, w, h, depth, usage_hint);
- } else {
- driver_alloc = 1;
- pPixmap = fbCreatePixmap(pScreen, 0, 0, depth, usage_hint);
- }
-
- if (!pPixmap)
- return NULL;
-
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
- pExaPixmap->driverPriv = NULL;
-
- bpp = pPixmap->drawable.bitsPerPixel;
-
- if (driver_alloc) {
- size_t paddedWidth, datasize;
-
- paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || h > 32767)
- return NullPixmap;
-
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
-
- if (paddedWidth < pExaPixmap->fb_pitch)
- paddedWidth = pExaPixmap->fb_pitch;
-
- datasize = h * paddedWidth;
-
- /* Set this before driver hooks, to allow for !offscreen pixmaps.
- * !offscreen pixmaps have a valid pointer at all times.
- */
- pPixmap->devPrivate.ptr = NULL;
-
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
- if (!pExaPixmap->driverPriv) {
- fbDestroyPixmap(pPixmap);
- return NULL;
- }
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->pDamage = NULL;
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
-
- } else {
- pExaPixmap->driverPriv = NULL;
- /* Scratch pixmaps may have w/h equal to zero, and may not be
- * migrated.
- */
- if (!w || !h)
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- else
- pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
-
- pPixmap->devPrivate.ptr = NULL;
- pExaPixmap->offscreen = FALSE;
-
- pExaPixmap->fb_ptr = NULL;
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
- pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
-
- if (pExaPixmap->fb_pitch > 131071) {
- fbDestroyPixmap(pPixmap);
- return NULL;
- }
-
- /* Set up damage tracking */
- pExaPixmap->pDamage = DamageCreate (NULL, NULL,
- DamageReportNone, TRUE,
- pScreen, pPixmap);
-
- if (pExaPixmap->pDamage == NULL) {
- fbDestroyPixmap (pPixmap);
- return NULL;
- }
-
- DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
- /* This ensures that pending damage reflects the current operation. */
- /* This is used by exa to optimize migration. */
- DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
- }
-
- pExaPixmap->area = NULL;
-
- /* None of the pixmap bits are valid initially */
- REGION_NULL(pScreen, &pExaPixmap->validSys);
- REGION_NULL(pScreen, &pExaPixmap->validFB);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- return pPixmap;
-}
-
-static Bool
-exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
+Bool
+exaPixmapIsPinned (PixmapPtr pPix)
{
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret;
-
- if (!pPixmap)
- return FALSE;
+ ExaPixmapPriv (pPix);
- pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
- if (pExaPixmap) {
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
-
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
-
- if (width > 0 && height > 0 && bitsPerPixel > 0) {
- exaSetFbPitch(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- }
- }
-
-
- if (pExaScr->info->ModifyPixmapHeader) {
- ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- if (ret == TRUE)
- return ret;
- }
- return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
+ return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
}
/**
- * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
+ * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
* with the CPU.
*
* Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
* deal with moving pixmaps in and out of system memory), EXA will give drivers
- * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE.
+ * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE.
*
* @return TRUE if the given drawable is in framebuffer memory.
*/
Bool
-exaPixmapIsOffscreen(PixmapPtr p)
+exaPixmapHasGpuCopy(PixmapPtr pPixmap)
{
- ScreenPtr pScreen = p->drawable.pScreen;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv(pScreen);
- ExaPixmapPriv(p);
- void *save_ptr;
- Bool ret;
-
- save_ptr = p->devPrivate.ptr;
-
- if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
- p->devPrivate.ptr = ExaGetPixmapAddress(p);
- if (pExaScr->info->PixmapIsOffscreen)
- ret = pExaScr->info->PixmapIsOffscreen(p);
- else
- ret = ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
- (CARD8 *) pExaScr->info->memoryBase) <
- pExaScr->info->memorySize);
-
- p->devPrivate.ptr = save_ptr;
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return FALSE;
- return ret;
+ return (*pExaScr->pixmap_has_gpu_copy)(pPixmap);
}
/**
- * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen().
+ * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
*/
Bool
exaDrawableIsOffscreen (DrawablePtr pDrawable)
{
- return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable));
+ return exaPixmapHasGpuCopy (exaGetDrawablePixmap (pDrawable));
}
/**
@@ -484,60 +276,96 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp);
- if (exaPixmapIsOffscreen (pPixmap))
+ if (exaPixmapHasGpuCopy (pPixmap))
return pPixmap;
else
return NULL;
}
-void
-ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
+/**
+ * Returns TRUE if the pixmap GPU copy is being accessed.
+ */
+Bool
+ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
{
- ScreenPtr pScreen = pDrawable->pScreen;
- ExaScreenPriv (pScreen);
- PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
- Bool offscreen = exaPixmapIsOffscreen(pPixmap);
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv (pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool has_gpu_copy, ret;
+ int i;
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return FALSE;
+
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
- /* Unhide pixmap pointer */
- if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
- pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ /* Handle repeated / nested calls. */
+ for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
+ if (pExaScr->access[i].pixmap == pPixmap) {
+ pExaScr->access[i].count++;
+ return pExaScr->access[i].retval;
+ }
}
- if (!offscreen)
- return;
+ /* If slot for this index is taken, find an empty slot */
+ if (pExaScr->access[index].pixmap) {
+ for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--)
+ if (!pExaScr->access[index].pixmap)
+ break;
+ }
+
+ /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
+ if (pPixmap->devPrivate.ptr != NULL) {
+ EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
+ pPixmap->devPrivate.ptr));
+ }
+
+ has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+
+ if (has_gpu_copy && pExaPixmap->fb_ptr) {
+ pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+ ret = TRUE;
+ } else {
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ ret = FALSE;
+ }
+
+ /* Store so we can handle repeated / nested calls. */
+ pExaScr->access[index].pixmap = pPixmap;
+ pExaScr->access[index].count = 1;
+
+ if (!has_gpu_copy)
+ goto out;
- exaWaitSync (pDrawable->pScreen);
+ exaWaitSync (pScreen);
if (pExaScr->info->PrepareAccess == NULL)
- return;
+ goto out;
- if (index >= EXA_PREPARE_AUX0 &&
+ if (index >= EXA_PREPARE_AUX_DEST &&
!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+ FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
exaMoveOutPixmap (pPixmap);
- return;
+ ret = FALSE;
+ goto out;
}
if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
- ExaPixmapPriv (pPixmap);
- if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
- FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
+ !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
+ FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
exaMoveOutPixmap (pPixmap);
+ ret = FALSE;
+ goto out;
}
-}
-
-void
-exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
-{
- ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = index == EXA_PREPARE_DEST;
- pixmaps[0].as_src = index != EXA_PREPARE_DEST;
- pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = pReg;
+ ret = TRUE;
- exaDoMigration(pixmaps, 1, FALSE);
-
- ExaDoPrepareAccess(pDrawable, index);
+out:
+ pExaScr->access[index].retval = ret;
+ return ret;
}
/**
@@ -549,7 +377,13 @@ exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
void
exaPrepareAccess(DrawablePtr pDrawable, int index)
{
- exaPrepareAccessReg(pDrawable, index, NULL);
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaScreenPriv(pDrawable->pScreen);
+
+ if (pExaScr->prepare_access_reg)
+ pExaScr->prepare_access_reg(pPixmap, index, NULL);
+ else
+ (void)ExaDoPrepareAccess(pPixmap, index);
}
/**
@@ -564,109 +398,207 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
ExaScreenPriv (pScreen);
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
+ int i;
- /* Rehide pixmap pointer if we're doing that. */
- if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
- pPixmap->devPrivate.ptr = NULL;
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
+
+ /* Handle repeated / nested calls. */
+ for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
+ if (pExaScr->access[i].pixmap == pPixmap) {
+ if (--pExaScr->access[i].count > 0)
+ return;
+ break;
+ }
}
- if (pExaScr->info->FinishAccess == NULL)
- return;
+ /* Catch unbalanced Prepare/FinishAccess calls. */
+ if (i == EXA_NUM_PREPARE_INDICES)
+ EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
+ pPixmap),);
+
+ pExaScr->access[i].pixmap = NULL;
- if (!exaPixmapIsOffscreen (pPixmap))
+ /* We always hide the devPrivate.ptr. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ if (!pExaScr->info->FinishAccess || !exaPixmapHasGpuCopy(pPixmap))
return;
- if (index >= EXA_PREPARE_AUX0 &&
+ if (i >= EXA_PREPARE_AUX_DEST &&
!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
"unsupported index EXA_PREPARE_AUX*\n");
return;
}
- (*pExaScr->info->FinishAccess) (pPixmap, index);
+ (*pExaScr->info->FinishAccess) (pPixmap, i);
}
/**
- * exaValidateGC() sets the ops to EXA's implementations, which may be
- * accelerated or may sync the card and fall back to fb.
+ * Here begins EXA's GC code.
+ * Do not ever access the fb/mi layer directly.
*/
+
+static void
+exaValidateGC(GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDrawable);
+
+static void
+exaDestroyGC(GCPtr pGC);
+
static void
-exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+exaChangeGC (GCPtr pGC,
+ unsigned long mask);
+
+static void
+exaCopyGC (GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst);
+
+static void
+exaChangeClip (GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects);
+
+static void
+exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
+
+static void
+exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
+
+static void
+exaDestroyClip(GCPtr pGC);
+
+const GCFuncs exaGCFuncs = {
+ exaValidateGC,
+ exaChangeGC,
+ exaCopyGC,
+ exaDestroyGC,
+ exaChangeClip,
+ exaDestroyClip,
+ exaCopyClip
+};
+
+static void
+exaValidateGC(GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDrawable)
{
/* fbValidateGC will do direct access to pixmaps if the tiling has changed.
- * Preempt fbValidateGC by doing its work and masking the change out, so
- * that we can do the Prepare/FinishAccess.
+ * Do a few smart things so fbValidateGC can do it's work.
*/
-#ifdef FB_24_32BIT
- if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
- (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
- fbGetRotatedPixmap(pGC) = 0;
- }
-
- if (pGC->fillStyle == FillTiled) {
- PixmapPtr pOldTile, pNewTile;
-
- pOldTile = pGC->tile.pixmap;
- if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
- {
- pNewTile = fbGetRotatedPixmap(pGC);
- if (!pNewTile ||
- pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
- {
- if (pNewTile)
- (*pGC->pScreen->DestroyPixmap) (pNewTile);
- /* fb24_32ReformatTile will do direct access of a newly-
- * allocated pixmap. This isn't a problem yet, since we don't
- * put pixmaps in FB until at least one accelerated EXA op.
- */
- exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
- pNewTile = fb24_32ReformatTile (pOldTile,
- pDrawable->bitsPerPixel);
- exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
- exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
- }
- if (pNewTile)
- {
- fbGetRotatedPixmap(pGC) = pOldTile;
- pGC->tile.pixmap = pNewTile;
- changes |= GCTile;
- }
- }
- }
-#endif
- if (changes & GCTile) {
- if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
- pDrawable->bitsPerPixel))
- {
- exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
- fbPadPixmap (pGC->tile.pixmap);
- exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
- exaPixmapDirty(pGC->tile.pixmap, 0, 0,
- pGC->tile.pixmap->drawable.width,
- pGC->tile.pixmap->drawable.height);
- }
- /* Mask out the GCTile change notification, now that we've done FB's
- * job for it.
+
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv(pScreen);
+ ExaGCPriv(pGC);
+ PixmapPtr pTile = NULL;
+ Bool finish_current_tile = FALSE;
+
+ /* Either of these conditions is enough to trigger access to a tile pixmap. */
+ /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
+ if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) {
+ pTile = pGC->tile.pixmap;
+
+ /* Sometimes tile pixmaps are swapped, you need access to:
+ * - The current tile if it depth matches.
+ * - Or the rotated tile if that one matches depth and !(changes & GCTile).
+ * - Or the current tile pixmap and a newly created one.
*/
- changes &= ~GCTile;
+ if (pTile && pTile->drawable.depth != pDrawable->depth && !(changes & GCTile)) {
+ PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);
+ if (pRotatedTile && pRotatedTile->drawable.depth == pDrawable->depth)
+ pTile = pRotatedTile;
+ else
+ finish_current_tile = TRUE; /* CreatePixmap will be called. */
+ }
}
- exaPrepareAccessGC(pGC);
- fbValidateGC (pGC, changes, pDrawable);
- exaFinishAccessGC(pGC);
+ if (pGC->stipple)
+ exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
+ if (pTile)
+ exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
+
+ /* Calls to Create/DestroyPixmap have to be identified as special. */
+ pExaScr->fallback_counter++;
+ swap(pExaGC, pGC, funcs);
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
+ swap(pExaGC, pGC, funcs);
+ pExaScr->fallback_counter--;
+
+ if (pTile)
+ exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
+ if (finish_current_tile && pGC->tile.pixmap)
+ exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_DEST);
+ if (pGC->stipple)
+ exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
+}
- pGC->ops = (GCOps *) &exaOps;
+/* Is exaPrepareAccessGC() needed? */
+static void
+exaDestroyGC(GCPtr pGC)
+{
+ ExaGCPriv(pGC);
+ swap(pExaGC, pGC, funcs);
+ (*pGC->funcs->DestroyGC)(pGC);
+ swap(pExaGC, pGC, funcs);
}
-static GCFuncs exaGCFuncs = {
- exaValidateGC,
- miChangeGC,
- miCopyGC,
- miDestroyGC,
- miChangeClip,
- miDestroyClip,
- miCopyClip
-};
+static void
+exaChangeGC (GCPtr pGC,
+ unsigned long mask)
+{
+ ExaGCPriv(pGC);
+ swap(pExaGC, pGC, funcs);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ swap(pExaGC, pGC, funcs);
+}
+
+static void
+exaCopyGC (GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst)
+{
+ ExaGCPriv(pGCDst);
+ swap(pExaGC, pGCDst, funcs);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ swap(pExaGC, pGCDst, funcs);
+}
+
+static void
+exaChangeClip (GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects)
+{
+ ExaGCPriv(pGC);
+ swap(pExaGC, pGC, funcs);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ swap(pExaGC, pGC, funcs);
+}
+
+static void
+exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
+{
+ ExaGCPriv(pGCDst);
+ swap(pExaGC, pGCDst, funcs);
+ (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
+ swap(pExaGC, pGCDst, funcs);
+}
+
+static void
+exaDestroyClip(GCPtr pGC)
+{
+ ExaGCPriv(pGC);
+ swap(pExaGC, pGC, funcs);
+ (*pGC->funcs->DestroyClip)(pGC);
+ swap(pExaGC, pGC, funcs);
+}
/**
* exaCreateGC makes a new GC and hooks up its funcs handler, so that
@@ -675,32 +607,44 @@ static GCFuncs exaGCFuncs = {
static int
exaCreateGC (GCPtr pGC)
{
- if (!fbCreateGC (pGC))
- return FALSE;
+ ScreenPtr pScreen = pGC->pScreen;
+ ExaScreenPriv(pScreen);
+ ExaGCPriv(pGC);
+ Bool ret;
- pGC->funcs = &exaGCFuncs;
+ swap(pExaScr, pScreen, CreateGC);
+ if ((ret = (*pScreen->CreateGC) (pGC))) {
+ wrap(pExaGC, pGC, funcs, (GCFuncs *) &exaGCFuncs);
+ wrap(pExaGC, pGC, ops, (GCOps *) &exaOps);
+ }
+ swap(pExaScr, pScreen, CreateGC);
- return TRUE;
+ return ret;
}
static Bool
exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
{
Bool ret;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ExaScreenPriv(pScreen);
if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
- exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+ exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
- exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
+ exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
- ret = fbChangeWindowAttributes(pWin, mask);
-
- if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
- exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
+ pExaScr->fallback_counter++;
+ swap(pExaScr, pScreen, ChangeWindowAttributes);
+ ret = pScreen->ChangeWindowAttributes(pWin, mask);
+ swap(pExaScr, pScreen, ChangeWindowAttributes);
+ pExaScr->fallback_counter--;
if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
- exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+ exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+ if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
+ exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
return ret;
}
@@ -708,11 +652,17 @@ exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
static RegionPtr
exaBitmapToRegion(PixmapPtr pPix)
{
- RegionPtr ret;
- exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC);
- ret = fbPixmapToRegion(pPix);
- exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC);
- return ret;
+ RegionPtr ret;
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC);
+ swap(pExaScr, pScreen, BitmapToRegion);
+ ret = pScreen->BitmapToRegion(pPix);
+ swap(pExaScr, pScreen, BitmapToRegion);
+ exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC);
+
+ return ret;
}
static Bool
@@ -722,9 +672,9 @@ exaCreateScreenResources(ScreenPtr pScreen)
PixmapPtr pScreenPixmap;
Bool b;
- pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources;
+ swap(pExaScr, pScreen, CreateScreenResources);
b = pScreen->CreateScreenResources(pScreen);
- pScreen->CreateScreenResources = exaCreateScreenResources;
+ swap(pExaScr, pScreen, CreateScreenResources);
if (!b)
return FALSE;
@@ -743,6 +693,58 @@ exaCreateScreenResources(ScreenPtr pScreen)
return TRUE;
}
+static void
+ExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ExaScreenPriv(pScreen);
+
+ /* Move any deferred results from a software fallback to the driver pixmap */
+ if (pExaScr->deferred_mixed_pixmap)
+ exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
+
+ unwrap(pExaScr, pScreen, BlockHandler);
+ (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
+ wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+
+ /* The rest only applies to classic EXA */
+ if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
+ return;
+
+ /* Try and keep the offscreen memory area tidy every now and then (at most
+ * once per second) when the server has been idle for at least 100ms.
+ */
+ if (pExaScr->numOffscreenAvailable > 1) {
+ CARD32 now = GetTimeInMillis();
+
+ pExaScr->nextDefragment = now +
+ max(100, (INT32)(pExaScr->lastDefragment + 1000 - now));
+ AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
+ }
+}
+
+static void
+ExaWakeupHandler(int screenNum, pointer wakeupData, unsigned long result,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[screenNum];
+ ExaScreenPriv(pScreen);
+
+ unwrap(pExaScr, pScreen, WakeupHandler);
+ (*pScreen->WakeupHandler) (screenNum, wakeupData, result, pReadmask);
+ wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
+
+ if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
+ CARD32 now = GetTimeInMillis();
+
+ if ((int)(now - pExaScr->nextDefragment) > 0) {
+ ExaOffscreenDefragment(pScreen);
+ pExaScr->lastDefragment = now;
+ }
+ }
+}
+
/**
* exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
* screen private, before calling down to the next CloseSccreen.
@@ -758,23 +760,32 @@ exaCloseScreen(int i, ScreenPtr pScreen)
if (ps->Glyphs == exaGlyphs)
exaGlyphsFini(pScreen);
- pScreen->CreateGC = pExaScr->SavedCreateGC;
- pScreen->CloseScreen = pExaScr->SavedCloseScreen;
- pScreen->GetImage = pExaScr->SavedGetImage;
- pScreen->GetSpans = pExaScr->SavedGetSpans;
- pScreen->CreatePixmap = pExaScr->SavedCreatePixmap;
- pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap;
- pScreen->CopyWindow = pExaScr->SavedCopyWindow;
- pScreen->ChangeWindowAttributes = pExaScr->SavedChangeWindowAttributes;
- pScreen->BitmapToRegion = pExaScr->SavedBitmapToRegion;
- pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources;
+ if (pScreen->BlockHandler == ExaBlockHandler)
+ unwrap(pExaScr, pScreen, BlockHandler);
+ if (pScreen->WakeupHandler == ExaWakeupHandler)
+ unwrap(pExaScr, pScreen, WakeupHandler);
+ unwrap(pExaScr, pScreen, CreateGC);
+ unwrap(pExaScr, pScreen, CloseScreen);
+ unwrap(pExaScr, pScreen, GetImage);
+ unwrap(pExaScr, pScreen, GetSpans);
+ if (pExaScr->SavedCreatePixmap)
+ unwrap(pExaScr, pScreen, CreatePixmap);
+ if (pExaScr->SavedDestroyPixmap)
+ unwrap(pExaScr, pScreen, DestroyPixmap);
+ if (pExaScr->SavedModifyPixmapHeader)
+ unwrap(pExaScr, pScreen, ModifyPixmapHeader);
+ unwrap(pExaScr, pScreen, CopyWindow);
+ unwrap(pExaScr, pScreen, ChangeWindowAttributes);
+ unwrap(pExaScr, pScreen, BitmapToRegion);
+ unwrap(pExaScr, pScreen, CreateScreenResources);
#ifdef RENDER
if (ps) {
- ps->Composite = pExaScr->SavedComposite;
- ps->Glyphs = pExaScr->SavedGlyphs;
- ps->Trapezoids = pExaScr->SavedTrapezoids;
- ps->Triangles = pExaScr->SavedTriangles;
- ps->AddTraps = pExaScr->SavedAddTraps;
+ unwrap(pExaScr, ps, Composite);
+ if (pExaScr->SavedGlyphs)
+ unwrap(pExaScr, ps, Glyphs);
+ unwrap(pExaScr, ps, Trapezoids);
+ unwrap(pExaScr, ps, Triangles);
+ unwrap(pExaScr, ps, AddTraps);
}
#endif
@@ -832,7 +843,7 @@ exaDriverInit (ScreenPtr pScreen,
return FALSE;
}
- if (!pScreenInfo->CreatePixmap) {
+ if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) {
if (!pScreenInfo->memoryBase) {
LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase "
"must be non-zero\n", pScreen->myNum);
@@ -889,7 +900,6 @@ exaDriverInit (ScreenPtr pScreen,
#endif
pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1);
-
if (!pExaScr) {
LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
pScreen->myNum);
@@ -904,51 +914,40 @@ exaDriverInit (ScreenPtr pScreen,
exaDDXDriverInit(pScreen);
+ if (!dixRequestPrivate(exaGCPrivateKey, sizeof(ExaGCPrivRec))) {
+ LogMessage(X_WARNING,
+ "EXA(%d): Failed to allocate GC private\n",
+ pScreen->myNum);
+ return FALSE;
+ }
+
/*
* Replace various fb screen functions
*/
- pExaScr->SavedCloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = exaCloseScreen;
-
- pExaScr->SavedCreateGC = pScreen->CreateGC;
- pScreen->CreateGC = exaCreateGC;
-
- pExaScr->SavedGetImage = pScreen->GetImage;
- pScreen->GetImage = exaGetImage;
-
- pExaScr->SavedGetSpans = pScreen->GetSpans;
- pScreen->GetSpans = ExaCheckGetSpans;
-
- pExaScr->SavedCopyWindow = pScreen->CopyWindow;
- pScreen->CopyWindow = exaCopyWindow;
-
- pExaScr->SavedChangeWindowAttributes = pScreen->ChangeWindowAttributes;
- pScreen->ChangeWindowAttributes = exaChangeWindowAttributes;
-
- pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion;
- pScreen->BitmapToRegion = exaBitmapToRegion;
-
- pExaScr->SavedCreateScreenResources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = exaCreateScreenResources;
+ if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
+ (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) ||
+ (pExaScr->info->flags & EXA_MIXED_PIXMAPS)))
+ wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
+ if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
+ !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
+ wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
+ wrap(pExaScr, pScreen, CreateGC, exaCreateGC);
+ wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen);
+ wrap(pExaScr, pScreen, GetImage, exaGetImage);
+ wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans);
+ wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow);
+ wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes);
+ wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion);
+ wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources);
#ifdef RENDER
if (ps) {
- pExaScr->SavedComposite = ps->Composite;
- ps->Composite = exaComposite;
-
- if (pScreenInfo->PrepareComposite) {
- pExaScr->SavedGlyphs = ps->Glyphs;
- ps->Glyphs = exaGlyphs;
- }
-
- pExaScr->SavedTriangles = ps->Triangles;
- ps->Triangles = exaTriangles;
-
- pExaScr->SavedTrapezoids = ps->Trapezoids;
- ps->Trapezoids = exaTrapezoids;
-
- pExaScr->SavedAddTraps = ps->AddTraps;
- ps->AddTraps = ExaCheckAddTraps;
+ wrap(pExaScr, ps, Composite, exaComposite);
+ if (pScreenInfo->PrepareComposite)
+ wrap(pExaScr, ps, Glyphs, exaGlyphs);
+ wrap(pExaScr, ps, Trapezoids, exaTrapezoids);
+ wrap(pExaScr, ps, Triangles, exaTriangles);
+ wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps);
}
#endif
@@ -969,15 +968,37 @@ exaDriverInit (ScreenPtr pScreen,
pScreen->myNum);
return FALSE;
}
- pExaScr->SavedCreatePixmap = pScreen->CreatePixmap;
- pScreen->CreatePixmap = exaCreatePixmap;
-
- pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
- pScreen->DestroyPixmap = exaDestroyPixmap;
-
- pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader;
- pScreen->ModifyPixmapHeader = exaModifyPixmapHeader;
- if (!pExaScr->info->CreatePixmap) {
+ if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) {
+ if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_mixed);
+ pExaScr->do_migration = exaDoMigration_mixed;
+ pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed;
+ pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
+ pExaScr->do_move_out_pixmap = NULL;
+ pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver);
+ pExaScr->do_migration = NULL;
+ pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver;
+ pExaScr->do_move_in_pixmap = NULL;
+ pExaScr->do_move_out_pixmap = NULL;
+ pExaScr->prepare_access_reg = NULL;
+ }
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_classic);
+ pExaScr->do_migration = exaDoMigration_classic;
+ pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic;
+ pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
+ pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
+ pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
+ }
+ if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
pScreen->myNum,
pExaScr->info->memorySize - pExaScr->info->offScreenBase);
@@ -990,7 +1011,7 @@ exaDriverInit (ScreenPtr pScreen,
else
LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
- if (!pExaScr->info->CreatePixmap) {
+ if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
pExaScr->info->memorySize));
if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
@@ -1074,3 +1095,47 @@ void exaWaitSync(ScreenPtr pScreen)
pExaScr->info->needsSync = FALSE;
}
}
+
+/**
+ * Performs migration of the pixmaps according to the operation information
+ * provided in pixmaps and can_accel and the migration scheme chosen in the
+ * config file.
+ */
+void
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_migration)
+ (*pExaScr->do_migration)(pixmaps, npixmaps, can_accel);
+}
+
+void
+exaMoveInPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_move_in_pixmap)
+ (*pExaScr->do_move_in_pixmap)(pPixmap);
+}
+
+void
+exaMoveOutPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_move_out_pixmap)
+ (*pExaScr->do_move_out_pixmap)(pPixmap);
+}
diff --git a/xserver/exa/exa.h b/xserver/exa/exa.h
index 4a96cc6f3..8c93d156f 100644
--- a/xserver/exa/exa.h
+++ b/xserver/exa/exa.h
@@ -39,7 +39,7 @@
#include "fb.h"
#define EXA_VERSION_MAJOR 2
-#define EXA_VERSION_MINOR 4
+#define EXA_VERSION_MINOR 5
#define EXA_VERSION_RELEASE 0
typedef struct _ExaOffscreenArea ExaOffscreenArea;
@@ -66,6 +66,9 @@ struct _ExaOffscreenArea {
ExaOffscreenArea *next;
unsigned eviction_cost;
+
+ ExaOffscreenArea *prev; /* Double-linked list for defragmentation */
+ int align; /* required alignment */
};
/**
@@ -499,27 +502,8 @@ typedef struct _ExaDriver {
int src_pitch);
/**
- * UploadToScratch() is used to upload a pixmap to a scratch area for
- * acceleration.
- *
- * @param pSrc source pixmap in host memory
- * @param pDst fake, scratch pixmap to be set up in offscreen memory.
- *
- * The UploadToScratch() call was added to support Xati before Xati had
- * support for hostdata uploads and before exaGlyphs() was written. It
- * behaves incorrectly (uses an invalid pixmap as pDst),
- * and UploadToScreen() should be implemented instead.
- *
- * Drivers implementing UploadToScratch() had to set up space (likely in a
- * statically allocated area) in offscreen memory, copy pSrc to that
- * scratch area, and adust pDst->devKind for the pitch and
- * pDst->devPrivate.ptr for the pointer to that scratch area. The driver
- * was responsible for syncing (as it was implemented using memcpy() in
- * Xati), and only the data from the last UploadToScratch() was guaranteed
- * to be valid at any given time.
- *
- * UploadToScratch() should not be implemented by drivers, and will likely
- * be removed in a future version of EXA.
+ * UploadToScratch() is no longer used and will be removed next time the EXA
+ * major version needs to be bumped.
*/
Bool (*UploadToScratch) (PixmapPtr pSrc,
PixmapPtr pDst);
@@ -602,14 +586,14 @@ typedef struct _ExaDriver {
* untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
* making CPU access use a different aperture.
*
- * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC, or
- * #EXA_PREPARE_MASK, indicating which pixmap is in question. Since only up
- * to three pixmaps will have PrepareAccess() called on them per operation,
- * drivers can have a small, statically-allocated space to maintain state
- * for PrepareAccess() and FinishAccess() in. Note that the same pixmap may
- * have PrepareAccess() called on it more than once, for example when doing
- * a copy within the same pixmap (so it gets PrepareAccess as()
- * #EXA_PREPARE_DEST and then as #EXA_PREPARE_SRC).
+ * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC,
+ * #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or
+ * #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps
+ * will have PrepareAccess() called on them per operation, drivers can have
+ * a small, statically-allocated space to maintain state for PrepareAccess()
+ * and FinishAccess() in. Note that PrepareAccess() is only called once per
+ * pixmap and operation, regardless of whether the pixmap is used as a
+ * destination and/or source, and the index may not reflect the usage.
*
* PrepareAccess() may fail. An example might be the case of hardware that
* can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
@@ -640,13 +624,13 @@ typedef struct _ExaDriver {
/**
* PixmapIsOffscreen() is an optional driver replacement to
- * exaPixmapIsOffscreen(). Set to NULL if you want the standard behaviour
- * of exaPixmapIsOffscreen().
+ * exaPixmapHasGpuCopy(). Set to NULL if you want the standard behaviour
+ * of exaPixmapHasGpuCopy().
*
* @param pPix the pixmap
* @return TRUE if the given drawable is in framebuffer memory.
*
- * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
+ * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
* memory, meaning that acceleration could probably be done to it, and that it
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
* with the CPU.
@@ -676,9 +660,10 @@ typedef struct _ExaDriver {
* EXA_PREPARE_AUX* are additional indices for other purposes, e.g.
* separate alpha maps with Composite operations.
*/
- #define EXA_PREPARE_AUX0 3
- #define EXA_PREPARE_AUX1 4
- #define EXA_PREPARE_AUX2 5
+ #define EXA_PREPARE_AUX_DEST 3
+ #define EXA_PREPARE_AUX_SRC 4
+ #define EXA_PREPARE_AUX_MASK 5
+ #define EXA_NUM_PREPARE_INDICES 6
/** @} */
/**
@@ -714,10 +699,21 @@ typedef struct _ExaDriver {
/* Hooks to allow driver to its own pixmap memory management */
void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align);
void (*DestroyPixmap)(ScreenPtr pScreen, void *driverPriv);
+ /**
+ * Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is
+ * not offscreen, which will never be accelerated and Prepare/FinishAccess won't
+ * be called.
+ */
Bool (*ModifyPixmapHeader)(PixmapPtr pPixmap, int width, int height,
int depth, int bitsPerPixel, int devKind,
pointer pPixData);
+ /* hooks for drivers with tiling support:
+ * driver MUST fill out new_fb_pitch with valid pitch of pixmap
+ */
+ void *(*CreatePixmap2)(ScreenPtr pScreen, int width, int height,
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch);
/** @} */
} ExaDriverRec, *ExaDriverPtr;
@@ -756,66 +752,83 @@ typedef struct _ExaDriver {
*/
#define EXA_SUPPORTS_PREPARE_AUX (1 << 4)
+/**
+ * EXA_SUPPORTS_OFFSCREEN_OVERLAPS indicates to EXA that the driver Copy hooks
+ * can handle the source and destination occupying overlapping offscreen memory
+ * areas. This allows the offscreen memory defragmentation code to defragment
+ * areas where the defragmented position overlaps the fragmented position.
+ *
+ * Typically this is supported by traditional 2D engines but not by 3D engines.
+ */
+#define EXA_SUPPORTS_OFFSCREEN_OVERLAPS (1 << 5)
+
+/**
+ * EXA_MIXED_PIXMAPS will hide unacceleratable pixmaps from drivers and manage the
+ * problem known software fallbacks like trapezoids. This only migrates pixmaps one way
+ * into a driver pixmap and then pins it.
+ */
+#define EXA_MIXED_PIXMAPS (1 << 6)
+
/** @} */
/* in exa.c */
-ExaDriverPtr
+extern _X_EXPORT ExaDriverPtr
exaDriverAlloc(void);
-Bool
+extern _X_EXPORT Bool
exaDriverInit(ScreenPtr pScreen,
ExaDriverPtr pScreenInfo);
-void
+extern _X_EXPORT void
exaDriverFini(ScreenPtr pScreen);
-void
+extern _X_EXPORT void
exaMarkSync(ScreenPtr pScreen);
-void
+extern _X_EXPORT void
exaWaitSync(ScreenPtr pScreen);
-unsigned long
+extern _X_EXPORT unsigned long
exaGetPixmapOffset(PixmapPtr pPix);
-unsigned long
+extern _X_EXPORT unsigned long
exaGetPixmapPitch(PixmapPtr pPix);
-unsigned long
+extern _X_EXPORT unsigned long
exaGetPixmapSize(PixmapPtr pPix);
-void *
+extern _X_EXPORT void *
exaGetPixmapDriverPrivate(PixmapPtr p);
/* in exa_offscreen.c */
-ExaOffscreenArea *
+extern _X_EXPORT ExaOffscreenArea *
exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
Bool locked,
ExaOffscreenSaveProc save,
pointer privData);
-ExaOffscreenArea *
+extern _X_EXPORT ExaOffscreenArea *
exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea *area);
-void
+extern _X_EXPORT void
ExaOffscreenMarkUsed (PixmapPtr pPixmap);
-void
+extern _X_EXPORT void
exaEnableDisableFBAccess (int index, Bool enable);
-Bool
+extern _X_EXPORT Bool
exaDrawableIsOffscreen (DrawablePtr pDrawable);
-/* in exa_migration.c */
-void
+/* in exa.c */
+extern _X_EXPORT void
exaMoveInPixmap (PixmapPtr pPixmap);
-void
+extern _X_EXPORT void
exaMoveOutPixmap (PixmapPtr pPixmap);
/* in exa_unaccel.c */
-CARD32
+extern _X_EXPORT CARD32
exaGetPixmapFirstPixel (PixmapPtr pPixmap);
diff --git a/xserver/exa/exa_accel.c b/xserver/exa/exa_accel.c
index dac6e6c79..57029fdc5 100644
--- a/xserver/exa/exa_accel.c
+++ b/xserver/exa/exa_accel.c
@@ -50,20 +50,24 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
int fullX1, fullX2, fullY1;
int partX1, partX2;
int off_x, off_y;
- ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
- if (pExaScr->swappedOut ||
+ if (pExaScr->fallback_counter ||
+ pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
pExaPixmap->accel_blocked)
{
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
- } else {
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -148,9 +152,13 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int nbox;
int xoff, yoff;
int bpp = pDrawable->bitsPerPixel;
- Bool access_prepared = FALSE;
+ Bool ret = TRUE;
- if (pExaPixmap->accel_blocked)
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
+ return FALSE;
+
+ /* If there's a system copy, we want to save the result there */
+ if (pExaPixmap->pDamage)
return FALSE;
/* Don't bother with under 8bpp, XYPixmaps. */
@@ -164,10 +172,10 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (pExaScr->swappedOut)
return FALSE;
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPix;
pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
@@ -177,7 +185,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (!pPix || !pExaScr->info->UploadToScreen)
+ if (!pPix)
return FALSE;
x += pDrawable->x;
@@ -210,42 +218,19 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
x2 - x1, y2 - y1, src, src_stride);
- /* If we fail to accelerate the upload, fall back to using unaccelerated
- * fb calls.
+ /* We have to fall back completely, and ignore what has already been completed.
+ * Messing with the fb layer directly like we used to is completely unacceptable.
*/
if (!ok) {
- FbStip *dst;
- FbStride dst_stride;
- int dstBpp;
- int dstXoff, dstYoff;
-
- if (!access_prepared) {
- ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST);
-
- access_prepared = TRUE;
- }
-
- fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
- dstXoff, dstYoff);
-
- fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
- src_stride / sizeof(FbStip),
- (x1 - x) * dstBpp,
- dst + (y1 + dstYoff) * dst_stride,
- dst_stride,
- (x1 + dstXoff) * dstBpp,
- (x2 - x1) * dstBpp,
- y2 - y1,
- GXcopy, FB_ALLONES, dstBpp);
+ ret = FALSE;
+ break;
}
}
- if (access_prepared)
- exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
- else
+ if (ret)
exaMarkSync(pDrawable->pScreen);
- return TRUE;
+ return ret;
}
static void
@@ -379,8 +364,8 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
return TRUE;
}
-void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
@@ -388,22 +373,20 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
int dx,
int dy,
Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure)
+ Bool upsidedown)
{
ExaScreenPriv (pDstDrawable->pScreen);
PixmapPtr pSrcPixmap, pDstPixmap;
ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
- ExaMigrationRec pixmaps[2];
RegionPtr srcregion = NULL, dstregion = NULL;
xRectangle *rects;
+ Bool ret = TRUE;
/* avoid doing copy operations if no boxes */
if (nbox == 0)
- return;
+ return TRUE;
pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
@@ -446,14 +429,6 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPixmap;
- pixmaps[0].pReg = dstregion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPixmap;
- pixmaps[1].pReg = srcregion;
pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
@@ -487,7 +462,20 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- exaDoMigration (pixmaps, 2, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPixmap;
+ pixmaps[0].pReg = dstregion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pSrcPixmap;
+ pixmaps[1].pReg = srcregion;
+
+ exaDoMigration (pixmaps, 2, TRUE);
+ }
/* Mixed directions must be handled specially if the card is lame */
if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
@@ -498,40 +486,68 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
goto fallback;
}
- if (!exaPixmapIsOffscreen(pSrcPixmap) ||
- !exaPixmapIsOffscreen(pDstPixmap) ||
- !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
- upsidedown ? -1 : 1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask : FB_ALLONES)) {
- goto fallback;
- }
+ if (exaPixmapHasGpuCopy(pDstPixmap)) {
+ /* Normal blitting. */
+ if (exaPixmapHasGpuCopy(pSrcPixmap)) {
+ if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ upsidedown ? -1 : 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES)) {
+ goto fallback;
+ }
- while (nbox--)
- {
- (*pExaScr->info->Copy) (pDstPixmap,
- pbox->x1 + dx + src_off_x,
- pbox->y1 + dy + src_off_y,
- pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
- pbox++;
- }
+ while (nbox--)
+ {
+ (*pExaScr->info->Copy) (pDstPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ (*pExaScr->info->DoneCopy) (pDstPixmap);
+ exaMarkSync (pDstDrawable->pScreen);
+ /* UTS: mainly for SHM PutImage's secondary path.
+ *
+ * Only taking this path for directly accessible pixmaps.
+ */
+ } else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) {
+ int bpp = pSrcDrawable->bitsPerPixel;
+ int src_stride = exaGetPixmapPitch(pSrcPixmap);
+ CARD8 *src = NULL;
+
+ if (!pExaScr->info->UploadToScreen)
+ goto fallback;
- (*pExaScr->info->DoneCopy) (pDstPixmap);
- exaMarkSync (pDstDrawable->pScreen);
+ if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
+ goto fallback;
+
+ if (pSrcDrawable->bitsPerPixel < 8)
+ goto fallback;
+
+ if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask)))
+ goto fallback;
+
+ while (nbox--)
+ {
+ src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8);
+ if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
+ (char *) src, src_stride))
+ goto fallback;
+
+ pbox++;
+ }
+ } else
+ goto fallback;
+ } else
+ goto fallback;
goto out;
fallback:
- EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
- exaDrawableLocation(pSrcDrawable),
- exaDrawableLocation(pDstDrawable)));
- exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, dstregion);
- exaPrepareAccessReg (pSrcDrawable, EXA_PREPARE_SRC, srcregion);
- fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
- upsidedown, bitplane, closure);
- exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
- exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
+ ret = FALSE;
out:
if (dstregion) {
@@ -542,6 +558,40 @@ out:
REGION_UNINIT(pScreen, srcregion);
REGION_DESTROY(pScreen, srcregion);
}
+
+ return ret;
+}
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ ExaScreenPriv(pDstDrawable->pScreen);
+
+ if (pExaScr->fallback_counter ||
+ (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW))
+ return;
+
+ if (exaHWCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown))
+ return;
+
+ /* This is a CopyWindow, it's cleaner to fallback at the original call. */
+ if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
+ return;
+ }
+
+ /* fallback */
+ ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
}
RegionPtr
@@ -550,12 +600,12 @@ exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
{
ExaScreenPriv (pDstDrawable->pScreen);
- if (pExaScr->swappedOut) {
+ if (pExaScr->fallback_counter || pExaScr->swappedOut) {
return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height, dstx, dsty);
}
- return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height,
dstx, dsty, exaCopyNtoN, 0, NULL);
}
@@ -564,13 +614,14 @@ static void
exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr ppt)
{
+ ExaScreenPriv (pDrawable->pScreen);
int i;
xRectangle *prect;
/* If we can't reuse the current GC as is, don't bother accelerating the
* points.
*/
- if (pGC->fillStyle != FillSolid) {
+ if (pExaScr->fallback_counter || pGC->fillStyle != FillSolid) {
ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt);
return;
}
@@ -599,10 +650,16 @@ static void
exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr ppt)
{
+ ExaScreenPriv (pDrawable->pScreen);
xRectangle *prect;
int x1, x2, y1, y2;
int i;
+ if (pExaScr->fallback_counter) {
+ ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
/* Don't try to do wide lines or non-solid fill style. */
if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
pGC->fillStyle != FillSolid) {
@@ -660,12 +717,13 @@ static void
exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
xSegment *pSeg)
{
+ ExaScreenPriv (pDrawable->pScreen);
xRectangle *prect;
int i;
/* Don't try to do wide lines or non-solid fill style. */
- if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
- pGC->fillStyle != FillSolid)
+ if (pExaScr->fallback_counter || pGC->lineWidth != 0 ||
+ pGC->lineStyle != LineSolid || pGC->fillStyle != FillSolid)
{
ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
return;
@@ -730,7 +788,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
int xoff, yoff;
int xorg, yorg;
int n;
- ExaMigrationRec pixmaps[2];
RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
/* Compute intersection of rects and clip region */
@@ -741,14 +798,10 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto out;
}
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
- if (pExaScr->swappedOut || pExaPixmap->accel_blocked)
+ if (pExaScr->fallback_counter || pExaScr->swappedOut ||
+ pExaPixmap->accel_blocked)
{
goto fallback;
}
@@ -778,9 +831,18 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto fallback;
}
- exaDoMigration (pixmaps, 1, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
- if (!exaPixmapIsOffscreen (pPixmap) ||
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ if (!exaPixmapHasGpuCopy (pPixmap) ||
!(*pExaScr->info->PrepareSolid) (pPixmap,
pGC->alu,
pGC->planemask,
@@ -898,6 +960,7 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
RegionRec rgnDst;
int dx, dy;
PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+ ExaScreenPriv(pWin->drawable.pScreen);
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
@@ -912,11 +975,25 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-pPixmap->screen_x, -pPixmap->screen_y);
#endif
- fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ if (pExaScr->fallback_counter) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
+ goto fallback;
+ }
+
+ pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW;
+ miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
NULL,
&rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
+ pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW;
+fallback:
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) {
+ pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy);
+ ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc);
+ }
}
static Bool
@@ -927,27 +1004,27 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
int xoff, yoff;
- ExaMigrationRec pixmaps[1];
Bool ret = FALSE;
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
- alu, clientClipType)
- ? NULL : pRegion;
-
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
- if (pExaPixmap->accel_blocked)
- {
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked)
goto out;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
+ alu, clientClipType) ? NULL : pRegion;
+
exaDoMigration (pixmaps, 1, TRUE);
}
- if (exaPixmapIsOffscreen (pPixmap) &&
+ if (exaPixmapHasGpuCopy (pPixmap) &&
(*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
{
int nbox;
@@ -965,10 +1042,12 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+ if (pExaPixmap->pDamage &&
+ pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP &&
pDrawable->width == 1 && pDrawable->height == 1 &&
pDrawable->bitsPerPixel != 24) {
ExaPixmapPriv(pPixmap);
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
switch (pDrawable->bitsPerPixel) {
case 32:
@@ -983,6 +1062,9 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
pRegion);
+ REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
+ pRegion);
+ REGION_SUBTRACT(pScreen, pending_damage, pending_damage, pRegion);
}
ret = TRUE;
@@ -1008,7 +1090,6 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
int xoff, yoff;
int tileWidth, tileHeight;
- ExaMigrationRec pixmaps[2];
int nbox = REGION_NUM_RECTS (pRegion);
BoxPtr pBox = REGION_RECTS (pRegion);
Bool ret = FALSE;
@@ -1025,29 +1106,32 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
exaGetPixmapFirstPixel (pTile), planemask,
alu, clientClipType);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
- alu, clientClipType)
- ? NULL : pRegion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pTile;
- pixmaps[1].pReg = NULL;
-
+ pPixmap = exaGetDrawablePixmap (pDrawable);
pExaPixmap = ExaGetPixmapPriv (pPixmap);
- if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
- {
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked ||
+ pTileExaPixmap->accel_blocked)
return FALSE;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
+ alu, clientClipType) ? NULL : pRegion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
+
exaDoMigration (pixmaps, 2, TRUE);
}
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (!pPixmap || !exaPixmapIsOffscreen(pTile))
+ if (!pPixmap || !exaPixmapHasGpuCopy(pTile))
return FALSE;
if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
@@ -1180,31 +1264,17 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d)
{
ExaScreenPriv (pDrawable->pScreen);
- ExaMigrationRec pixmaps[1];
- BoxRec Box;
- RegionRec Reg;
- PixmapPtr pPix;
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv(pPix);
int xoff, yoff;
Bool ok;
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = &Reg;
-
- exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);
-
- Box.x1 = pDrawable->y + x + xoff;
- Box.y1 = pDrawable->y + y + yoff;
- Box.x2 = Box.x1 + w;
- Box.y2 = Box.y1 + h;
-
- REGION_INIT(pScreen, &Reg, &Box, 1);
-
- if (pExaScr->swappedOut)
+ if (pExaScr->fallback_counter || pExaScr->swappedOut)
goto fallback;
- exaDoMigration(pixmaps, 1, FALSE);
+ /* If there's a system copy, we want to save the result there */
+ if (pExaPixmap->pDamage)
+ goto fallback;
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
@@ -1226,17 +1296,9 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
PixmapBytePad(w, pDrawable->depth));
if (ok) {
exaWaitSync(pDrawable->pScreen);
- goto out;
+ return;
}
fallback:
- EXA_FALLBACK(("from %p (%c)\n", pDrawable,
- exaDrawableLocation(pDrawable)));
-
- exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg);
- fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
- exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
-
-out:
- REGION_UNINIT(pScreen, &Reg);
+ ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
}
diff --git a/xserver/exa/exa_classic.c b/xserver/exa/exa_classic.c
new file mode 100644
index 000000000..9bc369ec1
--- /dev/null
+++ b/xserver/exa/exa_classic.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the classic exa specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
+ return pExaPixmap->fb_ptr;
+ else
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * If width and height are 0, this won't be a full-fledged pixmap and it will
+ * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
+ * ModifyPixmapHeader() would break migration. These types of pixmaps are used
+ * for scratch pixmaps, or to represent the visible screen.
+ */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ BoxRec box;
+ int bpp;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ pExaPixmap->driverPriv = NULL;
+ /* Scratch pixmaps may have w/h equal to zero, and may not be
+ * migrated.
+ */
+ if (!w || !h)
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ else
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->use_gpu_copy = FALSE;
+
+ pExaPixmap->fb_ptr = NULL;
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
+
+ if (pExaPixmap->fb_pitch > 131071) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate (NULL, NULL,
+ DamageReportNone, TRUE,
+ pScreen, pPixmap);
+
+ if (pExaPixmap->pDamage == NULL) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
+
+ pExaPixmap->area = NULL;
+
+ /* We set the initial pixmap as completely valid for a simple reason.
+ * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
+ * could form single pixel rects as part of a region. Setting the complete region
+ * as valid is a natural defragmentation of the region.
+ */
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ REGION_INIT(pScreen, &pExaPixmap->validSys, &box, 0);
+ REGION_INIT(pScreen, &pExaPixmap->validFB, &box, 0);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ /* Classic EXA:
+ * - Framebuffer.
+ * - Scratch pixmap with gpu memory.
+ */
+ if (pExaScr->info->memoryBase && pPixData) {
+ if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
+ ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
+ pExaScr->info->memorySize) {
+ pExaPixmap->fb_ptr = pPixData;
+ pExaPixmap->fb_pitch = devKind;
+ pExaPixmap->use_gpu_copy = TRUE;
+ }
+ }
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
+ * gpu memory, so there's no need to track damage.
+ */
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ /* During a fallback we must finish access, but we don't know the index. */
+ if (pExaScr->fallback_counter)
+ exaFinishAccess(&pPixmap->drawable, -1);
+
+ if (pExaPixmap->area)
+ {
+ DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ ExaGetPixmapPriv(pPixmap)->area->offset,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ /* Free the offscreen area */
+ exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool ret;
+
+ if (pExaScr->info->PixmapIsOffscreen) {
+ void* old_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = old_ptr;
+ } else
+ ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
+
+ return ret;
+}
diff --git a/xserver/exa/exa_driver.c b/xserver/exa/exa_driver.c
new file mode 100644
index 000000000..dcf1a9860
--- /dev/null
+++ b/xserver/exa/exa_driver.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * Pixmaps are always marked as pinned, because exa has no control over them.
+ */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth, datasize;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ /* Set this before driver hooks, to allow for driver pixmaps without gpu
+ * memory to back it. These pixmaps have a valid pointer at all times.
+ */
+ pPixmap->devPrivate.ptr = NULL;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ }
+ else {
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ datasize = h * paddedWidth;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
+ }
+
+ if (!pExaPixmap->driverPriv) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ pExaPixmap->sys_ptr = NULL;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ pExaPixmap->area = NULL;
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+ }
+
+ if (pExaScr->info->ModifyPixmapHeader) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+ * If pPixmap->devPrivate.ptr is non-NULL, then we've got a
+ * !has_gpu_copy pixmap. We need to store the pointer,
+ * because PrepareAccess won't be called.
+ */
+ if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+ }
+ if (ret == TRUE)
+ goto out;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ /* During a fallback we must finish access, but we don't know the index. */
+ if (pExaScr->fallback_counter)
+ exaFinishAccess(&pPixmap->drawable, -1);
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ pointer saved_ptr;
+ Bool ret;
+
+ saved_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = saved_ptr;
+
+ return ret;
+}
diff --git a/xserver/exa/exa_glyphs.c b/xserver/exa/exa_glyphs.c
index 93b8b36ae..fd14e9b87 100644
--- a/xserver/exa/exa_glyphs.c
+++ b/xserver/exa/exa_glyphs.c
@@ -68,7 +68,7 @@
#define GLYPH_BUFFER_SIZE 256
typedef struct {
- PicturePtr source;
+ PicturePtr mask;
ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
int count;
} ExaGlyphBuffer, *ExaGlyphBufferPtr;
@@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen,
/* All caches for a single format share a single pixmap for glyph storage,
* allowing mixing glyphs of different sizes without paying a penalty
- * for switching between source pixmaps. (Note that for a size of font
+ * for switching between mask pixmaps. (Note that for a size of font
* right at the border between two sizes, we might be switching for almost
* every glyph.)
*
@@ -187,7 +187,6 @@ exaRealizeGlyphCaches(ScreenPtr pScreen,
}
/* Now allocate the pixmap and picture */
-
pPixmap = (*pScreen->CreatePixmap) (pScreen,
CACHE_PICTURE_WIDTH,
height, depth, 0);
@@ -205,7 +204,6 @@ exaRealizeGlyphCaches(ScreenPtr pScreen,
return FALSE;
/* And store the picture in all the caches for the format */
-
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
int j;
@@ -354,11 +352,11 @@ exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
/* The most efficient thing to way to upload the glyph to the screen
* is to use the UploadToScreen() driver hook; this allows us to
- * pipeline glyph uploads and to avoid creating offscreen pixmaps for
+ * pipeline glyph uploads and to avoid creating gpu backed pixmaps for
* glyphs that we'll never use again.
*
- * If we can't do it with UploadToScreen (because the glyph is offscreen, etc),
- * we fall back to CompositePicture.
+ * If we can't do it with UploadToScreen (because the glyph has a gpu copy,
+ * etc), we fall back to CompositePicture.
*
* We need to damage the cache pixmap manually in either case because the damage
* layer unwrapped the picture screen before calling exaGlyphs.
@@ -366,7 +364,8 @@ exaGlyphCacheHashRemove(ExaGlyphCachePtr cache,
static void
exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
ExaGlyphCachePtr cache,
- int pos,
+ int x,
+ int y,
GlyphPtr pGlyph)
{
ExaScreenPriv(pScreen);
@@ -374,34 +373,37 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
ExaPixmapPriv(pGlyphPixmap);
PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
- ExaMigrationRec pixmaps[1];
if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
goto composite;
/* If the glyph pixmap is already uploaded, no point in doing
* things this way */
- if (exaPixmapIsOffscreen(pGlyphPixmap))
+ if (exaPixmapHasGpuCopy(pGlyphPixmap))
goto composite;
/* UploadToScreen only works if bpp match */
if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
goto composite;
- /* cache pixmap must be offscreen. */
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pCachePixmap;
- pixmaps[0].pReg = NULL;
- exaDoMigration (pixmaps, 1, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ /* cache pixmap must have a gpu copy. */
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pCachePixmap;
+ pixmaps[0].pReg = NULL;
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
- if (!exaPixmapIsOffscreen(pCachePixmap))
+ if (!exaPixmapHasGpuCopy(pCachePixmap))
goto composite;
- /* CACHE_{X,Y} are in pixmap coordinates, no need for cache{X,Y}off */
+ /* x,y are in pixmap coordinates, no need for cache{X,Y}off */
if (pExaScr->info->UploadToScreen(pCachePixmap,
- CACHE_X(pos),
- CACHE_Y(pos),
+ x,
+ y,
pGlyph->info.width,
pGlyph->info.height,
(char *)pExaPixmap->sys_ptr,
@@ -415,18 +417,18 @@ composite:
cache->picture,
0, 0,
0, 0,
- CACHE_X(pos),
- CACHE_Y(pos),
+ x,
+ y,
pGlyph->info.width,
pGlyph->info.height);
damage:
/* The cache pixmap isn't a window, so no need to offset coordinates. */
exaPixmapDirty (pCachePixmap,
- CACHE_X(pos),
- CACHE_Y(pos),
- CACHE_X(pos) + cache->glyphWidth,
- CACHE_Y(pos) + cache->glyphHeight);
+ x,
+ y,
+ x + cache->glyphWidth,
+ y + cache->glyphHeight);
}
static ExaGlyphCacheResult
@@ -434,13 +436,20 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
ExaGlyphCachePtr cache,
ExaGlyphBufferPtr buffer,
GlyphPtr pGlyph,
- int xGlyph,
- int yGlyph)
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst)
{
ExaCompositeRectPtr rect;
int pos;
+ int x, y;
- if (buffer->source && buffer->source != cache->picture)
+ if (buffer->mask && buffer->mask != cache->picture)
return ExaGlyphNeedFlush;
if (!cache->picture) {
@@ -455,10 +464,14 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
pos = exaGlyphCacheHashLookup(cache, pGlyph);
if (pos != -1) {
DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
+ x = CACHE_X(pos);
+ y = CACHE_Y(pos);
} else {
if (cache->glyphCount < cache->size) {
/* Space remaining; we fill from the start */
pos = cache->glyphCount;
+ x = CACHE_X(pos);
+ y = CACHE_Y(pos);
cache->glyphCount++;
DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
@@ -469,18 +482,17 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
* already in the output buffer were at this position in
* the cache
*/
-
pos = cache->evictionPosition;
+ x = CACHE_X(pos);
+ y = CACHE_Y(pos);
DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
if (buffer->count) {
- int x, y;
int i;
-
- x = CACHE_X(pos);
- y = CACHE_Y(pos);
for (i = 0; i < buffer->count; i++) {
- if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) {
+ if (pSrc ?
+ (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) :
+ (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) {
DBG_GLYPH_CACHE((" must flush buffer\n"));
return ExaGlyphNeedFlush;
}
@@ -495,16 +507,31 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
cache->evictionPosition = rand() % cache->size;
}
- exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph);
+ exaGlyphCacheUploadGlyph(pScreen, cache, x, y, pGlyph);
}
- buffer->source = cache->picture;
+ buffer->mask = cache->picture;
rect = &buffer->rects[buffer->count];
- rect->xSrc = CACHE_X(pos);
- rect->ySrc = CACHE_Y(pos);
- rect->xDst = xGlyph - pGlyph->info.x;
- rect->yDst = yGlyph - pGlyph->info.y;
+
+ if (pSrc)
+ {
+ rect->xSrc = xSrc;
+ rect->ySrc = ySrc;
+ rect->xMask = x;
+ rect->yMask = y;
+ }
+ else
+ {
+ rect->xSrc = x;
+ rect->ySrc = y;
+ rect->xMask = 0;
+ rect->yMask = 0;
+ }
+
+ rect->pDst = pDst;
+ rect->xDst = xDst;
+ rect->yDst = yDst;
rect->width = pGlyph->info.width;
rect->height = pGlyph->info.height;
@@ -520,15 +547,21 @@ static ExaGlyphCacheResult
exaBufferGlyph(ScreenPtr pScreen,
ExaGlyphBufferPtr buffer,
GlyphPtr pGlyph,
- int xGlyph,
- int yGlyph)
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst)
{
ExaScreenPriv(pScreen);
unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
int width = pGlyph->info.width;
int height = pGlyph->info.height;
ExaCompositeRectPtr rect;
- PicturePtr source;
+ PicturePtr mask;
int i;
if (buffer->count == GLYPH_BUFFER_SIZE)
@@ -543,9 +576,15 @@ exaBufferGlyph(ScreenPtr pScreen,
if (format == cache->format &&
width <= cache->glyphWidth &&
height <= cache->glyphHeight) {
- ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i],
+ ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen,
+ &pExaScr->glyphCaches[i],
buffer,
- pGlyph, xGlyph, yGlyph);
+ pGlyph,
+ pSrc,
+ pDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst);
switch (result) {
case ExaGlyphFail:
break;
@@ -558,19 +597,21 @@ exaBufferGlyph(ScreenPtr pScreen,
/* Couldn't find the glyph in the cache, use the glyph picture directly */
- source = GlyphPicture(pGlyph)[pScreen->myNum];
- if (buffer->source && buffer->source != source)
+ mask = GlyphPicture(pGlyph)[pScreen->myNum];
+ if (buffer->mask && buffer->mask != mask)
return ExaGlyphNeedFlush;
- buffer->source = source;
-
+ buffer->mask = mask;
+
rect = &buffer->rects[buffer->count];
- rect->xSrc = 0;
- rect->ySrc = 0;
- rect->xDst = xGlyph - pGlyph->info.x;
- rect->yDst = yGlyph - pGlyph->info.y;
- rect->width = pGlyph->info.width;
- rect->height = pGlyph->info.height;
+ rect->xSrc = xSrc;
+ rect->ySrc = ySrc;
+ rect->xMask = xMask;
+ rect->yMask = yMask;
+ rect->xDst = xDst;
+ rect->yDst = yDst;
+ rect->width = width;
+ rect->height = height;
buffer->count++;
@@ -581,44 +622,23 @@ static void
exaGlyphsToMask(PicturePtr pMask,
ExaGlyphBufferPtr buffer)
{
- exaCompositeRects(PictOpAdd, buffer->source, pMask,
+ exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask,
buffer->count, buffer->rects);
buffer->count = 0;
- buffer->source = NULL;
+ buffer->mask = NULL;
}
static void
-exaGlyphsToDst(CARD8 op,
- PicturePtr pSrc,
+exaGlyphsToDst(PicturePtr pSrc,
PicturePtr pDst,
- ExaGlyphBufferPtr buffer,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xDst,
- INT16 yDst)
+ ExaGlyphBufferPtr buffer)
{
- int i;
-
- for (i = 0; i < buffer->count; i++) {
- ExaCompositeRectPtr rect = &buffer->rects[i];
-
- CompositePicture (op,
- pSrc,
- buffer->source,
- pDst,
- xSrc + rect->xDst - xDst,
- ySrc + rect->yDst - yDst,
- rect->xSrc,
- rect->ySrc,
- rect->xDst,
- rect->yDst,
- rect->width,
- rect->height);
- }
+ exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count,
+ buffer->rects);
buffer->count = 0;
- buffer->source = NULL;
+ buffer->mask = NULL;
}
/* Cut and paste from render/glyph.c - probably should export it instead */
@@ -674,79 +694,6 @@ GlyphExtents (int nlist,
}
}
-/**
- * Returns TRUE if the glyphs in the lists intersect. Only checks based on
- * bounding box, which appears to be good enough to catch most cases at least.
- */
-static Bool
-exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs)
-{
- int x1, x2, y1, y2;
- int n;
- GlyphPtr glyph;
- int x, y;
- BoxRec extents;
- Bool first = TRUE;
-
- x = 0;
- y = 0;
- while (nlist--) {
- x += list->xOff;
- y += list->yOff;
- n = list->len;
- list++;
- while (n--) {
- glyph = *glyphs++;
-
- if (glyph->info.width == 0 || glyph->info.height == 0) {
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- continue;
- }
-
- x1 = x - glyph->info.x;
- if (x1 < MINSHORT)
- x1 = MINSHORT;
- y1 = y - glyph->info.y;
- if (y1 < MINSHORT)
- y1 = MINSHORT;
- x2 = x1 + glyph->info.width;
- if (x2 > MAXSHORT)
- x2 = MAXSHORT;
- y2 = y1 + glyph->info.height;
- if (y2 > MAXSHORT)
- y2 = MAXSHORT;
-
- if (first) {
- extents.x1 = x1;
- extents.y1 = y1;
- extents.x2 = x2;
- extents.y2 = y2;
- first = FALSE;
- } else {
- if (x1 < extents.x2 && x2 > extents.x1 &&
- y1 < extents.y2 && y2 > extents.y1)
- {
- return TRUE;
- }
-
- if (x1 < extents.x1)
- extents.x1 = x1;
- if (x2 > extents.x2)
- extents.x2 = x2;
- if (y1 < extents.y1)
- extents.y1 = y1;
- if (y2 > extents.y2)
- extents.y2 = y2;
- }
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- }
- }
-
- return FALSE;
-}
-
void
exaGlyphs (CARD8 op,
PicturePtr pSrc,
@@ -758,13 +705,12 @@ exaGlyphs (CARD8 op,
GlyphListPtr list,
GlyphPtr *glyphs)
{
- PicturePtr pPicture;
PixmapPtr pMaskPixmap = 0;
- PicturePtr pMask;
+ PicturePtr pMask = NULL;
ScreenPtr pScreen = pDst->pDrawable->pScreen;
int width = 0, height = 0;
int x, y;
- int xDst = list->xOff, yDst = list->yOff;
+ int first_xOff = list->xOff, first_yOff = list->yOff;
int n;
GlyphPtr glyph;
int error;
@@ -772,31 +718,9 @@ exaGlyphs (CARD8 op,
CARD32 component_alpha;
ExaGlyphBuffer buffer;
- /* If we don't have a mask format but all the glyphs have the same format
- * and don't intersect, use the glyph format as mask format for the full
- * benefits of the glyph cache.
- */
- if (!maskFormat) {
- Bool sameFormat = TRUE;
- int i;
-
- maskFormat = list[0].format;
-
- for (i = 0; i < nlist; i++) {
- if (maskFormat->format != list[i].format->format) {
- sameFormat = FALSE;
- break;
- }
- }
-
- if (!sameFormat || (maskFormat->depth != 1 &&
- exaGlyphsIntersect(nlist, list, glyphs))) {
- maskFormat = NULL;
- }
- }
-
if (maskFormat)
{
+ ExaScreenPriv(pScreen);
GCPtr pGC;
xRectangle rect;
@@ -823,10 +747,38 @@ exaGlyphs (CARD8 op,
pMask = CreatePicture (0, &pMaskPixmap->drawable,
maskFormat, CPComponentAlpha, &component_alpha,
serverClient, &error);
- if (!pMask)
+ if (!pMask ||
+ (!component_alpha && pExaScr->info->CheckComposite &&
+ !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask)))
{
+ PictFormatPtr argbFormat;
+
(*pScreen->DestroyPixmap) (pMaskPixmap);
- return;
+
+ if (!pMask)
+ return;
+
+ /* The driver can't seem to composite to a8, let's try argb (but
+ * without component-alpha) */
+ FreePicture ((pointer) pMask, (XID) 0);
+
+ argbFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
+
+ if (argbFormat)
+ maskFormat = argbFormat;
+
+ pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+ maskFormat->depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pMaskPixmap)
+ return;
+
+ pMask = CreatePicture (0, &pMaskPixmap->drawable, maskFormat, 0, 0,
+ serverClient, &error);
+ if (!pMask) {
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ return;
+ }
}
pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
ValidateGC (&pMaskPixmap->drawable, pGC);
@@ -841,12 +793,11 @@ exaGlyphs (CARD8 op,
}
else
{
- pMask = pDst;
x = 0;
y = 0;
}
buffer.count = 0;
- buffer.source = NULL;
+ buffer.mask = NULL;
while (nlist--)
{
x += list->xOff;
@@ -855,18 +806,33 @@ exaGlyphs (CARD8 op,
while (n--)
{
glyph = *glyphs++;
- pPicture = GlyphPicture (glyph)[pScreen->myNum];
- if (glyph->info.width > 0 && glyph->info.height > 0 &&
- exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush)
+ if (glyph->info.width > 0 && glyph->info.height > 0)
{
+ /* pGlyph->info.{x,y} compensate for empty space in the glyph. */
if (maskFormat)
- exaGlyphsToMask(pMask, &buffer);
+ {
+ if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
+ 0, 0, 0, 0, x - glyph->info.x, y - glyph->info.y) == ExaGlyphNeedFlush)
+ {
+ exaGlyphsToMask(pMask, &buffer);
+ exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
+ 0, 0, 0, 0, x - glyph->info.x, y - glyph->info.y);
+ }
+ }
else
- exaGlyphsToDst(op, pSrc, pDst, &buffer,
- xSrc, ySrc, xDst, yDst);
-
- exaBufferGlyph(pScreen, &buffer, glyph, x, y);
+ {
+ if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
+ xSrc + (x - glyph->info.x) - first_xOff, ySrc + (y - glyph->info.y) - first_yOff,
+ 0, 0, x - glyph->info.x, y - glyph->info.y)
+ == ExaGlyphNeedFlush)
+ {
+ exaGlyphsToDst(pSrc, pDst, &buffer);
+ exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
+ xSrc + (x - glyph->info.x) - first_xOff, ySrc + (y - glyph->info.y) - first_yOff,
+ 0, 0, x - glyph->info.x, y - glyph->info.y);
+ }
+ }
}
x += glyph->info.xOff;
@@ -879,8 +845,7 @@ exaGlyphs (CARD8 op,
if (maskFormat)
exaGlyphsToMask(pMask, &buffer);
else
- exaGlyphsToDst(op, pSrc, pDst, &buffer,
- xSrc, ySrc, xDst, yDst);
+ exaGlyphsToDst(pSrc, pDst, &buffer);
}
if (maskFormat)
@@ -891,8 +856,8 @@ exaGlyphs (CARD8 op,
pSrc,
pMask,
pDst,
- xSrc + x - xDst,
- ySrc + y - yDst,
+ xSrc + x - first_xOff,
+ ySrc + y - first_yOff,
0, 0,
x, y,
width, height);
diff --git a/xserver/exa/exa_migration.c b/xserver/exa/exa_migration_classic.c
index 4623eccdd..871679ffc 100644
--- a/xserver/exa/exa_migration.c
+++ b/xserver/exa/exa_migration_classic.c
@@ -42,20 +42,6 @@
#endif
/**
- * Returns TRUE if the pixmap is not movable. This is the case where it's a
- * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch
- * pixmap created by some other X Server internals (the score says it's
- * pinned).
- */
-static Bool
-exaPixmapIsPinned (PixmapPtr pPix)
-{
- ExaPixmapPriv (pPix);
-
- return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
-}
-
-/**
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
* and exaCopyDirtyToFb both needed to do this loop.
*/
@@ -75,7 +61,7 @@ exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
dst += dst_pitch;
}
}
-
+
/**
* Returns TRUE if the pixmap is dirty (has been modified in its current
* location compared to the other), or lacks a private for tracking
@@ -86,8 +72,13 @@ exaPixmapIsDirty (PixmapPtr pPix)
{
ExaPixmapPriv (pPix);
- return pExaPixmap == NULL ||
- REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)) ||
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
+
+ if (!pExaPixmap->pDamage)
+ return FALSE;
+
+ return REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)) ||
!REGION_EQUAL(pScreen, &pExaPixmap->validSys, &pExaPixmap->validFB);
}
@@ -116,15 +107,14 @@ exaPixmapShouldBeInFB (PixmapPtr pPix)
static void
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
- char *sys, int sys_pitch), CARD8 *fallback_src,
- CARD8 *fallback_dst, int fallback_srcpitch, int fallback_dstpitch,
- int fallback_index, void (*sync) (ScreenPtr pScreen))
+ char *sys, int sys_pitch), int fallback_index,
+ void (*sync) (ScreenPtr pScreen))
{
PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
RegionRec CopyReg;
- Bool save_offscreen;
+ Bool save_use_gpu_copy;
int save_pitch;
BoxPtr pBox;
int nbox;
@@ -132,7 +122,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
Bool need_sync = FALSE;
/* Damaged bits are valid in current copy but invalid in other one */
- if (exaPixmapIsOffscreen(pPixmap)) {
+ if (pExaPixmap->use_gpu_copy) {
REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
damage);
REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
@@ -173,7 +163,27 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
}
#endif
- REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage);
+ /* Try to prevent destination valid region from growing too many
+ * rects by filling it up to the extents of the union of the
+ * destination valid region and the pending damage region.
+ */
+ if (REGION_NUM_RECTS(pValidDst) > 10) {
+ BoxRec box;
+ BoxPtr pValidExt, pDamageExt;
+ RegionRec closure;
+
+ pValidExt = REGION_EXTENTS(pScreen, pValidDst);
+ pDamageExt = REGION_EXTENTS(pScreen, pending_damage);
+
+ box.x1 = min(pValidExt->x1, pDamageExt->x1);
+ box.y1 = min(pValidExt->y1, pDamageExt->y1);
+ box.x2 = max(pValidExt->x2, pDamageExt->x2);
+ box.y2 = max(pValidExt->y2, pDamageExt->y2);
+
+ REGION_INIT(pScreen, &closure, &box, 0);
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, &closure);
+ } else
+ REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, pending_damage);
}
/* The caller may provide a region to be subtracted from the calculated
@@ -193,9 +203,9 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
pBox = REGION_RECTS(&CopyReg);
nbox = REGION_NUM_RECTS(&CopyReg);
- save_offscreen = pExaPixmap->offscreen;
+ save_use_gpu_copy = pExaPixmap->use_gpu_copy;
save_pitch = pPixmap->devKind;
- pExaPixmap->offscreen = TRUE;
+ pExaPixmap->use_gpu_copy = TRUE;
pPixmap->devKind = pExaPixmap->fb_pitch;
while (nbox--) {
@@ -217,30 +227,43 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
pExaPixmap->sys_pitch))
{
if (!access_prepared) {
- ExaDoPrepareAccess(&pPixmap->drawable, fallback_index);
+ ExaDoPrepareAccess(pPixmap, fallback_index);
access_prepared = TRUE;
}
- exaMemcpyBox (pPixmap, pBox,
- fallback_src, fallback_srcpitch,
- fallback_dst, fallback_dstpitch);
+ if (fallback_index == EXA_PREPARE_DEST) {
+ exaMemcpyBox (pPixmap, pBox,
+ pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
+ pPixmap->devPrivate.ptr, pPixmap->devKind);
+ } else {
+ exaMemcpyBox (pPixmap, pBox,
+ pPixmap->devPrivate.ptr, pPixmap->devKind,
+ pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
+ }
} else
need_sync = TRUE;
pBox++;
}
- if (access_prepared)
- exaFinishAccess(&pPixmap->drawable, fallback_index);
- else if (need_sync)
- sync (pPixmap->drawable.pScreen);
-
- pExaPixmap->offscreen = save_offscreen;
+ pExaPixmap->use_gpu_copy = save_use_gpu_copy;
pPixmap->devKind = save_pitch;
+ /* Try to prevent source valid region from growing too many rects by
+ * removing parts of it which are also in the destination valid region.
+ * Removing anything beyond that would lead to data loss.
+ */
+ if (REGION_NUM_RECTS(pValidSrc) > 20)
+ REGION_SUBTRACT(pScreen, pValidSrc, pValidSrc, pValidDst);
+
/* The copied bits are now valid in destination */
REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg);
REGION_UNINIT(pScreen, &CopyReg);
+
+ if (access_prepared)
+ exaFinishAccess(&pPixmap->drawable, fallback_index);
+ else if (need_sync && sync)
+ sync (pPixmap->drawable.pScreen);
}
/**
@@ -248,7 +271,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
* the framebuffer memory copy to the system memory copy. Both areas must be
* allocated.
*/
-static void
+void
exaCopyDirtyToSys (ExaMigrationPtr migrate)
{
PixmapPtr pPixmap = migrate->pPix;
@@ -256,9 +279,8 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate)
ExaPixmapPriv (pPixmap);
exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
- pExaScr->info->DownloadFromScreen, pExaPixmap->fb_ptr,
- pExaPixmap->sys_ptr, pExaPixmap->fb_pitch,
- pExaPixmap->sys_pitch, EXA_PREPARE_SRC, exaWaitSync);
+ pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
+ exaWaitSync);
}
/**
@@ -266,7 +288,7 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate)
* the system memory copy to the framebuffer memory copy. Both areas must be
* allocated.
*/
-static void
+void
exaCopyDirtyToFb (ExaMigrationPtr migrate)
{
PixmapPtr pPixmap = migrate->pPix;
@@ -274,9 +296,7 @@ exaCopyDirtyToFb (ExaMigrationPtr migrate)
ExaPixmapPriv (pPixmap);
exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
- pExaScr->info->UploadToScreen, pExaPixmap->sys_ptr,
- pExaPixmap->fb_ptr, pExaPixmap->sys_pitch,
- pExaPixmap->fb_pitch, EXA_PREPARE_DEST, exaMarkSync);
+ pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
}
/**
@@ -334,7 +354,7 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
exaCopyDirtyToFb (migrate);
- if (exaPixmapIsOffscreen(pPixmap))
+ if (exaPixmapHasGpuCopy(pPixmap))
return;
DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
@@ -344,14 +364,14 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
pPixmap->drawable.height,
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
- pExaPixmap->offscreen = TRUE;
+ pExaPixmap->use_gpu_copy = TRUE;
pPixmap->devKind = pExaPixmap->fb_pitch;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
void
-exaMoveInPixmap (PixmapPtr pPixmap)
+exaMoveInPixmap_classic (PixmapPtr pPixmap)
{
static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
.pReg = NULL };
@@ -375,7 +395,7 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
exaCopyDirtyToSys (migrate);
- if (exaPixmapIsOffscreen(pPixmap)) {
+ if (exaPixmapHasGpuCopy(pPixmap)) {
DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
(void*)(ExaGetPixmapPriv(pPixmap)->area ?
@@ -384,7 +404,7 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
pPixmap->drawable.height,
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
- pExaPixmap->offscreen = FALSE;
+ pExaPixmap->use_gpu_copy = FALSE;
pPixmap->devKind = pExaPixmap->sys_pitch;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
@@ -392,7 +412,7 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
}
void
-exaMoveOutPixmap (PixmapPtr pPixmap)
+exaMoveOutPixmap_classic (PixmapPtr pPixmap)
{
static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
.pReg = NULL };
@@ -433,13 +453,6 @@ exaMigrateTowardFb (ExaMigrationPtr migrate)
PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
- if (pExaPixmap == NULL) {
- DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n",
- (pointer)pPixmap,
- exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
- return;
- }
-
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
(pointer)pPixmap));
@@ -458,12 +471,16 @@ exaMigrateTowardFb (ExaMigrationPtr migrate)
pExaPixmap->score++;
if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
- !exaPixmapIsOffscreen(pPixmap))
+ !exaPixmapHasGpuCopy(pPixmap))
{
exaDoMoveInPixmap(migrate);
}
- ExaOffscreenMarkUsed (pPixmap);
+ if (exaPixmapHasGpuCopy(pPixmap)) {
+ exaCopyDirtyToFb (migrate);
+ ExaOffscreenMarkUsed (pPixmap);
+ } else
+ exaCopyDirtyToSys (migrate);
}
/**
@@ -476,13 +493,6 @@ exaMigrateTowardSys (ExaMigrationPtr migrate)
PixmapPtr pPixmap = migrate->pPix;
ExaPixmapPriv (pPixmap);
- if (pExaPixmap == NULL) {
- DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n",
- (pointer)pPixmap,
- exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
- return;
- }
-
DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
@@ -496,6 +506,12 @@ exaMigrateTowardSys (ExaMigrationPtr migrate)
if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
exaDoMoveOutPixmap(migrate);
+
+ if (exaPixmapHasGpuCopy(pPixmap)) {
+ exaCopyDirtyToFb (migrate);
+ ExaOffscreenMarkUsed (pPixmap);
+ } else
+ exaCopyDirtyToSys (migrate);
}
/**
@@ -508,9 +524,9 @@ exaAssertNotDirty (PixmapPtr pPixmap)
ExaPixmapPriv (pPixmap);
CARD8 *dst, *src;
RegionRec ValidReg;
- int dst_pitch, src_pitch, cpp, y, nbox;
+ int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
BoxPtr pBox;
- Bool ret = TRUE;
+ Bool ret = TRUE, save_use_gpu_copy;
if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
return ret;
@@ -529,7 +545,14 @@ exaAssertNotDirty (PixmapPtr pPixmap)
src_pitch = pExaPixmap->fb_pitch;
cpp = pPixmap->drawable.bitsPerPixel / 8;
- ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+ save_use_gpu_copy = pExaPixmap->use_gpu_copy;
+ save_pitch = pPixmap->devKind;
+ pExaPixmap->use_gpu_copy = TRUE;
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+
+ if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
+ goto skip;
+
while (nbox--) {
int rowbytes;
@@ -542,7 +565,7 @@ exaAssertNotDirty (PixmapPtr pPixmap)
continue;
rowbytes = (pBox->x2 - pBox->x1) * cpp;
- src = pExaPixmap->fb_ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
+ src = (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
for (y = pBox->y1; y < pBox->y2;
@@ -555,8 +578,13 @@ exaAssertNotDirty (PixmapPtr pPixmap)
}
}
}
+
+skip:
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+ pExaPixmap->use_gpu_copy = save_use_gpu_copy;
+ pPixmap->devKind = save_pitch;
+
out:
REGION_UNINIT(pScreen, &ValidReg);
return ret;
@@ -568,15 +596,12 @@ out:
* config file.
*/
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
ExaScreenPriv(pScreen);
int i, j;
- if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
- return;
-
/* If this debugging flag is set, check each pixmap for whether it is marked
* as clean, and if so, actually check if that's the case. This should help
* catch issues with failing to mark a drawable as dirty. While it will
@@ -596,7 +621,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
*/
for (i = 0; i < npixmaps; i++) {
if (exaPixmapIsPinned (pixmaps[i].pPix) &&
- !exaPixmapIsOffscreen (pixmaps[i].pPix))
+ !exaPixmapHasGpuCopy (pixmaps[i].pPix))
{
EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
pixmaps[i].pPix->drawable.width,
@@ -658,7 +683,7 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
}
for (i = 0; i < npixmaps; i++) {
- if (exaPixmapIsOffscreen(pixmaps[i].pPix)) {
+ if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
/* Found one in FB, so move all to FB. */
for (j = 0; j < npixmaps; j++)
exaMigrateTowardFb(pixmaps + i);
@@ -687,14 +712,34 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
/* If we couldn't fit everything in, abort */
for (i = 0; i < npixmaps; i++) {
- if (!exaPixmapIsOffscreen(pixmaps[i].pPix)) {
+ if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
return;
}
}
- /* Yay, everything's offscreen, mark memory as used */
+ /* Yay, everything has a gpu copy, mark memory as used */
for (i = 0; i < npixmaps; i++) {
ExaOffscreenMarkUsed (pixmaps[i].pPix);
}
}
}
+
+void
+exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+ ExaMigrationRec pixmaps[1];
+
+ if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ } else {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ }
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = pReg;
+
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ (void)ExaDoPrepareAccess(pPixmap, index);
+}
diff --git a/xserver/exa/exa_migration_mixed.c b/xserver/exa/exa_migration_mixed.c
new file mode 100644
index 000000000..fb4715135
--- /dev/null
+++ b/xserver/exa/exa_migration_mixed.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
+ int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
+ int usage_hint = pPixmap->usage_hint;
+ int paddedWidth = pExaPixmap->sys_pitch;
+
+ /* Already done. */
+ if (pExaPixmap->driverPriv)
+ return;
+
+ if (exaPixmapIsPinned(pPixmap))
+ return;
+
+ /* Can't accel 1/4 bpp. */
+ if (pExaPixmap->accel_blocked || bpp < 8)
+ return;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ } else {
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0);
+ }
+
+ if (!pExaPixmap->driverPriv)
+ return;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+}
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ int i;
+
+ /* If anything is pinned in system memory, we won't be able to
+ * accelerate.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapIsPinned (pixmaps[i].pPix) &&
+ !exaPixmapHasGpuCopy (pixmaps[i].pPix))
+ {
+ can_accel = FALSE;
+ break;
+ }
+ }
+
+ /* We can do nothing. */
+ if (!can_accel)
+ return;
+
+ for (i = 0; i < npixmaps; i++) {
+ PixmapPtr pPixmap = pixmaps[i].pPix;
+ ExaPixmapPriv(pPixmap);
+
+ if (!pExaPixmap->driverPriv)
+ exaCreateDriverPixmap_mixed(pPixmap);
+
+ if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
+ ExaScreenPriv(pPixmap->drawable.pScreen);
+
+ /* This pitch is needed for proper acceleration. For some reason
+ * there are pixmaps without pDamage and a bad fb_pitch value.
+ * So setting devKind when only exaPixmapHasGpuCopy() is true
+ * causes corruption. Pixmaps without pDamage are not migrated
+ * and should have a valid devKind at all times, so that's why this
+ * isn't causing problems. Pixmaps have their gpu pitch set the
+ * first time in the MPH call from exaCreateDriverPixmap_mixed().
+ */
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+ exaCopyDirtyToFb(pixmaps + i);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap &&
+ !pixmaps[i].as_dst && !pixmaps[i].pReg)
+ pExaScr->deferred_mixed_pixmap = NULL;
+ }
+
+ pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ }
+}
+
+void
+exaMoveInPixmap_mixed(PixmapPtr pPixmap)
+{
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration(pixmaps, 1, TRUE);
+}
+
+void
+exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ PixmapPtr pPixmap = closure;
+ ExaPixmapPriv(pPixmap);
+
+ /* Move back results of software rendering on system memory copy of mixed driver
+ * pixmap (see exaPrepareAccessReg_mixed).
+ *
+ * Defer moving the destination back into the driver pixmap, to try and save
+ * overhead on multiple subsequent software fallbacks.
+ */
+ if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
+ ExaScreenPriv(pPixmap->drawable.pScreen);
+
+ if (pExaScr->deferred_mixed_pixmap &&
+ pExaScr->deferred_mixed_pixmap != pPixmap)
+ exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
+ pExaScr->deferred_mixed_pixmap = pPixmap;
+ }
+}
+
+/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
+ * use the DownloadFromScreen hook to retrieve contents to a copy in system
+ * memory, perform software rendering on that and move back the results with the
+ * UploadToScreen hook (see exaDamageReport_mixed).
+ */
+void
+exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+ ExaPixmapPriv(pPixmap);
+ Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ Bool success;
+
+ success = ExaDoPrepareAccess(pPixmap, index);
+
+ if (success && has_gpu_copy && pExaPixmap->pDamage) {
+ /* You cannot do accelerated operations while a buffer is mapped. */
+ exaFinishAccess(&pPixmap->drawable, index);
+ /* Update the gpu view of both deferred destination pixmaps and of
+ * source pixmaps that were migrated with a bounding region.
+ */
+ exaMoveInPixmap_mixed(pPixmap);
+ success = ExaDoPrepareAccess(pPixmap, index);
+
+ if (success) {
+ /* We have a gpu pixmap that can be accessed, we don't need the cpu
+ * copy anymore. Drivers that prefer DFS, should fail prepare
+ * access.
+ */
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+
+ return;
+ }
+ }
+
+ if (!success) {
+ ExaMigrationRec pixmaps[1];
+
+ /* Do we need to allocate our system buffer? */
+ if (!pExaPixmap->sys_ptr) {
+ pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
+ pPixmap->drawable.height);
+ if (!pExaPixmap->sys_ptr)
+ FatalError("EXA: malloc failed for size %d bytes\n",
+ pExaPixmap->sys_pitch * pPixmap->drawable.height);
+ }
+
+ if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ } else {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ }
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = pReg;
+
+ if (!pExaPixmap->pDamage &&
+ (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
+ Bool as_dst = pixmaps[0].as_dst;
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
+ DamageReportNonEmpty, TRUE,
+ pPixmap->drawable.pScreen,
+ pPixmap);
+
+ DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
+
+ if (has_gpu_copy) {
+ exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+ pPixmap->drawable.height);
+
+ /* We don't know which region of the destination will be damaged,
+ * have to assume all of it
+ */
+ if (as_dst) {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pReg = NULL;
+ }
+ exaCopyDirtyToSys(pixmaps);
+ }
+
+ if (as_dst)
+ exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+ pPixmap->drawable.height);
+ } else if (has_gpu_copy)
+ exaCopyDirtyToSys(pixmaps);
+
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ pExaPixmap->use_gpu_copy = FALSE;
+ }
+}
+
diff --git a/xserver/exa/exa_mixed.c b/xserver/exa/exa_mixed.c
new file mode 100644
index 000000000..21cc3bd13
--- /dev/null
+++ b/xserver/exa/exa_mixed.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps + better initial placement code.
+ */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ /* We will allocate the system pixmap later if needed. */
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->sys_pitch = paddedWidth;
+
+ pExaPixmap->area = NULL;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ /* A scratch pixmap will become a driver pixmap right away. */
+ if (!w || !h) {
+ exaCreateDriverPixmap_mixed(pPixmap);
+ pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ } else {
+ pExaPixmap->use_gpu_copy = FALSE;
+
+ if (w == 1 && h == 1) {
+ pExaPixmap->sys_ptr = malloc((pPixmap->drawable.bitsPerPixel + 7) / 8);
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
+ DamageReportNonEmpty, TRUE,
+ pPixmap->drawable.pScreen,
+ pPixmap);
+
+ DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
+ }
+ }
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret, has_gpu_copy;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pPixData) {
+ if (pExaPixmap->driverPriv) {
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ pExaPixmap->use_gpu_copy = FALSE;
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ }
+
+ has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+
+ if (width <= 0)
+ width = pPixmap->drawable.width;
+
+ if (height <= 0)
+ height = pPixmap->drawable.height;
+
+ if (bitsPerPixel <= 0) {
+ if (depth <= 0)
+ bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+ else
+ bitsPerPixel = BitsPerPixel(depth);
+ }
+
+ if (depth <= 0)
+ depth = pPixmap->drawable.depth;
+
+ if (width != pPixmap->drawable.width ||
+ height != pPixmap->drawable.height ||
+ depth != pPixmap->drawable.depth ||
+ bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
+ if (pExaPixmap->driverPriv) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ REGION_EMPTY(pScreen, &pExaPixmap->validFB);
+ }
+
+ /* Need to re-create system copy if there's also a GPU copy */
+ if (has_gpu_copy && pExaPixmap->sys_ptr) {
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->sys_pitch = devKind > 0 ? devKind :
+ PixmapBytePad(width, depth);
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ REGION_EMPTY(pScreen, &pExaPixmap->validSys);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap)
+ pExaScr->deferred_mixed_pixmap = NULL;
+ }
+ }
+
+ if (has_gpu_copy) {
+ pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+ } else {
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+
+ /* Only pass driver pixmaps to the driver. */
+ if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ if (ret == TRUE)
+ goto out;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ if (has_gpu_copy) {
+ pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->fb_pitch = pPixmap->devKind;
+ } else {
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+ }
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ /* During a fallback we must finish access, but we don't know the index. */
+ if (pExaScr->fallback_counter)
+ exaFinishAccess(&pPixmap->drawable, -1);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap)
+ pExaScr->deferred_mixed_pixmap = NULL;
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+
+ if (pExaPixmap->pDamage) {
+ if (pExaPixmap->sys_ptr)
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ pointer saved_ptr;
+ Bool ret;
+
+ if (!pExaPixmap->driverPriv)
+ return FALSE;
+
+ saved_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = saved_ptr;
+
+ return ret;
+}
diff --git a/xserver/exa/exa_offscreen.c b/xserver/exa/exa_offscreen.c
index 4aaa2c132..e3a9ab2f6 100644
--- a/xserver/exa/exa_offscreen.c
+++ b/xserver/exa/exa_offscreen.c
@@ -93,7 +93,7 @@ exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
{
ExaOffscreenArea *begin, *end, *best;
unsigned cost, best_cost;
- int avail, real_size, tmp;
+ int avail, real_size;
best_cost = UINT_MAX;
begin = end = pExaScr->info->offScreenAreas;
@@ -111,10 +111,7 @@ exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
break;
/* adjust size needed to account for alignment loss for this area */
- real_size = size;
- tmp = begin->base_offset % align;
- if (tmp)
- real_size += (align - tmp);
+ real_size = size + (begin->base_offset + begin->size - size) % align;
while (avail < real_size && end != NULL)
{
@@ -172,7 +169,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
{
ExaOffscreenArea *area;
ExaScreenPriv (pScreen);
- int tmp, real_size = 0;
+ int real_size = 0, largest_avail = 0;
#if DEBUG_OFFSCREEN
static int number = 0;
ErrorF("================= ============ allocating a new pixmap %d\n", ++number);
@@ -205,14 +202,14 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
continue;
/* adjust size to match alignment requirement */
- real_size = size;
- tmp = area->base_offset % align;
- if (tmp)
- real_size += (align - tmp);
+ real_size = size + (area->base_offset + area->size - size) % align;
/* does it fit? */
if (real_size <= area->size)
break;
+
+ if (area->size > largest_avail)
+ largest_avail = area->size;
}
if (!area)
@@ -228,10 +225,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
}
/* adjust size needed to account for alignment loss for this area */
- real_size = size;
- tmp = area->base_offset % align;
- if (tmp)
- real_size += (align - tmp);
+ real_size = size + (area->base_offset + area->size - size) % align;
/*
* Kick out first area if in use
@@ -254,17 +248,27 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
ExaOffscreenArea *new_area = xalloc (sizeof (ExaOffscreenArea));
if (!new_area)
return NULL;
- new_area->base_offset = area->base_offset + real_size;
+ new_area->base_offset = area->base_offset;
+
new_area->offset = new_area->base_offset;
+ new_area->align = 0;
new_area->size = area->size - real_size;
new_area->state = ExaOffscreenAvail;
new_area->save = NULL;
new_area->last_use = 0;
new_area->eviction_cost = 0;
- new_area->next = area->next;
- area->next = new_area;
+ new_area->next = area;
+ new_area->prev = area->prev;
+ if (area->prev->next)
+ area->prev->next = new_area;
+ else
+ pExaScr->info->offScreenAreas = new_area;
+ area->prev = new_area;
+ area->base_offset = new_area->base_offset + new_area->size;
area->size = real_size;
- }
+ } else
+ pExaScr->numOffscreenAvailable--;
+
/*
* Mark this area as in use
*/
@@ -277,6 +281,7 @@ exaOffscreenAlloc (ScreenPtr pScreen, int size, int align,
area->last_use = pExaScr->offScreenCounter++;
area->offset = (area->base_offset + align - 1);
area->offset -= area->offset % align;
+ area->align = align;
ExaOffscreenValidate (pScreen);
@@ -371,6 +376,9 @@ exaEnableDisableFBAccess (int index, Bool enable)
ScreenPtr pScreen = screenInfo.screens[index];
ExaScreenPriv (pScreen);
+ if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
+ return;
+
if (!enable && pExaScr->disableFbCount++ == 0) {
if (pExaScr->info->exa_minor < 1)
ExaOffscreenSwapOut (pScreen);
@@ -388,7 +396,7 @@ exaEnableDisableFBAccess (int index, Bool enable)
/* merge the next free area into this one */
static void
-ExaOffscreenMerge (ExaOffscreenArea *area)
+ExaOffscreenMerge (ExaScreenPrivPtr pExaScr, ExaOffscreenArea *area)
{
ExaOffscreenArea *next = area->next;
@@ -396,7 +404,13 @@ ExaOffscreenMerge (ExaOffscreenArea *area)
area->size += next->size;
/* frob pointer */
area->next = next->next;
+ if (area->next)
+ area->next->prev = area;
+ else
+ pExaScr->info->offScreenAreas->prev = area;
xfree (next);
+
+ pExaScr->numOffscreenAvailable--;
}
/**
@@ -433,19 +447,19 @@ exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
if (area == pExaScr->info->offScreenAreas)
prev = NULL;
else
- for (prev = pExaScr->info->offScreenAreas; prev; prev = prev->next)
- if (prev->next == area)
- break;
+ prev = area->prev;
+
+ pExaScr->numOffscreenAvailable++;
/* link with next area if free */
if (next && next->state == ExaOffscreenAvail)
- ExaOffscreenMerge (area);
+ ExaOffscreenMerge (pExaScr, area);
/* link with prev area if free */
if (prev && prev->state == ExaOffscreenAvail)
{
area = prev;
- ExaOffscreenMerge (area);
+ ExaOffscreenMerge (pExaScr, area);
}
ExaOffscreenValidate (pScreen);
@@ -466,6 +480,167 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap)
}
/**
+ * Defragment offscreen memory by compacting allocated areas at the end of it,
+ * leaving the total amount of memory available as a single area at the
+ * beginning (when there are no pinned allocations).
+ */
+_X_HIDDEN ExaOffscreenArea*
+ExaOffscreenDefragment (ScreenPtr pScreen)
+{
+ ExaScreenPriv (pScreen);
+ ExaOffscreenArea *area, *largest_available = NULL;
+ int largest_size = 0;
+ PixmapPtr pDstPix;
+ ExaPixmapPrivPtr pExaDstPix;
+
+ pDstPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, 0, 0);
+
+ if (!pDstPix)
+ return NULL;
+
+ pExaDstPix = ExaGetPixmapPriv (pDstPix);
+ pExaDstPix->use_gpu_copy = TRUE;
+
+ for (area = pExaScr->info->offScreenAreas->prev;
+ area != pExaScr->info->offScreenAreas;
+ )
+ {
+ ExaOffscreenArea *prev = area->prev;
+ PixmapPtr pSrcPix;
+ ExaPixmapPrivPtr pExaSrcPix;
+ Bool save_use_gpu_copy;
+ int save_pitch;
+
+ if (area->state != ExaOffscreenAvail ||
+ prev->state == ExaOffscreenLocked ||
+ (prev->state == ExaOffscreenRemovable &&
+ prev->save != exaPixmapSave)) {
+ area = prev;
+ continue;
+ }
+
+ if (prev->state == ExaOffscreenAvail) {
+ if (area == largest_available) {
+ largest_available = prev;
+ largest_size += prev->size;
+ }
+ area = prev;
+ ExaOffscreenMerge (pExaScr, area);
+ continue;
+ }
+
+ if (area->size > largest_size) {
+ largest_available = area;
+ largest_size = area->size;
+ }
+
+ pSrcPix = prev->privData;
+ pExaSrcPix = ExaGetPixmapPriv (pSrcPix);
+
+ pExaDstPix->fb_ptr = pExaScr->info->memoryBase +
+ area->base_offset + area->size - prev->size + prev->base_offset -
+ prev->offset;
+ pExaDstPix->fb_ptr -= (unsigned long)pExaDstPix->fb_ptr % prev->align;
+
+ if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) {
+ area = prev;
+ continue;
+ }
+
+ if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) &&
+ (pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) {
+ area = prev;
+ continue;
+ }
+
+ save_use_gpu_copy = pExaSrcPix->use_gpu_copy;
+ save_pitch = pSrcPix->devKind;
+
+ pExaSrcPix->use_gpu_copy = TRUE;
+ pSrcPix->devKind = pExaSrcPix->fb_pitch;
+
+ pDstPix->drawable.width = pSrcPix->drawable.width;
+ pDstPix->devKind = pSrcPix->devKind;
+ pDstPix->drawable.height = pSrcPix->drawable.height;
+ pDstPix->drawable.depth = pSrcPix->drawable.depth;
+ pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel;
+
+ if (!pExaScr->info->PrepareCopy (pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) {
+ pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
+ pSrcPix->devKind = save_pitch;
+ area = prev;
+ continue;
+ }
+
+ pExaScr->info->Copy (pDstPix, 0, 0, 0, 0, pDstPix->drawable.width,
+ pDstPix->drawable.height);
+ pExaScr->info->DoneCopy (pDstPix);
+ exaMarkSync (pScreen);
+
+ DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n",
+ prev->base_offset, prev->offset, prev->base_offset + prev->size,
+ area->base_offset, area->offset, area->base_offset + area->size));
+
+ /* Calculate swapped area offsets and sizes */
+ area->base_offset = prev->base_offset;
+ area->offset = area->base_offset;
+ prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr;
+ assert(prev->offset >= pExaScr->info->offScreenBase &&
+ prev->offset < pExaScr->info->memorySize);
+ prev->base_offset = prev->offset;
+ if (area->next)
+ prev->size = area->next->base_offset - prev->base_offset;
+ else
+ prev->size = pExaScr->info->memorySize - prev->base_offset;
+ area->size = prev->base_offset - area->base_offset;
+
+ DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n",
+ area->base_offset, area->offset, area->base_offset + area->size,
+ prev->base_offset, prev->offset, prev->base_offset + prev->size));
+
+ /* Swap areas in list */
+ if (area->next)
+ area->next->prev = prev;
+ else
+ pExaScr->info->offScreenAreas->prev = prev;
+ if (prev->prev->next)
+ prev->prev->next = area;
+ else
+ pExaScr->info->offScreenAreas = area;
+ prev->next = area->next;
+ area->next = prev;
+ area->prev = prev->prev;
+ prev->prev = area;
+ if (!area->prev->next)
+ pExaScr->info->offScreenAreas = area;
+
+#if DEBUG_OFFSCREEN
+ if (prev->prev == prev || prev->next == prev)
+ ErrorF("Whoops, prev points to itself!\n");
+
+ if (area->prev == area || area->next == area)
+ ErrorF("Whoops, area points to itself!\n");
+#endif
+
+ pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr;
+ pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
+ pSrcPix->devKind = save_pitch;
+ }
+
+ pDstPix->drawable.width = 0;
+ pDstPix->drawable.height = 0;
+ pDstPix->drawable.depth = 0;
+ pDstPix->drawable.bitsPerPixel = 0;
+
+ (*pScreen->DestroyPixmap) (pDstPix);
+
+ if (area->state == ExaOffscreenAvail && area->size > largest_size)
+ return area;
+
+ return largest_available;
+}
+
+/**
* exaOffscreenInit initializes the offscreen memory manager.
*
* @param pScreen current screen
@@ -488,15 +663,18 @@ exaOffscreenInit (ScreenPtr pScreen)
area->state = ExaOffscreenAvail;
area->base_offset = pExaScr->info->offScreenBase;
area->offset = area->base_offset;
+ area->align = 0;
area->size = pExaScr->info->memorySize - area->base_offset;
area->save = NULL;
area->next = NULL;
+ area->prev = area;
area->last_use = 0;
area->eviction_cost = 0;
/* Add it to the free areas */
pExaScr->info->offScreenAreas = area;
pExaScr->offScreenCounter = 1;
+ pExaScr->numOffscreenAvailable = 1;
ExaOffscreenValidate (pScreen);
diff --git a/xserver/exa/exa_priv.h b/xserver/exa/exa_priv.h
index 0911c6d8a..21d964683 100644
--- a/xserver/exa/exa_priv.h
+++ b/xserver/exa/exa_priv.h
@@ -33,7 +33,6 @@
#include "exa.h"
#include <X11/X.h>
-#define NEED_EVENTS
#include <X11/Xproto.h>
#ifdef MITSHM
#include "shmint.h"
@@ -86,6 +85,18 @@ exaDrawableLocation(DrawablePtr pDrawable);
#define EXA_MAX_FB FB_OVERLAY_MAX
#endif
+#ifdef DEBUG
+#define EXA_FatalErrorDebug(x) FatalError x
+#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x
+#else
+#define EXA_FatalErrorDebug(x) ErrorF x
+#define EXA_FatalErrorDebugWithRet(x, ret) \
+do { \
+ ErrorF x; \
+ return ret; \
+} while (0)
+#endif
+
/**
* This is the list of migration heuristics supported by EXA. See
* exaDoMigration() for what their implementations do.
@@ -128,9 +139,21 @@ typedef struct {
#define EXA_NUM_GLYPH_CACHES 4
+#define EXA_FALLBACK_COPYWINDOW (1 << 0)
+#define EXA_ACCEL_COPYWINDOW (1 << 1)
+
+typedef struct _ExaMigrationRec {
+ Bool as_dst;
+ Bool as_src;
+ PixmapPtr pPix;
+ RegionPtr pReg;
+} ExaMigrationRec, *ExaMigrationPtr;
+
typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
typedef struct {
ExaDriverPtr info;
+ ScreenBlockHandlerProcPtr SavedBlockHandler;
+ ScreenWakeupHandlerProcPtr SavedWakeupHandler;
CreateGCProcPtr SavedCreateGC;
CloseScreenProcPtr SavedCloseScreen;
GetImageProcPtr SavedGetImage;
@@ -142,6 +165,7 @@ typedef struct {
BitmapToRegionProcPtr SavedBitmapToRegion;
CreateScreenResourcesProcPtr SavedCreateScreenResources;
ModifyPixmapHeaderProcPtr SavedModifyPixmapHeader;
+ SourceValidateProcPtr SavedSourceValidate;
#ifdef RENDER
CompositeProcPtr SavedComposite;
TrianglesProcPtr SavedTriangles;
@@ -149,15 +173,44 @@ typedef struct {
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
#endif
-
+ void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+ Bool (*pixmap_has_gpu_copy) (PixmapPtr pPixmap);
+ void (*do_move_in_pixmap) (PixmapPtr pPixmap);
+ void (*do_move_out_pixmap) (PixmapPtr pPixmap);
+ void (*prepare_access_reg)(PixmapPtr pPixmap, int index, RegionPtr pReg);
+
Bool swappedOut;
enum ExaMigrationHeuristic migration;
Bool checkDirtyCorrectness;
unsigned disableFbCount;
Bool optimize_migration;
unsigned offScreenCounter;
+ unsigned numOffscreenAvailable;
+ CARD32 lastDefragment;
+ CARD32 nextDefragment;
+ PixmapPtr deferred_mixed_pixmap;
+
+ /* Reference counting for accessed pixmaps */
+ struct {
+ PixmapPtr pixmap;
+ int count;
+ Bool retval;
+ } access[EXA_NUM_PREPARE_INDICES];
+
+ /* Holds information on fallbacks that cannot be relayed otherwise. */
+ unsigned int fallback_flags;
+ unsigned int fallback_counter;
ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
+
+ /**
+ * Regions affected by fallback composite source / mask operations.
+ */
+
+ RegionRec srcReg;
+ RegionRec maskReg;
+ PixmapPtr srcPix;
+
} ExaScreenPrivRec, *ExaScreenPrivPtr;
/*
@@ -174,9 +227,48 @@ typedef struct {
extern DevPrivateKey exaScreenPrivateKey;
extern DevPrivateKey exaPixmapPrivateKey;
+extern DevPrivateKey exaGCPrivateKey;
#define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)dixLookupPrivate(&(s)->devPrivates, exaScreenPrivateKey))
#define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s)
+#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixLookupPrivate(&(gc)->devPrivates, exaGCPrivateKey))
+#define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc)
+
+/*
+ * Some macros to deal with function wrapping.
+ */
+#define wrap(priv, real, mem, func) {\
+ priv->Saved##mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->Saved##mem; \
+}
+
+#define swap(priv, real, mem) {\
+ void *tmp = priv->Saved##mem; \
+ priv->Saved##mem = real->mem; \
+ real->mem = tmp; \
+}
+
+#define EXA_PRE_FALLBACK(_screen_) \
+ ExaScreenPriv(_screen_); \
+ pExaScr->fallback_counter++;
+
+#define EXA_POST_FALLBACK(_screen_) \
+ pExaScr->fallback_counter--;
+
+#define EXA_PRE_FALLBACK_GC(_gc_) \
+ ExaScreenPriv(_gc_->pScreen); \
+ ExaGCPriv(_gc_); \
+ pExaScr->fallback_counter++; \
+ swap(pExaGC, _gc_, ops);
+
+#define EXA_POST_FALLBACK_GC(_gc_) \
+ pExaScr->fallback_counter--; \
+ swap(pExaGC, _gc_, ops);
+
/** Align an offset to an arbitrary alignment */
#define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
(((offset) + (align) - 1) % (align)))
@@ -201,7 +293,7 @@ extern DevPrivateKey exaPixmapPrivateKey;
typedef struct {
ExaOffscreenArea *area;
int score; /**< score for the move-in vs move-out heuristic */
- Bool offscreen;
+ Bool use_gpu_copy;
CARD8 *sys_ptr; /**< pointer to pixmap data in system memory */
int sys_pitch; /**< pitch of pixmap in system memory */
@@ -237,17 +329,19 @@ typedef struct {
*/
void *driverPriv;
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
-
-typedef struct _ExaMigrationRec {
- Bool as_dst;
- Bool as_src;
- PixmapPtr pPix;
- RegionPtr pReg;
-} ExaMigrationRec, *ExaMigrationPtr;
typedef struct {
+ /* GC values from the layer below. */
+ GCOps *Savedops;
+ GCFuncs *Savedfuncs;
+} ExaGCPrivRec, *ExaGCPrivPtr;
+
+typedef struct {
+ PicturePtr pDst;
INT16 xSrc;
INT16 ySrc;
+ INT16 xMask;
+ INT16 yMask;
INT16 xDst;
INT16 yDst;
INT16 width;
@@ -280,6 +374,11 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits);
+void
+ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
+ Bool upsidedown, Pixel bitplane, void *closure);
+
RegionPtr
ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty);
@@ -325,6 +424,13 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
int w, int h, int x, int y);
void
+ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+void
+ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d);
+
+void
ExaCheckGetSpans (DrawablePtr pDrawable,
int wMax,
DDXPointPtr ppt,
@@ -363,6 +469,34 @@ void
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
+RegionPtr
+exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown);
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure);
+
extern const GCOps exaOps;
#ifdef RENDER
@@ -388,6 +522,9 @@ ExaOffscreenSwapOut (ScreenPtr pScreen);
void
ExaOffscreenSwapIn (ScreenPtr pScreen);
+ExaOffscreenArea*
+ExaOffscreenDefragment (ScreenPtr pScreen);
+
Bool
exaOffscreenInit(ScreenPtr pScreen);
@@ -395,11 +532,8 @@ void
ExaOffscreenFini (ScreenPtr pScreen);
/* exa.c */
-void
-ExaDoPrepareAccess(DrawablePtr pDrawable, int index);
-
-void
-exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg);
+Bool
+ExaDoPrepareAccess(PixmapPtr pPixmap, int index);
void
exaPrepareAccess(DrawablePtr pDrawable, int index);
@@ -415,7 +549,7 @@ exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
int *xp, int *yp);
Bool
-exaPixmapIsOffscreen(PixmapPtr p);
+exaPixmapHasGpuCopy(PixmapPtr p);
PixmapPtr
exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp);
@@ -423,22 +557,82 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp);
PixmapPtr
exaGetDrawablePixmap(DrawablePtr pDrawable);
-RegionPtr
-exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
- int srcx, int srcy, int width, int height, int dstx, int dsty);
+void
+exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure);
+exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
+
+void
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+
+Bool
+exaPixmapIsPinned (PixmapPtr pPix);
+
+extern const GCFuncs exaGCFuncs;
+
+/* exa_classic.c */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap);
+
+Bool
+exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap);
+
+/* exa_driver.c */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap);
+
+Bool
+exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap);
+
+/* exa_mixed.c */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap);
+
+Bool
+exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap);
+
+/* exa_migration_mixed.c */
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap);
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+
+void
+exaMoveInPixmap_mixed(PixmapPtr pPixmap);
+
+void
+exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure);
+
+void
+exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg);
/* exa_render.c */
Bool
@@ -461,6 +655,7 @@ exaComposite(CARD8 op,
void
exaCompositeRects(CARD8 op,
PicturePtr Src,
+ PicturePtr pMask,
PicturePtr pDst,
int nrect,
ExaCompositeRectPtr rects);
@@ -493,11 +688,26 @@ exaGlyphs (CARD8 op,
GlyphListPtr list,
GlyphPtr *glyphs);
-/* exa_migration.c */
+/* exa_migration_classic.c */
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+exaCopyDirtyToSys (ExaMigrationPtr migrate);
+
+void
+exaCopyDirtyToFb (ExaMigrationPtr migrate);
+
+void
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
void
exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area);
+void
+exaMoveOutPixmap_classic (PixmapPtr pPixmap);
+
+void
+exaMoveInPixmap_classic (PixmapPtr pPixmap);
+
+void
+exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg);
+
#endif /* EXAPRIV_H */
diff --git a/xserver/exa/exa_render.c b/xserver/exa/exa_render.c
index 8c6bbf0f6..1b68e1cdc 100644
--- a/xserver/exa/exa_render.c
+++ b/xserver/exa/exa_render.c
@@ -54,6 +54,12 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
case PICT_x8r8g8b8:
snprintf(format, 20, "XRGB8888");
break;
+ case PICT_b8g8r8a8:
+ snprintf(format, 20, "BGRA8888");
+ break;
+ case PICT_b8g8r8x8:
+ snprintf(format, 20, "BGRX8888");
+ break;
case PICT_r5g6b5:
snprintf(format, 20, "RGB565 ");
break;
@@ -71,11 +77,17 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
break;
}
- loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+ if (pict->pDrawable) {
+ loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+
+ snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+ pict->pDrawable->height, pict->repeat ?
+ " R" : "");
+ } else {
+ loc = '-';
- snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
- pict->pDrawable->height, pict->repeat ?
- " R" : "");
+ snprintf(size, 20, "%s", pict->repeat ? " R" : "");
+ }
snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
}
@@ -138,32 +150,26 @@ exaGetPixelFromRGBA(CARD32 *pixel,
CARD16 green,
CARD16 blue,
CARD16 alpha,
- CARD32 format)
+ PictFormatPtr pFormat)
{
int rbits, bbits, gbits, abits;
int rshift, bshift, gshift, ashift;
*pixel = 0;
- if (!PICT_FORMAT_COLOR(format))
+ if (!PICT_FORMAT_COLOR(pFormat->format) &&
+ PICT_FORMAT_TYPE(pFormat->format) != PICT_TYPE_A)
return FALSE;
- rbits = PICT_FORMAT_R(format);
- gbits = PICT_FORMAT_G(format);
- bbits = PICT_FORMAT_B(format);
- abits = PICT_FORMAT_A(format);
+ rbits = PICT_FORMAT_R(pFormat->format);
+ gbits = PICT_FORMAT_G(pFormat->format);
+ bbits = PICT_FORMAT_B(pFormat->format);
+ abits = PICT_FORMAT_A(pFormat->format);
- if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
- bshift = 0;
- gshift = bbits;
- rshift = gshift + gbits;
- ashift = rshift + rbits;
- } else { /* PICT_TYPE_ABGR */
- rshift = 0;
- gshift = rbits;
- bshift = gshift + gbits;
- ashift = bshift + bbits;
- }
+ rshift = pFormat->direct.red;
+ gshift = pFormat->direct.green;
+ bshift = pFormat->direct.blue;
+ ashift = pFormat->direct.alpha;
*pixel |= ( blue >> (16 - bbits)) << bshift;
*pixel |= ( red >> (16 - rbits)) << rshift;
@@ -179,12 +185,13 @@ exaGetRGBAFromPixel(CARD32 pixel,
CARD16 *green,
CARD16 *blue,
CARD16 *alpha,
- CARD32 format)
+ PictFormatPtr pFormat,
+ PictFormatShort format)
{
int rbits, bbits, gbits, abits;
int rshift, bshift, gshift, ashift;
- if (!PICT_FORMAT_COLOR(format))
+ if (!PICT_FORMAT_COLOR(format) && PICT_FORMAT_TYPE(format) != PICT_TYPE_A)
return FALSE;
rbits = PICT_FORMAT_R(format);
@@ -192,34 +199,42 @@ exaGetRGBAFromPixel(CARD32 pixel,
bbits = PICT_FORMAT_B(format);
abits = PICT_FORMAT_A(format);
- if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
+ if (pFormat) {
+ rshift = pFormat->direct.red;
+ gshift = pFormat->direct.green;
+ bshift = pFormat->direct.blue;
+ ashift = pFormat->direct.alpha;
+ } else if (format == PICT_a8r8g8b8) {
+ rshift = 16;
+ gshift = 8;
bshift = 0;
- gshift = bbits;
- rshift = gshift + gbits;
- ashift = rshift + rbits;
- } else { /* PICT_TYPE_ABGR */
- rshift = 0;
- gshift = rbits;
- bshift = gshift + gbits;
- ashift = bshift + bbits;
- }
-
- *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
- while (rbits < 16) {
- *red |= *red >> rbits;
- rbits <<= 1;
- }
+ ashift = 24;
+ } else
+ FatalError("EXA bug: exaGetRGBAFromPixel() doesn't match "
+ "createSourcePicture()\n");
+
+ if (rbits) {
+ *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
+ while (rbits < 16) {
+ *red |= *red >> rbits;
+ rbits <<= 1;
+ }
- *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
- while (gbits < 16) {
- *green |= *green >> gbits;
- gbits <<= 1;
- }
+ *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
+ while (gbits < 16) {
+ *green |= *green >> gbits;
+ gbits <<= 1;
+ }
- *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
- while (bbits < 16) {
- *blue |= *blue >> bbits;
- bbits <<= 1;
+ *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
+ while (bbits < 16) {
+ *blue |= *blue >> bbits;
+ bbits <<= 1;
+ }
+ } else {
+ *red = 0x0000;
+ *green = 0x0000;
+ *blue = 0x0000;
}
if (abits) {
@@ -250,28 +265,26 @@ exaTryDriverSolidFill(PicturePtr pSrc,
int nbox;
int dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
+ ExaPixmapPrivPtr pDstExaPix;
CARD32 pixel;
CARD16 red, green, blue, alpha;
- ExaMigrationRec pixmaps[1];
pDstPix = exaGetDrawablePixmap (pDst->pDrawable);
- pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
-
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
pDstExaPix = ExaGetPixmapPriv(pDstPix);
- /* Check whether the accelerator can use these pixmaps.
+ /* Check whether the accelerator can use the destination pixmap.
*/
- if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked)
+ if (pDstExaPix->accel_blocked)
{
return -1;
}
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ if (pSrc->pDrawable) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
xSrc, ySrc, 0, 0, xDst, yDst,
@@ -282,31 +295,34 @@ exaTryDriverSolidFill(PicturePtr pSrc,
REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
- pixel = exaGetPixmapFirstPixel (pSrcPix);
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = &region;
- exaDoMigration(pixmaps, 1, TRUE);
-
- if (!exaPixmapIsOffscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
- }
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
+ pixel = exaGetPixmapFirstPixel (pSrcPix);
+ } else
+ pixel = pSrc->pSourcePict->solidFill.color;
if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
- pSrc->format))
+ pSrc->pFormat, pSrc->format) ||
+ !exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
+ pDst->pFormat))
{
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return -1;
}
- if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
- pDst->format))
- {
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPix;
+ pixmaps[0].pReg = &region;
+ exaDoMigration(pixmaps, 1, TRUE);
+ }
+
+ if (!exaPixmapHasGpuCopy(pDstPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return -1;
+ return 0;
}
if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
@@ -334,22 +350,29 @@ exaTryDriverSolidFill(PicturePtr pSrc,
static int
exaTryDriverCompositeRects(CARD8 op,
PicturePtr pSrc,
+ PicturePtr pMask,
PicturePtr pDst,
int nrect,
ExaCompositeRectPtr rects)
{
ExaScreenPriv (pDst->pDrawable->pScreen);
- int src_off_x, src_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
- struct _Pixmap scratch;
- ExaMigrationRec pixmaps[2];
+ int src_off_x = 0, src_off_y = 0, mask_off_x = 0, mask_off_y = 0;
+ int dst_off_x, dst_off_y;
+ PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+ ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
if (!pExaScr->info->PrepareComposite)
return -1;
- pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ }
+
+ if (pMask && pMask->pDrawable) {
+ pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
+ pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
+ }
pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
pDstExaPix = ExaGetPixmapPriv(pDstPix);
@@ -358,61 +381,92 @@ exaTryDriverCompositeRects(CARD8 op,
* FIXME: If it cannot, use temporary pixmaps so that the drawing
* happens within limits.
*/
- if (pSrcExaPix->accel_blocked ||
- pDstExaPix->accel_blocked)
+ if (pDstExaPix->accel_blocked ||
+ (pSrcExaPix && pSrcExaPix->accel_blocked) ||
+ (pMaskExaPix && pMaskExaPix->accel_blocked))
{
return -1;
}
if (pExaScr->info->CheckComposite &&
- !(*pExaScr->info->CheckComposite) (op, pSrc, NULL, pDst))
+ !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
{
return -1;
}
-
- exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = exaOpReadsDestination(op);
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = NULL;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPix;
- pixmaps[1].pReg = NULL;
- exaDoMigration(pixmaps, 2, TRUE);
-
- pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!exaPixmapIsOffscreen(pDstPix))
- return 0;
-
- if (!pSrcPix && pExaScr->info->UploadToScratch)
- {
- pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
- if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
- pSrcPix = &scratch;
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[3];
+ int i = 0;
+
+ pixmaps[i].as_dst = TRUE;
+ pixmaps[i].as_src = exaOpReadsDestination(op);
+ pixmaps[i].pPix = pDstPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+
+ if (pSrcPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pSrcPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ if (pMaskPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pMaskPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ exaDoMigration(pixmaps, i, TRUE);
}
- if (!pSrcPix)
+ pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix)
return 0;
- if (!(*pExaScr->info->PrepareComposite) (op, pSrc, NULL, pDst, pSrcPix,
- NULL, pDstPix))
+ if (pSrcPix) {
+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!pSrcPix)
+ return 0;
+ }
+
+ if (pMaskPix) {
+ pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y);
+ if (!pMaskPix)
+ return 0;
+ }
+
+ if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix,
+ pMaskPix, pDstPix))
return -1;
while (nrect--)
{
INT16 xDst = rects->xDst + pDst->pDrawable->x;
INT16 yDst = rects->yDst + pDst->pDrawable->y;
- INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
- INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
-
+ INT16 xMask = rects->xMask;
+ INT16 yMask = rects->yMask;
+ INT16 xSrc = rects->xSrc;
+ INT16 ySrc = rects->ySrc;
RegionRec region;
BoxPtr pbox;
int nbox;
- if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
- xSrc, ySrc, 0, 0, xDst, yDst,
+ if (pMaskPix) {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ }
+
+ if (pSrcPix) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
+
+ if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
rects->width, rects->height))
goto next_rect;
@@ -421,6 +475,8 @@ exaTryDriverCompositeRects(CARD8 op,
nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region);
+ xMask = xMask + mask_off_x - xDst - dst_off_x;
+ yMask = yMask + mask_off_y - yDst - dst_off_y;
xSrc = xSrc + src_off_x - xDst - dst_off_x;
ySrc = ySrc + src_off_y - yDst - dst_off_y;
@@ -429,7 +485,8 @@ exaTryDriverCompositeRects(CARD8 op,
(*pExaScr->info->Composite) (pDstPix,
pbox->x1 + xSrc,
pbox->y1 + ySrc,
- 0, 0,
+ pbox->x1 + xMask,
+ pbox->y1 + yMask,
pbox->x1,
pbox->y1,
pbox->x2 - pbox->x1,
@@ -451,25 +508,28 @@ exaTryDriverCompositeRects(CARD8 op,
/**
* Copy a number of rectangles from source to destination in a single
- * operation. This is specialized for building a glyph mask: we don'y
- * have a mask argument because we don't need it for that, and we
- * don't have he special-case fallbacks found in exaComposite() - if the
- * driver can support it, we use the driver functionality, otherwise we
- * fallback straight to software.
+ * operation. This is specialized for glyph rendering: we don't have the
+ * special-case fallbacks found in exaComposite() - if the driver can support
+ * it, we use the driver functionality, otherwise we fall back straight to
+ * software.
*/
void
exaCompositeRects(CARD8 op,
PicturePtr pSrc,
+ PicturePtr pMask,
PicturePtr pDst,
int nrect,
ExaCompositeRectPtr rects)
{
- PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
- ExaPixmapPriv(pPixmap);
+ ExaScreenPriv (pDst->pDrawable->pScreen);
int n;
ExaCompositeRectPtr r;
-
- if (pExaPixmap->pDamage) {
+ int ret;
+
+ /* If we get a mask, that means we're rendering to the exaGlyphs
+ * destination directly, so the damage layer takes care of this.
+ */
+ if (!pMask) {
RegionRec region;
int x1 = MAXSHORT;
int y1 = MAXSHORT;
@@ -480,7 +540,7 @@ exaCompositeRects(CARD8 op,
/* We have to manage the damage ourselves, since CompositeRects isn't
* something in the screen that can be managed by the damage extension,
* and EXA depends on damage to track what needs to be migrated between
- * offscreen and onscreen.
+ * the gpu and the cpu.
*/
/* Compute the overall extents of the composited region - we're making
@@ -526,24 +586,44 @@ exaCompositeRects(CARD8 op,
/************************************************************/
ValidatePicture (pSrc);
+ if (pMask)
+ ValidatePicture (pMask);
ValidatePicture (pDst);
-
- if (exaTryDriverCompositeRects(op, pSrc, pDst, nrect, rects) != 1) {
- n = nrect;
- r = rects;
- while (n--) {
- ExaCheckComposite (op, pSrc, NULL, pDst,
- r->xSrc, r->ySrc,
- 0, 0,
- r->xDst, r->yDst,
- r->width, r->height);
- r++;
+
+ ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects);
+
+ if (ret != 1) {
+ if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha &&
+ (!pExaScr->info->CheckComposite ||
+ ((*pExaScr->info->CheckComposite)(PictOpOutReverse, pSrc, pMask,
+ pDst) &&
+ (*pExaScr->info->CheckComposite)(PictOpAdd, pSrc, pMask, pDst)))) {
+ ret = exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask,
+ pDst, nrect, rects);
+ if (ret == 1) {
+ op = PictOpAdd;
+ ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect,
+ rects);
+ }
+ }
+
+ if (ret != 1) {
+ n = nrect;
+ r = rects;
+ while (n--) {
+ ExaCheckComposite (op, pSrc, pMask, pDst,
+ r->xSrc, r->ySrc,
+ r->xMask, r->yMask,
+ r->xDst, r->yDst,
+ r->width, r->height);
+ r++;
+ }
}
}
/************************************************************/
- if (pExaPixmap->pDamage) {
+ if (!pMask) {
/* Now we have to flush the damage out from pendingDamage => damage
* Calling DamageRegionProcessPending has that effect.
*/
@@ -571,18 +651,18 @@ exaTryDriverComposite(CARD8 op,
BoxPtr pbox;
int nbox;
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
- struct _Pixmap scratch;
- ExaMigrationRec pixmaps[3];
+ PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+ ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
- pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ }
pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
pDstExaPix = ExaGetPixmapPriv(pDstPix);
- if (pMask) {
+ if (pMask && pMask->pDrawable) {
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
}
@@ -591,9 +671,9 @@ exaTryDriverComposite(CARD8 op,
* FIXME: If it cannot, use temporary pixmaps so that the drawing
* happens within limits.
*/
- if (pSrcExaPix->accel_blocked ||
- pDstExaPix->accel_blocked ||
- (pMask && (pMaskExaPix->accel_blocked)))
+ if (pDstExaPix->accel_blocked ||
+ (pSrcExaPix && pSrcExaPix->accel_blocked) ||
+ (pMaskExaPix && (pMaskExaPix->accel_blocked)))
{
return -1;
}
@@ -601,13 +681,15 @@ exaTryDriverComposite(CARD8 op,
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- if (pMask) {
+ if (pMaskPix) {
xMask += pMask->pDrawable->x;
yMask += pMask->pDrawable->y;
}
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ if (pSrcPix) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
if (pExaScr->info->CheckComposite &&
!(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
@@ -624,45 +706,53 @@ exaTryDriverComposite(CARD8 op,
REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = exaOpReadsDestination(op);
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = pixmaps[0].as_src ? NULL : &region;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPix;
- pixmaps[1].pReg = NULL;
- if (pMask) {
- pixmaps[2].as_dst = FALSE;
- pixmaps[2].as_src = TRUE;
- pixmaps[2].pPix = pMaskPix;
- pixmaps[2].pReg = NULL;
- exaDoMigration(pixmaps, 3, TRUE);
- } else {
- exaDoMigration(pixmaps, 2, TRUE);
- }
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[3];
+ int i = 0;
+
+ pixmaps[i].as_dst = TRUE;
+ pixmaps[i].as_src = exaOpReadsDestination(op);
+ pixmaps[i].pPix = pDstPix;
+ pixmaps[i].pReg = pixmaps[0].as_src ? NULL : &region;
+ i++;
+
+ if (pSrcPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pSrcPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
- pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
- if (pMask)
- pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
- &mask_off_y);
+ if (pMaskPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pMaskPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
- if (!exaPixmapIsOffscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
+ exaDoMigration(pixmaps, i, TRUE);
}
- if (!pSrcPix && (!pMask || pMaskPix) && pExaScr->info->UploadToScratch) {
- pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
- if ((*pExaScr->info->UploadToScratch) (pSrcPix, &scratch))
- pSrcPix = &scratch;
- } else if (pSrcPix && pMask && !pMaskPix && pExaScr->info->UploadToScratch) {
- pMaskPix = exaGetDrawablePixmap (pMask->pDrawable);
- if ((*pExaScr->info->UploadToScratch) (pMaskPix, &scratch))
- pMaskPix = &scratch;
+ if (pSrcPix) {
+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!pSrcPix) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ return 0;
+ }
}
- if (!pSrcPix || (pMask && !pMaskPix)) {
+ if (pMaskPix) {
+ pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
+ &mask_off_y);
+ if (!pMaskPix) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ return 0;
+ }
+ }
+
+ if (!exaPixmapHasGpuCopy(pDstPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return 0;
}
@@ -813,44 +903,46 @@ exaComposite(CARD8 op,
Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
RegionRec region;
- /* We currently don't support acceleration of gradients, or other pictures
- * with a NULL pDrawable.
- */
- if (pExaScr->swappedOut ||
- pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
- {
+ if (pExaScr->swappedOut)
goto fallback;
- }
/* Remove repeat in source if useless */
- if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
+ if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
(xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
(ySrc + height) <= pSrc->pDrawable->height)
pSrc->repeat = 0;
- if (!pMask)
+ if (!pMask && !pSrc->alphaMap && !pDst->alphaMap &&
+ (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format))))
{
- if ((op == PictOpSrc &&
- ((pSrc->format == pDst->format) ||
- (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
- (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
- (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
- pSrc->format == pDst->format &&
- (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
+ if (pSrc->pDrawable ?
+ (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+ pSrc->repeat) :
+ (pSrc->pSourcePict->type == SourcePictTypeSolidFill))
{
- if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat)
- {
- ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
- }
- else if (pSrc->pDrawable != NULL &&
- !pSrc->repeat &&
- !pSrc->transform)
+ ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ } else if (pSrc->pDrawable && !pSrc->transform &&
+ ((op == PictOpSrc &&
+ (pSrc->format == pDst->format ||
+ (PICT_FORMAT_COLOR(pDst->format) &&
+ PICT_FORMAT_COLOR(pSrc->format) &&
+ pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format),
+ PICT_FORMAT_TYPE(pSrc->format),
+ 0,
+ PICT_FORMAT_R(pSrc->format),
+ PICT_FORMAT_G(pSrc->format),
+ PICT_FORMAT_B(pSrc->format))))) ||
+ (op == PictOpOver && pSrc->format == pDst->format &&
+ !PICT_FORMAT_A(pSrc->format))))
+ {
+ if (!pSrc->repeat && xSrc >= 0 && ySrc >= 0 &&
+ (xSrc + width <= pSrc->pDrawable->width) &&
+ (ySrc + height <= pSrc->pDrawable->height))
{
+ Bool ret;
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
xSrc += pSrc->pDrawable->x;
@@ -861,18 +953,25 @@ exaComposite(CARD8 op,
yDst, width, height))
goto done;
-
- exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL,
+ ret = exaHWCopyNtoN(pSrc->pDrawable, pDst->pDrawable, NULL,
REGION_RECTS(&region), REGION_NUM_RECTS(&region),
- xSrc - xDst, ySrc - yDst,
- FALSE, FALSE, 0, NULL);
+ xSrc - xDst, ySrc - yDst, FALSE, FALSE);
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+ /* Reset values to their original values. */
+ xDst -= pDst->pDrawable->x;
+ yDst -= pDst->pDrawable->y;
+ xSrc -= pSrc->pDrawable->x;
+ ySrc -= pSrc->pDrawable->y;
+
+ if (!ret)
+ goto fallback;
+
goto done;
}
- else if (pSrc->pDrawable != NULL &&
- pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
- !pSrc->transform &&
- pSrc->repeatType == RepeatNormal)
+
+ if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
+ pSrc->pDrawable->type == DRAWABLE_PIXMAP)
{
DDXPointRec patOrg;
@@ -922,9 +1021,9 @@ exaComposite(CARD8 op,
}
/* Remove repeat in mask if useless */
- if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
- (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
- (yMask + height) <= pMask->pDrawable->height)
+ if (pMask && pMask->pDrawable && pMask->repeat && !pMask->transform &&
+ xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
+ yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
pMask->repeat = 0;
if (pExaScr->info->PrepareComposite &&
@@ -940,9 +1039,10 @@ exaComposite(CARD8 op,
/* For generic masks and solid src pictures, mach64 can do Over in two
* passes, similar to the component-alpha case.
*/
- isSrcSolid = pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat;
+ isSrcSolid = pSrc->pDrawable ?
+ (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+ pSrc->repeat) :
+ (pSrc->pSourcePict->type == SourcePictTypeSolidFill);
/* If we couldn't do the Composite in a single pass, and it was a
* component-alpha Over, see if we can do it in two passes with
@@ -1063,7 +1163,6 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
return;
-
xDst = traps[0].left.p1.x >> 16;
yDst = traps[0].left.p1.y >> 16;
diff --git a/xserver/exa/exa_unaccel.c b/xserver/exa/exa_unaccel.c
index a515bac1f..8d7009813 100644
--- a/xserver/exa/exa_unaccel.c
+++ b/xserver/exa/exa_unaccel.c
@@ -74,22 +74,26 @@ void
ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccessGC (pGC);
- fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
+ pGC->ops->FillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
exaFinishAccessGC (pGC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ pGC->ops->SetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
@@ -97,32 +101,120 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits)
{
- ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaPixmapPriv(pPixmap);
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
- if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
+ if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
+ exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
pGC->alu, pGC->clientClipType))
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
else
- exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ?
- DamagePendingRegion(pExaPixmap->pDamage) : NULL);
- fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
+ pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
+ DamagePendingRegion(pExaPixmap->pDamage));
+ pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
+void
+ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
+ Bool upsidedown, Pixel bitplane, void *closure)
+{
+ RegionRec reg;
+ int xoff, yoff;
+ EXA_PRE_FALLBACK_GC(pGC);
+ EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+ exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
+
+ if (pExaScr->prepare_access_reg) {
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
+
+ exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
+ REGION_INIT(pScreen, &reg, pbox, nbox);
+ REGION_TRANSLATE(pScreen, &reg, xoff + dx, yoff + dy);
+ pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, &reg);
+ REGION_UNINIT(pScreen, &reg);
+ } else
+ exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
+
+ if (pExaScr->prepare_access_reg &&
+ !exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle,
+ pGC->alu, pGC->clientClipType)) {
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
+
+ exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
+ REGION_INIT(pScreen, &reg, pbox, nbox);
+ REGION_TRANSLATE(pScreen, &reg, xoff, yoff);
+ pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, &reg);
+ REGION_UNINIT(pScreen, &reg);
+ } else
+ exaPrepareAccess (pDst, EXA_PREPARE_DEST);
+
+ /* This will eventually call fbCopyNtoN, with some calculation overhead. */
+ while (nbox--) {
+ pGC->ops->CopyArea (pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx, pbox->y1 - pSrc->y + dy,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, pbox->x1 - pDst->x, pbox->y1 - pDst->y);
+ pbox++;
+ }
+ exaFinishAccess (pSrc, EXA_PREPARE_SRC);
+ exaFinishAccess (pDst, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
+}
+
+static void
+ExaFallbackPrepareReg(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x, int y, int width, int height,
+ int index, Bool checkReads)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (pExaScr->prepare_access_reg &&
+ !(checkReads && exaGCReadsDestination(pDrawable,
+ pGC->planemask,
+ pGC->fillStyle,
+ pGC->alu,
+ pGC->clientClipType))) {
+ BoxRec box;
+ RegionRec reg;
+ int xoff, yoff;
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ box.x1 = pDrawable->x + x + xoff;
+ box.y1 = pDrawable->y + y + yoff;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+
+ REGION_INIT(pScreen, &reg, &box, 1);
+ pExaScr->prepare_access_reg(pPixmap, index, &reg);
+ REGION_UNINIT(pScreen, &reg);
+ } else
+ exaPrepareAccess(pDrawable, index);
+}
+
+
RegionPtr
ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty)
{
RegionPtr ret;
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
- exaPrepareAccess (pDst, EXA_PREPARE_DEST);
- exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
- ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
+ ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h,
+ EXA_PREPARE_SRC, FALSE);
+ ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h,
+ EXA_PREPARE_DEST, TRUE);
+ ret = pGC->ops->CopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
exaFinishAccess (pSrc, EXA_PREPARE_SRC);
exaFinishAccess (pDst, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
return ret;
}
@@ -134,14 +226,18 @@ ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
{
RegionPtr ret;
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
- exaPrepareAccess (pDst, EXA_PREPARE_DEST);
- exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
- ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
+ ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h,
+ EXA_PREPARE_SRC, FALSE);
+ ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h,
+ EXA_PREPARE_DEST, TRUE);
+ ret = pGC->ops->CopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
bitPlane);
exaFinishAccess (pSrc, EXA_PREPARE_SRC);
exaFinishAccess (pDst, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
return ret;
}
@@ -150,85 +246,75 @@ void
ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
DDXPointPtr pptInit)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
+ pGC->ops->PolyPoint (pDrawable, pGC, mode, npt, pptInit);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC,
int mode, int npt, DDXPointPtr ppt)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
pDrawable, exaDrawableLocation(pDrawable),
pGC->lineWidth, mode, npt));
- if (pGC->lineWidth == 0) {
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- exaPrepareAccessGC (pGC);
- fbPolyLine (pDrawable, pGC, mode, npt, ppt);
- exaFinishAccessGC (pGC);
- exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- return;
- }
- /* fb calls mi functions in the lineWidth != 0 case. */
- fbPolyLine (pDrawable, pGC, mode, npt, ppt);
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessGC (pGC);
+ pGC->ops->Polylines (pDrawable, pGC, mode, npt, ppt);
+ exaFinishAccessGC (pGC);
+ exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC,
int nsegInit, xSegment *pSegInit)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
- if (pGC->lineWidth == 0) {
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- exaPrepareAccessGC (pGC);
- fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
- exaFinishAccessGC (pGC);
- exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- return;
- }
- /* fb calls mi functions in the lineWidth != 0 case. */
- fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
+
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessGC (pGC);
+ pGC->ops->PolySegment (pDrawable, pGC, nsegInit, pSegInit);
+ exaFinishAccessGC (pGC);
+ exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *pArcs)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
- /* Disable this as fbPolyArc can call miZeroPolyArc which in turn
- * can call accelerated functions, that as yet, haven't been notified
- * with exaFinishAccess().
- */
-#if 0
- if (pGC->lineWidth == 0)
- {
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- exaPrepareAccessGC (pGC);
- fbPolyArc (pDrawable, pGC, narcs, pArcs);
- exaFinishAccessGC (pGC);
- exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
- return;
- }
-#endif
- miPolyArc (pDrawable, pGC, narcs, pArcs);
+ exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
+ exaPrepareAccessGC (pGC);
+ pGC->ops->PolyArc (pDrawable, pGC, narcs, pArcs);
+ exaFinishAccessGC (pGC);
+ exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
int nrect, xRectangle *prect)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccessGC (pGC);
- fbPolyFillRect (pDrawable, pGC, nrect, prect);
+ pGC->ops->PolyFillRect (pDrawable, pGC, nrect, prect);
exaFinishAccessGC (pGC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
@@ -236,13 +322,15 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c)\n", pDrawable,
exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccessGC (pGC);
- fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ pGC->ops->ImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
exaFinishAccessGC (pGC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
@@ -250,13 +338,15 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu));
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
exaPrepareAccessGC (pGC);
- fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ pGC->ops->PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
exaFinishAccessGC (pGC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
}
void
@@ -264,16 +354,65 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable,
int w, int h, int x, int y)
{
+ EXA_PRE_FALLBACK_GC(pGC);
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
exaDrawableLocation(&pBitmap->drawable),
exaDrawableLocation(pDrawable)));
- exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
- exaPrepareAccess (&pBitmap->drawable, EXA_PREPARE_SRC);
+ ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h,
+ EXA_PREPARE_DEST, TRUE);
+ ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h,
+ EXA_PREPARE_SRC, FALSE);
exaPrepareAccessGC (pGC);
- fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
+ pGC->ops->PushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
exaFinishAccessGC (pGC);
exaFinishAccess (&pBitmap->drawable, EXA_PREPARE_SRC);
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK_GC(pGC);
+}
+
+void
+ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ DrawablePtr pDrawable = &pWin->drawable;
+ ScreenPtr pScreen = pDrawable->pScreen;
+ EXA_PRE_FALLBACK(pScreen);
+ EXA_FALLBACK(("from %p\n", pWin));
+
+ /* Only need the source bits, the destination region will be overwritten */
+ if (pExaScr->prepare_access_reg) {
+ PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
+ int xoff, yoff;
+
+ exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff);
+ pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc);
+ REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff);
+ } else
+ exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
+
+ swap(pExaScr, pScreen, CopyWindow);
+ pScreen->CopyWindow (pWin, ptOldOrg, prgnSrc);
+ swap(pExaScr, pScreen, CopyWindow);
+ exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
+ EXA_POST_FALLBACK(pScreen);
+}
+
+void
+ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ EXA_PRE_FALLBACK(pScreen);
+ EXA_FALLBACK(("from %p (%c)\n", pDrawable,
+ exaDrawableLocation(pDrawable)));
+
+ ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h,
+ EXA_PREPARE_SRC, FALSE);
+ swap(pExaScr, pScreen, GetImage);
+ pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d);
+ swap(pExaScr, pScreen, GetImage);
+ exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
+ EXA_POST_FALLBACK(pScreen);
}
void
@@ -284,10 +423,185 @@ ExaCheckGetSpans (DrawablePtr pDrawable,
int nspans,
char *pdstStart)
{
+ ScreenPtr pScreen = pDrawable->pScreen;
+
+ EXA_PRE_FALLBACK(pScreen);
EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
exaPrepareAccess (pDrawable, EXA_PREPARE_SRC);
- fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ swap(pExaScr, pScreen, GetSpans);
+ pScreen->GetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ swap(pExaScr, pScreen, GetSpans);
exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
+ EXA_POST_FALLBACK(pScreen);
+}
+
+static void
+ExaSrcValidate(DrawablePtr pDrawable,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv(pScreen);
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
+ BoxRec box;
+ RegionRec reg;
+ RegionPtr dst;
+ int xoff, yoff;
+
+ exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
+
+ box.x1 = x + xoff;
+ box.y1 = y + yoff;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+
+ dst = (pExaScr->srcPix == pPix) ? &pExaScr->srcReg :
+ &pExaScr->maskReg;
+
+ REGION_INIT(pScreen, &reg, &box, 1);
+ REGION_UNION(pScreen, dst, dst, &reg);
+ REGION_UNINIT(pScreen, &reg);
+
+ if (pExaScr->SavedSourceValidate) {
+ swap(pExaScr, pScreen, SourceValidate);
+ pScreen->SourceValidate(pDrawable, x, y, width, height);
+ swap(pExaScr, pScreen, SourceValidate);
+ }
+}
+
+static Bool
+ExaPrepareCompositeReg(ScreenPtr pScreen,
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ RegionRec region;
+ RegionPtr dstReg = NULL;
+ RegionPtr srcReg = NULL;
+ RegionPtr maskReg = NULL;
+ PixmapPtr pSrcPix = NULL;
+ PixmapPtr pMaskPix = NULL;
+ PixmapPtr pDstPix;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+
+ REGION_NULL(pScreen, &region);
+
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ REGION_NULL(pScreen, &pExaScr->srcReg);
+ srcReg = &pExaScr->srcReg;
+ pExaScr->srcPix = pSrcPix;
+ if (pSrc != pDst)
+ REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
+ -pSrc->pDrawable->x,
+ -pSrc->pDrawable->y);
+ }
+
+ if (pMask && pMask->pDrawable) {
+ pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
+ REGION_NULL(pScreen, &pExaScr->maskReg);
+ maskReg = &pExaScr->maskReg;
+ if (pMask != pDst && pMask != pSrc)
+ REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
+ -pMask->pDrawable->x,
+ -pMask->pDrawable->y);
+ }
+
+ REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
+ -pDst->pDrawable->x,
+ -pDst->pDrawable->y);
+
+ pExaScr->SavedSourceValidate = ExaSrcValidate;
+ swap(pExaScr, pScreen, SourceValidate);
+ ret = miComputeCompositeRegion (&region, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst,
+ yDst,
+ width, height);
+ swap(pExaScr, pScreen, SourceValidate);
+
+ REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
+ pDst->pDrawable->x,
+ pDst->pDrawable->y);
+ if (pSrc->pDrawable && pSrc != pDst)
+ REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
+ pSrc->pDrawable->x,
+ pSrc->pDrawable->y);
+ if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
+ REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
+ pMask->pDrawable->x,
+ pMask->pDrawable->y);
+
+ if (!ret) {
+ if (srcReg)
+ REGION_UNINIT(pScreen, srcReg);
+ if (maskReg)
+ REGION_UNINIT(pScreen, maskReg);
+
+ return FALSE;
+ }
+
+ /**
+ * Don't limit alphamaps readbacks for now until we've figured out how that
+ * should be done.
+ */
+
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+ pExaScr->prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
+ EXA_PREPARE_AUX_SRC,
+ NULL);
+ if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+ pExaScr->prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
+ EXA_PREPARE_AUX_MASK,
+ NULL);
+
+ if (pSrcPix)
+ pExaScr->prepare_access_reg(pSrcPix,
+ EXA_PREPARE_SRC,
+ srcReg);
+
+ if (pMaskPix)
+ pExaScr->prepare_access_reg(pMaskPix,
+ EXA_PREPARE_MASK,
+ maskReg);
+
+ if (srcReg)
+ REGION_UNINIT(pScreen, srcReg);
+ if (maskReg)
+ REGION_UNINIT(pScreen, maskReg);
+
+ pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
+ if (!exaOpReadsDestination(op)) {
+ int xoff;
+ int yoff;
+
+ exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, &region, pDst->pDrawable->x + xoff,
+ pDst->pDrawable->y + yoff);
+ dstReg = &region;
+ }
+
+ if (pDst->alphaMap && pDst->alphaMap->pDrawable)
+ pExaScr->prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
+ EXA_PREPARE_AUX_DEST,
+ dstReg);
+ pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
+
+ REGION_UNINIT(pScreen, &region);
+ return TRUE;
}
void
@@ -304,52 +618,45 @@ ExaCheckComposite (CARD8 op,
CARD16 width,
CARD16 height)
{
- RegionRec region;
- int xoff, yoff;
-
- REGION_NULL(pScreen, &region);
-
- /* We need to prepare access to any separate alpha maps first, in case the
- * driver doesn't support EXA_PREPARE_AUX*, in which case EXA_PREPARE_SRC
- * may be used for moving them out.
- */
- if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
- exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
- if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
- exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
-
- if (!exaOpReadsDestination(op)) {
- if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
- xSrc, ySrc, xMask, yMask, xDst, yDst,
- width, height))
- return;
-
- exaGetDrawableDeltas (pDst->pDrawable,
- exaGetDrawablePixmap(pDst->pDrawable),
- &xoff, &yoff);
-
- REGION_TRANSLATE(pScreen, &region, xoff, yoff);
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+#endif /* RENDER */
+ EXA_PRE_FALLBACK(pScreen);
+
+ if (pExaScr->prepare_access_reg) {
+ if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
+ ySrc, xMask, yMask, xDst, yDst, width,
+ height))
+ goto out_no_clip;
+ } else {
- if (pDst->alphaMap && pDst->alphaMap->pDrawable)
- exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0,
- &region);
+ /* We need to prepare access to any separate alpha maps first,
+ * in case the driver doesn't support EXA_PREPARE_AUX*,
+ * in which case EXA_PREPARE_SRC may be used for moving them out.
+ */
- exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region);
- } else {
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+ exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
+ if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+ exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
- exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
+ exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
- }
- EXA_FALLBACK(("from picts %p/%p to pict %p\n",
- pSrc, pMask, pDst));
+ EXA_FALLBACK(("from picts %p/%p to pict %p\n",
+ pSrc, pMask, pDst));
- if (pSrc->pDrawable != NULL)
- exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
- if (pMask && pMask->pDrawable != NULL)
- exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
- fbComposite (op,
+ if (pSrc->pDrawable != NULL)
+ exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
+ if (pMask && pMask->pDrawable != NULL)
+ exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
+ }
+
+#ifdef RENDER
+ swap(pExaScr, ps, Composite);
+ ps->Composite (op,
pSrc,
pMask,
pDst,
@@ -361,19 +668,22 @@ ExaCheckComposite (CARD8 op,
yDst,
width,
height);
+ swap(pExaScr, ps, Composite);
+#endif /* RENDER */
if (pMask && pMask->pDrawable != NULL)
exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
- if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
- exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
if (pSrc->pDrawable != NULL)
exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
- if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
- exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
- exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
+ exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+ exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
+ if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+ exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
- REGION_UNINIT(pScreen, &region);
+out_no_clip:
+ EXA_POST_FALLBACK(pScreen);
}
void
@@ -383,68 +693,58 @@ ExaCheckAddTraps (PicturePtr pPicture,
int ntrap,
xTrap *traps)
{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+#endif /* RENDER */
+ EXA_PRE_FALLBACK(pScreen);
+
EXA_FALLBACK(("to pict %p (%c)\n",
exaDrawableLocation(pPicture->pDrawable)));
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
- fbAddTraps (pPicture, x_off, y_off, ntrap, traps);
+#ifdef RENDER
+ swap(pExaScr, ps, AddTraps);
+ ps->AddTraps (pPicture, x_off, y_off, ntrap, traps);
+ swap(pExaScr, ps, AddTraps);
+#endif /* RENDER */
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
+ EXA_POST_FALLBACK(pScreen);
}
/**
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
* that happen to be 1x1. Pixmap must be at least 8bpp.
- *
- * XXX This really belongs in fb, so it can be aware of tiling and etc.
*/
CARD32
exaGetPixmapFirstPixel (PixmapPtr pPixmap)
{
- CARD32 pixel;
- void *fb;
- Bool need_finish = FALSE;
- BoxRec box;
- RegionRec migration;
- ExaPixmapPriv (pPixmap);
- Bool sys_valid = pExaPixmap->pDamage &&
- !miPointInRegion(&pExaPixmap->validSys, 0, 0, &box);
- Bool damaged = pExaPixmap->pDamage &&
- miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box);
- Bool offscreen = exaPixmapIsOffscreen(pPixmap);
-
- fb = pExaPixmap->sys_ptr;
-
- /* Try to avoid framebuffer readbacks */
- if ((!offscreen && !sys_valid && !damaged) ||
- (offscreen && (!sys_valid || damaged)))
- {
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = 1;
- box.y2 = 1;
- REGION_INIT(pScreen, &migration, &box, 1);
-
- need_finish = TRUE;
-
- exaPrepareAccessReg(&pPixmap->drawable, EXA_PREPARE_SRC, &migration);
- fb = pPixmap->devPrivate.ptr;
- }
-
switch (pPixmap->drawable.bitsPerPixel) {
case 32:
- pixel = *(CARD32 *)fb;
- break;
+ {
+ CARD32 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
case 16:
- pixel = *(CARD16 *)fb;
- break;
+ {
+ CARD16 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
+ case 8:
+ {
+ CARD8 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
default:
- pixel = *(CARD8 *)fb;
- break;
+ FatalError("%s called for invalid bpp %d\n", __func__,
+ pPixmap->drawable.bitsPerPixel);
}
-
- if (need_finish) {
- exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
- REGION_UNINIT(pScreen, &migration);
- }
-
- return pixel;
}