diff options
author | Wang Zhenyu <zhenyu.z.wang@intel.com> | 2006-08-24 10:23:22 +0800 |
---|---|---|
committer | Wang Zhenyu <zhenyu.z.wang@intel.com> | 2006-08-24 10:23:22 +0800 |
commit | 078af29fa65653c5322b006404f7ad29aec24cce (patch) | |
tree | 1c05fbbbc4e07cb6f2e930bc6048f8fa288a38f1 | |
parent | 7458a6adb5ea62f56bb3d4ab19ad7d1aa6ad2d19 (diff) | |
parent | ea63e82ef417a9918e7d7105910a8ddeba2994f6 (diff) |
Merge branch 'master' into exa
Conflicts:
man/i810.man
src/Makefile.am
src/i830_accel.c
src/i830_dga.c
src/i830_driver.c
-rw-r--r-- | README | 151 | ||||
-rw-r--r-- | README.sgml | 117 | ||||
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | man/.gitignore | 2 | ||||
-rw-r--r-- | man/i810.man | 34 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/brw_defines.h | 847 | ||||
-rw-r--r-- | src/brw_structs.h | 1340 | ||||
-rw-r--r-- | src/common.h | 35 | ||||
-rw-r--r-- | src/i810.h | 4 | ||||
-rw-r--r-- | src/i810_dri.h | 4 | ||||
-rw-r--r-- | src/i810_driver.c | 21 | ||||
-rw-r--r-- | src/i810_reg.h | 323 | ||||
-rw-r--r-- | src/i830.h | 67 | ||||
-rw-r--r-- | src/i830_3d.c | 1 | ||||
-rw-r--r-- | src/i830_accel.c | 14 | ||||
-rw-r--r-- | src/i830_common.h | 8 | ||||
-rw-r--r-- | src/i830_cursor.c | 218 | ||||
-rw-r--r-- | src/i830_dga.c | 47 | ||||
-rw-r--r-- | src/i830_dri.c | 118 | ||||
-rw-r--r-- | src/i830_dri.h | 38 | ||||
-rw-r--r-- | src/i830_driver.c | 2678 | ||||
-rw-r--r-- | src/i830_memory.c | 111 | ||||
-rw-r--r-- | src/i830_modes.c | 132 | ||||
-rw-r--r-- | src/i830_rotate.c | 40 | ||||
-rw-r--r-- | src/i830_video.c | 1528 | ||||
-rw-r--r-- | src/i830_video.h | 76 | ||||
-rw-r--r-- | src/i830_xaa.c | 76 | ||||
-rw-r--r-- | src/i915_3d.c | 1 | ||||
-rw-r--r-- | src/i915_video.c | 467 | ||||
-rw-r--r-- | src/wm_prog.h | 166 |
31 files changed, 8028 insertions, 654 deletions
@@ -1,8 +1,6 @@ - $XFree86: - xc/programs/Xserver/hw/xfree86/doc/sgml/i810.sgml,v 1.4 - 2001/04/04 01:34:18 dawes Exp $ Information for i810 Users - Precision Insight, Inc. - 3 March 2000 + Information for Intel graphics driver users + Eric Anholt + 2006-08-04 ____________________________________________________________ Table of Contents @@ -12,88 +10,85 @@ 2. Supported Hardware 3. Features 4. Technical Notes - 5. Reported Working Video Cards - 6. Configuration - 7. Driver Options - 8. Known Limitations - 9. Author + 5. Configuration + 6. Driver Options + 7. Known Limitations + 8. Author ______________________________________________________________________ - [1m1. Introduction[0m + 11.. IInnttrroodduuccttiioonn - This document provides a brief summary of the i810/i815 support - provided by the i810 driver. Support for later chipsets is not - covered here. More up to date information about the i810 driver can - be found in the i810(4) manual page. + This document provides a brief summary of the Intel graphics support + provided by the xf86-video-intel driver. More information can also be + found in the i810(4) manual page. - [1m2. Supported Hardware[0m + 22.. SSuuppppoorrtteedd HHaarrddwwaarree - +o Intel 810 motherboards: + +o i810, - +o i810, + +o i810-dc100, - +o i810-dc100, + +o i810e - +o i810e + +o i815 - +o i815 + +o i830 + +o i845 + +o i852 - [1m3. Features[0m + +o i855 + +o i915 - +o Full support for 8, 15, 16, and 24 bit pixel depths. + +o i945 - +o Hardware cursor support to reduce sprite flicker. + +o i965 - +o Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24 - bit pixel depths. - +o Support for high resolution video modes up to 1600x1200. - +o Fully programmable clock supported. + 33.. FFeeaattuurreess - +o Robust text mode restore for VT switching. + +o Full support for 8, 15, 16, and 24 bit pixel depths. + +o Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24 + bit pixel depths. - [1m4. Technical Notes[0m + +o Hardware accelerated 3D drawing using OpenGL and the DRI. + +o Hardware cursor support to reduce sprite flicker. - +o Hardware acceleration is not possible when using the framebuffer in - 32 bit per pixel format, and this mode is not supported by this - driver. + +o Textured video XV implementation on i915 through i965. - +o Interlace modes cannot be supported. + +o Hardware overlay XV implementation up through i945. - +o This driver currently only works for Linux/ix86 and recent versions - of FreeBSD. It requires the agpgart kernel support, which is - included in Linux kernels 2.3.42 and higher, and FreeBSD 4.1 and - higher. + +o Screen resize and rotation on chipsets up through i945. + +o Screen resize on i965. - [1m5. Reported Working Video Cards[0m + 44.. TTeecchhnniiccaall NNootteess - +o Intel evaluation hardware - i810, i810-dc100, i810e and i815. - +o Tyan Tomcat Motherboard. + +o Interlace modes cannot be supported. - +o HappyPC set-top box. + +o This driver requires kernel support for AGP, which is included in + Linux kernels 2.3.42 and higher, and FreeBSD 4.1 and higher. - [1m6. Configuration[0m + 55.. CCoonnffiigguurraattiioonn The driver auto-detects all device information necessary to initialize - the card. The only lines you need in the "Device" section of your - xorg.conf file are: + the card. The only lines you should need in the "Device" section of + your xorg.conf file are: Section "Device" Identifier "Intel i810" @@ -101,54 +96,68 @@ EndSection - or let xorgconfig do this for you. - However, if you have problems with auto-detection, you can specify: + In order to use most resolutions, it is necessary to install the + "agpgart.o" module. You will probably have to compile the module + yourself (see the notes in the module). - +o DacSpeed - in MHz - +o MemBase - physical address of the linear framebuffer + 66.. DDrriivveerr OOppttiioonnss - +o IOBase - physical address of the memory mapped IO registers + Please refer to the i810(4) manual page for information on + configuration options. - In order to use most resolutions, it is necessary to install the (see - the notes in the module). - Note: the i810 driver detects whether your motherboard has display - cache video memory. This memory is has reduced bandwidth compared to - normal system memory, and isn't used by the server. The main function - of this memory is for ancillary buffers (eg. z buffer) in a - forthcoming 3d capable server. + 77.. KKnnoowwnn LLiimmiittaattiioonnss - [1m7. Driver Options[0m + +o Many systems with Intel graphics have issues with setting video + modes at larger than some small maximum resolution. This is not + fixed in the current release, but is being actively worked on in + the modesetting branch. + +o Bug #5795: Some systems have issues with VT switching. This should + be fixed with the modesetting brach integration. - +o "NoAccel" - Turn off hardware acceleration + +o Bug #5817: Hotkey switching from LVDS to CRT breaks CRT output. + This is a known issue, but will not be fixed in the current + release. + +o Bug #6635: Video is output from an incorrect offset in the + framebuffer. This is expected to be fixed with the modesetting + branch integration. - +o "SWCursor" - Request a software cursor (hardware is default) + +o GL_EXT_texture_compression_s3tc is not supported. We can't support + the extension due to patent restrictions on compression, but may be + able to support an option for partial extension support in the + future. For now, this prevents Quake4 and some other games from + running. - +o "Dac6Bit" - Force the use of a 6 Bit Dac (8 Bit is the default) + +o Some X Test Suite cases sometimes fail due to a timeout. These + cases include: Xt8/XtResizeWindow, Xt8/XtQueryGeometry, + Xt9/XtAppAddInput, Xt9/XtRemoveInput, Xt9/XtAppAddTimeOut, + Xt9/XtRemoveTimeOut, Xt9/XtAddGrab, Xt9/XtRemoveGrab. + +o Some X Test Suite cases fail in 64-bit mode: Xlib9/XDrawArc, + XDrawImageString, XDrawLine, XDrawRectangle, XDrawSegments, + XFillArc, XFillPolygon, XFillRectangle, XPutImage, + Xt11/XtVaGetSubresources, XtSetSubvalues, and XtVaSetSubvalues. - [1m8. Known Limitations[0m + +o Some GLEAN test cases fail if DRI is enabled: pointAtten, + readPixSanity, texCombine, texCube, texEnv, texgen, + coloredTexPerf2, and coloredLitPerf2. - +o No 3D support in this release. - +o Running two X servers on different VTs is not supported at this - time. + 88.. AAuutthhoorr - - [1m9. Author[0m - + +o Eric Anholt +o Keith Whitwell - The X11R6.8 version of this driver originally came from XFree86 4.4 + The X11R7.1 version of this driver originally came from XFree86 4.4 rc2. The XFree86 version of this driver was donated to The XFree86 Project @@ -160,7 +169,9 @@ - http://www.precisioninsight.com + The X.Org version of this driver is maintained by Intel Corporation. + + http://www.intellinuxgraphics.org diff --git a/README.sgml b/README.sgml index 2aba95fd..fd52608c 100644 --- a/README.sgml +++ b/README.sgml @@ -3,31 +3,31 @@ ]> <article> -<title>Information for i810 Users -<author>Precision Insight, Inc. -<date>3 March 2000 -<ident> -$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/i810.sgml,v 1.4 2001/04/04 01:34:18 dawes Exp $ -</ident> +<title>Information for Intel graphics driver users +<author>Eric Anholt +<date>2006-08-04 <toc> <sect>Introduction <p> -This document provides a brief summary of the i810/i815 support provided -by the i810 driver. Support for later chipsets is not covered here. -More up to date information about the i810 driver can be found in the +This document provides a brief summary of the Intel graphics support provided +by the xf86-video-intel driver. More information can also be found in the <htmlurl name="i810(4)" url="i810.4.html"> manual page. <sect>Supported Hardware <p> <itemize> - <item>Intel 810 motherboards: - <itemize> - <item>i810, - <item>i810-dc100, - <item>i810e - <item>i815 - </itemize> + <item>i810, + <item>i810-dc100, + <item>i810e + <item>i815 + <item>i830 + <item>i845 + <item>i852 + <item>i855 + <item>i915 + <item>i945 + <item>i965 </itemize> @@ -35,42 +35,31 @@ More up to date information about the i810 driver can be found in the <p> <itemize> <item>Full support for 8, 15, 16, and 24 bit pixel depths. - <item>Hardware cursor support to reduce sprite flicker. <item>Hardware accelerated 2D drawing engine support for 8, 15, 16 and 24 bit pixel depths. - <item>Support for high resolution video modes up to 1600x1200. - <item>Fully programmable clock supported. - <item>Robust text mode restore for VT switching. + <item>Hardware accelerated 3D drawing using OpenGL and the DRI. + <item>Hardware cursor support to reduce sprite flicker. + <item>Textured video XV implementation on i915 through i965. + <item>Hardware overlay XV implementation up through i945. + <item>Screen resize and rotation on chipsets up through i945. + <item>Screen resize on i965. </itemize> <sect>Technical Notes <p> <itemize> - <item>Hardware acceleration is not possible when using the framebuffer - in 32 bit per pixel format, and this mode is not supported by - this driver. <item>Interlace modes cannot be supported. - <item>This driver currently only works for Linux/ix86 and recent versions - of FreeBSD. It requires the agpgart kernel support, which is + <item>This driver requires kernel support for AGP, which is included in Linux kernels 2.3.42 and higher, and FreeBSD 4.1 and higher. </itemize> -<sect>Reported Working Video Cards -<p> -<itemize> - <item>Intel evaluation hardware - i810, i810-dc100, i810e and i815. - <item>Tyan Tomcat Motherboard. - <item>HappyPC set-top box. -</itemize> - - <sect>Configuration <p> The driver auto-detects all device information necessary to -initialize the card. The only lines you need in the "Device" +initialize the card. The only lines you should need in the "Device" section of your xorg.conf file are: <verb> Section "Device" @@ -78,45 +67,51 @@ section of your xorg.conf file are: Driver "i810" EndSection </verb> -or let <tt>xorgconfig</tt> do this for you. - -However, if you have problems with auto-detection, you can specify: -<itemize> - <item>DacSpeed - in MHz - <item>MemBase - physical address of the linear framebuffer - <item>IOBase - physical address of the memory mapped IO registers -</itemize> In order to use most resolutions, it is necessary to install the -'agpgart.o' module. You will probably have to compile the module yourself +"agpgart.o" module. You will probably have to compile the module yourself (see the notes in the module). -Note: the i810 driver detects whether your motherboard has display cache -video memory. This memory is has reduced bandwidth compared to normal -system memory, and isn't used by the server. The main function of this -memory is for ancillary buffers (eg. z buffer) in a forthcoming 3d -capable server. - - <sect>Driver Options <p> -<itemize> - <item>"NoAccel" - Turn off hardware acceleration - <item>"SWCursor" - Request a software cursor (hardware is default) - <item>"Dac6Bit" - Force the use of a 6 Bit Dac (8 Bit is the default) -</itemize> +Please refer to the <htmlurl name="i810(4)" url="i810.4.html"> manual page +for information on configuration options. + <sect>Known Limitations <p> <itemize> - <item>No 3D support in this release. - <item>Running two X servers on different VTs is not supported at this time. + <item>Many systems with Intel graphics have issues with setting video modes +at larger than some small maximum resolution. This is not fixed in the current +release, but is being actively worked on in the modesetting branch. + <item>Bug #5795: Some systems have issues with VT switching. This should +be fixed with the modesetting brach integration. + <item>Bug #5817: Hotkey switching from LVDS to CRT breaks CRT output. This +is a known issue, but will not be fixed in the current release. + <item>Bug #6635: Video is output from an incorrect offset in the framebuffer. +This is expected to be fixed with the modesetting branch integration. + <item>GL_EXT_texture_compression_s3tc is not supported. We can't support the +extension due to patent restrictions on compression, but may be able to support +an option for partial extension support in the future. For now, this prevents +Quake4 and some other games from running. + <item>Some X Test Suite cases sometimes fail due to a timeout. These cases +include: Xt8/XtResizeWindow, Xt8/XtQueryGeometry, Xt9/XtAppAddInput, +Xt9/XtRemoveInput, Xt9/XtAppAddTimeOut, Xt9/XtRemoveTimeOut, Xt9/XtAddGrab, +Xt9/XtRemoveGrab. + <item>Some X Test Suite cases fail in 64-bit mode: Xlib9/XDrawArc, +XDrawImageString, XDrawLine, XDrawRectangle, XDrawSegments, XFillArc, +XFillPolygon, XFillRectangle, XPutImage, Xt11/XtVaGetSubresources, +XtSetSubvalues, and XtVaSetSubvalues. + <item>Some GLEAN test cases fail if DRI is enabled: pointAtten, +readPixSanity, texCombine, texCube, texEnv, texgen, coloredTexPerf2, and +coloredLitPerf2. </itemize> <sect>Author <p> <itemize> + <item>Eric Anholt <item>Keith Whitwell </itemize> @@ -129,8 +124,10 @@ The XFree86 version of this driver was donated to The XFree86 Project by: USA </verb> -<htmlurl name="http://www.precisioninsight.com" - url="http://www.precisioninsight.com"> +The X.Org version of this driver is maintained by Intel Corporation. + +<htmlurl name="http://www.intellinuxgraphics.org" + url="http://www.intellinuxgraphics.org"> </article> diff --git a/configure.ac b/configure.ac index 82d3e55f..436d7e5c 100644 --- a/configure.ac +++ b/configure.ac @@ -22,10 +22,20 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-i810], - 1.6.0, + 1.6.5, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-i810) +AC_DEFINE_UNQUOTED([INTEL_VERSION_MAJOR], + [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\)\.[[0-9]]\.[[0-9]]/\1/')], + [Major version]) +AC_DEFINE_UNQUOTED([INTEL_VERSION_MINOR], + [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.\([[0-9]]\)\.[[0-9]]/\1/')], + [Minor version]) +AC_DEFINE_UNQUOTED([INTEL_VERSION_PATCH], + [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.[[0-9]]\.\([[0-9]]\)/\1/')], + [Patch version]) + AC_CONFIG_SRCDIR([Makefile.am]) AM_CONFIG_HEADER([config.h]) AC_CONFIG_AUX_DIR(.) @@ -54,6 +64,7 @@ AC_ARG_ENABLE(dri, AC_HELP_STRING([--disable-dri], # Checks for extensions +XORG_DRIVER_CHECK_EXT(XINERAMA, xineramaproto) XORG_DRIVER_CHECK_EXT(RANDR, randrproto) XORG_DRIVER_CHECK_EXT(RENDER, renderproto) XORG_DRIVER_CHECK_EXT(XF86DRI, xextproto x11) diff --git a/man/.gitignore b/man/.gitignore deleted file mode 100644 index a438e807..00000000 --- a/man/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -i810.4 -i810.4x diff --git a/man/i810.man b/man/i810.man index 62d6b73d..e396e52f 100644 --- a/man/i810.man +++ b/man/i810.man @@ -17,30 +17,29 @@ i810 \- Intel 8xx integrated graphics chipsets is an __xservername__ driver for Intel integrated graphics chipsets. The driver supports depths 8, 15, 16 and 24. All visual types are supported in depth 8. For the i810/i815 other depths support the -TrueColor and DirectColor visuals. For the 830M and later, only the +TrueColor and DirectColor visuals. For the i830M and later, only the TrueColor visual is supported for depths greater than 8. The driver supports hardware accelerated 3D via the Direct Rendering Infrastructure (DRI), but only in depth 16 for the i810/i815 and depths 16 and 24 for the 830M and later. .SH SUPPORTED HARDWARE .B i810 -supports the i810, i810-DC100, i810e, i815, 830M, 845G, 852GM, 855GM, -865G, 915G and 915GM chipsets. +supports the i810, i810-DC100, i810e, i815, i830M, 845G, 852GM, 855GM, +865G, 915G, 915GM, 945G, 945GM, 965G, 965Q and 946GZ chipsets. .SH CONFIGURATION DETAILS Please refer to __xconfigfile__(__filemansuffix__) for general configuration details. This section only covers configuration details specific to this driver. .PP -The Intel 8xx family of integrated graphics chipsets has a unified memory -architecture and uses system memory for video ram. For the i810 and +The Intel 8xx and 9xx families of integrated graphics chipsets has a unified +memory architecture and uses system memory for video ram. For the i810 and i815 family of chipset, operating system support for allocating system -memory for video use is required in order to use this driver. For the -830M and later, this is required in order for the driver to use more -video ram than has been pre-allocated at boot time by the BIOS. This -is usually achieved with an "agpgart" or "agp" kernel driver. Linux, -and recent versions of FreeBSD, OpenBSD and NetBSD have such kernel -drivers available. +memory for video use is required in order to use this driver. For the 830M +and later, this is required in order for the driver to use more video ram +than has been pre-allocated at boot time by the BIOS. This is usually +achieved with an "agpgart" or "agp" kernel driver. Linux, and recent +versions of FreeBSD, OpenBSD and NetBSD have such kernel drivers available. .PP By default 8 Megabytes of system memory are used for graphics. For the 830M and later, the @@ -214,10 +213,11 @@ extension. Default: "XAA". .SH "SEE ALSO" __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) .SH AUTHORS -Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek, +Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek, Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu. 830M and 845G -support reworked for XFree86 4.3 by David Dawes and Keith Whitwell. -852GM, 855GM, and 865G support added by David Dawes and Keith Whitwell. -915G and 915GM support added by Alan Hourihane and Keith Whitwell. -Dual Head, Clone and lid status support added by Alan Hourihane. EXA support -added by Jesse Barnes. +support reworked for XFree86 4.3 by David Dawes and Keith Whitwell. 852GM, +855GM, and 865G support added by David Dawes and Keith Whitwell. 915G, +915GM, 945G, 945GM, 965G, 965Q and 946GZ support added by Alan Hourihane and +Keith Whitwell. Dual Head, Clone and lid status support added by Alan +Hourihane. Textured video support for 915G and later chips added by Keith +Packard and Eric Anholt. diff --git a/src/Makefile.am b/src/Makefile.am index c2e49ac3..e58350c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,9 @@ i810_drv_la_LDFLAGS = -module -avoid-version i810_drv_ladir = @moduledir@/drivers i810_drv_la_SOURCES = \ + brw_defines.h \ + brw_structs.h \ + wm_prog.h \ common.h \ i810_accel.c \ i810_common.h \ @@ -53,6 +56,7 @@ i810_drv_la_SOURCES = \ i830_memory.c \ i830_modes.c \ i830_video.c \ + i830_video.h \ i830_rotate.c \ i830_randr.c \ i830_3d.c \ @@ -60,6 +64,7 @@ i810_drv_la_SOURCES = \ i915_3d.c \ i915_3d.h \ i915_reg.h \ + i915_video.c \ i830_exa.c \ i830_xaa.c \ i830_exa_render.c \ diff --git a/src/brw_defines.h b/src/brw_defines.h new file mode 100644 index 00000000..93aed544 --- /dev/null +++ b/src/brw_defines.h @@ -0,0 +1,847 @@ + /************************************************************************** + * + * Copyright 2005 Tungsten Graphics, 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 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. + * + **************************************************************************/ + +#ifndef BRW_DEFINES_H +#define BRW_DEFINES_H + +/* + */ +#if 0 +#define MI_NOOP 0x00 +#define MI_USER_INTERRUPT 0x02 +#define MI_WAIT_FOR_EVENT 0x03 +#define MI_FLUSH 0x04 +#define MI_REPORT_HEAD 0x07 +#define MI_ARB_ON_OFF 0x08 +#define MI_BATCH_BUFFER_END 0x0A +#define MI_OVERLAY_FLIP 0x11 +#define MI_LOAD_SCAN_LINES_INCL 0x12 +#define MI_LOAD_SCAN_LINES_EXCL 0x13 +#define MI_DISPLAY_BUFFER_INFO 0x14 +#define MI_SET_CONTEXT 0x18 +#define MI_STORE_DATA_IMM 0x20 +#define MI_STORE_DATA_INDEX 0x21 +#define MI_LOAD_REGISTER_IMM 0x22 +#define MI_STORE_REGISTER_MEM 0x24 +#define MI_BATCH_BUFFER_START 0x31 + +#define MI_SYNCHRONOUS_FLIP 0x0 +#define MI_ASYNCHRONOUS_FLIP 0x1 + +#define MI_BUFFER_SECURE 0x0 +#define MI_BUFFER_NONSECURE 0x1 + +#define MI_ARBITRATE_AT_CHAIN_POINTS 0x0 +#define MI_ARBITRATE_BETWEEN_INSTS 0x1 +#define MI_NO_ARBITRATION 0x3 + +#define MI_CONDITION_CODE_WAIT_DISABLED 0x0 +#define MI_CONDITION_CODE_WAIT_0 0x1 +#define MI_CONDITION_CODE_WAIT_1 0x2 +#define MI_CONDITION_CODE_WAIT_2 0x3 +#define MI_CONDITION_CODE_WAIT_3 0x4 +#define MI_CONDITION_CODE_WAIT_4 0x5 + +#define MI_DISPLAY_PIPE_A 0x0 +#define MI_DISPLAY_PIPE_B 0x1 + +#define MI_DISPLAY_PLANE_A 0x0 +#define MI_DISPLAY_PLANE_B 0x1 +#define MI_DISPLAY_PLANE_C 0x2 + +#define MI_STANDARD_FLIP 0x0 +#define MI_ENQUEUE_FLIP_PERFORM_BASE_FRAME_NUMBER_LOAD 0x1 +#define MI_ENQUEUE_FLIP_TARGET_FRAME_NUMBER_RELATIVE 0x2 +#define MI_ENQUEUE_FLIP_ABSOLUTE_TARGET_FRAME_NUMBER 0x3 + +#define MI_PHYSICAL_ADDRESS 0x0 +#define MI_VIRTUAL_ADDRESS 0x1 + +#define MI_BUFFER_MEMORY_MAIN 0x0 +#define MI_BUFFER_MEMORY_GTT 0x2 +#define MI_BUFFER_MEMORY_PER_PROCESS_GTT 0x3 + +#define MI_FLIP_CONTINUE 0x0 +#define MI_FLIP_ON 0x1 +#define MI_FLIP_OFF 0x2 + +#define MI_UNTRUSTED_REGISTER_SPACE 0x0 +#define MI_TRUSTED_REGISTER_SPACE 0x1 +#endif + +/* 3D state: + */ +#define _3DOP_3DSTATE_PIPELINED 0x0 +#define _3DOP_3DSTATE_NONPIPELINED 0x1 +#define _3DOP_3DCONTROL 0x2 +#define _3DOP_3DPRIMITIVE 0x3 + +#define _3DSTATE_PIPELINED_POINTERS 0x00 +#define _3DSTATE_BINDING_TABLE_POINTERS 0x01 +#define _3DSTATE_VERTEX_BUFFERS 0x08 +#define _3DSTATE_VERTEX_ELEMENTS 0x09 +#define _3DSTATE_INDEX_BUFFER 0x0A +#define _3DSTATE_VF_STATISTICS 0x0B +#define _3DSTATE_DRAWING_RECTANGLE 0x00 +#define _3DSTATE_CONSTANT_COLOR 0x01 +#define _3DSTATE_SAMPLER_PALETTE_LOAD 0x02 +#define _3DSTATE_CHROMA_KEY 0x04 +#define _3DSTATE_DEPTH_BUFFER 0x05 +#define _3DSTATE_POLY_STIPPLE_OFFSET 0x06 +#define _3DSTATE_POLY_STIPPLE_PATTERN 0x07 +#define _3DSTATE_LINE_STIPPLE 0x08 +#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x09 +#define _3DCONTROL 0x00 +#define _3DPRIMITIVE 0x00 + +#define PIPE_CONTROL_NOWRITE 0x00 +#define PIPE_CONTROL_WRITEIMMEDIATE 0x01 +#define PIPE_CONTROL_WRITEDEPTH 0x02 +#define PIPE_CONTROL_WRITETIMESTAMP 0x03 + +#define PIPE_CONTROL_GTTWRITE_PROCESS_LOCAL 0x00 +#define PIPE_CONTROL_GTTWRITE_GLOBAL 0x01 + +#define _3DPRIM_POINTLIST 0x01 +#define _3DPRIM_LINELIST 0x02 +#define _3DPRIM_LINESTRIP 0x03 +#define _3DPRIM_TRILIST 0x04 +#define _3DPRIM_TRISTRIP 0x05 +#define _3DPRIM_TRIFAN 0x06 +#define _3DPRIM_QUADLIST 0x07 +#define _3DPRIM_QUADSTRIP 0x08 +#define _3DPRIM_LINELIST_ADJ 0x09 +#define _3DPRIM_LINESTRIP_ADJ 0x0A +#define _3DPRIM_TRILIST_ADJ 0x0B +#define _3DPRIM_TRISTRIP_ADJ 0x0C +#define _3DPRIM_TRISTRIP_REVERSE 0x0D +#define _3DPRIM_POLYGON 0x0E +#define _3DPRIM_RECTLIST 0x0F +#define _3DPRIM_LINELOOP 0x10 +#define _3DPRIM_POINTLIST_BF 0x11 +#define _3DPRIM_LINESTRIP_CONT 0x12 +#define _3DPRIM_LINESTRIP_BF 0x13 +#define _3DPRIM_LINESTRIP_CONT_BF 0x14 +#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15 + +#define _3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL 0 +#define _3DPRIM_VERTEXBUFFER_ACCESS_RANDOM 1 + +#define BRW_ANISORATIO_2 0 +#define BRW_ANISORATIO_4 1 +#define BRW_ANISORATIO_6 2 +#define BRW_ANISORATIO_8 3 +#define BRW_ANISORATIO_10 4 +#define BRW_ANISORATIO_12 5 +#define BRW_ANISORATIO_14 6 +#define BRW_ANISORATIO_16 7 + +#define BRW_BLENDFACTOR_ONE 0x1 +#define BRW_BLENDFACTOR_SRC_COLOR 0x2 +#define BRW_BLENDFACTOR_SRC_ALPHA 0x3 +#define BRW_BLENDFACTOR_DST_ALPHA 0x4 +#define BRW_BLENDFACTOR_DST_COLOR 0x5 +#define BRW_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6 +#define BRW_BLENDFACTOR_CONST_COLOR 0x7 +#define BRW_BLENDFACTOR_CONST_ALPHA 0x8 +#define BRW_BLENDFACTOR_SRC1_COLOR 0x9 +#define BRW_BLENDFACTOR_SRC1_ALPHA 0x0A +#define BRW_BLENDFACTOR_ZERO 0x11 +#define BRW_BLENDFACTOR_INV_SRC_COLOR 0x12 +#define BRW_BLENDFACTOR_INV_SRC_ALPHA 0x13 +#define BRW_BLENDFACTOR_INV_DST_ALPHA 0x14 +#define BRW_BLENDFACTOR_INV_DST_COLOR 0x15 +#define BRW_BLENDFACTOR_INV_CONST_COLOR 0x17 +#define BRW_BLENDFACTOR_INV_CONST_ALPHA 0x18 +#define BRW_BLENDFACTOR_INV_SRC1_COLOR 0x19 +#define BRW_BLENDFACTOR_INV_SRC1_ALPHA 0x1A + +#define BRW_BLENDFUNCTION_ADD 0 +#define BRW_BLENDFUNCTION_SUBTRACT 1 +#define BRW_BLENDFUNCTION_REVERSE_SUBTRACT 2 +#define BRW_BLENDFUNCTION_MIN 3 +#define BRW_BLENDFUNCTION_MAX 4 + +#define BRW_ALPHATEST_FORMAT_UNORM8 0 +#define BRW_ALPHATEST_FORMAT_FLOAT32 1 + +#define BRW_CHROMAKEY_KILL_ON_ANY_MATCH 0 +#define BRW_CHROMAKEY_REPLACE_BLACK 1 + +#define BRW_CLIP_API_OGL 0 +#define BRW_CLIP_API_DX 1 + +#define BRW_CLIPMODE_NORMAL 0 +#define BRW_CLIPMODE_CLIP_ALL 1 +#define BRW_CLIPMODE_CLIP_NON_REJECTED 2 +#define BRW_CLIPMODE_REJECT_ALL 3 +#define BRW_CLIPMODE_ACCEPT_ALL 4 + +#define BRW_CLIP_NDCSPACE 0 +#define BRW_CLIP_SCREENSPACE 1 + +#define BRW_COMPAREFUNCTION_ALWAYS 0 +#define BRW_COMPAREFUNCTION_NEVER 1 +#define BRW_COMPAREFUNCTION_LESS 2 +#define BRW_COMPAREFUNCTION_EQUAL 3 +#define BRW_COMPAREFUNCTION_LEQUAL 4 +#define BRW_COMPAREFUNCTION_GREATER 5 +#define BRW_COMPAREFUNCTION_NOTEQUAL 6 +#define BRW_COMPAREFUNCTION_GEQUAL 7 + +#define BRW_COVERAGE_PIXELS_HALF 0 +#define BRW_COVERAGE_PIXELS_1 1 +#define BRW_COVERAGE_PIXELS_2 2 +#define BRW_COVERAGE_PIXELS_4 3 + +#define BRW_CULLMODE_BOTH 0 +#define BRW_CULLMODE_NONE 1 +#define BRW_CULLMODE_FRONT 2 +#define BRW_CULLMODE_BACK 3 + +#define BRW_DEFAULTCOLOR_R8G8B8A8_UNORM 0 +#define BRW_DEFAULTCOLOR_R32G32B32A32_FLOAT 1 + +#define BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0 +#define BRW_DEPTHFORMAT_D32_FLOAT 1 +#define BRW_DEPTHFORMAT_D24_UNORM_S8_UINT 2 +#define BRW_DEPTHFORMAT_D16_UNORM 5 + +#define BRW_FLOATING_POINT_IEEE_754 0 +#define BRW_FLOATING_POINT_NON_IEEE_754 1 + +#define BRW_FRONTWINDING_CW 0 +#define BRW_FRONTWINDING_CCW 1 + +#define BRW_INDEX_BYTE 0 +#define BRW_INDEX_WORD 1 +#define BRW_INDEX_DWORD 2 + +#define BRW_LOGICOPFUNCTION_CLEAR 0 +#define BRW_LOGICOPFUNCTION_NOR 1 +#define BRW_LOGICOPFUNCTION_AND_INVERTED 2 +#define BRW_LOGICOPFUNCTION_COPY_INVERTED 3 +#define BRW_LOGICOPFUNCTION_AND_REVERSE 4 +#define BRW_LOGICOPFUNCTION_INVERT 5 +#define BRW_LOGICOPFUNCTION_XOR 6 +#define BRW_LOGICOPFUNCTION_NAND 7 +#define BRW_LOGICOPFUNCTION_AND 8 +#define BRW_LOGICOPFUNCTION_EQUIV 9 +#define BRW_LOGICOPFUNCTION_NOOP 10 +#define BRW_LOGICOPFUNCTION_OR_INVERTED 11 +#define BRW_LOGICOPFUNCTION_COPY 12 +#define BRW_LOGICOPFUNCTION_OR_REVERSE 13 +#define BRW_LOGICOPFUNCTION_OR 14 +#define BRW_LOGICOPFUNCTION_SET 15 + +#define BRW_MAPFILTER_NEAREST 0x0 +#define BRW_MAPFILTER_LINEAR 0x1 +#define BRW_MAPFILTER_ANISOTROPIC 0x2 + +#define BRW_MIPFILTER_NONE 0 +#define BRW_MIPFILTER_NEAREST 1 +#define BRW_MIPFILTER_LINEAR 3 + +#define BRW_POLYGON_FRONT_FACING 0 +#define BRW_POLYGON_BACK_FACING 1 + +#define BRW_PREFILTER_ALWAYS 0x0 +#define BRW_PREFILTER_NEVER 0x1 +#define BRW_PREFILTER_LESS 0x2 +#define BRW_PREFILTER_EQUAL 0x3 +#define BRW_PREFILTER_LEQUAL 0x4 +#define BRW_PREFILTER_GREATER 0x5 +#define BRW_PREFILTER_NOTEQUAL 0x6 +#define BRW_PREFILTER_GEQUAL 0x7 + +#define BRW_PROVOKING_VERTEX_0 0 +#define BRW_PROVOKING_VERTEX_1 1 +#define BRW_PROVOKING_VERTEX_2 2 + +#define BRW_RASTRULE_UPPER_LEFT 0 +#define BRW_RASTRULE_UPPER_RIGHT 1 + +#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0 +#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1 +#define BRW_RENDERTARGET_CLAMPRANGE_FORMAT 2 + +#define BRW_STENCILOP_KEEP 0 +#define BRW_STENCILOP_ZERO 1 +#define BRW_STENCILOP_REPLACE 2 +#define BRW_STENCILOP_INCRSAT 3 +#define BRW_STENCILOP_DECRSAT 4 +#define BRW_STENCILOP_INCR 5 +#define BRW_STENCILOP_DECR 6 +#define BRW_STENCILOP_INVERT 7 + +#define BRW_SURFACE_MIPMAPLAYOUT_BELOW 0 +#define BRW_SURFACE_MIPMAPLAYOUT_RIGHT 1 + +#define BRW_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000 +#define BRW_SURFACEFORMAT_R32G32B32A32_SINT 0x001 +#define BRW_SURFACEFORMAT_R32G32B32A32_UINT 0x002 +#define BRW_SURFACEFORMAT_R32G32B32A32_UNORM 0x003 +#define BRW_SURFACEFORMAT_R32G32B32A32_SNORM 0x004 +#define BRW_SURFACEFORMAT_R64G64_FLOAT 0x005 +#define BRW_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006 +#define BRW_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007 +#define BRW_SURFACEFORMAT_R32G32B32A32_USCALED 0x008 +#define BRW_SURFACEFORMAT_R32G32B32_FLOAT 0x040 +#define BRW_SURFACEFORMAT_R32G32B32_SINT 0x041 +#define BRW_SURFACEFORMAT_R32G32B32_UINT 0x042 +#define BRW_SURFACEFORMAT_R32G32B32_UNORM 0x043 +#define BRW_SURFACEFORMAT_R32G32B32_SNORM 0x044 +#define BRW_SURFACEFORMAT_R32G32B32_SSCALED 0x045 +#define BRW_SURFACEFORMAT_R32G32B32_USCALED 0x046 +#define BRW_SURFACEFORMAT_R16G16B16A16_UNORM 0x080 +#define BRW_SURFACEFORMAT_R16G16B16A16_SNORM 0x081 +#define BRW_SURFACEFORMAT_R16G16B16A16_SINT 0x082 +#define BRW_SURFACEFORMAT_R16G16B16A16_UINT 0x083 +#define BRW_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084 +#define BRW_SURFACEFORMAT_R32G32_FLOAT 0x085 +#define BRW_SURFACEFORMAT_R32G32_SINT 0x086 +#define BRW_SURFACEFORMAT_R32G32_UINT 0x087 +#define BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088 +#define BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089 +#define BRW_SURFACEFORMAT_L32A32_FLOAT 0x08A +#define BRW_SURFACEFORMAT_R32G32_UNORM 0x08B +#define BRW_SURFACEFORMAT_R32G32_SNORM 0x08C +#define BRW_SURFACEFORMAT_R64_FLOAT 0x08D +#define BRW_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E +#define BRW_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F +#define BRW_SURFACEFORMAT_A32X32_FLOAT 0x090 +#define BRW_SURFACEFORMAT_L32X32_FLOAT 0x091 +#define BRW_SURFACEFORMAT_I32X32_FLOAT 0x092 +#define BRW_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093 +#define BRW_SURFACEFORMAT_R16G16B16A16_USCALED 0x094 +#define BRW_SURFACEFORMAT_R32G32_SSCALED 0x095 +#define BRW_SURFACEFORMAT_R32G32_USCALED 0x096 +#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0 +#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1 +#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2 +#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3 +#define BRW_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4 +#define BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5 +#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7 +#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8 +#define BRW_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9 +#define BRW_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA +#define BRW_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB +#define BRW_SURFACEFORMAT_R16G16_UNORM 0x0CC +#define BRW_SURFACEFORMAT_R16G16_SNORM 0x0CD +#define BRW_SURFACEFORMAT_R16G16_SINT 0x0CE +#define BRW_SURFACEFORMAT_R16G16_UINT 0x0CF +#define BRW_SURFACEFORMAT_R16G16_FLOAT 0x0D0 +#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1 +#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2 +#define BRW_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3 +#define BRW_SURFACEFORMAT_R32_SINT 0x0D6 +#define BRW_SURFACEFORMAT_R32_UINT 0x0D7 +#define BRW_SURFACEFORMAT_R32_FLOAT 0x0D8 +#define BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9 +#define BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA +#define BRW_SURFACEFORMAT_L16A16_UNORM 0x0DF +#define BRW_SURFACEFORMAT_I24X8_UNORM 0x0E0 +#define BRW_SURFACEFORMAT_L24X8_UNORM 0x0E1 +#define BRW_SURFACEFORMAT_A24X8_UNORM 0x0E2 +#define BRW_SURFACEFORMAT_I32_FLOAT 0x0E3 +#define BRW_SURFACEFORMAT_L32_FLOAT 0x0E4 +#define BRW_SURFACEFORMAT_A32_FLOAT 0x0E5 +#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9 +#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA +#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB +#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC +#define BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED +#define BRW_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE +#define BRW_SURFACEFORMAT_L16A16_FLOAT 0x0F0 +#define BRW_SURFACEFORMAT_R32_UNORM 0x0F1 +#define BRW_SURFACEFORMAT_R32_SNORM 0x0F2 +#define BRW_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3 +#define BRW_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4 +#define BRW_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5 +#define BRW_SURFACEFORMAT_R16G16_SSCALED 0x0F6 +#define BRW_SURFACEFORMAT_R16G16_USCALED 0x0F7 +#define BRW_SURFACEFORMAT_R32_SSCALED 0x0F8 +#define BRW_SURFACEFORMAT_R32_USCALED 0x0F9 +#define BRW_SURFACEFORMAT_B5G6R5_UNORM 0x100 +#define BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101 +#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM 0x102 +#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103 +#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM 0x104 +#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105 +#define BRW_SURFACEFORMAT_R8G8_UNORM 0x106 +#define BRW_SURFACEFORMAT_R8G8_SNORM 0x107 +#define BRW_SURFACEFORMAT_R8G8_SINT 0x108 +#define BRW_SURFACEFORMAT_R8G8_UINT 0x109 +#define BRW_SURFACEFORMAT_R16_UNORM 0x10A +#define BRW_SURFACEFORMAT_R16_SNORM 0x10B +#define BRW_SURFACEFORMAT_R16_SINT 0x10C +#define BRW_SURFACEFORMAT_R16_UINT 0x10D +#define BRW_SURFACEFORMAT_R16_FLOAT 0x10E +#define BRW_SURFACEFORMAT_I16_UNORM 0x111 +#define BRW_SURFACEFORMAT_L16_UNORM 0x112 +#define BRW_SURFACEFORMAT_A16_UNORM 0x113 +#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114 +#define BRW_SURFACEFORMAT_I16_FLOAT 0x115 +#define BRW_SURFACEFORMAT_L16_FLOAT 0x116 +#define BRW_SURFACEFORMAT_A16_FLOAT 0x117 +#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119 +#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A +#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B +#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C +#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D +#define BRW_SURFACEFORMAT_R16_SSCALED 0x11E +#define BRW_SURFACEFORMAT_R16_USCALED 0x11F +#define BRW_SURFACEFORMAT_R8_UNORM 0x140 +#define BRW_SURFACEFORMAT_R8_SNORM 0x141 +#define BRW_SURFACEFORMAT_R8_SINT 0x142 +#define BRW_SURFACEFORMAT_R8_UINT 0x143 +#define BRW_SURFACEFORMAT_A8_UNORM 0x144 +#define BRW_SURFACEFORMAT_I8_UNORM 0x145 +#define BRW_SURFACEFORMAT_L8_UNORM 0x146 +#define BRW_SURFACEFORMAT_P4A4_UNORM 0x147 +#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148 +#define BRW_SURFACEFORMAT_R8_SSCALED 0x149 +#define BRW_SURFACEFORMAT_R8_USCALED 0x14A +#define BRW_SURFACEFORMAT_R1_UINT 0x181 +#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182 +#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183 +#define BRW_SURFACEFORMAT_BC1_UNORM 0x186 +#define BRW_SURFACEFORMAT_BC2_UNORM 0x187 +#define BRW_SURFACEFORMAT_BC3_UNORM 0x188 +#define BRW_SURFACEFORMAT_BC4_UNORM 0x189 +#define BRW_SURFACEFORMAT_BC5_UNORM 0x18A +#define BRW_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B +#define BRW_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C +#define BRW_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D +#define BRW_SURFACEFORMAT_MONO8 0x18E +#define BRW_SURFACEFORMAT_YCRCB_SWAPUV 0x18F +#define BRW_SURFACEFORMAT_YCRCB_SWAPY 0x190 +#define BRW_SURFACEFORMAT_DXT1_RGB 0x191 +#define BRW_SURFACEFORMAT_FXT1 0x192 +#define BRW_SURFACEFORMAT_R8G8B8_UNORM 0x193 +#define BRW_SURFACEFORMAT_R8G8B8_SNORM 0x194 +#define BRW_SURFACEFORMAT_R8G8B8_SSCALED 0x195 +#define BRW_SURFACEFORMAT_R8G8B8_USCALED 0x196 +#define BRW_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197 +#define BRW_SURFACEFORMAT_R64G64B64_FLOAT 0x198 +#define BRW_SURFACEFORMAT_BC4_SNORM 0x199 +#define BRW_SURFACEFORMAT_BC5_SNORM 0x19A +#define BRW_SURFACEFORMAT_R16G16B16_UNORM 0x19C +#define BRW_SURFACEFORMAT_R16G16B16_SNORM 0x19D +#define BRW_SURFACEFORMAT_R16G16B16_SSCALED 0x19E +#define BRW_SURFACEFORMAT_R16G16B16_USCALED 0x19F + +#define BRW_SURFACERETURNFORMAT_FLOAT32 0 +#define BRW_SURFACERETURNFORMAT_S1 1 + +#define BRW_SURFACE_1D 0 +#define BRW_SURFACE_2D 1 +#define BRW_SURFACE_3D 2 +#define BRW_SURFACE_CUBE 3 +#define BRW_SURFACE_BUFFER 4 +#define BRW_SURFACE_NULL 7 + +#define BRW_TEXCOORDMODE_WRAP 0 +#define BRW_TEXCOORDMODE_MIRROR 1 +#define BRW_TEXCOORDMODE_CLAMP 2 +#define BRW_TEXCOORDMODE_CUBE 3 +#define BRW_TEXCOORDMODE_CLAMP_BORDER 4 +#define BRW_TEXCOORDMODE_MIRROR_ONCE 5 + +#define BRW_THREAD_PRIORITY_NORMAL 0 +#define BRW_THREAD_PRIORITY_HIGH 1 + +#define BRW_TILEWALK_XMAJOR 0 +#define BRW_TILEWALK_YMAJOR 1 + +#define BRW_VERTEX_SUBPIXEL_PRECISION_8BITS 0 +#define BRW_VERTEX_SUBPIXEL_PRECISION_4BITS 1 + +#define BRW_VERTEXBUFFER_ACCESS_VERTEXDATA 0 +#define BRW_VERTEXBUFFER_ACCESS_INSTANCEDATA 1 + +#define BRW_VFCOMPONENT_NOSTORE 0 +#define BRW_VFCOMPONENT_STORE_SRC 1 +#define BRW_VFCOMPONENT_STORE_0 2 +#define BRW_VFCOMPONENT_STORE_1_FLT 3 +#define BRW_VFCOMPONENT_STORE_1_INT 4 +#define BRW_VFCOMPONENT_STORE_VID 5 +#define BRW_VFCOMPONENT_STORE_IID 6 +#define BRW_VFCOMPONENT_STORE_PID 7 + + + +/* Execution Unit (EU) defines + */ + +#define BRW_ALIGN_1 0 +#define BRW_ALIGN_16 1 + +#define BRW_ADDRESS_DIRECT 0 +#define BRW_ADDRESS_REGISTER_INDIRECT_REGISTER 1 + +#define BRW_CHANNEL_X 0 +#define BRW_CHANNEL_Y 1 +#define BRW_CHANNEL_Z 2 +#define BRW_CHANNEL_W 3 + +#define BRW_COMPRESSION_NONE 0 +#define BRW_COMPRESSION_2NDHALF 1 +#define BRW_COMPRESSION_COMPRESSED 2 + +#define BRW_CONDITIONAL_NONE 0 +#define BRW_CONDITIONAL_Z 1 +#define BRW_CONDITIONAL_NZ 2 +#define BRW_CONDITIONAL_EQ 1 /* Z */ +#define BRW_CONDITIONAL_NEQ 2 /* NZ */ +#define BRW_CONDITIONAL_G 3 +#define BRW_CONDITIONAL_GE 4 +#define BRW_CONDITIONAL_L 5 +#define BRW_CONDITIONAL_LE 6 +#define BRW_CONDITIONAL_C 7 +#define BRW_CONDITIONAL_O 8 + +#define BRW_DEBUG_NONE 0 +#define BRW_DEBUG_BREAKPOINT 1 + +#define BRW_DEPENDENCY_NORMAL 0 +#define BRW_DEPENDENCY_NOTCLEARED 1 +#define BRW_DEPENDENCY_NOTCHECKED 2 +#define BRW_DEPENDENCY_DISABLE 3 + +#define BRW_EXECUTE_1 0 +#define BRW_EXECUTE_2 1 +#define BRW_EXECUTE_4 2 +#define BRW_EXECUTE_8 3 +#define BRW_EXECUTE_16 4 +#define BRW_EXECUTE_32 5 + +#define BRW_HORIZONTAL_STRIDE_0 0 +#define BRW_HORIZONTAL_STRIDE_1 1 +#define BRW_HORIZONTAL_STRIDE_2 2 +#define BRW_HORIZONTAL_STRIDE_4 3 + +#define BRW_INSTRUCTION_NORMAL 0 +#define BRW_INSTRUCTION_SATURATE 1 + +#define BRW_MASK_ENABLE 0 +#define BRW_MASK_DISABLE 1 + +#define BRW_OPCODE_MOV 1 +#define BRW_OPCODE_SEL 2 +#define BRW_OPCODE_NOT 4 +#define BRW_OPCODE_AND 5 +#define BRW_OPCODE_OR 6 +#define BRW_OPCODE_XOR 7 +#define BRW_OPCODE_SHR 8 +#define BRW_OPCODE_SHL 9 +#define BRW_OPCODE_RSR 10 +#define BRW_OPCODE_RSL 11 +#define BRW_OPCODE_ASR 12 +#define BRW_OPCODE_CMP 16 +#define BRW_OPCODE_JMPI 32 +#define BRW_OPCODE_IF 34 +#define BRW_OPCODE_IFF 35 +#define BRW_OPCODE_ELSE 36 +#define BRW_OPCODE_ENDIF 37 +#define BRW_OPCODE_DO 38 +#define BRW_OPCODE_WHILE 39 +#define BRW_OPCODE_BREAK 40 +#define BRW_OPCODE_CONTINUE 41 +#define BRW_OPCODE_HALT 42 +#define BRW_OPCODE_MSAVE 44 +#define BRW_OPCODE_MRESTORE 45 +#define BRW_OPCODE_PUSH 46 +#define BRW_OPCODE_POP 47 +#define BRW_OPCODE_WAIT 48 +#define BRW_OPCODE_SEND 49 +#define BRW_OPCODE_ADD 64 +#define BRW_OPCODE_MUL 65 +#define BRW_OPCODE_AVG 66 +#define BRW_OPCODE_FRC 67 +#define BRW_OPCODE_RNDU 68 +#define BRW_OPCODE_RNDD 69 +#define BRW_OPCODE_RNDE 70 +#define BRW_OPCODE_RNDZ 71 +#define BRW_OPCODE_MAC 72 +#define BRW_OPCODE_MACH 73 +#define BRW_OPCODE_LZD 74 +#define BRW_OPCODE_SAD2 80 +#define BRW_OPCODE_SADA2 81 +#define BRW_OPCODE_DP4 84 +#define BRW_OPCODE_DPH 85 +#define BRW_OPCODE_DP3 86 +#define BRW_OPCODE_DP2 87 +#define BRW_OPCODE_DPA2 88 +#define BRW_OPCODE_LINE 89 +#define BRW_OPCODE_NOP 126 + +#define BRW_PREDICATE_NONE 0 +#define BRW_PREDICATE_NORMAL 1 +#define BRW_PREDICATE_ALIGN1_ANYV 2 +#define BRW_PREDICATE_ALIGN1_ALLV 3 +#define BRW_PREDICATE_ALIGN1_ANY2H 4 +#define BRW_PREDICATE_ALIGN1_ALL2H 5 +#define BRW_PREDICATE_ALIGN1_ANY4H 6 +#define BRW_PREDICATE_ALIGN1_ALL4H 7 +#define BRW_PREDICATE_ALIGN1_ANY8H 8 +#define BRW_PREDICATE_ALIGN1_ALL8H 9 +#define BRW_PREDICATE_ALIGN1_ANY16H 10 +#define BRW_PREDICATE_ALIGN1_ALL16H 11 +#define BRW_PREDICATE_ALIGN16_REPLICATE_X 2 +#define BRW_PREDICATE_ALIGN16_REPLICATE_Y 3 +#define BRW_PREDICATE_ALIGN16_REPLICATE_Z 4 +#define BRW_PREDICATE_ALIGN16_REPLICATE_W 5 +#define BRW_PREDICATE_ALIGN16_ANY4H 6 +#define BRW_PREDICATE_ALIGN16_ALL4H 7 + +#define BRW_ARCHITECTURE_REGISTER_FILE 0 +#define BRW_GENERAL_REGISTER_FILE 1 +#define BRW_MESSAGE_REGISTER_FILE 2 +#define BRW_IMMEDIATE_VALUE 3 + +#define BRW_REGISTER_TYPE_UD 0 +#define BRW_REGISTER_TYPE_D 1 +#define BRW_REGISTER_TYPE_UW 2 +#define BRW_REGISTER_TYPE_W 3 +#define BRW_REGISTER_TYPE_UB 4 +#define BRW_REGISTER_TYPE_B 5 +#define BRW_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */ +#define BRW_REGISTER_TYPE_HF 6 +#define BRW_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */ +#define BRW_REGISTER_TYPE_F 7 + +#define BRW_ARF_NULL 0x00 +#define BRW_ARF_ADDRESS 0x10 +#define BRW_ARF_ACCUMULATOR 0x20 +#define BRW_ARF_FLAG 0x30 +#define BRW_ARF_MASK 0x40 +#define BRW_ARF_MASK_STACK 0x50 +#define BRW_ARF_MASK_STACK_DEPTH 0x60 +#define BRW_ARF_STATE 0x70 +#define BRW_ARF_CONTROL 0x80 +#define BRW_ARF_NOTIFICATION_COUNT 0x90 +#define BRW_ARF_IP 0xA0 + +#define BRW_AMASK 0 +#define BRW_IMASK 1 +#define BRW_LMASK 2 +#define BRW_CMASK 3 + + + +#define BRW_THREAD_NORMAL 0 +#define BRW_THREAD_ATOMIC 1 +#define BRW_THREAD_SWITCH 2 + +#define BRW_VERTICAL_STRIDE_0 0 +#define BRW_VERTICAL_STRIDE_1 1 +#define BRW_VERTICAL_STRIDE_2 2 +#define BRW_VERTICAL_STRIDE_4 3 +#define BRW_VERTICAL_STRIDE_8 4 +#define BRW_VERTICAL_STRIDE_16 5 +#define BRW_VERTICAL_STRIDE_32 6 +#define BRW_VERTICAL_STRIDE_64 7 +#define BRW_VERTICAL_STRIDE_128 8 +#define BRW_VERTICAL_STRIDE_256 9 +#define BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF + +#define BRW_WIDTH_1 0 +#define BRW_WIDTH_2 1 +#define BRW_WIDTH_4 2 +#define BRW_WIDTH_8 3 +#define BRW_WIDTH_16 4 + +#define BRW_STATELESS_BUFFER_BOUNDARY_1K 0 +#define BRW_STATELESS_BUFFER_BOUNDARY_2K 1 +#define BRW_STATELESS_BUFFER_BOUNDARY_4K 2 +#define BRW_STATELESS_BUFFER_BOUNDARY_8K 3 +#define BRW_STATELESS_BUFFER_BOUNDARY_16K 4 +#define BRW_STATELESS_BUFFER_BOUNDARY_32K 5 +#define BRW_STATELESS_BUFFER_BOUNDARY_64K 6 +#define BRW_STATELESS_BUFFER_BOUNDARY_128K 7 +#define BRW_STATELESS_BUFFER_BOUNDARY_256K 8 +#define BRW_STATELESS_BUFFER_BOUNDARY_512K 9 +#define BRW_STATELESS_BUFFER_BOUNDARY_1M 10 +#define BRW_STATELESS_BUFFER_BOUNDARY_2M 11 + +#define BRW_POLYGON_FACING_FRONT 0 +#define BRW_POLYGON_FACING_BACK 1 + +#define BRW_MESSAGE_TARGET_NULL 0 +#define BRW_MESSAGE_TARGET_MATH 1 +#define BRW_MESSAGE_TARGET_SAMPLER 2 +#define BRW_MESSAGE_TARGET_GATEWAY 3 +#define BRW_MESSAGE_TARGET_DATAPORT_READ 4 +#define BRW_MESSAGE_TARGET_DATAPORT_WRITE 5 +#define BRW_MESSAGE_TARGET_URB 6 +#define BRW_MESSAGE_TARGET_THREAD_SPAWNER 7 + +#define BRW_SAMPLER_RETURN_FORMAT_FLOAT32 0 +#define BRW_SAMPLER_RETURN_FORMAT_UINT32 2 +#define BRW_SAMPLER_RETURN_FORMAT_SINT32 3 + +#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE 0 +#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE 0 +#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0 +#define BRW_SAMPLER_MESSAGE_SIMD8_KILLPIX 1 +#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1 +#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1 +#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2 +#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2 +#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0 +#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2 +#define BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2 +#define BRW_SAMPLER_MESSAGE_SIMD8_RESINFO 2 +#define BRW_SAMPLER_MESSAGE_SIMD16_RESINFO 2 +#define BRW_SAMPLER_MESSAGE_SIMD4X2_LD 3 +#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3 +#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3 + +#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0 +#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1 +#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2 +#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3 +#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4 + +#define BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0 +#define BRW_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2 + +#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2 +#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3 + +#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0 +#define BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1 +#define BRW_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ 2 +#define BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3 + +#define BRW_DATAPORT_READ_TARGET_DATA_CACHE 0 +#define BRW_DATAPORT_READ_TARGET_RENDER_CACHE 1 +#define BRW_DATAPORT_READ_TARGET_SAMPLER_CACHE 2 + +#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0 +#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1 +#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2 +#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3 +#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4 + +#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0 +#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1 +#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE 2 +#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3 +#define BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4 +#define BRW_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5 +#define BRW_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7 + +#define BRW_MATH_FUNCTION_INV 1 +#define BRW_MATH_FUNCTION_LOG 2 +#define BRW_MATH_FUNCTION_EXP 3 +#define BRW_MATH_FUNCTION_SQRT 4 +#define BRW_MATH_FUNCTION_RSQ 5 +#define BRW_MATH_FUNCTION_SIN 6 /* was 7 */ +#define BRW_MATH_FUNCTION_COS 7 /* was 8 */ +#define BRW_MATH_FUNCTION_SINCOS 8 /* was 6 */ +#define BRW_MATH_FUNCTION_TAN 9 +#define BRW_MATH_FUNCTION_POW 10 +#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11 +#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT 12 +#define BRW_MATH_FUNCTION_INT_DIV_REMAINDER 13 + +#define BRW_MATH_INTEGER_UNSIGNED 0 +#define BRW_MATH_INTEGER_SIGNED 1 + +#define BRW_MATH_PRECISION_FULL 0 +#define BRW_MATH_PRECISION_PARTIAL 1 + +#define BRW_MATH_SATURATE_NONE 0 +#define BRW_MATH_SATURATE_SATURATE 1 + +#define BRW_MATH_DATA_VECTOR 0 +#define BRW_MATH_DATA_SCALAR 1 + +#define BRW_URB_OPCODE_WRITE 0 + +#define BRW_URB_SWIZZLE_NONE 0 +#define BRW_URB_SWIZZLE_INTERLEAVE 1 +#define BRW_URB_SWIZZLE_TRANSPOSE 2 + +#define BRW_SCRATCH_SPACE_SIZE_1K 0 +#define BRW_SCRATCH_SPACE_SIZE_2K 1 +#define BRW_SCRATCH_SPACE_SIZE_4K 2 +#define BRW_SCRATCH_SPACE_SIZE_8K 3 +#define BRW_SCRATCH_SPACE_SIZE_16K 4 +#define BRW_SCRATCH_SPACE_SIZE_32K 5 +#define BRW_SCRATCH_SPACE_SIZE_64K 6 +#define BRW_SCRATCH_SPACE_SIZE_128K 7 +#define BRW_SCRATCH_SPACE_SIZE_256K 8 +#define BRW_SCRATCH_SPACE_SIZE_512K 9 +#define BRW_SCRATCH_SPACE_SIZE_1M 10 +#define BRW_SCRATCH_SPACE_SIZE_2M 11 + + + + +#define CMD_URB_FENCE 0x6000 +#define CMD_CONST_BUFFER_STATE 0x6001 +#define CMD_CONST_BUFFER 0x6002 + +#define CMD_STATE_BASE_ADDRESS 0x6101 +#define CMD_STATE_INSN_POINTER 0x6102 +#define CMD_PIPELINE_SELECT 0x6104 + +#define CMD_PIPELINED_STATE_POINTERS 0x7800 +#define CMD_BINDING_TABLE_PTRS 0x7801 +#define CMD_VERTEX_BUFFER 0x7808 +#define CMD_VERTEX_ELEMENT 0x7809 +#define CMD_INDEX_BUFFER 0x780a +#define CMD_VF_STATISTICS 0x780b + +#define CMD_DRAW_RECT 0x7900 +#define CMD_BLEND_CONSTANT_COLOR 0x7901 +#define CMD_CHROMA_KEY 0x7904 +#define CMD_DEPTH_BUFFER 0x7905 +#define CMD_POLY_STIPPLE_OFFSET 0x7906 +#define CMD_POLY_STIPPLE_PATTERN 0x7907 +#define CMD_LINE_STIPPLE_PATTERN 0x7908 +#define CMD_GLOBAL_DEPTH_OFFSET_CLAMP 0x7908 + +#define CMD_PIPE_CONTROL 0x7a00 + +#define CMD_3D_PRIM 0x7b00 + +#define CMD_MI_FLUSH 0x0200 + + +/* Various values from the R0 vertex header: + */ +#define R02_PRIM_END 0x1 +#define R02_PRIM_START 0x2 + + + +#endif diff --git a/src/brw_structs.h b/src/brw_structs.h new file mode 100644 index 00000000..d2f9be0f --- /dev/null +++ b/src/brw_structs.h @@ -0,0 +1,1340 @@ + /************************************************************************** + * + * Copyright 2005 Tungsten Graphics, 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 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. + * + **************************************************************************/ + +#ifndef BRW_STRUCTS_H +#define BRW_STRUCTS_H + +/* Command packets: + */ +struct header +{ + unsigned int length:16; + unsigned int opcode:16; +} bits; + + +union header_union +{ + struct header bits; + unsigned int dword; +}; + +struct brw_3d_control +{ + struct + { + unsigned int length:8; + unsigned int notify_enable:1; + unsigned int pad:3; + unsigned int wc_flush_enable:1; + unsigned int depth_stall_enable:1; + unsigned int operation:2; + unsigned int opcode:16; + } header; + + struct + { + unsigned int pad:2; + unsigned int dest_addr_type:1; + unsigned int dest_addr:29; + } dest; + + unsigned int dword2; + unsigned int dword3; +}; + + +struct brw_3d_primitive +{ + struct + { + unsigned int length:8; + unsigned int pad:2; + unsigned int topology:5; + unsigned int indexed:1; + unsigned int opcode:16; + } header; + + unsigned int verts_per_instance; + unsigned int start_vert_location; + unsigned int instance_count; + unsigned int start_instance_location; + unsigned int base_vert_location; +}; + +/* These seem to be passed around as function args, so it works out + * better to keep them as #defines: + */ +#define BRW_FLUSH_READ_CACHE 0x1 +#define BRW_FLUSH_STATE_CACHE 0x2 +#define BRW_INHIBIT_FLUSH_RENDER_CACHE 0x4 +#define BRW_FLUSH_SNAPSHOT_COUNTERS 0x8 + +struct brw_mi_flush +{ + unsigned int flags:4; + unsigned int pad:12; + unsigned int opcode:16; +}; + +struct brw_vf_statistics +{ + unsigned int statistics_enable:1; + unsigned int pad:15; + unsigned int opcode:16; +}; + + + +struct brw_binding_table_pointers +{ + struct header header; + unsigned int vs; + unsigned int gs; + unsigned int clp; + unsigned int sf; + unsigned int wm; +}; + + +struct brw_blend_constant_color +{ + struct header header; + float blend_constant_color[4]; +}; + + +struct brw_depthbuffer +{ + union header_union header; + + union { + struct { + unsigned int pitch:18; + unsigned int format:3; + unsigned int pad:4; + unsigned int depth_offset_disable:1; + unsigned int tile_walk:1; + unsigned int tiled_surface:1; + unsigned int pad2:1; + unsigned int surface_type:3; + } bits; + unsigned int dword; + } dword1; + + unsigned int dword2_base_addr; + + union { + struct { + unsigned int pad:1; + unsigned int mipmap_layout:1; + unsigned int lod:4; + unsigned int width:13; + unsigned int height:13; + } bits; + unsigned int dword; + } dword3; + + union { + struct { + unsigned int pad:12; + unsigned int min_array_element:9; + unsigned int depth:11; + } bits; + unsigned int dword; + } dword4; +}; + +struct brw_drawrect +{ + struct header header; + unsigned int xmin:16; + unsigned int ymin:16; + unsigned int xmax:16; + unsigned int ymax:16; + unsigned int xorg:16; + unsigned int yorg:16; +}; + + + + +struct brw_global_depth_offset_clamp +{ + struct header header; + float depth_offset_clamp; +}; + +struct brw_indexbuffer +{ + union { + struct + { + unsigned int length:8; + unsigned int index_format:2; + unsigned int cut_index_enable:1; + unsigned int pad:5; + unsigned int opcode:16; + } bits; + unsigned int dword; + + } header; + + unsigned int buffer_start; + unsigned int buffer_end; +}; + + +struct brw_line_stipple +{ + struct header header; + + struct + { + unsigned int pattern:16; + unsigned int pad:16; + } bits0; + + struct + { + unsigned int repeat_count:9; + unsigned int pad:7; + unsigned int inverse_repeat_count:16; + } bits1; +}; + + +struct brw_pipelined_state_pointers +{ + struct header header; + + struct { + unsigned int pad:5; + unsigned int offset:27; + } vs; + + struct + { + unsigned int enable:1; + unsigned int pad:4; + unsigned int offset:27; + } gs; + + struct + { + unsigned int enable:1; + unsigned int pad:4; + unsigned int offset:27; + } clp; + + struct + { + unsigned int pad:5; + unsigned int offset:27; + } sf; + + struct + { + unsigned int pad:5; + unsigned int offset:27; + } wm; + + struct + { + unsigned int pad:5; + unsigned int offset:27; /* KW: check me! */ + } cc; +}; + + +struct brw_polygon_stipple_offset +{ + struct header header; + + struct { + unsigned int y_offset:5; + unsigned int pad:3; + unsigned int x_offset:5; + unsigned int pad0:19; + } bits0; +}; + + + +struct brw_polygon_stipple +{ + struct header header; + unsigned int stipple[32]; +}; + + + +struct brw_pipeline_select +{ + struct + { + unsigned int pipeline_select:1; + unsigned int pad:15; + unsigned int opcode:16; + } header; +}; + + +struct brw_pipe_control +{ + struct + { + unsigned int length:8; + unsigned int notify_enable:1; + unsigned int pad:2; + unsigned int instruction_state_cache_flush_enable:1; + unsigned int write_cache_flush_enable:1; + unsigned int depth_stall_enable:1; + unsigned int post_sync_operation:2; + + unsigned int opcode:16; + } header; + + struct + { + unsigned int pad:2; + unsigned int dest_addr_type:1; + unsigned int dest_addr:29; + } bits1; + + unsigned int data0; + unsigned int data1; +}; + + +struct brw_urb_fence +{ + struct + { + unsigned int length:8; + unsigned int vs_realloc:1; + unsigned int gs_realloc:1; + unsigned int clp_realloc:1; + unsigned int sf_realloc:1; + unsigned int vfe_realloc:1; + unsigned int cs_realloc:1; + unsigned int pad:2; + unsigned int opcode:16; + } header; + + struct + { + unsigned int vs_fence:10; + unsigned int gs_fence:10; + unsigned int clp_fence:10; + unsigned int pad:2; + } bits0; + + struct + { + unsigned int sf_fence:10; + unsigned int vf_fence:10; + unsigned int cs_fence:10; + unsigned int pad:2; + } bits1; +}; + +struct brw_constant_buffer_state /* previously brw_command_streamer */ +{ + struct header header; + + struct + { + unsigned int nr_urb_entries:3; + unsigned int pad:1; + unsigned int urb_entry_size:5; + unsigned int pad0:23; + } bits0; +}; + +struct brw_constant_buffer +{ + struct + { + unsigned int length:8; + unsigned int valid:1; + unsigned int pad:7; + unsigned int opcode:16; + } header; + + struct + { + unsigned int buffer_length:6; + unsigned int buffer_address:26; + } bits0; +}; + +struct brw_state_base_address +{ + struct header header; + + struct + { + unsigned int modify_enable:1; + unsigned int pad:4; + unsigned int general_state_address:27; + } bits0; + + struct + { + unsigned int modify_enable:1; + unsigned int pad:4; + unsigned int surface_state_address:27; + } bits1; + + struct + { + unsigned int modify_enable:1; + unsigned int pad:4; + unsigned int indirect_object_state_address:27; + } bits2; + + struct + { + unsigned int modify_enable:1; + unsigned int pad:11; + unsigned int general_state_upper_bound:20; + } bits3; + + struct + { + unsigned int modify_enable:1; + unsigned int pad:11; + unsigned int indirect_object_state_upper_bound:20; + } bits4; +}; + +struct brw_state_prefetch +{ + struct header header; + + struct + { + unsigned int prefetch_count:3; + unsigned int pad:3; + unsigned int prefetch_pointer:26; + } bits0; +}; + +struct brw_system_instruction_pointer +{ + struct header header; + + struct + { + unsigned int pad:4; + unsigned int system_instruction_pointer:28; + } bits0; +}; + + + + +/* State structs for the various fixed function units: + */ + + +struct thread0 +{ + unsigned int pad0:1; + unsigned int grf_reg_count:3; + unsigned int pad1:2; + unsigned int kernel_start_pointer:26; +}; + +struct thread1 +{ + unsigned int ext_halt_exception_enable:1; + unsigned int sw_exception_enable:1; + unsigned int mask_stack_exception_enable:1; + unsigned int timeout_exception_enable:1; + unsigned int illegal_op_exception_enable:1; + unsigned int pad0:3; + unsigned int depth_coef_urb_read_offset:6; /* WM only */ + unsigned int pad1:2; + unsigned int floating_point_mode:1; + unsigned int thread_priority:1; + unsigned int binding_table_entry_count:8; + unsigned int pad3:5; + unsigned int single_program_flow:1; +}; + +struct thread2 +{ + unsigned int per_thread_scratch_space:4; + unsigned int pad0:6; + unsigned int scratch_space_base_pointer:22; +}; + + +struct thread3 +{ + unsigned int dispatch_grf_start_reg:4; + unsigned int urb_entry_read_offset:6; + unsigned int pad0:1; + unsigned int urb_entry_read_length:6; + unsigned int pad1:1; + unsigned int const_urb_entry_read_offset:6; + unsigned int pad2:1; + unsigned int const_urb_entry_read_length:6; + unsigned int pad3:1; +}; + + + +struct brw_clip_unit_state +{ + struct thread0 thread0; + struct thread1 thread1; + struct thread2 thread2; + struct thread3 thread3; + + struct + { + unsigned int pad0:9; + unsigned int gs_output_stats:1; /* not always */ + unsigned int stats_enable:1; + unsigned int nr_urb_entries:7; + unsigned int pad1:1; + unsigned int urb_entry_allocation_size:5; + unsigned int pad2:1; + unsigned int max_threads:6; /* may be less */ + unsigned int pad3:1; + } thread4; + + struct + { + unsigned int pad0:13; + unsigned int clip_mode:3; + unsigned int userclip_enable_flags:8; + unsigned int userclip_must_clip:1; + unsigned int pad1:1; + unsigned int guard_band_enable:1; + unsigned int viewport_z_clip_enable:1; + unsigned int viewport_xy_clip_enable:1; + unsigned int vertex_position_space:1; + unsigned int api_mode:1; + unsigned int pad2:1; + } clip5; + + struct + { + unsigned int pad0:5; + unsigned int clipper_viewport_state_ptr:27; + } clip6; + + + float viewport_xmin; + float viewport_xmax; + float viewport_ymin; + float viewport_ymax; +}; + + + +struct brw_cc_unit_state +{ + struct + { + unsigned int pad0:3; + unsigned int bf_stencil_pass_depth_pass_op:3; + unsigned int bf_stencil_pass_depth_fail_op:3; + unsigned int bf_stencil_fail_op:3; + unsigned int bf_stencil_func:3; + unsigned int bf_stencil_enable:1; + unsigned int pad1:2; + unsigned int stencil_write_enable:1; + unsigned int stencil_pass_depth_pass_op:3; + unsigned int stencil_pass_depth_fail_op:3; + unsigned int stencil_fail_op:3; + unsigned int stencil_func:3; + unsigned int stencil_enable:1; + } cc0; + + + struct + { + unsigned int bf_stencil_ref:8; + unsigned int stencil_write_mask:8; + unsigned int stencil_test_mask:8; + unsigned int stencil_ref:8; + } cc1; + + + struct + { + unsigned int logicop_enable:1; + unsigned int pad0:10; + unsigned int depth_write_enable:1; + unsigned int depth_test_function:3; + unsigned int depth_test:1; + unsigned int bf_stencil_write_mask:8; + unsigned int bf_stencil_test_mask:8; + } cc2; + + + struct + { + unsigned int pad0:8; + unsigned int alpha_test_func:3; + unsigned int alpha_test:1; + unsigned int blend_enable:1; + unsigned int ia_blend_enable:1; + unsigned int pad1:1; + unsigned int alpha_test_format:1; + unsigned int pad2:16; + } cc3; + + struct + { + unsigned int pad0:5; + unsigned int cc_viewport_state_offset:27; + } cc4; + + struct + { + unsigned int pad0:2; + unsigned int ia_dest_blend_factor:5; + unsigned int ia_src_blend_factor:5; + unsigned int ia_blend_function:3; + unsigned int statistics_enable:1; + unsigned int logicop_func:4; + unsigned int pad1:11; + unsigned int dither_enable:1; + } cc5; + + struct + { + unsigned int clamp_post_alpha_blend:1; + unsigned int clamp_pre_alpha_blend:1; + unsigned int clamp_range:2; + unsigned int pad0:11; + unsigned int y_dither_offset:2; + unsigned int x_dither_offset:2; + unsigned int dest_blend_factor:5; + unsigned int src_blend_factor:5; + unsigned int blend_function:3; + } cc6; + + struct { + union { + float f; + unsigned char ub[4]; + } alpha_ref; + } cc7; +}; + + + +struct brw_sf_unit_state +{ + struct thread0 thread0; + struct { + unsigned int pad0:7; + unsigned int sw_exception_enable:1; + unsigned int pad1:3; + unsigned int mask_stack_exception_enable:1; + unsigned int pad2:1; + unsigned int illegal_op_exception_enable:1; + unsigned int pad3:2; + unsigned int floating_point_mode:1; + unsigned int thread_priority:1; + unsigned int binding_table_entry_count:8; + unsigned int pad4:5; + unsigned int single_program_flow:1; + } sf1; + + struct thread2 thread2; + struct thread3 thread3; + + struct + { + unsigned int pad0:10; + unsigned int stats_enable:1; + unsigned int nr_urb_entries:7; + unsigned int pad1:1; + unsigned int urb_entry_allocation_size:5; + unsigned int pad2:1; + unsigned int max_threads:6; + unsigned int pad3:1; + } thread4; + + struct + { + unsigned int front_winding:1; + unsigned int viewport_transform:1; + unsigned int pad0:3; + unsigned int sf_viewport_state_offset:27; + } sf5; + + struct + { + unsigned int pad0:9; + unsigned int dest_org_vbias:4; + unsigned int dest_org_hbias:4; + unsigned int scissor:1; + unsigned int disable_2x2_trifilter:1; + unsigned int disable_zero_pix_trifilter:1; + unsigned int point_rast_rule:2; + unsigned int line_endcap_aa_region_width:2; + unsigned int line_width:4; + unsigned int fast_scissor_disable:1; + unsigned int cull_mode:2; + unsigned int aa_enable:1; + } sf6; + + struct + { + unsigned int point_size:11; + unsigned int use_point_size_state:1; + unsigned int subpixel_precision:1; + unsigned int sprite_point:1; + unsigned int pad0:11; + unsigned int trifan_pv:2; + unsigned int linestrip_pv:2; + unsigned int tristrip_pv:2; + unsigned int line_last_pixel_enable:1; + } sf7; + +}; + + +struct brw_gs_unit_state +{ + struct thread0 thread0; + struct thread1 thread1; + struct thread2 thread2; + struct thread3 thread3; + + struct + { + unsigned int pad0:10; + unsigned int stats_enable:1; + unsigned int nr_urb_entries:7; + unsigned int pad1:1; + unsigned int urb_entry_allocation_size:5; + unsigned int pad2:1; + unsigned int max_threads:1; + unsigned int pad3:6; + } thread4; + + struct + { + unsigned int sampler_count:3; + unsigned int pad0:2; + unsigned int sampler_state_pointer:27; + } gs5; + + + struct + { + unsigned int max_vp_index:4; + unsigned int pad0:26; + unsigned int reorder_enable:1; + unsigned int pad1:1; + } gs6; +}; + + +struct brw_vs_unit_state +{ + struct thread0 thread0; + struct thread1 thread1; + struct thread2 thread2; + struct thread3 thread3; + + struct + { + unsigned int pad0:10; + unsigned int stats_enable:1; + unsigned int nr_urb_entries:7; + unsigned int pad1:1; + unsigned int urb_entry_allocation_size:5; + unsigned int pad2:1; + unsigned int max_threads:4; + unsigned int pad3:3; + } thread4; + + struct + { + unsigned int sampler_count:3; + unsigned int pad0:2; + unsigned int sampler_state_pointer:27; + } vs5; + + struct + { + unsigned int vs_enable:1; + unsigned int vert_cache_disable:1; + unsigned int pad0:30; + } vs6; +}; + + +struct brw_wm_unit_state +{ + struct thread0 thread0; + struct thread1 thread1; + struct thread2 thread2; + struct thread3 thread3; + + struct { + unsigned int stats_enable:1; + unsigned int pad0:1; + unsigned int sampler_count:3; + unsigned int sampler_state_pointer:27; + } wm4; + + struct + { + unsigned int enable_8_pix:1; + unsigned int enable_16_pix:1; + unsigned int enable_32_pix:1; + unsigned int pad0:7; + unsigned int legacy_global_depth_bias:1; + unsigned int line_stipple:1; + unsigned int depth_offset:1; + unsigned int polygon_stipple:1; + unsigned int line_aa_region_width:2; + unsigned int line_endcap_aa_region_width:2; + unsigned int early_depth_test:1; + unsigned int thread_dispatch_enable:1; + unsigned int program_uses_depth:1; + unsigned int program_computes_depth:1; + unsigned int program_uses_killpixel:1; + unsigned int legacy_line_rast: 1; + unsigned int pad1:1; + unsigned int max_threads:6; + unsigned int pad2:1; + } wm5; + + float global_depth_offset_constant; + float global_depth_offset_scale; +}; + +struct brw_sampler_default_color { + float color[4]; +}; + +struct brw_sampler_state +{ + + struct + { + unsigned int shadow_function:3; + unsigned int lod_bias:11; + unsigned int min_filter:3; + unsigned int mag_filter:3; + unsigned int mip_filter:2; + unsigned int base_level:5; + unsigned int pad:1; + unsigned int lod_preclamp:1; + unsigned int default_color_mode:1; + unsigned int pad0:1; + unsigned int disable:1; + } ss0; + + struct + { + unsigned int r_wrap_mode:3; + unsigned int t_wrap_mode:3; + unsigned int s_wrap_mode:3; + unsigned int pad:3; + unsigned int max_lod:10; + unsigned int min_lod:10; + } ss1; + + + struct + { + unsigned int pad:5; + unsigned int default_color_pointer:27; + } ss2; + + struct + { + unsigned int pad:19; + unsigned int max_aniso:3; + unsigned int chroma_key_mode:1; + unsigned int chroma_key_index:2; + unsigned int chroma_key_enable:1; + unsigned int monochrome_filter_width:3; + unsigned int monochrome_filter_height:3; + } ss3; +}; + + +struct brw_clipper_viewport +{ + float xmin; + float xmax; + float ymin; + float ymax; +}; + +struct brw_cc_viewport +{ + float min_depth; + float max_depth; +}; + +struct brw_sf_viewport +{ + struct { + float m00; + float m11; + float m22; + float m30; + float m31; + float m32; + } viewport; + + struct { + short xmin; + short ymin; + short xmax; + short ymax; + } scissor; +}; + +/* Documented in the subsystem/shared-functions/sampler chapter... + */ +struct brw_surface_state +{ + struct { + unsigned int cube_pos_z:1; + unsigned int cube_neg_z:1; + unsigned int cube_pos_y:1; + unsigned int cube_neg_y:1; + unsigned int cube_pos_x:1; + unsigned int cube_neg_x:1; + unsigned int pad:3; + unsigned int render_cache_read_mode:1; + unsigned int mipmap_layout_mode:1; + unsigned int vert_line_stride_ofs:1; + unsigned int vert_line_stride:1; + unsigned int color_blend:1; + unsigned int writedisable_blue:1; + unsigned int writedisable_green:1; + unsigned int writedisable_red:1; + unsigned int writedisable_alpha:1; + unsigned int surface_format:9; + unsigned int data_return_format:1; + unsigned int pad0:1; + unsigned int surface_type:3; + } ss0; + + struct { + unsigned int base_addr; + } ss1; + + struct { + unsigned int render_target_rotation:2; + unsigned int mip_count:4; + unsigned int width:13; + unsigned int height:13; + } ss2; + + struct { + unsigned int tile_walk:1; + unsigned int tiled_surface:1; + unsigned int pad:1; + unsigned int pitch:18; + unsigned int depth:11; + } ss3; + + struct { + unsigned int pad:19; + unsigned int min_array_elt:9; + unsigned int min_lod:4; + } ss4; +}; + + + +struct brw_vertex_buffer_state +{ + struct { + unsigned int pitch:11; + unsigned int pad:15; + unsigned int access_type:1; + unsigned int vb_index:5; + } vb0; + + unsigned int start_addr; + unsigned int max_index; +#if 1 + unsigned int instance_data_step_rate; /* not included for sequential/random vertices? */ +#endif +}; + +#define BRW_VBP_MAX 17 + +struct brw_vb_array_state { + struct header header; + struct brw_vertex_buffer_state vb[BRW_VBP_MAX]; +}; + + +struct brw_vertex_element_state +{ + struct + { + unsigned int src_offset:11; + unsigned int pad:5; + unsigned int src_format:9; + unsigned int pad0:1; + unsigned int valid:1; + unsigned int vertex_buffer_index:5; + } ve0; + + struct + { + unsigned int dst_offset:8; + unsigned int pad:8; + unsigned int vfcomponent3:4; + unsigned int vfcomponent2:4; + unsigned int vfcomponent1:4; + unsigned int vfcomponent0:4; + } ve1; +}; + +#define BRW_VEP_MAX 18 + +struct brw_vertex_element_packet { + struct header header; + struct brw_vertex_element_state ve[BRW_VEP_MAX]; /* note: less than _TNL_ATTRIB_MAX */ +}; + + +struct brw_urb_immediate { + unsigned int opcode:4; + unsigned int offset:6; + unsigned int swizzle_control:2; + unsigned int pad:1; + unsigned int allocate:1; + unsigned int used:1; + unsigned int complete:1; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; +}; + +/* Instruction format for the execution units: + */ + +struct brw_instruction +{ + struct + { + unsigned int opcode:7; + unsigned int pad:1; + unsigned int access_mode:1; + unsigned int mask_control:1; + unsigned int dependency_control:2; + unsigned int compression_control:2; + unsigned int thread_control:2; + unsigned int predicate_control:4; + unsigned int predicate_inverse:1; + unsigned int execution_size:3; + unsigned int destreg__conditonalmod:4; /* destreg - send, conditionalmod - others */ + unsigned int pad0:2; + unsigned int debug_control:1; + unsigned int saturate:1; + } header; + + union { + struct + { + unsigned int dest_reg_file:2; + unsigned int dest_reg_type:3; + unsigned int src0_reg_file:2; + unsigned int src0_reg_type:3; + unsigned int src1_reg_file:2; + unsigned int src1_reg_type:3; + unsigned int pad:1; + unsigned int dest_subreg_nr:5; + unsigned int dest_reg_nr:8; + unsigned int dest_horiz_stride:2; + unsigned int dest_address_mode:1; + } da1; + + struct + { + unsigned int dest_reg_file:2; + unsigned int dest_reg_type:3; + unsigned int src0_reg_file:2; + unsigned int src0_reg_type:3; + unsigned int pad:6; + int dest_indirect_offset:10; /* offset against the deref'd address reg */ + unsigned int dest_subreg_nr:3; /* subnr for the address reg a0.x */ + unsigned int dest_horiz_stride:2; + unsigned int dest_address_mode:1; + } ia1; + + struct + { + unsigned int dest_reg_file:2; + unsigned int dest_reg_type:3; + unsigned int src0_reg_file:2; + unsigned int src0_reg_type:3; + unsigned int src1_reg_file:2; + unsigned int src1_reg_type:3; + unsigned int pad0:1; + unsigned int dest_writemask:4; + unsigned int dest_subreg_nr:1; + unsigned int dest_reg_nr:8; + unsigned int pad1:2; + unsigned int dest_address_mode:1; + } da16; + + struct + { + unsigned int dest_reg_file:2; + unsigned int dest_reg_type:3; + unsigned int src0_reg_file:2; + unsigned int src0_reg_type:3; + unsigned int pad0:6; + unsigned int dest_writemask:4; + int dest_indirect_offset:6; + unsigned int dest_subreg_nr:3; + unsigned int pad1:2; + unsigned int dest_address_mode:1; + } ia16; + } bits1; + + + union { + struct + { + unsigned int src0_subreg_nr:5; + unsigned int src0_reg_nr:8; + unsigned int src0_abs:1; + unsigned int src0_negate:1; + unsigned int src0_address_mode:1; + unsigned int src0_horiz_stride:2; + unsigned int src0_width:3; + unsigned int src0_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad:6; + } da1; + + struct + { + int src0_indirect_offset:10; + unsigned int src0_subreg_nr:3; + unsigned int src0_abs:1; + unsigned int src0_negate:1; + unsigned int src0_address_mode:1; + unsigned int src0_horiz_stride:2; + unsigned int src0_width:3; + unsigned int src0_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad:6; + } ia1; + + struct + { + unsigned int src0_swz_x:2; + unsigned int src0_swz_y:2; + unsigned int src0_subreg_nr:1; + unsigned int src0_reg_nr:8; + unsigned int src0_abs:1; + unsigned int src0_negate:1; + unsigned int src0_address_mode:1; + unsigned int src0_swz_z:2; + unsigned int src0_swz_w:2; + unsigned int pad0:1; + unsigned int src0_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad1:6; + } da16; + + struct + { + unsigned int src0_swz_x:2; + unsigned int src0_swz_y:2; + int src0_indirect_offset:6; + unsigned int src0_subreg_nr:3; + unsigned int src0_abs:1; + unsigned int src0_negate:1; + unsigned int src0_address_mode:1; + unsigned int src0_swz_z:2; + unsigned int src0_swz_w:2; + unsigned int pad0:1; + unsigned int src0_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad1:6; + } ia16; + + } bits2; + + union + { + struct + { + unsigned int src1_subreg_nr:5; + unsigned int src1_reg_nr:8; + unsigned int src1_abs:1; + unsigned int src1_negate:1; + unsigned int pad:1; + unsigned int src1_horiz_stride:2; + unsigned int src1_width:3; + unsigned int src1_vert_stride:4; + unsigned int pad0:7; + } da1; + + struct + { + unsigned int src1_swz_x:2; + unsigned int src1_swz_y:2; + unsigned int src1_subreg_nr:1; + unsigned int src1_reg_nr:8; + unsigned int src1_abs:1; + unsigned int src1_negate:1; + unsigned int pad0:1; + unsigned int src1_swz_z:2; + unsigned int src1_swz_w:2; + unsigned int pad1:1; + unsigned int src1_vert_stride:4; + unsigned int pad2:7; + } da16; + + struct + { + int src1_indirect_offset:10; + unsigned int src1_subreg_nr:3; + unsigned int src1_abs:1; + unsigned int src1_negate:1; + unsigned int pad0:1; + unsigned int src1_horiz_stride:2; + unsigned int src1_width:3; + unsigned int src1_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad1:6; + } ia1; + + struct + { + unsigned int src1_swz_x:2; + unsigned int src1_swz_y:2; + int src1_indirect_offset:6; + unsigned int src1_subreg_nr:3; + unsigned int src1_abs:1; + unsigned int src1_negate:1; + unsigned int pad0:1; + unsigned int src1_swz_z:2; + unsigned int src1_swz_w:2; + unsigned int pad1:1; + unsigned int src1_vert_stride:4; + unsigned int flag_reg_nr:1; + unsigned int pad2:6; + } ia16; + + + struct + { + int jump_count:16; /* note: signed */ + unsigned int pop_count:4; + unsigned int pad0:12; + } if_else; + + struct { + unsigned int function:4; + unsigned int int_type:1; + unsigned int precision:1; + unsigned int saturate:1; + unsigned int data_type:1; + unsigned int pad0:8; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; + } math; + + struct { + unsigned int binding_table_index:8; + unsigned int sampler:4; + unsigned int return_format:2; + unsigned int msg_type:2; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; + } sampler; + + struct brw_urb_immediate urb; + + struct { + unsigned int binding_table_index:8; + unsigned int msg_control:4; + unsigned int msg_type:2; + unsigned int target_cache:2; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; + } dp_read; + + struct { + unsigned int binding_table_index:8; + unsigned int msg_control:3; + unsigned int pixel_scoreboard_clear:1; + unsigned int msg_type:3; + unsigned int send_commit_msg:1; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; + } dp_write; + + struct { + unsigned int pad:16; + unsigned int response_length:4; + unsigned int msg_length:4; + unsigned int msg_target:4; + unsigned int pad1:3; + unsigned int end_of_thread:1; + } generic; + + unsigned int ud; + } bits3; +}; + + +#endif diff --git a/src/common.h b/src/common.h index 31e67b90..ad5ee1de 100644 --- a/src/common.h +++ b/src/common.h @@ -130,13 +130,17 @@ extern void I830DPRINTF_stub(const char *filename, int line, #define ADVANCE_LP_RING() do { \ if (ringused > needed) \ - ErrorF("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \ - __FUNCTION__, ringused, needed); \ + FatalError("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \ + __FUNCTION__, ringused, needed); \ + else if (ringused < needed) \ + FatalError("%s: ADVANCE_LP_RING: under-used allocation %d/%d\n ", \ + __FUNCTION__, ringused, needed); \ RecPtr->LpRing->tail = outring; \ RecPtr->LpRing->space -= ringused; \ if (outring & 0x07) \ - ErrorF("ADVANCE_LP_RING: " \ - "outring (0x%x) isn't on a QWord boundary\n", outring); \ + FatalError("%s: ADVANCE_LP_RING: " \ + "outring (0x%x) isn't on a QWord boundary\n", \ + __FUNCTION__, outring); \ OUTREG(LP_RING + RING_TAIL, outring); \ } while (0) @@ -277,6 +281,26 @@ extern int I810_DEBUG; #define PCI_CHIP_I945_GM_BRIDGE 0x27A0 #endif +#ifndef PCI_CHIP_I965_G_1 +#define PCI_CHIP_I965_G_1 0x2982 +#define PCI_CHIP_I965_G_1_BRIDGE 0x2980 +#endif + +#ifndef PCI_CHIP_I965_Q +#define PCI_CHIP_I965_Q 0x2992 +#define PCI_CHIP_I965_Q_BRIDGE 0x2990 +#endif + +#ifndef PCI_CHIP_I965_G +#define PCI_CHIP_I965_G 0x29A2 +#define PCI_CHIP_I965_G_BRIDGE 0x29A0 +#endif + +#ifndef PCI_CHIP_I946_GZ +#define PCI_CHIP_I946_GZ 0x2972 +#define PCI_CHIP_I946_GZ_BRIDGE 0x2970 +#endif + #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_E) @@ -292,7 +316,8 @@ extern int I810_DEBUG; #define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM) #define IS_I945G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_G) #define IS_I945GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I945_GM) -#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810)) +#define IS_I965G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I965_G || pI810->PciInfo->chipType == PCI_CHIP_I965_G_1 || pI810->PciInfo->chipType == PCI_CHIP_I965_Q || pI810->PciInfo->chipType == PCI_CHIP_I946_GZ) +#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810) || IS_I965G(pI810)) #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810)) @@ -64,10 +64,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define I810_VERSION 4000 #define I810_NAME "I810" #define I810_DRIVER_NAME "i810" -#define I810_MAJOR_VERSION 1 -#define I810_MINOR_VERSION 6 -#define I810_PATCHLEVEL 0 - /* HWMC Surfaces */ #define I810_MAX_SURFACES 7 diff --git a/src/i810_dri.h b/src/i810_dri.h index 408a4ebb..027a47a9 100644 --- a/src/i810_dri.h +++ b/src/i810_dri.h @@ -8,6 +8,10 @@ #define I810_MAX_DRAWABLES 256 +#define I810_MAJOR_VERSION 1 +#define I810_MINOR_VERSION 6 +#define I810_PATCHLEVEL 3 + typedef struct { drm_handle_t regs; drmSize regsSize; diff --git a/src/i810_driver.c b/src/i810_driver.c index 7d854df2..22635c86 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -140,6 +140,10 @@ static SymTabRec I810Chipsets[] = { {PCI_CHIP_I915_GM, "915GM"}, {PCI_CHIP_I945_G, "945G"}, {PCI_CHIP_I945_GM, "945GM"}, + {PCI_CHIP_I965_G, "965G"}, + {PCI_CHIP_I965_G_1, "965G"}, + {PCI_CHIP_I965_Q, "965Q"}, + {PCI_CHIP_I946_GZ, "946GZ"}, {-1, NULL} }; @@ -159,6 +163,10 @@ static PciChipsets I810PciChipsets[] = { {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA}, {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA}, + {PCI_CHIP_I965_G, PCI_CHIP_I965_G, RES_SHARED_VGA}, + {PCI_CHIP_I965_G_1, PCI_CHIP_I965_G_1, RES_SHARED_VGA}, + {PCI_CHIP_I965_Q, PCI_CHIP_I965_Q, RES_SHARED_VGA}, + {PCI_CHIP_I946_GZ, PCI_CHIP_I946_GZ, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; @@ -324,14 +332,13 @@ const char *I810driSymbols[] = { "DRICreatePCIBusID", NULL }; -#endif + +#endif /* I830_ONLY */ const char *I810shadowSymbols[] = { "shadowInit", "shadowSetup", "shadowAdd", - "shadowRemove", - "shadowUpdateRotatePacked", NULL }; @@ -372,7 +379,7 @@ static XF86ModuleVersionInfo i810VersRec = { MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, - I810_MAJOR_VERSION, I810_MINOR_VERSION, I810_PATCHLEVEL, + INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH, ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_VIDEODRV, @@ -401,9 +408,9 @@ i810Setup(pointer module, pointer opts, int *errmaj, int *errmin) #ifdef XF86DRI I810drmSymbols, I810driSymbols, +#endif I810shadowSymbols, I810shadowFBSymbols, -#endif I810vbeSymbols, vbeOptionalSymbols, I810ddcSymbols, I810int10Symbols, NULL); @@ -578,6 +585,10 @@ I810Probe(DriverPtr drv, int flags) case PCI_CHIP_I915_GM: case PCI_CHIP_I945_G: case PCI_CHIP_I945_GM: + case PCI_CHIP_I965_G: + case PCI_CHIP_I965_G_1: + case PCI_CHIP_I965_Q: + case PCI_CHIP_I946_GZ: xf86SetEntitySharable(usedChips[i]); /* Allocate an entity private if necessary */ diff --git a/src/i810_reg.h b/src/i810_reg.h index e52375f8..05710c48 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -293,8 +293,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define STATE_VAR_UPDATE_DISABLE 0x02 #define PAL_STIP_DISABLE 0x01 -#define INST_DONE 0x2090 -#define INST_PS 0x20c4 #define MEMMODE 0x20dc @@ -303,6 +301,66 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define IPEIR 0x2088 #define IPEHR 0x208C +#define INST_DONE 0x2090 +#define INST_PS 0x20c4 +#define IPEIR_I965 0x2064 /* i965 */ +#define IPEHR_I965 0x2068 /* i965 */ +#define INST_DONE_I965 0x206c +#define INST_PS_I965 0x2070 +#define ACTHD 0x2074 +#define DMA_FADD_P 0x2078 +#define INST_DONE_1 0x207c + +#define CACHE_MODE_0 0x2120 +#define CACHE_MODE_1 0x2124 +#define MI_ARB_STATE 0x20e4 + +#define WIZ_CTL 0x7c00 +#define WIZ_CTL_SINGLE_SUBSPAN (1<<6) +#define WIZ_CTL_IGNORE_STALLS (1<<5) + +#define SVG_WORK_CTL 0x7408 + +#define TS_CTL 0x7e00 +#define TS_MUX_ERR_CODE (0<<8) +#define TS_MUX_URB_0 (1<<8) +#define TS_MUX_DISPATCH_ID_0 (10<<8) +#define TS_MUX_ERR_CODE_VALID (15<<8) +#define TS_MUX_TID_0 (16<<8) +#define TS_MUX_EUID_0 (18<<8) +#define TS_MUX_FFID_0 (22<<8) +#define TS_MUX_EOT (26<<8) +#define TS_MUX_SIDEBAND_0 (27<<8) +#define TS_SNAP_ALL_CHILD (1<<2) +#define TS_SNAP_ALL_ROOT (1<<1) +#define TS_SNAP_ENABLE (1<<0) + +#define TS_DEBUG_DATA 0x7e0c + +#define TD_CTL 0x8000 +#define TD_CTL2 0x8004 + + +#define ECOSKPD 0x21d0 +#define EXCC 0x2028 + +/* I965 debug regs: + */ +#define IA_VERTICES_COUNT_QW 0x2310 +#define IA_PRIMITIVES_COUNT_QW 0x2318 +#define VS_INVOCATION_COUNT_QW 0x2320 +#define GS_INVOCATION_COUNT_QW 0x2328 +#define GS_PRIMITIVES_COUNT_QW 0x2330 +#define CL_INVOCATION_COUNT_QW 0x2338 +#define CL_PRIMITIVES_COUNT_QW 0x2340 +#define PS_INVOCATION_COUNT_QW 0x2348 +#define PS_DEPTH_COUNT_QW 0x2350 +#define TIMESTAMP_QW 0x2358 +#define CLKCMP_QW 0x2360 + + + + /* General error reporting regs, p296 @@ -366,6 +424,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FENCE 0x2000 #define FENCE_NR 8 +#define FENCE_NEW 0x3000 +#define FENCE_NEW_NR 16 + +#define FENCE_LINEAR 0 +#define FENCE_XMAJOR 1 +#define FENCE_YMAJOR 2 + #define I915G_FENCE_START_MASK 0x0ff00000 #define I830_FENCE_START_MASK 0x07f80000 @@ -772,6 +837,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DSPBPOS 0x7118C #define DSPBSIZE 0x71190 +#define DSPASURF 0x7019C +#define DSPATILEOFF 0x701A4 + +#define DSPBSURF 0x7119C +#define DSPBTILEOFF 0x711A4 + /* Various masks for reserved bits, etc. */ #define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \ (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \ @@ -866,15 +937,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define XY_MONO_SRC_BLT_WRITE_ALPHA (1<<21) #define XY_MONO_SRC_BLT_WRITE_RGB (1<<20) -/* 3d state */ #define STATE3D_FOG_MODE ((3<<29)|(0x1d<<24)|(0x89<<16)|2) #define FOG_MODE_VERTEX (1<<31) -#define STATE3D_MAP_COORD_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8c<<16)) + #define DISABLE_TEX_TRANSFORM (1<<28) #define TEXTURE_SET(x) (x<<29) -#define STATE3D_RASTERIZATION_RULES ((3<<29)|(0x07<<24)) -#define POINT_RASTER_ENABLE (1<<15) -#define POINT_RASTER_OGL (1<<13) + #define STATE3D_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16)) #define DISABLE_VIEWPORT_TRANSFORM (1<<31) #define DISABLE_PERSPECTIVE_DIVIDE (1<<29) @@ -907,7 +975,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define MI_WRITE_DIRTY_STATE (1<<4) #define MI_END_SCENE (1<<3) #define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2) +#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1) #define MI_INVALIDATE_MAP_CACHE (1<<0) +/* broadwater flush bits */ +#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3) /* Noop */ #define MI_NOOP 0x00 @@ -921,6 +992,244 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ENABLE_FOG_CONST (1<<24) #define ENABLE_FOG_DENSITY (1<<23) +/* + * New regs for broadwater -- we need to split this file up sensibly somehow. + */ +#define BRW_3D(Pipeline,Opcode,Subopcode) ((3 << 29) | \ + ((Pipeline) << 27) | \ + ((Opcode) << 24) | \ + ((Subopcode) << 16)) + +#define BRW_URB_FENCE BRW_3D(0, 0, 0) +#define BRW_CS_URB_STATE BRW_3D(0, 0, 1) +#define BRW_CONSTANT_BUFFER BRW_3D(0, 0, 2) +#define BRW_STATE_PREFETCH BRW_3D(0, 0, 3) + +#define BRW_STATE_BASE_ADDRESS BRW_3D(0, 1, 1) +#define BRW_STATE_SIP BRW_3D(0, 1, 2) +#define BRW_PIPELINE_SELECT BRW_3D(0, 1, 4) + +#define BRW_MEDIA_STATE_POINTERS BRW_3D(2, 0, 0) +#define BRW_MEDIA_OBJECT BRW_3D(2, 1, 0) + +#define BRW_3DSTATE_PIPELINED_POINTERS BRW_3D(3, 0, 0) +#define BRW_3DSTATE_BINDING_TABLE_POINTERS BRW_3D(3, 0, 1) +#define BRW_3DSTATE_VERTEX_BUFFERS BRW_3D(3, 0, 8) +#define BRW_3DSTATE_VERTEX_ELEMENTS BRW_3D(3, 0, 9) +#define BRW_3DSTATE_INDEX_BUFFER BRW_3D(3, 0, 0xa) +#define BRW_3DSTATE_VF_STATISTICS BRW_3D(3, 0, 0xb) + +#define BRW_3DSTATE_DRAWING_RECTANGLE BRW_3D(3, 1, 0) +#define BRW_3DSTATE_CONSTANT_COLOR BRW_3D(3, 1, 1) +#define BRW_3DSTATE_SAMPLER_PALETTE_LOAD BRW_3D(3, 1, 2) +#define BRW_3DSTATE_CHROMA_KEY BRW_3D(3, 1, 4) +#define BRW_3DSTATE_DEPTH_BUFFER BRW_3D(3, 1, 5) +#define BRW_3DSTATE_POLY_STIPPLE_OFFSET BRW_3D(3, 1, 6) +#define BRW_3DSTATE_POLY_STIPPLE_PATTERN BRW_3D(3, 1, 7) +#define BRW_3DSTATE_LINE_STIPPLE BRW_3D(3, 1, 8) +#define BRW_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP BRW_3D(3, 1, 9) +/* These two are BLC and CTG only, not BW or CL */ +#define BRW_3DSTATE_AA_LINE_PARAMS BRW_3D(3, 1, 0xa) +#define BRW_3DSTATE_GS_SVB_INDEX BRW_3D(3, 1, 0xb) + +#define BRW_PIPE_CONTROL BRW_3D(3, 2, 0) + +#define BRW_3DPRIMITIVE BRW_3D(3, 3, 0) + +#define PIPELINE_SELECT_3D 0 +#define PIPELINE_SELECT_MEDIA 1 + +#define UF0_CS_REALLOC (1 << 13) +#define UF0_VFE_REALLOC (1 << 12) +#define UF0_SF_REALLOC (1 << 11) +#define UF0_CLIP_REALLOC (1 << 10) +#define UF0_GS_REALLOC (1 << 9) +#define UF0_VS_REALLOC (1 << 8) +#define UF1_CLIP_FENCE_SHIFT 20 +#define UF1_GS_FENCE_SHIFT 10 +#define UF1_VS_FENCE_SHIFT 0 +#define UF2_CS_FENCE_SHIFT 20 +#define UF2_VFE_FENCE_SHIFT 10 +#define UF2_SF_FENCE_SHIFT 0 + +/* for BRW_STATE_BASE_ADDRESS */ +#define BASE_ADDRESS_MODIFY (1 << 0) + +/* for BRW_3DSTATE_PIPELINED_POINTERS */ +#define BRW_GS_DISABLE 0 +#define BRW_GS_ENABLE 1 +#define BRW_CLIP_DISABLE 0 +#define BRW_CLIP_ENABLE 1 + +/* for BRW_PIPE_CONTROL */ +#define BRW_PIPE_CONTROL_NOWRITE (0 << 14) +#define BRW_PIPE_CONTROL_WRITE_QWORD (1 << 14) +#define BRW_PIPE_CONTROL_WRITE_DEPTH (2 << 14) +#define BRW_PIPE_CONTROL_WRITE_TIME (3 << 14) +#define BRW_PIPE_CONTROL_DEPTH_STALL (1 << 13) +#define BRW_PIPE_CONTROL_WC_FLUSH (1 << 12) +#define BRW_PIPE_CONTROL_IS_FLUSH (1 << 11) +#define BRW_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8) +#define BRW_PIPE_CONTROL_GLOBAL_GTT (1 << 2) +#define BRW_PIPE_CONTROL_LOCAL_PGTT (0 << 2) + +/* VERTEX_BUFFER_STATE Structure */ +#define VB0_BUFFER_INDEX_SHIFT 27 +#define VB0_VERTEXDATA (0 << 26) +#define VB0_INSTANCEDATA (1 << 26) +#define VB0_BUFFER_PITCH_SHIFT 0 + +/* VERTEX_ELEMENT_STATE Structure */ +#define VE0_VERTEX_BUFFER_INDEX_SHIFT 27 +#define VE0_VALID (1 << 26) +#define VE0_FORMAT_SHIFT 16 +#define VE0_OFFSET_SHIFT 0 +#define VE1_VFCOMPONENT_0_SHIFT 28 +#define VE1_VFCOMPONENT_1_SHIFT 24 +#define VE1_VFCOMPONENT_2_SHIFT 20 +#define VE1_VFCOMPONENT_3_SHIFT 16 +#define VE1_DESTINATION_ELEMENT_OFFSET_SHIFT 0 + +/* 3DPRIMITIVE bits */ +#define BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL (0 << 15) +#define BRW_3DPRIMITIVE_VERTEX_RANDOM (1 << 15) +/* Primitive types are in brw_defines.h */ +#define BRW_3DPRIMITIVE_TOPOLOGY_SHIFT 10 + +#define BRW_SVG_CTL 0x7400 + +#define BRW_SVG_CTL_GS_BA (0 << 8) +#define BRW_SVG_CTL_SS_BA (1 << 8) +#define BRW_SVG_CTL_IO_BA (2 << 8) +#define BRW_SVG_CTL_GS_AUB (3 << 8) +#define BRW_SVG_CTL_IO_AUB (4 << 8) +#define BRW_SVG_CTL_SIP (5 << 8) + +#define BRW_SVG_RDATA 0x7404 +#define BRW_SVG_WORK_CTL 0x7408 + +#define BRW_VF_CTL 0x7500 + +#define BRW_VF_CTL_SNAPSHOT_COMPLETE (1 << 31) +#define BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID (0 << 8) +#define BRW_VF_CTL_SNAPSHOT_MUX_SELECT_VF_DEBUG (1 << 8) +#define BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_SEQUENCE (0 << 4) +#define BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX (1 << 4) +#define BRW_VF_CTL_SKIP_INITIAL_PRIMITIVES (1 << 3) +#define BRW_VF_CTL_MAX_PRIMITIVES_LIMIT_ENABLE (1 << 2) +#define BRW_VF_CTL_VERTEX_RANGE_LIMIT_ENABLE (1 << 1) +#define BRW_VF_CTL_SNAPSHOT_ENABLE (1 << 0) + +#define BRW_VF_STRG_VAL 0x7504 +#define BRW_VF_STR_VL_OVR 0x7508 +#define BRW_VF_VC_OVR 0x750c +#define BRW_VF_STR_PSKIP 0x7510 +#define BRW_VF_MAX_PRIM 0x7514 +#define BRW_VF_RDATA 0x7518 + +#define BRW_VS_CTL 0x7600 +#define BRW_VS_CTL_SNAPSHOT_COMPLETE (1 << 31) +#define BRW_VS_CTL_SNAPSHOT_MUX_VERTEX_0 (0 << 8) +#define BRW_VS_CTL_SNAPSHOT_MUX_VERTEX_1 (1 << 8) +#define BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT (2 << 8) +#define BRW_VS_CTL_SNAPSHOT_MUX_VS_KERNEL_POINTER (3 << 8) +#define BRW_VS_CTL_SNAPSHOT_ALL_THREADS (1 << 2) +#define BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) +#define BRW_VS_CTL_SNAPSHOT_ENABLE (1 << 0) + +#define BRW_VS_STRG_VAL 0x7604 +#define BRW_VS_RDATA 0x7608 + +#define BRW_SF_CTL 0x7b00 +#define BRW_SF_CTL_SNAPSHOT_COMPLETE (1 << 31) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_0_FF_ID (0 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_0_REL_COUNT (1 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_1_FF_ID (2 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_1_REL_COUNT (3 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_2_FF_ID (4 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_2_REL_COUNT (5 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT (6 << 8) +#define BRW_SF_CTL_SNAPSHOT_MUX_SF_KERNEL_POINTER (7 << 8) +#define BRW_SF_CTL_MIN_MAX_PRIMITIVE_RANGE_ENABLE (1 << 4) +#define BRW_SF_CTL_DEBUG_CLIP_RECTANGLE_ENABLE (1 << 3) +#define BRW_SF_CTL_SNAPSHOT_ALL_THREADS (1 << 2) +#define BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) +#define BRW_SF_CTL_SNAPSHOT_ENABLE (1 << 0) + +#define BRW_SF_STRG_VAL 0x7b04 +#define BRW_SF_RDATA 0x7b18 + +#define BRW_WIZ_CTL 0x7c00 +#define BRW_WIZ_CTL_SNAPSHOT_COMPLETE (1 << 31) +#define BRW_WIZ_CTL_SUBSPAN_INSTANCE_SHIFT 16 +#define BRW_WIZ_CTL_SNAPSHOT_MUX_WIZ_KERNEL_POINTER (0 << 8) +#define BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE (1 << 8) +#define BRW_WIZ_CTL_SNAPSHOT_MUX_PRIMITIVE_SEQUENCE (2 << 8) +#define BRW_WIZ_CTL_SINGLE_SUBSPAN_DISPATCH (1 << 6) +#define BRW_WIZ_CTL_IGNORE_COLOR_SCOREBOARD_STALLS (1 << 5) +#define BRW_WIZ_CTL_ENABLE_SUBSPAN_INSTANCE_COMPARE (1 << 4) +#define BRW_WIZ_CTL_USE_UPSTREAM_SNAPSHOT_FLAG (1 << 3) +#define BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS (1 << 2) +#define BRW_WIZ_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) +#define BRW_WIZ_CTL_SNAPSHOT_ENABLE (1 << 0) + +#define BRW_WIZ_STRG_VAL 0x7c04 +#define BRW_WIZ_RDATA 0x7c18 + +#define BRW_TS_CTL 0x7e00 +#define BRW_TS_CTL_SNAPSHOT_COMPLETE (1 << 31) +#define BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR (0 << 8) +#define BRW_TS_CTL_SNAPSHOT_INTERFACE_DESCRIPTOR (3 << 8) +#define BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS (1 << 2) +#define BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS (1 << 1) +#define BRW_TS_CTL_SNAPSHOT_ENABLE (1 << 0) + +#define BRW_TS_STRG_VAL 0x7e04 +#define BRW_TS_RDATA 0x7e08 + +#define BRW_TD_CTL 0x8000 +#define BRW_TD_CTL_MUX_SHIFT 8 +#define BRW_TD_CTL_EXTERNAL_HALT_R0_DEBUG_MATCH (1 << 7) +#define BRW_TD_CTL_FORCE_EXTERNAL_HALT (1 << 6) +#define BRW_TD_CTL_EXCEPTION_MASK_OVERRIDE (1 << 5) +#define BRW_TD_CTL_FORCE_THREAD_BREAKPOINT_ENABLE (1 << 4) +#define BRW_TD_CTL_BREAKPOINT_ENABLE (1 << 2) +#define BRW_TD_CTL2 0x8004 +#define BRW_TD_CTL2_ILLEGAL_OPCODE_EXCEPTION_OVERRIDE (1 << 28) +#define BRW_TD_CTL2_MASKSTACK_EXCEPTION_OVERRIDE (1 << 26) +#define BRW_TD_CTL2_SOFTWARE_EXCEPTION_OVERRIDE (1 << 25) +#define BRW_TD_CTL2_ACTIVE_THREAD_LIMIT_SHIFT 16 +#define BRW_TD_CTL2_ACTIVE_THREAD_LIMIT_ENABLE (1 << 8) +#define BRW_TD_CTL2_THREAD_SPAWNER_EXECUTION_MASK_ENABLE (1 << 7) +#define BRW_TD_CTL2_WIZ_EXECUTION_MASK_ENABLE (1 << 6) +#define BRW_TD_CTL2_SF_EXECUTION_MASK_ENABLE (1 << 5) +#define BRW_TD_CTL2_CLIPPER_EXECUTION_MASK_ENABLE (1 << 4) +#define BRW_TD_CTL2_GS_EXECUTION_MASK_ENABLE (1 << 3) +#define BRW_TD_CTL2_VS_EXECUTION_MASK_ENABLE (1 << 0) +#define BRW_TD_VF_VS_EMSK 0x8008 +#define BRW_TD_GS_EMSK 0x800c +#define BRW_TD_CLIP_EMSK 0x8010 +#define BRW_TD_SF_EMSK 0x8014 +#define BRW_TD_WIZ_EMSK 0x8018 +#define BRW_TD_0_6_EHTRG_VAL 0x801c +#define BRW_TD_0_7_EHTRG_VAL 0x8020 +#define BRW_TD_0_6_EHTRG_MSK 0x8024 +#define BRW_TD_0_7_EHTRG_MSK 0x8028 +#define BRW_TD_RDATA 0x802c +#define BRW_TD_TS_EMSK 0x8030 + +#define BRW_EU_CTL 0x8800 +#define BRW_EU_CTL_SELECT_SHIFT 16 +#define BRW_EU_CTL_DATA_MUX_SHIFT 8 +#define BRW_EU_ATT_0 0x8810 +#define BRW_EU_ATT_1 0x8814 +#define BRW_EU_ATT_DATA_0 0x8820 +#define BRW_EU_ATT_DATA_1 0x8824 +#define BRW_EU_ATT_CLR_0 0x8830 +#define BRW_EU_ATT_CLR_1 0x8834 +#define BRW_EU_RDATA 0x8840 + +/* End regs for broadwater */ #define MAX_DISPLAY_PIPES 2 @@ -47,6 +47,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef _I830_H_ #define _I830_H_ +#include "xf86_OSproc.h" #include "compiler.h" #include "xf86PciInfo.h" #include "xf86Pci.h" @@ -56,6 +57,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86xv.h" #include "xf86int10.h" #include "vbe.h" +#include "vbeModes.h" #include "vgaHW.h" #include "randrstr.h" @@ -79,6 +81,11 @@ Bool I830XAAInit(ScreenPtr pScreen); #include "common.h" +#define NEED_REPLIES /* ? */ +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" /* required */ +#include <X11/extensions/panoramiXproto.h> /* required */ + /* I830 Video BIOS support */ /* @@ -102,7 +109,6 @@ typedef struct _VESARec { int statePage, stateSize, stateMode, stateRefresh; CARD32 *savedPal; int savedScanlinePitch; - xf86MonPtr monitor; /* Don't try to set the refresh rate for any modes. */ Bool useDefaultRefresh; /* display start */ @@ -150,7 +156,7 @@ typedef struct { } I830RingBuffer; typedef struct { - unsigned int Fence[8]; + unsigned int Fence[FENCE_NEW_NR * 2]; } I830RegRec, *I830RegPtr; typedef struct { @@ -164,6 +170,29 @@ typedef struct { #endif } I830EntRec, *I830EntPtr; +typedef struct _MergedDisplayModeRec { + DisplayModePtr First; + DisplayModePtr Second; + int SecondPosition; +} I830MergedDisplayModeRec, *I830MergedDisplayModePtr; + +typedef struct _I830XineramaData { + int x; + int y; + int width; + int height; +} I830XineramaData; + +typedef struct _ModePrivateRec { + I830MergedDisplayModeRec merged; + VbeModeInfoData vbeData; +} I830ModePrivateRec, *I830ModePrivatePtr; + +typedef struct _region { + int x0,x1,y0,y1; +} region; + + typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; @@ -229,7 +258,25 @@ typedef struct _I830Rec { I830MemRange *OverlayMem; I830MemRange LinearMem; #endif - unsigned int LinearAlloc; + int LinearAlloc; + + Bool MergedFB; + ScrnInfoPtr pScrn_2; + char *SecondHSync; + char *SecondVRefresh; + char *MetaModes; + int SecondPosition; + int FirstXOffs, FirstYOffs, SecondXOffs, SecondYOffs; + int FirstframeX0, FirstframeX1, FirstframeY0, FirstframeY1; + int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX; + Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions; + int maxFirst_X1, maxFirst_X2, maxFirst_Y1, maxFirst_Y2; + int maxSecond_X1, maxSecond_X2, maxSecond_Y1, maxSecond_Y2; + region NonRectDead, OffDead1, OffDead2; + Bool IntelXinerama; + Bool SecondIsScrn0; + ExtensionEntry *XineramaExtEntry; + int I830XineramaVX, I830XineramaVY; XF86ModReqInfo shadowReq; /* to test for later libshadow */ I830MemRange RotatedMem; @@ -249,6 +296,12 @@ typedef struct _I830Rec { int TexGranularity; int drmMinor; Bool have3DWindows; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; #endif Bool NeedRingBufferLow; @@ -397,6 +450,9 @@ typedef struct _I830Rec { Bool devicePresence; OsTimerPtr devicesTimer; + + CARD32 savedAsurf; + CARD32 savedBsurf; } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) @@ -411,6 +467,7 @@ extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis); extern void I830SetPIOAccess(I830Ptr pI830); extern void I830SetMMIOAccess(I830Ptr pI830); extern void I830PrintErrorState(ScrnInfoPtr pScrn); +extern void I965PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); extern Bool I830CursorInit(ScreenPtr pScreen); @@ -471,8 +528,8 @@ extern long I830GetExcessMemoryAllocations(ScrnInfoPtr pScrn); extern Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags); extern Bool I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool); extern Bool I830FixupOffsets(ScrnInfoPtr pScrn); -extern Bool I830BindGARTMemory(ScrnInfoPtr pScrn); -extern Bool I830UnbindGARTMemory(ScrnInfoPtr pScrn); +extern Bool I830BindAGPMemory(ScrnInfoPtr pScrn); +extern Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); extern unsigned long I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags); diff --git a/src/i830_3d.c b/src/i830_3d.c index 214beb60..563dcef7 100644 --- a/src/i830_3d.c +++ b/src/i830_3d.c @@ -29,6 +29,7 @@ #include "config.h" #endif +#include "xf86.h" #include "i830.h" #include "i830_reg.h" diff --git a/src/i830_accel.c b/src/i830_accel.c index 6b338879..6ad62d1f 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -134,6 +134,7 @@ void I830Sync(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC)) ErrorF("I830Sync\n"); @@ -148,13 +149,17 @@ I830Sync(ScrnInfoPtr pScrn) if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return; + if (IS_I965G(pI830)) + flags = 0; + /* Send a flush instruction and then wait till the ring is empty. * This is stronger than waiting for the blitter to finish as it also * flushes the internal graphics caches. */ + { BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_FLUSH | flags); OUT_RING(MI_NOOP); /* pad to quadword */ ADVANCE_LP_RING(); } @@ -169,9 +174,13 @@ void I830EmitFlush(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; + + if (IS_I965G(pI830)) + flags = 0; BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(MI_FLUSH | flags); OUT_RING(MI_NOOP); /* pad to quadword */ ADVANCE_LP_RING(); } @@ -233,4 +242,3 @@ I830AccelInit(ScreenPtr pScreen) #endif return FALSE; } - diff --git a/src/i830_common.h b/src/i830_common.h index a27bc011..c3ef4cde 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -84,7 +84,7 @@ typedef struct { drmTextureRegion texList[I830_NR_TEX_REGIONS+1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ - int last_dispatch; /* age of the most recently dispatched buffer */ + volatile int last_dispatch; /* age of the most recently dispatched buffer */ int ctxOwner; /* last context to upload state */ int texAge; int pf_enabled; /* is pageflipping allowed? */ @@ -115,6 +115,12 @@ typedef struct { int rotated_size; int rotated_pitch; int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; } drmI830Sarea; /* Flags for perf_boxes diff --git a/src/i830_cursor.c b/src/i830_cursor.c index e465b98c..c9e04e97 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -93,30 +93,47 @@ I830InitHWCursor(ScrnInfoPtr pScrn) MCURSOR_PIPE_SELECT); temp |= CURSOR_MODE_DISABLE; temp |= (pI830->pipe << 28); - if(pI830->CursorIsARGB) - temp |= MCURSOR_GAMMA_ENABLE; - /* Need to set control, then address. */ - OUTREG(CURSOR_A_CONTROL, temp); if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { + temp |= CURSOR_MODE_64_4C_AX; + /* Need to set control, then address. */ + OUTREG(CURSOR_A_CONTROL, temp); + if (pI830->CursorNeedsPhysical) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start); + } + if (pI830->Clone || pI830->MergedFB) { temp &= ~MCURSOR_PIPE_SELECT; temp |= (!pI830->pipe << 28); OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + if (pI830->CursorNeedsPhysical) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start); + } } } else { temp = INREG(CURSOR_CONTROL); temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE | CURSOR_ENABLE | CURSOR_STRIDE_MASK); - temp |= (CURSOR_FORMAT_3C); if (pI830->CursorIsARGB) - temp |= CURSOR_GAMMA_ENABLE; + temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; + else + temp |= CURSOR_FORMAT_3C; /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ @@ -357,6 +374,102 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) } #endif +#define CDMPTR ((I830ModePrivatePtr)pI830->currentMode->Private)->merged + +static void +I830SetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) +{ + I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn2 = pI830->pScrn_2; + DisplayModePtr mode1 = CDMPTR.First; + Bool hide = FALSE, show = FALSE; + DisplayModePtr mode2 = CDMPTR.Second; + int x1, y1, x2, y2; + int total_y1 = pScrn->frameY1 - pScrn->frameY0; + int total_y2 = pScrn2->frameY1 - pScrn2->frameY0; + CARD32 temp = 0, temp2 = 0; + + x += pScrn->frameX0; + y += pScrn->frameY0; + + x1 = x - pI830->FirstframeX0; + y1 = y - pI830->FirstframeY0; + + x2 = x - pScrn2->frameX0; + y2 = y - pScrn2->frameY0; + + if (y1 > total_y1) + y1 = total_y1; + if (y2 > total_y2) + y2 = total_y2; + + /* move cursor offscreen */ + if (y1 >= 0 && y2 >= mode2->VDisplay) { + y2 = -I810_CURSOR_Y; + } else if (y2 >= 0 && y1 >= mode1->VDisplay) { + y1 = -I810_CURSOR_Y; + } + if (x1 >= 0 && x2 >= mode2->HDisplay) { + x2 = -I810_CURSOR_X; + } else if (x2 >= 0 && x1 >= mode1->HDisplay) { + x1 = -I810_CURSOR_X; + } + + /* Clamp the cursor position to the visible screen area */ + if (x1 >= mode1->HDisplay) x1 = mode1->HDisplay - 1; + if (y1 >= mode1->VDisplay) y1 = mode1->VDisplay - 1; + if (x1 <= -I810_CURSOR_X) x1 = -I810_CURSOR_X + 1; + if (y1 <= -I810_CURSOR_Y) y1 = -I810_CURSOR_Y + 1; + if (x2 >= mode2->HDisplay) x2 = mode2->HDisplay - 1; + if (y2 >= mode2->VDisplay) y2 = mode2->VDisplay - 1; + if (x2 <= -I810_CURSOR_X) x2 = -I810_CURSOR_X + 1; + if (y2 <= -I810_CURSOR_Y) y2 = -I810_CURSOR_Y + 1; + + if (x1 < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + x1 = -x1; + } + if (y1 < 0) { + temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + y1 = -y1; + } + if (x2 < 0) { + temp2 |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); + x2 = -x2; + } + if (y2 < 0) { + temp2 |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); + y2 = -y2; + } + + temp |= ((x1 & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp |= ((y1 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + temp2 |= ((x2 & CURSOR_POS_MASK) << CURSOR_X_SHIFT); + temp2 |= ((y2 & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); + + OUTREG(CURSOR_A_POSITION, temp); + OUTREG(CURSOR_B_POSITION, temp2); + + if (pI830->cursorOn) { + if (hide) + pI830->CursorInfoRec->HideCursor(pScrn); + else if (show) + pI830->CursorInfoRec->ShowCursor(pScrn); + pI830->cursorOn = TRUE; + } + + /* have to upload the base for the new position */ + if (IS_I9XX(pI830)) { + if (pI830->CursorIsARGB) { + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + } else { + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } + } +} + static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { @@ -369,6 +482,11 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) static Bool outsideViewport = FALSE; #endif + if (pI830->MergedFB) { + I830SetCursorPositionMerged(pScrn, x, y); + return; + } + oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ oldy += pScrn->frameY0; @@ -451,15 +569,29 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) /* have to upload the base for the new position */ if (IS_I9XX(pI830)) { - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { + if (pI830->CursorNeedsPhysical) { if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start); + } + if (pI830->Clone) { + if (pI830->CursorNeedsPhysical) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start); + } } } } @@ -483,7 +615,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->cursorOn = TRUE; if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT | MCURSOR_GAMMA_ENABLE); if (pI830->CursorIsARGB) temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; else @@ -491,25 +623,39 @@ I830ShowCursor(ScrnInfoPtr pScrn) temp |= (pI830->pipe << 28); /* Connect to correct pipe */ /* Need to set mode, then address. */ OUTREG(CURSOR_A_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { + if (pI830->CursorNeedsPhysical) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Start); + } + if (pI830->Clone || pI830->MergedFB) { temp &= ~MCURSOR_PIPE_SELECT; temp |= (!pI830->pipe << 28); OUTREG(CURSOR_B_CONTROL, temp); - if (pI830->CursorIsARGB) - OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); - else - OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + if (pI830->CursorNeedsPhysical) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } else { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Start); + } } } else { temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_FORMAT_MASK); + temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE); temp |= CURSOR_ENABLE; if (pI830->CursorIsARGB) - temp |= CURSOR_FORMAT_ARGB | CURSOR_GAMMA_ENABLE; + temp |= CURSOR_FORMAT_ARGB; else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); @@ -531,7 +677,7 @@ I830HideCursor(ScrnInfoPtr pScrn) pI830->cursorOn = FALSE; if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { temp = INREG(CURSOR_A_CONTROL); - temp &= ~(CURSOR_MODE|MCURSOR_GAMMA_ENABLE); + temp &= ~CURSOR_MODE; temp |= CURSOR_MODE_DISABLE; OUTREG(CURSOR_A_CONTROL, temp); /* This is needed to flush the above change. */ @@ -539,7 +685,7 @@ I830HideCursor(ScrnInfoPtr pScrn) OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); else OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); - if (pI830->Clone) { + if (pI830->Clone || pI830->MergedFB) { OUTREG(CURSOR_B_CONTROL, temp); if (pI830->CursorIsARGB) OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); @@ -548,7 +694,7 @@ I830HideCursor(ScrnInfoPtr pScrn) } } else { temp = INREG(CURSOR_CONTROL); - temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); + temp &= ~CURSOR_ENABLE; OUTREG(CURSOR_CONTROL, temp); } } @@ -570,7 +716,7 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); - if (pI830->Clone) { + if (pI830->Clone || pI830->MergedFB) { OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff); diff --git a/src/i830_dga.c b/src/i830_dga.c index 08207d39..c78063e1 100644 --- a/src/i830_dga.c +++ b/src/i830_dga.c @@ -99,6 +99,31 @@ I830DGAInit(ScreenPtr pScreen) while (pMode) { + if(pI830->MergedFB) { + Bool nogood = FALSE; + /* Filter out all meta modes that would require driver-side panning */ + switch(((I830ModePrivatePtr)pMode->Private)->merged.SecondPosition) { + case PosRightOf: + case PosLeftOf: + if( (((I830ModePrivatePtr)pMode->Private)->merged.First->VDisplay != + ((I830ModePrivatePtr)pMode->Private)->merged.Second->VDisplay) || + (((I830ModePrivatePtr)pMode->Private)->merged.First->VDisplay != pMode->VDisplay) ) + nogood = TRUE; + break; + default: + if( (((I830ModePrivatePtr)pMode->Private)->merged.First->HDisplay != + ((I830ModePrivatePtr)pMode->Private)->merged.Second->HDisplay) || + (((I830ModePrivatePtr)pMode->Private)->merged.First->HDisplay != pMode->HDisplay) ) + nogood = TRUE; + } + if(nogood) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DGA: MetaMode %dx%d not suitable for DGA, skipping\n", + pMode->HDisplay, pMode->VDisplay); + goto mode_nogood; + } + } + newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec)); if (!newmodes) { @@ -155,6 +180,7 @@ I830DGAInit(ScreenPtr pScreen) currentMode->maxViewportY = currentMode->imageHeight - currentMode->viewportHeight; +mode_nogood: pMode = pMode->next; if (pMode == firstMode) break; @@ -254,15 +280,26 @@ I830_FillRect(ScrnInfoPtr pScrn, static void I830_Sync(ScrnInfoPtr pScrn) { -#ifdef I830_USE_XAA I830Ptr pI830 = I830PTR(pScrn); + int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE; MARKER(); - if (pI830->AccelInfoRec) { - (*pI830->AccelInfoRec->Sync) (pScrn); - } -#endif + if (pI830->noAccel) + return; + + if (IS_I965G(pI830)) + flags = 0; + + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | flags); + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); + + I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0); + + pI830->LpRing->space = pI830->LpRing->mem.Size - 8; + pI830->nextColorExpandBuf = 0; } static void diff --git a/src/i830_dri.c b/src/i830_dri.c index 56534342..8a52750f 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -81,8 +81,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i830_dri.h" +#include "dristruct.h" + static char I830KernelDriverName[] = "i915"; static char I830ClientDriverName[] = "i915"; +static char I965ClientDriverName[] = "i965"; static Bool I830InitVisualConfigs(ScreenPtr pScreen); static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual, @@ -424,11 +427,13 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) * for known symbols in each module. */ if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) return FALSE; + if (!xf86LoaderCheckSymbol("DRIScreenInit")) + return FALSE; if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[dri] %s failed (libdri.a too old)\n", "I830DRIScreenInit"); + "[dri] %s failed (libdri.a too old)\n", "I830CheckDRIAvailable"); return FALSE; } @@ -440,10 +445,10 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] %s failed because of a version mismatch.\n" - "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n" + "[dri] libDRI version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling DRI.\n", - "I830DRIScreenInit", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + "I830CheckDRIAvailable", major, minor, patch, + DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); return FALSE; } } @@ -475,7 +480,11 @@ I830DRIScreenInit(ScreenPtr pScreen) pI830->LockHeld = 0; pDRIInfo->drmDriverName = I830KernelDriverName; - pDRIInfo->clientDriverName = I830ClientDriverName; + if (IS_I965G(pI830)) + pDRIInfo->clientDriverName = I965ClientDriverName; + else + pDRIInfo->clientDriverName = I830ClientDriverName; + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { pDRIInfo->busIdString = DRICreatePCIBusID(pI830->PciInfo); } else { @@ -488,13 +497,16 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL; -#if 1 /* temporary until this gets removed from the libdri layer */ +#if 1 /* Remove this soon - see bug 5714 */ pDRIInfo->frameBufferPhysicalAddress = (char *) pI830->LinearAddr + pI830->FrontBuffer.Start; pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * pI830->cpp); - pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; +#else + /* For rotation we map a 0 length framebuffer as we remap ourselves later */ + pDRIInfo->frameBufferSize = 0; #endif + pDRIInfo->frameBufferStride = pScrn->displayWidth * pI830->cpp; pDRIInfo->ddxDrawableTableEntry = I830_MAX_DRAWABLES; if (SAREA_MAX_DRAWABLES < I830_MAX_DRAWABLES) @@ -534,6 +546,7 @@ I830DRIScreenInit(ScreenPtr pScreen) pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d; + /* do driver-independent DRI screen initialization here */ if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); @@ -544,6 +557,27 @@ I830DRIScreenInit(ScreenPtr pScreen) return FALSE; } +#if 0 /* disabled now, see frameBufferSize above being set to 0 */ + /* for this driver, get rid of the front buffer mapping now */ + if (xf86LoaderCheckSymbol("DRIGetScreenPrivate")) { + DRIScreenPrivPtr pDRIPriv + = (DRIScreenPrivPtr) DRIGetScreenPrivate(pScreen); + + if (pDRIPriv && pDRIPriv->drmFD && pDRIPriv->hFrameBuffer) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[intel] removing original screen mapping\n"); + drmRmMap(pDRIPriv->drmFD, pDRIPriv->hFrameBuffer); + pDRIPriv->hFrameBuffer = 0; + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[intel] done removing original screen mapping\n"); + } + } + else { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[intel] DRIGetScreenPrivate not found!!!!\n"); + } +#endif + /* Check the i915 DRM versioning */ { drmVersionPtr version; @@ -589,11 +623,11 @@ I830DRIScreenInit(ScreenPtr pScreen) /* Check the i915 DRM version */ version = drmGetVersion(pI830->drmSubFD); if (version) { - if (version->version_major != 1 || version->version_minor < 4) { + if (version->version_major != 1 || version->version_minor < 3) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] %s failed because of a version mismatch.\n" - "[dri] i915 kernel module version is %d.%d.%d but version 1.4 or greater is needed.\n" + "[dri] i915 kernel module version is %d.%d.%d but version 1.3 or greater is needed.\n" "[dri] Disabling DRI.\n", "I830DRIScreenInit", version->version_major, @@ -623,21 +657,31 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] Mapping front buffer\n"); - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), - sarea->front_size, - DRM_FRAME_BUFFER, /*DRM_AGP,*/ - 0, - (drmAddress) &sarea->front_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; +#if 1 /* Remove this soon - see bug 5714 */ + pI830->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * + pScrn->virtualY * pI830->cpp); +#endif + + /* The I965G isn't ready for the front buffer mapping to be moved around, + * because of issues with rmmap, it seems. + */ + if (!IS_I965G(pI830)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] Mapping front buffer\n"); + if (drmAddMap(pI830->drmSubFD, + (drm_handle_t)(sarea->front_offset + pI830->LinearAddr), + sarea->front_size, + DRM_AGP, + 0, + (drmAddress) &sarea->front_handle) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] drmAddMap(front_handle) failed. Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n", + (int)sarea->front_handle); } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Front Buffer = 0x%08x\n", - (int)sarea->front_handle); if (drmAddMap(pI830->drmSubFD, (drm_handle_t)(sarea->back_offset + pI830->LinearAddr), @@ -684,12 +728,10 @@ I830DRIUnmapScreenRegions(ScrnInfoPtr pScrn, drmI830Sarea *sarea) { I830Ptr pI830 = I830PTR(pScrn); -#if 1 if (sarea->front_handle) { drmRmMap(pI830->drmSubFD, sarea->front_handle); sarea->front_handle = 0; } -#endif if (sarea->back_handle) { drmRmMap(pI830->drmSubFD, sarea->back_handle); sarea->back_handle = 0; @@ -785,7 +827,6 @@ I830DRIDoMappings(ScreenPtr pScreen) /* screen mappings probably failed */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(screen mappings) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); return FALSE; } @@ -824,9 +865,6 @@ I830DRIDoMappings(ScreenPtr pScreen) pI830DRI->mem = pScrn->videoRam * 1024; pI830DRI->cpp = pI830->cpp; - pI830DRI->fbOffset = pI830->FrontBuffer.Start; - pI830DRI->fbStride = pI830->backPitch; - pI830DRI->bitsPerPixel = pScrn->bitsPerPixel; pI830DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); @@ -1032,6 +1070,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, { ScreenPtr pScreen = pParent->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); BoxPtr pboxTmp, pboxNext, pboxBase; DDXPointPtr pptTmp, pptNew2; int xdir, ydir; @@ -1164,8 +1203,10 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, I830SelectBuffer(pScrn, I830_SELECT_BACK); I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); - I830SelectBuffer(pScrn, I830_SELECT_DEPTH); - I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + if (!IS_I965G(pI830)) { + I830SelectBuffer(pScrn, I830_SELECT_DEPTH); + I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + } } I830SelectBuffer(pScrn, I830_SELECT_FRONT); I830EmitFlush(pScrn); @@ -1204,6 +1245,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, * might be faster, but seems like a lot more work... */ + #if 0 /* This should be done *before* XAA syncs, * Otherwise will have to sync again??? @@ -1213,7 +1255,7 @@ I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - RegionPtr damage = (RegionPtr) shadowDamage(pBuf); + RegionPtr damage = &pBuf->damage; int i, num = REGION_NUM_RECTS(damage); BoxPtr pbox = REGION_RECTS(damage); drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); @@ -1343,6 +1385,7 @@ I830DRITransitionTo2d(ScreenPtr pScreen) } pI830->have3DWindows = 0; + } @@ -1359,6 +1402,14 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) I830DRIUnmapScreenRegions(pScrn, sarea); + sarea->front_tiled = pI830->front_tiled; + sarea->back_tiled = pI830->back_tiled; + sarea->depth_tiled = pI830->depth_tiled; + sarea->rotated_tiled = pI830->rotated_tiled; +#if 0 + sarea->rotated2_tiled = pI830->rotated2_tiled; +#endif + if (pI830->rotation == RR_Rotate_0) { sarea->front_offset = pI830->FrontBuffer.Start; /* Don't use FrontBuffer.Size here as it includes the pixmap cache area @@ -1418,7 +1469,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, drmI830Sarea *sarea) success = I830DRIMapScreenRegions(pScrn, sarea); - I830InitTextureHeap(pScrn, sarea); + if (success) + I830InitTextureHeap(pScrn, sarea); return success; } diff --git a/src/i830_dri.h b/src/i830_dri.h index 4f356d1f..41f8a90a 100644 --- a/src/i830_dri.h +++ b/src/i830_dri.h @@ -10,7 +10,7 @@ #define I830_MAJOR_VERSION 1 #define I830_MINOR_VERSION 6 -#define I830_PATCHLEVEL 0 +#define I830_PATCHLEVEL 4 #define I830_REG_SIZE 0x80000 @@ -18,20 +18,20 @@ typedef struct _I830DRIRec { drm_handle_t regs; drmSize regsSize; - drmSize backbufferSize; - drm_handle_t backbuffer; + drmSize unused1; /* backbufferSize */ + drm_handle_t unused2; /* backbuffer */ - drmSize depthbufferSize; - drm_handle_t depthbuffer; + drmSize unused3; /* depthbufferSize */ + drm_handle_t unused4; /* depthbuffer */ - drmSize rotatedSize; - drm_handle_t rotatedbuffer; + drmSize unused5; /* rotatedSize /*/ + drm_handle_t unused6; /* rotatedbuffer */ - drm_handle_t textures; - int textureSize; + drm_handle_t unused7; /* textures */ + int unused8; /* textureSize */ - drm_handle_t agp_buffers; - drmSize agp_buf_size; + drm_handle_t unused9; /* agp_buffers */ + drmSize unused10; /* agp_buf_size */ int deviceID; int width; @@ -40,20 +40,10 @@ typedef struct _I830DRIRec { int cpp; int bitsPerPixel; - int fbOffset; - int fbStride; + int unused11[8]; /* was front/back/depth/rotated offset/pitch */ - int backOffset; - int backPitch; - - int depthOffset; - int depthPitch; - - int rotatedOffset; - int rotatedPitch; - - int logTextureGranularity; - int textureOffset; + int unused12; /* logTextureGranularity */ + int unused13; /* textureOffset */ int irq; int sarea_priv_offset; diff --git a/src/i830_driver.c b/src/i830_driver.c index ed855855..10a329c9 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -150,6 +150,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * 09/2005 Alan Hourihane * - Add Intel(R) 945GM support. * + * 10/2005 Alan Hourihane, Keith Whitwell, Brian Paul + * - Added Rotation support + * + * 12/2005 Alan Hourihane, Keith Whitwell + * - Add Intel(R) 965G support. */ #ifdef HAVE_CONFIG_H @@ -161,6 +166,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #endif #include <string.h> +#include <stdio.h> #include <unistd.h> #include <stdlib.h> @@ -178,13 +184,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include <X11/extensions/randr.h> #include "fb.h" #include "miscstruct.h" +#include "dixstruct.h" #include "xf86xv.h" #include <X11/extensions/Xv.h> #include "vbe.h" -#include "vbeModes.h" #include "shadow.h" #include "i830.h" +#ifdef HAS_MTRR_SUPPORT +#include <asm/mtrr.h> +#endif + #ifdef XF86DRI #include "dri.h" #endif @@ -216,6 +226,10 @@ static SymTabRec I830BIOSChipsets[] = { {PCI_CHIP_I915_GM, "915GM"}, {PCI_CHIP_I945_G, "945G"}, {PCI_CHIP_I945_GM, "945GM"}, + {PCI_CHIP_I965_G, "965G"}, + {PCI_CHIP_I965_G_1, "965G"}, + {PCI_CHIP_I965_Q, "965Q"}, + {PCI_CHIP_I946_GZ, "946GZ"}, {-1, NULL} }; @@ -229,6 +243,10 @@ static PciChipsets I830BIOSPciChipsets[] = { {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {PCI_CHIP_I945_G, PCI_CHIP_I945_G, RES_SHARED_VGA}, {PCI_CHIP_I945_GM, PCI_CHIP_I945_GM, RES_SHARED_VGA}, + {PCI_CHIP_I965_G, PCI_CHIP_I965_G, RES_SHARED_VGA}, + {PCI_CHIP_I965_G_1, PCI_CHIP_I965_G_1, RES_SHARED_VGA}, + {PCI_CHIP_I965_Q, PCI_CHIP_I965_Q, RES_SHARED_VGA}, + {PCI_CHIP_I946_GZ, PCI_CHIP_I946_GZ, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED} }; @@ -259,7 +277,13 @@ typedef enum { OPTION_CHECKDEVICES, OPTION_FIXEDPIPE, OPTION_ROTATE, - OPTION_LINEARALLOC + OPTION_LINEARALLOC, + OPTION_MERGEDFB, + OPTION_METAMODES, + OPTION_SECONDHSYNC, + OPTION_SECONDVREFRESH, + OPTION_SECONDPOSITION, + OPTION_INTELXINERAMA } I830Opts; static OptionInfoRec I830BIOSOptions[] = { @@ -284,13 +308,19 @@ static OptionInfoRec I830BIOSOptions[] = { {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE}, {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE}, {OPTION_LINEARALLOC, "LinearAlloc", OPTV_INTEGER, {0}, FALSE}, + {OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_METAMODES, "MetaModes", OPTV_STRING, {0}, FALSE}, + {OPTION_SECONDHSYNC, "SecondMonitorHorizSync",OPTV_STRING, {0}, FALSE }, + {OPTION_SECONDVREFRESH,"SecondMonitorVertRefresh",OPTV_STRING,{0}, FALSE }, + {OPTION_SECONDPOSITION,"SecondPosition",OPTV_STRING, {0}, FALSE }, + {OPTION_INTELXINERAMA,"MergedXinerama",OPTV_BOOLEAN, {0}, TRUE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); -static void I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags); +static void I830AdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack); static Bool I830BIOSEnterVT(int scrnIndex, int flags); @@ -301,9 +331,24 @@ static Bool SetPipeAccess(ScrnInfoPtr pScrn); extern int I830EntityIndex; +static Bool I830noPanoramiXExtension = TRUE; +static int I830XineramaNumScreens = 0; +static I830XineramaData *I830XineramadataPtr = NULL; +static int I830XineramaGeneration; + +static int I830ProcXineramaQueryVersion(ClientPtr client); +static int I830ProcXineramaGetState(ClientPtr client); +static int I830ProcXineramaGetScreenCount(ClientPtr client); +static int I830ProcXineramaGetScreenSize(ClientPtr client); +static int I830ProcXineramaIsActive(ClientPtr client); +static int I830ProcXineramaQueryScreens(ClientPtr client); +static int I830SProcXineramaDispatch(ClientPtr client); + /* temporary */ extern void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y); +static const char *SecondMonitorName = "MergedFBMonitor"; + #ifdef I830DEBUG void @@ -372,11 +417,9 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn) if (mode) { do { if (mode->Private) { - VbeModeInfoData *data = (VbeModeInfoData *) mode->Private; + I830ModePrivatePtr mp = (I830ModePrivatePtr) mode->Private; - if (data->block) - xfree(data->block); - xfree(data); + xfree(mp); mode->Private = NULL; } mode = mode->next; @@ -391,8 +434,6 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn) } pVesa = pI830->vesa; - if (pVesa->monitor) - xfree(pVesa->monitor); if (pVesa->savedPal) xfree(pVesa->savedPal); xfree(pVesa); @@ -401,6 +442,1601 @@ I830BIOSFreeRec(ScrnInfoPtr pScrn) pScrn->driverPrivate = NULL; } +static Bool +InRegion(int x, int y, region r) +{ + return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); +} + +static int +I830StrToRanges(range *r, char *s, int max) +{ + float num = 0.0; + int rangenum = 0; + Bool gotdash = FALSE; + Bool nextdash = FALSE; + char *strnum = NULL; + do { + switch(*s) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + if(strnum == NULL) { + strnum = s; + gotdash = nextdash; + nextdash = FALSE; + } + break; + case '-': + case ' ': + case 0: + if(strnum == NULL) break; + sscanf(strnum, "%f", &num); + strnum = NULL; + if(gotdash) { + r[rangenum - 1].hi = num; + } else { + r[rangenum].lo = num; + r[rangenum].hi = num; + rangenum++; + } + if(*s == '-') nextdash = (rangenum != 0); + else if(rangenum >= max) return rangenum; + break; + default: + return 0; + } + + } while(*(s++) != 0); + + return rangenum; +} + +/* Calculate the vertical refresh rate from a mode */ +static float +I830CalcVRate(DisplayModePtr mode) +{ + float hsync, refresh = 0; + + if(mode->HSync > 0.0) + hsync = mode->HSync; + else if(mode->HTotal > 0) + hsync = (float)mode->Clock / (float)mode->HTotal; + else + hsync = 0.0; + + if(mode->VTotal > 0) + refresh = hsync * 1000.0 / mode->VTotal; + + if(mode->Flags & V_INTERLACE) + refresh *= 2.0; + + if(mode->Flags & V_DBLSCAN) + refresh /= 2.0; + + if(mode->VScan > 1) + refresh /= mode->VScan; + + if(mode->VRefresh > 0.0) + refresh = mode->VRefresh; + + if(hsync == 0.0 || refresh == 0.0) return 0.0; + + return refresh; +} + +/* Copy and link two modes (i, j) for mergedfb mode + * (Code base taken from mga driver) + * + * - Copy mode i, merge j to copy of i, link the result to dest + * - Link i and j in private record. + * - If dest is NULL, return value is copy of i linked to itself. + * - For mergedfb auto-config, we only check the dimension + * against virtualX/Y, if they were user-provided. + * - No special treatment required for CRTxxOffs. + * - Provide fake dotclock in order to distinguish between similar + * looking MetaModes (for RandR and VidMode extensions) + * - Set unique VRefresh of dest mode for RandR + */ +static DisplayModePtr +I830CopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, + DisplayModePtr i, DisplayModePtr j, + int pos) +{ + DisplayModePtr mode; + int dx = 0,dy = 0; + + if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; + memcpy(mode, i, sizeof(DisplayModeRec)); + if(!((mode->Private = xalloc(sizeof(I830ModePrivateRec))))) { + xfree(mode); + return dest; + } + ((I830ModePrivatePtr)mode->Private)->merged.First = i; + ((I830ModePrivatePtr)mode->Private)->merged.Second = j; + ((I830ModePrivatePtr)mode->Private)->merged.SecondPosition = pos; + if (((I830ModePrivatePtr)i->Private)->vbeData.mode > 0x30) { + ((I830ModePrivatePtr)mode->Private)->vbeData.mode = ((I830ModePrivatePtr)i->Private)->vbeData.mode; + ((I830ModePrivatePtr)mode->Private)->vbeData.data = ((I830ModePrivatePtr)i->Private)->vbeData.data; + } else { + ((I830ModePrivatePtr)mode->Private)->vbeData.mode = ((I830ModePrivatePtr)j->Private)->vbeData.mode; + ((I830ModePrivatePtr)mode->Private)->vbeData.data = ((I830ModePrivatePtr)j->Private)->vbeData.data; + } + mode->PrivSize = sizeof(I830ModePrivateRec); + + switch(pos) { + case PosLeftOf: + case PosRightOf: + if(!(pScrn->display->virtualX)) { + dx = i->HDisplay + j->HDisplay; + } else { + dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); + } + dx -= mode->HDisplay; + if(!(pScrn->display->virtualY)) { + dy = max(i->VDisplay, j->VDisplay); + } else { + dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); + } + dy -= mode->VDisplay; + break; + case PosAbove: + case PosBelow: + if(!(pScrn->display->virtualY)) { + dy = i->VDisplay + j->VDisplay; + } else { + dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); + } + dy -= mode->VDisplay; + if(!(pScrn->display->virtualX)) { + dx = max(i->HDisplay, j->HDisplay); + } else { + dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); + } + dx -= mode->HDisplay; + break; + } + mode->HDisplay += dx; + mode->HSyncStart += dx; + mode->HSyncEnd += dx; + mode->HTotal += dx; + mode->VDisplay += dy; + mode->VSyncStart += dy; + mode->VSyncEnd += dy; + mode->VTotal += dy; + + mode->type = M_T_DEFAULT; + + /* Set up as user defined (ie fake that the mode has been named in the + * Modes-list in the screen section; corrects cycling with CTRL-ALT-[-+] + * when source mode has not been listed there.) + */ + mode->type |= M_T_USERDEF; + + /* Set the VRefresh field (in order to make RandR use it for the rates). We + * simply set this to the refresh rate for the First mode (since Second will + * mostly be LCD or TV anyway). + */ + mode->VRefresh = I830CalcVRate(i); + + if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > (pScrn->videoRam * 1024)) || + (mode->HDisplay > 4088) || + (mode->VDisplay > 4096) ) { + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", + mode->name, mode->HDisplay, mode->VDisplay); + xfree(mode->Private); + xfree(mode); + + return dest; + } + + /* Now see if the resulting mode would be discarded as a "size" by the + * RandR extension, and increase its clock by 1000 in case it does. + */ + if(dest) { + DisplayModePtr t = dest; + do { + if((t->HDisplay == mode->HDisplay) && + (t->VDisplay == mode->VDisplay) && + ((int)(t->VRefresh + .5) == (int)(mode->VRefresh + .5))) { + mode->VRefresh += 1000.0; + } + t = t->next; + } while((t) && (t != dest)); + } + + /* Provide a fake but unique DotClock in order to trick the vidmode + * extension to allow selecting among a number of modes whose merged result + * looks identical but consists of different modes for First and Second + */ + mode->Clock = (int)(mode->VRefresh * 1000.0); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d (%d)\n", + i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, + mode->HDisplay, mode->VDisplay, (int)mode->VRefresh); + + mode->next = mode; + mode->prev = mode; + + if(dest) { + mode->next = dest->next; /* Insert node after "dest" */ + dest->next->prev = mode; + mode->prev = dest; + dest->next = mode; + } + + return mode; +} + +/* Helper function to find a mode from a given name + * (Code base taken from mga driver) + */ +static DisplayModePtr +I830GetModeFromName(char* str, DisplayModePtr i) +{ + DisplayModePtr c = i; + if(!i) return NULL; + do { + if(strcmp(str, c->name) == 0) return c; + c = c->next; + } while(c != i); + return NULL; +} + +static DisplayModePtr +I830FindWidestTallestMode(DisplayModePtr i, Bool tallest) +{ + DisplayModePtr c = i, d = NULL; + int max = 0; + if(!i) return NULL; + do { + if(tallest) { + if(c->VDisplay > max) { + max = c->VDisplay; + d = c; + } + } else { + if(c->HDisplay > max) { + max = c->HDisplay; + d = c; + } + } + c = c->next; + } while(c != i); + return d; +} + +static void +I830FindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, + DisplayModePtr *a, DisplayModePtr *b) +{ + DisplayModePtr c = i, d; + int max = 0; + Bool foundone; + + (*a) = (*b) = NULL; + + if(!i || !j) return; + + do { + d = j; + foundone = FALSE; + do { + if( (c->HDisplay == d->HDisplay) && + (c->VDisplay == d->VDisplay) ) { + foundone = TRUE; + break; + } + d = d->next; + } while(d != j); + if(foundone) { + if(tallest) { + if(c->VDisplay > max) { + max = c->VDisplay; + (*a) = c; + (*b) = d; + } + } else { + if(c->HDisplay > max) { + max = c->HDisplay; + (*a) = c; + (*b) = d; + } + } + } + c = c->next; + } while(c != i); +} + +static DisplayModePtr +I830GenerateModeListFromLargestModes(ScrnInfoPtr pScrn, + DisplayModePtr i, DisplayModePtr j, + int pos) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr mode1 = NULL; + DisplayModePtr mode2 = NULL; + DisplayModePtr mode3 = NULL; + DisplayModePtr mode4 = NULL; + DisplayModePtr result = NULL; + + /* Now build a default list of MetaModes. + * - Non-clone: If the user enabled NonRectangular, we use the + * largest mode for each First and Second. If not, we use the largest + * common mode for First and Second (if available). Additionally, and + * regardless if the above, we produce a clone mode consisting of + * the largest common mode (if available) in order to use DGA. + */ + + switch(pos) { + case PosLeftOf: + case PosRightOf: + mode1 = I830FindWidestTallestMode(i, FALSE); + mode2 = I830FindWidestTallestMode(j, FALSE); + I830FindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); + break; + case PosAbove: + case PosBelow: + mode1 = I830FindWidestTallestMode(i, TRUE); + mode2 = I830FindWidestTallestMode(j, TRUE); + I830FindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); + break; + } + + if(mode3 && mode4 && !pI830->NonRect) { + mode1 = mode3; + mode2 = mode2; + } + + if(mode1 && mode2) { + result = I830CopyModeNLink(pScrn, result, mode1, mode2, pos); + } + + return result; +} + +/* Generate the merged-fb mode modelist + * (Taken from mga driver) + */ +static DisplayModePtr +I830GenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + int pos) +{ + char* strmode = str; + char modename[256]; + Bool gotdash = FALSE; + char gotsep = 0; + int p; + DisplayModePtr mode1 = NULL; + DisplayModePtr mode2 = NULL; + DisplayModePtr result = NULL; + int myslen; + + do { + switch(*str) { + case 0: + case '-': + case '+': + case ' ': + case ',': + case ';': + if(strmode != str) { + + myslen = str - strmode; + if(myslen > 255) myslen = 255; + strncpy(modename, strmode, myslen); + modename[myslen] = 0; + + if(gotdash) { + if(mode1 == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Error parsing MetaModes parameter\n"); + return NULL; + } + mode2 = I830GetModeFromName(modename, j); + if(!mode2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for Second\n", modename); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); + mode1 = NULL; + gotsep = 0; + } + } else { + mode1 = I830GetModeFromName(modename, i); + if(!mode1) { + char* tmps = str; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for First\n", modename); + while(*tmps == ' ' || *tmps == ';') tmps++; + /* skip the next mode */ + if(*tmps == '-' || *tmps == '+' || *tmps == ',') { + tmps++; + /* skip spaces */ + while(*tmps == ' ' || *tmps == ';') tmps++; + /* skip modename */ + while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; + myslen = tmps - strmode; + if(myslen > 255) myslen = 255; + strncpy(modename,strmode,myslen); + modename[myslen] = 0; + str = tmps - 1; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s\")\n", modename); + mode1 = NULL; + gotsep = 0; + } + } + gotdash = FALSE; + } + strmode = str + 1; + gotdash |= (*str == '-' || *str == '+' || *str == ','); + if (*str == '-' || *str == '+' || *str == ',') + gotsep = *str; + + if(*str != 0) break; + /* Fall through otherwise */ + + default: + if(!gotdash && mode1) { + p = pos ; + if(!mode2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for Second\n", mode1->name); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s\")\n", modename); + mode1 = NULL; + } else { + result = I830CopyModeNLink(pScrn, result, mode1, mode2, p); + mode1 = NULL; + mode2 = NULL; + } + gotsep = 0; + } + break; + + } + + } while(*(str++) != 0); + + return result; +} + +static DisplayModePtr +I830GenerateModeList(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + int pos) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if(str != NULL) { + return(I830GenerateModeListFromMetaModes(pScrn, str, i, j, pos)); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No MetaModes given, linking %s modes by default\n", + (pI830->NonRect ? + (((pos == PosLeftOf) || (pos == PosRightOf)) ? "widest" : "tallest") + : + (((pos == PosLeftOf) || (pos == PosRightOf)) ? "widest common" : "tallest common")) ); + return(I830GenerateModeListFromLargestModes(pScrn, i, j, pos)); + } +} + +static void +I830RecalcDefaultVirtualSize(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr mode, bmode; + int maxh, maxv; + static const char *str = "MergedFB: Virtual %s %d\n"; + static const char *errstr = "Virtual %s to small for given SecondPosition offset\n"; + + mode = bmode = pScrn->modes; + maxh = maxv = 0; + do { + if(mode->HDisplay > maxh) maxh = mode->HDisplay; + if(mode->VDisplay > maxv) maxv = mode->VDisplay; + mode = mode->next; + } while(mode != bmode); + + maxh += pI830->FirstXOffs + pI830->SecondXOffs; + maxv += pI830->FirstYOffs + pI830->SecondYOffs; + + if(!(pScrn->display->virtualX)) { + if(maxh > 4088) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Virtual width with SecondPosition offset beyond hardware specs\n"); + pI830->FirstXOffs = pI830->SecondXOffs = 0; + maxh -= (pI830->FirstXOffs + pI830->SecondXOffs); + } + pScrn->virtualX = maxh; + pScrn->displayWidth = maxh; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); + } else { + if(maxh < pScrn->display->virtualX) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); + pI830->FirstXOffs = pI830->SecondXOffs = 0; + } + } + + if(!(pScrn->display->virtualY)) { + pScrn->virtualY = maxv; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); + } else { + if(maxv < pScrn->display->virtualY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); + pI830->FirstYOffs = pI830->SecondYOffs = 0; + } + } +} + +#define SDMPTR(x) ((I830ModePrivatePtr)x->currentMode->Private)->merged +#define CDMPTR ((I830ModePrivatePtr)pI830->currentMode->Private)->merged + +#define BOUND(test,low,hi) \ + { \ + if((test) < (low)) (test) = (low); \ + if((test) > (hi)) (test) = (hi); \ + } + +#define REBOUND(low,hi,test) \ + { \ + if((test) < (low)) { \ + (hi) += (test)-(low); \ + (low) = (test); \ + } \ + if((test) > (hi)) { \ + (low) += (test)-(hi); \ + (hi) = (test); \ + } \ + } + + +static void +I830MergedPointerMoved(int scrnIndex, int x, int y) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn1); + ScrnInfoPtr pScrn2 = pI830->pScrn_2; + region out, in1, in2, f2, f1; + int deltax, deltay; + int temp1, temp2; + int old1x0, old1y0, old2x0, old2y0; + int FirstXOffs = 0, FirstYOffs = 0, SecondXOffs = 0, SecondYOffs = 0; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + int sigstate; + Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; + int pos = ((I830MergedDisplayModePtr)pI830->currentMode->Private)->SecondPosition; + + if(pI830->DGAactive) { + return; + /* DGA: There is no cursor and no panning while DGA is active. */ + } else { + FirstXOffs = pI830->FirstXOffs; + FirstYOffs = pI830->FirstYOffs; + SecondXOffs = pI830->SecondXOffs; + SecondYOffs = pI830->SecondYOffs; + HaveNonRect = pI830->HaveNonRect; + HaveOffsRegions = pI830->HaveOffsRegions; + } + + /* Check if the pointer is inside our dead areas */ + if((pI830->MouseRestrictions) && !I830noPanoramiXExtension) { + if(HaveNonRect) { + if(InRegion(x, y, pI830->NonRectDead)) { + switch(pos) { + case PosLeftOf: + case PosRightOf: y = pI830->NonRectDead.y0 - 1; + doit = TRUE; + break; + case PosAbove: + case PosBelow: x = pI830->NonRectDead.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(HaveOffsRegions) { + if(InRegion(x, y, pI830->OffDead1)) { + switch(pos) { + case PosLeftOf: + case PosRightOf: y = pI830->OffDead1.y1; + doit = TRUE; + break; + case PosAbove: + case PosBelow: x = pI830->OffDead1.x1; + doit = TRUE; + default: break; + } + } else if(InRegion(x, y, pI830->OffDead2)) { + switch(pos) { + case PosLeftOf: + case PosRightOf: y = pI830->OffDead2.y0 - 1; + doit = TRUE; + break; + case PosAbove: + case PosBelow: x = pI830->OffDead2.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(doit) { + UpdateCurrentTime(); + sigstate = xf86BlockSIGIO(); + miPointerAbsoluteCursor(x, y, currentTime.milliseconds); + xf86UnblockSIGIO(sigstate); + return; + } + } + + f1.x0 = old1x0 = pI830->FirstframeX0; + f1.x1 = pI830->FirstframeX1; + f1.y0 = old1y0 = pI830->FirstframeY0; + f1.y1 = pI830->FirstframeY1; + f2.x0 = old2x0 = pScrn2->frameX0; + f2.x1 = pScrn2->frameX1; + f2.y0 = old2y0 = pScrn2->frameY0; + f2.y1 = pScrn2->frameY1; + + /* Define the outer region. Crossing this causes all frames to move */ + out.x0 = pScrn1->frameX0; + out.x1 = pScrn1->frameX1; + out.y0 = pScrn1->frameY0; + out.y1 = pScrn1->frameY1; + + /* + * Define the inner sliding window. Being outsize both frames but + * inside the outer clipping window will slide corresponding frame + */ + in1 = out; + in2 = out; + switch(pos) { + case PosLeftOf: + in1.x0 = f1.x0; + in2.x1 = f2.x1; + break; + case PosRightOf: + in1.x1 = f1.x1; + in2.x0 = f2.x0; + break; + case PosBelow: + in1.y1 = f1.y1; + in2.y0 = f2.y0; + break; + case PosAbove: + in1.y0 = f1.y0; + in2.y1 = f2.y1; + break; + } + + deltay = 0; + deltax = 0; + + if(InRegion(x, y, out)) { /* inside outer region */ + + if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { + REBOUND(f1.x0, f1.x1, x); + REBOUND(f1.y0, f1.y1, y); + deltax = 1; + } + if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { + REBOUND(f2.x0, f2.x1, x); + REBOUND(f2.y0, f2.y1, y); + deltax = 1; + } + + } else { /* outside outer region */ + + if(out.x0 > x) { + deltax = x - out.x0; + } + if(out.x1 < x) { + deltax = x - out.x1; + } + if(deltax) { + pScrn1->frameX0 += deltax; + pScrn1->frameX1 += deltax; + f1.x0 += deltax; + f1.x1 += deltax; + f2.x0 += deltax; + f2.x1 += deltax; + } + + if(out.y0 > y) { + deltay = y - out.y0; + } + if(out.y1 < y) { + deltay = y - out.y1; + } + if(deltay) { + pScrn1->frameY0 += deltay; + pScrn1->frameY1 += deltay; + f1.y0 += deltay; + f1.y1 += deltay; + f2.y0 += deltay; + f2.y1 += deltay; + } + + switch(pos) { + case PosLeftOf: + if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } + if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } + break; + case PosRightOf: + if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } + if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } + break; + case PosBelow: + if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } + if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } + break; + case PosAbove: + if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } + if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } + break; + } + + } + + if(deltax || deltay) { + pI830->FirstframeX0 = f1.x0; + pI830->FirstframeY0 = f1.y0; + pScrn2->frameX0 = f2.x0; + pScrn2->frameY0 = f2.y0; + + switch(pos) { + case PosLeftOf: + case PosRightOf: + if(FirstYOffs || SecondYOffs || HaveNonRect) { + if(pI830->FirstframeY0 != old1y0) { + if(pI830->FirstframeY0 < FirstYOffs) + pI830->FirstframeY0 = FirstYOffs; + + temp1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay; + temp2 = min((VVirt - SecondYOffs), (FirstYOffs + pI830->MBXNR1YMAX)); + if(temp1 > temp2) + pI830->FirstframeY0 -= (temp1 - temp2); + } + if(pScrn2->frameY0 != old2y0) { + if(pScrn2->frameY0 < SecondYOffs) + pScrn2->frameY0 = SecondYOffs; + + temp1 = pScrn2->frameY0 + CDMPTR.Second->VDisplay; + temp2 = min((VVirt - FirstYOffs), (SecondYOffs + pI830->MBXNR2YMAX)); + if(temp1 > temp2) + pScrn2->frameY0 -= (temp1 - temp2); + } + } + break; + case PosBelow: + case PosAbove: + if(FirstXOffs || SecondXOffs || HaveNonRect) { + if(pI830->FirstframeX0 != old1x0) { + if(pI830->FirstframeX0 < FirstXOffs) + pI830->FirstframeX0 = FirstXOffs; + + temp1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay; + temp2 = min((HVirt - SecondXOffs), (FirstXOffs + pI830->MBXNR1XMAX)); + if(temp1 > temp2) + pI830->FirstframeX0 -= (temp1 - temp2); + } + if(pScrn2->frameX0 != old2x0) { + if(pScrn2->frameX0 < SecondXOffs) + pScrn2->frameX0 = SecondXOffs; + + temp1 = pScrn2->frameX0 + CDMPTR.Second->HDisplay; + temp2 = min((HVirt - FirstXOffs), (SecondXOffs + pI830->MBXNR2XMAX)); + if(temp1 > temp2) + pScrn2->frameX0 -= (temp1 - temp2); + } + } + break; + } + + pI830->FirstframeX1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay - 1; + pI830->FirstframeY1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR.Second->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR.Second->VDisplay - 1; + + /* No need to update pScrn1->frame?1, done above */ + if (pI830->pipe == 0) { + OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn1->displayWidth + pI830->FirstframeX0) * pI830->cpp)); + OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pScrn2->frameY0 * pScrn1->displayWidth + pScrn2->frameX0) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn1->displayWidth + pI830->FirstframeX0) * pI830->cpp)); + OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pScrn2->frameY0 * pScrn1->displayWidth + pScrn2->frameX0) * pI830->cpp)); + } + } +} + +static void +I830AdjustFrameMerged(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + I830Ptr pI830 = I830PTR(pScrn1); + ScrnInfoPtr pScrn2 = pI830->pScrn_2; + int HTotal = pI830->currentMode->HDisplay; + int VTotal = pI830->currentMode->VDisplay; + int HMax = HTotal; + int VMax = VTotal; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + int x1 = x, x2 = x; + int y1 = y, y2 = y; + int FirstXOffs = 0, FirstYOffs = 0, SecondXOffs = 0, SecondYOffs = 0; + int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; + + if(pI830->DGAactive) { + HVirt = pScrn1->displayWidth; + VVirt = pScrn1->virtualY; + } else { + FirstXOffs = pI830->FirstXOffs; + FirstYOffs = pI830->FirstYOffs; + SecondXOffs = pI830->SecondXOffs; + SecondYOffs = pI830->SecondYOffs; + MBXNR1XMAX = pI830->MBXNR1XMAX; + MBXNR1YMAX = pI830->MBXNR1YMAX; + MBXNR2XMAX = pI830->MBXNR2XMAX; + MBXNR2YMAX = pI830->MBXNR2YMAX; + } + + BOUND(x, 0, HVirt - HTotal); + BOUND(y, 0, VVirt - VTotal); + BOUND(x1, FirstXOffs, min(HVirt, MBXNR1XMAX + FirstXOffs) - min(HTotal, MBXNR1XMAX) - SecondXOffs); + BOUND(y1, FirstYOffs, min(VVirt, MBXNR1YMAX + FirstYOffs) - min(VTotal, MBXNR1YMAX) - SecondYOffs); + BOUND(x2, SecondXOffs, min(HVirt, MBXNR2XMAX + SecondXOffs) - min(HTotal, MBXNR2XMAX) - FirstXOffs); + BOUND(y2, SecondYOffs, min(VVirt, MBXNR2YMAX + SecondYOffs) - min(VTotal, MBXNR2YMAX) - FirstYOffs); + + switch(SDMPTR(pScrn1).SecondPosition) { + case PosLeftOf: + pScrn2->frameX0 = x2; + BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR.Second->VDisplay); + pI830->FirstframeX0 = x1 + CDMPTR.Second->HDisplay; + BOUND(pI830->FirstframeY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR.First->VDisplay); + break; + case PosRightOf: + pI830->FirstframeX0 = x1; + BOUND(pI830->FirstframeY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR.First->VDisplay); + pScrn2->frameX0 = x2 + CDMPTR.First->HDisplay; + BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR.Second->VDisplay); + break; + case PosAbove: + BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR.Second->HDisplay); + pScrn2->frameY0 = y2; + BOUND(pI830->FirstframeX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR.First->HDisplay); + pI830->FirstframeY0 = y1 + CDMPTR.Second->VDisplay; + break; + case PosBelow: + BOUND(pI830->FirstframeX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR.First->HDisplay); + pI830->FirstframeY0 = y1; + BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR.Second->HDisplay); + pScrn2->frameY0 = y2 + CDMPTR.First->VDisplay; + break; + } + + BOUND(pI830->FirstframeX0, 0, HVirt - CDMPTR.First->HDisplay); + BOUND(pI830->FirstframeY0, 0, VVirt - CDMPTR.First->VDisplay); + BOUND(pScrn2->frameX0, 0, HVirt - CDMPTR.Second->HDisplay); + BOUND(pScrn2->frameY0, 0, VVirt - CDMPTR.Second->VDisplay); + + pScrn1->frameX0 = x; + pScrn1->frameY0 = y; + + pI830->FirstframeX1 = pI830->FirstframeX0 + CDMPTR.First->HDisplay - 1; + pI830->FirstframeY1 = pI830->FirstframeY0 + CDMPTR.First->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR.Second->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR.Second->VDisplay - 1; + + pScrn1->frameX1 = pScrn1->frameX0 + pI830->currentMode->HDisplay - 1; + pScrn1->frameY1 = pScrn1->frameY0 + pI830->currentMode->VDisplay - 1; + pScrn1->frameX1 += FirstXOffs + SecondXOffs; + pScrn1->frameY1 += FirstYOffs + SecondYOffs; +} + +/* Pseudo-Xinerama extension for MergedFB mode */ +static void +I830UpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) +{ + I830Ptr pI830 = I830PTR(pScrn1); + int scrnnum1 = 0, scrnnum2 = 1; + int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; + int realvirtX, realvirtY; + DisplayModePtr currentMode, firstMode; + Bool infochanged = FALSE; + Bool usenonrect = pI830->NonRect; + const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; + + pI830->MBXNR1XMAX = pI830->MBXNR1YMAX = pI830->MBXNR2XMAX = pI830->MBXNR2YMAX = 65536; + pI830->HaveNonRect = pI830->HaveOffsRegions = FALSE; + + if(!pI830->MergedFB) return; + + if(I830noPanoramiXExtension) return; + + if(!I830XineramadataPtr) return; + + if(pI830->SecondIsScrn0) { + scrnnum1 = 1; + scrnnum2 = 0; + } + + /* Attention: Usage of RandR may lead to virtual X and Y dimensions + * actually smaller than our MetaModes. To avoid this, we calculate + * the max* fields here (and not somewhere else, like in CopyNLink) + * + * *** Note: RandR is disabled if one of CRTxxOffs is non-zero. + */ + + /* "Real" virtual: Virtual without the Offset */ + realvirtX = pScrn1->virtualX - pI830->FirstXOffs - pI830->SecondXOffs; + realvirtY = pScrn1->virtualY - pI830->FirstYOffs - pI830->SecondYOffs; + + if((pI830->I830XineramaVX != pScrn1->virtualX) || (pI830->I830XineramaVY != pScrn1->virtualY)) { + + if(!(pScrn1->modes)) return; + + pI830->maxFirst_X1 = pI830->maxFirst_X2 = 0; + pI830->maxFirst_Y1 = pI830->maxFirst_Y2 = 0; + pI830->maxSecond_X1 = pI830->maxSecond_X2 = 0; + pI830->maxSecond_Y1 = pI830->maxSecond_Y2 = 0; + + currentMode = firstMode = pScrn1->modes; + + do { + + DisplayModePtr p = currentMode->next; + DisplayModePtr i = ((I830ModePrivatePtr)currentMode->Private)->merged.First; + DisplayModePtr j = ((I830ModePrivatePtr)currentMode->Private)->merged.Second; + + if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && + (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && + (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { + + if(pI830->maxFirst_X1 == i->HDisplay) { + if(pI830->maxFirst_X2 < j->HDisplay) { + pI830->maxFirst_X2 = j->HDisplay; /* Widest Second mode displayed with widest CRT1 mode */ + } + } else if(pI830->maxFirst_X1 < i->HDisplay) { + pI830->maxFirst_X1 = i->HDisplay; /* Widest CRT1 mode */ + pI830->maxFirst_X2 = j->HDisplay; + } + if(pI830->maxSecond_X2 == j->HDisplay) { + if(pI830->maxSecond_X1 < i->HDisplay) { + pI830->maxSecond_X1 = i->HDisplay; /* Widest First mode displayed with widest Second mode */ + } + } else if(pI830->maxSecond_X2 < j->HDisplay) { + pI830->maxSecond_X2 = j->HDisplay; /* Widest Second mode */ + pI830->maxSecond_X1 = i->HDisplay; + } + if(pI830->maxFirst_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ + if(pI830->maxFirst_Y2 < j->VDisplay) { + pI830->maxFirst_Y2 = j->VDisplay; + } + } else if(pI830->maxFirst_Y1 < i->VDisplay) { + pI830->maxFirst_Y1 = i->VDisplay; + pI830->maxFirst_Y2 = j->VDisplay; + } + if(pI830->maxSecond_Y2 == j->VDisplay) { + if(pI830->maxSecond_Y1 < i->VDisplay) { + pI830->maxSecond_Y1 = i->VDisplay; + } + } else if(pI830->maxSecond_Y2 < j->VDisplay) { + pI830->maxSecond_Y2 = j->VDisplay; + pI830->maxSecond_Y1 = i->VDisplay; + } + } + currentMode = p; + + } while((currentMode) && (currentMode != firstMode)); + + pI830->I830XineramaVX = pScrn1->virtualX; + pI830->I830XineramaVY = pScrn1->virtualY; + infochanged = TRUE; + + } + + if((usenonrect) && pI830->maxFirst_X1) { + switch(pI830->SecondPosition) { + case PosLeftOf: + case PosRightOf: + if((pI830->maxFirst_Y1 != realvirtY) && (pI830->maxSecond_Y2 != realvirtY)) { + usenonrect = FALSE; + } + break; + case PosAbove: + case PosBelow: + if((pI830->maxFirst_X1 != realvirtX) && (pI830->maxSecond_X2 != realvirtX)) { + usenonrect = FALSE; + } + break; + } + if(infochanged && !usenonrect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Virtual screen size does not match maximum display modes...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + + } + } else if(infochanged && usenonrect) { + usenonrect = FALSE; + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Only clone modes available for this virtual screen size...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + } + + if(pI830->maxFirst_X1) { /* Means we have at least one non-clone mode */ + switch(pI830->SecondPosition) { + case PosLeftOf: + x1 = min(pI830->maxFirst_X2, pScrn1->virtualX - pI830->maxFirst_X1); + if(x1 < 0) x1 = 0; + y1 = pI830->FirstYOffs; + w1 = pScrn1->virtualX - x1; + h1 = realvirtY; + if((usenonrect) && (pI830->maxFirst_Y1 != realvirtY)) { + h1 = pI830->MBXNR1YMAX = pI830->maxFirst_Y1; + pI830->NonRectDead.x0 = x1; + pI830->NonRectDead.x1 = x1 + w1 - 1; + pI830->NonRectDead.y0 = y1 + h1; + pI830->NonRectDead.y1 = pScrn1->virtualY - 1; + pI830->HaveNonRect = TRUE; + } + x2 = 0; + y2 = pI830->SecondYOffs; + w2 = max(pI830->maxSecond_X2, pScrn1->virtualX - pI830->maxSecond_X1); + if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; + h2 = realvirtY; + if((usenonrect) && (pI830->maxSecond_Y2 != realvirtY)) { + h2 = pI830->MBXNR2YMAX = pI830->maxSecond_Y2; + pI830->NonRectDead.x0 = x2; + pI830->NonRectDead.x1 = x2 + w2 - 1; + pI830->NonRectDead.y0 = y2 + h2; + pI830->NonRectDead.y1 = pScrn1->virtualY - 1; + pI830->HaveNonRect = TRUE; + } + break; + case PosRightOf: + x1 = 0; + y1 = pI830->FirstYOffs; + w1 = max(pI830->maxFirst_X1, pScrn1->virtualX - pI830->maxFirst_X2); + if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; + h1 = realvirtY; + if((usenonrect) && (pI830->maxFirst_Y1 != realvirtY)) { + h1 = pI830->MBXNR1YMAX = pI830->maxFirst_Y1; + pI830->NonRectDead.x0 = x1; + pI830->NonRectDead.x1 = x1 + w1 - 1; + pI830->NonRectDead.y0 = y1 + h1; + pI830->NonRectDead.y1 = pScrn1->virtualY - 1; + pI830->HaveNonRect = TRUE; + } + x2 = min(pI830->maxSecond_X1, pScrn1->virtualX - pI830->maxSecond_X2); + if(x2 < 0) x2 = 0; + y2 = pI830->SecondYOffs; + w2 = pScrn1->virtualX - x2; + h2 = realvirtY; + if((usenonrect) && (pI830->maxSecond_Y2 != realvirtY)) { + h2 = pI830->MBXNR2YMAX = pI830->maxSecond_Y2; + pI830->NonRectDead.x0 = x2; + pI830->NonRectDead.x1 = x2 + w2 - 1; + pI830->NonRectDead.y0 = y2 + h2; + pI830->NonRectDead.y1 = pScrn1->virtualY - 1; + pI830->HaveNonRect = TRUE; + } + break; + case PosAbove: + x1 = pI830->FirstXOffs; + y1 = min(pI830->maxFirst_Y2, pScrn1->virtualY - pI830->maxFirst_Y1); + if(y1 < 0) y1 = 0; + w1 = realvirtX; + h1 = pScrn1->virtualY - y1; + if((usenonrect) && (pI830->maxFirst_X1 != realvirtX)) { + w1 = pI830->MBXNR1XMAX = pI830->maxFirst_X1; + pI830->NonRectDead.x0 = x1 + w1; + pI830->NonRectDead.x1 = pScrn1->virtualX - 1; + pI830->NonRectDead.y0 = y1; + pI830->NonRectDead.y1 = y1 + h1 - 1; + pI830->HaveNonRect = TRUE; + } + x2 = pI830->SecondXOffs; + y2 = 0; + w2 = realvirtX; + h2 = max(pI830->maxSecond_Y2, pScrn1->virtualY - pI830->maxSecond_Y1); + if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; + if((usenonrect) && (pI830->maxSecond_X2 != realvirtX)) { + w2 = pI830->MBXNR2XMAX = pI830->maxSecond_X2; + pI830->NonRectDead.x0 = x2 + w2; + pI830->NonRectDead.x1 = pScrn1->virtualX - 1; + pI830->NonRectDead.y0 = y2; + pI830->NonRectDead.y1 = y2 + h2 - 1; + pI830->HaveNonRect = TRUE; + } + break; + case PosBelow: + x1 = pI830->FirstXOffs; + y1 = 0; + w1 = realvirtX; + h1 = max(pI830->maxFirst_Y1, pScrn1->virtualY - pI830->maxFirst_Y2); + if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; + if((usenonrect) && (pI830->maxFirst_X1 != realvirtX)) { + w1 = pI830->MBXNR1XMAX = pI830->maxFirst_X1; + pI830->NonRectDead.x0 = x1 + w1; + pI830->NonRectDead.x1 = pScrn1->virtualX - 1; + pI830->NonRectDead.y0 = y1; + pI830->NonRectDead.y1 = y1 + h1 - 1; + pI830->HaveNonRect = TRUE; + } + x2 = pI830->SecondXOffs; + y2 = min(pI830->maxSecond_Y1, pScrn1->virtualY - pI830->maxSecond_Y2); + if(y2 < 0) y2 = 0; + w2 = realvirtX; + h2 = pScrn1->virtualY - y2; + if((usenonrect) && (pI830->maxSecond_X2 != realvirtX)) { + w2 = pI830->MBXNR2XMAX = pI830->maxSecond_X2; + pI830->NonRectDead.x0 = x2 + w2; + pI830->NonRectDead.x1 = pScrn1->virtualX - 1; + pI830->NonRectDead.y0 = y2; + pI830->NonRectDead.y1 = y2 + h2 - 1; + pI830->HaveNonRect = TRUE; + } + default: + break; + } + + switch(pI830->SecondPosition) { + case PosLeftOf: + case PosRightOf: + if(pI830->FirstYOffs) { + pI830->OffDead1.x0 = x1; + pI830->OffDead1.x1 = x1 + w1 - 1; + pI830->OffDead1.y0 = 0; + pI830->OffDead1.y1 = y1 - 1; + pI830->OffDead2.x0 = x2; + pI830->OffDead2.x1 = x2 + w2 - 1; + pI830->OffDead2.y0 = y2 + h2; + pI830->OffDead2.y1 = pScrn1->virtualY - 1; + pI830->HaveOffsRegions = TRUE; + } else if(pI830->SecondYOffs) { + pI830->OffDead1.x0 = x2; + pI830->OffDead1.x1 = x2 + w2 - 1; + pI830->OffDead1.y0 = 0; + pI830->OffDead1.y1 = y2 - 1; + pI830->OffDead2.x0 = x1; + pI830->OffDead2.x1 = x1 + w1 - 1; + pI830->OffDead2.y0 = y1 + h1; + pI830->OffDead2.y1 = pScrn1->virtualY - 1; + pI830->HaveOffsRegions = TRUE; + } + break; + case PosAbove: + case PosBelow: + if(pI830->FirstXOffs) { + pI830->OffDead1.x0 = x2 + w2; + pI830->OffDead1.x1 = pScrn1->virtualX - 1; + pI830->OffDead1.y0 = y2; + pI830->OffDead1.y1 = y2 + h2 - 1; + pI830->OffDead2.x0 = 0; + pI830->OffDead2.x1 = x1 - 1; + pI830->OffDead2.y0 = y1; + pI830->OffDead2.y1 = y1 + h1 - 1; + pI830->HaveOffsRegions = TRUE; + } else if(pI830->SecondXOffs) { + pI830->OffDead1.x0 = x1 + w1; + pI830->OffDead1.x1 = pScrn1->virtualX - 1; + pI830->OffDead1.y0 = y1; + pI830->OffDead1.y1 = y1 + h1 - 1; + pI830->OffDead2.x0 = 0; + pI830->OffDead2.x1 = x2 - 1; + pI830->OffDead2.y0 = y2; + pI830->OffDead2.y1 = y2 + h2 - 1; + pI830->HaveOffsRegions = TRUE; + } + default: + break; + } + + } + + I830XineramadataPtr[scrnnum1].x = x1; + I830XineramadataPtr[scrnnum1].y = y1; + I830XineramadataPtr[scrnnum1].width = w1; + I830XineramadataPtr[scrnnum1].height = h1; + I830XineramadataPtr[scrnnum2].x = x2; + I830XineramadataPtr[scrnnum2].y = y2; + I830XineramadataPtr[scrnnum2].width = w2; + I830XineramadataPtr[scrnnum2].height = h2; + + if(infochanged) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: First (Screen %d) (%d,%d)-(%d,%d)\n", + scrnnum1, x1, y1, w1+x1-1, h1+y1-1); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Second (Screen %d) (%d,%d)-(%d,%d)\n", + scrnnum2, x2, y2, w2+x2-1, h2+y2-1); + if(pI830->HaveNonRect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", + pI830->NonRectDead.x0, pI830->NonRectDead.y0, + pI830->NonRectDead.x1, pI830->NonRectDead.y1); + } + if(pI830->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + pI830->OffDead1.x0, pI830->OffDead1.y0, + pI830->OffDead1.x1, pI830->OffDead1.y1); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + pI830->OffDead2.x0, pI830->OffDead2.y0, + pI830->OffDead2.x1, pI830->OffDead2.y1); + } + if(pI830->HaveNonRect || pI830->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Mouse restriction for inaccessible areas is %s\n", + pI830->MouseRestrictions ? "enabled" : "disabled"); + } + } +} + +/* Proc */ + +int +I830ProcXineramaQueryVersion(ClientPtr client) +{ + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = 1; + rep.minorVersion = 0; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +I830ProcXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + pWin = LookupWindow(stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !I830noPanoramiXExtension; + if(client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.state, n); + } + WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); + return client->noClientException; +} + +int +I830ProcXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + pWin = LookupWindow(stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = I830XineramaNumScreens; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.ScreenCount, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); + return client->noClientException; +} + +int +I830ProcXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + pWin = LookupWindow (stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.width = I830XineramadataPtr[stuff->screen].width; + rep.height = I830XineramadataPtr[stuff->screen].height; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); + return client->noClientException; +} + +int +I830ProcXineramaIsActive(ClientPtr client) +{ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !I830noPanoramiXExtension; + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.state, n); + } + WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); + return client->noClientException; +} + +int +I830ProcXineramaQueryScreens(ClientPtr client) +{ + xXineramaQueryScreensReply rep; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = (I830noPanoramiXExtension) ? 0 : I830XineramaNumScreens; + rep.length = rep.number * sz_XineramaScreenInfo >> 2; + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.number, n); + } + WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); + + if(!I830noPanoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < I830XineramaNumScreens; i++) { + scratch.x_org = I830XineramadataPtr[i].x; + scratch.y_org = I830XineramadataPtr[i].y; + scratch.width = I830XineramadataPtr[i].width; + scratch.height = I830XineramadataPtr[i].height; + if(client->swapped) { + register int n; + swaps(&scratch.x_org, n); + swaps(&scratch.y_org, n); + swaps(&scratch.width, n); + swaps(&scratch.height, n); + } + WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); + } + } + + return client->noClientException; +} + +static int +I830ProcXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return I830ProcXineramaQueryVersion(client); + case X_PanoramiXGetState: + return I830ProcXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return I830ProcXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return I830ProcXineramaGetScreenSize(client); + case X_XineramaIsActive: + return I830ProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return I830ProcXineramaQueryScreens(client); + } + return BadRequest; +} + +/* SProc */ + +static int +I830SProcXineramaQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return I830ProcXineramaQueryVersion(client); +} + +static int +I830SProcXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return I830ProcXineramaGetState(client); +} + +static int +I830SProcXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return I830ProcXineramaGetScreenCount(client); +} + +static int +I830SProcXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return I830ProcXineramaGetScreenSize(client); +} + +static int +I830SProcXineramaIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return I830ProcXineramaIsActive(client); +} + +static int +I830SProcXineramaQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return I830ProcXineramaQueryScreens(client); +} + +int +I830SProcXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return I830SProcXineramaQueryVersion(client); + case X_PanoramiXGetState: + return I830SProcXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return I830SProcXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return I830SProcXineramaGetScreenSize(client); + case X_XineramaIsActive: + return I830SProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return I830SProcXineramaQueryScreens(client); + } + return BadRequest; +} + +static void +I830XineramaResetProc(ExtensionEntry* extEntry) +{ + /* Called by CloseDownExtensions() */ + if(I830XineramadataPtr) { + Xfree(I830XineramadataPtr); + I830XineramadataPtr = NULL; + } +} + +static void +I830XineramaExtensionInit(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + Bool success = FALSE; + + if(!(I830XineramadataPtr)) { + + if(!pI830->MergedFB) { + I830noPanoramiXExtension = TRUE; + pI830->MouseRestrictions = FALSE; + return; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Xinerama active, not initializing Intel Pseudo-Xinerama\n"); + I830noPanoramiXExtension = TRUE; + pI830->MouseRestrictions = FALSE; + return; + } +#endif + + if(I830noPanoramiXExtension) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Intel Pseudo-Xinerama disabled\n"); + pI830->MouseRestrictions = FALSE; + return; + } + + I830XineramaNumScreens = 2; + + while(I830XineramaGeneration != serverGeneration) { + + pI830->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + I830ProcXineramaDispatch, + I830SProcXineramaDispatch, + I830XineramaResetProc, + StandardMinorOpcode); + + if(!pI830->XineramaExtEntry) break; + + if(!(I830XineramadataPtr = (I830XineramaData *) + xcalloc(I830XineramaNumScreens, sizeof(I830XineramaData)))) break; + + I830XineramaGeneration = serverGeneration; + success = TRUE; + } + + if(!success) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to initialize Intel Pseudo-Xinerama extension\n"); + I830noPanoramiXExtension = TRUE; + pI830->MouseRestrictions = FALSE; + return; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Intel Pseudo-Xinerama extension initialized\n"); + + pI830->I830XineramaVX = 0; + pI830->I830XineramaVY = 0; + + } + + I830UpdateXineramaScreenInfo(pScrn); + +} + static void I830BIOSProbeDDC(ScrnInfoPtr pScrn, int index) { @@ -489,7 +2125,7 @@ GetNextDisplayDeviceList(ScrnInfoPtr pScrn, int toggle) CARD32 VODA = (CARD32)((CARD32*)pVbe->memory)[i]; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Next ACPI _DGS [%d] 0x%lx\n", - i, (unsigned long) VODA); + i, VODA); /* Check if it's a custom Video Output Device Attribute */ if (!(VODA & 0x80000000)) @@ -546,8 +2182,7 @@ GetAttachableDisplayDeviceList(ScrnInfoPtr pScrn) for (i=0; i<(pVbe->pInt10->cx & 0xff); i++) xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attachable device 0x%lx.\n", - (unsigned long) ((CARD32*)pVbe->memory)[i]); + "Attachable device 0x%lx.\n", ((CARD32*)pVbe->memory)[i]); return pVbe->pInt10->cx & 0xffff; } @@ -944,7 +2579,7 @@ SetPipeAccess(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); /* Don't try messing with the pipe, unless we're dual head */ - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->origPipe != pI830->pipe) { + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || pI830->MergedFB || pI830->origPipe != pI830->pipe) { if (!SetBIOSPipe(pScrn, pI830->pipe)) return FALSE; } @@ -969,10 +2604,12 @@ I830Set640x480(ScrnInfoPtr pScrn) m = 0x50; break; } + m |= (1 << 15) | (1 << 14); if (VBESetVBEMode(pI830->pVbe, m, NULL)) return TRUE; + /* if the first failed, let's try the next - usually 800x600 */ m = 0x32; switch (pScrn->depth) { @@ -985,6 +2622,7 @@ I830Set640x480(ScrnInfoPtr pScrn) break; } m |= (1 << 15) | (1 << 14); + if (VBESetVBEMode(pI830->pVbe, m, NULL)) return TRUE; @@ -1089,7 +2727,7 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices) } /* LVDS doesn't exist on these */ - if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830)) + if (IS_I830(pI830) || IS_845G(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I945G(pI830) || IS_I965G(pI830)) singlepipe &= ~(PIPE_LFP | (PIPE_LFP<<8)); if (pI830->availablePipes == 1) @@ -1280,7 +2918,7 @@ static const char *displayDevices[] = { "TV", "DFP (digital flat panel)", "LFP (local flat panel)", - "CRT2 (second CRT)", + "Second (second CRT)", "TV2 (second TV)", "DFP2 (second digital flat panel)", "LFP2 (second local flat panel)", @@ -1459,8 +3097,11 @@ I830DetectMemory(ScrnInfoPtr pScrn) gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); /* We need to reduce the stolen size, by the GTT and the popup. - * The GTT varying according the the FbMapSize and the popup is 4KB */ - range = (pI830->FbMapSize / (1024*1024)) + 4; + * The GTT varying according the the FbMapSize and the popup is 4KB. */ + if (IS_I965G(pI830)) + range = 512 + 4; /* Fixed 512KB size for i965 */ + else + range = (pI830->FbMapSize / MB(1)) + 4; if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { @@ -1506,6 +3147,12 @@ I830DetectMemory(ScrnInfoPtr pScrn) break; } } + +#if 0 + /* And 64KB page aligned */ + memsize &= ~0xFFFF; +#endif + if (memsize > 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB stolen memory.\n", memsize / 1024); @@ -1877,19 +3524,94 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, unsigned char r, g, b; CARD32 val, temp; int palreg; - int dspreg, dspbase; + int dspreg, dspbase, dspsurf; DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); + if (pI830->Clone || pI830->MergedFB) { + if (!pI830->pipe == 0) { + palreg = PALETTE_A; + dspreg = DSPACNTR; + dspbase = DSPABASE; + } else { + palreg = PALETTE_B; + dspreg = DSPBCNTR; + dspbase = DSPBBASE; + } + + /* To ensure gamma is enabled we need to turn off and on the plane */ + temp = INREG(dspreg); + OUTREG(dspreg, temp & ~(1<<31)); + OUTREG(dspbase, INREG(dspbase)); + OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); + OUTREG(dspbase, INREG(dspbase)); + + /* It seems that an initial read is needed. */ + temp = INREG(palreg); + + switch(pScrn->depth) { + case 15: + for (i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index].red; + g = colors[index].green; + b = colors[index].blue; + val = (r << 16) | (g << 8) | b; + for (j = 0; j < 8; j++) { + OUTREG(palreg + index * 32 + (j * 4), val); + } + } + break; + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index / 2].red; + g = colors[index].green; + b = colors[index / 2].blue; + + val = (r << 16) | (g << 8) | b; + OUTREG(palreg + index * 16, val); + OUTREG(palreg + index * 16 + 4, val); + OUTREG(palreg + index * 16 + 8, val); + OUTREG(palreg + index * 16 + 12, val); + + if (index <= 31) { + r = colors[index].red; + g = colors[(index * 2) + 1].green; + b = colors[index].blue; + + val = (r << 16) | (g << 8) | b; + OUTREG(palreg + index * 32, val); + OUTREG(palreg + index * 32 + 4, val); + OUTREG(palreg + index * 32 + 8, val); + OUTREG(palreg + index * 32 + 12, val); + } + } + break; + default: + for(i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index].red; + g = colors[index].green; + b = colors[index].blue; + val = (r << 16) | (g << 8) | b; + OUTREG(palreg + index * 4, val); + } + break; + } + } + if (pI830->pipe == 0) { palreg = PALETTE_A; dspreg = DSPACNTR; dspbase = DSPABASE; + dspsurf = DSPASURF; } else { palreg = PALETTE_B; dspreg = DSPBCNTR; dspbase = DSPBBASE; + dspsurf = DSPBSURF; } /* To ensure gamma is enabled we need to turn off and on the plane */ @@ -1898,6 +3620,8 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, OUTREG(dspbase, INREG(dspbase)); OUTREG(dspreg, temp | DISPPLANE_GAMMA_ENABLE); OUTREG(dspbase, INREG(dspbase)); + if (IS_I965G(pI830)) + OUTREG(dspsurf, INREG(dspsurf)); /* It seems that an initial read is needed. */ temp = INREG(palreg); @@ -2109,9 +3833,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) int flags24; int defmon = 0; int i, n; - int DDCclock = 0; + int DDCclock = 0, DDCclock2 = 0; char *s; DisplayModePtr p, pMon; + xf86MonPtr monitor = NULL; pointer pDDCModule = NULL, pVBEModule = NULL; Bool enable; const char *chipname; @@ -2305,6 +4030,16 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) case PCI_CHIP_I945_GM: chipname = "945GM"; break; + case PCI_CHIP_I965_G: + case PCI_CHIP_I965_G_1: + chipname = "965G"; + break; + case PCI_CHIP_I965_Q: + chipname = "965Q"; + break; + case PCI_CHIP_I946_GZ: + chipname = "946GZ"; + break; default: chipname = "unknown chipset"; break; @@ -2545,8 +4280,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->LinearAlloc = 0; if (xf86GetOptValInteger(pI830->Options, OPTION_LINEARALLOC, &(pI830->LinearAlloc))) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n", + if (pI830->LinearAlloc > 0) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Allocating %dKbytes of memory\n", pI830->LinearAlloc); + else + pI830->LinearAlloc = 0; } pI830->fixedPipe = -1; @@ -2559,6 +4297,12 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->fixedPipe = 1; } + pI830->MergedFB = + xf86ReturnOptValBool(pI830->Options, OPTION_MERGEDFB, FALSE); + + pI830->IntelXinerama = + xf86ReturnOptValBool(pI830->Options, OPTION_INTELXINERAMA, TRUE); + pI830->MonType1 = PIPE_NONE; pI830->MonType2 = PIPE_NONE; pI830->specifiedMonitor = FALSE; @@ -2585,7 +4329,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType1 |= PIPE_DFP; else if (strcmp(sub, "LFP") == 0) pI830->MonType1 |= PIPE_LFP; - else if (strcmp(sub, "CRT2") == 0) + else if (strcmp(sub, "Second") == 0) pI830->MonType1 |= PIPE_CRT2; else if (strcmp(sub, "TV2") == 0) pI830->MonType1 |= PIPE_TV2; @@ -2614,7 +4358,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MonType2 |= PIPE_DFP; else if (strcmp(sub, "LFP") == 0) pI830->MonType2 |= PIPE_LFP; - else if (strcmp(sub, "CRT2") == 0) + else if (strcmp(sub, "Second") == 0) pI830->MonType2 |= PIPE_CRT2; else if (strcmp(sub, "TV2") == 0) pI830->MonType2 |= PIPE_TV2; @@ -2645,7 +4389,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->specifiedMonitor = TRUE; } - if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { + if (!pI830->MergedFB && + xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { if (pI830->availablePipes == 1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Can't enable Clone Mode because this is a single pipe device\n"); @@ -2676,17 +4421,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone) { + if ((pI830->entityPrivate && I830IsPrimary(pScrn)) || pI830->Clone || + pI830->MergedFB) { if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout " - "defined for use in a DualHead or Clone setup.\n"); + "defined for use in a DualHead, Clone or MergedFB setup.\n"); PreInitCleanup(pScrn); return FALSE; } if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 " - "cannot be type NONE in Dual or Clone setup.\n"); + "cannot be type NONE in DualHead, Clone or MergedFB setup.\n"); PreInitCleanup(pScrn); return FALSE; } @@ -2706,7 +4452,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* * Let's setup the mobile systems to check the lid status */ - if (IS_MOBILE(pI830)) { + if (IS_MOBILE(pI830) && !pI830->MergedFB) { pI830->checkDevices = TRUE; if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKDEVICES, TRUE)) { @@ -2914,6 +4660,80 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + if (pI830->MergedFB) { + pI830->pScrn_2 = xalloc(sizeof(ScrnInfoRec)); + + if(!pI830->pScrn_2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to allocate memory for MergedFB mode. Disabling.\n"); + pI830->MergedFB = FALSE; + } else { + memcpy(pI830->pScrn_2, pScrn, sizeof(ScrnInfoRec)); + } + if((s = (char *)xf86GetOptValString(pI830->Options, OPTION_SECONDPOSITION))) { + int result; + int ival; + Bool valid = FALSE; + char *tempstr = xalloc(strlen(s) + 1); + result = sscanf(s, "%s %d", tempstr, &ival); + if(result >= 1) { + if(!xf86NameCmp(tempstr,"LeftOf")) { + pI830->SecondPosition = PosLeftOf; + valid = TRUE; + if(result == 2) { + if(ival < 0) pI830->FirstYOffs = -ival; + else pI830->SecondYOffs = ival; + } + pI830->SecondIsScrn0 = TRUE; + } else if(!xf86NameCmp(tempstr,"RightOf")) { + pI830->SecondPosition = PosRightOf; + valid = TRUE; + if(result == 2) { + if(ival < 0) pI830->FirstYOffs = -ival; + else pI830->SecondYOffs = ival; + } + pI830->SecondIsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Above")) { + pI830->SecondPosition = PosAbove; + valid = TRUE; + if(result == 2) { + if(ival < 0) pI830->FirstXOffs = -ival; + else pI830->SecondXOffs = ival; + } + pI830->SecondIsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Below")) { + pI830->SecondPosition = PosBelow; + valid = TRUE; + if(result == 2) { + if(ival < 0) pI830->FirstXOffs = -ival; + else pI830->SecondXOffs = ival; + } + pI830->SecondIsScrn0 = TRUE; + } + } + if(!valid) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are: \"RightOf\", \"LeftOf\", \"Above\" or \"Below\"\n"); + } + xfree(tempstr); + } + if((s = (char *)xf86GetOptValString(pI830->Options, OPTION_METAMODES))) { + pI830->MetaModes = xalloc(strlen(s) + 1); + if(pI830->MetaModes) + memcpy(pI830->MetaModes, s, strlen(s) + 1); + } + if((s = (char *)xf86GetOptValString(pI830->Options, OPTION_SECONDHSYNC))) { + pI830->SecondHSync = xalloc(strlen(s) + 1); + if(pI830->SecondHSync) + memcpy(pI830->SecondHSync, s, strlen(s) + 1); + } + if((s = (char *)xf86GetOptValString(pI830->Options, OPTION_SECONDVREFRESH))) { + pI830->SecondVRefresh = xalloc(strlen(s) + 1); + if(pI830->SecondVRefresh) + memcpy(pI830->SecondVRefresh, s, strlen(s) + 1); + } + } + + /* * If the driver can do gamma correction, it should call xf86SetGamma() here. */ @@ -2962,7 +4782,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * or, at least it's meant to..... alas it doesn't seem to always work. */ if (pI830->devicePresence) { - int req=0, att=0, enc=0; + int req, att, enc; GetDevicePresence(pScrn, &req, &att, &enc); for (i = 0; i < NumDisplayTypes; i++) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2981,7 +4801,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* Override */ if (pI830->fixedPipe != -1) { - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || + pI830->MergedFB) { pI830->pipe = pI830->fixedPipe; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fixed Pipe setting primary to pipe %s.\n", @@ -3003,9 +4824,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; - if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone) { - /* If we're not dual head or clone, turn off the second head, - * if monitorlayout is also specified. */ + if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone && + !pI830->MergedFB) { + /* If we're not dual head, clone or mergedfb, turn off the + * second head if monitorlayout is also specified. + */ if (pI830->pipe == 0) pI830->operatingDevices = pI830->MonType1; @@ -3108,6 +4931,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) else pI830->CursorNeedsPhysical = FALSE; + if (IS_I965G(pI830)) + pI830->CursorNeedsPhysical = FALSE; + /* Force ring buffer to be in low memory for all chipsets */ pI830->NeedRingBufferLow = TRUE; @@ -3157,12 +4983,74 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pDDCModule = xf86LoadSubModule(pScrn, "ddc"); - pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule); - - if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) { - xf86PrintEDID(pI830->vesa->monitor); - xf86SetDDCproperties(pScrn, pI830->vesa->monitor); + monitor = vbeDoEDID(pI830->pVbe, pDDCModule); + + if ((pScrn->monitor->DDC = monitor) != NULL) { + xf86PrintEDID(monitor); + xf86SetDDCproperties(pScrn, monitor); + } + + if(pI830->MergedFB) { + pI830->pScrn_2->monitor = xalloc(sizeof(MonRec)); + if(pI830->pScrn_2->monitor) { + DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; + memcpy(pI830->pScrn_2->monitor, pScrn->monitor, sizeof(MonRec)); + pI830->pScrn_2->monitor->DDC = NULL; + pI830->pScrn_2->monitor->Modes = NULL; + pI830->pScrn_2->monitor->id = (char *)SecondMonitorName; + tempm = pScrn->monitor->Modes; + while(tempm) { + if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; + memcpy(newm, tempm, sizeof(DisplayModeRec)); + if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { + xfree(newm); + break; + } + strcpy(newm->name, tempm->name); + if(!pI830->pScrn_2->monitor->Modes) + pI830->pScrn_2->monitor->Modes = newm; + if(currentm) { + currentm->next = newm; + newm->prev = currentm; + } + currentm = newm; + tempm = tempm->next; + } + if(pI830->SecondHSync) { + pI830->pScrn_2->monitor->nHsync = + I830StrToRanges(pI830->pScrn_2->monitor->hsync, pI830->SecondHSync, MAX_HSYNC); + } + if(pI830->SecondVRefresh) { + pI830->pScrn_2->monitor->nVrefresh = + I830StrToRanges(pI830->pScrn_2->monitor->vrefresh, pI830->SecondVRefresh, MAX_VREFRESH); + } + SetBIOSPipe(pScrn, !pI830->pipe); + pI830->pVbe->ddc = DDC_UNCHECKED; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Probing DDC data for second head\n"); + if((monitor = vbeDoEDID(pI830->pVbe, pDDCModule))) { + xf86PrintEDID(monitor); + xf86SetDDCproperties(pI830->pScrn_2, monitor); + pI830->pScrn_2->monitor->DDC = monitor; + /* use DDC data if no ranges in config file */ + if(!pI830->SecondHSync) { + pI830->pScrn_2->monitor->nHsync = 0; + } + if(!pI830->SecondVRefresh) { + pI830->pScrn_2->monitor->nVrefresh = 0; + } + } + SetPipeAccess(pScrn); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for second monitor.\n"); + if(pI830->pScrn_2) + xfree(pI830->pScrn_2); + pI830->pScrn_2 = NULL; + pI830->MergedFB = FALSE; + } } + xf86UnloadSubModule(pDDCModule); /* XXX Move this to a header. */ @@ -3189,7 +5077,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->useExtendedRefresh = FALSE; - if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone || + pI830->MergedFB) { int pipe = (pI830->operatingDevices >> PIPE_SHIFT(pI830->pipe)) & PIPE_ACTIVE_MASK; if (pipe & ~PIPE_CRT_ACTIVE) { @@ -3268,6 +5157,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) DDCclock = I830UseDDC(pScrn); + if (pI830->MergedFB) + DDCclock2 = I830UseDDC(pI830->pScrn_2); + /* * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS * functions. @@ -3281,6 +5173,21 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (pI830->MergedFB) { + SetBIOSPipe(pScrn, !pI830->pipe); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Retrieving mode pool for second head.\n"); + pI830->pScrn_2->modePool = I830GetModePool(pI830->pScrn_2, pI830->pVbe, pI830->vbeInfo); + + if (!pI830->pScrn_2->modePool) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No Video BIOS modes for chosen depth.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + SetPipeAccess(pScrn); + } + /* This may look a little weird, but to notify that we're using the * default hsync/vrefresh we need to unset what we just set ..... */ @@ -3298,6 +5205,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) SetPipeAccess(pScrn); VBESetModeNames(pScrn->modePool); + if (pI830->MergedFB) + VBESetModeNames(pI830->pScrn_2->modePool); + /* * XXX DDC information: There's code in xf86ValidateModes @@ -3321,6 +5231,20 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (pI830->MergedFB) { + n = VBEValidateModes(pI830->pScrn_2, NULL, pI830->pScrn_2->display->modes, NULL, + NULL, 0, MAX_DISPLAY_PITCH, 1, + 0, MAX_DISPLAY_HEIGHT, + pScrn->display->virtualX, + pScrn->display->virtualY, + memsize, LOOKUP_BEST_REFRESH); + if (n <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + } + /* Only use this if we've got DDC available */ if (DDCclock > 0) { p = pScrn->modes; @@ -3352,6 +5276,37 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } while (p != NULL && p != pScrn->modes); } + /* Only use this if we've got DDC available */ + if (DDCclock2 > 0) { + p = pI830->pScrn_2->modes; + if (p == NULL) + return FALSE; + do { + int Clock = 100000000; /* incredible value */ + + if (p->status == MODE_OK) { + for (pMon = pI830->pScrn_2->monitor->Modes; pMon != NULL; pMon = pMon->next) { + if ((pMon->HDisplay != p->HDisplay) || + (pMon->VDisplay != p->VDisplay) || + (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) + continue; + + /* Find lowest supported Clock for this resolution */ + if (Clock > pMon->Clock) + Clock = pMon->Clock; + } + + if (Clock != 100000000 && DDCclock2 < 2550 && Clock / 1000.0 > DDCclock2) { + ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", + p->name, pI830->pScrn_2->monitor->id, + Clock/1000.0, DDCclock2); + p->status = MODE_BAD; + } + } + p = p->next; + } while (p != NULL && p != pI830->pScrn_2->modes); + } + xf86PruneDriverModes(pScrn); if (pScrn->modes == NULL) { @@ -3360,14 +5315,42 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + if (pI830->MergedFB) { + DisplayModePtr old_modes, cur_mode; + + xf86PruneDriverModes(pI830->pScrn_2); + + if (pI830->pScrn_2->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + + old_modes = pScrn->modes; + cur_mode = pScrn->currentMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); + + pScrn->modes = I830GenerateModeList(pScrn, pI830->MetaModes, + old_modes, pI830->pScrn_2->modes, + pI830->SecondPosition); + + if(!pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes. Disabling MergedFB.\n"); + pScrn->modes = old_modes; + pScrn->currentMode = cur_mode; + pI830->MergedFB = FALSE; + } + } + /* Now we check the VESA BIOS's displayWidth and reset if necessary */ p = pScrn->modes; do { - VbeModeInfoData *data = (VbeModeInfoData *) p->Private; + I830ModePrivatePtr mp = (I830ModePrivatePtr) p->Private; VbeModeInfoBlock *modeInfo; /* Get BytesPerScanline so we can reset displayWidth */ - if ((modeInfo = VBEGetModeInfo(pI830->pVbe, data->mode))) { + if ((modeInfo = VBEGetModeInfo(pI830->pVbe, mp->vbeData.mode))) { if (pScrn->displayWidth < modeInfo->BytesPerScanline / pI830->cpp) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Correcting stride (%d -> %d)\n", pScrn->displayWidth, modeInfo->BytesPerScanline); pScrn->displayWidth = modeInfo->BytesPerScanline / pI830->cpp; @@ -3378,6 +5361,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pScrn->currentMode = pScrn->modes; + if (pI830->MergedFB) { + /* If no virtual dimension was given by the user, + * calculate a sane one now. Adapts pScrn->virtualX, + * pScrn->virtualY and pScrn->displayWidth. + */ + I830RecalcDefaultVirtualSize(pScrn); + + pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ + pScrn->currentMode = pScrn->modes; + pI830->currentMode = pScrn->currentMode; + } + #ifndef USE_PITCHES #define USE_PITCHES 1 #endif @@ -3681,8 +5676,12 @@ CheckInheritedState(ScrnInfoPtr pScrn) } #if 0 - if (errors) - I830PrintErrorState(pScrn); + if (errors) { + if (IS_I965G(pI830)) + I965PrintErrorState(pScrn); + else + I830PrintErrorState(pScrn); + } #endif if (fatal) @@ -3712,8 +5711,15 @@ ResetState(ScrnInfoPtr pScrn, Bool flush) pI830->entityPrivate->RingRunning = 0; /* Reset the fence registers to 0 */ - for (i = 0; i < 8; i++) - OUTREG(FENCE + i * 4, 0); + if (IS_I965G(pI830)) { + for (i = 0; i < FENCE_NEW_NR; i++) { + OUTREG(FENCE_NEW + i * 8, 0); + OUTREG(FENCE_NEW + 4 + i * 8, 0); + } + } else { + for (i = 0; i < FENCE_NR; i++) + OUTREG(FENCE + i * 4, 0); + } /* Flush the ring buffer (if enabled), then disable it. */ /* God this is ugly */ #define flush_ring() do { \ @@ -3752,10 +5758,21 @@ SetFenceRegs(ScrnInfoPtr pScrn) if (!I830IsPrimary(pScrn)) return; - for (i = 0; i < 8; i++) { - OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]); - if (I810_DEBUG & DEBUG_VERBOSE_VGA) - ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]); + if (IS_I965G(pI830)) { + for (i = 0; i < FENCE_NEW_NR; i++) { + OUTREG(FENCE_NEW + i * 8, pI830->ModeReg.Fence[i]); + OUTREG(FENCE_NEW + 4 + i * 8, pI830->ModeReg.Fence[i+FENCE_NEW_NR]); + if (I810_DEBUG & DEBUG_VERBOSE_VGA) { + ErrorF("Fence Start Register : %x\n", pI830->ModeReg.Fence[i]); + ErrorF("Fence End Register : %x\n", pI830->ModeReg.Fence[i+FENCE_NEW_NR]); + } + } + } else { + for (i = 0; i < FENCE_NR; i++) { + OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]); + if (I810_DEBUG & DEBUG_VERBOSE_VGA) + ErrorF("Fence Register : %x\n", pI830->ModeReg.Fence[i]); + } } } @@ -3856,6 +5873,12 @@ SaveHWState(ScrnInfoPtr pScrn) vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); pVesa = pI830->vesa; + + if (IS_I965G(pI830)) { + pI830->savedAsurf = INREG(DSPASURF); + pI830->savedBsurf = INREG(DSPBSURF); + } + /* * This save/restore method doesn't work for 845G BIOS, or for some * other platforms. Enable it in all cases. @@ -3908,9 +5931,6 @@ RestoreHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreHWState\n"); -#ifdef XF86DRI - I830DRISetVBlankInterrupt (pScrn, FALSE); -#endif if (I830IsPrimary(pScrn) && pI830->pipe != pI830->origPipe) SetBIOSPipe(pScrn, pI830->origPipe); else @@ -3969,6 +5989,11 @@ RestoreHWState(ScrnInfoPtr pScrn) VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE); + if (IS_I965G(pI830)) { + OUTREG(DSPASURF, pI830->savedAsurf); + OUTREG(DSPBSURF, pI830->savedBsurf); + } + vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); @@ -4035,7 +6060,8 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) pScrn->virtualY * pI830->displayWidth * pI830->cpp); #endif - if (pI830->Clone && pI830->CloneHDisplay && pI830->CloneVDisplay && + if (pI830->Clone && + pI830->CloneHDisplay && pI830->CloneVDisplay && !pI830->preinit && !pI830->closing) { VbeCRTCInfoBlock newblock; int newmode = mode; @@ -4112,12 +6138,18 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) else Mon = pI830->MonType2; + /* Now recheck refresh operations we can use */ pI830->useExtendedRefresh = FALSE; pI830->vesa->useDefaultRefresh = FALSE; - if (Mon != PIPE_CRT) + if (Mon != PIPE_CRT) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "A non-CRT device is attached to pipe %c.\n" + "\tNo refresh rate overrides will be attempted.\n", + PIPE_NAME(pI830->pipe)); pI830->vesa->useDefaultRefresh = TRUE; + } mode |= 1 << 11; if (pI830->vesa->useDefaultRefresh) @@ -4169,7 +6201,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); vbeInfoPtr pVbe = pI830->pVbe; - VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private; + I830ModePrivatePtr mp = (I830ModePrivatePtr) pMode->Private; int mode, i; CARD32 planeA, planeB, temp; int refresh = 60; @@ -4180,7 +6212,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) DPRINTF(PFX, "I830VESASetMode\n"); /* Always Enable Linear Addressing */ - mode = data->mode | (1 << 15) | (1 << 14); + mode = mp->vbeData.mode | (1 << 15) | (1 << 14); #ifdef XF86DRI didLock = I830DRILock(pScrn); @@ -4200,18 +6232,63 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) SetPipeAccess(pScrn); - if (I830VESASetVBEMode(pScrn, mode, data->block) == FALSE) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); - return FALSE; + if (!pI830->MergedFB) { + if (I830VESASetVBEMode(pScrn, mode, mp->vbeData.block) == FALSE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); + return FALSE; + } + }else { + I830ModePrivatePtr s = (I830ModePrivatePtr)mp->merged.Second->Private; + I830ModePrivatePtr f = (I830ModePrivatePtr)mp->merged.First->Private; + int pipe = pI830->pipe; /* save current pipe */ + + SetBIOSPipe(pScrn, !pI830->pipe); + + pI830->pipe = !pI830->pipe; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode on Pipe %s.\n", pI830->pipe ? "B" : "A"); + + if (I830VESASetVBEMode(pScrn, (s->vbeData.mode | 1<<15 | 1<<14), s->vbeData.block) == FALSE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); + return FALSE; + } + + pI830->pipe = pipe; /* restore current pipe */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode on Pipe %s.\n", pI830->pipe ? "B" : "A"); + + SetPipeAccess(pScrn); + + if (I830VESASetVBEMode(pScrn, (f->vbeData.mode | 1<<15 | 1<<14), f->vbeData.block) == FALSE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Set VBE Mode failed!\n"); + return FALSE; + } } +#if 0 + { /* I965G ENABLE TILING */ + planeA = INREG(DSPACNTR) | 1<<10; + OUTREG(DSPACNTR, planeA); + /* flush the change. */ + temp = INREG(DSPABASE); + OUTREG(DSPABASE, temp); + } +#else + { /* I965G DISABLE TILING */ + planeA = INREG(DSPACNTR) & ~1<<10; + OUTREG(DSPACNTR, planeA); + /* flush the change. */ + temp = INREG(DSPABASE); + OUTREG(DSPABASE, temp); + OUTREG(DSPASURF, INREG(DSPASURF)); + } +#endif + /* * The BIOS may not set a scanline pitch that would require more video * memory than it's aware of. We check for this later, and set it * explicitly if necessary. */ - if (data->data->XResolution != pI830->displayWidth) { - if (pI830->Clone) { + if (mp->vbeData.data->XResolution != pI830->displayWidth) { + if (pI830->Clone || pI830->MergedFB) { SetBIOSPipe(pScrn, !pI830->pipe); VBESetLogicalScanline(pVbe, pI830->displayWidth); } @@ -4220,7 +6297,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) { - if (pI830->Clone) { + if (pI830->Clone || pI830->MergedFB) { SetBIOSPipe(pScrn, !pI830->pipe); VBESetGetDACPaletteFormat(pVbe, 8); } @@ -4264,6 +6341,10 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* flush the change. */ temp = INREG(DSPABASE); OUTREG(DSPABASE, temp); + if (IS_I965G(pI830)) { + temp = INREG(DSPASURF); + OUTREG(DSPASURF, temp); + } } if (pI830->planeEnabled[1]) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n"); @@ -4274,6 +6355,10 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* flush the change. */ temp = INREG(DSPBADDR); OUTREG(DSPBADDR, temp); + if (IS_I965G(pI830)) { + temp = INREG(DSPBSURF); + OUTREG(DSPBSURF, temp); + } } planeA = INREG(DSPACNTR); @@ -4306,6 +6391,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE; CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; + CARD32 surfreg = !pI830->pipe ? DSPASURF : DSPBSURF; I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); temp = INREG(stridereg); @@ -4319,12 +6405,17 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* Trigger update */ temp = INREG(basereg); OUTREG(basereg, temp); + if (IS_I965G(pI830)) { + temp = INREG(surfreg); + OUTREG(surfreg, temp); + } if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; basereg = pI830->pipe ? DSPABASE : DSPBBASE; sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; + surfreg = pI830->pipe ? DSPASURF : DSPBSURF; temp = INREG(stridereg); if (temp / pI8302->cpp != (CARD32)(pI8302->displayWidth)) { @@ -4337,11 +6428,16 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* Trigger update */ temp = INREG(basereg); OUTREG(basereg, temp); + if (IS_I965G(pI830)) { + temp = INREG(surfreg); + OUTREG(surfreg, temp); + } } } else { CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE; CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; + CARD32 surfreg = pI830->pipe ? DSPASURF : DSPBSURF; I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); @@ -4356,10 +6452,15 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* Trigger update */ temp = INREG(basereg); OUTREG(basereg, temp); + if (IS_I965G(pI830)) { + temp = INREG(surfreg); + OUTREG(surfreg, temp); + } stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; basereg = !pI830->pipe ? DSPABASE : DSPBBASE; sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; + surfreg = !pI830->pipe ? DSPASURF : DSPBSURF; temp = INREG(stridereg); if (temp / pI8302->cpp != ((CARD32)pI8302->displayWidth)) { @@ -4372,12 +6473,17 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* Trigger update */ temp = INREG(basereg); OUTREG(basereg, temp); + if (IS_I965G(pI830)) { + temp = INREG(surfreg); + OUTREG(surfreg, temp); + } } } else { for (i = 0; i < pI830->availablePipes; i++) { CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE; CARD32 basereg = i ? DSPBBASE : DSPABASE; CARD32 sizereg = i ? DSPBSIZE : DSPASIZE; + CARD32 surfreg = i ? DSPBSURF : DSPASURF; if (!pI830->planeEnabled[i]) continue; @@ -4389,10 +6495,29 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(temp / pI830->cpp), pI830->displayWidth); OUTREG(stridereg, pI830->displayWidth * pI830->cpp); } - OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); + + if (pI830->MergedFB) { + switch (pI830->SecondPosition) { + case PosRightOf: + case PosBelow: + OUTREG(DSPABASE, (CDMPTR.First->HDisplay - 1) | ((CDMPTR.First->VDisplay - 1) << 16)); + OUTREG(DSPBBASE, (CDMPTR.Second->HDisplay - 1) | ((CDMPTR.Second->VDisplay - 1) << 16)); + break; + case PosLeftOf: + case PosAbove: + OUTREG(DSPABASE, (CDMPTR.Second->HDisplay - 1) | ((CDMPTR.Second->VDisplay - 1) << 16)); + OUTREG(DSPBBASE, (CDMPTR.First->HDisplay - 1) | ((CDMPTR.First->VDisplay - 1) << 16)); + break; + } + } else + OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); /* Trigger update */ temp = INREG(basereg); OUTREG(basereg, temp); + if (IS_I965G(pI830)) { + temp = INREG(surfreg); + OUTREG(surfreg, temp); + } } } @@ -4495,9 +6620,13 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) SetHWOperatingState(pScrn); #endif -#ifdef XF86DRI - I830DRISetVBlankInterrupt (pScrn, TRUE); +#if 0 + if (IS_I965G(pI830)) + I965PrintErrorState(pScrn); + else + I830PrintErrorState(pScrn); #endif + #ifdef XF86DRI if (didLock) I830DRIUnlock(pScrn); @@ -4551,6 +6680,72 @@ I830PrintErrorState(ScrnInfoPtr pScrn) INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); } +void +I965PrintErrorState(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + INREG(PGETBL_CTL), INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + INREG(LP_RING + RING_TAIL), + INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START)); + + ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n", + (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR)); + + ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965), + (int)INREG(INST_DONE_1)); + ErrorF("instpm: %x\n", (int)INREG(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965)); + + ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x imr: %x iir: %x\n", + (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR), + (int)INREG(IIR)); + + ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P)); + ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC)); + + ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0), + (int)INREG(CACHE_MODE_1)); + ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE)); + + ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", (int)INREG(IA_VERTICES_COUNT_QW), + (int)INREG(IA_VERTICES_COUNT_QW+4)); + ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(IA_PRIMITIVES_COUNT_QW), + (int)INREG(IA_PRIMITIVES_COUNT_QW+4)); + + ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(VS_INVOCATION_COUNT_QW), + (int)INREG(VS_INVOCATION_COUNT_QW+4)); + + ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(GS_INVOCATION_COUNT_QW), + (int)INREG(GS_INVOCATION_COUNT_QW+4)); + ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(GS_PRIMITIVES_COUNT_QW), + (int)INREG(GS_PRIMITIVES_COUNT_QW+4)); + + ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(CL_INVOCATION_COUNT_QW), + (int)INREG(CL_INVOCATION_COUNT_QW+4)); + ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(CL_PRIMITIVES_COUNT_QW), + (int)INREG(CL_PRIMITIVES_COUNT_QW+4)); + + ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(PS_INVOCATION_COUNT_QW), + (int)INREG(PS_INVOCATION_COUNT_QW+4)); + ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", (int)INREG(PS_DEPTH_COUNT_QW), + (int)INREG(PS_DEPTH_COUNT_QW+4)); + + ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL)); + ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL), + (int)INREG(TS_DEBUG_DATA)); + ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2)); + + +} + #ifdef I830DEBUG static void dump_DSPACNTR(ScrnInfoPtr pScrn) @@ -4777,7 +6972,8 @@ I830CreateScreenResources (ScreenPtr pScreen) if (!(*pScreen->CreateScreenResources)(pScreen)) return FALSE; - if (pI830->rotation != RR_Rotate_0) { + if (xf86LoaderCheckSymbol("I830RandRSetConfig") && pI830->rotation != RR_Rotate_0) { + Rotation (*I830RandRSetConfig)(ScreenPtr pScreen, Rotation rr, int rate, RRScreenSizePtr pSize) = NULL; RRScreenSize p; Rotation requestedRotation = pI830->rotation; @@ -4789,9 +6985,12 @@ I830CreateScreenResources (ScreenPtr pScreen) p.mmWidth = pScreen->mmWidth; p.mmHeight = pScreen->mmHeight; - pI830->starting = TRUE; /* abuse this for dual head & rotation */ - I830RandRSetConfig (pScreen, requestedRotation, 0, &p); - pI830->starting = FALSE; + I830RandRSetConfig = LoaderSymbol("I830RandRSetConfig"); + if (I830RandRSetConfig) { + pI830->starting = TRUE; /* abuse this for dual head & rotation */ + (*I830RandRSetConfig) (pScreen, requestedRotation, 0, &p); + pI830->starting = FALSE; + } } return TRUE; @@ -4844,6 +7043,9 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); CARD32 ctx_addr; + if (pI830->noAccel) + return; + ctx_addr = pI830->ContextMem.Start; /* Align to a 2k boundry */ ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048; @@ -4857,10 +7059,13 @@ IntelEmitInvarientState(ScrnInfoPtr pScrn) ADVANCE_LP_RING(); } - if (IS_I9XX(pI830)) - I915EmitInvarientState(pScrn); - else - I830EmitInvarientState(pScrn); + if (!IS_I965G(pI830)) + { + if (IS_I9XX(pI830)) + I915EmitInvarientState(pScrn); + else + I830EmitInvarientState(pScrn); + } } static Bool @@ -4890,6 +7095,47 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->RotatedMem2.Key = -1; } +#ifdef HAS_MTRR_SUPPORT + { + int fd; + struct mtrr_gentry gentry; + struct mtrr_sentry sentry; + + if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) != -1 ) { + for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0; + ++gentry.regnum) { + + if (gentry.size < 1) { + /* DISABLED */ + continue; + } + + /* Check the MTRR range is one we like and if not - remove it. + * The Xserver common layer will then setup the right range + * for us. + */ + if (gentry.base == pI830->LinearAddr && + gentry.size < pI830->FbMapSize) { + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Removing bad MTRR range (base 0x%lx, size 0x%x)\n", + gentry.base, gentry.size); + + sentry.base = gentry.base; + sentry.size = gentry.size; + sentry.type = gentry.type; + + if (ioctl (fd, MTRRIOC_DEL_ENTRY, &sentry) == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to remove bad MTRR range\n"); + } + } + } + close(fd); + } + } +#endif + if (xf86IsEntityShared(pScrn->entityList[0])) { /* PreInit failed on the second head, so make sure we turn it off */ if (I830IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { @@ -5242,13 +7488,33 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = I830BIOSCloseScreen; - if (pI830->shadowReq.minorversion >= 1) { + if (pI830->MergedFB) { + pI830->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = I830MergedPointerMoved; + + if(pI830->IntelXinerama) { + I830noPanoramiXExtension = FALSE; + I830XineramaExtensionInit(pScrn); + if(!I830noPanoramiXExtension) { + if(pI830->HaveNonRect) { + /* Reset the viewport (now eventually non-recangular) */ + I830AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + } + } + } else { + pI830->MouseRestrictions = FALSE; + } + } else if (pI830->shadowReq.minorversion >= 1) { /* Rotation */ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR enabled, ignore the following RandR disabled message.\n"); xf86DisableRandR(); /* Disable built-in RandR extension */ shadowSetup(pScreen); /* support all rotations */ - I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + if (IS_I965G(pI830)) { + I830RandRInit(pScreen, RR_Rotate_0); /* only 0 degrees for I965G */ + } else { + I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + } pI830->PointerMoved = pScrn->PointerMoved; pScrn->PointerMoved = I830PointerMoved; pI830->CreateScreenResources = pScreen->CreateScreenResources; @@ -5265,6 +7531,20 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) I830_dump_registers(pScrn); #endif + if (IS_I965G(pI830)) { + /* turn off clock gating */ +#if 0 + OUTREG(0x6204, 0x70804000); + OUTREG(0x6208, 0x00000001); +#else + OUTREG(0x6204, 0x70000000); +#endif + /* Enable DAP stateless accesses. + * Required for all i965 steppings. + */ + OUTREG(SVG_WORK_CTL, 0x00000010); + } + pI830->starting = FALSE; pI830->closing = FALSE; pI830->suspended = FALSE; @@ -5296,7 +7576,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } static void -I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) +I830AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn; I830Ptr pI830; @@ -5307,12 +7587,26 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) pI830 = I830PTR(pScrn); pVbe = pI830->pVbe; - DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", + DPRINTF(PFX, "I830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); /* Sync the engine before adjust frame */ i830WaitSync(pScrn); + if (pI830->MergedFB) { + I830AdjustFrameMerged(scrnIndex, x, y, flags); + + if (pI830->pipe == 0) { + OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp)); + OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, pI830->FrontBuffer.Start + ((pI830->FirstframeY0 * pScrn->displayWidth + pI830->FirstframeX0) * pI830->cpp)); + OUTREG(DSPABASE, pI830->FrontBuffer.Start + ((pI830->pScrn_2->frameY0 * pScrn->displayWidth + pI830->pScrn_2->frameX0) * pI830->cpp)); + } + + return; + } + if (I830IsPrimary(pScrn)) Start = pI830->FrontBuffer.Start; else { @@ -5327,16 +7621,36 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) if (pI830->Clone) { if (!pI830->pipe == 0) { - OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + if (!IS_I965G(pI830)) { + OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPABASE, 0); + OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } } else { - OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + if (!IS_I965G(pI830)) { + OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, 0); + OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } } } if (pI830->pipe == 0) { - OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + if (!IS_I965G(pI830)) { + OUTREG(DSPABASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPABASE, 0); + OUTREG(DSPASURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } } else { - OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + if (!IS_I965G(pI830)) { + OUTREG(DSPBBASE, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, 0); + OUTREG(DSPBSURF, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } } } @@ -5395,7 +7709,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags) I830VideoSwitchModeBefore(pScrn, NULL); #endif - if (pI830->Clone) { + if (pI830->Clone || pI830->MergedFB) { /* Ensure we don't try and setup modes on a clone head */ pI830->CloneHDisplay = 0; pI830->CloneVDisplay = 0; @@ -5411,6 +7725,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingOpen) { DRILock(screenInfo.screens[pScrn->scrnIndex], 0); + + I830DRISetVBlankInterrupt (pScrn, FALSE); drmCtlUninstHandler(pI830->drmSubFD); } @@ -5467,10 +7783,11 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) pointer pDDCModule = NULL; DisplayModePtr p, pMon; int memsize; - int DDCclock = 0; + int DDCclock = 0, DDCclock2 = 0; int displayWidth = pScrn->displayWidth; int curHDisplay = pScrn->currentMode->HDisplay; int curVDisplay = pScrn->currentMode->VDisplay; + xf86MonPtr monitor = NULL; DPRINTF(PFX, "Detect Monitor Change\n"); @@ -5478,19 +7795,31 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) /* Re-read EDID */ pDDCModule = xf86LoadSubModule(pScrn, "ddc"); - if (pI830->vesa->monitor) - xfree(pI830->vesa->monitor); - pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule); + + if (pI830->MergedFB) { + pI830->pVbe->ddc = DDC_UNCHECKED; + SetBIOSPipe(pScrn, !pI830->pipe); + monitor = vbeDoEDID(pI830->pVbe, pDDCModule); + if ((pI830->pScrn_2->monitor->DDC = monitor) != NULL) { + xf86PrintEDID(monitor); + xf86SetDDCproperties(pScrn, monitor); + } + SetPipeAccess(pScrn); + } + + pI830->pVbe->ddc = DDC_UNCHECKED; + monitor = vbeDoEDID(pI830->pVbe, pDDCModule); xf86UnloadSubModule(pDDCModule); - if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) { - xf86PrintEDID(pI830->vesa->monitor); - xf86SetDDCproperties(pScrn, pI830->vesa->monitor); - } else - /* No DDC, so get out of here, and continue to use the current settings */ - return FALSE; + if ((pScrn->monitor->DDC = monitor) != NULL) { + xf86PrintEDID(monitor); + xf86SetDDCproperties(pScrn, monitor); + } - if (!(DDCclock = I830UseDDC(pScrn))) - return FALSE; + DDCclock = I830UseDDC(pScrn); + + /* Check if DDC exists on the second head, if not don't abort. */ + if (pI830->MergedFB) + DDCclock2 = I830UseDDC(pI830->pScrn_2); /* Revalidate the modes */ @@ -5498,6 +7827,8 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS * functions. */ + SetPipeAccess(pScrn); + pScrn->modePool = I830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo); if (!pScrn->modePool) { @@ -5508,8 +7839,24 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) return FALSE; } - SetPipeAccess(pScrn); + if (pI830->MergedFB) { + SetBIOSPipe(pScrn, !pI830->pipe); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Retrieving mode pool for second head.\n"); + pI830->pScrn_2->modePool = I830GetModePool(pI830->pScrn_2, pI830->pVbe, pI830->vbeInfo); + + if (!pI830->pScrn_2->modePool) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No Video BIOS modes for chosen depth.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + SetPipeAccess(pScrn); + } + VBESetModeNames(pScrn->modePool); + if (pI830->MergedFB) + VBESetModeNames(pI830->pScrn_2->modePool); if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64)) memsize = pI830->vbeInfo->TotalMemory * 64; @@ -5523,6 +7870,16 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) pScrn->display->virtualY, memsize, LOOKUP_BEST_REFRESH); + if (pI830->MergedFB) { + VBEValidateModes(pI830->pScrn_2, pI830->pScrn_2->monitor->Modes, + pI830->pScrn_2->display->modes, NULL, + NULL, 0, MAX_DISPLAY_PITCH, 1, + 0, MAX_DISPLAY_HEIGHT, + pScrn->display->virtualX, + pScrn->display->virtualY, + memsize, LOOKUP_BEST_REFRESH); + } + if (DDCclock > 0) { p = pScrn->modes; if (p == NULL) @@ -5553,10 +7910,61 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) } while (p != NULL && p != pScrn->modes); } - pScrn->displayWidth = displayWidth; /* restore old displayWidth */ + /* Only use this if we've got DDC available */ + if (pI830->MergedFB && DDCclock2 > 0) { + p = pI830->pScrn_2->modes; + if (p == NULL) + return FALSE; + do { + int Clock = 100000000; /* incredible value */ + + if (p->status == MODE_OK) { + for (pMon = pI830->pScrn_2->monitor->Modes; pMon != NULL; pMon = pMon->next) { + if ((pMon->HDisplay != p->HDisplay) || + (pMon->VDisplay != p->VDisplay) || + (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) + continue; + + /* Find lowest supported Clock for this resolution */ + if (Clock > pMon->Clock) + Clock = pMon->Clock; + } + + if (Clock != 100000000 && DDCclock2 < 2550 && Clock / 1000.0 > DDCclock2) { + ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", + p->name, pI830->pScrn_2->monitor->id, + Clock/1000.0, DDCclock2); + p->status = MODE_BAD; + } + } + p = p->next; + } while (p != NULL && p != pI830->pScrn_2->modes); + } xf86PruneDriverModes(pScrn); - I830PrintModes(pScrn); + + if (pI830->MergedFB) + xf86PruneDriverModes(pI830->pScrn_2); + + if (pI830->MergedFB) { + DisplayModePtr old_modes, cur_mode; + + old_modes = pScrn->modes; + cur_mode = pScrn->currentMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MergedFB: Generating mode list\n"); + + pScrn->modes = I830GenerateModeList(pScrn, pI830->MetaModes, + old_modes, pI830->pScrn_2->modes, + pI830->SecondPosition); + + if(!pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes. Disabling MergedFB.\n"); + pScrn->modes = old_modes; + pScrn->currentMode = cur_mode; + pI830->MergedFB = FALSE; + } + } if (!pI830->vesa->useDefaultRefresh) I830SetModeParameters(pScrn, pI830->pVbe); @@ -5566,6 +7974,21 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) * and reconnecting monitors */ pScrn->currentMode = pScrn->modes; + + if (pI830->MergedFB) { + /* If no virtual dimension was given by the user, + * calculate a sane one now. Adapts pScrn->virtualX, + * pScrn->virtualY and pScrn->displayWidth. + */ + I830RecalcDefaultVirtualSize(pScrn); + + pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList(), skip to first */ + pScrn->currentMode = pScrn->modes; + pI830->currentMode = pScrn->currentMode; + } + + pScrn->displayWidth = displayWidth; /* restore old displayWidth */ + p = pScrn->modes; if (p == NULL) return FALSE; @@ -5578,6 +8001,8 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) p = p->next; } while (p != NULL && p != pScrn->modes); + I830PrintModes(pScrn); + /* Now readjust for panning if necessary */ { pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2; @@ -5603,6 +8028,9 @@ I830DetectMonitorChange(ScrnInfoPtr pScrn) } } + if (pI830->MergedFB) + I830AdjustFrameMerged(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; } @@ -5712,7 +8140,6 @@ I830BIOSEnterVT(int scrnIndex, int flags) ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); - /* Detect monitor change and switch to suitable mode */ if (!pI830->starting) I830DetectMonitorChange(pScrn); @@ -5735,12 +8162,21 @@ I830BIOSEnterVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingEnabled) { if (!pI830->starting) { + ScreenPtr pScreen = pScrn->pScreen; + drmI830Sarea *sarea = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); + int i; + I830DRIResume(screenInfo.screens[scrnIndex]); + I830DRISetVBlankInterrupt (pScrn, TRUE); I830RefreshRing(pScrn); I830Sync(pScrn); DO_RING_IDLE(); + sarea->texAge++; + for(i = 0; i < I830_NR_TEX_REGIONS+1 ; i++) + sarea->texList[i].age = sarea->texAge; + DPRINTF(PFX, "calling dri unlock\n"); DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); } @@ -5797,7 +8233,8 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * The extra WindowTable check detects a rotation at startup. */ if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) && - !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved) ) { + !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved) && + !IS_I965G(pI830)) { if (!I830Rotate(pScrn, mode)) ret = FALSE; } @@ -5824,6 +8261,13 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #endif } + /* Since RandR (indirectly) uses SwitchMode(), we need to + * update our Xinerama info here, too, in case of resizing + */ + if(pI830->MergedFB) { + I830UpdateXineramaScreenInfo(pScrn); + } + return ret; } @@ -5833,7 +8277,7 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); Bool on = xf86IsUnblank(mode); - CARD32 temp, ctrl, base; + CARD32 temp, ctrl, base, surf; DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); @@ -5841,9 +8285,11 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) if (pI830->pipe == 0) { ctrl = DSPACNTR; base = DSPABASE; + surf = DSPASURF; } else { ctrl = DSPBCNTR; base = DSPBADDR; + surf = DSPBSURF; } if (pI830->planeEnabled[pI830->pipe]) { temp = INREG(ctrl); @@ -5855,6 +8301,10 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) /* Flush changes */ temp = INREG(base); OUTREG(base, temp); + if (IS_I965G(pI830)) { + temp = INREG(surf); + OUTREG(surf, temp); + } } if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { @@ -5876,7 +8326,7 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, I830Ptr pI830 = I830PTR(pScrn); vbeInfoPtr pVbe = pI830->pVbe; - if (pI830->Clone) { + if (pI830->Clone || pI830->MergedFB) { SetBIOSPipe(pScrn, !pI830->pipe); if (xf86LoaderCheckSymbol("VBEDPMSSet")) { VBEDPMSSet(pVbe, PowerManagementMode); @@ -5998,9 +8448,7 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->used3D = NULL; } - if (pI830->shadowReq.minorversion >= 1) - pScrn->PointerMoved = pI830->PointerMoved; - + pScrn->PointerMoved = pI830->PointerMoved; pScrn->vtSema = FALSE; pI830->closing = FALSE; pScreen->CloseScreen = pI830->CloseScreen; @@ -6323,16 +8771,23 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) offset = pI8301->FrontBuffer2.Start + ((pScrn->frameY0 * pI830->displayWidth + pScrn->frameX0) * pI830->cpp); } - if (pI830->pipe == 0) - adjust = INREG(DSPABASE); - else - adjust = INREG(DSPBBASE); + if (IS_I965G(pI830)) { + if (pI830->pipe == 0) + adjust = INREG(DSPASURF); + else + adjust = INREG(DSPBSURF); + } else { + if (pI830->pipe == 0) + adjust = INREG(DSPABASE); + else + adjust = INREG(DSPBBASE); + } if (adjust != offset) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Fixing display offsets.\n"); - I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + I830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); } } @@ -6340,7 +8795,6 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) ScreenPtr pCursorScreen; int x = 0, y = 0; - pCursorScreen = miPointerCurrentScreen(); if (pScrn->pScreen == pCursorScreen) miPointerPosition(&x, &y); @@ -6357,7 +8811,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI830->currentMode = NULL; I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); - I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + I830AdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); if (xf86IsEntityShared(pScrn->entityList[0])) { ScrnInfoPtr pScrn2; @@ -6376,7 +8830,7 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) pI8302->currentMode = NULL; I830BIOSSwitchMode(pScrn2->pScreen->myNum, pScrn2->currentMode, 0); - I830BIOSAdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); + I830AdjustFrame(pScrn2->pScreen->myNum, pScrn2->frameX0, pScrn2->frameY0, 0); (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, FALSE); (*pScrn2->EnableDisableFBAccess) (pScrn2->pScreen->myNum, TRUE); @@ -6462,7 +8916,7 @@ I830InitpScrn(ScrnInfoPtr pScrn) pScrn->PreInit = I830BIOSPreInit; pScrn->ScreenInit = I830BIOSScreenInit; pScrn->SwitchMode = I830BIOSSwitchMode; - pScrn->AdjustFrame = I830BIOSAdjustFrame; + pScrn->AdjustFrame = I830AdjustFrame; pScrn->EnterVT = I830BIOSEnterVT; pScrn->LeaveVT = I830BIOSLeaveVT; pScrn->FreeScreen = I830BIOSFreeScreen; diff --git a/src/i830_memory.c b/src/i830_memory.c index c1c7cb73..88dc5acb 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -209,12 +209,12 @@ AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size, if (newApStart > newApEnd) return 0; - if (flags & NEED_PHYSICAL_ADDR) { + if (flags & NEED_PHYSICAL_ADDR) result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &(result->Physical)); - } else { + else result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL); - } + if (result->Key == -1) return 0; } @@ -498,7 +498,7 @@ I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, int flags) alloced = 0; if (tileable) { align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | @@ -563,7 +563,7 @@ I830AllocateRotated2Buffer(ScrnInfoPtr pScrn, int flags) alloced = 0; if (tileable) { align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->RotatedMem2), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | @@ -673,6 +673,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); pI830->FrontBuffer2.Key = -1; +#if 1 /* ROTATION */ pI830->FbMemBox2.x1 = 0; pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; pI830->FbMemBox2.y1 = 0; @@ -680,6 +681,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; else pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; +#else + pI830->FbMemBox2.x1 = 0; + pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; + pI830->FbMemBox2.y1 = 0; + pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; +#endif /* * Calculate how much framebuffer memory to allocate. For the @@ -731,19 +738,26 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); if (tileable) { - align = KB(512); + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); alignflags = ALIGN_BOTH_ENDS; } else { align = KB(64); alignflags = 0; } +#if 1 /* ROTATION */ if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); else size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); size = ROUND_TO_PAGE(size); - +#else + size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); + size = ROUND_TO_PAGE(size); +#endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sSecondary framebuffer allocation size: %ld kByte\n", s, size / 1024); @@ -765,6 +779,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); pI830->FrontBuffer.Key = -1; +#if 1 /* ROTATION */ pI830->FbMemBox.x1 = 0; pI830->FbMemBox.x2 = pScrn->displayWidth; pI830->FbMemBox.y1 = 0; @@ -772,6 +787,12 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->FbMemBox.y2 = pScrn->virtualX; else pI830->FbMemBox.y2 = pScrn->virtualY; +#else + pI830->FbMemBox.x1 = 0; + pI830->FbMemBox.x2 = pScrn->displayWidth; + pI830->FbMemBox.y1 = 0; + pI830->FbMemBox.y2 = pScrn->virtualY; +#endif /* * Calculate how much framebuffer memory to allocate. For the @@ -823,19 +844,26 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn->displayWidth * pI830->cpp); if (tileable) { - align = KB(512); + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); alignflags = ALIGN_BOTH_ENDS; } else { align = KB(64); alignflags = 0; } +#if 1 /* ROTATION */ if (pScrn->virtualX > pScrn->virtualY) size = lineSize * (pScrn->virtualX + cacheLines); else size = lineSize * (pScrn->virtualY + cacheLines); size = ROUND_TO_PAGE(size); - +#else + size = lineSize * (pScrn->virtualY + cacheLines); + size = ROUND_TO_PAGE(size); +#endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, "%sInitial framebuffer allocation size: %ld kByte\n", s, size / 1024); @@ -937,7 +965,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && IsTileable(pScrn->displayWidth * pI830->cpp); if (tileable) { - align = KB(512); + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); alignflags = ALIGN_BOTH_ENDS; } else { align = KB(64); @@ -1175,7 +1206,7 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags) alloced = 0; if (tileable) { align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | @@ -1238,7 +1269,7 @@ I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags) alloced = 0; if (tileable) { align = GetBestTileAlignment(size); - for (align = GetBestTileAlignment(size); align >= KB(512); align >>= 1) { + for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) { alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer), &(pI830->StolenPool), size, align, flags | FROM_ANYWHERE | ALLOCATE_AT_TOP | @@ -1672,7 +1703,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, } static Bool -MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem) +MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem, unsigned int fence) { I830Ptr pI830 = I830PTR(pScrn); int pitch, ntiles, i; @@ -1690,6 +1721,31 @@ MakeTiles(ScrnInfoPtr pScrn, I830MemRange *pMem) } pitch = pScrn->displayWidth * pI830->cpp; + + if (IS_I965G(pI830)) { + I830RegPtr i830Reg = &pI830->ModeReg; + + switch (fence) { + case FENCE_XMAJOR: + i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | pMem->Start | 1; + break; + case FENCE_YMAJOR: + /* YMajor can be 128B aligned but the current code dictates + * otherwise. This isn't a problem apart from memory waste. + * FIXME */ + i830Reg->Fence[nextTile] = (((pitch / 128) - 1) << 2) | pMem->Start | 1; + i830Reg->Fence[nextTile] |= (1<<1); + break; + default: + case FENCE_LINEAR: + break; + } + + i830Reg->Fence[nextTile+FENCE_NEW_NR] = pMem->End; + nextTile++; + return TRUE; + } + /* * Simply try to break the region up into at most four pieces of size * equal to the alignment. @@ -1731,20 +1787,27 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) return; } + pI830->front_tiled = FENCE_LINEAR; + pI830->back_tiled = FENCE_LINEAR; + pI830->depth_tiled = FENCE_LINEAR; + pI830->rotated_tiled = FENCE_LINEAR; + pI830->rotated2_tiled = FENCE_LINEAR; + if (pI830->allowPageFlip) { if (pI830->allowPageFlip && pI830->FrontBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->FrontBuffer))) { + if (MakeTiles(pScrn, &(pI830->FrontBuffer), FENCE_XMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Activating tiled memory for the FRONT buffer\n"); + "Activating tiled memory for the front buffer\n"); + pI830->front_tiled = FENCE_XMAJOR; } else { pI830->allowPageFlip = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MakeTiles failed for the FRONT buffer\n"); + "MakeTiles failed for the front buffer\n"); } } else { pI830->allowPageFlip = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Alignment bad for the FRONT buffer\n"); + "Alignment bad for the front buffer\n"); } } @@ -1755,9 +1818,10 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) * value. */ if (pI830->BackBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->BackBuffer))) { + if (MakeTiles(pScrn, &(pI830->BackBuffer), FENCE_XMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Activating tiled memory for the back buffer.\n"); + pI830->back_tiled = FENCE_XMAJOR; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MakeTiles failed for the back buffer.\n"); @@ -1766,9 +1830,10 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) } if (pI830->DepthBuffer.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->DepthBuffer))) { + if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Activating tiled memory for the depth buffer.\n"); + "Activating tiled memory for the depth buffer.\n"); + pI830->depth_tiled = FENCE_YMAJOR; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MakeTiles failed for the depth buffer.\n"); @@ -1776,9 +1841,10 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) } if (pI830->RotatedMem.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->RotatedMem))) { + if (MakeTiles(pScrn, &(pI830->RotatedMem), FENCE_XMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Activating tiled memory for the rotated buffer.\n"); + pI830->rotated_tiled = FENCE_XMAJOR; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MakeTiles failed for the rotated buffer.\n"); @@ -1787,9 +1853,10 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn) #if 0 if (pI830->RotatedMem2.Alignment >= KB(512)) { - if (MakeTiles(pScrn, &(pI830->RotatedMem2))) { + if (MakeTiles(pScrn, &(pI830->RotatedMem2), FENCE_XMAJOR)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Activating tiled memory for the rotated2 buffer.\n"); + pI830->rotated2_tiled = FENCE_XMAJOR; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MakeTiles failed for the rotated buffer.\n"); diff --git a/src/i830_modes.c b/src/i830_modes.c index 97e40e0a..7d145198 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -42,8 +42,6 @@ #include <string.h> #include "xf86.h" -#include "vbe.h" -#include "vbeModes.h" #include "i830.h" #include <math.h> @@ -363,7 +361,11 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, CARD16 major, minor; VbeModeInfoBlock *mode; DisplayModePtr p = NULL, pMode = NULL; +#if 0 VbeModeInfoData *data; +#else + I830ModePrivatePtr data; +#endif Bool modeOK = FALSE; ModeStatus status = MODE_OK; @@ -602,12 +604,21 @@ CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, pMode->HDisplay = mode->XResolution; pMode->VDisplay = mode->YResolution; +#if 0 data = xnfcalloc(sizeof(VbeModeInfoData), 1); data->mode = id; data->data = mode; pMode->PrivSize = sizeof(VbeModeInfoData); pMode->Private = (INT32*)data; +#else + data = xnfcalloc(sizeof(I830ModePrivateRec), 1); + data->vbeData.mode = id; + data->vbeData.data = mode; + pMode->PrivSize = sizeof(I830ModePrivateRec); + pMode->Private = (INT32*)data; +#endif pMode->next = NULL; + return pMode; } @@ -663,54 +674,113 @@ I830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe) void I830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) { - DisplayModePtr pMode; - VbeModeInfoData *data; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr pMode = pScrn->modes; + DisplayModePtr ppMode = pScrn->modes; + I830ModePrivatePtr mp = NULL; - pMode = pScrn->modes; do { int clock; + + mp = (I830ModePrivatePtr) pMode->Private; - data = (VbeModeInfoData*)pMode->Private; - data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); - data->block->HorizontalTotal = pMode->HTotal; - data->block->HorizontalSyncStart = pMode->HSyncStart; - data->block->HorizontalSyncEnd = pMode->HSyncEnd; - data->block->VerticalTotal = pMode->VTotal; - data->block->VerticalSyncStart = pMode->VSyncStart; - data->block->VerticalSyncEnd = pMode->VSyncEnd; - data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | - ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); - data->block->PixelClock = pMode->Clock * 1000; + if (pI830->MergedFB) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", pScrn->monitor->id); + ppMode = (DisplayModePtr) mp->merged.First; + mp = (I830ModePrivatePtr) mp->merged.First->Private; + } + mp->vbeData.block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); + mp->vbeData.block->HorizontalTotal = ppMode->HTotal; + mp->vbeData.block->HorizontalSyncStart = ppMode->HSyncStart; + mp->vbeData.block->HorizontalSyncEnd = ppMode->HSyncEnd; + mp->vbeData.block->VerticalTotal = ppMode->VTotal; + mp->vbeData.block->VerticalSyncStart = ppMode->VSyncStart; + mp->vbeData.block->VerticalSyncEnd = ppMode->VSyncEnd; + mp->vbeData.block->Flags = ((ppMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | + ((ppMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); + mp->vbeData.block->PixelClock = ppMode->Clock * 1000; /* XXX May not have this. */ - clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); + clock = VBEGetPixelClock(pVbe, mp->vbeData.mode, mp->vbeData.block->PixelClock); if (clock) - data->block->PixelClock = clock; + mp->vbeData.block->PixelClock = clock; #ifdef DEBUG ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", - (double)data->block->PixelClock / 1000000.0, + (double)mp->vbeData.block->PixelClock / 1000000.0, (double)clock / 1000000.0); #endif - data->mode |= (1 << 11); - if (pMode->VRefresh != 0) { - data->block->RefreshRate = pMode->VRefresh * 100; + mp->vbeData.mode |= (1 << 11); + if (ppMode->VRefresh != 0) { + mp->vbeData.block->RefreshRate = ppMode->VRefresh * 100; } else { - data->block->RefreshRate = (int)(((double)(data->block->PixelClock)/ - (double)(pMode->HTotal * pMode->VTotal)) * 100); + mp->vbeData.block->RefreshRate = (int)(((double)(mp->vbeData.block->PixelClock)/ + (double)(ppMode->HTotal * ppMode->VTotal)) * 100); } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n", - (float)(((double)(data->block->PixelClock) / (double)(pMode->HTotal * pMode->VTotal))), pMode->name, data->mode); + (float)(((double)(mp->vbeData.block->PixelClock) / (double)(ppMode->HTotal * ppMode->VTotal))), ppMode->name, mp->vbeData.mode); #ifdef DEBUG ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - " " %i %i %i %i %.2f MHz Refresh: %.2f Hz\n", - data->mode, pMode->name, pMode->HDisplay, pMode->HSyncStart, - pMode->HSyncEnd, pMode->HTotal, pMode->VDisplay, - pMode->VSyncStart,pMode->VSyncEnd,pMode->VTotal, - (double)data->block->PixelClock/1000000.0, - (double)data->block->RefreshRate/100); + mp->vbeData.mode, ppMode->name, ppMode->HDisplay, ppMode->HSyncStart, + ppMode->HSyncEnd, ppMode->HTotal, ppMode->VDisplay, + ppMode->VSyncStart,ppMode->VSyncEnd,ppMode->VTotal, + (double)mp->vbeData.block->PixelClock/1000000.0, + (double)mp->vbeData.block->RefreshRate/100); #endif - pMode = pMode->next; + pMode = ppMode = pMode->next; } while (pMode != pScrn->modes); + + if (pI830->MergedFB) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s\n", pI830->pScrn_2->monitor->id); + pMode = pScrn->modes; + do { + int clock; + + mp = (I830ModePrivatePtr) pMode->Private; + ppMode = (DisplayModePtr) mp->merged.Second; + mp = (I830ModePrivatePtr) mp->merged.Second->Private; + + mp->vbeData.block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); + mp->vbeData.block->HorizontalTotal = ppMode->HTotal; + mp->vbeData.block->HorizontalSyncStart = ppMode->HSyncStart; + mp->vbeData.block->HorizontalSyncEnd = ppMode->HSyncEnd; + mp->vbeData.block->VerticalTotal = ppMode->VTotal; + mp->vbeData.block->VerticalSyncStart = ppMode->VSyncStart; + mp->vbeData.block->VerticalSyncEnd = ppMode->VSyncEnd; + mp->vbeData.block->Flags = ((ppMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | + ((ppMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); + mp->vbeData.block->PixelClock = ppMode->Clock * 1000; + /* XXX May not have this. */ + clock = VBEGetPixelClock(pVbe, mp->vbeData.mode, mp->vbeData.block->PixelClock); + if (clock) + mp->vbeData.block->PixelClock = clock; +#ifdef DEBUG + ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", + (double)mp->vbeData.block->PixelClock / 1000000.0, + (double)clock / 1000000.0); +#endif + mp->vbeData.mode |= (1 << 11); + if (ppMode->VRefresh != 0) { + mp->vbeData.block->RefreshRate = ppMode->VRefresh * 100; + } else { + mp->vbeData.block->RefreshRate = (int)(((double)(mp->vbeData.block->PixelClock)/ + (double)(ppMode->HTotal * ppMode->VTotal)) * 100); + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attempting to use %2.2fHz refresh for mode \"%s\" (%x)\n", + (float)(((double)(mp->vbeData.block->PixelClock) / (double)(ppMode->HTotal * ppMode->VTotal))), ppMode->name, mp->vbeData.mode); +#ifdef DEBUG + ErrorF("Video Modeline: ID: 0x%x Name: %s %i %i %i %i - " + " %i %i %i %i %.2f MHz Refresh: %.2f Hz\n", + mp->vbeData.mode, ppMode->name, ppMode->HDisplay, ppMode->HSyncStart, + ppMode->HSyncEnd, ppMode->HTotal, ppMode->VDisplay, + ppMode->VSyncStart,ppMode->VSyncEnd,ppMode->VTotal, + (double)mp->vbeData.block->PixelClock/1000000.0, + (double)mp->vbeData.block->RefreshRate/100); +#endif + pMode = ppMode = pMode->next; + } while (pMode != pScrn->modes); + } } void diff --git a/src/i830_rotate.c b/src/i830_rotate.c index e57a0878..76effa29 100644 --- a/src/i830_rotate.c +++ b/src/i830_rotate.c @@ -404,7 +404,7 @@ I915UpdateRotate (ScreenPtr pScreen, if (pI830->disableTiling) use_fence = 0; else - use_fence = 4; + use_fence = MS3_USE_FENCE_REGS; if (pI830->cpp == 1) use_fence |= MAPSURF_8BIT; @@ -575,15 +575,15 @@ I830UpdateRotate (ScreenPtr pScreen, OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); OUT_RING(0x00000000); /* draw rect */ - OUT_RING(0x7d800003); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); - OUT_RING(0x00000000); - OUT_RING(0x00000000); + OUT_RING(_3DSTATE_DRAW_RECT_CMD); + OUT_RING(0x00000000); /* flags */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + OUT_RING(MI_NOOP); /* front buffer */ - OUT_RING(0x7d8e0001); + OUT_RING(_3DSTATE_BUF_INFO_CMD); OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); if (I830IsPrimary(pScrn)) OUT_RING(pI830->FrontBuffer.Start); @@ -736,12 +736,12 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) }; if (pI830->noAccel) - func = LoaderSymbol("shadowUpdateRotatePacked"); + func = LoaderSymbol("shadowUpdateRotatePacked"); else - if (IS_I9XX(pI830)) - func = I915UpdateRotate; - else - func = I830UpdateRotate; + if (IS_I9XX(pI830)) + func = I915UpdateRotate; + else + func = I830UpdateRotate; if (I830IsPrimary(pScrn)) { pI8301 = pI830; @@ -771,6 +771,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) * We grab the DRI lock when reallocating buffers to avoid DRI clients * getting bogus information. */ + #ifdef XF86DRI if (pI8301->directRenderingEnabled && reAllocate) { didLock = I830DRILock(pScrn1); @@ -789,6 +790,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) } } + if (pI8301->TexMem.Key != -1) xf86UnbindGARTMemory(pScrn1->scrnIndex, pI8301->TexMem.Key); I830FreeVidMem(pScrn1, &(pI8301->TexMem)); @@ -891,7 +893,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) if (pI8301->rotation != RR_Rotate_0) { if (!I830AllocateRotatedBuffer(pScrn1, - (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) goto BAIL1; I830FixOffset(pScrn1, &(pI8301->RotatedMem)); @@ -903,8 +905,8 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayModePtr mode) shadowRemove (pScrn->pScreen, NULL); if (pI830->rotation != RR_Rotate_0) shadowAdd (pScrn->pScreen, - (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), - func, I830WindowLinear, pI830->rotation, 0); + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); if (I830IsPrimary(pScrn)) { if (pI830->rotation != RR_Rotate_0) @@ -1105,7 +1107,7 @@ BAIL0: if (pI8301->rotation != RR_Rotate_0) { if (!I830AllocateRotatedBuffer(pScrn1, - (pI8301->disableTiling ? ALLOC_NO_TILING : 0))) + pI8301->disableTiling ? ALLOC_NO_TILING : 0)) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Oh dear, the rotated buffer failed - badness\n"); @@ -1117,8 +1119,8 @@ BAIL0: shadowRemove (pScrn->pScreen, NULL); if (pI830->rotation != RR_Rotate_0) shadowAdd (pScrn->pScreen, - (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), - func, I830WindowLinear, pI830->rotation, 0); + (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen), + func, I830WindowLinear, pI830->rotation, 0); if (I830IsPrimary(pScrn)) { if (pI830->rotation != RR_Rotate_0) diff --git a/src/i830_video.c b/src/i830_video.c index 41ab055f..1c5bf4eb 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -66,6 +66,7 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <math.h> #include <string.h> +#include <assert.h> #include "xf86.h" #include "xf86_OSproc.h" @@ -77,12 +78,15 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "regionstr.h" #include "randrstr.h" #include "i830.h" +#include "i830_video.h" #include "xf86xv.h" #include <X11/extensions/Xv.h> #include "xaa.h" #include "xaalocal.h" #include "dixstruct.h" #include "fourcc.h" +#include "brw_defines.h" +#include "brw_structs.h" #ifndef USE_USLEEP_FOR_VIDEO #define USE_USLEEP_FOR_VIDEO 0 @@ -99,7 +103,8 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. static void I830InitOffscreenImages(ScreenPtr); -static XF86VideoAdaptorPtr I830SetupImageVideo(ScreenPtr); +static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr); +static XF86VideoAdaptorPtr I830SetupImageVideoTextured(ScreenPtr); static void I830StopVideo(ScrnInfoPtr, pointer, Bool); static int I830SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); static int I830GetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); @@ -109,20 +114,30 @@ static void I830QueryBestSize(ScrnInfoPtr, Bool, static int I830PutImage(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char *, short, short, Bool, RegionPtr, pointer, DrawablePtr); -static int I830QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, - unsigned short *, int *, int *); +static int I830QueryImageAttributesOverlay(ScrnInfoPtr, int, unsigned short *, + unsigned short *, int *, int *); +static int I830QueryImageAttributesTextured(ScrnInfoPtr, int, unsigned short *, + unsigned short *, int *, int *); static void I830BlockHandler(int, pointer, pointer, pointer); +static FBLinearPtr +I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size); + #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) static Atom xvBrightness, xvContrast, xvColorKey, xvPipe, xvDoubleBuffer; static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH 1920 -#define IMAGE_MAX_HEIGHT 1088 +#define IMAGE_MAX_HEIGHT 1080 #define IMAGE_MAX_WIDTH_LEGACY 1024 -#define IMAGE_MAX_HEIGHT_LEGACY 1088 +#define IMAGE_MAX_HEIGHT_LEGACY 1080 + +/* + * Broadwater requires a bit of extra video memory for state information + */ +#define BRW_LINEAR_EXTRA (32*1024) #if !VIDEO_DEBUG #define ErrorF Edummy @@ -157,7 +172,10 @@ Edummy(const char *dummy, ...) OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ } \ - OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + if (IS_I965G(pI830)) \ + OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); \ + else \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ ADVANCE_LP_RING(); \ ErrorF("OVERLAY_UPDATE\n"); \ } while(0) @@ -172,11 +190,17 @@ Edummy(const char *dummy, ...) OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ - OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + if (IS_I965G(pI830)) \ + OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); \ + else \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \ - OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ + if (IS_I965G(pI830)) \ + OUT_RING(pI830->OverlayMem->Start | OFC_UPDATE); \ + else \ + OUT_RING(pI830->OverlayMem->Physical | OFC_UPDATE); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ @@ -286,6 +310,12 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} }; +#define NUM_TEXTURED_ATTRIBUTES 2 +static XF86AttributeRec TexturedAttributes[NUM_ATTRIBUTES] = { + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, +}; + #define GAMMA_ATTRIBUTES 6 static XF86AttributeRec GammaAttributes[GAMMA_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, @@ -334,18 +364,18 @@ typedef struct { CARD32 OCONFIG; CARD32 OCMD; CARD32 RESERVED1; /* 0x6C */ - CARD32 AWINPOS; - CARD32 AWINSZ; - CARD32 RESERVED2; /* 0x78 */ - CARD32 RESERVED3; /* 0x7C */ - CARD32 RESERVED4; /* 0x80 */ - CARD32 RESERVED5; /* 0x84 */ - CARD32 RESERVED6; /* 0x88 */ - CARD32 RESERVED7; /* 0x8C */ - CARD32 RESERVED8; /* 0x90 */ - CARD32 RESERVED9; /* 0x94 */ - CARD32 RESERVEDA; /* 0x98 */ - CARD32 RESERVEDB; /* 0x9C */ + CARD32 OSTART_0Y; /* for i965 */ + CARD32 OSTART_1Y; /* for i965 */ + CARD32 OSTART_0U; + CARD32 OSTART_0V; + CARD32 OSTART_1U; + CARD32 OSTART_1V; + CARD32 OTILEOFF_0Y; + CARD32 OTILEOFF_1Y; + CARD32 OTILEOFF_0U; + CARD32 OTILEOFF_0V; + CARD32 OTILEOFF_1U; + CARD32 OTILEOFF_1V; CARD32 FASTHSCALE; /* 0xA0 */ CARD32 UVSCALEV; /* 0xA4 */ @@ -360,45 +390,6 @@ typedef struct { CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; } I830OverlayRegRec, *I830OverlayRegPtr; -typedef struct { - CARD32 YBuf0offset; - CARD32 UBuf0offset; - CARD32 VBuf0offset; - - CARD32 YBuf1offset; - CARD32 UBuf1offset; - CARD32 VBuf1offset; - - unsigned char currentBuf; - - int brightness; - int contrast; - int pipe; - int doubleBuffer; - - RegionRec clip; - CARD32 colorKey; - - CARD32 gamma0; - CARD32 gamma1; - CARD32 gamma2; - CARD32 gamma3; - CARD32 gamma4; - CARD32 gamma5; - - CARD32 videoStatus; - Time offTime; - Time freeTime; - FBLinearPtr linear; - - Bool overlayOK; - int oneLineMode; - int scaleRatio; -} I830PortPrivRec, *I830PortPrivPtr; - -#define GET_PORT_PRIVATE(pScrn) \ - (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr) - #if VIDEO_DEBUG static void CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) @@ -424,8 +415,9 @@ void I830InitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; - XF86VideoAdaptorPtr newAdaptor = NULL; + XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; int num_adaptors; DPRINTF(PFX, "I830InitVideo\n"); @@ -444,35 +436,54 @@ I830InitVideo(ScreenPtr pScreen) } #endif - if (pScrn->bitsPerPixel != 8) { - newAdaptor = I830SetupImageVideo(pScreen); + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + /* Give our adaptor list enough space for the overlay and/or texture video + * adaptors. + */ + newAdaptors = xalloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); + if (newAdaptors == NULL) + return; + + memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + adaptors = newAdaptors; + + /* Add the adaptors supported by our hardware. First, set up the atoms + * that will be used by both output adaptors. + */ + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + + /* Set up overlay video if we can do it at this depth. */ + if (!IS_I965G(pI830) && pScrn->bitsPerPixel != 8) { + overlayAdaptor = I830SetupImageVideoOverlay(pScreen); + if (overlayAdaptor != NULL) { + adaptors[num_adaptors++] = overlayAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up overlay video\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up overlay video\n"); + } I830InitOffscreenImages(pScreen); } - num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); - - if (newAdaptor) { - if (!num_adaptors) { - num_adaptors = 1; - adaptors = &newAdaptor; + /* Set up textured video if we can do it at this depth and we are on + * supported hardware. + */ + if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830))) { + texturedAdaptor = I830SetupImageVideoTextured(pScreen); + if (texturedAdaptor != NULL) { + adaptors[num_adaptors++] = texturedAdaptor; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); } else { - newAdaptors = /* need to free this someplace */ - xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); - if (newAdaptors) { - memcpy(newAdaptors, adaptors, num_adaptors * - sizeof(XF86VideoAdaptorPtr)); - newAdaptors[num_adaptors] = newAdaptor; - adaptors = newAdaptors; - num_adaptors++; - } + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set up textured video\n"); } } if (num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); - if (newAdaptors) - xfree(newAdaptors); + xfree(adaptors); } static void @@ -501,8 +512,10 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->SHEIGHT = 0; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); overlay->OCLRC1 = 0x00000080; /* saturation: bypass */ +#if 0 overlay->AWINPOS = 0; overlay->AWINSZ = 0; +#endif overlay->FASTHSCALE = 0; /* @@ -642,7 +655,7 @@ I830UpdateGamma(ScrnInfoPtr pScrn) } static XF86VideoAdaptorPtr -I830SetupImageVideo(ScreenPtr pScreen) +I830SetupImageVideoOverlay(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); @@ -650,7 +663,7 @@ I830SetupImageVideo(ScreenPtr pScreen) I830PortPrivPtr pPriv; XF86AttributePtr att; - DPRINTF(PFX, "I830SetupImageVideo\n"); + DPRINTF(PFX, "I830SetupImageVideoOverlay\n"); if (!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(I830PortPrivRec) + sizeof(DevUnion)))) @@ -703,8 +716,9 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->GetPortAttribute = I830GetPortAttribute; adapt->QueryBestSize = I830QueryBestSize; adapt->PutImage = I830PutImage; - adapt->QueryImageAttributes = I830QueryImageAttributes; + adapt->QueryImageAttributes = I830QueryImageAttributesOverlay; + pPriv->textured = FALSE; pPriv->colorKey = pI830->colorKey & ((1 << pScrn->depth) - 1); pPriv->videoStatus = 0; pPriv->brightness = 0; @@ -742,8 +756,6 @@ I830SetupImageVideo(ScreenPtr pScreen) pScreen->BlockHandler = I830BlockHandler; xvColorKey = MAKE_ATOM("XV_COLORKEY"); - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvContrast = MAKE_ATOM("XV_CONTRAST"); xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); /* Allow the pipe to be switched from pipe A to B when in clone mode */ @@ -766,6 +778,86 @@ I830SetupImageVideo(ScreenPtr pScreen) return adapt; } +static XF86VideoAdaptorPtr +I830SetupImageVideoTextured(ScreenPtr pScreen) +{ + XF86VideoAdaptorPtr adapt; + XF86VideoEncodingPtr encoding; + XF86AttributePtr attrs; + I830PortPrivPtr portPrivs; + DevUnion *devUnions; + int nports = 16, i; + int nAttributes; + + DPRINTF(PFX, "I830SetupImageVideoOverlay\n"); + + nAttributes = NUM_TEXTURED_ATTRIBUTES; + + adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec)); + portPrivs = xcalloc(nports, sizeof(I830PortPrivRec)); + devUnions = xcalloc(nports, sizeof(DevUnion)); + encoding = xcalloc(1, sizeof(XF86VideoEncodingRec)); + attrs = xcalloc(nAttributes, sizeof(XF86AttributeRec)); + if (adapt == NULL || portPrivs == NULL || devUnions == NULL || + encoding == NULL || attrs == NULL) + { + xfree(adapt); + xfree(portPrivs); + xfree(devUnions); + xfree(encoding); + xfree(attrs); + return NULL; + } + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "Intel(R) Textured Video"; + adapt->nEncodings = 1; + adapt->pEncodings = encoding; + adapt->pEncodings[0].id = 0; + adapt->pEncodings[0].name = "XV_IMAGE"; + adapt->pEncodings[0].width = 2048; + adapt->pEncodings[0].height = 2048; + adapt->pEncodings[0].rate.numerator = 1; + adapt->pEncodings[0].rate.denominator = 1; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = nports; + adapt->pPortPrivates = devUnions; + adapt->nAttributes = nAttributes; + adapt->pAttributes = attrs; + memcpy(attrs, TexturedAttributes, nAttributes * sizeof(XF86AttributeRec)); + adapt->nImages = NUM_IMAGES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = I830StopVideo; + adapt->SetPortAttribute = I830SetPortAttribute; + adapt->GetPortAttribute = I830GetPortAttribute; + adapt->QueryBestSize = I830QueryBestSize; + adapt->PutImage = I830PutImage; + adapt->QueryImageAttributes = I830QueryImageAttributesTextured; + + for (i = 0; i < nports; i++) { + I830PortPrivPtr pPriv = &portPrivs[i]; + + pPriv->textured = TRUE; + pPriv->videoStatus = 0; + pPriv->linear = NULL; + pPriv->currentBuf = 0; + pPriv->doubleBuffer = 0; + + /* gotta uninit this someplace, XXX: shouldn't be necessary for textured */ + REGION_NULL(pScreen, &pPriv->clip); + + adapt->pPortPrivates[i].ptr = (pointer) (pPriv); + } + + return adapt; +} + static Bool RegionsEqual(RegionPtr A, RegionPtr B) { @@ -803,6 +895,9 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + if (pPriv->textured) + return; + DPRINTF(PFX, "I830StopVideo\n"); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); @@ -842,6 +937,14 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); + if (pPriv->textured) { + /* XXX: Currently the brightness/saturation attributes aren't hooked up. + * However, apps expect them to be there, and the spec seems to let us + * sneak out of actually implementing them for now. + */ + return Success; + } + if (attribute == xvBrightness) { if ((value < -128) || (value > 127)) return BadValue; @@ -994,13 +1097,12 @@ I830QueryBestSize(ScrnInfoPtr pScrn, } static void -I830CopyPackedData(ScrnInfoPtr pScrn, +I830CopyPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, unsigned char *buf, int srcPitch, int dstPitch, int top, int left, int h, int w) { I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; unsigned char *src, *dst; int i,j; unsigned char *s; @@ -1088,13 +1190,72 @@ I830CopyPackedData(ScrnInfoPtr pScrn, } } +/* Copies planar data in *buf to UYVY-packed data in the screen atYBufXOffset. + */ +static void +I830CopyPlanarToPackedData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + unsigned char *buf, int srcPitch, + int srcPitch2, int dstPitch, int srcH, + int top, int left, int h, int w, int id) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD8 *dst1, *srcy, *srcu, *srcv; + int y; + + if (pPriv->currentBuf == 0) + dst1 = pI830->FbBase + pPriv->YBuf0offset; + else + dst1 = pI830->FbBase + pPriv->YBuf1offset; + + srcy = buf + (top * srcPitch) + left; + if (id == FOURCC_YV12) { + srcu = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2); + srcv = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) + + ((top / 2) * srcPitch2) + (left / 2); + } else { + srcv = buf + (srcH * srcPitch) + ((top / 2) * srcPitch2) + (left / 2); + srcu = buf + (srcH * srcPitch) + ((srcH / 2) * srcPitch2) + + ((top / 2) * srcPitch2) + (left / 2); + } + + for (y = 0; y < h; y++) { + CARD32 *dst = (CARD32 *)dst1; + CARD8 *sy = srcy; + CARD8 *su = srcu; + CARD8 *sv = srcv; + int i; + + i = w / 2; + while(i > 4) { + dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24); + dst[1] = sy[2] | (sy[3] << 16) | (sv[1] << 8) | (su[1] << 24); + dst[2] = sy[4] | (sy[5] << 16) | (sv[2] << 8) | (su[2] << 24); + dst[3] = sy[6] | (sy[7] << 16) | (sv[3] << 8) | (su[3] << 24); + dst += 4; su += 4; sv += 4; sy += 8; + i -= 4; + } + while(i--) { + dst[0] = sy[0] | (sy[1] << 16) | (sv[0] << 8) | (su[0] << 24); + dst++; su++; sv++; + sy += 2; + } + + dst1 += dstPitch; + srcy += srcPitch; + if (y & 1) { + srcu += srcPitch2; + srcv += srcPitch2; + } + } +} + static void -I830CopyPlanarData(ScrnInfoPtr pScrn, unsigned char *buf, int srcPitch, +I830CopyPlanarData(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + unsigned char *buf, int srcPitch, int srcPitch2, int dstPitch, int srcH, int top, int left, int h, int w, int id) { I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; int i, j = 0; unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; unsigned char *s; @@ -1400,6 +1561,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, unsigned int swidth; unsigned int mask, shift, offsety, offsetu; int tmp; + BoxRec dstBox2; ErrorF("I830DisplayVideo: %dx%d (pitch %d)\n", width, height, dstPitch); @@ -1411,21 +1573,24 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, CompareOverlay(pI830, (CARD32 *) overlay, 0x100); #endif - /* When in dual head with different bpp setups we need to refresh the - * color key, so let's reset the video parameters and refresh here */ - if (pI830->entityPrivate) - I830ResetVideo(pScrn); - - /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ - if (!*pI830->overlayOn) - OVERLAY_UPDATE; - switch (pI830->rotation) { case RR_Rotate_0: - dstBox->x1 -= pScrn->frameX0; - dstBox->x2 -= pScrn->frameX0; - dstBox->y1 -= pScrn->frameY0; - dstBox->y2 -= pScrn->frameY0; + if (pI830->MergedFB) { + memcpy(&dstBox2, dstBox, sizeof(BoxRec)); + dstBox->x1 -= pI830->FirstframeX0; + dstBox->x2 -= pI830->FirstframeX0; + dstBox->y1 -= pI830->FirstframeY0; + dstBox->y2 -= pI830->FirstframeY0; + dstBox2.x1 -= pI830->pScrn_2->frameX0; + dstBox2.x2 -= pI830->pScrn_2->frameX0; + dstBox2.y1 -= pI830->pScrn_2->frameY0; + dstBox2.y2 -= pI830->pScrn_2->frameY0; + } else { + dstBox->x1 -= pScrn->frameX0; + dstBox->x2 -= pScrn->frameX0; + dstBox->y1 -= pScrn->frameY0; + dstBox->y2 -= pScrn->frameY0; + } break; case RR_Rotate_90: tmp = dstBox->x1; @@ -1459,6 +1624,72 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, break; } + if (pI830->MergedFB) { + I830ModePrivatePtr mp = (I830ModePrivatePtr)pScrn->currentMode->Private; + int w1, h1, w2, h2; + + /* Clip the video to the independent modes of the merged screens */ + if (dstBox->x1 > mp->merged.First->HDisplay) dstBox->x1 = mp->merged.First->HDisplay - 1; + if (dstBox->x2 > mp->merged.First->HDisplay) dstBox->x2 = mp->merged.First->HDisplay - 1; + if (dstBox2.x1 > mp->merged.Second->HDisplay) dstBox2.x1 = mp->merged.Second->HDisplay - 1; + if (dstBox2.x2 > mp->merged.Second->HDisplay) dstBox2.x2 = mp->merged.Second->HDisplay - 1; + if (dstBox->y1 > mp->merged.First->VDisplay) dstBox->y1 = mp->merged.First->VDisplay - 1; + if (dstBox->y2 > mp->merged.First->VDisplay) dstBox->y2 = mp->merged.First->VDisplay - 1; + if (dstBox2.y1 > mp->merged.Second->VDisplay) dstBox2.y1 = mp->merged.Second->VDisplay - 1; + if (dstBox2.y2 > mp->merged.Second->VDisplay) dstBox2.y2 = mp->merged.Second->VDisplay - 1; + if (dstBox->y1 < 0) dstBox->y1 = 0; + if (dstBox->y2 < 0) dstBox->y2 = 0; + if (dstBox->x1 < 0) dstBox->x1 = 0; + if (dstBox->x2 < 0) dstBox->x2 = 0; + if (dstBox2.y1 < 0) dstBox2.y1 = 0; + if (dstBox2.y2 < 0) dstBox2.y2 = 0; + if (dstBox2.x1 < 0) dstBox2.x1 = 0; + if (dstBox2.x2 < 0) dstBox2.x2 = 0; + + w1 = dstBox->x2 - dstBox->x1; + w2 = dstBox2.x2 - dstBox2.x1; + h1 = dstBox->y2 - dstBox->y1; + h2 = dstBox2.y2 - dstBox2.y1; + + switch (pI830->SecondPosition) { + case PosRightOf: + case PosBelow: + if ((w2 > 0 && w1 == 0) || + (h2 > 0 && h1 == 0)) { + pPriv->pipe = !pI830->pipe; + dstBox->x1 = dstBox2.x1; + dstBox->y1 = dstBox2.y1; + dstBox->x2 = dstBox2.x2; + dstBox->y2 = dstBox2.y2; + } else + pPriv->pipe = pI830->pipe; + break; + case PosLeftOf: + case PosAbove: + if ((w1 > 0 && w2 == 0) || + (h1 > 0 && h2 == 0)) { + pPriv->pipe = pI830->pipe; + } else { + pPriv->pipe = !pI830->pipe; + dstBox->x1 = dstBox2.x1; + dstBox->y1 = dstBox2.y1; + dstBox->x2 = dstBox2.x2; + dstBox->y2 = dstBox2.y2; + } + break; + } + } + + /* When in dual head with different bpp setups we need to refresh the + * color key, so let's reset the video parameters and refresh here. + * In MergedFB mode, we may need to flip pipes too. */ + if (pI830->entityPrivate || pI830->MergedFB) + I830ResetVideo(pScrn); + + /* Ensure overlay is turned on with OVERLAY_ENABLE at 0 */ + if (!*pI830->overlayOn) + OVERLAY_UPDATE; + /* Fix up the dstBox if outside the visible screen */ { int offset_x = (dstBox->x1 < 0) ? -dstBox->x1 : 0; @@ -1522,7 +1753,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, /* Keep the engine happy and clip to the real vertical size just * in case an LFP is in use and it's not at it's native resolution. */ - int vactive = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + int vactive = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); vactive += 1; @@ -1647,14 +1878,31 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, dstBox->x2, dstBox->y2); /* buffer locations */ - overlay->OBUF_0Y = pPriv->YBuf0offset; - overlay->OBUF_0U = pPriv->UBuf0offset; - overlay->OBUF_0V = pPriv->VBuf0offset; - - if(pPriv->doubleBuffer) { - overlay->OBUF_1Y = pPriv->YBuf1offset; - overlay->OBUF_1U = pPriv->UBuf1offset; - overlay->OBUF_1V = pPriv->VBuf1offset; + if (IS_I965G(pI830)) + { + overlay->OBUF_0Y = 0; + overlay->OBUF_0U = 0; + overlay->OBUF_0V = 0; + overlay->OSTART_0Y = pPriv->YBuf0offset; + overlay->OSTART_0U = pPriv->UBuf0offset; + overlay->OSTART_0V = pPriv->VBuf0offset; + if(pPriv->doubleBuffer) { + overlay->OBUF_1Y = 0; + overlay->OBUF_1U = 0; + overlay->OBUF_1V = 0; + overlay->OSTART_1Y = pPriv->YBuf1offset; + overlay->OSTART_1U = pPriv->UBuf1offset; + overlay->OSTART_1V = pPriv->VBuf1offset; + } + } else { + overlay->OBUF_0Y = pPriv->YBuf0offset; + overlay->OBUF_0U = pPriv->UBuf0offset; + overlay->OBUF_0V = pPriv->VBuf0offset; + if(pPriv->doubleBuffer) { + overlay->OBUF_1Y = pPriv->YBuf1offset; + overlay->OBUF_1U = pPriv->UBuf1offset; + overlay->OBUF_1V = pPriv->VBuf1offset; + } } ErrorF("Buffers: Y0: 0x%lx, U0: 0x%lx, V0: 0x%lx\n", overlay->OBUF_0Y, @@ -1847,6 +2095,827 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, OVERLAY_UPDATE; } +static const CARD32 sip_kernel_static[][4] = { +/* wait (1) a0<1>UW a145<0,1,0>UW { align1 + } */ + { 0x00000030, 0x20000108, 0x00001220, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +}; + +/* + * this program computes dA/dx and dA/dy for the texture coordinates along + * with the base texture coordinate. It was extracted from the Mesa driver. + * It uses about 10 GRF registers. + */ + +#define SF_KERNEL_NUM_GRF 16 +#define SF_MAX_THREADS 1 + +static const CARD32 sf_kernel_static[][4] = { +/* send 0 (1) g6<1>F g1.12<0,1,0>F math mlen 1 rlen 1 { align1 + } */ + { 0x00000031, 0x20c01fbd, 0x0000002c, 0x01110081 }, +/* send 0 (1) g6.4<1>F g1.20<0,1,0>F math mlen 1 rlen 1 { align1 + } */ + { 0x00000031, 0x20c41fbd, 0x00000034, 0x01110081 }, +/* add (8) g7<1>F g4<8,8,1>F g3<8,8,1>F { align1 + } */ + { 0x00600040, 0x20e077bd, 0x008d0080, 0x008d4060 }, +/* mul (1) g7<1>F g7<0,1,0>F g6<0,1,0>F { align1 + } */ + { 0x00000041, 0x20e077bd, 0x000000e0, 0x000000c0 }, +/* mul (1) g7.4<1>F g7.4<0,1,0>F g6.4<0,1,0>F { align1 + } */ + { 0x00000041, 0x20e477bd, 0x000000e4, 0x000000c4 }, +/* mov (8) m1<1>F g7<0,1,0>F { align1 + } */ + { 0x00600001, 0x202003be, 0x000000e0, 0x00000000 }, +/* mov (8) m2<1>F g7.4<0,1,0>F { align1 + } */ + { 0x00600001, 0x204003be, 0x000000e4, 0x00000000 }, +/* mov (8) m3<1>F g3<8,8,1>F { align1 + } */ + { 0x00600001, 0x206003be, 0x008d0060, 0x00000000 }, +/* send 0 (8) a0<1>F g0<8,8,1>F urb mlen 4 rlen 0 write +0 transpose used complete EOT{ align1 + } */ + { 0x00600031, 0x20001fbc, 0x008d0000, 0x8640c800 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +}; + +/* + * Ok, this kernel picks up the required data flow values in g0 and g1 + * and passes those along in m0 and m1. In m2-m9, it sticks constant + * values (bright pink). + */ + +/* Our PS kernel uses less than 32 GRF registers (about 20) */ +#define PS_KERNEL_NUM_GRF 32 +#define PS_MAX_THREADS 32 + +#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) + +static const CARD32 ps_kernel_static[][4] = { +#include "wm_prog.h" +}; + +#define ALIGN(i,m) (((i) + (m) - 1) & ~((m) - 1)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define WM_BINDING_TABLE_ENTRIES 2 + +static CARD32 float_to_uint (float f) { + union {CARD32 i; float f;} x; + x.f = f; + return x.i; +} + +#if 0 +static struct { + CARD32 svg_ctl; + char *name; +} svg_ctl_bits[] = { + { BRW_SVG_CTL_GS_BA, "General State Base Address" }, + { BRW_SVG_CTL_SS_BA, "Surface State Base Address" }, + { BRW_SVG_CTL_IO_BA, "Indirect Object Base Address" }, + { BRW_SVG_CTL_GS_AUB, "Generate State Access Upper Bound" }, + { BRW_SVG_CTL_IO_AUB, "Indirect Object Access Upper Bound" }, + { BRW_SVG_CTL_SIP, "System Instruction Pointer" }, + { 0, 0 }, +}; + +static void +brw_debug (ScrnInfoPtr pScrn, char *when) +{ + I830Ptr pI830 = I830PTR(pScrn); + int i; + CARD32 v; + + I830Sync (pScrn); + ErrorF("brw_debug: %s\n", when); + for (i = 0; svg_ctl_bits[i].name; i++) { + OUTREG(BRW_SVG_CTL, svg_ctl_bits[i].svg_ctl); + v = INREG(BRW_SVG_RDATA); + ErrorF("\t%34.34s: 0x%08x\n", svg_ctl_bits[i].name, v); + } +} +#endif + +#define WATCH_SF 0 +#define WATCH_WIZ 0 +#define WATCH_STATS 0 + +static void +BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, + RegionPtr dstRegion, + short width, short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + DrawablePtr pDraw) +{ + I830Ptr pI830 = I830PTR(pScrn); + BoxPtr pbox; + int nbox, dxo, dyo; + int urb_vs_start, urb_vs_size; + int urb_gs_start, urb_gs_size; + int urb_clip_start, urb_clip_size; + int urb_sf_start, urb_sf_size; + int urb_cs_start, urb_cs_size; + struct brw_surface_state *dest_surf_state; + struct brw_surface_state *src_surf_state; + struct brw_sampler_state *src_sampler_state; + struct brw_vs_unit_state *vs_state; + struct brw_sf_unit_state *sf_state; + struct brw_wm_unit_state *wm_state; + struct brw_cc_unit_state *cc_state; + struct brw_cc_viewport *cc_viewport; + struct brw_instruction *sf_kernel; + struct brw_instruction *ps_kernel; + struct brw_instruction *sip_kernel; + float *vb; + CARD32 *binding_table; + Bool first_output = TRUE; + int dest_surf_offset, src_surf_offset, src_sampler_offset, vs_offset; + int sf_offset, wm_offset, cc_offset, vb_offset, cc_viewport_offset; + int wm_scratch_offset; + int sf_kernel_offset, ps_kernel_offset, sip_kernel_offset; + int binding_table_offset; + int next_offset, total_state_size; + int vb_size = (4 * 4) * 4; /* 4 DWORDS per vertex */ + char *state_base; + int state_base_offset; + +#if 0 + ErrorF("BroadwaterDisplayVideoTextured: %dx%d (pitch %d)\n", width, height, + video_pitch); +#endif + + /* enable debug */ + OUTREG (INST_PM, + (1 << (16 + 4)) | + (1 << 4)); +#if 0 + ErrorF ("INST_PM 0x%08x\n", INREG(INST_PM)); +#endif + + assert((id == FOURCC_UYVY) || (id == FOURCC_YUY2)); + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so we + * don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; + +#ifdef XF86DRI + /* Tell the DRI that we're smashing its state. */ + if (pI830->directRenderingEnabled) { + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + } +#endif /* XF86DRI */ + + next_offset = 0; + + /* Set up our layout of state in framebuffer. First the general state: */ + vs_offset = ALIGN(next_offset, 64); + next_offset = vs_offset + sizeof(*vs_state); + sf_offset = ALIGN(next_offset, 32); + next_offset = sf_offset + sizeof(*sf_state); + wm_offset = ALIGN(next_offset, 32); + next_offset = wm_offset + sizeof(*wm_state); + wm_scratch_offset = ALIGN(next_offset, 1024); + next_offset = wm_scratch_offset + 1024 * PS_MAX_THREADS; + cc_offset = ALIGN(next_offset, 32); + next_offset = cc_offset + sizeof(*cc_state); + + sf_kernel_offset = ALIGN(next_offset, 64); + next_offset = sf_kernel_offset + sizeof (sf_kernel_static); + ps_kernel_offset = ALIGN(next_offset, 64); + next_offset = ps_kernel_offset + sizeof (ps_kernel_static); + sip_kernel_offset = ALIGN(next_offset, 64); + next_offset = sip_kernel_offset + sizeof (sip_kernel_static); + cc_viewport_offset = ALIGN(next_offset, 32); + next_offset = cc_viewport_offset + sizeof(*cc_viewport); + + src_sampler_offset = ALIGN(next_offset, 32); + next_offset = src_sampler_offset + sizeof(*src_sampler_state); + + /* Align VB to native size of elements, for safety */ + vb_offset = ALIGN(next_offset, 8); + next_offset = vb_offset + vb_size; + + /* And then the general state: */ + dest_surf_offset = ALIGN(next_offset, 32); + next_offset = dest_surf_offset + sizeof(*dest_surf_state); + src_surf_offset = ALIGN(next_offset, 32); + next_offset = src_surf_offset + sizeof(*src_surf_state); + binding_table_offset = ALIGN(next_offset, 32); + next_offset = binding_table_offset + (WM_BINDING_TABLE_ENTRIES * 4); + + /* Allocate an area in framebuffer for our state layout we just set up */ + total_state_size = next_offset; + assert (total_state_size < BRW_LINEAR_EXTRA); + + /* + * Use the extra space allocated at the end of the Xv buffer + */ + state_base_offset = (pPriv->YBuf0offset + + pPriv->linear->size * pI830->cpp - + BRW_LINEAR_EXTRA); + state_base_offset = ALIGN(state_base_offset, 64); + + state_base = (char *)(pI830->FbBase + state_base_offset); + /* Set up our pointers to state structures in framebuffer. It would probably + * be a good idea to fill these structures out in system memory and then dump + * them there, instead. + */ + vs_state = (void *)(state_base + vs_offset); + sf_state = (void *)(state_base + sf_offset); + wm_state = (void *)(state_base + wm_offset); + cc_state = (void *)(state_base + cc_offset); + sf_kernel = (void *)(state_base + sf_kernel_offset); + ps_kernel = (void *)(state_base + ps_kernel_offset); + sip_kernel = (void *)(state_base + sip_kernel_offset); + + cc_viewport = (void *)(state_base + cc_viewport_offset); + dest_surf_state = (void *)(state_base + dest_surf_offset); + src_surf_state = (void *)(state_base + src_surf_offset); + src_sampler_state = (void *)(state_base + src_sampler_offset); + binding_table = (void *)(state_base + binding_table_offset); + vb = (void *)(state_base + vb_offset); + + /* For 3D, the VS must have 8, 12, 16, 24, or 32 VUEs allocated to it. + * A VUE consists of a 256-bit vertex header followed by the vertex data, + * which in our case is 4 floats (128 bits), thus a single 512-bit URB + * entry. + */ +#define URB_VS_ENTRIES 8 +#define URB_VS_ENTRY_SIZE 1 + +#define URB_GS_ENTRIES 0 +#define URB_GS_ENTRY_SIZE 0 + +#define URB_CLIP_ENTRIES 0 +#define URB_CLIP_ENTRY_SIZE 0 + + /* The SF kernel we use outputs only 4 256-bit registers, leading to an + * entry size of 2 512-bit URBs. We don't need to have many entries to + * output as we're generally working on large rectangles and don't care + * about having WM threads running on different rectangles simultaneously. + */ +#define URB_SF_ENTRIES 1 +#define URB_SF_ENTRY_SIZE 2 + +#define URB_CS_ENTRIES 0 +#define URB_CS_ENTRY_SIZE 0 + + urb_vs_start = 0; + urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; + urb_gs_start = urb_vs_start + urb_vs_size; + urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; + urb_clip_start = urb_gs_start + urb_gs_size; + urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; + urb_sf_start = urb_clip_start + urb_clip_size; + urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; + urb_cs_start = urb_sf_start + urb_sf_size; + urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; + + /* We'll be poking the state buffers that could be in use by the 3d hardware + * here, but we should have synced the 3D engine already in I830PutImage. + */ + + memset (cc_viewport, 0, sizeof (*cc_viewport)); + cc_viewport->min_depth = -1.e35; + cc_viewport->max_depth = 1.e35; + + /* Color calculator state */ + memset(cc_state, 0, sizeof(*cc_state)); + cc_state->cc0.stencil_enable = 0; /* disable stencil */ + cc_state->cc2.depth_test = 0; /* disable depth test */ + cc_state->cc2.logicop_enable = 1; /* enable logic op */ + cc_state->cc3.ia_blend_enable = 1; /* blend alpha just like colors */ + cc_state->cc3.blend_enable = 0; /* disable color blend */ + cc_state->cc3.alpha_test = 0; /* disable alpha test */ + cc_state->cc4.cc_viewport_state_offset = (state_base_offset + cc_viewport_offset) >> 5; + cc_state->cc5.dither_enable = 0; /* disable dither */ + cc_state->cc5.logicop_func = 0xc; /* WHITE */ + cc_state->cc5.statistics_enable = 1; + cc_state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; + cc_state->cc5.ia_src_blend_factor = BRW_BLENDFACTOR_ONE; + cc_state->cc5.ia_dest_blend_factor = BRW_BLENDFACTOR_ONE; + + /* Upload system kernel */ + memcpy (sip_kernel, sip_kernel_static, sizeof (sip_kernel_static)); + + /* Set up the state buffer for the destination surface */ + memset(dest_surf_state, 0, sizeof(*dest_surf_state)); + dest_surf_state->ss0.surface_type = BRW_SURFACE_2D; + dest_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; + if (pI830->cpp == 2) { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; + } else { + dest_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; + } + dest_surf_state->ss0.writedisable_alpha = 0; + dest_surf_state->ss0.writedisable_red = 0; + dest_surf_state->ss0.writedisable_green = 0; + dest_surf_state->ss0.writedisable_blue = 0; + dest_surf_state->ss0.color_blend = 1; + dest_surf_state->ss0.vert_line_stride = 0; + dest_surf_state->ss0.vert_line_stride_ofs = 0; + dest_surf_state->ss0.mipmap_layout_mode = 0; + dest_surf_state->ss0.render_cache_read_mode = 0; + + dest_surf_state->ss1.base_addr = pI830->FrontBuffer.Start; + dest_surf_state->ss2.height = pScrn->virtualY - 1; + dest_surf_state->ss2.width = pScrn->virtualX - 1; + dest_surf_state->ss2.mip_count = 0; + dest_surf_state->ss2.render_target_rotation = 0; + dest_surf_state->ss3.pitch = (pI830->displayWidth * pI830->cpp) - 1; + + /* Set up the source surface state buffer */ + memset(src_surf_state, 0, sizeof(*src_surf_state)); + src_surf_state->ss0.surface_type = BRW_SURFACE_2D; +/* src_surf_state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; */ + switch (id) { + case FOURCC_YUY2: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + src_surf_state->ss0.surface_format = BRW_SURFACEFORMAT_YCRCB_SWAPY; + break; + } + src_surf_state->ss0.writedisable_alpha = 0; + src_surf_state->ss0.writedisable_red = 0; + src_surf_state->ss0.writedisable_green = 0; + src_surf_state->ss0.writedisable_blue = 0; + src_surf_state->ss0.color_blend = 1; + src_surf_state->ss0.vert_line_stride = 0; + src_surf_state->ss0.vert_line_stride_ofs = 0; + src_surf_state->ss0.mipmap_layout_mode = 0; + src_surf_state->ss0.render_cache_read_mode = 0; + + src_surf_state->ss1.base_addr = pPriv->YBuf0offset; + src_surf_state->ss2.width = width - 1; + src_surf_state->ss2.height = height - 1; + src_surf_state->ss2.mip_count = 0; + src_surf_state->ss2.render_target_rotation = 0; + src_surf_state->ss3.pitch = video_pitch - 1; + + /* Set up a binding table for our two surfaces. Only the PS will use it */ + /* XXX: are these offset from the right place? */ + binding_table[0] = state_base_offset + dest_surf_offset; + binding_table[1] = state_base_offset + src_surf_offset; + + /* Set up the packed YUV source sampler. Doesn't do colorspace conversion. + */ + memset(src_sampler_state, 0, sizeof(*src_sampler_state)); + src_sampler_state->ss0.min_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss0.mag_filter = BRW_MAPFILTER_LINEAR; + src_sampler_state->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + src_sampler_state->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; + + /* Set up the vertex shader to be disabled (passthrough) */ + memset(vs_state, 0, sizeof(*vs_state)); + vs_state->thread4.nr_urb_entries = URB_VS_ENTRIES; + vs_state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; + vs_state->vs6.vs_enable = 0; + vs_state->vs6.vert_cache_disable = 1; + + /* Set up the SF kernel to do coord interp: for each attribute, + * calculate dA/dx and dA/dy. Hand these interpolation coefficients + * back to SF which then hands pixels off to WM. + */ + + memcpy (sf_kernel, sf_kernel_static, sizeof (sf_kernel_static)); + memset(sf_state, 0, sizeof(*sf_state)); +#if 0 + ErrorF ("sf kernel: 0x%08x\n", state_base_offset + sf_kernel_offset); +#endif + sf_state->thread0.kernel_start_pointer = + (state_base_offset + sf_kernel_offset) >> 6; + sf_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(SF_KERNEL_NUM_GRF); + sf_state->sf1.single_program_flow = 1; /* XXX */ + sf_state->sf1.binding_table_entry_count = 0; + sf_state->sf1.thread_priority = 0; + sf_state->sf1.floating_point_mode = 0; /* Mesa does this */ + sf_state->sf1.illegal_op_exception_enable = 1; + sf_state->sf1.mask_stack_exception_enable = 1; + sf_state->sf1.sw_exception_enable = 1; + sf_state->thread2.per_thread_scratch_space = 0; + sf_state->thread2.scratch_space_base_pointer = 0; /* not used in our kernel */ + sf_state->thread3.const_urb_entry_read_length = 0; /* no const URBs */ + sf_state->thread3.const_urb_entry_read_offset = 0; /* no const URBs */ + sf_state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ + sf_state->thread3.urb_entry_read_offset = 0; + sf_state->thread3.dispatch_grf_start_reg = 3; + sf_state->thread4.max_threads = SF_MAX_THREADS - 1; + sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; + sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES; + sf_state->thread4.stats_enable = 1; + sf_state->sf5.viewport_transform = FALSE; /* skip viewport */ + sf_state->sf6.cull_mode = BRW_CULLMODE_NONE; + sf_state->sf6.scissor = 0; + sf_state->sf7.trifan_pv = 2; + sf_state->sf6.dest_org_vbias = 0x8; + sf_state->sf6.dest_org_hbias = 0x8; + + memcpy (ps_kernel, ps_kernel_static, sizeof (ps_kernel_static)); +#if 0 + ErrorF ("ps kernel: 0x%08x\n", state_base_offset + ps_kernel_offset); +#endif + memset (wm_state, 0, sizeof (*wm_state)); + wm_state->thread0.kernel_start_pointer = + (state_base_offset + ps_kernel_offset) >> 6; + wm_state->thread0.grf_reg_count = BRW_GRF_BLOCKS(PS_KERNEL_NUM_GRF); + wm_state->thread1.single_program_flow = 1; /* XXX */ + wm_state->thread1.binding_table_entry_count = 2; + /* Though we never use the scratch space in our WM kernel, it has to be + * set, and the minimum allocation is 1024 bytes. + */ + wm_state->thread2.scratch_space_base_pointer = (state_base_offset + + wm_scratch_offset) >> 10; + wm_state->thread2.per_thread_scratch_space = 0; /* 1024 bytes */ + wm_state->thread3.dispatch_grf_start_reg = 3; /* XXX */ + wm_state->thread3.const_urb_entry_read_length = 0; + wm_state->thread3.const_urb_entry_read_offset = 0; + wm_state->thread3.urb_entry_read_length = 1; /* XXX */ + wm_state->thread3.urb_entry_read_offset = 0; /* XXX */ + wm_state->wm4.stats_enable = 1; + wm_state->wm4.sampler_state_pointer = (state_base_offset + src_sampler_offset) >> 5; + wm_state->wm4.sampler_count = 1; /* 1-4 samplers used */ + wm_state->wm5.max_threads = PS_MAX_THREADS - 1; + wm_state->wm5.thread_dispatch_enable = 1; + wm_state->wm5.enable_16_pix = 1; + wm_state->wm5.enable_8_pix = 0; + wm_state->wm5.early_depth_test = 1; + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | + MI_STATE_INSTRUCTION_CACHE_FLUSH | + BRW_MI_GLOBAL_SNAPSHOT_RESET); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } + +/* brw_debug (pScrn, "before base address modify"); */ + { BEGIN_LP_RING(12); + /* Match Mesa driver setup */ + OUT_RING(BRW_PIPELINE_SELECT | PIPELINE_SELECT_3D); + + /* Mesa does this. Who knows... */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING((0 << 4) | /* URB Entry Allocation Size */ + (0 << 0)); /* Number of URB Entries */ + + /* Zero out the two base address registers so all offsets are absolute */ + OUT_RING(BRW_STATE_BASE_ADDRESS | 4); + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Generate state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* Surface state base address */ + OUT_RING(0 | BASE_ADDRESS_MODIFY); /* media base addr, don't care */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* general state max addr, disabled */ + OUT_RING(0x10000000 | BASE_ADDRESS_MODIFY); /* media object state max addr, disabled */ + + /* Set system instruction pointer */ + OUT_RING(BRW_STATE_SIP | 0); + OUT_RING(state_base_offset + sip_kernel_offset); /* system instruction pointer */ + + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); } + +/* brw_debug (pScrn, "after base address modify"); */ + + { BEGIN_LP_RING(42); + /* Enable VF statistics */ + OUT_RING(BRW_3DSTATE_VF_STATISTICS | 1); + + /* Pipe control */ + OUT_RING(BRW_PIPE_CONTROL | + BRW_PIPE_CONTROL_NOWRITE | + BRW_PIPE_CONTROL_IS_FLUSH | + 2); + OUT_RING(0); /* Destination address */ + OUT_RING(0); /* Immediate data low DW */ + OUT_RING(0); /* Immediate data high DW */ + + /* Binding table pointers */ + OUT_RING(BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); + OUT_RING(0); /* vs */ + OUT_RING(0); /* gs */ + OUT_RING(0); /* clip */ + OUT_RING(0); /* sf */ + /* Only the PS uses the binding table */ + OUT_RING(state_base_offset + binding_table_offset); /* ps */ + + /* Blend constant color (magenta is fun) */ + OUT_RING(BRW_3DSTATE_CONSTANT_COLOR | 3); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (0.0)); + OUT_RING(float_to_uint (1.0)); + OUT_RING(float_to_uint (1.0)); + + /* The drawing rectangle clipping is always on. Set it to values that + * shouldn't do any clipping. + */ + OUT_RING(BRW_3DSTATE_DRAWING_RECTANGLE | 2); /* XXX 3 for BLC or CTG */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + + /* skip the depth buffer */ + /* skip the polygon stipple */ + /* skip the polygon stipple offset */ + /* skip the line stipple */ + + /* Set the pointers to the 3d pipeline state */ + OUT_RING(BRW_3DSTATE_PIPELINED_POINTERS | 5); + OUT_RING(state_base_offset + vs_offset); /* 32 byte aligned */ + OUT_RING(BRW_GS_DISABLE); /* disable GS, resulting in passthrough */ + OUT_RING(BRW_CLIP_DISABLE); /* disable CLIP, resulting in passthrough */ + OUT_RING(state_base_offset + sf_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + wm_offset); /* 32 byte aligned */ + OUT_RING(state_base_offset + cc_offset); /* 64 byte aligned */ + + /* URB fence */ + OUT_RING(BRW_URB_FENCE | + UF0_CS_REALLOC | + UF0_SF_REALLOC | + UF0_CLIP_REALLOC | + UF0_GS_REALLOC | + UF0_VS_REALLOC | + 1); + OUT_RING(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | + ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | + ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); + OUT_RING(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | + ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); + + /* Constant buffer state */ + OUT_RING(BRW_CS_URB_STATE | 0); + OUT_RING(((URB_CS_ENTRY_SIZE - 1) << 4) | /* URB Entry Allocation Size */ + (URB_CS_ENTRIES << 0)); /* Number of URB Entries */ + + /* Set up the pointer to our vertex buffer */ + OUT_RING(BRW_3DSTATE_VERTEX_BUFFERS | 2); + OUT_RING((0 << VB0_BUFFER_INDEX_SHIFT) | + VB0_VERTEXDATA | + ((4 * 4) << VB0_BUFFER_PITCH_SHIFT)); /* four 32-bit floats per vertex */ + OUT_RING(state_base_offset + vb_offset); + OUT_RING(3); /* four corners to our rectangle */ + + /* Set up our vertex elements, sourced from the single vertex buffer. */ + OUT_RING(BRW_3DSTATE_VERTEX_ELEMENTS | 3); + /* offset 0: X,Y -> {X, Y, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (0 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (0 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + /* offset 8: S0, T0 -> {S0, T0, 1.0, 1.0} */ + OUT_RING((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | + VE0_VALID | + (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | + (8 << VE0_OFFSET_SHIFT)); + OUT_RING((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | + (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) | + (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | + (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); + + OUT_RING(MI_NOOP); /* pad to quadword */ + ADVANCE_LP_RING(); } + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) + { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + int i; + float src_scale_x, src_scale_y; + + if (!first_output) { + /* Since we use the same little vertex buffer over and over, sync for + * subsequent rectangles. + */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + } + + pbox++; + + /* Use normalized texture coordinates */ + src_scale_x = (float)1.0 / (float)drw_w; + src_scale_y = (float)1.0 / (float)drw_h; + + i = 0; + vb[i++] = (box_x2 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x2; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y2 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y2; + + vb[i++] = (box_x1 - dxo) * src_scale_x; + vb[i++] = (box_y1 - dyo) * src_scale_y; + vb[i++] = (float) box_x1; + vb[i++] = (float) box_y1; + +#if 0 + ErrorF ("before EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); + + OUTREG(BRW_VF_CTL, + BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID | + BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX | + BRW_VF_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_VF_STRG_VAL, 0); +#endif + +#if 0 + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_ALL_THREADS | + BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT | + BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE); + + OUTREG(BRW_VS_STRG_VAL, 0); +#endif + +#if WATCH_SF + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT | + BRW_SF_CTL_SNAPSHOT_ALL_THREADS | + BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE); + OUTREG(BRW_SF_STRG_VAL, 0); +#endif + +#if WATCH_WIZ + OUTREG(BRW_WIZ_CTL, + BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE | + BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS | + BRW_WIZ_CTL_SNAPSHOT_ENABLE); + OUTREG(BRW_WIZ_STRG_VAL, + (box_x1) | (box_y1 << 16)); +#endif + +#if 0 + OUTREG(BRW_TS_CTL, + BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR | + BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS | + BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS | + BRW_TS_CTL_SNAPSHOT_ENABLE); +#endif + + BEGIN_LP_RING(6); + OUT_RING(BRW_3DPRIMITIVE | + BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | + (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | + (0 << 9) | /* CTG - indirect vertex count */ + 4); + OUT_RING(3); /* vertex count per instance */ + OUT_RING(0); /* start vertex offset */ + OUT_RING(1); /* single instance */ + OUT_RING(0); /* start instance location */ + OUT_RING(0); /* index buffer offset, ignored */ + ADVANCE_LP_RING(); + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_VF_CTL); + if (ctl & BRW_VF_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VF_RDATA); + OUTREG(BRW_VF_CTL, 0); + ErrorF ("VF_CTL: 0x%08x VF_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_VS_CTL); + if (ctl & BRW_VS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_VS_RDATA); + for (k = 0; k <= 3; k++) { + OUTREG(BRW_VS_CTL, + BRW_VS_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_VS_RDATA); + ErrorF ("VS_CTL: 0x%08x VS_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_VS_CTL, 0); +#endif + +#if WATCH_SF + for (j = 0; j < 1000000; j++) { + ctl = INREG(BRW_SF_CTL); + if (ctl & BRW_SF_CTL_SNAPSHOT_COMPLETE) + break; + } + + for (k = 0; k <= 7; k++) { + OUTREG(BRW_SF_CTL, + BRW_SF_CTL_SNAPSHOT_COMPLETE | + (k << 8)); + rdata = INREG(BRW_SF_RDATA); + ErrorF ("SF_CTL: 0x%08x SF_RDATA(%d): 0x%08x\n", ctl, k, rdata); + } + + OUTREG(BRW_SF_CTL, 0); +#endif + +#if WATCH_WIZ + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_WIZ_CTL); + if (ctl & BRW_WIZ_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_WIZ_RDATA); + OUTREG(BRW_WIZ_CTL, 0); + ErrorF ("WIZ_CTL: 0x%08x WIZ_RDATA: 0x%08x\n", ctl, rdata); +#endif + +#if 0 + for (j = 0; j < 100000; j++) { + ctl = INREG(BRW_TS_CTL); + if (ctl & BRW_TS_CTL_SNAPSHOT_COMPLETE) + break; + } + + rdata = INREG(BRW_TS_RDATA); + OUTREG(BRW_TS_CTL, 0); + ErrorF ("TS_CTL: 0x%08x TS_RDATA: 0x%08x\n", ctl, rdata); + + ErrorF ("after EU_ATT 0x%08x%08x EU_ATT_DATA 0x%08x%08x\n", + INREG(BRW_EU_ATT_1), INREG(BRW_EU_ATT_0), + INREG(BRW_EU_ATT_DATA_1), INREG(BRW_EU_ATT_DATA_0)); +#endif + +#if 0 + for (j = 0; j < 256; j++) { + OUTREG(BRW_TD_CTL, j << BRW_TD_CTL_MUX_SHIFT); + rdata = INREG(BRW_TD_RDATA); + ErrorF ("TD_RDATA(%d): 0x%08x\n", j, rdata); + } +#endif + first_output = FALSE; + if (pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = TRUE; + } + + if (pI830->AccelInfoRec) + (*pI830->AccelInfoRec->Sync)(pScrn); +#if WATCH_STATS + I830PrintErrorState (pScrn); +#endif +} + static FBLinearPtr I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { @@ -1887,6 +2956,19 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) return new_linear; } +/* + * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). + * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). + * id is a fourcc code for the format of the video. + * buf is the pointer to the source data in system memory. + * width and height are the w/h of the source data. + * If "sync" is TRUE, then we must be finished with *buf at the point of return + * (which we always are). + * clipBoxes is the clipping region in screen space. + * data is a pointer to our port private. + * pDraw is a Drawable, which might not be the screen in the case of + * compositing. It's a new argument to the function in the 1.1 server. + */ static int I830PutImage(ScrnInfoPtr pScrn, short src_x, short src_y, @@ -1904,9 +2986,11 @@ I830PutImage(ScrnInfoPtr pScrn, I830OverlayRegPtr overlay = (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); INT32 x1, x2, y1, y2; - int srcPitch, srcPitch2 = 0, dstPitch; + int srcPitch, srcPitch2 = 0, dstPitch, destId; int top, left, npixels, nlines, size, loops; BoxRec dstBox; + int pitchAlignMask; + int extraLinear; DPRINTF(PFX, "I830PutImage: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d)\n" "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y, @@ -1950,63 +3034,85 @@ I830PutImage(ScrnInfoPtr pScrn, width, height)) return Success; + destId = id; switch (id) { case FOURCC_YV12: case FOURCC_I420: srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; -#if 1 - if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - dstPitch = ((height / 2) + 63) & ~63; - size = dstPitch * width * 3; - } else { - dstPitch = ((width / 2) + 63) & ~63; /* of chroma */ - size = dstPitch * height * 3; + if (pPriv->textured) { + destId = FOURCC_YUY2; } -#else + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = width << 1; + break; + } + + /* Only needs to be DWORD-aligned for textured on i915, but overlay has + * stricter requirements. + */ + if (pPriv->textured) { + pitchAlignMask = 3; + } else { + if (IS_I965G(pI830)) + pitchAlignMask = 255; + else + pitchAlignMask = 63; + } + + /* Determine the desired destination pitch (representing the chroma's pitch, + * in the planar case. + */ + switch (destId) { + case FOURCC_YV12: + case FOURCC_I420: if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - dstPitch = ((height / 2) + 511) & ~511; + dstPitch = ((height / 2) + pitchAlignMask) & ~pitchAlignMask; size = dstPitch * width * 3; } else { - dstPitch = ((width / 2) + 511) & ~511; /* of chroma */ + dstPitch = ((width / 2) + pitchAlignMask) & ~pitchAlignMask; size = dstPitch * height * 3; } -#endif break; case FOURCC_UYVY: case FOURCC_YUY2: default: - srcPitch = width << 1; -#if 1 if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - dstPitch = ((height << 1) + 63) & ~63; + dstPitch = ((height << 1) + pitchAlignMask) & ~pitchAlignMask; size = dstPitch * width; } else { - dstPitch = ((width << 1) + 63) & ~63; /* of chroma */ + dstPitch = ((width << 1) + pitchAlignMask) & ~pitchAlignMask; size = dstPitch * height; } -#else - if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { - dstPitch = ((height << 1) + 511) & ~511; - size = dstPitch * width; - } else { - dstPitch = ((width << 1) + 511) & ~511; /* of chroma */ - size = dstPitch * height; - } -#endif break; } +#if 0 ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, dstPitch, size); +#endif + + if (IS_I965G(pI830)) + extraLinear = BRW_LINEAR_EXTRA; + else + extraLinear = 0; /* size is multiplied by 2 because we have two buffers that are flipping */ pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, - (pPriv->doubleBuffer ? size * 2 : size) / pI830->cpp); + (extraLinear + + (pPriv->doubleBuffer ? size * 2 : size)) / + pI830->cpp); if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) return BadAlloc; /* fixup pointers */ +#if 0 + pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; +#else pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; +#endif if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * width / 2); @@ -2027,7 +3133,9 @@ I830PutImage(ScrnInfoPtr pScrn, /* Make sure this buffer isn't in use */ loops = 0; - if (*pI830->overlayOn && pPriv->doubleBuffer && (overlay->OCMD & OVERLAY_ENABLE)) { + if (!pPriv->textured && *pI830->overlayOn && pPriv->doubleBuffer && + (overlay->OCMD & OVERLAY_ENABLE)) + { while (loops < 1000000) { #if USE_USLEEP_FOR_VIDEO usleep(10); @@ -2056,32 +3164,58 @@ I830PutImage(ScrnInfoPtr pScrn, left = (x1 >> 16) & ~1; npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + if (pPriv->textured) { + /* For textured video, we don't double buffer, and instead just wait for + * acceleration to finish before writing the new video data into + * framebuffer. + */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + } + switch (id) { case FOURCC_YV12: case FOURCC_I420: top &= ~1; nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; - I830CopyPlanarData(pScrn, buf, srcPitch, srcPitch2, dstPitch, height, top, left, - nlines, npixels, id); + if (pPriv->textured) { + I830CopyPlanarToPackedData(pScrn, pPriv, buf, srcPitch, srcPitch2, + dstPitch, height, top, left, nlines, + npixels, id); + } else { + I830CopyPlanarData(pScrn, pPriv, buf, srcPitch, srcPitch2, dstPitch, + height, top, left, nlines, npixels, id); + } break; case FOURCC_UYVY: case FOURCC_YUY2: default: nlines = ((y2 + 0xffff) >> 16) - top; - I830CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, - npixels); + I830CopyPackedData(pScrn, pPriv, buf, srcPitch, dstPitch, top, left, + nlines, npixels); break; } - /* update cliplist */ - if (!RegionsEqual(&pPriv->clip, clipBoxes)) { - REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); - xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes); - } - - I830DisplayVideo(pScrn, id, width, height, dstPitch, - x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + if (!pPriv->textured) { + /* update cliplist */ + if (!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes); + } + I830DisplayVideo(pScrn, destId, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + } else if (IS_I965G(pI830)) { + BroadwaterDisplayVideoTextured (pScrn, pPriv, destId, clipBoxes, width, height, + dstPitch, x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pDraw); + } else { + I915DisplayVideoTextured(pScrn, pPriv, destId, clipBoxes, width, height, + dstPitch, x1, y1, x2, y2, + src_w, src_h, drw_w, drw_h, pDraw); + } pPriv->videoStatus = CLIENT_VIDEO_ON; return Success; @@ -2091,23 +3225,27 @@ static int I830QueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, - int *pitches, int *offsets) + int *pitches, int *offsets, Bool textured) { I830Ptr pI830 = I830PTR(pScrn); int size, tmp; +#if 0 ErrorF("I830QueryImageAttributes: w is %d, h is %d\n", *w, *h); +#endif - if (IS_845G(pI830) || IS_I830(pI830)) { - if (*w > IMAGE_MAX_WIDTH_LEGACY) - *w = IMAGE_MAX_WIDTH_LEGACY; - if (*h > IMAGE_MAX_HEIGHT_LEGACY) - *h = IMAGE_MAX_HEIGHT_LEGACY; - } else { - if (*w > IMAGE_MAX_WIDTH) - *w = IMAGE_MAX_WIDTH; - if (*h > IMAGE_MAX_HEIGHT) - *h = IMAGE_MAX_HEIGHT; + if (!textured) { + if (IS_845G(pI830) || IS_I830(pI830)) { + if (*w > IMAGE_MAX_WIDTH_LEGACY) + *w = IMAGE_MAX_WIDTH_LEGACY; + if (*h > IMAGE_MAX_HEIGHT_LEGACY) + *h = IMAGE_MAX_HEIGHT_LEGACY; + } else { + if (*w > IMAGE_MAX_WIDTH) + *w = IMAGE_MAX_WIDTH; + if (*h > IMAGE_MAX_HEIGHT) + *h = IMAGE_MAX_HEIGHT; + } } *w = (*w + 1) & ~1; @@ -2160,6 +3298,24 @@ I830QueryImageAttributes(ScrnInfoPtr pScrn, return size; } +static int +I830QueryImageAttributesOverlay(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, FALSE); +} + +static int +I830QueryImageAttributesTextured(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + return I830QueryImageAttributes(pScrn, id, w, h, pitches, offsets, TRUE); +} + static void I830BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) @@ -2178,7 +3334,11 @@ I830BlockHandler(int i, pScreen->BlockHandler = I830BlockHandler; if (pPriv->videoStatus & TIMER_MASK) { +#if 1 Time now = currentTime.milliseconds; +#else + UpdateCurrentTime(); +#endif if (pPriv->videoStatus & OFF_TIMER) { if (pPriv->offTime < now) { /* Turn off the overlay */ @@ -2278,7 +3438,11 @@ I830AllocateSurface(ScrnInfoPtr pScrn, surface->offsets[0] = linear->offset * bpp; surface->devPrivate.ptr = (pointer) pPriv; +#if 0 + memset(pI830->FbBase + pScrn->fbOffset + surface->offsets[0], 0, size); +#else memset(pI830->FbBase + pI830->FrontBuffer.Start + surface->offsets[0], 0, size); +#endif return Success; } @@ -2524,37 +3688,39 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } } - if (pPriv->pipe == 0) { - if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe A is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; + if (!IS_I965G(pI830)) { + if (pPriv->pipe == 0) { + if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe A is in double-wide mode.\n"); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n"); + pPriv->overlayOK = TRUE; + } } - } - if (pPriv->pipe == 1) { - if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe B is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; + if (pPriv->pipe == 1) { + if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe B is in double-wide mode.\n"); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n"); + pPriv->overlayOK = TRUE; + } } } /* Check we have an LFP connected */ if ((pPriv->pipe == 1 && pI830->operatingDevices & (PIPE_LFP << 8)) || (pPriv->pipe == 0 && pI830->operatingDevices & PIPE_LFP) ) { - size = pI830->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); + size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); hsize = (size >> 16) & 0x7FF; vsize = size & 0x7FF; - active = pI830->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + active = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); if (vsize < active && hsize > 1024) I830SetOneLineModeRatio(pScrn); diff --git a/src/i830_video.h b/src/i830_video.h new file mode 100644 index 00000000..9e11641e --- /dev/null +++ b/src/i830_video.h @@ -0,0 +1,76 @@ +/*************************************************************************** + +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. + +**************************************************************************/ + +#include "xf86.h" +#include "xf86_OSproc.h" + +typedef struct { + CARD32 YBuf0offset; + CARD32 UBuf0offset; + CARD32 VBuf0offset; + + CARD32 YBuf1offset; + CARD32 UBuf1offset; + CARD32 VBuf1offset; + + unsigned char currentBuf; + + int brightness; + int contrast; + int pipe; + int doubleBuffer; + + RegionRec clip; + CARD32 colorKey; + + CARD32 gamma0; + CARD32 gamma1; + CARD32 gamma2; + CARD32 gamma3; + CARD32 gamma4; + CARD32 gamma5; + + CARD32 videoStatus; + Time offTime; + Time freeTime; + FBLinearPtr linear; + + Bool overlayOK; + int oneLineMode; + int scaleRatio; + Bool textured; +} I830PortPrivRec, *I830PortPrivPtr; + +#define GET_PORT_PRIVATE(pScrn) \ + (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +void I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, + int id, RegionPtr dstRegion, short width, + short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, + short drw_w, short drw_h, + DrawablePtr pDraw); diff --git a/src/i830_xaa.c b/src/i830_xaa.c index 9f3a3910..6948be08 100644 --- a/src/i830_xaa.c +++ b/src/i830_xaa.c @@ -230,6 +230,32 @@ I830XAAInit(ScreenPtr pScreen) return XAAInit(pScreen, infoPtr); } +#ifdef XF86DRI +static unsigned int +CheckTiling(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = 0; + + /* Check tiling */ + if (IS_I965G(pI830)) { + if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR) + tiled = 1; + if (pI830->bufferOffset == pI830->RotatedMem.Start && pI830->rotated_tiled == FENCE_XMAJOR) + tiled = 1; + if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR) + tiled = 1; + /* not really supported as it's always YMajor tiled */ + if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR) + tiled = 1; + } + + return tiled; +} +#else +#define CheckTiling(pScrn) 0 +#endif + void I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) @@ -292,6 +318,9 @@ I830SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) ADVANCE_LP_RING(); } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); } void @@ -334,6 +363,7 @@ I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1, { I830Ptr pI830 = I830PTR(pScrn); int dst_x2, dst_y2; + unsigned int tiled = CheckTiling(pScrn); if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) ErrorF("I830SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n", @@ -342,14 +372,18 @@ I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1, dst_x2 = dst_x1 + w; dst_y2 = dst_y1 + h; + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + { BEGIN_LP_RING(8); if (pScrn->bitsPerPixel == 32) { OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + XY_SRC_COPY_BLT_WRITE_RGB | tiled << 15 | tiled << 11); } else { - OUT_RING(XY_SRC_COPY_BLT_CMD); + OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 15 | tiled << 11); } OUT_RING(pI830->BR[13]); OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff)); @@ -361,6 +395,9 @@ I830SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x1, int src_y1, ADVANCE_LP_RING(); } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); } static void @@ -402,6 +439,7 @@ I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, { I830Ptr pI830 = I830PTR(pScrn); int x1, x2, y1, y2; + unsigned int tiled = CheckTiling(pScrn); x1 = x; x2 = x + w; @@ -411,16 +449,20 @@ I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) ErrorF("I830SubsequentMono8x8PatternFillRect\n"); + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + { BEGIN_LP_RING(10); if (pScrn->bitsPerPixel == 32) { OUT_RING(XY_MONO_PAT_BLT_CMD | XY_MONO_PAT_BLT_WRITE_ALPHA | - XY_MONO_PAT_BLT_WRITE_RGB | + XY_MONO_PAT_BLT_WRITE_RGB | tiled << 11 | ((patty << 8) & XY_MONO_PAT_VERT_SEED) | ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); } else { - OUT_RING(XY_MONO_PAT_BLT_CMD | + OUT_RING(XY_MONO_PAT_BLT_CMD | tiled << 11 | ((patty << 8) & XY_MONO_PAT_VERT_SEED) | ((pattx << 12) & XY_MONO_PAT_HORT_SEED)); } @@ -435,6 +477,9 @@ I830SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, OUT_RING(0); ADVANCE_LP_RING(); } + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); } static void @@ -510,6 +555,7 @@ static void I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) { I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = CheckTiling(pScrn); if (pI830->init == 0) { pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - @@ -527,14 +573,18 @@ I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n", bufno, pI830->BR[12]); + if (tiled) + pI830->BR[13] = ((pI830->BR[13] & 0xFFFF) >> 2) | + (pI830->BR[13] & 0xFFFF0000); + { BEGIN_LP_RING(8); if (pScrn->bitsPerPixel == 32) { OUT_RING(XY_MONO_SRC_BLT_CMD | XY_MONO_SRC_BLT_WRITE_ALPHA | - XY_MONO_SRC_BLT_WRITE_RGB); + tiled << 11 | XY_MONO_SRC_BLT_WRITE_RGB); } else { - OUT_RING(XY_MONO_SRC_BLT_CMD); + OUT_RING(XY_MONO_SRC_BLT_CMD | tiled << 11); } OUT_RING(pI830->BR[13]); OUT_RING(0); /* x1 = 0, y1 = 0 */ @@ -551,6 +601,9 @@ I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) */ pI830->BR[9] += pScrn->displayWidth * pI830->cpp; I830GetNextScanlineColorExpandBuffer(pScrn); + + if (IS_I965G(pI830)) + I830EmitFlush(pScrn); } #if DO_SCANLINE_IMAGE_WRITE @@ -602,6 +655,7 @@ static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) { I830Ptr pI830 = I830PTR(pScrn); + unsigned int tiled = CheckTiling(pScrn); if (pI830->init == 0) { pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - @@ -624,15 +678,15 @@ I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) if (pScrn->bitsPerPixel == 32) { OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); + tiled << 11 | XY_SRC_COPY_BLT_WRITE_RGB); } else { - OUT_RING(XY_SRC_COPY_BLT_CMD); + OUT_RING(XY_SRC_COPY_BLT_CMD | tiled << 11); } OUT_RING(pI830->BR[13]); - OUT_RING(0); /* x1 = 0, y1 = 0 */ + OUT_RING(0); /* x1 = 0, y1 = 0 */ OUT_RING(pI830->BR[11]); /* x2 = w, y2 = 1 */ - OUT_RING(pI830->BR[9]); /* dst addr */ - OUT_RING(0); /* source origin (0,0) */ + OUT_RING(pI830->BR[9]); /* dst addr */ + OUT_RING(0); /* source origin (0,0) */ OUT_RING(pI830->BR[11] & 0xffff); /* source pitch */ OUT_RING(pI830->BR[12]); /* src addr */ diff --git a/src/i915_3d.c b/src/i915_3d.c index 942dbd17..e70bb24a 100644 --- a/src/i915_3d.c +++ b/src/i915_3d.c @@ -29,6 +29,7 @@ #include "config.h" #endif +#include "xf86.h" #include "i830.h" #include "i915_reg.h" diff --git a/src/i915_video.c b/src/i915_video.c new file mode 100644 index 00000000..0833d508 --- /dev/null +++ b/src/i915_video.c @@ -0,0 +1,467 @@ +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86xv.h" +#include "fourcc.h" + +#include "i830.h" +#include "i830_video.h" +#include "i915_reg.h" +#include "i915_3d.h" + +union intfloat { + CARD32 ui; + float f; +}; + +#define OUT_RING_F(x) do { \ + union intfloat _tmp; \ + _tmp.f = x; \ + OUT_RING(_tmp.ui); \ +} while (0) + + +void +I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, + RegionPtr dstRegion, + short width, short height, int video_pitch, + int x1, int y1, int x2, int y2, + short src_w, short src_h, short drw_w, short drw_h, + DrawablePtr pDraw) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 format, ms3, s2; + BoxPtr pbox; + int nbox, dxo, dyo; + Bool planar; + + ErrorF("I915DisplayVideo: %dx%d (pitch %d)\n", width, height, + video_pitch); + + switch (id) { + case FOURCC_UYVY: + case FOURCC_YUY2: + planar = FALSE; + break; + case FOURCC_YV12: + case FOURCC_I420: + planar = TRUE; + break; + default: + ErrorF("Unknown format 0x%x\n", id); + planar = FALSE; + break; + } + + /* Tell the rotation code that we have stomped its invariant state by + * setting a high bit. We don't use any invariant 3D state for video, so we + * don't have to worry about it ourselves. + */ + *pI830->used3D |= 1 << 30; + + BEGIN_LP_RING(44); + + /* invarient state */ + OUT_RING(MI_NOOP); + OUT_RING(_3DSTATE_AA_CMD | + AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 | + AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0); + + OUT_RING(_3DSTATE_DFLT_DIFFUSE_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DFLT_SPEC_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DFLT_Z_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0, 0) | CSB_TCB(1, 1) | + CSB_TCB(2,2) | CSB_TCB(3,3) | CSB_TCB(4,4) | CSB_TCB(5,5) | + CSB_TCB(6,6) | CSB_TCB(7,7)); + + OUT_RING(_3DSTATE_RASTER_RULES_CMD | + ENABLE_TRI_FAN_PROVOKE_VRTX | TRI_FAN_PROVOKE_VRTX(2) | + ENABLE_LINE_STRIP_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) | + ENABLE_TEXKILL_3D_4D | TEXKILL_4D | + ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 1); + OUT_RING(0x00000000); /* texture coordinate wrap */ + + /* flush map & render cache */ + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + + /* draw rect -- just clipping */ + OUT_RING(_3DSTATE_DRAW_RECT_CMD); + OUT_RING(0x00000000); /* flags */ + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING((pScrn->virtualX - 1) | + (pScrn->virtualY - 1) << 16); /* ymax, xmax */ + OUT_RING(0x00000000); /* yorigin, xorigin */ + OUT_RING(MI_NOOP); + + /* scissor */ + OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); + OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD); + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING(0x00000000); /* ymax, xmax */ + + OUT_RING(0x7c000003); /* unknown command */ + OUT_RING(0x7d070000); + OUT_RING(0x00000000); + OUT_RING(0x68000002); + + /* context setup */ + OUT_RING(_3DSTATE_MODES_4_CMD | + ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) | + ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff) | + ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(0xff)); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(2) | + I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4); + s2 = S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D); + if (planar) + s2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_2D); + else + s2 |= S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT); + s2 |= S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT); + OUT_RING(s2); + OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | + S4_CULLMODE_NONE | S4_VFMT_XY); + OUT_RING(0x00000000); /* S5 - enable bits */ + OUT_RING((2 << S6_DEPTH_TEST_FUNC_SHIFT) | + (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) | + (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE | + (2 << S6_TRISTRIP_PV_SHIFT)); + + OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | + IAB_MODIFY_ENABLE | + IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) | + IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) | + IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT)); + + OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DST_BUF_VARS_CMD); + if (pI830->cpp == 2) + format = COLR_BUF_RGB565; + else + format = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER; + + OUT_RING(LOD_PRECLAMP_OGL | + DSTORG_HORT_BIAS(0x80) | DSTORG_VERT_BIAS(0x80) | format); + + OUT_RING(_3DSTATE_STIPPLE); + OUT_RING(0x00000000); + + /* front buffer, pitch, offset */ + OUT_RING(_3DSTATE_BUF_INFO_CMD); + OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | + (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + OUT_RING(pI830->bufferOffset); + ADVANCE_LP_RING(); + + if (!planar) { + FS_LOCALS(3); + + BEGIN_LP_RING(10); + OUT_RING(_3DSTATE_SAMPLER_STATE | 3); + OUT_RING(0x00000001); + OUT_RING(SS2_COLORSPACE_CONVERSION | + (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | + (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); + OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT)); + OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_MAP_STATE | 3); + OUT_RING(0x00000001); /* texture map #1 */ + OUT_RING(pPriv->YBuf0offset); + ms3 = MAPSURF_422; + switch (id) { + case FOURCC_YUY2: + ms3 |= MT_422_YCRCB_NORMAL; + break; + case FOURCC_UYVY: + ms3 |= MT_422_YCRCB_SWAPY; + break; + } + ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; + ms3 |= (width - 1) << MS3_WIDTH_SHIFT; + if (!pI830->disableTiling) + ms3 |= MS3_USE_FENCE_REGS; + OUT_RING(ms3); + OUT_RING(((video_pitch / 4) - 1) << 21); + ADVANCE_LP_RING(); + + FS_BEGIN(); + i915_fs_dcl(FS_S0); + i915_fs_dcl(FS_T0); + i915_fs_texld(FS_OC, FS_S0, FS_T0); + FS_END(); + } else { + FS_LOCALS(16); + + BEGIN_LP_RING(1 + 18 + 11 + 11); + OUT_RING(MI_NOOP); + /* 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 + * shader setup to work, I did the manual pixel shader: + * + * y' = y - .0625 + * u' = u - .5 + * v' = v - .5; + * + * r = 1.1643 * y' + 0.0 * u' + 1.5958 * v' + * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v' + * b = 1.1643 * y' + 2.017 * u' + 0.0 * v' + * + * register assignment: + * r0 = (y',u',v',0) + * r1 = (y,y,y,y) + * r2 = (u,u,u,u) + * r3 = (v,v,v,v) + * OC = (r,g,b,1) + */ + OUT_RING(_3DSTATE_PIXEL_SHADER_CONSTANTS | 16); + OUT_RING(0x000000f); /* constants 0-3 */ + /* constant 0: normalization offsets */ + OUT_RING_F(-0.0625); + OUT_RING_F(-0.5); + OUT_RING_F(-0.5); + OUT_RING_F(0.0); + /* constant 1: r coefficients*/ + OUT_RING_F(1.1643); + OUT_RING_F(0.0); + OUT_RING_F(1.5958); + OUT_RING_F(0.0); + /* constant 2: g coefficients */ + OUT_RING_F(1.1643); + OUT_RING_F(-0.39173); + OUT_RING_F(-0.81290); + OUT_RING_F(0.0); + /* constant 3: b coefficients */ + OUT_RING_F(1.1643); + OUT_RING_F(2.017); + OUT_RING_F(0.0); + OUT_RING_F(0.0); + + OUT_RING(_3DSTATE_SAMPLER_STATE | 9); + OUT_RING(0x00000007); + /* sampler 0 */ + OUT_RING(0x00000000); + OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | + (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); + OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT)); + /* sampler 1 */ + OUT_RING(0x00000000); + OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | + (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); + OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT)); + /* sampler 2 */ + OUT_RING(0x00000000); + OUT_RING((FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | + (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT)); + OUT_RING((TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT)); + + OUT_RING(_3DSTATE_MAP_STATE | 9); + OUT_RING(0x00000007); + + OUT_RING(pPriv->YBuf0offset); + ms3 = MAPSURF_8BIT | MT_8BIT_I8; + ms3 |= (height - 1) << MS3_HEIGHT_SHIFT; + ms3 |= (width - 1) << MS3_WIDTH_SHIFT; + OUT_RING(ms3); + OUT_RING(((video_pitch * 2 / 4) - 1) << 21); + + OUT_RING(pPriv->UBuf0offset); + ms3 = MAPSURF_8BIT | MT_8BIT_I8; + ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; + ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; + OUT_RING(ms3); + OUT_RING(((video_pitch / 4) - 1) << 21); + + OUT_RING(pPriv->VBuf0offset); + ms3 = MAPSURF_8BIT | MT_8BIT_I8; + ms3 |= (height / 2 - 1) << MS3_HEIGHT_SHIFT; + ms3 |= (width / 2 - 1) << MS3_WIDTH_SHIFT; + OUT_RING(ms3); + OUT_RING(((video_pitch / 4) - 1) << 21); + ADVANCE_LP_RING(); + + FS_BEGIN(); + /* Declare samplers */ + i915_fs_dcl(FS_S0); + i915_fs_dcl(FS_S1); + i915_fs_dcl(FS_S2); + i915_fs_dcl(FS_T0); + i915_fs_dcl(FS_T1); + + /* Load samplers to temporaries. Y (sampler 0) gets the un-halved coords- + * from t1. + */ + i915_fs_texld(FS_R1, FS_S0, FS_T1); + i915_fs_texld(FS_R2, FS_S1, FS_T0); + i915_fs_texld(FS_R3, FS_S2, FS_T0); + + /* Move the sampled YUV data in R[123] to the first 3 channels of R0. */ + i915_fs_mov_masked(FS_R0, MASK_X, i915_fs_operand_reg(FS_R1)); + i915_fs_mov_masked(FS_R0, MASK_Y, i915_fs_operand_reg(FS_R2)); + i915_fs_mov_masked(FS_R0, MASK_Z, i915_fs_operand_reg(FS_R3)); + + /* Normalize the YUV data */ + i915_fs_add(FS_R0, i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C0)); + /* dot-product the YUV data in R0 by the vectors of coefficients for + * calculating R, G, and B, storing the results in the R, G, or B channels + * of the output color. + */ + i915_fs_dp3_masked(FS_OC, MASK_X | MASK_SATURATE, + i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C1)); + i915_fs_dp3_masked(FS_OC, MASK_Y | MASK_SATURATE, + i915_fs_operand_reg(FS_R0), + i915_fs_operand_reg(FS_C2)); + i915_fs_dp3_masked(FS_OC, MASK_Z | MASK_SATURATE, + 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. + */ + i915_fs_mov_masked(FS_OC, MASK_W, i915_fs_operand_one()); + FS_END(); + } + + { + BEGIN_LP_RING(2); + OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); + OUT_RING(0x00000000); + ADVANCE_LP_RING(); + } + + dxo = dstRegion->extents.x1; + dyo = dstRegion->extents.y1; + + pbox = REGION_RECTS(dstRegion); + nbox = REGION_NUM_RECTS(dstRegion); + while (nbox--) + { + int box_x1 = pbox->x1; + int box_y1 = pbox->y1; + int box_x2 = pbox->x2; + int box_y2 = pbox->y2; + float src_scale_x, src_scale_y; + int vert_data_count; + + pbox++; + + src_scale_x = (float)src_w / (float)drw_w; + src_scale_y = (float)src_h / (float)drw_h; + + if (!planar) + vert_data_count = 12; + else + vert_data_count = 18; + + BEGIN_LP_RING(vert_data_count + 8); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + + /* vertex data - rect list consists of bottom right, bottom left, and top + * left vertices. + */ + OUT_RING(PRIM3D_INLINE | PRIM3D_RECTLIST | + (vert_data_count - 1)); + + /* bottom right */ + OUT_RING_F(box_x2); + OUT_RING_F(box_y2); + if (!planar) { + OUT_RING_F((box_x2 - dxo) * src_scale_x); + OUT_RING_F((box_y2 - dyo) * src_scale_y); + } else { + OUT_RING_F((box_x2 - dxo) * src_scale_x / 2.0); + OUT_RING_F((box_y2 - dyo) * src_scale_y / 2.0); + OUT_RING_F((box_x2 - dxo) * src_scale_x); + OUT_RING_F((box_y2 - dyo) * src_scale_y); + } + + /* bottom left */ + OUT_RING_F(box_x1); + OUT_RING_F(box_y2); + if (!planar) { + OUT_RING_F((box_x1 - dxo) * src_scale_x); + OUT_RING_F((box_y2 - dyo) * src_scale_y); + } else { + OUT_RING_F((box_x1 - dxo) * src_scale_x / 2.0); + OUT_RING_F((box_y2 - dyo) * src_scale_y / 2.0); + OUT_RING_F((box_x1 - dxo) * src_scale_x); + OUT_RING_F((box_y2 - dyo) * src_scale_y); + } + + /* top left */ + OUT_RING_F(box_x1); + OUT_RING_F(box_y1); + if (!planar) { + OUT_RING_F((box_x1 - dxo) * src_scale_x); + OUT_RING_F((box_y1 - dyo) * src_scale_y); + } else { + OUT_RING_F((box_x1 - dxo) * src_scale_x / 2.0); + OUT_RING_F((box_y1 - dyo) * src_scale_y / 2.0); + OUT_RING_F((box_x1 - dxo) * src_scale_x); + OUT_RING_F((box_y1 - dyo) * src_scale_y); + } + + ADVANCE_LP_RING(); + } + + if (pI830->AccelInfoRec) + pI830->AccelInfoRec->NeedToSync = TRUE; +} + diff --git a/src/wm_prog.h b/src/wm_prog.h new file mode 100644 index 00000000..297ddcbf --- /dev/null +++ b/src/wm_prog.h @@ -0,0 +1,166 @@ +/* wm_program */ +/* mov (1) g4<1>F g1.8<0,1,0>UW { align1 + } */ + { 0x00000001, 0x2080013d, 0x00000028, 0x00000000 }, +/* add (1) g4.4<1>F g1.8<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20840d3d, 0x00000028, 0x00000001 }, +/* mov (1) g4.8<1>F g1.8<0,1,0>UW { align1 + } */ + { 0x00000001, 0x2088013d, 0x00000028, 0x00000000 }, +/* add (1) g4.12<1>F g1.8<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x208c0d3d, 0x00000028, 0x00000001 }, +/* mov (1) g6<1>F g1.10<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20c0013d, 0x0000002a, 0x00000000 }, +/* mov (1) g6.4<1>F g1.10<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20c4013d, 0x0000002a, 0x00000000 }, +/* add (1) g6.8<1>F g1.10<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20c80d3d, 0x0000002a, 0x00000001 }, +/* add (1) g6.12<1>F g1.10<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20cc0d3d, 0x0000002a, 0x00000001 }, +/* mov (1) g4.16<1>F g1.12<0,1,0>UW { align1 + } */ + { 0x00000001, 0x2090013d, 0x0000002c, 0x00000000 }, +/* add (1) g4.20<1>F g1.12<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20940d3d, 0x0000002c, 0x00000001 }, +/* mov (1) g4.24<1>F g1.12<0,1,0>UW { align1 + } */ + { 0x00000001, 0x2098013d, 0x0000002c, 0x00000000 }, +/* add (1) g4.28<1>F g1.12<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x209c0d3d, 0x0000002c, 0x00000001 }, +/* mov (1) g6.16<1>F g1.14<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20d0013d, 0x0000002e, 0x00000000 }, +/* mov (1) g6.20<1>F g1.14<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20d4013d, 0x0000002e, 0x00000000 }, +/* add (1) g6.24<1>F g1.14<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20d80d3d, 0x0000002e, 0x00000001 }, +/* add (1) g6.28<1>F g1.14<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20dc0d3d, 0x0000002e, 0x00000001 }, +/* mov (1) g5<1>F g1.16<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20a0013d, 0x00000030, 0x00000000 }, +/* add (1) g5.4<1>F g1.16<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20a40d3d, 0x00000030, 0x00000001 }, +/* mov (1) g5.8<1>F g1.16<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20a8013d, 0x00000030, 0x00000000 }, +/* add (1) g5.12<1>F g1.16<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20ac0d3d, 0x00000030, 0x00000001 }, +/* mov (1) g7<1>F g1.18<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20e0013d, 0x00000032, 0x00000000 }, +/* mov (1) g7.4<1>F g1.18<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20e4013d, 0x00000032, 0x00000000 }, +/* add (1) g7.8<1>F g1.18<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20e80d3d, 0x00000032, 0x00000001 }, +/* add (1) g7.12<1>F g1.18<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20ec0d3d, 0x00000032, 0x00000001 }, +/* mov (1) g5.16<1>F g1.20<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20b0013d, 0x00000034, 0x00000000 }, +/* add (1) g5.20<1>F g1.20<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20b40d3d, 0x00000034, 0x00000001 }, +/* mov (1) g5.24<1>F g1.20<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20b8013d, 0x00000034, 0x00000000 }, +/* add (1) g5.28<1>F g1.20<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20bc0d3d, 0x00000034, 0x00000001 }, +/* mov (1) g7.16<1>F g1.22<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20f0013d, 0x00000036, 0x00000000 }, +/* mov (1) g7.20<1>F g1.22<0,1,0>UW { align1 + } */ + { 0x00000001, 0x20f4013d, 0x00000036, 0x00000000 }, +/* add (1) g7.24<1>F g1.22<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20f80d3d, 0x00000036, 0x00000001 }, +/* add (1) g7.28<1>F g1.22<0,1,0>UW 1 { align1 + } */ + { 0x00000040, 0x20fc0d3d, 0x00000036, 0x00000001 }, +/* add (8) g4<1>F g4<8,8,1>F g1<0,1,0>F { align1 + } */ + { 0x00600040, 0x208077bd, 0x008d0080, 0x00004020 }, +/* add (8) g5<1>F g5<8,8,1>F g1<0,1,0>F { align1 + } */ + { 0x00600040, 0x20a077bd, 0x008d00a0, 0x00004020 }, +/* mul (8) g4<1>F g4<8,8,1>F g3<0,1,0>F { align1 + } */ + { 0x00600041, 0x208077bd, 0x008d0080, 0x00000060 }, +/* mul (8) g5<1>F g5<8,8,1>F g3<0,1,0>F { align1 + } */ + { 0x00600041, 0x20a077bd, 0x008d00a0, 0x00000060 }, +/* add (8) g4<1>F g4<8,8,1>F g3.12<0,1,0>F { align1 + } */ + { 0x00600040, 0x208077bd, 0x008d0080, 0x0000006c }, +/* add (8) g5<1>F g5<8,8,1>F g3.12<0,1,0>F { align1 + } */ + { 0x00600040, 0x20a077bd, 0x008d00a0, 0x0000006c }, +/* add (8) g6<1>F g6<8,8,1>F g1.4<0,1,0>F { align1 + } */ + { 0x00600040, 0x20c077bd, 0x008d00c0, 0x00004024 }, +/* add (8) g7<1>F g7<8,8,1>F g1.4<0,1,0>F { align1 + } */ + { 0x00600040, 0x20e077bd, 0x008d00e0, 0x00004024 }, +/* mul (8) g6<1>F g6<8,8,1>F g3.20<0,1,0>F { align1 + } */ + { 0x00600041, 0x20c077bd, 0x008d00c0, 0x00000074 }, +/* mul (8) g7<1>F g7<8,8,1>F g3.20<0,1,0>F { align1 + } */ + { 0x00600041, 0x20e077bd, 0x008d00e0, 0x00000074 }, +/* add (8) g6<1>F g6<8,8,1>F g3.28<0,1,0>F { align1 + } */ + { 0x00600040, 0x20c077bd, 0x008d00c0, 0x0000007c }, +/* add (8) g7<1>F g7<8,8,1>F g3.28<0,1,0>F { align1 + } */ + { 0x00600040, 0x20e077bd, 0x008d00e0, 0x0000007c }, +/* mov (8) m1<1>F g4<8,8,1>F { align1 + } */ + { 0x00600001, 0x202003be, 0x008d0080, 0x00000000 }, +/* mov (8) m2<1>F g5<8,8,1>F { align1 + } */ + { 0x00600001, 0x204003be, 0x008d00a0, 0x00000000 }, +/* mov (8) m3<1>F g6<8,8,1>F { align1 + } */ + { 0x00600001, 0x206003be, 0x008d00c0, 0x00000000 }, +/* mov (8) m4<1>F g7<8,8,1>F { align1 + } */ + { 0x00600001, 0x208003be, 0x008d00e0, 0x00000000 }, +/* send 0 (16) g12<1>UW g0<8,8,1>UW sampler mlen 5 rlen 8 { align1 + } */ + { 0x00800031, 0x21801d29, 0x008d0000, 0x02580001 }, +/* mov (8) g19<1>UW g19<8,8,1>UW { align1 + } */ + { 0x00600001, 0x22600129, 0x008d0260, 0x00000000 }, +/* add (8) g14<1>F g14<8,8,1>F -0.0627451{ align1 + } */ + { 0x00600040, 0x21c07fbd, 0x008d01c0, 0xbd808081 }, +/* add (8) g12<1>F g12<8,8,1>F -0.501961{ align1 + } */ + { 0x00600040, 0x21807fbd, 0x008d0180, 0xbf008081 }, +/* add (8) g16<1>F g16<8,8,1>F -0.501961{ align1 + } */ + { 0x00600040, 0x22007fbd, 0x008d0200, 0xbf008081 }, +/* mul (8) g14<1>F g14<8,8,1>F 1.164{ align1 + } */ + { 0x00600041, 0x21c07fbd, 0x008d01c0, 0x3f94fdf4 }, +/* mul (8) a0<1>F g12<8,8,1>F 1.596{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d0180, 0x3fcc49ba }, +/* mac (8) m2<1>F g14<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x20407fbe, 0x008d01c0, 0x3f800000 }, +/* mul (8) a0<1>F g12<8,8,1>F -0.813{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d0180, 0xbf5020c5 }, +/* mac (8) a0<1>F g16<8,8,1>F -0.392{ align1 + } */ + { 0x00600048, 0x20007fbc, 0x008d0200, 0xbec8b439 }, +/* mac (8) m3<1>F g14<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x20607fbe, 0x008d01c0, 0x3f800000 }, +/* mul (8) a0<1>F g16<8,8,1>F 2.017{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d0200, 0x40011687 }, +/* mac (8) m4<1>F g14<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x20807fbe, 0x008d01c0, 0x3f800000 }, +/* add (8) g15<1>F g15<8,8,1>F -0.0627451{ align1 + } */ + { 0x00600040, 0x21e07fbd, 0x008d01e0, 0xbd808081 }, +/* add (8) g13<1>F g13<8,8,1>F -0.501961{ align1 + } */ + { 0x00600040, 0x21a07fbd, 0x008d01a0, 0xbf008081 }, +/* add (8) g17<1>F g17<8,8,1>F -0.501961{ align1 + } */ + { 0x00600040, 0x22207fbd, 0x008d0220, 0xbf008081 }, +/* mul (8) g15<1>F g15<8,8,1>F 1.164{ align1 + } */ + { 0x00600041, 0x21e07fbd, 0x008d01e0, 0x3f94fdf4 }, +/* mul (8) a0<1>F g13<8,8,1>F 1.596{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d01a0, 0x3fcc49ba }, +/* mac (8) m6<1>F g15<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x20c07fbe, 0x008d01e0, 0x3f800000 }, +/* mul (8) a0<1>F g13<8,8,1>F -0.813{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d01a0, 0xbf5020c5 }, +/* mac (8) a0<1>F g17<8,8,1>F -0.392{ align1 + } */ + { 0x00600048, 0x20007fbc, 0x008d0220, 0xbec8b439 }, +/* mac (8) m7<1>F g15<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x20e07fbe, 0x008d01e0, 0x3f800000 }, +/* mul (8) a0<1>F g17<8,8,1>F 2.017{ align1 + } */ + { 0x00600041, 0x20007fbc, 0x008d0220, 0x40011687 }, +/* mac (8) m8<1>F g15<8,8,1>F 1{ align1 + Saturate } */ + { 0x80600048, 0x21007fbe, 0x008d01e0, 0x3f800000 }, +/* mov (8) m1<1>UD g1<8,8,1>UD { align1 mask_disable + } */ + { 0x00600201, 0x20200022, 0x008d0020, 0x00000000 }, +/* send 0 (16) a0<1>UW g0<8,8,1>UW write mlen 10 rlen 0 EOT{ align1 + } */ + { 0x00800031, 0x20001d28, 0x008d0000, 0x85a04800 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, +/* nop (4) g0<1>UD { align1 + } */ + { 0x0040007e, 0x20000c21, 0x00690000, 0x00000000 }, + |