summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2010-07-18 14:47:49 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2010-07-18 14:47:49 +0000
commit01dea479f07aa226272d1ca44995383755187447 (patch)
tree49ef4141f987553823c1982cf6abcbe33dcc0aea
parent301f11bce5a3c84f04cec6df50b03ff1fadc559d (diff)
Update the intel driver to (mostly) a backport of 2.12.
It is missing a few commits that I have yet to verify (ones that try and continue if we lock the gpu rendering engine and can't reset it, for example) taht will be verified and sent out for extra testing soon. Should contain a bunch of speedups and some correctness improvements (though rendercheck still gives some errors that I am looking into). This has been in snaps since the first day of c2k10, any known issues with just this driver have (to my knowledge) been fixed since. A problem with macbooks pointed out by otto happens with both this and the in-tree driver and thus doesn't stop this moving forward. As well as the 2.12 improvements, this driver also has a backport (partially aided by the backports in RHEL 5 kindly provided by Dave Airlie) from the kms code of modesetting support for ironlake (arrandale and clarkdale: the IGDs build into intel nehalem cpu dies) which has been tested on a number of chipsets. Note that Display port and eDP displays have not yet been worked on (and probably won't until I can find a displayport monitor), but VGA and lvds at least are known to work, sure beats vesa. "no objection on my side" matthieu@, prodding (as always) from princess marco.
-rw-r--r--driver/xf86-video-intel/COPYING169
-rw-r--r--driver/xf86-video-intel/aclocal.m43
-rw-r--r--driver/xf86-video-intel/configure12
-rw-r--r--driver/xf86-video-intel/src/common.h1
-rw-r--r--driver/xf86-video-intel/src/drmmode_display.c22
-rw-r--r--driver/xf86-video-intel/src/i810_dga.c4
-rw-r--r--driver/xf86-video-intel/src/i810_dri.c50
-rw-r--r--driver/xf86-video-intel/src/i810_driver.c12
-rw-r--r--driver/xf86-video-intel/src/i810_hwmc.c10
-rw-r--r--driver/xf86-video-intel/src/i810_reg.h62
-rw-r--r--driver/xf86-video-intel/src/i810_video.c26
-rw-r--r--driver/xf86-video-intel/src/i830.h156
-rw-r--r--driver/xf86-video-intel/src/i830_3d.c4
-rw-r--r--driver/xf86-video-intel/src/i830_accel.c71
-rw-r--r--driver/xf86-video-intel/src/i830_batchbuffer.c201
-rw-r--r--driver/xf86-video-intel/src/i830_batchbuffer.h90
-rw-r--r--driver/xf86-video-intel/src/i830_bios.c12
-rw-r--r--driver/xf86-video-intel/src/i830_crt.c90
-rw-r--r--driver/xf86-video-intel/src/i830_display.c956
-rw-r--r--driver/xf86-video-intel/src/i830_display.h1
-rw-r--r--driver/xf86-video-intel/src/i830_dri.c617
-rw-r--r--driver/xf86-video-intel/src/i830_driver.c327
-rw-r--r--driver/xf86-video-intel/src/i830_dvo.c8
-rw-r--r--driver/xf86-video-intel/src/i830_hdmi.c56
-rw-r--r--driver/xf86-video-intel/src/i830_hwmc.c4
-rw-r--r--driver/xf86-video-intel/src/i830_lvds.c200
-rw-r--r--driver/xf86-video-intel/src/i830_memory.c187
-rw-r--r--driver/xf86-video-intel/src/i830_quirks.c8
-rw-r--r--driver/xf86-video-intel/src/i830_render.c278
-rw-r--r--driver/xf86-video-intel/src/i830_sdvo.c16
-rw-r--r--driver/xf86-video-intel/src/i830_tv.c8
-rw-r--r--driver/xf86-video-intel/src/i830_uxa.c665
-rw-r--r--driver/xf86-video-intel/src/i830_video.c25
-rw-r--r--driver/xf86-video-intel/src/i915_3d.c11
-rw-r--r--driver/xf86-video-intel/src/i915_3d.h860
-rw-r--r--driver/xf86-video-intel/src/i915_reg.h27
-rw-r--r--driver/xf86-video-intel/src/i915_render.c1138
-rw-r--r--driver/xf86-video-intel/src/i915_video.c160
-rw-r--r--driver/xf86-video-intel/src/i965_render.c159
-rw-r--r--driver/xf86-video-intel/src/i965_video.c20
-rw-r--r--driver/xf86-video-intel/src/xvmc/i965_xvmc.c2
-rw-r--r--driver/xf86-video-intel/src/xvmc/xvmc_vld.c2
-rw-r--r--driver/xf86-video-intel/uxa/uxa-accel.c473
-rw-r--r--driver/xf86-video-intel/uxa/uxa-glyphs.c1527
-rw-r--r--driver/xf86-video-intel/uxa/uxa-priv.h117
-rw-r--r--driver/xf86-video-intel/uxa/uxa-render.c1214
-rw-r--r--driver/xf86-video-intel/uxa/uxa.c73
-rw-r--r--driver/xf86-video-intel/uxa/uxa.h45
48 files changed, 6780 insertions, 3399 deletions
diff --git a/driver/xf86-video-intel/COPYING b/driver/xf86-video-intel/COPYING
index 7f33cbfd2..ae75ef951 100644
--- a/driver/xf86-video-intel/COPYING
+++ b/driver/xf86-video-intel/COPYING
@@ -1,12 +1,165 @@
-This is a stub file. This package has not yet had its complete licensing
-information compiled. Please see the individual source files for details on
-your rights to use and modify this software.
+Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+All Rights Reserved.
-Please submit updated COPYING files to the Xorg bugzilla:
+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, sub license, 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:
-https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
-All licensing questions regarding this software should be directed at the
-Xorg mailing list:
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
+Copyright © 2002 David Dawes
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright © 2006 Intel Corporation
+Copyright © 2006,2010 Intel Corporation
+Copyright © 2007 Intel Corporation
+Copyright © 2008 Intel Corporation
+Copyright © 2009 Intel Corporation
+Copyright © 2007 Red Hat, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Alan Hourihane not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Alan Hourihane makes no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+Copyright 2000 Intel Corporation. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright 2001 VA Linux Systems Inc., Fremont, California.
+Copyright © 2002 by David Dawes
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Copyright © 1999 Keith Packard
+Copyright ® 2001 Keith Packard
+Copyright © 2000, 2008 Keith Packard
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Keith Packard not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. Keith Packard makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
-http://lists.freedesktop.org/mailman/listinfo/xorg
diff --git a/driver/xf86-video-intel/aclocal.m4 b/driver/xf86-video-intel/aclocal.m4
index ec8edc72c..4d51d7e87 100644
--- a/driver/xf86-video-intel/aclocal.m4
+++ b/driver/xf86-video-intel/aclocal.m4
@@ -8767,9 +8767,8 @@ dnl
# is defined, then add $1 to $REQUIRED_MODULES.
AC_DEFUN([XORG_DRIVER_CHECK_EXT],[
- AC_REQUIRE([PKG_PROG_PKG_CONFIG])
SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -I`$PKG_CONFIG --variable=sdkdir xorg-server`"
+ CFLAGS="$CFLAGS -I`pkg-config --variable=sdkdir xorg-server`"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include "xorg-server.h"
#if !defined $1
diff --git a/driver/xf86-video-intel/configure b/driver/xf86-video-intel/configure
index 34a49ca4e..61176dc4c 100644
--- a/driver/xf86-video-intel/configure
+++ b/driver/xf86-video-intel/configure
@@ -22160,9 +22160,8 @@ fi
# Checks for extensions
-
SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -I`$PKG_CONFIG --variable=sdkdir xorg-server`"
+ CFLAGS="$CFLAGS -I`pkg-config --variable=sdkdir xorg-server`"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -22220,9 +22219,8 @@ $as_echo "$_EXT_CHECK" >&6; }
fi
-
SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -I`$PKG_CONFIG --variable=sdkdir xorg-server`"
+ CFLAGS="$CFLAGS -I`pkg-config --variable=sdkdir xorg-server`"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -22280,9 +22278,8 @@ $as_echo "$_EXT_CHECK" >&6; }
fi
-
SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -I`$PKG_CONFIG --variable=sdkdir xorg-server`"
+ CFLAGS="$CFLAGS -I`pkg-config --variable=sdkdir xorg-server`"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -22340,9 +22337,8 @@ $as_echo "$_EXT_CHECK" >&6; }
fi
-
SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -I`$PKG_CONFIG --variable=sdkdir xorg-server`"
+ CFLAGS="$CFLAGS -I`pkg-config --variable=sdkdir xorg-server`"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
diff --git a/driver/xf86-video-intel/src/common.h b/driver/xf86-video-intel/src/common.h
index 73b4d05f3..6f35d56db 100644
--- a/driver/xf86-video-intel/src/common.h
+++ b/driver/xf86-video-intel/src/common.h
@@ -412,6 +412,7 @@ intel_host_bridge (void);
enum {
INTEL_CREATE_PIXMAP_TILING_X = 0x10000000,
INTEL_CREATE_PIXMAP_TILING_Y,
+ INTEL_CREATE_PIXMAP_TILING_NONE,
};
#endif /* _INTEL_COMMON_H_ */
diff --git a/driver/xf86-video-intel/src/drmmode_display.c b/driver/xf86-video-intel/src/drmmode_display.c
index e0df39610..de40fe9b5 100644
--- a/driver/xf86-video-intel/src/drmmode_display.c
+++ b/driver/xf86-video-intel/src/drmmode_display.c
@@ -336,7 +336,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
crtc->y = y;
crtc->rotation = rotation;
- output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
+ output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids) {
ret = FALSE;
goto done;
@@ -729,7 +729,7 @@ static int drmmode_output_lvds_edid(xf86OutputPtr output,
* device. This is similar to what we have done in i830_lvds.c
*/
edid_mon = NULL;
- edid_mon = xcalloc(1, sizeof(xf86Monitor));
+ edid_mon = calloc(1, sizeof(xf86Monitor));
if (!edid_mon) {
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
"Can't allocate memory for edid_mon.\n");
@@ -869,17 +869,17 @@ drmmode_output_destroy(xf86OutputPtr output)
drmModeFreePropertyBlob(drmmode_output->edid_blob);
for (i = 0; i < drmmode_output->num_props; i++) {
drmModeFreeProperty(drmmode_output->props[i].mode_prop);
- xfree(drmmode_output->props[i].atoms);
+ free(drmmode_output->props[i].atoms);
}
- xfree(drmmode_output->props);
+ free(drmmode_output->props);
drmModeFreeConnector(drmmode_output->mode_output);
if (drmmode_output->private_data) {
- xfree(drmmode_output->private_data);
+ free(drmmode_output->private_data);
drmmode_output->private_data = NULL;
}
if (drmmode_output->backlight_iface)
drmmode_backlight_set(output, drmmode_output->backlight_active_level);
- xfree(drmmode_output);
+ free(drmmode_output);
output->driver_private = NULL;
}
@@ -970,7 +970,7 @@ drmmode_output_create_resources(xf86OutputPtr output)
drmModePropertyPtr drmmode_prop;
int i, j, err;
- drmmode_output->props = xcalloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+ drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
if (!drmmode_output->props)
return;
@@ -995,7 +995,7 @@ drmmode_output_create_resources(xf86OutputPtr output)
INT32 range[2];
p->num_atoms = 1;
- p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ p->atoms = calloc(p->num_atoms, sizeof(Atom));
if (!p->atoms)
continue;
p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
@@ -1017,7 +1017,7 @@ drmmode_output_create_resources(xf86OutputPtr output)
}
} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
p->num_atoms = drmmode_prop->count_enums + 1;
- p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ p->atoms = calloc(p->num_atoms, sizeof(Atom));
if (!p->atoms)
continue;
p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
@@ -1262,7 +1262,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num)
return;
}
- drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
+ drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
if (!drmmode_output) {
xf86OutputDestroy(output);
drmModeFreeConnector(koutput);
@@ -1276,7 +1276,7 @@ drmmode_output_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, int num)
*/
drmmode_output->private_data = NULL;
if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) {
- drmmode_output->private_data = xcalloc(
+ drmmode_output->private_data = calloc(
sizeof(struct fixed_panel_lvds), 1);
if (!drmmode_output->private_data)
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
diff --git a/driver/xf86-video-intel/src/i810_dga.c b/driver/xf86-video-intel/src/i810_dga.c
index 3f5305793..52a01b76f 100644
--- a/driver/xf86-video-intel/src/i810_dga.c
+++ b/driver/xf86-video-intel/src/i810_dga.c
@@ -84,10 +84,10 @@ I810DGAInit(ScreenPtr pScreen)
while (pMode) {
- newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
+ newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
if (!newmodes) {
- xfree(modes);
+ free(modes);
return FALSE;
}
modes = newmodes;
diff --git a/driver/xf86-video-intel/src/i810_dri.c b/driver/xf86-video-intel/src/i810_dri.c
index e566acf61..c40224238 100644
--- a/driver/xf86-video-intel/src/i810_dri.c
+++ b/driver/xf86-video-intel/src/i810_dri.c
@@ -172,25 +172,25 @@ I810InitVisualConfigs(ScreenPtr pScreen)
numConfigs = 8;
pConfigs =
- (__GLXvisualConfig *) xcalloc(sizeof(__GLXvisualConfig),
+ (__GLXvisualConfig *) calloc(sizeof(__GLXvisualConfig),
numConfigs);
if (!pConfigs)
return FALSE;
pI810Configs =
- (I810ConfigPrivPtr) xcalloc(sizeof(I810ConfigPrivRec),
+ (I810ConfigPrivPtr) calloc(sizeof(I810ConfigPrivRec),
numConfigs);
if (!pI810Configs) {
- xfree(pConfigs);
+ free(pConfigs);
return FALSE;
}
pI810ConfigPtrs =
- (I810ConfigPrivPtr *) xcalloc(sizeof(I810ConfigPrivPtr),
+ (I810ConfigPrivPtr *) calloc(sizeof(I810ConfigPrivPtr),
numConfigs);
if (!pI810ConfigPtrs) {
- xfree(pConfigs);
- xfree(pI810Configs);
+ free(pConfigs);
+ free(pI810Configs);
return FALSE;
}
@@ -338,7 +338,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo);
} else {
- pDRIInfo->busIdString = xalloc(64);
+ pDRIInfo->busIdString = malloc(64);
sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus),
pI810->PciInfo->dev, pI810->PciInfo->func
@@ -370,7 +370,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
}
pDRIInfo->SAREASize = SAREA_MAX;
- if (!(pI810DRI = (I810DRIPtr) xcalloc(sizeof(I810DRIRec), 1))) {
+ if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) {
DRIDestroyInfoRec(pI810->pDRIInfo);
pI810->pDRIInfo = NULL;
return FALSE;
@@ -399,7 +399,7 @@ I810DRIScreenInit(ScreenPtr pScreen)
if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) {
xf86DrvMsg(pScreen->myNum, X_ERROR,
"[dri] DRIScreenInit failed. Disabling DRI.\n");
- xfree(pDRIInfo->devPrivate);
+ free(pDRIInfo->devPrivate);
pDRIInfo->devPrivate = NULL;
DRIDestroyInfoRec(pI810->pDRIInfo);
pI810->pDRIInfo = NULL;
@@ -1055,16 +1055,16 @@ I810DRICloseScreen(ScreenPtr pScreen)
if (pI810->pDRIInfo) {
if (pI810->pDRIInfo->devPrivate) {
- xfree(pI810->pDRIInfo->devPrivate);
+ free(pI810->pDRIInfo->devPrivate);
pI810->pDRIInfo->devPrivate = NULL;
}
DRIDestroyInfoRec(pI810->pDRIInfo);
pI810->pDRIInfo = NULL;
}
if (pI810->pVisualConfigs)
- xfree(pI810->pVisualConfigs);
+ free(pI810->pVisualConfigs);
if (pI810->pVisualConfigsPriv)
- xfree(pI810->pVisualConfigsPriv);
+ free(pI810->pVisualConfigsPriv);
}
static Bool
@@ -1202,12 +1202,12 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
if (nbox > 1) {
/* Keep ordering in each band, reverse order of bands */
- pboxNew1 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox);
+ pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
if (!pboxNew1)
return;
- pptNew1 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox);
+ pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
if (!pptNew1) {
- xfree(pboxNew1);
+ free(pboxNew1);
return;
}
pboxBase = pboxNext = pbox + nbox - 1;
@@ -1238,16 +1238,16 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
if (nbox > 1) {
/*reverse orderof rects in each band */
- pboxNew2 = (BoxPtr) xalloc(sizeof(BoxRec) * nbox);
- pptNew2 = (DDXPointPtr) xalloc(sizeof(DDXPointRec) * nbox);
+ pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
+ pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox);
if (!pboxNew2 || !pptNew2) {
if (pptNew2)
- xfree(pptNew2);
+ free(pptNew2);
if (pboxNew2)
- xfree(pboxNew2);
+ free(pboxNew2);
if (pboxNew1) {
- xfree(pptNew1);
- xfree(pboxNew1);
+ free(pptNew1);
+ free(pboxNew1);
}
return;
}
@@ -1312,12 +1312,12 @@ I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
I810EmitFlush(pScrn);
if (pboxNew2) {
- xfree(pptNew2);
- xfree(pboxNew2);
+ free(pptNew2);
+ free(pboxNew2);
}
if (pboxNew1) {
- xfree(pptNew1);
- xfree(pboxNew1);
+ free(pptNew1);
+ free(pboxNew1);
}
if (pI810->AccelInfoRec)
diff --git a/driver/xf86-video-intel/src/i810_driver.c b/driver/xf86-video-intel/src/i810_driver.c
index 68e45bb60..345854f2d 100644
--- a/driver/xf86-video-intel/src/i810_driver.c
+++ b/driver/xf86-video-intel/src/i810_driver.c
@@ -364,7 +364,7 @@ I810FreeRec(ScrnInfoPtr pScrn)
return;
if (!pScrn->driverPrivate)
return;
- xfree(pScrn->driverPrivate);
+ free(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
#endif
@@ -618,7 +618,7 @@ I810PreInit(ScrnInfoPtr pScrn, int flags)
/* Process the options */
xf86CollectOptions(pScrn, NULL);
- if (!(pI810->Options = xalloc(sizeof(I810Options))))
+ if (!(pI810->Options = malloc(sizeof(I810Options))))
return FALSE;
memcpy(pI810->Options, I810Options, sizeof(I810Options));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options);
@@ -1914,7 +1914,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
pI810 = I810PTR(pScrn);
hwp = VGAHWPTR(pScrn);
- pI810->LpRing = xcalloc(sizeof(I810RingBuffer),1);
+ pI810->LpRing = calloc(sizeof(I810RingBuffer),1);
if (!pI810->LpRing) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Could not allocate lpring data structure.\n");
@@ -2326,13 +2326,13 @@ I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
vgaHWUnmapMem(pScrn);
if (pI810->ScanlineColorExpandBuffers) {
- xfree(pI810->ScanlineColorExpandBuffers);
+ free(pI810->ScanlineColorExpandBuffers);
pI810->ScanlineColorExpandBuffers = NULL;
}
if (infoPtr) {
if (infoPtr->ScanlineColorExpandBuffers)
- xfree(infoPtr->ScanlineColorExpandBuffers);
+ free(infoPtr->ScanlineColorExpandBuffers);
XAADestroyInfoRec(infoPtr);
pI810->AccelInfoRec = NULL;
}
@@ -2353,7 +2353,7 @@ I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
*/
xf86GARTCloseScreen(scrnIndex);
- xfree(pI810->LpRing);
+ free(pI810->LpRing);
pI810->LpRing = NULL;
pScrn->vtSema = FALSE;
diff --git a/driver/xf86-video-intel/src/i810_hwmc.c b/driver/xf86-video-intel/src/i810_hwmc.c
index 1c3ffc99e..724e1beab 100644
--- a/driver/xf86-video-intel/src/i810_hwmc.c
+++ b/driver/xf86-video-intel/src/i810_hwmc.c
@@ -230,7 +230,7 @@ void I810InitMC(ScreenPtr pScreen)
* Set *num_priv to the number of 32bit words that make up the size of
* of the data that priv will point to.
*
- * *priv = (long *) xcalloc (elements, sizeof(element))
+ * *priv = (long *) calloc (elements, sizeof(element))
* *num_priv = (elements * sizeof(element)) >> 2;
*
**************************************************************************/
@@ -256,7 +256,7 @@ int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
return BadAlloc;
}
- *priv = xcalloc(1,sizeof(I810XvMCCreateContextRec));
+ *priv = calloc(1,sizeof(I810XvMCCreateContextRec));
contextRec = (I810XvMCCreateContextRec *)*priv;
if(!*priv) {
@@ -268,7 +268,7 @@ int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"I810XvMCCreateContext: Unable to create DRMContext!\n");
- xfree(*priv);
+ free(*priv);
return BadAlloc;
}
@@ -295,7 +295,7 @@ int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
I810Ptr pI810 = I810PTR(pScrn);
int i;
- *priv = (long *)xcalloc(2,sizeof(long));
+ *priv = (long *)calloc(2,sizeof(long));
if(!*priv) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -341,7 +341,7 @@ int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
I810Ptr pI810 = I810PTR(pScrn);
int i;
- *priv = (long *)xcalloc(1,sizeof(long));
+ *priv = (long *)calloc(1,sizeof(long));
if(!*priv) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff --git a/driver/xf86-video-intel/src/i810_reg.h b/driver/xf86-video-intel/src/i810_reg.h
index 191ddb2ae..9f78eb1d5 100644
--- a/driver/xf86-video-intel/src/i810_reg.h
+++ b/driver/xf86-video-intel/src/i810_reg.h
@@ -2214,6 +2214,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# define SVBLANK_INT_STATUS (1 << 2)
# define VBLANK_INT_STATUS (1 << 1)
# define OREG_UPDATE_STATUS (1 << 0)
+#define PIPE_BPC_MASK (7 << 5) /* Ironlake */
+#define PIPE_8BPC (0 << 5)
+#define PIPE_10BPC (1 << 5)
+#define PIPE_6BPC (2 << 5)
+#define PIPE_12BPC (3 << 5)
+
#define DSPARB 0x70030
@@ -2350,6 +2356,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* IGDNG */
#define DISPPLANE_X_TILE (1<<10)
#define DISPPLANE_LINEAR (0<<10)
+#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14)
#define DSPABASE 0x70184
/* IGDNG */
@@ -3067,6 +3074,10 @@ typedef enum {
#define PFA_CTL_1 0x68080
#define PFB_CTL_1 0x68880
#define PF_ENABLE (1<<31)
+#define PFA_WIN_SZ 0x68074
+#define PFB_WIN_SZ 0x68874
+#define PFA_WIN_POS 0x68070
+#define PFB_WIN_POS 0x68870
#define PFA_WIN_POS 0x68070
#define PFB_WIN_POS 0x68870
@@ -3118,6 +3129,10 @@ typedef enum {
#define GTIIR 0x44018
#define GTIER 0x4401c
+
+#define DISP_ARB_CTL 0x45000
+#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
+
/* PCH */
/* south display engine interrupt */
@@ -3189,8 +3204,11 @@ typedef enum {
#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3<<13)
#define DREF_SSC_SOURCE_DISABLE (0<<11)
#define DREF_SSC_SOURCE_ENABLE (2<<11)
+#define DREF_SSC_SOURCE_MASK (2<<11)
#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9)
+#define DREF_NONSPREAD_CK505_ENABLE (1<<9)
#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9)
+#define DREF_NONSPREAD_SOURCE_MASK (2<<9)
#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7)
#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7)
#define DREF_SSC4_DOWNSPREAD (0<<6)
@@ -3302,6 +3320,7 @@ typedef enum {
#define FDI_DP_PORT_WIDTH_X2 (1<<19)
#define FDI_DP_PORT_WIDTH_X3 (2<<19)
#define FDI_DP_PORT_WIDTH_X4 (3<<19)
+#define FDI_DP_PORT_WIDTH_MASK (7<<19)
#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
/* IGDNG: hardwired to 1 */
#define FDI_TX_PLL_ENABLE (1<<14)
@@ -3320,6 +3339,7 @@ typedef enum {
#define FDI_10BPC (1<<16)
#define FDI_6BPC (2<<16)
#define FDI_12BPC (3<<16)
+#define FDI_BPC_MASK (3<<16)
#define FDI_LINK_REVERSE_OVERWRITE (1<<15)
#define FDI_DMI_LINK_REVERSE_MASK (1<<14)
#define FDI_RX_PLL_ENABLE (1<<13)
@@ -3406,6 +3426,48 @@ typedef enum {
#define HDMIC 0xe1150
#define HDMID 0xe1160
#define PCH_LVDS 0xe1180
+#define LVDS_DETECTED (1 << 1)
+
+#define PCH_DP_B 0xe4100
+#define PCH_DP_C 0xe4200
+#define PCH_DP_D 0xe4200
+
+#define BLC_PWM_CPU_CTL2 0x48250
+#define PWM_ENABLE (1 << 31)
+#define PWM_PIPE_A (0 << 29)
+#define PWM_PIPE_B (1 << 29)
+#define BLC_PWM_CPU_CTL 0x48254
+
+#define BLC_PWM_PCH_CTL1 0xc8250
+#define PWM_PCH_ENABLE (1 << 31)
+#define PWM_POLARITY_ACTIVE_LOW (1 << 29)
+#define PWM_POLARITY_ACTIVE_HIGH (0 << 29)
+#define PWM_POLARITY_ACTIVE_LOW2 (1 << 28)
+#define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28)
+
+#define BLC_PWM_PCH_CTL2 0xc8254
+
+#define PCH_PP_STATUS 0xc7200
+#define PCH_PP_CONTROL 0xc7204
+#define EDP_FORCE_VDD (1 << 3)
+#define EDP_BLC_ENABLE (1 << 2)
+#define PANEL_POWER_RESET (1 << 1)
+#define PANEL_POWER_OFF (0 << 0)
+#define PANEL_POWER_ON (1 << 0)
+#define PCH_PP_ON_DELAYS 0xc7208
+#define EDP_PANEL (1 << 30)
+#define PCH_PP_OFF_DELAYS 0xc720c
+#define PCH_PP_DIVISOR 0xc7210
+
+#define DE_POWER1 0x42400
+#define WM0_PIPE_A 0x45100
+#define WM0_PIPE_B 0x45104
+#define WM1 0x45108
+#define WM2 0x4510C
+#define WM3 0x45110
+#define WM1S 0x45120
+
+
#define AUD_CONFIG 0x62000
#define AUD_DEBUG 0x62010
diff --git a/driver/xf86-video-intel/src/i810_video.c b/driver/xf86-video-intel/src/i810_video.c
index ee1a2326b..85b5b65c6 100644
--- a/driver/xf86-video-intel/src/i810_video.c
+++ b/driver/xf86-video-intel/src/i810_video.c
@@ -174,7 +174,7 @@ void I810InitVideo(ScreenPtr pScreen)
adaptors = &newAdaptor;
} else {
newAdaptors = /* need to free this someplace */
- xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
+ malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
if(newAdaptors) {
memcpy(newAdaptors, adaptors, num_adaptors *
sizeof(XF86VideoAdaptorPtr));
@@ -189,7 +189,7 @@ void I810InitVideo(ScreenPtr pScreen)
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
if(newAdaptors)
- xfree(newAdaptors);
+ free(newAdaptors);
}
/* *INDENT-OFF* */
@@ -383,7 +383,7 @@ I810SetupImageVideo(ScreenPtr pScreen)
XF86VideoAdaptorPtr adapt;
I810PortPrivPtr pPriv;
- if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
sizeof(I810PortPrivRec) +
sizeof(DevUnion))))
return NULL;
@@ -1225,18 +1225,18 @@ I810AllocateSurface(
surface->width = w;
surface->height = h;
- if(!(surface->pitches = xalloc(sizeof(int)))) {
+ if(!(surface->pitches = malloc(sizeof(int)))) {
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
- if(!(surface->offsets = xalloc(sizeof(int)))) {
- xfree(surface->pitches);
+ if(!(surface->offsets = malloc(sizeof(int)))) {
+ free(surface->pitches);
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
- if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
- xfree(surface->pitches);
- xfree(surface->offsets);
+ if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
+ free(surface->pitches);
+ free(surface->offsets);
xf86FreeOffscreenLinear(linear);
return BadAlloc;
}
@@ -1286,9 +1286,9 @@ I810FreeSurface(
I810StopSurface(surface);
}
xf86FreeOffscreenLinear(pPriv->linear);
- xfree(surface->pitches);
- xfree(surface->offsets);
- xfree(surface->devPrivate.ptr);
+ free(surface->pitches);
+ free(surface->offsets);
+ free(surface->devPrivate.ptr);
return Success;
}
@@ -1401,7 +1401,7 @@ I810InitOffscreenImages(ScreenPtr pScreen)
XF86OffscreenImagePtr offscreenImages;
/* need to free this someplace */
- if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {
+ if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) {
return;
}
diff --git a/driver/xf86-video-intel/src/i830.h b/driver/xf86-video-intel/src/i830.h
index 6e4d5528f..d7a3aa9cd 100644
--- a/driver/xf86-video-intel/src/i830.h
+++ b/driver/xf86-video-intel/src/i830.h
@@ -58,6 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "xf86Crtc.h"
#include "xf86RandR12.h"
+#include "xf86int10.h"
+
#include "xorg-server.h"
#include <pciaccess.h>
@@ -76,6 +78,15 @@ void i830_uxa_block_handler(ScreenPtr pScreen);
Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
int num_bos);
+/* XXX
+ * The X server gained an *almost* identical implementation in 1.9.
+ *
+ * Remove this duplicate code either in 2.16 (when we can depend upon 1.9)
+ * or the drivers are merged back into the xserver tree, whichever happens
+ * earlier.
+ */
+
+#ifndef _LIST_H_
/* classic doubly-link circular list */
struct list {
struct list *next, *prev;
@@ -123,41 +134,77 @@ list_is_empty(struct list *head)
{
return head->next == head;
}
+#endif
#ifndef container_of
#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)
#endif
+#ifndef list_entry
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
+#endif
+#ifndef list_first_entry
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
+#endif
+#ifndef list_foreach
#define list_foreach(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
+#endif
+/* XXX list.h from xserver-1.9 uses a GCC-ism to avoid having to pass type */
+#ifndef list_foreach_entry
#define list_foreach_entry(pos, type, head, member) \
for (pos = list_entry((head)->next, type, member);\
&pos->member != (head); \
pos = list_entry(pos->member.next, type, member))
+#endif
struct intel_pixmap {
dri_bo *bo;
- uint32_t tiling, stride;
- uint32_t flush_write_domain;
- uint32_t flush_read_domains;
- uint32_t batch_write_domain;
- uint32_t batch_read_domains;
+
struct list flush, batch, in_flight;
+
+ uint16_t stride;
+ uint8_t tiling;
+ int8_t busy :2;
+ int8_t batch_write :1;
};
-struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap);
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec uxa_pixmap_index;
+#else
+extern int uxa_pixmap_index;
+#endif
+
+static inline struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
+#else
+ return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
+#endif
+}
+
+static inline Bool intel_pixmap_is_busy(struct intel_pixmap *priv)
+{
+ if (priv->busy == -1)
+ priv->busy = drm_intel_bo_busy(priv->bo);
+ return priv->busy;
+}
+
+static inline void i830_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel)
+{
+ dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel);
+}
static inline Bool i830_uxa_pixmap_is_dirty(PixmapPtr pixmap)
{
- return i830_get_pixmap_intel(pixmap)->flush_write_domain != 0;
+ return !list_is_empty(&i830_get_pixmap_intel(pixmap)->flush);
}
static inline Bool i830_pixmap_tiled(PixmapPtr pixmap)
@@ -264,15 +311,6 @@ struct _i830_memory {
Bool lifetime_fixed_offset;
};
-typedef struct {
- int tail_mask;
- i830_memory *mem;
- unsigned char *virtual_start;
- int head;
- int tail;
- int space;
-} I830RingBuffer;
-
/* store information about an Ixxx DVO */
/* The i830->i865 use multiple DVOs with multiple i2cs */
/* the i915, i945 have a single sDVO i2c bus - which is different */
@@ -328,6 +366,7 @@ typedef struct _I830CrtcPrivateRec {
uint64_t cursor_addr;
unsigned long cursor_argb_addr;
Bool cursor_is_argb;
+ int bpc;
} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -398,6 +437,10 @@ enum last_3d {
* BCM_KERNEL: use kernel methods for controlling the backlight
* This is only available on some platforms, but where present this can
* provide the best user experience.
+ *
+ * And, if you're in EL5, a fifth!
+ * BCM_IRONLAKE_NULL: just don't do anything and be quiet about it. This is
+ * a workaround for an RHGB interaction; you won't hit this at runtime.
*/
enum backlight_control {
@@ -405,6 +448,7 @@ enum backlight_control {
BCM_LEGACY,
BCM_COMBO,
BCM_KERNEL,
+ BCM_IRONLAKE_NULL
};
enum dri_type {
@@ -451,22 +495,10 @@ typedef struct intel_screen_private {
i830_memory *cursor_mem_classic[2];
/* One big buffer for all cursors for kernels that support this */
i830_memory *cursor_mem_argb[2];
- i830_memory *fake_bufmgr_mem;
-
- /* Regions allocated either from the above pools, or from agpgart. */
- I830RingBuffer ring;
-
- /** Number of bytes being emitted in the current BEGIN_LP_RING */
- unsigned int ring_emitting;
- /** Number of bytes that have been emitted in the current BEGIN_LP_RING */
- unsigned int ring_used;
- /** Offset in the ring for the next DWORD emit */
- uint32_t ring_next;
-
dri_bufmgr *bufmgr;
- uint8_t *batch_ptr;
+ uint32_t batch_ptr[4096];
/** Byte offset in batch_ptr for the next dword to be emitted. */
unsigned int batch_used;
/** Position in batch_ptr at the start of the current BEGIN_BATCH */
@@ -500,8 +532,6 @@ typedef struct intel_screen_private {
i830_memory *memory_manager; /**< DRI memory manager aperture */
- Bool have_gem;
-
Bool need_mi_flush;
Bool tiling;
@@ -525,6 +555,7 @@ typedef struct intel_screen_private {
CloseScreenProcPtr CloseScreen;
+ void (*vertex_flush) (struct intel_screen_private *intel);
void (*batch_flush_notify) (ScrnInfoPtr scrn);
uxa_driver_t *uxa_driver;
@@ -533,6 +564,7 @@ typedef struct intel_screen_private {
int accel_pixmap_offset_alignment;
int accel_max_x;
int accel_max_y;
+ int max_bo_size;
int max_gtt_map_size;
int max_tiling_size;
@@ -565,17 +597,17 @@ typedef struct intel_screen_private {
float scale_units[2][2];
/** Transform pointers for src/mask, or NULL if identity */
PictTransform *transform[2];
- float dst_coord_adjust;
- float src_coord_adjust;
- float mask_coord_adjust;
PixmapPtr render_source, render_mask, render_dest;
PicturePtr render_source_picture, render_mask_picture, render_dest_picture;
CARD32 render_source_solid;
CARD32 render_mask_solid;
+ PixmapPtr render_current_dest;
Bool render_source_is_solid;
Bool render_mask_is_solid;
Bool needs_render_state_emit;
+ Bool needs_render_vertex_emit;
+ Bool needs_render_ca_pass;
/* i830 render accel state */
uint32_t render_dest_format;
@@ -591,6 +623,20 @@ typedef struct intel_screen_private {
uint32_t dst_format;
} i915_render_state;
+ uint32_t prim_offset;
+ void (*prim_emit)(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h);
+ int floats_per_vertex;
+ int last_floats_per_vertex;
+ uint32_t vertex_count;
+ uint32_t vertex_index;
+ uint32_t vertex_used;
+ float vertex_ptr[4*1024];
+ dri_bo *vertex_bo;
+
/* 965 render acceleration state */
struct gen4_render_state *gen4_render_state;
@@ -598,6 +644,9 @@ typedef struct intel_screen_private {
Bool directRenderingOpen;
int drmSubFD;
+#ifdef notyet
+ drmEventContext event_context;
+#endif
char *deviceName;
/* Broken-out options. */
@@ -623,8 +672,6 @@ typedef struct intel_screen_private {
unsigned int SaveGeneration;
- OsTimerPtr devicesTimer;
-
int ddc2;
enum backlight_control backlight_control_method;
@@ -708,7 +755,6 @@ typedef struct intel_screen_private {
enum last_3d last_3d;
Bool use_drm_mode;
- Bool kernel_exec_fencing;
/** Enables logging of debug output related to mode switching. */
Bool debug_modes;
@@ -720,6 +766,10 @@ typedef struct intel_screen_private {
Bool fallback_debug;
struct sdvo_device_mapping sdvo_mappings[2];
unsigned debug_flush;
+
+ /* ironlake vt restore hack */
+ xf86Int10InfoPtr int10;
+ int int10Mode;
} intel_screen_private;
enum {
@@ -751,7 +801,6 @@ unsigned long intel_get_pixmap_pitch(PixmapPtr pixmap);
#include "i830_batchbuffer.h"
/* I830 specific functions */
-extern int I830WaitLpRing(ScrnInfoPtr scrn, int n, int timeout_millis);
extern void I830SetPIOAccess(intel_screen_private *intel);
extern void I830SetMMIOAccess(intel_screen_private *intel);
extern void I830InitHWCursor(ScrnInfoPtr scrn);
@@ -804,6 +853,8 @@ i830_pipe_a_require_deactivate (ScrnInfoPtr scrn);
Bool I830DRI2ScreenInit(ScreenPtr pScreen);
void I830DRI2CloseScreen(ScreenPtr pScreen);
+void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *user_data);
extern Bool drmmode_pre_init(ScrnInfoPtr scrn, int fd, int cpp);
extern int drmmode_get_pipe_from_crtc_id(drm_intel_bufmgr * bufmgr,
@@ -891,8 +942,11 @@ DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
void i830_tv_init(ScrnInfoPtr scrn);
/* i830_render.c */
-Bool i830_check_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest);
+Bool i830_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
+Bool i830_check_composite_target(PixmapPtr pixmap);
+Bool i830_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i830_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
PixmapPtr maskPixmap, PixmapPtr destPixmap);
@@ -902,21 +956,27 @@ void i830_composite(PixmapPtr dest, int srcX, int srcY,
int maskX, int maskY, int dstX, int dstY, int w, int h);
void i830_done_composite(PixmapPtr dest);
/* i915_render.c */
-Bool i915_check_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest);
+Bool i915_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
+Bool i915_check_composite_target(PixmapPtr pixmap);
+Bool i915_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i915_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
PixmapPtr maskPixmap, PixmapPtr destPixmap);
void i915_composite(PixmapPtr dest, int srcX, int srcY,
int maskX, int maskY, int dstX, int dstY, int w, int h);
+void i915_vertex_flush(intel_screen_private *intel);
void i915_batch_flush_notify(ScrnInfoPtr scrn);
void i830_batch_flush_notify(ScrnInfoPtr scrn);
/* i965_render.c */
unsigned int gen4_render_state_size(ScrnInfoPtr scrn);
void gen4_render_state_init(ScrnInfoPtr scrn);
void gen4_render_state_cleanup(ScrnInfoPtr scrn);
-Bool i965_check_composite(int op, PicturePtr sourcec, PicturePtr mask,
- PicturePtr dest);
+Bool i965_check_composite(int op,
+ PicturePtr sourcec, PicturePtr mask, PicturePtr dest,
+ int width, int height);
+Bool i965_check_composite_texture(ScreenPtr screen, PicturePtr picture);
Bool i965_prepare_composite(int op, PicturePtr sourcec, PicturePtr mask,
PicturePtr dest, PixmapPtr sourcecPixmap,
PixmapPtr maskPixmap, PixmapPtr destPixmap);
@@ -937,14 +997,6 @@ void i830_enter_render(ScrnInfoPtr);
extern void intel_sync(ScrnInfoPtr scrn);
-static inline void
-i830_wait_ring_idle(ScrnInfoPtr scrn)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- I830WaitLpRing(scrn, intel->ring.mem->size - 8, 0);
-}
-
static inline int i830_fb_compression_supported(intel_screen_private *intel)
{
if (!IS_MOBILE(intel))
diff --git a/driver/xf86-video-intel/src/i830_3d.c b/driver/xf86-video-intel/src/i830_3d.c
index e83cb3f7b..a92da055d 100644
--- a/driver/xf86-video-intel/src/i830_3d.c
+++ b/driver/xf86-video-intel/src/i830_3d.c
@@ -38,7 +38,7 @@ void I830EmitInvarientState(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- ATOMIC_BATCH(58);
+ assert(intel->in_batch_atomic);
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
@@ -222,6 +222,4 @@ void I830EmitInvarientState(ScrnInfoPtr scrn)
AA_LINE_ECAAR_WIDTH_1_0 |
AA_LINE_REGION_WIDTH_ENABLE |
AA_LINE_REGION_WIDTH_1_0 | AA_LINE_DISABLE);
-
- ADVANCE_BATCH();
}
diff --git a/driver/xf86-video-intel/src/i830_accel.c b/driver/xf86-video-intel/src/i830_accel.c
index 0b9195f30..df4f58db9 100644
--- a/driver/xf86-video-intel/src/i830_accel.c
+++ b/driver/xf86-video-intel/src/i830_accel.c
@@ -46,80 +46,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i830_ring.h"
#include "i915_drm.h"
-unsigned long intel_get_pixmap_offset(PixmapPtr pixmap)
-{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- return (unsigned long)pixmap->devPrivate.ptr -
- (unsigned long)intel->FbBase;
-}
-
unsigned long intel_get_pixmap_pitch(PixmapPtr pixmap)
{
return (unsigned long)pixmap->devKind;
}
-int
-I830WaitLpRing(ScrnInfoPtr scrn, int n, int timeout_millis)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- I830RingBuffer *ring = &intel->ring;
- int iters = 0;
- unsigned int start = 0;
- unsigned int now = 0;
- int last_head = 0;
- unsigned int first = 0;
-
- /* If your system hasn't moved the head pointer in 2 seconds, I'm going to
- * call it crashed.
- */
- if (timeout_millis == 0)
- timeout_millis = 2000;
-
- if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
- ErrorF("I830WaitLpRing %d\n", n);
- first = GetTimeInMillis();
- }
-
- while (ring->space < n) {
- ring->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
- ring->space = ring->head - (ring->tail + 8);
-
- if (ring->space < 0)
- ring->space += ring->mem->size;
-
- iters++;
- now = GetTimeInMillis();
- if (start == 0 || now < start || ring->head != last_head) {
- if (I810_DEBUG & DEBUG_VERBOSE_ACCEL)
- if (now > start)
- ErrorF("space: %d wanted %d\n", ring->space, n);
- start = now;
- last_head = ring->head;
- } else if (now - start > timeout_millis) {
- ErrorF("Error in I830WaitLpRing(), timeout for %d seconds\n",
- timeout_millis/1000);
- ErrorF("space: %d wanted %d\n", ring->space, n);
- intel->uxa_driver = NULL;
- FatalError("lockup\n");
- }
-
- DELAY(10);
- }
-
- if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) {
- now = GetTimeInMillis();
- if (now - first) {
- ErrorF("Elapsed %u ms\n", now - first);
- ErrorF("space: %d wanted %d\n", ring->space, n);
- }
- }
-
- return iters;
-}
-
void i830_debug_flush(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -128,7 +59,7 @@ void i830_debug_flush(ScrnInfoPtr scrn)
intel_batch_emit_flush(scrn);
if (intel->debug_flush & DEBUG_FLUSH_BATCHES)
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
}
/* The following function sets up the supported acceleration. Call it
diff --git a/driver/xf86-video-intel/src/i830_batchbuffer.c b/driver/xf86-video-intel/src/i830_batchbuffer.c
index d067d4801..2ef89f246 100644
--- a/driver/xf86-video-intel/src/i830_batchbuffer.c
+++ b/driver/xf86-video-intel/src/i830_batchbuffer.c
@@ -40,72 +40,29 @@
#define DUMP_BATCHBUFFERS NULL /* "/tmp/i915-batchbuffers.dump" */
-static int
-intel_nondrm_exec(dri_bo *bo, unsigned int used, void *priv)
+static void intel_end_vertex(intel_screen_private *intel)
{
- ScrnInfoPtr scrn = priv;
- intel_screen_private *intel = intel_get_screen_private(scrn);
+ if (intel->vertex_bo) {
+ if (intel->vertex_used)
+ dri_bo_subdata(intel->vertex_bo, 0, intel->vertex_used*4, intel->vertex_ptr);
- BEGIN_LP_RING(4);
- OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
- OUT_RING(bo->offset);
- OUT_RING(MI_NOOP);
- OUT_RING(MI_NOOP);
- ADVANCE_LP_RING();
-
- return 0;
-}
-
-static int
-intel_nondrm_exec_i830(dri_bo *bo, unsigned int used, void *priv)
-{
- ScrnInfoPtr scrn = priv;
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- BEGIN_LP_RING(4);
- OUT_RING(MI_BATCH_BUFFER);
- OUT_RING(bo->offset);
- OUT_RING(bo->offset + intel->batch_used - 4);
- OUT_RING(MI_NOOP);
- ADVANCE_LP_RING();
-
- return 0;
-}
-
-/**
- * Creates a fence value representing a request to be passed.
- *
- * Stub implementation that should be avoided when DRM functions are available.
- */
-static unsigned int
-intel_nondrm_emit(void *priv)
-{
- static unsigned int fence = 0;
-
- /* Match DRM in not using half the range. The fake bufmgr relies on this. */
- if (++fence >= 0x8000000)
- fence = 1;
-
- return fence;
+ dri_bo_unreference(intel->vertex_bo);
+ intel->vertex_bo = NULL;
+ }
}
-/**
- * Waits on a fence representing a request to be passed.
- *
- * Stub implementation that should be avoided when DRM functions are available.
- */
-static void
-intel_nondrm_wait(unsigned int fence, void *priv)
+void intel_next_vertex(intel_screen_private *intel)
{
- ScrnInfoPtr scrn = priv;
+ intel_end_vertex(intel);
- i830_wait_ring_idle(scrn);
+ intel->vertex_bo =
+ dri_bo_alloc(intel->bufmgr, "vertex", sizeof (intel->vertex_ptr), 4096);
+ intel->vertex_used = 0;
}
static void intel_next_batch(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- int ret;
/* The 865 has issues with larger-than-page-sized batch buffers. */
if (IS_I865G(intel))
@@ -115,12 +72,7 @@ static void intel_next_batch(ScrnInfoPtr scrn)
intel->batch_bo =
dri_bo_alloc(intel->bufmgr, "batch", 4096 * 4, 4096);
- ret = dri_bo_map(intel->batch_bo, 1);
- if (ret != 0)
- FatalError("Failed to map batchbuffer: %s\n", strerror(-ret));
-
intel->batch_used = 0;
- intel->batch_ptr = intel->batch_bo->virtual;
/* We don't know when another client has executed, so we have
* to reinitialize our 3D state per batch.
@@ -136,34 +88,54 @@ void intel_batch_init(ScrnInfoPtr scrn)
intel->batch_emitting = 0;
intel_next_batch(scrn);
-
- if (!intel->have_gem) {
- if (IS_I830(intel) || IS_845G(intel)) {
- intel_bufmgr_fake_set_exec_callback(intel->bufmgr,
- intel_nondrm_exec_i830, scrn);
- } else {
- intel_bufmgr_fake_set_exec_callback(intel->bufmgr,
- intel_nondrm_exec, scrn);
- }
- intel_bufmgr_fake_set_fence_callback(intel->bufmgr,
- intel_nondrm_emit, intel_nondrm_wait, scrn);
- }
}
void intel_batch_teardown(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- if (intel->batch_ptr != NULL) {
- dri_bo_unmap(intel->batch_bo);
- intel->batch_ptr = NULL;
-
+ if (intel->batch_bo != NULL) {
dri_bo_unreference(intel->batch_bo);
intel->batch_bo = NULL;
+ }
+ if (intel->last_batch_bo != NULL) {
dri_bo_unreference(intel->last_batch_bo);
intel->last_batch_bo = NULL;
}
+
+ if (intel->vertex_bo) {
+ dri_bo_unreference(intel->vertex_bo);
+ intel->vertex_bo = NULL;
+ }
+
+ while (!list_is_empty(&intel->batch_pixmaps))
+ list_del(intel->batch_pixmaps.next);
+
+ while (!list_is_empty(&intel->flush_pixmaps))
+ list_del(intel->flush_pixmaps.next);
+
+ while (!list_is_empty(&intel->in_flight)) {
+ struct intel_pixmap *entry;
+
+ entry = list_first_entry(&intel->in_flight,
+ struct intel_pixmap,
+ in_flight);
+
+ dri_bo_unreference(entry->bo);
+ list_del(&entry->in_flight);
+ free(entry);
+ }
+}
+
+void intel_batch_do_flush(ScrnInfoPtr scrn)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ while (!list_is_empty(&intel->flush_pixmaps))
+ list_del(intel->flush_pixmaps.next);
+
+ intel->need_mi_flush = FALSE;
}
void intel_batch_emit_flush(ScrnInfoPtr scrn)
@@ -182,55 +154,44 @@ void intel_batch_emit_flush(ScrnInfoPtr scrn)
OUT_BATCH(MI_FLUSH | flags);
ADVANCE_BATCH();
- while (!list_is_empty(&intel->flush_pixmaps)) {
- struct intel_pixmap *entry;
-
- entry = list_first_entry(&intel->flush_pixmaps,
- struct intel_pixmap,
- flush);
-
- entry->flush_read_domains = entry->flush_write_domain = 0;
- list_del(&entry->flush);
- }
-
- intel->need_mi_flush = FALSE;
+ intel_batch_do_flush(scrn);
}
-void intel_batch_submit(ScrnInfoPtr scrn)
+void intel_batch_submit(ScrnInfoPtr scrn, int flush)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
int ret;
assert (!intel->in_batch_atomic);
+ if (intel->vertex_flush)
+ intel->vertex_flush(intel);
+ intel_end_vertex(intel);
+
+ if (flush)
+ intel_batch_emit_flush(scrn);
+
if (intel->batch_used == 0)
return;
- /* Emit a padding dword if we aren't going to be quad-word aligned. */
- if ((intel->batch_used & 4) == 0) {
- *(uint32_t *) (intel->batch_ptr + intel->batch_used) = MI_NOOP;
- intel->batch_used += 4;
- }
-
/* Mark the end of the batchbuffer. */
- *(uint32_t *) (intel->batch_ptr + intel->batch_used) =
- MI_BATCH_BUFFER_END;
- intel->batch_used += 4;
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ /* Emit a padding dword if we aren't going to be quad-word aligned. */
+ if (intel->batch_used & 1)
+ OUT_BATCH(MI_NOOP);
if (DUMP_BATCHBUFFERS) {
FILE *file = fopen(DUMP_BATCHBUFFERS, "a");
if (file) {
- fwrite (intel->batch_ptr, intel->batch_used, 1, file);
+ fwrite (intel->batch_ptr, intel->batch_used*4, 1, file);
fclose(file);
}
}
- dri_bo_unmap(intel->batch_bo);
- intel->batch_ptr = NULL;
-
- ret =
- dri_bo_exec(intel->batch_bo, intel->batch_used, NULL, 0,
- 0xffffffff);
+ ret = dri_bo_subdata(intel->batch_bo, 0, intel->batch_used*4, intel->batch_ptr);
+ if (ret == 0)
+ ret = dri_bo_exec(intel->batch_bo, intel->batch_used*4,
+ NULL, 0, 0xffffffff);
if (ret != 0) {
static int once;
@@ -250,25 +211,14 @@ void intel_batch_submit(ScrnInfoPtr scrn)
struct intel_pixmap,
batch);
- entry->batch_read_domains = entry->batch_write_domain = 0;
+ entry->busy = -1;
+ entry->batch_write = 0;
list_del(&entry->batch);
}
- /* Mark that we need to flush whatever potential rendering we've done in the
- * blockhandler. We could set this less often, but it's probably not worth
- * the work.
- */
- intel->need_mi_flush = !list_is_empty(&intel->flush_pixmaps);
- while (!list_is_empty(&intel->flush_pixmaps)) {
- struct intel_pixmap *entry;
-
- entry = list_first_entry(&intel->flush_pixmaps,
- struct intel_pixmap,
- flush);
-
- entry->flush_read_domains = entry->flush_write_domain = 0;
- list_del(&entry->flush);
- }
+ intel->need_mi_flush |= !list_is_empty(&intel->flush_pixmaps);
+ while (!list_is_empty(&intel->flush_pixmaps))
+ list_del(intel->flush_pixmaps.next);
while (!list_is_empty(&intel->in_flight)) {
struct intel_pixmap *entry;
@@ -279,7 +229,7 @@ void intel_batch_submit(ScrnInfoPtr scrn)
dri_bo_unreference(entry->bo);
list_del(&entry->in_flight);
- xfree(entry);
+ free(entry);
}
/* Save a ref to the last batch emitted, which we use for syncing
@@ -306,8 +256,8 @@ void intel_batch_wait_last(ScrnInfoPtr scrn)
/* Map it CPU write, which guarantees it's done. This is a completely
* non performance path, so we don't need anything better.
*/
- drm_intel_bo_map(intel->last_batch_bo, TRUE);
- drm_intel_bo_unmap(intel->last_batch_bo);
+ drm_intel_gem_bo_map_gtt(intel->last_batch_bo);
+ drm_intel_gem_bo_unmap_gtt(intel->last_batch_bo);
}
void intel_sync(ScrnInfoPtr scrn)
@@ -320,7 +270,6 @@ void intel_sync(ScrnInfoPtr scrn)
if (!scrn->vtSema || !intel->batch_bo || !intel->batch_ptr)
return;
- intel_batch_emit_flush(scrn);
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, TRUE);
intel_batch_wait_last(scrn);
}
diff --git a/driver/xf86-video-intel/src/i830_batchbuffer.h b/driver/xf86-video-intel/src/i830_batchbuffer.h
index 50cb966df..30680855d 100644
--- a/driver/xf86-video-intel/src/i830_batchbuffer.h
+++ b/driver/xf86-video-intel/src/i830_batchbuffer.h
@@ -36,12 +36,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
void intel_batch_init(ScrnInfoPtr scrn);
void intel_batch_teardown(ScrnInfoPtr scrn);
void intel_batch_emit_flush(ScrnInfoPtr scrn);
-void intel_batch_submit(ScrnInfoPtr scrn);
+void intel_batch_do_flush(ScrnInfoPtr scrn);
+void intel_batch_submit(ScrnInfoPtr scrn, int flush);
void intel_batch_wait_last(ScrnInfoPtr scrn);
static inline int intel_batch_space(intel_screen_private *intel)
{
- return (intel->batch_bo->size - BATCH_RESERVED) - (intel->batch_used);
+ return (intel->batch_bo->size - BATCH_RESERVED) - (4*intel->batch_used);
+}
+
+static inline int intel_vertex_space(intel_screen_private *intel)
+{
+ return intel->vertex_bo ? intel->vertex_bo->size - (4*intel->vertex_used) : 0;
}
static inline void
@@ -49,7 +55,7 @@ intel_batch_require_space(ScrnInfoPtr scrn, intel_screen_private *intel, GLuint
{
assert(sz < intel->batch_bo->size - 8);
if (intel_batch_space(intel) < sz)
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
}
static inline void intel_batch_start_atomic(ScrnInfoPtr scrn, unsigned int sz)
@@ -60,7 +66,7 @@ static inline void intel_batch_start_atomic(ScrnInfoPtr scrn, unsigned int sz)
intel_batch_require_space(scrn, intel, sz * 4);
intel->in_batch_atomic = TRUE;
- intel->batch_atomic_limit = intel->batch_used + sz * 4;
+ intel->batch_atomic_limit = intel->batch_used + sz;
}
static inline void intel_batch_end_atomic(ScrnInfoPtr scrn)
@@ -74,22 +80,19 @@ static inline void intel_batch_end_atomic(ScrnInfoPtr scrn)
static inline void intel_batch_emit_dword(intel_screen_private *intel, uint32_t dword)
{
- assert(intel->batch_ptr != NULL);
- assert(intel->batch_emitting);
- *(uint32_t *) (intel->batch_ptr + intel->batch_used) = dword;
- intel->batch_used += 4;
+ intel->batch_ptr[intel->batch_used++] = dword;
}
static inline void intel_batch_align(intel_screen_private *intel, uint32_t align)
{
uint32_t delta;
- assert(intel->batch_ptr != NULL);
+ align /= 4;
assert(align);
if ((delta = intel->batch_used & (align - 1))) {
delta = align - delta;
- memset (intel->batch_ptr + intel->batch_used, 0, delta);
+ memset (intel->batch_ptr + intel->batch_used, 0, 4*delta);
intel->batch_used += delta;
}
}
@@ -100,20 +103,17 @@ intel_batch_emit_reloc(intel_screen_private *intel,
uint32_t read_domains,
uint32_t write_domains, uint32_t delta, int needs_fence)
{
- assert(intel_batch_space(intel) >= 4);
- *(uint32_t *) (intel->batch_ptr + intel->batch_used) =
- bo->offset + delta;
if (needs_fence)
drm_intel_bo_emit_reloc_fence(intel->batch_bo,
- intel->batch_used,
+ intel->batch_used * 4,
bo, delta,
read_domains, write_domains);
else
- drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used,
+ drm_intel_bo_emit_reloc(intel->batch_bo, intel->batch_used * 4,
bo, delta,
read_domains, write_domains);
- intel->batch_used += 4;
+ intel_batch_emit_dword(intel, bo->offset + delta);
}
static inline void
@@ -123,18 +123,14 @@ intel_batch_mark_pixmap_domains(intel_screen_private *intel,
{
assert (read_domains);
assert (write_domain == 0 || write_domain == read_domains);
- assert (write_domain == 0 ||
- priv->flush_write_domain == 0 ||
- priv->flush_write_domain == write_domain);
-
- priv->flush_read_domains |= read_domains;
- priv->batch_read_domains |= read_domains;
- priv->flush_write_domain |= write_domain;
- priv->batch_write_domain |= write_domain;
+
if (list_is_empty(&priv->batch))
list_add(&priv->batch, &intel->batch_pixmaps);
- if (list_is_empty(&priv->flush))
+ if (write_domain && list_is_empty(&priv->flush))
list_add(&priv->flush, &intel->flush_pixmaps);
+
+ priv->batch_write |= write_domain != 0;
+ priv->busy = 1;
}
static inline void
@@ -142,21 +138,12 @@ intel_batch_emit_reloc_pixmap(intel_screen_private *intel, PixmapPtr pixmap,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta, int needs_fence)
{
- dri_bo *bo = i830_get_pixmap_bo(pixmap);
- uint32_t offset;
- assert(intel->batch_ptr != NULL);
- assert(intel_batch_space(intel) >= 4);
- if (bo) {
- struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
- intel_batch_mark_pixmap_domains(intel, priv, read_domains,
- write_domain);
- intel_batch_emit_reloc(intel, priv->bo, read_domains,
- write_domain, delta, needs_fence);
- return;
- }
- offset = intel_get_pixmap_offset(pixmap);
- *(uint32_t *)(intel->batch_ptr + intel->batch_used) = offset + delta;
- intel->batch_used += 4;
+ struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
+
+ intel_batch_mark_pixmap_domains(intel, priv, read_domains,
+ write_domain);
+ intel_batch_emit_reloc(intel, priv->bo, read_domains,
+ write_domain, delta, needs_fence);
}
#define ALIGN_BATCH(align) intel_batch_align(intel, align);
@@ -189,19 +176,7 @@ do { \
"ADVANCE_BATCH\n", __FUNCTION__); \
assert(!intel->in_batch_atomic); \
intel_batch_require_space(scrn, intel, (n) * 4); \
- intel->batch_emitting = (n) * 4; \
- intel->batch_emit_start = intel->batch_used; \
-} while (0)
-
-/* special-case variant for when we have preallocated space */
-#define ATOMIC_BATCH(n) \
-do { \
- if (intel->batch_emitting != 0) \
- FatalError("%s: ATOMIC_BATCH called without closing " \
- "ADVANCE_BATCH\n", __FUNCTION__); \
- assert(intel->in_batch_atomic); \
- assert(intel->batch_used + (n) * 4 <= intel->batch_atomic_limit); \
- intel->batch_emitting = (n) * 4; \
+ intel->batch_emitting = (n); \
intel->batch_emit_start = intel->batch_used; \
} while (0)
@@ -224,9 +199,16 @@ do { \
if ((intel->batch_emitting > 8) && \
(I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \
/* Note: not actually syncing, just flushing each batch. */ \
- intel_batch_submit(scrn); \
+ intel_batch_submit(scrn, FALSE); \
} \
intel->batch_emitting = 0; \
} while (0)
+void intel_next_vertex(intel_screen_private *intel);
+static inline void intel_vertex_emit(intel_screen_private *intel, float v)
+{
+ intel->vertex_ptr[intel->vertex_used++] = v;
+}
+#define OUT_VERTEX(v) intel_vertex_emit(intel, v)
+
#endif /* _INTEL_BATCHBUFFER_H */
diff --git a/driver/xf86-video-intel/src/i830_bios.c b/driver/xf86-video-intel/src/i830_bios.c
index dd73b5711..da77cd432 100644
--- a/driver/xf86-video-intel/src/i830_bios.c
+++ b/driver/xf86-video-intel/src/i830_bios.c
@@ -210,6 +210,8 @@ static void parse_general_features(intel_screen_private *intel, struct bdb_heade
if (intel->lvds_use_ssc) {
if (IS_I85X(intel))
intel->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
+ else if (IS_IGDNG(intel))
+ intel->lvds_ssc_freq = general->ssc_freq ? 100 : 120;
else
intel->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
}
@@ -350,7 +352,7 @@ int i830_bios_init(ScrnInfoPtr scrn)
"libpciaccess reported 0 rom size, guessing %dkB\n",
size / 1024);
}
- bios = xalloc(size);
+ bios = malloc(size);
if (bios == NULL)
return -1;
@@ -359,7 +361,7 @@ int i830_bios_init(ScrnInfoPtr scrn)
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"libpciaccess failed to read %dkB video BIOS: %s\n",
size / 1024, strerror(-ret));
- xfree(bios);
+ free(bios);
return -1;
}
@@ -367,7 +369,7 @@ int i830_bios_init(ScrnInfoPtr scrn)
if (vbt_off >= size) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Bad VBT offset: 0x%x\n",
vbt_off);
- xfree(bios);
+ free(bios);
return -1;
}
@@ -375,7 +377,7 @@ int i830_bios_init(ScrnInfoPtr scrn)
if (memcmp(vbt->signature, "$VBT", 4) != 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Bad VBT signature\n");
- xfree(bios);
+ free(bios);
return -1;
}
@@ -388,7 +390,7 @@ int i830_bios_init(ScrnInfoPtr scrn)
parse_driver_feature(intel, bdb);
parse_sdvo_mapping(scrn, bdb);
- xfree(bios);
+ free(bios);
return 0;
}
diff --git a/driver/xf86-video-intel/src/i830_crt.c b/driver/xf86-video-intel/src/i830_crt.c
index e2e3694b9..b18834e74 100644
--- a/driver/xf86-video-intel/src/i830_crt.c
+++ b/driver/xf86-video-intel/src/i830_crt.c
@@ -29,6 +29,8 @@
#include "config.h"
#endif
+#include <unistd.h>
+
#include "xf86.h"
#include "i830.h"
#include "xf86Modes.h"
@@ -39,9 +41,14 @@ i830_crt_dpms(xf86OutputPtr output, int mode)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t temp;
+ uint32_t temp, reg;
+
+ if (IS_IGDNG(intel))
+ reg = PCH_ADPA;
+ else
+ reg = ADPA;
- temp = INREG(ADPA);
+ temp = INREG(reg);
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
temp &= ~ADPA_DAC_ENABLE;
@@ -60,7 +67,7 @@ i830_crt_dpms(xf86OutputPtr output, int mode)
break;
}
- OUTREG(ADPA, temp);
+ OUTREG(reg, temp);
}
static void
@@ -68,8 +75,9 @@ i830_crt_save (xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t reg = IS_IGDNG(intel) ? PCH_ADPA : ADPA;
- intel->saveADPA = INREG(ADPA);
+ intel->saveADPA = INREG(reg);
}
static void
@@ -77,8 +85,9 @@ i830_crt_restore (xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t reg = IS_IGDNG(intel) ? PCH_ADPA : ADPA;
- OUTREG(ADPA, intel->saveADPA);
+ OUTREG(reg, intel->saveADPA);
}
static int
@@ -122,16 +131,23 @@ i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
I830CrtcPrivatePtr i830_crtc = crtc->driver_private;
int dpll_md_reg;
uint32_t adpa, dpll_md;
+ uint32_t adpa_reg;
if (i830_crtc->pipe == 0)
dpll_md_reg = DPLL_A_MD;
else
dpll_md_reg = DPLL_B_MD;
+
+ if (IS_IGDNG(intel))
+ adpa_reg = PCH_ADPA;
+ else
+ adpa_reg = ADPA;
+
/*
* Disable separate mode multiplier used when cloning SDVO to CRT
* XXX this needs to be adjusted when we really are cloning
*/
- if (IS_I965G(intel))
+ if (IS_I965G(intel) && !IS_IGDNG(intel))
{
dpll_md = INREG(dpll_md_reg);
OUTREG(dpll_md_reg, dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
@@ -146,15 +162,55 @@ i830_crt_mode_set(xf86OutputPtr output, DisplayModePtr mode,
if (i830_crtc->pipe == 0)
{
adpa |= ADPA_PIPE_A_SELECT;
- OUTREG(BCLRPAT_A, 0);
+ if (!IS_IGDNG(intel))
+ OUTREG(BCLRPAT_A, 0);
}
else
{
adpa |= ADPA_PIPE_B_SELECT;
- OUTREG(BCLRPAT_B, 0);
+ if (!IS_IGDNG(intel))
+ OUTREG(BCLRPAT_B, 0);
}
- OUTREG(ADPA, adpa);
+ OUTREG(adpa_reg, adpa);
+}
+
+static Bool intel_igdng_crt_detect_hotplug(xf86OutputPtr output)
+{
+ ScrnInfoPtr scrn = output->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t adpa;
+ Bool ret;
+
+ adpa = INREG(PCH_ADPA);
+
+ adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+
+ adpa |= (ADPA_CRT_HOTPLUG_PERIOD_64 |
+ ADPA_CRT_HOTPLUG_WARMUP_5MS |
+ ADPA_CRT_HOTPLUG_SAMPLE_2S |
+ ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
+ ADPA_CRT_HOTPLUG_VOLREF_325MV);
+ OUTREG(PCH_ADPA, adpa);
+
+ usleep(6000); /* warmup */
+
+ adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+
+ OUTREG(PCH_ADPA, adpa);
+
+ while (INREG(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER)
+ ;
+
+ /* Check the status to see if both blue and green are on now */
+ adpa = INREG(PCH_ADPA) & ADPA_CRT_HOTPLUG_MONITOR_MASK;
+ if (adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR ||
+ adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO)
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ return ret;
}
/**
@@ -176,6 +232,9 @@ i830_crt_detect_hotplug(xf86OutputPtr output)
int tries = 1;
int try;
+ if (IS_IGDNG(intel))
+ return intel_igdng_crt_detect_hotplug(output);
+
/* On 4 series desktop, CRT detect sequence need to be done twice
* to get a reliable result. */
if (IS_G4X(intel) && !IS_GM45(intel))
@@ -441,7 +500,7 @@ static void
i830_crt_destroy (xf86OutputPtr output)
{
if (output->driver_private)
- xfree (output->driver_private);
+ free (output->driver_private);
}
#ifdef RANDR_GET_CRTC_INTERFACE
@@ -459,11 +518,18 @@ i830_crt_get_crtc(xf86OutputPtr output)
static xf86MonPtr
i830_get_edid(xf86OutputPtr output, int gpio_reg, char *gpio_str)
{
+ ScrnInfoPtr scrn = output->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
I830OutputPrivatePtr intel_output = output->driver_private;
xf86MonPtr edid_mon = NULL;
+ uint32_t i2c_reg;
/* Set up the DDC bus. */
- I830I2CInit(output->scrn, &intel_output->pDDCBus, gpio_reg, gpio_str);
+ if (IS_IGDNG(intel))
+ i2c_reg = PCH_GPIOA;
+ else
+ i2c_reg = GPIOA;
+ I830I2CInit(scrn, &intel_output->pDDCBus, i2c_reg, "CRTDDC_A");
edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
@@ -471,7 +537,7 @@ i830_get_edid(xf86OutputPtr output, int gpio_reg, char *gpio_str)
xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
intel_output->pDDCBus = NULL;
if (edid_mon) {
- xfree(edid_mon);
+ free(edid_mon);
edid_mon = NULL;
}
}
diff --git a/driver/xf86-video-intel/src/i830_display.c b/driver/xf86-video-intel/src/i830_display.c
index 736ed043c..cb4b9e6bb 100644
--- a/driver/xf86-video-intel/src/i830_display.c
+++ b/driver/xf86-video-intel/src/i830_display.c
@@ -42,6 +42,7 @@
#include "i830_bios.h"
#include "i830_display.h"
#include "xf86Modes.h"
+#include "i810_reg.h"
typedef struct {
/* given values */
@@ -149,6 +150,16 @@ struct intel_limit {
#define I9XX_P2_LVDS_FAST 7
#define I9XX_P2_LVDS_SLOW_LIMIT 112000
+#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */
+#define IRONLAKE_DOT_MIN 25000
+#define IRONLAKE_DOT_MAX 350000
+#define IRONLAKE_VCO_MIN 1760000
+#define IRONLAKE_VCO_MAX 3510000
+#define IRONLAKE_M1_MIN 12
+#define IRONLAKE_M1_MAX 22
+#define IRONLAKE_M2_MIN 5
+#define IRONLAKE_M2_MAX 9
+
#define INTEL_LIMIT_I8XX_DVO_DAC 0
#define INTEL_LIMIT_I8XX_LVDS 1
#define INTEL_LIMIT_I9XX_SDVO_DAC 2
@@ -238,12 +249,75 @@ struct intel_limit {
#define G4X_P2_DUAL_LVDS_FAST 7
#define G4X_P2_DUAL_LVDS_LIMIT 0
+/* DAC & HDMI Refclk 120Mhz */
+#define IRONLAKE_DAC_N_MIN 1
+#define IRONLAKE_DAC_N_MAX 5
+#define IRONLAKE_DAC_M_MIN 79
+#define IRONLAKE_DAC_M_MAX 127
+#define IRONLAKE_DAC_P_MIN 5
+#define IRONLAKE_DAC_P_MAX 80
+#define IRONLAKE_DAC_P1_MIN 1
+#define IRONLAKE_DAC_P1_MAX 8
+#define IRONLAKE_DAC_P2_SLOW 10
+#define IRONLAKE_DAC_P2_FAST 5
+
+/* LVDS single-channel 120Mhz refclk */
+#define IRONLAKE_LVDS_S_N_MIN 1
+#define IRONLAKE_LVDS_S_N_MAX 3
+#define IRONLAKE_LVDS_S_M_MIN 79
+#define IRONLAKE_LVDS_S_M_MAX 118
+#define IRONLAKE_LVDS_S_P_MIN 28
+#define IRONLAKE_LVDS_S_P_MAX 112
+#define IRONLAKE_LVDS_S_P1_MIN 2
+#define IRONLAKE_LVDS_S_P1_MAX 8
+#define IRONLAKE_LVDS_S_P2_SLOW 14
+#define IRONLAKE_LVDS_S_P2_FAST 14
+
+/* LVDS dual-channel 120Mhz refclk */
+#define IRONLAKE_LVDS_D_N_MIN 1
+#define IRONLAKE_LVDS_D_N_MAX 3
+#define IRONLAKE_LVDS_D_M_MIN 79
+#define IRONLAKE_LVDS_D_M_MAX 127
+#define IRONLAKE_LVDS_D_P_MIN 14
+#define IRONLAKE_LVDS_D_P_MAX 56
+#define IRONLAKE_LVDS_D_P1_MIN 2
+#define IRONLAKE_LVDS_D_P1_MAX 8
+#define IRONLAKE_LVDS_D_P2_SLOW 7
+#define IRONLAKE_LVDS_D_P2_FAST 7
+
+/* LVDS single-channel 100Mhz refclk */
+#define IRONLAKE_LVDS_S_SSC_N_MIN 1
+#define IRONLAKE_LVDS_S_SSC_N_MAX 2
+#define IRONLAKE_LVDS_S_SSC_M_MIN 79
+#define IRONLAKE_LVDS_S_SSC_M_MAX 126
+#define IRONLAKE_LVDS_S_SSC_P_MIN 28
+#define IRONLAKE_LVDS_S_SSC_P_MAX 112
+#define IRONLAKE_LVDS_S_SSC_P1_MIN 2
+#define IRONLAKE_LVDS_S_SSC_P1_MAX 8
+#define IRONLAKE_LVDS_S_SSC_P2_SLOW 14
+#define IRONLAKE_LVDS_S_SSC_P2_FAST 14
+
+/* LVDS dual-channel 100Mhz refclk */
+#define IRONLAKE_LVDS_D_SSC_N_MIN 1
+#define IRONLAKE_LVDS_D_SSC_N_MAX 3
+#define IRONLAKE_LVDS_D_SSC_M_MIN 79
+#define IRONLAKE_LVDS_D_SSC_M_MAX 126
+#define IRONLAKE_LVDS_D_SSC_P_MIN 14
+#define IRONLAKE_LVDS_D_SSC_P_MAX 42
+#define IRONLAKE_LVDS_D_SSC_P1_MIN 2
+#define IRONLAKE_LVDS_D_SSC_P1_MAX 6
+#define IRONLAKE_LVDS_D_SSC_P2_SLOW 7
+#define IRONLAKE_LVDS_D_SSC_P2_FAST 7
+
static Bool
intel_find_pll_i8xx_and_i9xx(const intel_limit_t *, xf86CrtcPtr,
int, int, intel_clock_t *);
static Bool
intel_find_pll_g4x(const intel_limit_t *, xf86CrtcPtr,
int, int, intel_clock_t *);
+static Bool
+intel_igdng_find_best_PLL(const intel_limit_t *, xf86CrtcPtr,
+ int, int, intel_clock_t *);
static void
i830_crtc_load_lut(xf86CrtcPtr crtc);
@@ -405,6 +479,112 @@ static const intel_limit_t intel_limits[] = {
},
};
+static const intel_limit_t intel_limits_ironlake_dac = {
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },
+ .n = { .min = IRONLAKE_DAC_N_MIN, .max = IRONLAKE_DAC_N_MAX },
+ .m = { .min = IRONLAKE_DAC_M_MIN, .max = IRONLAKE_DAC_M_MAX },
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },
+ .p = { .min = IRONLAKE_DAC_P_MIN, .max = IRONLAKE_DAC_P_MAX },
+ .p1 = { .min = IRONLAKE_DAC_P1_MIN, .max = IRONLAKE_DAC_P1_MAX },
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+ .p2_slow = IRONLAKE_DAC_P2_SLOW,
+ .p2_fast = IRONLAKE_DAC_P2_FAST },
+ .find_pll = intel_igdng_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_single_lvds = {
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },
+ .n = { .min = IRONLAKE_LVDS_S_N_MIN, .max = IRONLAKE_LVDS_S_N_MAX },
+ .m = { .min = IRONLAKE_LVDS_S_M_MIN, .max = IRONLAKE_LVDS_S_M_MAX },
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },
+ .p = { .min = IRONLAKE_LVDS_S_P_MIN, .max = IRONLAKE_LVDS_S_P_MAX },
+ .p1 = { .min = IRONLAKE_LVDS_S_P1_MIN, .max = IRONLAKE_LVDS_S_P1_MAX },
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+ .p2_slow = IRONLAKE_LVDS_S_P2_SLOW,
+ .p2_fast = IRONLAKE_LVDS_S_P2_FAST },
+ .find_pll = intel_igdng_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_dual_lvds = {
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },
+ .n = { .min = IRONLAKE_LVDS_D_N_MIN, .max = IRONLAKE_LVDS_D_N_MAX },
+ .m = { .min = IRONLAKE_LVDS_D_M_MIN, .max = IRONLAKE_LVDS_D_M_MAX },
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },
+ .p = { .min = IRONLAKE_LVDS_D_P_MIN, .max = IRONLAKE_LVDS_D_P_MAX },
+ .p1 = { .min = IRONLAKE_LVDS_D_P1_MIN, .max = IRONLAKE_LVDS_D_P1_MAX },
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+ .p2_slow = IRONLAKE_LVDS_D_P2_SLOW,
+ .p2_fast = IRONLAKE_LVDS_D_P2_FAST },
+ .find_pll = intel_igdng_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },
+ .n = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX },
+ .m = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX },
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },
+ .p = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX },
+ .p1 = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX },
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+ .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW,
+ .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST },
+ .find_pll = intel_igdng_find_best_PLL,
+};
+
+static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
+ .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX },
+ .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX },
+ .n = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX },
+ .m = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX },
+ .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX },
+ .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX },
+ .p = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX },
+ .p1 = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX },
+ .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
+ .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW,
+ .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST },
+ .find_pll = intel_igdng_find_best_PLL,
+};
+
+
+static const intel_limit_t *intel_igdng_limit(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ const intel_limit_t *limit;
+
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ int refclk = 120;
+
+ if (intel->lvds_use_ssc && intel->lvds_ssc_freq)
+ refclk = 100;
+
+ if ((INREG(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) {
+ if (refclk == 100)
+ limit = &intel_limits_ironlake_dual_lvds_100m;
+ else
+ limit = &intel_limits_ironlake_dual_lvds;
+ } else {
+ if (refclk == 100)
+ limit = &intel_limits_ironlake_single_lvds_100m;
+ else
+ limit = &intel_limits_ironlake_single_lvds;
+ }
+ } else
+ limit = &intel_limits_ironlake_dac;
+
+ return limit;
+}
+
+
static const intel_limit_t *intel_limit_g4x (xf86CrtcPtr crtc)
{
ScrnInfoPtr scrn = crtc->scrn;
@@ -433,7 +613,9 @@ static const intel_limit_t *intel_limit (xf86CrtcPtr crtc)
intel_screen_private *intel = intel_get_screen_private(scrn);
const intel_limit_t *limit;
- if (IS_G4X(intel)) {
+ if (IS_IGDNG(intel)) {
+ limit = intel_igdng_limit(crtc);
+ } else if (IS_G4X(intel)) {
limit = intel_limit_g4x(crtc);
} else if (IS_I9XX(intel) && !IS_IGD(intel)) {
if (i830PipeHasType (crtc, I830_OUTPUT_LVDS))
@@ -507,6 +689,62 @@ i830PrintPll(ScrnInfoPtr scrn, char *prefix, intel_clock_t *clock)
clock->p, clock->p1, clock->p2);
}
+static Bool
+i830PllIsValid(xf86CrtcPtr crtc, intel_clock_t *clock);
+
+static Bool
+intel_igdng_find_best_PLL(const intel_limit_t *limit, xf86CrtcPtr crtc,
+ int target, int refclk, intel_clock_t *best_clock)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ intel_clock_t clock;
+ int max_n;
+ Bool found = FALSE;
+ /* Approximately equals target * 0.00585 */
+ int err_most = (target >> 8) + (target >> 9);
+
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ if ((INREG(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+ clock.p2 = limit->p2.p2_fast;
+ else
+ clock.p2 = limit->p2.p2_slow;
+ } else {
+ if (target < limit->p2.dot_limit)
+ clock.p2 = limit->p2.p2_slow;
+ else
+ clock.p2 = limit->p2.p2_fast;
+ }
+
+ memset(best_clock, 0, sizeof(*best_clock));
+ max_n = limit->n.max;
+ /* based on hardware requriment prefer smaller n to precision */
+ for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
+ /* based on hardware requirment prefere larger m1,m2 */
+ for (clock.m1 = limit->m1.max; clock.m1 >= limit->m1.min; clock.m1--) {
+ for (clock.m2 = limit->m2.max;
+ clock.m2 >= limit->m2.min; clock.m2--) {
+ for (clock.p1 = limit->p1.max;
+ clock.p1 >= limit->p1.min; clock.p1--) {
+ int this_err;
+
+ intel_clock(intel, refclk, &clock);
+ if (!i830PllIsValid(crtc, &clock))
+ continue;
+ this_err = abs(clock.dot - target) ;
+ if (this_err < err_most) {
+ *best_clock = clock;
+ err_most = this_err;
+ max_n = clock.n;
+ found = TRUE;
+ }
+ }
+ }
+ }
+ }
+ return found;
+}
+
/**
* Returns whether any output on the specified pipe is of the specified type
*/
@@ -530,7 +768,11 @@ i830PipeHasType (xf86CrtcPtr crtc, int type)
return FALSE;
}
+#if 1
#define i830PllInvalid(s) { /* ErrorF (s) */; return FALSE; }
+#else
+#define i830PllInvalid(s) { ErrorF (s) ; return FALSE; }
+#endif
/**
* Returns whether the given set of divisors are valid for a given refclk with
* the given outputs.
@@ -770,6 +1012,7 @@ Bool
i830_pipe_a_require_activate (ScrnInfoPtr scrn)
{
xf86CrtcPtr crtc = i830_crtc_for_pipe (scrn, 0);
+ intel_screen_private *intel = intel_get_screen_private(scrn);
/* VESA 640x480x72Hz mode to set on the pipe */
static DisplayModeRec mode = {
NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
@@ -783,6 +1026,9 @@ i830_pipe_a_require_activate (ScrnInfoPtr scrn)
FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
};
+ if (IS_IGDNG(intel))
+ return FALSE;
+
if (!crtc)
return FALSE;
if (crtc->enabled)
@@ -1076,6 +1322,16 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
ScrnInfoPtr scrn = crtc->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
uint8_t sr01;
+ uint32_t vga_reg, vgacntrl;
+
+ if (IS_IGDNG(intel))
+ vga_reg = CPU_VGACNTRL;
+ else
+ vga_reg = VGACNTRL;
+
+ vgacntrl = INREG(vga_reg);
+ if (vgacntrl & VGA_DISP_DISABLE)
+ return;
/*
* Bug #17235: G4X machine needs following steps
@@ -1092,8 +1348,11 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
usleep(30);
}
- OUTREG(VGACNTRL, VGA_DISP_DISABLE);
- i830WaitForVblank(scrn);
+ while (!(INREG(vga_reg) & VGA_DISP_DISABLE)) {
+ vgacntrl |= VGA_DISP_DISABLE;
+ OUTREG(vga_reg, vgacntrl);
+ i830WaitForVblank(scrn);
+ }
/* restore SR01 */
if (IS_G4X(intel)) {
@@ -1230,6 +1489,446 @@ i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
i830_disable_vga_plane (crtc);
}
+static void ironlake_fdi_link_train(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+ int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
+ int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
+ uint32_t temp, tries = 0;
+
+ /* enable CPU FDI TX and PCH FDI RX */
+ temp = INREG(fdi_tx_reg);
+ temp |= FDI_TX_ENABLE;
+ temp &= ~(7 << 19);
+ temp |= /*(intel_crtc->fdi_lanes - 1)*/3 << 19;
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_tx_reg, temp);
+ INREG(fdi_tx_reg);
+
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_rx_reg, temp | FDI_RX_ENABLE);
+ INREG(fdi_rx_reg);
+ usleep(150);
+
+ /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
+ for train result */
+ temp = INREG(fdi_rx_imr_reg);
+ temp &= ~FDI_RX_SYMBOL_LOCK;
+ temp &= ~FDI_RX_BIT_LOCK;
+ OUTREG(fdi_rx_imr_reg, temp);
+ INREG(fdi_rx_imr_reg);
+ usleep(150);
+
+ for (;;) {
+ temp = INREG(fdi_rx_iir_reg);
+ ErrorF("FDI_RX_IIR 0x%x\n", temp);
+
+ if ((temp & FDI_RX_BIT_LOCK)) {
+ ErrorF("FDI train 1 done.\n");
+ OUTREG(fdi_rx_iir_reg,
+ temp | FDI_RX_BIT_LOCK);
+ break;
+ }
+
+ tries++;
+
+ if (tries > 5) {
+ ErrorF("FDI train 1 fail!\n");
+ break;
+ }
+ }
+
+ /* Train 2 */
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
+ OUTREG(fdi_tx_reg, temp);
+
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
+ OUTREG(fdi_rx_reg, temp);
+ usleep(150);
+
+ tries = 0;
+
+ for (;;) {
+ temp = INREG(fdi_rx_iir_reg);
+ ErrorF("FDI_RX_IIR 0x%x\n", temp);
+
+ if (temp & FDI_RX_SYMBOL_LOCK) {
+ OUTREG(fdi_rx_iir_reg,
+ temp | FDI_RX_SYMBOL_LOCK);
+ ErrorF("FDI train 2 done.\n");
+ break;
+ }
+
+ tries++;
+
+ if (tries > 5) {
+ ErrorF("FDI train 2 fail!\n");
+ break;
+ }
+ }
+
+ ErrorF("FDI train done\n");
+}
+
+static void
+ironlake_crtc_enable(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int plane = intel_crtc->plane;
+ int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+ int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+ int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
+ int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
+ int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
+ int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
+ int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+ int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+ int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+ int cpu_vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+ int cpu_vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+ int cpu_vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+ int trans_htot_reg = (pipe == 0) ? TRANS_HTOTAL_A : TRANS_HTOTAL_B;
+ int trans_hblank_reg = (pipe == 0) ? TRANS_HBLANK_A : TRANS_HBLANK_B;
+ int trans_hsync_reg = (pipe == 0) ? TRANS_HSYNC_A : TRANS_HSYNC_B;
+ int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
+ int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
+ int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
+ uint32_t temp, pipe_bpc;
+
+ temp = INREG(pipeconf_reg);
+ pipe_bpc = temp & PIPE_BPC_MASK;
+
+ /* XXX no LVDS port force */
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ temp = INREG(PCH_LVDS);
+ if ((temp & LVDS_PORT_EN) == 0) {
+ OUTREG(PCH_LVDS, temp | LVDS_PORT_EN);
+ INREG(PCH_LVDS);
+ }
+ }
+
+ ErrorF("PCH FDI RX PLL enable\n");
+ temp = INREG(fdi_rx_reg);
+ temp &= ~(0x7 << 16);
+ temp |= (pipe_bpc << 11);
+ temp &= ~(FDI_DP_PORT_WIDTH_MASK);
+ temp |= FDI_DP_PORT_WIDTH_X4;
+
+ OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); /* default 4 lanes */
+ INREG(fdi_rx_reg);
+ usleep(200);
+
+ temp = INREG(fdi_rx_reg);
+ OUTREG(fdi_rx_reg, temp | FDI_SEL_PCDCLK);
+ temp = INREG(fdi_rx_reg);
+ usleep(200);
+
+ ErrorF("PCH FDI TX PLL enable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+ OUTREG(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+ INREG(fdi_tx_reg);
+ usleep(100);
+ }
+
+
+
+#define PF_FILTER_MASK (3<<23)
+#define PF_FILTER_MED_3x3 (1<<23)
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ temp = INREG(pf_ctl_reg);
+ temp &= ~PF_FILTER_MASK;
+ OUTREG(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
+ /* currently full aspect */
+ OUTREG(pf_win_pos, 0);
+ OUTREG(pf_win_size, (intel->lvds_fixed_mode->HDisplay << 16) |
+ (intel->lvds_fixed_mode->VDisplay));
+ }
+
+ ErrorF("Pipe enable\n");
+ /* Enable CPU pipe */
+ temp = INREG(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) == 0) {
+ OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
+ INREG(pipeconf_reg);
+ usleep(100);
+ }
+
+ ErrorF("Plane enable\n");
+ /* configure and enable CPU plane */
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+ OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ usleep(10);
+ }
+ /* twice, like the BIOS */
+ OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+
+ /* Train FDI. */
+ ironlake_fdi_link_train(crtc);
+
+ /* enable PCH DPLL */
+ temp = INREG(pch_dpll_reg);
+ if ((temp & DPLL_VCO_ENABLE) == 0) {
+ OUTREG(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
+ INREG(pch_dpll_reg);
+ }
+ usleep(200);
+
+ /* set transcoder timing */
+ OUTREG(trans_htot_reg, INREG(cpu_htot_reg));
+ OUTREG(trans_hblank_reg, INREG(cpu_hblank_reg));
+ OUTREG(trans_hsync_reg, INREG(cpu_hsync_reg));
+
+ OUTREG(trans_vtot_reg, INREG(cpu_vtot_reg));
+ OUTREG(trans_vblank_reg, INREG(cpu_vblank_reg));
+ OUTREG(trans_vsync_reg, INREG(cpu_vsync_reg));
+
+ /* enable normal */
+
+ ErrorF("FDI TX link normal\n");
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ OUTREG(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
+ FDI_TX_ENHANCE_FRAME_ENABLE);
+ INREG(fdi_tx_reg);
+
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_NONE;
+
+ OUTREG(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE);
+ INREG(fdi_rx_reg);
+
+ usleep(100);
+
+ ErrorF("transcoder enable\n");
+ /* enable transcoder */
+ temp = INREG(transconf_reg);
+ temp &= ~PIPE_BPC_MASK;
+ temp |= pipe_bpc;
+ OUTREG(transconf_reg, temp | TRANS_ENABLE);
+ INREG(transconf_reg);
+
+ while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) == 0)
+ ;
+
+ ErrorF("LUT load\n");
+ i830_crtc_load_lut(crtc);
+
+ ErrorF("DPMS on done\n");
+
+ i830_modeset_ctl(crtc, 0);
+}
+
+void
+ironlake_crtc_disable(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+ int pipe = intel_crtc->pipe;
+ int plane = intel_crtc->plane;
+ int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
+ int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+ int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
+ int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
+ int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
+ uint32_t temp, pipe_bpc;
+ int n;
+
+ i830_modeset_ctl(crtc, 1);
+
+ temp = INREG(pipeconf_reg);
+ pipe_bpc = temp & PIPE_BPC_MASK;
+
+ ErrorF("Plane disable\n");
+ temp = INREG(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+ OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+ /* flush plane changes */
+ OUTREG(dspbase_reg, INREG(dspbase_reg));
+ INREG(dspbase_reg);
+ }
+
+ i830_disable_vga_plane (crtc);
+
+ ErrorF("Pipe disable\n");
+ /* disable cpu pipe, disable after all planes disabled */
+ temp = INREG(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+ INREG(pipeconf_reg);
+ n = 0;
+ /* wait for cpu pipe off, pipe state */
+ while ((INREG(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
+ n++;
+ if (n < 60) {
+ usleep(500);
+ continue;
+ } else {
+ ErrorF("aborting pipeconf disable early\n");
+ break;
+ }
+ }
+ }
+
+ usleep(100);
+
+ ErrorF("PFIT disable\n");
+ temp = INREG(pf_ctl_reg);
+ if ((temp & PF_ENABLE) != 0) {
+ OUTREG(pf_ctl_reg, temp & ~PF_ENABLE);
+ INREG(pf_ctl_reg);
+ }
+ OUTREG(pf_win_size, 0);
+ INREG(pf_win_size);
+
+ ErrorF("FDI TX disable\n");
+ temp = INREG(fdi_tx_reg);
+ OUTREG(fdi_tx_reg, temp & ~FDI_TX_ENABLE);
+ INREG(fdi_tx_reg);
+
+ ErrorF("FDI RX disable\n");
+ temp = INREG(fdi_rx_reg);
+ temp &= ~(0x07 << 16);
+ temp |= pipe_bpc << 11;
+ OUTREG(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
+ INREG(fdi_rx_reg);
+
+ usleep(100);
+
+ ErrorF("FDI TX train 1 preload\n");
+ /* still set train pattern 1 */
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_tx_reg, temp);
+ INREG(fdi_tx_reg);
+
+ ErrorF("FDI RX train 1 preload\n");
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_LINK_TRAIN_NONE;
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
+ OUTREG(fdi_rx_reg, temp);
+ INREG(fdi_rx_reg);
+
+ usleep(100);
+
+ ErrorF("LVDS port force off\n");
+ if (i830PipeHasType(crtc, I830_OUTPUT_LVDS)) {
+ while ((temp = INREG(PCH_LVDS)) & PORT_ENABLE) {
+ OUTREG(PCH_LVDS, temp & ~LVDS_PORT_EN);
+ INREG(PCH_LVDS);
+ usleep(100);
+ }
+ }
+
+ ErrorF("Transcoder disable\n");
+ /* disable PCH transcoder */
+ temp = INREG(transconf_reg);
+ if ((temp & TRANS_STATE_ENABLE) != 0) {
+ OUTREG(transconf_reg, temp & ~TRANS_ENABLE);
+ INREG(transconf_reg);
+ n = 0;
+ /* wait for PCH transcoder off, transcoder state */
+ while ((INREG(transconf_reg) & TRANS_STATE_ENABLE) != 0) {
+ n++;
+ if (n < 600) {
+ usleep(500);
+ continue;
+ } else {
+ ErrorF("aborting transcoder disable early, 0x%08x\n", INREG(transconf_reg));
+ break;
+ }
+ }
+ }
+
+ temp = INREG(transconf_reg);
+ temp &= ~PIPE_BPC_MASK;
+ temp |= pipe_bpc;
+ OUTREG(transconf_reg, temp);
+ INREG(transconf_reg);
+ usleep(100);
+
+ ErrorF("PCH DPLL disable\n");
+ /* disable PCH DPLL */
+ temp = INREG(pch_dpll_reg);
+ OUTREG(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
+ INREG(pch_dpll_reg);
+
+ ErrorF("FDI RX PLL PCD disable\n");
+ temp = INREG(fdi_rx_reg);
+ temp &= ~FDI_SEL_PCDCLK;
+ OUTREG(fdi_rx_reg, temp);
+ temp = INREG(fdi_rx_reg);
+
+ ErrorF("FDI TX PLL disable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ temp &= ~FDI_TX_PLL_ENABLE;
+ OUTREG(fdi_tx_reg, temp);
+ temp = INREG(fdi_tx_reg);
+ usleep(100);
+
+ ErrorF("FDI RX PLL disable %08x\n", temp);
+ temp = INREG(fdi_tx_reg);
+ OUTREG(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
+ INREG(fdi_tx_reg);
+ usleep(100);
+
+ ErrorF("DPMS off done\n");
+ /* Wait for the clocks to turn off. */
+ usleep(150);
+}
+
+static void igdng_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (intel_crtc->pipe != intel_crtc->plane)
+ FatalError("pipe/plane mismatch, aborting\n");
+
+ /* XXX: When our outputs are all unaware of DPMS modes other than off
+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+ */
+ switch (mode) {
+ case DPMSModeOn:
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ ironlake_crtc_enable(crtc);
+ break;
+ case DPMSModeOff:
+ ironlake_crtc_disable(crtc);
+ intel_crtc->enabled = FALSE;
+ break;
+ }
+}
+
/**
* Sets the power management mode of the pipe and plane.
*
@@ -1237,7 +1936,7 @@ i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
* on appropriately at the same time as we're turning the pipe off/on.
*/
static void
-i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+i9xx_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
ScrnInfoPtr scrn = crtc->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -1261,6 +1960,19 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
intel_crtc->enabled = FALSE;
break;
}
+}
+
+static void
+i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (IS_IGDNG(intel))
+ igdng_crtc_dpms(crtc, mode);
+ else
+ i9xx_crtc_dpms(crtc, mode);
intel_crtc->dpms_mode = mode;
}
@@ -1331,6 +2043,15 @@ static Bool
i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ if (IS_IGDNG(intel)) {
+ /* FDI link clock is fixed at 2.7G */
+ if (mode->Clock * 3 > 27000 * 4)
+ return MODE_CLOCK_HIGH;
+ }
+
return TRUE;
}
@@ -1479,6 +2200,48 @@ i830_update_dsparb(ScrnInfoPtr scrn)
OUTREG(DSPARB, planea_entries << DSPARB_AEND_SHIFT);
}
+struct fdi_m_n {
+ CARD32 tu;
+ CARD32 gmch_m;
+ CARD32 gmch_n;
+ CARD32 link_m;
+ CARD32 link_n;
+};
+
+static void
+fdi_reduce_ratio(CARD32 *num, CARD32 *den)
+{
+ while (*num > 0xffffff || *den > 0xffffff) {
+ *num >>= 1;
+ *den >>= 1;
+ }
+}
+
+#define DATA_N 0x800000
+#define LINK_N 0x80000
+
+static void
+igdng_compute_m_n(int bits_per_pixel, int nlanes,
+ int pixel_clock, int link_clock,
+ struct fdi_m_n *m_n)
+{
+ uint64_t temp;
+
+ m_n->tu = 64; /* default size */
+
+ temp = (uint64_t) DATA_N * pixel_clock;
+ temp = temp / link_clock;
+ m_n->gmch_m = (temp * bits_per_pixel) / nlanes;
+ m_n->gmch_m >>= 3; /* convert to bytes per pixel */
+ m_n->gmch_n = DATA_N;
+ fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+
+ temp = (uint64_t) LINK_N * pixel_clock;
+ m_n->link_m = temp / link_clock;
+ m_n->link_n = LINK_N;
+ fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
/**
* Sets up registers for the given mode/adjusted_mode pair.
*
@@ -1521,6 +2284,19 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
Bool is_crt = FALSE, is_lvds = FALSE, is_tv = FALSE;
const intel_limit_t *limit;
+ struct fdi_m_n m_n = {0};
+ int data_m1_reg = (pipe == 0) ? PIPEA_DATA_M1 : PIPEB_DATA_M1;
+ int data_n1_reg = (pipe == 0) ? PIPEA_DATA_N1 : PIPEB_DATA_N1;
+ int link_m1_reg = (pipe == 0) ? PIPEA_LINK_M1 : PIPEB_LINK_M1;
+ int link_n1_reg = (pipe == 0) ? PIPEA_LINK_N1 : PIPEB_LINK_N1;
+ int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
+ int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
+ int lvds_reg = LVDS;
+ uint32_t temp;
+ int sdvo_pixel_multiply;
+
/* Set up some convenient bools for what outputs are connected to
* our pipe, used in DPLL setup.
*/
@@ -1533,6 +2309,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
switch (intel_output->type) {
case I830_OUTPUT_LVDS:
+ ErrorF("is lvds\n");
is_lvds = TRUE;
lvds_bits = intel_output->lvds_bits;
break;
@@ -1551,6 +2328,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
is_tv = TRUE;
break;
case I830_OUTPUT_ANALOG:
+ ErrorF("is crt\n");
is_crt = TRUE;
break;
}
@@ -1568,6 +2346,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
"using SSC reference clock of %d MHz\n", refclk / 1000);
} else if (IS_I9XX(intel)) {
refclk = 96000;
+ if (IS_IGDNG(intel))
+ refclk = 120000; /* 120Mhz refclk */
} else {
refclk = 48000;
}
@@ -1610,12 +2390,46 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
}
}
+ if (IS_IGDNG(intel)) {
+ int bpp = 24;
+ if (is_lvds) {
+ uint32_t lvds_reg = INREG(PCH_LVDS);
+
+ if (!((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP))
+ bpp = 18;
+ }
+
+ igdng_compute_m_n(bpp, 4, /* lane num 4 */
+ adjusted_mode->Clock,
+ 270000, /* lane clock */
+ &m_n);
+ ErrorF("bpp %d\n", bpp / 3);
+ intel_crtc->bpc = bpp / 3;
+ }
+
+ if (IS_IGDNG(intel)) {
+ uint32_t temp;
+
+ temp = INREG(PCH_DREF_CONTROL);
+ /* Always enable nonspread source */
+ temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+ temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+ OUTREG(PCH_DREF_CONTROL, temp);
+ temp = INREG(PCH_DREF_CONTROL);
+
+ temp &= ~DREF_SSC_SOURCE_MASK;
+ temp |= DREF_SSC_SOURCE_ENABLE;
+ OUTREG(PCH_DREF_CONTROL, temp);
+ temp = INREG(PCH_DREF_CONTROL);
+ }
+
if (IS_IGD(intel))
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
else
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
- dpll = DPLL_VGA_MODE_DIS;
+ if (!IS_IGDNG(intel))
+ dpll = DPLL_VGA_MODE_DIS;
if (IS_I9XX(intel)) {
if (is_lvds)
dpll |= DPLLB_MODE_LVDS;
@@ -1624,11 +2438,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
if (is_sdvo)
{
dpll |= DPLL_DVO_HIGH_SPEED;
+ sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
if ((IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel)))
- {
- int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
- }
+ else if (IS_IGDNG(intel))
+ dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
+
}
/* compute bitmask from p1 value */
@@ -1650,7 +2465,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
break;
}
- if (IS_I965G(intel) && !IS_GM45(intel))
+ if (IS_I965G(intel) && !IS_GM45(intel) && !IS_IGDNG(intel))
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
} else {
if (is_lvds) {
@@ -1680,6 +2495,10 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
+ /* this is "must be enabled" in the docs, but not set by bios */
+ if (IS_IGDNG(intel))
+ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
switch (scrn->bitsPerPixel) {
case 8:
dspcntr |= DISPPLANE_8BPP;
@@ -1697,10 +2516,14 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
FatalError("unknown display bpp\n");
}
- if (pipe == 0)
- dspcntr |= DISPPLANE_SEL_PIPE_A;
- else
- dspcntr |= DISPPLANE_SEL_PIPE_B;
+ /* IGDNG's plane is forced to pipe, bit 24 is to
+ enable color space conversion */
+ if (!IS_IGDNG(intel)) {
+ if (pipe == 0)
+ dspcntr |= DISPPLANE_SEL_PIPE_A;
+ else
+ dspcntr |= DISPPLANE_SEL_PIPE_B;
+ }
if (IS_I965G(intel) && i830_display_tiled(crtc))
dspcntr |= DISPLAY_PLANE_TILED;
@@ -1719,6 +2542,15 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
else
pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
}
+
+ if (IS_IGDNG(intel)) {
+ pipeconf &= ~(7 << 5);
+ if (intel_crtc->bpc == 6)
+ pipeconf |= (1 << 6); /* 0 is 8bpc */
+ if (intel_crtc->bpc != 8)
+ pipeconf |= (1 << 4); /* enable dithering */
+ }
+
/*
* This "shouldn't" be needed as the dpms on code
* will be run after the mode is set. On 9xx, it helps.
@@ -1732,7 +2564,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
}
/* Disable the panel fitter if it was on our pipe */
- if (i830_panel_fitter_pipe (intel) == pipe)
+ if (!IS_IGDNG(intel) && i830_panel_fitter_pipe (intel) == pipe)
OUTREG(PFIT_CONTROL, 0);
if (intel->debug_modes) {
@@ -1747,6 +2579,12 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
i830PrintPll(scrn, "chosen", &clock);
}
+ /* assign to IGDNG registers */
+ if (IS_IGDNG(intel)) {
+ fp_reg = pch_fp_reg;
+ dpll_reg = pch_dpll_reg;
+ }
+
if (dpll & DPLL_VCO_ENABLE)
{
OUTREG(fp_reg, fp);
@@ -1761,9 +2599,17 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
*/
if (is_lvds)
{
- uint32_t lvds = INREG(LVDS);
+ uint32_t lvds;
+
+ if (IS_IGDNG(intel))
+ lvds_reg = PCH_LVDS;
- lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
+ lvds = INREG(lvds_reg);
+ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
+ if (IS_IGDNG(intel))
+ lvds |= (pipe == 1) ? LVDS_PIPEB_SELECT : 0;
+ else
+ lvds |= LVDS_PIPEB_SELECT;
/* Set the B0-B3 data pairs corresponding to whether we're going to
* set the DPLLs for dual-channel mode or not.
*/
@@ -1799,17 +2645,18 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
lvds |= lvds_bits;
- OUTREG(LVDS, lvds);
- POSTING_READ(LVDS);
+ OUTREG(lvds_reg, lvds);
+ POSTING_READ(lvds_reg);
}
OUTREG(fp_reg, fp);
+/* OUTREG(fp_reg + 4, fp); RHEL had this... wtf? */
OUTREG(dpll_reg, dpll);
POSTING_READ(dpll_reg);
/* Wait for the clocks to stabilize. */
usleep(150);
- if (IS_I965G(intel)) {
+ if (IS_I965G(intel) && !IS_IGDNG(intel)) {
int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
@@ -1832,7 +2679,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
((adjusted_mode->CrtcHSyncEnd - 1) << 16));
OUTREG(vtot_reg, (adjusted_mode->CrtcVDisplay - 1) |
((adjusted_mode->CrtcVTotal - 1) << 16));
-
+
OUTREG(vblank_reg, (adjusted_mode->CrtcVBlankStart - 1) |
((adjusted_mode->CrtcVBlankEnd - 1) << 16));
OUTREG(vsync_reg, (adjusted_mode->CrtcVSyncStart - 1) |
@@ -1840,13 +2687,44 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
/* pipesrc and dspsize control the size that is scaled from, which should
* always be the user's requested size.
*/
- OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
- OUTREG(dsppos_reg, 0);
+ if (!IS_IGDNG(intel)) {
+ OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1));
+ OUTREG(dsppos_reg, 0);
+ }
OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1));
+
+ if (IS_IGDNG(intel)) {
+ OUTREG(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
+ OUTREG(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
+ OUTREG(link_m1_reg, m_n.link_m);
+ OUTREG(link_n1_reg, m_n.link_n);
+
+ /* enable FDI RX PLL too */
+ temp = INREG(fdi_rx_reg);
+ OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
+ INREG(fdi_rx_reg);
+ usleep(200);
+
+ temp = INREG(fdi_tx_reg);
+ OUTREG(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+ INREG(fdi_tx_reg);
+
+ temp = INREG(fdi_rx_reg);
+ OUTREG(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
+ INREG(fdi_rx_reg);
+ usleep(200);
+ }
+
OUTREG(pipeconf_reg, pipeconf);
POSTING_READ(pipeconf_reg);
i830WaitForVblank(scrn);
+ if (IS_IGDNG(intel)) {
+ /* enable address swizzle for tiling buffer */
+ temp = INREG(DISP_ARB_CTL);
+ OUTREG(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
+ }
+
OUTREG(dspcntr_reg, dspcntr);
/* Flush the plane changes */
i830PipeSetBase(crtc, x, y);
@@ -1869,6 +2747,11 @@ i830_crtc_load_lut(xf86CrtcPtr crtc)
if (!crtc->enabled)
return;
+ /* use legacy palette for IGDNG */
+ if (IS_IGDNG(intel))
+ palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
+ LGC_PALETTE_B;
+
for (i = 0; i < 256; i++) {
OUTREG(palreg + 4 * i,
(intel_crtc->lut_r[i] << 16) |
@@ -1882,6 +2765,8 @@ static void
i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
int size)
{
+ ScrnInfoPtr scrn = crtc->scrn;
+ intel_screen_private *intel = intel_get_screen_private(scrn);
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int i;
@@ -1893,7 +2778,13 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
intel_crtc->lut_b[i] = blue[i] >> 8;
}
- i830_crtc_load_lut(crtc);
+ /*
+ * 855 at least really doesn't seem like like you poking its
+ * pallette registers other than at mode set time. so just disable
+ * this for now on 8xx. Stops hard machine lockups for me.
+ */
+ if (IS_I9XX(intel))
+ i830_crtc_load_lut(crtc);
}
/**
@@ -2024,6 +2915,12 @@ i830DescribeOutputConfiguration(ScrnInfoPtr scrn)
INREG(PIPEBCONF);
Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
Bool hw_pipe_enable = (pipeconf & PIPEACONF_ENABLE) != 0;
+ int pipe;
+
+ if (IS_IGDNG(intel))
+ pipe = intel_crtc->plane;
+ else
+ pipe = !!(dspcntr & DISPPLANE_SEL_PIPE_MASK);
xf86DrvMsg(scrn->scrnIndex, X_INFO,
" Pipe %c is %s\n",
@@ -2032,7 +2929,7 @@ i830DescribeOutputConfiguration(ScrnInfoPtr scrn)
" Display plane %c is now %s and connected to pipe %c.\n",
'A' + intel_crtc->plane,
hw_plane_enable ? "enabled" : "disabled",
- dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
+ 'A' + pipe);
if (hw_pipe_enable != crtc->enabled) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
" Hardware claims pipe %c is %s while software "
@@ -2235,19 +3132,22 @@ i830_crtc_clock_get(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
return 0;
}
- if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
+ if (IS_IGDNG(intel))
+ i9xx_clock(120000, &clock);
+ else if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
intel_clock(intel, 100000, &clock);
else
intel_clock(intel, 96000, &clock);
} else {
- Bool is_lvds = (pipe == 1) && (INREG(LVDS) & LVDS_PORT_EN);
+ CARD32 lvds = IS_IGDNG(intel) ? PCH_LVDS : LVDS;
+ Bool is_lvds = (pipe == 1) && (INREG(lvds) & LVDS_PORT_EN);
if (is_lvds) {
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
DPLL_FPA01_P1_POST_DIV_SHIFT);
/* if LVDS is dual-channel, p2 = 7 */
- if ((INREG(LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+ if ((INREG(lvds) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
clock.p2 = 7;
else
clock.p2 = 14;
@@ -2295,7 +3195,7 @@ i830_crtc_mode_get(ScrnInfoPtr scrn, xf86CrtcPtr crtc)
int vtot = INREG((pipe == 0) ? VTOTAL_A : VTOTAL_B);
int vsync = INREG((pipe == 0) ? VSYNC_A : VSYNC_B);
- mode = xcalloc(1, sizeof(DisplayModeRec));
+ mode = calloc(1, sizeof(DisplayModeRec));
if (mode == NULL)
return NULL;
diff --git a/driver/xf86-video-intel/src/i830_display.h b/driver/xf86-video-intel/src/i830_display.h
index f19753164..90d584ad8 100644
--- a/driver/xf86-video-intel/src/i830_display.h
+++ b/driver/xf86-video-intel/src/i830_display.h
@@ -33,6 +33,7 @@ void i830WaitForVblank(ScrnInfoPtr scrn);
void i830DescribeOutputConfiguration(ScrnInfoPtr scrn);
void i830_set_new_crtc_bo(ScrnInfoPtr scrn);
void i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe);
+void ironlake_crtc_disable(xf86CrtcPtr crtc);
xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode,
int *dpms_mode);
diff --git a/driver/xf86-video-intel/src/i830_dri.c b/driver/xf86-video-intel/src/i830_dri.c
index d6522649c..ab895df73 100644
--- a/driver/xf86-video-intel/src/i830_dri.c
+++ b/driver/xf86-video-intel/src/i830_dri.c
@@ -44,6 +44,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
#include "xf86.h"
#include "xf86_OSproc.h"
@@ -72,6 +75,7 @@ extern XF86ModuleData dri2ModuleData;
#endif
typedef struct {
+ int refcnt;
PixmapPtr pixmap;
unsigned int attachment;
} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
@@ -90,12 +94,12 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
I830DRI2BufferPrivatePtr privates;
PixmapPtr pixmap, pDepthPixmap;
- buffers = xcalloc(count, sizeof *buffers);
+ buffers = calloc(count, sizeof *buffers);
if (buffers == NULL)
return NULL;
- privates = xcalloc(count, sizeof *privates);
+ privates = calloc(count, sizeof *privates);
if (privates == NULL) {
- xfree(buffers);
+ free(buffers);
return NULL;
}
@@ -125,8 +129,7 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
break;
}
- if (!intel->tiling ||
- (!IS_I965G(intel) && !intel->kernel_exec_fencing))
+ if (!intel->tiling)
hint = 0;
pixmap = screen->CreatePixmap(screen,
@@ -145,14 +148,14 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
buffers[i].driverPrivate = &privates[i];
buffers[i].flags = 0; /* not tiled */
+ privates[i].refcnt = 1;
privates[i].pixmap = pixmap;
privates[i].attachment = attachments[i];
bo = i830_get_pixmap_bo(pixmap);
- if (dri_bo_flink(bo, &buffers[i].name) != 0) {
+ if (bo != NULL && dri_bo_flink(bo, &buffers[i].name) != 0) {
/* failed to name buffer */
}
-
}
return buffers;
@@ -172,12 +175,12 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
I830DRI2BufferPrivatePtr privates;
PixmapPtr pixmap;
- buffer = xcalloc(1, sizeof *buffer);
+ buffer = calloc(1, sizeof *buffer);
if (buffer == NULL)
return NULL;
- privates = xcalloc(1, sizeof *privates);
+ privates = calloc(1, sizeof *privates);
if (privates == NULL) {
- xfree(buffer);
+ free(buffer);
return NULL;
}
@@ -203,8 +206,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
break;
}
- if (!intel->tiling ||
- (!IS_I965G(intel) && !intel->kernel_exec_fencing))
+ if (!intel->tiling)
hint = 0;
pixmap = screen->CreatePixmap(screen,
@@ -213,6 +215,11 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
(format != 0) ? format :
drawable->depth,
hint);
+ if (pixmap == NULL) {
+ free(privates);
+ free(buffer);
+ return NULL;
+ }
}
@@ -222,12 +229,17 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
buffer->driverPrivate = privates;
buffer->format = format;
buffer->flags = 0; /* not tiled */
+ privates->refcnt = 1;
privates->pixmap = pixmap;
privates->attachment = attachment;
bo = i830_get_pixmap_bo(pixmap);
- if (dri_bo_flink(bo, &buffer->name) != 0) {
+ if (bo == NULL || dri_bo_flink(bo, &buffer->name) != 0) {
/* failed to name buffer */
+ screen->DestroyPixmap(pixmap);
+ free(privates);
+ free(buffer);
+ return NULL;
}
return buffer;
@@ -250,8 +262,8 @@ I830DRI2DestroyBuffers(DrawablePtr drawable, DRI2BufferPtr buffers, int count)
}
if (buffers) {
- xfree(buffers[0].driverPrivate);
- xfree(buffers);
+ free(buffers[0].driverPrivate);
+ free(buffers);
}
}
@@ -261,17 +273,27 @@ static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
{
if (buffer) {
I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
- ScreenPtr screen = drawable->pScreen;
+ if (--private->refcnt == 0) {
+ ScreenPtr screen = private->pixmap->drawable.pScreen;
- screen->DestroyPixmap(private->pixmap);
+ screen->DestroyPixmap(private->pixmap);
- xfree(private);
- xfree(buffer);
+ free(private);
+ free(buffer);
+ }
}
}
#endif
+static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer)
+{
+ if (buffer) {
+ I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
+ private->refcnt++;
+ }
+}
+
static void
I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer)
@@ -288,7 +310,10 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
RegionPtr pCopyClip;
GCPtr gc;
- gc = GetScratchGC(drawable->depth, screen);
+ gc = GetScratchGC(dst->depth, screen);
+ if (!gc)
+ return;
+
pCopyClip = REGION_CREATE(screen, NULL, 0);
REGION_COPY(screen, pCopyClip, pRegion);
(*gc->funcs->ChangeClip) (gc, CT_REGION, pCopyClip, 0);
@@ -375,15 +400,542 @@ I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
* later.
*
* We can't rely on getting into the block handler before the DRI
- * client gets to run again so flush now. */
- intel_batch_submit(scrn);
-#if ALWAYS_SYNC
- intel_sync(scrn);
-#endif
+ * client gets to run again so flush now.
+ */
+ intel_batch_submit(scrn, TRUE);
drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
+}
+
+#if DRI2INFOREC_VERSION >= 4
+
+enum DRI2FrameEventType {
+ DRI2_SWAP,
+ DRI2_FLIP,
+ DRI2_WAITMSC,
+};
+
+typedef struct _DRI2FrameEvent {
+ XID drawable_id;
+ ClientPtr client;
+ enum DRI2FrameEventType type;
+ int frame;
+
+ /* for swaps & flips only */
+ DRI2SwapEventPtr event_complete;
+ void *event_data;
+ DRI2BufferPtr front;
+ DRI2BufferPtr back;
+} DRI2FrameEventRec, *DRI2FrameEventPtr;
+
+static int
+I830DRI2DrawablePipe(DrawablePtr pDraw)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ BoxRec box, crtcbox;
+ xf86CrtcPtr crtc;
+ int pipe = -1;
+
+ box.x1 = pDraw->x;
+ box.y1 = pDraw->y;
+ box.x2 = box.x1 + pDraw->width;
+ box.y2 = box.y1 + pDraw->height;
+
+ crtc = i830_covering_crtc(pScrn, &box, NULL, &crtcbox);
+
+ /* Make sure the CRTC is valid and this is the real front buffer */
+ if (crtc != NULL && !crtc->rotatedData)
+ pipe = i830_crtc_to_pipe(crtc);
+
+ return pipe;
+}
+
+static void
+I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front,
+ DRI2BufferPtr back)
+{
+ I830DRI2BufferPrivatePtr front_priv, back_priv;
+ struct intel_pixmap *front_intel, *back_intel;
+ ScreenPtr screen;
+ intel_screen_private *intel;
+ int tmp;
+
+ front_priv = front->driverPrivate;
+ back_priv = back->driverPrivate;
+
+ /* Swap BO names so DRI works */
+ tmp = front->name;
+ front->name = back->name;
+ back->name = tmp;
+
+ /* Swap pixmap bos */
+ front_intel = i830_get_pixmap_intel(front_priv->pixmap);
+ back_intel = i830_get_pixmap_intel(back_priv->pixmap);
+ i830_set_pixmap_intel(front_priv->pixmap, back_intel);
+ i830_set_pixmap_intel(back_priv->pixmap, front_intel); /* should be screen */
+
+ /* Do we need to update the Screen? */
+ screen = draw->pScreen;
+ intel = intel_get_screen_private(xf86Screens[screen->myNum]);
+ if (front_intel->bo == intel->front_buffer->bo) {
+ dri_bo_unreference (intel->front_buffer->bo);
+ intel->front_buffer->bo = back_intel->bo;
+ dri_bo_reference (intel->front_buffer->bo);
+ i830_set_pixmap_intel(screen->GetScreenPixmap(screen),
+ back_intel);
+ }
+}
+
+#ifdef notyet
+void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *event_data)
+{
+ DRI2FrameEventPtr event = event_data;
+ DrawablePtr drawable;
+ ScreenPtr screen;
+ ScrnInfoPtr scrn;
+ intel_screen_private *intel;
+ int status;
+
+ status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
+ M_ANY, DixWriteAccess);
+ if (status != Success) {
+ I830DRI2DestroyBuffer(NULL, event->front);
+ I830DRI2DestroyBuffer(NULL, event->back);
+ free(event);
+ return;
+ }
+
+ screen = drawable->pScreen;
+ scrn = xf86Screens[screen->myNum];
+ intel = intel_get_screen_private(scrn);
+
+ switch (event->type) {
+ case DRI2_SWAP: {
+ int swap_type;
+
+ if (DRI2CanExchange(drawable)) {
+ I830DRI2ExchangeBuffers(drawable,
+ event->front, event->back);
+ swap_type = DRI2_EXCHANGE_COMPLETE;
+ } else {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = drawable->width;
+ box.y2 = drawable->height;
+ REGION_INIT(pScreen, &region, &box, 0);
+
+ I830DRI2CopyRegion(drawable,
+ &region, event->front, event->back);
+ swap_type = DRI2_BLIT_COMPLETE;
+ }
+ DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
+ swap_type,
+ event->event_complete, event->event_data);
+ break;
+ }
+ case DRI2_WAITMSC:
+ DRI2WaitMSCComplete(event->client, drawable,
+ frame, tv_sec, tv_usec);
+ break;
+ default:
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: unknown vblank event received\n", __func__);
+ /* Unknown type */
+ break;
+ }
+
+ I830DRI2DestroyBuffer(drawable, event->front);
+ I830DRI2DestroyBuffer(drawable, event->back);
+ free(event);
+}
+
+void I830DRI2FlipEventHandler(unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *event_data)
+{
+ DRI2FrameEventPtr flip = event_data;
+ DrawablePtr drawable;
+ ScreenPtr screen;
+ ScrnInfoPtr scrn;
+ int status;
+
+ status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
+ M_ANY, DixWriteAccess);
+ if (status != Success) {
+ free(flip);
+ return;
+ }
+
+ screen = drawable->pScreen;
+ scrn = xf86Screens[screen->myNum];
+
+ /* We assume our flips arrive in order, so we don't check the frame */
+ switch (flip->type) {
+ case DRI2_SWAP:
+ DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
+ DRI2_FLIP_COMPLETE, flip->event_complete,
+ flip->event_data);
+ break;
+ default:
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: unknown vblank event received\n", __func__);
+ /* Unknown type */
+ break;
+ }
+
+ free(flip);
+}
+
+/*
+ * ScheduleSwap is responsible for requesting a DRM vblank event for the
+ * appropriate frame.
+ *
+ * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
+ * the vblank requested can simply be the last queued swap frame + the swap
+ * interval for the drawable.
+ *
+ * In the case of a page flip, we request an event for the last queued swap
+ * frame + swap interval - 1, since we'll need to queue the flip for the frame
+ * immediately following the received event.
+ *
+ * The client will be blocked if it tries to perform further GL commands
+ * after queueing a swap, though in the Intel case after queueing a flip, the
+ * client is free to queue more commands; they'll block in the kernel if
+ * they access buffers busy with the flip.
+ *
+ * When the swap is complete, the driver should call into the server so it
+ * can send any swap complete events that have been requested.
+ */
+static int
+I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
+ DRI2BufferPtr back, CARD64 *target_msc, CARD64 divisor,
+ CARD64 remainder, DRI2SwapEventPtr func, void *data)
+{
+ ScreenPtr screen = draw->pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ drmVBlank vbl;
+ int ret, pipe = I830DRI2DrawablePipe(draw), flip = 0;
+ DRI2FrameEventPtr swap_info;
+ enum DRI2FrameEventType swap_type = DRI2_SWAP;
+ CARD64 current_msc;
+ BoxRec box;
+ RegionRec region;
+
+ /* Truncate to match kernel interfaces; means occasional overflow
+ * misses, but that's generally not a big deal */
+ *target_msc &= 0xffffffff;
+ divisor &= 0xffffffff;
+ remainder &= 0xffffffff;
+
+ swap_info = calloc(1, sizeof(DRI2FrameEventRec));
+
+ /* Drawable not displayed... just complete the swap */
+ if (pipe == -1 || !swap_info)
+ goto blit_fallback;
+
+ swap_info->drawable_id = draw->id;
+ swap_info->client = client;
+ swap_info->event_complete = func;
+ swap_info->event_data = data;
+ swap_info->front = front;
+ swap_info->back = back;
+ I830DRI2ReferenceBuffer(front);
+ I830DRI2ReferenceBuffer(back);
+
+ /* Get current count */
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "first get vblank counter failed: %s\n",
+ strerror(errno));
+ goto blit_fallback;
+ }
+ current_msc = vbl.reply.sequence;
+
+ swap_info->type = swap_type;
+
+ /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+ * Do it early, so handling of different timing constraints
+ * for divisor, remainder and msc vs. target_msc works.
+ */
+ if (*target_msc > 0)
+ *target_msc -= flip;
+
+ /*
+ * If divisor is zero, or current_msc is smaller than target_msc
+ * we just need to make sure target_msc passes before initiating
+ * the swap.
+ */
+ if (divisor == 0 || current_msc < *target_msc) {
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ /* If non-pageflipping, but blitting/exchanging, we need to use
+ * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
+ * on.
+ */
+ if (flip == 0)
+ vbl.request.type |= DRM_VBLANK_NEXTONMISS;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ /* If target_msc already reached or passed, set it to
+ * current_msc to ensure we return a reasonable value back
+ * to the caller. This makes swap_interval logic more robust.
+ */
+ if (current_msc >= *target_msc)
+ *target_msc = current_msc;
+
+ vbl.request.sequence = *target_msc;
+ vbl.request.signal = (unsigned long)swap_info;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "divisor 0 get vblank counter failed: %s\n",
+ strerror(errno));
+ goto blit_fallback;
+ }
+
+ *target_msc = vbl.reply.sequence + flip;
+ swap_info->frame = *target_msc;
+
+ return TRUE;
+ }
+
+ /*
+ * If we get here, target_msc has already passed or we don't have one,
+ * and we need to queue an event that will satisfy the divisor/remainder
+ * equation.
+ */
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ if (flip == 0)
+ vbl.request.type |= DRM_VBLANK_NEXTONMISS;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ vbl.request.sequence = current_msc - (current_msc % divisor) +
+ remainder;
+
+ /*
+ * If the calculated deadline vbl.request.sequence is smaller than
+ * or equal to current_msc, it means we've passed the last point
+ * when effective onset frame seq could satisfy
+ * seq % divisor == remainder, so we need to wait for the next time
+ * this will happen.
+
+ * This comparison takes the 1 frame swap delay in pageflipping mode
+ * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
+ * if we are blitting/exchanging instead of flipping.
+ */
+ if (vbl.request.sequence <= current_msc)
+ vbl.request.sequence += divisor;
+
+ /* Account for 1 frame extra pageflip delay if flip > 0 */
+ vbl.request.sequence -= flip;
+
+ vbl.request.signal = (unsigned long)swap_info;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "final get vblank counter failed: %s\n",
+ strerror(errno));
+ goto blit_fallback;
+ }
+
+ /* Adjust returned value for 1 fame pageflip offset of flip > 0 */
+ *target_msc = vbl.reply.sequence + flip;
+ swap_info->frame = *target_msc;
+
+ return TRUE;
+
+blit_fallback:
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = draw->width;
+ box.y2 = draw->height;
+ REGION_INIT(pScreen, &region, &box, 0);
+
+ I830DRI2CopyRegion(draw, &region, front, back);
+
+ DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+ if (swap_info) {
+ I830DRI2DestroyBuffer(draw, swap_info->front);
+ I830DRI2DestroyBuffer(draw, swap_info->back);
+ free(swap_info);
+ }
+ *target_msc = 0; /* offscreen, so zero out target vblank count */
+ return TRUE;
}
+/*
+ * Get current frame count and frame count timestamp, based on drawable's
+ * crtc.
+ */
+static int
+I830DRI2GetMSC(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
+{
+ ScreenPtr screen = draw->pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ drmVBlank vbl;
+ int ret, pipe = I830DRI2DrawablePipe(draw);
+
+ /* Drawable not displayed, make up a value */
+ if (pipe == -1) {
+ *ust = 0;
+ *msc = 0;
+ return TRUE;
+ }
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+ *msc = vbl.reply.sequence;
+
+ return TRUE;
+}
+
+/*
+ * Request a DRM event when the requested conditions will be satisfied.
+ *
+ * We need to handle the event and ask the server to wake up the client when
+ * we receive it.
+ */
+static int
+I830DRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
+ CARD64 divisor, CARD64 remainder)
+{
+ ScreenPtr screen = draw->pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ DRI2FrameEventPtr wait_info;
+ drmVBlank vbl;
+ int ret, pipe = I830DRI2DrawablePipe(draw);
+ CARD64 current_msc;
+
+ /* Truncate to match kernel interfaces; means occasional overflow
+ * misses, but that's generally not a big deal */
+ target_msc &= 0xffffffff;
+ divisor &= 0xffffffff;
+ remainder &= 0xffffffff;
+
+ /* Drawable not visible, return immediately */
+ if (pipe == -1)
+ goto out_complete;
+
+ wait_info = calloc(1, sizeof(DRI2FrameEventRec));
+ if (!wait_info)
+ goto out_complete;
+
+ wait_info->drawable_id = draw->id;
+ wait_info->client = client;
+ wait_info->type = DRI2_WAITMSC;
+
+ /* Get current count */
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = 0;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ goto out_complete;
+ }
+
+ current_msc = vbl.reply.sequence;
+
+ /*
+ * If divisor is zero, or current_msc is smaller than target_msc,
+ * we just need to make sure target_msc passes before waking up the
+ * client.
+ */
+ if (divisor == 0 || current_msc < target_msc) {
+ /* If target_msc already reached or passed, set it to
+ * current_msc to ensure we return a reasonable value back
+ * to the caller. This keeps the client from continually
+ * sending us MSC targets from the past by forcibly updating
+ * their count on this call.
+ */
+ if (current_msc >= target_msc)
+ target_msc = current_msc;
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = target_msc;
+ vbl.request.signal = (unsigned long)wait_info;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ goto out_complete;
+ }
+
+ wait_info->frame = vbl.reply.sequence;
+ DRI2BlockClient(client, draw);
+ return TRUE;
+ }
+
+ /*
+ * If we get here, target_msc has already passed or we don't have one,
+ * so we queue an event that will satisfy the divisor/remainder equation.
+ */
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ if (pipe > 0)
+ vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+ vbl.request.sequence = current_msc - (current_msc % divisor) +
+ remainder;
+
+ /*
+ * If calculated remainder is larger than requested remainder,
+ * it means we've passed the last point where
+ * seq % divisor == remainder, so we need to wait for the next time
+ * that will happen.
+ */
+ if ((current_msc % divisor) >= remainder)
+ vbl.request.sequence += divisor;
+
+ vbl.request.signal = (unsigned long)wait_info;
+ ret = drmWaitVBlank(intel->drmSubFD, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ goto out_complete;
+ }
+
+ wait_info->frame = vbl.reply.sequence;
+ DRI2BlockClient(client, draw);
+
+ return TRUE;
+
+out_complete:
+ DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+ return TRUE;
+}
+#endif
+#endif
+
Bool I830DRI2ScreenInit(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
@@ -393,6 +945,9 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
int dri2_major = 1;
int dri2_minor = 0;
#endif
+#if DRI2INFOREC_VERSION >= 4
+ const char *driverNames[1];
+#endif
#ifdef USE_DRI2_1_1_0
if (xf86LoaderCheckSymbol("DRI2Version")) {
@@ -407,6 +962,7 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
#endif
intel->deviceName = drmGetDeviceNameFromFd(intel->drmSubFD);
+ memset(&info, '\0', sizeof(info));
info.fd = intel->drmSubFD;
info.driverName = IS_I965G(intel) ? "i965" : "i915";
info.deviceName = intel->deviceName;
@@ -430,6 +986,17 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
#endif
info.CopyRegion = I830DRI2CopyRegion;
+#if DRI2INFOREC_VERSION >= 4
+#ifdef notyet
+ info.version = 4;
+ info.ScheduleSwap = I830DRI2ScheduleSwap;
+ info.GetMSC = I830DRI2GetMSC;
+ info.ScheduleWaitMSC = I830DRI2ScheduleWaitMSC;
+ info.numDrivers = 1;
+ info.driverNames = driverNames;
+ driverNames[0] = info.driverName;
+#endif
+#endif
return DRI2ScreenInit(screen, &info);
}
diff --git a/driver/xf86-video-intel/src/i830_driver.c b/driver/xf86-video-intel/src/i830_driver.c
index 9da622043..af57830d0 100644
--- a/driver/xf86-video-intel/src/i830_driver.c
+++ b/driver/xf86-video-intel/src/i830_driver.c
@@ -48,6 +48,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
+#include <poll.h>
#include "xf86.h"
#include "xf86_OSproc.h"
@@ -254,16 +255,12 @@ static Bool I830GetRec(ScrnInfoPtr scrn)
static void I830FreeRec(ScrnInfoPtr scrn)
{
- intel_screen_private *intel;
-
if (!scrn)
return;
if (!scrn->driverPrivate)
return;
- intel = intel_get_screen_private(scrn);
-
- xfree(scrn->driverPrivate);
+ free(scrn->driverPrivate);
scrn->driverPrivate = NULL;
}
@@ -498,10 +495,6 @@ I830MapMem(ScrnInfoPtr scrn)
if (err)
return FALSE;
- if (intel->ring.mem != NULL) {
- intel->ring.virtual_start = intel->FbBase + intel->ring.mem->offset;
- }
-
return TRUE;
}
@@ -659,7 +652,29 @@ static void I830SetupOutputs(ScrnInfoPtr scrn)
if (IS_MOBILE(intel) && !IS_I830(intel))
i830_lvds_init(scrn);
- if (IS_I9XX(intel)) {
+ if (IS_IGDNG(intel)) {
+ int found;
+
+ if (INREG(HDMIB) & PORT_DETECTED) {
+ /* check SDVOB */
+ /* found = intel_sdvo_init(dev, HDMIB); */
+ found = 0;
+ if (!found)
+ i830_hdmi_init(scrn, HDMIB);
+ }
+
+ if (INREG(HDMIC) & PORT_DETECTED)
+ i830_hdmi_init(scrn, HDMIC);
+
+ if (INREG(HDMID) & PORT_DETECTED)
+ i830_hdmi_init(scrn, HDMID);
+
+ /* Disable DP by force */
+ OUTREG(PCH_DP_B, INREG(PCH_DP_B) & ~PORT_ENABLE);
+ OUTREG(PCH_DP_C, INREG(PCH_DP_C) & ~PORT_ENABLE);
+ OUTREG(PCH_DP_D, INREG(PCH_DP_D) & ~PORT_ENABLE);
+
+ } else if (IS_I9XX(intel)) {
Bool found = FALSE;
if ((INREG(SDVOB) & SDVO_DETECTED)) {
found = i830_sdvo_init(scrn, SDVOB);
@@ -678,7 +693,7 @@ static void I830SetupOutputs(ScrnInfoPtr scrn)
} else {
i830_dvo_init(scrn);
}
- if (IS_I9XX(intel) && IS_MOBILE(intel))
+ if (IS_I9XX(intel) && IS_MOBILE(intel) && !IS_IGDNG(intel))
i830_tv_init(scrn);
for (o = 0; o < config->num_output; o++) {
@@ -966,7 +981,7 @@ static Bool i830_kernel_mode_enabled(ScrnInfoPtr scrn)
/* Be nice to the user and load fbcon too */
if (!ret)
(void)xf86LoadKernelModule("fbcon");
- xfree(busIdString);
+ free(busIdString);
if (ret)
return FALSE;
@@ -1236,7 +1251,7 @@ static Bool I830GetEarlyOptions(ScrnInfoPtr scrn)
/* Process the options */
xf86CollectOptions(scrn, NULL);
- if (!(intel->Options = xalloc(sizeof(I830Options))))
+ if (!(intel->Options = malloc(sizeof(I830Options))))
return FALSE;
memcpy(intel->Options, I830Options, sizeof(I830Options));
xf86ProcessOptions(scrn->scrnIndex, scrn->options, intel->Options);
@@ -1327,6 +1342,25 @@ static void i830_check_dri_option(ScrnInfoPtr scrn)
}
}
+#ifdef notyet
+static void
+drm_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *event_data)
+{
+ I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event_data);
+}
+
+static void
+drm_wakeup_handler(pointer data, int err, pointer p)
+{
+ intel_screen_private *intel = data;
+ fd_set *read_mask = p;
+
+ if (err >= 0 && FD_ISSET(intel->drmSubFD, read_mask))
+ drmHandleEvent(intel->drmSubFD, &intel->event_context);
+}
+#endif
+
static Bool i830_user_modesetting_init(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -1361,6 +1395,14 @@ static Bool i830_user_modesetting_init(ScrnInfoPtr scrn)
RestoreHWState(scrn);
intel->stolen_size = I830DetectMemory(scrn);
+#ifdef notyet
+ intel->event_context.version = DRM_EVENT_CONTEXT_VERSION;
+ intel->event_context.vblank_handler = drm_vblank_handler;
+ AddGeneralSocket(intel->drmSubFD);
+ RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
+ drm_wakeup_handler, intel);
+#endif
+
return TRUE;
}
@@ -1383,11 +1425,11 @@ static Bool i830_open_drm_master(ScrnInfoPtr scrn)
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"[drm] Failed to open DRM device for %s: %s\n",
busid, strerror(errno));
- xfree(busid);
+ free(busid);
return FALSE;
}
- xfree(busid);
+ free(busid);
/* Check that what we opened was a master or a master-capable FD,
* by setting the version of the interface we'll use to talk to it.
@@ -1442,8 +1484,6 @@ static Bool I830DrmModeInit(ScrnInfoPtr scrn)
return FALSE;
}
- intel->have_gem = TRUE;
-
i830_init_bufmgr(scrn);
return TRUE;
@@ -1515,7 +1555,6 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
intel->SaveGeneration = -1;
intel->pEnt = pEnt;
intel->use_drm_mode = drm_mode_setting;
- intel->kernel_exec_fencing = intel->use_drm_mode;
if (!I830LoadSyms(scrn))
return FALSE;
@@ -1617,6 +1656,30 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
}
if (!intel->use_drm_mode) {
+ /* console hack, stolen from G80 */
+ if (IS_IGDNG(intel)) {
+ if (xf86LoadSubModule(scrn, "int10")) {
+ intel->int10 = xf86InitInt10(pEnt->index);
+ if (intel->int10) {
+ intel->int10->num = 0x10;
+ intel->int10->ax = 0x4f03;
+ intel->int10->bx =
+ intel->int10->cx =
+ intel->int10->dx = 0;
+ xf86ExecX86int10(intel->int10);
+ intel->int10Mode = intel->int10->bx & 0x3fff;
+ xf86DrvMsg(scrn->scrnIndex, X_PROBED,
+ "Console VGA mode is 0x%x\n", intel->int10Mode);
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed int10 setup, VT switch won't work\n");
+ }
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to load int10module, ironlake vt switch broken");
+ }
+ }
+
I830UnmapMMIO(scrn);
/* We won't be using the VGA access after the probe. */
@@ -1634,81 +1697,6 @@ static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
return TRUE;
}
-/*
- * Reset registers that it doesn't make sense to save/restore to a sane state.
- * This is basically the ring buffer and fence registers. Restoring these
- * doesn't make sense without restoring GTT mappings. This is something that
- * whoever gets control next should do.
- */
-static void i830_stop_ring(ScrnInfoPtr scrn, Bool flush)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- unsigned long temp;
-
- DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush));
-
- /* Flush the ring buffer, then disable it. */
- temp = INREG(LP_RING + RING_LEN);
- if (temp & RING_VALID) {
- i830_refresh_ring(scrn);
- i830_wait_ring_idle(scrn);
- }
-
- OUTREG(LP_RING + RING_LEN, 0);
- OUTREG(LP_RING + RING_HEAD, 0);
- OUTREG(LP_RING + RING_TAIL, 0);
- OUTREG(LP_RING + RING_START, 0);
-}
-
-static void i830_start_ring(ScrnInfoPtr scrn)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- unsigned int itemp;
-
- DPRINTF(PFX, "SetRingRegs\n");
-
- OUTREG(LP_RING + RING_LEN, 0);
- OUTREG(LP_RING + RING_TAIL, 0);
- OUTREG(LP_RING + RING_HEAD, 0);
-
- assert((intel->ring.mem->offset & I830_RING_START_MASK) ==
- intel->ring.mem->offset);
-
- /* Don't care about the old value. Reserved bits must be zero anyway. */
- itemp = intel->ring.mem->offset;
- OUTREG(LP_RING + RING_START, itemp);
-
- if (((intel->ring.mem->size - 4096) & I830_RING_NR_PAGES) !=
- intel->ring.mem->size - 4096) {
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates "
- "its mask (%x)\n", intel->ring.mem->size - 4096,
- I830_RING_NR_PAGES);
- }
- /* Don't care about the old value. Reserved bits must be zero anyway. */
- itemp = (intel->ring.mem->size - 4096) & I830_RING_NR_PAGES;
- itemp |= (RING_NO_REPORT | RING_VALID);
- OUTREG(LP_RING + RING_LEN, itemp);
- i830_refresh_ring(scrn);
-}
-
-void i830_refresh_ring(ScrnInfoPtr scrn)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- /* If we're reaching RefreshRing as a result of grabbing the DRI lock
- * before we've set up the ringbuffer, don't bother.
- */
- if (intel->ring.mem == NULL)
- return;
-
- intel->ring.head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
- intel->ring.tail = INREG(LP_RING + RING_TAIL);
- intel->ring.space = intel->ring.head - (intel->ring.tail + 8);
- if (intel->ring.space < 0)
- intel->ring.space += intel->ring.mem->size;
-}
-
enum pipe {
PIPE_A = 0,
PIPE_B,
@@ -1716,40 +1704,57 @@ enum pipe {
static Bool i830_pipe_enabled(intel_screen_private *intel, enum pipe pipe)
{
- if (pipe == PIPE_A)
- return (INREG(PIPEACONF) & PIPEACONF_ENABLE);
- else
- return (INREG(PIPEBCONF) & PIPEBCONF_ENABLE);
+ uint32_t dpll_reg;
+
+ if (IS_IGDNG(intel)) {
+ dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A : PCH_DPLL_B;
+ } else {
+ dpll_reg = (pipe == PIPE_A) ? DPLL_A : DPLL_B;
+ }
+
+ return (INREG(dpll_reg) & DPLL_VCO_ENABLE);
}
static void i830_save_palette(intel_screen_private *intel, enum pipe pipe)
{
+ uint32_t reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ uint32_t *array;
int i;
if (!i830_pipe_enabled(intel, pipe))
return;
- for(i= 0; i < 256; i++) {
- if (pipe == PIPE_A)
- intel->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
- else
- intel->savePaletteB[i] = INREG(PALETTE_B + (i << 2));
- }
+ if (IS_IGDNG(intel))
+ reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+
+ if (pipe == PIPE_A)
+ array = intel->savePaletteA;
+ else
+ array = intel->savePaletteB;
+
+ for (i = 0; i < 256; i++)
+ array[i] = INREG(reg + (i << 2));
}
static void i830_restore_palette(intel_screen_private *intel, enum pipe pipe)
{
+ uint32_t reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+ uint32_t *array;
int i;
if (!i830_pipe_enabled(intel, pipe))
return;
- for(i= 0; i < 256; i++) {
- if (pipe == PIPE_A)
- OUTREG(PALETTE_A + (i << 2), intel->savePaletteA[i]);
- else
- OUTREG(PALETTE_B + (i << 2), intel->savePaletteB[i]);
- }
+ if (IS_IGDNG(intel))
+ reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+
+ if (pipe == PIPE_A)
+ array = intel->savePaletteA;
+ else
+ array = intel->savePaletteB;
+
+ for (i = 0; i < 256; i++)
+ OUTREG(reg + (i << 2), array[i]);
}
static Bool SaveHWState(ScrnInfoPtr scrn)
@@ -1760,6 +1765,9 @@ static Bool SaveHWState(ScrnInfoPtr scrn)
vgaRegPtr vgaReg = &hwp->SavedReg;
int i;
+ if (IS_IGDNG(intel))
+ return TRUE;
+
if (intel->fb_compression) {
intel->saveFBC_CFB_BASE = INREG(FBC_CFB_BASE);
intel->saveFBC_LL_BASE = INREG(FBC_LL_BASE);
@@ -1886,6 +1894,9 @@ static Bool RestoreHWState(ScrnInfoPtr scrn)
vgaRegPtr vgaReg = &hwp->SavedReg;
int i;
+ if (IS_IGDNG(intel))
+ return TRUE;
+
DPRINTF(PFX, "RestoreHWState\n");
/* Disable outputs */
@@ -2087,7 +2098,7 @@ static Bool RestoreHWState(ScrnInfoPtr scrn)
if (output->funcs->restore)
output->funcs->restore(output);
}
-
+
i830_restore_palette(intel, PIPE_A);
i830_restore_palette(intel, PIPE_B);
@@ -2157,16 +2168,10 @@ I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
/* Emit a flush of the rendering cache, or on the 965 and beyond
* rendering results may not hit the framebuffer until significantly
* later.
- *
- * XXX Under KMS this is only required because tfp does not have
- * the appropriate synchronisation points, so that outstanding updates
- * to the pixmap are flushed prior to use as a texture. The framebuffer
- * should be handled by the kernel domain management...
*/
- if (intel->need_mi_flush || !list_is_empty(&intel->flush_pixmaps))
- intel_batch_emit_flush(scrn);
-
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn,
+ intel->need_mi_flush ||
+ !list_is_empty(&intel->flush_pixmaps));
drmCommandNone(intel->drmSubFD, DRM_I915_GEM_THROTTLE);
}
@@ -2304,24 +2309,16 @@ void i830_init_bufmgr(ScrnInfoPtr scrn)
if (intel->bufmgr)
return;
- if (intel->have_gem) {
+ batch_size = 4096 * 4;
- batch_size = 4096 * 4;
+ /* The 865 has issues with larger-than-page-sized batch buffers. */
+ if (IS_I865G(intel))
+ batch_size = 4096;
- /* The 865 has issues with larger-than-page-sized batch buffers. */
- if (IS_I865G(intel))
- batch_size = 4096;
+ intel->bufmgr = intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
+ intel_bufmgr_gem_enable_reuse(intel->bufmgr);
+ drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
- intel->bufmgr = intel_bufmgr_gem_init(intel->drmSubFD, batch_size);
- intel_bufmgr_gem_enable_reuse(intel->bufmgr);
- drm_intel_bufmgr_gem_enable_fenced_relocs(intel->bufmgr);
- } else {
- assert(intel->FbBase != NULL);
- intel->bufmgr = intel_bufmgr_fake_init(intel->drmSubFD,
- intel->fake_bufmgr_mem->offset, intel->FbBase +
- intel->fake_bufmgr_mem->offset,
- intel->fake_bufmgr_mem->size, NULL);
- }
list_init(&intel->batch_pixmaps);
list_init(&intel->flush_pixmaps);
list_init(&intel->in_flight);
@@ -2443,7 +2440,8 @@ I830SwapPipes(ScrnInfoPtr scrn)
* alone in that case.
* Also make sure the DRM can handle the swap.
*/
- if (I830LVDSPresent(scrn) && !IS_I965GM(intel) && !IS_GM45(intel)) {
+ if (I830LVDSPresent(scrn) && !IS_I965GM(intel) && !IS_GM45(intel) &&
+ !IS_IGDNG(intel)) {
xf86DrvMsg(scrn->scrnIndex, X_INFO, "adjusting plane->pipe "
"mappings to allow for framebuffer compression\n");
for (c = 0; c < config->num_crtc; c++) {
@@ -2478,7 +2476,7 @@ i830_disable_render_standby(ScrnInfoPtr scrn)
static Bool
I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
vgaHWPtr hwp = NULL;
intel_screen_private *intel = intel_get_screen_private(scrn);
VisualPtr visual;
@@ -2688,11 +2686,12 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
return FALSE;
}
- if (IS_I965G(intel))
+ if (IS_I965G(intel)) {
intel->batch_flush_notify = i965_batch_flush_notify;
- else if (IS_I9XX(intel))
+ } else if (IS_I9XX(intel)) {
+ intel->vertex_flush = i915_vertex_flush;
intel->batch_flush_notify = i915_batch_flush_notify;
- else
+ } else
intel->batch_flush_notify = i830_batch_flush_notify;
miInitializeBackingStore(screen);
@@ -2778,7 +2777,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
intel->closing = FALSE;
intel->suspended = FALSE;
- return TRUE;
+ return uxa_resources_init(screen);
}
static void i830AdjustFrame(int scrnIndex, int x, int y, int flags)
@@ -2826,26 +2825,25 @@ static void I830LeaveVT(int scrnIndex, int flags)
intel->leaving = TRUE;
- if (intel->devicesTimer)
- TimerFree(intel->devicesTimer);
- intel->devicesTimer = NULL;
-
i830SetHotkeyControl(scrn, HOTKEY_BIOS_SWITCH);
xf86RotateFreeShadow(scrn);
xf86_hide_cursors(scrn);
- intel_sync(scrn);
-
if (!intel->use_drm_mode) {
RestoreHWState(scrn);
- /* Evict everything from the bufmgr, as we're about to lose
- * ownership of the graphics memory.
- */
- if (!intel->have_gem) {
- intel_bufmgr_fake_evict_all(intel->bufmgr);
- i830_stop_ring(scrn, TRUE);
+
+ /* console restore hack */
+ if (IS_IGDNG(intel) && intel->int10 && intel->int10Mode) {
+ xf86Int10InfoPtr int10 = intel->int10;
+
+ /* Use int10 to restore the console mode */
+ int10->num = 0x10;
+ int10->ax = 0x4f02;
+ int10->bx = intel->int10Mode | 0x8000;
+ int10->cx = int10->dx = 0;
+ xf86ExecX86int10(int10);
}
}
@@ -2854,7 +2852,7 @@ static void I830LeaveVT(int scrnIndex, int flags)
i830_unbind_all_memory(scrn);
- if (intel->have_gem && !intel->use_drm_mode) {
+ if (!intel->use_drm_mode) {
int ret;
/* Tell the kernel to evict all buffer objects and block GTT
@@ -2925,19 +2923,21 @@ static Bool I830EnterVT(int scrnIndex, int flags)
/* Disable pipes */
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
- i830_crtc_disable(crtc, TRUE);
+ if (IS_IGDNG(intel))
+ ironlake_crtc_disable(crtc);
+ else
+ i830_crtc_disable(crtc, TRUE);
}
i830WaitForVblank(scrn);
}
intel->leaving = FALSE;
- if (!intel->use_drm_mode)
- i830_disable_render_standby(scrn);
-
- if (intel->have_gem && !intel->use_drm_mode) {
+ if (!intel->use_drm_mode) {
int ret;
+ i830_disable_render_standby(scrn);
+
/* Tell the kernel that we're back in control and ready for GTT
* usage.
*/
@@ -2958,11 +2958,6 @@ static Bool I830EnterVT(int scrnIndex, int flags)
gen4_render_state_init(scrn);
if (!intel->use_drm_mode) {
- /* Re-set up the ring. */
- if (!intel->have_gem) {
- i830_stop_ring(scrn, FALSE);
- i830_start_ring(scrn);
- }
I830InitHWCursor(scrn);
/* Tell the BIOS that we're in control of mode setting now. */
@@ -3014,10 +3009,6 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
I830LeaveVT(scrnIndex, 0);
}
- if (intel->devicesTimer)
- TimerFree(intel->devicesTimer);
- intel->devicesTimer = NULL;
-
if (!intel->use_drm_mode) {
DPRINTF(PFX, "\nUnmapping memory\n");
I830UnmapMem(scrn);
@@ -3026,7 +3017,7 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
if (intel->uxa_driver) {
uxa_driver_fini(screen);
- xfree(intel->uxa_driver);
+ free(intel->uxa_driver);
intel->uxa_driver = NULL;
}
if (intel->front_buffer) {
diff --git a/driver/xf86-video-intel/src/i830_dvo.c b/driver/xf86-video-intel/src/i830_dvo.c
index 3deb254b8..bccbe7b02 100644
--- a/driver/xf86-video-intel/src/i830_dvo.c
+++ b/driver/xf86-video-intel/src/i830_dvo.c
@@ -302,7 +302,7 @@ i830_dvo_destroy (xf86OutputPtr output)
xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
if (intel_output->pDDCBus)
xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
- xfree (intel_output);
+ free (intel_output);
}
}
@@ -407,7 +407,7 @@ i830_dvo_init(ScrnInfoPtr scrn)
/* Set up the DDC bus */
ret = I830I2CInit(scrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
if (!ret) {
- xfree(intel_output);
+ free(intel_output);
return;
}
@@ -482,7 +482,7 @@ i830_dvo_init(ScrnInfoPtr scrn)
if (output == NULL) {
xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
- xfree(intel_output);
+ free(intel_output);
xf86UnloadSubModule(drv->modhandle);
return;
}
@@ -517,5 +517,5 @@ i830_dvo_init(ScrnInfoPtr scrn)
if (pI2CBus != NULL)
xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
- xfree(intel_output);
+ free(intel_output);
}
diff --git a/driver/xf86-video-intel/src/i830_hdmi.c b/driver/xf86-video-intel/src/i830_hdmi.c
index d2f95376b..41b264ec7 100644
--- a/driver/xf86-video-intel/src/i830_hdmi.c
+++ b/driver/xf86-video-intel/src/i830_hdmi.c
@@ -136,6 +136,22 @@ i830_hdmi_restore(xf86OutputPtr output)
OUTREG(dev_priv->output_reg, dev_priv->save_SDVO);
}
+static xf86OutputStatus
+igdng_hdmi_detect(xf86OutputPtr output)
+{
+ DisplayModePtr modes;
+ xf86OutputStatus status;
+
+ modes = i830_ddc_get_modes(output);
+
+ if (modes == NULL)
+ status = XF86OutputStatusDisconnected;
+ else
+ status = XF86OutputStatusConnected;
+
+ return status;
+}
+
/**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect HDMI connection.
*
@@ -155,6 +171,9 @@ i830_hdmi_detect(xf86OutputPtr output)
dev_priv->has_hdmi_sink = FALSE;
+ if (IS_IGDNG(intel))
+ return igdng_hdmi_detect(output);
+
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written 0xd.
* Failure to do so will result in spurious interrupts being
* generated on the port when a cable is not attached.
@@ -212,7 +231,7 @@ i830_hdmi_detect(xf86OutputPtr output)
dev_priv->has_hdmi_sink ? "HDMI" : "DVI",
(dev_priv->output_reg == SDVOB) ? 1 : 2);
- xfree(edid_mon);
+ free(edid_mon);
return status;
}
@@ -223,7 +242,7 @@ i830_hdmi_destroy (xf86OutputPtr output)
if (intel_output != NULL) {
xf86DestroyI2CBusRec(intel_output->pDDCBus, FALSE, FALSE);
- xfree(intel_output);
+ free(intel_output);
}
}
@@ -332,9 +351,27 @@ i830_hdmi_init(ScrnInfoPtr scrn, int output_reg)
xf86OutputPtr output;
I830OutputPrivatePtr intel_output;
struct i830_hdmi_priv *dev_priv;
+ const char *name;
- output = xf86OutputCreate(scrn, &i830_hdmi_output_funcs,
- (output_reg == SDVOB) ? "HDMI-1" : "HDMI-2");
+ switch (output_reg) {
+ case SDVOB:
+ name = "HDMI-1";
+ break;
+ case SDVOC:
+ name = "HDMI-2";
+ break;
+ case HDMIB:
+ name = "HDMI-3";
+ break;
+ case HDMIC:
+ name = "HDMI-4";
+ break;
+ case HDMID:
+ name = "HDMI-5";
+ break;
+ }
+
+ output = xf86OutputCreate(scrn, &i830_hdmi_output_funcs, name);
if (!output)
return;
intel_output = xnfcalloc(sizeof (I830OutputPrivateRec) +
@@ -359,10 +396,15 @@ i830_hdmi_init(ScrnInfoPtr scrn, int output_reg)
/* Set up the DDC bus. */
if (output_reg == SDVOB)
I830I2CInit(scrn, &intel_output->pDDCBus, GPIOE, "HDMIDDC_B");
- else
+ else if (output_reg == SDVOC)
I830I2CInit(scrn, &intel_output->pDDCBus, GPIOD, "HDMIDDC_C");
+ else if (output_reg == HDMIB)
+ I830I2CInit(scrn, &intel_output->pDDCBus, PCH_GPIOE, "HDMIB");
+ else if (output_reg == HDMIC)
+ I830I2CInit(scrn, &intel_output->pDDCBus, PCH_GPIOD, "HDMIC");
+ else if (output_reg == HDMID)
+ I830I2CInit(scrn, &intel_output->pDDCBus, PCH_GPIOF, "HDMID");
xf86DrvMsg(scrn->scrnIndex, X_INFO,
- "HDMI output %d detected\n",
- (output_reg == SDVOB) ? 1 : 2);
+ "%s output detected\n", output->name);
}
diff --git a/driver/xf86-video-intel/src/i830_hwmc.c b/driver/xf86-video-intel/src/i830_hwmc.c
index 850bf8765..9aa0af33b 100644
--- a/driver/xf86-video-intel/src/i830_hwmc.c
+++ b/driver/xf86-video-intel/src/i830_hwmc.c
@@ -62,7 +62,7 @@ static int create_context(ScrnInfoPtr scrn, XvMCContextPtr pContext,
intel_screen_private *intel = intel_get_screen_private(scrn);
struct intel_xvmc_hw_context *contextRec;
- *priv = xcalloc(1, sizeof(struct intel_xvmc_hw_context));
+ *priv = calloc(1, sizeof(struct intel_xvmc_hw_context));
contextRec = (struct intel_xvmc_hw_context *) *priv;
if (!contextRec) {
*num_priv = 0;
@@ -207,7 +207,7 @@ Bool intel_xvmc_adaptor_init(ScreenPtr pScreen)
return FALSE;
}
- pAdapt = xcalloc(1, sizeof(XF86MCAdaptorRec));
+ pAdapt = calloc(1, sizeof(XF86MCAdaptorRec));
if (!pAdapt) {
ErrorF("Allocation error.\n");
return FALSE;
diff --git a/driver/xf86-video-intel/src/i830_lvds.c b/driver/xf86-video-intel/src/i830_lvds.c
index b33b461da..651916cf5 100644
--- a/driver/xf86-video-intel/src/i830_lvds.c
+++ b/driver/xf86-video-intel/src/i830_lvds.c
@@ -140,6 +140,10 @@ i830_set_lvds_backlight_method(xf86OutputPtr output)
if (i830_kernel_backlight_available(output)) {
method = BCM_KERNEL;
+#if 0
+ } else if (IS_IGDNG(intel)) {
+ method = BCM_IRONLAKE_NULL;
+#endif
} else if (IS_I965GM(intel) || IS_GM45(intel)) {
blc_pwm_ctl2 = INREG(BLC_PWM_CTL2);
if (blc_pwm_ctl2 & BLM_LEGACY_MODE2)
@@ -161,11 +165,16 @@ i830_lvds_set_backlight_native(xf86OutputPtr output, int level)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t blc_pwm_ctl;
+ uint32_t blc_pwm_ctl, reg;
- blc_pwm_ctl = INREG(BLC_PWM_CTL);
+ if (IS_IGDNG(intel))
+ reg = BLC_PWM_CPU_CTL;
+ else
+ reg = BLC_PWM_CTL;
+
+ blc_pwm_ctl = INREG(reg);
blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
- OUTREG(BLC_PWM_CTL, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+ OUTREG(reg, blc_pwm_ctl | (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
}
static int
@@ -185,8 +194,15 @@ i830_lvds_get_backlight_max_native(xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t pwm_ctl = INREG(BLC_PWM_CTL);
- int val;
+ uint32_t pwm_ctl;
+ int val, reg;
+
+ if (IS_IGDNG(intel))
+ reg = BLC_PWM_PCH_CTL2;
+ else
+ reg = BLC_PWM_CTL;
+
+ pwm_ctl = INREG(reg);
if (IS_I965GM(intel) || IS_GM45(intel)) {
val = ((pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK2) >>
@@ -278,6 +294,18 @@ i830_lvds_get_backlight_max_combo(xf86OutputPtr output)
return i830_lvds_get_backlight_max_native(output) >> 1;
}
+/* null methods */
+static int
+i830_lvds_get_backlight_null(xf86OutputPtr output)
+{
+ return 1;
+}
+
+static void
+i830_lvds_set_backlight_null(xf86OutputPtr output, int level)
+{
+}
+
/*
* Kernel methods
*/
@@ -482,46 +510,49 @@ i830SetLVDSPanelPower(xf86OutputPtr output, Bool on)
struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t pp_status;
+ uint32_t pp_status, ctl_reg, status_reg, lvds_reg;
+
+ if (IS_IGDNG(intel)) {
+ ctl_reg = PCH_PP_CONTROL;
+ status_reg = PCH_PP_STATUS;
+ lvds_reg = PCH_LVDS;
+ } else {
+ ctl_reg = PP_CONTROL;
+ status_reg = PP_STATUS;
+ lvds_reg = LVDS;
+ }
if (on) {
- /* if we're going from on->on, be aware to current level. */
- if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
- dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
+ OUTREG(lvds_reg, INREG(lvds_reg) | LVDS_PORT_EN);
+ INREG(lvds_reg);
- /*
- * If we're going from off->on we may need to turn on the backlight.
- * We should use the saved value whenever possible, but on some
- * machines 0 is a valid backlight value (due to an external backlight
- * controller for example), so on them, when turning LVDS back on,
- * they'll always re-maximize the brightness.
- */
- if (!(INREG(PP_CONTROL) & POWER_TARGET_ON) &&
+ if (!(INREG(ctl_reg) & POWER_TARGET_ON) &&
dev_priv->backlight_duty_cycle == 0 &&
intel->backlight_control_method < BCM_KERNEL)
dev_priv->backlight_duty_cycle = dev_priv->backlight_max;
- OUTREG(PP_CONTROL, INREG(PP_CONTROL) | POWER_TARGET_ON);
+ OUTREG(ctl_reg, INREG(ctl_reg) | POWER_TARGET_ON);
+ INREG(ctl_reg);
do {
- pp_status = INREG(PP_STATUS);
+ pp_status = INREG(status_reg);
} while ((pp_status & PP_ON) == 0);
+ /* set backlight */
dev_priv->set_backlight(output, dev_priv->backlight_duty_cycle);
dev_priv->dpmsoff = FALSE;
} else {
- /*
- * Only save the current backlight value if we're going from
- * on to off.
- */
- if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
+ if ((INREG(ctl_reg) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
dev_priv->set_backlight(output, 0);
- OUTREG(PP_CONTROL, INREG(PP_CONTROL) & ~POWER_TARGET_ON);
+ OUTREG(ctl_reg, INREG(ctl_reg) & ~POWER_TARGET_ON);
+ INREG(ctl_reg);
do {
- pp_status = INREG(PP_STATUS);
+ pp_status = INREG(status_reg);
} while (pp_status & PP_ON);
-
+
+ OUTREG(lvds_reg, INREG(lvds_reg) & ~LVDS_PORT_EN);
+ INREG(lvds_reg);
dev_priv->dpmsoff = TRUE;
}
}
@@ -544,14 +575,29 @@ i830_lvds_save (xf86OutputPtr output)
struct i830_lvds_priv *dev_priv = intel_output->dev_priv;
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg, pwm_ctl_reg;
+
+ if (IS_IGDNG(intel)) {
+ pp_on_reg = PCH_PP_ON_DELAYS;
+ pp_off_reg = PCH_PP_OFF_DELAYS;
+ pp_ctl_reg = PCH_PP_CONTROL;
+ pp_div_reg = PCH_PP_DIVISOR;
+ pwm_ctl_reg = BLC_PWM_CPU_CTL;
+ } else {
+ pp_on_reg = PP_ON_DELAYS;
+ pp_off_reg = PP_OFF_DELAYS;
+ pp_ctl_reg = PP_CONTROL;
+ pp_div_reg = PP_DIVISOR;
+ pwm_ctl_reg = BLC_PWM_CTL;
+ }
if (IS_I965GM(intel) || IS_GM45(intel))
intel->saveBLC_PWM_CTL2 = INREG(BLC_PWM_CTL2);
- intel->savePP_ON = INREG(PP_ON_DELAYS);
- intel->savePP_OFF = INREG(PP_OFF_DELAYS);
- intel->savePP_CONTROL = INREG(PP_CONTROL);
- intel->savePP_DIVISOR = INREG(PP_DIVISOR);
- intel->saveBLC_PWM_CTL = INREG(BLC_PWM_CTL);
+ intel->savePP_ON = INREG(pp_on_reg);
+ intel->savePP_OFF = INREG(pp_off_reg);
+ intel->savePP_CONTROL = INREG(pp_ctl_reg);
+ intel->savePP_DIVISOR = INREG(pp_div_reg);
+ intel->saveBLC_PWM_CTL = INREG(pwm_ctl_reg);
if ((INREG(PP_CONTROL) & POWER_TARGET_ON) && !dev_priv->dpmsoff)
dev_priv->backlight_duty_cycle = dev_priv->get_backlight(output);
}
@@ -561,14 +607,31 @@ i830_lvds_restore(xf86OutputPtr output)
{
ScrnInfoPtr scrn = output->scrn;
intel_screen_private *intel = intel_get_screen_private(scrn);
+ uint32_t pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
+ uint32_t pwm_ctl_reg;
+
+ if (IS_IGDNG(intel)) {
+ pp_on_reg = PCH_PP_ON_DELAYS;
+ pp_off_reg = PCH_PP_OFF_DELAYS;
+ pp_ctl_reg = PCH_PP_CONTROL;
+ pp_div_reg = PCH_PP_DIVISOR;
+ pwm_ctl_reg = BLC_PWM_CPU_CTL;
+ } else {
+ pp_on_reg = PP_ON_DELAYS;
+ pp_off_reg = PP_OFF_DELAYS;
+ pp_ctl_reg = PP_CONTROL;
+ pp_div_reg = PP_DIVISOR;
+ pwm_ctl_reg = BLC_PWM_CTL;
+ }
if (IS_I965GM(intel) || IS_GM45(intel))
OUTREG(BLC_PWM_CTL2, intel->saveBLC_PWM_CTL2);
- OUTREG(BLC_PWM_CTL, intel->saveBLC_PWM_CTL);
- OUTREG(PP_ON_DELAYS, intel->savePP_ON);
- OUTREG(PP_OFF_DELAYS, intel->savePP_OFF);
- OUTREG(PP_DIVISOR, intel->savePP_DIVISOR);
- OUTREG(PP_CONTROL, intel->savePP_CONTROL);
+ OUTREG(pwm_ctl_reg, intel->saveBLC_PWM_CTL);
+ OUTREG(pp_on_reg, intel->savePP_ON);
+ OUTREG(pp_off_reg, intel->savePP_OFF);
+ OUTREG(pp_div_reg, intel->savePP_DIVISOR);
+ OUTREG(pp_ctl_reg, intel->savePP_CONTROL);
+
if (intel->savePP_CONTROL & POWER_TARGET_ON)
i830SetLVDSPanelPower(output, TRUE);
else
@@ -624,7 +687,7 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
}
}
- if (intel_crtc->pipe == 0) {
+ if (!IS_IGDNG(intel) && intel_crtc->pipe == 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Can't support LVDS on pipe A\n");
return FALSE;
@@ -662,6 +725,10 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
goto out;
}
+ /* only full screen scale for now */
+ if (IS_IGDNG(intel))
+ goto out;
+
/* 965+ wants fuzzy fitting */
if (IS_I965G(intel))
pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
@@ -688,8 +755,10 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
* register description and PRM.
*/
/* Change the value here to see the borders for debugging */
- OUTREG(BCLRPAT_A, 0);
- OUTREG(BCLRPAT_B, 0);
+ if (!IS_IGDNG(intel)) {
+ OUTREG(BCLRPAT_A, 0);
+ OUTREG(BCLRPAT_B, 0);
+ }
switch (dev_priv->fitting_mode) {
case CENTER:
/*
@@ -895,6 +964,15 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
intel_screen_private *intel = intel_get_screen_private(scrn);
/*
+ * The LVDS pin pair will already have been turned on in the
+ * main modesetting function since it has a large impact on the
+ * DPLL settings.
+ */
+
+ if (IS_IGDNG(intel))
+ return;
+
+ /*
* PFIT must be enabled/disabled while LVDS is on but pipes are still off
*/
OUTREG(PFIT_PGM_RATIOS, dev_priv->pfit_pgm_ratios);
@@ -907,6 +985,8 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
static xf86OutputStatus
i830_lvds_detect(xf86OutputPtr output)
{
+ enum lid_status lid;
+
/* Fallback to origin, mark LVDS always connected.
* From wider tests, we have seen both broken cases with
* ACPI lid and SWF bit. So disable them for now until we
@@ -914,8 +994,6 @@ i830_lvds_detect(xf86OutputPtr output)
*/
return XF86OutputStatusConnected;
- enum lid_status lid;
-
lid = i830_lvds_acpi_lid_open(output);
if (lid == LID_OPEN)
return XF86OutputStatusConnected;
@@ -1006,7 +1084,7 @@ i830_lvds_get_modes(xf86OutputPtr output)
if (!output->MonInfo)
{
- edid_mon = xcalloc (1, sizeof (xf86Monitor));
+ edid_mon = calloc (1, sizeof (xf86Monitor));
if (edid_mon)
{
struct detailed_monitor_section *det_mon = edid_mon->det_mon;
@@ -1057,7 +1135,7 @@ i830_lvds_destroy (xf86OutputPtr output)
xf86DeleteMode (&intel->lvds_fixed_mode, intel->lvds_fixed_mode);
if (intel_output)
- xfree (intel_output);
+ free (intel_output);
}
#ifdef RANDR_12_INTERFACE
@@ -1070,12 +1148,13 @@ static Atom backlight_atom;
* or not at all.
*/
#define BACKLIGHT_CONTROL_NAME "BACKLIGHT_CONTROL"
-#define NUM_BACKLIGHT_CONTROL_METHODS 4
+#define NUM_BACKLIGHT_CONTROL_METHODS 5
static char *backlight_control_names[] = {
"native",
"legacy",
"combination",
"kernel",
+ "null",
};
static Atom backlight_control_atom;
static Atom backlight_control_name_atoms[NUM_BACKLIGHT_CONTROL_METHODS];
@@ -1135,6 +1214,11 @@ i830_lvds_set_backlight_control(xf86OutputPtr output)
dev_priv->backlight_max =
i830_lvds_get_backlight_max_kernel(output);
break;
+ case BCM_IRONLAKE_NULL:
+ dev_priv->set_backlight = i830_lvds_set_backlight_null;
+ dev_priv->get_backlight = i830_lvds_get_backlight_null;
+ dev_priv->backlight_max = 1;
+ break;
default:
/*
* Should be impossible to get here unless the caller set a bogus
@@ -1447,6 +1531,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
DisplayModePtr modes, scan;
DisplayModePtr lvds_ddc_mode = NULL;
struct i830_lvds_priv *dev_priv;
+ int gpio = GPIOC;
if (!intel->integrated_lvds) {
if (intel->debug_modes)
@@ -1458,6 +1543,12 @@ i830_lvds_init(ScrnInfoPtr scrn)
if (intel->quirk_flag & QUIRK_IGNORE_LVDS)
return;
+ if (IS_IGDNG(intel)) {
+ if ((INREG(PCH_LVDS) & LVDS_DETECTED) == 0)
+ return;
+ gpio = PCH_GPIOC;
+ }
+
output = xf86OutputCreate (scrn, &i830_lvds_output_funcs, "LVDS");
if (!output)
return;
@@ -1470,6 +1561,8 @@ i830_lvds_init(ScrnInfoPtr scrn)
}
intel_output->type = I830_OUTPUT_LVDS;
intel_output->pipe_mask = (1 << 1);
+ if (0 && IS_IGDNG(intel)) /* XXX put me back */
+ intel_output->pipe_mask |= (1 << 0);
intel_output->clone_mask = (1 << I830_OUTPUT_LVDS);
output->driver_private = intel_output;
@@ -1492,7 +1585,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
* be useful if available.
*/
- I830I2CInit(scrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
+ I830I2CInit(scrn, &intel_output->pDDCBus, gpio, "LVDSDDC_C");
if (intel->skip_panel_detect) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
@@ -1541,7 +1634,7 @@ i830_lvds_init(ScrnInfoPtr scrn)
* turned on. If so, assume that whatever is currently programmed is the
* correct mode.
*/
- if (!intel->lvds_fixed_mode) {
+ if (!intel->lvds_fixed_mode && !IS_IGDNG(intel)) {
uint32_t lvds = INREG(LVDS);
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1619,6 +1712,19 @@ found_mode:
*/
dev_priv->fitting_mode = FULL_ASPECT;
+ if (IS_IGDNG(intel)) {
+ CARD32 pwm;
+ /* make sure PWM is enabled */
+ pwm = INREG(BLC_PWM_CPU_CTL2);
+ pwm |= (PWM_ENABLE | PWM_PIPE_B);
+ OUTREG(BLC_PWM_CPU_CTL2, pwm);
+
+ pwm = INREG(BLC_PWM_PCH_CTL1);
+ pwm |= PWM_PCH_ENABLE;
+ OUTREG(BLC_PWM_PCH_CTL1, pwm);
+ }
+
+
return;
disable_exit:
diff --git a/driver/xf86-video-intel/src/i830_memory.c b/driver/xf86-video-intel/src/i830_memory.c
index 935575dd2..0e523b7ca 100644
--- a/driver/xf86-video-intel/src/i830_memory.c
+++ b/driver/xf86-video-intel/src/i830_memory.c
@@ -198,7 +198,7 @@ static Bool i830_bind_memory(ScrnInfoPtr scrn, i830_memory *mem)
if (mem == NULL || mem->bound || intel->use_drm_mode)
return TRUE;
- if (intel->have_gem && mem->bo != NULL) {
+ if (mem->bo != NULL) {
if (dri_bo_pin(mem->bo, mem->alignment) != 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -223,11 +223,6 @@ static Bool i830_bind_memory(ScrnInfoPtr scrn, i830_memory *mem)
mem->bound = TRUE;
}
- if (mem->tiling != TILE_NONE && !intel->kernel_exec_fencing) {
- mem->fence_nr = i830_set_tiling(scrn, mem->offset, mem->pitch,
- mem->allocated_size, mem->tiling);
- }
-
return TRUE;
}
@@ -238,10 +233,6 @@ static Bool i830_unbind_memory(ScrnInfoPtr scrn, i830_memory *mem)
if (mem == NULL || !mem->bound)
return TRUE;
- if (mem->tiling != TILE_NONE && !intel->use_drm_mode &&
- !intel->kernel_exec_fencing)
- i830_clear_tiling(scrn, mem->fence_nr);
-
if (mem->bo != NULL && !intel->use_drm_mode) {
if (dri_bo_unpin(mem->bo) == 0) {
mem->bound = FALSE;
@@ -285,8 +276,8 @@ void i830_free_memory(ScrnInfoPtr scrn, i830_memory * mem)
if (mem->next)
mem->next->prev = mem->prev;
}
- xfree(mem->name);
- xfree(mem);
+ free(mem->name);
+ free(mem);
return;
}
/* Disconnect from the list of allocations */
@@ -300,8 +291,8 @@ void i830_free_memory(ScrnInfoPtr scrn, i830_memory * mem)
mem->key = -1;
}
- xfree(mem->name);
- xfree(mem);
+ free(mem->name);
+ free(mem);
}
/* Resets the state of the aperture allocator, freeing all memory that had
@@ -341,8 +332,6 @@ void i830_reset_allocations(ScrnInfoPtr scrn)
intel->front_buffer = NULL;
intel->overlay_regs = NULL;
intel->power_context = NULL;
- intel->ring.mem = NULL;
- intel->fake_bufmgr_mem = NULL;
}
/**
@@ -360,25 +349,25 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size)
i830_memory *start, *end;
struct drm_i915_setparam sp;
- start = xcalloc(1, sizeof(*start));
+ start = calloc(1, sizeof(*start));
if (start == NULL)
return FALSE;
start->name = xstrdup("start marker");
if (start->name == NULL) {
- xfree(start);
+ free(start);
return FALSE;
}
- end = xcalloc(1, sizeof(*end));
+ end = calloc(1, sizeof(*end));
if (end == NULL) {
- xfree(start->name);
- xfree(start);
+ free(start->name);
+ free(start);
return FALSE;
}
end->name = xstrdup("end marker");
if (end->name == NULL) {
- xfree(start->name);
- xfree(start);
- xfree(end);
+ free(start->name);
+ free(start);
+ free(end);
return FALSE;
}
@@ -442,8 +431,8 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size)
ret = drmCommandWrite(intel->drmSubFD,
DRM_I915_SETPARAM, &sp, sizeof(sp));
- if (ret == 0)
- intel->kernel_exec_fencing = TRUE;
+ if (ret != 0)
+ ErrorF("no kernel exec fencing, wtf?");
init.gtt_start = intel->memory_manager->offset;
init.gtt_end = intel->memory_manager->offset +
intel->memory_manager->size;
@@ -451,15 +440,14 @@ Bool i830_allocator_init(ScrnInfoPtr scrn, unsigned long size)
/* Tell the kernel to manage it */
ret = ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_INIT,
&init);
- if (ret == 0) {
- intel->have_gem = TRUE;
- i830_init_bufmgr(scrn);
- } else {
+ if (ret != 0) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to initialize kernel memory manager\n");
i830_free_memory(scrn, intel->memory_manager);
intel->memory_manager = NULL;
+ return FALSE;
}
+ i830_init_bufmgr(scrn);
} else {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to allocate space for kernel memory manager\n");
@@ -473,8 +461,8 @@ void i830_allocator_fini(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- /* The memory manager is more special */ if
- (intel->memory_manager) {
+ /* The memory manager is more special */
+ if (intel->memory_manager) {
i830_free_memory(scrn, intel->memory_manager);
intel->memory_manager = NULL;
}
@@ -576,7 +564,7 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size,
intel_screen_private *intel = intel_get_screen_private(scrn);
i830_memory *mem, *scan;
- mem = xcalloc(1, sizeof(*mem));
+ mem = calloc(1, sizeof(*mem));
if (mem == NULL)
return NULL;
@@ -585,7 +573,7 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size,
mem->name = xstrdup(name);
if (mem->name == NULL) {
- xfree(mem);
+ free(mem);
return NULL;
}
/* Only allocate page-sized increments. */
@@ -636,8 +624,8 @@ i830_allocate_aperture(ScrnInfoPtr scrn, const char *name, unsigned long size,
}
if (scan->next == NULL) {
/* Reached the end of the list, and didn't find space */
- xfree(mem->name);
- xfree(mem);
+ free(mem->name);
+ free(mem);
return NULL;
}
/* Insert new allocation into the list */
@@ -709,21 +697,21 @@ static i830_memory *i830_allocate_memory_bo(ScrnInfoPtr scrn, const char *name,
size = ALIGN(size, GTT_PAGE_SIZE);
align = i830_get_fence_alignment(intel, size);
- mem = xcalloc(1, sizeof(*mem));
+ mem = calloc(1, sizeof(*mem));
if (mem == NULL)
return NULL;
mem->name = xstrdup(name);
if (mem->name == NULL) {
- xfree(mem);
+ free(mem);
return NULL;
}
mem->bo = dri_bo_alloc(intel->bufmgr, name, size, align);
if (!mem->bo) {
- xfree(mem->name);
- xfree(mem);
+ free(mem->name);
+ free(mem);
return NULL;
}
@@ -767,8 +755,8 @@ static i830_memory *i830_allocate_memory_bo(ScrnInfoPtr scrn, const char *name,
if (scrn->vtSema || intel->use_drm_mode) {
if (!i830_bind_memory(scrn, mem)) {
dri_bo_unreference (mem->bo);
- xfree(mem->name);
- xfree(mem);
+ free(mem->name);
+ free(mem);
return NULL;
}
}
@@ -838,7 +826,7 @@ i830_memory *i830_allocate_memory(ScrnInfoPtr scrn, const char *name,
* kernel. Under UMS, we separately reserve space for
* a few objects (overlays, power context, cursors, etc).
*/
- if (intel->have_gem && (intel->use_drm_mode ||
+ if ((intel->use_drm_mode ||
!(flags & (NEED_PHYSICAL_ADDR|NEED_LIFETIME_FIXED)))) {
return i830_allocate_memory_bo(scrn, name, size, pitch,
alignment, flags, tile_format);
@@ -943,31 +931,6 @@ i830_describe_allocations(ScrnInfoPtr scrn, int verbosity, const char *prefix)
}
}
-static Bool i830_allocate_ringbuffer(ScrnInfoPtr scrn)
-{
- intel_screen_private *intel = intel_get_screen_private(scrn);
-
- if (intel->have_gem || intel->ring.mem != NULL)
- return TRUE;
-
- /* We don't have any mechanism in the DRM yet to alert it that we've
- * moved the ringbuffer since init time, so allocate it fixed for its
- * lifetime.
- */
- intel->ring.mem = i830_allocate_memory(scrn, "ring buffer",
- PRIMARY_RINGBUFFER_SIZE, PITCH_NONE, GTT_PAGE_SIZE,
- NEED_LIFETIME_FIXED, TILE_NONE);
- if (intel->ring.mem == NULL) {
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "Failed to allocate Ring Buffer space\n");
- return FALSE;
- }
-
- intel->ring.tail_mask = intel->ring.mem->size - 1;
- intel->ring.virtual_start = intel->FbBase + intel->ring.mem->offset;
- return TRUE;
-}
-
/**
* Allocate space for overlay registers.
*/
@@ -1247,10 +1210,6 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr scrn)
"\tthe agpgart module loaded.\n");
return FALSE;
}
-
- /* Allocate the ring buffer first, so it ends up in stolen mem. */
- if (!i830_allocate_ringbuffer(scrn))
- return FALSE;
}
if (intel->fb_compression)
@@ -1263,18 +1222,6 @@ Bool i830_allocate_2d_memory(ScrnInfoPtr scrn)
return FALSE;
}
- if (!intel->have_gem) {
- intel->fake_bufmgr_mem = i830_allocate_memory(scrn,
- "fake bufmgr", MB(8), PITCH_NONE, GTT_PAGE_SIZE, 0,
- TILE_NONE);
- if (intel->fake_bufmgr_mem == NULL) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "Failed to allocate fake bufmgr space.\n");
- return FALSE;
- }
- i830_init_bufmgr(scrn);
- }
-
if (!intel->use_drm_mode)
i830_allocate_overlay(scrn);
@@ -1680,53 +1627,55 @@ void i830_free_xvmc_buffer(ScrnInfoPtr scrn, i830_memory * buffer)
#endif
-static void i830_set_max_gtt_map_size(ScrnInfoPtr scrn)
+static void i830_set_max_bo_size(intel_screen_private *intel,
+ const struct drm_i915_gem_get_aperture *aperture)
{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- struct drm_i915_gem_get_aperture aperture;
- int ret;
-
- /* Default low value in case it gets used during server init. */
- intel->max_gtt_map_size = 16 * 1024 * 1024;
-
- if (!intel->have_gem)
- return;
+ if (aperture->aper_available_size)
+ /* Large BOs will tend to hit SW fallbacks frequently, and also will
+ * tend to fail to successfully map when doing SW fallbacks because we
+ * overcommit address space for BO access, or worse cause aperture
+ * thrashing.
+ */
+ intel->max_bo_size = aperture->aper_available_size / 2;
+ else
+ intel->max_bo_size = 64 * 1024 * 1024;
+}
- ret =
- ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
- if (ret == 0) {
- /* Let objects up get bound up to the size where only 2 would
- * fit in the aperture, but then leave slop to account for
- * alignment like libdrm does.
+static void i830_set_max_gtt_map_size(intel_screen_private *intel,
+ const struct drm_i915_gem_get_aperture *aperture)
+{
+ if (aperture->aper_available_size)
+ /* Let objects up get bound up to the size where only 2 would fit in
+ * the aperture, but then leave slop to account for alignment like
+ * libdrm does.
*/
intel->max_gtt_map_size =
- aperture.aper_available_size * 3 / 4 / 2;
- }
+ aperture->aper_available_size * 3 / 4 / 2;
+ else
+ intel->max_gtt_map_size = 16 * 1024 * 1024;
}
-static void i830_set_max_tiling_size(ScrnInfoPtr scrn)
+static void i830_set_max_tiling_size(intel_screen_private *intel,
+ const struct drm_i915_gem_get_aperture *aperture)
{
- intel_screen_private *intel = intel_get_screen_private(scrn);
- struct drm_i915_gem_get_aperture aperture;
- int ret;
-
- /* Default low value in case it gets used during server init. */
- intel->max_tiling_size = 4 * 1024 * 1024;
-
- ret =
- ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
- if (ret == 0) {
+ if (aperture->aper_available_size)
/* Let objects be tiled up to the size where only 4 would fit in
* the aperture, presuming worst case alignment.
*/
- intel->max_tiling_size = aperture.aper_available_size / 4;
- if (!IS_I965G(intel))
- intel->max_tiling_size /= 2;
- }
+ intel->max_tiling_size = aperture->aper_available_size / 4;
+ else
+ intel->max_tiling_size = 4 * 1024 * 1024;
}
void i830_set_gem_max_sizes(ScrnInfoPtr scrn)
{
- i830_set_max_gtt_map_size(scrn);
- i830_set_max_tiling_size(scrn);
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ struct drm_i915_gem_get_aperture aperture;
+
+ aperture.aper_available_size = 0;
+ ioctl(intel->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
+
+ i830_set_max_bo_size(intel, &aperture);
+ i830_set_max_gtt_map_size(intel, &aperture);
+ i830_set_max_tiling_size(intel, &aperture);
}
diff --git a/driver/xf86-video-intel/src/i830_quirks.c b/driver/xf86-video-intel/src/i830_quirks.c
index 1d9b681c1..285856933 100644
--- a/driver/xf86-video-intel/src/i830_quirks.c
+++ b/driver/xf86-video-intel/src/i830_quirks.c
@@ -73,7 +73,7 @@ static void i830_dmi_store_##field(void) \
int ret;\
f = fopen(DMIID_FILE(field), "r");\
if (f == NULL) {\
- xfree(i830_dmi_data[field]); i830_dmi_data[field] = NULL;\
+ free(i830_dmi_data[field]); i830_dmi_data[field] = NULL;\
return;\
}\
ret = fread(i830_dmi_data[field], 64, 1, f); \
@@ -104,11 +104,11 @@ static void i830_dmi_scan(void)
int i;
for (i = 0; i < dmi_data_max; i++) {
- i830_dmi_data[i] = xcalloc(64, sizeof(char));
+ i830_dmi_data[i] = calloc(64, sizeof(char));
if (!i830_dmi_data[i]) {
int j;
for (j = 0; j < i; j++) {
- xfree(i830_dmi_data[j]);
+ free(i830_dmi_data[j]);
i830_dmi_data[i] = NULL;
}
return;
@@ -426,5 +426,5 @@ void i830_fixup_devices(ScrnInfoPtr scrn)
for (i = 0; i < dmi_data_max; i++)
if (i830_dmi_data[i])
- xfree(i830_dmi_data[i]);
+ free(i830_dmi_data[i]);
}
diff --git a/driver/xf86-video-intel/src/i830_render.c b/driver/xf86-video-intel/src/i830_render.c
index da075d935..43f4e28b9 100644
--- a/driver/xf86-video-intel/src/i830_render.c
+++ b/driver/xf86-video-intel/src/i830_render.c
@@ -126,19 +126,18 @@ static struct blendinfo i830_blend_op[] = {
{0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE},
};
-/* The x8* formats could use MT_32BIT_X* on 855+, but since we implement
- * workarounds for 830/845 anyway, we just rely on those whether the hardware
- * could handle it for us or not.
- */
static struct formatinfo i830_tex_formats[] = {
- {PICT_a8r8g8b8, MT_32BIT_ARGB8888},
- {PICT_x8r8g8b8, MT_32BIT_ARGB8888},
- {PICT_a8b8g8r8, MT_32BIT_ABGR8888},
- {PICT_x8b8g8r8, MT_32BIT_ABGR8888},
- {PICT_r5g6b5, MT_16BIT_RGB565},
- {PICT_a1r5g5b5, MT_16BIT_ARGB1555},
- {PICT_x1r5g5b5, MT_16BIT_ARGB1555},
- {PICT_a8, MT_8BIT_A8},
+ {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8},
+ {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888},
+ {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888},
+ {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565},
+ {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555},
+ {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444},
+};
+
+static struct formatinfo i855_tex_formats[] = {
+ {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888},
+ {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888},
};
static Bool i830_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
@@ -221,61 +220,26 @@ static Bool i830_get_blend_cntl(ScrnInfoPtr scrn, int op, PicturePtr mask,
return TRUE;
}
-static Bool i830_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
- int unit)
+static uint32_t i8xx_get_card_format(intel_screen_private *intel,
+ PicturePtr picture)
{
- if (picture->repeatType > RepeatReflect) {
- intel_debug_fallback(scrn, "Unsupported picture repeat %d\n",
- picture->repeatType);
- return FALSE;
- }
+ int i;
- if (picture->filter != PictFilterNearest &&
- picture->filter != PictFilterBilinear) {
- intel_debug_fallback(scrn, "Unsupported filter 0x%x\n",
- picture->filter);
- return FALSE;
+ for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+ i++) {
+ if (i830_tex_formats[i].fmt == picture->format)
+ return i830_tex_formats[i].card_fmt;
}
- if (picture->pDrawable) {
- int w, h, i;
-
- w = picture->pDrawable->width;
- h = picture->pDrawable->height;
- if ((w > 2048) || (h > 2048)) {
- intel_debug_fallback(scrn,
- "Picture w/h too large (%dx%d)\n",
- w, h);
- return FALSE;
- }
-
- for (i = 0;
- i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
+ if (IS_I85X(intel) || IS_I865G(intel)) {
+ for (i = 0; i < sizeof(i855_tex_formats) / sizeof(i855_tex_formats[0]);
i++) {
- if (i830_tex_formats[i].fmt == picture->format)
- break;
- }
- if (i == sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]))
- {
- intel_debug_fallback(scrn, "Unsupported picture format "
- "0x%x\n",
- (int)picture->format);
- return FALSE;
+ if (i855_tex_formats[i].fmt == picture->format)
+ return i855_tex_formats[i].card_fmt;
}
}
- return TRUE;
-}
-
-static uint32_t i8xx_get_card_format(PicturePtr picture)
-{
- int i;
- for (i = 0; i < sizeof(i830_tex_formats) / sizeof(i830_tex_formats[0]);
- i++) {
- if (i830_tex_formats[i].fmt == picture->format)
- return i830_tex_formats[i].card_fmt;
- }
- FatalError("Unsupported format type %d\n", picture->format);
+ return 0;
}
static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
@@ -297,8 +261,6 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
else
texcoordtype = TEXCOORDTYPE_HOMOGENEOUS;
- format = i8xx_get_card_format(picture);
-
switch (picture->repeatType) {
case RepeatNone:
wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
@@ -331,63 +293,59 @@ static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
}
filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
- {
- if (pixmap->drawable.bitsPerPixel == 8)
- format |= MAPSURF_8BIT;
- else if (pixmap->drawable.bitsPerPixel == 16)
- format |= MAPSURF_16BIT;
- else
- format |= MAPSURF_32BIT;
-
- if (i830_pixmap_tiled(pixmap)) {
- tiling_bits = TM0S1_TILED_SURFACE;
- if (i830_get_pixmap_intel(pixmap)->tiling
- == I915_TILING_Y)
- tiling_bits |= TM0S1_TILE_WALK;
- } else
- tiling_bits = 0;
-
- ATOMIC_BATCH(10);
- OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
- LOAD_TEXTURE_MAP(unit) | 4);
- OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0);
- OUT_BATCH(((pixmap->drawable.height -
- 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width -
- 1) <<
- TM0S1_WIDTH_SHIFT) |
- format | tiling_bits);
- OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
- OUT_BATCH(filter);
- OUT_BATCH(0); /* default color */
- OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
- ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
- texcoordtype | ENABLE_ADDR_V_CNTL |
- TEXCOORD_ADDR_V_MODE(wrap_mode) |
- ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
- /* map texel stream */
- OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
- if (unit == 0)
- OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
- TEXBIND_SET1(TEXCOORDSRC_KEEP) |
- TEXBIND_SET2(TEXCOORDSRC_KEEP) |
- TEXBIND_SET3(TEXCOORDSRC_KEEP));
- else
- OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
- TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
- TEXBIND_SET2(TEXCOORDSRC_KEEP) |
- TEXBIND_SET3(TEXCOORDSRC_KEEP));
- OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
- DISABLE_TEX_STREAM_BUMP |
- ENABLE_TEX_STREAM_COORD_SET |
- TEX_STREAM_COORD_SET(unit) |
- ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit));
- ADVANCE_BATCH();
- }
+ if (i830_pixmap_tiled(pixmap)) {
+ tiling_bits = TM0S1_TILED_SURFACE;
+ if (i830_get_pixmap_intel(pixmap)->tiling
+ == I915_TILING_Y)
+ tiling_bits |= TM0S1_TILE_WALK;
+ } else
+ tiling_bits = 0;
+
+ format = i8xx_get_card_format(intel, picture);
+
+ assert(intel->in_batch_atomic);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
+ LOAD_TEXTURE_MAP(unit) | 4);
+ OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0);
+ OUT_BATCH(((pixmap->drawable.height -
+ 1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width -
+ 1) <<
+ TM0S1_WIDTH_SHIFT) |
+ format | tiling_bits);
+ OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
+ OUT_BATCH(filter);
+ OUT_BATCH(0); /* default color */
+ OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
+ ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
+ texcoordtype | ENABLE_ADDR_V_CNTL |
+ TEXCOORD_ADDR_V_MODE(wrap_mode) |
+ ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
+ /* map texel stream */
+ OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
+ if (unit == 0)
+ OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+ TEXBIND_SET1(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET3(TEXCOORDSRC_KEEP));
+ else
+ OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
+ TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
+ TEXBIND_SET2(TEXCOORDSRC_KEEP) |
+ TEXBIND_SET3(TEXCOORDSRC_KEEP));
+ OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
+ DISABLE_TEX_STREAM_BUMP |
+ ENABLE_TEX_STREAM_COORD_SET |
+ TEX_STREAM_COORD_SET(unit) |
+ ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit));
}
Bool
-i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
- PicturePtr dest_picture)
+i830_check_composite(int op,
+ PicturePtr source_picture,
+ PicturePtr mask_picture,
+ PicturePtr dest_picture,
+ int width, int height)
{
ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
uint32_t tmp1;
@@ -414,25 +372,77 @@ i830_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
}
}
- if (!i830_check_composite_texture(scrn, source_picture, 0)) {
- intel_debug_fallback(scrn, "Check Src picture texture\n");
+ if (!i830_get_dest_format(dest_picture, &tmp1)) {
+ intel_debug_fallback(scrn, "Get Color buffer format\n");
return FALSE;
}
- if (mask_picture != NULL
- && !i830_check_composite_texture(scrn, mask_picture, 1)) {
- intel_debug_fallback(scrn, "Check Mask picture texture\n");
+
+ if (width > 2048 || height > 2048) {
+ intel_debug_fallback(scrn, "Operation is too large (%d, %d)\n", width, height);
return FALSE;
}
- if (!i830_get_dest_format(dest_picture, &tmp1)) {
- intel_debug_fallback(scrn, "Get Color buffer format\n");
+ return TRUE;
+}
+
+Bool
+i830_check_composite_target(PixmapPtr pixmap)
+{
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
+ return FALSE;
+
+ if(!intel_check_pitch_3d(pixmap))
return FALSE;
- }
return TRUE;
}
Bool
+i830_check_composite_texture(ScreenPtr screen, PicturePtr picture)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ if (picture->repeatType > RepeatReflect) {
+ intel_debug_fallback(scrn, "Unsupported picture repeat %d\n",
+ picture->repeatType);
+ return FALSE;
+ }
+
+ if (picture->filter != PictFilterNearest &&
+ picture->filter != PictFilterBilinear) {
+ intel_debug_fallback(scrn, "Unsupported filter 0x%x\n",
+ picture->filter);
+ return FALSE;
+ }
+
+ if (picture->pDrawable) {
+ int w, h;
+
+ w = picture->pDrawable->width;
+ h = picture->pDrawable->height;
+ if ((w > 2048) || (h > 2048)) {
+ intel_debug_fallback(scrn,
+ "Picture w/h too large (%dx%d)\n",
+ w, h);
+ return FALSE;
+ }
+
+ /* XXX we can use the xrgb32 types if there the picture covers the clip */
+ if (!i8xx_get_card_format(intel, picture)) {
+ intel_debug_fallback(scrn, "Unsupported picture format "
+ "0x%x\n",
+ (int)picture->format);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+Bool
i830_prepare_composite(int op, PicturePtr source_picture,
PicturePtr mask_picture, PicturePtr dest_picture,
PixmapPtr source, PixmapPtr mask, PixmapPtr dest)
@@ -456,6 +466,20 @@ i830_prepare_composite(int op, PicturePtr source_picture,
if (!intel_check_pitch_3d(source))
return FALSE;
if (mask) {
+ if (mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i830_blend_op[op].src_alpha &&
+ (i830_blend_op[op].src_blend != BLENDFACTOR_ZERO)) {
+ intel_debug_fallback(scrn, "Component alpha not "
+ "supported with source alpha and "
+ "source value blending.\n");
+ return FALSE;
+ }
+ }
if (!intel_check_pitch_3d(mask))
return FALSE;
}
@@ -560,7 +584,7 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn)
IntelEmitInvarientState(scrn);
intel->last_3d = LAST_3D_RENDER;
- ATOMIC_BATCH(21);
+ assert(intel->in_batch_atomic);
if (i830_pixmap_tiled(intel->render_dest)) {
tiling_bits = BUF_3D_TILED_SURFACE;
@@ -626,8 +650,6 @@ static void i830_emit_composite_state(ScrnInfoPtr scrn)
}
OUT_BATCH(_3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt);
- ADVANCE_BATCH();
-
i830_texture_setup(intel->render_source_picture, intel->render_source, 0);
if (intel->render_mask) {
i830_texture_setup(intel->render_mask_picture,
@@ -767,8 +789,6 @@ i830_emit_composite_primitive(PixmapPtr dest,
num_floats = 3 * per_vertex;
- ATOMIC_BATCH(1 + num_floats);
-
OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1));
OUT_BATCH_F(dstX + w);
OUT_BATCH_F(dstY + h);
@@ -814,8 +834,6 @@ i830_emit_composite_primitive(PixmapPtr dest,
OUT_BATCH_F(mask_w[0]);
}
}
-
- ADVANCE_BATCH();
}
/**
diff --git a/driver/xf86-video-intel/src/i830_sdvo.c b/driver/xf86-video-intel/src/i830_sdvo.c
index 393804eaf..a9275afa3 100644
--- a/driver/xf86-video-intel/src/i830_sdvo.c
+++ b/driver/xf86-video-intel/src/i830_sdvo.c
@@ -1723,7 +1723,7 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag)
}
/* if exist origin name it will be freed in xf86OutputRename() */
- dev_priv->name = xalloc(strlen(name_prefix) + strlen(name_suffix) + 1);
+ dev_priv->name = malloc(strlen(name_prefix) + strlen(name_suffix) + 1);
strcpy (dev_priv->name, name_prefix);
strcat (dev_priv->name, name_suffix);
@@ -1740,11 +1740,11 @@ i830_sdvo_output_setup (xf86OutputPtr output, uint16_t flag)
if (output->randr_output) {
int nameLength = strlen(dev_priv->name);
RROutputPtr randr_output = output->randr_output;
- char *name = xalloc(nameLength + 1);
+ char *name = malloc(nameLength + 1);
if (name) {
if (randr_output->name != (char *) (randr_output + 1))
- xfree(randr_output->name);
+ free(randr_output->name);
randr_output->name = name;
randr_output->nameLength = nameLength;
memcpy(randr_output->name, dev_priv->name, nameLength);
@@ -1825,10 +1825,10 @@ i830_sdvo_detect(xf86OutputPtr output)
/* Check EDID in DVI-I case */
edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
if (edid_mon && !DIGITAL(edid_mon->features.input_type)) {
- xfree(edid_mon);
+ free(edid_mon);
return XF86OutputStatusDisconnected;
}
- xfree(edid_mon);
+ free(edid_mon);
}
return XF86OutputStatusConnected;
}
@@ -1898,7 +1898,7 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height,
{
DisplayModePtr mode;
- mode = xcalloc(1, sizeof(*mode));
+ mode = calloc(1, sizeof(*mode));
if (mode == NULL)
return;
@@ -2020,14 +2020,14 @@ i830_sdvo_destroy (xf86OutputPtr output)
RROutputPtr randr_output = output->randr_output;
if (randr_output->name &&
randr_output->name != (char *) (randr_output + 1))
- xfree(randr_output->name);
+ free(randr_output->name);
}
if (dev_priv->sdvo_lvds_fixed_mode)
xf86DeleteMode(&dev_priv->sdvo_lvds_fixed_mode,
dev_priv->sdvo_lvds_fixed_mode);
- xfree (intel_output);
+ free (intel_output);
}
}
diff --git a/driver/xf86-video-intel/src/i830_tv.c b/driver/xf86-video-intel/src/i830_tv.c
index 8f37f3c81..71fd7df21 100644
--- a/driver/xf86-video-intel/src/i830_tv.c
+++ b/driver/xf86-video-intel/src/i830_tv.c
@@ -1570,7 +1570,7 @@ static void
i830_tv_destroy (xf86OutputPtr output)
{
if (output->driver_private)
- xfree (output->driver_private);
+ free (output->driver_private);
}
#ifdef RANDR_12_INTERFACE
@@ -1807,16 +1807,16 @@ i830_tv_set_property(xf86OutputPtr output, Atom property,
memcpy (&atom, value->data, 4);
name = NameForAtom (atom);
- val = xalloc (strlen (name) + 1);
+ val = malloc (strlen (name) + 1);
if (!val)
return FALSE;
strcpy (val, name);
if (!i830_tv_mode_lookup (val))
{
- xfree (val);
+ free (val);
return FALSE;
}
- xfree (dev_priv->tv_format);
+ free (dev_priv->tv_format);
dev_priv->tv_format = val;
if (intel->starting || output->crtc == NULL)
diff --git a/driver/xf86-video-intel/src/i830_uxa.c b/driver/xf86-video-intel/src/i830_uxa.c
index f974e40c3..03a013728 100644
--- a/driver/xf86-video-intel/src/i830_uxa.c
+++ b/driver/xf86-video-intel/src/i830_uxa.c
@@ -36,6 +36,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "i830.h"
#include "i810_reg.h"
#include "i915_drm.h"
+#include "brw_defines.h"
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
@@ -78,7 +79,31 @@ const int I830PatternROP[16] = {
ROP_1
};
-static int uxa_pixmap_index;
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec uxa_pixmap_index;
+#else
+int uxa_pixmap_index;
+#endif
+
+static void
+ironlake_blt_workaround(ScrnInfoPtr scrn)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ /* Ironlake has a limitation that a 3D or Media command can't
+ * be the first command after a BLT, unless it's
+ * non-pipelined. Instead of trying to track it and emit a
+ * command at the right time, we just emit a dummy
+ * non-pipelined 3D instruction after each blit.
+ */
+
+ if (IS_IGDNG(intel)) {
+ BEGIN_BATCH(2);
+ OUT_BATCH(CMD_POLY_STIPPLE_OFFSET << 16);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ }
+}
Bool
i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
@@ -93,7 +118,7 @@ i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table,
bo_table[0] = intel->batch_bo;
if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) != 0) {
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
bo_table[0] = intel->batch_bo;
if (drm_intel_bufmgr_check_aperture_space(bo_table, num_bos) !=
0) {
@@ -127,14 +152,13 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
{
ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- int pitch, pitch_align;
- int size;
+ int pitch, size;
if (*tiling != I915_TILING_NONE) {
/* First check whether tiling is necessary. */
- pitch_align = intel->accel_pixmap_pitch_alignment;
- size = ROUND_TO((w * pixmap->drawable.bitsPerPixel + 7) / 8,
- pitch_align) * ALIGN (h, 2);
+ pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8;
+ pitch = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment);
+ size = pitch * ALIGN (h, 2);
if (!IS_I965G(intel)) {
/* Older hardware requires fences to be pot size
* aligned with a minimum of 1 MiB, so causes
@@ -142,6 +166,12 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
*/
if (size < 1024*1024/2)
*tiling = I915_TILING_NONE;
+
+ /* Gen 2/3 has a maximum stride for tiling of
+ * 8192 bytes.
+ */
+ if (pitch > KB(8))
+ *tiling = I915_TILING_NONE;
} else if (size <= 4096) {
/* Disable tiling beneath a page size, we will not see
* any benefit from reducing TLB misses and instead
@@ -154,29 +184,19 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
pitch = (w * pixmap->drawable.bitsPerPixel + 7) / 8;
if (pitch <= 256)
*tiling = I915_TILING_NONE;
- repeat:
- if (*tiling == I915_TILING_NONE) {
- pitch_align = intel->accel_pixmap_pitch_alignment;
- } else {
- pitch_align = 512;
- }
- *stride = ROUND_TO(pitch, pitch_align);
+ if (*tiling != I915_TILING_NONE) {
+ int aligned_h;
- if (*tiling == I915_TILING_NONE) {
- /* Round the height up so that the GPU's access to a 2x2 aligned
- * subspan doesn't address an invalid page offset beyond the
- * end of the GTT.
- */
- size = *stride * ALIGN(h, 2);
- } else {
- int aligned_h = h;
if (*tiling == I915_TILING_X)
aligned_h = ALIGN(h, 8);
else
aligned_h = ALIGN(h, 32);
- *stride = i830_get_fence_pitch(intel, *stride, *tiling);
+ *stride = i830_get_fence_pitch(intel,
+ ROUND_TO(pitch, 512),
+ *tiling);
+
/* Round the object up to the size of the fence it will live in
* if necessary. We could potentially make the kernel allocate
* a larger aperture space and just bind the subset of pages in,
@@ -184,17 +204,45 @@ i830_uxa_pixmap_compute_size(PixmapPtr pixmap,
* with drm_intel_bufmgr_check_aperture().
*/
size = i830_get_fence_size(intel, *stride * aligned_h);
- assert(size >= *stride * aligned_h);
+
+ if (size > intel->max_tiling_size)
+ *tiling = I915_TILING_NONE;
}
- if (*tiling != I915_TILING_NONE && size > intel->max_tiling_size) {
- *tiling = I915_TILING_NONE;
- goto repeat;
+ if (*tiling == I915_TILING_NONE) {
+ /* Round the height up so that the GPU's access to a 2x2 aligned
+ * subspan doesn't address an invalid page offset beyond the
+ * end of the GTT.
+ */
+ *stride = ROUND_TO(pitch, intel->accel_pixmap_pitch_alignment);
+ size = *stride * ALIGN(h, 2);
}
return size;
}
+static Bool
+i830_uxa_check_solid(DrawablePtr drawable, int alu, Pixel planemask)
+{
+ ScrnInfoPtr scrn = xf86Screens[drawable->pScreen->myNum];
+
+ if (!UXA_PM_IS_SOLID(drawable, planemask)) {
+ intel_debug_fallback(scrn, "planemask is not solid\n");
+ return FALSE;
+ }
+
+ switch (drawable->bitsPerPixel) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* Sets up hardware state for a series of solid fills.
*/
@@ -203,32 +251,14 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
{
ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- unsigned long pitch;
drm_intel_bo *bo_table[] = {
NULL, /* batch_bo */
i830_get_pixmap_bo(pixmap),
};
- if (!UXA_PM_IS_SOLID(&pixmap->drawable, planemask)) {
- intel_debug_fallback(scrn, "planemask is not solid\n");
- return FALSE;
- }
-
- if (pixmap->drawable.bitsPerPixel == 24) {
- intel_debug_fallback(scrn, "solid 24bpp unsupported!\n");
- return FALSE;
- }
-
- if (pixmap->drawable.bitsPerPixel < 8) {
- intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n");
- return FALSE;
- }
-
if (!intel_check_pitch_2d(pixmap))
return FALSE;
- pitch = i830_pixmap_pitch(pixmap);
-
if (!i830_pixmap_pitch_is_aligned(pixmap)) {
intel_debug_fallback(scrn, "pixmap pitch not aligned");
return FALSE;
@@ -248,11 +278,10 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
case 32:
/* RGB8888 */
intel->BR[13] |= ((1 << 24) | (1 << 25));
- if (pixmap->drawable.depth == 24)
- fg |= 0xff000000;
break;
}
intel->BR[16] = fg;
+
return TRUE;
}
@@ -272,6 +301,9 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
if (y2 > pixmap->drawable.height)
y2 = pixmap->drawable.height;
+ if (x2 <= x1 || y2 <= y1)
+ return;
+
pitch = i830_pixmap_pitch(pixmap);
{
@@ -299,6 +331,8 @@ static void i830_uxa_solid(PixmapPtr pixmap, int x1, int y1, int x2, int y2)
OUT_BATCH(intel->BR[16]);
ADVANCE_BATCH();
}
+
+ ironlake_blt_workaround(scrn);
}
static void i830_uxa_done_solid(PixmapPtr pixmap)
@@ -313,39 +347,57 @@ static void i830_uxa_done_solid(PixmapPtr pixmap)
* - support planemask using FULL_BLT_CMD?
*/
static Bool
-i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
- int ydir, int alu, Pixel planemask)
+i830_uxa_check_copy(PixmapPtr source, PixmapPtr dest,
+ int alu, Pixel planemask)
{
ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(source),
- i830_get_pixmap_bo(dest),
- };
+
if (!UXA_PM_IS_SOLID(&source->drawable, planemask)) {
intel_debug_fallback(scrn, "planemask is not solid");
return FALSE;
}
- if (dest->drawable.bitsPerPixel < 8) {
- intel_debug_fallback(scrn, "under 8bpp pixmaps unsupported\n");
+ if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel) {
+ intel_debug_fallback(scrn, "mixed bpp copies unsupported\n");
return FALSE;
}
-
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ switch (source->drawable.bitsPerPixel) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
return FALSE;
+ }
if (!intel_check_pitch_2d(source))
return FALSE;
if (!intel_check_pitch_2d(dest))
return FALSE;
+ return TRUE;
+}
+
+static Bool
+i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
+ int ydir, int alu, Pixel planemask)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ drm_intel_bo *bo_table[] = {
+ NULL, /* batch_bo */
+ i830_get_pixmap_bo(source),
+ i830_get_pixmap_bo(dest),
+ };
+
+ if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ return FALSE;
+
intel->render_source = source;
intel->BR[13] = I830CopyROP[alu] << 16;
-
switch (source->drawable.bitsPerPixel) {
case 8:
break;
@@ -356,6 +408,7 @@ i830_uxa_prepare_copy(PixmapPtr source, PixmapPtr dest, int xdir,
intel->BR[13] |= ((1 << 25) | (1 << 24));
break;
}
+
return TRUE;
}
@@ -416,6 +469,7 @@ i830_uxa_copy(PixmapPtr dest, int src_x1, int src_y1, int dst_x1,
ADVANCE_BATCH();
}
+ ironlake_blt_workaround(scrn);
}
static void i830_uxa_done_copy(PixmapPtr dest)
@@ -433,6 +487,10 @@ static void i830_uxa_done_copy(PixmapPtr dest)
void i830_done_composite(PixmapPtr dest)
{
ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ if (intel->vertex_flush)
+ intel->vertex_flush(intel);
i830_debug_flush(scrn);
}
@@ -518,16 +576,6 @@ Bool i830_transform_is_affine(PictTransformPtr t)
return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
}
-struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap)
-{
- return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
-}
-
-static void i830_uxa_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel)
-{
- dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel);
-}
-
dri_bo *i830_get_pixmap_bo(PixmapPtr pixmap)
{
struct intel_pixmap *intel;
@@ -547,21 +595,35 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
priv = i830_get_pixmap_intel(pixmap);
+ if (priv == NULL && bo == NULL)
+ return;
+
if (priv != NULL) {
+ if (priv->bo == bo)
+ return;
+
if (list_is_empty(&priv->batch)) {
dri_bo_unreference(priv->bo);
+ } else if (!drm_intel_bo_is_reusable(priv->bo)) {
+ dri_bo_unreference(priv->bo);
+ list_del(&priv->batch);
+ list_del(&priv->flush);
} else {
list_add(&priv->in_flight, &intel->in_flight);
priv = NULL;
}
+
+ if (intel->render_current_dest == pixmap)
+ intel->render_current_dest = NULL;
}
if (bo != NULL) {
+ uint32_t tiling;
uint32_t swizzle_mode;
int ret;
if (priv == NULL) {
- priv = xcalloc(1, sizeof (struct intel_pixmap));
+ priv = calloc(1, sizeof (struct intel_pixmap));
if (priv == NULL)
goto BAIL;
@@ -574,21 +636,24 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo)
priv->stride = i830_pixmap_pitch(pixmap);
ret = drm_intel_bo_get_tiling(bo,
- &priv->tiling,
+ &tiling,
&swizzle_mode);
if (ret != 0) {
FatalError("Couldn't get tiling on bo %p: %s\n",
bo, strerror(-ret));
}
+
+ priv->tiling = tiling;
+ priv->busy = -1;
} else {
if (priv != NULL) {
- xfree(priv);
+ free(priv);
priv = NULL;
}
}
BAIL:
- i830_uxa_set_pixmap_intel(pixmap, priv);
+ i830_set_pixmap_intel(pixmap, priv);
}
static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
@@ -600,40 +665,30 @@ static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access)
int ret;
if (!list_is_empty(&priv->batch) &&
- (access == UXA_ACCESS_RW || priv->batch_write_domain))
- intel_batch_submit(scrn);
-
- if (bo) {
- if (intel->kernel_exec_fencing) {
- if (bo->size > intel->max_gtt_map_size || !intel->have_gem) {
- ret = dri_bo_map(bo, access == UXA_ACCESS_RW);
- if (ret != 0) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: bo map failed: %s\n",
- __FUNCTION__,
- strerror(-ret));
- return FALSE;
- }
- } else {
- ret = drm_intel_gem_bo_map_gtt(bo);
- if (ret != 0) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: gtt bo map failed: %s\n",
- __FUNCTION__,
- strerror(-ret));
- return FALSE;
- }
- }
- pixmap->devPrivate.ptr = bo->virtual;
- } else {
- if (drm_intel_bo_pin(bo, 4096) != 0)
- return FALSE;
- drm_intel_gem_bo_start_gtt_access(bo, access ==
- UXA_ACCESS_RW);
- pixmap->devPrivate.ptr = intel->FbBase + bo->offset;
+ (access == UXA_ACCESS_RW || priv->batch_write))
+ intel_batch_submit(scrn, FALSE);
+
+ if (bo->size > intel->max_gtt_map_size) {
+ ret = dri_bo_map(bo, access == UXA_ACCESS_RW);
+ if (ret != 0) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map failed: %s\n",
+ __FUNCTION__,
+ strerror(-ret));
+ return FALSE;
}
- } else
- i830_wait_ring_idle(scrn);
+ } else {
+ ret = drm_intel_gem_bo_map_gtt(bo);
+ if (ret != 0) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: gtt bo map failed: %s\n",
+ __FUNCTION__,
+ strerror(-ret));
+ return FALSE;
+ }
+ }
+ pixmap->devPrivate.ptr = bo->virtual;
+ priv->busy = 0;
return TRUE;
}
@@ -648,206 +703,207 @@ static void i830_uxa_finish_access(PixmapPtr pixmap)
if (bo == intel->front_buffer->bo)
intel->need_flush = TRUE;
- if (intel->kernel_exec_fencing) {
- if (bo->size > intel->max_gtt_map_size)
- dri_bo_unmap(bo);
- else
- drm_intel_gem_bo_unmap_gtt(bo);
- pixmap->devPrivate.ptr = NULL;
- }
+ if (bo->size > intel->max_gtt_map_size)
+ dri_bo_unmap(bo);
+ else
+ drm_intel_gem_bo_unmap_gtt(bo);
+ pixmap->devPrivate.ptr = NULL;
}
-static Bool i830_bo_put_image(PixmapPtr pixmap, dri_bo *bo, char *src, int src_pitch, int w, int h)
+static Bool i830_uxa_pixmap_put_image(PixmapPtr pixmap,
+ char *src, int src_pitch,
+ int x, int y, int w, int h)
{
+ struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
int stride = i830_pixmap_pitch(pixmap);
-
- /* fill alpha channel */
- if (pixmap->drawable.depth == 24) {
- pixman_image_t *src_image, *dst_image;
-
- src_image = pixman_image_create_bits (PIXMAN_x8r8g8b8,
- w, h,
- (uint32_t *) src, src_pitch);
-
- dst_image = pixman_image_create_bits (PIXMAN_a8r8g8b8,
- w, h,
- (uint32_t *) bo->virtual, stride);
-
- if (src_image && dst_image)
- pixman_image_composite (PictOpSrc,
- src_image, NULL, dst_image,
- 0, 0,
- 0, 0,
- 0, 0,
- w, h);
-
- if (src_image)
- pixman_image_unref (src_image);
-
- if (dst_image)
- pixman_image_unref (dst_image);
-
- if (src_image == NULL || dst_image == NULL)
- return FALSE;
- } else if (src_pitch == stride) {
- memcpy (bo->virtual, src, stride * h);
- } else {
- char *dst = bo->virtual;
- int row_length = w * pixmap->drawable.bitsPerPixel/8;
+ int ret = FALSE;
+
+ if (src_pitch == stride && w == pixmap->drawable.width && priv->tiling == I915_TILING_NONE) {
+ ret = drm_intel_bo_subdata(priv->bo, y * stride, stride * h, src) == 0;
+ } else if (drm_intel_gem_bo_map_gtt(priv->bo) == 0) {
+ char *dst = priv->bo->virtual;
+ int cpp = pixmap->drawable.bitsPerPixel/8;
+ int row_length = w * cpp;
int num_rows = h;
- while (num_rows--) {
+ if (row_length == src_pitch && src_pitch == stride)
+ num_rows = 1, row_length *= h;
+ dst += y * stride + x * cpp;
+ do {
memcpy (dst, src, row_length);
src += src_pitch;
dst += stride;
- }
+ } while (--num_rows);
+ drm_intel_gem_bo_unmap_gtt(priv->bo);
+ ret = TRUE;
}
- return TRUE;
+ return ret;
}
-static Bool
-i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap,
- char *src, int src_pitch)
+static Bool i830_uxa_put_image(PixmapPtr pixmap,
+ int x, int y,
+ int w, int h,
+ char *src, int src_pitch)
{
- ScrnInfoPtr scrn = xf86Screens[pixmap->drawable.pScreen->myNum];
- intel_screen_private *intel = intel_get_screen_private(scrn);
struct intel_pixmap *priv;
- dri_bo *bo;
- uint32_t tiling = I915_TILING_X;
- int stride;
- int w = pixmap->drawable.width;
- int h = pixmap->drawable.height;
- Bool ret;
priv = i830_get_pixmap_intel(pixmap);
+ if (!intel_pixmap_is_busy(priv)) {
+ /* bo is not busy so can be replaced without a stall, upload in-place. */
+ return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, x, y, w, h);
+ } else {
+ ScreenPtr screen = pixmap->drawable.pScreen;
+
+ if (x == 0 && y == 0 &&
+ w == pixmap->drawable.width &&
+ h == pixmap->drawable.height)
+ {
+ intel_screen_private *intel = intel_get_screen_private(xf86Screens[screen->myNum]);
+ uint32_t tiling = priv->tiling;
+ int size, stride;
+ dri_bo *bo;
+
+ /* Replace busy bo. */
+ size = i830_uxa_pixmap_compute_size (pixmap, w, h,
+ &tiling, &stride);
+ if (size > intel->max_gtt_map_size)
+ return FALSE;
- if (priv->batch_read_domains || drm_intel_bo_busy(priv->bo)) {
- unsigned int size;
+ bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
+ if (bo == NULL)
+ return FALSE;
- size = i830_uxa_pixmap_compute_size (pixmap, w, h,
- &tiling, &stride);
- if (size > intel->max_gtt_map_size)
- return FALSE;
+ if (tiling != I915_TILING_NONE)
+ drm_intel_bo_set_tiling(bo, &tiling, stride);
- bo = drm_intel_bo_alloc(intel->bufmgr, "pixmap", size, 0);
- if (bo == NULL)
- return FALSE;
+ screen->ModifyPixmapHeader(pixmap,
+ w, h,
+ 0, 0,
+ stride, NULL);
+ i830_set_pixmap_bo(pixmap, bo);
+ dri_bo_unreference(bo);
- if (tiling != I915_TILING_NONE)
- drm_intel_bo_set_tiling(bo, &tiling, stride);
+ return i830_uxa_pixmap_put_image(pixmap, src, src_pitch, 0, 0, w, h);
+ }
+ else
+ {
+ PixmapPtr scratch;
+ Bool ret;
+
+ /* Upload to a linear buffer and queue a blit. */
+ scratch = (*screen->CreatePixmap)(screen, w, h,
+ pixmap->drawable.depth,
+ UXA_CREATE_PIXMAP_FOR_MAP);
+ if (!scratch)
+ return FALSE;
- dri_bo_unreference(priv->bo);
- priv->bo = bo;
- priv->tiling = tiling;
- priv->batch_read_domains = priv->batch_write_domain = 0;
- priv->flush_read_domains = priv->flush_write_domain = 0;
- list_del(&priv->batch);
- list_del(&priv->flush);
- pixmap->drawable.pScreen->ModifyPixmapHeader(pixmap,
- w, h,
- 0, 0,
- stride, NULL);
- } else {
- bo = priv->bo;
- stride = i830_pixmap_pitch(pixmap);
- }
+ ret = i830_uxa_pixmap_put_image(scratch, src, src_pitch, 0, 0, w, h);
+ if (ret) {
+ GCPtr gc = GetScratchGC(pixmap->drawable.depth, screen);
+ if (gc) {
+ ValidateGC(&pixmap->drawable, gc);
- if (drm_intel_gem_bo_map_gtt(bo)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: bo map failed\n", __FUNCTION__);
- return FALSE;
+ (*gc->ops->CopyArea)(&scratch->drawable,
+ &pixmap->drawable,
+ gc, 0, 0, w, h, x, y);
+
+ FreeScratchGC(gc);
+ } else
+ ret = FALSE;
+ }
+
+ (*screen->DestroyPixmap)(scratch);
+ return ret;
+ }
}
+}
+
+static Bool i830_uxa_pixmap_get_image(PixmapPtr pixmap,
+ int x, int y, int w, int h,
+ char *dst, int dst_pitch)
+{
+ struct intel_pixmap *priv = i830_get_pixmap_intel(pixmap);
+ int stride = i830_pixmap_pitch(pixmap);
- ret = i830_bo_put_image(pixmap, bo, src, src_pitch, w, h);
+ if (dst_pitch == stride && w == pixmap->drawable.width) {
+ return drm_intel_bo_get_subdata(priv->bo, y * stride, stride * h, dst) == 0;
+ } else {
+ char *src;
+ int cpp;
- drm_intel_gem_bo_unmap_gtt(bo);
+ if (drm_intel_bo_map(priv->bo, FALSE))
+ return FALSE;
- return ret;
+ cpp = pixmap->drawable.bitsPerPixel/8;
+ src = (char *) priv->bo->virtual + y * stride + x * cpp;
+ w *= cpp;
+ do {
+ memcpy(dst, src, w);
+ src += stride;
+ dst += dst_pitch;
+ } while (--h);
+
+ drm_intel_bo_unmap(priv->bo);
+
+ return TRUE;
+ }
}
-static Bool i830_uxa_put_image(PixmapPtr pixmap,
+static Bool i830_uxa_get_image(PixmapPtr pixmap,
int x, int y,
int w, int h,
- char *src, int src_pitch)
+ char *dst, int dst_pitch)
{
- ScreenPtr screen = pixmap->drawable.pScreen;
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
- PixmapPtr scratch;
struct intel_pixmap *priv;
- GCPtr gc;
+ PixmapPtr scratch = NULL;
Bool ret;
- if (x == 0 && y == 0 &&
- w == pixmap->drawable.width &&
- h == pixmap->drawable.height)
- {
- /* Replace GPU hot bo with new CPU data. */
- return i830_uxa_pixmap_swap_bo_with_image(pixmap,
- src, src_pitch);
- }
+ /* The presumption is that we wish to keep the target hot, so
+ * copy to a new bo and move that to the CPU in preference to
+ * causing ping-pong of the original.
+ *
+ * Also the gpu is much faster at detiling.
+ */
priv = i830_get_pixmap_intel(pixmap);
- if (priv->batch_read_domains ||
- drm_intel_bo_busy(priv->bo) ||
- pixmap->drawable.depth == 24) {
- dri_bo *bo;
-
- /* Partial replacement, copy incoming image to a bo and blit. */
- scratch = (*screen->CreatePixmap)(screen, w, h,
- pixmap->drawable.depth,
- UXA_CREATE_PIXMAP_FOR_MAP);
+ if (intel_pixmap_is_busy(priv) || priv->tiling != I915_TILING_NONE) {
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ GCPtr gc;
+
+ /* Copy to a linear buffer and pull. */
+ scratch = screen->CreatePixmap(screen, w, h,
+ pixmap->drawable.depth,
+ INTEL_CREATE_PIXMAP_TILING_NONE);
if (!scratch)
return FALSE;
- bo = i830_get_pixmap_bo(scratch);
- if (drm_intel_gem_bo_map_gtt(bo)) {
- (*screen->DestroyPixmap) (scratch);
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: bo map failed\n", __FUNCTION__);
+ gc = GetScratchGC(pixmap->drawable.depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(scratch);
return FALSE;
}
- ret = i830_bo_put_image(scratch, bo, src, src_pitch, w, h);
+ ValidateGC(&pixmap->drawable, gc);
- drm_intel_gem_bo_unmap_gtt(bo);
+ gc->ops->CopyArea(&pixmap->drawable,
+ &scratch->drawable,
+ gc, x, y, w, h, 0, 0);
- if (ret) {
- gc = GetScratchGC(pixmap->drawable.depth, screen);
- if (gc) {
- ValidateGC(&pixmap->drawable, gc);
+ FreeScratchGC(gc);
- (*gc->ops->CopyArea)(&scratch->drawable,
- &pixmap->drawable,
- gc, 0, 0, w, h, x, y);
+ intel_batch_submit(xf86Screens[screen->myNum], FALSE);
- FreeScratchGC(gc);
- } else
- ret = FALSE;
- }
-
- (*screen->DestroyPixmap)(scratch);
- } else {
- /* bo is not busy so can be mapped without a stall, upload in-place. */
- if (drm_intel_gem_bo_map_gtt(priv->bo)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: bo map failed\n", __FUNCTION__);
- return FALSE;
- }
+ x = y = 0;
+ pixmap = scratch;
+ }
- pixman_blt((uint32_t *)src, priv->bo->virtual,
- src_pitch / sizeof(uint32_t),
- pixmap->devKind / sizeof(uint32_t),
- pixmap->drawable.bitsPerPixel,
- pixmap->drawable.bitsPerPixel,
- 0, 0,
- x, y,
- w, h);
+ ret = i830_uxa_pixmap_get_image(pixmap, x, y, w, h, dst, dst_pitch);
- drm_intel_gem_bo_unmap_gtt(priv->bo);
- ret = TRUE;
- }
+ if (scratch)
+ scratch->drawable.pScreen->DestroyPixmap(scratch);
return ret;
+
}
void i830_uxa_block_handler(ScreenPtr screen)
@@ -883,6 +939,9 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
if (w > 32767 || h > 32767)
return NullPixmap;
+ if (depth == 1)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+
if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
return fbCreatePixmap(screen, w, h, depth, usage);
@@ -900,7 +959,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
tiling = I915_TILING_X;
if (usage == INTEL_CREATE_PIXMAP_TILING_Y)
tiling = I915_TILING_Y;
- if (usage == UXA_CREATE_PIXMAP_FOR_MAP)
+ if (usage == UXA_CREATE_PIXMAP_FOR_MAP || usage == INTEL_CREATE_PIXMAP_TILING_NONE)
tiling = I915_TILING_NONE;
if (tiling != I915_TILING_NONE) {
@@ -911,21 +970,16 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
}
size = i830_uxa_pixmap_compute_size(pixmap, w, h, &tiling, &stride);
- /* Fail very large allocations on 32-bit systems. Large BOs will
- * tend to hit SW fallbacks frequently, and also will tend to fail
- * to successfully map when doing SW fallbacks because we overcommit
- * address space for BO access.
- *
- * Note that size should fit in 32 bits. We throw out >32767x32767x4,
- * and pitch alignment could get us up to 32768x32767x4.
+ /* Fail very large allocations. Large BOs will tend to hit SW fallbacks
+ * frequently, and also will tend to fail to successfully map when doing
+ * SW fallbacks because we overcommit address space for BO access.
*/
- if (sizeof(unsigned long) == 4 &&
- size > (unsigned int)(1024 * 1024 * 1024)) {
+ if (size > intel->max_bo_size || stride >= KB(32)) {
fbDestroyPixmap(pixmap);
- return NullPixmap;
+ return fbCreatePixmap(screen, w, h, depth, usage);
}
- /* Perform a premilinary search for an in-flight bo */
+ /* Perform a preliminary search for an in-flight bo */
if (usage != UXA_CREATE_PIXMAP_FOR_MAP) {
int aligned_h;
@@ -939,52 +993,63 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth,
list_foreach_entry(priv, struct intel_pixmap,
&intel->in_flight,
in_flight) {
- if (priv->tiling == tiling &&
- priv->stride >= stride &&
- priv->bo->size >= priv->stride * aligned_h) {
- list_del(&priv->in_flight);
- screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
- i830_uxa_set_pixmap_intel(pixmap, priv);
- return pixmap;
+ if (priv->tiling != tiling)
+ continue;
+
+ if (tiling == I915_TILING_NONE) {
+ if (priv->bo->size < size)
+ continue;
+
+ priv->stride = stride;
+ } else {
+ if (priv->stride < stride ||
+ priv->bo->size < priv->stride * aligned_h)
+ continue;
+
+ stride = priv->stride;
}
+
+ list_del(&priv->in_flight);
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
+ i830_set_pixmap_intel(pixmap, priv);
+ return pixmap;
}
}
- priv = xcalloc(1, sizeof (struct intel_pixmap));
+ priv = calloc(1, sizeof (struct intel_pixmap));
if (priv == NULL) {
fbDestroyPixmap(pixmap);
- if (errno == EFBIG)
- return fbCreatePixmap(screen, w, h, depth, usage);
return NullPixmap;
}
- if (usage == UXA_CREATE_PIXMAP_FOR_MAP)
+ if (usage == UXA_CREATE_PIXMAP_FOR_MAP) {
+ priv->busy = 0;
priv->bo = drm_intel_bo_alloc(intel->bufmgr,
"pixmap", size, 0);
- else
+ } else {
+ priv->busy = -1;
priv->bo = drm_intel_bo_alloc_for_render(intel->bufmgr,
"pixmap",
size, 0);
+ }
if (!priv->bo) {
- xfree(priv);
+ free(priv);
fbDestroyPixmap(pixmap);
if (errno == EFBIG)
return fbCreatePixmap(screen, w, h, depth, usage);
return NullPixmap;
}
+ if (tiling != I915_TILING_NONE)
+ drm_intel_bo_set_tiling(priv->bo, &tiling, stride);
priv->stride = stride;
priv->tiling = tiling;
- if (priv->tiling != I915_TILING_NONE)
- drm_intel_bo_set_tiling(priv->bo,
- &priv->tiling,
- stride);
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
list_init(&priv->batch);
list_init(&priv->flush);
- i830_uxa_set_pixmap_intel(pixmap, priv);
+ i830_set_pixmap_intel(pixmap, priv);
}
return pixmap;
@@ -1008,6 +1073,7 @@ void i830_uxa_create_screen_resources(ScreenPtr screen)
if (bo != NULL) {
PixmapPtr pixmap = screen->GetScreenPixmap(screen);
i830_set_pixmap_bo(pixmap, bo);
+ i830_get_pixmap_intel(pixmap)->busy = 1;
}
}
@@ -1016,7 +1082,11 @@ Bool i830_uxa_init(ScreenPtr screen)
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&uxa_pixmap_index, PRIVATE_PIXMAP, 0))
+#else
if (!dixRequestPrivate(&uxa_pixmap_index, 0))
+#endif
return FALSE;
intel->uxa_driver = uxa_driver_alloc();
@@ -1029,12 +1099,21 @@ Bool i830_uxa_init(ScreenPtr screen)
intel->uxa_driver->uxa_major = 1;
intel->uxa_driver->uxa_minor = 0;
+ intel->render_current_dest = NULL;
+ intel->prim_offset = 0;
+ intel->vertex_count = 0;
+ intel->floats_per_vertex = 0;
+ intel->last_floats_per_vertex = 0;
+ intel->vertex_bo = NULL;
+
/* Solid fill */
+ intel->uxa_driver->check_solid = i830_uxa_check_solid;
intel->uxa_driver->prepare_solid = i830_uxa_prepare_solid;
intel->uxa_driver->solid = i830_uxa_solid;
intel->uxa_driver->done_solid = i830_uxa_done_solid;
/* Copy */
+ intel->uxa_driver->check_copy = i830_uxa_check_copy;
intel->uxa_driver->prepare_copy = i830_uxa_prepare_copy;
intel->uxa_driver->copy = i830_uxa_copy;
intel->uxa_driver->done_copy = i830_uxa_done_copy;
@@ -1042,17 +1121,22 @@ Bool i830_uxa_init(ScreenPtr screen)
/* Composite */
if (!IS_I9XX(intel)) {
intel->uxa_driver->check_composite = i830_check_composite;
+ intel->uxa_driver->check_composite_target = i830_check_composite_target;
+ intel->uxa_driver->check_composite_texture = i830_check_composite_texture;
intel->uxa_driver->prepare_composite = i830_prepare_composite;
intel->uxa_driver->composite = i830_composite;
intel->uxa_driver->done_composite = i830_done_composite;
} else if (IS_I915G(intel) || IS_I915GM(intel) ||
IS_I945G(intel) || IS_I945GM(intel) || IS_G33CLASS(intel)) {
intel->uxa_driver->check_composite = i915_check_composite;
+ intel->uxa_driver->check_composite_target = i915_check_composite_target;
+ intel->uxa_driver->check_composite_texture = i915_check_composite_texture;
intel->uxa_driver->prepare_composite = i915_prepare_composite;
intel->uxa_driver->composite = i915_composite;
intel->uxa_driver->done_composite = i830_done_composite;
} else {
intel->uxa_driver->check_composite = i965_check_composite;
+ intel->uxa_driver->check_composite_texture = i965_check_composite_texture;
intel->uxa_driver->prepare_composite = i965_prepare_composite;
intel->uxa_driver->composite = i965_composite;
intel->uxa_driver->done_composite = i830_done_composite;
@@ -1060,21 +1144,22 @@ Bool i830_uxa_init(ScreenPtr screen)
/* PutImage */
intel->uxa_driver->put_image = i830_uxa_put_image;
+ intel->uxa_driver->get_image = i830_uxa_get_image;
intel->uxa_driver->prepare_access = i830_uxa_prepare_access;
intel->uxa_driver->finish_access = i830_uxa_finish_access;
intel->uxa_driver->pixmap_is_offscreen = i830_uxa_pixmap_is_offscreen;
+ screen->CreatePixmap = i830_uxa_create_pixmap;
+ screen->DestroyPixmap = i830_uxa_destroy_pixmap;
+
if (!uxa_driver_init(screen, intel->uxa_driver)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"UXA initialization failed\n");
- xfree(intel->uxa_driver);
+ free(intel->uxa_driver);
return FALSE;
}
- screen->CreatePixmap = i830_uxa_create_pixmap;
- screen->DestroyPixmap = i830_uxa_destroy_pixmap;
-
uxa_set_fallback_debug(screen, intel->fallback_debug);
return TRUE;
diff --git a/driver/xf86-video-intel/src/i830_video.c b/driver/xf86-video-intel/src/i830_video.c
index 23163684d..7aa16bb6d 100644
--- a/driver/xf86-video-intel/src/i830_video.c
+++ b/driver/xf86-video-intel/src/i830_video.c
@@ -557,7 +557,7 @@ void I830InitVideo(ScreenPtr screen)
* adaptors.
*/
newAdaptors =
- xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+ malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
if (newAdaptors == NULL)
return;
@@ -574,8 +574,7 @@ void I830InitVideo(ScreenPtr screen)
/* Set up textured video if we can do it at this depth and we are on
* supported hardware.
*/
- if (scrn->bitsPerPixel >= 16 && (IS_I9XX(intel) || IS_I965G(intel)) &&
- !(!IS_I965G(intel) && scrn->displayWidth > 2048)) {
+ if (scrn->bitsPerPixel >= 16 && (IS_I9XX(intel) || IS_I965G(intel))) {
texturedAdaptor = I830SetupImageVideoTextured(screen);
if (texturedAdaptor != NULL) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
@@ -619,7 +618,7 @@ void I830InitVideo(ScreenPtr screen)
if (texturedAdaptor)
intel_xvmc_adaptor_init(screen);
#endif
- xfree(adaptors);
+ free(adaptors);
}
static void
@@ -818,7 +817,7 @@ static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr screen)
OVERLAY_DEBUG("I830SetupImageVideoOverlay\n");
- if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+ if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
sizeof(intel_adaptor_private) + sizeof(DevUnion))))
return NULL;
@@ -950,16 +949,16 @@ static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr screen)
nAttributes = NUM_TEXTURED_ATTRIBUTES;
- adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec));
- adaptor_privs = xcalloc(nports, sizeof(intel_adaptor_private));
- devUnions = xcalloc(nports, sizeof(DevUnion));
- attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec));
+ adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
+ adaptor_privs = calloc(nports, sizeof(intel_adaptor_private));
+ devUnions = calloc(nports, sizeof(DevUnion));
+ attrs = calloc(nAttributes, sizeof(XF86AttributeRec));
if (adapt == NULL || adaptor_privs == NULL || devUnions == NULL ||
attrs == NULL) {
- xfree(adapt);
- xfree(adaptor_privs);
- xfree(devUnions);
- xfree(attrs);
+ free(adapt);
+ free(adaptor_privs);
+ free(devUnions);
+ free(attrs);
return NULL;
}
diff --git a/driver/xf86-video-intel/src/i915_3d.c b/driver/xf86-video-intel/src/i915_3d.c
index 517c6851b..906043b16 100644
--- a/driver/xf86-video-intel/src/i915_3d.c
+++ b/driver/xf86-video-intel/src/i915_3d.c
@@ -38,7 +38,7 @@ void I915EmitInvarientState(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- ATOMIC_BATCH(24);
+ assert(intel->in_batch_atomic);
OUT_BATCH(_3DSTATE_AA_CMD |
AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -85,8 +85,13 @@ void I915EmitInvarientState(ScrnInfoPtr scrn)
ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) |
ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff));
- OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 0);
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | I1_LOAD_S(4) | I1_LOAD_S(5) | 2);
OUT_BATCH(0x00000000); /* Disable texture coordinate wrap-shortest */
+ OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) |
+ S4_LINE_WIDTH_ONE |
+ S4_CULLMODE_NONE |
+ S4_VFMT_XY);
+ OUT_BATCH(0x00000000); /* Stencil. */
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
@@ -104,6 +109,4 @@ void I915EmitInvarientState(ScrnInfoPtr scrn)
OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE |
0);
OUT_BATCH(MI_NOOP);
-
- ADVANCE_BATCH();
}
diff --git a/driver/xf86-video-intel/src/i915_3d.h b/driver/xf86-video-intel/src/i915_3d.h
index f85780aad..04531f332 100644
--- a/driver/xf86-video-intel/src/i915_3d.h
+++ b/driver/xf86-video-intel/src/i915_3d.h
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 4 -*- */
/*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2006,2010 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,9 +23,213 @@
*
* Authors:
* Eric Anholt <eric@anholt.net>
+ * Chris Wilson <chris@chris-wilson.co.uk>
*
*/
+/* Each instruction is 3 dwords long, though most don't require all
+ * this space. Maximum of 123 instructions. Smaller maxes per insn
+ * type.
+ */
+#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16))
+
+#define REG_TYPE_R 0 /* temporary regs, no need to
+ * dcl, must be written before
+ * read -- Preserved between
+ * phases.
+ */
+#define REG_TYPE_T 1 /* Interpolated values, must be
+ * dcl'ed before use.
+ *
+ * 0..7: texture coord,
+ * 8: diffuse spec,
+ * 9: specular color,
+ * 10: fog parameter in w.
+ */
+#define REG_TYPE_CONST 2 /* Restriction: only one const
+ * can be referenced per
+ * instruction, though it may be
+ * selected for multiple inputs.
+ * Constants not initialized
+ * default to zero.
+ */
+#define REG_TYPE_S 3 /* sampler */
+#define REG_TYPE_OC 4 /* output color (rgba) */
+#define REG_TYPE_OD 5 /* output depth (w), xyz are
+ * temporaries. If not written,
+ * interpolated depth is used?
+ */
+#define REG_TYPE_U 6 /* unpreserved temporaries */
+#define REG_TYPE_MASK 0x7
+#define REG_TYPE_SHIFT 4
+#define REG_NR_MASK 0xf
+
+/* REG_TYPE_T:
+*/
+#define T_TEX0 0
+#define T_TEX1 1
+#define T_TEX2 2
+#define T_TEX3 3
+#define T_TEX4 4
+#define T_TEX5 5
+#define T_TEX6 6
+#define T_TEX7 7
+#define T_DIFFUSE 8
+#define T_SPECULAR 9
+#define T_FOG_W 10 /* interpolated fog is in W coord */
+
+/* Arithmetic instructions */
+
+/* .replicate_swizzle == selection and replication of a particular
+ * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww
+ */
+#define A0_NOP (0x0<<24) /* no operation */
+#define A0_ADD (0x1<<24) /* dst = src0 + src1 */
+#define A0_MOV (0x2<<24) /* dst = src0 */
+#define A0_MUL (0x3<<24) /* dst = src0 * src1 */
+#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */
+#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */
+#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */
+#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */
+#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */
+#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */
+#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */
+#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */
+#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */
+#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */
+#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */
+#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */
+#define A0_FLR (0x10<<24) /* dst = floor(src0) */
+#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */
+#define A0_TRC (0x12<<24) /* dst = int(src0) */
+#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */
+#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */
+#define A0_DEST_SATURATE (1<<22)
+#define A0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+#define A0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define A0_DEST_CHANNEL_X (1<<10)
+#define A0_DEST_CHANNEL_Y (2<<10)
+#define A0_DEST_CHANNEL_Z (4<<10)
+#define A0_DEST_CHANNEL_W (8<<10)
+#define A0_DEST_CHANNEL_ALL (0xf<<10)
+#define A0_DEST_CHANNEL_SHIFT 10
+#define A0_SRC0_TYPE_SHIFT 7
+#define A0_SRC0_NR_SHIFT 2
+
+#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y)
+#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z)
+
+#define SRC_X 0
+#define SRC_Y 1
+#define SRC_Z 2
+#define SRC_W 3
+#define SRC_ZERO 4
+#define SRC_ONE 5
+
+#define A1_SRC0_CHANNEL_X_NEGATE (1<<31)
+#define A1_SRC0_CHANNEL_X_SHIFT 28
+#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27)
+#define A1_SRC0_CHANNEL_Y_SHIFT 24
+#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23)
+#define A1_SRC0_CHANNEL_Z_SHIFT 20
+#define A1_SRC0_CHANNEL_W_NEGATE (1<<19)
+#define A1_SRC0_CHANNEL_W_SHIFT 16
+#define A1_SRC1_TYPE_SHIFT 13
+#define A1_SRC1_NR_SHIFT 8
+#define A1_SRC1_CHANNEL_X_NEGATE (1<<7)
+#define A1_SRC1_CHANNEL_X_SHIFT 4
+#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3)
+#define A1_SRC1_CHANNEL_Y_SHIFT 0
+
+#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31)
+#define A2_SRC1_CHANNEL_Z_SHIFT 28
+#define A2_SRC1_CHANNEL_W_NEGATE (1<<27)
+#define A2_SRC1_CHANNEL_W_SHIFT 24
+#define A2_SRC2_TYPE_SHIFT 21
+#define A2_SRC2_NR_SHIFT 16
+#define A2_SRC2_CHANNEL_X_NEGATE (1<<15)
+#define A2_SRC2_CHANNEL_X_SHIFT 12
+#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11)
+#define A2_SRC2_CHANNEL_Y_SHIFT 8
+#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7)
+#define A2_SRC2_CHANNEL_Z_SHIFT 4
+#define A2_SRC2_CHANNEL_W_NEGATE (1<<3)
+#define A2_SRC2_CHANNEL_W_SHIFT 0
+
+/* Texture instructions */
+#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared
+ * sampler and address, and output
+ * filtered texel data to destination
+ * register */
+#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a
+ * perspective divide of the texture
+ * coordinate .xyz values by .w before
+ * sampling. */
+#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the
+ * computed LOD by w. Only S4.6 two's
+ * comp is used. This implies that a
+ * float to fixed conversion is
+ * done. */
+#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling
+ * operation. Simply kills the pixel
+ * if any channel of the address
+ * register is < 0.0. */
+#define T0_DEST_TYPE_SHIFT 19
+/* Allow: R, OC, OD, U */
+/* Note: U (unpreserved) regs do not retain their values between
+ * phases (cannot be used for feedback)
+ *
+ * Note: oC and OD registers can only be used as the destination of a
+ * texture instruction once per phase (this is an implementation
+ * restriction).
+ */
+#define T0_DEST_NR_SHIFT 14
+/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */
+#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */
+#define T0_SAMPLER_NR_MASK (0xf<<0)
+
+#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */
+/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */
+#define T1_ADDRESS_REG_NR_SHIFT 17
+#define T2_MBZ 0
+
+/* Declaration instructions */
+#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib)
+ * register or an s (sampler)
+ * register. */
+#define D0_SAMPLE_TYPE_SHIFT 22
+#define D0_SAMPLE_TYPE_2D (0x0<<22)
+#define D0_SAMPLE_TYPE_CUBE (0x1<<22)
+#define D0_SAMPLE_TYPE_VOLUME (0x2<<22)
+#define D0_SAMPLE_TYPE_MASK (0x3<<22)
+
+#define D0_TYPE_SHIFT 19
+/* Allow: T, S */
+#define D0_NR_SHIFT 14
+/* Allow T: 0..10, S: 0..15 */
+#define D0_CHANNEL_X (1<<10)
+#define D0_CHANNEL_Y (2<<10)
+#define D0_CHANNEL_Z (4<<10)
+#define D0_CHANNEL_W (8<<10)
+#define D0_CHANNEL_ALL (0xf<<10)
+#define D0_CHANNEL_NONE (0<<10)
+
+#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y)
+#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z)
+
+/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse
+ * or specular declarations.
+ *
+ * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw)
+ *
+ * Must be zero for S (sampler) dcls
+ */
+#define D1_MBZ 0
+#define D2_MBZ 0
+
+
/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic
* operations
*/
@@ -38,130 +242,101 @@
#define MASK_SATURATE 0x10
/* Temporary, undeclared regs. Preserved between phases */
-#define FS_R0 ((REG_TYPE_R << 8) | 0)
-#define FS_R1 ((REG_TYPE_R << 8) | 1)
-#define FS_R2 ((REG_TYPE_R << 8) | 2)
-#define FS_R3 ((REG_TYPE_R << 8) | 3)
+#define FS_R0 ((REG_TYPE_R << REG_TYPE_SHIFT) | 0)
+#define FS_R1 ((REG_TYPE_R << REG_TYPE_SHIFT) | 1)
+#define FS_R2 ((REG_TYPE_R << REG_TYPE_SHIFT) | 2)
+#define FS_R3 ((REG_TYPE_R << REG_TYPE_SHIFT) | 3)
/* Texture coordinate regs. Must be declared. */
-#define FS_T0 ((REG_TYPE_T << 8) | 0)
-#define FS_T1 ((REG_TYPE_T << 8) | 1)
-#define FS_T2 ((REG_TYPE_T << 8) | 2)
-#define FS_T3 ((REG_TYPE_T << 8) | 3)
-#define FS_T4 ((REG_TYPE_T << 8) | 4)
-#define FS_T5 ((REG_TYPE_T << 8) | 5)
-#define FS_T6 ((REG_TYPE_T << 8) | 6)
-#define FS_T7 ((REG_TYPE_T << 8) | 7)
-#define FS_T8 ((REG_TYPE_T << 8) | 8)
-#define FS_T9 ((REG_TYPE_T << 8) | 9)
-#define FS_T10 ((REG_TYPE_T << 8) | 10)
+#define FS_T0 ((REG_TYPE_T << REG_TYPE_SHIFT) | 0)
+#define FS_T1 ((REG_TYPE_T << REG_TYPE_SHIFT) | 1)
+#define FS_T2 ((REG_TYPE_T << REG_TYPE_SHIFT) | 2)
+#define FS_T3 ((REG_TYPE_T << REG_TYPE_SHIFT) | 3)
+#define FS_T4 ((REG_TYPE_T << REG_TYPE_SHIFT) | 4)
+#define FS_T5 ((REG_TYPE_T << REG_TYPE_SHIFT) | 5)
+#define FS_T6 ((REG_TYPE_T << REG_TYPE_SHIFT) | 6)
+#define FS_T7 ((REG_TYPE_T << REG_TYPE_SHIFT) | 7)
+#define FS_T8 ((REG_TYPE_T << REG_TYPE_SHIFT) | 8)
+#define FS_T9 ((REG_TYPE_T << REG_TYPE_SHIFT) | 9)
+#define FS_T10 ((REG_TYPE_T << REG_TYPE_SHIFT) | 10)
/* Constant values */
-#define FS_C0 ((REG_TYPE_CONST << 8) | 0)
-#define FS_C1 ((REG_TYPE_CONST << 8) | 1)
-#define FS_C2 ((REG_TYPE_CONST << 8) | 2)
-#define FS_C3 ((REG_TYPE_CONST << 8) | 3)
-#define FS_C4 ((REG_TYPE_CONST << 8) | 4)
-#define FS_C5 ((REG_TYPE_CONST << 8) | 5)
-#define FS_C6 ((REG_TYPE_CONST << 8) | 6)
-#define FS_C7 ((REG_TYPE_CONST << 8) | 7)
+#define FS_C0 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 0)
+#define FS_C1 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 1)
+#define FS_C2 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 2)
+#define FS_C3 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 3)
+#define FS_C4 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 4)
+#define FS_C5 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 5)
+#define FS_C6 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 6)
+#define FS_C7 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 7)
/* Sampler regs */
-#define FS_S0 ((REG_TYPE_S << 8) | 0)
-#define FS_S1 ((REG_TYPE_S << 8) | 1)
-#define FS_S2 ((REG_TYPE_S << 8) | 2)
-#define FS_S3 ((REG_TYPE_S << 8) | 3)
+#define FS_S0 ((REG_TYPE_S << REG_TYPE_SHIFT) | 0)
+#define FS_S1 ((REG_TYPE_S << REG_TYPE_SHIFT) | 1)
+#define FS_S2 ((REG_TYPE_S << REG_TYPE_SHIFT) | 2)
+#define FS_S3 ((REG_TYPE_S << REG_TYPE_SHIFT) | 3)
/* Output color */
-#define FS_OC ((REG_TYPE_OC << 8) | 0)
+#define FS_OC ((REG_TYPE_OC << REG_TYPE_SHIFT) | 0)
/* Output depth */
-#define FS_OD ((REG_TYPE_OD << 8) | 0)
+#define FS_OD ((REG_TYPE_OD << REG_TYPE_SHIFT) | 0)
/* Unpreserved temporary regs */
-#define FS_U0 ((REG_TYPE_U << 8) | 0)
-#define FS_U1 ((REG_TYPE_U << 8) | 1)
-#define FS_U2 ((REG_TYPE_U << 8) | 2)
-#define FS_U3 ((REG_TYPE_U << 8) | 3)
-
-#define REG_TYPE(reg) ((reg) >> 8)
-#define REG_NR(reg) ((reg) & 0xff)
-
-struct i915_fs_op {
- uint32_t ui[3];
+#define FS_U0 ((REG_TYPE_U << REG_TYPE_SHIFT) | 0)
+#define FS_U1 ((REG_TYPE_U << REG_TYPE_SHIFT) | 1)
+#define FS_U2 ((REG_TYPE_U << REG_TYPE_SHIFT) | 2)
+#define FS_U3 ((REG_TYPE_U << REG_TYPE_SHIFT) | 3)
+
+#define X_CHANNEL_SHIFT (REG_TYPE_SHIFT + 3)
+#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 4)
+#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 4)
+#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 4)
+
+#define REG_CHANNEL_MASK 0xf
+
+#define REG_NR(reg) ((reg) & REG_NR_MASK)
+#define REG_TYPE(reg) (((reg) >> REG_TYPE_SHIFT) & REG_TYPE_MASK)
+#define REG_X(reg) (((reg) >> X_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_Y(reg) (((reg) >> Y_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_Z(reg) (((reg) >> Z_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+#define REG_W(reg) (((reg) >> W_CHANNEL_SHIFT) & REG_CHANNEL_MASK)
+
+enum i915_fs_channel {
+ X_CHANNEL_VAL = 0,
+ Y_CHANNEL_VAL,
+ Z_CHANNEL_VAL,
+ W_CHANNEL_VAL,
+ ZERO_CHANNEL_VAL,
+ ONE_CHANNEL_VAL,
+
+ NEG_X_CHANNEL_VAL = X_CHANNEL_VAL | 0x8,
+ NEG_Y_CHANNEL_VAL = Y_CHANNEL_VAL | 0x8,
+ NEG_Z_CHANNEL_VAL = Z_CHANNEL_VAL | 0x8,
+ NEG_W_CHANNEL_VAL = W_CHANNEL_VAL | 0x8,
+ NEG_ONE_CHANNEL_VAL = ONE_CHANNEL_VAL | 0x8
};
-#define X_CHANNEL_VAL 1
-#define Y_CHANNEL_VAL 2
-#define Z_CHANNEL_VAL 3
-#define W_CHANNEL_VAL 4
-#define ZERO_CHANNEL_VAL 5
-#define ONE_CHANNEL_VAL 6
+#define i915_fs_operand(reg, x, y, z, w) \
+ (reg) | \
+(x##_CHANNEL_VAL << X_CHANNEL_SHIFT) | \
+(y##_CHANNEL_VAL << Y_CHANNEL_SHIFT) | \
+(z##_CHANNEL_VAL << Z_CHANNEL_SHIFT) | \
+(w##_CHANNEL_VAL << W_CHANNEL_SHIFT)
/**
- * This structure represents the contents of an operand to an i915 fragment
- * shader.
- *
- * It is not a hardware representation, though closely related.
- */
-struct i915_fs_operand {
- /**< REG_TYPE_* register type */
- int reg;
- /**< *_CHANNEL_VAL swizzle value, with optional negation */
- int x;
- /**< *_CHANNEL_VAL swizzle value, with optional negation */
- int y;
- /**< *_CHANNEL_VAL swizzle value, with optional negation */
- int z;
- /**< *_CHANNEL_VAL swizzle value, with optional negation */
- int w;
-};
-
-/**
- * Construct an operand description for the fragment shader.
- *
- * \param regtype FS_* register used as the source value for X/Y/Z/W sources.
- * \param x *_CHANNEL_VAL swizzle value prefix for operand X channel, with
- * optional negation.
- * \param y *_CHANNEL_VAL swizzle value prefix for operand Y channel, with
- * optional negation.
- * \param z *_CHANNEL_VAL swizzle value prefix for operand Z channel, with
- * optional negation.
- * \param w *_CHANNEL_VAL swizzle value prefix for operand W channel, with
- * optional negation.
- */
-#define i915_fs_operand(reg, x, y, z, w) \
- _i915_fs_operand(reg, \
- x##_CHANNEL_VAL, y##_CHANNEL_VAL, \
- z##_CHANNEL_VAL, w##_CHANNEL_VAL)
-
-/**
- * Construct an oeprand description for using a register with no swizzling
+ * Construct an operand description for using a register with no swizzling
*/
#define i915_fs_operand_reg(reg) \
- i915_fs_operand(reg, X, Y, Z, W)
-
-static inline struct i915_fs_operand
-_i915_fs_operand(int reg, int x, int y, int z, int w)
-{
- struct i915_fs_operand operand;
+ i915_fs_operand(reg, X, Y, Z, W)
- operand.reg = reg;
- operand.x = x;
- operand.y = y;
- operand.z = z;
- operand.w = w;
-
- return operand;
-}
+#define i915_fs_operand_reg_negate(reg) \
+ i915_fs_operand(reg, NEG_X, NEG_Y, NEG_Z, NEG_W)
/**
* Returns an operand containing (0.0, 0.0, 0.0, 0.0).
*/
-static inline struct i915_fs_operand i915_fs_operand_zero(void)
-{
- return i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO);
-}
+#define i915_fs_operand_zero() i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO)
/**
* Returns an unused operand
@@ -171,246 +346,256 @@ static inline struct i915_fs_operand i915_fs_operand_zero(void)
/**
* Returns an operand containing (1.0, 1.0, 1.0, 1.0).
*/
-static inline struct i915_fs_operand i915_fs_operand_one(void)
-{
- return i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE);
-}
-
-static inline int i915_get_hardware_channel_val(int channel_val)
-{
- if (channel_val < 0)
- channel_val = -channel_val;
-
- switch (channel_val) {
- case X_CHANNEL_VAL:
- return SRC_X;
- case Y_CHANNEL_VAL:
- return SRC_Y;
- case Z_CHANNEL_VAL:
- return SRC_Z;
- case W_CHANNEL_VAL:
- return SRC_W;
- case ZERO_CHANNEL_VAL:
- return SRC_ZERO;
- case ONE_CHANNEL_VAL:
- return SRC_ONE;
- }
- FatalError("Bad channel value %d\n", channel_val);
-}
+#define i915_fs_operand_one() i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE)
+
+#define i915_get_hardware_channel_val(val, shift, negate) \
+ (((val & 0x7) << shift) | ((val & 0x8) ? negate : 0))
/**
* Outputs a fragment shader command to declare a sampler or texture register.
*/
#define i915_fs_dcl(reg) \
-do { \
- FS_OUT(_i915_fs_dcl(reg)); \
-} while (0)
-
-/**
- * Constructs a fragment shader command to declare a sampler or texture
- * register.
- */
-static inline struct i915_fs_op _i915_fs_dcl(int reg)
-{
- struct i915_fs_op op;
+ do { \
+ OUT_BATCH(D0_DCL | \
+ (REG_TYPE(reg) << D0_TYPE_SHIFT) | \
+ (REG_NR(reg) << D0_NR_SHIFT) | \
+ ((REG_TYPE(reg) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0)); \
+ OUT_BATCH(0); \
+ OUT_BATCH(0); \
+ } while (0)
- op.ui[0] = D0_DCL | (REG_TYPE(reg) << D0_TYPE_SHIFT) |
- (REG_NR(reg) << D0_NR_SHIFT);
- op.ui[1] = 0;
- op.ui[2] = 0;
- if (REG_TYPE(reg) != REG_TYPE_S)
- op.ui[0] |= D0_CHANNEL_ALL;
-
- return op;
-}
-
-/**
- * Constructs a fragment shader command to load from a texture sampler.
- */
#define i915_fs_texld(dest_reg, sampler_reg, address_reg) \
-do { \
- FS_OUT(_i915_fs_texld(T0_TEXLD, dest_reg, sampler_reg, address_reg)); \
-} while (0)
+ do { \
+ OUT_BATCH(T0_TEXLD | \
+ (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \
+ (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \
+ OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \
+ (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \
+ OUT_BATCH(0); \
+ } while (0)
#define i915_fs_texldp(dest_reg, sampler_reg, address_reg) \
-do { \
- FS_OUT(_i915_fs_texld(T0_TEXLDP, dest_reg, sampler_reg, address_reg)); \
-} while (0)
-
-static inline struct i915_fs_op
-_i915_fs_texld(int load_op, int dest_reg, int sampler_reg, int address_reg)
-{
- struct i915_fs_op op;
-
- op.ui[0] = 0;
- op.ui[1] = 0;
- op.ui[2] = 0;
-
- if (REG_TYPE(sampler_reg) != REG_TYPE_S)
- FatalError("Bad sampler reg type\n");
-
- op.ui[0] |= load_op;
- op.ui[0] |= REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT;
- op.ui[0] |= REG_NR(dest_reg) << T0_DEST_NR_SHIFT;
- op.ui[0] |= REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT;
- op.ui[1] |= REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT;
- op.ui[1] |= REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT;
-
- return op;
-}
+ do { \
+ OUT_BATCH(T0_TEXLDP | \
+ (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \
+ (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \
+ OUT_BATCH((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \
+ (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \
+ OUT_BATCH(0); \
+ } while (0)
+
+#define i915_fs_arith_masked(op, dest_reg, dest_mask, operand0, operand1, operand2) \
+ _i915_fs_arith_masked(A0_##op, dest_reg, dest_mask, operand0, operand1, operand2)
#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \
- _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2)
-
-static inline struct i915_fs_op
-_i915_fs_arith(int cmd, int dest_reg,
- struct i915_fs_operand operand0,
- struct i915_fs_operand operand1, struct i915_fs_operand operand2)
-{
- struct i915_fs_op op;
-
- op.ui[0] = 0;
- op.ui[1] = 0;
- op.ui[2] = 0;
-
- /* Set up destination register and write mask */
- op.ui[0] |= cmd;
- op.ui[0] |= REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT;
- op.ui[0] |= REG_NR(dest_reg) << A0_DEST_NR_SHIFT;
- op.ui[0] |= A0_DEST_CHANNEL_ALL;
-
- /* Set up operand 0 */
- op.ui[0] |= REG_TYPE(operand0.reg) << A0_SRC0_TYPE_SHIFT;
- op.ui[0] |= REG_NR(operand0.reg) << A0_SRC0_NR_SHIFT;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand0.x) <<
- A1_SRC0_CHANNEL_X_SHIFT;
- if (operand0.x < 0)
- op.ui[1] |= A1_SRC0_CHANNEL_X_NEGATE;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand0.y) <<
- A1_SRC0_CHANNEL_Y_SHIFT;
- if (operand0.y < 0)
- op.ui[1] |= A1_SRC0_CHANNEL_Y_NEGATE;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand0.z) <<
- A1_SRC0_CHANNEL_Z_SHIFT;
- if (operand0.z < 0)
- op.ui[1] |= A1_SRC0_CHANNEL_Z_NEGATE;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand0.w) <<
- A1_SRC0_CHANNEL_W_SHIFT;
- if (operand0.w < 0)
- op.ui[1] |= A1_SRC0_CHANNEL_W_NEGATE;
-
- /* Set up operand 1 */
- op.ui[1] |= REG_TYPE(operand1.reg) << A1_SRC1_TYPE_SHIFT;
- op.ui[1] |= REG_NR(operand1.reg) << A1_SRC1_NR_SHIFT;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand1.x) <<
- A1_SRC1_CHANNEL_X_SHIFT;
- if (operand1.x < 0)
- op.ui[1] |= A1_SRC1_CHANNEL_X_NEGATE;
-
- op.ui[1] |= i915_get_hardware_channel_val(operand1.y) <<
- A1_SRC1_CHANNEL_Y_SHIFT;
- if (operand1.y < 0)
- op.ui[1] |= A1_SRC1_CHANNEL_Y_NEGATE;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand1.z) <<
- A2_SRC1_CHANNEL_Z_SHIFT;
- if (operand1.z < 0)
- op.ui[2] |= A2_SRC1_CHANNEL_Z_NEGATE;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand1.w) <<
- A2_SRC1_CHANNEL_W_SHIFT;
- if (operand1.w < 0)
- op.ui[2] |= A2_SRC1_CHANNEL_W_NEGATE;
-
- /* Set up operand 2 */
- op.ui[2] |= REG_TYPE(operand2.reg) << A2_SRC2_TYPE_SHIFT;
- op.ui[2] |= REG_NR(operand2.reg) << A2_SRC2_NR_SHIFT;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand2.x) <<
- A2_SRC2_CHANNEL_X_SHIFT;
- if (operand2.x < 0)
- op.ui[2] |= A2_SRC2_CHANNEL_X_NEGATE;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand2.y) <<
- A2_SRC2_CHANNEL_Y_SHIFT;
- if (operand2.y < 0)
- op.ui[2] |= A2_SRC2_CHANNEL_Y_NEGATE;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand2.z) <<
- A2_SRC2_CHANNEL_Z_SHIFT;
- if (operand2.z < 0)
- op.ui[2] |= A2_SRC2_CHANNEL_Z_NEGATE;
-
- op.ui[2] |= i915_get_hardware_channel_val(operand2.w) <<
- A2_SRC2_CHANNEL_W_SHIFT;
- if (operand2.w < 0)
- op.ui[2] |= A2_SRC2_CHANNEL_W_NEGATE;
-
- return op;
-}
-
-/** Move operand0 to dest_reg */
-#define i915_fs_mov(dest_reg, operand0) \
-do { \
- FS_OUT(i915_fs_arith(MOV, dest_reg, operand0, \
- i915_fs_operand_none(), \
- i915_fs_operand_none())); \
+ _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2)
+
+#define _i915_fs_arith_masked(cmd, dest_reg, dest_mask, operand0, operand1, operand2) \
+ do { \
+ /* Set up destination register and write mask */ \
+ OUT_BATCH(cmd | \
+ (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \
+ (((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT) | \
+ (((dest_mask) & MASK_SATURATE) ? A0_DEST_SATURATE : 0) | \
+ /* Set up operand 0 */ \
+ (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \
+ (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \
+ A1_SRC0_CHANNEL_X_SHIFT, \
+ A1_SRC0_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand0), \
+ A1_SRC0_CHANNEL_Y_SHIFT, \
+ A1_SRC0_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand0), \
+ A1_SRC0_CHANNEL_Z_SHIFT, \
+ A1_SRC0_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand0), \
+ A1_SRC0_CHANNEL_W_SHIFT, \
+ A1_SRC0_CHANNEL_W_NEGATE) | \
+ /* Set up operand 1 */ \
+ (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \
+ (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand1), \
+ A1_SRC1_CHANNEL_X_SHIFT, \
+ A1_SRC1_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand1), \
+ A1_SRC1_CHANNEL_Y_SHIFT, \
+ A1_SRC1_CHANNEL_Y_NEGATE)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \
+ A2_SRC1_CHANNEL_Z_SHIFT, \
+ A2_SRC1_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand1), \
+ A2_SRC1_CHANNEL_W_SHIFT, \
+ A2_SRC1_CHANNEL_W_NEGATE) | \
+ /* Set up operand 2 */ \
+ (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \
+ (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand2), \
+ A2_SRC2_CHANNEL_X_SHIFT, \
+ A2_SRC2_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand2), \
+ A2_SRC2_CHANNEL_Y_SHIFT, \
+ A2_SRC2_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand2), \
+ A2_SRC2_CHANNEL_Z_SHIFT, \
+ A2_SRC2_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand2), \
+ A2_SRC2_CHANNEL_W_SHIFT, \
+ A2_SRC2_CHANNEL_W_NEGATE)); \
+ } while (0)
+
+#define _i915_fs_arith(cmd, dest_reg, operand0, operand1, operand2) do {\
+ /* Set up destination register and write mask */ \
+ OUT_BATCH(cmd | \
+ (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \
+ (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \
+ (A0_DEST_CHANNEL_ALL) | \
+ /* Set up operand 0 */ \
+ (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \
+ (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_X(operand0), \
+ A1_SRC0_CHANNEL_X_SHIFT, \
+ A1_SRC0_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand0), \
+ A1_SRC0_CHANNEL_Y_SHIFT, \
+ A1_SRC0_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand0), \
+ A1_SRC0_CHANNEL_Z_SHIFT, \
+ A1_SRC0_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand0), \
+ A1_SRC0_CHANNEL_W_SHIFT, \
+ A1_SRC0_CHANNEL_W_NEGATE) | \
+ /* Set up operand 1 */ \
+ (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \
+ (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand1), \
+ A1_SRC1_CHANNEL_X_SHIFT, \
+ A1_SRC1_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand1), \
+ A1_SRC1_CHANNEL_Y_SHIFT, \
+ A1_SRC1_CHANNEL_Y_NEGATE)); \
+ OUT_BATCH(i915_get_hardware_channel_val(REG_Z(operand1), \
+ A2_SRC1_CHANNEL_Z_SHIFT, \
+ A2_SRC1_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand1), \
+ A2_SRC1_CHANNEL_W_SHIFT, \
+ A2_SRC1_CHANNEL_W_NEGATE) | \
+ /* Set up operand 2 */ \
+ (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \
+ (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \
+ i915_get_hardware_channel_val(REG_X(operand2), \
+ A2_SRC2_CHANNEL_X_SHIFT, \
+ A2_SRC2_CHANNEL_X_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Y(operand2), \
+ A2_SRC2_CHANNEL_Y_SHIFT, \
+ A2_SRC2_CHANNEL_Y_NEGATE) | \
+ i915_get_hardware_channel_val(REG_Z(operand2), \
+ A2_SRC2_CHANNEL_Z_SHIFT, \
+ A2_SRC2_CHANNEL_Z_NEGATE) | \
+ i915_get_hardware_channel_val(REG_W(operand2), \
+ A2_SRC2_CHANNEL_W_SHIFT, \
+ A2_SRC2_CHANNEL_W_NEGATE)); \
} while (0)
-/**
- * Move the value in operand0 to the dest reg with the masking/saturation
- * specified.
- */
+#define i915_fs_mov(dest_reg, operand0) \
+ i915_fs_arith(MOV, dest_reg, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
+
#define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \
-do { \
- struct i915_fs_op op; \
- \
- op = i915_fs_arith(MOV, dest_reg, operand0, i915_fs_operand_none(), \
- i915_fs_operand_none()); \
- op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \
- op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \
- if ((dest_mask) & MASK_SATURATE) \
- op.ui[0] |= A0_DEST_SATURATE; \
- \
- FS_OUT(op); \
-} while (0)
+ i915_fs_arith_masked (MOV, dest_reg, dest_mask, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
+
+
+#define i915_fs_frc(dest_reg, operand0) \
+ i915_fs_arith (FRC, dest_reg, \
+ operand0, \
+ i915_fs_operand_none(), \
+ i915_fs_operand_none())
/** Add operand0 and operand1 and put the result in dest_reg */
#define i915_fs_add(dest_reg, operand0, operand1) \
-do { \
- FS_OUT(i915_fs_arith(ADD, dest_reg, operand0, operand1, \
- i915_fs_operand_none())); \
-} while (0)
+ i915_fs_arith (ADD, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
-/** Add operand0 and operand1 and put the result in dest_reg */
+/** Multiply operand0 and operand1 and put the result in dest_reg */
#define i915_fs_mul(dest_reg, operand0, operand1) \
-do { \
- FS_OUT(i915_fs_arith(MUL, dest_reg, operand0, operand1, \
- i915_fs_operand_none())); \
-} while (0)
+ i915_fs_arith (MUL, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+/** Computes 1/sqrt(operand0.replicate_swizzle) puts the result in dest_reg */
+#define i915_fs_rsq(dest_reg, dest_mask, operand0) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (RSQ, dest_reg, dest_mask, \
+ operand0, \
+ i915_fs_operand_none (), \
+ i915_fs_operand_none ()); \
+ } else { \
+ i915_fs_arith (RSQ, dest_reg, \
+ operand0, \
+ i915_fs_operand_none (), \
+ i915_fs_operand_none ()); \
+ } \
+ } while (0)
+
+/** Puts the minimum of operand0 and operand1 in dest_reg */
+#define i915_fs_min(dest_reg, operand0, operand1) \
+ i915_fs_arith (MIN, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+/** Puts the maximum of operand0 and operand1 in dest_reg */
+#define i915_fs_max(dest_reg, operand0, operand1) \
+ i915_fs_arith (MAX, dest_reg, \
+ operand0, operand1, \
+ i915_fs_operand_none())
+
+#define i915_fs_cmp(dest_reg, operand0, operand1, operand2) \
+ i915_fs_arith (CMP, dest_reg, operand0, operand1, operand2)
+
+/** Perform operand0 * operand1 + operand2 and put the result in dest_reg */
+#define i915_fs_mad(dest_reg, dest_mask, op0, op1, op2) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (MAD, dest_reg, dest_mask, op0, op1, op2); \
+ } else { \
+ i915_fs_arith (MAD, dest_reg, op0, op1, op2); \
+ } \
+ } while (0)
+
+#define i915_fs_dp2add(dest_reg, dest_mask, op0, op1, op2) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (DP2ADD, dest_reg, dest_mask, op0, op1, op2); \
+ } else { \
+ i915_fs_arith (DP2ADD, dest_reg, op0, op1, op2); \
+ } \
+ } while (0)
/**
* Perform a 3-component dot-product of operand0 and operand1 and put the
* resulting scalar in the channels of dest_reg specified by the dest_mask.
*/
-#define i915_fs_dp3_masked(dest_reg, dest_mask, operand0, operand1) \
-do { \
- struct i915_fs_op op; \
- \
- op = i915_fs_arith(DP3, dest_reg, operand0, operand1, \
- i915_fs_operand_none()); \
- op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \
- op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \
- if ((dest_mask) & MASK_SATURATE) \
- op.ui[0] |= A0_DEST_SATURATE; \
- \
- FS_OUT(op); \
-} while (0)
+#define i915_fs_dp3(dest_reg, dest_mask, op0, op1) \
+ do { \
+ if (dest_mask) { \
+ i915_fs_arith_masked (DP3, dest_reg, dest_mask, \
+ op0, op1,\
+ i915_fs_operand_none()); \
+ } else { \
+ i915_fs_arith (DP3, dest_reg, op0, op1,\
+ i915_fs_operand_none()); \
+ } \
+ } while (0)
/**
* Sets up local state for accumulating a fragment shader buffer.
@@ -418,36 +603,17 @@ do { \
* \param x maximum number of shader commands that may be used between
* a FS_START and FS_END
*/
-#define FS_LOCALS(x) \
- uint32_t _shader_buf[(x) * 3]; \
- unsigned int _max_shader_commands = x; \
- unsigned int _cur_shader_commands
+#define FS_LOCALS() \
+ uint32_t _shader_offset
#define FS_BEGIN() \
-do { \
- _cur_shader_commands = 0; \
-} while (0)
-
-#define FS_OUT(_shaderop) \
-do { \
- if (_cur_shader_commands >= _max_shader_commands) \
- FatalError("fragment shader command buffer exceeded (%d)\n", \
- _cur_shader_commands); \
- _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0]; \
- _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1]; \
- _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2]; \
- ++_cur_shader_commands; \
-} while (0)
+ do { \
+ _shader_offset = intel->batch_used++; \
+ } while (0)
#define FS_END() \
-do { \
- int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \
- ATOMIC_BATCH(_cur_shader_commands * 3 + 1 + _pad); \
- OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | \
- (_cur_shader_commands * 3 - 1)); \
- for (_i = 0; _i < _cur_shader_commands * 3; _i++) \
- OUT_BATCH(_shader_buf[_i]); \
- if (_pad != 0) \
- OUT_BATCH(MI_NOOP); \
- ADVANCE_BATCH(); \
-} while (0);
+ do { \
+ intel->batch_ptr[_shader_offset] = \
+ _3DSTATE_PIXEL_SHADER_PROGRAM | \
+ (intel->batch_used - _shader_offset - 2); \
+ } while (0);
diff --git a/driver/xf86-video-intel/src/i915_reg.h b/driver/xf86-video-intel/src/i915_reg.h
index a61bc4013..746a4131c 100644
--- a/driver/xf86-video-intel/src/i915_reg.h
+++ b/driver/xf86-video-intel/src/i915_reg.h
@@ -32,19 +32,20 @@
#define CMD_3D (0x3<<29)
-#define PRIM3D_INLINE (CMD_3D | (0x1f<<24))
-#define PRIM3D_TRILIST (0x0<<18)
-#define PRIM3D_TRISTRIP (0x1<<18)
-#define PRIM3D_TRISTRIP_RVRSE (0x2<<18)
-#define PRIM3D_TRIFAN (0x3<<18)
-#define PRIM3D_POLY (0x4<<18)
-#define PRIM3D_LINELIST (0x5<<18)
-#define PRIM3D_LINESTRIP (0x6<<18)
-#define PRIM3D_RECTLIST (0x7<<18)
-#define PRIM3D_POINTLIST (0x8<<18)
-#define PRIM3D_DIB (0x9<<18)
-#define PRIM3D_CLEAR_RECT (0xa<<18)
-#define PRIM3D_ZONE_INIT (0xd<<18)
+#define PRIM3D (CMD_3D | (0x1f<<24))
+#define PRIM3D_INDIRECT_SEQUENTIAL ((1<<23) | (0<<17))
+#define PRIM3D_TRILIST (PRIM3D | (0x0<<18))
+#define PRIM3D_TRISTRIP (PRIM3D | (0x1<<18))
+#define PRIM3D_TRISTRIP_RVRSE (PRIM3D | (0x2<<18))
+#define PRIM3D_TRIFAN (PRIM3D | (0x3<<18))
+#define PRIM3D_POLY (PRIM3D | (0x4<<18))
+#define PRIM3D_LINELIST (PRIM3D | (0x5<<18))
+#define PRIM3D_LINESTRIP (PRIM3D | (0x6<<18))
+#define PRIM3D_RECTLIST (PRIM3D | (0x7<<18))
+#define PRIM3D_POINTLIST (PRIM3D | (0x8<<18))
+#define PRIM3D_DIB (PRIM3D | (0x9<<18))
+#define PRIM3D_CLEAR_RECT (PRIM3D | (0xa<<18))
+#define PRIM3D_ZONE_INIT (PRIM3D | (0xd<<18))
#define PRIM3D_MASK (0x1f<<18)
/* p137 */
diff --git a/driver/xf86-video-intel/src/i915_render.c b/driver/xf86-video-intel/src/i915_render.c
index 98b5b88a8..53c991420 100644
--- a/driver/xf86-video-intel/src/i915_render.c
+++ b/driver/xf86-video-intel/src/i915_render.c
@@ -35,8 +35,6 @@
#include "i915_reg.h"
#include "i915_3d.h"
-#define PIXEL_CENTRE_SAMPLE 0
-
struct formatinfo {
int fmt;
uint32_t card_fmt;
@@ -133,8 +131,10 @@ static uint32_t i915_get_blend_cntl(int op, PicturePtr mask,
}
}
- return (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
- (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
+ return S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
+ (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) |
+ (sblend << S6_CBUF_SRC_BLEND_FACT_SHIFT) |
+ (dblend << S6_CBUF_DST_BLEND_FACT_SHIFT);
}
#define DSTORG_HORT_BIAS(x) ((x)<<20)
@@ -170,16 +170,72 @@ static Bool i915_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
(int)dest_picture->format);
return FALSE;
}
-#if PIXEL_CENTRE_SAMPLE
*dst_format |= DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8);
-#endif
return TRUE;
}
-static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
- int unit)
+Bool
+i915_check_composite(int op,
+ PicturePtr source_picture,
+ PicturePtr mask_picture,
+ PicturePtr dest_picture,
+ int width, int height)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
+ uint32_t tmp1;
+
+ /* Check for unsupported compositing operations. */
+ if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) {
+ intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n",
+ op);
+ return FALSE;
+ }
+ if (mask_picture != NULL && mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ /* Check if it's component alpha that relies on a source alpha
+ * and on the source value. We can only get one of those
+ * into the single source value that we get to blend with.
+ */
+ if (i915_blend_op[op].src_alpha &&
+ (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) {
+ if (op != PictOpOver) {
+ intel_debug_fallback(scrn,
+ "Component alpha not supported "
+ "with source alpha and source "
+ "value blending.\n");
+ return FALSE;
+ }
+ }
+ }
+
+ if (!i915_get_dest_format(dest_picture, &tmp1)) {
+ intel_debug_fallback(scrn, "Get Color buffer format\n");
+ return FALSE;
+ }
+
+ if (width > 2048 || height > 2048)
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+i915_check_composite_target(PixmapPtr pixmap)
+{
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048)
+ return FALSE;
+
+ if(!intel_check_pitch_3d(pixmap))
+ return FALSE;
+
+ return TRUE;
+}
+
+Bool
+i915_check_composite_texture(ScreenPtr screen, PicturePtr picture)
{
if (picture->repeatType > RepeatReflect) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn, "Unsupported picture repeat %d\n",
picture->repeatType);
return FALSE;
@@ -187,17 +243,25 @@ static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
if (picture->filter != PictFilterNearest &&
picture->filter != PictFilterBilinear) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn, "Unsupported filter 0x%x\n",
picture->filter);
return FALSE;
}
+ if (picture->pSourcePict) {
+ SourcePict *source = picture->pSourcePict;
+ if (source->type == SourcePictTypeSolidFill)
+ return TRUE;
+ }
+
if (picture->pDrawable) {
int w, h, i;
w = picture->pDrawable->width;
h = picture->pDrawable->height;
if ((w > 2048) || (h > 2048)) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn,
"Picture w/h too large (%dx%d)\n",
w, h);
@@ -212,61 +276,17 @@ static Bool i915_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
}
if (i == sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]))
{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn, "Unsupported picture format "
"0x%x\n",
(int)picture->format);
return FALSE;
}
- }
-
- return TRUE;
-}
-
-Bool
-i915_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
- PicturePtr dest_picture)
-{
- ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
- uint32_t tmp1;
-
- /* Check for unsupported compositing operations. */
- if (op >= sizeof(i915_blend_op) / sizeof(i915_blend_op[0])) {
- intel_debug_fallback(scrn, "Unsupported Composite op 0x%x\n",
- op);
- return FALSE;
- }
- if (mask_picture != NULL && mask_picture->componentAlpha &&
- PICT_FORMAT_RGB(mask_picture->format)) {
- /* Check if it's component alpha that relies on a source alpha
- * and on the source value. We can only get one of those
- * into the single source value that we get to blend with.
- */
- if (i915_blend_op[op].src_alpha &&
- (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) {
- intel_debug_fallback(scrn,
- "Component alpha not supported "
- "with source alpha and source "
- "value blending.\n");
- return FALSE;
- }
- }
- if (!i915_check_composite_texture(scrn, source_picture, 0)) {
- intel_debug_fallback(scrn, "Check Src picture texture\n");
- return FALSE;
- }
- if (mask_picture != NULL
- && !i915_check_composite_texture(scrn, mask_picture, 1)) {
- intel_debug_fallback(scrn, "Check Mask picture texture\n");
- return FALSE;
+ return TRUE;
}
- if (!i915_get_dest_format(dest_picture, &tmp1)) {
- intel_debug_fallback(scrn, "Get Color buffer format\n");
- return FALSE;
- }
-
- return TRUE;
+ return FALSE;
}
static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
@@ -280,8 +300,8 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
pitch = intel_get_pixmap_pitch(pixmap);
w = picture->pDrawable->width;
h = picture->pDrawable->height;
- intel->scale_units[unit][0] = pixmap->drawable.width;
- intel->scale_units[unit][1] = pixmap->drawable.height;
+ intel->scale_units[unit][0] = 1. / pixmap->drawable.width;
+ intel->scale_units[unit][1] = 1. / pixmap->drawable.height;
for (i = 0; i < sizeof(i915_tex_formats) / sizeof(i915_tex_formats[0]);
i++) {
@@ -360,352 +380,161 @@ static Bool i915_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
return TRUE;
}
-Bool
-i915_prepare_composite(int op, PicturePtr source_picture,
- PicturePtr mask_picture, PicturePtr dest_picture,
- PixmapPtr source, PixmapPtr mask, PixmapPtr dest)
+static void
+i915_emit_composite_primitive_constant(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h)
{
- ScrnInfoPtr scrn = xf86Screens[source_picture->pDrawable->pScreen->myNum];
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- drm_intel_bo *bo_table[] = {
- NULL, /* batch_bo */
- i830_get_pixmap_bo(source),
- mask ? i830_get_pixmap_bo(mask) : NULL,
- i830_get_pixmap_bo(dest),
- };
- int tex_unit = 0;
-
- intel->render_source_picture = source_picture;
- intel->render_source = source;
- intel->render_mask_picture = mask_picture;
- intel->render_mask = mask;
- intel->render_dest_picture = dest_picture;
- intel->render_dest = dest;
- intel->render_source_is_solid =
- source_picture->pDrawable &&
- source_picture->pDrawable->width == 1 &&
- source_picture->pDrawable->height == 1 &&
- source_picture->repeat;
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
- if (intel->render_source_is_solid) {
- if (! uxa_get_color_for_pixmap (source,
- source_picture->format,
- PICT_a8r8g8b8,
- &intel->render_source_solid))
- intel->render_source_is_solid = FALSE;
- }
- if (!intel->render_source_is_solid && !intel_check_pitch_3d(source))
- return FALSE;
-
-
- intel->render_mask_is_solid = TRUE; /* mask == NULL => opaque */
- if (mask) {
- intel->render_mask_is_solid =
- mask_picture->pDrawable &&
- mask_picture->pDrawable->width == 1 &&
- mask_picture->pDrawable->height == 1 &&
- mask_picture->repeat;
- if (intel->render_mask_is_solid) {
- if (! uxa_get_color_for_pixmap (mask,
- mask_picture->format,
- PICT_a8r8g8b8,
- &intel->render_mask_solid))
- intel->render_mask_is_solid = FALSE;
- }
- if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask))
- return FALSE;
- }
-
- if (!intel_check_pitch_3d(dest))
- return FALSE;
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
- if (!i915_get_dest_format(dest_picture,
- &intel->i915_render_state.dst_format))
- return FALSE;
-
- if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
- return FALSE;
- intel->dst_coord_adjust = 0;
- intel->src_coord_adjust = 0;
- intel->mask_coord_adjust = 0;
-
- intel->transform[0] = NULL;
- intel->scale_units[0][0] = -1;
- intel->scale_units[0][1] = -1;
- intel->transform[1] = NULL;
- intel->scale_units[1][0] = -1;
- intel->scale_units[1][1] = -1;
-
- if (! intel->render_source_is_solid) {
- if (!i915_texture_setup(source_picture, source, tex_unit++)) {
- intel_debug_fallback(scrn, "fail to setup src texture\n");
- return FALSE;
- }
-
- if (source_picture->filter == PictFilterNearest) {
-#if PIXEL_CENTRE_SAMPLE
- intel->src_coord_adjust = 0.375;
-#else
- intel->dst_coord_adjust = -0.125;
-#endif
- }
- }
-
- if (mask != NULL) {
- if (! intel->render_mask_is_solid) {
- if (!i915_texture_setup(mask_picture, mask, tex_unit++)) {
- intel_debug_fallback(scrn,
- "fail to setup mask texture\n");
- return FALSE;
- }
-
- if (mask_picture->filter == PictFilterNearest) {
-#if PIXEL_CENTRE_SAMPLE
- intel->mask_coord_adjust = 0.375;
-#else
- intel->dst_coord_adjust = -0.125;
-#endif
- }
- }
- }
-
- intel->i915_render_state.op = op;
-
- if(i830_uxa_pixmap_is_dirty(source) ||
- (mask && i830_uxa_pixmap_is_dirty(mask)))
- intel_batch_emit_flush(scrn);
-
- intel->needs_render_state_emit = TRUE;
-
- return TRUE;
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
}
-static void i915_emit_composite_setup(ScrnInfoPtr scrn)
+static void
+i915_emit_composite_primitive_identity_source(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h)
{
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
- int op = intel->i915_render_state.op;
- PicturePtr mask_picture = intel->render_mask_picture;
- PicturePtr dest_picture = intel->render_dest_picture;
- PixmapPtr mask = intel->render_mask;
- PixmapPtr dest = intel->render_dest;
- uint32_t dst_format = intel->i915_render_state.dst_format, dst_pitch;
- uint32_t blendctl, tiling_bits;
- Bool is_affine_src, is_affine_mask;
- Bool is_solid_src, is_solid_mask;
- int tex_count, t;
- intel->needs_render_state_emit = FALSE;
-
- IntelEmitInvarientState(scrn);
- intel->last_3d = LAST_3D_RENDER;
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX((srcX + w) * intel->scale_units[0][0]);
+ OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
- dst_pitch = intel_get_pixmap_pitch(dest);
-
- is_affine_src = i830_transform_is_affine(intel->transform[0]);
- is_affine_mask = i830_transform_is_affine(intel->transform[1]);
-
- is_solid_src = intel->render_source_is_solid;
- is_solid_mask = intel->render_mask_is_solid;
-
- tex_count = 0;
- tex_count += ! is_solid_src;
- tex_count += mask && ! is_solid_mask;
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX(srcX * intel->scale_units[0][0]);
+ OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
- t = 15;
- if (tex_count)
- t += 6 * tex_count + 4;
- if (is_solid_src)
- t += 2;
- if (mask && is_solid_mask)
- t += 2;
- ATOMIC_BATCH (t);
-
- if (tex_count != 0) {
- OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count));
- OUT_BATCH((1 << tex_count) - 1);
- for (t = 0; t < tex_count; t++) {
- OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0);
- OUT_BATCH(intel->mapstate[3*t + 1]);
- OUT_BATCH(intel->mapstate[3*t + 2]);
- }
-
- OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count));
- OUT_BATCH((1 << tex_count) - 1);
- for (t = 0; t < tex_count; t++) {
- OUT_BATCH(intel->samplerstate[3*t + 0]);
- OUT_BATCH(intel->samplerstate[3*t + 1]);
- OUT_BATCH(intel->samplerstate[3*t + 2]);
- }
- }
-
- if (is_solid_src) {
- OUT_BATCH (_3DSTATE_DFLT_DIFFUSE_CMD);
- OUT_BATCH (intel->render_source_solid);
- }
- if (mask && is_solid_mask) {
- OUT_BATCH (_3DSTATE_DFLT_SPEC_CMD);
- OUT_BATCH (intel->render_mask_solid);
- }
-
- if (i830_pixmap_tiled(dest)) {
- tiling_bits = BUF_3D_TILED_SURFACE;
- if (i830_get_pixmap_intel(dest)->tiling
- == I915_TILING_Y)
- tiling_bits |= BUF_3D_TILE_WALK_Y;
- } else
- tiling_bits = 0;
-
- OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
- OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
- BUF_3D_PITCH(dst_pitch));
- OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER,
- I915_GEM_DOMAIN_RENDER, 0);
-
- OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
- OUT_BATCH(dst_format);
-
- {
- uint32_t ss2;
-
- OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
- I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
- ss2 = ~0;
- t = 0;
- if (! is_solid_src) {
- ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT);
- ss2 |= S2_TEXCOORD_FMT(t,
- is_affine_src ? TEXCOORDFMT_2D :
- TEXCOORDFMT_4D);
- t++;
- }
- if (mask && ! is_solid_mask) {
- ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT);
- ss2 |= S2_TEXCOORD_FMT(t,
- is_affine_mask ? TEXCOORDFMT_2D :
- TEXCOORDFMT_4D);
- t++;
- }
- OUT_BATCH(ss2);
- OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
- S4_CULLMODE_NONE | S4_VFMT_XY);
- blendctl =
- i915_get_blend_cntl(op, mask_picture, dest_picture->format);
- OUT_BATCH(0x00000000); /* Disable stencil buffer */
- OUT_BATCH(S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE |
- (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) |
- blendctl);
-
- /* draw rect is unconditional */
- OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
- OUT_BATCH(0x00000000);
- OUT_BATCH(0x00000000); /* ymin, xmin */
- OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) |
- DRAW_XMAX(dest->drawable.width - 1));
- /* yorig, xorig (relate to color buffer?) */
- OUT_BATCH(0x00000000);
- }
-
- ADVANCE_BATCH();
-
- {
- FS_LOCALS(20);
- int src_reg, mask_reg, out_reg = FS_OC;
-
- FS_BEGIN();
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
+ OUT_VERTEX(srcX * intel->scale_units[0][0]);
+ OUT_VERTEX(srcY * intel->scale_units[0][1]);
+}
- if (dst_format == COLR_BUF_8BIT)
- out_reg = FS_U0;
+static void
+i915_emit_composite_primitive_affine_source(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ float src_x[3], src_y[3];
+
+ if (!i830_get_transformed_coordinates(srcX, srcY,
+ intel->transform[0],
+ &src_x[0],
+ &src_y[0]))
+ return;
+
+ if (!i830_get_transformed_coordinates(srcX, srcY + h,
+ intel->transform[0],
+ &src_x[1],
+ &src_y[1]))
+ return;
+
+ if (!i830_get_transformed_coordinates(srcX + w, srcY + h,
+ intel->transform[0],
+ &src_x[2],
+ &src_y[2]))
+ return;
+
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX(src_x[2] * intel->scale_units[0][0]);
+ OUT_VERTEX(src_y[2] * intel->scale_units[0][1]);
+
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX(src_x[1] * intel->scale_units[0][0]);
+ OUT_VERTEX(src_y[1] * intel->scale_units[0][1]);
+
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
+ OUT_VERTEX(src_x[0] * intel->scale_units[0][0]);
+ OUT_VERTEX(src_y[0] * intel->scale_units[0][1]);
+}
- /* Declare the registers necessary for our program. */
- t = 0;
- if (is_solid_src) {
- i915_fs_dcl(FS_T8);
- src_reg = FS_T8;
- } else {
- i915_fs_dcl(FS_T0);
- i915_fs_dcl(FS_S0);
- t++;
- }
- if (mask) {
- if (is_solid_mask) {
- i915_fs_dcl(FS_T9);
- mask_reg = FS_T9;
- } else {
- i915_fs_dcl(FS_T0 + t);
- i915_fs_dcl(FS_S0 + t);
- }
- }
+static void
+i915_emit_composite_primitive_constant_identity_mask(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
- /* Load the source_picture texel */
- if (! is_solid_src) {
- if (is_affine_src) {
- i915_fs_texld(FS_R0, FS_S0, FS_T0);
- } else {
- i915_fs_texldp(FS_R0, FS_S0, FS_T0);
- }
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX((maskX + w) * intel->scale_units[0][0]);
+ OUT_VERTEX((maskY + h) * intel->scale_units[0][1]);
- src_reg = FS_R0;
- }
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX(maskX * intel->scale_units[0][0]);
+ OUT_VERTEX((maskY + h) * intel->scale_units[0][1]);
- if (!mask) {
- /* No mask, so move to output color */
- i915_fs_mov(out_reg, i915_fs_operand_reg(src_reg));
- } else {
- if (! is_solid_mask) {
- /* Load the mask_picture texel */
- if (is_affine_mask) {
- i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t);
- } else {
- i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t);
- }
-
- mask_reg = FS_R1;
- }
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
+ OUT_VERTEX(maskX * intel->scale_units[0][0]);
+ OUT_VERTEX(maskY * intel->scale_units[0][1]);
+}
- /* If component alpha is active in the mask and the blend
- * operation uses the source alpha, then we know we don't
- * need the source value (otherwise we would have hit a
- * fallback earlier), so we provide the source alpha (src.A *
- * mask.X) as output color.
- * Conversely, if CA is set and we don't need the source alpha,
- * then we produce the source value (src.X * mask.X) and the
- * source alpha is unused. Otherwise, we provide the non-CA
- * source value (src.X * mask.A).
- */
- if (mask_picture->componentAlpha &&
- PICT_FORMAT_RGB(mask_picture->format)) {
- if (i915_blend_op[op].src_alpha) {
- i915_fs_mul(out_reg,
- i915_fs_operand(src_reg, W, W, W, W),
- i915_fs_operand_reg(mask_reg));
- } else {
- i915_fs_mul(out_reg,
- i915_fs_operand_reg(src_reg),
- i915_fs_operand_reg(mask_reg));
- }
- } else {
- i915_fs_mul(out_reg,
- i915_fs_operand_reg(src_reg),
- i915_fs_operand(mask_reg, W, W, W, W));
- }
- }
- if (dst_format == COLR_BUF_8BIT)
- i915_fs_mov(FS_OC, i915_fs_operand(out_reg, W, W, W, W));
+static void
+i915_emit_composite_primitive_identity_source_mask(PixmapPtr dest,
+ int srcX, int srcY,
+ int maskX, int maskY,
+ int dstX, int dstY,
+ int w, int h)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
- FS_END();
- }
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX((srcX + w) * intel->scale_units[0][0]);
+ OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
+ OUT_VERTEX((maskX + w) * intel->scale_units[1][0]);
+ OUT_VERTEX((maskY + h) * intel->scale_units[1][1]);
+
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
+ OUT_VERTEX(srcX * intel->scale_units[0][0]);
+ OUT_VERTEX((srcY + h) * intel->scale_units[0][1]);
+ OUT_VERTEX(maskX * intel->scale_units[1][0]);
+ OUT_VERTEX((maskY + h) * intel->scale_units[1][1]);
+
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
+ OUT_VERTEX(srcX * intel->scale_units[0][0]);
+ OUT_VERTEX(srcY * intel->scale_units[0][1]);
+ OUT_VERTEX(maskX * intel->scale_units[1][0]);
+ OUT_VERTEX(maskY * intel->scale_units[1][1]);
}
-/* Emit the vertices for a single composite rectangle.
- *
- * This function is no longer shared between i830 and i915 generation code.
- */
static void
i915_emit_composite_primitive(PixmapPtr dest,
int srcX, int srcY,
int maskX, int maskY,
- int dstX, int dstY, int w, int h)
+ int dstX, int dstY,
+ int w, int h)
{
ScrnInfoPtr scrn = xf86Screens[dest->drawable.pScreen->myNum];
intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -718,28 +547,25 @@ i915_emit_composite_primitive(PixmapPtr dest,
per_vertex = 2; /* dest x/y */
if (! intel->render_source_is_solid) {
- float x = srcX + intel->src_coord_adjust;
- float y = srcY + intel->src_coord_adjust;
-
src_unit = tex_unit++;
is_affine_src = i830_transform_is_affine(intel->transform[src_unit]);
if (is_affine_src) {
- if (!i830_get_transformed_coordinates(x, y,
+ if (!i830_get_transformed_coordinates(srcX, srcY,
intel->
transform[src_unit],
&src_x[0],
&src_y[0]))
return;
- if (!i830_get_transformed_coordinates(x, y + h,
+ if (!i830_get_transformed_coordinates(srcX, srcY + h,
intel->
transform[src_unit],
&src_x[1],
&src_y[1]))
return;
- if (!i830_get_transformed_coordinates(x + w, y + h,
+ if (!i830_get_transformed_coordinates(srcX + w, srcY + h,
intel->
transform[src_unit],
&src_x[2],
@@ -748,7 +574,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
per_vertex += 2; /* src x/y */
} else {
- if (!i830_get_transformed_coordinates_3d(x, y,
+ if (!i830_get_transformed_coordinates_3d(srcX, srcY,
intel->
transform[src_unit],
&src_x[0],
@@ -756,7 +582,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
&src_w[0]))
return;
- if (!i830_get_transformed_coordinates_3d(x, y + h,
+ if (!i830_get_transformed_coordinates_3d(srcX, srcY + h,
intel->
transform[src_unit],
&src_x[1],
@@ -764,7 +590,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
&src_w[1]))
return;
- if (!i830_get_transformed_coordinates_3d(x + w, y + h,
+ if (!i830_get_transformed_coordinates_3d(srcX + w, srcY + h,
intel->
transform[src_unit],
&src_x[2],
@@ -777,28 +603,25 @@ i915_emit_composite_primitive(PixmapPtr dest,
}
if (intel->render_mask && ! intel->render_mask_is_solid) {
- float x = maskX + intel->mask_coord_adjust;
- float y = maskY + intel->mask_coord_adjust;
-
mask_unit = tex_unit++;
is_affine_mask = i830_transform_is_affine(intel->transform[mask_unit]);
if (is_affine_mask) {
- if (!i830_get_transformed_coordinates(x, y,
+ if (!i830_get_transformed_coordinates(maskX, maskY,
intel->
transform[mask_unit],
&mask_x[0],
&mask_y[0]))
return;
- if (!i830_get_transformed_coordinates(x, y + h,
+ if (!i830_get_transformed_coordinates(maskX, maskY + h,
intel->
transform[mask_unit],
&mask_x[1],
&mask_y[1]))
return;
- if (!i830_get_transformed_coordinates(x + w, y + h,
+ if (!i830_get_transformed_coordinates(maskX + w, maskY + h,
intel->
transform[mask_unit],
&mask_x[2],
@@ -807,7 +630,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
per_vertex += 2; /* mask x/y */
} else {
- if (!i830_get_transformed_coordinates_3d(x, y,
+ if (!i830_get_transformed_coordinates_3d(maskX, maskY,
intel->
transform[mask_unit],
&mask_x[0],
@@ -815,7 +638,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
&mask_w[0]))
return;
- if (!i830_get_transformed_coordinates_3d(x, y + h,
+ if (!i830_get_transformed_coordinates_3d(maskX, maskY + h,
intel->
transform[mask_unit],
&mask_x[1],
@@ -823,7 +646,7 @@ i915_emit_composite_primitive(PixmapPtr dest,
&mask_w[1]))
return;
- if (!i830_get_transformed_coordinates_3d(x + w, y + h,
+ if (!i830_get_transformed_coordinates_3d(maskX + w, maskY + h,
intel->
transform[mask_unit],
&mask_x[2],
@@ -837,67 +660,444 @@ i915_emit_composite_primitive(PixmapPtr dest,
num_floats = 3 * per_vertex;
- ATOMIC_BATCH(1 + num_floats);
-
- OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (num_floats - 1));
- OUT_BATCH_F(intel->dst_coord_adjust + dstX + w);
- OUT_BATCH_F(intel->dst_coord_adjust + dstY + h);
+ OUT_VERTEX(dstX + w);
+ OUT_VERTEX(dstY + h);
if (! intel->render_source_is_solid) {
- OUT_BATCH_F(src_x[2] / intel->scale_units[src_unit][0]);
- OUT_BATCH_F(src_y[2] / intel->scale_units[src_unit][1]);
+ OUT_VERTEX(src_x[2] * intel->scale_units[src_unit][0]);
+ OUT_VERTEX(src_y[2] * intel->scale_units[src_unit][1]);
if (!is_affine_src) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(src_w[2]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(src_w[2]);
}
}
if (intel->render_mask && ! intel->render_mask_is_solid) {
- OUT_BATCH_F(mask_x[2] / intel->scale_units[mask_unit][0]);
- OUT_BATCH_F(mask_y[2] / intel->scale_units[mask_unit][1]);
+ OUT_VERTEX(mask_x[2] * intel->scale_units[mask_unit][0]);
+ OUT_VERTEX(mask_y[2] * intel->scale_units[mask_unit][1]);
if (!is_affine_mask) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(mask_w[2]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(mask_w[2]);
}
}
- OUT_BATCH_F(intel->dst_coord_adjust + dstX);
- OUT_BATCH_F(intel->dst_coord_adjust + dstY + h);
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY + h);
if (! intel->render_source_is_solid) {
- OUT_BATCH_F(src_x[1] / intel->scale_units[src_unit][0]);
- OUT_BATCH_F(src_y[1] / intel->scale_units[src_unit][1]);
+ OUT_VERTEX(src_x[1] * intel->scale_units[src_unit][0]);
+ OUT_VERTEX(src_y[1] * intel->scale_units[src_unit][1]);
if (!is_affine_src) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(src_w[1]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(src_w[1]);
}
}
if (intel->render_mask && ! intel->render_mask_is_solid) {
- OUT_BATCH_F(mask_x[1] / intel->scale_units[mask_unit][0]);
- OUT_BATCH_F(mask_y[1] / intel->scale_units[mask_unit][1]);
+ OUT_VERTEX(mask_x[1] * intel->scale_units[mask_unit][0]);
+ OUT_VERTEX(mask_y[1] * intel->scale_units[mask_unit][1]);
if (!is_affine_mask) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(mask_w[1]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(mask_w[1]);
}
}
- OUT_BATCH_F(intel->dst_coord_adjust + dstX);
- OUT_BATCH_F(intel->dst_coord_adjust + dstY);
+ OUT_VERTEX(dstX);
+ OUT_VERTEX(dstY);
if (! intel->render_source_is_solid) {
- OUT_BATCH_F(src_x[0] / intel->scale_units[src_unit][0]);
- OUT_BATCH_F(src_y[0] / intel->scale_units[src_unit][1]);
+ OUT_VERTEX(src_x[0] * intel->scale_units[src_unit][0]);
+ OUT_VERTEX(src_y[0] * intel->scale_units[src_unit][1]);
if (!is_affine_src) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(src_w[0]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(src_w[0]);
}
}
if (intel->render_mask && ! intel->render_mask_is_solid) {
- OUT_BATCH_F(mask_x[0] / intel->scale_units[mask_unit][0]);
- OUT_BATCH_F(mask_y[0] / intel->scale_units[mask_unit][1]);
+ OUT_VERTEX(mask_x[0] * intel->scale_units[mask_unit][0]);
+ OUT_VERTEX(mask_y[0] * intel->scale_units[mask_unit][1]);
if (!is_affine_mask) {
- OUT_BATCH_F(0.0);
- OUT_BATCH_F(mask_w[0]);
+ OUT_VERTEX(0.0);
+ OUT_VERTEX(mask_w[0]);
+ }
+ }
+}
+
+Bool
+i915_prepare_composite(int op, PicturePtr source_picture,
+ PicturePtr mask_picture, PicturePtr dest_picture,
+ PixmapPtr source, PixmapPtr mask, PixmapPtr dest)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ drm_intel_bo *bo_table[] = {
+ NULL, /* batch_bo */
+ i830_get_pixmap_bo(dest),
+ source ? i830_get_pixmap_bo(source) : NULL,
+ mask ? i830_get_pixmap_bo(mask) : NULL,
+ };
+ int tex_unit = 0;
+ int floats_per_vertex;
+
+ intel->render_source_picture = source_picture;
+ intel->render_source = source;
+ intel->render_mask_picture = mask_picture;
+ intel->render_mask = mask;
+ intel->render_dest_picture = dest_picture;
+ intel->render_dest = dest;
+
+ intel->render_source_is_solid = FALSE;
+ if (source_picture->pSourcePict) {
+ SourcePict *source = source_picture->pSourcePict;
+ if (source->type == SourcePictTypeSolidFill) {
+ intel->render_source_is_solid = TRUE;
+ intel->render_source_solid = source->solidFill.color;
+ }
+ }
+ if (!intel->render_source_is_solid && !intel_check_pitch_3d(source))
+ return FALSE;
+
+ intel->render_mask_is_solid = FALSE;
+ if (mask) {
+ if (mask_picture->pSourcePict) {
+ SourcePict *source = mask_picture->pSourcePict;
+ if (source->type == SourcePictTypeSolidFill) {
+ intel->render_mask_is_solid = TRUE;
+ intel->render_mask_solid = source->solidFill.color;
+ }
+ }
+ if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask))
+ return FALSE;
+ }
+
+ if (!intel_check_pitch_3d(dest))
+ return FALSE;
+
+ if (!i915_get_dest_format(dest_picture,
+ &intel->i915_render_state.dst_format))
+ return FALSE;
+
+ if (!i830_get_aperture_space(scrn, bo_table, ARRAY_SIZE(bo_table)))
+ return FALSE;
+
+ intel->needs_render_ca_pass = FALSE;
+ if (mask_picture != NULL && mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ /* Check if it's component alpha that relies on a source alpha
+ * and on the source value. We can only get one of those
+ * into the single source value that we get to blend with.
+ */
+ if (i915_blend_op[op].src_alpha &&
+ (i915_blend_op[op].src_blend != BLENDFACT_ZERO)) {
+ if (op != PictOpOver)
+ return FALSE;
+
+ intel->needs_render_ca_pass = TRUE;
+ }
+ }
+
+ intel->transform[0] = NULL;
+ intel->scale_units[0][0] = -1;
+ intel->scale_units[0][1] = -1;
+ intel->transform[1] = NULL;
+ intel->scale_units[1][0] = -1;
+ intel->scale_units[1][1] = -1;
+
+ floats_per_vertex = 2; /* dest x/y */
+ if (! intel->render_source_is_solid) {
+ if (!i915_texture_setup(source_picture, source, tex_unit++)) {
+ intel_debug_fallback(scrn, "fail to setup src texture\n");
+ return FALSE;
+ }
+
+ if (i830_transform_is_affine(source_picture->transform))
+ floats_per_vertex += 2; /* src x/y */
+ else
+ floats_per_vertex += 4; /* src x/y/z/w */
+ }
+
+ if (mask != NULL) {
+ if (! intel->render_mask_is_solid) {
+ if (!i915_texture_setup(mask_picture, mask, tex_unit++)) {
+ intel_debug_fallback(scrn,
+ "fail to setup mask texture\n");
+ return FALSE;
+ }
+
+ if (i830_transform_is_affine(mask_picture->transform))
+ floats_per_vertex += 2; /* mask x/y */
+ else
+ floats_per_vertex += 4; /* mask x/y/z/w */
}
}
- ADVANCE_BATCH();
+ intel->i915_render_state.op = op;
+
+ /* BUF_INFO is an implicit flush */
+ if (dest != intel->render_current_dest)
+ intel_batch_do_flush(scrn);
+ else if((source && i830_uxa_pixmap_is_dirty(source)) ||
+ (mask && i830_uxa_pixmap_is_dirty(mask)))
+ intel_batch_emit_flush(scrn);
+
+ intel->needs_render_state_emit = TRUE;
+
+ intel->prim_emit = i915_emit_composite_primitive;
+ if (!mask) {
+ if (intel->render_source_is_solid)
+ intel->prim_emit = i915_emit_composite_primitive_constant;
+ else if (intel->transform[0] == NULL)
+ intel->prim_emit = i915_emit_composite_primitive_identity_source;
+ else if (i830_transform_is_affine(intel->transform[0]))
+ intel->prim_emit = i915_emit_composite_primitive_affine_source;
+ } else {
+ if (intel->transform[0] == NULL) {
+ if (intel->render_source_is_solid)
+ intel->prim_emit = i915_emit_composite_primitive_constant_identity_mask;
+ else if (intel->transform[1] == NULL)
+ intel->prim_emit = i915_emit_composite_primitive_identity_source_mask;
+ }
+ }
+
+ if (floats_per_vertex != intel->floats_per_vertex) {
+ intel->floats_per_vertex = floats_per_vertex;
+ intel->needs_render_vertex_emit = TRUE;
+ }
+
+ return TRUE;
+}
+
+static void
+i915_composite_emit_shader(intel_screen_private *intel, CARD8 op)
+{
+ PicturePtr mask_picture = intel->render_mask_picture;
+ PixmapPtr mask = intel->render_mask;
+ int src_reg, mask_reg;
+ Bool is_solid_src, is_solid_mask;
+ Bool dest_is_alpha = PIXMAN_FORMAT_RGB(intel->render_dest_picture->format) == 0;
+ int tex_unit, t;
+ FS_LOCALS();
+
+ is_solid_src = intel->render_source_is_solid;
+ is_solid_mask = intel->render_mask_is_solid;
+
+ FS_BEGIN();
+
+ /* Declare the registers necessary for our program. */
+ t = 0;
+ if (is_solid_src) {
+ i915_fs_dcl(FS_T8);
+ src_reg = FS_T8;
+ } else {
+ i915_fs_dcl(FS_T0);
+ i915_fs_dcl(FS_S0);
+ t++;
+ }
+ if (!mask) {
+ /* No mask, so load directly to output color */
+ if (! is_solid_src) {
+ if (dest_is_alpha)
+ src_reg = FS_R0;
+ else
+ src_reg = FS_OC;
+
+ if (i830_transform_is_affine(intel->transform[0]))
+ i915_fs_texld(src_reg, FS_S0, FS_T0);
+ else
+ i915_fs_texldp(src_reg, FS_S0, FS_T0);
+ }
+
+ if (src_reg != FS_OC) {
+ if (dest_is_alpha)
+ i915_fs_mov(FS_OC, i915_fs_operand(src_reg, W, W, W, W));
+ else
+ i915_fs_mov(FS_OC, i915_fs_operand_reg(src_reg));
+ }
+ } else {
+ if (is_solid_mask) {
+ i915_fs_dcl(FS_T9);
+ mask_reg = FS_T9;
+ } else {
+ i915_fs_dcl(FS_T0 + t);
+ i915_fs_dcl(FS_S0 + t);
+ }
+
+ tex_unit = 0;
+ if (! is_solid_src) {
+ /* Load the source_picture texel */
+ if (i830_transform_is_affine(intel->transform[tex_unit]))
+ i915_fs_texld(FS_R0, FS_S0, FS_T0);
+ else
+ i915_fs_texldp(FS_R0, FS_S0, FS_T0);
+
+ src_reg = FS_R0;
+ tex_unit++;
+ }
+
+ if (! is_solid_mask) {
+ /* Load the mask_picture texel */
+ if (i830_transform_is_affine(intel->transform[tex_unit]))
+ i915_fs_texld(FS_R1, FS_S0 + t, FS_T0 + t);
+ else
+ i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t);
+
+ mask_reg = FS_R1;
+ }
+
+ if (dest_is_alpha) {
+ i915_fs_mul(FS_OC,
+ i915_fs_operand(src_reg, W, W, W, W),
+ i915_fs_operand(mask_reg, W, W, W, W));
+ } else {
+ /* If component alpha is active in the mask and the blend
+ * operation uses the source alpha, then we know we don't
+ * need the source value (otherwise we would have hit a
+ * fallback earlier), so we provide the source alpha (src.A *
+ * mask.X) as output color.
+ * Conversely, if CA is set and we don't need the source alpha,
+ * then we produce the source value (src.X * mask.X) and the
+ * source alpha is unused. Otherwise, we provide the non-CA
+ * source value (src.X * mask.A).
+ */
+ if (mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ if (i915_blend_op[op].src_alpha) {
+ i915_fs_mul(FS_OC,
+ i915_fs_operand(src_reg, W, W, W, W),
+ i915_fs_operand_reg(mask_reg));
+ } else {
+ i915_fs_mul(FS_OC,
+ i915_fs_operand_reg(src_reg),
+ i915_fs_operand_reg(mask_reg));
+ }
+ } else {
+ i915_fs_mul(FS_OC,
+ i915_fs_operand_reg(src_reg),
+ i915_fs_operand(mask_reg, W, W, W, W));
+ }
+ }
+ }
+
+ FS_END();
+}
+
+static void i915_emit_composite_setup(ScrnInfoPtr scrn)
+{
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+ int op = intel->i915_render_state.op;
+ PicturePtr mask_picture = intel->render_mask_picture;
+ PicturePtr dest_picture = intel->render_dest_picture;
+ PixmapPtr mask = intel->render_mask;
+ PixmapPtr dest = intel->render_dest;
+ Bool is_solid_src, is_solid_mask;
+ int tex_count, t;
+
+ intel->needs_render_state_emit = FALSE;
+
+ IntelEmitInvarientState(scrn);
+ intel->last_3d = LAST_3D_RENDER;
+
+ is_solid_src = intel->render_source_is_solid;
+ is_solid_mask = intel->render_mask_is_solid;
+
+ tex_count = 0;
+ tex_count += ! is_solid_src;
+ tex_count += mask && ! is_solid_mask;
+
+ assert(intel->in_batch_atomic);
+
+ if (tex_count != 0) {
+ OUT_BATCH(_3DSTATE_MAP_STATE | (3 * tex_count));
+ OUT_BATCH((1 << tex_count) - 1);
+ for (t = 0; t < tex_count; t++) {
+ OUT_RELOC_PIXMAP(intel->texture[t], I915_GEM_DOMAIN_SAMPLER, 0, 0);
+ OUT_BATCH(intel->mapstate[3*t + 1]);
+ OUT_BATCH(intel->mapstate[3*t + 2]);
+ }
+
+ OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * tex_count));
+ OUT_BATCH((1 << tex_count) - 1);
+ for (t = 0; t < tex_count; t++) {
+ OUT_BATCH(intel->samplerstate[3*t + 0]);
+ OUT_BATCH(intel->samplerstate[3*t + 1]);
+ OUT_BATCH(intel->samplerstate[3*t + 2]);
+ }
+ }
+
+ if (is_solid_src) {
+ OUT_BATCH (_3DSTATE_DFLT_DIFFUSE_CMD);
+ OUT_BATCH (intel->render_source_solid);
+ }
+ if (mask && is_solid_mask) {
+ OUT_BATCH (_3DSTATE_DFLT_SPEC_CMD);
+ OUT_BATCH (intel->render_mask_solid);
+ }
+
+ /* BUF_INFO is an implicit flush, so avoid if the target has not changed.
+ * XXX However for reasons unfathomed, correct rendering in KDE requires
+ * at least a MI_FLUSH | INHIBIT_RENDER_CACHE_FLUSH here.
+ */
+ if (1 || dest != intel->render_current_dest) {
+ uint32_t tiling_bits;
+
+ intel_batch_do_flush(scrn);
+
+ if (i830_pixmap_tiled(dest)) {
+ tiling_bits = BUF_3D_TILED_SURFACE;
+ if (i830_get_pixmap_intel(dest)->tiling
+ == I915_TILING_Y)
+ tiling_bits |= BUF_3D_TILE_WALK_Y;
+ } else
+ tiling_bits = 0;
+
+ OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling_bits |
+ BUF_3D_PITCH(intel_get_pixmap_pitch(dest)));
+ OUT_RELOC_PIXMAP(dest, I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER, 0);
+
+ OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
+ OUT_BATCH(intel->i915_render_state.dst_format);
+
+ /* draw rect is unconditional */
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(0x00000000);
+ OUT_BATCH(0x00000000); /* ymin, xmin */
+ OUT_BATCH(DRAW_YMAX(dest->drawable.height - 1) |
+ DRAW_XMAX(dest->drawable.width - 1));
+ /* yorig, xorig (relate to color buffer?) */
+ OUT_BATCH(0x00000000);
+
+ intel->render_current_dest = dest;
+ }
+
+ {
+ uint32_t ss2;
+
+ ss2 = ~0;
+ t = 0;
+ if (! is_solid_src) {
+ ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(t,
+ i830_transform_is_affine(intel->transform[t]) ?
+ TEXCOORDFMT_2D : TEXCOORDFMT_4D);
+ t++;
+ }
+ if (mask && ! is_solid_mask) {
+ ss2 &= ~S2_TEXCOORD_FMT(t, TEXCOORDFMT_NOT_PRESENT);
+ ss2 |= S2_TEXCOORD_FMT(t,
+ i830_transform_is_affine(intel->transform[t]) ?
+ TEXCOORDFMT_2D : TEXCOORDFMT_4D);
+ t++;
+ }
+
+ if (intel->needs_render_ca_pass) {
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | 0);
+ OUT_BATCH(ss2);
+ } else {
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | I1_LOAD_S(6) | 1);
+ OUT_BATCH(ss2);
+ OUT_BATCH(i915_get_blend_cntl(op, mask_picture, dest_picture->format));
+ }
+ }
+
+ if (! intel->needs_render_ca_pass)
+ i915_composite_emit_shader(intel, op);
}
void
@@ -913,15 +1113,87 @@ i915_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY,
if (intel->needs_render_state_emit)
i915_emit_composite_setup(scrn);
- i915_emit_composite_primitive(dest, srcX, srcY, maskX, maskY, dstX,
- dstY, w, h);
+ if (intel->needs_render_vertex_emit ||
+ intel_vertex_space(intel) < 3*4*intel->floats_per_vertex) {
+ i915_vertex_flush(intel);
+
+ if (intel_vertex_space(intel) < 256) {
+ intel_next_vertex(intel);
+
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
+ OUT_RELOC(intel->vertex_bo, I915_GEM_DOMAIN_VERTEX, 0, 0);
+ OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
+ (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
+ intel->vertex_index = 0;
+ } else if (intel->floats_per_vertex != intel->last_floats_per_vertex){
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
+ I1_LOAD_S(1) | 0);
+ OUT_BATCH((intel->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
+ (intel->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
+
+ intel->vertex_index =
+ (intel->vertex_used + intel->floats_per_vertex - 1) / intel->floats_per_vertex;
+ intel->vertex_used = intel->vertex_index * intel->floats_per_vertex;
+ }
+
+ intel->last_floats_per_vertex = intel->floats_per_vertex;
+ intel->needs_render_vertex_emit = FALSE;
+ }
+
+ if (intel->prim_offset == 0) {
+ if (intel->needs_render_ca_pass) {
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
+ OUT_BATCH(i915_get_blend_cntl(PictOpOutReverse,
+ intel->render_mask_picture,
+ intel->render_dest_picture->format));
+ i915_composite_emit_shader(intel, PictOpOutReverse);
+ }
+
+ intel->prim_offset = intel->batch_used;
+ OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL);
+ OUT_BATCH(intel->vertex_index);
+ }
+ intel->vertex_count += 3;
+
+ intel->prim_emit(dest,
+ srcX, srcY,
+ maskX, maskY,
+ dstX, dstY,
+ w, h);
intel_batch_end_atomic(scrn);
}
-void i915_batch_flush_notify(ScrnInfoPtr scrn)
+void
+i915_vertex_flush(intel_screen_private *intel)
+{
+ if (intel->prim_offset == 0)
+ return;
+
+ intel->batch_ptr[intel->prim_offset] |= intel->vertex_count;
+ intel->prim_offset = 0;
+
+ if (intel->needs_render_ca_pass) {
+ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(6) | 0);
+ OUT_BATCH(i915_get_blend_cntl(PictOpAdd,
+ intel->render_mask_picture,
+ intel->render_dest_picture->format));
+ i915_composite_emit_shader(intel, PictOpAdd);
+ OUT_BATCH(PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL | intel->vertex_count);
+ OUT_BATCH(intel->vertex_index);
+ }
+
+ intel->vertex_index += intel->vertex_count;
+ intel->vertex_count = 0;
+}
+
+void
+i915_batch_flush_notify(ScrnInfoPtr scrn)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
intel->needs_render_state_emit = TRUE;
+ intel->render_current_dest = NULL;
+ intel->last_floats_per_vertex = 0;
}
diff --git a/driver/xf86-video-intel/src/i915_video.c b/driver/xf86-video-intel/src/i915_video.c
index 927047be7..893855bd6 100644
--- a/driver/xf86-video-intel/src/i915_video.c
+++ b/driver/xf86-video-intel/src/i915_video.c
@@ -49,17 +49,47 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
PixmapPtr pixmap)
{
intel_screen_private *intel = intel_get_screen_private(scrn);
- uint32_t format, ms3, s5;
+ uint32_t format, ms3, s5, tiling;
BoxPtr pbox = REGION_RECTS(dstRegion);
int nbox_total = REGION_NUM_RECTS(dstRegion);
int nbox_this_time;
int dxo, dyo, pix_xoff, pix_yoff;
+ PixmapPtr target;
#if 0
ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height,
video_pitch);
#endif
+ dxo = dstRegion->extents.x1;
+ dyo = dstRegion->extents.y1;
+
+ if (pixmap->drawable.width > 2048 || pixmap->drawable.height > 2048 ||
+ !intel_check_pitch_3d(pixmap)) {
+ ScreenPtr screen = pixmap->drawable.pScreen;
+
+ target = screen->CreatePixmap(screen,
+ drw_w, drw_h,
+ pixmap->drawable.depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+
+ pix_xoff = -dxo;
+ pix_yoff = -dyo;
+ } else {
+ target = pixmap;
+
+ /* Set up the offset for translating from the given region
+ * (in screen coordinates) to the backing pixmap.
+ */
+#ifdef COMPOSITE
+ pix_xoff = -target->screen_x + target->drawable.x;
+ pix_yoff = -target->screen_y + target->drawable.y;
+#else
+ pix_xoff = 0;
+ pix_yoff = 0;
+#endif
+ }
+
#define BYTES_FOR_BOXES(n) ((200 + (n) * 20) * 4)
#define BOXES_IN_BYTES(s) ((((s)/4) - 200) / 20)
#define BATCH_BYTES(p) ((p)->batch_bo->size - 16)
@@ -75,26 +105,18 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
IntelEmitInvarientState(scrn);
intel->last_3d = LAST_3D_VIDEO;
- ATOMIC_BATCH(20);
-
- /* flush map & render cache */
- OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE |
- MI_INVALIDATE_MAP_CACHE);
- OUT_BATCH(0x00000000);
-
/* draw rect -- just clipping */
OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
OUT_BATCH(DRAW_DITHER_OFS_X(pixmap->drawable.x & 3) |
DRAW_DITHER_OFS_Y(pixmap->drawable.y & 3));
OUT_BATCH(0x00000000); /* ymin, xmin */
/* ymax, xmax */
- OUT_BATCH((pixmap->drawable.width - 1) |
- (pixmap->drawable.height - 1) << 16);
+ OUT_BATCH((target->drawable.width - 1) |
+ (target->drawable.height - 1) << 16);
OUT_BATCH(0x00000000); /* yorigin, xorigin */
- OUT_BATCH(MI_NOOP);
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) |
- I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 3);
+ I1_LOAD_S(5) | I1_LOAD_S(6) | 2);
OUT_BATCH(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) |
@@ -103,8 +125,6 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) |
S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT));
- OUT_BATCH((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE |
- S4_CULLMODE_NONE | S4_VFMT_XY);
s5 = 0x0;
if (intel->cpp == 2)
s5 |= S5_COLOR_DITHER_ENABLE;
@@ -129,17 +149,21 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
DSTORG_VERT_BIAS(0x8) | format);
/* front buffer, pitch, offset */
+ if (i830_pixmap_tiled(target)) {
+ tiling = BUF_3D_TILED_SURFACE;
+ if (i830_get_pixmap_intel(target)->tiling == I915_TILING_Y)
+ tiling |= BUF_3D_TILE_WALK_Y;
+ } else
+ tiling = 0;
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
- OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
- BUF_3D_PITCH(intel_get_pixmap_pitch(pixmap)));
- OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_RENDER,
+ OUT_BATCH(BUF_3D_ID_COLOR_BACK | tiling |
+ BUF_3D_PITCH(intel_get_pixmap_pitch(target)));
+ OUT_RELOC_PIXMAP(target, I915_GEM_DOMAIN_RENDER,
I915_GEM_DOMAIN_RENDER, 0);
- ADVANCE_BATCH();
if (!is_planar_fourcc(id)) {
- FS_LOCALS(10);
+ FS_LOCALS();
- ATOMIC_BATCH(16);
OUT_BATCH(_3DSTATE_PIXEL_SHADER_CONSTANTS | 4);
OUT_BATCH(0x0000001); /* constant 0 */
/* constant 0: brightness/contrast */
@@ -170,7 +194,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
else
OUT_BATCH(adaptor_priv->YBufOffset);
- ms3 = MAPSURF_422 | MS3_USE_FENCE_REGS;
+ ms3 = MAPSURF_422;
switch (id) {
case FOURCC_YUY2:
ms3 |= MT_422_YCRCB_NORMAL;
@@ -184,8 +208,6 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
OUT_BATCH(ms3);
OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
- ADVANCE_BATCH();
-
FS_BEGIN();
i915_fs_dcl(FS_S0);
i915_fs_dcl(FS_T0);
@@ -198,9 +220,8 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
}
FS_END();
} else {
- FS_LOCALS(16);
+ FS_LOCALS();
- ATOMIC_BATCH(22 + 11 + 11);
/* For the planar formats, we set up three samplers --
* one for each plane, in a Y8 format. Because I
* couldn't get the special PLANAR_TO_PACKED
@@ -292,7 +313,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
else
OUT_BATCH(adaptor_priv->YBufOffset);
- ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
+ ms3 = MAPSURF_8BIT | MT_8BIT_I8;
ms3 |= (height - 1) << MS3_HEIGHT_SHIFT;
ms3 |= (width - 1) << MS3_WIDTH_SHIFT;
OUT_BATCH(ms3);
@@ -314,7 +335,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
else
OUT_BATCH(adaptor_priv->UBufOffset);
- ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
+ ms3 = MAPSURF_8BIT | MT_8BIT_I8;
ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
OUT_BATCH(ms3);
@@ -327,12 +348,11 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
else
OUT_BATCH(adaptor_priv->VBufOffset);
- ms3 = MAPSURF_8BIT | MT_8BIT_I8 | MS3_USE_FENCE_REGS;
+ ms3 = MAPSURF_8BIT | MT_8BIT_I8;
ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT;
ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT;
OUT_BATCH(ms3);
OUT_BATCH(((video_pitch / 4) - 1) << MS4_PITCH_SHIFT);
- ADVANCE_BATCH();
FS_BEGIN();
/* Declare samplers */
@@ -365,15 +385,15 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
* color. The OC results are implicitly clamped
* at the end of the program.
*/
- i915_fs_dp3_masked(FS_OC, MASK_X,
- i915_fs_operand_reg(FS_R0),
- i915_fs_operand_reg(FS_C1));
- i915_fs_dp3_masked(FS_OC, MASK_Y,
- i915_fs_operand_reg(FS_R0),
- i915_fs_operand_reg(FS_C2));
- i915_fs_dp3_masked(FS_OC, MASK_Z,
- i915_fs_operand_reg(FS_R0),
- i915_fs_operand_reg(FS_C3));
+ i915_fs_dp3(FS_OC, MASK_X,
+ i915_fs_operand_reg(FS_R0),
+ i915_fs_operand_reg(FS_C1));
+ i915_fs_dp3(FS_OC, MASK_Y,
+ i915_fs_operand_reg(FS_R0),
+ i915_fs_operand_reg(FS_C2));
+ i915_fs_dp3(FS_OC, MASK_Z,
+ i915_fs_operand_reg(FS_R0),
+ i915_fs_operand_reg(FS_C3));
/* Set alpha of the output to 1.0, by wiring W to 1
* and not actually using the source.
*/
@@ -389,28 +409,7 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
FS_END();
}
- {
- ATOMIC_BATCH(2);
- OUT_BATCH(MI_FLUSH | MI_WRITE_DIRTY_STATE |
- MI_INVALIDATE_MAP_CACHE);
- OUT_BATCH(0x00000000);
- ADVANCE_BATCH();
- }
-
- /* Set up the offset for translating from the given region
- * (in screen coordinates) to the backing pixmap.
- */
-#ifdef COMPOSITE
- pix_xoff = -pixmap->screen_x + pixmap->drawable.x;
- pix_yoff = -pixmap->screen_y + pixmap->drawable.y;
-#else
- pix_xoff = 0;
- pix_yoff = 0;
-#endif
-
- dxo = dstRegion->extents.x1;
- dyo = dstRegion->extents.y1;
-
+ OUT_BATCH(PRIM3D_RECTLIST | (12 * nbox_this_time - 1));
while (nbox_this_time--) {
int box_x1 = pbox->x1;
int box_y1 = pbox->y1;
@@ -423,19 +422,9 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
src_scale_x = ((float)src_w / width) / drw_w;
src_scale_y = ((float)src_h / height) / drw_h;
- ATOMIC_BATCH(8 + 12);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
- OUT_BATCH(MI_NOOP);
-
/* vertex data - rect list consists of bottom right,
* bottom left, and top left vertices.
*/
- OUT_BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | (12 - 1));
/* bottom right */
OUT_BATCH_F(box_x2 + pix_xoff);
@@ -454,12 +443,39 @@ I915DisplayVideoTextured(ScrnInfoPtr scrn,
OUT_BATCH_F(box_y1 + pix_yoff);
OUT_BATCH_F((box_x1 - dxo) * src_scale_x);
OUT_BATCH_F((box_y1 - dyo) * src_scale_y);
-
- ADVANCE_BATCH();
}
intel_batch_end_atomic(scrn);
}
+ if (target != pixmap) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pixmap->drawable.depth,
+ pixmap->drawable.pScreen);
+ if (gc) {
+ RegionPtr tmp;
+
+ ValidateGC(&pixmap->drawable, gc);
+
+ if (REGION_NUM_RECTS(dstRegion) > 1) {
+ tmp = REGION_CREATE(pixmap->drawable.pScreen, NULL, 0);
+ if (tmp) {
+ REGION_COPY(pixmap->drawable.pScreen, tmp, dstRegion);
+ gc->funcs->ChangeClip(gc, CT_REGION, tmp, 0);
+ }
+ }
+
+ gc->ops->CopyArea(&target->drawable, &pixmap->drawable, gc,
+ 0, 0,
+ target->drawable.width,
+ target->drawable.height,
+ -pix_xoff, -pix_yoff);
+ FreeScratchGC(gc);
+ }
+
+ target->drawable.pScreen->DestroyPixmap(target);
+ }
+
i830_debug_flush(scrn);
}
diff --git a/driver/xf86-video-intel/src/i965_render.c b/driver/xf86-video-intel/src/i965_render.c
index 7866dd750..75d63807d 100644
--- a/driver/xf86-video-intel/src/i965_render.c
+++ b/driver/xf86-video-intel/src/i965_render.c
@@ -183,10 +183,52 @@ static Bool i965_get_dest_format(PicturePtr dest_picture, uint32_t * dst_format)
return TRUE;
}
-static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
- int unit)
+Bool
+i965_check_composite(int op,
+ PicturePtr source_picture,
+ PicturePtr mask_picture,
+ PicturePtr dest_picture,
+ int width, int height)
+{
+ ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
+ uint32_t tmp1;
+
+ /* Check for unsupported compositing operations. */
+ if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0])) {
+ intel_debug_fallback(scrn,
+ "Unsupported Composite op 0x%x\n", op);
+ return FALSE;
+ }
+
+ if (mask_picture && mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i965_blend_op[op].src_alpha &&
+ (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) {
+ intel_debug_fallback(scrn,
+ "Component alpha not supported "
+ "with source alpha and source "
+ "value blending.\n");
+ return FALSE;
+ }
+ }
+
+ if (!i965_get_dest_format(dest_picture, &tmp1)) {
+ intel_debug_fallback(scrn, "Get Color buffer format\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Bool
+i965_check_composite_texture(ScreenPtr screen, PicturePtr picture)
{
if (picture->repeatType > RepeatReflect) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn,
"extended repeat (%d) not supported\n",
picture->repeatType);
@@ -195,6 +237,7 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
if (picture->filter != PictFilterNearest &&
picture->filter != PictFilterBilinear) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn, "Unsupported filter 0x%x\n",
picture->filter);
return FALSE;
@@ -206,6 +249,7 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
w = picture->pDrawable->width;
h = picture->pDrawable->height;
if ((w > 8192) || (h > 8192)) {
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn,
"Picture w/h too large (%dx%d)\n",
w, h);
@@ -220,66 +264,21 @@ static Bool i965_check_composite_texture(ScrnInfoPtr scrn, PicturePtr picture,
}
if (i == sizeof(i965_tex_formats) / sizeof(i965_tex_formats[0]))
{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
intel_debug_fallback(scrn,
"Unsupported picture format "
"0x%x\n",
(int)picture->format);
return FALSE;
}
- }
-
- return TRUE;
-}
-
-Bool
-i965_check_composite(int op, PicturePtr source_picture, PicturePtr mask_picture,
- PicturePtr dest_picture)
-{
- ScrnInfoPtr scrn = xf86Screens[dest_picture->pDrawable->pScreen->myNum];
- uint32_t tmp1;
-
- /* Check for unsupported compositing operations. */
- if (op >= sizeof(i965_blend_op) / sizeof(i965_blend_op[0])) {
- intel_debug_fallback(scrn,
- "Unsupported Composite op 0x%x\n", op);
- return FALSE;
- }
-
- if (mask_picture && mask_picture->componentAlpha &&
- PICT_FORMAT_RGB(mask_picture->format)) {
- /* Check if it's component alpha that relies on a source alpha and on
- * the source value. We can only get one of those into the single
- * source value that we get to blend with.
- */
- if (i965_blend_op[op].src_alpha &&
- (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) {
- intel_debug_fallback(scrn,
- "Component alpha not supported "
- "with source alpha and source "
- "value blending.\n");
- return FALSE;
- }
- }
- if (!i965_check_composite_texture(scrn, source_picture, 0)) {
- intel_debug_fallback(scrn, "Check Src picture texture\n");
- return FALSE;
- }
- if (mask_picture != NULL
- && !i965_check_composite_texture(scrn, mask_picture, 1)) {
- intel_debug_fallback(scrn, "Check Mask picture texture\n");
- return FALSE;
+ return TRUE;
}
- if (!i965_get_dest_format(dest_picture, &tmp1)) {
- intel_debug_fallback(scrn, "Get Color buffer format\n");
- return FALSE;
- }
-
- return TRUE;
-
+ return FALSE;
}
+
#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1)
/* Set up a default static partitioning of the URB, which is supposed to
@@ -1143,6 +1142,12 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
IntelEmitInvarientState(scrn);
intel->last_3d = LAST_3D_RENDER;
+ /* Mark the destination dirty within this batch */
+ intel_batch_mark_pixmap_domains(intel,
+ i830_get_pixmap_intel(dest),
+ I915_GEM_DOMAIN_RENDER,
+ I915_GEM_DOMAIN_RENDER);
+
urb_vs_start = 0;
urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
urb_gs_start = urb_vs_start + urb_vs_size;
@@ -1167,12 +1172,8 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
*/
ALIGN_BATCH(64);
+ assert(intel->in_batch_atomic);
{
- if (IS_IGDNG(intel))
- ATOMIC_BATCH(14);
- else
- ATOMIC_BATCH(12);
-
/* Match Mesa driver setup */
OUT_BATCH(MI_FLUSH |
MI_STATE_INSTRUCTION_CACHE_FLUSH |
@@ -1215,12 +1216,17 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
OUT_BATCH(BRW_STATE_SIP | 0);
OUT_RELOC(render_state->sip_kernel_bo,
I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
- ADVANCE_BATCH();
+ }
+
+ if (IS_IGDNG(intel)) {
+ /* Ironlake errata workaround: Before disabling the clipper,
+ * you have to MI_FLUSH to get the pipeline idle.
+ */
+ OUT_BATCH(MI_FLUSH);
}
{
int pipe_ctrl;
- ATOMIC_BATCH(26);
/* Pipe control */
if (IS_IGDNG(intel))
@@ -1315,7 +1321,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
OUT_BATCH(BRW_CS_URB_STATE | 0);
OUT_BATCH(((URB_CS_ENTRY_SIZE - 1) << 4) |
(URB_CS_ENTRIES << 0));
- ADVANCE_BATCH();
}
{
/*
@@ -1342,7 +1347,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
}
if (IS_IGDNG(intel)) {
- ATOMIC_BATCH(mask ? 9 : 7);
/*
* The reason to add this extra vertex element in the header is that
* IGDNG has different vertex header definition and origin method to
@@ -1372,7 +1376,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
(BRW_VFCOMPONENT_STORE_0 <<
VE1_VFCOMPONENT_3_SHIFT));
} else {
- ATOMIC_BATCH(mask ? 7 : 5);
/* Set up our vertex elements, sourced from the single vertex buffer.
* that will be set up later.
*/
@@ -1434,8 +1437,6 @@ static void i965_emit_composite_state(ScrnInfoPtr scrn)
else
OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | (w_component << VE1_VFCOMPONENT_2_SHIFT) | (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | ((4 + 4 + 4) << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); /* VUE offset in dwords */
}
-
- ADVANCE_BATCH();
}
}
@@ -1496,6 +1497,22 @@ i965_prepare_composite(int op, PicturePtr source_picture,
}
if (mask_picture) {
+ if (mask_picture->componentAlpha &&
+ PICT_FORMAT_RGB(mask_picture->format)) {
+ /* Check if it's component alpha that relies on a source alpha and on
+ * the source value. We can only get one of those into the single
+ * source value that we get to blend with.
+ */
+ if (i965_blend_op[op].src_alpha &&
+ (i965_blend_op[op].src_blend != BRW_BLENDFACTOR_ZERO)) {
+ intel_debug_fallback(scrn,
+ "Component alpha not supported "
+ "with source alpha and source "
+ "value blending.\n");
+ return FALSE;
+ }
+ }
+
composite_op->mask_filter =
sampler_state_filter_from_picture(mask_picture->filter);
if (composite_op->mask_filter < 0) {
@@ -1515,6 +1532,12 @@ i965_prepare_composite(int op, PicturePtr source_picture,
composite_op->mask_extend = SAMPLER_STATE_EXTEND_NONE;
}
+ /* Flush any pending writes prior to relocating the textures. */
+ if(i830_uxa_pixmap_is_dirty(source) ||
+ (mask && i830_uxa_pixmap_is_dirty(mask)))
+ intel_batch_emit_flush(scrn);
+
+
/* Set up the surface states. */
surface_state_bo = dri_bo_alloc(intel->bufmgr, "surface_state",
3 * sizeof(brw_surface_state_padded),
@@ -1638,7 +1661,7 @@ i965_prepare_composite(int op, PicturePtr source_picture,
}
if (!i965_composite_check_aperture(scrn)) {
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
if (!i965_composite_check_aperture(scrn)) {
intel_debug_fallback(scrn,
"Couldn't fit render operation "
@@ -1647,10 +1670,6 @@ i965_prepare_composite(int op, PicturePtr source_picture,
}
}
- if(i830_uxa_pixmap_is_dirty(source) ||
- (mask && i830_uxa_pixmap_is_dirty(mask)))
- intel_batch_emit_flush(scrn);
-
intel->needs_render_state_emit = TRUE;
return TRUE;
@@ -1815,13 +1834,12 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY,
drm_intel_bo_subdata(vb_bo, render_state->vb_offset * 4, i * 4, vb);
if (!i965_composite_check_aperture(scrn))
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
intel_batch_start_atomic(scrn, 200);
if (intel->needs_render_state_emit)
i965_emit_composite_state(scrn);
- ATOMIC_BATCH(12);
OUT_BATCH(MI_FLUSH);
/* Set up the pointer to our (single) vertex buffer */
OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3);
@@ -1846,7 +1864,6 @@ i965_composite(PixmapPtr dest, int srcX, int srcY, int maskX, int maskY,
OUT_BATCH(1); /* single instance */
OUT_BATCH(0); /* start instance location */
OUT_BATCH(0); /* index buffer offset, ignored */
- ADVANCE_BATCH();
render_state->vb_offset += i;
drm_intel_bo_unreference(vb_bo);
diff --git a/driver/xf86-video-intel/src/i965_video.c b/driver/xf86-video-intel/src/i965_video.c
index c5378608e..e25184b6a 100644
--- a/driver/xf86-video-intel/src/i965_video.c
+++ b/driver/xf86-video-intel/src/i965_video.c
@@ -779,18 +779,12 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf)
urb_cs_start = urb_sf_start + urb_sf_size;
urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
- ATOMIC_BATCH(2);
OUT_BATCH(MI_FLUSH |
MI_STATE_INSTRUCTION_CACHE_FLUSH |
BRW_MI_GLOBAL_SNAPSHOT_RESET);
OUT_BATCH(MI_NOOP);
- ADVANCE_BATCH();
/* brw_debug (scrn, "before base address modify"); */
- if (IS_IGDNG(intel))
- ATOMIC_BATCH(14);
- else
- ATOMIC_BATCH(12);
/* Match Mesa driver setup */
if (IS_G4X(intel) || IS_IGDNG(intel))
OUT_BATCH(NEW_PIPELINE_SELECT | PIPELINE_SELECT_3D);
@@ -834,9 +828,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf)
OUT_RELOC(intel->video.gen4_sip_kernel_bo,
I915_GEM_DOMAIN_INSTRUCTION, 0, 0);
- OUT_BATCH(MI_NOOP);
- ADVANCE_BATCH();
-
/* brw_debug (scrn, "after base address modify"); */
if (IS_IGDNG(intel))
@@ -844,10 +835,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf)
else
pipe_ctl = BRW_PIPE_CONTROL_NOWRITE | BRW_PIPE_CONTROL_IS_FLUSH;
- ATOMIC_BATCH(38);
-
- OUT_BATCH(MI_NOOP);
-
/* Pipe control */
OUT_BATCH(BRW_PIPE_CONTROL | pipe_ctl | 2);
OUT_BATCH(0); /* Destination address */
@@ -971,9 +958,6 @@ i965_emit_video_setup(ScrnInfoPtr scrn, drm_intel_bo * bind_bo, int n_src_surf)
VE1_VFCOMPONENT_3_SHIFT) | (4 <<
VE1_DESTINATION_ELEMENT_OFFSET_SHIFT));
}
-
- OUT_BATCH(MI_NOOP); /* pad to quadword */
- ADVANCE_BATCH();
}
void
@@ -1213,14 +1197,13 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn,
if (drm_intel_bufmgr_check_aperture_space(bo_table,
ARRAY_SIZE(bo_table))
< 0) {
- intel_batch_submit(scrn);
+ intel_batch_submit(scrn, FALSE);
}
intel_batch_start_atomic(scrn, 100);
i965_emit_video_setup(scrn, bind_bo, n_src_surf);
- ATOMIC_BATCH(12);
/* Set up the pointer to our vertex buffer */
OUT_BATCH(BRW_3DSTATE_VERTEX_BUFFERS | 3);
/* four 32-bit floats per vertex */
@@ -1242,7 +1225,6 @@ I965DisplayVideoTextured(ScrnInfoPtr scrn,
OUT_BATCH(0); /* start instance location */
OUT_BATCH(0); /* index buffer offset, ignored */
OUT_BATCH(MI_NOOP);
- ADVANCE_BATCH();
intel_batch_end_atomic(scrn);
diff --git a/driver/xf86-video-intel/src/xvmc/i965_xvmc.c b/driver/xf86-video-intel/src/xvmc/i965_xvmc.c
index 1665f6d00..52b93e327 100644
--- a/driver/xf86-video-intel/src/xvmc/i965_xvmc.c
+++ b/driver/xf86-video-intel/src/xvmc/i965_xvmc.c
@@ -207,7 +207,7 @@ struct media_state {
};
struct media_state media_state;
-static int free_object(struct media_state *s)
+static void free_object(struct media_state *s)
{
int i;
#define FREE_ONE_BO(bo) drm_intel_bo_unreference(bo)
diff --git a/driver/xf86-video-intel/src/xvmc/xvmc_vld.c b/driver/xf86-video-intel/src/xvmc/xvmc_vld.c
index 5687593a7..9ef840b36 100644
--- a/driver/xf86-video-intel/src/xvmc/xvmc_vld.c
+++ b/driver/xf86-video-intel/src/xvmc/xvmc_vld.c
@@ -354,7 +354,7 @@ static struct media_state {
/* XvMCQMatrix * 2 + idct_table + 8 * kernel offset pointer */
#define CS_OBJECT_SIZE (32*20 + sizeof(unsigned int) * 8)
-static int free_object(struct media_state *s)
+static void free_object(struct media_state *s)
{
int i;
#define FREE_ONE_BO(bo) \
diff --git a/driver/xf86-video-intel/uxa/uxa-accel.c b/driver/xf86-video-intel/uxa/uxa-accel.c
index bede1f41f..245738a65 100644
--- a/driver/xf86-video-intel/uxa/uxa-accel.c
+++ b/driver/xf86-video-intel/uxa/uxa-accel.c
@@ -34,33 +34,185 @@
#include <X11/fonts/fontstruct.h>
#include "dixfontstr.h"
#include "uxa.h"
+#include "mipict.h"
+
+static CARD32
+format_for_depth(int depth)
+{
+ switch (depth) {
+ case 1: return PICT_a1;
+ case 4: return PICT_a4;
+ case 8: return PICT_a8;
+ case 15: return PICT_x1r5g5b5;
+ case 16: return PICT_r5g6b5;
+ default:
+ case 24: return PICT_x8r8g8b8;
+#if 0
+ case 30: return PICT_x2r10g10b10;
+#endif
+ case 32: return PICT_a8r8g8b8;
+ }
+}
static void
uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
- ScreenPtr pScreen = pDrawable->pScreen;
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
+ ScreenPtr screen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ PixmapPtr dst_pixmap, src_pixmap = NULL;
BoxPtr pextent, pbox;
int nbox;
int extentX1, extentX2, extentY1, extentY2;
int fullX1, fullX2, fullY1;
int partX1, partX2;
int off_x, off_y;
+ xRenderColor color;
+ PictFormatPtr format;
+ PicturePtr dst, src;
+ int error;
+
+ if (uxa_screen->swappedOut)
+ goto fallback;
+
+ if (pGC->fillStyle != FillSolid)
+ goto fallback;
+
+ dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y);
+ if (!dst_pixmap)
+ goto fallback;
+
+ if (pGC->alu != GXcopy || pGC->planemask != FB_ALLONES)
+ goto solid;
+
+ format = PictureMatchFormat(screen,
+ dst_pixmap->drawable.depth,
+ format_for_depth(dst_pixmap->drawable.depth));
+ dst = CreatePicture(0, &dst_pixmap->drawable, format, 0, 0, serverClient, &error);
+ if (!dst)
+ goto solid;
+
+ ValidatePicture(dst);
+
+ uxa_get_rgba_from_pixel(pGC->fgPixel,
+ &color.red,
+ &color.green,
+ &color.blue,
+ &color.alpha,
+ format_for_depth(dst_pixmap->drawable.depth));
+ src = CreateSolidPicture(0, &color, &error);
+ if (!src) {
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+ }
- if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid ||
- !(pPixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y)) ||
- !(*uxa_screen->info->prepare_solid) (pPixmap,
+ if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, dst_pixmap)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto solid;
+ }
+
+ pextent = REGION_EXTENTS(pGC->screen, pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (n--) {
+ fullX1 = ppt->x;
+ fullY1 = ppt->y;
+ fullX2 = fullX1 + (int)*pwidth;
+ ppt++;
+ pwidth++;
+
+ if (fullY1 < extentY1 || extentY2 <= fullY1)
+ continue;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullX1 >= fullX2)
+ continue;
+
+ nbox = REGION_NUM_RECTS(pClip);
+ if (nbox == 1) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ fullX1 + off_x,
+ fullY1 + off_y,
+ fullX2 - fullX1, 1);
+ } else {
+ pbox = REGION_RECTS(pClip);
+ while (nbox--) {
+ if (pbox->y1 > fullY1)
+ break;
+
+ if (pbox->y1 <= fullY1) {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+
+ if (partX2 > partX1) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ partX1 + off_x,
+ fullY1 + off_y,
+ partX2 - partX1, 1);
+ }
+ }
+ pbox++;
+ }
+ }
+ }
+
+ uxa_screen->info->done_composite(dst_pixmap);
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ return;
+
+solid:
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask))
+ goto fallback;
+
+ if (!(*uxa_screen->info->prepare_solid) (dst_pixmap,
pGC->alu,
pGC->planemask,
- pGC->fgPixel)) {
- uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
- return;
- }
+ pGC->fgPixel))
+ goto fallback;
- pextent = REGION_EXTENTS(pGC->pScreen, pClip);
+ pextent = REGION_EXTENTS(pGC->screen, pClip);
extentX1 = pextent->x1;
extentY1 = pextent->y1;
extentX2 = pextent->x2;
@@ -86,7 +238,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
nbox = REGION_NUM_RECTS(pClip);
if (nbox == 1) {
- (*uxa_screen->info->solid) (pPixmap,
+ (*uxa_screen->info->solid) (dst_pixmap,
fullX1 + off_x,
fullY1 + off_y,
fullX2 + off_x,
@@ -103,7 +255,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
partX2 = fullX2;
if (partX2 > partX1) {
(*uxa_screen->info->
- solid) (pPixmap,
+ solid) (dst_pixmap,
partX1 + off_x,
fullY1 + off_y,
partX2 + off_x,
@@ -114,7 +266,12 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
}
}
}
- (*uxa_screen->info->done_solid) (pPixmap);
+ (*uxa_screen->info->done_solid) (dst_pixmap);
+
+ return;
+
+fallback:
+ uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
}
static Bool
@@ -204,92 +361,12 @@ uxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
return TRUE;
}
-#ifdef MITSHM
-
-#include "xorgVersion.h"
-
-static Bool
-uxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
- unsigned int format, int w, int h, int sx, int sy, int sw,
- int sh, int dx, int dy, char *data)
-{
- int src_stride = PixmapBytePad(w, depth);
-
- if (uxa_do_put_image
- (pDrawable, pGC, depth, dx, dy, sw, sh, format,
- data + sy * src_stride + sx * BitsPerPixel(depth) / 8, src_stride))
- return TRUE;
-
- if (format == ZPixmap) {
- PixmapPtr pPixmap;
-
- pPixmap =
- GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth,
- BitsPerPixel(depth), PixmapBytePad(w,
- depth),
- (pointer) data);
- if (!pPixmap)
- return FALSE;
-
- if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
- FreeScratchPixmapHeader(pPixmap);
- return FALSE;
- }
-
- fbCopyArea((DrawablePtr) pPixmap, pDrawable, pGC, sx, sy, sw,
- sh, dx, dy);
- uxa_finish_access(pDrawable);
-
- FreeScratchPixmapHeader(pPixmap);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
-
-/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to
- * inform any interested parties of the damage incurred to the drawable.
- *
- * We also need to set the pending damage to ensure correct migration in all
- * cases.
- */
-void
-uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
- unsigned int format, int w, int h, int sx, int sy, int sw,
- int sh, int dx, int dy, char *data)
-{
- if (!uxa_do_shm_put_image
- (pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
- data)) {
- if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW))
- return;
- fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw,
- sh, dx, dy, data);
- uxa_finish_access(pDrawable);
- }
-}
-#else
-#define uxa_shm_put_image NULL
-#endif
-
-ShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image };
-
-#endif
-
static void
uxa_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int w, int h, int leftPad, int format, char *bits)
{
-#ifdef MITSHM
- if (!uxa_do_shm_put_image
- (pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y, bits))
-#else
if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits,
PixmapBytePad(w, pDrawable->depth)))
-#endif
uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad,
format, bits);
}
@@ -435,6 +512,14 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable);
pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable);
+ if (!pSrcPixmap || !pDstPixmap)
+ goto fallback;
+
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES))
+ goto fallback;
uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x,
&src_off_y);
@@ -450,8 +535,45 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
goto fallback;
}
- if (!uxa_pixmap_is_offscreen(pDstPixmap))
- goto fallback;
+ if (!uxa_pixmap_is_offscreen(pDstPixmap)) {
+ int stride, bpp;
+ char *dst;
+
+ if (!uxa_pixmap_is_offscreen(pSrcPixmap))
+ goto fallback;
+
+ if (!uxa_screen->info->get_image)
+ goto fallback;
+
+ /* Don't bother with under 8bpp, XYPixmaps. */
+ bpp = pSrcPixmap->drawable.bitsPerPixel;
+ if (bpp != pDstDrawable->bitsPerPixel || bpp < 8)
+ goto fallback;
+
+ /* Only accelerate copies: no rop or planemask. */
+ if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy))
+ goto fallback;
+
+ dst = pDstPixmap->devPrivate.ptr;
+ stride = pDstPixmap->devKind;
+ bpp /= 8;
+ while (nbox--) {
+ if (!uxa_screen->info->get_image(pSrcPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1,
+ (char *) dst +
+ (pbox->y1 + dst_off_y) * stride +
+ (pbox->x1 + dst_off_x) * bpp,
+ stride))
+ goto fallback;
+
+ pbox++;
+ }
+
+ return;
+ }
if (uxa_pixmap_is_offscreen(pSrcPixmap)) {
if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap,
@@ -558,7 +680,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
return;
}
- prect = xalloc(sizeof(xRectangle) * npt);
+ prect = malloc(sizeof(xRectangle) * npt);
if (!prect)
return;
for (i = 0; i < npt; i++) {
@@ -572,7 +694,7 @@ uxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
prect[i].height = 1;
}
pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
- xfree(prect);
+ free(prect);
}
/**
@@ -595,7 +717,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
return;
}
- prect = xalloc(sizeof(xRectangle) * (npt - 1));
+ prect = malloc(sizeof(xRectangle) * (npt - 1));
if (!prect)
return;
x1 = ppt[0].x;
@@ -611,7 +733,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
}
if (x1 != x2 && y1 != y2) {
- xfree(prect);
+ free(prect);
uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
return;
}
@@ -635,7 +757,7 @@ uxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
y1 = y2;
}
pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
- xfree(prect);
+ free(prect);
}
/**
@@ -664,7 +786,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
}
}
- prect = xalloc(sizeof(xRectangle) * nseg);
+ prect = malloc(sizeof(xRectangle) * nseg);
if (!prect)
return;
for (i = 0; i < nseg; i++) {
@@ -692,7 +814,7 @@ uxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
}
}
pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
- xfree(prect);
+ free(prect);
}
static Bool uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion,
@@ -704,7 +826,7 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ PixmapPtr pPixmap;
register BoxPtr pbox;
BoxPtr pextent;
int extentX1, extentX2, extentY1, extentY2;
@@ -722,11 +844,13 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
if (!REGION_NUM_RECTS(pReg))
goto out;
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
-
if (uxa_screen->swappedOut)
goto fallback;
+ pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff);
+ if (!pPixmap)
+ goto fallback;
+
/* For ROPs where overlaps don't matter, convert rectangles to region
* and call uxa_fill_region_{solid,tiled}.
*/
@@ -752,8 +876,12 @@ uxa_poly_fill_rect(DrawablePtr pDrawable,
goto fallback;
}
- if (!uxa_pixmap_is_offscreen(pPixmap) ||
- !(*uxa_screen->info->prepare_solid) (pPixmap,
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) {
+ goto fallback;
+ }
+
+ if (!(*uxa_screen->info->prepare_solid) (pPixmap,
pGC->alu,
pGC->planemask,
pGC->fgPixel)) {
@@ -896,35 +1024,121 @@ uxa_fill_region_solid(DrawablePtr pDrawable,
RegionPtr pRegion,
Pixel pixel, CARD32 planemask, CARD32 alu)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen);
- PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
+ ScreenPtr screen = pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr pixmap;
int xoff, yoff;
+ int nbox;
+ BoxPtr pBox, extents;
Bool ret = FALSE;
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
- REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+ pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
+ if (!pixmap)
+ return FALSE;
- if (uxa_pixmap_is_offscreen(pPixmap) &&
- (*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel))
- {
- int nbox;
- BoxPtr pBox;
+ REGION_TRANSLATE(screen, pRegion, xoff, yoff);
- nbox = REGION_NUM_RECTS(pRegion);
- pBox = REGION_RECTS(pRegion);
+ nbox = REGION_NUM_RECTS(pRegion);
+ pBox = REGION_RECTS(pRegion);
+ extents = REGION_EXTENTS(screen, pRegion);
+
+ /* Using GEM, the relocation costs outweigh the advantages of the blitter */
+ if (nbox == 1 || (alu != GXcopy && alu != GXclear) || planemask != FB_ALLONES) {
+try_solid:
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(&pixmap->drawable, alu, planemask))
+ goto err;
+
+ if (!uxa_screen->info->prepare_solid(pixmap, alu, planemask, pixel))
+ goto err;
while (nbox--) {
- (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1,
- pBox->x2, pBox->y2);
+ uxa_screen->info->solid(pixmap,
+ pBox->x1, pBox->y1,
+ pBox->x2, pBox->y2);
pBox++;
}
- (*uxa_screen->info->done_solid) (pPixmap);
- ret = TRUE;
+ uxa_screen->info->done_solid(pixmap);
+ } else {
+ PicturePtr dst, src;
+ PixmapPtr src_pixmap = NULL;
+ xRenderColor color;
+ int error;
+
+ dst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen,
+ pixmap->drawable.depth,
+ format_for_depth(pixmap->drawable.depth)),
+ 0, 0, serverClient, &error);
+ if (!dst)
+ goto err;
+
+ ValidatePicture(dst);
+
+ uxa_get_rgba_from_pixel(pixel,
+ &color.red,
+ &color.green,
+ &color.blue,
+ &color.alpha,
+ format_for_depth(pixmap->drawable.depth));
+ src = CreateSolidPicture(0, &color, &error);
+ if (!src) {
+ FreePicture(dst, 0);
+ goto err;
+ }
+
+ if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst,
+ extents->x2 - extents->x1,
+ extents->y2 - extents->y1)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto try_solid;
+ }
+
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto err;
+ }
+ }
+
+ if (!uxa_screen->info->prepare_composite(PictOpSrc, src, NULL, dst, src_pixmap, NULL, pixmap)) {
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
+ goto err;
+ }
+
+ while (nbox--) {
+ uxa_screen->info->composite(pixmap,
+ 0, 0, 0, 0,
+ pBox->x1,
+ pBox->y1,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1);
+ pBox++;
+ }
+
+ uxa_screen->info->done_composite(pixmap);
+ FreePicture(src, 0);
+ FreePicture(dst, 0);
}
- REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff);
+ ret = TRUE;
+err:
+ REGION_TRANSLATE(screen, pRegion, -xoff, -yoff);
return ret;
}
@@ -956,15 +1170,16 @@ uxa_fill_region_tiled(DrawablePtr pDrawable,
uxa_get_pixmap_first_pixel(pTile),
planemask, alu);
- pPixmap = uxa_get_drawable_pixmap(pDrawable);
- uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff);
- REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
-
pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff);
-
if (!pPixmap || !uxa_pixmap_is_offscreen(pTile))
goto out;
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask))
+ return FALSE;
+
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu,
planemask)) {
while (nbox--) {
diff --git a/driver/xf86-video-intel/uxa/uxa-glyphs.c b/driver/xf86-video-intel/uxa/uxa-glyphs.c
index 5c233216a..823cf82f7 100644
--- a/driver/xf86-video-intel/uxa/uxa-glyphs.c
+++ b/driver/xf86-video-intel/uxa/uxa-glyphs.c
@@ -1,11 +1,29 @@
/*
- * Copyright © 2008 Red Hat, Inc.
+ * Copyright © 2010 Intel Corporation
+ * Partly based on code Copyright © 2008 Red Hat, Inc.
* Partly based on code Copyright © 2000 SuSE, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Intel not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Intel makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL INTEL
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
* documentation, and that the name of Red Hat not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Red Hat makes no representations about the
@@ -16,7 +34,7 @@
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Permission to use, copy, modify, distribute, and sell this software and its
@@ -33,11 +51,11 @@
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * Author: Owen Taylor <otaylor@fishsoup.net>
- * Based on code by: Keith Packard
+ * Author: Chris Wilson <chris@chris-wilson.co.uk>
+ * Based on code by: Keith Packard <keithp@keithp.com> and Owen Taylor <otaylor@fishsoup.net>
*/
#ifdef HAVE_DIX_CONFIG_H
@@ -51,99 +69,63 @@
#include "mipict.h"
-#if DEBUG_GLYPH_CACHE
-#define DBG_GLYPH_CACHE(a) ErrorF a
-#else
-#define DBG_GLYPH_CACHE(a)
-#endif
-
/* Width of the pixmaps we use for the caches; this should be less than
* max texture size of the driver; this may need to actually come from
* the driver.
*/
-#define CACHE_PICTURE_WIDTH 1024
-
-/* Maximum number of glyphs we buffer on the stack before flushing
- * rendering to the mask or destination surface.
- */
-#define GLYPH_BUFFER_SIZE 256
-
-typedef struct {
- PicturePtr source;
- uxa_composite_rect_t rects[GLYPH_BUFFER_SIZE];
- int count;
-} uxa_glyph_buffer_t;
-
-typedef enum {
- UXA_GLYPH_SUCCESS, /* Glyph added to render buffer */
- UXA_GLYPH_FAIL, /* out of memory, etc */
- UXA_GLYPH_NEED_FLUSH, /* would evict a glyph already in the buffer */
-} uxa_glyph_cache_result_t;
+#define CACHE_PICTURE_SIZE 1024
+#define GLYPH_MIN_SIZE 8
+#define GLYPH_MAX_SIZE 64
+#define GLYPH_CACHE_SIZE (CACHE_PICTURE_SIZE * CACHE_PICTURE_SIZE / (GLYPH_MIN_SIZE * GLYPH_MIN_SIZE))
+
+struct uxa_glyph {
+ uxa_glyph_cache_t *cache;
+ uint16_t x, y;
+ uint16_t size, pos;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+static DevPrivateKeyRec uxa_glyph_key;
+#else
+static int uxa_glyph_key;
+#endif
-void uxa_glyphs_init(ScreenPtr pScreen)
+static inline struct uxa_glyph *uxa_glyph_get_private(GlyphPtr glyph)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int i = 0;
-
- memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&glyph->devPrivates, &uxa_glyph_key);
+#else
+ return dixLookupPrivate(&glyph->devPrivates, &uxa_glyph_key);
+#endif
+}
- uxa_screen->glyphCaches[i].format = PICT_a8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 16;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 32;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 16;
- i++;
- uxa_screen->glyphCaches[i].format = PICT_a8r8g8b8;
- uxa_screen->glyphCaches[i].glyphWidth =
- uxa_screen->glyphCaches[i].glyphHeight = 32;
- i++;
-
- assert(i == UXA_NUM_GLYPH_CACHES);
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_screen->glyphCaches[i].columns =
- CACHE_PICTURE_WIDTH / uxa_screen->glyphCaches[i].glyphWidth;
- uxa_screen->glyphCaches[i].size = 256;
- uxa_screen->glyphCaches[i].hashSize = 557;
- }
+static inline void uxa_glyph_set_private(GlyphPtr glyph, struct uxa_glyph *priv)
+{
+ dixSetPrivate(&glyph->devPrivates, &uxa_glyph_key, priv);
}
-static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format)
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
+static void uxa_unrealize_glyph_caches(ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
int i;
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ for (i = 0; i < UXA_NUM_GLYPH_CACHE_FORMATS; i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- if (cache->format != format)
- continue;
-
- if (cache->picture) {
- FreePicture((pointer) cache->picture, (XID) 0);
- cache->picture = NULL;
- }
-
- if (cache->hashEntries) {
- xfree(cache->hashEntries);
- cache->hashEntries = NULL;
- }
+ if (cache->picture)
+ FreePicture(cache->picture, 0);
- if (cache->glyphs) {
- xfree(cache->glyphs);
- cache->glyphs = NULL;
- }
- cache->glyphCount = 0;
+ if (cache->glyphs)
+ free(cache->glyphs);
}
}
-#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+void uxa_glyphs_fini(ScreenPtr pScreen)
+{
+ uxa_unrealize_glyph_caches(pScreen);
+}
/* All caches for a single format share a single pixmap for glyph storage,
* allowing mixing glyphs of different sizes without paying a penalty
@@ -154,460 +136,176 @@ static void uxa_unrealize_glyph_caches(ScreenPtr pScreen, unsigned int format)
* This function allocates the storage pixmap, and then fills in the
* rest of the allocated structures for all caches with the given format.
*/
-static Bool uxa_realize_glyph_caches(ScreenPtr pScreen, unsigned int format)
+static Bool uxa_realize_glyph_caches(ScreenPtr pScreen)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int depth = PIXMAN_FORMAT_DEPTH(format);
- PictFormatPtr pPictFormat;
- PixmapPtr pPixmap;
- PicturePtr pPicture;
- CARD32 component_alpha;
- int height;
+ unsigned int formats[] = {
+ PIXMAN_a8,
+ PIXMAN_a8r8g8b8,
+ };
int i;
- int error;
- pPictFormat = PictureMatchFormat(pScreen, depth, format);
- if (!pPictFormat)
- return FALSE;
-
- /* Compute the total vertical size needed for the format */
+ memset(uxa_screen->glyphCaches, 0, sizeof(uxa_screen->glyphCaches));
- height = 0;
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
+ for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- int rows;
-
- if (cache->format != format)
- continue;
-
- cache->yOffset = height;
-
- rows = (cache->size + cache->columns - 1) / cache->columns;
- height += rows * cache->glyphHeight;
- }
-
- /* Now allocate the pixmap and picture */
-
- pPixmap = (*pScreen->CreatePixmap) (pScreen,
- CACHE_PICTURE_WIDTH,
- height, depth,
- INTEL_CREATE_PIXMAP_TILING_X);
- if (!pPixmap)
- return FALSE;
-
- component_alpha = NeedsComponent(pPictFormat->format);
- pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
- CPComponentAlpha, &component_alpha,
- serverClient, &error);
-
- (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
+ PixmapPtr pixmap;
+ PicturePtr picture;
+ CARD32 component_alpha;
+ int depth = PIXMAN_FORMAT_DEPTH(formats[i]);
+ int error;
+ PictFormatPtr pPictFormat = PictureMatchFormat(pScreen, depth, formats[i]);
+ if (!pPictFormat)
+ goto bail;
- if (!pPicture)
- return FALSE;
+ /* Now allocate the pixmap and picture */
+ pixmap = pScreen->CreatePixmap(pScreen,
+ CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE, depth,
+ INTEL_CREATE_PIXMAP_TILING_X);
+ if (!pixmap)
+ goto bail;
+ assert (uxa_pixmap_is_offscreen(pixmap));
- /* And store the picture in all the caches for the format */
+ component_alpha = NeedsComponent(pPictFormat->format);
+ picture = CreatePicture(0, &pixmap->drawable, pPictFormat,
+ CPComponentAlpha, &component_alpha,
+ serverClient, &error);
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- int j;
+ pScreen->DestroyPixmap(pixmap);
- if (cache->format != format)
- continue;
+ if (!picture)
+ goto bail;
- cache->picture = pPicture;
- cache->picture->refcnt++;
- cache->hashEntries = xalloc(sizeof(int) * cache->hashSize);
- cache->glyphs =
- xalloc(sizeof(uxa_cached_glyph_t) * cache->size);
- cache->glyphCount = 0;
+ ValidatePicture(picture);
- if (!cache->hashEntries || !cache->glyphs)
+ cache->picture = picture;
+ cache->glyphs = calloc(sizeof(GlyphPtr), GLYPH_CACHE_SIZE);
+ if (!cache->glyphs)
goto bail;
- for (j = 0; j < cache->hashSize; j++)
- cache->hashEntries[j] = -1;
-
- cache->evictionPosition = rand() % cache->size;
+ cache->evict = rand() % GLYPH_CACHE_SIZE;
}
+ assert(i == UXA_NUM_GLYPH_CACHE_FORMATS);
- /* Each cache references the picture individually */
- FreePicture((pointer) pPicture, (XID) 0);
return TRUE;
bail:
- uxa_unrealize_glyph_caches(pScreen, format);
+ uxa_unrealize_glyph_caches(pScreen);
return FALSE;
}
-void uxa_glyphs_fini(ScreenPtr pScreen)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- int i;
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
- if (cache->picture)
- uxa_unrealize_glyph_caches(pScreen, cache->format);
- }
-}
-
-static int
-uxa_glyph_cache_hash_lookup(uxa_glyph_cache_t * cache, GlyphPtr pGlyph)
+Bool uxa_glyphs_init(ScreenPtr pScreen)
{
- int slot;
-
- slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- int entryPos = cache->hashEntries[slot];
- if (entryPos == -1)
- return -1;
-
- if (memcmp
- (pGlyph->sha1, cache->glyphs[entryPos].sha1,
- sizeof(pGlyph->sha1)) == 0) {
- return entryPos;
- }
-
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
-}
-
-static void
-uxa_glyph_cache_hash_insert(uxa_glyph_cache_t * cache, GlyphPtr pGlyph, int pos)
-{
- int slot;
-
- memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
-
- slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- if (cache->hashEntries[slot] == -1) {
- cache->hashEntries[slot] = pos;
- return;
- }
-
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
-}
-
-static void uxa_glyph_cache_hash_remove(uxa_glyph_cache_t * cache, int pos)
-{
- int slot;
- int emptiedSlot = -1;
-
- slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
-
- while (TRUE) { /* hash table can never be full */
- int entryPos = cache->hashEntries[slot];
+ /* We are trying to initialise per screen resources prior to the
+ * complete initialisation of the screen. So ensure the components
+ * that we depend upon are initialsed prior to our use.
+ */
+ if (!CreateScratchPixmapsForScreen(pScreen->myNum))
+ return FALSE;
- if (entryPos == -1)
- return;
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&uxa_glyph_key, PRIVATE_GLYPH, 0))
+ return FALSE;
+#else
+ if (!dixRequestPrivate(&uxa_glyph_key, 0))
+ return FALSE;
+#endif
- if (entryPos == pos) {
- cache->hashEntries[slot] = -1;
- emptiedSlot = slot;
- } else if (emptiedSlot != -1) {
- /* See if we can move this entry into the emptied slot,
- * we can't do that if if entry would have hashed
- * between the current position and the emptied slot.
- * (taking wrapping into account). Bad positions
- * are:
- *
- * | XXXXXXXXXX |
- * i j
- *
- * |XXX XXXX|
- * j i
- *
- * i - slot, j - emptiedSlot
- *
- * (Knuth 6.4R)
- */
-
- int entrySlot =
- (*(CARD32 *) cache->glyphs[entryPos].sha1) %
- cache->hashSize;
-
- if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
- (emptiedSlot < slot
- && (entrySlot < emptiedSlot
- || entrySlot >= slot)))) {
- cache->hashEntries[emptiedSlot] = entryPos;
- cache->hashEntries[slot] = -1;
- emptiedSlot = slot;
- }
- }
+ if (!uxa_realize_glyph_caches(pScreen))
+ return FALSE;
- slot--;
- if (slot < 0)
- slot = cache->hashSize - 1;
- }
+ return TRUE;
}
-#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
-#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
-
/* The most efficient thing to way to upload the glyph to the screen
* is to use CopyArea; uxa pixmaps are always offscreen.
*/
-static Bool
-uxa_glyph_cache_upload_glyph(ScreenPtr pScreen,
+static void
+uxa_glyph_cache_upload_glyph(ScreenPtr screen,
uxa_glyph_cache_t * cache,
- int pos, GlyphPtr pGlyph)
+ GlyphPtr glyph,
+ int x, int y)
{
- PicturePtr pGlyphPicture = GlyphPicture(pGlyph)[pScreen->myNum];
+ PicturePtr pGlyphPicture = GlyphPicture(glyph)[screen->myNum];
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
PixmapPtr scratch;
- GCPtr pGC;
+ GCPtr gc;
- /* UploadToScreen only works if bpp match */
- if (pGlyphPixmap->drawable.bitsPerPixel !=
- pCachePixmap->drawable.bitsPerPixel)
- return FALSE;
+ gc = GetScratchGC(pCachePixmap->drawable.depth, screen);
+ if (!gc)
+ return;
- pGC = GetScratchGC(pCachePixmap->drawable.depth, pScreen);
- ValidateGC(&pCachePixmap->drawable, pGC);
+ ValidateGC(&pCachePixmap->drawable, gc);
+ scratch = pGlyphPixmap;
/* Create a temporary bo to stream the updates to the cache */
- scratch = (*pScreen->CreatePixmap)(pScreen,
- pGlyph->info.width,
- pGlyph->info.height,
- pGlyphPixmap->drawable.depth,
- UXA_CREATE_PIXMAP_FOR_MAP);
- if (scratch) {
- (void)uxa_copy_area(&pGlyphPixmap->drawable,
- &scratch->drawable,
- pGC,
- 0, 0,
- pGlyph->info.width, pGlyph->info.height,
- 0, 0);
- } else {
- scratch = pGlyphPixmap;
- }
-
- (void)uxa_copy_area(&scratch->drawable,
- &pCachePixmap->drawable,
- pGC,
- 0, 0, pGlyph->info.width, pGlyph->info.height,
- CACHE_X(pos), CACHE_Y(pos));
-
- if (scratch != pGlyphPixmap)
- (*pScreen->DestroyPixmap)(scratch);
-
- FreeScratchGC(pGC);
-
- return TRUE;
-}
-
-static uxa_glyph_cache_result_t
-uxa_glyph_cache_buffer_glyph(ScreenPtr pScreen,
- uxa_glyph_cache_t * cache,
- uxa_glyph_buffer_t * buffer,
- GlyphPtr pGlyph, int xGlyph, int yGlyph)
-{
- uxa_composite_rect_t *rect;
- int pos;
-
- if (buffer->source && buffer->source != cache->picture)
- return UXA_GLYPH_NEED_FLUSH;
-
- if (!cache->picture) {
- if (!uxa_realize_glyph_caches(pScreen, cache->format))
- return UXA_GLYPH_FAIL;
- }
-
- DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
- cache->glyphWidth, cache->glyphHeight,
- cache->format == PICT_a8 ? "A" : "ARGB",
- (long)*(CARD32 *) pGlyph->sha1));
-
- pos = uxa_glyph_cache_hash_lookup(cache, pGlyph);
- if (pos != -1) {
- DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
- } else {
- if (cache->glyphCount < cache->size) {
- /* Space remaining; we fill from the start */
- pos = cache->glyphCount;
- cache->glyphCount++;
- DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
-
- uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
-
- } else {
- /* Need to evict an entry. We have to see if any glyphs
- * already in the output buffer were at this position in
- * the cache
- */
-
- pos = cache->evictionPosition;
- 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) {
- DBG_GLYPH_CACHE((" must flush buffer\n"));
- return UXA_GLYPH_NEED_FLUSH;
- }
+ if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth ||
+ !uxa_pixmap_is_offscreen(scratch)) {
+ scratch = screen->CreatePixmap(screen,
+ glyph->info.width,
+ glyph->info.height,
+ pCachePixmap->drawable.depth,
+ UXA_CREATE_PIXMAP_FOR_MAP);
+ if (scratch) {
+ if (pGlyphPixmap->drawable.depth != pCachePixmap->drawable.depth) {
+ PicturePtr picture;
+ int error;
+
+ picture = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ pCachePixmap->drawable.depth,
+ cache->picture->format),
+ 0, NULL,
+ serverClient, &error);
+ if (picture) {
+ ValidatePicture(picture);
+ uxa_composite(PictOpSrc, pGlyphPicture, NULL, picture,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ glyph->info.width, glyph->info.height);
+ FreePicture(picture, 0);
}
+ } else {
+ uxa_copy_area(&pGlyphPixmap->drawable,
+ &scratch->drawable,
+ gc,
+ 0, 0,
+ glyph->info.width, glyph->info.height,
+ 0, 0);
}
-
- /* OK, we're all set, swap in the new glyph */
- uxa_glyph_cache_hash_remove(cache, pos);
- uxa_glyph_cache_hash_insert(cache, pGlyph, pos);
-
- /* And pick a new eviction position */
- cache->evictionPosition = rand() % cache->size;
- }
-
- /* Now actually upload the glyph into the cache picture; if
- * we can't do it with UploadToScreen (because the glyph is
- * offscreen, etc), we fall back to CompositePicture.
- */
- if (!uxa_glyph_cache_upload_glyph(pScreen, cache, pos, pGlyph)) {
- CompositePicture(PictOpSrc,
- GlyphPicture(pGlyph)[pScreen->myNum],
- None,
- cache->picture,
- 0, 0,
- 0, 0,
- CACHE_X(pos),
- CACHE_Y(pos),
- pGlyph->info.width,
- pGlyph->info.height);
- }
-
- }
-
- buffer->source = 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;
- rect->width = pGlyph->info.width;
- rect->height = pGlyph->info.height;
-
- buffer->count++;
-
- return UXA_GLYPH_SUCCESS;
-}
-
-#undef CACHE_X
-#undef CACHE_Y
-
-static uxa_glyph_cache_result_t
-uxa_buffer_glyph(ScreenPtr pScreen,
- uxa_glyph_buffer_t * buffer,
- GlyphPtr pGlyph, int xGlyph, int yGlyph)
-{
- uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
- unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format;
- int width = pGlyph->info.width;
- int height = pGlyph->info.height;
- uxa_composite_rect_t *rect;
- PicturePtr source;
- int i;
-
- if (buffer->count == GLYPH_BUFFER_SIZE)
- return UXA_GLYPH_NEED_FLUSH;
-
- if (PICT_FORMAT_BPP(format) == 1)
- format = PICT_a8;
-
- for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) {
- uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[i];
-
- if (format == cache->format &&
- width <= cache->glyphWidth &&
- height <= cache->glyphHeight) {
- uxa_glyph_cache_result_t result =
- uxa_glyph_cache_buffer_glyph(pScreen,
- &uxa_screen->
- glyphCaches[i],
- buffer,
- pGlyph, xGlyph,
- yGlyph);
- switch (result) {
- case UXA_GLYPH_FAIL:
- break;
- case UXA_GLYPH_SUCCESS:
- case UXA_GLYPH_NEED_FLUSH:
- return result;
- }
+ } else {
+ scratch = pGlyphPixmap;
}
}
- /* Couldn't find the glyph in the cache, use the glyph picture directly */
-
- source = GlyphPicture(pGlyph)[pScreen->myNum];
- if (buffer->source && buffer->source != source)
- return UXA_GLYPH_NEED_FLUSH;
+ uxa_copy_area(&scratch->drawable, &pCachePixmap->drawable, gc,
+ 0, 0,
+ glyph->info.width, glyph->info.height,
+ x, y);
- buffer->source = source;
-
- 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;
-
- buffer->count++;
+ if (scratch != pGlyphPixmap)
+ screen->DestroyPixmap(scratch);
- return UXA_GLYPH_SUCCESS;
+ FreeScratchGC(gc);
}
-static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer)
+void
+uxa_glyph_unrealize(ScreenPtr pScreen,
+ GlyphPtr pGlyph)
{
- uxa_composite_rects(PictOpAdd, buffer->source, pMask,
- buffer->count, buffer->rects);
-
- buffer->count = 0;
- buffer->source = NULL;
-}
+ struct uxa_glyph *priv;
-static void
-uxa_glyphs_to_dst(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- uxa_glyph_buffer_t * buffer,
- INT16 xSrc, INT16 ySrc, INT16 xDst, INT16 yDst)
-{
- int i;
+ priv = uxa_glyph_get_private(pGlyph);
+ if (priv == NULL)
+ return;
- for (i = 0; i < buffer->count; i++) {
- uxa_composite_rect_t *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);
- }
+ priv->cache->glyphs[priv->pos] = NULL;
- buffer->count = 0;
- buffer->source = NULL;
+ uxa_glyph_set_private(pGlyph, NULL);
+ free(priv);
}
/* Cut and paste from render/glyph.c - probably should export it instead */
@@ -616,47 +314,43 @@ uxa_glyph_extents(int nlist,
GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
{
int x1, x2, y1, y2;
- int n;
- GlyphPtr glyph;
- int x, y;
+ int x, y, n;
- x = 0;
- y = 0;
- extents->x1 = MAXSHORT;
- extents->x2 = MINSHORT;
- extents->y1 = MAXSHORT;
- extents->y2 = MINSHORT;
+ x1 = y1 = MAXSHORT;
+ x2 = y2 = MINSHORT;
+ x = y = 0;
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
list++;
while (n--) {
- glyph = *glyphs++;
- x1 = x - glyph->info.x;
- if (x1 < MINSHORT)
- x1 = MINSHORT;
- y1 = y - glyph->info.y;
- if (y1 < MINSHORT)
- y1 = MINSHORT;
- x2 = x1 + glyph->info.width;
- if (x2 > MAXSHORT)
- x2 = MAXSHORT;
- y2 = y1 + glyph->info.height;
- if (y2 > MAXSHORT)
- y2 = MAXSHORT;
- if (x1 < extents->x1)
- extents->x1 = x1;
- if (x2 > extents->x2)
- extents->x2 = x2;
- if (y1 < extents->y1)
- extents->y1 = y1;
- if (y2 > extents->y2)
- extents->y2 = y2;
+ GlyphPtr glyph = *glyphs++;
+ int v;
+
+ v = x - glyph->info.x;
+ if (v < x1)
+ x1 = v;
+ v += glyph->info.width;
+ if (v > x2)
+ x2 = v;
+
+ v = y - glyph->info.y;
+ if (v < y1)
+ y1 = v;
+ v += glyph->info.height;
+ if (v > y2)
+ y2 = v;
+
x += glyph->info.xOff;
y += glyph->info.yOff;
}
}
+
+ extents->x1 = x1 < MINSHORT ? MINSHORT : x1;
+ extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2;
+ extents->y1 = y1 < MINSHORT ? MINSHORT : y1;
+ extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2;
}
/**
@@ -668,7 +362,6 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
int x1, x2, y1, y2;
int n;
- GlyphPtr glyph;
int x, y;
BoxRec extents;
Bool first = TRUE;
@@ -685,7 +378,7 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
n = list->len;
list++;
while (n--) {
- glyph = *glyphs++;
+ GlyphPtr glyph = *glyphs++;
if (glyph->info.width == 0 || glyph->info.height == 0) {
x += glyph->info.xOff;
@@ -735,121 +428,98 @@ uxa_glyphs_intersect(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
return FALSE;
}
-void
-uxa_glyphs(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+static void
+uxa_check_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
{
- PicturePtr pPicture;
- PixmapPtr pMaskPixmap = 0;
- PicturePtr pMask;
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ int screen = dst->pDrawable->pScreen->myNum;
+ pixman_image_t *image;
+ PixmapPtr scratch;
+ PicturePtr mask;
int width = 0, height = 0;
- int x, y;
+ int x, y, n;
int xDst = list->xOff, yDst = list->yOff;
- int n;
- GlyphPtr glyph;
- int error;
BoxRec extents = { 0, 0, 0, 0 };
- CARD32 component_alpha;
- uxa_glyph_buffer_t 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 &&
- uxa_glyphs_intersect(nlist, list,
- glyphs))) {
- maskFormat = NULL;
- }
- }
if (maskFormat) {
- GCPtr pGC;
- xRectangle rect;
+ pixman_format_code_t format;
+ CARD32 component_alpha;
+ int error;
uxa_glyph_extents(nlist, list, glyphs, &extents);
-
if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
return;
+
width = extents.x2 - extents.x1;
height = extents.y2 - extents.y1;
- if (maskFormat->depth == 1) {
- PictFormatPtr a8Format =
- PictureMatchFormat(pScreen, 8, PICT_a8);
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
- if (a8Format)
- maskFormat = a8Format;
- }
+ scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
- pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
- maskFormat->depth,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pMaskPixmap)
+ if (!scratch) {
+ pixman_image_unref(image);
return;
+ }
+
component_alpha = NeedsComponent(maskFormat->format);
- pMask = CreatePicture(0, &pMaskPixmap->drawable,
- maskFormat, CPComponentAlpha,
- &component_alpha, serverClient, &error);
- if (!pMask) {
- (*pScreen->DestroyPixmap) (pMaskPixmap);
+ mask = CreatePicture(0, &scratch->drawable,
+ maskFormat, CPComponentAlpha,
+ &component_alpha, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
return;
}
- pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
- ValidateGC(&pMaskPixmap->drawable, pGC);
- rect.x = 0;
- rect.y = 0;
- rect.width = width;
- rect.height = height;
- (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1,
- &rect);
- FreeScratchGC(pGC);
+ ValidatePicture(mask);
+
x = -extents.x1;
y = -extents.y1;
} else {
- pMask = pDst;
+ mask = dst;
x = 0;
y = 0;
}
- buffer.count = 0;
- buffer.source = NULL;
+
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
while (n--) {
- glyph = *glyphs++;
- pPicture = GlyphPicture(glyph)[pScreen->myNum];
-
- if (glyph->info.width > 0 && glyph->info.height > 0 &&
- uxa_buffer_glyph(pScreen, &buffer, glyph, x,
- y) == UXA_GLYPH_NEED_FLUSH) {
- if (maskFormat)
- uxa_glyphs_to_mask(pMask, &buffer);
- else
- uxa_glyphs_to_dst(op, pSrc, pDst,
- &buffer, xSrc, ySrc,
- xDst, yDst);
-
- uxa_buffer_glyph(pScreen, &buffer, glyph, x, y);
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr g = GlyphPicture(glyph)[screen];
+ if (g) {
+ if (maskFormat) {
+ CompositePicture(PictOpAdd, g, NULL, mask,
+ 0, 0,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ } else {
+ CompositePicture(op, src, g, dst,
+ xSrc + (x - glyph->info.x) - xDst,
+ ySrc + (y - glyph->info.y) - yDst,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
}
x += glyph->info.xOff;
@@ -858,24 +528,659 @@ uxa_glyphs(CARD8 op,
list++;
}
- if (buffer.count) {
- if (maskFormat)
- uxa_glyphs_to_mask(pMask, &buffer);
- else
- uxa_glyphs_to_dst(op, pSrc, pDst, &buffer,
- xSrc, ySrc, xDst, yDst);
- }
-
if (maskFormat) {
x = extents.x1;
y = extents.y1;
- CompositePicture(op,
- pSrc,
- pMask,
- pDst,
+ CompositePicture(op, src, mask, dst,
xSrc + x - xDst,
- ySrc + y - yDst, 0, 0, x, y, width, height);
- FreePicture((pointer) pMask, (XID) 0);
- (*pScreen->DestroyPixmap) (pMaskPixmap);
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+ FreePicture(mask, 0);
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ }
+}
+
+static inline unsigned int
+uxa_glyph_size_to_count(int size)
+{
+ size /= GLYPH_MIN_SIZE;
+ return size * size;
+}
+
+static inline unsigned int
+uxa_glyph_count_to_mask(int count)
+{
+ return ~(count - 1);
+}
+
+static inline unsigned int
+uxa_glyph_size_to_mask(int size)
+{
+ return uxa_glyph_count_to_mask(uxa_glyph_size_to_count(size));
+}
+
+static PicturePtr
+uxa_glyph_cache(ScreenPtr screen, GlyphPtr glyph, int *out_x, int *out_y)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr glyph_picture = GlyphPicture(glyph)[screen->myNum];
+ uxa_glyph_cache_t *cache = &uxa_screen->glyphCaches[PICT_FORMAT_RGB(glyph_picture->format) != 0];
+ struct uxa_glyph *priv = NULL;
+ int size, mask, pos, s;
+
+ if (glyph->info.width > GLYPH_MAX_SIZE || glyph->info.height > GLYPH_MAX_SIZE)
+ return NULL;
+
+ for (size = GLYPH_MIN_SIZE; size <= GLYPH_MAX_SIZE; size *= 2)
+ if (glyph->info.width <= size && glyph->info.height <= size)
+ break;
+
+ s = uxa_glyph_size_to_count(size);
+ mask = uxa_glyph_count_to_mask(s);
+ pos = (cache->count + s - 1) & mask;
+ if (pos < GLYPH_CACHE_SIZE) {
+ cache->count = pos + s;
+ } else {
+ for (s = size; s <= GLYPH_MAX_SIZE; s *= 2) {
+ int i = cache->evict & uxa_glyph_size_to_mask(s);
+ GlyphPtr evicted = cache->glyphs[i];
+ if (evicted == NULL)
+ continue;
+
+ priv = uxa_glyph_get_private(evicted);
+ if (priv->size >= s) {
+ cache->glyphs[i] = NULL;
+ uxa_glyph_set_private(evicted, NULL);
+ pos = cache->evict & uxa_glyph_size_to_mask(size);
+ } else
+ priv = NULL;
+ break;
+ }
+ if (priv == NULL) {
+ int count = uxa_glyph_size_to_count(size);
+ mask = uxa_glyph_count_to_mask(count);
+ pos = cache->evict & mask;
+ for (s = 0; s < count; s++) {
+ GlyphPtr evicted = cache->glyphs[pos + s];
+ if (evicted != NULL) {
+ if (priv != NULL)
+ free(priv);
+
+ priv = uxa_glyph_get_private(evicted);
+ uxa_glyph_set_private(evicted, NULL);
+ cache->glyphs[pos + s] = NULL;
+ }
+ }
+ }
+
+ /* And pick a new eviction position */
+ cache->evict = rand() % GLYPH_CACHE_SIZE;
+ }
+
+ if (priv == NULL) {
+ priv = malloc(sizeof(struct uxa_glyph));
+ if (priv == NULL)
+ return NULL;
+ }
+
+ uxa_glyph_set_private(glyph, priv);
+ cache->glyphs[pos] = glyph;
+
+ priv->cache = cache;
+ priv->size = size;
+ priv->pos = pos;
+ s = pos / ((GLYPH_MAX_SIZE / GLYPH_MIN_SIZE) * (GLYPH_MAX_SIZE / GLYPH_MIN_SIZE));
+ priv->x = s % (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE) * GLYPH_MAX_SIZE;
+ priv->y = (s / (CACHE_PICTURE_SIZE / GLYPH_MAX_SIZE)) * GLYPH_MAX_SIZE;
+ for (s = GLYPH_MIN_SIZE; s < GLYPH_MAX_SIZE; s *= 2) {
+ if (pos & 1)
+ priv->x += s;
+ if (pos & 2)
+ priv->y += s;
+ pos >>= 2;
+ }
+
+ uxa_glyph_cache_upload_glyph(screen, cache, glyph, priv->x, priv->y);
+
+ *out_x = priv->x;
+ *out_y = priv->y;
+ return cache->picture;
+}
+
+static int
+uxa_glyphs_to_dst(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ INT16 src_x, INT16 src_y,
+ INT16 xDst, INT16 yDst,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs,
+ BoxPtr extents)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr src_pixmap, dst_pixmap;
+ PicturePtr localSrc, glyph_atlas;
+ int x, y, n;
+ BoxRec box;
+
+ if (uxa_screen->info->check_composite_texture &&
+ uxa_screen->info->check_composite_texture(screen, pSrc)) {
+ if (pSrc->pDrawable) {
+ int src_off_x, src_off_y;
+
+ src_pixmap = uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (src_pixmap == NULL)
+ return -1;
+
+ src_x += pSrc->pDrawable->x + src_off_x;
+ src_y += pSrc->pDrawable->y + src_off_y;
+ } else {
+ src_pixmap = NULL;
+ }
+ localSrc = pSrc;
+ } else {
+ int width, height;
+
+ if (extents == NULL) {
+ uxa_glyph_extents(nlist, list, glyphs, &box);
+ extents = &box;
+ }
+
+ width = extents->x2 - extents->x1;
+ height = extents->y2 - extents->y1;
+ if (width == 0 || height == 0)
+ return 0;
+
+ if (pSrc->pDrawable) {
+ int src_off_x, src_off_y;
+
+ src_off_x = extents->x1 - xDst;
+ src_off_y = extents->y1 - yDst;
+ localSrc = uxa_acquire_drawable(screen, pSrc,
+ src_x + src_off_x, src_y + src_off_y,
+ width, height,
+ &src_x, &src_y);
+ if (uxa_screen->info->check_composite_texture &&
+ !uxa_screen->info->check_composite_texture(screen, localSrc)) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_pixmap = uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y);
+ if (src_pixmap == NULL) {
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_x += localSrc->pDrawable->x + src_off_x;
+ src_y += localSrc->pDrawable->y + src_off_y;
+ } else {
+ localSrc = uxa_acquire_pattern(screen, pSrc,
+ PICT_a8r8g8b8, x, y, width, height);
+ if (!localSrc)
+ return 1;
+
+ src_pixmap = uxa_get_drawable_pixmap(localSrc->pDrawable);
+ if (src_pixmap == NULL) {
+ FreePicture(localSrc, 0);
+ return -1;
+ }
+
+ src_x = src_y = 0;
+ }
+ }
+
+ dst_pixmap = uxa_get_offscreen_pixmap(pDst->pDrawable, &x, &y);
+ x += xDst + pDst->pDrawable->x - list->xOff;
+ y += yDst + pDst->pDrawable->y - list->yOff;
+
+ glyph_atlas = NULL;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr this_atlas;
+ int mask_x, mask_y, nrect;
+ struct uxa_glyph *priv;
+ BoxPtr rects;
+
+ if (glyph->info.width == 0 || glyph->info.height == 0)
+ goto next_glyph;
+
+ priv = uxa_glyph_get_private(glyph);
+ if (priv != NULL) {
+ mask_x = priv->x;
+ mask_y = priv->y;
+ this_atlas = priv->cache->picture;
+ } else {
+ if (glyph_atlas) {
+ uxa_screen->info->done_composite(dst_pixmap);
+ glyph_atlas = NULL;
+ }
+ this_atlas = uxa_glyph_cache(screen, glyph, &mask_x, &mask_y);
+ if (this_atlas == NULL) {
+ /* no cache for this glyph */
+ this_atlas = GlyphPicture(glyph)[screen->myNum];
+ mask_x = mask_y = 0;
+ }
+ }
+
+ if (this_atlas != glyph_atlas) {
+ PixmapPtr mask_pixmap;
+
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(dst_pixmap);
+
+ mask_pixmap =
+ uxa_get_drawable_pixmap(this_atlas->pDrawable);
+ assert (uxa_pixmap_is_offscreen(mask_pixmap));
+
+ if (!uxa_screen->info->prepare_composite(op,
+ localSrc, this_atlas, pDst,
+ src_pixmap, mask_pixmap, dst_pixmap))
+ return -1;
+
+ glyph_atlas = this_atlas;
+ }
+
+ rects = REGION_RECTS(pDst->pCompositeClip);
+ nrect = REGION_NUM_RECTS(pDst->pCompositeClip);
+ while (nrect--) {
+ int x1 = x - glyph->info.x, dx = 0;
+ int y1 = y - glyph->info.y, dy = 0;
+ int x2 = x1 + glyph->info.width;
+ int y2 = y1 + glyph->info.height;
+
+ if (rects->y1 >= y2)
+ break;
+
+ if (x1 < rects->x1)
+ dx = rects->x1 - x1, x1 = rects->x1;
+ if (x2 > rects->x2)
+ x2 = rects->x2;
+ if (y1 < rects->y1)
+ dy = rects->y1 - y1, y1 = rects->y1;
+ if (y2 > rects->y2)
+ y2 = rects->y2;
+
+ if (x1 < x2 && y1 < y2) {
+ uxa_screen->info->composite(dst_pixmap,
+ x1 + src_x, y1 + src_y,
+ dx + mask_x, dy + mask_y,
+ x1, y1,
+ x2 - x1, y2 - y1);
+ }
+ rects++;
+ }
+
+next_glyph:
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(dst_pixmap);
+
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+
+ return 0;
+}
+
+static void
+uxa_clear_pixmap(ScreenPtr screen,
+ uxa_screen_t *uxa_screen,
+ PixmapPtr pixmap)
+{
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(&pixmap->drawable, GXcopy, FB_ALLONES))
+ goto fallback;
+
+ if (!uxa_screen->info->prepare_solid(pixmap, GXcopy, FB_ALLONES, 0))
+ goto fallback;
+
+ uxa_screen->info->solid(pixmap,
+ 0, 0,
+ pixmap->drawable.width,
+ pixmap->drawable.height);
+
+ uxa_screen->info->done_solid(pixmap);
+ return;
+
+fallback:
+ {
+ GCPtr gc;
+
+ gc = GetScratchGC(pixmap->drawable.depth, screen);
+ if (gc) {
+ xRectangle rect;
+
+ ValidateGC(&pixmap->drawable, gc);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = pixmap->drawable.width;
+ rect.height = pixmap->drawable.height;
+ gc->ops->PolyFillRect(&pixmap->drawable, gc, 1, &rect);
+
+ FreeScratchGC(gc);
+ }
+ }
+}
+
+static int
+uxa_glyphs_via_mask(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xDst, INT16 yDst,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs,
+ BoxPtr extents)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ CARD32 component_alpha;
+ PixmapPtr pixmap;
+ PicturePtr glyph_atlas, mask;
+ int x, y, width, height;
+ int dst_off_x, dst_off_y;
+ int n, error;
+ BoxRec box;
+
+ if (!extents) {
+ uxa_glyph_extents(nlist, list, glyphs, &box);
+
+ if (box.x2 <= box.x1 || box.y2 <= box.y1)
+ return 0;
+
+ extents = &box;
+ dst_off_x = box.x1;
+ dst_off_y = box.y1;
+ } else {
+ dst_off_x = dst_off_y = 0;
+ }
+
+ width = extents->x2 - extents->x1;
+ height = extents->y2 - extents->y1;
+ x = -extents->x1;
+ y = -extents->y1;
+
+ if (maskFormat->depth == 1) {
+ PictFormatPtr a8Format =
+ PictureMatchFormat(screen, 8, PICT_a8);
+
+ if (!a8Format)
+ return -1;
+
+ maskFormat = a8Format;
+ }
+
+ pixmap = screen->CreatePixmap(screen, width, height,
+ maskFormat->depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return 1;
+
+ uxa_clear_pixmap(screen, uxa_screen, pixmap);
+
+ component_alpha = NeedsComponent(maskFormat->format);
+ mask = CreatePicture(0, &pixmap->drawable,
+ maskFormat, CPComponentAlpha,
+ &component_alpha, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!mask)
+ return 1;
+
+ ValidatePicture(mask);
+
+ glyph_atlas = NULL;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr this_atlas;
+ int src_x, src_y;
+ struct uxa_glyph *priv;
+
+ if (glyph->info.width == 0 || glyph->info.height == 0)
+ goto next_glyph;
+
+ priv = uxa_glyph_get_private(glyph);
+ if (priv != NULL) {
+ src_x = priv->x;
+ src_y = priv->y;
+ this_atlas = priv->cache->picture;
+ } else {
+ if (glyph_atlas) {
+ uxa_screen->info->done_composite(pixmap);
+ glyph_atlas = NULL;
+ }
+ this_atlas = uxa_glyph_cache(screen, glyph, &src_x, &src_y);
+ if (this_atlas == NULL) {
+ /* no cache for this glyph */
+ this_atlas = GlyphPicture(glyph)[screen->myNum];
+ src_x = src_y = 0;
+ }
+ }
+
+ if (this_atlas != glyph_atlas) {
+ PixmapPtr src_pixmap;
+
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(pixmap);
+
+ src_pixmap =
+ uxa_get_drawable_pixmap(this_atlas->pDrawable);
+ assert (uxa_pixmap_is_offscreen(src_pixmap));
+
+ if (!uxa_screen->info->prepare_composite(PictOpAdd,
+ this_atlas, NULL, mask,
+ src_pixmap, NULL, pixmap))
+ return -1;
+
+ glyph_atlas = this_atlas;
+ }
+
+ uxa_screen->info->composite(pixmap,
+ src_x, src_y,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+
+next_glyph:
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ if (glyph_atlas)
+ uxa_screen->info->done_composite(pixmap);
+
+ uxa_composite(op,
+ pSrc, mask, pDst,
+ dst_off_x + xSrc - xDst,
+ dst_off_y + ySrc - yDst,
+ 0, 0,
+ dst_off_x, dst_off_y,
+ width, height);
+
+ FreePicture(mask, 0);
+ return 0;
+}
+
+void
+uxa_glyphs(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ int xDst = list->xOff, yDst = list->yOff;
+ BoxRec extents = { 0, 0, 0, 0 };
+ Bool have_extents = FALSE;
+ int width, height, ret;
+ PicturePtr localDst = pDst;
+
+ if (!uxa_screen->info->prepare_composite ||
+ uxa_screen->swappedOut ||
+ !uxa_drawable_is_offscreen(pDst->pDrawable) ||
+ pDst->alphaMap || pSrc->alphaMap) {
+fallback:
+ uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ return;
+ }
+
+ /* basic sanity check */
+ if (uxa_screen->info->check_composite &&
+ !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) {
+ goto fallback;
+ }
+
+ ValidatePicture(pSrc);
+ ValidatePicture(pDst);
+
+ if (!maskFormat) {
+ /* If we don't have a mask format but all the glyphs have the same format,
+ * require ComponentAlpha and don't intersect, use the glyph format as mask
+ * format for the full benefits of the glyph cache.
+ */
+ if (NeedsComponent(list[0].format->format)) {
+ 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 ||
+ uxa_glyphs_intersect(nlist, list, glyphs))
+ maskFormat = NULL;
+ }
+ }
+
+ if (!maskFormat &&
+ uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int x, y, error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ goto fallback;
+
+ uxa_glyph_extents(nlist, list, glyphs, &extents);
+
+ /* clip against dst bounds */
+ if (extents.x1 < 0)
+ extents.x1 = 0;
+ if (extents.y1 < 0)
+ extents.y1 = 0;
+ if (extents.x2 > pDst->pDrawable->width)
+ extents.x2 = pDst->pDrawable->width;
+ if (extents.y2 > pDst->pDrawable->height)
+ extents.y2 = pDst->pDrawable->height;
+
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+ x = -extents.x1;
+ y = -extents.y1;
+ have_extents = TRUE;
+
+ xDst += x;
+ yDst += y;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ extents.x1, extents.y1,
+ width, height,
+ 0, 0);
+ FreeScratchGC(gc);
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return;
+
+ ValidatePicture(localDst);
+ }
+
+ if (maskFormat) {
+ ret = uxa_glyphs_via_mask(op,
+ pSrc, localDst, maskFormat,
+ xSrc, ySrc,
+ xDst, yDst,
+ nlist, list, glyphs,
+ have_extents ? &extents : NULL);
+ } else {
+ ret = uxa_glyphs_to_dst(op,
+ pSrc, localDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ nlist, list, glyphs,
+ have_extents ? &extents : NULL);
+ }
+ if (ret) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
+
+ goto fallback;
+ }
+
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0,
+ width, height,
+ extents.x1, extents.y1);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
}
}
diff --git a/driver/xf86-video-intel/uxa/uxa-priv.h b/driver/xf86-video-intel/uxa/uxa-priv.h
index c1f3688cf..4b988f4e7 100644
--- a/driver/xf86-video-intel/uxa/uxa-priv.h
+++ b/driver/xf86-video-intel/uxa/uxa-priv.h
@@ -41,14 +41,6 @@
#include <X11/X.h>
#define NEED_EVENTS
#include <X11/Xproto.h>
-#ifdef MITSHM
-#ifdef HAVE_XEXTPROTO_71
-#include <X11/extensions/shm.h>
-#else
-#define _XSHM_SERVER_
-#include <X11/extensions/shmstr.h>
-#endif
-#endif
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "windowstr.h"
@@ -103,37 +95,13 @@ char uxa_drawable_location(DrawablePtr pDrawable);
#endif
typedef struct {
- unsigned char sha1[20];
-} uxa_cached_glyph_t;
-
-typedef struct {
- /* The identity of the cache, statically configured at initialization */
- unsigned int format;
- int glyphWidth;
- int glyphHeight;
-
- /* Size of cache; eventually this should be dynamically determined */
- int size;
-
- /* Hash table mapping from glyph sha1 to position in the glyph; we use
- * open addressing with a hash table size determined based on size and large
- * enough so that we always have a good amount of free space, so we can
- * use linear probing. (Linear probing is preferrable to double hashing
- * here because it allows us to easily remove entries.)
- */
- int *hashEntries;
- int hashSize;
-
- uxa_cached_glyph_t *glyphs;
- int glyphCount; /* Current number of glyphs */
-
PicturePtr picture; /* Where the glyphs of the cache are stored */
- int yOffset; /* y location within the picture where the cache starts */
- int columns; /* Number of columns the glyphs are layed out in */
- int evictionPosition; /* Next random position to evict a glyph */
+ GlyphPtr *glyphs;
+ uint16_t count;
+ uint16_t evict;
} uxa_glyph_cache_t;
-#define UXA_NUM_GLYPH_CACHES 4
+#define UXA_NUM_GLYPH_CACHE_FORMATS 2
typedef struct {
uint32_t color;
@@ -156,10 +124,12 @@ typedef struct {
BitmapToRegionProcPtr SavedBitmapToRegion;
#ifdef RENDER
CompositeProcPtr SavedComposite;
+ CompositeRectsProcPtr SavedCompositeRects;
TrianglesProcPtr SavedTriangles;
GlyphsProcPtr SavedGlyphs;
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph;
#endif
EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess;
@@ -168,7 +138,7 @@ typedef struct {
unsigned disableFbCount;
unsigned offScreenCounter;
- uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHES];
+ uxa_glyph_cache_t glyphCaches[UXA_NUM_GLYPH_CACHE_FORMATS];
PicturePtr solid_clear, solid_black, solid_white;
uxa_solid_cache_t solid_cache[UXA_NUM_SOLID_CACHE];
@@ -187,11 +157,19 @@ typedef struct {
(PixmapWidthPaddingInfo[d].padRoundUp+1)))
#endif
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec uxa_screen_index;
+#else
extern int uxa_screen_index;
+#endif
+
static inline uxa_screen_t *uxa_get_screen(ScreenPtr screen)
{
- return (uxa_screen_t *) dixLookupPrivate(&screen->devPrivates,
- &uxa_screen_index);
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&screen->devPrivates, &uxa_screen_index);
+#else
+ return dixLookupPrivate(&screen->devPrivates, &uxa_screen_index);
+#endif
}
/** Align an offset to an arbitrary alignment */
@@ -307,11 +285,6 @@ Bool
uxa_fill_region_tiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu);
-void
-uxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
- unsigned int format, int w, int h, int sx, int sy, int sw,
- int sh, int dx, int dy, char *data);
-
void uxa_paint_window(WindowPtr pWin, RegionPtr pRegion, int what);
void
@@ -320,24 +293,6 @@ uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
extern const GCOps uxa_ops;
-#ifdef MITSHM
-/* XXX these come from shmint.h, which isn't exported by the server */
-
-#ifdef HAVE_XEXTPROTO_71
-#include "shmint.h"
-#else
-
-void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
-
-void ShmSetPixmapFormat(ScreenPtr pScreen, int format);
-
-void fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
-#endif
-
-extern ShmFuncs uxa_shm_funcs;
-
-#endif
-
#ifdef RENDER
/* XXX these are in fbpict.h, which is not installed */
@@ -417,6 +372,13 @@ uxa_composite_rects(CARD8 op,
PicturePtr pDst, int nrect, uxa_composite_rect_t * rects);
void
+uxa_solid_rects (CARD8 op,
+ PicturePtr dst,
+ xRenderColor *color,
+ int num_rects,
+ xRectangle *rects);
+
+void
uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntrap, xTrapezoid * traps);
@@ -426,8 +388,33 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntri, xTriangle * tris);
+PicturePtr
+uxa_acquire_solid(ScreenPtr screen, SourcePict *source);
+
+PicturePtr
+uxa_acquire_drawable(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y);
+
+PicturePtr
+uxa_acquire_pattern(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height);
+
+Bool
+uxa_get_rgba_from_pixel(CARD32 pixel,
+ CARD16 * red,
+ CARD16 * green,
+ CARD16 * blue,
+ CARD16 * alpha,
+ CARD32 format);
+
/* uxa_glyph.c */
-void uxa_glyphs_init(ScreenPtr pScreen);
+Bool uxa_glyphs_init(ScreenPtr pScreen);
void uxa_glyphs_fini(ScreenPtr pScreen);
@@ -439,4 +426,8 @@ uxa_glyphs(CARD8 op,
INT16 xSrc,
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
+void
+uxa_glyph_unrealize(ScreenPtr pScreen,
+ GlyphPtr pGlyph);
+
#endif /* UXAPRIV_H */
diff --git a/driver/xf86-video-intel/uxa/uxa-render.c b/driver/xf86-video-intel/uxa/uxa-render.c
index 30934d0d8..056b60a47 100644
--- a/driver/xf86-video-intel/uxa/uxa-render.c
+++ b/driver/xf86-video-intel/uxa/uxa-render.c
@@ -85,29 +85,88 @@ static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string,
pict->alphaMap ? " with alpha map" :"");
}
+static const char *
+op_to_string(CARD8 op)
+{
+ switch (op) {
+#define C(x) case PictOp##x: return #x
+ C(Clear);
+ C(Src);
+ C(Dst);
+ C(Over);
+ C(OverReverse);
+ C(In);
+ C(InReverse);
+ C(Out);
+ C(OutReverse);
+ C(Atop);
+ C(AtopReverse);
+ C(Xor);
+ C(Add);
+ C(Saturate);
+
+ /*
+ * Operators only available in version 0.2
+ */
+ C(DisjointClear);
+ C(DisjointSrc);
+ C(DisjointDst);
+ C(DisjointOver);
+ C(DisjointOverReverse);
+ C(DisjointIn);
+ C(DisjointInReverse);
+ C(DisjointOut);
+ C(DisjointOutReverse);
+ C(DisjointAtop);
+ C(DisjointAtopReverse);
+ C(DisjointXor);
+
+ C(ConjointClear);
+ C(ConjointSrc);
+ C(ConjointDst);
+ C(ConjointOver);
+ C(ConjointOverReverse);
+ C(ConjointIn);
+ C(ConjointInReverse);
+ C(ConjointOut);
+ C(ConjointOutReverse);
+ C(ConjointAtop);
+ C(ConjointAtopReverse);
+ C(ConjointXor);
+
+ /*
+ * Operators only available in version 0.11
+ */
+ C(Multiply);
+ C(Screen);
+ C(Overlay);
+ C(Darken);
+ C(Lighten);
+ C(ColorDodge);
+ C(ColorBurn);
+ C(HardLight);
+ C(SoftLight);
+ C(Difference);
+ C(Exclusion);
+ C(HSLHue);
+ C(HSLSaturation);
+ C(HSLColor);
+ C(HSLLuminosity);
+ default: return "garbage";
+#undef C
+ }
+}
+
static void
uxa_print_composite_fallback(const char *func, CARD8 op,
PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
- char sop[20];
char srcdesc[40], maskdesc[40], dstdesc[40];
if (! uxa_screen->fallback_debug)
return;
- switch (op) {
- case PictOpSrc:
- sprintf(sop, "Src");
- break;
- case PictOpOver:
- sprintf(sop, "Over");
- break;
- default:
- sprintf(sop, "0x%x", (int)op);
- break;
- }
-
uxa_composite_fallback_pict_desc(pSrc, srcdesc, 40);
uxa_composite_fallback_pict_desc(pMask, maskdesc, 40);
uxa_composite_fallback_pict_desc(pDst, dstdesc, 40);
@@ -118,7 +177,7 @@ uxa_print_composite_fallback(const char *func, CARD8 op,
" mask %s, \n"
" dst %s, \n"
" screen %s\n",
- func, sop, srcdesc, maskdesc, dstdesc,
+ func, op_to_string (op), srcdesc, maskdesc, dstdesc,
uxa_screen->swappedOut ? "swapped out" : "normal");
}
@@ -182,7 +241,7 @@ uxa_get_pixel_from_rgba(CARD32 * pixel,
return TRUE;
}
-static Bool
+Bool
uxa_get_rgba_from_pixel(CARD32 pixel,
CARD16 * red,
CARD16 * green,
@@ -290,7 +349,12 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
PixmapPtr pSrcPix = NULL, pDstPix;
CARD32 pixel;
- pDstPix = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_solid && !uxa_screen->info->check_solid(pDst->pDrawable, GXcopy, FB_ALLONES))
+ return -1;
+
+ pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix)
+ return -1;
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
@@ -306,16 +370,6 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
width, height))
return 1;
- uxa_get_drawable_deltas(pDst->pDrawable, pDstPix, &dst_off_x,
- &dst_off_y);
-
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
- if (!uxa_pixmap_is_offscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
- }
-
if (pSrcPix) {
if (! uxa_get_color_for_pixmap (pSrcPix, pSrc->format, pDst->format, &pixel)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
@@ -334,11 +388,13 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
}
if (!(*uxa_screen->info->prepare_solid)
- (pDstPix, GXcopy, 0xffffffff, pixel)) {
+ (pDstPix, GXcopy, FB_ALLONES, pixel)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return -1;
}
+ REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
+
nbox = REGION_NUM_RECTS(&region);
pbox = REGION_RECTS(&region);
@@ -391,74 +447,84 @@ uxa_picture_for_pixman_format(ScreenPtr pScreen,
}
static PicturePtr
-uxa_picture_from_pixman_image(ScreenPtr pScreen,
+uxa_picture_from_pixman_image(ScreenPtr screen,
pixman_image_t * image,
pixman_format_code_t format)
{
- PicturePtr pPicture;
- PixmapPtr pPixmap;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr picture;
+ PixmapPtr pixmap;
int width, height;
width = pixman_image_get_width(image);
height = pixman_image_get_height(image);
- pPicture = uxa_picture_for_pixman_format(pScreen, format,
- width, height);
- if (!pPicture)
+ picture = uxa_picture_for_pixman_format(screen, format,
+ width, height);
+ if (!picture)
return 0;
- pPixmap = GetScratchPixmapHeader(pScreen, width, height,
- PIXMAN_FORMAT_DEPTH(format),
- PIXMAN_FORMAT_BPP(format),
- pixman_image_get_stride(image),
- pixman_image_get_data(image));
- if (!pPixmap) {
- FreePicture(pPicture, 0);
+ if (uxa_screen->info->put_image &&
+ ((picture->pDrawable->depth << 24) | picture->format) == format &&
+ uxa_screen->info->put_image((PixmapPtr)picture->pDrawable,
+ 0, 0,
+ width, height,
+ (char *)pixman_image_get_data(image),
+ pixman_image_get_stride(image)))
+ return picture;
+
+ pixmap = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ if (!pixmap) {
+ FreePicture(picture, 0);
return 0;
}
- if (((pPicture->pDrawable->depth << 24) | pPicture->format) == format) {
- GCPtr pGC;
+ if (((picture->pDrawable->depth << 24) | picture->format) == format) {
+ GCPtr gc;
- pGC = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), pScreen);
- if (!pGC) {
- FreeScratchPixmapHeader(pPixmap);
- FreePicture(pPicture, 0);
- return 0;
- }
- ValidateGC(pPicture->pDrawable, pGC);
+ gc = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), screen);
+ if (!gc) {
+ FreeScratchPixmapHeader(pixmap);
+ FreePicture(picture, 0);
+ return 0;
+ }
+ ValidateGC(picture->pDrawable, gc);
- (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
- pGC, 0, 0, width, height, 0, 0);
+ (*gc->ops->CopyArea) (&pixmap->drawable, picture->pDrawable,
+ gc, 0, 0, width, height, 0, 0);
- FreeScratchGC(pGC);
+ FreeScratchGC(gc);
} else {
- PicturePtr pSrc;
- int error;
-
- pSrc = CreatePicture(0, &pPixmap->drawable,
- PictureMatchFormat(pScreen,
- PIXMAN_FORMAT_DEPTH(format),
- format),
- 0, 0, serverClient, &error);
- if (!pSrc) {
- FreeScratchPixmapHeader(pPixmap);
- FreePicture(pPicture, 0);
- return 0;
- }
- ValidatePicture(pSrc);
+ PicturePtr src;
+ int error;
+
+ src = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ if (!src) {
+ FreeScratchPixmapHeader(pixmap);
+ FreePicture(picture, 0);
+ return 0;
+ }
+ ValidatePicture(src);
- if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) {
- fbComposite(PictOpSrc, pSrc, NULL, pPicture,
- 0, 0, 0, 0, 0, 0, width, height);
- uxa_finish_access(pPicture->pDrawable);
- }
+ if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) {
+ fbComposite(PictOpSrc, src, NULL, picture,
+ 0, 0, 0, 0, 0, 0, width, height);
+ uxa_finish_access(picture->pDrawable);
+ }
- FreePicture(pSrc, 0);
+ FreePicture(src, 0);
}
- FreeScratchPixmapHeader(pPixmap);
+ FreeScratchPixmapHeader(pixmap);
- return pPicture;
+ return picture;
}
static PicturePtr
@@ -490,6 +556,21 @@ uxa_create_solid(ScreenPtr screen, uint32_t color)
}
static PicturePtr
+uxa_solid_clear(ScreenPtr screen)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr picture;
+
+ if (!uxa_screen->solid_clear) {
+ uxa_screen->solid_clear = uxa_create_solid(screen, 0);
+ if (!uxa_screen->solid_clear)
+ return 0;
+ }
+ picture = uxa_screen->solid_clear;
+ return picture;
+}
+
+PicturePtr
uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
{
uxa_screen_t *uxa_screen = uxa_get_screen(screen);
@@ -498,12 +579,10 @@ uxa_acquire_solid(ScreenPtr screen, SourcePict *source)
int i;
if ((solid->color >> 24) == 0) {
- if (!uxa_screen->solid_clear) {
- uxa_screen->solid_clear = uxa_create_solid(screen, 0);
- if (!uxa_screen->solid_clear)
- return 0;
- }
- picture = uxa_screen->solid_clear;
+ picture = uxa_solid_clear(screen);
+ if (!picture)
+ return 0;
+
goto DONE;
} else if (solid->color == 0xff000000) {
if (!uxa_screen->solid_black) {
@@ -548,7 +627,7 @@ DONE:
return picture;
}
-static PicturePtr
+PicturePtr
uxa_acquire_pattern(ScreenPtr pScreen,
PicturePtr pSrc,
pixman_format_code_t format,
@@ -577,158 +656,398 @@ uxa_acquire_pattern(ScreenPtr pScreen,
}
}
-static PicturePtr
-uxa_acquire_source(ScreenPtr pScreen,
- PicturePtr pPict,
- INT16 x, INT16 y,
- CARD16 width, CARD16 height, INT16 * out_x, INT16 * out_y)
+static Bool
+transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
{
- if (pPict->pDrawable) {
- *out_x = x + pPict->pDrawable->x;
- *out_y = y + pPict->pDrawable->y;
- return pPict;
+ if (t == NULL) {
+ *tx = *ty = 0;
+ return TRUE;
}
- *out_x = 0;
- *out_y = 0;
- return uxa_acquire_pattern(pScreen, pPict,
- PICT_a8r8g8b8, x, y, width, height);
+ if (t->matrix[0][0] != IntToxFixed(1) ||
+ t->matrix[0][1] != 0 ||
+ t->matrix[1][0] != 0 ||
+ t->matrix[1][1] != IntToxFixed(1) ||
+ t->matrix[2][0] != 0 ||
+ t->matrix[2][1] != 0 ||
+ t->matrix[2][2] != IntToxFixed(1))
+ return FALSE;
+
+ if (xFixedFrac(t->matrix[0][2]) != 0 ||
+ xFixedFrac(t->matrix[1][2]) != 0)
+ return FALSE;
+
+ *tx = xFixedToInt(t->matrix[0][2]);
+ *ty = xFixedToInt(t->matrix[1][2]);
+ return TRUE;
}
static PicturePtr
-uxa_acquire_mask(ScreenPtr pScreen,
- PicturePtr pPict,
- INT16 x, INT16 y,
- INT16 width, INT16 height, INT16 * out_x, INT16 * out_y)
+uxa_render_picture(ScreenPtr screen,
+ PicturePtr src,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height)
{
- if (pPict->pDrawable) {
- *out_x = x + pPict->pDrawable->x;
- *out_y = y + pPict->pDrawable->y;
- return pPict;
+ PicturePtr picture;
+ int ret = 0;
+
+ /* XXX we need a mechanism for the card to choose the fallback format */
+
+ /* force alpha channel in case source does not entirely cover the extents */
+ if (PIXMAN_FORMAT_A(format) == 0)
+ format = PIXMAN_a8r8g8b8; /* available on all hardware */
+
+ picture = uxa_picture_for_pixman_format(screen, format, width, height);
+ if (!picture)
+ return 0;
+
+ if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(src->pDrawable, UXA_ACCESS_RO)) {
+ ret = 1;
+ fbComposite(PictOpSrc, src, NULL, picture,
+ x, y, 0, 0, 0, 0, width, height);
+ uxa_finish_access(src->pDrawable);
+ }
+ uxa_finish_access(picture->pDrawable);
}
- *out_x = 0;
- *out_y = 0;
- return uxa_acquire_pattern(pScreen, pPict,
- PICT_a8, x, y, width, height);
+ if (!ret) {
+ FreePicture(picture, 0);
+ return 0;
+ }
+
+ return picture;
}
static int
-uxa_try_driver_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- int nrect, uxa_composite_rect_t * rects)
+drawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
- int src_off_x, src_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pDstPix;
+ if (x < 0 || y < 0)
+ return FALSE;
- if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut)
- return -1;
+ if (x + w > drawable->width)
+ return FALSE;
- if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) {
- return -1;
+ if (y + h > drawable->height)
+ return FALSE;
+
+ return TRUE;
+}
+
+PicturePtr
+uxa_acquire_drawable(ScreenPtr pScreen,
+ PicturePtr pSrc,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ PixmapPtr pPixmap;
+ PicturePtr pDst;
+ int depth, error;
+ int tx, ty;
+ GCPtr pGC;
+
+ depth = pSrc->pDrawable->depth;
+ if (!transform_is_integer_translation(pSrc->transform, &tx, &ty) ||
+ !drawable_contains(pSrc->pDrawable, x + tx, y + ty, width, height) ||
+ depth == 1 ||
+ pSrc->filter == PictFilterConvolution) {
+ /* XXX extract the sample extents and do the transformation on the GPU */
+ pDst = uxa_render_picture(pScreen, pSrc,
+ pSrc->format | (BitsPerPixel(pSrc->pDrawable->depth) << 24),
+ x, y, width, height);
+
+ goto done;
+ } else {
+ if (width == pSrc->pDrawable->width && height == pSrc->pDrawable->height) {
+ *out_x = x + pSrc->pDrawable->x;
+ *out_y = y + pSrc->pDrawable->y;
+ return pSrc;
+ }
}
- pDstPix =
- uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
- if (!pDstPix)
+ pPixmap = pScreen->CreatePixmap(pScreen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
return 0;
- pSrcPix =
- uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!pSrcPix)
+ /* Skip the copy if the result remains in memory and not a bo */
+ if (!uxa_pixmap_is_offscreen(pPixmap)) {
+ pScreen->DestroyPixmap(pPixmap);
return 0;
+ }
- if (!(*uxa_screen->info->prepare_composite)
- (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix))
- return -1;
+ pGC = GetScratchGC(depth, pScreen);
+ if (!pGC) {
+ pScreen->DestroyPixmap(pPixmap);
+ return 0;
+ }
+
+ ValidateGC(&pPixmap->drawable, pGC);
+ pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
+ x + tx, y + ty, width, height, 0, 0);
+ FreeScratchGC(pGC);
+
+ pDst = CreatePicture(0, &pPixmap->drawable,
+ PictureMatchFormat(pScreen, depth, pSrc->format),
+ 0, 0, serverClient, &error);
+ pScreen->DestroyPixmap(pPixmap);
+ ValidatePicture(pDst);
+
+done:
+ pDst->componentAlpha = pSrc->componentAlpha;
+ *out_x = 0;
+ *out_y = 0;
+ return pDst;
+}
- 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;
-
- RegionRec region;
- BoxPtr pbox;
- int nbox;
-
- if (!miComputeCompositeRegion(&region, pSrc, NULL, pDst,
- xSrc, ySrc, 0, 0, xDst, yDst,
- rects->width, rects->height))
- goto next_rect;
-
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
- nbox = REGION_NUM_RECTS(&region);
- pbox = REGION_RECTS(&region);
-
- xSrc = xSrc + src_off_x - xDst - dst_off_x;
- ySrc = ySrc + src_off_y - yDst - dst_off_y;
-
- while (nbox--) {
- (*uxa_screen->info->composite) (pDstPix,
- pbox->x1 + xSrc,
- pbox->y1 + ySrc,
- 0, 0,
- pbox->x1,
- pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
- pbox++;
+static PicturePtr
+uxa_acquire_picture(ScreenPtr screen,
+ PicturePtr src,
+ pixman_format_code_t format,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+
+ if (uxa_screen->info->check_composite_texture &&
+ uxa_screen->info->check_composite_texture(screen, src)) {
+ if (src->pDrawable) {
+ *out_x = x + src->pDrawable->x;
+ *out_y = y + src->pDrawable->y;
+ } else {
+ *out_x = x;
+ *out_y = y;
}
+ return src;
+ }
-next_rect:
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ if (src->pDrawable) {
+ PicturePtr dst;
- rects++;
+ dst = uxa_acquire_drawable(screen, src,
+ x, y, width, height,
+ out_x, out_y);
+ if (!dst)
+ return 0;
+
+ if (uxa_screen->info->check_composite_texture &&
+ !uxa_screen->info->check_composite_texture(screen, dst)) {
+ if (dst != src)
+ FreePicture(dst, 0);
+ return 0;
+ }
+
+ return dst;
}
- (*uxa_screen->info->done_composite) (pDstPix);
- return 1;
+ *out_x = 0;
+ *out_y = 0;
+ return uxa_acquire_pattern(screen, src,
+ format, x, y, width, height);
+}
+
+static PicturePtr
+uxa_acquire_source(ScreenPtr screen,
+ PicturePtr pict,
+ INT16 x, INT16 y,
+ CARD16 width, CARD16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ return uxa_acquire_picture (screen, pict,
+ PICT_a8r8g8b8,
+ x, y,
+ width, height,
+ out_x, out_y);
+}
+
+static PicturePtr
+uxa_acquire_mask(ScreenPtr screen,
+ PicturePtr pict,
+ INT16 x, INT16 y,
+ INT16 width, INT16 height,
+ INT16 * out_x, INT16 * out_y)
+{
+ return uxa_acquire_picture (screen, pict,
+ PICT_a8,
+ x, y,
+ width, height,
+ out_x, out_y);
+}
+
+static Bool
+_pixman_region_init_rectangles(pixman_region16_t *region,
+ int num_rects,
+ xRectangle *rects,
+ int tx, int ty)
+{
+ pixman_box16_t stack_boxes[64], *boxes = stack_boxes;
+ pixman_bool_t ret;
+ int i;
+
+ if (num_rects > sizeof(stack_boxes) / sizeof(stack_boxes[0])) {
+ boxes = malloc(sizeof(pixman_box16_t) * num_rects);
+ if (boxes == NULL)
+ return FALSE;
+ }
+
+ for (i = 0; i < num_rects; i++) {
+ boxes[i].x1 = rects[i].x + tx;
+ boxes[i].y1 = rects[i].y + ty;
+ boxes[i].x2 = rects[i].x + tx + rects[i].width;
+ boxes[i].y2 = rects[i].y + ty + rects[i].height;
+ }
+
+ ret = pixman_region_init_rects(region, boxes, num_rects);
+
+ if (boxes != stack_boxes)
+ free(boxes);
+
+ return ret;
}
-/**
- * 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 uxa_composite() - if the
- * driver can support it, we use the driver functionality, otherwise we
- * fallback straight to software.
- */
void
-uxa_composite_rects(CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst, int nrect, uxa_composite_rect_t * rects)
+uxa_solid_rects (CARD8 op,
+ PicturePtr dst,
+ xRenderColor *color,
+ int num_rects,
+ xRectangle *rects)
{
- int n;
- uxa_composite_rect_t *r;
+ ScreenPtr screen = dst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PixmapPtr dst_pixmap, src_pixmap = NULL;
+ pixman_region16_t region;
+ pixman_box16_t *boxes, *extents;
+ PicturePtr src;
+ int dst_x, dst_y;
+ int num_boxes;
+
+ if (!pixman_region_not_empty(dst->pCompositeClip))
+ return;
- /************************************************************/
+ if (dst->alphaMap)
+ goto fallback;
- ValidatePicture(pSrc);
- ValidatePicture(pDst);
+ dst_pixmap = uxa_get_offscreen_pixmap(dst->pDrawable, &dst_x, &dst_y);
+ if (!dst_pixmap)
+ goto fallback;
+
+ if (!_pixman_region_init_rectangles(&region,
+ num_rects, rects,
+ dst->pDrawable->x, dst->pDrawable->y))
+ goto fallback;
+
+ if (!pixman_region_intersect(&region, &region, dst->pCompositeClip)) {
+ pixman_region_fini(&region);
+ return;
+ }
+
+ /* XXX xserver-1.8: CompositeRects is not tracked by Damage, so we must
+ * manually append the damaged regions ourselves.
+ */
+ DamageRegionAppend(dst->pDrawable, &region);
+
+ pixman_region_translate(&region, dst_x, dst_y);
+ boxes = pixman_region_rectangles(&region, &num_boxes);
+ extents = pixman_region_extents (&region);
+
+ if (op == PictOpClear)
+ color->red = color->green = color->blue = color->alpha = 0;
+ if (color->alpha >= 0xff00 && op == PictOpOver) {
+ color->alpha = 0xffff;
+ op = PictOpSrc;
+ }
+
+ /* Using GEM, the relocation costs outweigh the advantages of the blitter */
+ if (num_boxes == 1 && (op == PictOpSrc || op == PictOpClear)) {
+ CARD32 pixel;
+
+try_solid:
+ if (uxa_screen->info->check_solid &&
+ !uxa_screen->info->check_solid(&dst_pixmap->drawable, GXcopy, FB_ALLONES))
+ goto err_region;
+
+ if (!uxa_get_pixel_from_rgba(&pixel,
+ color->red,
+ color->green,
+ color->blue,
+ color->alpha,
+ dst->format))
+ goto err_region;
+
+ if (!uxa_screen->info->prepare_solid(dst_pixmap, GXcopy, FB_ALLONES, pixel))
+ goto err_region;
+
+ while (num_boxes--) {
+ uxa_screen->info->solid(dst_pixmap,
+ boxes->x1, boxes->y1,
+ boxes->x2, boxes->y2);
+ boxes++;
+ }
+
+ uxa_screen->info->done_solid(dst_pixmap);
+ } else {
+ int error;
+
+ src = CreateSolidPicture(0, color, &error);
+ if (!src)
+ goto err_region;
+
+ if (!uxa_screen->info->check_composite(op, src, NULL, dst,
+ extents->x2 - extents->x1,
+ extents->y2 - extents->y1)) {
+ if (op == PictOpSrc || op == PictOpClear) {
+ FreePicture(src, 0);
+ goto try_solid;
+ }
+
+ goto err_src;
+ }
- if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) {
- uxa_print_composite_fallback("uxa_composite_rects",
- op, pSrc, NULL, pDst);
-
- n = nrect;
- r = rects;
- while (n--) {
- uxa_check_composite(op, pSrc, NULL, pDst,
- r->xSrc, r->ySrc,
- 0, 0,
- r->xDst, r->yDst,
- r->width, r->height);
- r++;
+ if (!uxa_screen->info->check_composite_texture ||
+ !uxa_screen->info->check_composite_texture(screen, src)) {
+ PicturePtr solid;
+ int src_off_x, src_off_y;
+
+ solid = uxa_acquire_solid(screen, src->pSourcePict);
+ FreePicture(src, 0);
+
+ src = solid;
+ src_pixmap = uxa_get_offscreen_pixmap(src->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!src_pixmap)
+ goto err_src;
}
+
+ if (!uxa_screen->info->prepare_composite(op, src, NULL, dst, src_pixmap, NULL, dst_pixmap))
+ goto err_src;
+
+ while (num_boxes--) {
+ uxa_screen->info->composite(dst_pixmap,
+ 0, 0, 0, 0,
+ boxes->x1,
+ boxes->y1,
+ boxes->x2 - boxes->x1,
+ boxes->y2 - boxes->y1);
+ boxes++;
+ }
+
+ uxa_screen->info->done_composite(dst_pixmap);
+ FreePicture(src, 0);
}
- /************************************************************/
+ pixman_region_fini(&region);
+ return;
+err_src:
+ FreePicture(src, 0);
+err_region:
+ pixman_region_fini(&region);
+fallback:
+ uxa_screen->SavedCompositeRects(op, dst, color, num_rects, rects);
}
static int
@@ -736,130 +1055,217 @@ uxa_try_driver_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
RegionRec region;
BoxPtr pbox;
int nbox;
+ int xDst_copy, yDst_copy;
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
PicturePtr localSrc, localMask = NULL;
+ PicturePtr localDst = pDst;
- xDst += pDst->pDrawable->x;
- yDst += pDst->pDrawable->y;
+ if (uxa_screen->info->check_composite &&
+ !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst, width, height))
+ return -1;
+
+ if (uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ return -1;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return 0;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return 0;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ xDst, yDst, width, height, 0, 0);
+ FreeScratchGC(gc);
- localSrc = uxa_acquire_source(pDst->pDrawable->pScreen,
- pSrc, xSrc, ySrc, width, height,
+ xDst_copy = xDst; xDst = 0;
+ yDst_copy = yDst; yDst = 0;
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return 0;
+
+ ValidatePicture(localDst);
+ }
+
+ pDstPix =
+ uxa_get_offscreen_pixmap(localDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (!pDstPix) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
+ return -1;
+ }
+
+ xDst += localDst->pDrawable->x;
+ yDst += localDst->pDrawable->y;
+
+ localSrc = uxa_acquire_source(screen, pSrc,
+ xSrc, ySrc,
+ width, height,
&xSrc, &ySrc);
- if (!localSrc)
+ if (!localSrc) {
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 0;
+ }
if (pMask) {
- localMask = uxa_acquire_mask(pDst->pDrawable->pScreen,
- pMask, xMask, yMask, width, height,
+ localMask = uxa_acquire_mask(screen, pMask,
+ xMask, yMask,
+ width, height,
&xMask, &yMask);
if (!localMask) {
if (localSrc != pSrc)
FreePicture(localSrc, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 0;
}
}
- if (uxa_screen->info->check_composite &&
- !(*uxa_screen->info->check_composite) (op, localSrc, localMask,
- pDst)) {
- if (localSrc != pSrc)
- FreePicture(localSrc, 0);
- if (localMask && localMask != pMask)
- FreePicture(localMask, 0);
-
- return -1;
- }
-
- if (!miComputeCompositeRegion(&region, localSrc, localMask, pDst,
+ if (!miComputeCompositeRegion(&region, localSrc, localMask, localDst,
xSrc, ySrc, xMask, yMask, xDst, yDst,
width, height)) {
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return 1;
}
- pDstPix =
- uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+ if (localSrc->pDrawable) {
+ pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
+ &src_off_x, &src_off_y);
+ if (!pSrcPix) {
+ REGION_UNINIT(screen, &region);
- pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
- &src_off_x, &src_off_y);
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ if (localMask && localMask != pMask)
+ FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
- if (localMask)
- pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
- &mask_off_x, &mask_off_y);
+ return 0;
+ }
+ } else {
+ pSrcPix = NULL;
+ }
- if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ if (localMask) {
+ if (localMask->pDrawable) {
+ pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
+ &mask_off_x, &mask_off_y);
+ if (!pMaskPix) {
+ REGION_UNINIT(screen, &region);
- if (localSrc != pSrc)
- FreePicture(localSrc, 0);
- if (localMask && localMask != pMask)
- FreePicture(localMask, 0);
+ if (localSrc != pSrc)
+ FreePicture(localSrc, 0);
+ if (localMask && localMask != pMask)
+ FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
- return 0;
+ return 0;
+ }
+ } else {
+ pMaskPix = NULL;
+ }
}
- REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
-
if (!(*uxa_screen->info->prepare_composite)
- (op, localSrc, localMask, pDst, pSrcPix, pMaskPix, pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ (op, localSrc, localMask, localDst, pSrcPix, pMaskPix, pDstPix)) {
+ REGION_UNINIT(screen, &region);
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst)
+ FreePicture(localDst, 0);
return -1;
}
- nbox = REGION_NUM_RECTS(&region);
- pbox = REGION_RECTS(&region);
-
if (pMask) {
- xMask = xMask + mask_off_x - xDst - dst_off_x;
- yMask = yMask + mask_off_y - yDst - dst_off_y;
+ xMask = xMask + mask_off_x - xDst;
+ yMask = yMask + mask_off_y - yDst;
}
- xSrc = xSrc + src_off_x - xDst - dst_off_x;
- ySrc = ySrc + src_off_y - yDst - dst_off_y;
+ xSrc = xSrc + src_off_x - xDst;
+ ySrc = ySrc + src_off_y - yDst;
+ nbox = REGION_NUM_RECTS(&region);
+ pbox = REGION_RECTS(&region);
while (nbox--) {
(*uxa_screen->info->composite) (pDstPix,
pbox->x1 + xSrc,
pbox->y1 + ySrc,
pbox->x1 + xMask,
pbox->y1 + yMask,
- pbox->x1,
- pbox->y1,
+ pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y,
pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1);
pbox++;
}
(*uxa_screen->info->done_composite) (pDstPix);
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ REGION_UNINIT(screen, &region);
if (localSrc != pSrc)
FreePicture(localSrc, 0);
if (localMask && localMask != pMask)
FreePicture(localMask, 0);
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0, width, height, xDst_copy, yDst_copy);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
+ }
+
return 1;
}
@@ -917,36 +1323,100 @@ uxa_try_magic_two_pass_composite_helper(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
- uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ uxa_screen_t *uxa_screen = uxa_get_screen(screen);
+ PicturePtr localDst = pDst;
+ int xDst_copy, yDst_copy;
assert(op == PictOpOver);
if (uxa_screen->info->check_composite &&
(!(*uxa_screen->info->check_composite) (PictOpOutReverse, pSrc,
- pMask, pDst)
+ pMask, pDst, width, height)
|| !(*uxa_screen->info->check_composite) (PictOpAdd, pSrc, pMask,
- pDst))) {
+ pDst, width, height))) {
return -1;
}
+ if (uxa_screen->info->check_composite_target &&
+ !uxa_screen->info->check_composite_target(uxa_get_drawable_pixmap(pDst->pDrawable))) {
+ int depth = pDst->pDrawable->depth;
+ PixmapPtr pixmap;
+ int error;
+ GCPtr gc;
+
+ pixmap = uxa_get_drawable_pixmap(pDst->pDrawable);
+ if (uxa_screen->info->check_copy &&
+ !uxa_screen->info->check_copy(pixmap, pixmap, GXcopy, FB_ALLONES))
+ return -1;
+
+ pixmap = screen->CreatePixmap(screen,
+ width, height, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pixmap)
+ return 0;
+
+ gc = GetScratchGC(depth, screen);
+ if (!gc) {
+ screen->DestroyPixmap(pixmap);
+ return 0;
+ }
+
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(pDst->pDrawable, &pixmap->drawable, gc,
+ xDst, yDst, width, height, 0, 0);
+ FreeScratchGC(gc);
+
+ xDst_copy = xDst; xDst = 0;
+ yDst_copy = yDst; yDst = 0;
+
+ localDst = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen, depth, pDst->format),
+ 0, 0, serverClient, &error);
+ screen->DestroyPixmap(pixmap);
+
+ if (!localDst)
+ return 0;
+
+ ValidatePicture(localDst);
+ }
+
/* Now, we think we should be able to accelerate this operation. First,
* composite the destination to be the destination times the source alpha
* factors.
*/
- uxa_composite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask,
- yMask, xDst, yDst, width, height);
+ uxa_composite(PictOpOutReverse, pSrc, pMask, localDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
/* Then, add in the source value times the destination alpha factors (1.0).
*/
- uxa_composite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
- xDst, yDst, width, height);
+ uxa_composite(PictOpAdd, pSrc, pMask, localDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+
+ if (localDst != pDst) {
+ GCPtr gc;
+
+ gc = GetScratchGC(pDst->pDrawable->depth, screen);
+ if (gc) {
+ ValidateGC(pDst->pDrawable, gc);
+ gc->ops->CopyArea(localDst->pDrawable, pDst->pDrawable, gc,
+ 0, 0, width, height, xDst_copy, yDst_copy);
+ FreeScratchGC(gc);
+ }
+
+ FreePicture(localDst, 0);
+ }
return 1;
}
@@ -958,99 +1428,113 @@ compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
if (src->format == dst->format)
return 1;
- if (src->format == PICT_a8r8g8b8 && dst->format == PICT_x8r8g8b8)
+ /* Is the destination an alpha-less version of source? */
+ if (dst->format == PICT_FORMAT(PICT_FORMAT_BPP(src->format),
+ PICT_FORMAT_TYPE(src->format),
+ 0,
+ PICT_FORMAT_R(src->format),
+ PICT_FORMAT_G(src->format),
+ PICT_FORMAT_B(src->format)))
return 1;
- if (src->format == PICT_a8b8g8r8 && dst->format == PICT_x8b8g8r8)
- return 1;
-
- /* xrgb is promoted to argb during image upload... */
+ /* XXX xrgb is promoted to argb during image upload... */
+#if 0
if (dst->format == PICT_a8r8g8b8 && src->format == PICT_x8r8g8b8)
return 1;
+#endif
} else if (op == PictOpOver) {
- if (src->alphaMap || dst->alphaMap)
- return 0;
-
- if (src->format != dst->format)
+ if (PICT_FORMAT_A(src->format))
return 0;
- if (src->format == PICT_x8r8g8b8 || src->format == PICT_x8b8g8r8)
- return 1;
+ return src->format == dst->format;
}
return 0;
}
-static int
-drawable_contains (DrawablePtr drawable, int x1, int y1, int x2, int y2)
-{
- if (x1 < 0 || y1 < 0)
- return FALSE;
-
- if (x2 > drawable->width)
- return FALSE;
-
- if (y2 > drawable->height)
- return FALSE;
-
- return TRUE;
-}
-
void
uxa_composite(CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
{
uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
int ret = -1;
Bool saveSrcRepeat = pSrc->repeat;
Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
RegionRec region;
+ int tx, ty;
if (uxa_screen->swappedOut)
goto fallback;
+ if (!uxa_drawable_is_offscreen(pDst->pDrawable))
+ goto fallback;
+
+
+ if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
+ goto fallback;
+
+
/* Remove repeat in source if useless */
- if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform &&
+ if (pSrc->pDrawable && pSrc->repeat && pSrc->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
(pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
- xSrc >= 0 && (xSrc + width) <= pSrc->pDrawable->width &&
- ySrc >= 0 && (ySrc + height) <= pSrc->pDrawable->height)
+ drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
pSrc->repeat = 0;
if (!pMask) {
+ if (op == PictOpClear) {
+ PicturePtr clear = uxa_solid_clear(pDst->pDrawable->pScreen);
+ if (clear &&
+ uxa_try_driver_solid_fill(clear, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height) == 1)
+ goto done;
+ }
+
if (pSrc->pDrawable == NULL) {
if (pSrc->pSourcePict) {
SourcePict *source = pSrc->pSourcePict;
if (source->type == SourcePictTypeSolidFill) {
- ret = uxa_try_driver_solid_fill(pSrc, pDst,
- xSrc, ySrc,
- xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
+ if (op == PictOpSrc ||
+ (op == PictOpOver &&
+ (source->solidFill.color & 0xff000000) == 0xff000000)) {
+ ret = uxa_try_driver_solid_fill(pSrc, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ }
}
}
- } else if (compatible_formats (op, pDst, pSrc)) {
- if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat) {
- ret = uxa_try_driver_solid_fill(pSrc, pDst,
- xSrc, ySrc,
- xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
- } else if (!pSrc->repeat && !pSrc->transform &&
- drawable_contains(pSrc->pDrawable, xSrc, ySrc, xSrc + width, ySrc + height)) {
+ } else if (pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1 &&
+ pSrc->repeat &&
+ (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) {
+ ret = uxa_try_driver_solid_fill(pSrc, pDst,
+ xSrc, ySrc,
+ xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ } else if (compatible_formats (op, pDst, pSrc) &&
+ pSrc->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
+ if (!pSrc->repeat &&
+ drawable_contains(pSrc->pDrawable,
+ xSrc + tx, ySrc + ty,
+ width, height)) {
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ xSrc += pSrc->pDrawable->x + tx;
+ ySrc += pSrc->pDrawable->y + ty;
if (!miComputeCompositeRegion
(&region, pSrc, pMask, pDst, xSrc, ySrc,
@@ -1066,16 +1550,14 @@ uxa_composite(CARD8 op,
REGION_UNINIT(pDst->pDrawable->pScreen,
&region);
goto done;
- } else if (pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
- !pSrc->transform &&
- pSrc->repeatType == RepeatNormal) {
+ } else if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
+ pSrc->pDrawable->type == DRAWABLE_PIXMAP) {
DDXPointRec patOrg;
/* Let's see if the driver can do the repeat
* in one go
*/
- if (uxa_screen->info->prepare_composite
- && !pSrc->alphaMap && !pDst->alphaMap) {
+ if (uxa_screen->info->prepare_composite) {
ret = uxa_try_driver_composite(op, pSrc,
pMask, pDst,
xSrc, ySrc,
@@ -1091,8 +1573,8 @@ uxa_composite(CARD8 op,
*/
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ xSrc += pSrc->pDrawable->x + tx;
+ ySrc += pSrc->pDrawable->y + ty;
if (!miComputeCompositeRegion
(&region, pSrc, pMask, pDst, xSrc, ySrc,
@@ -1121,15 +1603,14 @@ uxa_composite(CARD8 op,
}
/* Remove repeat in mask if useless */
- if (pMask && pMask->repeat && !pMask->transform && pMask->pDrawable &&
+ if (pMask && pMask->pDrawable && pMask->repeat &&
+ pMask->filter != PictFilterConvolution &&
+ transform_is_integer_translation(pMask->transform, &tx, &ty) &&
(pMask->pDrawable->width > 1 || pMask->pDrawable->height > 1) &&
- xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
- yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
+ drawable_contains(pMask->pDrawable, xMask + tx, yMask + ty, width, height))
pMask->repeat = 0;
- if (uxa_screen->info->prepare_composite &&
- !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
- {
+ if (uxa_screen->info->prepare_composite) {
Bool isSrcSolid;
ret =
@@ -1142,9 +1623,15 @@ uxa_composite(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 &&
- 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 ?
+ pSrc->pSourcePict->type == SourcePictTypeSolidFill :
+ 0;
/* 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
@@ -1156,13 +1643,13 @@ uxa_composite(CARD8 op,
uxa_try_magic_two_pass_composite_helper(op, pSrc,
pMask, pDst,
xSrc, ySrc,
- xMask,
- yMask, xDst,
- yDst, width,
- height);
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
if (ret == 1)
goto done;
}
+
}
fallback:
@@ -1232,15 +1719,15 @@ uxa_create_alpha_picture(ScreenPtr pScreen,
* uxa_check_poly_fill_rect to initialize the contents.
*/
void
-uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+uxa_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int ntrap, xTrapezoid * traps)
{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
+ ScreenPtr screen = dst->pDrawable->pScreen;
BoxRec bounds;
- Bool direct = op == PictOpAdd && miIsSolidAlpha(pSrc);
+ Bool direct;
+ direct = op == PictOpAdd && miIsSolidAlpha(src);
if (maskFormat || direct) {
miTrapezoidBounds(ntrap, traps, &bounds);
@@ -1252,7 +1739,7 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
* Check for solid alpha add
*/
if (direct) {
- DrawablePtr pDraw = pDst->pDrawable;
+ DrawablePtr pDraw = dst->pDrawable;
PixmapPtr pixmap = uxa_get_drawable_pixmap(pDraw);
int xoff, yoff;
@@ -1262,12 +1749,15 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
yoff += pDraw->y;
if (uxa_prepare_access(pDraw, UXA_ACCESS_RW)) {
+ PictureScreenPtr ps = GetPictureScreen(screen);
+
for (; ntrap; ntrap--, traps++)
- (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+ (*ps->RasterizeTrapezoid) (dst, traps, 0, 0);
uxa_finish_access(pDraw);
}
} else if (maskFormat) {
- PicturePtr pPicture;
+ PixmapPtr scratch = NULL;
+ PicturePtr mask;
INT16 xDst, yDst;
INT16 xRel, yRel;
int width, height;
@@ -1291,28 +1781,48 @@ uxa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
pixman_rasterize_trapezoid(image,
(pixman_trapezoid_t *) traps,
-bounds.x1, -bounds.y1);
-
- pPicture =
- uxa_picture_from_pixman_image(pScreen, image, format);
- pixman_image_unref(image);
- if (!pPicture)
+ if (uxa_drawable_is_offscreen(dst->pDrawable)) {
+ mask = uxa_picture_from_pixman_image(screen, image, format);
+ } else {
+ int error;
+
+ scratch = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ mask = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ }
+ if (!mask) {
+ if (scratch)
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
return;
+ }
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
- CompositePicture(op, pSrc, pPicture, pDst,
+ CompositePicture(op, src, mask, dst,
xRel, yRel,
0, 0,
bounds.x1, bounds.y1,
width, height);
- FreePicture(pPicture, 0);
+ FreePicture(mask, 0);
+
+ if (scratch)
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
} else {
- if (pDst->polyEdge == PolyEdgeSharp)
- maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
+ if (dst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
else
- maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
+ maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
for (; ntrap; ntrap--, traps++)
- uxa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ uxa_trapezoids(op, src, dst, maskFormat, xSrc, ySrc,
1, traps);
}
}
diff --git a/driver/xf86-video-intel/uxa/uxa.c b/driver/xf86-video-intel/uxa/uxa.c
index d6ad5a631..37546dc3a 100644
--- a/driver/xf86-video-intel/uxa/uxa.c
+++ b/driver/xf86-video-intel/uxa/uxa.c
@@ -39,7 +39,11 @@
#include "dixfontstr.h"
#include "uxa.h"
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec uxa_screen_index;
+#else
int uxa_screen_index;
+#endif
/**
* uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@@ -388,14 +392,17 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
#ifdef RENDER
if (ps) {
ps->Composite = uxa_screen->SavedComposite;
+ ps->CompositeRects = uxa_screen->SavedCompositeRects;
ps->Glyphs = uxa_screen->SavedGlyphs;
ps->Trapezoids = uxa_screen->SavedTrapezoids;
ps->AddTraps = uxa_screen->SavedAddTraps;
ps->Triangles = uxa_screen->SavedTriangles;
+
+ ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
}
#endif
- xfree(uxa_screen);
+ free(uxa_screen);
return (*pScreen->CloseScreen) (i, pScreen);
}
@@ -406,13 +413,13 @@ static Bool uxa_close_screen(int i, ScreenPtr pScreen)
* without breaking ABI between UXA and the drivers. The driver's
* responsibility is to check beforehand that the UXA module has a matching
* major number and sufficient minor. Drivers are responsible for freeing the
- * driver structure using xfree().
+ * driver structure using free().
*
* @return a newly allocated, zero-filled driver structure
*/
uxa_driver_t *uxa_driver_alloc(void)
{
- return xcalloc(1, sizeof(uxa_driver_t));
+ return calloc(1, sizeof(uxa_driver_t));
}
/**
@@ -429,9 +436,6 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
{
uxa_screen_t *uxa_screen;
ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-#ifdef RENDER
- PictureScreenPtr ps;
-#endif
if (!uxa_driver)
return FALSE;
@@ -460,11 +464,11 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
"non-NULL\n", screen->myNum);
return FALSE;
}
-#ifdef RENDER
- ps = GetPictureScreenIfSet(screen);
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
+ return FALSE;
#endif
-
- uxa_screen = xcalloc(sizeof(uxa_screen_t), 1);
+ uxa_screen = calloc(sizeof(uxa_screen_t), 1);
if (!uxa_screen) {
LogMessage(X_WARNING,
@@ -513,33 +517,32 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access;
#ifdef RENDER
- if (ps) {
- uxa_screen->SavedComposite = ps->Composite;
- ps->Composite = uxa_composite;
+ {
+ PictureScreenPtr ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ uxa_screen->SavedComposite = ps->Composite;
+ ps->Composite = uxa_composite;
- uxa_screen->SavedGlyphs = ps->Glyphs;
- ps->Glyphs = uxa_glyphs;
+ uxa_screen->SavedCompositeRects = ps->CompositeRects;
+ ps->CompositeRects = uxa_solid_rects;
- uxa_screen->SavedTriangles = ps->Triangles;
- ps->Triangles = uxa_triangles;
+ uxa_screen->SavedGlyphs = ps->Glyphs;
+ ps->Glyphs = uxa_glyphs;
- uxa_screen->SavedTrapezoids = ps->Trapezoids;
- ps->Trapezoids = uxa_trapezoids;
+ uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
+ ps->UnrealizeGlyph = uxa_glyph_unrealize;
- uxa_screen->SavedAddTraps = ps->AddTraps;
- ps->AddTraps = uxa_check_add_traps;
- }
-#endif
+ uxa_screen->SavedTriangles = ps->Triangles;
+ ps->Triangles = uxa_triangles;
-#ifdef MITSHM
- /* Re-register with the MI funcs, which don't allow shared pixmaps.
- * Shared pixmaps are almost always a performance loss for us, but this
- * still allows for SHM PutImage.
- */
- ShmRegisterFuncs(screen, &uxa_shm_funcs);
-#endif
+ uxa_screen->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = uxa_trapezoids;
- uxa_glyphs_init(screen);
+ uxa_screen->SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = uxa_check_add_traps;
+ }
+ }
+#endif
LogMessage(X_INFO,
"UXA(%d): Driver registered support for the following"
@@ -561,6 +564,14 @@ Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
return TRUE;
}
+Bool uxa_resources_init(ScreenPtr screen)
+{
+ if (!uxa_glyphs_init(screen))
+ return FALSE;
+
+ return TRUE;
+}
+
/**
* uxa_driver_fini tears down UXA on a given screen.
*
diff --git a/driver/xf86-video-intel/uxa/uxa.h b/driver/xf86-video-intel/uxa/uxa.h
index c7e5566ac..efadfdaaa 100644
--- a/driver/xf86-video-intel/uxa/uxa.h
+++ b/driver/xf86-video-intel/uxa/uxa.h
@@ -74,6 +74,17 @@ typedef struct _UxaDriver {
* @{
*/
/**
+ * check_solid() checks whether the driver can do a solid fill to this drawable.
+ * @param pDrawable Destination drawable
+ * @param alu raster operation
+ * @param planemask write mask for the fill
+ *
+ * The check_solid() call is recommended if prepare_solid() is
+ * implemented, but is not required.
+ */
+ Bool(*check_solid) (DrawablePtr pDrawable, int alu, Pixel planemask);
+
+ /**
* prepare_solid() sets up the driver for doing a solid fill.
* @param pPixmap Destination pixmap
* @param alu raster operation
@@ -138,6 +149,10 @@ typedef struct _UxaDriver {
* @{
*/
/**
+ * check_copy() checks whether the driver can blit between the two Pictures
+ */
+ Bool(*check_copy) (PixmapPtr pSrc, PixmapPtr pDst, int alu, Pixel planemask);
+ /**
* prepare_copy() sets up the driver for doing a copy within video
* memory.
- *
@@ -232,6 +247,8 @@ typedef struct _UxaDriver {
* @param pSrcPicture source Picture
* @param pMaskPicture mask picture
* @param pDstPicture destination Picture
+ * @param width The width of the composite operation
+ * @param height The height of the composite operation
*
* The check_composite() call checks if the driver could handle
* acceleration of op with the given source, mask, and destination
@@ -249,7 +266,32 @@ typedef struct _UxaDriver {
Bool(*check_composite) (int op,
PicturePtr pSrcPicture,
PicturePtr pMaskPicture,
- PicturePtr pDstPicture);
+ PicturePtr pDstPicture,
+ int width, int height);
+
+ /**
+ * check_composite_target() checks to see if the destination of the composite
+ * operation can be used without midification.
+ *
+ * @param pixmap Destination Pixmap
+ *
+ * The check_composite_target() call is recommended if prepare_composite() is
+ * implemented, but is not required.
+ */
+ Bool(*check_composite_target) (PixmapPtr pixmap);
+
+ /**
+ * check_composite_texture() checks to see if a source to the composite
+ * operation can be used without midification.
+ *
+ * @param pScreen Screen
+ * @param pPicture Picture
+ *
+ * The check_composite_texture() call is recommended if prepare_composite() is
+ * implemented, but is not required.
+ */
+ Bool(*check_composite_texture) (ScreenPtr pScreen,
+ PicturePtr pPicture);
/**
* prepare_composite() sets up the driver for doing a composite
@@ -516,6 +558,7 @@ typedef struct _UxaDriver {
uxa_driver_t *uxa_driver_alloc(void);
Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver);
+Bool uxa_resources_init(ScreenPtr screen);
void uxa_driver_fini(ScreenPtr pScreen);