summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau/nv30
diff options
context:
space:
mode:
authorJohannes Obermayr <[email protected]>2013-08-20 20:14:00 +0200
committerChristoph Bumiller <[email protected]>2013-09-11 21:47:07 +0200
commit5eb7ff1175a644ffe3b0f1a75cb235400355f9fb (patch)
tree613342591e12a96725df715853a5e579ba1ec8ea /src/gallium/drivers/nouveau/nv30
parentebcdaa7bbc3a10fe59447ae77b508ee85eaa582f (diff)
Move nv30, nv50 and nvc0 to nouveau.
It is planned to ship openSUSE 13.1 with -shared libs. nouveau.la, nv30.la, nv50.la and nvc0.la are currently LIBADDs in all nouveau related targets. This change makes it possible to easily build one shared libnouveau.so which is then LIBADDed. Also dlopen will be faster for one library instead of three and build time on -jX will be reduced. Whitespace fixes were requested by 'git am'. Signed-off-by: Johannes Obermayr <[email protected]> Acked-by: Christoph Bumiller <[email protected]> Acked-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/gallium/drivers/nouveau/nv30')
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv01_2d.xml.h1416
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30-40_3d.xml.h2045
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_clear.c226
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_context.c263
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_context.h237
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_draw.c506
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_format.c259
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_format.h57
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_fragprog.c170
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_fragtex.c202
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_miptree.c490
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_push.c290
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_query.c274
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_resource.c77
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_resource.h75
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_screen.c588
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_screen.h51
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_state.c458
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_state.h144
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_state_validate.c538
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_texture.c306
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_transfer.c754
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_transfer.h40
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_vbo.c627
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_vertprog.c258
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_vertprog.h176
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_winsys.h158
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv40_vertprog.h178
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv40_verttex.c100
-rw-r--r--src/gallium/drivers/nouveau/nv30/nvfx_fragprog.c1251
-rw-r--r--src/gallium/drivers/nouveau/nv30/nvfx_shader.h525
-rw-r--r--src/gallium/drivers/nouveau/nv30/nvfx_vertprog.c1133
32 files changed, 13872 insertions, 0 deletions
diff --git a/src/gallium/drivers/nouveau/nv30/nv01_2d.xml.h b/src/gallium/drivers/nouveau/nv30/nv01_2d.xml.h
new file mode 100644
index 00000000000..afae00cd0a2
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv01_2d.xml.h
@@ -0,0 +1,1416 @@
+#ifndef _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV01_2D_XML
+#define _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV01_2D_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/skeggsb/git/envytools/rnndb/nv_objects.xml ( 794 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/copyright.xml ( 6452 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv_m2mf.xml ( 2696 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv_object.xml ( 12672 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nvchipsets.xml ( 3617 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv_defs.xml ( 4437 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv50_defs.xml ( 5468 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nvc0_m2mf.xml ( 2687 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv01_2d.xml ( 32584 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv04_dvd.xml ( 3000 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv03_3d.xml ( 5209 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv04_3d.xml ( 17759 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv_3ddefs.xml ( 16394 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv10_3d.xml ( 18437 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv20_3d.xml ( 21107 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv30-40_3d.xml ( 31987 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv50_2d.xml ( 11113 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv50_3d.xml ( 65233 bytes, from 2011-11-30 05:49:35)
+- /home/skeggsb/git/envytools/rnndb/nv50_compute.xml ( 14012 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nv84_crypt.xml ( 2071 bytes, from 2011-11-30 05:49:35)
+- /home/skeggsb/git/envytools/rnndb/nv31_mpeg.xml ( 2269 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/nvc0_3d.xml ( 52547 bytes, from 2011-11-30 05:49:35)
+- /home/skeggsb/git/envytools/rnndb/nvc0_compute.xml ( 10865 bytes, from 2011-10-22 08:01:09)
+- /home/skeggsb/git/envytools/rnndb/blob_nvc0_pcopy.xml ( 4516 bytes, from 2011-10-22 08:01:09)
+
+Copyright (C) 2006-2011 by the following authors:
+- Artur Huillet <[email protected]> (ahuillet)
+- Ben Skeggs (darktama, darktama_)
+- B. R. <[email protected]> (koala_br)
+- Carlos Martin <[email protected]> (carlosmn)
+- Christoph Bumiller <[email protected]> (calim, chrisbmr)
+- Dawid Gajownik <[email protected]> (gajownik)
+- Dmitry Baryshkov
+- Dmitry Eremin-Solenikov <[email protected]> (lumag)
+- EdB <[email protected]> (edb_)
+- Erik Waling <[email protected]> (erikwaling)
+- Francisco Jerez <[email protected]> (curro)
+- imirkin <[email protected]> (imirkin)
+- jb17bsome <[email protected]> (jb17bsome)
+- Jeremy Kolb <[email protected]> (kjeremy)
+- Laurent Carlier <[email protected]> (lordheavy)
+- Luca Barbieri <[email protected]> (lb, lb1)
+- Maarten Maathuis <[email protected]> (stillunknown)
+- Marcin Koƛcielnicki <[email protected]> (mwk, koriakin)
+- Mark Carey <[email protected]> (careym)
+- Matthieu Castet <[email protected]> (mat-c)
+- nvidiaman <[email protected]> (nvidiaman)
+- Patrice Mandin <[email protected]> (pmandin, pmdata)
+- Pekka Paalanen <[email protected]> (pq, ppaalanen)
+- Peter Popov <[email protected]> (ironpeter)
+- Richard Hughes <[email protected]> (hughsient)
+- Rudi Cilibrasi <[email protected]> (cilibrar)
+- Serge Martin
+- Simon Raffeiner
+- Stephane Loeuillet <[email protected]> (leroutier)
+- Stephane Marchesin <[email protected]> (marcheu)
+- sturmflut <[email protected]> (sturmflut)
+- Sylvain Munaut <[email protected]>
+- Victor Stinner <[email protected]> (haypo)
+- Wladmir van der Laan <[email protected]> (miathan6)
+- Younes Manton <[email protected]> (ymanton)
+
+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 COPYRIGHT OWNER(S) 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.
+*/
+
+
+
+#define NV01_BETA_DMA_NOTIFY 0x00000180
+
+#define NV01_BETA_BETA_1D31 0x00000300
+
+
+#define NV04_BETA4_DMA_NOTIFY 0x00000180
+
+#define NV04_BETA4_BETA_FACTOR 0x00000300
+
+
+#define NV01_CHROMA_DMA_NOTIFY 0x00000180
+
+#define NV01_CHROMA_COLOR_FORMAT 0x00000300
+#define NV01_CHROMA_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV01_CHROMA_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV01_CHROMA_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV01_CHROMA_COLOR 0x00000304
+
+
+#define NV01_PATTERN_DMA_NOTIFY 0x00000180
+
+#define NV01_PATTERN_COLOR_FORMAT 0x00000300
+#define NV01_PATTERN_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV01_PATTERN_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV01_PATTERN_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV01_PATTERN_MONOCHROME_FORMAT 0x00000304
+#define NV01_PATTERN_MONOCHROME_FORMAT_CGA6 0x00000001
+#define NV01_PATTERN_MONOCHROME_FORMAT_LE 0x00000002
+
+#define NV01_PATTERN_MONOCHROME_SHAPE 0x00000308
+#define NV01_PATTERN_MONOCHROME_SHAPE_8X8 0x00000000
+#define NV01_PATTERN_MONOCHROME_SHAPE_64X1 0x00000001
+#define NV01_PATTERN_MONOCHROME_SHAPE_1X64 0x00000002
+
+#define NV04_PATTERN_PATTERN_SELECT 0x0000030c
+#define NV04_PATTERN_PATTERN_SELECT_MONO 0x00000001
+#define NV04_PATTERN_PATTERN_SELECT_COLOR 0x00000002
+
+#define NV01_PATTERN_MONOCHROME_COLOR(i0) (0x00000310 + 0x4*(i0))
+#define NV01_PATTERN_MONOCHROME_COLOR__ESIZE 0x00000004
+#define NV01_PATTERN_MONOCHROME_COLOR__LEN 0x00000002
+
+#define NV01_PATTERN_MONOCHROME_PATTERN(i0) (0x00000318 + 0x4*(i0))
+#define NV01_PATTERN_MONOCHROME_PATTERN__ESIZE 0x00000004
+#define NV01_PATTERN_MONOCHROME_PATTERN__LEN 0x00000002
+
+#define NV04_PATTERN_PATTERN_Y8(i0) (0x00000400 + 0x4*(i0))
+#define NV04_PATTERN_PATTERN_Y8__ESIZE 0x00000004
+#define NV04_PATTERN_PATTERN_Y8__LEN 0x00000010
+#define NV04_PATTERN_PATTERN_Y8_Y0__MASK 0x000000ff
+#define NV04_PATTERN_PATTERN_Y8_Y0__SHIFT 0
+#define NV04_PATTERN_PATTERN_Y8_Y1__MASK 0x0000ff00
+#define NV04_PATTERN_PATTERN_Y8_Y1__SHIFT 8
+#define NV04_PATTERN_PATTERN_Y8_Y2__MASK 0x00ff0000
+#define NV04_PATTERN_PATTERN_Y8_Y2__SHIFT 16
+#define NV04_PATTERN_PATTERN_Y8_Y3__MASK 0xff000000
+#define NV04_PATTERN_PATTERN_Y8_Y3__SHIFT 24
+
+#define NV04_PATTERN_PATTERN_R5G6B5(i0) (0x00000500 + 0x4*(i0))
+#define NV04_PATTERN_PATTERN_R5G6B5__ESIZE 0x00000004
+#define NV04_PATTERN_PATTERN_R5G6B5__LEN 0x00000020
+#define NV04_PATTERN_PATTERN_R5G6B5_B0__MASK 0x0000001f
+#define NV04_PATTERN_PATTERN_R5G6B5_B0__SHIFT 0
+#define NV04_PATTERN_PATTERN_R5G6B5_G0__MASK 0x000007e0
+#define NV04_PATTERN_PATTERN_R5G6B5_G0__SHIFT 5
+#define NV04_PATTERN_PATTERN_R5G6B5_R0__MASK 0x0000f800
+#define NV04_PATTERN_PATTERN_R5G6B5_R0__SHIFT 11
+#define NV04_PATTERN_PATTERN_R5G6B5_B1__MASK 0x001f0000
+#define NV04_PATTERN_PATTERN_R5G6B5_B1__SHIFT 16
+#define NV04_PATTERN_PATTERN_R5G6B5_G1__MASK 0x07e00000
+#define NV04_PATTERN_PATTERN_R5G6B5_G1__SHIFT 21
+#define NV04_PATTERN_PATTERN_R5G6B5_R1__MASK 0xf8000000
+#define NV04_PATTERN_PATTERN_R5G6B5_R1__SHIFT 27
+
+#define NV04_PATTERN_PATTERN_X1R5G5B5(i0) (0x00000600 + 0x4*(i0))
+#define NV04_PATTERN_PATTERN_X1R5G5B5__ESIZE 0x00000004
+#define NV04_PATTERN_PATTERN_X1R5G5B5__LEN 0x00000020
+#define NV04_PATTERN_PATTERN_X1R5G5B5_B0__MASK 0x0000001f
+#define NV04_PATTERN_PATTERN_X1R5G5B5_B0__SHIFT 0
+#define NV04_PATTERN_PATTERN_X1R5G5B5_G0__MASK 0x000003e0
+#define NV04_PATTERN_PATTERN_X1R5G5B5_G0__SHIFT 5
+#define NV04_PATTERN_PATTERN_X1R5G5B5_R0__MASK 0x00007c00
+#define NV04_PATTERN_PATTERN_X1R5G5B5_R0__SHIFT 10
+#define NV04_PATTERN_PATTERN_X1R5G5B5_B1__MASK 0x001f0000
+#define NV04_PATTERN_PATTERN_X1R5G5B5_B1__SHIFT 16
+#define NV04_PATTERN_PATTERN_X1R5G5B5_G1__MASK 0x03e00000
+#define NV04_PATTERN_PATTERN_X1R5G5B5_G1__SHIFT 21
+#define NV04_PATTERN_PATTERN_X1R5G5B5_R1__MASK 0x7c000000
+#define NV04_PATTERN_PATTERN_X1R5G5B5_R1__SHIFT 26
+
+#define NV04_PATTERN_PATTERN_X8R8G8B8(i0) (0x00000700 + 0x4*(i0))
+#define NV04_PATTERN_PATTERN_X8R8G8B8__ESIZE 0x00000004
+#define NV04_PATTERN_PATTERN_X8R8G8B8__LEN 0x00000040
+#define NV04_PATTERN_PATTERN_X8R8G8B8_B__MASK 0x000000ff
+#define NV04_PATTERN_PATTERN_X8R8G8B8_B__SHIFT 0
+#define NV04_PATTERN_PATTERN_X8R8G8B8_G__MASK 0x0000ff00
+#define NV04_PATTERN_PATTERN_X8R8G8B8_G__SHIFT 8
+#define NV04_PATTERN_PATTERN_X8R8G8B8_R__MASK 0x00ff0000
+#define NV04_PATTERN_PATTERN_X8R8G8B8_R__SHIFT 16
+
+
+#define NV01_CLIP_DMA_NOTIFY 0x00000180
+
+#define NV01_CLIP_POINT 0x00000300
+#define NV01_CLIP_POINT_X__MASK 0x0000ffff
+#define NV01_CLIP_POINT_X__SHIFT 0
+#define NV01_CLIP_POINT_Y__MASK 0xffff0000
+#define NV01_CLIP_POINT_Y__SHIFT 16
+
+#define NV01_CLIP_SIZE 0x00000304
+#define NV01_CLIP_SIZE_W__MASK 0x0000ffff
+#define NV01_CLIP_SIZE_W__SHIFT 0
+#define NV01_CLIP_SIZE_H__MASK 0xffff0000
+#define NV01_CLIP_SIZE_H__SHIFT 16
+
+
+#define NV01_ROP_DMA_NOTIFY 0x00000180
+
+#define NV01_ROP_ROP 0x00000300
+
+
+#define NV04_SURFACE_2D_DMA_NOTIFY 0x00000180
+
+#define NV04_SURFACE_2D_DMA_IMAGE_SOURCE 0x00000184
+
+#define NV04_SURFACE_2D_DMA_IMAGE_DESTIN 0x00000188
+
+
+#define NV50_SURFACE_2D_SRC_LINEAR 0x00000200
+
+#define NV50_SURFACE_2D_SRC_TILE_MODE 0x00000204
+
+#define NV50_SURFACE_2D_SRC_WIDTH 0x00000208
+
+#define NV50_SURFACE_2D_SRC_HEIGHT 0x0000020c
+
+#define NV50_SURFACE_2D_UNK0210 0x00000210
+
+#define NV50_SURFACE_2D_UNK0214 0x00000214
+
+#define NV50_SURFACE_2D_DST_LINEAR 0x00000218
+
+#define NV50_SURFACE_2D_DST_TILE_MODE 0x0000021c
+
+#define NV50_SURFACE_2D_DST_WIDTH 0x00000220
+
+#define NV50_SURFACE_2D_DST_HEIGHT 0x00000224
+
+#define NV50_SURFACE_2D_UNK0228 0x00000228
+
+#define NV50_SURFACE_2D_UNK022C 0x0000022c
+
+#define NV50_SURFACE_2D_OFFSET_SOURCE_HIGH 0x00000230
+
+#define NV50_SURFACE_2D_OFFSET_DESTIN_HIGH 0x00000234
+
+#define NV04_SURFACE_2D_FORMAT 0x00000300
+#define NV04_SURFACE_2D_FORMAT_Y8 0x00000001
+#define NV04_SURFACE_2D_FORMAT_X1R5G5B5_Z1R5G5B5 0x00000002
+#define NV04_SURFACE_2D_FORMAT_X1R5G5B5_X1R5G5B5 0x00000003
+#define NV04_SURFACE_2D_FORMAT_R5G6B5 0x00000004
+#define NV04_SURFACE_2D_FORMAT_Y16 0x00000005
+#define NV04_SURFACE_2D_FORMAT_X8R8G8B8_Z8R8G8B8 0x00000006
+#define NV04_SURFACE_2D_FORMAT_X8R8G8B8_X8R8G8B8 0x00000007
+#define NV04_SURFACE_2D_FORMAT_X1A7R8G8B8_Z1A7R8G8B8 0x00000008
+#define NV04_SURFACE_2D_FORMAT_X1A7R8G8B8_X1A7R8G8B8 0x00000009
+#define NV04_SURFACE_2D_FORMAT_A8R8G8B8 0x0000000a
+#define NV04_SURFACE_2D_FORMAT_Y32 0x0000000b
+
+#define NV04_SURFACE_2D_PITCH 0x00000304
+#define NV04_SURFACE_2D_PITCH_SOURCE__MASK 0x0000ffff
+#define NV04_SURFACE_2D_PITCH_SOURCE__SHIFT 0
+#define NV04_SURFACE_2D_PITCH_DESTIN__MASK 0xffff0000
+#define NV04_SURFACE_2D_PITCH_DESTIN__SHIFT 16
+
+#define NV04_SURFACE_2D_OFFSET_SOURCE 0x00000308
+
+#define NV04_SURFACE_2D_OFFSET_DESTIN 0x0000030c
+
+
+#define NV04_SURFACE_SWZ_DMA_NOTIFY 0x00000180
+
+#define NV04_SURFACE_SWZ_DMA_IMAGE 0x00000184
+
+#define NV04_SURFACE_SWZ_FORMAT 0x00000300
+#define NV04_SURFACE_SWZ_FORMAT_COLOR__MASK 0x000000ff
+#define NV04_SURFACE_SWZ_FORMAT_COLOR__SHIFT 0
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_Y8 0x00000001
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5 0x00000002
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X1R5G5B5_X1R5G5B5 0x00000003
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5 0x00000004
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_Y16 0x00000005
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8 0x00000006
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X8R8G8B8_X8R8G8B8 0x00000007
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8 0x00000008
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8 0x00000009
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8 0x0000000a
+#define NV04_SURFACE_SWZ_FORMAT_COLOR_Y32 0x0000000b
+#define NV04_SURFACE_SWZ_FORMAT_BASE_SIZE_U__MASK 0x00ff0000
+#define NV04_SURFACE_SWZ_FORMAT_BASE_SIZE_U__SHIFT 16
+#define NV04_SURFACE_SWZ_FORMAT_BASE_SIZE_V__MASK 0xff000000
+#define NV04_SURFACE_SWZ_FORMAT_BASE_SIZE_V__SHIFT 24
+
+#define NV04_SURFACE_SWZ_OFFSET 0x00000304
+
+
+#define NV01_POINT_PATCH 0x0000010c
+
+#define NV01_POINT_DMA_NOTIFY 0x00000180
+
+#define NV01_POINT_CLIP 0x00000184
+
+#define NV01_POINT_PATTERN 0x00000188
+
+#define NV01_POINT_ROP 0x0000018c
+
+#define NV01_POINT_BETA 0x00000190
+
+#define NV01_POINT_SURFACE_DST 0x00000194
+
+#define NV01_POINT_OPERATION 0x000002fc
+#define NV01_POINT_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_POINT_OPERATION_ROP_AND 0x00000001
+#define NV01_POINT_OPERATION_BLEND_AND 0x00000002
+#define NV01_POINT_OPERATION_SRCCOPY 0x00000003
+#define NV01_POINT_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_POINT_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_POINT_COLOR_FORMAT 0x00000300
+#define NV01_POINT_COLOR_FORMAT_X16A8Y8 0x00000001
+#define NV01_POINT_COLOR_FORMAT_X24Y8 0x00000002
+#define NV01_POINT_COLOR_FORMAT_X16A1R5G5B5 0x00000003
+#define NV01_POINT_COLOR_FORMAT_X17R5G5B5 0x00000004
+#define NV01_POINT_COLOR_FORMAT_A8R8G8B8 0x00000005
+#define NV01_POINT_COLOR_FORMAT_X8R8G8B8 0x00000006
+#define NV01_POINT_COLOR_FORMAT_A16Y16 0x00000007
+#define NV01_POINT_COLOR_FORMAT_X16Y16 0x00000008
+
+#define NV01_POINT_COLOR 0x00000304
+
+#define NV01_POINT_POINT(i0) (0x00000400 + 0x4*(i0))
+#define NV01_POINT_POINT__ESIZE 0x00000004
+#define NV01_POINT_POINT__LEN 0x00000020
+#define NV01_POINT_POINT_X__MASK 0x0000ffff
+#define NV01_POINT_POINT_X__SHIFT 0
+#define NV01_POINT_POINT_Y__MASK 0xffff0000
+#define NV01_POINT_POINT_Y__SHIFT 16
+
+#define NV01_POINT_POINT32_X(i0) (0x00000480 + 0x8*(i0))
+#define NV01_POINT_POINT32_X__ESIZE 0x00000008
+#define NV01_POINT_POINT32_X__LEN 0x00000010
+
+#define NV01_POINT_POINT32_Y(i0) (0x00000484 + 0x8*(i0))
+#define NV01_POINT_POINT32_Y__ESIZE 0x00000008
+#define NV01_POINT_POINT32_Y__LEN 0x00000010
+
+#define NV01_POINT_CPOINT_COLOR(i0) (0x00000500 + 0x8*(i0))
+#define NV01_POINT_CPOINT_COLOR__ESIZE 0x00000008
+#define NV01_POINT_CPOINT_COLOR__LEN 0x00000010
+
+#define NV01_POINT_CPOINT_POINT(i0) (0x00000504 + 0x8*(i0))
+#define NV01_POINT_CPOINT_POINT__ESIZE 0x00000008
+#define NV01_POINT_CPOINT_POINT__LEN 0x00000010
+#define NV01_POINT_CPOINT_POINT_X__MASK 0x0000ffff
+#define NV01_POINT_CPOINT_POINT_X__SHIFT 0
+#define NV01_POINT_CPOINT_POINT_Y__MASK 0xffff0000
+#define NV01_POINT_CPOINT_POINT_Y__SHIFT 16
+
+
+#define NV01_LINE_PATCH 0x0000010c
+
+#define NV01_LINE_DMA_NOTIFY 0x00000180
+
+#define NV01_LINE_CLIP 0x00000184
+
+#define NV01_LINE_PATTERN 0x00000188
+
+#define NV04_LIN_PATTERN 0x00000188
+
+#define NV01_LINE_ROP 0x0000018c
+
+#define NV01_LINE_BETA 0x00000190
+
+#define NV01_LINE_SURFACE_DST 0x00000194
+
+
+#define NV04_LIN_BETA4 0x00000194
+
+#define NV04_LIN_SURFACE 0x00000198
+
+#define NV01_LINE_OPERATION 0x000002fc
+#define NV01_LINE_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_LINE_OPERATION_ROP_AND 0x00000001
+#define NV01_LINE_OPERATION_BLEND_AND 0x00000002
+#define NV01_LINE_OPERATION_SRCCOPY 0x00000003
+#define NV01_LINE_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_LINE_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_LINE_COLOR_FORMAT 0x00000300
+#define NV01_LINE_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV01_LINE_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV01_LINE_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV01_LINE_COLOR 0x00000304
+
+#define NV01_LINE_LINE_POINT0(i0) (0x00000400 + 0x8*(i0))
+#define NV01_LINE_LINE_POINT0__ESIZE 0x00000008
+#define NV01_LINE_LINE_POINT0__LEN 0x00000010
+#define NV01_LINE_LINE_POINT0_X__MASK 0x0000ffff
+#define NV01_LINE_LINE_POINT0_X__SHIFT 0
+#define NV01_LINE_LINE_POINT0_Y__MASK 0xffff0000
+#define NV01_LINE_LINE_POINT0_Y__SHIFT 16
+
+#define NV01_LINE_LINE_POINT1(i0) (0x00000404 + 0x8*(i0))
+#define NV01_LINE_LINE_POINT1__ESIZE 0x00000008
+#define NV01_LINE_LINE_POINT1__LEN 0x00000010
+#define NV01_LINE_LINE_POINT1_X__MASK 0x0000ffff
+#define NV01_LINE_LINE_POINT1_X__SHIFT 0
+#define NV01_LINE_LINE_POINT1_Y__MASK 0xffff0000
+#define NV01_LINE_LINE_POINT1_Y__SHIFT 16
+
+#define NV01_LINE_LINE32_POINT0_X(i0) (0x00000480 + 0x10*(i0))
+#define NV01_LINE_LINE32_POINT0_X__ESIZE 0x00000010
+#define NV01_LINE_LINE32_POINT0_X__LEN 0x00000008
+
+#define NV01_LINE_LINE32_POINT0_Y(i0) (0x00000484 + 0x10*(i0))
+#define NV01_LINE_LINE32_POINT0_Y__ESIZE 0x00000010
+#define NV01_LINE_LINE32_POINT0_Y__LEN 0x00000008
+
+#define NV01_LINE_LINE32_POINT1_X(i0) (0x00000488 + 0x10*(i0))
+#define NV01_LINE_LINE32_POINT1_X__ESIZE 0x00000010
+#define NV01_LINE_LINE32_POINT1_X__LEN 0x00000008
+
+#define NV01_LINE_LINE32_POINT1_Y(i0) (0x0000048c + 0x10*(i0))
+#define NV01_LINE_LINE32_POINT1_Y__ESIZE 0x00000010
+#define NV01_LINE_LINE32_POINT1_Y__LEN 0x00000008
+
+#define NV01_LINE_POLYLINE(i0) (0x00000500 + 0x4*(i0))
+#define NV01_LINE_POLYLINE__ESIZE 0x00000004
+#define NV01_LINE_POLYLINE__LEN 0x00000020
+#define NV01_LINE_POLYLINE_X__MASK 0x0000ffff
+#define NV01_LINE_POLYLINE_X__SHIFT 0
+#define NV01_LINE_POLYLINE_Y__MASK 0xffff0000
+#define NV01_LINE_POLYLINE_Y__SHIFT 16
+
+#define NV01_LINE_POLYLINE32_POINT_X(i0) (0x00000580 + 0x8*(i0))
+#define NV01_LINE_POLYLINE32_POINT_X__ESIZE 0x00000008
+#define NV01_LINE_POLYLINE32_POINT_X__LEN 0x00000010
+
+#define NV01_LINE_POLYLINE32_POINT_Y(i0) (0x00000584 + 0x8*(i0))
+#define NV01_LINE_POLYLINE32_POINT_Y__ESIZE 0x00000008
+#define NV01_LINE_POLYLINE32_POINT_Y__LEN 0x00000010
+
+#define NV01_LINE_CPOLYLINE_COLOR(i0) (0x00000600 + 0x8*(i0))
+#define NV01_LINE_CPOLYLINE_COLOR__ESIZE 0x00000008
+#define NV01_LINE_CPOLYLINE_COLOR__LEN 0x00000010
+
+#define NV01_LINE_CPOLYLINE_POINT(i0) (0x00000604 + 0x8*(i0))
+#define NV01_LINE_CPOLYLINE_POINT__ESIZE 0x00000008
+#define NV01_LINE_CPOLYLINE_POINT__LEN 0x00000010
+#define NV01_LINE_CPOLYLINE_POINT_X__MASK 0x0000ffff
+#define NV01_LINE_CPOLYLINE_POINT_X__SHIFT 0
+#define NV01_LINE_CPOLYLINE_POINT_Y__MASK 0xffff0000
+#define NV01_LINE_CPOLYLINE_POINT_Y__SHIFT 16
+
+
+#define NV01_TRI_PATCH 0x0000010c
+
+#define NV01_TRI_DMA_NOTIFY 0x00000180
+
+#define NV01_TRI_CLIP 0x00000184
+
+#define NV01_TRI_PATTERN 0x00000188
+
+#define NV04_TRI_PATTERN 0x00000188
+
+#define NV01_TRI_ROP 0x0000018c
+
+#define NV01_TRI_BETA 0x00000190
+
+#define NV01_TRI_SURFACE_DST 0x00000194
+
+
+#define NV04_TRI_BETA4 0x00000194
+
+#define NV04_TRI_SURFACE 0x00000198
+
+#define NV01_TRI_OPERATION 0x000002fc
+#define NV01_TRI_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_TRI_OPERATION_ROP_AND 0x00000001
+#define NV01_TRI_OPERATION_BLEND_AND 0x00000002
+#define NV01_TRI_OPERATION_SRCCOPY 0x00000003
+#define NV01_TRI_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_TRI_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_TRI_COLOR_FORMAT 0x00000300
+#define NV01_TRI_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV01_TRI_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV01_TRI_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV01_TRI_COLOR 0x00000304
+
+#define NV01_TRI_TRIANGLE_POINT0 0x00000310
+#define NV01_TRI_TRIANGLE_POINT0_X__MASK 0x0000ffff
+#define NV01_TRI_TRIANGLE_POINT0_X__SHIFT 0
+#define NV01_TRI_TRIANGLE_POINT0_Y__MASK 0xffff0000
+#define NV01_TRI_TRIANGLE_POINT0_Y__SHIFT 16
+
+#define NV01_TRI_TRIANGLE_POINT1 0x00000314
+#define NV01_TRI_TRIANGLE_POINT1_X__MASK 0x0000ffff
+#define NV01_TRI_TRIANGLE_POINT1_X__SHIFT 0
+#define NV01_TRI_TRIANGLE_POINT1_Y__MASK 0xffff0000
+#define NV01_TRI_TRIANGLE_POINT1_Y__SHIFT 16
+
+#define NV01_TRI_TRIANGLE_POINT2 0x00000318
+#define NV01_TRI_TRIANGLE_POINT2_X__MASK 0x0000ffff
+#define NV01_TRI_TRIANGLE_POINT2_X__SHIFT 0
+#define NV01_TRI_TRIANGLE_POINT2_Y__MASK 0xffff0000
+#define NV01_TRI_TRIANGLE_POINT2_Y__SHIFT 16
+
+#define NV01_TRI_TRIANGLE32_POINT0_X 0x00000320
+
+#define NV01_TRI_TRIANGLE32_POINT0_Y 0x00000324
+
+#define NV01_TRI_TRIANGLE32_POINT1_X 0x00000328
+
+#define NV01_TRI_TRIANGLE32_POINT1_Y 0x0000032c
+
+#define NV01_TRI_TRIANGLE32_POINT2_X 0x00000330
+
+#define NV01_TRI_TRIANGLE32_POINT2_Y 0x00000334
+
+#define NV01_TRI_TRIMESH(i0) (0x00000400 + 0x4*(i0))
+#define NV01_TRI_TRIMESH__ESIZE 0x00000004
+#define NV01_TRI_TRIMESH__LEN 0x00000020
+#define NV01_TRI_TRIMESH_X__MASK 0x0000ffff
+#define NV01_TRI_TRIMESH_X__SHIFT 0
+#define NV01_TRI_TRIMESH_Y__MASK 0xffff0000
+#define NV01_TRI_TRIMESH_Y__SHIFT 16
+
+#define NV01_TRI_TRIMESH32_POINT_X(i0) (0x00000480 + 0x8*(i0))
+#define NV01_TRI_TRIMESH32_POINT_X__ESIZE 0x00000008
+#define NV01_TRI_TRIMESH32_POINT_X__LEN 0x00000010
+
+#define NV01_TRI_TRIMESH32_POINT_Y(i0) (0x00000484 + 0x8*(i0))
+#define NV01_TRI_TRIMESH32_POINT_Y__ESIZE 0x00000008
+#define NV01_TRI_TRIMESH32_POINT_Y__LEN 0x00000010
+
+#define NV01_TRI_CTRIANGLE_COLOR(i0) (0x00000500 + 0x10*(i0))
+#define NV01_TRI_CTRIANGLE_COLOR__ESIZE 0x00000010
+#define NV01_TRI_CTRIANGLE_COLOR__LEN 0x00000008
+
+#define NV01_TRI_CTRIANGLE_POINT0(i0) (0x00000504 + 0x10*(i0))
+#define NV01_TRI_CTRIANGLE_POINT0__ESIZE 0x00000010
+#define NV01_TRI_CTRIANGLE_POINT0__LEN 0x00000008
+#define NV01_TRI_CTRIANGLE_POINT0_X__MASK 0x0000ffff
+#define NV01_TRI_CTRIANGLE_POINT0_X__SHIFT 0
+#define NV01_TRI_CTRIANGLE_POINT0_Y__MASK 0xffff0000
+#define NV01_TRI_CTRIANGLE_POINT0_Y__SHIFT 16
+
+#define NV01_TRI_CTRIANGLE_POINT1(i0) (0x00000508 + 0x10*(i0))
+#define NV01_TRI_CTRIANGLE_POINT1__ESIZE 0x00000010
+#define NV01_TRI_CTRIANGLE_POINT1__LEN 0x00000008
+#define NV01_TRI_CTRIANGLE_POINT1_X__MASK 0x0000ffff
+#define NV01_TRI_CTRIANGLE_POINT1_X__SHIFT 0
+#define NV01_TRI_CTRIANGLE_POINT1_Y__MASK 0xffff0000
+#define NV01_TRI_CTRIANGLE_POINT1_Y__SHIFT 16
+
+#define NV01_TRI_CTRIANGLE_POINT2(i0) (0x0000050c + 0x10*(i0))
+#define NV01_TRI_CTRIANGLE_POINT2__ESIZE 0x00000010
+#define NV01_TRI_CTRIANGLE_POINT2__LEN 0x00000008
+#define NV01_TRI_CTRIANGLE_POINT2_X__MASK 0x0000ffff
+#define NV01_TRI_CTRIANGLE_POINT2_X__SHIFT 0
+#define NV01_TRI_CTRIANGLE_POINT2_Y__MASK 0xffff0000
+#define NV01_TRI_CTRIANGLE_POINT2_Y__SHIFT 16
+
+#define NV01_TRI_CTRIMESH_COLOR(i0) (0x00000580 + 0x8*(i0))
+#define NV01_TRI_CTRIMESH_COLOR__ESIZE 0x00000008
+#define NV01_TRI_CTRIMESH_COLOR__LEN 0x00000010
+
+#define NV01_TRI_CTRIMESH_POINT(i0) (0x00000584 + 0x8*(i0))
+#define NV01_TRI_CTRIMESH_POINT__ESIZE 0x00000008
+#define NV01_TRI_CTRIMESH_POINT__LEN 0x00000010
+#define NV01_TRI_CTRIMESH_POINT_X__MASK 0x0000ffff
+#define NV01_TRI_CTRIMESH_POINT_X__SHIFT 0
+#define NV01_TRI_CTRIMESH_POINT_Y__MASK 0xffff0000
+#define NV01_TRI_CTRIMESH_POINT_Y__SHIFT 16
+
+
+#define NV01_RECT_PATCH 0x0000010c
+
+#define NV01_RECT_DMA_NOTIFY 0x00000180
+
+#define NV01_RECT_CLIP 0x00000184
+
+#define NV01_RECT_PATTERN 0x00000188
+
+#define NV04_RECT_PATTERN 0x00000188
+
+#define NV01_RECT_ROP 0x0000018c
+
+#define NV01_RECT_BETA 0x00000190
+
+#define NV01_RECT_SURFACE_DST 0x00000194
+
+
+#define NV04_RECT_BETA4 0x00000194
+
+#define NV04_RECT_SURFACE 0x00000198
+
+#define NV01_RECT_OPERATION 0x000002fc
+#define NV01_RECT_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_RECT_OPERATION_ROP_AND 0x00000001
+#define NV01_RECT_OPERATION_BLEND_AND 0x00000002
+#define NV01_RECT_OPERATION_SRCCOPY 0x00000003
+#define NV01_RECT_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_RECT_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_RECT_COLOR_FORMAT 0x00000300
+#define NV01_RECT_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV01_RECT_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV01_RECT_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV01_RECT_COLOR 0x00000304
+
+#define NV01_RECT_RECTANGLE_POINT(i0) (0x00000400 + 0x8*(i0))
+#define NV01_RECT_RECTANGLE_POINT__ESIZE 0x00000008
+#define NV01_RECT_RECTANGLE_POINT__LEN 0x00000010
+#define NV01_RECT_RECTANGLE_POINT_X__MASK 0x0000ffff
+#define NV01_RECT_RECTANGLE_POINT_X__SHIFT 0
+#define NV01_RECT_RECTANGLE_POINT_Y__MASK 0xffff0000
+#define NV01_RECT_RECTANGLE_POINT_Y__SHIFT 16
+
+#define NV01_RECT_RECTANGLE_SIZE(i0) (0x00000404 + 0x8*(i0))
+#define NV01_RECT_RECTANGLE_SIZE__ESIZE 0x00000008
+#define NV01_RECT_RECTANGLE_SIZE__LEN 0x00000010
+#define NV01_RECT_RECTANGLE_SIZE_W__MASK 0x0000ffff
+#define NV01_RECT_RECTANGLE_SIZE_W__SHIFT 0
+#define NV01_RECT_RECTANGLE_SIZE_H__MASK 0xffff0000
+#define NV01_RECT_RECTANGLE_SIZE_H__SHIFT 16
+
+
+#define NV01_BLIT_PATCH 0x0000010c
+
+
+#define NV15_BLIT_WAIT_FOR_IDLE 0x00000108
+
+#define NV15_BLIT_FLIP_SET_READ 0x00000120
+
+#define NV15_BLIT_FLIP_SET_WRITE 0x00000124
+
+#define NV15_BLIT_FLIP_MAX 0x00000128
+
+#define NV15_BLIT_FLIP_INCR_WRITE 0x0000012c
+
+#define NV15_BLIT_FLIP_WAIT 0x00000130
+
+#define NV15_BLIT_FLIP_CRTC_INCR_READ 0x00000134
+
+#define NV01_BLIT_DMA_NOTIFY 0x00000180
+
+#define NV01_BLIT_COLOR_KEY 0x00000184
+
+#define NV04_BLIT_COLOR_KEY 0x00000184
+
+#define NV01_BLIT_CLIP 0x00000188
+
+#define NV01_BLIT_PATTERN 0x0000018c
+
+#define NV04_BLIT_PATTERN 0x0000018c
+
+#define NV01_BLIT_ROP 0x00000190
+
+#define NV01_BLIT_BETA 0x00000194
+
+
+#define NV01_BLIT_SURFACE_SRC 0x00000198
+
+#define NV01_BLIT_SURFACE_DST 0x0000019c
+
+
+#define NV04_BLIT_BETA4 0x00000198
+
+#define NV04_BLIT_SURFACES 0x0000019c
+
+#define NV01_BLIT_OPERATION 0x000002fc
+#define NV01_BLIT_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_BLIT_OPERATION_ROP_AND 0x00000001
+#define NV01_BLIT_OPERATION_BLEND_AND 0x00000002
+#define NV01_BLIT_OPERATION_SRCCOPY 0x00000003
+#define NV01_BLIT_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_BLIT_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_BLIT_POINT_IN 0x00000300
+#define NV01_BLIT_POINT_IN_X__MASK 0x0000ffff
+#define NV01_BLIT_POINT_IN_X__SHIFT 0
+#define NV01_BLIT_POINT_IN_Y__MASK 0xffff0000
+#define NV01_BLIT_POINT_IN_Y__SHIFT 16
+
+#define NV01_BLIT_POINT_OUT 0x00000304
+#define NV01_BLIT_POINT_OUT_X__MASK 0x0000ffff
+#define NV01_BLIT_POINT_OUT_X__SHIFT 0
+#define NV01_BLIT_POINT_OUT_Y__MASK 0xffff0000
+#define NV01_BLIT_POINT_OUT_Y__SHIFT 16
+
+#define NV01_BLIT_SIZE 0x00000308
+#define NV01_BLIT_SIZE_W__MASK 0x0000ffff
+#define NV01_BLIT_SIZE_W__SHIFT 0
+#define NV01_BLIT_SIZE_H__MASK 0xffff0000
+#define NV01_BLIT_SIZE_H__SHIFT 16
+
+
+#define NV04_INDEX_PATCH 0x0000010c
+
+#define NV04_INDEX_DMA_NOTIFY 0x00000180
+
+#define NV04_INDEX_DMA_LUT 0x00000184
+
+#define NV04_INDEX_COLOR_KEY 0x00000188
+
+#define NV04_INDEX_CLIP 0x0000018c
+
+#define NV04_INDEX_PATTERN 0x00000190
+
+#define NV04_INDEX_ROP 0x00000194
+
+#define NV04_INDEX_BETA 0x00000198
+
+#define NV04_INDEX_BETA4 0x0000019c
+
+#define NV04_INDEX_SURFACE 0x000001a0
+
+#define NV05_INDEX_SURFACE 0x000001a0
+
+#define NV05_INDEX_COLOR_CONVERSION 0x000003e0
+
+#define NV04_INDEX_OPERATION 0x000003e4
+
+#define NV04_INDEX_COLOR_FORMAT 0x000003e8
+
+#define NV04_INDEX_INDEX_FORMAT 0x000003ec
+
+#define NV04_INDEX_LUT_OFFSET 0x000003f0
+
+#define NV04_INDEX_POINT 0x000003f4
+
+#define NV04_INDEX_SIZE_OUT 0x000003f8
+
+#define NV04_INDEX_SIZE_IN 0x000003fc
+
+#define NV04_INDEX_COLOR(i0) (0x00000400 + 0x4*(i0))
+#define NV04_INDEX_COLOR__ESIZE 0x00000004
+#define NV04_INDEX_COLOR__LEN 0x00000700
+
+
+#define NV10_IFC_WAIT_FOR_IDLE 0x00000108
+
+#define NV01_IFC_PATCH 0x0000010c
+
+#define NV01_IFC_DMA_NOTIFY 0x00000180
+
+#define NV01_IFC_COLOR_KEY 0x00000184
+
+#define NV04_IFC_COLOR_KEY 0x00000184
+
+#define NV01_IFC_CLIP 0x00000188
+
+#define NV01_IFC_PATTERN 0x0000018c
+
+#define NV04_IFC_PATTERN 0x0000018c
+
+#define NV01_IFC_ROP 0x00000190
+
+#define NV01_IFC_BETA 0x00000194
+
+
+#define NV01_IFC_SURFACE_DST 0x00000198
+
+
+#define NV04_IFC_BETA4 0x00000198
+
+#define NV04_IFC_SURFACE 0x0000019c
+
+#define NV05_IFC_COLOR_CONVERSION 0x000002f8
+
+#define NV01_IFC_OPERATION 0x000002fc
+#define NV01_IFC_OPERATION_SRCCOPY_AND 0x00000000
+#define NV01_IFC_OPERATION_ROP_AND 0x00000001
+#define NV01_IFC_OPERATION_BLEND_AND 0x00000002
+#define NV01_IFC_OPERATION_SRCCOPY 0x00000003
+#define NV01_IFC_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV01_IFC_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV01_IFC_COLOR_FORMAT 0x00000300
+#define NV01_IFC_COLOR_FORMAT_R5G6G5 0x00000001
+#define NV01_IFC_COLOR_FORMAT_A1R5G5B5 0x00000002
+#define NV01_IFC_COLOR_FORMAT_X1R5G5B5 0x00000003
+#define NV01_IFC_COLOR_FORMAT_A8R8G8B8 0x00000004
+#define NV01_IFC_COLOR_FORMAT_X8R8G8B8 0x00000005
+
+#define NV01_IFC_POINT 0x00000304
+#define NV01_IFC_POINT_X__MASK 0x0000ffff
+#define NV01_IFC_POINT_X__SHIFT 0
+#define NV01_IFC_POINT_Y__MASK 0xffff0000
+#define NV01_IFC_POINT_Y__SHIFT 16
+
+#define NV01_IFC_SIZE_OUT 0x00000308
+#define NV01_IFC_SIZE_OUT_W__MASK 0x0000ffff
+#define NV01_IFC_SIZE_OUT_W__SHIFT 0
+#define NV01_IFC_SIZE_OUT_H__MASK 0xffff0000
+#define NV01_IFC_SIZE_OUT_H__SHIFT 16
+
+#define NV01_IFC_SIZE_IN 0x0000030c
+#define NV01_IFC_SIZE_IN_W__MASK 0x0000ffff
+#define NV01_IFC_SIZE_IN_W__SHIFT 0
+#define NV01_IFC_SIZE_IN_H__MASK 0xffff0000
+#define NV01_IFC_SIZE_IN_H__SHIFT 16
+
+#define NV01_IFC_COLOR(i0) (0x00000400 + 0x4*(i0))
+#define NV01_IFC_COLOR__ESIZE 0x00000004
+#define NV01_IFC_COLOR__LEN 0x00000020
+
+#define NV04_IFC_COLOR(i0) (0x00000400 + 0x4*(i0))
+#define NV04_IFC_COLOR__ESIZE 0x00000004
+#define NV04_IFC_COLOR__LEN 0x00000700
+
+
+#define NV03_SIFC_PATCH 0x0000010c
+
+#define NV03_SIFC_DMA_NOTIFY 0x00000180
+
+#define NV03_SIFC_COLOR_KEY 0x00000184
+
+#define NV04_SIFC_COLOR_KEY 0x00000184
+
+#define NV03_SIFC_PATTERN 0x00000188
+
+#define NV04_SIFC_PATTERN 0x00000188
+
+#define NV03_SIFC_ROP 0x0000018c
+
+#define NV03_SIFC_BETA 0x00000190
+
+
+#define NV03_SIFC_SURFACE_DST 0x00000194
+
+
+#define NV04_SIFC_BETA4 0x00000194
+
+#define NV04_SIFC_SURFACE 0x00000198
+
+#define NV05_SIFC_COLOR_CONVERSION 0x000002f8
+
+#define NV03_SIFC_OPERATION 0x000002fc
+
+#define NV03_SIFC_COLOR_FORMAT 0x00000300
+
+#define NV03_SIFC_SIZE_IN 0x00000304
+#define NV03_SIFC_SIZE_IN_W__MASK 0x0000ffff
+#define NV03_SIFC_SIZE_IN_W__SHIFT 0
+#define NV03_SIFC_SIZE_IN_H__MASK 0xffff0000
+#define NV03_SIFC_SIZE_IN_H__SHIFT 16
+
+#define NV03_SIFC_DX_DU 0x00000308
+
+#define NV03_SIFC_DY_DV 0x0000030c
+
+#define NV03_SIFC_CLIP_POINT 0x00000310
+#define NV03_SIFC_CLIP_POINT_X__MASK 0x0000ffff
+#define NV03_SIFC_CLIP_POINT_X__SHIFT 0
+#define NV03_SIFC_CLIP_POINT_Y__MASK 0xffff0000
+#define NV03_SIFC_CLIP_POINT_Y__SHIFT 16
+
+#define NV03_SIFC_CLIP_SIZE 0x00000314
+#define NV03_SIFC_CLIP_SIZE_W__MASK 0x0000ffff
+#define NV03_SIFC_CLIP_SIZE_W__SHIFT 0
+#define NV03_SIFC_CLIP_SIZE_H__MASK 0xffff0000
+#define NV03_SIFC_CLIP_SIZE_H__SHIFT 16
+
+#define NV03_SIFC_POINT12D4 0x00000318
+#define NV03_SIFC_POINT12D4_X__MASK 0x0000ffff
+#define NV03_SIFC_POINT12D4_X__SHIFT 0
+#define NV03_SIFC_POINT12D4_Y__MASK 0xffff0000
+#define NV03_SIFC_POINT12D4_Y__SHIFT 16
+
+#define NV03_SIFC_COLOR(i0) (0x00000400 + 0x4*(i0))
+#define NV03_SIFC_COLOR__ESIZE 0x00000004
+#define NV03_SIFC_COLOR__LEN 0x00000700
+
+
+#define NV10_SIFM_WAIT_FOR_IDLE 0x00000108
+
+#define NV03_SIFM_DMA_NOTIFY 0x00000180
+
+#define NV03_SIFM_DMA_IMAGE 0x00000184
+
+#define NV03_SIFM_PATTERN 0x00000188
+
+#define NV04_SIFM_PATTERN 0x00000188
+
+#define NV03_SIFM_ROP 0x0000018c
+
+#define NV03_SIFM_BETA 0x00000190
+
+
+#define NV03_SIFM_SURFACE_DST 0x00000194
+
+
+#define NV04_SIFM_BETA4 0x00000194
+
+#define NV04_SIFM_SURFACE 0x00000198
+
+#define NV05_SIFM_SURFACE 0x00000198
+
+#define NV05_SIFM_COLOR_CONVERSION 0x000002fc
+#define NV05_SIFM_COLOR_CONVERSION_DITHER 0x00000000
+#define NV05_SIFM_COLOR_CONVERSION_TRUNCATE 0x00000001
+#define NV05_SIFM_COLOR_CONVERSION_SUBTR_TRUNCATE 0x00000002
+
+#define NV03_SIFM_COLOR_FORMAT 0x00000300
+#define NV03_SIFM_COLOR_FORMAT_A1R5G5B5 0x00000001
+#define NV03_SIFM_COLOR_FORMAT_X1R5G5B5 0x00000002
+#define NV03_SIFM_COLOR_FORMAT_A8R8G8B8 0x00000003
+#define NV03_SIFM_COLOR_FORMAT_X8R8G8B8 0x00000004
+#define NV03_SIFM_COLOR_FORMAT_V8YB8U8YA8 0x00000005
+#define NV03_SIFM_COLOR_FORMAT_YB8V8YA8U8 0x00000006
+#define NV03_SIFM_COLOR_FORMAT_R5G6B5 0x00000007
+#define NV03_SIFM_COLOR_FORMAT_Y8 0x00000008
+#define NV03_SIFM_COLOR_FORMAT_AY8 0x00000009
+
+#define NV03_SIFM_OPERATION 0x00000304
+#define NV03_SIFM_OPERATION_SRCCOPY_AND 0x00000000
+#define NV03_SIFM_OPERATION_ROP_AND 0x00000001
+#define NV03_SIFM_OPERATION_BLEND_AND 0x00000002
+#define NV03_SIFM_OPERATION_SRCCOPY 0x00000003
+#define NV03_SIFM_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV03_SIFM_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV03_SIFM_CLIP_POINT 0x00000308
+#define NV03_SIFM_CLIP_POINT_X__MASK 0x0000ffff
+#define NV03_SIFM_CLIP_POINT_X__SHIFT 0
+#define NV03_SIFM_CLIP_POINT_Y__MASK 0xffff0000
+#define NV03_SIFM_CLIP_POINT_Y__SHIFT 16
+
+#define NV03_SIFM_CLIP_SIZE 0x0000030c
+#define NV03_SIFM_CLIP_SIZE_W__MASK 0x0000ffff
+#define NV03_SIFM_CLIP_SIZE_W__SHIFT 0
+#define NV03_SIFM_CLIP_SIZE_H__MASK 0xffff0000
+#define NV03_SIFM_CLIP_SIZE_H__SHIFT 16
+
+#define NV03_SIFM_OUT_POINT 0x00000310
+#define NV03_SIFM_OUT_POINT_X__MASK 0x0000ffff
+#define NV03_SIFM_OUT_POINT_X__SHIFT 0
+#define NV03_SIFM_OUT_POINT_Y__MASK 0xffff0000
+#define NV03_SIFM_OUT_POINT_Y__SHIFT 16
+
+#define NV03_SIFM_OUT_SIZE 0x00000314
+#define NV03_SIFM_OUT_SIZE_W__MASK 0x0000ffff
+#define NV03_SIFM_OUT_SIZE_W__SHIFT 0
+#define NV03_SIFM_OUT_SIZE_H__MASK 0xffff0000
+#define NV03_SIFM_OUT_SIZE_H__SHIFT 16
+
+#define NV03_SIFM_DU_DX 0x00000318
+
+#define NV03_SIFM_DV_DY 0x0000031c
+
+#define NV03_SIFM_SIZE 0x00000400
+#define NV03_SIFM_SIZE_W__MASK 0x0000ffff
+#define NV03_SIFM_SIZE_W__SHIFT 0
+#define NV03_SIFM_SIZE_H__MASK 0xffff0000
+#define NV03_SIFM_SIZE_H__SHIFT 16
+
+#define NV03_SIFM_FORMAT 0x00000404
+#define NV03_SIFM_FORMAT_PITCH__MASK 0x0000ffff
+#define NV03_SIFM_FORMAT_PITCH__SHIFT 0
+#define NV03_SIFM_FORMAT_ORIGIN__MASK 0x00ff0000
+#define NV03_SIFM_FORMAT_ORIGIN__SHIFT 16
+#define NV03_SIFM_FORMAT_ORIGIN_CENTER 0x00010000
+#define NV03_SIFM_FORMAT_ORIGIN_CORNER 0x00020000
+#define NV03_SIFM_FORMAT_FILTER__MASK 0xff000000
+#define NV03_SIFM_FORMAT_FILTER__SHIFT 24
+#define NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE 0x00000000
+#define NV03_SIFM_FORMAT_FILTER_BILINEAR 0x01000000
+
+#define NV03_SIFM_OFFSET 0x00000408
+
+#define NV03_SIFM_POINT 0x0000040c
+#define NV03_SIFM_POINT_U__MASK 0x0000ffff
+#define NV03_SIFM_POINT_U__SHIFT 0
+#define NV03_SIFM_POINT_V__MASK 0xffff0000
+#define NV03_SIFM_POINT_V__SHIFT 16
+
+
+#define NV50_SIFM_OFFSET_HIGH 0x00000410
+
+#define NV50_SIFM_SRC_LINEAR 0x00000414
+
+#define NV50_SIFM_SRC_TILE_MODE 0x00000418
+
+
+#define NV03_GDI_DMA_NOTIFY 0x00000180
+
+#define NV03_GDI_PATTERN 0x00000184
+
+#define NV03_GDI_ROP 0x00000188
+
+#define NV03_GDI_BETA 0x0000019c
+
+#define NV03_GDI_SURFACE_DST 0x00000190
+
+#define NV03_GDI_OPERATION 0x000002fc
+
+#define NV03_GDI_COLOR_FORMAT 0x00000300
+
+#define NV03_GDI_MONOCHROME_FORMAT 0x00000304
+
+#define NV03_GDI_COLOR1_A 0x000003fc
+
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT(i0) (0x00000400 + 0x8*(i0))
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT__ESIZE 0x00000008
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT__LEN 0x00000040
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT_Y__MASK 0x0000ffff
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT_Y__SHIFT 0
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT_X__MASK 0xffff0000
+#define NV03_GDI_UNCLIPPED_RECTANGLE_POINT_X__SHIFT 16
+
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE(i0) (0x00000404 + 0x8*(i0))
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE__ESIZE 0x00000008
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE__LEN 0x00000040
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE_H__MASK 0x0000ffff
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE_H__SHIFT 0
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE_W__MASK 0xffff0000
+#define NV03_GDI_UNCLIPPED_RECTANGLE_SIZE_W__SHIFT 16
+
+#define NV03_GDI_CLIP_POINT0_B 0x000007f4
+#define NV03_GDI_CLIP_POINT0_B_L__MASK 0x0000ffff
+#define NV03_GDI_CLIP_POINT0_B_L__SHIFT 0
+#define NV03_GDI_CLIP_POINT0_B_T__MASK 0xffff0000
+#define NV03_GDI_CLIP_POINT0_B_T__SHIFT 16
+
+#define NV03_GDI_CLIP_POINT1_B 0x000007f8
+#define NV03_GDI_CLIP_POINT1_B_R__MASK 0x0000ffff
+#define NV03_GDI_CLIP_POINT1_B_R__SHIFT 0
+#define NV03_GDI_CLIP_POINT1_B_B__MASK 0xffff0000
+#define NV03_GDI_CLIP_POINT1_B_B__SHIFT 16
+
+#define NV03_GDI_COLOR1_B 0x000007fc
+
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0(i0) (0x00000800 + 0x8*(i0))
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0__ESIZE 0x00000008
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0__LEN 0x00000040
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0_L__MASK 0x0000ffff
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0_L__SHIFT 0
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0_T__MASK 0xffff0000
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_0_T__SHIFT 16
+
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1(i0) (0x00000804 + 0x8*(i0))
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1__ESIZE 0x00000008
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1__LEN 0x00000040
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1_R__MASK 0x0000ffff
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1_R__SHIFT 0
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1_B__MASK 0xffff0000
+#define NV03_GDI_CLIPPED_RECTANGLE_POINT_1_B__SHIFT 16
+
+#define NV03_GDI_CLIP_C_POINT0 0x00000bec
+#define NV03_GDI_CLIP_C_POINT0_L__MASK 0x0000ffff
+#define NV03_GDI_CLIP_C_POINT0_L__SHIFT 0
+#define NV03_GDI_CLIP_C_POINT0_T__MASK 0xffff0000
+#define NV03_GDI_CLIP_C_POINT0_T__SHIFT 16
+
+#define NV03_GDI_CLIP_C_POINT1 0x00000bf0
+#define NV03_GDI_CLIP_C_POINT1_R__MASK 0x0000ffff
+#define NV03_GDI_CLIP_C_POINT1_R__SHIFT 0
+#define NV03_GDI_CLIP_C_POINT1_B__MASK 0xffff0000
+#define NV03_GDI_CLIP_C_POINT1_B__SHIFT 16
+
+#define NV03_GDI_COLOR1_C 0x00000bf4
+
+#define NV03_GDI_SIZE_C 0x00000bf8
+#define NV03_GDI_SIZE_C_W__MASK 0x0000ffff
+#define NV03_GDI_SIZE_C_W__SHIFT 0
+#define NV03_GDI_SIZE_C_H__MASK 0xffff0000
+#define NV03_GDI_SIZE_C_H__SHIFT 16
+
+#define NV03_GDI_POINT_C 0x00000bfc
+#define NV03_GDI_POINT_C_X__MASK 0x0000ffff
+#define NV03_GDI_POINT_C_X__SHIFT 0
+#define NV03_GDI_POINT_C_Y__MASK 0xffff0000
+#define NV03_GDI_POINT_C_Y__SHIFT 16
+
+#define NV03_GDI_MONOCHROME_COLOR1_C(i0) (0x00000c00 + 0x4*(i0))
+#define NV03_GDI_MONOCHROME_COLOR1_C__ESIZE 0x00000004
+#define NV03_GDI_MONOCHROME_COLOR1_C__LEN 0x00000080
+
+#define NV03_GDI_CLIP_D_POINT0 0x00000fe8
+#define NV03_GDI_CLIP_D_POINT0_L__MASK 0x0000ffff
+#define NV03_GDI_CLIP_D_POINT0_L__SHIFT 0
+#define NV03_GDI_CLIP_D_POINT0_T__MASK 0xffff0000
+#define NV03_GDI_CLIP_D_POINT0_T__SHIFT 16
+
+#define NV03_GDI_CLIP_D_POINT1 0x00000fec
+#define NV03_GDI_CLIP_D_POINT1_R__MASK 0x0000ffff
+#define NV03_GDI_CLIP_D_POINT1_R__SHIFT 0
+#define NV03_GDI_CLIP_D_POINT1_B__MASK 0xffff0000
+#define NV03_GDI_CLIP_D_POINT1_B__SHIFT 16
+
+#define NV03_GDI_COLOR1_D 0x00000ff0
+
+#define NV03_GDI_SIZE_IN_D 0x00000ff4
+#define NV03_GDI_SIZE_IN_D_W__MASK 0x0000ffff
+#define NV03_GDI_SIZE_IN_D_W__SHIFT 0
+#define NV03_GDI_SIZE_IN_D_H__MASK 0xffff0000
+#define NV03_GDI_SIZE_IN_D_H__SHIFT 16
+
+#define NV03_GDI_SIZE_OUT_D 0x00000ff8
+#define NV03_GDI_SIZE_OUT_D_W__MASK 0x0000ffff
+#define NV03_GDI_SIZE_OUT_D_W__SHIFT 0
+#define NV03_GDI_SIZE_OUT_D_H__MASK 0xffff0000
+#define NV03_GDI_SIZE_OUT_D_H__SHIFT 16
+
+#define NV03_GDI_POINT_D 0x00000ffc
+#define NV03_GDI_POINT_D_X__MASK 0x0000ffff
+#define NV03_GDI_POINT_D_X__SHIFT 0
+#define NV03_GDI_POINT_D_Y__MASK 0xffff0000
+#define NV03_GDI_POINT_D_Y__SHIFT 16
+
+#define NV03_GDI_MONOCHROME_COLOR1_D(i0) (0x00001000 + 0x4*(i0))
+#define NV03_GDI_MONOCHROME_COLOR1_D__ESIZE 0x00000004
+#define NV03_GDI_MONOCHROME_COLOR1_D__LEN 0x00000080
+
+#define NV03_GDI_CLIP_E_POINT0 0x000013e4
+#define NV03_GDI_CLIP_E_POINT0_L__MASK 0x0000ffff
+#define NV03_GDI_CLIP_E_POINT0_L__SHIFT 0
+#define NV03_GDI_CLIP_E_POINT0_T__MASK 0xffff0000
+#define NV03_GDI_CLIP_E_POINT0_T__SHIFT 16
+
+#define NV03_GDI_CLIP_E_POINT1 0x000013e8
+#define NV03_GDI_CLIP_E_POINT1_R__MASK 0x0000ffff
+#define NV03_GDI_CLIP_E_POINT1_R__SHIFT 0
+#define NV03_GDI_CLIP_E_POINT1_B__MASK 0xffff0000
+#define NV03_GDI_CLIP_E_POINT1_B__SHIFT 16
+
+#define NV03_GDI_COLOR0_E 0x000013ec
+
+#define NV03_GDI_COLOR1_E 0x000013f0
+
+#define NV03_GDI_SIZE_IN_E 0x000013f4
+#define NV03_GDI_SIZE_IN_E_W__MASK 0x0000ffff
+#define NV03_GDI_SIZE_IN_E_W__SHIFT 0
+#define NV03_GDI_SIZE_IN_E_H__MASK 0xffff0000
+#define NV03_GDI_SIZE_IN_E_H__SHIFT 16
+
+#define NV03_GDI_SIZE_OUT_E 0x000013f8
+#define NV03_GDI_SIZE_OUT_E_W__MASK 0x0000ffff
+#define NV03_GDI_SIZE_OUT_E_W__SHIFT 0
+#define NV03_GDI_SIZE_OUT_E_H__MASK 0xffff0000
+#define NV03_GDI_SIZE_OUT_E_H__SHIFT 16
+
+#define NV03_GDI_POINT_E 0x000013fc
+#define NV03_GDI_POINT_E_X__MASK 0x0000ffff
+#define NV03_GDI_POINT_E_X__SHIFT 0
+#define NV03_GDI_POINT_E_Y__MASK 0xffff0000
+#define NV03_GDI_POINT_E_Y__SHIFT 16
+
+#define NV03_GDI_MONOCHROME_COLOR01_E(i0) (0x00001400 + 0x4*(i0))
+#define NV03_GDI_MONOCHROME_COLOR01_E__ESIZE 0x00000004
+#define NV03_GDI_MONOCHROME_COLOR01_E__LEN 0x00000080
+
+
+#define NV04_GDI_PATCH 0x0000010c
+
+#define NV04_GDI_DMA_NOTIFY 0x00000180
+
+#define NV04_GDI_DMA_FONTS 0x00000184
+
+#define NV04_GDI_PATTERN 0x00000188
+
+#define NV04_GDI_ROP 0x0000018c
+
+#define NV04_GDI_BETA 0x00000190
+
+#define NV04_GDI_BETA4 0x00000194
+
+#define NV04_GDI_SURFACE 0x00000198
+
+#define NV04_GDI_OPERATION 0x000002fc
+#define NV04_GDI_OPERATION_SRCCOPY_AND 0x00000000
+#define NV04_GDI_OPERATION_ROP_AND 0x00000001
+#define NV04_GDI_OPERATION_BLEND_AND 0x00000002
+#define NV04_GDI_OPERATION_SRCCOPY 0x00000003
+#define NV04_GDI_OPERATION_SRCCOPY_PREMULT 0x00000004
+#define NV04_GDI_OPERATION_BLEND_PREMULT 0x00000005
+
+#define NV04_GDI_COLOR_FORMAT 0x00000300
+#define NV04_GDI_COLOR_FORMAT_A16R5G6B5 0x00000001
+#define NV04_GDI_COLOR_FORMAT_X16A1R5G5B5 0x00000002
+#define NV04_GDI_COLOR_FORMAT_A8R8G8B8 0x00000003
+
+#define NV04_GDI_MONOCHROME_FORMAT 0x00000304
+#define NV04_GDI_MONOCHROME_FORMAT_CGA6 0x00000001
+#define NV04_GDI_MONOCHROME_FORMAT_LE 0x00000002
+
+#define NV04_GDI_COLOR1_A 0x000003fc
+
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT(i0) (0x00000400 + 0x8*(i0))
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT__ESIZE 0x00000008
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT__LEN 0x00000020
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT_Y__MASK 0x0000ffff
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT_Y__SHIFT 0
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT_X__MASK 0xffff0000
+#define NV04_GDI_UNCLIPPED_RECTANGLE_POINT_X__SHIFT 16
+
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE(i0) (0x00000404 + 0x8*(i0))
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE__ESIZE 0x00000008
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE__LEN 0x00000020
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE_H__MASK 0x0000ffff
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE_H__SHIFT 0
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE_W__MASK 0xffff0000
+#define NV04_GDI_UNCLIPPED_RECTANGLE_SIZE_W__SHIFT 16
+
+#define NV04_GDI_CLIP_B_POINT0 0x000005f4
+#define NV04_GDI_CLIP_B_POINT0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIP_B_POINT0_L__SHIFT 0
+#define NV04_GDI_CLIP_B_POINT0_T__MASK 0xffff0000
+#define NV04_GDI_CLIP_B_POINT0_T__SHIFT 16
+
+#define NV04_GDI_CLIP_B_POINT1 0x000005f8
+#define NV04_GDI_CLIP_B_POINT1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIP_B_POINT1_R__SHIFT 0
+#define NV04_GDI_CLIP_B_POINT1_B__MASK 0xffff0000
+#define NV04_GDI_CLIP_B_POINT1_B__SHIFT 16
+
+#define NV04_GDI_COLOR1_B 0x000005fc
+
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0(i0) (0x00000600 + 0x8*(i0))
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0__ESIZE 0x00000008
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0__LEN 0x00000020
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0_L__SHIFT 0
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0_T__MASK 0xffff0000
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_0_T__SHIFT 16
+
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1(i0) (0x00000604 + 0x8*(i0))
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1__ESIZE 0x00000008
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1__LEN 0x00000020
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1_R__SHIFT 0
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1_B__MASK 0xffff0000
+#define NV04_GDI_CLIPPED_RECTANGLE_POINT_1_B__SHIFT 16
+
+#define NV04_GDI_CLIP_C_POINT0 0x000007ec
+#define NV04_GDI_CLIP_C_POINT0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIP_C_POINT0_L__SHIFT 0
+#define NV04_GDI_CLIP_C_POINT0_T__MASK 0xffff0000
+#define NV04_GDI_CLIP_C_POINT0_T__SHIFT 16
+
+#define NV04_GDI_CLIP_C_POINT1 0x000007f0
+#define NV04_GDI_CLIP_C_POINT1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIP_C_POINT1_R__SHIFT 0
+#define NV04_GDI_CLIP_C_POINT1_B__MASK 0xffff0000
+#define NV04_GDI_CLIP_C_POINT1_B__SHIFT 16
+
+#define NV04_GDI_COLOR1_C 0x000007f4
+
+#define NV04_GDI_SIZE_C 0x000007f8
+#define NV04_GDI_SIZE_C_W__MASK 0x0000ffff
+#define NV04_GDI_SIZE_C_W__SHIFT 0
+#define NV04_GDI_SIZE_C_H__MASK 0xffff0000
+#define NV04_GDI_SIZE_C_H__SHIFT 16
+
+#define NV04_GDI_POINT_C 0x000007fc
+#define NV04_GDI_POINT_C_X__MASK 0x0000ffff
+#define NV04_GDI_POINT_C_X__SHIFT 0
+#define NV04_GDI_POINT_C_Y__MASK 0xffff0000
+#define NV04_GDI_POINT_C_Y__SHIFT 16
+
+#define NV04_GDI_MONOCHROME_COLOR1_C(i0) (0x00000800 + 0x4*(i0))
+#define NV04_GDI_MONOCHROME_COLOR1_C__ESIZE 0x00000004
+#define NV04_GDI_MONOCHROME_COLOR1_C__LEN 0x00000080
+
+#define NV04_GDI_CLIP_E_POINT0 0x00000be4
+#define NV04_GDI_CLIP_E_POINT0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIP_E_POINT0_L__SHIFT 0
+#define NV04_GDI_CLIP_E_POINT0_T__MASK 0xffff0000
+#define NV04_GDI_CLIP_E_POINT0_T__SHIFT 16
+
+#define NV04_GDI_CLIP_E_POINT1 0x00000be8
+#define NV04_GDI_CLIP_E_POINT1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIP_E_POINT1_R__SHIFT 0
+#define NV04_GDI_CLIP_E_POINT1_B__MASK 0xffff0000
+#define NV04_GDI_CLIP_E_POINT1_B__SHIFT 16
+
+#define NV04_GDI_COLOR0_E 0x00000bec
+
+#define NV04_GDI_COLOR1_E 0x00000bf0
+
+#define NV04_GDI_SIZE_IN_E 0x00000bf4
+#define NV04_GDI_SIZE_IN_E_W__MASK 0x0000ffff
+#define NV04_GDI_SIZE_IN_E_W__SHIFT 0
+#define NV04_GDI_SIZE_IN_E_H__MASK 0xffff0000
+#define NV04_GDI_SIZE_IN_E_H__SHIFT 16
+
+#define NV04_GDI_SIZE_OUT_E 0x00000bf8
+#define NV04_GDI_SIZE_OUT_E_W__MASK 0x0000ffff
+#define NV04_GDI_SIZE_OUT_E_W__SHIFT 0
+#define NV04_GDI_SIZE_OUT_E_H__MASK 0xffff0000
+#define NV04_GDI_SIZE_OUT_E_H__SHIFT 16
+
+#define NV04_GDI_POINT_E 0x00000bfc
+#define NV04_GDI_POINT_E_X__MASK 0x0000ffff
+#define NV04_GDI_POINT_E_X__SHIFT 0
+#define NV04_GDI_POINT_E_Y__MASK 0xffff0000
+#define NV04_GDI_POINT_E_Y__SHIFT 16
+
+#define NV04_GDI_MONOCHROME_COLOR01_E(i0) (0x00000c00 + 0x4*(i0))
+#define NV04_GDI_MONOCHROME_COLOR01_E__ESIZE 0x00000004
+#define NV04_GDI_MONOCHROME_COLOR01_E__LEN 0x00000080
+
+#define NV04_GDI_FONT_F 0x00000ff0
+#define NV04_GDI_FONT_F_OFFSET__MASK 0x0fffffff
+#define NV04_GDI_FONT_F_OFFSET__SHIFT 0
+#define NV04_GDI_FONT_F_PITCH__MASK 0xf0000000
+#define NV04_GDI_FONT_F_PITCH__SHIFT 28
+
+#define NV04_GDI_CLIP_F_POINT0 0x00000ff4
+#define NV04_GDI_CLIP_F_POINT0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIP_F_POINT0_L__SHIFT 0
+#define NV04_GDI_CLIP_F_POINT0_T__MASK 0xffff0000
+#define NV04_GDI_CLIP_F_POINT0_T__SHIFT 16
+
+#define NV04_GDI_CLIP_F_POINT1 0x00000ff8
+#define NV04_GDI_CLIP_F_POINT1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIP_F_POINT1_R__SHIFT 0
+#define NV04_GDI_CLIP_F_POINT1_B__MASK 0xffff0000
+#define NV04_GDI_CLIP_F_POINT1_B__SHIFT 16
+
+#define NV04_GDI_COLOR1_F 0x00000ffc
+
+#define NV04_GDI_CHARACTER_COLOR1_F(i0) (0x00001000 + 0x4*(i0))
+#define NV04_GDI_CHARACTER_COLOR1_F__ESIZE 0x00000004
+#define NV04_GDI_CHARACTER_COLOR1_F__LEN 0x00000100
+#define NV04_GDI_CHARACTER_COLOR1_F_INDEX__MASK 0x000000ff
+#define NV04_GDI_CHARACTER_COLOR1_F_INDEX__SHIFT 0
+#define NV04_GDI_CHARACTER_COLOR1_F_X__MASK 0x000fff00
+#define NV04_GDI_CHARACTER_COLOR1_F_X__SHIFT 8
+#define NV04_GDI_CHARACTER_COLOR1_F_Y__MASK 0xfff00000
+#define NV04_GDI_CHARACTER_COLOR1_F_Y__SHIFT 20
+
+#define NV04_GDI_FONT_G 0x000017f0
+#define NV04_GDI_FONT_G_OFFSET__MASK 0x0fffffff
+#define NV04_GDI_FONT_G_OFFSET__SHIFT 0
+#define NV04_GDI_FONT_G_PITCH__MASK 0xf0000000
+#define NV04_GDI_FONT_G_PITCH__SHIFT 28
+
+#define NV04_GDI_CLIP_G_POINT0 0x000017f4
+#define NV04_GDI_CLIP_G_POINT0_L__MASK 0x0000ffff
+#define NV04_GDI_CLIP_G_POINT0_L__SHIFT 0
+#define NV04_GDI_CLIP_G_POINT0_T__MASK 0xffff0000
+#define NV04_GDI_CLIP_G_POINT0_T__SHIFT 16
+
+#define NV04_GDI_CLIP_G_POINT1 0x000017f8
+#define NV04_GDI_CLIP_G_POINT1_R__MASK 0x0000ffff
+#define NV04_GDI_CLIP_G_POINT1_R__SHIFT 0
+#define NV04_GDI_CLIP_G_POINT1_B__MASK 0xffff0000
+#define NV04_GDI_CLIP_G_POINT1_B__SHIFT 16
+
+#define NV04_GDI_COLOR1_G 0x000017fc
+
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT(i0) (0x00001800 + 0x8*(i0))
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT__ESIZE 0x00000008
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT__LEN 0x00000100
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT_X__MASK 0x0000ffff
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT_X__SHIFT 0
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT_Y__MASK 0xffff0000
+#define NV04_GDI_CHARACTER_COLOR1_G_POINT_Y__SHIFT 16
+
+#define NV04_GDI_CHARACTER_COLOR1_G_INDEX(i0) (0x00001804 + 0x8*(i0))
+#define NV04_GDI_CHARACTER_COLOR1_G_INDEX__ESIZE 0x00000008
+#define NV04_GDI_CHARACTER_COLOR1_G_INDEX__LEN 0x00000100
+
+
+#define NV10_TEXUPLOAD_WAIT_FOR_IDLE 0x00000108
+
+#define NV10_TEXUPLOAD_DMA_NOTIFY 0x00000180
+
+#define NV10_TEXUPLOAD_SURFACE 0x00000184
+
+#define NV10_TEXUPLOAD_COLOR_FORMAT 0x00000300
+
+#define NV10_TEXUPLOAD_POINT 0x00000304
+#define NV10_TEXUPLOAD_POINT_X__MASK 0x0000ffff
+#define NV10_TEXUPLOAD_POINT_X__SHIFT 0
+#define NV10_TEXUPLOAD_POINT_Y__MASK 0xffff0000
+#define NV10_TEXUPLOAD_POINT_Y__SHIFT 16
+
+#define NV10_TEXUPLOAD_SIZE 0x00000308
+#define NV10_TEXUPLOAD_SIZE_W__MASK 0x0000ffff
+#define NV10_TEXUPLOAD_SIZE_W__SHIFT 0
+#define NV10_TEXUPLOAD_SIZE_H__MASK 0xffff0000
+#define NV10_TEXUPLOAD_SIZE_H__SHIFT 16
+
+#define NV10_TEXUPLOAD_CLIP_HORIZONTAL 0x0000030c
+#define NV10_TEXUPLOAD_CLIP_HORIZONTAL_X__MASK 0x0000ffff
+#define NV10_TEXUPLOAD_CLIP_HORIZONTAL_X__SHIFT 0
+#define NV10_TEXUPLOAD_CLIP_HORIZONTAL_W__MASK 0xffff0000
+#define NV10_TEXUPLOAD_CLIP_HORIZONTAL_W__SHIFT 16
+
+#define NV10_TEXUPLOAD_CLIP_VERTICAL 0x00000310
+#define NV10_TEXUPLOAD_CLIP_VERTICAL_Y__MASK 0x0000ffff
+#define NV10_TEXUPLOAD_CLIP_VERTICAL_Y__SHIFT 0
+#define NV10_TEXUPLOAD_CLIP_VERTICAL_H__MASK 0xffff0000
+#define NV10_TEXUPLOAD_CLIP_VERTICAL_H__SHIFT 16
+
+#define NV10_TEXUPLOAD_COLOR(i0) (0x00000400 + 0x4*(i0))
+#define NV10_TEXUPLOAD_COLOR__ESIZE 0x00000004
+#define NV10_TEXUPLOAD_COLOR__LEN 0x00000700
+
+
+#endif /* _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV01_2D_XML */
diff --git a/src/gallium/drivers/nouveau/nv30/nv30-40_3d.xml.h b/src/gallium/drivers/nouveau/nv30/nv30-40_3d.xml.h
new file mode 100644
index 00000000000..447f4b3b7ae
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30-40_3d.xml.h
@@ -0,0 +1,2045 @@
+#ifndef _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV30_40_3D_XML
+#define _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV30_40_3D_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://0x04.net/cgit/index.cgi/rules-ng-ng
+git clone git://0x04.net/rules-ng-ng
+
+The rules-ng-ng source files this header was generated from are:
+- /home/skeggsb/git/envytools/rnndb/nv30-40_3d.xml ( 32450 bytes, from 2012-02-10 02:41:48)
+- /home/skeggsb/git/envytools/rnndb/copyright.xml ( 6452 bytes, from 2011-06-30 00:27:55)
+- /home/skeggsb/git/envytools/rnndb/nv_3ddefs.xml ( 16394 bytes, from 2011-06-30 00:27:55)
+- /home/skeggsb/git/envytools/rnndb/nv_defs.xml ( 4437 bytes, from 2011-06-30 00:27:55)
+- /home/skeggsb/git/envytools/rnndb/nv_object.xml ( 12672 bytes, from 2011-07-13 22:28:24)
+- /home/skeggsb/git/envytools/rnndb/nvchipsets.xml ( 3617 bytes, from 2011-07-17 23:19:55)
+- /home/skeggsb/git/envytools/rnndb/nv50_defs.xml ( 5468 bytes, from 2011-07-08 05:22:51)
+
+Copyright (C) 2006-2012 by the following authors:
+- Artur Huillet <[email protected]> (ahuillet)
+- Ben Skeggs (darktama, darktama_)
+- B. R. <[email protected]> (koala_br)
+- Carlos Martin <[email protected]> (carlosmn)
+- Christoph Bumiller <[email protected]> (calim, chrisbmr)
+- Dawid Gajownik <[email protected]> (gajownik)
+- Dmitry Baryshkov
+- Dmitry Eremin-Solenikov <[email protected]> (lumag)
+- EdB <[email protected]> (edb_)
+- Erik Waling <[email protected]> (erikwaling)
+- Francisco Jerez <[email protected]> (curro)
+- imirkin <[email protected]> (imirkin)
+- jb17bsome <[email protected]> (jb17bsome)
+- Jeremy Kolb <[email protected]> (kjeremy)
+- Laurent Carlier <[email protected]> (lordheavy)
+- Luca Barbieri <[email protected]> (lb, lb1)
+- Maarten Maathuis <[email protected]> (stillunknown)
+- Marcin Koƛcielnicki <[email protected]> (mwk, koriakin)
+- Mark Carey <[email protected]> (careym)
+- Matthieu Castet <[email protected]> (mat-c)
+- nvidiaman <[email protected]> (nvidiaman)
+- Patrice Mandin <[email protected]> (pmandin, pmdata)
+- Pekka Paalanen <[email protected]> (pq, ppaalanen)
+- Peter Popov <[email protected]> (ironpeter)
+- Richard Hughes <[email protected]> (hughsient)
+- Rudi Cilibrasi <[email protected]> (cilibrar)
+- Serge Martin
+- Simon Raffeiner
+- Stephane Loeuillet <[email protected]> (leroutier)
+- Stephane Marchesin <[email protected]> (marcheu)
+- sturmflut <[email protected]> (sturmflut)
+- Sylvain Munaut <[email protected]>
+- Victor Stinner <[email protected]> (haypo)
+- Wladmir van der Laan <[email protected]> (miathan6)
+- Younes Manton <[email protected]> (ymanton)
+
+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 COPYRIGHT OWNER(S) 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.
+*/
+
+
+
+#define NV30_3D_FLIP_SET_READ 0x00000120
+
+#define NV30_3D_FLIP_SET_WRITE 0x00000124
+
+#define NV30_3D_FLIP_MAX 0x00000128
+
+#define NV30_3D_FLIP_INCR_WRITE 0x0000012c
+
+#define NV30_3D_FLIP_WAIT 0x00000130
+
+#define NV30_3D_DMA_NOTIFY 0x00000180
+
+#define NV30_3D_DMA_TEXTURE0 0x00000184
+
+#define NV30_3D_DMA_TEXTURE1 0x00000188
+
+#define NV30_3D_DMA_COLOR1 0x0000018c
+
+#define NV30_3D_DMA_UNK190 0x00000190
+
+#define NV30_3D_DMA_COLOR0 0x00000194
+
+#define NV30_3D_DMA_ZETA 0x00000198
+
+#define NV30_3D_DMA_VTXBUF0 0x0000019c
+
+#define NV30_3D_DMA_VTXBUF1 0x000001a0
+
+#define NV30_3D_DMA_FENCE 0x000001a4
+
+#define NV30_3D_DMA_QUERY 0x000001a8
+
+#define NV30_3D_DMA_UNK1AC 0x000001ac
+
+#define NV30_3D_DMA_UNK1B0 0x000001b0
+
+#define NV40_3D_DMA_COLOR2 0x000001b4
+
+#define NV40_3D_DMA_COLOR3 0x000001b8
+
+#define NV30_3D_RT_HORIZ 0x00000200
+#define NV30_3D_RT_HORIZ_X__MASK 0x0000ffff
+#define NV30_3D_RT_HORIZ_X__SHIFT 0
+#define NV30_3D_RT_HORIZ_W__MASK 0xffff0000
+#define NV30_3D_RT_HORIZ_W__SHIFT 16
+
+#define NV30_3D_RT_VERT 0x00000204
+#define NV30_3D_RT_VERT_Y__MASK 0x0000ffff
+#define NV30_3D_RT_VERT_Y__SHIFT 0
+#define NV30_3D_RT_VERT_H__MASK 0xffff0000
+#define NV30_3D_RT_VERT_H__SHIFT 16
+
+#define NV30_3D_RT_FORMAT 0x00000208
+#define NV30_3D_RT_FORMAT_COLOR__MASK 0x0000001f
+#define NV30_3D_RT_FORMAT_COLOR__SHIFT 0
+#define NV30_3D_RT_FORMAT_COLOR_R5G6B5 0x00000003
+#define NV30_3D_RT_FORMAT_COLOR_X8R8G8B8 0x00000005
+#define NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 0x00000008
+#define NV30_3D_RT_FORMAT_COLOR_B8 0x00000009
+#define NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT 0x0000000b
+#define NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT 0x0000000c
+#define NV30_3D_RT_FORMAT_COLOR_R32_FLOAT 0x0000000d
+#define NV30_3D_RT_FORMAT_COLOR_UNK0D 0x0000000d
+#define NV30_3D_RT_FORMAT_COLOR_X8B8G8R8 0x0000000f
+#define NV30_3D_RT_FORMAT_COLOR_A8B8G8R8 0x00000010
+#define NV30_3D_RT_FORMAT_ZETA__MASK 0x000000e0
+#define NV30_3D_RT_FORMAT_ZETA__SHIFT 5
+#define NV30_3D_RT_FORMAT_ZETA_Z16 0x00000020
+#define NV30_3D_RT_FORMAT_ZETA_Z24S8 0x00000040
+#define NV30_3D_RT_FORMAT_TYPE__MASK 0x00000f00
+#define NV30_3D_RT_FORMAT_TYPE__SHIFT 8
+#define NV30_3D_RT_FORMAT_TYPE_LINEAR 0x00000100
+#define NV30_3D_RT_FORMAT_TYPE_SWIZZLED 0x00000200
+#define NV30_3D_RT_FORMAT_LOG2_WIDTH__MASK 0x00ff0000
+#define NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT 16
+#define NV30_3D_RT_FORMAT_LOG2_HEIGHT__MASK 0xff000000
+#define NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT 24
+
+#define NV30_3D_COLOR0_PITCH 0x0000020c
+#define NV30_3D_COLOR0_PITCH_COLOR0__MASK 0x0000ffff
+#define NV30_3D_COLOR0_PITCH_COLOR0__SHIFT 0
+#define NV30_3D_COLOR0_PITCH_ZETA__MASK 0xffff0000
+#define NV30_3D_COLOR0_PITCH_ZETA__SHIFT 16
+
+#define NV40_3D_COLOR0_PITCH 0x0000020c
+
+#define NV30_3D_COLOR0_OFFSET 0x00000210
+
+#define NV30_3D_ZETA_OFFSET 0x00000214
+
+#define NV30_3D_COLOR1_OFFSET 0x00000218
+
+#define NV30_3D_COLOR1_PITCH 0x0000021c
+
+#define NV30_3D_RT_ENABLE 0x00000220
+#define NV30_3D_RT_ENABLE_COLOR0 0x00000001
+#define NV30_3D_RT_ENABLE_COLOR1 0x00000002
+#define NV40_3D_RT_ENABLE_COLOR2 0x00000004
+#define NV40_3D_RT_ENABLE_COLOR3 0x00000008
+#define NV30_3D_RT_ENABLE_MRT 0x00000010
+
+#define NV40_3D_ZETA_PITCH 0x0000022c
+
+#define NV30_3D_HIERZ_PITCH 0x0000022c
+
+#define NV30_3D_HIERZ_OFFSET 0x00000230
+
+#define NV30_3D_TEX_UNITS_ENABLE 0x0000023c
+#define NV30_3D_TEX_UNITS_ENABLE_TX0 0x00000001
+#define NV30_3D_TEX_UNITS_ENABLE_TX1 0x00000002
+#define NV30_3D_TEX_UNITS_ENABLE_TX2 0x00000004
+#define NV30_3D_TEX_UNITS_ENABLE_TX3 0x00000008
+#define NV30_3D_TEX_UNITS_ENABLE_TX4 0x00000010
+#define NV30_3D_TEX_UNITS_ENABLE_TX5 0x00000020
+#define NV30_3D_TEX_UNITS_ENABLE_TX6 0x00000040
+#define NV30_3D_TEX_UNITS_ENABLE_TX7 0x00000080
+
+#define NV30_3D_TEX_MATRIX_ENABLE(i0) (0x00000240 + 0x4*(i0))
+#define NV30_3D_TEX_MATRIX_ENABLE__ESIZE 0x00000004
+#define NV30_3D_TEX_MATRIX_ENABLE__LEN 0x00000008
+
+#define NV40_3D_COLOR2_PITCH 0x00000280
+
+#define NV40_3D_COLOR3_PITCH 0x00000284
+
+#define NV40_3D_COLOR2_OFFSET 0x00000288
+
+#define NV40_3D_COLOR3_OFFSET 0x0000028c
+
+#define NV30_3D_VIEWPORT_TX_ORIGIN 0x000002b8
+#define NV30_3D_VIEWPORT_TX_ORIGIN_X__MASK 0x0000ffff
+#define NV30_3D_VIEWPORT_TX_ORIGIN_X__SHIFT 0
+#define NV30_3D_VIEWPORT_TX_ORIGIN_Y__MASK 0xffff0000
+#define NV30_3D_VIEWPORT_TX_ORIGIN_Y__SHIFT 16
+
+#define NV30_3D_VIEWPORT_CLIP_MODE 0x000002bc
+
+#define NV30_3D_VIEWPORT_CLIP_HORIZ(i0) (0x000002c0 + 0x8*(i0))
+#define NV30_3D_VIEWPORT_CLIP_HORIZ__ESIZE 0x00000008
+#define NV30_3D_VIEWPORT_CLIP_HORIZ__LEN 0x00000008
+#define NV30_3D_VIEWPORT_CLIP_HORIZ_L__MASK 0x0000ffff
+#define NV30_3D_VIEWPORT_CLIP_HORIZ_L__SHIFT 0
+#define NV30_3D_VIEWPORT_CLIP_HORIZ_R__MASK 0xffff0000
+#define NV30_3D_VIEWPORT_CLIP_HORIZ_R__SHIFT 16
+
+#define NV30_3D_VIEWPORT_CLIP_VERT(i0) (0x000002c4 + 0x8*(i0))
+#define NV30_3D_VIEWPORT_CLIP_VERT__ESIZE 0x00000008
+#define NV30_3D_VIEWPORT_CLIP_VERT__LEN 0x00000008
+#define NV30_3D_VIEWPORT_CLIP_VERT_T__MASK 0x0000ffff
+#define NV30_3D_VIEWPORT_CLIP_VERT_T__SHIFT 0
+#define NV30_3D_VIEWPORT_CLIP_VERT_D__MASK 0xffff0000
+#define NV30_3D_VIEWPORT_CLIP_VERT_D__SHIFT 16
+
+#define NV30_3D_DITHER_ENABLE 0x00000300
+
+#define NV30_3D_ALPHA_FUNC_ENABLE 0x00000304
+
+#define NV30_3D_ALPHA_FUNC_FUNC 0x00000308
+#define NV30_3D_ALPHA_FUNC_FUNC_NEVER 0x00000200
+#define NV30_3D_ALPHA_FUNC_FUNC_LESS 0x00000201
+#define NV30_3D_ALPHA_FUNC_FUNC_EQUAL 0x00000202
+#define NV30_3D_ALPHA_FUNC_FUNC_LEQUAL 0x00000203
+#define NV30_3D_ALPHA_FUNC_FUNC_GREATER 0x00000204
+#define NV30_3D_ALPHA_FUNC_FUNC_NOTEQUAL 0x00000205
+#define NV30_3D_ALPHA_FUNC_FUNC_GEQUAL 0x00000206
+#define NV30_3D_ALPHA_FUNC_FUNC_ALWAYS 0x00000207
+
+#define NV30_3D_ALPHA_FUNC_REF 0x0000030c
+
+#define NV30_3D_BLEND_FUNC_ENABLE 0x00000310
+
+#define NV30_3D_BLEND_FUNC_SRC 0x00000314
+#define NV30_3D_BLEND_FUNC_SRC_RGB__MASK 0x0000ffff
+#define NV30_3D_BLEND_FUNC_SRC_RGB__SHIFT 0
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ZERO 0x00000000
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE 0x00000001
+#define NV30_3D_BLEND_FUNC_SRC_RGB_SRC_COLOR 0x00000300
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR 0x00000301
+#define NV30_3D_BLEND_FUNC_SRC_RGB_SRC_ALPHA 0x00000302
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA 0x00000303
+#define NV30_3D_BLEND_FUNC_SRC_RGB_DST_ALPHA 0x00000304
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA 0x00000305
+#define NV30_3D_BLEND_FUNC_SRC_RGB_DST_COLOR 0x00000306
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR 0x00000307
+#define NV30_3D_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE 0x00000308
+#define NV30_3D_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR 0x00008001
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR 0x00008002
+#define NV30_3D_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA 0x00008003
+#define NV30_3D_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA 0x00008004
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA__MASK 0xffff0000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA__SHIFT 16
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ZERO 0x00000000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE 0x00010000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_SRC_COLOR 0x03000000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR 0x03010000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA 0x03020000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA 0x03030000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_DST_ALPHA 0x03040000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA 0x03050000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_DST_COLOR 0x03060000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR 0x03070000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE 0x03080000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR 0x80010000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR 0x80020000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA 0x80030000
+#define NV30_3D_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA 0x80040000
+
+#define NV30_3D_BLEND_FUNC_DST 0x00000318
+#define NV30_3D_BLEND_FUNC_DST_RGB__MASK 0x0000ffff
+#define NV30_3D_BLEND_FUNC_DST_RGB__SHIFT 0
+#define NV30_3D_BLEND_FUNC_DST_RGB_ZERO 0x00000000
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE 0x00000001
+#define NV30_3D_BLEND_FUNC_DST_RGB_SRC_COLOR 0x00000300
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR 0x00000301
+#define NV30_3D_BLEND_FUNC_DST_RGB_SRC_ALPHA 0x00000302
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA 0x00000303
+#define NV30_3D_BLEND_FUNC_DST_RGB_DST_ALPHA 0x00000304
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA 0x00000305
+#define NV30_3D_BLEND_FUNC_DST_RGB_DST_COLOR 0x00000306
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR 0x00000307
+#define NV30_3D_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE 0x00000308
+#define NV30_3D_BLEND_FUNC_DST_RGB_CONSTANT_COLOR 0x00008001
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR 0x00008002
+#define NV30_3D_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA 0x00008003
+#define NV30_3D_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA 0x00008004
+#define NV30_3D_BLEND_FUNC_DST_ALPHA__MASK 0xffff0000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA__SHIFT 16
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ZERO 0x00000000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE 0x00010000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_SRC_COLOR 0x03000000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR 0x03010000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_SRC_ALPHA 0x03020000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA 0x03030000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_DST_ALPHA 0x03040000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA 0x03050000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_DST_COLOR 0x03060000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR 0x03070000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE 0x03080000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR 0x80010000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR 0x80020000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA 0x80030000
+#define NV30_3D_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA 0x80040000
+
+#define NV30_3D_BLEND_COLOR 0x0000031c
+#define NV30_3D_BLEND_COLOR_B__MASK 0x000000ff
+#define NV30_3D_BLEND_COLOR_B__SHIFT 0
+#define NV30_3D_BLEND_COLOR_G__MASK 0x0000ff00
+#define NV30_3D_BLEND_COLOR_G__SHIFT 8
+#define NV30_3D_BLEND_COLOR_R__MASK 0x00ff0000
+#define NV30_3D_BLEND_COLOR_R__SHIFT 16
+#define NV30_3D_BLEND_COLOR_A__MASK 0xff000000
+#define NV30_3D_BLEND_COLOR_A__SHIFT 24
+
+#define NV30_3D_BLEND_EQUATION 0x00000320
+#define NV30_3D_BLEND_EQUATION_FUNC_ADD 0x00008006
+#define NV30_3D_BLEND_EQUATION_MIN 0x00008007
+#define NV30_3D_BLEND_EQUATION_MAX 0x00008008
+#define NV30_3D_BLEND_EQUATION_FUNC_SUBTRACT 0x0000800a
+#define NV30_3D_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT 0x0000800b
+
+#define NV40_3D_BLEND_EQUATION 0x00000320
+#define NV40_3D_BLEND_EQUATION_RGB__MASK 0x0000ffff
+#define NV40_3D_BLEND_EQUATION_RGB__SHIFT 0
+#define NV40_3D_BLEND_EQUATION_RGB_FUNC_ADD 0x00008006
+#define NV40_3D_BLEND_EQUATION_RGB_MIN 0x00008007
+#define NV40_3D_BLEND_EQUATION_RGB_MAX 0x00008008
+#define NV40_3D_BLEND_EQUATION_RGB_FUNC_SUBTRACT 0x0000800a
+#define NV40_3D_BLEND_EQUATION_RGB_FUNC_REVERSE_SUBTRACT 0x0000800b
+#define NV40_3D_BLEND_EQUATION_ALPHA__MASK 0xffff0000
+#define NV40_3D_BLEND_EQUATION_ALPHA__SHIFT 16
+#define NV40_3D_BLEND_EQUATION_ALPHA_FUNC_ADD 0x80060000
+#define NV40_3D_BLEND_EQUATION_ALPHA_MIN 0x80070000
+#define NV40_3D_BLEND_EQUATION_ALPHA_MAX 0x80080000
+#define NV40_3D_BLEND_EQUATION_ALPHA_FUNC_SUBTRACT 0x800a0000
+#define NV40_3D_BLEND_EQUATION_ALPHA_FUNC_REVERSE_SUBTRACT 0x800b0000
+
+#define NV30_3D_COLOR_MASK 0x00000324
+#define NV30_3D_COLOR_MASK_B 0x000000ff
+#define NV30_3D_COLOR_MASK_G 0x0000ff00
+#define NV30_3D_COLOR_MASK_R 0x00ff0000
+#define NV30_3D_COLOR_MASK_A 0xff000000
+
+#define NV30_3D_STENCIL(i0) (0x00000328 + 0x20*(i0))
+#define NV30_3D_STENCIL__ESIZE 0x00000020
+#define NV30_3D_STENCIL__LEN 0x00000002
+
+#define NV30_3D_STENCIL_ENABLE(i0) (0x00000328 + 0x20*(i0))
+
+#define NV30_3D_STENCIL_MASK(i0) (0x0000032c + 0x20*(i0))
+
+#define NV30_3D_STENCIL_FUNC_FUNC(i0) (0x00000330 + 0x20*(i0))
+#define NV30_3D_STENCIL_FUNC_FUNC_NEVER 0x00000200
+#define NV30_3D_STENCIL_FUNC_FUNC_LESS 0x00000201
+#define NV30_3D_STENCIL_FUNC_FUNC_EQUAL 0x00000202
+#define NV30_3D_STENCIL_FUNC_FUNC_LEQUAL 0x00000203
+#define NV30_3D_STENCIL_FUNC_FUNC_GREATER 0x00000204
+#define NV30_3D_STENCIL_FUNC_FUNC_NOTEQUAL 0x00000205
+#define NV30_3D_STENCIL_FUNC_FUNC_GEQUAL 0x00000206
+#define NV30_3D_STENCIL_FUNC_FUNC_ALWAYS 0x00000207
+
+#define NV30_3D_STENCIL_FUNC_REF(i0) (0x00000334 + 0x20*(i0))
+
+#define NV30_3D_STENCIL_FUNC_MASK(i0) (0x00000338 + 0x20*(i0))
+
+#define NV30_3D_STENCIL_OP_FAIL(i0) (0x0000033c + 0x20*(i0))
+#define NV30_3D_STENCIL_OP_FAIL_ZERO 0x00000000
+#define NV30_3D_STENCIL_OP_FAIL_INVERT 0x0000150a
+#define NV30_3D_STENCIL_OP_FAIL_KEEP 0x00001e00
+#define NV30_3D_STENCIL_OP_FAIL_REPLACE 0x00001e01
+#define NV30_3D_STENCIL_OP_FAIL_INCR 0x00001e02
+#define NV30_3D_STENCIL_OP_FAIL_DECR 0x00001e03
+#define NV30_3D_STENCIL_OP_FAIL_INCR_WRAP 0x00008507
+#define NV30_3D_STENCIL_OP_FAIL_DECR_WRAP 0x00008508
+
+#define NV30_3D_STENCIL_OP_ZFAIL(i0) (0x00000340 + 0x20*(i0))
+#define NV30_3D_STENCIL_OP_ZFAIL_ZERO 0x00000000
+#define NV30_3D_STENCIL_OP_ZFAIL_INVERT 0x0000150a
+#define NV30_3D_STENCIL_OP_ZFAIL_KEEP 0x00001e00
+#define NV30_3D_STENCIL_OP_ZFAIL_REPLACE 0x00001e01
+#define NV30_3D_STENCIL_OP_ZFAIL_INCR 0x00001e02
+#define NV30_3D_STENCIL_OP_ZFAIL_DECR 0x00001e03
+#define NV30_3D_STENCIL_OP_ZFAIL_INCR_WRAP 0x00008507
+#define NV30_3D_STENCIL_OP_ZFAIL_DECR_WRAP 0x00008508
+
+#define NV30_3D_STENCIL_OP_ZPASS(i0) (0x00000344 + 0x20*(i0))
+#define NV30_3D_STENCIL_OP_ZPASS_ZERO 0x00000000
+#define NV30_3D_STENCIL_OP_ZPASS_INVERT 0x0000150a
+#define NV30_3D_STENCIL_OP_ZPASS_KEEP 0x00001e00
+#define NV30_3D_STENCIL_OP_ZPASS_REPLACE 0x00001e01
+#define NV30_3D_STENCIL_OP_ZPASS_INCR 0x00001e02
+#define NV30_3D_STENCIL_OP_ZPASS_DECR 0x00001e03
+#define NV30_3D_STENCIL_OP_ZPASS_INCR_WRAP 0x00008507
+#define NV30_3D_STENCIL_OP_ZPASS_DECR_WRAP 0x00008508
+
+#define NV30_3D_SHADE_MODEL 0x00000368
+#define NV30_3D_SHADE_MODEL_FLAT 0x00001d00
+#define NV30_3D_SHADE_MODEL_SMOOTH 0x00001d01
+
+#define NV30_3D_FOG_ENABLE 0x0000036c
+
+#define NV30_3D_FOG_COLOR 0x00000370
+#define NV30_3D_FOG_COLOR_R__MASK 0x000000ff
+#define NV30_3D_FOG_COLOR_R__SHIFT 0
+#define NV30_3D_FOG_COLOR_G__MASK 0x0000ff00
+#define NV30_3D_FOG_COLOR_G__SHIFT 8
+#define NV30_3D_FOG_COLOR_B__MASK 0x00ff0000
+#define NV30_3D_FOG_COLOR_B__SHIFT 16
+#define NV30_3D_FOG_COLOR_A__MASK 0xff000000
+#define NV30_3D_FOG_COLOR_A__SHIFT 24
+
+#define NV40_3D_MRT_COLOR_MASK 0x00000370
+#define NV40_3D_MRT_COLOR_MASK_BUFFER1_A 0x00000010
+#define NV40_3D_MRT_COLOR_MASK_BUFFER1_R 0x00000020
+#define NV40_3D_MRT_COLOR_MASK_BUFFER1_G 0x00000040
+#define NV40_3D_MRT_COLOR_MASK_BUFFER1_B 0x00000080
+#define NV40_3D_MRT_COLOR_MASK_BUFFER2_A 0x00000100
+#define NV40_3D_MRT_COLOR_MASK_BUFFER2_R 0x00000200
+#define NV40_3D_MRT_COLOR_MASK_BUFFER2_G 0x00000400
+#define NV40_3D_MRT_COLOR_MASK_BUFFER2_B 0x00000800
+#define NV40_3D_MRT_COLOR_MASK_BUFFER3_A 0x00001000
+#define NV40_3D_MRT_COLOR_MASK_BUFFER3_R 0x00002000
+#define NV40_3D_MRT_COLOR_MASK_BUFFER3_G 0x00004000
+#define NV40_3D_MRT_COLOR_MASK_BUFFER3_B 0x00008000
+
+#define NV30_3D_COLOR_LOGIC_OP_ENABLE 0x00000374
+
+#define NV30_3D_COLOR_LOGIC_OP_OP 0x00000378
+#define NV30_3D_COLOR_LOGIC_OP_OP_CLEAR 0x00001500
+#define NV30_3D_COLOR_LOGIC_OP_OP_AND 0x00001501
+#define NV30_3D_COLOR_LOGIC_OP_OP_AND_REVERSE 0x00001502
+#define NV30_3D_COLOR_LOGIC_OP_OP_COPY 0x00001503
+#define NV30_3D_COLOR_LOGIC_OP_OP_AND_INVERTED 0x00001504
+#define NV30_3D_COLOR_LOGIC_OP_OP_NOOP 0x00001505
+#define NV30_3D_COLOR_LOGIC_OP_OP_XOR 0x00001506
+#define NV30_3D_COLOR_LOGIC_OP_OP_OR 0x00001507
+#define NV30_3D_COLOR_LOGIC_OP_OP_NOR 0x00001508
+#define NV30_3D_COLOR_LOGIC_OP_OP_EQUIV 0x00001509
+#define NV30_3D_COLOR_LOGIC_OP_OP_INVERT 0x0000150a
+#define NV30_3D_COLOR_LOGIC_OP_OP_OR_REVERSE 0x0000150b
+#define NV30_3D_COLOR_LOGIC_OP_OP_COPY_INVERTED 0x0000150c
+#define NV30_3D_COLOR_LOGIC_OP_OP_OR_INVERTED 0x0000150d
+#define NV30_3D_COLOR_LOGIC_OP_OP_NAND 0x0000150e
+#define NV30_3D_COLOR_LOGIC_OP_OP_SET 0x0000150f
+
+#define NV30_3D_NORMALIZE_ENABLE 0x0000037c
+
+#define NV35_3D_DEPTH_BOUNDS_TEST_ENABLE 0x00000380
+
+#define NV35_3D_DEPTH_BOUNDS_TEST_ZMIN 0x00000384
+
+#define NV35_3D_DEPTH_BOUNDS_TEST_ZMAX 0x00000388
+
+#define NV30_3D_COLOR_MATERIAL 0x00000390
+#define NV30_3D_COLOR_MATERIAL_FRONT_EMISSION_ENABLE 0x00000001
+#define NV30_3D_COLOR_MATERIAL_FRONT_AMBIENT_ENABLE 0x00000004
+#define NV30_3D_COLOR_MATERIAL_FRONT_DIFFUSE_ENABLE 0x00000010
+#define NV30_3D_COLOR_MATERIAL_FRONT_SPECULAR_ENABLE 0x00000040
+#define NV30_3D_COLOR_MATERIAL_BACK_EMISSION_ENABLE 0x00000100
+#define NV30_3D_COLOR_MATERIAL_BACK_AMBIENT_ENABLE 0x00000400
+#define NV30_3D_COLOR_MATERIAL_BACK_DIFFUSE_ENABLE 0x00001000
+#define NV30_3D_COLOR_MATERIAL_BACK_SPECULAR_ENABLE 0x00004000
+
+#define NV30_3D_DEPTH_RANGE_NEAR 0x00000394
+
+#define NV30_3D_DEPTH_RANGE_FAR 0x00000398
+
+#define NV30_3D_COLOR_MATERIAL_FRONT 0x000003a0
+
+
+#define NV30_3D_COLOR_MATERIAL_FRONT_R 0x000003a0
+
+#define NV30_3D_COLOR_MATERIAL_FRONT_G 0x000003a4
+
+#define NV30_3D_COLOR_MATERIAL_FRONT_B 0x000003a8
+
+#define NV30_3D_COLOR_MATERIAL_FRONT_A 0x000003ac
+
+#define NV40_3D_MIPMAP_ROUNDING 0x000003b0
+#define NV40_3D_MIPMAP_ROUNDING_MODE__MASK 0x00100000
+#define NV40_3D_MIPMAP_ROUNDING_MODE__SHIFT 20
+#define NV40_3D_MIPMAP_ROUNDING_MODE_UP 0x00000000
+#define NV40_3D_MIPMAP_ROUNDING_MODE_DOWN 0x00100000
+
+#define NV30_3D_LINE_WIDTH 0x000003b8
+
+#define NV30_3D_LINE_SMOOTH_ENABLE 0x000003bc
+
+
+
+#define NV30_3D_TEX_GEN_MODE(i0, i1) (0x00000400 + 0x10*(i0) + 0x4*(i1))
+#define NV30_3D_TEX_GEN_MODE__ESIZE 0x00000004
+#define NV30_3D_TEX_GEN_MODE__LEN 0x00000004
+#define NV30_3D_TEX_GEN_MODE_FALSE 0x00000000
+#define NV30_3D_TEX_GEN_MODE_EYE_LINEAR 0x00002400
+#define NV30_3D_TEX_GEN_MODE_OBJECT_LINEAR 0x00002401
+#define NV30_3D_TEX_GEN_MODE_SPHERE_MAP 0x00002402
+#define NV30_3D_TEX_GEN_MODE_NORMAL_MAP 0x00008511
+#define NV30_3D_TEX_GEN_MODE_REFLECTION_MAP 0x00008512
+
+#define NV30_3D_MODELVIEW_MATRIX(i0) (0x00000480 + 0x4*(i0))
+#define NV30_3D_MODELVIEW_MATRIX__ESIZE 0x00000004
+#define NV30_3D_MODELVIEW_MATRIX__LEN 0x00000010
+
+#define NV30_3D_INVERSE_MODELVIEW_MATRIX(i0) (0x00000580 + 0x4*(i0))
+#define NV30_3D_INVERSE_MODELVIEW_MATRIX__ESIZE 0x00000004
+#define NV30_3D_INVERSE_MODELVIEW_MATRIX__LEN 0x0000000c
+
+#define NV30_3D_PROJECTION_MATRIX(i0) (0x00000680 + 0x4*(i0))
+#define NV30_3D_PROJECTION_MATRIX__ESIZE 0x00000004
+#define NV30_3D_PROJECTION_MATRIX__LEN 0x00000010
+
+
+#define NV30_3D_TEX_MATRIX(i0, i1) (0x000006c0 + 0x40*(i0) + 0x4*(i1))
+#define NV30_3D_TEX_MATRIX__ESIZE 0x00000004
+#define NV30_3D_TEX_MATRIX__LEN 0x00000010
+
+#define NV30_3D_SCISSOR_HORIZ 0x000008c0
+#define NV30_3D_SCISSOR_HORIZ_X__MASK 0x0000ffff
+#define NV30_3D_SCISSOR_HORIZ_X__SHIFT 0
+#define NV30_3D_SCISSOR_HORIZ_W__MASK 0xffff0000
+#define NV30_3D_SCISSOR_HORIZ_W__SHIFT 16
+
+#define NV30_3D_SCISSOR_VERT 0x000008c4
+#define NV30_3D_SCISSOR_VERT_Y__MASK 0x0000ffff
+#define NV30_3D_SCISSOR_VERT_Y__SHIFT 0
+#define NV30_3D_SCISSOR_VERT_H__MASK 0xffff0000
+#define NV30_3D_SCISSOR_VERT_H__SHIFT 16
+
+#define NV30_3D_FOG_COORD_DIST 0x000008c8
+
+#define NV30_3D_FOG_MODE 0x000008cc
+
+#define NV30_3D_FOG_EQUATION_CONSTANT 0x000008d0
+
+#define NV30_3D_FOG_EQUATION_LINEAR 0x000008d4
+
+#define NV30_3D_FOG_EQUATION_QUADRATIC 0x000008d8
+
+#define NV30_3D_FP_ACTIVE_PROGRAM 0x000008e4
+#define NV30_3D_FP_ACTIVE_PROGRAM_DMA0 0x00000001
+#define NV30_3D_FP_ACTIVE_PROGRAM_DMA1 0x00000002
+#define NV30_3D_FP_ACTIVE_PROGRAM_OFFSET__MASK 0xfffffffc
+#define NV30_3D_FP_ACTIVE_PROGRAM_OFFSET__SHIFT 2
+
+
+#define NV30_3D_RC_COLOR0 0x000008ec
+#define NV30_3D_RC_COLOR0_B__MASK 0x000000ff
+#define NV30_3D_RC_COLOR0_B__SHIFT 0
+#define NV30_3D_RC_COLOR0_G__MASK 0x0000ff00
+#define NV30_3D_RC_COLOR0_G__SHIFT 8
+#define NV30_3D_RC_COLOR0_R__MASK 0x00ff0000
+#define NV30_3D_RC_COLOR0_R__SHIFT 16
+#define NV30_3D_RC_COLOR0_A__MASK 0xff000000
+#define NV30_3D_RC_COLOR0_A__SHIFT 24
+
+#define NV30_3D_RC_COLOR1 0x000008f0
+#define NV30_3D_RC_COLOR1_B__MASK 0x000000ff
+#define NV30_3D_RC_COLOR1_B__SHIFT 0
+#define NV30_3D_RC_COLOR1_G__MASK 0x0000ff00
+#define NV30_3D_RC_COLOR1_G__SHIFT 8
+#define NV30_3D_RC_COLOR1_R__MASK 0x00ff0000
+#define NV30_3D_RC_COLOR1_R__SHIFT 16
+#define NV30_3D_RC_COLOR1_A__MASK 0xff000000
+#define NV30_3D_RC_COLOR1_A__SHIFT 24
+
+#define NV30_3D_RC_FINAL0 0x000008f4
+#define NV30_3D_RC_FINAL0_D_INPUT__MASK 0x0000000f
+#define NV30_3D_RC_FINAL0_D_INPUT__SHIFT 0
+#define NV30_3D_RC_FINAL0_D_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR0 0x00000001
+#define NV30_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR1 0x00000002
+#define NV30_3D_RC_FINAL0_D_INPUT_FOG 0x00000003
+#define NV30_3D_RC_FINAL0_D_INPUT_PRIMARY_COLOR 0x00000004
+#define NV30_3D_RC_FINAL0_D_INPUT_SECONDARY_COLOR 0x00000005
+#define NV30_3D_RC_FINAL0_D_INPUT_TEXTURE0 0x00000008
+#define NV30_3D_RC_FINAL0_D_INPUT_TEXTURE1 0x00000009
+#define NV30_3D_RC_FINAL0_D_INPUT_TEXTURE2 0x0000000a
+#define NV30_3D_RC_FINAL0_D_INPUT_TEXTURE3 0x0000000b
+#define NV30_3D_RC_FINAL0_D_INPUT_SPARE0 0x0000000c
+#define NV30_3D_RC_FINAL0_D_INPUT_SPARE1 0x0000000d
+#define NV30_3D_RC_FINAL0_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e
+#define NV30_3D_RC_FINAL0_D_INPUT_E_TIMES_F 0x0000000f
+#define NV30_3D_RC_FINAL0_D_COMPONENT_USAGE__MASK 0x00000010
+#define NV30_3D_RC_FINAL0_D_COMPONENT_USAGE__SHIFT 4
+#define NV30_3D_RC_FINAL0_D_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL0_D_COMPONENT_USAGE_ALPHA 0x00000010
+#define NV30_3D_RC_FINAL0_D_MAPPING__MASK 0x000000e0
+#define NV30_3D_RC_FINAL0_D_MAPPING__SHIFT 5
+#define NV30_3D_RC_FINAL0_D_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL0_D_MAPPING_UNSIGNED_INVERT 0x00000020
+#define NV30_3D_RC_FINAL0_D_MAPPING_EXPAND_NORMAL 0x00000040
+#define NV30_3D_RC_FINAL0_D_MAPPING_EXPAND_NEGATE 0x00000060
+#define NV30_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NORMAL 0x00000080
+#define NV30_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0
+#define NV30_3D_RC_FINAL0_D_MAPPING_SIGNED_IDENTITY 0x000000c0
+#define NV30_3D_RC_FINAL0_D_MAPPING_SIGNED_NEGATE 0x000000e0
+#define NV30_3D_RC_FINAL0_C_INPUT__MASK 0x00000f00
+#define NV30_3D_RC_FINAL0_C_INPUT__SHIFT 8
+#define NV30_3D_RC_FINAL0_C_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_FINAL0_C_INPUT_FOG 0x00000300
+#define NV30_3D_RC_FINAL0_C_INPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_FINAL0_C_INPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_FINAL0_C_INPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_FINAL0_C_INPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_FINAL0_C_INPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_FINAL0_C_INPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_FINAL0_C_INPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_FINAL0_C_INPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_FINAL0_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_FINAL0_C_INPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_FINAL0_C_COMPONENT_USAGE__MASK 0x00001000
+#define NV30_3D_RC_FINAL0_C_COMPONENT_USAGE__SHIFT 12
+#define NV30_3D_RC_FINAL0_C_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL0_C_COMPONENT_USAGE_ALPHA 0x00001000
+#define NV30_3D_RC_FINAL0_C_MAPPING__MASK 0x0000e000
+#define NV30_3D_RC_FINAL0_C_MAPPING__SHIFT 13
+#define NV30_3D_RC_FINAL0_C_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL0_C_MAPPING_UNSIGNED_INVERT 0x00002000
+#define NV30_3D_RC_FINAL0_C_MAPPING_EXPAND_NORMAL 0x00004000
+#define NV30_3D_RC_FINAL0_C_MAPPING_EXPAND_NEGATE 0x00006000
+#define NV30_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NORMAL 0x00008000
+#define NV30_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000
+#define NV30_3D_RC_FINAL0_C_MAPPING_SIGNED_IDENTITY 0x0000c000
+#define NV30_3D_RC_FINAL0_C_MAPPING_SIGNED_NEGATE 0x0000e000
+#define NV30_3D_RC_FINAL0_B_INPUT__MASK 0x000f0000
+#define NV30_3D_RC_FINAL0_B_INPUT__SHIFT 16
+#define NV30_3D_RC_FINAL0_B_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR0 0x00010000
+#define NV30_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR1 0x00020000
+#define NV30_3D_RC_FINAL0_B_INPUT_FOG 0x00030000
+#define NV30_3D_RC_FINAL0_B_INPUT_PRIMARY_COLOR 0x00040000
+#define NV30_3D_RC_FINAL0_B_INPUT_SECONDARY_COLOR 0x00050000
+#define NV30_3D_RC_FINAL0_B_INPUT_TEXTURE0 0x00080000
+#define NV30_3D_RC_FINAL0_B_INPUT_TEXTURE1 0x00090000
+#define NV30_3D_RC_FINAL0_B_INPUT_TEXTURE2 0x000a0000
+#define NV30_3D_RC_FINAL0_B_INPUT_TEXTURE3 0x000b0000
+#define NV30_3D_RC_FINAL0_B_INPUT_SPARE0 0x000c0000
+#define NV30_3D_RC_FINAL0_B_INPUT_SPARE1 0x000d0000
+#define NV30_3D_RC_FINAL0_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000
+#define NV30_3D_RC_FINAL0_B_INPUT_E_TIMES_F 0x000f0000
+#define NV30_3D_RC_FINAL0_B_COMPONENT_USAGE__MASK 0x00100000
+#define NV30_3D_RC_FINAL0_B_COMPONENT_USAGE__SHIFT 20
+#define NV30_3D_RC_FINAL0_B_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL0_B_COMPONENT_USAGE_ALPHA 0x00100000
+#define NV30_3D_RC_FINAL0_B_MAPPING__MASK 0x00e00000
+#define NV30_3D_RC_FINAL0_B_MAPPING__SHIFT 21
+#define NV30_3D_RC_FINAL0_B_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL0_B_MAPPING_UNSIGNED_INVERT 0x00200000
+#define NV30_3D_RC_FINAL0_B_MAPPING_EXPAND_NORMAL 0x00400000
+#define NV30_3D_RC_FINAL0_B_MAPPING_EXPAND_NEGATE 0x00600000
+#define NV30_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NORMAL 0x00800000
+#define NV30_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000
+#define NV30_3D_RC_FINAL0_B_MAPPING_SIGNED_IDENTITY 0x00c00000
+#define NV30_3D_RC_FINAL0_B_MAPPING_SIGNED_NEGATE 0x00e00000
+#define NV30_3D_RC_FINAL0_A_INPUT__MASK 0x0f000000
+#define NV30_3D_RC_FINAL0_A_INPUT__SHIFT 24
+#define NV30_3D_RC_FINAL0_A_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR0 0x01000000
+#define NV30_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR1 0x02000000
+#define NV30_3D_RC_FINAL0_A_INPUT_FOG 0x03000000
+#define NV30_3D_RC_FINAL0_A_INPUT_PRIMARY_COLOR 0x04000000
+#define NV30_3D_RC_FINAL0_A_INPUT_SECONDARY_COLOR 0x05000000
+#define NV30_3D_RC_FINAL0_A_INPUT_TEXTURE0 0x08000000
+#define NV30_3D_RC_FINAL0_A_INPUT_TEXTURE1 0x09000000
+#define NV30_3D_RC_FINAL0_A_INPUT_TEXTURE2 0x0a000000
+#define NV30_3D_RC_FINAL0_A_INPUT_TEXTURE3 0x0b000000
+#define NV30_3D_RC_FINAL0_A_INPUT_SPARE0 0x0c000000
+#define NV30_3D_RC_FINAL0_A_INPUT_SPARE1 0x0d000000
+#define NV30_3D_RC_FINAL0_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000
+#define NV30_3D_RC_FINAL0_A_INPUT_E_TIMES_F 0x0f000000
+#define NV30_3D_RC_FINAL0_A_COMPONENT_USAGE__MASK 0x10000000
+#define NV30_3D_RC_FINAL0_A_COMPONENT_USAGE__SHIFT 28
+#define NV30_3D_RC_FINAL0_A_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL0_A_COMPONENT_USAGE_ALPHA 0x10000000
+#define NV30_3D_RC_FINAL0_A_MAPPING__MASK 0xe0000000
+#define NV30_3D_RC_FINAL0_A_MAPPING__SHIFT 29
+#define NV30_3D_RC_FINAL0_A_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_UNSIGNED_INVERT 0x20000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_EXPAND_NORMAL 0x40000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_EXPAND_NEGATE 0x60000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NORMAL 0x80000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_SIGNED_IDENTITY 0xc0000000
+#define NV30_3D_RC_FINAL0_A_MAPPING_SIGNED_NEGATE 0xe0000000
+
+#define NV30_3D_RC_FINAL1 0x000008f8
+#define NV30_3D_RC_FINAL1_COLOR_SUM_CLAMP 0x00000080
+#define NV30_3D_RC_FINAL1_G_INPUT__MASK 0x00000f00
+#define NV30_3D_RC_FINAL1_G_INPUT__SHIFT 8
+#define NV30_3D_RC_FINAL1_G_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_FINAL1_G_INPUT_FOG 0x00000300
+#define NV30_3D_RC_FINAL1_G_INPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_FINAL1_G_INPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_FINAL1_G_INPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_FINAL1_G_INPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_FINAL1_G_INPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_FINAL1_G_INPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_FINAL1_G_INPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_FINAL1_G_INPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_FINAL1_G_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_FINAL1_G_INPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_FINAL1_G_COMPONENT_USAGE__MASK 0x00001000
+#define NV30_3D_RC_FINAL1_G_COMPONENT_USAGE__SHIFT 12
+#define NV30_3D_RC_FINAL1_G_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL1_G_COMPONENT_USAGE_ALPHA 0x00001000
+#define NV30_3D_RC_FINAL1_G_MAPPING__MASK 0x0000e000
+#define NV30_3D_RC_FINAL1_G_MAPPING__SHIFT 13
+#define NV30_3D_RC_FINAL1_G_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL1_G_MAPPING_UNSIGNED_INVERT 0x00002000
+#define NV30_3D_RC_FINAL1_G_MAPPING_EXPAND_NORMAL 0x00004000
+#define NV30_3D_RC_FINAL1_G_MAPPING_EXPAND_NEGATE 0x00006000
+#define NV30_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NORMAL 0x00008000
+#define NV30_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NEGATE 0x0000a000
+#define NV30_3D_RC_FINAL1_G_MAPPING_SIGNED_IDENTITY 0x0000c000
+#define NV30_3D_RC_FINAL1_G_MAPPING_SIGNED_NEGATE 0x0000e000
+#define NV30_3D_RC_FINAL1_F_INPUT__MASK 0x000f0000
+#define NV30_3D_RC_FINAL1_F_INPUT__SHIFT 16
+#define NV30_3D_RC_FINAL1_F_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR0 0x00010000
+#define NV30_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR1 0x00020000
+#define NV30_3D_RC_FINAL1_F_INPUT_FOG 0x00030000
+#define NV30_3D_RC_FINAL1_F_INPUT_PRIMARY_COLOR 0x00040000
+#define NV30_3D_RC_FINAL1_F_INPUT_SECONDARY_COLOR 0x00050000
+#define NV30_3D_RC_FINAL1_F_INPUT_TEXTURE0 0x00080000
+#define NV30_3D_RC_FINAL1_F_INPUT_TEXTURE1 0x00090000
+#define NV30_3D_RC_FINAL1_F_INPUT_TEXTURE2 0x000a0000
+#define NV30_3D_RC_FINAL1_F_INPUT_TEXTURE3 0x000b0000
+#define NV30_3D_RC_FINAL1_F_INPUT_SPARE0 0x000c0000
+#define NV30_3D_RC_FINAL1_F_INPUT_SPARE1 0x000d0000
+#define NV30_3D_RC_FINAL1_F_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000
+#define NV30_3D_RC_FINAL1_F_INPUT_E_TIMES_F 0x000f0000
+#define NV30_3D_RC_FINAL1_F_COMPONENT_USAGE__MASK 0x00100000
+#define NV30_3D_RC_FINAL1_F_COMPONENT_USAGE__SHIFT 20
+#define NV30_3D_RC_FINAL1_F_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL1_F_COMPONENT_USAGE_ALPHA 0x00100000
+#define NV30_3D_RC_FINAL1_F_MAPPING__MASK 0x00e00000
+#define NV30_3D_RC_FINAL1_F_MAPPING__SHIFT 21
+#define NV30_3D_RC_FINAL1_F_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL1_F_MAPPING_UNSIGNED_INVERT 0x00200000
+#define NV30_3D_RC_FINAL1_F_MAPPING_EXPAND_NORMAL 0x00400000
+#define NV30_3D_RC_FINAL1_F_MAPPING_EXPAND_NEGATE 0x00600000
+#define NV30_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NORMAL 0x00800000
+#define NV30_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NEGATE 0x00a00000
+#define NV30_3D_RC_FINAL1_F_MAPPING_SIGNED_IDENTITY 0x00c00000
+#define NV30_3D_RC_FINAL1_F_MAPPING_SIGNED_NEGATE 0x00e00000
+#define NV30_3D_RC_FINAL1_E_INPUT__MASK 0x0f000000
+#define NV30_3D_RC_FINAL1_E_INPUT__SHIFT 24
+#define NV30_3D_RC_FINAL1_E_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR0 0x01000000
+#define NV30_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR1 0x02000000
+#define NV30_3D_RC_FINAL1_E_INPUT_FOG 0x03000000
+#define NV30_3D_RC_FINAL1_E_INPUT_PRIMARY_COLOR 0x04000000
+#define NV30_3D_RC_FINAL1_E_INPUT_SECONDARY_COLOR 0x05000000
+#define NV30_3D_RC_FINAL1_E_INPUT_TEXTURE0 0x08000000
+#define NV30_3D_RC_FINAL1_E_INPUT_TEXTURE1 0x09000000
+#define NV30_3D_RC_FINAL1_E_INPUT_TEXTURE2 0x0a000000
+#define NV30_3D_RC_FINAL1_E_INPUT_TEXTURE3 0x0b000000
+#define NV30_3D_RC_FINAL1_E_INPUT_SPARE0 0x0c000000
+#define NV30_3D_RC_FINAL1_E_INPUT_SPARE1 0x0d000000
+#define NV30_3D_RC_FINAL1_E_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000
+#define NV30_3D_RC_FINAL1_E_INPUT_E_TIMES_F 0x0f000000
+#define NV30_3D_RC_FINAL1_E_COMPONENT_USAGE__MASK 0x10000000
+#define NV30_3D_RC_FINAL1_E_COMPONENT_USAGE__SHIFT 28
+#define NV30_3D_RC_FINAL1_E_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_FINAL1_E_COMPONENT_USAGE_ALPHA 0x10000000
+#define NV30_3D_RC_FINAL1_E_MAPPING__MASK 0xe0000000
+#define NV30_3D_RC_FINAL1_E_MAPPING__SHIFT 29
+#define NV30_3D_RC_FINAL1_E_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_UNSIGNED_INVERT 0x20000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_EXPAND_NORMAL 0x40000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_EXPAND_NEGATE 0x60000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NORMAL 0x80000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NEGATE 0xa0000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_SIGNED_IDENTITY 0xc0000000
+#define NV30_3D_RC_FINAL1_E_MAPPING_SIGNED_NEGATE 0xe0000000
+
+#define NV30_3D_RC_ENABLE 0x000008fc
+#define NV30_3D_RC_ENABLE_NUM_COMBINERS__MASK 0x0000000f
+#define NV30_3D_RC_ENABLE_NUM_COMBINERS__SHIFT 0
+#define NV30_3D_RC_ENABLE_STAGE_CONSTANT_COLOR0 0x0000f000
+#define NV30_3D_RC_ENABLE_STAGE_CONSTANT_COLOR1 0x000f0000
+
+
+#define NV30_3D_RC_IN_ALPHA(i0) (0x00000900 + 0x20*(i0))
+#define NV30_3D_RC_IN_ALPHA_D_INPUT__MASK 0x0000000f
+#define NV30_3D_RC_IN_ALPHA_D_INPUT__SHIFT 0
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR0 0x00000001
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR1 0x00000002
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_FOG 0x00000003
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_PRIMARY_COLOR 0x00000004
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_SECONDARY_COLOR 0x00000005
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_TEXTURE0 0x00000008
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_TEXTURE1 0x00000009
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_TEXTURE2 0x0000000a
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_TEXTURE3 0x0000000b
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_SPARE0 0x0000000c
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_SPARE1 0x0000000d
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e
+#define NV30_3D_RC_IN_ALPHA_D_INPUT_E_TIMES_F 0x0000000f
+#define NV30_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__MASK 0x00000010
+#define NV30_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__SHIFT 4
+#define NV30_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_BLUE 0x00000000
+#define NV30_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA 0x00000010
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING__MASK 0x000000e0
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING__SHIFT 5
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT 0x00000020
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NORMAL 0x00000040
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NEGATE 0x00000060
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NORMAL 0x00000080
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_IDENTITY 0x000000c0
+#define NV30_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_NEGATE 0x000000e0
+#define NV30_3D_RC_IN_ALPHA_C_INPUT__MASK 0x00000f00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT__SHIFT 8
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_FOG 0x00000300
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_IN_ALPHA_C_INPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__MASK 0x00001000
+#define NV30_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__SHIFT 12
+#define NV30_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_BLUE 0x00000000
+#define NV30_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA 0x00001000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING__MASK 0x0000e000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING__SHIFT 13
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT 0x00002000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NORMAL 0x00004000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NEGATE 0x00006000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NORMAL 0x00008000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_IDENTITY 0x0000c000
+#define NV30_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_NEGATE 0x0000e000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT__MASK 0x000f0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT__SHIFT 16
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR0 0x00010000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR1 0x00020000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_FOG 0x00030000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_PRIMARY_COLOR 0x00040000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_SECONDARY_COLOR 0x00050000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_TEXTURE0 0x00080000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_TEXTURE1 0x00090000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_TEXTURE2 0x000a0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_TEXTURE3 0x000b0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_SPARE0 0x000c0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_SPARE1 0x000d0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000
+#define NV30_3D_RC_IN_ALPHA_B_INPUT_E_TIMES_F 0x000f0000
+#define NV30_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__MASK 0x00100000
+#define NV30_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__SHIFT 20
+#define NV30_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_BLUE 0x00000000
+#define NV30_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA 0x00100000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING__MASK 0x00e00000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING__SHIFT 21
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT 0x00200000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NORMAL 0x00400000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NEGATE 0x00600000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NORMAL 0x00800000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_IDENTITY 0x00c00000
+#define NV30_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_NEGATE 0x00e00000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT__MASK 0x0f000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT__SHIFT 24
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR0 0x01000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR1 0x02000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_FOG 0x03000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_PRIMARY_COLOR 0x04000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_SECONDARY_COLOR 0x05000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_TEXTURE0 0x08000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_TEXTURE1 0x09000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_TEXTURE2 0x0a000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_TEXTURE3 0x0b000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_SPARE0 0x0c000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_SPARE1 0x0d000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000
+#define NV30_3D_RC_IN_ALPHA_A_INPUT_E_TIMES_F 0x0f000000
+#define NV30_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__MASK 0x10000000
+#define NV30_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__SHIFT 28
+#define NV30_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_BLUE 0x00000000
+#define NV30_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA 0x10000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING__MASK 0xe0000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING__SHIFT 29
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT 0x20000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NORMAL 0x40000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NEGATE 0x60000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NORMAL 0x80000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_IDENTITY 0xc0000000
+#define NV30_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_NEGATE 0xe0000000
+
+#define NV30_3D_RC_IN_RGB(i0) (0x00000904 + 0x20*(i0))
+#define NV30_3D_RC_IN_RGB_D_INPUT__MASK 0x0000000f
+#define NV30_3D_RC_IN_RGB_D_INPUT__SHIFT 0
+#define NV30_3D_RC_IN_RGB_D_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR0 0x00000001
+#define NV30_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1 0x00000002
+#define NV30_3D_RC_IN_RGB_D_INPUT_FOG 0x00000003
+#define NV30_3D_RC_IN_RGB_D_INPUT_PRIMARY_COLOR 0x00000004
+#define NV30_3D_RC_IN_RGB_D_INPUT_SECONDARY_COLOR 0x00000005
+#define NV30_3D_RC_IN_RGB_D_INPUT_TEXTURE0 0x00000008
+#define NV30_3D_RC_IN_RGB_D_INPUT_TEXTURE1 0x00000009
+#define NV30_3D_RC_IN_RGB_D_INPUT_TEXTURE2 0x0000000a
+#define NV30_3D_RC_IN_RGB_D_INPUT_TEXTURE3 0x0000000b
+#define NV30_3D_RC_IN_RGB_D_INPUT_SPARE0 0x0000000c
+#define NV30_3D_RC_IN_RGB_D_INPUT_SPARE1 0x0000000d
+#define NV30_3D_RC_IN_RGB_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e
+#define NV30_3D_RC_IN_RGB_D_INPUT_E_TIMES_F 0x0000000f
+#define NV30_3D_RC_IN_RGB_D_COMPONENT_USAGE__MASK 0x00000010
+#define NV30_3D_RC_IN_RGB_D_COMPONENT_USAGE__SHIFT 4
+#define NV30_3D_RC_IN_RGB_D_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_IN_RGB_D_COMPONENT_USAGE_ALPHA 0x00000010
+#define NV30_3D_RC_IN_RGB_D_MAPPING__MASK 0x000000e0
+#define NV30_3D_RC_IN_RGB_D_MAPPING__SHIFT 5
+#define NV30_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT 0x00000020
+#define NV30_3D_RC_IN_RGB_D_MAPPING_EXPAND_NORMAL 0x00000040
+#define NV30_3D_RC_IN_RGB_D_MAPPING_EXPAND_NEGATE 0x00000060
+#define NV30_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NORMAL 0x00000080
+#define NV30_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0
+#define NV30_3D_RC_IN_RGB_D_MAPPING_SIGNED_IDENTITY 0x000000c0
+#define NV30_3D_RC_IN_RGB_D_MAPPING_SIGNED_NEGATE 0x000000e0
+#define NV30_3D_RC_IN_RGB_C_INPUT__MASK 0x00000f00
+#define NV30_3D_RC_IN_RGB_C_INPUT__SHIFT 8
+#define NV30_3D_RC_IN_RGB_C_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_IN_RGB_C_INPUT_FOG 0x00000300
+#define NV30_3D_RC_IN_RGB_C_INPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_IN_RGB_C_INPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_IN_RGB_C_INPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_IN_RGB_C_INPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_IN_RGB_C_INPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_IN_RGB_C_INPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_IN_RGB_C_INPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_IN_RGB_C_INPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_IN_RGB_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_IN_RGB_C_INPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_IN_RGB_C_COMPONENT_USAGE__MASK 0x00001000
+#define NV30_3D_RC_IN_RGB_C_COMPONENT_USAGE__SHIFT 12
+#define NV30_3D_RC_IN_RGB_C_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA 0x00001000
+#define NV30_3D_RC_IN_RGB_C_MAPPING__MASK 0x0000e000
+#define NV30_3D_RC_IN_RGB_C_MAPPING__SHIFT 13
+#define NV30_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT 0x00002000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_EXPAND_NORMAL 0x00004000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_EXPAND_NEGATE 0x00006000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NORMAL 0x00008000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_SIGNED_IDENTITY 0x0000c000
+#define NV30_3D_RC_IN_RGB_C_MAPPING_SIGNED_NEGATE 0x0000e000
+#define NV30_3D_RC_IN_RGB_B_INPUT__MASK 0x000f0000
+#define NV30_3D_RC_IN_RGB_B_INPUT__SHIFT 16
+#define NV30_3D_RC_IN_RGB_B_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0 0x00010000
+#define NV30_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR1 0x00020000
+#define NV30_3D_RC_IN_RGB_B_INPUT_FOG 0x00030000
+#define NV30_3D_RC_IN_RGB_B_INPUT_PRIMARY_COLOR 0x00040000
+#define NV30_3D_RC_IN_RGB_B_INPUT_SECONDARY_COLOR 0x00050000
+#define NV30_3D_RC_IN_RGB_B_INPUT_TEXTURE0 0x00080000
+#define NV30_3D_RC_IN_RGB_B_INPUT_TEXTURE1 0x00090000
+#define NV30_3D_RC_IN_RGB_B_INPUT_TEXTURE2 0x000a0000
+#define NV30_3D_RC_IN_RGB_B_INPUT_TEXTURE3 0x000b0000
+#define NV30_3D_RC_IN_RGB_B_INPUT_SPARE0 0x000c0000
+#define NV30_3D_RC_IN_RGB_B_INPUT_SPARE1 0x000d0000
+#define NV30_3D_RC_IN_RGB_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000
+#define NV30_3D_RC_IN_RGB_B_INPUT_E_TIMES_F 0x000f0000
+#define NV30_3D_RC_IN_RGB_B_COMPONENT_USAGE__MASK 0x00100000
+#define NV30_3D_RC_IN_RGB_B_COMPONENT_USAGE__SHIFT 20
+#define NV30_3D_RC_IN_RGB_B_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA 0x00100000
+#define NV30_3D_RC_IN_RGB_B_MAPPING__MASK 0x00e00000
+#define NV30_3D_RC_IN_RGB_B_MAPPING__SHIFT 21
+#define NV30_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT 0x00200000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_EXPAND_NORMAL 0x00400000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_EXPAND_NEGATE 0x00600000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NORMAL 0x00800000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_SIGNED_IDENTITY 0x00c00000
+#define NV30_3D_RC_IN_RGB_B_MAPPING_SIGNED_NEGATE 0x00e00000
+#define NV30_3D_RC_IN_RGB_A_INPUT__MASK 0x0f000000
+#define NV30_3D_RC_IN_RGB_A_INPUT__SHIFT 24
+#define NV30_3D_RC_IN_RGB_A_INPUT_ZERO 0x00000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR0 0x01000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR1 0x02000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_FOG 0x03000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_PRIMARY_COLOR 0x04000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_SECONDARY_COLOR 0x05000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_TEXTURE0 0x08000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_TEXTURE1 0x09000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_TEXTURE2 0x0a000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_TEXTURE3 0x0b000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_SPARE0 0x0c000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_SPARE1 0x0d000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000
+#define NV30_3D_RC_IN_RGB_A_INPUT_E_TIMES_F 0x0f000000
+#define NV30_3D_RC_IN_RGB_A_COMPONENT_USAGE__MASK 0x10000000
+#define NV30_3D_RC_IN_RGB_A_COMPONENT_USAGE__SHIFT 28
+#define NV30_3D_RC_IN_RGB_A_COMPONENT_USAGE_RGB 0x00000000
+#define NV30_3D_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA 0x10000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING__MASK 0xe0000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING__SHIFT 29
+#define NV30_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_IDENTITY 0x00000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT 0x20000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_EXPAND_NORMAL 0x40000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_EXPAND_NEGATE 0x60000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NORMAL 0x80000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_SIGNED_IDENTITY 0xc0000000
+#define NV30_3D_RC_IN_RGB_A_MAPPING_SIGNED_NEGATE 0xe0000000
+
+#define NV30_3D_RC_CONSTANT_COLOR0(i0) (0x00000908 + 0x20*(i0))
+#define NV30_3D_RC_CONSTANT_COLOR0_B__MASK 0x000000ff
+#define NV30_3D_RC_CONSTANT_COLOR0_B__SHIFT 0
+#define NV30_3D_RC_CONSTANT_COLOR0_G__MASK 0x0000ff00
+#define NV30_3D_RC_CONSTANT_COLOR0_G__SHIFT 8
+#define NV30_3D_RC_CONSTANT_COLOR0_R__MASK 0x00ff0000
+#define NV30_3D_RC_CONSTANT_COLOR0_R__SHIFT 16
+#define NV30_3D_RC_CONSTANT_COLOR0_A__MASK 0xff000000
+#define NV30_3D_RC_CONSTANT_COLOR0_A__SHIFT 24
+
+#define NV30_3D_RC_CONSTANT_COLOR1(i0) (0x0000090c + 0x20*(i0))
+#define NV30_3D_RC_CONSTANT_COLOR1_B__MASK 0x000000ff
+#define NV30_3D_RC_CONSTANT_COLOR1_B__SHIFT 0
+#define NV30_3D_RC_CONSTANT_COLOR1_G__MASK 0x0000ff00
+#define NV30_3D_RC_CONSTANT_COLOR1_G__SHIFT 8
+#define NV30_3D_RC_CONSTANT_COLOR1_R__MASK 0x00ff0000
+#define NV30_3D_RC_CONSTANT_COLOR1_R__SHIFT 16
+#define NV30_3D_RC_CONSTANT_COLOR1_A__MASK 0xff000000
+#define NV30_3D_RC_CONSTANT_COLOR1_A__SHIFT 24
+
+#define NV30_3D_RC_OUT_ALPHA(i0) (0x00000910 + 0x20*(i0))
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT__MASK 0x0000000f
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT__SHIFT 0
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR0 0x00000001
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR1 0x00000002
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_FOG 0x00000003
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_PRIMARY_COLOR 0x00000004
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_SECONDARY_COLOR 0x00000005
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE0 0x00000008
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE1 0x00000009
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE2 0x0000000a
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE3 0x0000000b
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0 0x0000000c
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE1 0x0000000d
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e
+#define NV30_3D_RC_OUT_ALPHA_CD_OUTPUT_E_TIMES_F 0x0000000f
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT__MASK 0x000000f0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT__SHIFT 4
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR0 0x00000010
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR1 0x00000020
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_FOG 0x00000030
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_PRIMARY_COLOR 0x00000040
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_SECONDARY_COLOR 0x00000050
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE0 0x00000080
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE1 0x00000090
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE2 0x000000a0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE3 0x000000b0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0 0x000000c0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE1 0x000000d0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0
+#define NV30_3D_RC_OUT_ALPHA_AB_OUTPUT_E_TIMES_F 0x000000f0
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT__MASK 0x00000f00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT__SHIFT 8
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_FOG 0x00000300
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_OUT_ALPHA_SUM_OUTPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_OUT_ALPHA_CD_DOT_PRODUCT 0x00001000
+#define NV30_3D_RC_OUT_ALPHA_AB_DOT_PRODUCT 0x00002000
+#define NV30_3D_RC_OUT_ALPHA_MUX_SUM 0x00004000
+#define NV30_3D_RC_OUT_ALPHA_BIAS__MASK 0x00008000
+#define NV30_3D_RC_OUT_ALPHA_BIAS__SHIFT 15
+#define NV30_3D_RC_OUT_ALPHA_BIAS_NONE 0x00000000
+#define NV30_3D_RC_OUT_ALPHA_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000
+#define NV30_3D_RC_OUT_ALPHA_SCALE__MASK 0x00030000
+#define NV30_3D_RC_OUT_ALPHA_SCALE__SHIFT 16
+#define NV30_3D_RC_OUT_ALPHA_SCALE_NONE 0x00000000
+#define NV30_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_TWO 0x00010000
+#define NV30_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_FOUR 0x00020000
+#define NV30_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_ONE_HALF 0x00030000
+
+#define NV30_3D_RC_OUT_RGB(i0) (0x00000914 + 0x20*(i0))
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT__MASK 0x0000000f
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT__SHIFT 0
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR0 0x00000001
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR1 0x00000002
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_FOG 0x00000003
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_PRIMARY_COLOR 0x00000004
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_SECONDARY_COLOR 0x00000005
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE0 0x00000008
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE1 0x00000009
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE2 0x0000000a
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE3 0x0000000b
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0 0x0000000c
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_SPARE1 0x0000000d
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e
+#define NV30_3D_RC_OUT_RGB_CD_OUTPUT_E_TIMES_F 0x0000000f
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT__MASK 0x000000f0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT__SHIFT 4
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR0 0x00000010
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR1 0x00000020
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_FOG 0x00000030
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_PRIMARY_COLOR 0x00000040
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_SECONDARY_COLOR 0x00000050
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE0 0x00000080
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE1 0x00000090
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE2 0x000000a0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE3 0x000000b0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 0x000000c0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_SPARE1 0x000000d0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0
+#define NV30_3D_RC_OUT_RGB_AB_OUTPUT_E_TIMES_F 0x000000f0
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT__MASK 0x00000f00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT__SHIFT 8
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_ZERO 0x00000000
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_FOG 0x00000300
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_PRIMARY_COLOR 0x00000400
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_SECONDARY_COLOR 0x00000500
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE0 0x00000800
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE1 0x00000900
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE2 0x00000a00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE3 0x00000b00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0 0x00000c00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE1 0x00000d00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00
+#define NV30_3D_RC_OUT_RGB_SUM_OUTPUT_E_TIMES_F 0x00000f00
+#define NV30_3D_RC_OUT_RGB_CD_DOT_PRODUCT 0x00001000
+#define NV30_3D_RC_OUT_RGB_AB_DOT_PRODUCT 0x00002000
+#define NV30_3D_RC_OUT_RGB_MUX_SUM 0x00004000
+#define NV30_3D_RC_OUT_RGB_BIAS__MASK 0x00008000
+#define NV30_3D_RC_OUT_RGB_BIAS__SHIFT 15
+#define NV30_3D_RC_OUT_RGB_BIAS_NONE 0x00000000
+#define NV30_3D_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000
+#define NV30_3D_RC_OUT_RGB_SCALE__MASK 0x00030000
+#define NV30_3D_RC_OUT_RGB_SCALE__SHIFT 16
+#define NV30_3D_RC_OUT_RGB_SCALE_NONE 0x00000000
+#define NV30_3D_RC_OUT_RGB_SCALE_SCALE_BY_TWO 0x00010000
+#define NV30_3D_RC_OUT_RGB_SCALE_SCALE_BY_FOUR 0x00020000
+#define NV30_3D_RC_OUT_RGB_SCALE_SCALE_BY_ONE_HALF 0x00030000
+
+#define NV30_3D_VIEWPORT_HORIZ 0x00000a00
+#define NV30_3D_VIEWPORT_HORIZ_X__MASK 0x0000ffff
+#define NV30_3D_VIEWPORT_HORIZ_X__SHIFT 0
+#define NV30_3D_VIEWPORT_HORIZ_W__MASK 0xffff0000
+#define NV30_3D_VIEWPORT_HORIZ_W__SHIFT 16
+
+#define NV30_3D_VIEWPORT_VERT 0x00000a04
+#define NV30_3D_VIEWPORT_VERT_Y__MASK 0x0000ffff
+#define NV30_3D_VIEWPORT_VERT_Y__SHIFT 0
+#define NV30_3D_VIEWPORT_VERT_H__MASK 0xffff0000
+#define NV30_3D_VIEWPORT_VERT_H__SHIFT 16
+
+#define NV30_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION 0x00000a10
+
+
+#define NV30_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x00000a10
+
+#define NV30_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x00000a14
+
+#define NV30_3D_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x00000a18
+
+#define NV30_3D_VIEWPORT_TRANSLATE 0x00000a20
+
+
+#define NV30_3D_VIEWPORT_TRANSLATE_X 0x00000a20
+
+#define NV30_3D_VIEWPORT_TRANSLATE_Y 0x00000a24
+
+#define NV30_3D_VIEWPORT_TRANSLATE_Z 0x00000a28
+
+#define NV30_3D_VIEWPORT_TRANSLATE_W 0x00000a2c
+
+#define NV30_3D_VIEWPORT_SCALE 0x00000a30
+
+
+#define NV30_3D_VIEWPORT_SCALE_X 0x00000a30
+
+#define NV30_3D_VIEWPORT_SCALE_Y 0x00000a34
+
+#define NV30_3D_VIEWPORT_SCALE_Z 0x00000a38
+
+#define NV30_3D_VIEWPORT_SCALE_W 0x00000a3c
+
+#define NV30_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000a60
+
+#define NV30_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000a64
+
+#define NV30_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000a68
+
+#define NV30_3D_DEPTH_FUNC 0x00000a6c
+#define NV30_3D_DEPTH_FUNC_NEVER 0x00000200
+#define NV30_3D_DEPTH_FUNC_LESS 0x00000201
+#define NV30_3D_DEPTH_FUNC_EQUAL 0x00000202
+#define NV30_3D_DEPTH_FUNC_LEQUAL 0x00000203
+#define NV30_3D_DEPTH_FUNC_GREATER 0x00000204
+#define NV30_3D_DEPTH_FUNC_NOTEQUAL 0x00000205
+#define NV30_3D_DEPTH_FUNC_GEQUAL 0x00000206
+#define NV30_3D_DEPTH_FUNC_ALWAYS 0x00000207
+
+#define NV30_3D_DEPTH_WRITE_ENABLE 0x00000a70
+
+#define NV30_3D_DEPTH_TEST_ENABLE 0x00000a74
+
+#define NV30_3D_POLYGON_OFFSET_FACTOR 0x00000a78
+
+#define NV30_3D_POLYGON_OFFSET_UNITS 0x00000a7c
+
+#define NV30_3D_VTX_ATTR_3I_XY(i0) (0x00000a80 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_3I_XY__ESIZE 0x00000008
+#define NV30_3D_VTX_ATTR_3I_XY__LEN 0x00000010
+#define NV30_3D_VTX_ATTR_3I_XY_X__MASK 0x0000ffff
+#define NV30_3D_VTX_ATTR_3I_XY_X__SHIFT 0
+#define NV30_3D_VTX_ATTR_3I_XY_Y__MASK 0xffff0000
+#define NV30_3D_VTX_ATTR_3I_XY_Y__SHIFT 16
+
+#define NV30_3D_VTX_ATTR_3I_Z(i0) (0x00000a84 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_3I_Z__ESIZE 0x00000008
+#define NV30_3D_VTX_ATTR_3I_Z__LEN 0x00000010
+#define NV30_3D_VTX_ATTR_3I_Z_Z__MASK 0x0000ffff
+#define NV30_3D_VTX_ATTR_3I_Z_Z__SHIFT 0
+
+#define NV30_3D_TEX_FILTER_OPTIMIZATION(i0) (0x00000b00 + 0x4*(i0))
+#define NV30_3D_TEX_FILTER_OPTIMIZATION__ESIZE 0x00000004
+#define NV30_3D_TEX_FILTER_OPTIMIZATION__LEN 0x00000004
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR__MASK 0x0000001f
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR__SHIFT 0
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR_OFF 0x00000000
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR_HIGH_QUALITY 0x00000004
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR_QUALITY 0x00000006
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR_PERFORMANCE 0x00000008
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_TRILINEAR_HIGH_PERFORMANCE 0x00000018
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE__MASK 0x000001c0
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE__SHIFT 6
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE_OFF 0x00000000
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE_HIGH_QUALITY 0x000000c0
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE_QUALITY 0x000001c0
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_ANISO_SAMPLE_PERFORMANCE 0x00000140
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_UNKNOWN__MASK 0x00007c00
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_UNKNOWN__SHIFT 10
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_UNKNOWN_OFF 0x00000000
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_UNKNOWN_PARTIAL 0x00002c00
+#define NV40_3D_TEX_FILTER_OPTIMIZATION_UNKNOWN_FULL 0x00007c00
+
+#define NV40_3D_UNK0B40(i0) (0x00000b40 + 0x4*(i0))
+#define NV40_3D_UNK0B40__ESIZE 0x00000004
+#define NV40_3D_UNK0B40__LEN 0x00000008
+
+#define NV30_3D_VP_UPLOAD_INST(i0) (0x00000b80 + 0x4*(i0))
+#define NV30_3D_VP_UPLOAD_INST__ESIZE 0x00000004
+#define NV30_3D_VP_UPLOAD_INST__LEN 0x00000004
+
+
+#define NV30_3D_TEX_CLIP_PLANE(i0) (0x00000e00 + 0x10*(i0))
+
+
+#define NV30_3D_TEX_CLIP_PLANE_X(i0) (0x00000e00 + 0x10*(i0))
+
+#define NV30_3D_TEX_CLIP_PLANE_Y(i0) (0x00000e04 + 0x10*(i0))
+
+#define NV30_3D_TEX_CLIP_PLANE_Z(i0) (0x00000e08 + 0x10*(i0))
+
+#define NV30_3D_TEX_CLIP_PLANE_W(i0) (0x00000e0c + 0x10*(i0))
+
+#define NV30_3D_LIGHT 0x00001000
+
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT(i0) (0x00001000 + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(i0) (0x00001000 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(i0) (0x00001004 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(i0) (0x00001008 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE(i0) (0x0000100c + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(i0) (0x0000100c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(i0) (0x00001010 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(i0) (0x00001014 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR(i0) (0x00001018 + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(i0) (0x00001018 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(i0) (0x0000101c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(i0) (0x00001020 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_UNK24(i0) (0x00001024 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_HALF_VECTOR(i0) (0x00001028 + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_HALF_VECTOR_X(i0) (0x00001028 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_HALF_VECTOR_Y(i0) (0x0000102c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_HALF_VECTOR_Z(i0) (0x00001030 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_DIRECTION(i0) (0x00001034 + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_DIRECTION_X(i0) (0x00001034 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_DIRECTION_Y(i0) (0x00001038 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_DIRECTION_Z(i0) (0x0000103c + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_SPOT_CUTOFF_A(i0) (0x00001200 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_CUTOFF_B(i0) (0x00001204 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_CUTOFF_C(i0) (0x00001208 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_DIR(i0) (0x0000120c + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_SPOT_DIR_X(i0) (0x0000120c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_DIR_Y(i0) (0x00001210 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_DIR_Z(i0) (0x00001214 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_SPOT_CUTOFF_D(i0) (0x00001218 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_POSITION(i0) (0x0000121c + 0x40*(i0))
+
+
+#define NV30_3D_LIGHT_POSITION_X(i0) (0x0000121c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_POSITION_Y(i0) (0x00001220 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_POSITION_Z(i0) (0x00001224 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_ATTENUATION(i0) (0x00001228 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_ATTENUATION_CONSTANT(i0) (0x00001228 + 0x40*(i0))
+
+#define NV30_3D_LIGHT_ATTENUATION_LINEAR(i0) (0x0000122c + 0x40*(i0))
+
+#define NV30_3D_LIGHT_ATTENUATION_QUADRATIC(i0) (0x00001230 + 0x40*(i0))
+
+#define NV30_3D_FRONT_MATERIAL_SHININESS(i0) (0x00001400 + 0x4*(i0))
+#define NV30_3D_FRONT_MATERIAL_SHININESS__ESIZE 0x00000004
+#define NV30_3D_FRONT_MATERIAL_SHININESS__LEN 0x00000006
+
+#define NV30_3D_ENABLED_LIGHTS 0x00001420
+
+#define NV30_3D_VERTEX_TWO_SIDE_ENABLE 0x0000142c
+
+#define NV30_3D_FP_REG_CONTROL 0x00001450
+#define NV30_3D_FP_REG_CONTROL_UNK0__MASK 0x0000ffff
+#define NV30_3D_FP_REG_CONTROL_UNK0__SHIFT 0
+#define NV30_3D_FP_REG_CONTROL_UNK1__MASK 0xffff0000
+#define NV30_3D_FP_REG_CONTROL_UNK1__SHIFT 16
+
+#define NV30_3D_FLATSHADE_FIRST 0x00001454
+
+#define NV30_3D_EDGEFLAG 0x0000145c
+#define NV30_3D_EDGEFLAG_ENABLE 0x00000001
+
+#define NV30_3D_VP_CLIP_PLANES_ENABLE 0x00001478
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0 0x00000002
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1 0x00000020
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2 0x00000200
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3 0x00002000
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE4 0x00020000
+#define NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE5 0x00200000
+
+#define NV30_3D_POLYGON_STIPPLE_ENABLE 0x0000147c
+
+#define NV30_3D_POLYGON_STIPPLE_PATTERN(i0) (0x00001480 + 0x4*(i0))
+#define NV30_3D_POLYGON_STIPPLE_PATTERN__ESIZE 0x00000004
+#define NV30_3D_POLYGON_STIPPLE_PATTERN__LEN 0x00000020
+
+#define NV30_3D_VTX_ATTR_3F(i0) (0x00001500 + 0x10*(i0))
+#define NV30_3D_VTX_ATTR_3F__ESIZE 0x00000010
+#define NV30_3D_VTX_ATTR_3F__LEN 0x00000010
+
+
+#define NV30_3D_VTX_ATTR_3F_X(i0) (0x00001500 + 0x10*(i0))
+
+#define NV30_3D_VTX_ATTR_3F_Y(i0) (0x00001504 + 0x10*(i0))
+
+#define NV30_3D_VTX_ATTR_3F_Z(i0) (0x00001508 + 0x10*(i0))
+
+
+#define NV30_3D_VP_CLIP_PLANE(i0, i1) (0x00001600 + 0x10*(i0) + 0x4*(i1))
+#define NV30_3D_VP_CLIP_PLANE__ESIZE 0x00000004
+#define NV30_3D_VP_CLIP_PLANE__LEN 0x00000004
+
+#define NV30_3D_VTXBUF(i0) (0x00001680 + 0x4*(i0))
+#define NV30_3D_VTXBUF__ESIZE 0x00000004
+#define NV30_3D_VTXBUF__LEN 0x00000010
+#define NV30_3D_VTXBUF_OFFSET__MASK 0x0fffffff
+#define NV30_3D_VTXBUF_OFFSET__SHIFT 0
+#define NV30_3D_VTXBUF_DMA1 0x80000000
+
+#define NV40_3D_VTX_CACHE_INVALIDATE 0x00001714
+
+#define NV30_3D_VTXFMT(i0) (0x00001740 + 0x4*(i0))
+#define NV30_3D_VTXFMT__ESIZE 0x00000004
+#define NV30_3D_VTXFMT__LEN 0x00000010
+#define NV30_3D_VTXFMT_TYPE__MASK 0x0000000f
+#define NV30_3D_VTXFMT_TYPE__SHIFT 0
+#define NV30_3D_VTXFMT_TYPE_B8G8R8A8_UNORM 0x00000000
+#define NV30_3D_VTXFMT_TYPE_V16_SNORM 0x00000001
+#define NV30_3D_VTXFMT_TYPE_V32_FLOAT 0x00000002
+#define NV30_3D_VTXFMT_TYPE_V16_FLOAT 0x00000003
+#define NV30_3D_VTXFMT_TYPE_U8_UNORM 0x00000004
+#define NV30_3D_VTXFMT_TYPE_V16_SSCALED 0x00000005
+#define NV30_3D_VTXFMT_TYPE_U8_USCALED 0x00000007
+#define NV30_3D_VTXFMT_SIZE__MASK 0x000000f0
+#define NV30_3D_VTXFMT_SIZE__SHIFT 4
+#define NV30_3D_VTXFMT_STRIDE__MASK 0x0000ff00
+#define NV30_3D_VTXFMT_STRIDE__SHIFT 8
+
+#define NV30_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION 0x000017a0
+
+
+#define NV30_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R 0x000017a0
+
+#define NV30_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G 0x000017a4
+
+#define NV30_3D_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B 0x000017a8
+
+#define NV30_3D_COLOR_MATERIAL_BACK 0x000017b0
+
+
+#define NV30_3D_COLOR_MATERIAL_BACK_R 0x000017b0
+
+#define NV30_3D_COLOR_MATERIAL_BACK_G 0x000017b4
+
+#define NV30_3D_COLOR_MATERIAL_BACK_B 0x000017b8
+
+#define NV30_3D_COLOR_MATERIAL_BACK_A 0x000017bc
+
+#define NV30_3D_QUERY_RESET 0x000017c8
+
+#define NV30_3D_QUERY_ENABLE 0x000017cc
+
+#define NV30_3D_QUERY_GET 0x00001800
+#define NV30_3D_QUERY_GET_OFFSET__MASK 0x00ffffff
+#define NV30_3D_QUERY_GET_OFFSET__SHIFT 0
+#define NV30_3D_QUERY_GET_UNK24__MASK 0xff000000
+#define NV30_3D_QUERY_GET_UNK24__SHIFT 24
+
+#define NV30_3D_VERTEX_BEGIN_END 0x00001808
+#define NV30_3D_VERTEX_BEGIN_END_STOP 0x00000000
+#define NV30_3D_VERTEX_BEGIN_END_POINTS 0x00000001
+#define NV30_3D_VERTEX_BEGIN_END_LINES 0x00000002
+#define NV30_3D_VERTEX_BEGIN_END_LINE_LOOP 0x00000003
+#define NV30_3D_VERTEX_BEGIN_END_LINE_STRIP 0x00000004
+#define NV30_3D_VERTEX_BEGIN_END_TRIANGLES 0x00000005
+#define NV30_3D_VERTEX_BEGIN_END_TRIANGLE_STRIP 0x00000006
+#define NV30_3D_VERTEX_BEGIN_END_TRIANGLE_FAN 0x00000007
+#define NV30_3D_VERTEX_BEGIN_END_QUADS 0x00000008
+#define NV30_3D_VERTEX_BEGIN_END_QUAD_STRIP 0x00000009
+#define NV30_3D_VERTEX_BEGIN_END_POLYGON 0x0000000a
+
+#define NV30_3D_VB_ELEMENT_U16 0x0000180c
+#define NV30_3D_VB_ELEMENT_U16_0__MASK 0x0000ffff
+#define NV30_3D_VB_ELEMENT_U16_0__SHIFT 0
+#define NV30_3D_VB_ELEMENT_U16_1__MASK 0xffff0000
+#define NV30_3D_VB_ELEMENT_U16_1__SHIFT 16
+
+#define NV30_3D_VB_ELEMENT_U32 0x00001810
+
+#define NV30_3D_VB_VERTEX_BATCH 0x00001814
+#define NV30_3D_VB_VERTEX_BATCH_OFFSET__MASK 0x00ffffff
+#define NV30_3D_VB_VERTEX_BATCH_OFFSET__SHIFT 0
+#define NV30_3D_VB_VERTEX_BATCH_COUNT__MASK 0xff000000
+#define NV30_3D_VB_VERTEX_BATCH_COUNT__SHIFT 24
+
+#define NV30_3D_VERTEX_DATA 0x00001818
+
+#define NV30_3D_IDXBUF_OFFSET 0x0000181c
+
+#define NV30_3D_IDXBUF_FORMAT 0x00001820
+#define NV30_3D_IDXBUF_FORMAT_DMA1 0x00000001
+#define NV30_3D_IDXBUF_FORMAT_TYPE__MASK 0x000000f0
+#define NV30_3D_IDXBUF_FORMAT_TYPE__SHIFT 4
+#define NV30_3D_IDXBUF_FORMAT_TYPE_U32 0x00000000
+#define NV30_3D_IDXBUF_FORMAT_TYPE_U16 0x00000010
+
+#define NV30_3D_VB_INDEX_BATCH 0x00001824
+#define NV30_3D_VB_INDEX_BATCH_START__MASK 0x00ffffff
+#define NV30_3D_VB_INDEX_BATCH_START__SHIFT 0
+#define NV30_3D_VB_INDEX_BATCH_COUNT__MASK 0xff000000
+#define NV30_3D_VB_INDEX_BATCH_COUNT__SHIFT 24
+
+#define NV30_3D_POLYGON_MODE_FRONT 0x00001828
+#define NV30_3D_POLYGON_MODE_FRONT_POINT 0x00001b00
+#define NV30_3D_POLYGON_MODE_FRONT_LINE 0x00001b01
+#define NV30_3D_POLYGON_MODE_FRONT_FILL 0x00001b02
+
+#define NV30_3D_POLYGON_MODE_BACK 0x0000182c
+#define NV30_3D_POLYGON_MODE_BACK_POINT 0x00001b00
+#define NV30_3D_POLYGON_MODE_BACK_LINE 0x00001b01
+#define NV30_3D_POLYGON_MODE_BACK_FILL 0x00001b02
+
+#define NV30_3D_CULL_FACE 0x00001830
+#define NV30_3D_CULL_FACE_FRONT 0x00000404
+#define NV30_3D_CULL_FACE_BACK 0x00000405
+#define NV30_3D_CULL_FACE_FRONT_AND_BACK 0x00000408
+
+#define NV30_3D_FRONT_FACE 0x00001834
+#define NV30_3D_FRONT_FACE_CW 0x00000900
+#define NV30_3D_FRONT_FACE_CCW 0x00000901
+
+#define NV30_3D_POLYGON_SMOOTH_ENABLE 0x00001838
+
+#define NV30_3D_CULL_FACE_ENABLE 0x0000183c
+
+#define NV30_3D_TEX_PALETTE_OFFSET(i0) (0x00001840 + 0x4*(i0))
+#define NV30_3D_TEX_PALETTE_OFFSET__ESIZE 0x00000004
+#define NV30_3D_TEX_PALETTE_OFFSET__LEN 0x00000008
+
+#define NV40_3D_TEX_SIZE1(i0) (0x00001840 + 0x4*(i0))
+#define NV40_3D_TEX_SIZE1__ESIZE 0x00000004
+#define NV40_3D_TEX_SIZE1__LEN 0x00000008
+#define NV40_3D_TEX_SIZE1_DEPTH__MASK 0xfff00000
+#define NV40_3D_TEX_SIZE1_DEPTH__SHIFT 20
+#define NV40_3D_TEX_SIZE1_PITCH__MASK 0x0000ffff
+#define NV40_3D_TEX_SIZE1_PITCH__SHIFT 0
+
+#define NV30_3D_VTX_ATTR_2F(i0) (0x00001880 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_2F__ESIZE 0x00000008
+#define NV30_3D_VTX_ATTR_2F__LEN 0x00000010
+
+
+#define NV30_3D_VTX_ATTR_2F_X(i0) (0x00001880 + 0x8*(i0))
+
+#define NV30_3D_VTX_ATTR_2F_Y(i0) (0x00001884 + 0x8*(i0))
+
+#define NV30_3D_VTX_ATTR_2I(i0) (0x00001900 + 0x4*(i0))
+#define NV30_3D_VTX_ATTR_2I__ESIZE 0x00000004
+#define NV30_3D_VTX_ATTR_2I__LEN 0x00000010
+#define NV30_3D_VTX_ATTR_2I_X__MASK 0x0000ffff
+#define NV30_3D_VTX_ATTR_2I_X__SHIFT 0
+#define NV30_3D_VTX_ATTR_2I_Y__MASK 0xffff0000
+#define NV30_3D_VTX_ATTR_2I_Y__SHIFT 16
+
+#define NV30_3D_VTX_ATTR_4UB(i0) (0x00001940 + 0x4*(i0))
+#define NV30_3D_VTX_ATTR_4UB__ESIZE 0x00000004
+#define NV30_3D_VTX_ATTR_4UB__LEN 0x00000010
+#define NV30_3D_VTX_ATTR_4UB_X__MASK 0x000000ff
+#define NV30_3D_VTX_ATTR_4UB_X__SHIFT 0
+#define NV30_3D_VTX_ATTR_4UB_Y__MASK 0x0000ff00
+#define NV30_3D_VTX_ATTR_4UB_Y__SHIFT 8
+#define NV30_3D_VTX_ATTR_4UB_Z__MASK 0x00ff0000
+#define NV30_3D_VTX_ATTR_4UB_Z__SHIFT 16
+#define NV30_3D_VTX_ATTR_4UB_W__MASK 0xff000000
+#define NV30_3D_VTX_ATTR_4UB_W__SHIFT 24
+
+#define NV30_3D_VTX_ATTR_4I(i0) (0x00001980 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_4I__ESIZE 0x00000008
+#define NV30_3D_VTX_ATTR_4I__LEN 0x00000010
+
+#define NV30_3D_VTX_ATTR_4I_XY(i0) (0x00001980 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_4I_XY_X__MASK 0x0000ffff
+#define NV30_3D_VTX_ATTR_4I_XY_X__SHIFT 0
+#define NV30_3D_VTX_ATTR_4I_XY_Y__MASK 0xffff0000
+#define NV30_3D_VTX_ATTR_4I_XY_Y__SHIFT 16
+
+#define NV30_3D_VTX_ATTR_4I_ZW(i0) (0x00001984 + 0x8*(i0))
+#define NV30_3D_VTX_ATTR_4I_ZW_Z__MASK 0x0000ffff
+#define NV30_3D_VTX_ATTR_4I_ZW_Z__SHIFT 0
+#define NV30_3D_VTX_ATTR_4I_ZW_W__MASK 0xffff0000
+#define NV30_3D_VTX_ATTR_4I_ZW_W__SHIFT 16
+
+#define NV30_3D_TEX_OFFSET(i0) (0x00001a00 + 0x20*(i0))
+#define NV30_3D_TEX_OFFSET__ESIZE 0x00000020
+#define NV30_3D_TEX_OFFSET__LEN 0x00000008
+
+#define NV30_3D_TEX_FORMAT(i0) (0x00001a04 + 0x20*(i0))
+#define NV30_3D_TEX_FORMAT__ESIZE 0x00000020
+#define NV30_3D_TEX_FORMAT__LEN 0x00000008
+#define NV30_3D_TEX_FORMAT_DMA0 0x00000001
+#define NV30_3D_TEX_FORMAT_DMA1 0x00000002
+#define NV30_3D_TEX_FORMAT_CUBIC 0x00000004
+#define NV30_3D_TEX_FORMAT_NO_BORDER 0x00000008
+#define NV30_3D_TEX_FORMAT_DIMS__MASK 0x000000f0
+#define NV30_3D_TEX_FORMAT_DIMS__SHIFT 4
+#define NV30_3D_TEX_FORMAT_DIMS_1D 0x00000010
+#define NV30_3D_TEX_FORMAT_DIMS_2D 0x00000020
+#define NV30_3D_TEX_FORMAT_DIMS_3D 0x00000030
+#define NV30_3D_TEX_FORMAT_FORMAT__MASK 0x0000ff00
+#define NV30_3D_TEX_FORMAT_FORMAT__SHIFT 8
+#define NV30_3D_TEX_FORMAT_FORMAT_L8 0x00000000
+#define NV30_3D_TEX_FORMAT_FORMAT_I8 0x00000100
+#define NV30_3D_TEX_FORMAT_FORMAT_A1R5G5B5 0x00000200
+#define NV30_3D_TEX_FORMAT_FORMAT_A4R4G4B4 0x00000400
+#define NV30_3D_TEX_FORMAT_FORMAT_R5G6B5 0x00000500
+#define NV30_3D_TEX_FORMAT_FORMAT_A8R8G8B8 0x00000600
+#define NV30_3D_TEX_FORMAT_FORMAT_X8R8G8B8 0x00000700
+#define NV30_3D_TEX_FORMAT_FORMAT_INDEX8 0x00000b00
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT1 0x00000c00
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT3 0x00000e00
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT5 0x00000f00
+#define NV30_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT 0x00001000
+#define NV30_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT 0x00001100
+#define NV30_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT 0x00001200
+#define NV30_3D_TEX_FORMAT_FORMAT_L8_RECT 0x00001300
+#define NV30_3D_TEX_FORMAT_FORMAT_DSDT8_RECT 0x00001700
+#define NV30_3D_TEX_FORMAT_FORMAT_A8L8 0x00001a00
+#define NV30_3D_TEX_FORMAT_FORMAT_I8_RECT 0x00001b00
+#define NV30_3D_TEX_FORMAT_FORMAT_A4R4G4B4_RECT 0x00001d00
+#define NV30_3D_TEX_FORMAT_FORMAT_R8G8B8_RECT 0x00001e00
+#define NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT 0x00002000
+#define NV30_3D_TEX_FORMAT_FORMAT_Z24 0x00002a00
+#define NV30_3D_TEX_FORMAT_FORMAT_Z24_RECT 0x00002b00
+#define NV30_3D_TEX_FORMAT_FORMAT_Z16 0x00002c00
+#define NV30_3D_TEX_FORMAT_FORMAT_Z16_RECT 0x00002d00
+#define NV30_3D_TEX_FORMAT_FORMAT_DSDT8 0x00002800
+#define NV30_3D_TEX_FORMAT_FORMAT_HILO16 0x00003300
+#define NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT 0x00003600
+#define NV30_3D_TEX_FORMAT_FORMAT_HILO8 0x00004400
+#define NV30_3D_TEX_FORMAT_FORMAT_SIGNED_HILO8 0x00004500
+#define NV30_3D_TEX_FORMAT_FORMAT_HILO8_RECT 0x00004600
+#define NV30_3D_TEX_FORMAT_FORMAT_SIGNED_HILO8_RECT 0x00004700
+#define NV30_3D_TEX_FORMAT_FORMAT_A16 0x00003200
+#define NV30_3D_TEX_FORMAT_FORMAT_A16_RECT 0x00003500
+#define NV30_3D_TEX_FORMAT_FORMAT_UNK3F 0x00003f00
+#define NV30_3D_TEX_FORMAT_FORMAT_FLOAT_RGBA16_NV 0x00004a00
+#define NV30_3D_TEX_FORMAT_FORMAT_FLOAT_RGBA32_NV 0x00004b00
+#define NV30_3D_TEX_FORMAT_FORMAT_FLOAT_R32_NV 0x00004c00
+#define NV40_3D_TEX_FORMAT_FORMAT__MASK 0x00001f00
+#define NV40_3D_TEX_FORMAT_FORMAT__SHIFT 8
+#define NV40_3D_TEX_FORMAT_FORMAT_L8 0x00000100
+#define NV40_3D_TEX_FORMAT_FORMAT_A1R5G5B5 0x00000200
+#define NV40_3D_TEX_FORMAT_FORMAT_A4R4G4B4 0x00000300
+#define NV40_3D_TEX_FORMAT_FORMAT_R5G6B5 0x00000400
+#define NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8 0x00000500
+#define NV40_3D_TEX_FORMAT_FORMAT_DXT1 0x00000600
+#define NV40_3D_TEX_FORMAT_FORMAT_DXT3 0x00000700
+#define NV40_3D_TEX_FORMAT_FORMAT_DXT5 0x00000800
+#define NV40_3D_TEX_FORMAT_FORMAT_A8L8 0x00000b00
+#define NV40_3D_TEX_FORMAT_FORMAT_Z24 0x00001000
+#define NV40_3D_TEX_FORMAT_FORMAT_Z16 0x00001200
+#define NV40_3D_TEX_FORMAT_FORMAT_A16 0x00001400
+#define NV40_3D_TEX_FORMAT_FORMAT_A16L16 0x00001500
+#define NV40_3D_TEX_FORMAT_FORMAT_HILO8 0x00001800
+#define NV40_3D_TEX_FORMAT_FORMAT_RGBA16F 0x00001a00
+#define NV40_3D_TEX_FORMAT_FORMAT_RGBA32F 0x00001b00
+#define NV40_3D_TEX_FORMAT_LINEAR 0x00002000
+#define NV40_3D_TEX_FORMAT_RECT 0x00004000
+#define NV40_3D_TEX_FORMAT_MIPMAP_COUNT__MASK 0x000f0000
+#define NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT 16
+#define NV30_3D_TEX_FORMAT_MIPMAP 0x00080000
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_U__MASK 0x00f00000
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT 20
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_V__MASK 0x0f000000
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT 24
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_W__MASK 0xf0000000
+#define NV30_3D_TEX_FORMAT_BASE_SIZE_W__SHIFT 28
+
+#define NV30_3D_TEX_WRAP(i0) (0x00001a08 + 0x20*(i0))
+#define NV30_3D_TEX_WRAP__ESIZE 0x00000020
+#define NV30_3D_TEX_WRAP__LEN 0x00000008
+#define NV30_3D_TEX_WRAP_S__MASK 0x000000ff
+#define NV30_3D_TEX_WRAP_S__SHIFT 0
+#define NV30_3D_TEX_WRAP_S_REPEAT 0x00000001
+#define NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT 0x00000002
+#define NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE 0x00000003
+#define NV30_3D_TEX_WRAP_S_CLAMP_TO_BORDER 0x00000004
+#define NV30_3D_TEX_WRAP_S_CLAMP 0x00000005
+#define NV40_3D_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE 0x00000006
+#define NV40_3D_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER 0x00000007
+#define NV40_3D_TEX_WRAP_S_MIRROR_CLAMP 0x00000008
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION__MASK 0x00000070
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION__SHIFT 4
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF 0x00000000
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_QUALITY 0x00000020
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_PERFORMANCE 0x00000030
+#define NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_HIGH_PERFORMANCE 0x00000070
+#define NV30_3D_TEX_WRAP_T__MASK 0x00000f00
+#define NV30_3D_TEX_WRAP_T__SHIFT 8
+#define NV30_3D_TEX_WRAP_T_REPEAT 0x00000100
+#define NV30_3D_TEX_WRAP_T_MIRRORED_REPEAT 0x00000200
+#define NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE 0x00000300
+#define NV30_3D_TEX_WRAP_T_CLAMP_TO_BORDER 0x00000400
+#define NV30_3D_TEX_WRAP_T_CLAMP 0x00000500
+#define NV40_3D_TEX_WRAP_T_MIRROR_CLAMP_TO_EDGE 0x00000600
+#define NV40_3D_TEX_WRAP_T_MIRROR_CLAMP_TO_BORDER 0x00000700
+#define NV40_3D_TEX_WRAP_T_MIRROR_CLAMP 0x00000800
+#define NV30_3D_TEX_WRAP_EXPAND_NORMAL 0x0000f000
+#define NV30_3D_TEX_WRAP_R__MASK 0x000f0000
+#define NV30_3D_TEX_WRAP_R__SHIFT 16
+#define NV30_3D_TEX_WRAP_R_REPEAT 0x00010000
+#define NV30_3D_TEX_WRAP_R_MIRRORED_REPEAT 0x00020000
+#define NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE 0x00030000
+#define NV30_3D_TEX_WRAP_R_CLAMP_TO_BORDER 0x00040000
+#define NV30_3D_TEX_WRAP_R_CLAMP 0x00050000
+#define NV40_3D_TEX_WRAP_R_MIRROR_CLAMP_TO_EDGE 0x00060000
+#define NV40_3D_TEX_WRAP_R_MIRROR_CLAMP_TO_BORDER 0x00070000
+#define NV40_3D_TEX_WRAP_R_MIRROR_CLAMP 0x00080000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER__MASK 0x00f00000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER__SHIFT 20
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER_NONE 0x00000000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER_RED 0x00100000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER_GREEN 0x00200000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER_BLUE 0x00400000
+#define NV40_3D_TEX_WRAP_GAMMA_DECREASE_FILTER_ALL 0x00f00000
+#define NV30_3D_TEX_WRAP_RCOMP__MASK 0xf0000000
+#define NV30_3D_TEX_WRAP_RCOMP__SHIFT 28
+#define NV30_3D_TEX_WRAP_RCOMP_NEVER 0x00000000
+#define NV30_3D_TEX_WRAP_RCOMP_GREATER 0x10000000
+#define NV30_3D_TEX_WRAP_RCOMP_EQUAL 0x20000000
+#define NV30_3D_TEX_WRAP_RCOMP_GEQUAL 0x30000000
+#define NV30_3D_TEX_WRAP_RCOMP_LESS 0x40000000
+#define NV30_3D_TEX_WRAP_RCOMP_NOTEQUAL 0x50000000
+#define NV30_3D_TEX_WRAP_RCOMP_LEQUAL 0x60000000
+#define NV30_3D_TEX_WRAP_RCOMP_ALWAYS 0x70000000
+
+#define NV30_3D_TEX_ENABLE(i0) (0x00001a0c + 0x20*(i0))
+#define NV30_3D_TEX_ENABLE__ESIZE 0x00000020
+#define NV30_3D_TEX_ENABLE__LEN 0x00000008
+#define NV30_3D_TEX_ENABLE_ANISO__MASK 0x00000030
+#define NV30_3D_TEX_ENABLE_ANISO__SHIFT 4
+#define NV30_3D_TEX_ENABLE_ANISO_NONE 0x00000000
+#define NV30_3D_TEX_ENABLE_ANISO_2X 0x00000010
+#define NV30_3D_TEX_ENABLE_ANISO_4X 0x00000020
+#define NV30_3D_TEX_ENABLE_ANISO_8X 0x00000030
+#define NV40_3D_TEX_ENABLE_ANISO__MASK 0x000000f0
+#define NV40_3D_TEX_ENABLE_ANISO__SHIFT 4
+#define NV40_3D_TEX_ENABLE_ANISO_NONE 0x00000000
+#define NV40_3D_TEX_ENABLE_ANISO_2X 0x00000010
+#define NV40_3D_TEX_ENABLE_ANISO_4X 0x00000020
+#define NV40_3D_TEX_ENABLE_ANISO_6X 0x00000030
+#define NV40_3D_TEX_ENABLE_ANISO_8X 0x00000040
+#define NV40_3D_TEX_ENABLE_ANISO_10X 0x00000050
+#define NV40_3D_TEX_ENABLE_ANISO_12X 0x00000060
+#define NV40_3D_TEX_ENABLE_ANISO_16X 0x00000070
+#define NV30_3D_TEX_ENABLE_MIPMAP_MAX_LOD__MASK 0x0003c000
+#define NV30_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT 14
+#define NV40_3D_TEX_ENABLE_MIPMAP_MAX_LOD__MASK 0x00038000
+#define NV40_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT 15
+#define NV30_3D_TEX_ENABLE_MIPMAP_MIN_LOD__MASK 0x3c000000
+#define NV30_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT 26
+#define NV40_3D_TEX_ENABLE_MIPMAP_MIN_LOD__MASK 0x38000000
+#define NV40_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT 27
+#define NV30_3D_TEX_ENABLE_ENABLE 0x40000000
+#define NV40_3D_TEX_ENABLE_ENABLE 0x80000000
+
+#define NV30_3D_TEX_SWIZZLE(i0) (0x00001a10 + 0x20*(i0))
+#define NV30_3D_TEX_SWIZZLE__ESIZE 0x00000020
+#define NV30_3D_TEX_SWIZZLE__LEN 0x00000008
+#define NV30_3D_TEX_SWIZZLE_S1_W__MASK 0x00000003
+#define NV30_3D_TEX_SWIZZLE_S1_W__SHIFT 0
+#define NV30_3D_TEX_SWIZZLE_S1_W_W 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S1_W_Z 0x00000001
+#define NV30_3D_TEX_SWIZZLE_S1_W_Y 0x00000002
+#define NV30_3D_TEX_SWIZZLE_S1_W_X 0x00000003
+#define NV30_3D_TEX_SWIZZLE_S1_Z__MASK 0x0000000c
+#define NV30_3D_TEX_SWIZZLE_S1_Z__SHIFT 2
+#define NV30_3D_TEX_SWIZZLE_S1_Z_W 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S1_Z_Z 0x00000004
+#define NV30_3D_TEX_SWIZZLE_S1_Z_Y 0x00000008
+#define NV30_3D_TEX_SWIZZLE_S1_Z_X 0x0000000c
+#define NV30_3D_TEX_SWIZZLE_S1_Y__MASK 0x00000030
+#define NV30_3D_TEX_SWIZZLE_S1_Y__SHIFT 4
+#define NV30_3D_TEX_SWIZZLE_S1_Y_W 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S1_Y_Z 0x00000010
+#define NV30_3D_TEX_SWIZZLE_S1_Y_Y 0x00000020
+#define NV30_3D_TEX_SWIZZLE_S1_Y_X 0x00000030
+#define NV30_3D_TEX_SWIZZLE_S1_X__MASK 0x000000c0
+#define NV30_3D_TEX_SWIZZLE_S1_X__SHIFT 6
+#define NV30_3D_TEX_SWIZZLE_S1_X_W 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S1_X_Z 0x00000040
+#define NV30_3D_TEX_SWIZZLE_S1_X_Y 0x00000080
+#define NV30_3D_TEX_SWIZZLE_S1_X_X 0x000000c0
+#define NV30_3D_TEX_SWIZZLE_S0_W__MASK 0x00000300
+#define NV30_3D_TEX_SWIZZLE_S0_W__SHIFT 8
+#define NV30_3D_TEX_SWIZZLE_S0_W_ZERO 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S0_W_ONE 0x00000100
+#define NV30_3D_TEX_SWIZZLE_S0_W_S1 0x00000200
+#define NV30_3D_TEX_SWIZZLE_S0_Z__MASK 0x00000c00
+#define NV30_3D_TEX_SWIZZLE_S0_Z__SHIFT 10
+#define NV30_3D_TEX_SWIZZLE_S0_Z_ZERO 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S0_Z_ONE 0x00000400
+#define NV30_3D_TEX_SWIZZLE_S0_Z_S1 0x00000800
+#define NV30_3D_TEX_SWIZZLE_S0_Y__MASK 0x00003000
+#define NV30_3D_TEX_SWIZZLE_S0_Y__SHIFT 12
+#define NV30_3D_TEX_SWIZZLE_S0_Y_ZERO 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S0_Y_ONE 0x00001000
+#define NV30_3D_TEX_SWIZZLE_S0_Y_S1 0x00002000
+#define NV30_3D_TEX_SWIZZLE_S0_X__MASK 0x0000c000
+#define NV30_3D_TEX_SWIZZLE_S0_X__SHIFT 14
+#define NV30_3D_TEX_SWIZZLE_S0_X_ZERO 0x00000000
+#define NV30_3D_TEX_SWIZZLE_S0_X_ONE 0x00004000
+#define NV30_3D_TEX_SWIZZLE_S0_X_S1 0x00008000
+#define NV30_3D_TEX_SWIZZLE_RECT_PITCH__MASK 0xffff0000
+#define NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT 16
+
+#define NV30_3D_TEX_FILTER(i0) (0x00001a14 + 0x20*(i0))
+#define NV30_3D_TEX_FILTER__ESIZE 0x00000020
+#define NV30_3D_TEX_FILTER__LEN 0x00000008
+#define NV30_3D_TEX_FILTER_LOD_BIAS__MASK 0x00000f00
+#define NV30_3D_TEX_FILTER_LOD_BIAS__SHIFT 8
+#define NV30_3D_TEX_FILTER_MIN__MASK 0x000f0000
+#define NV30_3D_TEX_FILTER_MIN__SHIFT 16
+#define NV30_3D_TEX_FILTER_MIN_NEAREST 0x00010000
+#define NV30_3D_TEX_FILTER_MIN_LINEAR 0x00020000
+#define NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST 0x00030000
+#define NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST 0x00040000
+#define NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR 0x00050000
+#define NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR 0x00060000
+#define NV30_3D_TEX_FILTER_MAG__MASK 0x0f000000
+#define NV30_3D_TEX_FILTER_MAG__SHIFT 24
+#define NV30_3D_TEX_FILTER_MAG_NEAREST 0x01000000
+#define NV30_3D_TEX_FILTER_MAG_LINEAR 0x02000000
+#define NV30_3D_TEX_FILTER_SIGNED_BLUE 0x10000000
+#define NV30_3D_TEX_FILTER_SIGNED_GREEN 0x20000000
+#define NV30_3D_TEX_FILTER_SIGNED_RED 0x40000000
+#define NV30_3D_TEX_FILTER_SIGNED_ALPHA 0x80000000
+
+#define NV30_3D_TEX_NPOT_SIZE(i0) (0x00001a18 + 0x20*(i0))
+#define NV30_3D_TEX_NPOT_SIZE__ESIZE 0x00000020
+#define NV30_3D_TEX_NPOT_SIZE__LEN 0x00000008
+#define NV30_3D_TEX_NPOT_SIZE_H__MASK 0x0000ffff
+#define NV30_3D_TEX_NPOT_SIZE_H__SHIFT 0
+#define NV30_3D_TEX_NPOT_SIZE_W__MASK 0xffff0000
+#define NV30_3D_TEX_NPOT_SIZE_W__SHIFT 16
+
+#define NV30_3D_TEX_BORDER_COLOR(i0) (0x00001a1c + 0x20*(i0))
+#define NV30_3D_TEX_BORDER_COLOR__ESIZE 0x00000020
+#define NV30_3D_TEX_BORDER_COLOR__LEN 0x00000008
+#define NV30_3D_TEX_BORDER_COLOR_B__MASK 0x000000ff
+#define NV30_3D_TEX_BORDER_COLOR_B__SHIFT 0
+#define NV30_3D_TEX_BORDER_COLOR_G__MASK 0x0000ff00
+#define NV30_3D_TEX_BORDER_COLOR_G__SHIFT 8
+#define NV30_3D_TEX_BORDER_COLOR_R__MASK 0x00ff0000
+#define NV30_3D_TEX_BORDER_COLOR_R__SHIFT 16
+#define NV30_3D_TEX_BORDER_COLOR_A__MASK 0xff000000
+#define NV30_3D_TEX_BORDER_COLOR_A__SHIFT 24
+
+#define NV30_3D_VTX_ATTR_4F(i0) (0x00001c00 + 0x10*(i0))
+#define NV30_3D_VTX_ATTR_4F__ESIZE 0x00000010
+#define NV30_3D_VTX_ATTR_4F__LEN 0x00000010
+
+
+#define NV30_3D_VTX_ATTR_4F_X(i0) (0x00001c00 + 0x10*(i0))
+
+#define NV30_3D_VTX_ATTR_4F_Y(i0) (0x00001c04 + 0x10*(i0))
+
+#define NV30_3D_VTX_ATTR_4F_Z(i0) (0x00001c08 + 0x10*(i0))
+
+#define NV30_3D_VTX_ATTR_4F_W(i0) (0x00001c0c + 0x10*(i0))
+
+#define NV30_3D_FP_CONTROL 0x00001d60
+#define NV30_3D_FP_CONTROL_USED_REGS_MINUS1_DIV2__MASK 0x0000000f
+#define NV30_3D_FP_CONTROL_USED_REGS_MINUS1_DIV2__SHIFT 0
+#define NV30_3D_FP_CONTROL_USES_KIL 0x00000080
+#define NV40_3D_FP_CONTROL_KIL 0x00000080
+#define NV40_3D_FP_CONTROL_TEMP_COUNT__MASK 0xff000000
+#define NV40_3D_FP_CONTROL_TEMP_COUNT__SHIFT 24
+
+#define NV30_3D_FENCE_OFFSET 0x00001d6c
+
+#define NV30_3D_FENCE_VALUE 0x00001d70
+
+#define NV30_3D_DEPTH_CONTROL 0x00001d78
+#define NV30_3D_DEPTH_CONTROL_CLAMP 0x000000f0
+
+#define NV30_3D_MULTISAMPLE_CONTROL 0x00001d7c
+#define NV30_3D_MULTISAMPLE_CONTROL_ENABLE 0x00000001
+#define NV30_3D_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_COVERAGE 0x00000010
+#define NV30_3D_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_ONE 0x00000100
+#define NV30_3D_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE__MASK 0xffff0000
+#define NV30_3D_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE__SHIFT 16
+
+#define NV30_3D_COORD_CONVENTIONS 0x00001d88
+#define NV30_3D_COORD_CONVENTIONS_HEIGHT__MASK 0x00000fff
+#define NV30_3D_COORD_CONVENTIONS_HEIGHT__SHIFT 0
+#define NV30_3D_COORD_CONVENTIONS_ORIGIN__MASK 0x00001000
+#define NV30_3D_COORD_CONVENTIONS_ORIGIN__SHIFT 12
+#define NV30_3D_COORD_CONVENTIONS_ORIGIN_NORMAL 0x00000000
+#define NV30_3D_COORD_CONVENTIONS_ORIGIN_INVERTED 0x00001000
+#define NV30_3D_COORD_CONVENTIONS_CENTER__MASK 0x00010000
+#define NV30_3D_COORD_CONVENTIONS_CENTER__SHIFT 16
+#define NV30_3D_COORD_CONVENTIONS_CENTER_HALF_INTEGER 0x00000000
+#define NV30_3D_COORD_CONVENTIONS_CENTER_INTEGER 0x00010000
+
+#define NV30_3D_CLEAR_DEPTH_VALUE 0x00001d8c
+
+#define NV30_3D_CLEAR_COLOR_VALUE 0x00001d90
+#define NV30_3D_CLEAR_COLOR_VALUE_B__MASK 0x000000ff
+#define NV30_3D_CLEAR_COLOR_VALUE_B__SHIFT 0
+#define NV30_3D_CLEAR_COLOR_VALUE_G__MASK 0x0000ff00
+#define NV30_3D_CLEAR_COLOR_VALUE_G__SHIFT 8
+#define NV30_3D_CLEAR_COLOR_VALUE_R__MASK 0x00ff0000
+#define NV30_3D_CLEAR_COLOR_VALUE_R__SHIFT 16
+#define NV30_3D_CLEAR_COLOR_VALUE_A__MASK 0xff000000
+#define NV30_3D_CLEAR_COLOR_VALUE_A__SHIFT 24
+
+#define NV30_3D_CLEAR_BUFFERS 0x00001d94
+#define NV30_3D_CLEAR_BUFFERS_DEPTH 0x00000001
+#define NV30_3D_CLEAR_BUFFERS_STENCIL 0x00000002
+#define NV30_3D_CLEAR_BUFFERS_COLOR_R 0x00000010
+#define NV30_3D_CLEAR_BUFFERS_COLOR_G 0x00000020
+#define NV30_3D_CLEAR_BUFFERS_COLOR_B 0x00000040
+#define NV30_3D_CLEAR_BUFFERS_COLOR_A 0x00000080
+
+#define NV30_3D_PRIMITIVE_RESTART_ENABLE 0x00001dac
+
+#define NV30_3D_PRIMITIVE_RESTART_INDEX 0x00001db0
+
+#define NV30_3D_LINE_STIPPLE_ENABLE 0x00001db4
+
+#define NV30_3D_LINE_STIPPLE_PATTERN 0x00001db8
+#define NV30_3D_LINE_STIPPLE_PATTERN_FACTOR__MASK 0x0000ffff
+#define NV30_3D_LINE_STIPPLE_PATTERN_FACTOR__SHIFT 0
+#define NV30_3D_LINE_STIPPLE_PATTERN_PATTERN__MASK 0xffff0000
+#define NV30_3D_LINE_STIPPLE_PATTERN_PATTERN__SHIFT 16
+
+#define NV30_3D_BACK_MATERIAL_SHININESS(i0) (0x00001e20 + 0x4*(i0))
+#define NV30_3D_BACK_MATERIAL_SHININESS__ESIZE 0x00000004
+#define NV30_3D_BACK_MATERIAL_SHININESS__LEN 0x00000006
+
+#define NV30_3D_VTX_ATTR_1F(i0) (0x00001e40 + 0x4*(i0))
+#define NV30_3D_VTX_ATTR_1F__ESIZE 0x00000004
+#define NV30_3D_VTX_ATTR_1F__LEN 0x00000010
+
+#define NV30_3D_ENGINE 0x00001e94
+#define NV30_3D_ENGINE_FP 0x00000001
+#define NV30_3D_ENGINE_VP 0x00000002
+#define NV30_3D_ENGINE_FIXED 0x00000004
+
+#define NV30_3D_VP_UPLOAD_FROM_ID 0x00001e9c
+
+#define NV30_3D_VP_START_FROM_ID 0x00001ea0
+
+#define NV30_3D_POINT_PARAMETERS(i0) (0x00001ec0 + 0x4*(i0))
+#define NV30_3D_POINT_PARAMETERS__ESIZE 0x00000004
+#define NV30_3D_POINT_PARAMETERS__LEN 0x00000008
+
+#define NV30_3D_POINT_SIZE 0x00001ee0
+
+#define NV30_3D_POINT_PARAMETERS_ENABLE 0x00001ee4
+
+#define NV30_3D_POINT_SPRITE 0x00001ee8
+#define NV30_3D_POINT_SPRITE_ENABLE 0x00000001
+#define NV30_3D_POINT_SPRITE_R_MODE__MASK 0x00000006
+#define NV30_3D_POINT_SPRITE_R_MODE__SHIFT 1
+#define NV30_3D_POINT_SPRITE_R_MODE_ZERO 0x00000000
+#define NV30_3D_POINT_SPRITE_R_MODE_R 0x00000002
+#define NV30_3D_POINT_SPRITE_R_MODE_S 0x00000004
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_0 0x00000100
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_1 0x00000200
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_2 0x00000400
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_3 0x00000800
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_4 0x00001000
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_5 0x00002000
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_6 0x00004000
+#define NV30_3D_POINT_SPRITE_COORD_REPLACE_7 0x00008000
+
+#define NV30_3D_VP_UPLOAD_CONST_ID 0x00001efc
+
+#define NV30_3D_VP_UPLOAD_CONST(i0) (0x00001f00 + 0x10*(i0))
+#define NV30_3D_VP_UPLOAD_CONST__ESIZE 0x00000010
+#define NV30_3D_VP_UPLOAD_CONST__LEN 0x00000004
+
+
+#define NV30_3D_VP_UPLOAD_CONST_X(i0) (0x00001f00 + 0x10*(i0))
+
+#define NV30_3D_VP_UPLOAD_CONST_Y(i0) (0x00001f04 + 0x10*(i0))
+
+#define NV30_3D_VP_UPLOAD_CONST_Z(i0) (0x00001f08 + 0x10*(i0))
+
+#define NV30_3D_VP_UPLOAD_CONST_W(i0) (0x00001f0c + 0x10*(i0))
+
+#define NV30_3D_UNK1F80(i0) (0x00001f80 + 0x4*(i0))
+#define NV30_3D_UNK1F80__ESIZE 0x00000004
+#define NV30_3D_UNK1F80__LEN 0x00000010
+
+#define NV40_3D_TEX_CACHE_CTL 0x00001fd8
+
+#define NV40_3D_VP_ATTRIB_EN 0x00001ff0
+
+#define NV40_3D_VP_RESULT_EN 0x00001ff4
+
+
+#endif /* _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV30_40_3D_XML */
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_clear.c b/src/gallium/drivers/nouveau/nv30/nv30_clear.c
new file mode 100644
index 00000000000..5317e892b25
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_clear.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "pipe/p_defines.h"
+#include "util/u_pack_color.h"
+
+#include "nouveau_gldefs.h"
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+static INLINE uint32_t
+pack_rgba(enum pipe_format format, const float *rgba)
+{
+ union util_color uc;
+ util_pack_color(rgba, format, &uc);
+ return uc.ui;
+}
+
+static INLINE uint32_t
+pack_zeta(enum pipe_format format, double depth, unsigned stencil)
+{
+ uint32_t zuint = (uint32_t)(depth * 4294967295.0);
+ if (format != PIPE_FORMAT_Z16_UNORM)
+ return (zuint & 0xffffff00) | (stencil & 0xff);
+ return zuint >> 16;
+}
+
+static void
+nv30_clear(struct pipe_context *pipe, unsigned buffers,
+ const union pipe_color_union *color, double depth, unsigned stencil)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+ uint32_t colr = 0, zeta = 0, mode = 0;
+
+ if (!nv30_state_validate(nv30, TRUE))
+ return;
+
+ if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
+ colr = pack_rgba(fb->cbufs[0]->format, color->f);
+ mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R |
+ NV30_3D_CLEAR_BUFFERS_COLOR_G |
+ NV30_3D_CLEAR_BUFFERS_COLOR_B |
+ NV30_3D_CLEAR_BUFFERS_COLOR_A;
+ }
+
+ if (fb->zsbuf) {
+ zeta = pack_zeta(fb->zsbuf->format, depth, stencil);
+ if (buffers & PIPE_CLEAR_DEPTH)
+ mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
+ if (buffers & PIPE_CLEAR_STENCIL)
+ mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
+ }
+
+ /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */
+ if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
+ PUSH_DATA (push, zeta);
+ PUSH_DATA (push, colr);
+ PUSH_DATA (push, mode);
+ }
+
+ BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3);
+ PUSH_DATA (push, zeta);
+ PUSH_DATA (push, colr);
+ PUSH_DATA (push, mode);
+
+ nv30_state_release(nv30);
+}
+
+static void
+nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
+ const union pipe_color_union *color,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_surface *sf = nv30_surface(ps);
+ struct nv30_miptree *mt = nv30_miptree(ps->texture);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nouveau_pushbuf_refn refn;
+ uint32_t rt_format;
+
+ rt_format = nv30_format(pipe->screen, ps->format)->hw;
+ if (util_format_get_blocksize(ps->format) == 4)
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
+
+ if (nv30_miptree(ps->texture)->swizzled) {
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ rt_format |= util_logbase2(sf->width) << 16;
+ rt_format |= util_logbase2(sf->height) << 24;
+ } else {
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ }
+
+ refn.bo = mt->base.bo;
+ refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
+ if (nouveau_pushbuf_space(push, 16, 1, 0) ||
+ nouveau_pushbuf_refn (push, &refn, 1))
+ return;
+
+ BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
+ PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
+ BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
+ PUSH_DATA (push, sf->width << 16);
+ PUSH_DATA (push, sf->height << 16);
+ PUSH_DATA (push, rt_format);
+ BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
+ if (eng3d->oclass < NV40_3D_CLASS)
+ PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
+ else
+ PUSH_DATA (push, sf->pitch);
+ PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
+ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
+ PUSH_DATA (push, (w << 16) | x);
+ PUSH_DATA (push, (h << 16) | y);
+
+ BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
+ PUSH_DATA (push, pack_rgba(ps->format, color->f));
+ PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
+ NV30_3D_CLEAR_BUFFERS_COLOR_G |
+ NV30_3D_CLEAR_BUFFERS_COLOR_B |
+ NV30_3D_CLEAR_BUFFERS_COLOR_A);
+
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
+}
+
+static void
+nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
+ unsigned buffers, double depth, unsigned stencil,
+ unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_surface *sf = nv30_surface(ps);
+ struct nv30_miptree *mt = nv30_miptree(ps->texture);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nouveau_pushbuf_refn refn;
+ uint32_t rt_format, mode = 0;
+
+ rt_format = nv30_format(pipe->screen, ps->format)->hw;
+ if (util_format_get_blocksize(ps->format) == 4)
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
+
+ if (nv30_miptree(ps->texture)->swizzled) {
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ rt_format |= util_logbase2(sf->width) << 16;
+ rt_format |= util_logbase2(sf->height) << 24;
+ } else {
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTH)
+ mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
+ if (buffers & PIPE_CLEAR_STENCIL)
+ mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;
+
+ refn.bo = mt->base.bo;
+ refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
+ if (nouveau_pushbuf_space(push, 32, 1, 0) ||
+ nouveau_pushbuf_refn (push, &refn, 1))
+ return;
+
+ BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
+ PUSH_DATA (push, sf->width << 16);
+ PUSH_DATA (push, sf->height << 16);
+ PUSH_DATA (push, rt_format);
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
+ PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
+ } else {
+ BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
+ PUSH_DATA (push, sf->pitch);
+ }
+ BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
+ PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
+ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
+ PUSH_DATA (push, (w << 16) | x);
+ PUSH_DATA (push, (h << 16) | y);
+
+ BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
+ PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
+ BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
+ PUSH_DATA (push, mode);
+
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
+}
+
+void
+nv30_clear_init(struct pipe_context *pipe)
+{
+ pipe->clear = nv30_clear;
+ pipe->clear_render_target = nv30_clear_render_target;
+ pipe->clear_depth_stencil = nv30_clear_depth_stencil;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c
new file mode 100644
index 00000000000..2146d2726b4
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "draw/draw_context.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+
+#include "nouveau_fence.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_transfer.h"
+#include "nv30/nv30_state.h"
+
+static void
+nv30_context_kick_notify(struct nouveau_pushbuf *push)
+{
+ struct nouveau_screen *screen;
+ struct nv30_context *nv30;
+
+ if (!push->user_priv)
+ return;
+ nv30 = container_of(push->user_priv, nv30, bufctx);
+ screen = &nv30->screen->base;
+
+ nouveau_fence_next(screen);
+ nouveau_fence_update(screen, TRUE);
+
+ if (push->bufctx) {
+ struct nouveau_bufref *bref;
+ LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) {
+ struct nv04_resource *res = bref->priv;
+ if (res && res->mm) {
+ nouveau_fence_ref(screen->fence.current, &res->fence);
+
+ if (bref->flags & NOUVEAU_BO_RD)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
+
+ if (bref->flags & NOUVEAU_BO_WR) {
+ nouveau_fence_ref(screen->fence.current, &res->fence_wr);
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
+ NOUVEAU_BUFFER_STATUS_DIRTY;
+ }
+ }
+ }
+ }
+}
+
+static void
+nv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence,
+ unsigned flags)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ if (fence)
+ nouveau_fence_ref(nv30->screen->base.fence.current,
+ (struct nouveau_fence **)fence);
+
+ PUSH_KICK(push);
+
+ nouveau_context_update_frame_stats(&nv30->base);
+}
+
+static int
+nv30_invalidate_resource_storage(struct nouveau_context *nv,
+ struct pipe_resource *res,
+ int ref)
+{
+ struct nv30_context *nv30 = nv30_context(&nv->pipe);
+ unsigned i;
+
+ if (res->bind & PIPE_BIND_RENDER_TARGET) {
+ for (i = 0; i < nv30->framebuffer.nr_cbufs; ++i) {
+ if (nv30->framebuffer.cbufs[i] &&
+ nv30->framebuffer.cbufs[i]->texture == res) {
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER;
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
+ if (!--ref)
+ return ref;
+ }
+ }
+ }
+ if (res->bind & PIPE_BIND_DEPTH_STENCIL) {
+ if (nv30->framebuffer.zsbuf &&
+ nv30->framebuffer.zsbuf->texture == res) {
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER;
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
+ if (!--ref)
+ return ref;
+ }
+ }
+
+ if (res->bind & PIPE_BIND_VERTEX_BUFFER) {
+ for (i = 0; i < nv30->num_vtxbufs; ++i) {
+ if (nv30->vtxbuf[i].buffer == res) {
+ nv30->dirty |= NV30_NEW_ARRAYS;
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
+ if (!--ref)
+ return ref;
+ }
+ }
+ }
+ if (res->bind & PIPE_BIND_INDEX_BUFFER) {
+ if (nv30->idxbuf.buffer == res) {
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_IDXBUF);
+ if (!--ref)
+ return ref;
+ }
+ }
+
+ if (res->bind & PIPE_BIND_SAMPLER_VIEW) {
+ for (i = 0; i < nv30->fragprog.num_textures; ++i) {
+ if (nv30->fragprog.textures[i] &&
+ nv30->fragprog.textures[i]->texture == res) {
+ nv30->dirty |= NV30_NEW_FRAGTEX;
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
+ if (!--ref)
+ return ref;
+ }
+ }
+ for (i = 0; i < nv30->vertprog.num_textures; ++i) {
+ if (nv30->vertprog.textures[i] &&
+ nv30->vertprog.textures[i]->texture == res) {
+ nv30->dirty |= NV30_NEW_VERTTEX;
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
+ if (!--ref)
+ return ref;
+ }
+ }
+ }
+
+ return ref;
+}
+
+static void
+nv30_context_destroy(struct pipe_context *pipe)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ if (nv30->blitter)
+ util_blitter_destroy(nv30->blitter);
+
+ if (nv30->draw)
+ draw_destroy(nv30->draw);
+
+ nouveau_bufctx_del(&nv30->bufctx);
+
+ if (nv30->screen->cur_ctx == nv30)
+ nv30->screen->cur_ctx = NULL;
+
+ nouveau_context_destroy(&nv30->base);
+}
+
+#define FAIL_CONTEXT_INIT(str, err) \
+ do { \
+ NOUVEAU_ERR(str, err); \
+ nv30_context_destroy(pipe); \
+ return NULL; \
+ } while(0)
+
+struct pipe_context *
+nv30_context_create(struct pipe_screen *pscreen, void *priv)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context);
+ struct nouveau_pushbuf *push;
+ struct pipe_context *pipe;
+ int ret;
+
+ if (!nv30)
+ return NULL;
+
+ nv30->screen = screen;
+ nv30->base.screen = &screen->base;
+ nv30->base.copy_data = nv30_transfer_copy_data;
+
+ pipe = &nv30->base.pipe;
+ pipe->screen = pscreen;
+ pipe->priv = priv;
+ pipe->destroy = nv30_context_destroy;
+ pipe->flush = nv30_context_flush;
+
+ /*XXX: *cough* per-context client */
+ nv30->base.client = screen->base.client;
+
+ /*XXX: *cough* per-context pushbufs */
+ push = screen->base.pushbuf;
+ nv30->base.pushbuf = push;
+ nv30->base.pushbuf->user_priv = &nv30->bufctx; /* hack at validate time */
+ nv30->base.pushbuf->rsvd_kick = 16; /* hack in screen before first space */
+ nv30->base.pushbuf->kick_notify = nv30_context_kick_notify;
+
+ nv30->base.invalidate_resource_storage = nv30_invalidate_resource_storage;
+
+ ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx);
+ if (ret) {
+ nv30_context_destroy(pipe);
+ return NULL;
+ }
+
+ /*XXX: make configurable with performance vs quality, these defaults
+ * match the binary driver's defaults
+ */
+ if (screen->eng3d->oclass < NV40_3D_CLASS)
+ nv30->config.filter = 0x00000004;
+ else
+ nv30->config.filter = 0x00002dc4;
+
+ nv30->config.aniso = NV40_3D_TEX_WRAP_ANISO_MIP_FILTER_OPTIMIZATION_OFF;
+
+ if (debug_get_bool_option("NV30_SWTNL", FALSE))
+ nv30->draw_flags |= NV30_NEW_SWTNL;
+
+ /*XXX: nvfx... */
+ nv30->is_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
+ nv30->use_nv4x = (screen->eng3d->oclass >= NV40_3D_CLASS) ? ~0 : 0;
+ nv30->render_mode = HW;
+
+ nv30->sample_mask = 0xffff;
+ nv30_vbo_init(pipe);
+ nv30_query_init(pipe);
+ nv30_state_init(pipe);
+ nv30_resource_init(pipe);
+ nv30_clear_init(pipe);
+ nv30_fragprog_init(pipe);
+ nv30_vertprog_init(pipe);
+ nv30_texture_init(pipe);
+ nv30_fragtex_init(pipe);
+ nv40_verttex_init(pipe);
+ nv30_draw_init(pipe);
+
+ nv30->blitter = util_blitter_create(pipe);
+ if (!nv30->blitter) {
+ nv30_context_destroy(pipe);
+ return NULL;
+ }
+
+ nouveau_context_init_vdec(&nv30->base);
+
+ return pipe;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.h b/src/gallium/drivers/nouveau/nv30/nv30_context.h
new file mode 100644
index 00000000000..12ae0c71e4f
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.h
@@ -0,0 +1,237 @@
+#ifndef __NV30_CONTEXT_H__
+#define __NV30_CONTEXT_H__
+
+#include "pipe/p_format.h"
+#include "util/u_blitter.h"
+
+#include "nv30/nv30_screen.h"
+#include "nv30/nv30_state.h"
+
+#include "nouveau_context.h"
+
+#define BUFCTX_FB 0
+#define BUFCTX_VTXTMP 1
+#define BUFCTX_VTXBUF 2
+#define BUFCTX_IDXBUF 3
+#define BUFCTX_VERTTEX(n) (4 + (n))
+#define BUFCTX_FRAGPROG 8
+#define BUFCTX_FRAGTEX(n) (9 + (n))
+
+#define NV30_NEW_BLEND (1 << 0)
+#define NV30_NEW_RASTERIZER (1 << 1)
+#define NV30_NEW_ZSA (1 << 2)
+#define NV30_NEW_VERTPROG (1 << 3)
+#define NV30_NEW_VERTCONST (1 << 4)
+#define NV30_NEW_FRAGPROG (1 << 5)
+#define NV30_NEW_FRAGCONST (1 << 6)
+#define NV30_NEW_BLEND_COLOUR (1 << 7)
+#define NV30_NEW_STENCIL_REF (1 << 8)
+#define NV30_NEW_CLIP (1 << 9)
+#define NV30_NEW_SAMPLE_MASK (1 << 10)
+#define NV30_NEW_FRAMEBUFFER (1 << 11)
+#define NV30_NEW_STIPPLE (1 << 12)
+#define NV30_NEW_SCISSOR (1 << 13)
+#define NV30_NEW_VIEWPORT (1 << 14)
+#define NV30_NEW_ARRAYS (1 << 15)
+#define NV30_NEW_VERTEX (1 << 16)
+#define NV30_NEW_CONSTBUF (1 << 17)
+#define NV30_NEW_FRAGTEX (1 << 18)
+#define NV30_NEW_VERTTEX (1 << 19)
+#define NV30_NEW_SWTNL (1 << 31)
+#define NV30_NEW_ALL 0x000fffff
+
+struct nv30_context {
+ struct nouveau_context base;
+ struct nv30_screen *screen;
+ struct blitter_context *blitter;
+
+ struct nouveau_bufctx *bufctx;
+
+ struct {
+ unsigned rt_enable;
+ unsigned scissor_off;
+ unsigned num_vtxelts;
+ boolean prim_restart;
+ struct nv30_fragprog *fragprog;
+ } state;
+
+ uint32_t dirty;
+
+ struct draw_context *draw;
+ uint32_t draw_flags;
+ uint32_t draw_dirty;
+
+ struct nv30_blend_stateobj *blend;
+ struct nv30_rasterizer_stateobj *rast;
+ struct nv30_zsa_stateobj *zsa;
+ struct nv30_vertex_stateobj *vertex;
+
+ struct {
+ unsigned filter;
+ unsigned aniso;
+ } config;
+
+ struct {
+ struct nv30_vertprog *program;
+
+ struct pipe_resource *constbuf;
+ unsigned constbuf_nr;
+
+ struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
+ unsigned num_textures;
+ struct nv30_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ unsigned num_samplers;
+ unsigned dirty_samplers;
+ } vertprog;
+
+ struct {
+ struct nv30_fragprog *program;
+
+ struct pipe_resource *constbuf;
+ unsigned constbuf_nr;
+
+ struct pipe_sampler_view *textures[PIPE_MAX_SAMPLERS];
+ unsigned num_textures;
+ struct nv30_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ unsigned num_samplers;
+ unsigned dirty_samplers;
+ } fragprog;
+
+ struct pipe_framebuffer_state framebuffer;
+ struct pipe_blend_color blend_colour;
+ struct pipe_stencil_ref stencil_ref;
+ struct pipe_poly_stipple stipple;
+ struct pipe_scissor_state scissor;
+ struct pipe_viewport_state viewport;
+ struct pipe_clip_state clip;
+
+ unsigned sample_mask;
+
+ struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+ unsigned num_vtxbufs;
+ struct pipe_index_buffer idxbuf;
+ uint32_t vbo_fifo;
+ uint32_t vbo_user;
+ unsigned vbo_min_index;
+ unsigned vbo_max_index;
+ boolean vbo_push_hint;
+
+ struct nouveau_heap *blit_vp;
+ struct pipe_resource *blit_fp;
+
+ /*XXX: nvfx state, DO NOT USE EVER OUTSIDE "STOLEN" NVFX code */
+ unsigned is_nv4x;
+ unsigned use_nv4x;
+ bool hw_pointsprite_control;
+ enum {
+ HW,
+ } render_mode;
+
+ struct pipe_query *render_cond_query;
+ unsigned render_cond_mode;
+ boolean render_cond_cond;
+};
+
+static INLINE struct nv30_context *
+nv30_context(struct pipe_context *pipe)
+{
+ return (struct nv30_context *)pipe;
+}
+
+struct pipe_context *
+nv30_context_create(struct pipe_screen *pscreen, void *priv);
+
+void
+nv30_vbo_init(struct pipe_context *pipe);
+
+void
+nv30_vbo_validate(struct nv30_context *nv30);
+
+void
+nv30_query_init(struct pipe_context *pipe);
+
+void
+nv30_state_init(struct pipe_context *pipe);
+
+void
+nv30_clear_init(struct pipe_context *pipe);
+
+void
+nv30_vertprog_init(struct pipe_context *pipe);
+
+void
+nv30_vertprog_validate(struct nv30_context *nv30);
+
+void
+nv30_fragprog_init(struct pipe_context *pipe);
+
+void
+nv30_fragprog_validate(struct nv30_context *nv30);
+
+void
+nv30_texture_init(struct pipe_context *pipe);
+
+void
+nv30_texture_validate(struct nv30_context *nv30);
+
+void
+nv30_fragtex_init(struct pipe_context *pipe);
+
+void
+nv30_fragtex_validate(struct nv30_context *nv30);
+
+void
+nv40_verttex_init(struct pipe_context *pipe);
+
+void
+nv40_verttex_validate(struct nv30_context *nv30);
+
+void
+nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info);
+
+void
+nv30_draw_init(struct pipe_context *pipe);
+
+void
+nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info);
+
+boolean
+nv30_state_validate(struct nv30_context *nv30, boolean hwtnl);
+
+void
+nv30_state_release(struct nv30_context *nv30);
+
+//XXX: needed to make it build, clean this up!
+void
+_nvfx_fragprog_translate(struct nv30_context *nvfx, struct nv30_fragprog *fp,
+ boolean emulate_sprite_flipping);
+
+boolean
+_nvfx_vertprog_translate(struct nv30_context *nv30, struct nv30_vertprog *vp);
+
+#ifdef NV30_3D_VERTEX_BEGIN_END
+#define NV30_PRIM_GL_CASE(n) \
+ case PIPE_PRIM_##n: return NV30_3D_VERTEX_BEGIN_END_##n
+
+static INLINE unsigned
+nv30_prim_gl(unsigned prim)
+{
+ switch (prim) {
+ NV30_PRIM_GL_CASE(POINTS);
+ NV30_PRIM_GL_CASE(LINES);
+ NV30_PRIM_GL_CASE(LINE_LOOP);
+ NV30_PRIM_GL_CASE(LINE_STRIP);
+ NV30_PRIM_GL_CASE(TRIANGLES);
+ NV30_PRIM_GL_CASE(TRIANGLE_STRIP);
+ NV30_PRIM_GL_CASE(TRIANGLE_FAN);
+ NV30_PRIM_GL_CASE(QUADS);
+ NV30_PRIM_GL_CASE(QUAD_STRIP);
+ NV30_PRIM_GL_CASE(POLYGON);
+ default:
+ return NV30_3D_VERTEX_BEGIN_END_POINTS;
+ break;
+ }
+}
+#endif
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_draw.c b/src/gallium/drivers/nouveau/nv30/nv30_draw.c
new file mode 100644
index 00000000000..3575c3d29fa
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_draw.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pipe.h"
+#include "draw/draw_vbuf.h"
+#include "draw/draw_private.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+struct nv30_render {
+ struct vbuf_render base;
+ struct nv30_context *nv30;
+
+ struct pipe_transfer *transfer;
+ struct pipe_resource *buffer;
+ unsigned offset;
+ unsigned length;
+
+ struct vertex_info vertex_info;
+
+ struct nouveau_heap *vertprog;
+ uint32_t vtxprog[16][4];
+ uint32_t vtxfmt[16];
+ uint32_t vtxptr[16];
+ uint32_t prim;
+};
+
+static INLINE struct nv30_render *
+nv30_render(struct vbuf_render *render)
+{
+ return (struct nv30_render *)render;
+}
+
+static const struct vertex_info *
+nv30_render_get_vertex_info(struct vbuf_render *render)
+{
+ return &nv30_render(render)->vertex_info;
+}
+
+static boolean
+nv30_render_allocate_vertices(struct vbuf_render *render,
+ ushort vertex_size, ushort nr_vertices)
+{
+ struct nv30_render *r = nv30_render(render);
+ struct nv30_context *nv30 = r->nv30;
+
+ r->length = vertex_size * nr_vertices;
+
+ if (r->offset + r->length >= render->max_vertex_buffer_bytes) {
+ pipe_resource_reference(&r->buffer, NULL);
+ r->buffer = pipe_buffer_create(&nv30->screen->base.base,
+ PIPE_BIND_VERTEX_BUFFER, 0,
+ render->max_vertex_buffer_bytes);
+ if (!r->buffer)
+ return FALSE;
+
+ r->offset = 0;
+ }
+
+ return TRUE;
+}
+
+static void *
+nv30_render_map_vertices(struct vbuf_render *render)
+{
+ struct nv30_render *r = nv30_render(render);
+ char *map = pipe_buffer_map(&r->nv30->base.pipe, r->buffer,
+ PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_UNSYNCHRONIZED, &r->transfer);
+ return map + r->offset;
+}
+
+static void
+nv30_render_unmap_vertices(struct vbuf_render *render,
+ ushort min_index, ushort max_index)
+{
+ struct nv30_render *r = nv30_render(render);
+ pipe_buffer_unmap(&r->nv30->base.pipe, r->transfer);
+}
+
+static void
+nv30_render_set_primitive(struct vbuf_render *render, unsigned prim)
+{
+ struct nv30_render *r = nv30_render(render);
+
+ r->prim = nv30_prim_gl(prim);
+}
+
+static void
+nv30_render_draw_elements(struct vbuf_render *render,
+ const ushort *indices, uint count)
+{
+ struct nv30_render *r = nv30_render(render);
+ struct nv30_context *nv30 = r->nv30;
+ struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
+ unsigned i;
+
+ BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
+ for (i = 0; i < r->vertex_info.num_attribs; i++) {
+ PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
+ nv04_resource(r->buffer), r->offset + r->vtxptr[i],
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
+ }
+
+ if (!nv30_state_validate(nv30, FALSE))
+ return;
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, r->prim);
+
+ if (count & 1) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (push, *indices++);
+ }
+
+ count >>= 1;
+ while (count) {
+ unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
+ while (npush--) {
+ PUSH_DATA(push, (indices[1] << 16) | indices[0]);
+ indices += 2;
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ PUSH_RESET(push, BUFCTX_VTXTMP);
+}
+
+static void
+nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)
+{
+ struct nv30_render *r = nv30_render(render);
+ struct nv30_context *nv30 = r->nv30;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned fn = nr >> 8, pn = nr & 0xff;
+ unsigned ps = fn + (pn ? 1 : 0);
+ unsigned i;
+
+ BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
+ for (i = 0; i < r->vertex_info.num_attribs; i++) {
+ PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
+ nv04_resource(r->buffer), r->offset + r->vtxptr[i],
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
+ }
+
+ if (!nv30_state_validate(nv30, FALSE))
+ return;
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, r->prim);
+
+ BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);
+ while (fn--) {
+ PUSH_DATA (push, 0xff000000 | start);
+ start += 256;
+ }
+
+ if (pn)
+ PUSH_DATA (push, ((pn - 1) << 24) | start);
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ PUSH_RESET(push, BUFCTX_VTXTMP);
+}
+
+static void
+nv30_render_release_vertices(struct vbuf_render *render)
+{
+ struct nv30_render *r = nv30_render(render);
+ r->offset += r->length;
+}
+
+static const struct {
+ unsigned emit;
+ unsigned interp;
+ unsigned vp30;
+ unsigned vp40;
+ unsigned ow40;
+} vroute [] = {
+ [TGSI_SEMANTIC_POSITION] = { EMIT_4F, INTERP_PERSPECTIVE, 0, 0, 0x00000000 },
+ [TGSI_SEMANTIC_COLOR ] = { EMIT_4F, INTERP_LINEAR , 3, 1, 0x00000001 },
+ [TGSI_SEMANTIC_BCOLOR ] = { EMIT_4F, INTERP_LINEAR , 1, 3, 0x00000004 },
+ [TGSI_SEMANTIC_FOG ] = { EMIT_4F, INTERP_PERSPECTIVE, 5, 5, 0x00000010 },
+ [TGSI_SEMANTIC_PSIZE ] = { EMIT_1F_PSIZE, INTERP_POS , 6, 6, 0x00000020 },
+ [TGSI_SEMANTIC_GENERIC ] = { EMIT_4F, INTERP_PERSPECTIVE, 8, 7, 0x00004000 }
+};
+
+static boolean
+vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
+{
+ struct pipe_screen *pscreen = &r->nv30->screen->base.base;
+ struct nv30_fragprog *fp = r->nv30->fragprog.program;
+ struct vertex_info *vinfo = &r->vertex_info;
+ enum pipe_format format;
+ uint emit = EMIT_OMIT;
+ uint result = *idx;
+
+ if (sem == TGSI_SEMANTIC_GENERIC && result >= 8) {
+ for (result = 0; result < 8; result++) {
+ if (fp->texcoord[result] == *idx) {
+ emit = vroute[sem].emit;
+ break;
+ }
+ }
+ } else {
+ emit = vroute[sem].emit;
+ }
+
+ if (emit == EMIT_OMIT)
+ return FALSE;
+
+ draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
+ format = draw_translate_vinfo_format(emit);
+
+ r->vtxfmt[attrib] = nv30_vtxfmt(pscreen, format)->hw;
+ r->vtxptr[attrib] = vinfo->size | NV30_3D_VTXBUF_DMA1;
+ vinfo->size += draw_translate_vinfo_size(emit);
+
+ if (nv30_screen(pscreen)->eng3d->oclass < NV40_3D_CLASS) {
+ r->vtxprog[attrib][0] = 0x001f38d8;
+ r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
+ r->vtxprog[attrib][2] = 0x0836106c;
+ r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
+ } else {
+ r->vtxprog[attrib][0] = 0x401f9c6c;
+ r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
+ r->vtxprog[attrib][2] = 0x8106c083;
+ r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
+ }
+
+ *idx = vroute[sem].ow40 << result;
+ return TRUE;
+}
+
+static boolean
+nv30_render_validate(struct nv30_context *nv30)
+{
+ struct nv30_render *r = nv30_render(nv30->draw->render);
+ struct nv30_rasterizer_stateobj *rast = nv30->rast;
+ struct pipe_screen *pscreen = &nv30->screen->base.base;
+ struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nv30_vertprog *vp = nv30->vertprog.program;
+ struct vertex_info *vinfo = &r->vertex_info;
+ unsigned vp_attribs = 0;
+ unsigned vp_results = 0;
+ unsigned attrib = 0;
+ unsigned pntc;
+ int i;
+
+ if (!r->vertprog) {
+ struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap;
+ if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) {
+ while (heap->next && heap->size < 16) {
+ struct nouveau_heap **evict = heap->next->priv;
+ nouveau_heap_free(evict);
+ }
+
+ if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog))
+ return FALSE;
+ }
+ }
+
+ vinfo->num_attribs = 0;
+ vinfo->size = 0;
+
+ /* setup routing for all necessary vp outputs */
+ for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) {
+ uint semantic = vp->info.output_semantic_name[i];
+ uint index = vp->info.output_semantic_index[i];
+ if (vroute_add(r, attrib, semantic, &index)) {
+ vp_attribs |= (1 << attrib++);
+ vp_results |= index;
+ }
+ }
+
+ /* setup routing for replaced point coords not written by vp */
+ if (rast && rast->pipe.point_quad_rasterization)
+ pntc = rast->pipe.sprite_coord_enable & 0x000002ff;
+ else
+ pntc = 0;
+
+ while (pntc && attrib < 16) {
+ uint index = ffs(pntc) - 1; pntc &= ~(1 << index);
+ if (vroute_add(r, attrib, TGSI_SEMANTIC_GENERIC, &index)) {
+ vp_attribs |= (1 << attrib++);
+ vp_results |= index;
+ }
+ }
+
+ /* modify vertex format for correct stride, and stub out unused ones */
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
+ PUSH_DATA (push, r->vertprog->start);
+ r->vtxprog[attrib - 1][3] |= 1;
+ for (i = 0; i < attrib; i++) {
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
+ PUSH_DATAp(push, r->vtxprog[i], 4);
+ r->vtxfmt[i] |= vinfo->size << 8;
+ }
+ for (; i < 16; i++)
+ r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT;
+
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 1.0);
+
+ BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16);
+ PUSH_DATAp(push, r->vtxfmt, 16);
+
+ BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
+ PUSH_DATA (push, r->vertprog->start);
+ BEGIN_NV04(push, NV30_3D(ENGINE), 1);
+ PUSH_DATA (push, 0x00000103);
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
+ PUSH_DATA (push, vp_attribs);
+ PUSH_DATA (push, vp_results);
+ }
+
+ vinfo->size /= 4;
+ return TRUE;
+}
+
+void
+nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct draw_context *draw = nv30->draw;
+ struct pipe_transfer *transfer[PIPE_MAX_ATTRIBS] = {NULL};
+ struct pipe_transfer *transferi = NULL;
+ int i;
+
+ nv30_render_validate(nv30);
+
+ if (nv30->draw_dirty & NV30_NEW_VIEWPORT)
+ draw_set_viewport_states(draw, 0, 1, &nv30->viewport);
+ if (nv30->draw_dirty & NV30_NEW_RASTERIZER)
+ draw_set_rasterizer_state(draw, &nv30->rast->pipe, NULL);
+ if (nv30->draw_dirty & NV30_NEW_CLIP)
+ draw_set_clip_state(draw, &nv30->clip);
+ if (nv30->draw_dirty & NV30_NEW_ARRAYS) {
+ draw_set_vertex_buffers(draw, 0, nv30->num_vtxbufs, nv30->vtxbuf);
+ draw_set_vertex_elements(draw, nv30->vertex->num_elements, nv30->vertex->pipe);
+ }
+ if (nv30->draw_dirty & NV30_NEW_FRAGPROG) {
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ if (!fp->draw)
+ fp->draw = draw_create_fragment_shader(draw, &fp->pipe);
+ draw_bind_fragment_shader(draw, fp->draw);
+ }
+ if (nv30->draw_dirty & NV30_NEW_VERTPROG) {
+ struct nv30_vertprog *vp = nv30->vertprog.program;
+ if (!vp->draw)
+ vp->draw = draw_create_vertex_shader(draw, &vp->pipe);
+ draw_bind_vertex_shader(draw, vp->draw);
+ }
+ if (nv30->draw_dirty & NV30_NEW_VERTCONST) {
+ if (nv30->vertprog.constbuf) {
+ void *map = nv04_resource(nv30->vertprog.constbuf)->data;
+ draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
+ map, nv30->vertprog.constbuf_nr);
+ }
+ }
+
+ for (i = 0; i < nv30->num_vtxbufs; i++) {
+ const void *map = nv30->vtxbuf[i].user_buffer;
+ if (!map) {
+ if (!nv30->vtxbuf[i].buffer) {
+ continue;
+ }
+ map = pipe_buffer_map(pipe, nv30->vtxbuf[i].buffer,
+ PIPE_TRANSFER_UNSYNCHRONIZED |
+ PIPE_TRANSFER_READ, &transfer[i]);
+ }
+ draw_set_mapped_vertex_buffer(draw, i, map, ~0);
+ }
+
+ if (info->indexed) {
+ const void *map = nv30->idxbuf.user_buffer;
+ if (!map)
+ pipe_buffer_map(pipe, nv30->idxbuf.buffer,
+ PIPE_TRANSFER_UNSYNCHRONIZED |
+ PIPE_TRANSFER_READ, &transferi);
+ draw_set_indexes(draw,
+ (ubyte *) map + nv30->idxbuf.offset,
+ nv30->idxbuf.index_size, ~0);
+ } else {
+ draw_set_indexes(draw, NULL, 0, 0);
+ }
+
+ draw_vbo(draw, info);
+ draw_flush(draw);
+
+ if (info->indexed && transferi)
+ pipe_buffer_unmap(pipe, transferi);
+ for (i = 0; i < nv30->num_vtxbufs; i++)
+ if (transfer[i])
+ pipe_buffer_unmap(pipe, transfer[i]);
+
+ nv30->draw_dirty = 0;
+ nv30_state_release(nv30);
+}
+
+static void
+nv30_render_destroy(struct vbuf_render *render)
+{
+ FREE(render);
+}
+
+static struct vbuf_render *
+nv30_render_create(struct nv30_context *nv30)
+{
+ struct nv30_render *r = CALLOC_STRUCT(nv30_render);
+ if (!r)
+ return NULL;
+
+ r->nv30 = nv30;
+ r->offset = 1 * 1024 * 1024;
+
+ r->base.max_indices = 16 * 1024;
+ r->base.max_vertex_buffer_bytes = r->offset;
+
+ r->base.get_vertex_info = nv30_render_get_vertex_info;
+ r->base.allocate_vertices = nv30_render_allocate_vertices;
+ r->base.map_vertices = nv30_render_map_vertices;
+ r->base.unmap_vertices = nv30_render_unmap_vertices;
+ r->base.set_primitive = nv30_render_set_primitive;
+ r->base.draw_elements = nv30_render_draw_elements;
+ r->base.draw_arrays = nv30_render_draw_arrays;
+ r->base.release_vertices = nv30_render_release_vertices;
+ r->base.destroy = nv30_render_destroy;
+ return &r->base;
+}
+
+void
+nv30_draw_init(struct pipe_context *pipe)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct vbuf_render *render;
+ struct draw_context *draw;
+ struct draw_stage *stage;
+
+ draw = draw_create(pipe);
+ if (!draw)
+ return;
+
+ render = nv30_render_create(nv30);
+ if (!render) {
+ draw_destroy(draw);
+ return;
+ }
+
+ stage = draw_vbuf_stage(draw, render);
+ if (!stage) {
+ render->destroy(render);
+ draw_destroy(draw);
+ return;
+ }
+
+ draw_set_render(draw, render);
+ draw_set_rasterize_stage(draw, stage);
+ draw_wide_line_threshold(draw, 10000000.f);
+ draw_wide_point_threshold(draw, 10000000.f);
+ draw_wide_point_sprites(draw, TRUE);
+ nv30->draw = draw;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_format.c b/src/gallium/drivers/nouveau/nv30/nv30_format.c
new file mode 100644
index 00000000000..67e0d5e9c56
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_format.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+#define NV30_3D_RT_FORMAT_COLOR_X1R5G5B5 2
+
+#define NV30_3D_TEX_FORMAT_FORMAT_A16L16 NV30_3D_TEX_FORMAT_FORMAT_HILO16
+#define NV30_3D_TEX_FORMAT_FORMAT_A16L16_RECT NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT
+#define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F 0x00004a00
+#define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA16F
+#define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F 0x00004b00
+#define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA32F
+#define NV30_3D_TEX_FORMAT_FORMAT_R32F 0x00004c00
+#define NV30_3D_TEX_FORMAT_FORMAT_R32F_RECT NV30_3D_TEX_FORMAT_FORMAT_R32F
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT1_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT1
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT3_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT3
+#define NV30_3D_TEX_FORMAT_FORMAT_DXT5_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT5
+#define NV30_3D_TEX_FORMAT_FORMAT_RG16F 0xdeadcafe
+#define NV30_3D_TEX_FORMAT_FORMAT_RG16F_RECT 0xdeadcafe
+
+#define NV40_3D_TEX_FORMAT_FORMAT_R32F 0x00001c00
+#define NV40_3D_TEX_FORMAT_FORMAT_RG16F 0x00001f00
+
+#define ____ 0
+#define S___ PIPE_BIND_SAMPLER_VIEW
+#define _R__ PIPE_BIND_RENDER_TARGET
+#define _B__ PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLENDABLE
+#define _Z__ PIPE_BIND_DEPTH_STENCIL
+#define __V_ PIPE_BIND_VERTEX_BUFFER
+#define SR__ (S___ | _R__)
+#define SB__ (S___ | _B__)
+#define SZ__ (S___ | _Z__)
+#define S_V_ (S___ | __V_)
+#define SRV_ (SR__ | __V_)
+#define SBV_ (SB__ | __V_)
+
+#define _(a,b) [PIPE_FORMAT_##a] = { \
+ .bindings = (b), \
+}
+const struct nv30_format_info
+nv30_format_info_table[PIPE_FORMAT_COUNT] = {
+ _(L8_UNORM , S___),
+ _(L8_SNORM , S___),
+ _(L8_SRGB , S___),
+ _(I8_UNORM , S___),
+ _(I8_SNORM , S___),
+ _(A8_UNORM , S___),
+ _(A8_SNORM , S___),
+ _(R8_UNORM , S_V_),
+ _(R8_SNORM , S___),
+ _(B5G5R5X1_UNORM , SB__),
+ _(B5G5R5A1_UNORM , S___),
+ _(B4G4R4X4_UNORM , S___),
+ _(B4G4R4A4_UNORM , S___),
+ _(B5G6R5_UNORM , SB__),
+ _(B8G8R8X8_UNORM , SB__),
+ _(B8G8R8X8_SRGB , S___),
+ _(B8G8R8A8_UNORM , SB__),
+ _(B8G8R8A8_SRGB , S___),
+ _(R8G8B8A8_UNORM , __V_),
+ _(R8G8B8A8_SNORM , S___),
+ _(DXT1_RGB , S___),
+ _(DXT1_SRGB , S___),
+ _(DXT1_RGBA , S___),
+ _(DXT1_SRGBA , S___),
+ _(DXT3_RGBA , S___),
+ _(DXT3_SRGBA , S___),
+ _(DXT5_RGBA , S___),
+ _(DXT5_SRGBA , S___),
+ _(L8A8_UNORM , S___),
+ _(L8A8_SRGB , S___),
+ _(R8G8_UNORM , S_V_),
+ _(R8G8_SNORM , S___),
+ _(R8G8B8_UNORM , __V_),
+ _(Z16_UNORM , SZ__),
+ _(X8Z24_UNORM , SZ__),
+ _(S8_UINT_Z24_UNORM , SZ__),
+ _(L16_UNORM , S___),
+ _(L16_SNORM , S___),
+ _(I16_UNORM , S___),
+ _(I16_SNORM , S___),
+ _(A16_UNORM , S___),
+ _(A16_SNORM , S___),
+ _(R16_UNORM , S___),
+ _(R16_SNORM , S_V_),
+ _(R16G16_SNORM , __V_),
+ _(R16G16B16_SNORM , __V_),
+ _(R16G16B16A16_SNORM , __V_),
+ _(R8G8B8A8_USCALED , __V_),
+ _(R16_FLOAT , __V_),
+ _(R16G16_FLOAT , __V_), //S_V_),
+ _(R16G16B16_FLOAT , __V_),
+ _(R16G16B16A16_FLOAT , __V_), //SBV_),
+ _(R16_SSCALED , __V_),
+ _(R16G16_SSCALED , __V_),
+ _(R16G16B16_SSCALED , __V_),
+ _(R16G16B16A16_SSCALED, __V_),
+ _(R32_FLOAT , __V_), //SRV_),
+ _(R32G32_FLOAT , __V_),
+ _(R32G32B32_FLOAT , __V_),
+ _(R32G32B32A32_FLOAT , __V_), //SRV_),
+};
+#undef _
+#undef ____
+
+#define R_(a,b) [PIPE_FORMAT_##a] = { \
+ .hw = NV30_3D_RT_FORMAT_COLOR_##b, \
+}
+#define Z_(a,b) [PIPE_FORMAT_##a] = { \
+ .hw = NV30_3D_RT_FORMAT_ZETA_##b, \
+}
+const struct nv30_format
+nv30_format_table[PIPE_FORMAT_COUNT] = {
+ R_(B5G5R5X1_UNORM , X1R5G5B5 ),
+ R_(B5G6R5_UNORM , R5G6B5 ),
+ R_(B8G8R8X8_UNORM , X8R8G8B8 ),
+ R_(B8G8R8A8_UNORM , A8R8G8B8 ),
+ Z_(Z16_UNORM , Z16 ),
+ Z_(X8Z24_UNORM , Z24S8 ),
+ Z_(S8_UINT_Z24_UNORM , Z24S8 ),
+ R_(R16G16B16A16_FLOAT, A16B16G16R16_FLOAT),
+ R_(R32G32B32A32_FLOAT, A32B32G32R32_FLOAT),
+ R_(R32_FLOAT , R32_FLOAT ),
+};
+
+#define _(a,b,c) [PIPE_FORMAT_##a] = { \
+ .hw = NV30_3D_VTXFMT_TYPE_##b | ((c) << NV30_3D_VTXFMT_SIZE__SHIFT) \
+}
+const struct nv30_vtxfmt
+nv30_vtxfmt_table[PIPE_FORMAT_COUNT] = {
+ _(R8_UNORM , U8_UNORM , 1),
+ _(R8G8_UNORM , U8_UNORM , 2),
+ _(R8G8B8_UNORM , U8_UNORM , 3),
+ _(R8G8B8A8_UNORM , U8_UNORM , 4),
+ _(R8G8B8A8_USCALED , U8_USCALED , 4),
+ _(R16_SNORM , V16_SNORM , 1),
+ _(R16G16_SNORM , V16_SNORM , 2),
+ _(R16G16B16_SNORM , V16_SNORM , 3),
+ _(R16G16B16A16_SNORM , V16_SNORM , 4),
+ _(R16_SSCALED , V16_SSCALED, 1),
+ _(R16G16_SSCALED , V16_SSCALED, 2),
+ _(R16G16B16_SSCALED , V16_SSCALED, 3),
+ _(R16G16B16A16_SSCALED, V16_SSCALED, 4),
+ _(R16_FLOAT , V16_FLOAT , 1),
+ _(R16G16_FLOAT , V16_FLOAT , 2),
+ _(R16G16B16_FLOAT , V16_FLOAT , 3),
+ _(R16G16B16A16_FLOAT , V16_FLOAT , 4),
+ _(R32_FLOAT , V32_FLOAT , 1),
+ _(R32G32_FLOAT , V32_FLOAT , 2),
+ _(R32G32B32_FLOAT , V32_FLOAT , 3),
+ _(R32G32B32A32_FLOAT , V32_FLOAT , 4),
+};
+#undef _
+
+#define SWZ_OUT_0 0
+#define SWZ_OUT_1 1
+#define SWZ_OUT_C 2
+
+#define SWZ_SRC_0 3
+#define SWZ_SRC_1 2
+#define SWZ_SRC_2 1
+#define SWZ_SRC_3 0
+#define SWZ_SRC_x 0
+
+#define NONE 0x00000000
+#define SRGB 0x00700000
+
+#define ____ 0x00000000
+#define SSSS 0xf0000000
+
+#define _(a,b,c,d,e,f,g,h,i,j,k,l,m) [PIPE_FORMAT_##a] = { \
+ .nv30 = NV30_3D_TEX_FORMAT_FORMAT_##b, \
+ .nv30_rect = NV30_3D_TEX_FORMAT_FORMAT_##b##_RECT, \
+ .nv40 = NV40_3D_TEX_FORMAT_FORMAT_##b, \
+ .swz[0] = { SWZ_OUT_##d, SWZ_SRC_##h }, \
+ .swz[1] = { SWZ_OUT_##e, SWZ_SRC_##i }, \
+ .swz[2] = { SWZ_OUT_##f, SWZ_SRC_##j }, \
+ .swz[3] = { SWZ_OUT_##g, SWZ_SRC_##k }, \
+ .swz[4] = { SWZ_OUT_0, SWZ_SRC_x }, \
+ .swz[5] = { SWZ_OUT_1, SWZ_SRC_x }, \
+ .swizzle = (c) * 0x00010000, \
+ .wrap = (l), \
+ .filter = (m), \
+}
+const struct nv30_texfmt
+nv30_texfmt_table[PIPE_FORMAT_COUNT] = {
+ _(L8_UNORM , L8 , 0, C, C, C, 1, 0, 0, 0, x, NONE, ____),
+ _(L8_SNORM , L8 , 0, C, C, C, 1, 0, 0, 0, x, NONE, SSSS),
+ _(L8_SRGB , L8 , 0, C, C, C, 1, 0, 0, 0, x, SRGB, ____),
+ _(I8_UNORM , L8 , 0, C, C, C, C, 0, 0, 0, 0, NONE, ____),
+ _(I8_SNORM , L8 , 0, C, C, C, C, 0, 0, 0, 0, NONE, SSSS),
+ _(A8_UNORM , L8 , 0, 0, 0, 0, C, x, x, x, 0, NONE, ____),
+ _(A8_SNORM , L8 , 0, 0, 0, 0, C, x, x, x, 0, NONE, SSSS),
+ _(R8_UNORM , L8 , 0, C, 0, 0, 1, 0, x, x, x, NONE, ____),
+ _(R8_SNORM , L8 , 0, C, 0, 0, 1, 0, x, x, x, NONE, SSSS),
+ _(B5G5R5X1_UNORM , A1R5G5B5, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
+ _(B5G5R5A1_UNORM , A1R5G5B5, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(B4G4R4X4_UNORM , A4R4G4B4, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
+ _(B4G4R4A4_UNORM , A4R4G4B4, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(B5G6R5_UNORM , R5G6B5 , 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
+ _(B8G8R8X8_UNORM , A8R8G8B8, 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
+ _(B8G8R8X8_SRGB , A8R8G8B8, 0, C, C, C, 1, 2, 1, 0, x, SRGB, ____),
+ _(B8G8R8A8_UNORM , A8R8G8B8, 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(B8G8R8A8_SRGB , A8R8G8B8, 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
+ _(R8G8B8A8_SNORM , A8R8G8B8, 0, C, C, C, C, 0, 1, 2, 3, NONE, SSSS),
+ _(DXT1_RGB , DXT1 , 0, C, C, C, 1, 2, 1, 0, x, NONE, ____),
+ _(DXT1_SRGB , DXT1 , 0, C, C, C, 1, 2, 1, 0, x, SRGB, ____),
+ _(DXT1_RGBA , DXT1 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(DXT1_SRGBA , DXT1 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
+ _(DXT3_RGBA , DXT3 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(DXT3_SRGBA , DXT3 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
+ _(DXT5_RGBA , DXT5 , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(DXT5_SRGBA , DXT5 , 0, C, C, C, C, 2, 1, 0, 3, SRGB, ____),
+ _(L8A8_UNORM , A8L8 , 0, C, C, C, C, 0, 0, 0, 3, NONE, ____),
+ _(L8A8_SRGB , A8L8 , 0, C, C, C, C, 0, 0, 0, 3, SRGB, ____),
+ _(R8G8_UNORM , A8L8 , 0, C, C, 0, 1, 0, 3, x, x, NONE, ____),
+ _(R8G8_SNORM , A8L8 , 0, C, C, 0, 1, 0, 3, x, x, NONE, SSSS),
+ _(Z16_UNORM , Z16 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
+ _(X8Z24_UNORM , Z24 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
+ _(S8_UINT_Z24_UNORM , Z24 , 0, C, C, C, 1, 3, 3, 3, x, NONE, ____),
+ _(L16_UNORM , A16 , 0, C, C, C, 1, 1, 1, 1, 1, NONE, ____),
+ _(L16_SNORM , A16 , 0, C, C, C, 1, 1, 1, 1, 1, NONE, SSSS),
+ _(I16_UNORM , A16 , 0, C, C, C, C, 1, 1, 1, 1, NONE, ____),
+ _(I16_SNORM , A16 , 0, C, C, C, C, 1, 1, 1, 1, NONE, SSSS),
+ _(A16_UNORM , A16 , 0, 0, 0, 0, C, 1, 1, 1, 1, NONE, ____),
+ _(A16_SNORM , A16 , 0, 0, 0, 0, C, 1, 1, 1, 1, NONE, SSSS),
+ _(R16_UNORM , A16 , 0, C, 0, 0, 1, 1, 1, 1, 1, NONE, ____),
+ _(R16_SNORM , A16 , 0, C, 0, 0, 1, 1, 1, 1, 1, NONE, SSSS),
+ _(R16G16_FLOAT , RG16F , 0, C, C, 0, 1, 2, 1, 0, 3, NONE, ____),
+ _(R16G16B16A16_FLOAT, RGBA16F , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+ _(R32_FLOAT , R32F , 0, C, 0, 0, 1, 2, 1, 0, 3, NONE, ____),
+ _(R32G32B32A32_FLOAT, RGBA32F , 0, C, C, C, C, 2, 1, 0, 3, NONE, ____),
+};
+#undef _
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_format.h b/src/gallium/drivers/nouveau/nv30/nv30_format.h
new file mode 100644
index 00000000000..8bf4a37299f
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_format.h
@@ -0,0 +1,57 @@
+#ifndef __NV30_FORMAT_H__
+#define __NV30_FORMAT_H__
+
+struct nv30_format_info {
+ unsigned bindings;
+};
+
+struct nv30_format {
+ unsigned hw;
+};
+
+struct nv30_vtxfmt {
+ unsigned hw;
+};
+
+struct nv30_texfmt {
+ unsigned nv30;
+ unsigned nv30_rect;
+ unsigned nv40;
+ struct {
+ unsigned src;
+ unsigned cmp;
+ } swz[6];
+ unsigned swizzle;
+ unsigned filter;
+ unsigned wrap;
+};
+
+extern const struct nv30_format_info nv30_format_info_table[];
+static INLINE const struct nv30_format_info *
+nv30_format_info(struct pipe_screen *pscreen, enum pipe_format format)
+{
+ return &nv30_format_info_table[format];
+}
+
+extern const struct nv30_format nv30_format_table[];
+static INLINE const struct nv30_format *
+nv30_format(struct pipe_screen *pscreen, enum pipe_format format)
+{
+ return &nv30_format_table[format];
+}
+
+extern const struct nv30_vtxfmt nv30_vtxfmt_table[];
+static INLINE const struct nv30_vtxfmt *
+nv30_vtxfmt(struct pipe_screen *pscreen, enum pipe_format format)
+{
+ return &nv30_vtxfmt_table[format];
+}
+
+extern const struct nv30_texfmt nv30_texfmt_table[];
+static INLINE const struct nv30_texfmt *
+nv30_texfmt(struct pipe_screen *pscreen, enum pipe_format format)
+{
+ return &nv30_texfmt_table[format];
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c b/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c
new file mode 100644
index 00000000000..e8acdfeaf75
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_fragprog.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nvfx_shader.h"
+
+static void
+nv30_fragprog_upload(struct nv30_context *nv30)
+{
+ struct nouveau_context *nv = &nv30->base;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ struct pipe_context *pipe = &nv30->base.pipe;
+ struct pipe_transfer *transfer;
+ uint32_t *map;
+ int i; (void)i;
+
+ if (unlikely(!fp->buffer)) {
+ fp->buffer = pipe_buffer_create(pipe->screen, 0, 0, fp->insn_len * 4);
+ }
+
+ map = pipe_buffer_map(pipe, fp->buffer, PIPE_TRANSFER_WRITE, &transfer);
+#ifndef PIPE_ARCH_BIG_ENDIAN
+ memcpy(map, fp->insn, fp->insn_len * 4);
+#else
+ for (i = 0; i < fp->insn_len; i++)
+ *map++ = (fp->insn[i] >> 16) | (fp->insn[i] << 16);
+#endif
+ pipe_buffer_unmap(pipe, transfer);
+
+ if (nv04_resource(fp->buffer)->domain != NOUVEAU_BO_VRAM)
+ nouveau_buffer_migrate(nv, nv04_resource(fp->buffer), NOUVEAU_BO_VRAM);
+}
+
+void
+nv30_fragprog_validate(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ boolean upload = FALSE;
+ int i;
+
+ if (!fp->translated) {
+ _nvfx_fragprog_translate(nv30, fp, FALSE);
+ if (!fp->translated)
+ return;
+
+ upload = TRUE;
+ }
+
+ /* update constants, also needs to be done on every fp switch as we
+ * have no idea whether the constbuf changed in the meantime
+ */
+ if (nv30->fragprog.constbuf) {
+ struct pipe_resource *constbuf = nv30->fragprog.constbuf;
+ uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data;
+
+ for (i = 0; i < fp->nr_consts; i++) {
+ unsigned off = fp->consts[i].offset;
+ unsigned idx = fp->consts[i].index * 4;
+
+ if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4))
+ continue;
+ memcpy(&fp->insn[off], &cbuf[idx], 4 * 4);
+ upload = TRUE;
+ }
+ }
+
+ if (upload)
+ nv30_fragprog_upload(nv30);
+
+ /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
+ * were updated. TEX_CACHE_CTL magic is not enough to convince the
+ * GPU that it should re-read the fragprog from VRAM... sigh.
+ */
+ if (nv30->state.fragprog != fp || upload) {
+ struct nv04_resource *r = nv04_resource(fp->buffer);
+
+ if (!PUSH_SPACE(push, 8))
+ return;
+ PUSH_RESET(push, BUFCTX_FRAGPROG);
+
+ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
+ PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0,
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD | NOUVEAU_BO_OR,
+ NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
+ NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
+ BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
+ PUSH_DATA (push, fp->fp_control);
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
+ PUSH_DATA (push, 0x00010004);
+ BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1);
+ PUSH_DATA (push, fp->texcoords);
+ } else {
+ BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
+ PUSH_DATA (push, 0x00000000);
+ }
+
+ nv30->state.fragprog = fp;
+ }
+}
+
+static void *
+nv30_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv30_fragprog *fp = CALLOC_STRUCT(nv30_fragprog);
+ if (!fp)
+ return NULL;
+
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+ return fp;
+}
+
+static void
+nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_fragprog *fp = hwcso;
+
+ pipe_resource_reference(&fp->buffer, NULL);
+
+ FREE((void *)fp->pipe.tokens);
+ FREE(fp->insn);
+ FREE(fp);
+}
+
+static void
+nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->fragprog.program = hwcso;
+ nv30->dirty |= NV30_NEW_FRAGPROG;
+}
+
+void
+nv30_fragprog_init(struct pipe_context *pipe)
+{
+ pipe->create_fs_state = nv30_fp_state_create;
+ pipe->bind_fs_state = nv30_fp_state_bind;
+ pipe->delete_fs_state = nv30_fp_state_delete;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c b/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c
new file mode 100644
index 00000000000..60ffb03c89f
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_fragtex.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_inlines.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+void
+nv30_fragtex_validate(struct nv30_context *nv30)
+{
+ struct pipe_screen *pscreen = &nv30->screen->base.base;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned dirty = nv30->fragprog.dirty_samplers;
+
+ while (dirty) {
+ unsigned unit = ffs(dirty) - 1;
+ struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
+ struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];
+
+ PUSH_RESET(push, BUFCTX_FRAGTEX(unit));
+
+ if (ss && sv) {
+ const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format);
+ struct pipe_resource *pt = sv->pipe.texture;
+ struct nv30_miptree *mt = nv30_miptree(pt);
+ unsigned min_lod, max_lod;
+ u32 filter = sv->filt | (ss->filt & sv->filt_mask);
+ u32 format = sv->fmt | ss->fmt;
+ u32 enable = ss->en;
+
+ /* handle base_level when not using a mip filter, min/max level
+ * is unfortunately ignored by the hardware otherwise
+ */
+ if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ if (sv->base_lod)
+ filter += 0x00020000; /* N/L -> NMN/LMN */
+ max_lod = sv->base_lod;
+ min_lod = sv->base_lod;
+ } else {
+ max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod);
+ min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod);
+ }
+
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ /* this is a tad stupid of the hardware, but there's no non-rcomp
+ * z16/z24 texture formats to be had, we have to suffer and lose
+ * some precision to handle this case.
+ */
+ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16)
+ format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8;
+ else
+ if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24)
+ format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16;
+ else
+ format |= fmt->nv40;
+ } else {
+ format |= fmt->nv40;
+ }
+
+ enable |= (min_lod << 19) | (max_lod << 7);
+ enable |= NV40_3D_TEX_ENABLE_ENABLE;
+
+ BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1);
+ PUSH_DATA (push, sv->npot_size1);
+ } else {
+ /* this is a tad stupid of the hardware, but there's no non-rcomp
+ * z16/z24 texture formats to be had, we have to suffer and lose
+ * some precision to handle this case.
+ */
+ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) {
+ if (ss->pipe.normalized_coords)
+ format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8;
+ else
+ format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT;
+ } else
+ if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) {
+ if (ss->pipe.normalized_coords)
+ format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16;
+ else
+ format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT;
+ } else {
+ if (ss->pipe.normalized_coords)
+ format |= fmt->nv30;
+ else
+ format |= fmt->nv30_rect;
+ }
+ } else {
+ if (ss->pipe.normalized_coords)
+ format |= fmt->nv30;
+ else
+ format |= fmt->nv30_rect;
+ }
+
+ enable |= NV30_3D_TEX_ENABLE_ENABLE;
+ enable |= (min_lod << 18) | (max_lod << 6);
+ }
+
+ BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
+ PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit),
+ mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit),
+ mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD,
+ NV30_3D_TEX_FORMAT_DMA0,
+ NV30_3D_TEX_FORMAT_DMA1);
+ PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask));
+ PUSH_DATA (push, enable);
+ PUSH_DATA (push, sv->swz);
+ PUSH_DATA (push, filter);
+ PUSH_DATA (push, sv->npot_size0);
+ PUSH_DATA (push, ss->bcol);
+ BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1);
+ PUSH_DATA (push, nv30->config.filter);
+ } else {
+ BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1);
+ PUSH_DATA (push, 0);
+ }
+
+ dirty &= ~(1 << unit);
+ }
+
+ nv30->fragprog.dirty_samplers = 0;
+}
+
+static void
+nv30_fragtex_sampler_states_bind(struct pipe_context *pipe,
+ unsigned nr, void **hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ nv30->fragprog.samplers[i] = hwcso[i];
+ nv30->fragprog.dirty_samplers |= (1 << i);
+ }
+
+ for (; i < nv30->fragprog.num_samplers; i++) {
+ nv30->fragprog.samplers[i] = NULL;
+ nv30->fragprog.dirty_samplers |= (1 << i);
+ }
+
+ nv30->fragprog.num_samplers = nr;
+ nv30->dirty |= NV30_NEW_FRAGTEX;
+}
+
+
+static void
+nv30_fragtex_set_sampler_views(struct pipe_context *pipe, unsigned nr,
+ struct pipe_sampler_view **views)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
+ pipe_sampler_view_reference(&nv30->fragprog.textures[i], views[i]);
+ nv30->fragprog.dirty_samplers |= (1 << i);
+ }
+
+ for (; i < nv30->fragprog.num_textures; i++) {
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FRAGTEX(i));
+ pipe_sampler_view_reference(&nv30->fragprog.textures[i], NULL);
+ nv30->fragprog.dirty_samplers |= (1 << i);
+ }
+
+ nv30->fragprog.num_textures = nr;
+ nv30->dirty |= NV30_NEW_FRAGTEX;
+}
+
+void
+nv30_fragtex_init(struct pipe_context *pipe)
+{
+ pipe->bind_fragment_sampler_states = nv30_fragtex_sampler_states_bind;
+ pipe->set_fragment_sampler_views = nv30_fragtex_set_sampler_views;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c
new file mode 100644
index 00000000000..4c237f615cd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "util/u_surface.h"
+
+#include "nv_m2mf.xml.h"
+#include "nv30/nv30_screen.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_resource.h"
+#include "nv30/nv30_transfer.h"
+
+static INLINE unsigned
+layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer)
+{
+ struct nv30_miptree *mt = nv30_miptree(pt);
+ struct nv30_miptree_level *lvl = &mt->level[level];
+
+ if (pt->target == PIPE_TEXTURE_CUBE)
+ return (layer * mt->layer_size) + lvl->offset;
+
+ return lvl->offset + (layer * lvl->zslice_size);
+}
+
+static boolean
+nv30_miptree_get_handle(struct pipe_screen *pscreen,
+ struct pipe_resource *pt,
+ struct winsys_handle *handle)
+{
+ struct nv30_miptree *mt = nv30_miptree(pt);
+ unsigned stride;
+
+ if (!mt || !mt->base.bo)
+ return FALSE;
+
+ stride = mt->level[0].pitch;
+
+ return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle);
+}
+
+static void
+nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
+{
+ struct nv30_miptree *mt = nv30_miptree(pt);
+
+ nouveau_bo_ref(NULL, &mt->base.bo);
+ FREE(mt);
+}
+
+struct nv30_transfer {
+ struct pipe_transfer base;
+ struct nv30_rect img;
+ struct nv30_rect tmp;
+ unsigned nblocksx;
+ unsigned nblocksy;
+};
+
+static INLINE struct nv30_transfer *
+nv30_transfer(struct pipe_transfer *ptx)
+{
+ return (struct nv30_transfer *)ptx;
+}
+
+static INLINE void
+define_rect(struct pipe_resource *pt, unsigned level, unsigned z,
+ unsigned x, unsigned y, unsigned w, unsigned h,
+ struct nv30_rect *rect)
+{
+ struct nv30_miptree *mt = nv30_miptree(pt);
+ struct nv30_miptree_level *lvl = &mt->level[level];
+
+ rect->w = u_minify(pt->width0, level) << mt->ms_x;
+ rect->w = util_format_get_nblocksx(pt->format, rect->w);
+ rect->h = u_minify(pt->height0, level) << mt->ms_y;
+ rect->h = util_format_get_nblocksy(pt->format, rect->h);
+ rect->d = 1;
+ rect->z = 0;
+ if (mt->swizzled) {
+ if (pt->target == PIPE_TEXTURE_3D) {
+ rect->d = u_minify(pt->depth0, level);
+ rect->z = z; z = 0;
+ }
+ rect->pitch = 0;
+ } else {
+ rect->pitch = lvl->pitch;
+ }
+
+ rect->bo = mt->base.bo;
+ rect->domain = NOUVEAU_BO_VRAM;
+ rect->offset = layer_offset(pt, level, z);
+ rect->cpp = util_format_get_blocksize(pt->format);
+
+ rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x;
+ rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y;
+ rect->x1 = rect->x0 + (w << mt->ms_x);
+ rect->y1 = rect->y0 + (h << mt->ms_y);
+}
+
+void
+nv30_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dstres, unsigned dst_level,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *srcres, unsigned src_level,
+ const struct pipe_box *src_box)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_rect src, dst;
+
+ if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) {
+ nouveau_copy_buffer(&nv30->base,
+ nv04_resource(dstres), dstx,
+ nv04_resource(srcres), src_box->x, src_box->width);
+ return;
+ }
+
+ define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y,
+ src_box->width, src_box->height, &src);
+ define_rect(dstres, dst_level, dstz, dstx, dsty,
+ src_box->width, src_box->height, &dst);
+
+ nv30_transfer_rect(nv30, NEAREST, &src, &dst);
+}
+
+void
+nv30_resource_resolve(struct pipe_context *pipe,
+ const struct pipe_resolve_info *info)
+{
+#if 0
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_rect src, dst;
+
+ define_rect(info->src.res, 0, 0, info->src.x0, info->src.y0,
+ info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &src);
+ define_rect(info->dst.res, info->dst.level, 0, info->dst.x0, info->dst.y0,
+ info->dst.x1 - info->dst.x0, info->dst.y1 - info->dst.y0, &dst);
+
+ nv30_transfer_rect(nv30, BILINEAR, &src, &dst);
+#endif
+}
+
+void
+nv30_blit(struct pipe_context *pipe,
+ const struct pipe_blit_info *blit_info)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct pipe_blit_info info = *blit_info;
+
+ if (info.src.resource->nr_samples > 1 &&
+ info.dst.resource->nr_samples <= 1 &&
+ !util_format_is_depth_or_stencil(info.src.resource->format) &&
+ !util_format_is_pure_integer(info.src.resource->format)) {
+ debug_printf("nv30: color resolve unimplemented\n");
+ return;
+ }
+
+ if (util_try_blit_via_copy_region(pipe, &info)) {
+ return; /* done */
+ }
+
+ if (info.mask & PIPE_MASK_S) {
+ debug_printf("nv30: cannot blit stencil, skipping\n");
+ info.mask &= ~PIPE_MASK_S;
+ }
+
+ if (!util_blitter_is_blit_supported(nv30->blitter, &info)) {
+ debug_printf("nv30: blit unsupported %s -> %s\n",
+ util_format_short_name(info.src.resource->format),
+ util_format_short_name(info.dst.resource->format));
+ return;
+ }
+
+ /* XXX turn off occlusion queries */
+
+ util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf);
+ util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex);
+ util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program);
+ util_blitter_save_rasterizer(nv30->blitter, nv30->rast);
+ util_blitter_save_viewport(nv30->blitter, &nv30->viewport);
+ util_blitter_save_scissor(nv30->blitter, &nv30->scissor);
+ util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program);
+ util_blitter_save_blend(nv30->blitter, nv30->blend);
+ util_blitter_save_depth_stencil_alpha(nv30->blitter,
+ nv30->zsa);
+ util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref);
+ util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask);
+ util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer);
+ util_blitter_save_fragment_sampler_states(nv30->blitter,
+ nv30->fragprog.num_samplers,
+ (void**)nv30->fragprog.samplers);
+ util_blitter_save_fragment_sampler_views(nv30->blitter,
+ nv30->fragprog.num_textures, nv30->fragprog.textures);
+ util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query,
+ nv30->render_cond_cond, nv30->render_cond_mode);
+ util_blitter_blit(nv30->blitter, &info);
+}
+
+static void *
+nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt,
+ unsigned level, unsigned usage,
+ const struct pipe_box *box,
+ struct pipe_transfer **ptransfer)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_device *dev = nv30->screen->base.device;
+ struct nv30_transfer *tx;
+ unsigned access = 0;
+ int ret;
+
+ tx = CALLOC_STRUCT(nv30_transfer);
+ if (!tx)
+ return NULL;
+ pipe_resource_reference(&tx->base.resource, pt);
+ tx->base.level = level;
+ tx->base.usage = usage;
+ tx->base.box = *box;
+ tx->base.stride = util_format_get_nblocksx(pt->format, box->width) *
+ util_format_get_blocksize(pt->format);
+ tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) *
+ tx->base.stride;
+
+ tx->nblocksx = util_format_get_nblocksx(pt->format, box->width);
+ tx->nblocksy = util_format_get_nblocksy(pt->format, box->height);
+
+ define_rect(pt, level, box->z, box->x, box->y,
+ tx->nblocksx, tx->nblocksy, &tx->img);
+
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
+ tx->base.layer_stride, NULL, &tx->tmp.bo);
+ if (ret) {
+ pipe_resource_reference(&tx->base.resource, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ tx->tmp.domain = NOUVEAU_BO_GART;
+ tx->tmp.offset = 0;
+ tx->tmp.pitch = tx->base.stride;
+ tx->tmp.cpp = tx->img.cpp;
+ tx->tmp.w = tx->nblocksx;
+ tx->tmp.h = tx->nblocksy;
+ tx->tmp.d = 1;
+ tx->tmp.x0 = 0;
+ tx->tmp.y0 = 0;
+ tx->tmp.x1 = tx->tmp.w;
+ tx->tmp.y1 = tx->tmp.h;
+ tx->tmp.z = 0;
+
+ if (usage & PIPE_TRANSFER_READ)
+ nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp);
+
+ if (tx->tmp.bo->map) {
+ *ptransfer = &tx->base;
+ return tx->tmp.bo->map;
+ }
+
+ if (usage & PIPE_TRANSFER_READ)
+ access |= NOUVEAU_BO_RD;
+ if (usage & PIPE_TRANSFER_WRITE)
+ access |= NOUVEAU_BO_WR;
+
+ ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client);
+ if (ret) {
+ pipe_resource_reference(&tx->base.resource, NULL);
+ FREE(tx);
+ return NULL;
+ }
+
+ *ptransfer = &tx->base;
+ return tx->tmp.bo->map;
+}
+
+static void
+nv30_miptree_transfer_unmap(struct pipe_context *pipe,
+ struct pipe_transfer *ptx)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_transfer *tx = nv30_transfer(ptx);
+
+ if (ptx->usage & PIPE_TRANSFER_WRITE)
+ nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
+
+ nouveau_bo_ref(NULL, &tx->tmp.bo);
+ pipe_resource_reference(&ptx->resource, NULL);
+ FREE(tx);
+}
+
+const struct u_resource_vtbl nv30_miptree_vtbl = {
+ nv30_miptree_get_handle,
+ nv30_miptree_destroy,
+ nv30_miptree_transfer_map,
+ u_default_transfer_flush_region,
+ nv30_miptree_transfer_unmap,
+ u_default_transfer_inline_write
+};
+
+struct pipe_resource *
+nv30_miptree_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *tmpl)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree);
+ struct pipe_resource *pt = &mt->base.base;
+ unsigned blocksz, size;
+ unsigned w, h, d, l;
+ int ret;
+
+ switch (tmpl->nr_samples) {
+ case 4:
+ mt->ms_mode = 0x00004000;
+ mt->ms_x = 1;
+ mt->ms_y = 1;
+ break;
+ case 2:
+ mt->ms_mode = 0x00003000;
+ mt->ms_x = 1;
+ mt->ms_y = 0;
+ break;
+ default:
+ mt->ms_mode = 0x00000000;
+ mt->ms_x = 0;
+ mt->ms_y = 0;
+ break;
+ }
+
+ mt->base.vtbl = &nv30_miptree_vtbl;
+ *pt = *tmpl;
+ pipe_reference_init(&pt->reference, 1);
+ pt->screen = pscreen;
+
+ w = pt->width0 << mt->ms_x;
+ h = pt->height0 << mt->ms_y;
+ d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1;
+ blocksz = util_format_get_blocksize(pt->format);
+
+ if ((pt->target == PIPE_TEXTURE_RECT) ||
+ !util_is_power_of_two(pt->width0) ||
+ !util_is_power_of_two(pt->height0) ||
+ !util_is_power_of_two(pt->depth0) ||
+ util_format_is_compressed(pt->format) ||
+ util_format_is_float(pt->format) || mt->ms_mode) {
+ mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz;
+ mt->uniform_pitch = align(mt->uniform_pitch, 64);
+ }
+
+ if (!mt->uniform_pitch)
+ mt->swizzled = TRUE;
+
+ size = 0;
+ for (l = 0; l <= pt->last_level; l++) {
+ struct nv30_miptree_level *lvl = &mt->level[l];
+ unsigned nbx = util_format_get_nblocksx(pt->format, w);
+ unsigned nby = util_format_get_nblocksx(pt->format, h);
+
+ lvl->offset = size;
+ lvl->pitch = mt->uniform_pitch;
+ if (!lvl->pitch)
+ lvl->pitch = nbx * blocksz;
+
+ lvl->zslice_size = lvl->pitch * nby;
+ size += lvl->zslice_size * d;
+
+ w = u_minify(w, 1);
+ h = u_minify(h, 1);
+ d = u_minify(d, 1);
+ }
+
+ mt->layer_size = size;
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ if (!mt->uniform_pitch)
+ mt->layer_size = align(mt->layer_size, 128);
+ size = mt->layer_size * 6;
+ }
+
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo);
+ if (ret) {
+ FREE(mt);
+ return NULL;
+ }
+
+ mt->base.domain = NOUVEAU_BO_VRAM;
+ return &mt->base.base;
+}
+
+struct pipe_resource *
+nv30_miptree_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_resource *tmpl,
+ struct winsys_handle *handle)
+{
+ struct nv30_miptree *mt;
+ unsigned stride;
+
+ /* only supports 2D, non-mipmapped textures for the moment */
+ if ((tmpl->target != PIPE_TEXTURE_2D &&
+ tmpl->target != PIPE_TEXTURE_RECT) ||
+ tmpl->last_level != 0 ||
+ tmpl->depth0 != 1 ||
+ tmpl->array_size > 1)
+ return NULL;
+
+ mt = CALLOC_STRUCT(nv30_miptree);
+ if (!mt)
+ return NULL;
+
+ mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride);
+ if (mt->base.bo == NULL) {
+ FREE(mt);
+ return NULL;
+ }
+
+ mt->base.base = *tmpl;
+ mt->base.vtbl = &nv30_miptree_vtbl;
+ pipe_reference_init(&mt->base.base.reference, 1);
+ mt->base.base.screen = pscreen;
+ mt->uniform_pitch = stride;
+ mt->level[0].pitch = mt->uniform_pitch;
+ mt->level[0].offset = 0;
+
+ /* no need to adjust bo reference count */
+ return &mt->base.base;
+}
+
+struct pipe_surface *
+nv30_miptree_surface_new(struct pipe_context *pipe,
+ struct pipe_resource *pt,
+ const struct pipe_surface *tmpl)
+{
+ struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
+ struct nv30_surface *ns;
+ struct pipe_surface *ps;
+ struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];
+
+ ns = CALLOC_STRUCT(nv30_surface);
+ if (!ns)
+ return NULL;
+ ps = &ns->base;
+
+ pipe_reference_init(&ps->reference, 1);
+ pipe_resource_reference(&ps->texture, pt);
+ ps->context = pipe;
+ ps->format = tmpl->format;
+ ps->u.tex.level = tmpl->u.tex.level;
+ ps->u.tex.first_layer = tmpl->u.tex.first_layer;
+ ps->u.tex.last_layer = tmpl->u.tex.last_layer;
+
+ ns->width = u_minify(pt->width0, ps->u.tex.level);
+ ns->height = u_minify(pt->height0, ps->u.tex.level);
+ ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
+ ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
+ if (mt->swizzled)
+ ns->pitch = 4096; /* random, just something the hw won't reject.. */
+ else
+ ns->pitch = lvl->pitch;
+
+ /* comment says there are going to be removed, but they're used by the st */
+ ps->width = ns->width;
+ ps->height = ns->height;
+ return ps;
+}
+
+void
+nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
+{
+ struct nv30_surface *ns = nv30_surface(ps);
+
+ pipe_resource_reference(&ps->texture, NULL);
+ FREE(ns);
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_push.c b/src/gallium/drivers/nouveau/nv30/nv30_push.c
new file mode 100644
index 00000000000..e0734fa70d3
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_push.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "translate/translate.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_resource.h"
+
+struct push_context {
+ struct nouveau_pushbuf *push;
+
+ const void *idxbuf;
+
+ float edgeflag;
+ int edgeflag_attr;
+
+ uint32_t vertex_words;
+ uint32_t packet_vertex_limit;
+
+ struct translate *translate;
+
+ boolean primitive_restart;
+ uint32_t prim;
+ uint32_t restart_index;
+};
+
+static INLINE unsigned
+prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
+static INLINE unsigned
+prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
+static INLINE unsigned
+prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)
+{
+ unsigned i;
+ for (i = 0; i < push; ++i)
+ if (elts[i] == index)
+ break;
+ return i;
+}
+
+static void
+emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)
+{
+ uint8_t *elts = (uint8_t *)ctx->idxbuf + start;
+
+ while (count) {
+ unsigned push = MIN2(count, ctx->packet_vertex_limit);
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i08(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
+
+ BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
+
+ ctx->translate->run_elts8(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
+
+ ctx->push->cur += size;
+ count -= nr;
+ elts += nr;
+
+ if (nr != push) {
+ BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (ctx->push, ctx->restart_index);
+ count--;
+ elts++;
+ }
+ }
+}
+
+static void
+emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)
+{
+ uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
+
+ while (count) {
+ unsigned push = MIN2(count, ctx->packet_vertex_limit);
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i16(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
+
+ BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
+
+ ctx->translate->run_elts16(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
+
+ ctx->push->cur += size;
+ count -= nr;
+ elts += nr;
+
+ if (nr != push) {
+ BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (ctx->push, ctx->restart_index);
+ count--;
+ elts++;
+ }
+ }
+}
+
+static void
+emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)
+{
+ uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
+
+ while (count) {
+ unsigned push = MIN2(count, ctx->packet_vertex_limit);
+ unsigned size, nr;
+
+ nr = push;
+ if (ctx->primitive_restart)
+ nr = prim_restart_search_i32(elts, push, ctx->restart_index);
+
+ size = ctx->vertex_words * nr;
+
+ BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
+
+ ctx->translate->run_elts(ctx->translate, elts, nr, 0, 0, ctx->push->cur);
+
+ ctx->push->cur += size;
+ count -= nr;
+ elts += nr;
+
+ if (nr != push) {
+ BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (ctx->push, ctx->restart_index);
+ count--;
+ elts++;
+ }
+ }
+}
+
+static void
+emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)
+{
+ while (count) {
+ unsigned push = MIN2(count, ctx->packet_vertex_limit);
+ unsigned size = ctx->vertex_words * push;
+
+ BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size);
+
+ ctx->translate->run(ctx->translate, start, push, 0, 0, ctx->push->cur);
+ ctx->push->cur += size;
+ count -= push;
+ start += push;
+ }
+}
+
+void
+nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info)
+{
+ struct push_context ctx;
+ unsigned i, index_size;
+ boolean apply_bias = info->indexed && info->index_bias;
+
+ ctx.push = nv30->base.pushbuf;
+ ctx.translate = nv30->vertex->translate;
+ ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max;
+ ctx.vertex_words = nv30->vertex->vtx_size;
+
+ for (i = 0; i < nv30->num_vtxbufs; ++i) {
+ uint8_t *data;
+ struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i];
+ struct nv04_resource *res = nv04_resource(vb->buffer);
+
+ if (!vb->buffer && !vb->user_buffer) {
+ continue;
+ }
+
+ data = nouveau_resource_map_offset(&nv30->base, res,
+ vb->buffer_offset, NOUVEAU_BO_RD);
+
+ if (apply_bias)
+ data += info->index_bias * vb->stride;
+
+ ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
+ }
+
+ if (info->indexed) {
+ if (nv30->idxbuf.buffer)
+ ctx.idxbuf = nouveau_resource_map_offset(&nv30->base,
+ nv04_resource(nv30->idxbuf.buffer), nv30->idxbuf.offset,
+ NOUVEAU_BO_RD);
+ else
+ ctx.idxbuf = nv30->idxbuf.user_buffer;
+ if (!ctx.idxbuf) {
+ nv30_state_release(nv30);
+ return;
+ }
+ index_size = nv30->idxbuf.index_size;
+ ctx.primitive_restart = info->primitive_restart;
+ ctx.restart_index = info->restart_index;
+ } else {
+ ctx.idxbuf = NULL;
+ index_size = 0;
+ ctx.primitive_restart = FALSE;
+ ctx.restart_index = 0;
+ }
+
+ if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2);
+ PUSH_DATA (ctx.push, info->primitive_restart);
+ PUSH_DATA (ctx.push, info->restart_index);
+ nv30->state.prim_restart = info->primitive_restart;
+ }
+
+ ctx.prim = nv30_prim_gl(info->mode);
+
+ PUSH_RESET(ctx.push, BUFCTX_IDXBUF);
+ BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (ctx.push, ctx.prim);
+ switch (index_size) {
+ case 0:
+ emit_vertices_seq(&ctx, info->start, info->count);
+ break;
+ case 1:
+ emit_vertices_i08(&ctx, info->start, info->count);
+ break;
+ case 2:
+ emit_vertices_i16(&ctx, info->start, info->count);
+ break;
+ case 4:
+ emit_vertices_i32(&ctx, info->start, info->count);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP);
+
+ if (info->indexed)
+ nouveau_resource_unmap(nv04_resource(nv30->idxbuf.buffer));
+
+ for (i = 0; i < nv30->num_vtxbufs; ++i) {
+ if (nv30->vtxbuf[i].buffer) {
+ nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer));
+ }
+ }
+
+ nv30_state_release(nv30);
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_query.c b/src/gallium/drivers/nouveau/nv30/nv30_query.c
new file mode 100644
index 00000000000..01b3817c45d
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_query.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_screen.h"
+#include "nv30/nv30_context.h"
+
+#define LIST_FIRST_ENTRY(__type, __item, __field) \
+ LIST_ENTRY(__type, (__item)->next, __field)
+
+struct nv30_query_object {
+ struct list_head list;
+ struct nouveau_heap *hw;
+};
+
+static volatile void *
+nv30_ntfy(struct nv30_screen *screen, struct nv30_query_object *qo)
+{
+ struct nv04_notify *query = screen->query->data;
+ struct nouveau_bo *notify = screen->notify;
+ volatile void *ntfy = NULL;
+
+ if (qo && qo->hw)
+ ntfy = (char *)notify->map + query->offset + qo->hw->start;
+
+ return ntfy;
+}
+
+static void
+nv30_query_object_del(struct nv30_screen *screen, struct nv30_query_object **po)
+{
+ struct nv30_query_object *qo = *po; *po = NULL;
+ if (qo) {
+ volatile uint32_t *ntfy = nv30_ntfy(screen, qo);
+ while (ntfy[3] & 0xff000000) {
+ }
+ nouveau_heap_free(&qo->hw);
+ LIST_DEL(&qo->list);
+ FREE(qo);
+ }
+}
+
+static struct nv30_query_object *
+nv30_query_object_new(struct nv30_screen *screen)
+{
+ struct nv30_query_object *oq, *qo = CALLOC_STRUCT(nv30_query_object);
+ volatile uint32_t *ntfy;
+
+ if (!qo)
+ return NULL;
+
+ /* allocate a new hw query object, if no hw objects left we need to
+ * spin waiting for one to become free
+ */
+ while (nouveau_heap_alloc(screen->query_heap, 32, NULL, &qo->hw)) {
+ oq = LIST_FIRST_ENTRY(struct nv30_query_object, &screen->queries, list);
+ nv30_query_object_del(screen, &oq);
+ }
+
+ LIST_ADDTAIL(&qo->list, &screen->queries);
+
+ ntfy = nv30_ntfy(screen, qo);
+ ntfy[0] = 0x00000000;
+ ntfy[1] = 0x00000000;
+ ntfy[2] = 0x00000000;
+ ntfy[3] = 0x01000000;
+ return qo;
+}
+
+struct nv30_query {
+ struct nv30_query_object *qo[2];
+ unsigned type;
+ uint32_t report;
+ uint32_t enable;
+ uint64_t result;
+};
+
+static INLINE struct nv30_query *
+nv30_query(struct pipe_query *pipe)
+{
+ return (struct nv30_query *)pipe;
+}
+
+static struct pipe_query *
+nv30_query_create(struct pipe_context *pipe, unsigned type)
+{
+ struct nv30_query *q = CALLOC_STRUCT(nv30_query);
+ if (!q)
+ return NULL;
+
+ q->type = type;
+
+ switch (q->type) {
+ case PIPE_QUERY_TIMESTAMP:
+ case PIPE_QUERY_TIME_ELAPSED:
+ q->enable = 0x0000;
+ q->report = 1;
+ break;
+ case PIPE_QUERY_OCCLUSION_COUNTER:
+ q->enable = NV30_3D_QUERY_ENABLE;
+ q->report = 1;
+ break;
+ case NV30_QUERY_ZCULL_0:
+ case NV30_QUERY_ZCULL_1:
+ case NV30_QUERY_ZCULL_2:
+ case NV30_QUERY_ZCULL_3:
+ q->enable = 0x1804;
+ q->report = 2 + (q->type - NV30_QUERY_ZCULL_0);
+ break;
+ default:
+ FREE(q);
+ return NULL;
+ }
+
+ return (struct pipe_query *)q;
+}
+
+static void
+nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ FREE(pq);
+}
+
+static void
+nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_query *q = nv30_query(pq);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ switch (q->type) {
+ case PIPE_QUERY_TIME_ELAPSED:
+ q->qo[0] = nv30_query_object_new(nv30->screen);
+ if (q->qo[0]) {
+ BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
+ PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start);
+ }
+ break;
+ case PIPE_QUERY_TIMESTAMP:
+ return;
+ default:
+ BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1);
+ PUSH_DATA (push, q->report);
+ break;
+ }
+
+ if (q->enable) {
+ BEGIN_NV04(push, SUBC_3D(q->enable), 1);
+ PUSH_DATA (push, 1);
+ }
+}
+
+static void
+nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_screen *screen = nv30->screen;
+ struct nv30_query *q = nv30_query(pq);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ q->qo[1] = nv30_query_object_new(screen);
+ if (q->qo[1]) {
+ BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
+ PUSH_DATA (push, (q->report << 24) | q->qo[1]->hw->start);
+ }
+
+ if (q->enable) {
+ BEGIN_NV04(push, SUBC_3D(q->enable), 1);
+ PUSH_DATA (push, 0);
+ }
+ PUSH_KICK (push);
+}
+
+static boolean
+nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+ boolean wait, union pipe_query_result *result)
+{
+ struct nv30_screen *screen = nv30_screen(pipe->screen);
+ struct nv30_query *q = nv30_query(pq);
+ volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]);
+ volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]);
+ uint64_t *res64 = &result->u64;
+
+ if (ntfy1) {
+ while (ntfy1[3] & 0xff000000) {
+ if (!wait)
+ return FALSE;
+ }
+
+ switch (q->type) {
+ case PIPE_QUERY_TIMESTAMP:
+ q->result = *(uint64_t *)&ntfy1[0];
+ break;
+ case PIPE_QUERY_TIME_ELAPSED:
+ q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0];
+ break;
+ default:
+ q->result = ntfy1[2];
+ break;
+ }
+
+ nv30_query_object_del(screen, &q->qo[0]);
+ nv30_query_object_del(screen, &q->qo[1]);
+ }
+
+ *res64 = q->result;
+ return TRUE;
+}
+
+static void
+nv40_query_render_condition(struct pipe_context *pipe,
+ struct pipe_query *pq,
+ boolean condition, uint mode)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nv30_query *q = nv30_query(pq);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ nv30->render_cond_query = pq;
+ nv30->render_cond_mode = mode;
+ nv30->render_cond_cond = condition;
+
+ if (!pq) {
+ BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
+ PUSH_DATA (push, 0x01000000);
+ return;
+ }
+
+ if (mode == PIPE_RENDER_COND_WAIT ||
+ mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
+ BEGIN_NV04(push, SUBC_3D(0x0110), 1);
+ PUSH_DATA (push, 0);
+ }
+
+ BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
+ PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start);
+}
+
+void
+nv30_query_init(struct pipe_context *pipe)
+{
+ struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
+
+ pipe->create_query = nv30_query_create;
+ pipe->destroy_query = nv30_query_destroy;
+ pipe->begin_query = nv30_query_begin;
+ pipe->end_query = nv30_query_end;
+ pipe->get_query_result = nv30_query_result;
+ if (eng3d->oclass >= NV40_3D_CLASS)
+ pipe->render_condition = nv40_query_render_condition;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_resource.c b/src/gallium/drivers/nouveau/nv30/nv30_resource.c
new file mode 100644
index 00000000000..c99db1ce91b
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_resource.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+
+#include "nv30/nv30_screen.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_resource.h"
+#include "nv30/nv30_transfer.h"
+
+static struct pipe_resource *
+nv30_resource_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *tmpl)
+{
+ switch (tmpl->target) {
+ case PIPE_BUFFER:
+ return nouveau_buffer_create(pscreen, tmpl);
+ default:
+ return nv30_miptree_create(pscreen, tmpl);
+ }
+}
+
+static struct pipe_resource *
+nv30_resource_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_resource *tmpl,
+ struct winsys_handle *handle)
+{
+ if (tmpl->target == PIPE_BUFFER)
+ return NULL;
+ else
+ return nv30_miptree_from_handle(pscreen, tmpl, handle);
+}
+
+void
+nv30_resource_screen_init(struct pipe_screen *pscreen)
+{
+ pscreen->resource_create = nv30_resource_create;
+ pscreen->resource_from_handle = nv30_resource_from_handle;
+ pscreen->resource_get_handle = u_resource_get_handle_vtbl;
+ pscreen->resource_destroy = u_resource_destroy_vtbl;
+}
+
+void
+nv30_resource_init(struct pipe_context *pipe)
+{
+ pipe->transfer_map = u_transfer_map_vtbl;
+ pipe->transfer_flush_region = u_transfer_flush_region_vtbl;
+ pipe->transfer_unmap = u_transfer_unmap_vtbl;
+ pipe->transfer_inline_write = u_transfer_inline_write_vtbl;
+ pipe->create_surface = nv30_miptree_surface_new;
+ pipe->surface_destroy = nv30_miptree_surface_del;
+ pipe->resource_copy_region = nv30_resource_copy_region;
+ pipe->blit = nv30_blit;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_resource.h b/src/gallium/drivers/nouveau/nv30/nv30_resource.h
new file mode 100644
index 00000000000..aff41966b3c
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_resource.h
@@ -0,0 +1,75 @@
+#ifndef __NV30_RESOURCE_H__
+#define __NV30_RESOURCE_H__
+
+#include "nouveau_buffer.h"
+
+void nv30_resource_screen_init(struct pipe_screen *);
+void nv30_resource_init(struct pipe_context *);
+
+struct nv30_surface {
+ struct pipe_surface base;
+ uint32_t offset;
+ uint32_t pitch;
+ uint32_t width;
+ uint16_t height;
+ uint16_t depth;
+};
+
+static INLINE struct nv30_surface *
+nv30_surface(struct pipe_surface *ps)
+{
+ return (struct nv30_surface *)ps;
+}
+
+struct nv30_miptree_level {
+ uint32_t offset;
+ uint32_t pitch;
+ uint32_t zslice_size;
+};
+
+struct nv30_miptree {
+ struct nv04_resource base;
+ struct nv30_miptree_level level[13];
+ uint32_t uniform_pitch;
+ uint32_t layer_size;
+ boolean swizzled;
+ unsigned ms_mode;
+ unsigned ms_x:1;
+ unsigned ms_y:1;
+};
+
+static INLINE struct nv30_miptree *
+nv30_miptree(struct pipe_resource *pt)
+{
+ return (struct nv30_miptree *)pt;
+}
+
+struct pipe_resource *
+nv30_miptree_create(struct pipe_screen *, const struct pipe_resource *);
+
+struct pipe_resource *
+nv30_miptree_from_handle(struct pipe_screen *, const struct pipe_resource *,
+ struct winsys_handle *);
+
+struct pipe_surface *
+nv30_miptree_surface_new(struct pipe_context *, struct pipe_resource *,
+ const struct pipe_surface *);
+
+void
+nv30_miptree_surface_del(struct pipe_context *, struct pipe_surface *);
+
+void
+nv30_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst, unsigned dst_level,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src, unsigned src_level,
+ const struct pipe_box *src_box);
+
+void
+nv30_resource_resolve(struct pipe_context *, const struct pipe_resolve_info *);
+
+void
+nv30_blit(struct pipe_context *pipe,
+ const struct pipe_blit_info *blit_info);
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
new file mode 100644
index 00000000000..50ddfec3b21
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_format_s3tc.h"
+
+#include "nv_object.xml.h"
+#include "nv_m2mf.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv01_2d.xml.h"
+
+#include "nouveau_fence.h"
+#include "nv30/nv30_screen.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_resource.h"
+#include "nv30/nv30_format.h"
+
+#define RANKINE_0397_CHIPSET 0x00000003
+#define RANKINE_0497_CHIPSET 0x000001e0
+#define RANKINE_0697_CHIPSET 0x00000010
+#define CURIE_4097_CHIPSET 0x00000baf
+#define CURIE_4497_CHIPSET 0x00005450
+#define CURIE_4497_CHIPSET6X 0x00000088
+
+static int
+nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nouveau_object *eng3d = screen->eng3d;
+
+ switch (param) {
+ /* non-boolean capabilities */
+ case PIPE_CAP_MAX_RENDER_TARGETS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 4 : 1;
+ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+ return 10;
+ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+ return 13;
+ case PIPE_CAP_MAX_COMBINED_SAMPLERS:
+ return 16;
+ case PIPE_CAP_GLSL_FEATURE_LEVEL:
+ return 120;
+ /* supported capabilities */
+ case PIPE_CAP_TWO_SIDED_STENCIL:
+ case PIPE_CAP_ANISOTROPIC_FILTER:
+ case PIPE_CAP_POINT_SPRITE:
+ case PIPE_CAP_SCALED_RESOLVE:
+ case PIPE_CAP_OCCLUSION_QUERY:
+ case PIPE_CAP_QUERY_TIME_ELAPSED:
+ case PIPE_CAP_QUERY_TIMESTAMP:
+ case PIPE_CAP_TEXTURE_SHADOW_MAP:
+ case PIPE_CAP_TEXTURE_SWIZZLE:
+ case PIPE_CAP_DEPTH_CLIP_DISABLE:
+ case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
+ case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
+ case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
+ case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
+ case PIPE_CAP_TGSI_TEXCOORD:
+ case PIPE_CAP_USER_CONSTANT_BUFFERS:
+ case PIPE_CAP_USER_INDEX_BUFFERS:
+ return 1;
+ case PIPE_CAP_USER_VERTEX_BUFFERS:
+ return 0;
+ case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+ return 16;
+ /* nv4x capabilities */
+ case PIPE_CAP_BLEND_EQUATION_SEPARATE:
+ case PIPE_CAP_NPOT_TEXTURES:
+ case PIPE_CAP_CONDITIONAL_RENDER:
+ case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ case PIPE_CAP_PRIMITIVE_RESTART:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0;
+ /* unsupported */
+ case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
+ case PIPE_CAP_SM3:
+ case PIPE_CAP_INDEP_BLEND_ENABLE:
+ case PIPE_CAP_INDEP_BLEND_FUNC:
+ case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+ case PIPE_CAP_SHADER_STENCIL_EXPORT:
+ case PIPE_CAP_TGSI_INSTANCEID:
+ case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: /* XXX: yes? */
+ case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
+ case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+ case PIPE_CAP_MIN_TEXEL_OFFSET:
+ case PIPE_CAP_MAX_TEXEL_OFFSET:
+ case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
+ case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
+ case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
+ case PIPE_CAP_TEXTURE_BARRIER:
+ case PIPE_CAP_SEAMLESS_CUBE_MAP:
+ case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
+ case PIPE_CAP_CUBE_MAP_ARRAY:
+ case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
+ case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
+ case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
+ case PIPE_CAP_START_INSTANCE:
+ case PIPE_CAP_TEXTURE_MULTISAMPLE:
+ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
+ case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+ case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+ case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
+ case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+ case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
+ return 0;
+ case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
+ return 1;
+ case PIPE_CAP_ENDIANNESS:
+ return PIPE_ENDIAN_LITTLE;
+ default:
+ debug_printf("unknown param %d\n", param);
+ return 0;
+ }
+}
+
+static float
+nv30_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nouveau_object *eng3d = screen->eng3d;
+
+ switch (param) {
+ case PIPE_CAPF_MAX_LINE_WIDTH:
+ case PIPE_CAPF_MAX_LINE_WIDTH_AA:
+ return 10.0;
+ case PIPE_CAPF_MAX_POINT_WIDTH:
+ case PIPE_CAPF_MAX_POINT_WIDTH_AA:
+ return 64.0;
+ case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 16.0 : 8.0;
+ case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
+ return 15.0;
+ default:
+ debug_printf("unknown paramf %d\n", param);
+ return 0;
+ }
+}
+
+static int
+nv30_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
+ enum pipe_shader_cap param)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nouveau_object *eng3d = screen->eng3d;
+
+ switch (shader) {
+ case PIPE_SHADER_VERTEX:
+ switch (param) {
+ case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 512 : 256;
+ case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 512 : 0;
+ case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+ return 0;
+ case PIPE_SHADER_CAP_MAX_INPUTS:
+ return 16;
+ case PIPE_SHADER_CAP_MAX_CONSTS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? (468 - 6): (256 - 6);
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+ return 1;
+ case PIPE_SHADER_CAP_MAX_TEMPS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 32 : 13;
+ case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+ return 0;
+ case PIPE_SHADER_CAP_MAX_ADDRS:
+ return 2;
+ case PIPE_SHADER_CAP_MAX_PREDS:
+ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+ case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
+ case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+ case PIPE_SHADER_CAP_SUBROUTINES:
+ case PIPE_SHADER_CAP_INTEGERS:
+ return 0;
+ default:
+ debug_printf("unknown vertex shader param %d\n", param);
+ return 0;
+ }
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ switch (param) {
+ case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
+ case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
+ return 4096;
+ case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
+ return 0;
+ case PIPE_SHADER_CAP_MAX_INPUTS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 12 : 10;
+ case PIPE_SHADER_CAP_MAX_CONSTS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 224 : 32;
+ case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
+ return 1;
+ case PIPE_SHADER_CAP_MAX_TEMPS:
+ return 32;
+ case PIPE_SHADER_CAP_MAX_ADDRS:
+ return (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0;
+ case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
+ return 16;
+ case PIPE_SHADER_CAP_MAX_PREDS:
+ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
+ case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
+ case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
+ case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
+ case PIPE_SHADER_CAP_SUBROUTINES:
+ return 0;
+ default:
+ debug_printf("unknown fragment shader param %d\n", param);
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+}
+
+static boolean
+nv30_screen_is_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned sample_count,
+ unsigned bindings)
+{
+ if (sample_count > 4)
+ return FALSE;
+ if (!(0x00000017 & (1 << sample_count)))
+ return FALSE;
+
+ if (!util_format_is_supported(format, bindings)) {
+ return FALSE;
+ }
+
+ /* transfers & shared are always supported */
+ bindings &= ~(PIPE_BIND_TRANSFER_READ |
+ PIPE_BIND_TRANSFER_WRITE |
+ PIPE_BIND_SHARED);
+
+ return (nv30_format_info(pscreen, format)->bindings & bindings) == bindings;
+}
+
+static void
+nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nouveau_pushbuf *push = screen->base.pushbuf;
+
+ *sequence = ++screen->base.fence.sequence;
+
+ BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, *sequence);
+}
+
+static uint32_t
+nv30_screen_fence_update(struct pipe_screen *pscreen)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+ struct nv04_notify *fence = screen->fence->data;
+ return *(uint32_t *)((char *)screen->notify->map + fence->offset);
+}
+
+static void
+nv30_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv30_screen *screen = nv30_screen(pscreen);
+
+ if (screen->base.fence.current &&
+ screen->base.fence.current->state >= NOUVEAU_FENCE_STATE_EMITTED) {
+ nouveau_fence_wait(screen->base.fence.current);
+ nouveau_fence_ref (NULL, &screen->base.fence.current);
+ }
+
+ nouveau_object_del(&screen->query);
+ nouveau_object_del(&screen->fence);
+ nouveau_object_del(&screen->ntfy);
+
+ nouveau_object_del(&screen->sifm);
+ nouveau_object_del(&screen->swzsurf);
+ nouveau_object_del(&screen->surf2d);
+ nouveau_object_del(&screen->m2mf);
+ nouveau_object_del(&screen->eng3d);
+ nouveau_object_del(&screen->null);
+
+ nouveau_screen_fini(&screen->base);
+ FREE(screen);
+}
+
+#define FAIL_SCREEN_INIT(str, err) \
+ do { \
+ NOUVEAU_ERR(str, err); \
+ nv30_screen_destroy(pscreen); \
+ return NULL; \
+ } while(0)
+
+struct pipe_screen *
+nv30_screen_create(struct nouveau_device *dev)
+{
+ struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
+ struct pipe_screen *pscreen;
+ struct nouveau_pushbuf *push;
+ struct nv04_fifo *fifo;
+ unsigned oclass = 0;
+ int ret, i;
+
+ if (!screen)
+ return NULL;
+
+ switch (dev->chipset & 0xf0) {
+ case 0x30:
+ if (RANKINE_0397_CHIPSET & (1 << (dev->chipset & 0x0f)))
+ oclass = NV30_3D_CLASS;
+ else
+ if (RANKINE_0697_CHIPSET & (1 << (dev->chipset & 0x0f)))
+ oclass = NV34_3D_CLASS;
+ else
+ if (RANKINE_0497_CHIPSET & (1 << (dev->chipset & 0x0f)))
+ oclass = NV35_3D_CLASS;
+ break;
+ case 0x40:
+ if (CURIE_4097_CHIPSET & (1 << (dev->chipset & 0x0f)))
+ oclass = NV40_3D_CLASS;
+ else
+ if (CURIE_4497_CHIPSET & (1 << (dev->chipset & 0x0f)))
+ oclass = NV44_3D_CLASS;
+ break;
+ case 0x60:
+ if (CURIE_4497_CHIPSET6X & (1 << (dev->chipset & 0x0f)))
+ oclass = NV44_3D_CLASS;
+ break;
+ default:
+ break;
+ }
+
+ if (!oclass) {
+ NOUVEAU_ERR("unknown 3d class for 0x%02x\n", dev->chipset);
+ FREE(screen);
+ return NULL;
+ }
+
+ pscreen = &screen->base.base;
+ pscreen->destroy = nv30_screen_destroy;
+ pscreen->get_param = nv30_screen_get_param;
+ pscreen->get_paramf = nv30_screen_get_paramf;
+ pscreen->get_shader_param = nv30_screen_get_shader_param;
+ pscreen->context_create = nv30_context_create;
+ pscreen->is_format_supported = nv30_screen_is_format_supported;
+ nv30_resource_screen_init(pscreen);
+ nouveau_screen_init_vdec(&screen->base);
+
+ screen->base.fence.emit = nv30_screen_fence_emit;
+ screen->base.fence.update = nv30_screen_fence_update;
+
+ ret = nouveau_screen_init(&screen->base, dev);
+ if (ret)
+ FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);
+
+ screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
+ screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
+ if (oclass == NV40_3D_CLASS) {
+ screen->base.vidmem_bindings |= PIPE_BIND_INDEX_BUFFER;
+ screen->base.sysmem_bindings |= PIPE_BIND_INDEX_BUFFER;
+ }
+
+ fifo = screen->base.channel->data;
+ push = screen->base.pushbuf;
+ push->rsvd_kick = 16;
+
+ ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS,
+ NULL, 0, &screen->null);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating null object: %d\n", ret);
+
+ /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
+ * this means that the address pointed at by the DMA object must
+ * be 4KiB aligned, which means this object needs to be the first
+ * one allocated on the channel.
+ */
+ ret = nouveau_object_new(screen->base.channel, 0xbeef1e00,
+ NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
+ .length = 32 }, sizeof(struct nv04_notify),
+ &screen->fence);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating fence notifier: %d\n", ret);
+
+ /* DMA_NOTIFY object, we don't actually use this but M2MF fails without */
+ ret = nouveau_object_new(screen->base.channel, 0xbeef0301,
+ NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
+ .length = 32 }, sizeof(struct nv04_notify),
+ &screen->ntfy);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating sync notifier: %d\n", ret);
+
+ /* DMA_QUERY, used to implement occlusion queries, we attempt to allocate
+ * the remainder of the "notifier block" assigned by the kernel for
+ * use as query objects
+ */
+ ret = nouveau_object_new(screen->base.channel, 0xbeef0351,
+ NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
+ .length = 4096 - 128 }, sizeof(struct nv04_notify),
+ &screen->query);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating query notifier: %d\n", ret);
+
+ ret = nouveau_heap_init(&screen->query_heap, 0, 4096 - 128);
+ if (ret)
+ FAIL_SCREEN_INIT("error creating query heap: %d\n", ret);
+
+ LIST_INITHEAD(&screen->queries);
+
+ /* Vertex program resources (code/data), currently 6 of the constant
+ * slots are reserved to implement user clipping planes
+ */
+ if (oclass < NV40_3D_CLASS) {
+ nouveau_heap_init(&screen->vp_exec_heap, 0, 256);
+ nouveau_heap_init(&screen->vp_data_heap, 6, 256 - 6);
+ } else {
+ nouveau_heap_init(&screen->vp_exec_heap, 0, 512);
+ nouveau_heap_init(&screen->vp_data_heap, 6, 468 - 6);
+ }
+
+ ret = nouveau_bo_wrap(screen->base.device, fifo->notify, &screen->notify);
+ if (ret == 0)
+ nouveau_bo_map(screen->notify, 0, screen->base.client);
+ if (ret)
+ FAIL_SCREEN_INIT("error mapping notifier memory: %d\n", ret);
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef3097, oclass,
+ NULL, 0, &screen->eng3d);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating 3d object: %d\n", ret);
+
+ BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
+ PUSH_DATA (push, screen->eng3d->handle);
+ BEGIN_NV04(push, NV30_3D(DMA_NOTIFY), 13);
+ PUSH_DATA (push, screen->ntfy->handle);
+ PUSH_DATA (push, fifo->vram); /* TEXTURE0 */
+ PUSH_DATA (push, fifo->gart); /* TEXTURE1 */
+ PUSH_DATA (push, fifo->vram); /* COLOR1 */
+ PUSH_DATA (push, screen->null->handle); /* UNK190 */
+ PUSH_DATA (push, fifo->vram); /* COLOR0 */
+ PUSH_DATA (push, fifo->vram); /* ZETA */
+ PUSH_DATA (push, fifo->vram); /* VTXBUF0 */
+ PUSH_DATA (push, fifo->gart); /* VTXBUF1 */
+ PUSH_DATA (push, screen->fence->handle); /* FENCE */
+ PUSH_DATA (push, screen->query->handle); /* QUERY - intr 0x80 if nullobj */
+ PUSH_DATA (push, screen->null->handle); /* UNK1AC */
+ PUSH_DATA (push, screen->null->handle); /* UNK1B0 */
+ if (screen->eng3d->oclass < NV40_3D_CLASS) {
+ BEGIN_NV04(push, SUBC_3D(0x03b0), 1);
+ PUSH_DATA (push, 0x00100000);
+ BEGIN_NV04(push, SUBC_3D(0x1d80), 1);
+ PUSH_DATA (push, 3);
+
+ BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, SUBC_3D(0x17e0), 3);
+ PUSH_DATA (push, fui(0.0));
+ PUSH_DATA (push, fui(0.0));
+ PUSH_DATA (push, fui(1.0));
+ BEGIN_NV04(push, SUBC_3D(0x1f80), 16);
+ for (i = 0; i < 16; i++)
+ PUSH_DATA (push, (i == 8) ? 0x0000ffff : 0);
+
+ BEGIN_NV04(push, NV30_3D(RC_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ } else {
+ BEGIN_NV04(push, NV40_3D(DMA_COLOR2), 2);
+ PUSH_DATA (push, fifo->vram);
+ PUSH_DATA (push, fifo->vram); /* COLOR3 */
+
+ BEGIN_NV04(push, SUBC_3D(0x1450), 1);
+ PUSH_DATA (push, 0x00000004);
+
+ BEGIN_NV04(push, SUBC_3D(0x1ea4), 3); /* ZCULL */
+ PUSH_DATA (push, 0x00000010);
+ PUSH_DATA (push, 0x01000100);
+ PUSH_DATA (push, 0xff800006);
+
+ /* vtxprog output routing */
+ BEGIN_NV04(push, SUBC_3D(0x1fc4), 1);
+ PUSH_DATA (push, 0x06144321);
+ BEGIN_NV04(push, SUBC_3D(0x1fc8), 2);
+ PUSH_DATA (push, 0xedcba987);
+ PUSH_DATA (push, 0x0000006f);
+ BEGIN_NV04(push, SUBC_3D(0x1fd0), 1);
+ PUSH_DATA (push, 0x00171615);
+ BEGIN_NV04(push, SUBC_3D(0x1fd4), 1);
+ PUSH_DATA (push, 0x001b1a19);
+
+ BEGIN_NV04(push, SUBC_3D(0x1ef8), 1);
+ PUSH_DATA (push, 0x0020ffff);
+ BEGIN_NV04(push, SUBC_3D(0x1d64), 1);
+ PUSH_DATA (push, 0x01d300d4);
+
+ BEGIN_NV04(push, NV40_3D(MIPMAP_ROUNDING), 1);
+ PUSH_DATA (push, NV40_3D_MIPMAP_ROUNDING_MODE_DOWN);
+ }
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef3901, NV03_M2MF_CLASS,
+ NULL, 0, &screen->m2mf);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating m2mf object: %d\n", ret);
+
+ BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
+ PUSH_DATA (push, screen->m2mf->handle);
+ BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
+ PUSH_DATA (push, screen->ntfy->handle);
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef6201,
+ NV10_SURFACE_2D_CLASS, NULL, 0, &screen->surf2d);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating surf2d object: %d\n", ret);
+
+ BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
+ PUSH_DATA (push, screen->surf2d->handle);
+ BEGIN_NV04(push, NV04_SF2D(DMA_NOTIFY), 1);
+ PUSH_DATA (push, screen->ntfy->handle);
+
+ if (dev->chipset < 0x40)
+ oclass = NV30_SURFACE_SWZ_CLASS;
+ else
+ oclass = NV40_SURFACE_SWZ_CLASS;
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef5201, oclass,
+ NULL, 0, &screen->swzsurf);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating swizzled surface object: %d\n", ret);
+
+ BEGIN_NV04(push, NV01_SUBC(SSWZ, OBJECT), 1);
+ PUSH_DATA (push, screen->swzsurf->handle);
+ BEGIN_NV04(push, NV04_SSWZ(DMA_NOTIFY), 1);
+ PUSH_DATA (push, screen->ntfy->handle);
+
+ if (dev->chipset < 0x40)
+ oclass = NV30_SIFM_CLASS;
+ else
+ oclass = NV40_SIFM_CLASS;
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef7701, oclass,
+ NULL, 0, &screen->sifm);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating scaled image object: %d\n", ret);
+
+ BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
+ PUSH_DATA (push, screen->sifm->handle);
+ BEGIN_NV04(push, NV03_SIFM(DMA_NOTIFY), 1);
+ PUSH_DATA (push, screen->ntfy->handle);
+ BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
+ PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE);
+
+ nouveau_pushbuf_kick(push, push->channel);
+
+ nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE);
+ return pscreen;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.h b/src/gallium/drivers/nouveau/nv30/nv30_screen.h
new file mode 100644
index 00000000000..c4c3aae52d9
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.h
@@ -0,0 +1,51 @@
+#ifndef __NV30_SCREEN_H__
+#define __NV30_SCREEN_H__
+
+#include <stdio.h>
+
+#define NOUVEAU_ERR(fmt, args...) \
+ fprintf(stderr, "%s:%d - "fmt, __FUNCTION__, __LINE__, ##args);
+
+#include "util/u_double_list.h"
+
+#include "nouveau_screen.h"
+#include "nouveau_fence.h"
+#include "nouveau_heap.h"
+#include "nv30/nv30_winsys.h"
+#include "nv30/nv30_resource.h"
+
+struct nv30_context;
+
+struct nv30_screen {
+ struct nouveau_screen base;
+
+ struct nv30_context *cur_ctx;
+
+ struct nouveau_bo *notify;
+
+ struct nouveau_object *ntfy;
+ struct nouveau_object *fence;
+
+ struct nouveau_object *query;
+ struct nouveau_heap *query_heap;
+ struct list_head queries;
+
+ struct nouveau_object *null;
+ struct nouveau_object *eng3d;
+ struct nouveau_object *m2mf;
+ struct nouveau_object *surf2d;
+ struct nouveau_object *swzsurf;
+ struct nouveau_object *sifm;
+
+ /*XXX: nvfx state */
+ struct nouveau_heap *vp_exec_heap;
+ struct nouveau_heap *vp_data_heap;
+};
+
+static INLINE struct nv30_screen *
+nv30_screen(struct pipe_screen *pscreen)
+{
+ return (struct nv30_screen *)pscreen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state.c b/src/gallium/drivers/nouveau/nv30/nv30_state.c
new file mode 100644
index 00000000000..64be1b78f79
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_state.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_helpers.h"
+#include "util/u_inlines.h"
+
+#include "nouveau_gldefs.h"
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_winsys.h"
+
+#define NV40_3D_MRT_BLEND_ENABLE 0x0000036c
+
+static void *
+nv30_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
+ struct nv30_blend_stateobj *so;
+ uint32_t blend[2], cmask[2];
+ int i;
+
+ so = CALLOC_STRUCT(nv30_blend_stateobj);
+ if (!so)
+ return NULL;
+ so->pipe = *cso;
+
+ if (cso->logicop_enable) {
+ SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 2);
+ SB_DATA (so, 1);
+ SB_DATA (so, nvgl_logicop_func(cso->logicop_func));
+ } else {
+ SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 1);
+ SB_DATA (so, 0);
+ }
+
+ SB_MTHD30(so, DITHER_ENABLE, 1);
+ SB_DATA (so, cso->dither);
+
+ blend[0] = cso->rt[0].blend_enable;
+ cmask[0] = !!(cso->rt[0].colormask & PIPE_MASK_A) << 24 |
+ !!(cso->rt[0].colormask & PIPE_MASK_R) << 16 |
+ !!(cso->rt[0].colormask & PIPE_MASK_G) << 8 |
+ !!(cso->rt[0].colormask & PIPE_MASK_B);
+ if (cso->independent_blend_enable) {
+ blend[1] = 0;
+ cmask[1] = 0;
+ for (i = 1; i < 4; i++) {
+ blend[1] |= cso->rt[i].blend_enable << i;
+ cmask[1] |= !!(cso->rt[i].colormask & PIPE_MASK_A) << (0 + (i * 4)) |
+ !!(cso->rt[i].colormask & PIPE_MASK_R) << (1 + (i * 4)) |
+ !!(cso->rt[i].colormask & PIPE_MASK_G) << (2 + (i * 4)) |
+ !!(cso->rt[i].colormask & PIPE_MASK_B) << (3 + (i * 4));
+ }
+ } else {
+ blend[1] = 0x0000000e * (blend[0] & 0x00000001);
+ cmask[1] = 0x00001110 * !!(cmask[0] & 0x01000000);
+ cmask[1] |= 0x00002220 * !!(cmask[0] & 0x00010000);
+ cmask[1] |= 0x00004440 * !!(cmask[0] & 0x00000100);
+ cmask[1] |= 0x00008880 * !!(cmask[0] & 0x00000001);
+ }
+
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ SB_MTHD40(so, MRT_BLEND_ENABLE, 2);
+ SB_DATA (so, blend[1]);
+ SB_DATA (so, cmask[1]);
+ }
+
+ if (blend[0] || blend[1]) {
+ SB_MTHD30(so, BLEND_FUNC_ENABLE, 3);
+ SB_DATA (so, blend[0]);
+ SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
+ nvgl_blend_func(cso->rt[0].rgb_src_factor));
+ SB_DATA (so, (nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16) |
+ nvgl_blend_func(cso->rt[0].rgb_dst_factor));
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ SB_MTHD30(so, BLEND_EQUATION, 1);
+ SB_DATA (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
+ } else {
+ SB_MTHD40(so, BLEND_EQUATION, 1);
+ SB_DATA (so, (nvgl_blend_eqn(cso->rt[0].alpha_func) << 16) |
+ nvgl_blend_eqn(cso->rt[0].rgb_func));
+ }
+ } else {
+ SB_MTHD30(so, BLEND_FUNC_ENABLE, 1);
+ SB_DATA (so, blend[0]);
+ }
+
+ SB_MTHD30(so, COLOR_MASK, 1);
+ SB_DATA (so, cmask[0]);
+ return so;
+}
+
+static void
+nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->blend = hwcso;
+ nv30->dirty |= NV30_NEW_BLEND;
+}
+
+static void
+nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv30_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv30_rasterizer_stateobj *so;
+
+ so = CALLOC_STRUCT(nv30_rasterizer_stateobj);
+ if (!so)
+ return NULL;
+ so->pipe = *cso;
+
+ SB_MTHD30(so, SHADE_MODEL, 1);
+ SB_DATA (so, cso->flatshade ? NV30_3D_SHADE_MODEL_FLAT :
+ NV30_3D_SHADE_MODEL_SMOOTH);
+
+ SB_MTHD30(so, POLYGON_MODE_FRONT, 6);
+ SB_DATA (so, nvgl_polygon_mode(cso->fill_front));
+ SB_DATA (so, nvgl_polygon_mode(cso->fill_back));
+ if (cso->cull_face == PIPE_FACE_FRONT_AND_BACK)
+ SB_DATA (so, NV30_3D_CULL_FACE_FRONT_AND_BACK);
+ else
+ if (cso->cull_face == PIPE_FACE_FRONT)
+ SB_DATA (so, NV30_3D_CULL_FACE_FRONT);
+ else
+ SB_DATA (so, NV30_3D_CULL_FACE_BACK);
+ SB_DATA (so, cso->front_ccw ? NV30_3D_FRONT_FACE_CCW :
+ NV30_3D_FRONT_FACE_CW);
+ SB_DATA (so, cso->poly_smooth);
+ SB_DATA (so, cso->cull_face != PIPE_FACE_NONE);
+
+ SB_MTHD30(so, POLYGON_OFFSET_POINT_ENABLE, 3);
+ SB_DATA (so, cso->offset_point);
+ SB_DATA (so, cso->offset_line);
+ SB_DATA (so, cso->offset_tri);
+ if (cso->offset_point || cso->offset_line || cso->offset_tri) {
+ SB_MTHD30(so, POLYGON_OFFSET_FACTOR, 2);
+ SB_DATA (so, fui(cso->offset_scale));
+ SB_DATA (so, fui(cso->offset_units * 2.0));
+ }
+
+ SB_MTHD30(so, LINE_WIDTH, 2);
+ SB_DATA (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+ SB_DATA (so, cso->line_smooth);
+ SB_MTHD30(so, LINE_STIPPLE_ENABLE, 2);
+ SB_DATA (so, cso->line_stipple_enable);
+ SB_DATA (so, (cso->line_stipple_pattern << 16) |
+ cso->line_stipple_factor);
+
+ SB_MTHD30(so, VERTEX_TWO_SIDE_ENABLE, 1);
+ SB_DATA (so, cso->light_twoside);
+ SB_MTHD30(so, POLYGON_STIPPLE_ENABLE, 1);
+ SB_DATA (so, cso->poly_stipple_enable);
+ SB_MTHD30(so, POINT_SIZE, 1);
+ SB_DATA (so, fui(cso->point_size));
+ SB_MTHD30(so, FLATSHADE_FIRST, 1);
+ SB_DATA (so, cso->flatshade_first);
+
+ SB_MTHD30(so, DEPTH_CONTROL, 1);
+ SB_DATA (so, cso->depth_clip ? 0x00000001 : 0x00000010);
+ return so;
+}
+
+static void
+nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->rast = hwcso;
+ nv30->dirty |= NV30_NEW_RASTERIZER;
+}
+
+static void
+nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv30_zsa_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv30_zsa_stateobj *so;
+
+ so = CALLOC_STRUCT(nv30_zsa_stateobj);
+ if (!so)
+ return NULL;
+ so->pipe = *cso;
+
+ SB_MTHD30(so, DEPTH_FUNC, 3);
+ SB_DATA (so, nvgl_comparison_op(cso->depth.func));
+ SB_DATA (so, cso->depth.writemask);
+ SB_DATA (so, cso->depth.enabled);
+
+ if (cso->stencil[0].enabled) {
+ SB_MTHD30(so, STENCIL_ENABLE(0), 3);
+ SB_DATA (so, 1);
+ SB_DATA (so, cso->stencil[0].writemask);
+ SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func));
+ SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4);
+ SB_DATA (so, cso->stencil[0].valuemask);
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+ } else {
+ SB_MTHD30(so, STENCIL_ENABLE(0), 2);
+ SB_DATA (so, 0);
+ SB_DATA (so, 0x000000ff);
+ }
+
+ if (cso->stencil[1].enabled) {
+ SB_MTHD30(so, STENCIL_ENABLE(1), 3);
+ SB_DATA (so, 1);
+ SB_DATA (so, cso->stencil[1].writemask);
+ SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func));
+ SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4);
+ SB_DATA (so, cso->stencil[1].valuemask);
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+ SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+ } else {
+ SB_MTHD30(so, STENCIL_ENABLE(1), 1);
+ SB_DATA (so, 0);
+ }
+
+ SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3);
+ SB_DATA (so, cso->alpha.enabled ? 1 : 0);
+ SB_DATA (so, nvgl_comparison_op(cso->alpha.func));
+ SB_DATA (so, float_to_ubyte(cso->alpha.ref_value));
+
+ return so;
+}
+
+static void
+nv30_zsa_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->zsa = hwcso;
+ nv30->dirty |= NV30_NEW_ZSA;
+}
+
+static void
+nv30_zsa_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv30_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->blend_colour = *bcol;
+ nv30->dirty |= NV30_NEW_BLEND_COLOUR;
+}
+
+static void
+nv30_set_stencil_ref(struct pipe_context *pipe,
+ const struct pipe_stencil_ref *sr)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->stencil_ref = *sr;
+ nv30->dirty |= NV30_NEW_STENCIL_REF;
+}
+
+static void
+nv30_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ memcpy(nv30->clip.ucp, clip->ucp, sizeof(clip->ucp));
+
+ nv30->dirty |= NV30_NEW_CLIP;
+}
+
+static void
+nv30_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->sample_mask = sample_mask;
+ nv30->dirty |= NV30_NEW_SAMPLE_MASK;
+}
+
+static void
+nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ struct pipe_constant_buffer *cb)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct pipe_resource *buf = cb ? cb->buffer : NULL;
+ unsigned size;
+
+ if (cb && cb->user_buffer) {
+ buf = nouveau_user_buffer_create(pipe->screen, (void*)cb->user_buffer,
+ cb->buffer_size,
+ PIPE_BIND_CONSTANT_BUFFER);
+ }
+
+ size = 0;
+ if (buf)
+ size = buf->width0 / (4 * sizeof(float));
+
+ if (shader == PIPE_SHADER_VERTEX) {
+ pipe_resource_reference(&nv30->vertprog.constbuf, buf);
+ nv30->vertprog.constbuf_nr = size;
+ nv30->dirty |= NV30_NEW_VERTCONST;
+ } else
+ if (shader == PIPE_SHADER_FRAGMENT) {
+ pipe_resource_reference(&nv30->fragprog.constbuf, buf);
+ nv30->fragprog.constbuf_nr = size;
+ nv30->dirty |= NV30_NEW_FRAGCONST;
+ }
+
+ if (cb && cb->user_buffer) {
+ pipe_resource_reference(&buf, NULL);
+ }
+}
+
+static void
+nv30_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);
+
+ nv30->framebuffer = *fb;
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER;
+}
+
+static void
+nv30_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->stipple = *stipple;
+ nv30->dirty |= NV30_NEW_STIPPLE;
+}
+
+static void
+nv30_set_scissor_states(struct pipe_context *pipe,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_scissor_state *scissor)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->scissor = *scissor;
+ nv30->dirty |= NV30_NEW_SCISSOR;
+}
+
+static void
+nv30_set_viewport_states(struct pipe_context *pipe,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->viewport = *vpt;
+ nv30->dirty |= NV30_NEW_VIEWPORT;
+}
+
+static void
+nv30_set_vertex_buffers(struct pipe_context *pipe,
+ unsigned start_slot, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
+
+ util_set_vertex_buffers_count(nv30->vtxbuf, &nv30->num_vtxbufs,
+ vb, start_slot, count);
+
+ nv30->dirty |= NV30_NEW_ARRAYS;
+}
+
+static void
+nv30_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ if (ib) {
+ pipe_resource_reference(&nv30->idxbuf.buffer, ib->buffer);
+ nv30->idxbuf.index_size = ib->index_size;
+ nv30->idxbuf.offset = ib->offset;
+ nv30->idxbuf.user_buffer = ib->user_buffer;
+ } else {
+ pipe_resource_reference(&nv30->idxbuf.buffer, NULL);
+ nv30->idxbuf.user_buffer = NULL;
+ }
+}
+
+void
+nv30_state_init(struct pipe_context *pipe)
+{
+ pipe->create_blend_state = nv30_blend_state_create;
+ pipe->bind_blend_state = nv30_blend_state_bind;
+ pipe->delete_blend_state = nv30_blend_state_delete;
+
+ pipe->create_rasterizer_state = nv30_rasterizer_state_create;
+ pipe->bind_rasterizer_state = nv30_rasterizer_state_bind;
+ pipe->delete_rasterizer_state = nv30_rasterizer_state_delete;
+
+ pipe->create_depth_stencil_alpha_state = nv30_zsa_state_create;
+ pipe->bind_depth_stencil_alpha_state = nv30_zsa_state_bind;
+ pipe->delete_depth_stencil_alpha_state = nv30_zsa_state_delete;
+
+ pipe->set_blend_color = nv30_set_blend_color;
+ pipe->set_stencil_ref = nv30_set_stencil_ref;
+ pipe->set_clip_state = nv30_set_clip_state;
+ pipe->set_sample_mask = nv30_set_sample_mask;
+ pipe->set_constant_buffer = nv30_set_constant_buffer;
+ pipe->set_framebuffer_state = nv30_set_framebuffer_state;
+ pipe->set_polygon_stipple = nv30_set_polygon_stipple;
+ pipe->set_scissor_states = nv30_set_scissor_states;
+ pipe->set_viewport_states = nv30_set_viewport_states;
+
+ pipe->set_vertex_buffers = nv30_set_vertex_buffers;
+ pipe->set_index_buffer = nv30_set_index_buffer;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state.h b/src/gallium/drivers/nouveau/nv30/nv30_state.h
new file mode 100644
index 00000000000..e27e16fae82
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_state.h
@@ -0,0 +1,144 @@
+#ifndef __NV30_STATE_H__
+#define __NV30_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+#include "util/u_dynarray.h"
+
+#define NV30_QUERY_ZCULL_0 (PIPE_QUERY_TYPES + 0)
+#define NV30_QUERY_ZCULL_1 (PIPE_QUERY_TYPES + 1)
+#define NV30_QUERY_ZCULL_2 (PIPE_QUERY_TYPES + 2)
+#define NV30_QUERY_ZCULL_3 (PIPE_QUERY_TYPES + 3)
+
+#define SB_DATA(so, u) (so)->data[(so)->size++] = (u)
+#define SB_MTHD30(so, mthd, size) \
+ SB_DATA((so), ((size) << 18) | (7 << 13) | NV30_3D_##mthd)
+#define SB_MTHD40(so, mthd, size) \
+ SB_DATA((so), ((size) << 18) | (7 << 13) | NV40_3D_##mthd)
+
+struct nv30_blend_stateobj {
+ struct pipe_blend_state pipe;
+ unsigned data[16];
+ unsigned size;
+};
+
+struct nv30_rasterizer_stateobj {
+ struct pipe_rasterizer_state pipe;
+ unsigned data[32];
+ unsigned size;
+};
+
+struct nv30_zsa_stateobj {
+ struct pipe_depth_stencil_alpha_state pipe;
+ unsigned data[32];
+ unsigned size;
+};
+
+struct nv30_sampler_state {
+ struct pipe_sampler_state pipe;
+ unsigned fmt;
+ unsigned wrap;
+ unsigned en;
+ unsigned filt;
+ unsigned bcol;
+ /* 4.8 */
+ unsigned min_lod;
+ unsigned max_lod;
+};
+
+struct nv30_sampler_view {
+ struct pipe_sampler_view pipe;
+ unsigned fmt;
+ unsigned swz;
+ unsigned filt;
+ unsigned filt_mask;
+ unsigned wrap;
+ unsigned wrap_mask;
+ unsigned npot_size0;
+ unsigned npot_size1;
+ /* 4.8 */
+ unsigned base_lod;
+ unsigned high_lod;
+};
+
+struct nv30_shader_reloc {
+ unsigned location;
+ int target;
+};
+
+struct nv30_vertprog_exec {
+ uint32_t data[4];
+};
+
+struct nv30_vertprog_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv30_vertprog {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ struct draw_vertex_shader *draw;
+ boolean translated;
+ unsigned enabled_ucps;
+ uint16_t texcoord[10];
+
+ struct util_dynarray branch_relocs;
+ struct nv30_vertprog_exec *insns;
+ unsigned nr_insns;
+
+ struct util_dynarray const_relocs;
+ struct nv30_vertprog_data *consts;
+ unsigned nr_consts;
+
+ struct nouveau_heap *exec;
+ struct nouveau_heap *data;
+ uint32_t ir;
+ uint32_t or;
+ void *nvfx;
+};
+
+struct nv30_fragprog_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv30_fragprog {
+ struct pipe_shader_state pipe;
+ struct tgsi_shader_info info;
+
+ struct draw_fragment_shader *draw;
+ boolean translated;
+
+ uint32_t *insn;
+ unsigned insn_len;
+
+ uint16_t texcoord[10];
+ struct nv30_fragprog_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_resource *buffer;
+ uint32_t vp_or; /* appended to VP_RESULT_EN */
+ uint32_t fp_control;
+ uint32_t point_sprite_control;
+ uint32_t coord_conventions;
+ uint32_t texcoords;
+ uint32_t rt_enable;
+};
+
+struct nv30_vertex_element {
+ unsigned state;
+};
+
+struct nv30_vertex_stateobj {
+ struct pipe_vertex_element pipe[PIPE_MAX_ATTRIBS];
+ struct translate *translate;
+ bool need_conversion;
+ unsigned num_elements;
+ unsigned vtx_size;
+ unsigned vtx_per_packet_max;
+ struct nv30_vertex_element element[];
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c
new file mode 100644
index 00000000000..f22755983ba
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_half.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+static void
+nv30_validate_fb(struct nv30_context *nv30)
+{
+ struct pipe_screen *pscreen = &nv30->screen->base.base;
+ struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ uint32_t rt_format;
+ int h = fb->height;
+ int w = fb->width;
+ int x = 0;
+ int y = 0;
+
+ nv30->state.rt_enable = (NV30_3D_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
+ if (nv30->state.rt_enable > 1)
+ nv30->state.rt_enable |= NV30_3D_RT_ENABLE_MRT;
+
+ rt_format = 0;
+ if (fb->nr_cbufs > 0) {
+ struct nv30_miptree *mt = nv30_miptree(fb->cbufs[0]->texture);
+ rt_format |= nv30_format(pscreen, fb->cbufs[0]->format)->hw;
+ rt_format |= mt->ms_mode;
+ if (mt->swizzled)
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ } else {
+ if (fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) > 2)
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
+ }
+
+ if (fb->zsbuf) {
+ rt_format |= nv30_format(pscreen, fb->zsbuf->format)->hw;
+ if (nv30_miptree(fb->zsbuf->texture)->swizzled)
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ } else {
+ if (fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) > 2)
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
+ }
+
+ /* hardware rounds down render target offset to 64 bytes, but surfaces
+ * with a size of 2x2 pixel (16bpp) or 1x1 pixel (32bpp) have an
+ * unaligned start aaddress. For these two important square formats
+ * we can hack around this limitation by adjusting the viewport origin
+ */
+ if (nv30->state.rt_enable) {
+ int off = nv30_surface(fb->cbufs[0])->offset & 63;
+ if (off) {
+ x += off / (util_format_get_blocksize(fb->cbufs[0]->format) * 2);
+ w = 16;
+ h = 2;
+ }
+ }
+
+ if (rt_format & NV30_3D_RT_FORMAT_TYPE_SWIZZLED) {
+ rt_format |= util_logbase2(w) << 16;
+ rt_format |= util_logbase2(h) << 24;
+ }
+
+ if (!PUSH_SPACE(push, 64))
+ return;
+ PUSH_RESET(push, BUFCTX_FB);
+
+ BEGIN_NV04(push, SUBC_3D(0x1da4), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
+ PUSH_DATA (push, w << 16);
+ PUSH_DATA (push, h << 16);
+ PUSH_DATA (push, rt_format);
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
+ PUSH_DATA (push, w << 16);
+ PUSH_DATA (push, h << 16);
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 4);
+ PUSH_DATA (push, (y << 16) | x);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, ((w - 1) << 16) | 0);
+ PUSH_DATA (push, ((h - 1) << 16) | 0);
+
+ if ((nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR0) || fb->zsbuf) {
+ struct nv30_surface *rsf = nv30_surface(fb->cbufs[0]);
+ struct nv30_surface *zsf = nv30_surface(fb->zsbuf);
+ struct nouveau_bo *rbo, *zbo;
+
+ if (!rsf) rsf = zsf;
+ else if (!zsf) zsf = rsf;
+ rbo = nv30_miptree(rsf->base.texture)->base.bo;
+ zbo = nv30_miptree(zsf->base.texture)->base.bo;
+
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
+ PUSH_DATA (push, zsf->pitch);
+ BEGIN_NV04(push, NV40_3D(COLOR0_PITCH), 3);
+ PUSH_DATA (push, rsf->pitch);
+ } else {
+ BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 3);
+ PUSH_DATA (push, (zsf->pitch << 16) | rsf->pitch);
+ }
+ PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), BUFCTX_FB, rbo, rsf->offset & ~63,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ PUSH_MTHDl(push, NV30_3D(ZETA_OFFSET), BUFCTX_FB, zbo, zsf->offset & ~63,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ }
+
+ if (nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR1) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[1]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV30_3D(COLOR1_OFFSET), 2);
+ PUSH_MTHDl(push, NV30_3D(COLOR1_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ PUSH_DATA (push, sf->pitch);
+ }
+
+ if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR2) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[2]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV40_3D(COLOR2_OFFSET), 1);
+ PUSH_MTHDl(push, NV40_3D(COLOR2_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ BEGIN_NV04(push, NV40_3D(COLOR2_PITCH), 1);
+ PUSH_DATA (push, sf->pitch);
+ }
+
+ if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR3) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[3]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV40_3D(COLOR3_OFFSET), 1);
+ PUSH_MTHDl(push, NV40_3D(COLOR3_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ BEGIN_NV04(push, NV40_3D(COLOR3_PITCH), 1);
+ PUSH_DATA (push, sf->pitch);
+ }
+}
+
+static void
+nv30_validate_blend_colour(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ float *rgba = nv30->blend_colour.color;
+
+ if (nv30->framebuffer.nr_cbufs) {
+ switch (nv30->framebuffer.cbufs[0]->format) {
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
+ PUSH_DATA (push, (util_float_to_half(rgba[0]) << 0) |
+ (util_float_to_half(rgba[1]) << 16));
+ BEGIN_NV04(push, SUBC_3D(0x037c), 1);
+ PUSH_DATA (push, (util_float_to_half(rgba[2]) << 0) |
+ (util_float_to_half(rgba[3]) << 16));
+ break;
+ default:
+ break;
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
+ PUSH_DATA (push, (float_to_ubyte(rgba[3]) << 24) |
+ (float_to_ubyte(rgba[0]) << 16) |
+ (float_to_ubyte(rgba[1]) << 8) |
+ (float_to_ubyte(rgba[2]) << 0));
+}
+
+static void
+nv30_validate_stencil_ref(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(0)), 1);
+ PUSH_DATA (push, nv30->stencil_ref.ref_value[0]);
+ BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(1)), 1);
+ PUSH_DATA (push, nv30->stencil_ref.ref_value[1]);
+}
+
+static void
+nv30_validate_stipple(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
+ PUSH_DATAp(push, nv30->stipple.stipple, 32);
+}
+
+static void
+nv30_validate_scissor(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct pipe_scissor_state *s = &nv30->scissor;
+
+ if (!(nv30->dirty & NV30_NEW_SCISSOR) &&
+ nv30->rast->pipe.scissor != nv30->state.scissor_off)
+ return;
+ nv30->state.scissor_off = !nv30->rast->pipe.scissor;
+
+ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
+ if (nv30->rast->pipe.scissor) {
+ PUSH_DATA (push, ((s->maxx - s->minx) << 16) | s->minx);
+ PUSH_DATA (push, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ PUSH_DATA (push, 0x10000000);
+ PUSH_DATA (push, 0x10000000);
+ }
+}
+
+static void
+nv30_validate_viewport(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct pipe_viewport_state *vp = &nv30->viewport;
+
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
+ PUSH_DATAf(push, vp->translate[0]);
+ PUSH_DATAf(push, vp->translate[1]);
+ PUSH_DATAf(push, vp->translate[2]);
+ PUSH_DATAf(push, vp->translate[3]);
+ PUSH_DATAf(push, vp->scale[0]);
+ PUSH_DATAf(push, vp->scale[1]);
+ PUSH_DATAf(push, vp->scale[2]);
+ PUSH_DATAf(push, vp->scale[3]);
+ BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
+ PUSH_DATAf(push, vp->translate[2] - fabsf(vp->scale[2]));
+ PUSH_DATAf(push, vp->translate[2] + fabsf(vp->scale[2]));
+}
+
+static void
+nv30_validate_clip(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned i;
+ uint32_t clpd_enable = 0;
+
+ for (i = 0; i < 6; i++) {
+ if (nv30->rast->pipe.clip_plane_enable & (1 << i)) {
+ if (nv30->dirty & NV30_NEW_CLIP) {
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
+ PUSH_DATA (push, i);
+ PUSH_DATAp(push, nv30->clip.ucp[i], 4);
+ }
+
+ clpd_enable |= 1 << (1 + 4*i);
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
+ PUSH_DATA (push, clpd_enable);
+}
+
+static void
+nv30_validate_blend(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->blend->size);
+ PUSH_DATAp(push, nv30->blend->data, nv30->blend->size);
+}
+
+static void
+nv30_validate_zsa(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->zsa->size);
+ PUSH_DATAp(push, nv30->zsa->data, nv30->zsa->size);
+}
+
+static void
+nv30_validate_rasterizer(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->rast->size);
+ PUSH_DATAp(push, nv30->rast->data, nv30->rast->size);
+}
+
+static void
+nv30_validate_multisample(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
+ struct pipe_blend_state *blend = &nv30->blend->pipe;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ uint32_t ctrl = nv30->sample_mask << 16;
+
+ if (blend->alpha_to_one)
+ ctrl |= 0x00000100;
+ if (blend->alpha_to_coverage)
+ ctrl |= 0x00000010;
+ if (rasterizer->multisample)
+ ctrl |= 0x00000001;
+
+ BEGIN_NV04(push, NV30_3D(MULTISAMPLE_CONTROL), 1);
+ PUSH_DATA (push, ctrl);
+}
+
+static void
+nv30_validate_fragment(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+
+ BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
+ PUSH_DATA (push, nv30->state.rt_enable & ~fp->rt_enable);
+ BEGIN_NV04(push, NV30_3D(COORD_CONVENTIONS), 1);
+ PUSH_DATA (push, fp->coord_conventions | nv30->framebuffer.height);
+}
+
+static void
+nv30_validate_point_coord(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ uint32_t hw = 0x00000000;
+
+ if (rasterizer) {
+ hw |= (nv30->rast->pipe.sprite_coord_enable & 0xff) << 8;
+ if (fp)
+ hw |= fp->point_sprite_control;
+
+ if (rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) {
+ if (hw)
+ nv30->draw_flags |= NV30_NEW_RASTERIZER;
+ } else
+ if (rasterizer->point_quad_rasterization) {
+ hw |= NV30_3D_POINT_SPRITE_ENABLE;
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(POINT_SPRITE), 1);
+ PUSH_DATA (push, hw);
+}
+
+struct state_validate {
+ void (*func)(struct nv30_context *);
+ uint32_t mask;
+};
+
+static struct state_validate hwtnl_validate_list[] = {
+ { nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_blend, NV30_NEW_BLEND },
+ { nv30_validate_zsa, NV30_NEW_ZSA },
+ { nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
+ { nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
+ NV30_NEW_RASTERIZER },
+ { nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
+ NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
+ { nv30_validate_stipple, NV30_NEW_STIPPLE },
+ { nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
+ { nv30_validate_viewport, NV30_NEW_VIEWPORT },
+ { nv30_validate_clip, NV30_NEW_CLIP },
+ { nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
+ { nv30_vertprog_validate, NV30_NEW_VERTPROG | NV30_NEW_VERTCONST |
+ NV30_NEW_FRAGPROG | NV30_NEW_RASTERIZER },
+ { nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
+ { nv30_validate_point_coord, NV30_NEW_RASTERIZER | NV30_NEW_FRAGPROG },
+ { nv30_fragtex_validate, NV30_NEW_FRAGTEX },
+ { nv40_verttex_validate, NV30_NEW_VERTTEX },
+ { nv30_vbo_validate, NV30_NEW_VERTEX | NV30_NEW_ARRAYS },
+ {}
+};
+
+#define NV30_SWTNL_MASK (NV30_NEW_VIEWPORT | \
+ NV30_NEW_CLIP | \
+ NV30_NEW_VERTPROG | \
+ NV30_NEW_VERTCONST | \
+ NV30_NEW_VERTTEX | \
+ NV30_NEW_VERTEX | \
+ NV30_NEW_ARRAYS)
+
+static struct state_validate swtnl_validate_list[] = {
+ { nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_blend, NV30_NEW_BLEND },
+ { nv30_validate_zsa, NV30_NEW_ZSA },
+ { nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
+ { nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
+ NV30_NEW_RASTERIZER },
+ { nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
+ NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
+ { nv30_validate_stipple, NV30_NEW_STIPPLE },
+ { nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
+ { nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
+ { nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
+ { nv30_fragtex_validate, NV30_NEW_FRAGTEX },
+ {}
+};
+
+static void
+nv30_state_context_switch(struct nv30_context *nv30)
+{
+ struct nv30_context *prev = nv30->screen->cur_ctx;
+
+ if (prev)
+ nv30->state = prev->state;
+ nv30->dirty = NV30_NEW_ALL;
+
+ if (!nv30->vertex)
+ nv30->dirty &= ~(NV30_NEW_VERTEX | NV30_NEW_ARRAYS);
+
+ if (!nv30->vertprog.program)
+ nv30->dirty &= ~NV30_NEW_VERTPROG;
+ if (!nv30->fragprog.program)
+ nv30->dirty &= ~NV30_NEW_FRAGPROG;
+
+ if (!nv30->blend)
+ nv30->dirty &= ~NV30_NEW_BLEND;
+ if (!nv30->rast)
+ nv30->dirty &= ~NV30_NEW_RASTERIZER;
+ if (!nv30->zsa)
+ nv30->dirty &= ~NV30_NEW_ZSA;
+
+ nv30->screen->cur_ctx = nv30;
+ nv30->base.pushbuf->user_priv = &nv30->bufctx;
+}
+
+boolean
+nv30_state_validate(struct nv30_context *nv30, boolean hwtnl)
+{
+ struct nouveau_screen *screen = &nv30->screen->base;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_bufctx *bctx = nv30->bufctx;
+ struct nouveau_bufref *bref;
+ struct state_validate *validate;
+
+ if (nv30->screen->cur_ctx != nv30)
+ nv30_state_context_switch(nv30);
+
+ if (hwtnl) {
+ nv30->draw_dirty |= nv30->dirty;
+ if (nv30->draw_flags) {
+ nv30->draw_flags &= ~nv30->dirty;
+ if (!nv30->draw_flags)
+ nv30->dirty |= NV30_SWTNL_MASK;
+ }
+ }
+
+ if (!nv30->draw_flags)
+ validate = hwtnl_validate_list;
+ else
+ validate = swtnl_validate_list;
+
+ if (nv30->dirty) {
+ while (validate->func) {
+ if (nv30->dirty & validate->mask)
+ validate->func(nv30);
+ validate++;
+ }
+
+ nv30->dirty = 0;
+ }
+
+ nouveau_pushbuf_bufctx(push, bctx);
+ if (nouveau_pushbuf_validate(push)) {
+ nouveau_pushbuf_bufctx(push, NULL);
+ return FALSE;
+ }
+
+ /*XXX*/
+ BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
+ PUSH_DATA (push, 0);
+ if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
+ PUSH_DATA (push, 2);
+ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
+ PUSH_DATA (push, 1);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ }
+
+ LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) {
+ struct nv04_resource *res = bref->priv;
+ if (res && res->mm) {
+ nouveau_fence_ref(screen->fence.current, &res->fence);
+
+ if (bref->flags & NOUVEAU_BO_RD)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
+
+ if (bref->flags & NOUVEAU_BO_WR) {
+ nouveau_fence_ref(screen->fence.current, &res->fence_wr);
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+void
+nv30_state_release(struct nv30_context *nv30)
+{
+ nouveau_pushbuf_bufctx(nv30->base.pushbuf, NULL);
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_texture.c b/src/gallium/drivers/nouveau/nv30/nv30_texture.c
new file mode 100644
index 00000000000..d3cffcfb261
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_texture.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+#define NV30_3D_TEX_WRAP_S_MIRROR_REPEAT NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT
+#define NV30_WRAP(n) \
+ case PIPE_TEX_WRAP_##n: ret = NV30_3D_TEX_WRAP_S_##n; break
+#define NV40_WRAP(n) \
+ case PIPE_TEX_WRAP_##n: ret = NV40_3D_TEX_WRAP_S_##n; break
+
+static INLINE unsigned
+wrap_mode(unsigned pipe)
+{
+ unsigned ret = NV30_3D_TEX_WRAP_S_REPEAT;
+
+ switch (pipe) {
+ NV30_WRAP(REPEAT);
+ NV30_WRAP(MIRROR_REPEAT);
+ NV30_WRAP(CLAMP_TO_EDGE);
+ NV30_WRAP(CLAMP_TO_BORDER);
+ NV30_WRAP(CLAMP);
+ NV40_WRAP(MIRROR_CLAMP_TO_EDGE);
+ NV40_WRAP(MIRROR_CLAMP_TO_BORDER);
+ NV40_WRAP(MIRROR_CLAMP);
+ default:
+ break;
+ }
+
+ return ret >> NV30_3D_TEX_WRAP_S__SHIFT;
+}
+
+static INLINE unsigned
+filter_mode(const struct pipe_sampler_state *cso)
+{
+ unsigned filter;
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ filter = NV30_3D_TEX_FILTER_MAG_LINEAR;
+ break;
+ default:
+ filter = NV30_3D_TEX_FILTER_MAG_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR;
+ break;
+ default:
+ filter |= NV30_3D_TEX_FILTER_MIN_LINEAR;
+ break;
+ }
+ break;
+ default:
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ filter |= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ filter |= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR;
+ break;
+ default:
+ filter |= NV30_3D_TEX_FILTER_MIN_NEAREST;
+ break;
+ }
+ break;
+ }
+
+ return filter;
+}
+
+static INLINE unsigned
+compare_mode(const struct pipe_sampler_state *cso)
+{
+ if (cso->compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE)
+ return 0;
+
+ switch (cso->compare_func) {
+ case PIPE_FUNC_NEVER : return NV30_3D_TEX_WRAP_RCOMP_NEVER;
+ case PIPE_FUNC_GREATER : return NV30_3D_TEX_WRAP_RCOMP_GREATER;
+ case PIPE_FUNC_EQUAL : return NV30_3D_TEX_WRAP_RCOMP_EQUAL;
+ case PIPE_FUNC_GEQUAL : return NV30_3D_TEX_WRAP_RCOMP_GEQUAL;
+ case PIPE_FUNC_LESS : return NV30_3D_TEX_WRAP_RCOMP_LESS;
+ case PIPE_FUNC_NOTEQUAL: return NV30_3D_TEX_WRAP_RCOMP_NOTEQUAL;
+ case PIPE_FUNC_LEQUAL : return NV30_3D_TEX_WRAP_RCOMP_LEQUAL;
+ case PIPE_FUNC_ALWAYS : return NV30_3D_TEX_WRAP_RCOMP_ALWAYS;
+ default:
+ return 0;
+ }
+}
+
+static void *
+nv30_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
+ struct nv30_sampler_state *so;
+ const float max_lod = 15.0 + (255.0 / 256.0);
+
+ so = MALLOC_STRUCT(nv30_sampler_state);
+ if (!so)
+ return NULL;
+
+ so->pipe = *cso;
+ so->fmt = 0;
+ so->wrap = (wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) |
+ (wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) |
+ (wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT);
+ so->en = 0;
+ so->wrap |= compare_mode(cso);
+ so->filt = filter_mode(cso) | 0x00002000;
+ so->bcol = (float_to_ubyte(cso->border_color.f[3]) << 24) |
+ (float_to_ubyte(cso->border_color.f[0]) << 16) |
+ (float_to_ubyte(cso->border_color.f[1]) << 8) |
+ (float_to_ubyte(cso->border_color.f[2]) << 0);
+
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ unsigned aniso = cso->max_anisotropy;
+
+ if (!cso->normalized_coords)
+ so->fmt |= NV40_3D_TEX_FORMAT_RECT;
+
+ if (aniso > 1) {
+ if (aniso >= 16) so->en |= NV40_3D_TEX_ENABLE_ANISO_16X;
+ else if (aniso >= 12) so->en |= NV40_3D_TEX_ENABLE_ANISO_12X;
+ else if (aniso >= 10) so->en |= NV40_3D_TEX_ENABLE_ANISO_10X;
+ else if (aniso >= 8) so->en |= NV40_3D_TEX_ENABLE_ANISO_8X;
+ else if (aniso >= 6) so->en |= NV40_3D_TEX_ENABLE_ANISO_6X;
+ else if (aniso >= 4) so->en |= NV40_3D_TEX_ENABLE_ANISO_4X;
+ else so->en |= NV40_3D_TEX_ENABLE_ANISO_2X;
+
+ so->wrap |= nv30_context(pipe)->config.aniso;
+ }
+ } else {
+ so->en |= NV30_3D_TEX_ENABLE_ENABLE;
+
+ if (cso->max_anisotropy >= 8) so->en |= NV30_3D_TEX_ENABLE_ANISO_8X;
+ else if (cso->max_anisotropy >= 4) so->en |= NV30_3D_TEX_ENABLE_ANISO_4X;
+ else if (cso->max_anisotropy >= 2) so->en |= NV30_3D_TEX_ENABLE_ANISO_2X;
+ }
+
+ so->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+ so->max_lod = (int)(CLAMP(cso->max_lod, 0.0, max_lod) * 256.0);
+ so->min_lod = (int)(CLAMP(cso->min_lod, 0.0, max_lod) * 256.0);
+ return so;
+}
+
+static void
+nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static INLINE uint32_t
+swizzle(const struct nv30_texfmt *fmt, unsigned cmp, unsigned swz)
+{
+ uint32_t data = fmt->swz[swz].src << 8;
+ if (swz <= PIPE_SWIZZLE_ALPHA)
+ data |= fmt->swz[swz].cmp;
+ else
+ data |= fmt->swz[cmp].cmp;
+ return data;
+}
+
+static struct pipe_sampler_view *
+nv30_sampler_view_create(struct pipe_context *pipe, struct pipe_resource *pt,
+ const struct pipe_sampler_view *tmpl)
+{
+ const struct nv30_texfmt *fmt = nv30_texfmt(pipe->screen, tmpl->format);
+ struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
+ struct nv30_miptree *mt = nv30_miptree(pt);
+ struct nv30_sampler_view *so;
+
+ so = MALLOC_STRUCT(nv30_sampler_view);
+ if (!so)
+ return NULL;
+ so->pipe = *tmpl;
+ so->pipe.reference.count = 1;
+ so->pipe.texture = NULL;
+ so->pipe.context = pipe;
+ pipe_resource_reference(&so->pipe.texture, pt);
+
+ so->fmt = NV30_3D_TEX_FORMAT_NO_BORDER;
+ switch (pt->target) {
+ case PIPE_TEXTURE_1D:
+ so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ so->fmt |= NV30_3D_TEX_FORMAT_CUBIC;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ so->fmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
+ break;
+ case PIPE_TEXTURE_3D:
+ so->fmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
+ break;
+ default:
+ assert(0);
+ so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
+ break;
+ }
+
+ so->filt = fmt->filter;
+ so->wrap = fmt->wrap;
+ so->swz = fmt->swizzle;
+ so->swz |= swizzle(fmt, 3, tmpl->swizzle_a);
+ so->swz |= swizzle(fmt, 0, tmpl->swizzle_r) << 2;
+ so->swz |= swizzle(fmt, 1, tmpl->swizzle_g) << 4;
+ so->swz |= swizzle(fmt, 2, tmpl->swizzle_b) << 6;
+
+ /* apparently, we need to ignore the t coordinate for 1D textures to
+ * fix piglit tex1d-2dborder
+ */
+ so->wrap_mask = ~0;
+ if (pt->target == PIPE_TEXTURE_1D) {
+ so->wrap_mask &= ~NV30_3D_TEX_WRAP_T__MASK;
+ so->wrap |= NV30_3D_TEX_WRAP_T_REPEAT;
+ }
+
+ /* yet more hardware suckage, can't filter 32-bit float formats */
+ switch (tmpl->format) {
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ so->filt_mask = ~(NV30_3D_TEX_FILTER_MIN__MASK |
+ NV30_3D_TEX_FILTER_MAG__MASK);
+ so->filt |= NV30_3D_TEX_FILTER_MIN_NEAREST |
+ NV30_3D_TEX_FILTER_MAG_NEAREST;
+ break;
+ default:
+ so->filt_mask = ~0;
+ break;
+ }
+
+ so->npot_size0 = (pt->width0 << 16) | pt->height0;
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ so->npot_size1 = (pt->depth0 << 20) | mt->uniform_pitch;
+ if (!mt->swizzled)
+ so->fmt |= NV40_3D_TEX_FORMAT_LINEAR;
+ so->fmt |= 0x00008000;
+ so->fmt |= (pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
+ } else {
+ so->swz |= mt->uniform_pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT;
+ if (pt->last_level)
+ so->fmt |= NV30_3D_TEX_FORMAT_MIPMAP;
+ so->fmt |= util_logbase2(pt->width0) << 20;
+ so->fmt |= util_logbase2(pt->height0) << 24;
+ so->fmt |= util_logbase2(pt->depth0) << 28;
+ so->fmt |= 0x00010000;
+ }
+
+ so->base_lod = so->pipe.u.tex.first_level << 8;
+ so->high_lod = MIN2(pt->last_level, so->pipe.u.tex.last_level) << 8;
+ return &so->pipe;
+}
+
+static void
+nv30_sampler_view_destroy(struct pipe_context *pipe,
+ struct pipe_sampler_view *view)
+{
+ pipe_resource_reference(&view->texture, NULL);
+ FREE(view);
+}
+
+void
+nv30_texture_init(struct pipe_context *pipe)
+{
+ pipe->create_sampler_state = nv30_sampler_state_create;
+ pipe->delete_sampler_state = nv30_sampler_state_delete;
+ pipe->create_sampler_view = nv30_sampler_view_create;
+ pipe->sampler_view_destroy = nv30_sampler_view_destroy;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.c b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c
new file mode 100644
index 00000000000..99bc0994ac2
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#define XFER_ARGS \
+ struct nv30_context *nv30, enum nv30_transfer_filter filter, \
+ struct nv30_rect *src, struct nv30_rect *dst
+
+#include "util/u_math.h"
+
+#include "nv_object.xml.h"
+#include "nv_m2mf.xml.h"
+#include "nv30/nv01_2d.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_transfer.h"
+
+/* Various helper functions to transfer different types of data in a number
+ * of different ways.
+ */
+
+static INLINE boolean
+nv30_transfer_scaled(struct nv30_rect *src, struct nv30_rect *dst)
+{
+ if (src->x1 - src->x0 != dst->x1 - dst->x0)
+ return TRUE;
+ if (src->y1 - src->y0 != dst->y1 - dst->y0)
+ return TRUE;
+ return FALSE;
+}
+
+static INLINE boolean
+nv30_transfer_blit(XFER_ARGS)
+{
+ if (nv30->screen->eng3d->oclass < NV40_3D_CLASS)
+ return FALSE;
+ if (dst->offset & 63 || dst->pitch & 63 || dst->d > 1)
+ return FALSE;
+ if (dst->w < 2 || dst->h < 2)
+ return FALSE;
+ if (dst->cpp > 4 || (dst->cpp == 1 && !dst->pitch))
+ return FALSE;
+ if (src->cpp > 4)
+ return FALSE;
+ return TRUE;
+}
+
+static INLINE struct nouveau_heap *
+nv30_transfer_rect_vertprog(struct nv30_context *nv30)
+{
+ struct nouveau_heap *heap = nv30->screen->vp_exec_heap;
+ struct nouveau_heap *vp;
+
+ vp = nv30->blit_vp;
+ if (!vp) {
+ if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp)) {
+ while (heap->next && heap->size < 2) {
+ struct nouveau_heap **evict = heap->next->priv;
+ nouveau_heap_free(evict);
+ }
+
+ if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp))
+ return NULL;
+ }
+
+ vp = nv30->blit_vp;
+ if (vp) {
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
+ PUSH_DATA (push, vp->start);
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
+ PUSH_DATA (push, 0x401f9c6c); /* mov o[hpos], a[0]; */
+ PUSH_DATA (push, 0x0040000d);
+ PUSH_DATA (push, 0x8106c083);
+ PUSH_DATA (push, 0x6041ff80);
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
+ PUSH_DATA (push, 0x401f9c6c); /* mov o[tex0], a[8]; end; */
+ PUSH_DATA (push, 0x0040080d);
+ PUSH_DATA (push, 0x8106c083);
+ PUSH_DATA (push, 0x6041ff9d);
+ }
+ }
+
+ return vp;
+}
+
+
+static INLINE struct nv04_resource *
+nv30_transfer_rect_fragprog(struct nv30_context *nv30)
+{
+ struct nv04_resource *fp = nv04_resource(nv30->blit_fp);
+ struct pipe_context *pipe = &nv30->base.pipe;
+
+ if (!fp) {
+ nv30->blit_fp = pipe_buffer_create(pipe->screen, 0, 0, 12 * 4);
+ if (nv30->blit_fp) {
+ struct pipe_transfer *transfer;
+ u32 *map = pipe_buffer_map(pipe, nv30->blit_fp,
+ PIPE_TRANSFER_WRITE, &transfer);
+ if (map) {
+ map[0] = 0x17009e00; /* texr r0, i[tex0], texture[0]; end; */
+ map[1] = 0x1c9dc801;
+ map[2] = 0x0001c800;
+ map[3] = 0x3fe1c800;
+ map[4] = 0x01401e81; /* end; */
+ map[5] = 0x1c9dc800;
+ map[6] = 0x0001c800;
+ map[7] = 0x0001c800;
+ pipe_buffer_unmap(pipe, transfer);
+ }
+
+ fp = nv04_resource(nv30->blit_fp);
+ nouveau_buffer_migrate(&nv30->base, fp, NOUVEAU_BO_VRAM);
+ }
+ }
+
+ return fp;
+}
+
+static void
+nv30_transfer_rect_blit(XFER_ARGS)
+{
+ struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30);
+ struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_pushbuf_refn refs[] = {
+ { fp->bo, fp->domain | NOUVEAU_BO_RD },
+ { src->bo, src->domain | NOUVEAU_BO_RD },
+ { dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },
+ };
+ u32 texfmt, texswz;
+ u32 format, stride;
+
+ if (nouveau_pushbuf_space(push, 512, 8, 0) ||
+ nouveau_pushbuf_refn (push, refs, sizeof(refs) / sizeof(refs[0])))
+ return;
+
+ /* various switches depending on cpp of the transfer */
+ switch (dst->cpp) {
+ case 4:
+ format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 |
+ NV30_3D_RT_FORMAT_ZETA_Z24S8;
+ texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
+ texswz = 0x0000aae4;
+ break;
+ case 2:
+ format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 |
+ NV30_3D_RT_FORMAT_ZETA_Z16;
+ texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5;
+ texswz = 0x0000a9e4;
+ break;
+ case 1:
+ format = NV30_3D_RT_FORMAT_COLOR_B8 |
+ NV30_3D_RT_FORMAT_ZETA_Z16;
+ texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8;
+ texswz = 0x0000aaff;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ /* render target */
+ if (!dst->pitch) {
+ format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ format |= util_logbase2(dst->w) << 16;
+ format |= util_logbase2(dst->h) << 24;
+ stride = 64;
+ } else {
+ format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ stride = dst->pitch;
+ }
+
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
+ PUSH_DATA (push, dst->w << 16);
+ PUSH_DATA (push, dst->h << 16);
+ BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5);
+ PUSH_DATA (push, dst->w << 16);
+ PUSH_DATA (push, dst->h << 16);
+ PUSH_DATA (push, format);
+ PUSH_DATA (push, stride);
+ PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+ BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
+ PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
+
+ nv30->dirty |= NV30_NEW_FRAMEBUFFER;
+
+ /* viewport state */
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ PUSH_DATAf(push, 1.0);
+ BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
+ PUSH_DATAf(push, 0.0);
+ PUSH_DATAf(push, 1.0);
+
+ nv30->dirty |= NV30_NEW_VIEWPORT;
+
+ /* blend state */
+ BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);
+ PUSH_DATA (push, 0x01010101);
+
+ nv30->dirty |= NV30_NEW_BLEND;
+
+ /* depth-stencil-alpha state */
+ BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);
+ PUSH_DATA (push, 0);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);
+ PUSH_DATA (push, 0);
+
+ nv30->dirty |= NV30_NEW_ZSA;
+
+ /* rasterizer state */
+ BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1);
+ PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT);
+ BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2);
+ PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL);
+ PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL);
+ BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1);
+ PUSH_DATA (push, 0);
+
+ nv30->state.scissor_off = 0;
+ nv30->dirty |= NV30_NEW_RASTERIZER;
+
+ /* vertex program */
+ BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
+ PUSH_DATA (push, vp->start);
+ BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
+ PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */
+ PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */
+ BEGIN_NV04(push, NV30_3D(ENGINE), 1);
+ PUSH_DATA (push, 0x00000103);
+ BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
+ PUSH_DATA (push, 0x00000000);
+
+ nv30->dirty |= NV30_NEW_VERTPROG;
+ nv30->dirty |= NV30_NEW_CLIP;
+
+ /* fragment program */
+ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
+ PUSH_RELOC(push, fp->bo, fp->offset, fp->domain |
+ NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+ NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
+ NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
+ BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
+ PUSH_DATA (push, 0x02000000);
+
+ nv30->state.fragprog = NULL;
+ nv30->dirty |= NV30_NEW_FRAGPROG;
+
+ /* texture */
+ texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
+ texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER;
+ texfmt |= NV40_3D_TEX_FORMAT_RECT;
+ texfmt |= 0x00008000;
+ if (src->d < 2)
+ texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
+ else
+ texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
+ if (src->pitch)
+ texfmt |= NV40_3D_TEX_FORMAT_LINEAR;
+
+ BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8);
+ PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR,
+ NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
+ PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE |
+ NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |
+ NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);
+ PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE);
+ PUSH_DATA (push, texswz);
+ switch (filter) {
+ case BILINEAR:
+ PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
+ NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000);
+ break;
+ default:
+ PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |
+ NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000);
+ break;
+ }
+ PUSH_DATA (push, (src->w << 16) | src->h);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1);
+ PUSH_DATA (push, 0x00100000 | src->pitch);
+ BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
+ PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000);
+ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
+ PUSH_DATA (push, 1);
+
+ nv30->fragprog.dirty_samplers |= 1;
+ nv30->dirty |= NV30_NEW_FRAGTEX;
+
+ /* blit! */
+ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
+ PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0);
+ PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0);
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
+ PUSH_DATAf(push, src->x0);
+ PUSH_DATAf(push, src->y0);
+ PUSH_DATAf(push, src->z);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
+ PUSH_DATA (push, (dst->y0 << 16) | dst->x0);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
+ PUSH_DATAf(push, src->x1);
+ PUSH_DATAf(push, src->y0);
+ PUSH_DATAf(push, src->z);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
+ PUSH_DATA (push, (dst->y0 << 16) | dst->x1);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
+ PUSH_DATAf(push, src->x1);
+ PUSH_DATAf(push, src->y1);
+ PUSH_DATAf(push, src->z);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
+ PUSH_DATA (push, (dst->y1 << 16) | dst->x1);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
+ PUSH_DATAf(push, src->x0);
+ PUSH_DATAf(push, src->y1);
+ PUSH_DATAf(push, src->z);
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
+ PUSH_DATA (push, (dst->y1 << 16) | dst->x0);
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+}
+
+static boolean
+nv30_transfer_sifm(XFER_ARGS)
+{
+ if (!src->pitch || (src->w | src->h) > 1024 || src->w < 2 || src->h < 2)
+ return FALSE;
+
+ if (src->d > 1 || dst->d > 1)
+ return FALSE;
+
+ if (dst->offset & 63)
+ return FALSE;
+
+ if (!dst->pitch) {
+ if ((dst->w | dst->h) > 2048 || dst->w < 2 || dst->h < 2)
+ return FALSE;
+ } else {
+ if (dst->domain != NOUVEAU_BO_VRAM)
+ return FALSE;
+ if (dst->pitch & 63)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+nv30_transfer_rect_sifm(XFER_ARGS)
+
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_pushbuf_refn refs[] = {
+ { src->bo, src->domain | NOUVEAU_BO_RD },
+ { dst->bo, dst->domain | NOUVEAU_BO_WR },
+ };
+ struct nv04_fifo *fifo = push->channel->data;
+ unsigned si_fmt, si_arg;
+ unsigned ss_fmt;
+
+ switch (dst->cpp) {
+ case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break;
+ case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break;
+ default:
+ ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8;
+ break;
+ }
+
+ switch (src->cpp) {
+ case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break;
+ case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break;
+ default:
+ si_fmt = NV03_SIFM_COLOR_FORMAT_AY8;
+ break;
+ }
+
+ if (filter == NEAREST) {
+ si_arg = NV03_SIFM_FORMAT_ORIGIN_CENTER;
+ si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE;
+ } else {
+ si_arg = NV03_SIFM_FORMAT_ORIGIN_CORNER;
+ si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR;
+ }
+
+ if (nouveau_pushbuf_space(push, 32, 6, 0) ||
+ nouveau_pushbuf_refn (push, refs, 2))
+ return;
+
+ if (dst->pitch) {
+ BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
+ PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+ PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+ BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
+ PUSH_DATA (push, ss_fmt);
+ PUSH_DATA (push, dst->pitch << 16 | dst->pitch);
+ PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+ BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
+ PUSH_DATA (push, nv30->screen->surf2d->handle);
+ } else {
+ BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
+ PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+ BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
+ PUSH_DATA (push, ss_fmt | (util_logbase2(dst->w) << 16) |
+ (util_logbase2(dst->h) << 24));
+ PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
+ BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
+ PUSH_DATA (push, nv30->screen->swzsurf->handle);
+ }
+
+ BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
+ PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
+ BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
+ PUSH_DATA (push, si_fmt);
+ PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);
+ PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);
+ PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
+ PUSH_DATA (push, ( dst->y0 << 16) | dst->x0);
+ PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
+ PUSH_DATA (push, ((src->x1 - src->x0) << 20) / (dst->x1 - dst->x0));
+ PUSH_DATA (push, ((src->y1 - src->y0) << 20) / (dst->y1 - dst->y0));
+ BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
+ PUSH_DATA (push, align(src->h, 2) << 16 | align(src->w, 2));
+ PUSH_DATA (push, src->pitch | si_arg);
+ PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_DATA (push, (src->y0 << 20) | src->x0 << 4);
+}
+
+/* The NOP+OFFSET_OUT stuff after each M2MF transfer *is* actually required
+ * to prevent some odd things from happening, easily reproducible by
+ * attempting to do conditional rendering that has a M2MF transfer done
+ * some time before it. 0x1e98 will fail with a DMA_W_PROTECTION (assuming
+ * that name is still accurate on nv4x) error.
+ */
+
+static boolean
+nv30_transfer_m2mf(XFER_ARGS)
+{
+ if (!src->pitch || !dst->pitch)
+ return FALSE;
+ if (nv30_transfer_scaled(src, dst))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+nv30_transfer_rect_m2mf(XFER_ARGS)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_pushbuf_refn refs[] = {
+ { src->bo, src->domain | NOUVEAU_BO_RD },
+ { dst->bo, dst->domain | NOUVEAU_BO_WR },
+ };
+ struct nv04_fifo *fifo = push->channel->data;
+ unsigned src_offset = src->offset;
+ unsigned dst_offset = dst->offset;
+ unsigned w = dst->x1 - dst->x0;
+ unsigned h = dst->y1 - dst->y0;
+
+ src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp);
+ dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp);
+
+ BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
+ PUSH_DATA (push, (src->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
+ PUSH_DATA (push, (dst->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
+
+ while (h) {
+ unsigned lines = (h > 2047) ? 2047 : h;
+
+ if (nouveau_pushbuf_space(push, 13, 2, 0) ||
+ nouveau_pushbuf_refn (push, refs, 2))
+ return;
+
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
+ PUSH_RELOC(push, src->bo, src_offset, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_RELOC(push, dst->bo, dst_offset, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_DATA (push, src->pitch);
+ PUSH_DATA (push, dst->pitch);
+ PUSH_DATA (push, w * src->cpp);
+ PUSH_DATA (push, lines);
+ PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
+ NV03_M2MF_FORMAT_OUTPUT_INC_1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
+ PUSH_DATA (push, 0x00000000);
+
+ h -= lines;
+ src_offset += src->pitch * lines;
+ dst_offset += dst->pitch * lines;
+ }
+}
+
+static boolean
+nv30_transfer_cpu(XFER_ARGS)
+{
+ if (nv30_transfer_scaled(src, dst))
+ return FALSE;
+ return TRUE;
+}
+
+static char *
+linear_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
+{
+ return base + (y * rect->pitch) + (x * rect->cpp);
+}
+
+static INLINE unsigned
+swizzle2d(unsigned v, unsigned s)
+{
+ v = (v | (v << 8)) & 0x00ff00ff;
+ v = (v | (v << 4)) & 0x0f0f0f0f;
+ v = (v | (v << 2)) & 0x33333333;
+ v = (v | (v << 1)) & 0x55555555;
+ return v << s;
+}
+
+static char *
+swizzle2d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
+{
+ unsigned k = util_logbase2(MIN2(rect->w, rect->h));
+ unsigned km = (1 << k) - 1;
+ unsigned nx = rect->w >> k;
+ unsigned tx = x >> k;
+ unsigned ty = y >> k;
+ unsigned m;
+
+ m = swizzle2d(x & km, 0);
+ m |= swizzle2d(y & km, 1);
+ m += ((ty * nx) + tx) << k << k;
+
+ return base + (m * rect->cpp);
+}
+
+static char *
+swizzle3d_ptr(struct nv30_rect *rect, char *base, int x, int y, int z)
+{
+ unsigned w = rect->w >> 1;
+ unsigned h = rect->h >> 1;
+ unsigned d = rect->d >> 1;
+ unsigned i = 0, o;
+ unsigned v = 0;
+
+ do {
+ o = i;
+ if (w) {
+ v |= (x & 1) << i++;
+ x >>= 1;
+ w >>= 1;
+ }
+ if (h) {
+ v |= (y & 1) << i++;
+ y >>= 1;
+ h >>= 1;
+ }
+ if (d) {
+ v |= (z & 1) << i++;
+ z >>= 1;
+ d >>= 1;
+ }
+ } while(o != i);
+
+ return base + (v * rect->cpp);
+}
+
+typedef char *(*get_ptr_t)(struct nv30_rect *, char *, int, int, int);
+
+static INLINE get_ptr_t
+get_ptr(struct nv30_rect *rect)
+{
+ if (rect->pitch)
+ return linear_ptr;
+
+ if (rect->d <= 1)
+ return swizzle2d_ptr;
+
+ return swizzle3d_ptr;
+}
+
+static void
+nv30_transfer_rect_cpu(XFER_ARGS)
+{
+ get_ptr_t sp = get_ptr(src);
+ get_ptr_t dp = get_ptr(dst);
+ char *srcmap, *dstmap;
+ int x, y;
+
+ nouveau_bo_map(src->bo, NOUVEAU_BO_RD, nv30->base.client);
+ nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, nv30->base.client);
+ srcmap = src->bo->map + src->offset;
+ dstmap = dst->bo->map + dst->offset;
+
+ for (y = 0; y < (dst->y1 - dst->y0); y++) {
+ for (x = 0; x < (dst->x1 - dst->x0); x++) {
+ memcpy(dp(dst, dstmap, dst->x0 + x, dst->y0 + y, dst->z),
+ sp(src, srcmap, src->x0 + x, src->y0 + y, src->z), dst->cpp);
+ }
+ }
+}
+
+void
+nv30_transfer_rect(struct nv30_context *nv30, enum nv30_transfer_filter filter,
+ struct nv30_rect *src, struct nv30_rect *dst)
+{
+ static const struct {
+ char *name;
+ boolean (*possible)(XFER_ARGS);
+ void (*execute)(XFER_ARGS);
+ } *method, methods[] = {
+ { "m2mf", nv30_transfer_m2mf, nv30_transfer_rect_m2mf },
+ { "sifm", nv30_transfer_sifm, nv30_transfer_rect_sifm },
+ { "blit", nv30_transfer_blit, nv30_transfer_rect_blit },
+ { "rect", nv30_transfer_cpu, nv30_transfer_rect_cpu },
+ {}
+ };
+
+ method = methods - 1;
+ while ((++method)->possible) {
+ if (method->possible(nv30, filter, src, dst)) {
+ method->execute(nv30, filter, src, dst);
+ return;
+ }
+ }
+
+ assert(0);
+}
+
+void
+nv30_transfer_push_data(struct nouveau_context *nv,
+ struct nouveau_bo *bo, unsigned offset, unsigned domain,
+ unsigned size, void *data)
+{
+ /* use ifc, or scratch + copy_data? */
+ fprintf(stderr, "nv30: push_data not implemented\n");
+}
+
+void
+nv30_transfer_copy_data(struct nouveau_context *nv,
+ struct nouveau_bo *dst, unsigned d_off, unsigned d_dom,
+ struct nouveau_bo *src, unsigned s_off, unsigned s_dom,
+ unsigned size)
+{
+ struct nv04_fifo *fifo = nv->screen->channel->data;
+ struct nouveau_pushbuf_refn refs[] = {
+ { src, s_dom | NOUVEAU_BO_RD },
+ { dst, d_dom | NOUVEAU_BO_WR },
+ };
+ struct nouveau_pushbuf *push = nv->pushbuf;
+ unsigned pages, lines;
+
+ pages = size >> 12;
+ size -= (pages << 12);
+
+ BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
+ PUSH_DATA (push, (s_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
+ PUSH_DATA (push, (d_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
+
+ while (pages) {
+ lines = (pages > 2047) ? 2047 : pages;
+ pages -= lines;
+
+ if (nouveau_pushbuf_space(push, 13, 2, 0) ||
+ nouveau_pushbuf_refn (push, refs, 2))
+ return;
+
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
+ PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_DATA (push, 4096);
+ PUSH_DATA (push, 4096);
+ PUSH_DATA (push, 4096);
+ PUSH_DATA (push, lines);
+ PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
+ NV03_M2MF_FORMAT_OUTPUT_INC_1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
+ PUSH_DATA (push, 0x00000000);
+
+ s_off += (lines << 12);
+ d_off += (lines << 12);
+ }
+
+ if (size) {
+ if (nouveau_pushbuf_space(push, 13, 2, 0) ||
+ nouveau_pushbuf_refn (push, refs, 2))
+ return;
+
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
+ PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
+ PUSH_DATA (push, size);
+ PUSH_DATA (push, size);
+ PUSH_DATA (push, size);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
+ NV03_M2MF_FORMAT_OUTPUT_INC_1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
+ PUSH_DATA (push, 0x00000000);
+ BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
+ PUSH_DATA (push, 0x00000000);
+ }
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_transfer.h b/src/gallium/drivers/nouveau/nv30/nv30_transfer.h
new file mode 100644
index 00000000000..3fa6cd0c029
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_transfer.h
@@ -0,0 +1,40 @@
+#ifndef __NV30_TRANSFER_H__
+#define __NV30_TRANSFER_H__
+
+struct nv30_rect {
+ struct nouveau_bo *bo;
+ unsigned offset;
+ unsigned domain;
+ unsigned pitch;
+ unsigned cpp;
+ unsigned w;
+ unsigned h;
+ unsigned d;
+ unsigned z;
+ unsigned x0;
+ unsigned x1;
+ unsigned y0;
+ unsigned y1;
+};
+
+enum nv30_transfer_filter {
+ NEAREST = 0,
+ BILINEAR
+};
+
+void
+nv30_transfer_rect(struct nv30_context *, enum nv30_transfer_filter filter,
+ struct nv30_rect *, struct nv30_rect *);
+
+void
+nv30_transfer_push_data(struct nouveau_context *,
+ struct nouveau_bo *, unsigned offset, unsigned domain,
+ unsigned size, void *data);
+
+void
+nv30_transfer_copy_data(struct nouveau_context *,
+ struct nouveau_bo *, unsigned dstoff, unsigned dstdom,
+ struct nouveau_bo *, unsigned srcoff, unsigned srcdom,
+ unsigned size);
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c
new file mode 100644
index 00000000000..d9b3c3ed04a
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+#include "translate/translate.h"
+
+#include "nouveau_fence.h"
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_format.h"
+
+static void
+nv30_emit_vtxattr(struct nv30_context *nv30, struct pipe_vertex_buffer *vb,
+ struct pipe_vertex_element *ve, unsigned attr)
+{
+ const unsigned nc = util_format_get_nr_components(ve->src_format);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv04_resource *res = nv04_resource(vb->buffer);
+ const struct util_format_description *desc =
+ util_format_description(ve->src_format);
+ const void *data;
+ float v[4];
+
+ data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset +
+ ve->src_offset, NOUVEAU_BO_RD);
+
+ desc->unpack_rgba_float(v, 0, data, 0, 1, 1);
+
+ switch (nc) {
+ case 4:
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_4F(attr)), 4);
+ PUSH_DATAf(push, v[0]);
+ PUSH_DATAf(push, v[1]);
+ PUSH_DATAf(push, v[2]);
+ PUSH_DATAf(push, v[3]);
+ break;
+ case 3:
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(attr)), 3);
+ PUSH_DATAf(push, v[0]);
+ PUSH_DATAf(push, v[1]);
+ PUSH_DATAf(push, v[2]);
+ break;
+ case 2:
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_2F(attr)), 2);
+ PUSH_DATAf(push, v[0]);
+ PUSH_DATAf(push, v[1]);
+ break;
+ case 1:
+ BEGIN_NV04(push, NV30_3D(VTX_ATTR_1F(attr)), 1);
+ PUSH_DATAf(push, v[0]);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static INLINE void
+nv30_vbuf_range(struct nv30_context *nv30, int vbi,
+ uint32_t *base, uint32_t *size)
+{
+ assert(nv30->vbo_max_index != ~0);
+ *base = nv30->vbo_min_index * nv30->vtxbuf[vbi].stride;
+ *size = (nv30->vbo_max_index -
+ nv30->vbo_min_index + 1) * nv30->vtxbuf[vbi].stride;
+}
+
+static void
+nv30_prevalidate_vbufs(struct nv30_context *nv30)
+{
+ struct pipe_vertex_buffer *vb;
+ struct nv04_resource *buf;
+ int i;
+ uint32_t base, size;
+
+ nv30->vbo_fifo = nv30->vbo_user = 0;
+
+ for (i = 0; i < nv30->num_vtxbufs; i++) {
+ vb = &nv30->vtxbuf[i];
+ if (!vb->stride || !vb->buffer) /* NOTE: user_buffer not implemented */
+ continue;
+ buf = nv04_resource(vb->buffer);
+
+ /* NOTE: user buffers with temporary storage count as mapped by GPU */
+ if (!nouveau_resource_mapped_by_gpu(vb->buffer)) {
+ if (nv30->vbo_push_hint) {
+ nv30->vbo_fifo = ~0;
+ continue;
+ } else {
+ if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) {
+ nv30->vbo_user |= 1 << i;
+ assert(vb->stride > vb->buffer_offset);
+ nv30_vbuf_range(nv30, i, &base, &size);
+ nouveau_user_buffer_upload(&nv30->base, buf, base, size);
+ } else {
+ nouveau_buffer_migrate(&nv30->base, buf, NOUVEAU_BO_GART);
+ }
+ nv30->base.vbo_dirty = TRUE;
+ }
+ }
+ }
+}
+
+static void
+nv30_update_user_vbufs(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ uint32_t base, offset, size;
+ int i;
+ uint32_t written = 0;
+
+ for (i = 0; i < nv30->vertex->num_elements; i++) {
+ struct pipe_vertex_element *ve = &nv30->vertex->pipe[i];
+ const int b = ve->vertex_buffer_index;
+ struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b];
+ struct nv04_resource *buf = nv04_resource(vb->buffer);
+
+ if (!(nv30->vbo_user & (1 << b)))
+ continue;
+
+ if (!vb->stride) {
+ nv30_emit_vtxattr(nv30, vb, ve, i);
+ continue;
+ }
+ nv30_vbuf_range(nv30, b, &base, &size);
+
+ if (!(written & (1 << b))) {
+ written |= 1 << b;
+ nouveau_user_buffer_upload(&nv30->base, buf, base, size);
+ }
+
+ offset = vb->buffer_offset + ve->src_offset;
+
+ BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
+ PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset,
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
+ 0, NV30_3D_VTXBUF_DMA1);
+ }
+ nv30->base.vbo_dirty = TRUE;
+}
+
+static INLINE void
+nv30_release_user_vbufs(struct nv30_context *nv30)
+{
+ uint32_t vbo_user = nv30->vbo_user;
+
+ while (vbo_user) {
+ int i = ffs(vbo_user) - 1;
+ vbo_user &= ~(1 << i);
+
+ nouveau_buffer_release_gpu_storage(nv04_resource(nv30->vtxbuf[i].buffer));
+ }
+
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXTMP);
+}
+
+void
+nv30_vbo_validate(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv30_vertex_stateobj *vertex = nv30->vertex;
+ struct pipe_vertex_element *ve;
+ struct pipe_vertex_buffer *vb;
+ unsigned i, redefine;
+
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
+ if (!nv30->vertex || nv30->draw_flags)
+ return;
+
+ if (unlikely(vertex->need_conversion)) {
+ nv30->vbo_fifo = ~0;
+ nv30->vbo_user = 0;
+ } else {
+ nv30_prevalidate_vbufs(nv30);
+ }
+
+ if (!PUSH_SPACE(push, 128))
+ return;
+
+ redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts);
+ BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine);
+
+ for (i = 0; i < vertex->num_elements; i++) {
+ ve = &vertex->pipe[i];
+ vb = &nv30->vtxbuf[ve->vertex_buffer_index];
+
+ if (likely(vb->stride) || nv30->vbo_fifo)
+ PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state);
+ else
+ PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
+ }
+
+ for (; i < nv30->state.num_vtxelts; i++) {
+ PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
+ }
+
+ for (i = 0; i < vertex->num_elements; i++) {
+ struct nv04_resource *res;
+ unsigned offset;
+ boolean user;
+
+ ve = &vertex->pipe[i];
+ vb = &nv30->vtxbuf[ve->vertex_buffer_index];
+ user = (nv30->vbo_user & (1 << ve->vertex_buffer_index));
+
+ res = nv04_resource(vb->buffer);
+
+ if (nv30->vbo_fifo || unlikely(vb->stride == 0)) {
+ if (!nv30->vbo_fifo)
+ nv30_emit_vtxattr(nv30, vb, ve, i);
+ continue;
+ }
+
+ offset = ve->src_offset + vb->buffer_offset;
+
+ BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
+ PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF,
+ res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
+ 0, NV30_3D_VTXBUF_DMA1);
+ }
+
+ nv30->state.num_vtxelts = vertex->num_elements;
+}
+
+static void *
+nv30_vertex_state_create(struct pipe_context *pipe, unsigned num_elements,
+ const struct pipe_vertex_element *elements)
+{
+ struct nv30_vertex_stateobj *so;
+ struct translate_key transkey;
+ unsigned i;
+
+ assert(num_elements);
+
+ so = MALLOC(sizeof(*so) + sizeof(*so->element) * num_elements);
+ if (!so)
+ return NULL;
+ memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
+ so->num_elements = num_elements;
+ so->need_conversion = FALSE;
+
+ transkey.nr_elements = 0;
+ transkey.output_stride = 0;
+
+ for (i = 0; i < num_elements; i++) {
+ const struct pipe_vertex_element *ve = &elements[i];
+ const unsigned vbi = ve->vertex_buffer_index;
+ enum pipe_format fmt = ve->src_format;
+
+ so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
+ if (!so->element[i].state) {
+ switch (util_format_get_nr_components(fmt)) {
+ case 1: fmt = PIPE_FORMAT_R32_FLOAT; break;
+ case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break;
+ case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break;
+ case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break;
+ default:
+ assert(0);
+ FREE(so);
+ return NULL;
+ }
+ so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
+ so->need_conversion = TRUE;
+ }
+
+ if (1) {
+ unsigned j = transkey.nr_elements++;
+
+ transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
+ transkey.element[j].input_format = ve->src_format;
+ transkey.element[j].input_buffer = vbi;
+ transkey.element[j].input_offset = ve->src_offset;
+ transkey.element[j].instance_divisor = ve->instance_divisor;
+
+ transkey.element[j].output_format = fmt;
+ transkey.element[j].output_offset = transkey.output_stride;
+ transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
+ }
+ }
+
+ so->translate = translate_create(&transkey);
+ so->vtx_size = transkey.output_stride / 4;
+ so->vtx_per_packet_max = NV04_PFIFO_MAX_PACKET_LEN / MAX2(so->vtx_size, 1);
+ return so;
+}
+
+static void
+nv30_vertex_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_vertex_stateobj *so = hwcso;
+
+ if (so->translate)
+ so->translate->release(so->translate);
+ FREE(hwcso);
+}
+
+static void
+nv30_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->vertex = hwcso;
+ nv30->dirty |= NV30_NEW_VERTEX;
+}
+
+static void
+nv30_draw_arrays(struct nv30_context *nv30,
+ unsigned mode, unsigned start, unsigned count,
+ unsigned instance_count)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned prim;
+
+ prim = nv30_prim_gl(mode);
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, prim);
+ while (count) {
+ const unsigned mpush = 2047 * 256;
+ unsigned npush = (count > mpush) ? mpush : count;
+ unsigned wpush = ((npush + 255) & ~255) >> 8;
+
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), wpush);
+ while (npush >= 256) {
+ PUSH_DATA (push, 0xff000000 | start);
+ start += 256;
+ npush -= 256;
+ }
+
+ if (npush)
+ PUSH_DATA (push, ((npush - 1) << 24) | start);
+ }
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+}
+
+static void
+nv30_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map,
+ unsigned start, unsigned count)
+{
+ map += start;
+
+ if (count & 1) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (push, *map++);
+ }
+
+ count >>= 1;
+ while (count) {
+ unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
+ while (npush--) {
+ PUSH_DATA (push, (map[1] << 16) | map[0]);
+ map += 2;
+ }
+ }
+
+}
+
+static void
+nv30_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map,
+ unsigned start, unsigned count)
+{
+ map += start;
+
+ if (count & 1) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (push, *map++);
+ }
+
+ count >>= 1;
+ while (count) {
+ unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
+ while (npush--) {
+ PUSH_DATA (push, (map[1] << 16) | map[0]);
+ map += 2;
+ }
+ }
+}
+
+static void
+nv30_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map,
+ unsigned start, unsigned count)
+{
+ map += start;
+
+ while (count) {
+ const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
+
+ BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U32), nr);
+ PUSH_DATAp(push, map, nr);
+
+ map += nr;
+ count -= nr;
+ }
+}
+
+static void
+nv30_draw_elements_inline_u32_short(struct nouveau_pushbuf *push,
+ const uint32_t *map,
+ unsigned start, unsigned count)
+{
+ map += start;
+
+ if (count & 1) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
+ PUSH_DATA (push, *map++);
+ }
+
+ count >>= 1;
+ while (count) {
+ unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);;
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
+ while (npush--) {
+ PUSH_DATA (push, (map[1] << 16) | map[0]);
+ map += 2;
+ }
+ }
+}
+
+static void
+nv30_draw_elements(struct nv30_context *nv30, boolean shorten,
+ unsigned mode, unsigned start, unsigned count,
+ unsigned instance_count, int32_t index_bias)
+{
+ const unsigned index_size = nv30->idxbuf.index_size;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ unsigned prim = nv30_prim_gl(mode);
+
+#if 0 /*XXX*/
+ if (index_bias != nv30->state.index_bias) {
+ BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1);
+ PUSH_DATA (push, index_bias);
+ nv30->state.index_bias = index_bias;
+ }
+#endif
+
+ if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 &&
+ nv30->idxbuf.buffer) {
+ struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer);
+ unsigned offset = nv30->idxbuf.offset;
+
+ assert(nouveau_resource_mapped_by_gpu(&res->base));
+
+ BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2);
+ PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset,
+ NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
+ PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo,
+ (index_size == 2) ? 0x00000010 : 0x00000000,
+ res->domain | NOUVEAU_BO_RD,
+ 0, NV30_3D_IDXBUF_FORMAT_DMA1);
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, prim);
+ while (count) {
+ const unsigned mpush = 2047 * 256;
+ unsigned npush = (count > mpush) ? mpush : count;
+ unsigned wpush = ((npush + 255) & ~255) >> 8;
+
+ count -= npush;
+
+ BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush);
+ while (npush >= 256) {
+ PUSH_DATA (push, 0xff000000 | start);
+ start += 256;
+ npush -= 256;
+ }
+
+ if (npush)
+ PUSH_DATA (push, ((npush - 1) << 24) | start);
+ }
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ PUSH_RESET(push, BUFCTX_IDXBUF);
+ } else {
+ const void *data;
+ if (nv30->idxbuf.buffer)
+ data = nouveau_resource_map_offset(&nv30->base,
+ nv04_resource(nv30->idxbuf.buffer),
+ nv30->idxbuf.offset, NOUVEAU_BO_RD);
+ else
+ data = nv30->idxbuf.user_buffer;
+ if (!data)
+ return;
+
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, prim);
+ switch (index_size) {
+ case 1:
+ nv30_draw_elements_inline_u08(push, data, start, count);
+ break;
+ case 2:
+ nv30_draw_elements_inline_u16(push, data, start, count);
+ break;
+ case 4:
+ if (shorten)
+ nv30_draw_elements_inline_u32_short(push, data, start, count);
+ else
+ nv30_draw_elements_inline_u32(push, data, start, count);
+ break;
+ default:
+ assert(0);
+ return;
+ }
+ BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
+ PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
+ }
+}
+
+static void
+nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ /* For picking only a few vertices from a large user buffer, push is better,
+ * if index count is larger and we expect repeated vertices, suggest upload.
+ */
+ nv30->vbo_push_hint = /* the 64 is heuristic */
+ !(info->indexed &&
+ ((info->max_index - info->min_index + 64) < info->count));
+
+ nv30->vbo_min_index = info->min_index;
+ nv30->vbo_max_index = info->max_index;
+
+ if (nv30->vbo_push_hint != !!nv30->vbo_fifo)
+ nv30->dirty |= NV30_NEW_ARRAYS;
+
+ push->user_priv = &nv30->bufctx;
+ if (nv30->vbo_user && !(nv30->dirty & (NV30_NEW_VERTEX | NV30_NEW_ARRAYS)))
+ nv30_update_user_vbufs(nv30);
+
+ nv30_state_validate(nv30, TRUE);
+ if (nv30->draw_flags) {
+ nv30_render_vbo(pipe, info);
+ return;
+ } else
+ if (nv30->vbo_fifo) {
+ nv30_push_vbo(nv30, info);
+ return;
+ }
+
+ if (nv30->base.vbo_dirty) {
+ BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
+ PUSH_DATA (push, 0);
+ nv30->base.vbo_dirty = FALSE;
+ }
+
+ if (!info->indexed) {
+ nv30_draw_arrays(nv30,
+ info->mode, info->start, info->count,
+ info->instance_count);
+ } else {
+ boolean shorten = info->max_index <= 65535;
+
+ if (info->primitive_restart != nv30->state.prim_restart) {
+ if (info->primitive_restart) {
+ BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 2);
+ PUSH_DATA (push, 1);
+ PUSH_DATA (push, info->restart_index);
+
+ if (info->restart_index > 65535)
+ shorten = FALSE;
+ } else {
+ BEGIN_NV04(push, NV40_3D(PRIM_RESTART_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ }
+ nv30->state.prim_restart = info->primitive_restart;
+ } else
+ if (info->primitive_restart) {
+ BEGIN_NV04(push, NV40_3D(PRIM_RESTART_INDEX), 1);
+ PUSH_DATA (push, info->restart_index);
+
+ if (info->restart_index > 65535)
+ shorten = FALSE;
+ }
+
+ nv30_draw_elements(nv30, shorten,
+ info->mode, info->start, info->count,
+ info->instance_count, info->index_bias);
+ }
+
+ nv30_state_release(nv30);
+ nv30_release_user_vbufs(nv30);
+}
+
+void
+nv30_vbo_init(struct pipe_context *pipe)
+{
+ pipe->create_vertex_elements_state = nv30_vertex_state_create;
+ pipe->delete_vertex_elements_state = nv30_vertex_state_delete;
+ pipe->bind_vertex_elements_state = nv30_vertex_state_bind;
+ pipe->draw_vbo = nv30_draw_vbo;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c
new file mode 100644
index 00000000000..7bf05ddfe0a
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_dynarray.h"
+#include "tgsi/tgsi_parse.h"
+
+#include "nv_object.xml.h"
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_state.h"
+
+static void
+nv30_vertprog_destroy(struct nv30_vertprog *vp)
+{
+ util_dynarray_fini(&vp->branch_relocs);
+ nouveau_heap_free(&vp->exec);
+ FREE(vp->insns);
+ vp->insns = NULL;
+ vp->nr_insns = 0;
+
+ util_dynarray_fini(&vp->const_relocs);
+ nouveau_heap_free(&vp->data);
+ FREE(vp->consts);
+ vp->consts = NULL;
+ vp->nr_consts = 0;
+
+ vp->translated = FALSE;
+}
+
+void
+nv30_vertprog_validate(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ struct nv30_vertprog *vp = nv30->vertprog.program;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ boolean upload_code = FALSE;
+ boolean upload_data = FALSE;
+ unsigned i;
+
+ if (nv30->dirty & NV30_NEW_FRAGPROG) {
+ if (memcmp(vp->texcoord, fp->texcoord, sizeof(vp->texcoord))) {
+ if (vp->translated)
+ nv30_vertprog_destroy(vp);
+ memcpy(vp->texcoord, fp->texcoord, sizeof(vp->texcoord));
+ }
+ }
+
+ if (nv30->rast && nv30->rast->pipe.clip_plane_enable != vp->enabled_ucps) {
+ vp->enabled_ucps = nv30->rast->pipe.clip_plane_enable;
+ if (vp->translated)
+ nv30_vertprog_destroy(vp);
+ }
+
+ if (!vp->translated) {
+ vp->translated = _nvfx_vertprog_translate(nv30, vp);
+ if (!vp->translated) {
+ nv30->draw_flags |= NV30_NEW_VERTPROG;
+ return;
+ }
+ nv30->dirty |= NV30_NEW_VERTPROG;
+ }
+
+ if (!vp->exec) {
+ struct nouveau_heap *heap = nv30->screen->vp_exec_heap;
+ struct nv30_shader_reloc *reloc = vp->branch_relocs.data;
+ unsigned nr_reloc = vp->branch_relocs.size / sizeof(*reloc);
+ uint32_t *inst, target;
+
+ if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) {
+ while (heap->next && heap->size < vp->nr_insns) {
+ struct nouveau_heap **evict = heap->next->priv;
+ nouveau_heap_free(evict);
+ }
+
+ if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) {
+ nv30->draw_flags |= NV30_NEW_VERTPROG;
+ return;
+ }
+ }
+
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ while (nr_reloc--) {
+ inst = vp->insns[reloc->location].data;
+ target = vp->exec->start + reloc->target;
+
+ inst[2] &= ~0x000007fc;
+ inst[2] |= target << 2;
+ reloc++;
+ }
+ } else {
+ while (nr_reloc--) {
+ inst = vp->insns[reloc->location].data;
+ target = vp->exec->start + reloc->target;
+
+ inst[2] &= ~0x0000003f;
+ inst[2] |= target >> 3;
+ inst[3] &= ~0xe0000000;
+ inst[3] |= target << 29;
+ reloc++;
+ }
+ }
+
+ upload_code = TRUE;
+ }
+
+ if (vp->nr_consts && !vp->data) {
+ struct nouveau_heap *heap = nv30->screen->vp_data_heap;
+ struct nv30_shader_reloc *reloc = vp->const_relocs.data;
+ unsigned nr_reloc = vp->const_relocs.size / sizeof(*reloc);
+ uint32_t *inst, target;
+
+ if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ while (heap->next && heap->size < vp->nr_consts) {
+ struct nv30_vertprog *evp = heap->next->priv;
+ nouveau_heap_free(&evp->data);
+ }
+
+ if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ nv30->draw_flags |= NV30_NEW_VERTPROG;
+ return;
+ }
+ }
+
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ while (nr_reloc--) {
+ inst = vp->insns[reloc->location].data;
+ target = vp->data->start + reloc->target;
+
+ inst[1] &= ~0x0007fc000;
+ inst[1] |= (target & 0x1ff) << 14;
+ reloc++;
+ }
+ } else {
+ while (nr_reloc--) {
+ inst = vp->insns[reloc->location].data;
+ target = vp->data->start + reloc->target;
+
+ inst[1] &= ~0x0001ff000;
+ inst[1] |= (target & 0x1ff) << 12;
+ reloc++;
+ }
+ }
+
+ upload_code = TRUE;
+ upload_data = TRUE;
+ }
+
+ if (vp->nr_consts) {
+ struct nv04_resource *res = nv04_resource(nv30->vertprog.constbuf);
+
+ for (i = 0; i < vp->nr_consts; i++) {
+ struct nv30_vertprog_data *data = &vp->consts[i];
+
+ if (data->index < 0) {
+ if (!upload_data)
+ continue;
+ } else {
+ float *constbuf = (float *)res->data;
+ if (!upload_data &&
+ !memcmp(data->value, &constbuf[data->index * 4], 16))
+ continue;
+ memcpy(data->value, &constbuf[data->index * 4], 16);
+ }
+
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
+ PUSH_DATA (push, vp->data->start + i);
+ PUSH_DATAp(push, data->value, 4);
+ }
+ }
+
+ if (upload_code) {
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1);
+ PUSH_DATA (push, vp->exec->start);
+ for (i = 0; i < vp->nr_insns; i++) {
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4);
+ PUSH_DATAp(push, vp->insns[i].data, 4);
+ }
+ }
+
+ if (nv30->dirty & (NV30_NEW_VERTPROG | NV30_NEW_FRAGPROG)) {
+ BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
+ PUSH_DATA (push, vp->exec->start);
+ if (eng3d->oclass < NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV30_3D(ENGINE), 1);
+ PUSH_DATA (push, 0x00000013); /* vp instead of ff, somehow */
+ } else {
+ BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
+ PUSH_DATA (push, vp->ir);
+ PUSH_DATA (push, vp->or | fp->vp_or);
+ BEGIN_NV04(push, NV30_3D(ENGINE), 1);
+ PUSH_DATA (push, 0x00000011);
+ }
+ }
+}
+
+static void *
+nv30_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv30_vertprog *vp = CALLOC_STRUCT(nv30_vertprog);
+ if (!vp)
+ return NULL;
+
+ vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ tgsi_scan_shader(vp->pipe.tokens, &vp->info);
+ return vp;
+}
+
+static void
+nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_vertprog *vp = hwcso;
+
+ if (vp->translated)
+ nv30_vertprog_destroy(vp);
+ FREE((void *)vp->pipe.tokens);
+ FREE(vp);
+}
+
+static void
+nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+
+ nv30->vertprog.program = hwcso;
+ nv30->dirty |= NV30_NEW_VERTPROG;
+}
+
+void
+nv30_vertprog_init(struct pipe_context *pipe)
+{
+ pipe->create_vs_state = nv30_vp_state_create;
+ pipe->bind_vs_state = nv30_vp_state_bind;
+ pipe->delete_vs_state = nv30_vp_state_delete;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vertprog.h b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.h
new file mode 100644
index 00000000000..5556e0c77bd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_vertprog.h
@@ -0,0 +1,176 @@
+#ifndef __NV30_SHADER_H__
+#define __NV30_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * 128bit opcodes, split into 4 32-bit ones for ease of use.
+ *
+ * Non-native instructions
+ * ABS - MOV + NV40_VP_INST0_DEST_ABS
+ * POW - EX2 + MUL + LG2
+ * SUB - ADD, second source negated
+ * SWZ - MOV
+ * XPD -
+ *
+ * Register access
+ * - Only one INPUT can be accessed per-instruction (move extras into TEMPs)
+ * - Only one CONST can be accessed per-instruction (move extras into TEMPs)
+ *
+ * Relative Addressing
+ * According to the value returned for
+ * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB
+ *
+ * there are only two address registers available. The destination in the
+ * ARL instruction is set to TEMP <n> (The temp isn't actually written).
+ *
+ * When using vanilla ARB_v_p, the proprietary driver will squish both the
+ * available ADDRESS regs into the first hardware reg in the X and Y
+ * components.
+ *
+ * To use an address reg as an index into consts, the CONST_SRC is set to
+ * (const_base + offset) and INDEX_CONST is set.
+ *
+ * To access the second address reg use ADDR_REG_SELECT_1. A particular
+ * component of the address regs is selected with ADDR_SWZ.
+ *
+ * Only one address register can be accessed per instruction.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details) Conditional
+ * execution of an instruction is enabled by setting COND_TEST_ENABLE, and
+ * selecting the condition which will allow the test to pass with
+ * COND_{FL,LT,...}. It is possible to swizzle the values in the condition
+ * register, which allows for testing against an individual component.
+ *
+ * Branching:
+ *
+ * The BRA/CAL instructions seem to follow a slightly different opcode
+ * layout. The destination instruction ID (IADDR) overlaps a source field.
+ * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO
+ * command, and is incremented automatically on each UPLOAD_INST FIFO
+ * command.
+ *
+ * Conditional branching is achieved by using the condition tests described
+ * above. There doesn't appear to be dedicated looping instructions, but
+ * this can be done using a temp reg + conditional branching.
+ *
+ * Subroutines may be uploaded before the main program itself, but the first
+ * executed instruction is determined by the PROGRAM_START_ID FIFO command.
+ *
+ */
+
+/* DWORD 0 */
+
+/* guess that this is the same as nv40 */
+#define NV30_VP_INST_INDEX_INPUT (1 << 27)
+
+#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */
+#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */
+#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */
+#define NV30_VP_INST_VEC_RESULT (1 << 20)
+#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16
+#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16)
+#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15)
+#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 16)
+#define NV30_VP_INST_COND_TEST_ENABLE (1<<14)
+#define NV30_VP_INST_COND_SHIFT 11
+#define NV30_VP_INST_COND_MASK (0x07 << 11)
+#define NV30_VP_INST_COND_SWZ_X_SHIFT 9
+#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9)
+#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7
+#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7)
+#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5
+#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5)
+#define NV30_VP_INST_COND_SWZ_W_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3)
+#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3
+#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3)
+#define NV30_VP_INST_ADDR_SWZ_SHIFT 1
+#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1)
+#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0
+#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0)
+
+/* DWORD 1 */
+#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28
+#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28)
+#define NV30_VP_INST_VEC_OPCODE_SHIFT 23
+#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23)
+#define NV30_VP_INST_CONST_SRC_SHIFT 14
+#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14)
+#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/
+#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/
+#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/
+
+/* Please note: the IADDR fields overlap other fields because they are used
+ * only for branch instructions. See Branching: label above
+ *
+ * DWORD 2
+ */
+#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/
+#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */
+#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/
+#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/
+#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/
+#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/
+#define NV30_VP_INST_IADDR_SHIFT 2
+#define NV30_VP_INST_IADDR_MASK (0x1FF << 2) /* NV30_VP_SRC2_LOW_MASK << 28 */
+
+/* DWORD 3 */
+#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/
+#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/
+#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24
+#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24)
+#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20
+#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20)
+#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16
+#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16)
+#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/
+#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/
+#define NV30_VP_INST_DEST_SHIFT 2
+#define NV30_VP_INST_DEST_MASK (0x1F << 2)
+# define NV30_VP_INST_DEST_POS 0
+# define NV30_VP_INST_DEST_BFC0 1
+# define NV30_VP_INST_DEST_BFC1 2
+# define NV30_VP_INST_DEST_COL0 3
+# define NV30_VP_INST_DEST_COL1 4
+# define NV30_VP_INST_DEST_FOGC 5
+# define NV30_VP_INST_DEST_PSZ 6
+# define NV30_VP_INST_DEST_TC(n) (8+(n))
+# define NV30_VP_INST_DEST_CLP(n) (17 + (n))
+
+/* guess that this is the same as nv40 */
+#define NV30_VP_INST_INDEX_CONST (1 << 1)
+
+/* Useful to split the source selection regs into their pieces */
+#define NV30_VP_SRC0_HIGH_SHIFT 6
+#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0
+#define NV30_VP_SRC0_LOW_MASK 0x0000003F
+#define NV30_VP_SRC2_HIGH_SHIFT 4
+#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0
+#define NV30_VP_SRC2_LOW_MASK 0x0000000F
+
+
+/* Source-register definition - matches NV20 exactly */
+#define NV30_VP_SRC_NEGATE (1<<14)
+#define NV30_VP_SRC_SWZ_X_SHIFT 12
+#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12)
+#define NV30_VP_SRC_SWZ_Y_SHIFT 10
+#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10)
+#define NV30_VP_SRC_SWZ_Z_SHIFT 8
+#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8)
+#define NV30_VP_SRC_SWZ_W_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6)
+#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6
+#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6)
+#define NV30_VP_SRC_TEMP_SRC_SHIFT 2
+#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0)
+#define NV30_VP_SRC_REG_TYPE_SHIFT 0
+#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0)
+#define NV30_VP_SRC_REG_TYPE_TEMP 1
+#define NV30_VP_SRC_REG_TYPE_INPUT 2
+#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */
+
+#include "nv30/nvfx_shader.h"
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_winsys.h b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h
new file mode 100644
index 00000000000..5cee5df60ce
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv30_winsys.h
@@ -0,0 +1,158 @@
+#ifndef __NV30_WINSYS_H__
+#define __NV30_WINSYS_H__
+
+#include <string.h>
+#include "nouveau_winsys.h"
+#include "nouveau_buffer.h"
+
+/*XXX: rnn */
+#define NV40_3D_VTXTEX_OFFSET(i) (0x0900 + ((i) * 0x20)) // 401e80
+#define NV40_3D_VTXTEX_FORMAT(i) (0x0904 + ((i) * 0x20)) // 401e90
+#define NV40_3D_VTXTEX_WRAP(i) (0x0908 + ((i) * 0x20)) // 401ea0
+#define NV40_3D_VTXTEX_ENABLE(i) (0x090c + ((i) * 0x20)) // 401eb0
+#define NV40_3D_VTXTEX_SWZ(i) (0x0910 + ((i) * 0x20)) // 401ec0
+#define NV40_3D_VTXTEX_FILTER(i) (0x0914 + ((i) * 0x20)) // 401ed0
+#define NV40_3D_VTXTEX_SIZE(i) (0x0918 + ((i) * 0x20)) // 401ee0
+#define NV40_3D_VTXTEX_BCOL(i) (0x091c + ((i) * 0x20)) // 401ef0
+#define NV30_3D_VTX_CACHE_INVALIDATE_1710 0x1710
+#define NV30_3D_R1718 0x1718
+#define NV40_3D_PRIM_RESTART_ENABLE 0x1dac
+#define NV40_3D_PRIM_RESTART_INDEX 0x1db0
+
+static INLINE void
+PUSH_RELOC(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t offset,
+ uint32_t flags, uint32_t vor, uint32_t tor)
+{
+ nouveau_pushbuf_reloc(push, bo, offset, flags, vor, tor);
+}
+
+static INLINE struct nouveau_bufctx *
+bufctx(struct nouveau_pushbuf *push)
+{
+ struct nouveau_bufctx **pctx = push->user_priv;
+ return *pctx;
+}
+
+static INLINE void
+PUSH_RESET(struct nouveau_pushbuf *push, int bin)
+{
+ nouveau_bufctx_reset(bufctx(push), bin);
+}
+
+static INLINE void
+PUSH_REFN(struct nouveau_pushbuf *push, int bin,
+ struct nouveau_bo *bo, uint32_t access)
+{
+ nouveau_bufctx_refn(bufctx(push), bin, bo, access);
+}
+
+static INLINE void
+PUSH_MTHDl(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
+ struct nouveau_bo *bo, uint32_t offset, uint32_t access)
+{
+ nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
+ bo, offset, access | NOUVEAU_BO_LOW, 0, 0)->priv = NULL;
+ PUSH_DATA(push, bo->offset + offset);
+}
+
+static INLINE void
+PUSH_MTHDo(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
+ struct nouveau_bo *bo, uint32_t access, uint32_t vor, uint32_t tor)
+{
+ nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
+ bo, 0, access | NOUVEAU_BO_OR, vor, tor)->priv = NULL;
+ if (bo->flags & NOUVEAU_BO_VRAM)
+ PUSH_DATA(push, vor);
+ else
+ PUSH_DATA(push, tor);
+}
+
+static INLINE void
+PUSH_MTHDs(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
+ struct nouveau_bo *bo, uint32_t data, uint32_t access,
+ uint32_t vor, uint32_t tor)
+{
+ nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
+ bo, data, access | NOUVEAU_BO_OR, vor, tor)->priv = NULL;
+ if (bo->flags & NOUVEAU_BO_VRAM)
+ PUSH_DATA(push, data | vor);
+ else
+ PUSH_DATA(push, data | tor);
+}
+
+static INLINE struct nouveau_bufref *
+PUSH_MTHD(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
+ struct nouveau_bo *bo, uint32_t data, uint32_t access,
+ uint32_t vor, uint32_t tor)
+{
+ struct nouveau_bufref *bref =
+ nouveau_bufctx_mthd(bufctx(push), bin, (1 << 18) | (subc << 13) | mthd,
+ bo, data, access | NOUVEAU_BO_OR, vor, tor);
+ if (access & NOUVEAU_BO_LOW)
+ data += bo->offset;
+ if (bo->flags & NOUVEAU_BO_VRAM)
+ data |= vor;
+ else
+ data |= tor;
+ PUSH_DATA(push, data);
+ bref->priv = NULL;
+ return bref;
+}
+
+static INLINE void
+PUSH_RESRC(struct nouveau_pushbuf *push, int subc, int mthd, int bin,
+ struct nv04_resource *r, uint32_t data, uint32_t access,
+ uint32_t vor, uint32_t tor)
+{
+ PUSH_MTHD(push, subc, mthd, bin, r->bo, r->offset + data,
+ r->domain | access, vor, tor)->priv = r;
+}
+
+static INLINE void
+BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ PUSH_SPACE(push, size + 1);
+ PUSH_DATA (push, 0x00000000 | (size << 18) | (subc << 13) | mthd);
+}
+
+static INLINE void
+BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
+{
+ PUSH_SPACE(push, size + 1);
+ PUSH_DATA (push, 0x40000000 | (size << 18) | (subc << 13) | mthd);
+}
+
+/* subchannel assignment
+ *
+ * 0: <1.0.0 - used by kernel for m2mf
+ * 1.0.0 - used by kernel for nvsw
+ *
+ * 1: <1.0.0 - used by kernel for nvsw
+ * 1.0.0 - free for userspace
+ *
+ * 2-7: free for userspace on all kernel versions
+ */
+
+#define SUBC_M2MF(mthd) 2, (mthd)
+#define NV03_M2MF(mthd) SUBC_M2MF(NV03_M2MF_##mthd)
+
+#define SUBC_SF2D(mthd) 3, (mthd)
+#define NV04_SF2D(mthd) SUBC_SF2D(NV04_SURFACE_2D_##mthd)
+
+#define SUBC_SSWZ(mthd) 4, (mthd)
+#define NV04_SSWZ(mthd) SUBC_SSWZ(NV04_SURFACE_SWZ_##mthd)
+
+#define SUBC_SIFM(mthd) 5, (mthd)
+#define NV03_SIFM(mthd) SUBC_SIFM(NV03_SIFM_##mthd)
+#define NV05_SIFM(mthd) SUBC_SIFM(NV05_SIFM_##mthd)
+
+#define SUBC_3D(mthd) 7, (mthd)
+#define NV30_3D(mthd) SUBC_3D(NV30_3D_##mthd)
+#define NV40_3D(mthd) SUBC_3D(NV40_3D_##mthd)
+
+#define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd))
+#define NV11_SUBC(subc, mthd) SUBC_##subc((NV11_SUBCHAN_##mthd))
+
+#define NV04_GRAPH(subc, mthd) SUBC_##subc((NV04_GRAPH_##mthd))
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv40_vertprog.h b/src/gallium/drivers/nouveau/nv30/nv40_vertprog.h
new file mode 100644
index 00000000000..b369ced886e
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv40_vertprog.h
@@ -0,0 +1,178 @@
+#ifndef __NV40_SHADER_H__
+#define __NV40_SHADER_H__
+
+/* Vertex programs instruction set
+ *
+ * The NV40 instruction set is very similar to NV30. Most fields are in
+ * a slightly different position in the instruction however.
+ *
+ * Merged instructions
+ * In some cases it is possible to put two instructions into one opcode
+ * slot. The rules for when this is OK is not entirely clear to me yet.
+ *
+ * There are separate writemasks and dest temp register fields for each
+ * grouping of instructions. There is however only one field with the
+ * ID of a result register. Writing to temp/result regs is selected by
+ * setting VEC_RESULT/SCA_RESULT.
+ *
+ * Temporary registers
+ * The source/dest temp register fields have been extended by 1 bit, to
+ * give a total of 32 temporary registers.
+ *
+ * Relative Addressing
+ * NV40 can use an address register to index into vertex attribute regs.
+ * This is done by putting the offset value into INPUT_SRC and setting
+ * the INDEX_INPUT flag.
+ *
+ * Conditional execution (see NV_vertex_program{2,3} for details)
+ * There is a second condition code register on NV40, it's use is enabled
+ * by setting the COND_REG_SELECT_1 flag.
+ *
+ * Texture lookup
+ * TODO
+ */
+
+/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */
+#define NV40_VP_INST_VEC_RESULT (1 << 30)
+/* uncertain.. */
+#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29)
+/* use address reg as index into attribs */
+#define NV40_VP_INST_INDEX_INPUT (1 << 27)
+#define NV40_VP_INST_SATURATE (1 << 26)
+#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25)
+#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24)
+#define NV40_VP_INST_SRC2_ABS (1 << 23)
+#define NV40_VP_INST_SRC1_ABS (1 << 22)
+#define NV40_VP_INST_SRC0_ABS (1 << 21)
+#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15
+#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x3F << 15)
+#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13)
+#define NV40_VP_INST_COND_SHIFT 10
+#define NV40_VP_INST_COND_MASK (0x7 << 10)
+#define NV40_VP_INST_COND_SWZ_X_SHIFT 8
+#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8)
+#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6
+#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6)
+#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4
+#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4)
+#define NV40_VP_INST_COND_SWZ_W_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2)
+#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2
+#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2)
+#define NV40_VP_INST_ADDR_SWZ_SHIFT 0
+#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0)
+#define NV40_VP_INST0_KNOWN ( \
+ NV40_VP_INST_INDEX_INPUT | \
+ NV40_VP_INST_COND_REG_SELECT_1 | \
+ NV40_VP_INST_ADDR_REG_SELECT_1 | \
+ NV40_VP_INST_SRC2_ABS | \
+ NV40_VP_INST_SRC1_ABS | \
+ NV40_VP_INST_SRC0_ABS | \
+ NV40_VP_INST_VEC_DEST_TEMP_MASK | \
+ NV40_VP_INST_COND_TEST_ENABLE | \
+ NV40_VP_INST_COND_MASK | \
+ NV40_VP_INST_COND_SWZ_ALL_MASK | \
+ NV40_VP_INST_ADDR_SWZ_MASK)
+
+/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */
+#define NV40_VP_INST_VEC_OPCODE_SHIFT 22
+#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22)
+#define NV40_VP_INST_SCA_OPCODE_SHIFT 27
+#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27)
+#define NV40_VP_INST_CONST_SRC_SHIFT 12
+#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12)
+#define NV40_VP_INST_INPUT_SRC_SHIFT 8
+#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8)
+#define NV40_VP_INST_SRC0H_SHIFT 0
+#define NV40_VP_INST_SRC0H_MASK (0xFF << 0)
+#define NV40_VP_INST1_KNOWN ( \
+ NV40_VP_INST_VEC_OPCODE_MASK | \
+ NV40_VP_INST_SCA_OPCODE_MASK | \
+ NV40_VP_INST_CONST_SRC_MASK | \
+ NV40_VP_INST_INPUT_SRC_MASK | \
+ NV40_VP_INST_SRC0H_MASK \
+ )
+
+/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */
+#define NV40_VP_INST_SRC0L_SHIFT 23
+#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23)
+#define NV40_VP_INST_SRC1_SHIFT 6
+#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6)
+#define NV40_VP_INST_SRC2H_SHIFT 0
+#define NV40_VP_INST_SRC2H_MASK (0x3F << 0)
+#define NV40_VP_INST_IADDRH_SHIFT 0
+#define NV40_VP_INST_IADDRH_MASK (0x3F << 0)
+
+/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */
+#define NV40_VP_INST_IADDRL_SHIFT 29
+#define NV40_VP_INST_IADDRL_MASK (7 << 29)
+#define NV40_VP_INST_SRC2L_SHIFT 21
+#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21)
+#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17
+#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17)
+# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20)
+# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19)
+# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18)
+# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17)
+#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13
+#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13)
+# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16)
+# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15)
+# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14)
+# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13)
+#define NV40_VP_INST_SCA_RESULT (1 << 12)
+#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7
+#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7)
+#define NV40_VP_INST_DEST_SHIFT 2
+#define NV40_VP_INST_DEST_MASK (31 << 2)
+# define NV40_VP_INST_DEST_POS 0
+# define NV40_VP_INST_DEST_COL0 1
+# define NV40_VP_INST_DEST_COL1 2
+# define NV40_VP_INST_DEST_BFC0 3
+# define NV40_VP_INST_DEST_BFC1 4
+# define NV40_VP_INST_DEST_FOGC 5
+# define NV40_VP_INST_DEST_PSZ 6
+# define NV40_VP_INST_DEST_TC0 7
+# define NV40_VP_INST_DEST_TC(n) (7+n)
+# define NV40_VP_INST_DEST_TEMP 0x1F
+#define NV40_VP_INST_INDEX_CONST (1 << 1)
+#define NV40_VP_INST3_KNOWN ( \
+ NV40_VP_INST_SRC2L_MASK |\
+ NV40_VP_INST_SCA_WRITEMASK_MASK |\
+ NV40_VP_INST_VEC_WRITEMASK_MASK |\
+ NV40_VP_INST_SCA_DEST_TEMP_MASK |\
+ NV40_VP_INST_DEST_MASK |\
+ NV40_VP_INST_INDEX_CONST)
+
+/* Useful to split the source selection regs into their pieces */
+#define NV40_VP_SRC0_HIGH_SHIFT 9
+#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00
+#define NV40_VP_SRC0_LOW_MASK 0x000001FF
+#define NV40_VP_SRC2_HIGH_SHIFT 11
+#define NV40_VP_SRC2_HIGH_MASK 0x0001F800
+#define NV40_VP_SRC2_LOW_MASK 0x000007FF
+
+/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */
+#define NV40_VP_SRC_NEGATE (1 << 16)
+#define NV40_VP_SRC_SWZ_X_SHIFT 14
+#define NV40_VP_SRC_SWZ_X_MASK (3 << 14)
+#define NV40_VP_SRC_SWZ_Y_SHIFT 12
+#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12)
+#define NV40_VP_SRC_SWZ_Z_SHIFT 10
+#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10)
+#define NV40_VP_SRC_SWZ_W_SHIFT 8
+#define NV40_VP_SRC_SWZ_W_MASK (3 << 8)
+#define NV40_VP_SRC_SWZ_ALL_SHIFT 8
+#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8)
+#define NV40_VP_SRC_TEMP_SRC_SHIFT 2
+#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2)
+#define NV40_VP_SRC_REG_TYPE_SHIFT 0
+#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0)
+# define NV40_VP_SRC_REG_TYPE_UNK0 0
+# define NV40_VP_SRC_REG_TYPE_TEMP 1
+# define NV40_VP_SRC_REG_TYPE_INPUT 2
+# define NV40_VP_SRC_REG_TYPE_CONST 3
+
+#include "nv30/nvfx_shader.h"
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv40_verttex.c b/src/gallium/drivers/nouveau/nv30/nv40_verttex.c
new file mode 100644
index 00000000000..9a7163c448f
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nv40_verttex.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice 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: Ben Skeggs
+ *
+ */
+
+#include "util/u_inlines.h"
+#include "nv30/nv30_context.h"
+
+void
+nv40_verttex_validate(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned dirty = nv30->vertprog.dirty_samplers;
+
+ while (dirty) {
+ unsigned unit = ffs(dirty) - 1;
+ struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
+ struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];
+
+ if (ss && sv) {
+ } else {
+ BEGIN_NV04(push, NV40_3D(VTXTEX_ENABLE(unit)), 1);
+ PUSH_DATA (push, 0);
+ }
+ }
+
+ nv30->vertprog.dirty_samplers = 0;
+}
+
+static void
+nv40_verttex_sampler_states_bind(struct pipe_context *pipe,
+ unsigned nr, void **hwcso)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ nv30->vertprog.samplers[i] = hwcso[i];
+ nv30->vertprog.dirty_samplers |= (1 << i);
+ }
+
+ for (; i < nv30->vertprog.num_samplers; i++) {
+ nv30->vertprog.samplers[i] = NULL;
+ nv30->vertprog.dirty_samplers |= (1 << i);
+ }
+
+ nv30->vertprog.num_samplers = nr;
+ nv30->dirty |= NV30_NEW_VERTTEX;
+}
+
+
+static void
+nv40_verttex_set_sampler_views(struct pipe_context *pipe, unsigned nr,
+ struct pipe_sampler_view **views)
+{
+ struct nv30_context *nv30 = nv30_context(pipe);
+ unsigned i;
+
+ for (i = 0; i < nr; i++) {
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
+ pipe_sampler_view_reference(&nv30->vertprog.textures[i], views[i]);
+ nv30->vertprog.dirty_samplers |= (1 << i);
+ }
+
+ for (; i < nv30->vertprog.num_textures; i++) {
+ nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VERTTEX(i));
+ pipe_sampler_view_reference(&nv30->vertprog.textures[i], NULL);
+ nv30->vertprog.dirty_samplers |= (1 << i);
+ }
+
+ nv30->vertprog.num_textures = nr;
+ nv30->dirty |= NV30_NEW_VERTTEX;
+}
+
+void
+nv40_verttex_init(struct pipe_context *pipe)
+{
+ pipe->bind_vertex_sampler_states = nv40_verttex_sampler_states_bind;
+ pipe->set_vertex_sampler_views = nv40_verttex_set_sampler_views;
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nvfx_fragprog.c b/src/gallium/drivers/nouveau/nv30/nvfx_fragprog.c
new file mode 100644
index 00000000000..4751ec80de5
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nvfx_fragprog.c
@@ -0,0 +1,1251 @@
+#include <float.h>
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_linkage.h"
+#include "util/u_inlines.h"
+#include "util/u_debug.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_ureg.h"
+
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nvfx_shader.h"
+
+struct nvfx_fpc {
+ struct nv30_fragprog *fp;
+
+ unsigned max_temps;
+ unsigned long long r_temps;
+ unsigned long long r_temps_discard;
+ struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
+ struct nvfx_reg r_input[PIPE_MAX_SHADER_INPUTS];
+ struct nvfx_reg *r_temp;
+
+ int num_regs;
+
+ unsigned inst_offset;
+ unsigned have_const;
+
+ struct util_dynarray imm_data;
+
+ struct nvfx_reg* r_imm;
+ unsigned nr_imm;
+
+ struct util_dynarray if_stack;
+ //struct util_dynarray loop_stack;
+ struct util_dynarray label_relocs;
+};
+
+static INLINE struct nvfx_reg
+temp(struct nvfx_fpc *fpc)
+{
+ int idx = __builtin_ctzll(~fpc->r_temps);
+
+ if (idx >= fpc->max_temps) {
+ NOUVEAU_ERR("out of temps!!\n");
+ assert(0);
+ return nvfx_reg(NVFXSR_TEMP, 0);
+ }
+
+ fpc->r_temps |= (1ULL << idx);
+ fpc->r_temps_discard |= (1ULL << idx);
+ return nvfx_reg(NVFXSR_TEMP, idx);
+}
+
+static INLINE void
+release_temps(struct nvfx_fpc *fpc)
+{
+ fpc->r_temps &= ~fpc->r_temps_discard;
+ fpc->r_temps_discard = 0ULL;
+}
+
+static inline struct nvfx_reg
+nvfx_fp_imm(struct nvfx_fpc *fpc, float a, float b, float c, float d)
+{
+ float v[4] = {a, b, c, d};
+ int idx = fpc->imm_data.size >> 4;
+
+ memcpy(util_dynarray_grow(&fpc->imm_data, sizeof(float) * 4), v, 4 * sizeof(float));
+ return nvfx_reg(NVFXSR_IMM, idx);
+}
+
+static void
+grow_insns(struct nvfx_fpc *fpc, int size)
+{
+ struct nv30_fragprog *fp = fpc->fp;
+
+ fp->insn_len += size;
+ fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
+}
+
+static void
+emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_src src)
+{
+ struct nv30_fragprog *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+ uint32_t sr = 0;
+
+ switch (src.reg.type) {
+ case NVFXSR_INPUT:
+ sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT);
+ hw[0] |= (src.reg.index << NVFX_FP_OP_INPUT_SRC_SHIFT);
+ break;
+ case NVFXSR_OUTPUT:
+ sr |= NVFX_FP_REG_SRC_HALF;
+ /* fall-through */
+ case NVFXSR_TEMP:
+ sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT);
+ sr |= (src.reg.index << NVFX_FP_REG_SRC_SHIFT);
+ break;
+ case NVFXSR_IMM:
+ if (!fpc->have_const) {
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ fpc->have_const = 1;
+ }
+
+ memcpy(&fp->insn[fpc->inst_offset + 4],
+ (float*)fpc->imm_data.data + src.reg.index * 4,
+ sizeof(uint32_t) * 4);
+
+ sr |= (NVFX_FP_REG_TYPE_CONST << NVFX_FP_REG_TYPE_SHIFT);
+ break;
+ case NVFXSR_CONST:
+ if (!fpc->have_const) {
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ fpc->have_const = 1;
+ }
+
+ {
+ struct nv30_fragprog_data *fpd;
+
+ fp->consts = realloc(fp->consts, ++fp->nr_consts *
+ sizeof(*fpd));
+ fpd = &fp->consts[fp->nr_consts - 1];
+ fpd->offset = fpc->inst_offset + 4;
+ fpd->index = src.reg.index;
+ memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
+ }
+
+ sr |= (NVFX_FP_REG_TYPE_CONST << NVFX_FP_REG_TYPE_SHIFT);
+ break;
+ case NVFXSR_NONE:
+ sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NVFX_FP_REG_NEGATE;
+
+ if (src.abs)
+ hw[1] |= (1 << (29 + pos));
+
+ sr |= ((src.swz[0] << NVFX_FP_REG_SWZ_X_SHIFT) |
+ (src.swz[1] << NVFX_FP_REG_SWZ_Y_SHIFT) |
+ (src.swz[2] << NVFX_FP_REG_SWZ_Z_SHIFT) |
+ (src.swz[3] << NVFX_FP_REG_SWZ_W_SHIFT));
+
+ hw[pos + 1] |= sr;
+}
+
+static void
+emit_dst(struct nvfx_fpc *fpc, struct nvfx_reg dst)
+{
+ struct nv30_fragprog *fp = fpc->fp;
+ uint32_t *hw = &fp->insn[fpc->inst_offset];
+
+ switch (dst.type) {
+ case NVFXSR_OUTPUT:
+ if (dst.index == 1)
+ fp->fp_control |= 0x0000000e;
+ else {
+ hw[0] |= NVFX_FP_OP_OUT_REG_HALF;
+ dst.index <<= 1;
+ }
+ /* fall-through */
+ case NVFXSR_TEMP:
+ if (fpc->num_regs < (dst.index + 1))
+ fpc->num_regs = dst.index + 1;
+ break;
+ case NVFXSR_NONE:
+ hw[0] |= (1 << 30);
+ break;
+ default:
+ assert(0);
+ }
+
+ hw[0] |= (dst.index << NVFX_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+nvfx_fp_emit(struct nvfx_fpc *fpc, struct nvfx_insn insn)
+{
+ struct nv30_fragprog *fp = fpc->fp;
+ uint32_t *hw;
+
+ fpc->inst_offset = fp->insn_len;
+ fpc->have_const = 0;
+ grow_insns(fpc, 4);
+ hw = &fp->insn[fpc->inst_offset];
+ memset(hw, 0, sizeof(uint32_t) * 4);
+
+ if (insn.op == NVFX_FP_OP_OPCODE_KIL)
+ fp->fp_control |= NV30_3D_FP_CONTROL_USES_KIL;
+ hw[0] |= (insn.op << NVFX_FP_OP_OPCODE_SHIFT);
+ hw[0] |= (insn.mask << NVFX_FP_OP_OUTMASK_SHIFT);
+ hw[2] |= (insn.scale << NVFX_FP_OP_DST_SCALE_SHIFT);
+
+ if (insn.sat)
+ hw[0] |= NVFX_FP_OP_OUT_SAT;
+
+ if (insn.cc_update)
+ hw[0] |= NVFX_FP_OP_COND_WRITE_ENABLE;
+ hw[1] |= (insn.cc_test << NVFX_FP_OP_COND_SHIFT);
+ hw[1] |= ((insn.cc_swz[0] << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+ (insn.cc_swz[1] << NVFX_FP_OP_COND_SWZ_Y_SHIFT) |
+ (insn.cc_swz[2] << NVFX_FP_OP_COND_SWZ_Z_SHIFT) |
+ (insn.cc_swz[3] << NVFX_FP_OP_COND_SWZ_W_SHIFT));
+
+ if(insn.unit >= 0)
+ {
+ hw[0] |= (insn.unit << NVFX_FP_OP_TEX_UNIT_SHIFT);
+ }
+
+ emit_dst(fpc, insn.dst);
+ emit_src(fpc, 0, insn.src[0]);
+ emit_src(fpc, 1, insn.src[1]);
+ emit_src(fpc, 2, insn.src[2]);
+}
+
+#define arith(s,o,d,m,s0,s1,s2) \
+ nvfx_insn((s), NVFX_FP_OP_OPCODE_##o, -1, \
+ (d), (m), (s0), (s1), (s2))
+
+#define tex(s,o,u,d,m,s0,s1,s2) \
+ nvfx_insn((s), NVFX_FP_OP_OPCODE_##o, (u), \
+ (d), (m), (s0), none, none)
+
+/* IF src.x != 0, as TGSI specifies */
+static void
+nv40_fp_if(struct nvfx_fpc *fpc, struct nvfx_src src)
+{
+ const struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+ struct nvfx_insn insn = arith(0, MOV, none.reg, NVFX_FP_MASK_X, src, none, none);
+ uint32_t *hw;
+ insn.cc_update = 1;
+ nvfx_fp_emit(fpc, insn);
+
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_IF << NVFX_FP_OP_OPCODE_SHIFT) |
+ NV40_FP_OP_OUT_NONE |
+ (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (0 << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+ (0 << NVFX_FP_OP_COND_SWZ_Y_SHIFT) |
+ (0 << NVFX_FP_OP_COND_SWZ_Z_SHIFT) |
+ (0 << NVFX_FP_OP_COND_SWZ_W_SHIFT) |
+ (NVFX_FP_OP_COND_NE << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = 0; /* | NV40_FP_OP_OPCODE_IS_BRANCH | else_offset */
+ hw[3] = 0; /* | endif_offset */
+ util_dynarray_append(&fpc->if_stack, unsigned, fpc->inst_offset);
+}
+
+/* IF src.x != 0, as TGSI specifies */
+static void
+nv40_fp_cal(struct nvfx_fpc *fpc, unsigned target)
+{
+ struct nvfx_relocation reloc;
+ uint32_t *hw;
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_CAL << NVFX_FP_OP_OPCODE_SHIFT);
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+ (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | call_offset */
+ hw[3] = 0;
+ reloc.target = target;
+ reloc.location = fpc->inst_offset + 2;
+ util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+}
+
+static void
+nv40_fp_ret(struct nvfx_fpc *fpc)
+{
+ uint32_t *hw;
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_RET << NVFX_FP_OP_OPCODE_SHIFT);
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+ (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | call_offset */
+ hw[3] = 0;
+}
+
+static void
+nv40_fp_rep(struct nvfx_fpc *fpc, unsigned count, unsigned target)
+{
+ struct nvfx_relocation reloc;
+ uint32_t *hw;
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_REP << NVFX_FP_OP_OPCODE_SHIFT) |
+ NV40_FP_OP_OUT_NONE |
+ (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_ALL_SHIFT) |
+ (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH |
+ (count << NV40_FP_OP_REP_COUNT1_SHIFT) |
+ (count << NV40_FP_OP_REP_COUNT2_SHIFT) |
+ (count << NV40_FP_OP_REP_COUNT3_SHIFT);
+ hw[3] = 0; /* | end_offset */
+ reloc.target = target;
+ reloc.location = fpc->inst_offset + 3;
+ util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+ //util_dynarray_append(&fpc->loop_stack, unsigned, target);
+}
+
+/* warning: this only works forward, and probably only if not inside any IF */
+static void
+nv40_fp_bra(struct nvfx_fpc *fpc, unsigned target)
+{
+ struct nvfx_relocation reloc;
+ uint32_t *hw;
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_IF << NVFX_FP_OP_OPCODE_SHIFT) |
+ NV40_FP_OP_OUT_NONE |
+ (NVFX_FP_PRECISION_FP16 << NVFX_FP_OP_PRECISION_SHIFT);
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+ (NVFX_FP_OP_COND_FL << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH; /* | else_offset */
+ hw[3] = 0; /* | endif_offset */
+ reloc.target = target;
+ reloc.location = fpc->inst_offset + 2;
+ util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+ reloc.target = target;
+ reloc.location = fpc->inst_offset + 3;
+ util_dynarray_append(&fpc->label_relocs, struct nvfx_relocation, reloc);
+}
+
+static void
+nv40_fp_brk(struct nvfx_fpc *fpc)
+{
+ uint32_t *hw;
+ fpc->inst_offset = fpc->fp->insn_len;
+ grow_insns(fpc, 4);
+ hw = &fpc->fp->insn[fpc->inst_offset];
+ /* I really wonder why fp16 precision is used. Presumably the hardware ignores it? */
+ hw[0] = (NV40_FP_OP_BRA_OPCODE_BRK << NVFX_FP_OP_OPCODE_SHIFT) |
+ NV40_FP_OP_OUT_NONE;
+ /* Use .xxxx swizzle so that we check only src[0].x*/
+ hw[1] = (NVFX_SWZ_IDENTITY << NVFX_FP_OP_COND_SWZ_X_SHIFT) |
+ (NVFX_FP_OP_COND_TR << NVFX_FP_OP_COND_SHIFT);
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH;
+ hw[3] = 0;
+}
+
+static INLINE struct nvfx_src
+tgsi_src(struct nvfx_fpc *fpc, const struct tgsi_full_src_register *fsrc)
+{
+ struct nvfx_src src;
+
+ switch (fsrc->Register.File) {
+ case TGSI_FILE_INPUT:
+ src.reg = fpc->r_input[fsrc->Register.Index];
+ break;
+ case TGSI_FILE_CONSTANT:
+ src.reg = nvfx_reg(NVFXSR_CONST, fsrc->Register.Index);
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ assert(fsrc->Register.Index < fpc->nr_imm);
+ src.reg = fpc->r_imm[fsrc->Register.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ src.reg = fpc->r_temp[fsrc->Register.Index];
+ break;
+ /* NV40 fragprog result regs are just temps, so this is simple */
+ case TGSI_FILE_OUTPUT:
+ src.reg = fpc->r_result[fsrc->Register.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ src.reg.index = 0;
+ src.reg.type = 0;
+ break;
+ }
+
+ src.abs = fsrc->Register.Absolute;
+ src.negate = fsrc->Register.Negate;
+ src.swz[0] = fsrc->Register.SwizzleX;
+ src.swz[1] = fsrc->Register.SwizzleY;
+ src.swz[2] = fsrc->Register.SwizzleZ;
+ src.swz[3] = fsrc->Register.SwizzleW;
+ src.indirect = 0;
+ src.indirect_reg = 0;
+ src.indirect_swz = 0;
+ return src;
+}
+
+static INLINE struct nvfx_reg
+tgsi_dst(struct nvfx_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
+ switch (fdst->Register.File) {
+ case TGSI_FILE_OUTPUT:
+ return fpc->r_result[fdst->Register.Index];
+ case TGSI_FILE_TEMPORARY:
+ return fpc->r_temp[fdst->Register.Index];
+ case TGSI_FILE_NULL:
+ return nvfx_reg(NVFXSR_NONE, 0);
+ default:
+ NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File);
+ return nvfx_reg(NVFXSR_NONE, 0);
+ }
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_FP_MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_FP_MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_FP_MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_FP_MASK_W;
+ return mask;
+}
+
+static boolean
+nvfx_fragprog_parse_instruction(struct nv30_context* nvfx, struct nvfx_fpc *fpc,
+ const struct tgsi_full_instruction *finst)
+{
+ const struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+ struct nvfx_insn insn;
+ struct nvfx_src src[3], tmp;
+ struct nvfx_reg dst;
+ int mask, sat, unit = 0;
+ int ai = -1, ci = -1, ii = -1;
+ int i;
+
+ if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->Src[i];
+ if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(fpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->Src[i];
+
+ switch (fsrc->Register.File) {
+ case TGSI_FILE_INPUT:
+ if(fpc->fp->info.input_semantic_name[fsrc->Register.Index] == TGSI_SEMANTIC_FOG && (0
+ || fsrc->Register.SwizzleX == PIPE_SWIZZLE_ALPHA
+ || fsrc->Register.SwizzleY == PIPE_SWIZZLE_ALPHA
+ || fsrc->Register.SwizzleZ == PIPE_SWIZZLE_ALPHA
+ || fsrc->Register.SwizzleW == PIPE_SWIZZLE_ALPHA
+ )) {
+ /* hardware puts 0 in fogcoord.w, but GL/Gallium want 1 there */
+ struct nvfx_src addend = nvfx_src(nvfx_fp_imm(fpc, 0, 0, 0, 1));
+ addend.swz[0] = fsrc->Register.SwizzleX;
+ addend.swz[1] = fsrc->Register.SwizzleY;
+ addend.swz[2] = fsrc->Register.SwizzleZ;
+ addend.swz[3] = fsrc->Register.SwizzleW;
+ src[i] = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, ADD, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), addend, none));
+ } else if (ai == -1 || ai == fsrc->Register.Index) {
+ ai = fsrc->Register.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if ((ci == -1 && ii == -1) ||
+ ci == fsrc->Register.Index) {
+ ci = fsrc->Register.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ if ((ci == -1 && ii == -1) ||
+ ii == fsrc->Register.Index) {
+ ii = fsrc->Register.Index;
+ src[i] = tgsi_src(fpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MOV, src[i].reg, NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ case TGSI_FILE_SAMPLER:
+ unit = fsrc->Register.Index;
+ break;
+ case TGSI_FILE_OUTPUT:
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ dst = tgsi_dst(fpc, &finst->Dst[0]);
+ mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
+ sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, abs(src[0]), none, none));
+ break;
+ case TGSI_OPCODE_ADD:
+ nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_CEIL:
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, FLR, tmp.reg, mask, neg(src[0]), none, none));
+ nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, neg(tmp), none, none));
+ break;
+ case TGSI_OPCODE_CMP:
+ insn = arith(0, MOV, none.reg, mask, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_fp_emit(fpc, insn);
+
+ insn = arith(sat, MOV, dst, mask, src[2], none, none);
+ insn.cc_test = NVFX_COND_GE;
+ nvfx_fp_emit(fpc, insn);
+
+ insn = arith(sat, MOV, dst, mask, src[1], none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_fp_emit(fpc, insn);
+ break;
+ case TGSI_OPCODE_COS:
+ nvfx_fp_emit(fpc, arith(sat, COS, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_DDX:
+ if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) {
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(sat, DDX, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none));
+ nvfx_fp_emit(fpc, arith(0, MOV, tmp.reg, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none));
+ nvfx_fp_emit(fpc, arith(sat, DDX, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none));
+ nvfx_fp_emit(fpc, arith(0, MOV, dst, mask, tmp, none, none));
+ } else {
+ nvfx_fp_emit(fpc, arith(sat, DDX, dst, mask, src[0], none, none));
+ }
+ break;
+ case TGSI_OPCODE_DDY:
+ if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) {
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(sat, DDY, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none));
+ nvfx_fp_emit(fpc, arith(0, MOV, tmp.reg, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none));
+ nvfx_fp_emit(fpc, arith(sat, DDY, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none));
+ nvfx_fp_emit(fpc, arith(0, MOV, dst, mask, tmp, none, none));
+ } else {
+ nvfx_fp_emit(fpc, arith(sat, DDY, dst, mask, src[0], none, none));
+ }
+ break;
+ case TGSI_OPCODE_DP2:
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], src[1], none));
+ nvfx_fp_emit(fpc, arith(0, ADD, dst, mask, swz(tmp, X, X, X, X), swz(tmp, Y, Y, Y, Y), none));
+ break;
+ case TGSI_OPCODE_DP3:
+ nvfx_fp_emit(fpc, arith(sat, DP3, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_DP4:
+ nvfx_fp_emit(fpc, arith(sat, DP4, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_DPH:
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_X, src[0], src[1], none));
+ nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, swz(tmp, X, X, X, X), swz(src[1], W, W, W, W), none));
+ break;
+ case TGSI_OPCODE_DST:
+ nvfx_fp_emit(fpc, arith(sat, DST, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_EX2:
+ nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_FLR:
+ nvfx_fp_emit(fpc, arith(sat, FLR, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_FRC:
+ nvfx_fp_emit(fpc, arith(sat, FRC, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_KILL:
+ nvfx_fp_emit(fpc, arith(0, KIL, none.reg, 0, none, none, none));
+ break;
+ case TGSI_OPCODE_KILL_IF:
+ insn = arith(0, MOV, none.reg, NVFX_FP_MASK_ALL, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_fp_emit(fpc, insn);
+
+ insn = arith(0, KIL, none.reg, 0, none, none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_fp_emit(fpc, insn);
+ break;
+ case TGSI_OPCODE_LG2:
+ nvfx_fp_emit(fpc, arith(sat, LG2, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_LIT:
+ if(!nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, arith(sat, LIT_NV30, dst, mask, src[0], none, none));
+ else {
+ /* we use FLT_MIN, so that log2 never gives -infinity, and thus multiplication by
+ * specular 0 always gives 0, so that ex2 gives 1, to satisfy the 0^0 = 1 requirement
+ *
+ * NOTE: if we start using half precision, we might need an fp16 FLT_MIN here instead
+ */
+ struct nvfx_src maxs = nvfx_src(nvfx_fp_imm(fpc, 0, FLT_MIN, 0, 0));
+ tmp = nvfx_src(temp(fpc));
+ if (ci>= 0 || ii >= 0) {
+ nvfx_fp_emit(fpc, arith(0, MOV, tmp.reg, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, maxs, none, none));
+ maxs = tmp;
+ }
+ nvfx_fp_emit(fpc, arith(0, MAX, tmp.reg, NVFX_FP_MASK_Y | NVFX_FP_MASK_W, swz(src[0], X, X, X, Y), swz(maxs, X, X, Y, Y), none));
+ nvfx_fp_emit(fpc, arith(0, LG2, tmp.reg, NVFX_FP_MASK_W, swz(tmp, W, W, W, W), none, none));
+ nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, NVFX_FP_MASK_W, swz(tmp, W, W, W, W), swz(src[0], W, W, W, W), none));
+ nvfx_fp_emit(fpc, arith(sat, LITEX2_NV40, dst, mask, swz(tmp, Y, Y, W, W), none, none));
+ }
+ break;
+ case TGSI_OPCODE_LRP:
+ if(!nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, arith(sat, LRP_NV30, dst, mask, src[0], src[1], src[2]));
+ else {
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MAD, tmp.reg, mask, neg(src[0]), src[2], src[2]));
+ nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, src[0], src[1], tmp));
+ }
+ break;
+ case TGSI_OPCODE_MAD:
+ nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, src[0], src[1], src[2]));
+ break;
+ case TGSI_OPCODE_MAX:
+ nvfx_fp_emit(fpc, arith(sat, MAX, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_MIN:
+ nvfx_fp_emit(fpc, arith(sat, MIN, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_MOV:
+ nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_MUL:
+ nvfx_fp_emit(fpc, arith(sat, MUL, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_NOP:
+ break;
+ case TGSI_OPCODE_POW:
+ if(!nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, arith(sat, POW_NV30, dst, mask, src[0], src[1], none));
+ else {
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, LG2, tmp.reg, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
+ nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, NVFX_FP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none));
+ nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, swz(tmp, X, X, X, X), none, none));
+ }
+ break;
+ case TGSI_OPCODE_RCP:
+ nvfx_fp_emit(fpc, arith(sat, RCP, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_RFL:
+ if(!nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, arith(0, RFL_NV30, dst, mask, src[0], src[1], none));
+ else {
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_X, src[0], src[0], none));
+ nvfx_fp_emit(fpc, arith(0, DP3, tmp.reg, NVFX_FP_MASK_Y, src[0], src[1], none));
+ insn = arith(0, DIV, tmp.reg, NVFX_FP_MASK_Z, swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
+ insn.scale = NVFX_FP_OP_DST_SCALE_2X;
+ nvfx_fp_emit(fpc, insn);
+ nvfx_fp_emit(fpc, arith(sat, MAD, dst, mask, swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])));
+ }
+ break;
+ case TGSI_OPCODE_RSQ:
+ if(!nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, arith(sat, RSQ_NV30, dst, mask, abs(swz(src[0], X, X, X, X)), none, none));
+ else {
+ tmp = nvfx_src(temp(fpc));
+ insn = arith(0, LG2, tmp.reg, NVFX_FP_MASK_X, abs(swz(src[0], X, X, X, X)), none, none);
+ insn.scale = NVFX_FP_OP_DST_SCALE_INV_2X;
+ nvfx_fp_emit(fpc, insn);
+ nvfx_fp_emit(fpc, arith(sat, EX2, dst, mask, neg(swz(tmp, X, X, X, X)), none, none));
+ }
+ break;
+ case TGSI_OPCODE_SCS:
+ /* avoid overwriting the source */
+ if(src[0].swz[NVFX_SWZ_X] != NVFX_SWZ_X)
+ {
+ if (mask & NVFX_FP_MASK_X)
+ nvfx_fp_emit(fpc, arith(sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
+ if (mask & NVFX_FP_MASK_Y)
+ nvfx_fp_emit(fpc, arith(sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none));
+ }
+ else
+ {
+ if (mask & NVFX_FP_MASK_Y)
+ nvfx_fp_emit(fpc, arith(sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none));
+ if (mask & NVFX_FP_MASK_X)
+ nvfx_fp_emit(fpc, arith(sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none));
+ }
+ break;
+ case TGSI_OPCODE_SEQ:
+ nvfx_fp_emit(fpc, arith(sat, SEQ, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SFL:
+ nvfx_fp_emit(fpc, arith(sat, SFL, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SGE:
+ nvfx_fp_emit(fpc, arith(sat, SGE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SGT:
+ nvfx_fp_emit(fpc, arith(sat, SGT, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SIN:
+ nvfx_fp_emit(fpc, arith(sat, SIN, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_SLE:
+ nvfx_fp_emit(fpc, arith(sat, SLE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SLT:
+ nvfx_fp_emit(fpc, arith(sat, SLT, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SNE:
+ nvfx_fp_emit(fpc, arith(sat, SNE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SSG:
+ {
+ struct nvfx_src minones = swz(nvfx_src(nvfx_fp_imm(fpc, -1, -1, -1, -1)), X, X, X, X);
+
+ insn = arith(sat, MOV, dst, mask, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_fp_emit(fpc, insn);
+
+ insn = arith(0, STR, dst, mask, none, none, none);
+ insn.cc_test = NVFX_COND_GT;
+ nvfx_fp_emit(fpc, insn);
+
+ if(!sat) {
+ insn = arith(0, MOV, dst, mask, minones, none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_fp_emit(fpc, insn);
+ }
+ break;
+ }
+ case TGSI_OPCODE_STR:
+ nvfx_fp_emit(fpc, arith(sat, STR, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SUB:
+ nvfx_fp_emit(fpc, arith(sat, ADD, dst, mask, src[0], neg(src[1]), none));
+ break;
+ case TGSI_OPCODE_TEX:
+ nvfx_fp_emit(fpc, tex(sat, TEX, unit, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_TRUNC:
+ tmp = nvfx_src(temp(fpc));
+ insn = arith(0, MOV, none.reg, mask, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_fp_emit(fpc, insn);
+
+ nvfx_fp_emit(fpc, arith(0, FLR, tmp.reg, mask, abs(src[0]), none, none));
+ nvfx_fp_emit(fpc, arith(sat, MOV, dst, mask, tmp, none, none));
+
+ insn = arith(sat, MOV, dst, mask, neg(tmp), none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_fp_emit(fpc, insn);
+ break;
+ case TGSI_OPCODE_TXB:
+ nvfx_fp_emit(fpc, tex(sat, TXB, unit, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_TXL:
+ if(nvfx->is_nv4x)
+ nvfx_fp_emit(fpc, tex(sat, TXL_NV40, unit, dst, mask, src[0], none, none));
+ else /* unsupported on nv30, use TEX and hope they like it */
+ nvfx_fp_emit(fpc, tex(sat, TEX, unit, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_TXP:
+ nvfx_fp_emit(fpc, tex(sat, TXP, unit, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = nvfx_src(temp(fpc));
+ nvfx_fp_emit(fpc, arith(0, MUL, tmp.reg, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none));
+ nvfx_fp_emit(fpc, arith(sat, MAD, dst, (mask & ~NVFX_FP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)));
+ break;
+
+ case TGSI_OPCODE_IF:
+ // MOVRC0 R31 (TR0.xyzw), R<src>:
+ // IF (NE.xxxx) ELSE <else> END <end>
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ nv40_fp_if(fpc, src[0]);
+ break;
+
+ case TGSI_OPCODE_ELSE:
+ {
+ uint32_t *hw;
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ assert(util_dynarray_contains(&fpc->if_stack, unsigned));
+ hw = &fpc->fp->insn[util_dynarray_top(&fpc->if_stack, unsigned)];
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH | fpc->fp->insn_len;
+ break;
+ }
+
+ case TGSI_OPCODE_ENDIF:
+ {
+ uint32_t *hw;
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ assert(util_dynarray_contains(&fpc->if_stack, unsigned));
+ hw = &fpc->fp->insn[util_dynarray_pop(&fpc->if_stack, unsigned)];
+ if(!hw[2])
+ hw[2] = NV40_FP_OP_OPCODE_IS_BRANCH | fpc->fp->insn_len;
+ hw[3] = fpc->fp->insn_len;
+ break;
+ }
+
+ case TGSI_OPCODE_BRA:
+ /* This can in limited cases be implemented with an IF with the else and endif labels pointing to the target */
+ /* no state tracker uses this, so don't implement this for now */
+ assert(0);
+ nv40_fp_bra(fpc, finst->Label.Label);
+ break;
+
+ case TGSI_OPCODE_BGNSUB:
+ case TGSI_OPCODE_ENDSUB:
+ /* nothing to do here */
+ break;
+
+ case TGSI_OPCODE_CAL:
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ nv40_fp_cal(fpc, finst->Label.Label);
+ break;
+
+ case TGSI_OPCODE_RET:
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ nv40_fp_ret(fpc);
+ break;
+
+ case TGSI_OPCODE_BGNLOOP:
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ /* TODO: we should support using two nested REPs to allow a > 255 iteration count */
+ nv40_fp_rep(fpc, 255, finst->Label.Label);
+ break;
+
+ case TGSI_OPCODE_ENDLOOP:
+ break;
+
+ case TGSI_OPCODE_BRK:
+ if(!nvfx->use_nv4x)
+ goto nv3x_cflow;
+ nv40_fp_brk(fpc);
+ break;
+
+ case TGSI_OPCODE_CONT:
+ {
+ static int warned = 0;
+ if(!warned) {
+ NOUVEAU_ERR("Sorry, the continue keyword is not implemented: ignoring it.\n");
+ warned = 1;
+ }
+ break;
+ }
+
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+out:
+ release_temps(fpc);
+ return TRUE;
+nv3x_cflow:
+ {
+ static int warned = 0;
+ if(!warned) {
+ NOUVEAU_ERR(
+ "Sorry, control flow instructions are not supported in hardware on nv3x: ignoring them\n"
+ "If rendering is incorrect, try to disable GLSL support in the application.\n");
+ warned = 1;
+ }
+ }
+ goto out;
+}
+
+static boolean
+nvfx_fragprog_parse_decl_input(struct nv30_context *nvfx, struct nvfx_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned idx = fdec->Range.First;
+ unsigned hw;
+
+ switch (fdec->Semantic.Name) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NVFX_FP_OP_INPUT_SRC_POSITION;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ hw = NVFX_FP_OP_INPUT_SRC_COL0 + fdec->Semantic.Index;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NVFX_FP_OP_INPUT_SRC_FOGC;
+ break;
+ case TGSI_SEMANTIC_FACE:
+ hw = NV40_FP_OP_INPUT_SRC_FACING;
+ break;
+ case TGSI_SEMANTIC_TEXCOORD:
+ assert(fdec->Semantic.Index < 8);
+ fpc->fp->texcoord[fdec->Semantic.Index] = fdec->Semantic.Index;
+ fpc->fp->texcoords |= (1 << fdec->Semantic.Index);
+ fpc->fp->vp_or |= (0x00004000 << fdec->Semantic.Index);
+ hw = NVFX_FP_OP_INPUT_SRC_TC(fdec->Semantic.Index);
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_PCOORD:
+ /* will be assigned to remaining TC slots later */
+ return TRUE;
+ default:
+ assert(0);
+ return FALSE;
+ }
+
+ fpc->r_input[idx] = nvfx_reg(NVFXSR_INPUT, hw);
+ return TRUE;
+}
+
+static boolean
+nvfx_fragprog_assign_generic(struct nv30_context *nvfx, struct nvfx_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned num_texcoords = nvfx->use_nv4x ? 10 : 8;
+ unsigned idx = fdec->Range.First;
+ unsigned hw;
+
+ switch (fdec->Semantic.Name) {
+ case TGSI_SEMANTIC_GENERIC:
+ case TGSI_SEMANTIC_PCOORD:
+ for (hw = 0; hw < num_texcoords; hw++) {
+ if (fpc->fp->texcoord[hw] == 0xffff) {
+ if (hw <= 7) {
+ fpc->fp->texcoords |= (0x1 << hw);
+ fpc->fp->vp_or |= (0x00004000 << hw);
+ } else {
+ fpc->fp->vp_or |= (0x00001000 << (hw - 8));
+ }
+ if (fdec->Semantic.Name == TGSI_SEMANTIC_PCOORD) {
+ fpc->fp->texcoord[hw] = 0xfffe;
+ fpc->fp->point_sprite_control |= (0x00000100 << hw);
+ } else {
+ fpc->fp->texcoord[hw] = fdec->Semantic.Index + 8;
+ }
+ hw = NVFX_FP_OP_INPUT_SRC_TC(hw);
+ fpc->r_input[idx] = nvfx_reg(NVFXSR_INPUT, hw);
+ return TRUE;
+ }
+ }
+ return FALSE;
+ default:
+ return TRUE;
+ }
+}
+
+static boolean
+nvfx_fragprog_parse_decl_output(struct nv30_context* nvfx, struct nvfx_fpc *fpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned idx = fdec->Range.First;
+ unsigned hw;
+
+ switch (fdec->Semantic.Name) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = 1;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+ hw = ~0;
+ switch (fdec->Semantic.Index) {
+ case 0: hw = 0; break;
+ case 1: hw = 2; break;
+ case 2: hw = 3; break;
+ case 3: hw = 4; break;
+ }
+ if(hw > ((nvfx->use_nv4x) ? 4 : 2)) {
+ NOUVEAU_ERR("bad rcol index\n");
+ return FALSE;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ fpc->r_result[idx] = nvfx_reg(NVFXSR_OUTPUT, hw);
+ fpc->r_temps |= (1ULL << hw);
+ return TRUE;
+}
+
+static boolean
+nvfx_fragprog_prepare(struct nv30_context* nvfx, struct nvfx_fpc *fpc)
+{
+ struct tgsi_parse_context p;
+ int high_temp = -1, i;
+
+ fpc->r_imm = CALLOC(fpc->fp->info.immediate_count, sizeof(struct nvfx_reg));
+
+ tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ if (!nvfx_fragprog_parse_decl_input(nvfx, fpc, fdec))
+ goto out_err;
+ break;
+ case TGSI_FILE_OUTPUT:
+ if (!nvfx_fragprog_parse_decl_output(nvfx, fpc, fdec))
+ goto out_err;
+ break;
+ case TGSI_FILE_TEMPORARY:
+ if (fdec->Range.Last > high_temp) {
+ high_temp =
+ fdec->Range.Last;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ struct tgsi_full_immediate *imm;
+
+ imm = &p.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(fpc->nr_imm < fpc->fp->info.immediate_count);
+
+ fpc->r_imm[fpc->nr_imm++] = nvfx_fp_imm(fpc, imm->u[0].Float, imm->u[1].Float, imm->u[2].Float, imm->u[3].Float);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const struct tgsi_full_declaration *fdec;
+ tgsi_parse_token(&p);
+ switch(p.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_INPUT:
+ if (!nvfx_fragprog_assign_generic(nvfx, fpc, fdec))
+ goto out_err;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (++high_temp) {
+ fpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_reg));
+ for (i = 0; i < high_temp; i++)
+ fpc->r_temp[i] = temp(fpc);
+ fpc->r_temps_discard = 0ULL;
+ }
+
+ return TRUE;
+
+out_err:
+ FREE(fpc->r_temp);
+ fpc->r_temp = NULL;
+
+ tgsi_parse_free(&p);
+ return FALSE;
+}
+
+DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_fp, "NVFX_DUMP_FP", FALSE)
+
+void
+_nvfx_fragprog_translate(struct nv30_context *nvfx, struct nv30_fragprog *fp,
+ boolean emulate_sprite_flipping)
+{
+ struct tgsi_parse_context parse;
+ struct nvfx_fpc *fpc = NULL;
+ struct util_dynarray insns;
+
+ fp->translated = FALSE;
+ fp->point_sprite_control = 0;
+ fp->vp_or = 0;
+
+ fpc = CALLOC_STRUCT(nvfx_fpc);
+ if (!fpc)
+ goto out_err;
+
+ fpc->max_temps = nvfx->use_nv4x ? 48 : 32;
+ fpc->fp = fp;
+ fpc->num_regs = 2;
+ memset(fp->texcoord, 0xff, sizeof(fp->texcoord));
+
+ for (unsigned i = 0; i < fp->info.num_properties; ++i) {
+ switch (fp->info.properties[i].name) {
+ case TGSI_PROPERTY_FS_COORD_ORIGIN:
+ if (fp->info.properties[i].data[0])
+ fp->coord_conventions |= NV30_3D_COORD_CONVENTIONS_ORIGIN_INVERTED;
+ break;
+ case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
+ if (fp->info.properties[i].data[0])
+ fp->coord_conventions |= NV30_3D_COORD_CONVENTIONS_CENTER_INTEGER;
+ break;
+ case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
+ if (fp->info.properties[i].data[0])
+ fp->rt_enable |= NV30_3D_RT_ENABLE_MRT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!nvfx_fragprog_prepare(nvfx, fpc))
+ goto out_err;
+
+ tgsi_parse_init(&parse, fp->pipe.tokens);
+ util_dynarray_init(&insns);
+
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+
+ util_dynarray_append(&insns, unsigned, fp->insn_len);
+ finst = &parse.FullToken.FullInstruction;
+ if (!nvfx_fragprog_parse_instruction(nvfx, fpc, finst))
+ goto out_err;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ util_dynarray_append(&insns, unsigned, fp->insn_len);
+
+ for(unsigned i = 0; i < fpc->label_relocs.size; i += sizeof(struct nvfx_relocation))
+ {
+ struct nvfx_relocation* label_reloc = (struct nvfx_relocation*)((char*)fpc->label_relocs.data + i);
+ fp->insn[label_reloc->location] |= ((unsigned*)insns.data)[label_reloc->target];
+ }
+ util_dynarray_fini(&insns);
+
+ if(!nvfx->is_nv4x)
+ fp->fp_control |= (fpc->num_regs-1)/2;
+ else
+ fp->fp_control |= fpc->num_regs << NV40_3D_FP_CONTROL_TEMP_COUNT__SHIFT;
+
+ /* Terminate final instruction */
+ if(fp->insn)
+ fp->insn[fpc->inst_offset] |= 0x00000001;
+
+ /* Append NOP + END instruction for branches to the end of the program */
+ fpc->inst_offset = fp->insn_len;
+ grow_insns(fpc, 4);
+ fp->insn[fpc->inst_offset + 0] = 0x00000001;
+ fp->insn[fpc->inst_offset + 1] = 0x00000000;
+ fp->insn[fpc->inst_offset + 2] = 0x00000000;
+ fp->insn[fpc->inst_offset + 3] = 0x00000000;
+
+ if(debug_get_option_nvfx_dump_fp())
+ {
+ debug_printf("\n");
+ tgsi_dump(fp->pipe.tokens, 0);
+
+ debug_printf("\n%s fragment program:\n", nvfx->is_nv4x ? "nv4x" : "nv3x");
+ for (unsigned i = 0; i < fp->insn_len; i += 4)
+ debug_printf("%3u: %08x %08x %08x %08x\n", i >> 2, fp->insn[i], fp->insn[i + 1], fp->insn[i + 2], fp->insn[i + 3]);
+ debug_printf("\n");
+ }
+
+ fp->translated = TRUE;
+
+out:
+ tgsi_parse_free(&parse);
+ if(fpc)
+ {
+ FREE(fpc->r_temp);
+ util_dynarray_fini(&fpc->if_stack);
+ util_dynarray_fini(&fpc->label_relocs);
+ util_dynarray_fini(&fpc->imm_data);
+ //util_dynarray_fini(&fpc->loop_stack);
+ FREE(fpc);
+ }
+
+ return;
+
+out_err:
+ _debug_printf("Error: failed to compile this fragment program:\n");
+ tgsi_dump(fp->pipe.tokens, 0);
+ goto out;
+}
+
+static inline void
+nvfx_fp_memcpy(void* dst, const void* src, size_t len)
+{
+#ifndef PIPE_ARCH_BIG_ENDIAN
+ memcpy(dst, src, len);
+#else
+ size_t i;
+ for(i = 0; i < len; i += 4) {
+ uint32_t v = *(uint32_t*)((char*)src + i);
+ *(uint32_t*)((char*)dst + i) = (v >> 16) | (v << 16);
+ }
+#endif
+}
diff --git a/src/gallium/drivers/nouveau/nv30/nvfx_shader.h b/src/gallium/drivers/nouveau/nv30/nvfx_shader.h
new file mode 100644
index 00000000000..987e1b043dd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nvfx_shader.h
@@ -0,0 +1,525 @@
+#ifndef __NVFX_SHADER_H__
+#define __NVFX_SHADER_H__
+
+#include <stdint.h>
+
+#include "pipe/p_compiler.h"
+
+#define NVFX_SWZ_IDENTITY ((3 << 6) | (2 << 4) | (1 << 2) | (0 << 0))
+
+/* this will resolve to either the NV30 or the NV40 version
+ * depending on the current hardware */
+/* unusual, but very fast and compact method */
+#define NVFX_VP(c) ((NV30_VP_##c) + (nv30->is_nv4x & ((NV40_VP_##c) - (NV30_VP_##c))))
+
+#define NVFX_VP_INST_SLOT_VEC 0
+#define NVFX_VP_INST_SLOT_SCA 1
+
+#define NVFX_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */
+#define NVFX_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */
+#define NVFX_VP_INST_IN_NORMAL 2
+#define NVFX_VP_INST_IN_COL0 3 /* Should probably confirm them all though */
+#define NVFX_VP_INST_IN_COL1 4
+#define NVFX_VP_INST_IN_FOGC 5
+#define NVFX_VP_INST_IN_TC0 8
+#define NVFX_VP_INST_IN_TC(n) (8+n)
+
+#define NVFX_VP_INST_SCA_OP_NOP 0x00
+#define NVFX_VP_INST_SCA_OP_MOV 0x01
+#define NVFX_VP_INST_SCA_OP_RCP 0x02
+#define NVFX_VP_INST_SCA_OP_RCC 0x03
+#define NVFX_VP_INST_SCA_OP_RSQ 0x04
+#define NVFX_VP_INST_SCA_OP_EXP 0x05
+#define NVFX_VP_INST_SCA_OP_LOG 0x06
+#define NVFX_VP_INST_SCA_OP_LIT 0x07
+#define NVFX_VP_INST_SCA_OP_BRA 0x09
+#define NVFX_VP_INST_SCA_OP_CAL 0x0B
+#define NVFX_VP_INST_SCA_OP_RET 0x0C
+#define NVFX_VP_INST_SCA_OP_LG2 0x0D
+#define NVFX_VP_INST_SCA_OP_EX2 0x0E
+#define NVFX_VP_INST_SCA_OP_SIN 0x0F
+#define NVFX_VP_INST_SCA_OP_COS 0x10
+
+#define NV40_VP_INST_SCA_OP_PUSHA 0x13
+#define NV40_VP_INST_SCA_OP_POPA 0x14
+
+#define NVFX_VP_INST_VEC_OP_NOP 0x00
+#define NVFX_VP_INST_VEC_OP_MOV 0x01
+#define NVFX_VP_INST_VEC_OP_MUL 0x02
+#define NVFX_VP_INST_VEC_OP_ADD 0x03
+#define NVFX_VP_INST_VEC_OP_MAD 0x04
+#define NVFX_VP_INST_VEC_OP_DP3 0x05
+#define NVFX_VP_INST_VEC_OP_DPH 0x06
+#define NVFX_VP_INST_VEC_OP_DP4 0x07
+#define NVFX_VP_INST_VEC_OP_DST 0x08
+#define NVFX_VP_INST_VEC_OP_MIN 0x09
+#define NVFX_VP_INST_VEC_OP_MAX 0x0A
+#define NVFX_VP_INST_VEC_OP_SLT 0x0B
+#define NVFX_VP_INST_VEC_OP_SGE 0x0C
+#define NVFX_VP_INST_VEC_OP_ARL 0x0D
+#define NVFX_VP_INST_VEC_OP_FRC 0x0E
+#define NVFX_VP_INST_VEC_OP_FLR 0x0F
+#define NVFX_VP_INST_VEC_OP_SEQ 0x10
+#define NVFX_VP_INST_VEC_OP_SFL 0x11
+#define NVFX_VP_INST_VEC_OP_SGT 0x12
+#define NVFX_VP_INST_VEC_OP_SLE 0x13
+#define NVFX_VP_INST_VEC_OP_SNE 0x14
+#define NVFX_VP_INST_VEC_OP_STR 0x15
+#define NVFX_VP_INST_VEC_OP_SSG 0x16
+#define NVFX_VP_INST_VEC_OP_ARR 0x17
+#define NVFX_VP_INST_VEC_OP_ARA 0x18
+
+#define NV40_VP_INST_VEC_OP_TXL 0x19
+
+/* DWORD 3 */
+#define NVFX_VP_INST_LAST (1 << 0)
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ * 0: OPDEST
+ * 0: program end
+ * 1-6: destination register
+ * 7: destination register is fp16?? (use for outputs)
+ * 8: set condition code
+ * 9: writemask x
+ * 10: writemask y
+ * 11: writemask z
+ * 12: writemask w
+ * 13-16: source attribute register number (e.g. COL0)
+ * 17-20: texture unit number
+ * 21: expand value on texture operation (x -> 2x - 1)
+ * 22-23: precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = s0.8 fixed (nv40-only))
+ * 24-29: opcode
+ * 30: no destination
+ * 31: saturate
+ * 1 - SRC0
+ * 0-17: see common source fields
+ * 18: execute if condition code less
+ * 19: execute if condition code equal
+ * 20: execute if condition code greater
+ * 21-22: condition code swizzle x source component
+ * 23-24: condition code swizzle y source component
+ * 25-26: condition code swizzle z source component
+ * 27-28: condition code swizzle w source component
+ * 29: source 0 absolute
+ * 30: always 0 in renouveau tests
+ * 31: always 0 in renouveau tests
+ * 2 - SRC1
+ * 0-17: see common source fields
+ * 18: source 1 absolute
+ * 19-20: input precision 0 = fp32, 1 = fp16, 2 = s1.10 fixed, 3 = ???
+ * 21-27: always 0 in renouveau tests
+ * 28-30: scale (0 = 1x, 1 = 2x, 2 = 4x, 3 = 8x, 4 = ???, 5, = 1/2, 6 = 1/4, 7 = 1/8)
+ * 31: opcode is branch
+ * 3 - SRC2
+ * 0-17: see common source fields
+ * 18: source 2 absolute
+ * 19-29: address register displacement
+ * 30: use index register
+ * 31: disable perspective-correct interpolation?
+ *
+* Common fields of 0, 1, 2 - SRC
+ * 0-1: source register type (0 = temp, 1 = input, 2 = immediate, 3 = ???)
+ * 2-7: source temp register index
+ * 8: source register is fp16??
+ * 9-10: source swizzle x source component
+ * 11-12: source swizzle y source component
+ * 13-14: source swizzle z source component
+ * 15-16: source swizzle w source component
+ * 17: negate
+
+ * There appears to be no special difference between result regs and temp regs.
+ * result.color == R0.xyzw
+ * result.depth == R1.z
+ * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0
+ * otherwise it is set to 1.
+ *
+ * Constants are inserted directly after the instruction that uses them.
+ *
+ * It appears that it's not possible to use two input registers in one
+ * instruction as the input sourcing is done in the instruction dword
+ * and not the source selection dwords. As such instructions such as:
+ *
+ * ADD result.color, fragment.color, fragment.texcoord[0];
+ *
+ * must be split into two MOV's and then an ADD (nvidia does this) but
+ * I'm not sure why it's not just one MOV and then source the second input
+ * in the ADD instruction..
+ *
+ * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary
+ * negation requires multiplication with a const.
+ *
+ * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE
+ * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO
+ * is implemented simply by not writing to the relevant components of the destination.
+ *
+ * Conditional execution
+ * TODO
+ *
+ * Non-native instructions:
+ * LIT
+ * LRP - MAD+MAD
+ * SUB - ADD, negate second source
+ * RSQ - LG2 + EX2
+ * POW - LG2 + MUL + EX2
+ * SCS - COS + SIN
+ * XPD
+ *
+ * NV40 Looping
+ * Loops appear to be fairly expensive on NV40 at least, the proprietary
+ * driver goes to a lot of effort to avoid using the native looping
+ * instructions. If the total number of *executed* instructions between
+ * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop.
+ * The maximum loop count is 255.
+ *
+ */
+
+//== Opcode / Destination selection ==
+#define NVFX_FP_OP_PROGRAM_END (1 << 0)
+#define NVFX_FP_OP_OUT_REG_SHIFT 1
+#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */
+#define NV40_FP_OP_OUT_REG_MASK (63 << 1)
+/* Needs to be set when writing outputs to get expected result.. */
+#define NVFX_FP_OP_OUT_REG_HALF (1 << 7)
+#define NVFX_FP_OP_COND_WRITE_ENABLE (1 << 8)
+#define NVFX_FP_OP_OUTMASK_SHIFT 9
+#define NVFX_FP_OP_OUTMASK_MASK (0xF << 9)
+# define NVFX_FP_OP_OUT_X (1<<9)
+# define NVFX_FP_OP_OUT_Y (1<<10)
+# define NVFX_FP_OP_OUT_Z (1<<11)
+# define NVFX_FP_OP_OUT_W (1<<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NVFX_FP_OP_INPUT_SRC_SHIFT 13
+#define NVFX_FP_OP_INPUT_SRC_MASK (15 << 13)
+# define NVFX_FP_OP_INPUT_SRC_POSITION 0x0
+# define NVFX_FP_OP_INPUT_SRC_COL0 0x1
+# define NVFX_FP_OP_INPUT_SRC_COL1 0x2
+# define NVFX_FP_OP_INPUT_SRC_FOGC 0x3
+# define NVFX_FP_OP_INPUT_SRC_TC0 0x4
+# define NVFX_FP_OP_INPUT_SRC_TC(n) (0x4 + n)
+# define NV40_FP_OP_INPUT_SRC_FACING 0xE
+#define NVFX_FP_OP_TEX_UNIT_SHIFT 17
+#define NVFX_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */
+#define NVFX_FP_OP_PRECISION_SHIFT 22
+#define NVFX_FP_OP_PRECISION_MASK (3 << 22)
+# define NVFX_FP_PRECISION_FP32 0
+# define NVFX_FP_PRECISION_FP16 1
+# define NVFX_FP_PRECISION_FX12 2
+#define NVFX_FP_OP_OPCODE_SHIFT 24
+#define NVFX_FP_OP_OPCODE_MASK (0x3F << 24)
+/* NV30/NV40 fragment program opcodes */
+#define NVFX_FP_OP_OPCODE_NOP 0x00
+#define NVFX_FP_OP_OPCODE_MOV 0x01
+#define NVFX_FP_OP_OPCODE_MUL 0x02
+#define NVFX_FP_OP_OPCODE_ADD 0x03
+#define NVFX_FP_OP_OPCODE_MAD 0x04
+#define NVFX_FP_OP_OPCODE_DP3 0x05
+#define NVFX_FP_OP_OPCODE_DP4 0x06
+#define NVFX_FP_OP_OPCODE_DST 0x07
+#define NVFX_FP_OP_OPCODE_MIN 0x08
+#define NVFX_FP_OP_OPCODE_MAX 0x09
+#define NVFX_FP_OP_OPCODE_SLT 0x0A
+#define NVFX_FP_OP_OPCODE_SGE 0x0B
+#define NVFX_FP_OP_OPCODE_SLE 0x0C
+#define NVFX_FP_OP_OPCODE_SGT 0x0D
+#define NVFX_FP_OP_OPCODE_SNE 0x0E
+#define NVFX_FP_OP_OPCODE_SEQ 0x0F
+#define NVFX_FP_OP_OPCODE_FRC 0x10
+#define NVFX_FP_OP_OPCODE_FLR 0x11
+#define NVFX_FP_OP_OPCODE_KIL 0x12
+#define NVFX_FP_OP_OPCODE_PK4B 0x13
+#define NVFX_FP_OP_OPCODE_UP4B 0x14
+#define NVFX_FP_OP_OPCODE_DDX 0x15 /* can only write XY */
+#define NVFX_FP_OP_OPCODE_DDY 0x16 /* can only write XY */
+#define NVFX_FP_OP_OPCODE_TEX 0x17
+#define NVFX_FP_OP_OPCODE_TXP 0x18
+#define NVFX_FP_OP_OPCODE_TXD 0x19
+#define NVFX_FP_OP_OPCODE_RCP 0x1A
+#define NVFX_FP_OP_OPCODE_EX2 0x1C
+#define NVFX_FP_OP_OPCODE_LG2 0x1D
+#define NVFX_FP_OP_OPCODE_STR 0x20
+#define NVFX_FP_OP_OPCODE_SFL 0x21
+#define NVFX_FP_OP_OPCODE_COS 0x22
+#define NVFX_FP_OP_OPCODE_SIN 0x23
+#define NVFX_FP_OP_OPCODE_PK2H 0x24
+#define NVFX_FP_OP_OPCODE_UP2H 0x25
+#define NVFX_FP_OP_OPCODE_PK4UB 0x27
+#define NVFX_FP_OP_OPCODE_UP4UB 0x28
+#define NVFX_FP_OP_OPCODE_PK2US 0x29
+#define NVFX_FP_OP_OPCODE_UP2US 0x2A
+#define NVFX_FP_OP_OPCODE_DP2A 0x2E
+#define NVFX_FP_OP_OPCODE_TXB 0x31
+#define NVFX_FP_OP_OPCODE_DIV 0x3A
+
+/* NV30 only fragment program opcodes */
+#define NVFX_FP_OP_OPCODE_RSQ_NV30 0x1B
+#define NVFX_FP_OP_OPCODE_LIT_NV30 0x1E
+#define NVFX_FP_OP_OPCODE_LRP_NV30 0x1F
+#define NVFX_FP_OP_OPCODE_POW_NV30 0x26
+#define NVFX_FP_OP_OPCODE_RFL_NV30 0x36
+
+/* NV40 only fragment program opcodes */
+#define NVFX_FP_OP_OPCODE_TXL_NV40 0x2F
+#define NVFX_FP_OP_OPCODE_LITEX2_NV40 0x3C
+
+/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/
+#define NV40_FP_OP_BRA_OPCODE_BRK 0x0
+#define NV40_FP_OP_BRA_OPCODE_CAL 0x1
+#define NV40_FP_OP_BRA_OPCODE_IF 0x2
+#define NV40_FP_OP_BRA_OPCODE_LOOP 0x3
+#define NV40_FP_OP_BRA_OPCODE_REP 0x4
+#define NV40_FP_OP_BRA_OPCODE_RET 0x5
+
+#define NV40_FP_OP_OUT_NONE (1 << 30)
+#define NVFX_FP_OP_OUT_SAT (1 << 31)
+
+/* high order bits of SRC0 */
+#define NVFX_FP_OP_SRC0_ABS (1 << 29)
+#define NVFX_FP_OP_COND_SWZ_W_SHIFT 27
+#define NVFX_FP_OP_COND_SWZ_W_MASK (3 << 27)
+#define NVFX_FP_OP_COND_SWZ_Z_SHIFT 25
+#define NVFX_FP_OP_COND_SWZ_Z_MASK (3 << 25)
+#define NVFX_FP_OP_COND_SWZ_Y_SHIFT 23
+#define NVFX_FP_OP_COND_SWZ_Y_MASK (3 << 23)
+#define NVFX_FP_OP_COND_SWZ_X_SHIFT 21
+#define NVFX_FP_OP_COND_SWZ_X_MASK (3 << 21)
+#define NVFX_FP_OP_COND_SWZ_ALL_SHIFT 21
+#define NVFX_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21)
+#define NVFX_FP_OP_COND_SHIFT 18
+#define NVFX_FP_OP_COND_MASK (0x07 << 18)
+# define NVFX_FP_OP_COND_FL 0
+# define NVFX_FP_OP_COND_LT 1
+# define NVFX_FP_OP_COND_EQ 2
+# define NVFX_FP_OP_COND_LE 3
+# define NVFX_FP_OP_COND_GT 4
+# define NVFX_FP_OP_COND_NE 5
+# define NVFX_FP_OP_COND_GE 6
+# define NVFX_FP_OP_COND_TR 7
+
+/* high order bits of SRC1 */
+#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
+#define NVFX_FP_OP_DST_SCALE_SHIFT 28
+#define NVFX_FP_OP_DST_SCALE_MASK (3 << 28)
+#define NVFX_FP_OP_DST_SCALE_1X 0
+#define NVFX_FP_OP_DST_SCALE_2X 1
+#define NVFX_FP_OP_DST_SCALE_4X 2
+#define NVFX_FP_OP_DST_SCALE_8X 3
+#define NVFX_FP_OP_DST_SCALE_INV_2X 5
+#define NVFX_FP_OP_DST_SCALE_INV_4X 6
+#define NVFX_FP_OP_DST_SCALE_INV_8X 7
+#define NVFX_FP_OP_SRC1_ABS (1 << 18)
+
+/* SRC1 LOOP */
+#define NV40_FP_OP_LOOP_INCR_SHIFT 19
+#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19)
+#define NV40_FP_OP_LOOP_INDEX_SHIFT 10
+#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10)
+#define NV40_FP_OP_LOOP_COUNT_SHIFT 2
+#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2)
+
+/* SRC1 IF: absolute offset in dwords */
+#define NV40_FP_OP_ELSE_OFFSET_SHIFT 0
+#define NV40_FP_OP_ELSE_OFFSET_MASK (0x7FFFFFFF << 0)
+
+/* SRC1 CAL */
+#define NV40_FP_OP_SUB_OFFSET_SHIFT 0
+#define NV40_FP_OP_SUB_OFFSET_MASK (0x7FFFFFFF << 0)
+
+/* SRC1 REP
+ * I have no idea why there are 3 count values here.. but they
+ * have always been filled with the same value in my tests so
+ * far..
+ */
+#define NV40_FP_OP_REP_COUNT1_SHIFT 2
+#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2)
+#define NV40_FP_OP_REP_COUNT2_SHIFT 10
+#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10)
+#define NV40_FP_OP_REP_COUNT3_SHIFT 19
+#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19)
+
+/* SRC2 REP/IF: absolute offset in dwords */
+#define NV40_FP_OP_END_OFFSET_SHIFT 0
+#define NV40_FP_OP_END_OFFSET_MASK (0x7FFFFFFF << 0)
+
+/* high order bits of SRC2 */
+#define NVFX_FP_OP_INDEX_INPUT (1 << 30)
+#define NV40_FP_OP_ADDR_INDEX_SHIFT 19
+#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19)
+
+//== Register selection ==
+#define NVFX_FP_REG_TYPE_SHIFT 0
+#define NVFX_FP_REG_TYPE_MASK (3 << 0)
+# define NVFX_FP_REG_TYPE_TEMP 0
+# define NVFX_FP_REG_TYPE_INPUT 1
+# define NVFX_FP_REG_TYPE_CONST 2
+#define NVFX_FP_REG_SRC_SHIFT 2
+#define NV30_FP_REG_SRC_MASK (31 << 2)
+#define NV40_FP_REG_SRC_MASK (63 << 2)
+#define NVFX_FP_REG_SRC_HALF (1 << 8)
+#define NVFX_FP_REG_SWZ_ALL_SHIFT 9
+#define NVFX_FP_REG_SWZ_ALL_MASK (255 << 9)
+#define NVFX_FP_REG_SWZ_X_SHIFT 9
+#define NVFX_FP_REG_SWZ_X_MASK (3 << 9)
+#define NVFX_FP_REG_SWZ_Y_SHIFT 11
+#define NVFX_FP_REG_SWZ_Y_MASK (3 << 11)
+#define NVFX_FP_REG_SWZ_Z_SHIFT 13
+#define NVFX_FP_REG_SWZ_Z_MASK (3 << 13)
+#define NVFX_FP_REG_SWZ_W_SHIFT 15
+#define NVFX_FP_REG_SWZ_W_MASK (3 << 15)
+# define NVFX_FP_SWIZZLE_X 0
+# define NVFX_FP_SWIZZLE_Y 1
+# define NVFX_FP_SWIZZLE_Z 2
+# define NVFX_FP_SWIZZLE_W 3
+#define NVFX_FP_REG_NEGATE (1 << 17)
+
+#define NVFXSR_NONE 0
+#define NVFXSR_OUTPUT 1
+#define NVFXSR_INPUT 2
+#define NVFXSR_TEMP 3
+#define NVFXSR_CONST 5
+#define NVFXSR_IMM 6
+
+#define NVFX_COND_FL 0
+#define NVFX_COND_LT 1
+#define NVFX_COND_EQ 2
+#define NVFX_COND_LE 3
+#define NVFX_COND_GT 4
+#define NVFX_COND_NE 5
+#define NVFX_COND_GE 6
+#define NVFX_COND_TR 7
+
+/* Yes, this are ordered differently... */
+
+#define NVFX_VP_MASK_X 8
+#define NVFX_VP_MASK_Y 4
+#define NVFX_VP_MASK_Z 2
+#define NVFX_VP_MASK_W 1
+#define NVFX_VP_MASK_ALL 0xf
+
+#define NVFX_FP_MASK_X 1
+#define NVFX_FP_MASK_Y 2
+#define NVFX_FP_MASK_Z 4
+#define NVFX_FP_MASK_W 8
+#define NVFX_FP_MASK_ALL 0xf
+
+#define NVFX_SWZ_X 0
+#define NVFX_SWZ_Y 1
+#define NVFX_SWZ_Z 2
+#define NVFX_SWZ_W 3
+
+#define swz(s,x,y,z,w) nvfx_src_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w)
+#define neg(s) nvfx_src_neg((s))
+#define abs(s) nvfx_src_abs((s))
+
+struct nvfx_reg {
+ int8_t type;
+ int32_t index;
+};
+
+struct nvfx_src {
+ struct nvfx_reg reg;
+
+ uint8_t indirect : 1;
+ uint8_t indirect_reg : 1;
+ uint8_t indirect_swz : 2;
+ uint8_t negate : 1;
+ uint8_t abs : 1;
+ uint8_t swz[4];
+};
+
+struct nvfx_insn
+{
+ uint8_t op;
+ char scale;
+ int8_t unit;
+ uint8_t mask;
+ uint8_t cc_swz[4];
+
+ uint8_t sat : 1;
+ uint8_t cc_update : 1;
+ uint8_t cc_update_reg : 1;
+ uint8_t cc_test : 3;
+ uint8_t cc_test_reg : 1;
+
+ struct nvfx_reg dst;
+ struct nvfx_src src[3];
+};
+
+static INLINE struct nvfx_insn
+nvfx_insn(boolean sat, unsigned op, int unit, struct nvfx_reg dst, unsigned mask, struct nvfx_src s0, struct nvfx_src s1, struct nvfx_src s2)
+{
+ struct nvfx_insn insn = {
+ .op = op,
+ .scale = 0,
+ .unit = unit,
+ .sat = sat,
+ .mask = mask,
+ .cc_update = 0,
+ .cc_update_reg = 0,
+ .cc_test = NVFX_COND_TR,
+ .cc_test_reg = 0,
+ .cc_swz = { 0, 1, 2, 3 },
+ .dst = dst,
+ .src = {s0, s1, s2}
+ };
+ return insn;
+}
+
+static INLINE struct nvfx_reg
+nvfx_reg(int type, int index)
+{
+ struct nvfx_reg temp = {
+ .type = type,
+ .index = index,
+ };
+ return temp;
+}
+
+static INLINE struct nvfx_src
+nvfx_src(struct nvfx_reg reg)
+{
+ struct nvfx_src temp = {
+ .reg = reg,
+ .abs = 0,
+ .negate = 0,
+ .swz = { 0, 1, 2, 3 },
+ .indirect = 0,
+ };
+ return temp;
+}
+
+static INLINE struct nvfx_src
+nvfx_src_swz(struct nvfx_src src, int x, int y, int z, int w)
+{
+ struct nvfx_src dst = src;
+
+ dst.swz[NVFX_SWZ_X] = src.swz[x];
+ dst.swz[NVFX_SWZ_Y] = src.swz[y];
+ dst.swz[NVFX_SWZ_Z] = src.swz[z];
+ dst.swz[NVFX_SWZ_W] = src.swz[w];
+ return dst;
+}
+
+static INLINE struct nvfx_src
+nvfx_src_neg(struct nvfx_src src)
+{
+ src.negate = !src.negate;
+ return src;
+}
+
+static INLINE struct nvfx_src
+nvfx_src_abs(struct nvfx_src src)
+{
+ src.abs = 1;
+ return src;
+}
+
+struct nvfx_relocation {
+ unsigned location;
+ unsigned target;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nvfx_vertprog.c b/src/gallium/drivers/nouveau/nv30/nvfx_vertprog.c
new file mode 100644
index 00000000000..3ae51ef9e82
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nv30/nvfx_vertprog.c
@@ -0,0 +1,1133 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "util/u_linkage.h"
+#include "util/u_debug.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_ureg.h"
+
+#include "draw/draw_context.h"
+
+#include "nv30/nv30-40_3d.xml.h"
+#include "nv30/nv30_context.h"
+#include "nv30/nv30_resource.h"
+
+/* TODO (at least...):
+ * 1. Indexed consts + ARL
+ * 3. NV_vp11, NV_vp2, NV_vp3 features
+ * - extra arith opcodes
+ * - branching
+ * - texture sampling
+ * - indexed attribs
+ * - indexed results
+ * 4. bugs
+ */
+
+#include "nv30/nv30_vertprog.h"
+#include "nv30/nv40_vertprog.h"
+
+struct nvfx_loop_entry {
+ unsigned brk_target;
+ unsigned cont_target;
+};
+
+struct nvfx_vpc {
+ struct nv30_context* nv30;
+ struct pipe_shader_state pipe;
+ struct nv30_vertprog *vp;
+ struct tgsi_shader_info* info;
+
+ struct nv30_vertprog_exec *vpi;
+
+ unsigned r_temps;
+ unsigned r_temps_discard;
+ struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
+ struct nvfx_reg *r_address;
+ struct nvfx_reg *r_temp;
+ struct nvfx_reg *r_const;
+ struct nvfx_reg r_0_1;
+
+ struct nvfx_reg *imm;
+ unsigned nr_imm;
+
+ int hpos_idx;
+ int cvtx_idx;
+
+ struct util_dynarray label_relocs;
+ struct util_dynarray loop_stack;
+};
+
+static struct nvfx_reg
+temp(struct nvfx_vpc *vpc)
+{
+ int idx = ffs(~vpc->r_temps) - 1;
+
+ if (idx < 0) {
+ NOUVEAU_ERR("out of temps!!\n");
+ assert(0);
+ return nvfx_reg(NVFXSR_TEMP, 0);
+ }
+
+ vpc->r_temps |= (1 << idx);
+ vpc->r_temps_discard |= (1 << idx);
+ return nvfx_reg(NVFXSR_TEMP, idx);
+}
+
+static inline void
+release_temps(struct nvfx_vpc *vpc)
+{
+ vpc->r_temps &= ~vpc->r_temps_discard;
+ vpc->r_temps_discard = 0;
+}
+
+static struct nvfx_reg
+constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+ struct nv30_vertprog *vp = vpc->vp;
+ struct nv30_vertprog_data *vpd;
+ int idx;
+
+ if (pipe >= 0) {
+ for (idx = 0; idx < vp->nr_consts; idx++) {
+ if (vp->consts[idx].index == pipe)
+ return nvfx_reg(NVFXSR_CONST, idx);
+ }
+ }
+
+ idx = vp->nr_consts++;
+ vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts);
+ vpd = &vp->consts[idx];
+
+ vpd->index = pipe;
+ vpd->value[0] = x;
+ vpd->value[1] = y;
+ vpd->value[2] = z;
+ vpd->value[3] = w;
+ return nvfx_reg(NVFXSR_CONST, idx);
+}
+
+#define arith(s,t,o,d,m,s0,s1,s2) \
+ nvfx_insn((s), (NVFX_VP_INST_SLOT_##t << 7) | NVFX_VP_INST_##t##_OP_##o, -1, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv30_context *nv30, struct nvfx_vpc *vpc, uint32_t *hw,
+ int pos, struct nvfx_src src)
+{
+ struct nv30_vertprog *vp = vpc->vp;
+ uint32_t sr = 0;
+ struct nvfx_relocation reloc;
+
+ switch (src.reg.type) {
+ case NVFXSR_TEMP:
+ sr |= (NVFX_VP(SRC_REG_TYPE_TEMP) << NVFX_VP(SRC_REG_TYPE_SHIFT));
+ sr |= (src.reg.index << NVFX_VP(SRC_TEMP_SRC_SHIFT));
+ break;
+ case NVFXSR_INPUT:
+ sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
+ NVFX_VP(SRC_REG_TYPE_SHIFT));
+ vp->ir |= (1 << src.reg.index);
+ hw[1] |= (src.reg.index << NVFX_VP(INST_INPUT_SRC_SHIFT));
+ break;
+ case NVFXSR_CONST:
+ sr |= (NVFX_VP(SRC_REG_TYPE_CONST) <<
+ NVFX_VP(SRC_REG_TYPE_SHIFT));
+ if (src.reg.index < 256 && src.reg.index >= -256) {
+ reloc.location = vp->nr_insns - 1;
+ reloc.target = src.reg.index;
+ util_dynarray_append(&vp->const_relocs, struct nvfx_relocation, reloc);
+ } else {
+ hw[1] |= (src.reg.index << NVFX_VP(INST_CONST_SRC_SHIFT)) &
+ NVFX_VP(INST_CONST_SRC_MASK);
+ }
+ break;
+ case NVFXSR_NONE:
+ sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) <<
+ NVFX_VP(SRC_REG_TYPE_SHIFT));
+ break;
+ default:
+ assert(0);
+ }
+
+ if (src.negate)
+ sr |= NVFX_VP(SRC_NEGATE);
+
+ if (src.abs)
+ hw[0] |= (1 << (21 + pos));
+
+ sr |= ((src.swz[0] << NVFX_VP(SRC_SWZ_X_SHIFT)) |
+ (src.swz[1] << NVFX_VP(SRC_SWZ_Y_SHIFT)) |
+ (src.swz[2] << NVFX_VP(SRC_SWZ_Z_SHIFT)) |
+ (src.swz[3] << NVFX_VP(SRC_SWZ_W_SHIFT)));
+
+ if(src.indirect) {
+ if(src.reg.type == NVFXSR_CONST)
+ hw[3] |= NVFX_VP(INST_INDEX_CONST);
+ else if(src.reg.type == NVFXSR_INPUT)
+ hw[0] |= NVFX_VP(INST_INDEX_INPUT);
+ else
+ assert(0);
+
+ if(src.indirect_reg)
+ hw[0] |= NVFX_VP(INST_ADDR_REG_SELECT_1);
+ hw[0] |= src.indirect_swz << NVFX_VP(INST_ADDR_SWZ_SHIFT);
+ }
+
+ switch (pos) {
+ case 0:
+ hw[1] |= ((sr & NVFX_VP(SRC0_HIGH_MASK)) >>
+ NVFX_VP(SRC0_HIGH_SHIFT)) << NVFX_VP(INST_SRC0H_SHIFT);
+ hw[2] |= (sr & NVFX_VP(SRC0_LOW_MASK)) <<
+ NVFX_VP(INST_SRC0L_SHIFT);
+ break;
+ case 1:
+ hw[2] |= sr << NVFX_VP(INST_SRC1_SHIFT);
+ break;
+ case 2:
+ hw[2] |= ((sr & NVFX_VP(SRC2_HIGH_MASK)) >>
+ NVFX_VP(SRC2_HIGH_SHIFT)) << NVFX_VP(INST_SRC2H_SHIFT);
+ hw[3] |= (sr & NVFX_VP(SRC2_LOW_MASK)) <<
+ NVFX_VP(INST_SRC2L_SHIFT);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+emit_dst(struct nv30_context *nv30, struct nvfx_vpc *vpc, uint32_t *hw,
+ int slot, struct nvfx_reg dst)
+{
+ struct nv30_vertprog *vp = vpc->vp;
+
+ switch (dst.type) {
+ case NVFXSR_NONE:
+ if(!nv30->is_nv4x)
+ hw[0] |= NV30_VP_INST_DEST_TEMP_ID_MASK;
+ else {
+ hw[3] |= NV40_VP_INST_DEST_MASK;
+ if (slot == 0)
+ hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
+ else
+ hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ }
+ break;
+ case NVFXSR_TEMP:
+ if(!nv30->is_nv4x)
+ hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
+ else {
+ hw[3] |= NV40_VP_INST_DEST_MASK;
+ if (slot == 0)
+ hw[0] |= (dst.index << NV40_VP_INST_VEC_DEST_TEMP_SHIFT);
+ else
+ hw[3] |= (dst.index << NV40_VP_INST_SCA_DEST_TEMP_SHIFT);
+ }
+ break;
+ case NVFXSR_OUTPUT:
+ /* TODO: this may be wrong because on nv30 COL0 and BFC0 are swapped */
+ if(nv30->is_nv4x) {
+ switch (dst.index) {
+ case NV30_VP_INST_DEST_CLP(0):
+ dst.index = NVFX_VP(INST_DEST_FOGC);
+ vp->or |= (1 << 6);
+ break;
+ case NV30_VP_INST_DEST_CLP(1):
+ dst.index = NVFX_VP(INST_DEST_FOGC);
+ vp->or |= (1 << 7);
+ break;
+ case NV30_VP_INST_DEST_CLP(2):
+ dst.index = NVFX_VP(INST_DEST_FOGC);
+ vp->or |= (1 << 8);
+ break;
+ case NV30_VP_INST_DEST_CLP(3):
+ dst.index = NVFX_VP(INST_DEST_PSZ);
+ vp->or |= (1 << 9);
+ break;
+ case NV30_VP_INST_DEST_CLP(4):
+ dst.index = NVFX_VP(INST_DEST_PSZ);
+ vp->or |= (1 << 10);
+ break;
+ case NV30_VP_INST_DEST_CLP(5):
+ dst.index = NVFX_VP(INST_DEST_PSZ);
+ vp->or |= (1 << 11);
+ break;
+ case NV40_VP_INST_DEST_COL0: vp->or |= (1 << 0); break;
+ case NV40_VP_INST_DEST_COL1: vp->or |= (1 << 1); break;
+ case NV40_VP_INST_DEST_BFC0: vp->or |= (1 << 2); break;
+ case NV40_VP_INST_DEST_BFC1: vp->or |= (1 << 3); break;
+ case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break;
+ case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break;
+ }
+ }
+
+ if(!nv30->is_nv4x) {
+ hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
+ hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK;
+
+ /*XXX: no way this is entirely correct, someone needs to
+ * figure out what exactly it is.
+ */
+ hw[3] |= 0x800;
+ } else {
+ hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT);
+ if (slot == 0) {
+ hw[0] |= NV40_VP_INST_VEC_RESULT;
+ hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK;
+ } else {
+ hw[3] |= NV40_VP_INST_SCA_RESULT;
+ hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ }
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static void
+nvfx_vp_emit(struct nvfx_vpc *vpc, struct nvfx_insn insn)
+{
+ struct nv30_context *nv30 = vpc->nv30;
+ struct nv30_vertprog *vp = vpc->vp;
+ unsigned slot = insn.op >> 7;
+ unsigned op = insn.op & 0x7f;
+ uint32_t *hw;
+
+ vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi));
+ vpc->vpi = &vp->insns[vp->nr_insns - 1];
+ memset(vpc->vpi, 0, sizeof(*vpc->vpi));
+
+ hw = vpc->vpi->data;
+
+ if (insn.cc_test != NVFX_COND_TR)
+ hw[0] |= NVFX_VP(INST_COND_TEST_ENABLE);
+ hw[0] |= (insn.cc_test << NVFX_VP(INST_COND_SHIFT));
+ hw[0] |= ((insn.cc_swz[0] << NVFX_VP(INST_COND_SWZ_X_SHIFT)) |
+ (insn.cc_swz[1] << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) |
+ (insn.cc_swz[2] << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) |
+ (insn.cc_swz[3] << NVFX_VP(INST_COND_SWZ_W_SHIFT)));
+ if(insn.cc_update)
+ hw[0] |= NVFX_VP(INST_COND_UPDATE_ENABLE);
+
+ if(insn.sat) {
+ assert(nv30->use_nv4x);
+ if(nv30->use_nv4x)
+ hw[0] |= NV40_VP_INST_SATURATE;
+ }
+
+ if(!nv30->is_nv4x) {
+ if(slot == 0)
+ hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+ else {
+ hw[0] |= ((op >> 4) << NV30_VP_INST_SCA_OPCODEH_SHIFT);
+ hw[1] |= ((op & 0xf) << NV30_VP_INST_SCA_OPCODEL_SHIFT);
+ }
+// hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK);
+// hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT));
+
+ if (insn.dst.type == NVFXSR_OUTPUT) {
+ if (slot)
+ hw[3] |= (insn.mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (insn.mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
+ } else {
+ if (slot)
+ hw[3] |= (insn.mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
+ else
+ hw[3] |= (insn.mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
+ }
+ } else {
+ if (slot == 0) {
+ hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT);
+ hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+ hw[3] |= (insn.mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT);
+ } else {
+ hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT);
+ hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK ;
+ hw[3] |= (insn.mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
+ }
+ }
+
+ emit_dst(nv30, vpc, hw, slot, insn.dst);
+ emit_src(nv30, vpc, hw, 0, insn.src[0]);
+ emit_src(nv30, vpc, hw, 1, insn.src[1]);
+ emit_src(nv30, vpc, hw, 2, insn.src[2]);
+
+// if(insn.src[0].indirect || op == NVFX_VP_INST_VEC_OP_ARL)
+// hw[3] |= NV40_VP_INST_SCA_RESULT;
+}
+
+static inline struct nvfx_src
+tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+ struct nvfx_src src;
+
+ switch (fsrc->Register.File) {
+ case TGSI_FILE_INPUT:
+ src.reg = nvfx_reg(NVFXSR_INPUT, fsrc->Register.Index);
+ break;
+ case TGSI_FILE_CONSTANT:
+ if(fsrc->Register.Indirect) {
+ src.reg = vpc->r_const[0];
+ src.reg.index = fsrc->Register.Index;
+ } else {
+ src.reg = vpc->r_const[fsrc->Register.Index];
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ src.reg = vpc->imm[fsrc->Register.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ src.reg = vpc->r_temp[fsrc->Register.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ src.reg.index = 0;
+ src.reg.type = -1;
+ break;
+ }
+
+ src.abs = fsrc->Register.Absolute;
+ src.negate = fsrc->Register.Negate;
+ src.swz[0] = fsrc->Register.SwizzleX;
+ src.swz[1] = fsrc->Register.SwizzleY;
+ src.swz[2] = fsrc->Register.SwizzleZ;
+ src.swz[3] = fsrc->Register.SwizzleW;
+ src.indirect = 0;
+ src.indirect_reg = 0;
+ src.indirect_swz = 0;
+
+ if(fsrc->Register.Indirect) {
+ if(fsrc->Indirect.File == TGSI_FILE_ADDRESS &&
+ (fsrc->Register.File == TGSI_FILE_CONSTANT ||
+ fsrc->Register.File == TGSI_FILE_INPUT)) {
+ src.indirect = 1;
+ src.indirect_reg = fsrc->Indirect.Index;
+ src.indirect_swz = fsrc->Indirect.Swizzle;
+ } else {
+ src.reg.index = 0;
+ src.reg.type = -1;
+ }
+ }
+
+ return src;
+}
+
+static INLINE struct nvfx_reg
+tgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+ struct nvfx_reg dst;
+
+ switch (fdst->Register.File) {
+ case TGSI_FILE_NULL:
+ dst = nvfx_reg(NVFXSR_NONE, 0);
+ break;
+ case TGSI_FILE_OUTPUT:
+ dst = vpc->r_result[fdst->Register.Index];
+ break;
+ case TGSI_FILE_TEMPORARY:
+ dst = vpc->r_temp[fdst->Register.Index];
+ break;
+ case TGSI_FILE_ADDRESS:
+ dst = vpc->r_address[fdst->Register.Index];
+ break;
+ default:
+ NOUVEAU_ERR("bad dst file %i\n", fdst->Register.File);
+ dst.index = 0;
+ dst.type = 0;
+ break;
+ }
+
+ return dst;
+}
+
+static inline int
+tgsi_mask(uint tgsi)
+{
+ int mask = 0;
+
+ if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_VP_MASK_X;
+ if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_VP_MASK_Y;
+ if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_VP_MASK_Z;
+ if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_VP_MASK_W;
+ return mask;
+}
+
+static boolean
+nvfx_vertprog_parse_instruction(struct nv30_context *nv30, struct nvfx_vpc *vpc,
+ unsigned idx, const struct tgsi_full_instruction *finst)
+{
+ struct nvfx_src src[3], tmp;
+ struct nvfx_reg dst;
+ struct nvfx_reg final_dst;
+ struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+ struct nvfx_insn insn;
+ struct nvfx_relocation reloc;
+ struct nvfx_loop_entry loop;
+ boolean sat = FALSE;
+ int mask;
+ int ai = -1, ci = -1, ii = -1;
+ int i;
+ unsigned sub_depth = 0;
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->Src[i];
+ if (fsrc->Register.File == TGSI_FILE_TEMPORARY) {
+ src[i] = tgsi_src(vpc, fsrc);
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ const struct tgsi_full_src_register *fsrc;
+
+ fsrc = &finst->Src[i];
+
+ switch (fsrc->Register.File) {
+ case TGSI_FILE_INPUT:
+ if (ai == -1 || ai == fsrc->Register.Index) {
+ ai = fsrc->Register.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if ((ci == -1 && ii == -1) ||
+ ci == fsrc->Register.Index) {
+ ci = fsrc->Register.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_IMMEDIATE:
+ if ((ci == -1 && ii == -1) ||
+ ii == fsrc->Register.Index) {
+ ii = fsrc->Register.Index;
+ src[i] = tgsi_src(vpc, fsrc);
+ } else {
+ src[i] = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MOV, src[i].reg, NVFX_VP_MASK_ALL,
+ tgsi_src(vpc, fsrc), none, none));
+ }
+ break;
+ case TGSI_FILE_TEMPORARY:
+ /* handled above */
+ break;
+ default:
+ NOUVEAU_ERR("bad src file\n");
+ return FALSE;
+ }
+ }
+
+ for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+ if(src[i].reg.type < 0)
+ return FALSE;
+ }
+
+ if(finst->Dst[0].Register.File == TGSI_FILE_ADDRESS &&
+ finst->Instruction.Opcode != TGSI_OPCODE_ARL)
+ return FALSE;
+
+ final_dst = dst = tgsi_dst(vpc, &finst->Dst[0]);
+ mask = tgsi_mask(finst->Dst[0].Register.WriteMask);
+ if(finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) {
+ assert(finst->Instruction.Opcode != TGSI_OPCODE_ARL);
+ if (nv30->use_nv4x)
+ sat = TRUE;
+ else
+ if(dst.type != NVFXSR_TEMP)
+ dst = temp(vpc);
+ }
+
+ switch (finst->Instruction.Opcode) {
+ case TGSI_OPCODE_ABS:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, abs(src[0]), none, none));
+ break;
+ case TGSI_OPCODE_ADD:
+ nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, src[0], none, src[1]));
+ break;
+ case TGSI_OPCODE_ARL:
+ nvfx_vp_emit(vpc, arith(0, VEC, ARL, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_CEIL:
+ tmp = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, FLR, tmp.reg, mask, neg(src[0]), none, none));
+ nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, neg(tmp), none, none));
+ break;
+ case TGSI_OPCODE_CMP:
+ insn = arith(0, VEC, MOV, none.reg, mask, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_vp_emit(vpc, insn);
+
+ insn = arith(sat, VEC, MOV, dst, mask, src[2], none, none);
+ insn.cc_test = NVFX_COND_GE;
+ nvfx_vp_emit(vpc, insn);
+
+ insn = arith(sat, VEC, MOV, dst, mask, src[1], none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_vp_emit(vpc, insn);
+ break;
+ case TGSI_OPCODE_COS:
+ nvfx_vp_emit(vpc, arith(sat, SCA, COS, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_DP2:
+ tmp = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, NVFX_VP_MASK_X | NVFX_VP_MASK_Y, src[0], src[1], none));
+ nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, swz(tmp, X, X, X, X), none, swz(tmp, Y, Y, Y, Y)));
+ break;
+ case TGSI_OPCODE_DP3:
+ nvfx_vp_emit(vpc, arith(sat, VEC, DP3, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_DP4:
+ nvfx_vp_emit(vpc, arith(sat, VEC, DP4, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_DPH:
+ nvfx_vp_emit(vpc, arith(sat, VEC, DPH, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_DST:
+ nvfx_vp_emit(vpc, arith(sat, VEC, DST, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_EX2:
+ nvfx_vp_emit(vpc, arith(sat, SCA, EX2, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_EXP:
+ nvfx_vp_emit(vpc, arith(sat, SCA, EXP, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_FLR:
+ nvfx_vp_emit(vpc, arith(sat, VEC, FLR, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_FRC:
+ nvfx_vp_emit(vpc, arith(sat, VEC, FRC, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_LG2:
+ nvfx_vp_emit(vpc, arith(sat, SCA, LG2, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_LIT:
+ nvfx_vp_emit(vpc, arith(sat, SCA, LIT, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_LOG:
+ nvfx_vp_emit(vpc, arith(sat, SCA, LOG, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_LRP:
+ tmp = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MAD, tmp.reg, mask, neg(src[0]), src[2], src[2]));
+ nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, mask, src[0], src[1], tmp));
+ break;
+ case TGSI_OPCODE_MAD:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, mask, src[0], src[1], src[2]));
+ break;
+ case TGSI_OPCODE_MAX:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MAX, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_MIN:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MIN, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_MOV:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_MUL:
+ nvfx_vp_emit(vpc, arith(sat, VEC, MUL, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_NOP:
+ break;
+ case TGSI_OPCODE_POW:
+ tmp = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, SCA, LG2, tmp.reg, NVFX_VP_MASK_X, none, none, swz(src[0], X, X, X, X)));
+ nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), swz(src[1], X, X, X, X), none));
+ nvfx_vp_emit(vpc, arith(sat, SCA, EX2, dst, mask, none, none, swz(tmp, X, X, X, X)));
+ break;
+ case TGSI_OPCODE_RCP:
+ nvfx_vp_emit(vpc, arith(sat, SCA, RCP, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_RSQ:
+ nvfx_vp_emit(vpc, arith(sat, SCA, RSQ, dst, mask, none, none, abs(src[0])));
+ break;
+ case TGSI_OPCODE_SEQ:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SEQ, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SFL:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SFL, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SGE:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SGE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SGT:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SGT, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SIN:
+ nvfx_vp_emit(vpc, arith(sat, SCA, SIN, dst, mask, none, none, src[0]));
+ break;
+ case TGSI_OPCODE_SLE:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SLE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SLT:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SLT, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SNE:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SNE, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SSG:
+ nvfx_vp_emit(vpc, arith(sat, VEC, SSG, dst, mask, src[0], none, none));
+ break;
+ case TGSI_OPCODE_STR:
+ nvfx_vp_emit(vpc, arith(sat, VEC, STR, dst, mask, src[0], src[1], none));
+ break;
+ case TGSI_OPCODE_SUB:
+ nvfx_vp_emit(vpc, arith(sat, VEC, ADD, dst, mask, src[0], none, neg(src[1])));
+ break;
+ case TGSI_OPCODE_TRUNC:
+ tmp = nvfx_src(temp(vpc));
+ insn = arith(0, VEC, MOV, none.reg, mask, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_vp_emit(vpc, insn);
+
+ nvfx_vp_emit(vpc, arith(0, VEC, FLR, tmp.reg, mask, abs(src[0]), none, none));
+ nvfx_vp_emit(vpc, arith(sat, VEC, MOV, dst, mask, tmp, none, none));
+
+ insn = arith(sat, VEC, MOV, dst, mask, neg(tmp), none, none);
+ insn.cc_test = NVFX_COND_LT;
+ nvfx_vp_emit(vpc, insn);
+ break;
+ case TGSI_OPCODE_XPD:
+ tmp = nvfx_src(temp(vpc));
+ nvfx_vp_emit(vpc, arith(0, VEC, MUL, tmp.reg, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none));
+ nvfx_vp_emit(vpc, arith(sat, VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)));
+ break;
+ case TGSI_OPCODE_IF:
+ insn = arith(0, VEC, MOV, none.reg, NVFX_VP_MASK_X, src[0], none, none);
+ insn.cc_update = 1;
+ nvfx_vp_emit(vpc, insn);
+
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = finst->Label.Label + 1;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+ insn = arith(0, SCA, BRA, none.reg, 0, none, none, none);
+ insn.cc_test = NVFX_COND_EQ;
+ insn.cc_swz[0] = insn.cc_swz[1] = insn.cc_swz[2] = insn.cc_swz[3] = 0;
+ nvfx_vp_emit(vpc, insn);
+ break;
+ case TGSI_OPCODE_ELSE:
+ case TGSI_OPCODE_BRA:
+ case TGSI_OPCODE_CAL:
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = finst->Label.Label;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+ if(finst->Instruction.Opcode == TGSI_OPCODE_CAL)
+ insn = arith(0, SCA, CAL, none.reg, 0, none, none, none);
+ else
+ insn = arith(0, SCA, BRA, none.reg, 0, none, none, none);
+ nvfx_vp_emit(vpc, insn);
+ break;
+ case TGSI_OPCODE_RET:
+ if(sub_depth || !vpc->vp->enabled_ucps) {
+ tmp = none;
+ tmp.swz[0] = tmp.swz[1] = tmp.swz[2] = tmp.swz[3] = 0;
+ nvfx_vp_emit(vpc, arith(0, SCA, RET, none.reg, 0, none, none, tmp));
+ } else {
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = vpc->info->num_instructions;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+ nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+ }
+ break;
+ case TGSI_OPCODE_BGNSUB:
+ ++sub_depth;
+ break;
+ case TGSI_OPCODE_ENDSUB:
+ --sub_depth;
+ break;
+ case TGSI_OPCODE_ENDIF:
+ /* nothing to do here */
+ break;
+ case TGSI_OPCODE_BGNLOOP:
+ loop.cont_target = idx;
+ loop.brk_target = finst->Label.Label + 1;
+ util_dynarray_append(&vpc->loop_stack, struct nvfx_loop_entry, loop);
+ break;
+ case TGSI_OPCODE_ENDLOOP:
+ loop = util_dynarray_pop(&vpc->loop_stack, struct nvfx_loop_entry);
+
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = loop.cont_target;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+ nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+ break;
+ case TGSI_OPCODE_CONT:
+ loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
+
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = loop.cont_target;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+ nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+ break;
+ case TGSI_OPCODE_BRK:
+ loop = util_dynarray_top(&vpc->loop_stack, struct nvfx_loop_entry);
+
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = loop.brk_target;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+
+ nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+ break;
+ case TGSI_OPCODE_END:
+ assert(!sub_depth);
+ if(vpc->vp->enabled_ucps) {
+ if(idx != (vpc->info->num_instructions - 1)) {
+ reloc.location = vpc->vp->nr_insns;
+ reloc.target = vpc->info->num_instructions;
+ util_dynarray_append(&vpc->label_relocs, struct nvfx_relocation, reloc);
+ nvfx_vp_emit(vpc, arith(0, SCA, BRA, none.reg, 0, none, none, none));
+ }
+ } else {
+ if(vpc->vp->nr_insns)
+ vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+ nvfx_vp_emit(vpc, arith(0, VEC, NOP, none.reg, 0, none, none, none));
+ vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+ }
+ break;
+ default:
+ NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+ return FALSE;
+ }
+
+ if(finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE && !nv30->use_nv4x) {
+ if (!vpc->r_0_1.type)
+ vpc->r_0_1 = constant(vpc, -1, 0, 1, 0, 0);
+ nvfx_vp_emit(vpc, arith(0, VEC, MAX, dst, mask, nvfx_src(dst), swz(nvfx_src(vpc->r_0_1), X, X, X, X), none));
+ nvfx_vp_emit(vpc, arith(0, VEC, MIN, final_dst, mask, nvfx_src(dst), swz(nvfx_src(vpc->r_0_1), Y, Y, Y, Y), none));
+ }
+
+ release_temps(vpc);
+ return TRUE;
+}
+
+static boolean
+nvfx_vertprog_parse_decl_output(struct nv30_context *nv30, struct nvfx_vpc *vpc,
+ const struct tgsi_full_declaration *fdec)
+{
+ unsigned num_texcoords = nv30->is_nv4x ? 10 : 8;
+ unsigned idx = fdec->Range.First;
+ unsigned semantic_index = fdec->Semantic.Index;
+ int hw = 0, i;
+
+ switch (fdec->Semantic.Name) {
+ case TGSI_SEMANTIC_POSITION:
+ hw = NVFX_VP(INST_DEST_POS);
+ vpc->hpos_idx = idx;
+ break;
+ case TGSI_SEMANTIC_CLIPVERTEX:
+ vpc->r_result[idx] = temp(vpc);
+ vpc->r_temps_discard = 0;
+ vpc->cvtx_idx = idx;
+ return TRUE;
+ case TGSI_SEMANTIC_COLOR:
+ if (fdec->Semantic.Index == 0) {
+ hw = NVFX_VP(INST_DEST_COL0);
+ } else
+ if (fdec->Semantic.Index == 1) {
+ hw = NVFX_VP(INST_DEST_COL1);
+ } else {
+ NOUVEAU_ERR("bad colour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ if (fdec->Semantic.Index == 0) {
+ hw = NVFX_VP(INST_DEST_BFC0);
+ } else
+ if (fdec->Semantic.Index == 1) {
+ hw = NVFX_VP(INST_DEST_BFC1);
+ } else {
+ NOUVEAU_ERR("bad bcolour semantic index\n");
+ return FALSE;
+ }
+ break;
+ case TGSI_SEMANTIC_FOG:
+ hw = NVFX_VP(INST_DEST_FOGC);
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ hw = NVFX_VP(INST_DEST_PSZ);
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ /* this is really an identifier for VP/FP linkage */
+ semantic_index += 8;
+ /* fall through */
+ case TGSI_SEMANTIC_TEXCOORD:
+ for (i = 0; i < num_texcoords; i++) {
+ if (vpc->vp->texcoord[i] == semantic_index) {
+ hw = NVFX_VP(INST_DEST_TC(i));
+ break;
+ }
+ }
+
+ if (i == num_texcoords) {
+ vpc->r_result[idx] = nvfx_reg(NVFXSR_NONE, 0);
+ return TRUE;
+ }
+ break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ /* not really an error just a fallback */
+ NOUVEAU_ERR("cannot handle edgeflag output\n");
+ return FALSE;
+ default:
+ NOUVEAU_ERR("bad output semantic\n");
+ return FALSE;
+ }
+
+ vpc->r_result[idx] = nvfx_reg(NVFXSR_OUTPUT, hw);
+ return TRUE;
+}
+
+static boolean
+nvfx_vertprog_prepare(struct nv30_context *nv30, struct nvfx_vpc *vpc)
+{
+ struct tgsi_parse_context p;
+ int high_const = -1, high_temp = -1, high_addr = -1, nr_imm = 0, i;
+
+ tgsi_parse_init(&p, vpc->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&p)) {
+ const union tgsi_full_token *tok = &p.FullToken;
+
+ tgsi_parse_token(&p);
+ switch(tok->Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ nr_imm++;
+ break;
+ case TGSI_TOKEN_TYPE_DECLARATION:
+ {
+ const struct tgsi_full_declaration *fdec;
+
+ fdec = &p.FullToken.FullDeclaration;
+ switch (fdec->Declaration.File) {
+ case TGSI_FILE_TEMPORARY:
+ if (fdec->Range.Last > high_temp) {
+ high_temp =
+ fdec->Range.Last;
+ }
+ break;
+ case TGSI_FILE_ADDRESS:
+ if (fdec->Range.Last > high_addr) {
+ high_addr =
+ fdec->Range.Last;
+ }
+ break;
+ case TGSI_FILE_CONSTANT:
+ if (fdec->Range.Last > high_const) {
+ high_const =
+ fdec->Range.Last;
+ }
+ break;
+ case TGSI_FILE_OUTPUT:
+ if (!nvfx_vertprog_parse_decl_output(nv30, vpc, fdec))
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ tgsi_parse_free(&p);
+
+ if (nr_imm) {
+ vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_reg));
+ assert(vpc->imm);
+ }
+
+ if (++high_temp) {
+ vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_reg));
+ for (i = 0; i < high_temp; i++)
+ vpc->r_temp[i] = temp(vpc);
+ }
+
+ if (++high_addr) {
+ vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_reg));
+ for (i = 0; i < high_addr; i++)
+ vpc->r_address[i] = nvfx_reg(NVFXSR_TEMP, i);
+ }
+
+ if(++high_const) {
+ vpc->r_const = CALLOC(high_const, sizeof(struct nvfx_reg));
+ for (i = 0; i < high_const; i++)
+ vpc->r_const[i] = constant(vpc, i, 0, 0, 0, 0);
+ }
+
+ vpc->r_temps_discard = 0;
+ return TRUE;
+}
+
+DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_vp, "NVFX_DUMP_VP", FALSE)
+
+boolean
+_nvfx_vertprog_translate(struct nv30_context *nv30, struct nv30_vertprog *vp)
+{
+ struct tgsi_parse_context parse;
+ struct nvfx_vpc *vpc = NULL;
+ struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE, 0));
+ struct util_dynarray insns;
+ int i, ucps;
+
+ vp->translated = FALSE;
+ vp->nr_insns = 0;
+ vp->nr_consts = 0;
+
+ vpc = CALLOC_STRUCT(nvfx_vpc);
+ if (!vpc)
+ return FALSE;
+ vpc->nv30 = nv30;
+ vpc->vp = vp;
+ vpc->pipe = vp->pipe;
+ vpc->info = &vp->info;
+ vpc->cvtx_idx = -1;
+
+ if (!nvfx_vertprog_prepare(nv30, vpc)) {
+ FREE(vpc);
+ return FALSE;
+ }
+
+ /* Redirect post-transform vertex position to a temp if user clip
+ * planes are enabled. We need to append code to the vtxprog
+ * to handle clip planes later.
+ */
+ if (vp->enabled_ucps && vpc->cvtx_idx < 0) {
+ vpc->r_result[vpc->hpos_idx] = temp(vpc);
+ vpc->r_temps_discard = 0;
+ vpc->cvtx_idx = vpc->hpos_idx;
+ }
+
+ util_dynarray_init(&insns);
+
+ tgsi_parse_init(&parse, vp->pipe.tokens);
+ while (!tgsi_parse_end_of_tokens(&parse)) {
+ tgsi_parse_token(&parse);
+
+ switch (parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_IMMEDIATE:
+ {
+ const struct tgsi_full_immediate *imm;
+
+ imm = &parse.FullToken.FullImmediate;
+ assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+ assert(imm->Immediate.NrTokens == 4 + 1);
+ vpc->imm[vpc->nr_imm++] =
+ constant(vpc, -1,
+ imm->u[0].Float,
+ imm->u[1].Float,
+ imm->u[2].Float,
+ imm->u[3].Float);
+ }
+ break;
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
+ {
+ const struct tgsi_full_instruction *finst;
+ unsigned idx = insns.size >> 2;
+ util_dynarray_append(&insns, unsigned, vp->nr_insns);
+ finst = &parse.FullToken.FullInstruction;
+ if (!nvfx_vertprog_parse_instruction(nv30, vpc, idx, finst))
+ goto out;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ util_dynarray_append(&insns, unsigned, vp->nr_insns);
+
+ for(unsigned i = 0; i < vpc->label_relocs.size; i += sizeof(struct nvfx_relocation))
+ {
+ struct nvfx_relocation* label_reloc = (struct nvfx_relocation*)((char*)vpc->label_relocs.data + i);
+ struct nvfx_relocation hw_reloc;
+
+ hw_reloc.location = label_reloc->location;
+ hw_reloc.target = ((unsigned*)insns.data)[label_reloc->target];
+
+ //debug_printf("hw %u -> tgsi %u = hw %u\n", hw_reloc.location, label_reloc->target, hw_reloc.target);
+
+ util_dynarray_append(&vp->branch_relocs, struct nvfx_relocation, hw_reloc);
+ }
+ util_dynarray_fini(&insns);
+ util_dynarray_trim(&vp->branch_relocs);
+
+ /* XXX: what if we add a RET before?! make sure we jump here...*/
+
+ /* Write out HPOS if it was redirected to a temp earlier */
+ if (vpc->r_result[vpc->hpos_idx].type != NVFXSR_OUTPUT) {
+ struct nvfx_reg hpos = nvfx_reg(NVFXSR_OUTPUT,
+ NVFX_VP(INST_DEST_POS));
+ struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->hpos_idx]);
+
+ nvfx_vp_emit(vpc, arith(0, VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none));
+ }
+
+ /* Insert code to handle user clip planes */
+ ucps = vp->enabled_ucps;
+ while (ucps) {
+ int i = ffs(ucps) - 1; ucps &= ~(1 << i);
+ struct nvfx_reg cdst = nvfx_reg(NVFXSR_OUTPUT, NV30_VP_INST_DEST_CLP(i));
+ struct nvfx_src ceqn = nvfx_src(nvfx_reg(NVFXSR_CONST, 512 + i));
+ struct nvfx_src htmp = nvfx_src(vpc->r_result[vpc->cvtx_idx]);
+ unsigned mask;
+
+ if(nv30->is_nv4x)
+ {
+ switch (i) {
+ case 0: case 3: mask = NVFX_VP_MASK_Y; break;
+ case 1: case 4: mask = NVFX_VP_MASK_Z; break;
+ case 2: case 5: mask = NVFX_VP_MASK_W; break;
+ default:
+ NOUVEAU_ERR("invalid clip dist #%d\n", i);
+ goto out;
+ }
+ }
+ else
+ mask = NVFX_VP_MASK_X;
+
+ nvfx_vp_emit(vpc, arith(0, VEC, DP4, cdst, mask, htmp, ceqn, none));
+ }
+
+ if (vpc->vp->nr_insns)
+ vpc->vp->insns[vpc->vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST;
+
+ if(debug_get_option_nvfx_dump_vp())
+ {
+ debug_printf("\n");
+ tgsi_dump(vpc->pipe.tokens, 0);
+
+ debug_printf("\n%s vertex program:\n", nv30->is_nv4x ? "nv4x" : "nv3x");
+ for (i = 0; i < vp->nr_insns; i++)
+ debug_printf("%3u: %08x %08x %08x %08x\n", i, vp->insns[i].data[0], vp->insns[i].data[1], vp->insns[i].data[2], vp->insns[i].data[3]);
+ debug_printf("\n");
+ }
+
+ vp->translated = TRUE;
+
+out:
+ tgsi_parse_free(&parse);
+ if(vpc) {
+ util_dynarray_fini(&vpc->label_relocs);
+ util_dynarray_fini(&vpc->loop_stack);
+ FREE(vpc->r_temp);
+ FREE(vpc->r_address);
+ FREE(vpc->r_const);
+ FREE(vpc->imm);
+ FREE(vpc);
+ }
+
+ return vp->translated;
+}