Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
authorBen Skeggs <skeggsb@gmail.com>
Sun, 13 Jul 2008 15:14:52 +0000 (01:14 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Sun, 13 Jul 2008 15:14:52 +0000 (01:14 +1000)
178 files changed:
configs/default
configs/linux-dri
src/gallium/auxiliary/draw/draw_context.c
src/gallium/drivers/nouveau/nouveau_bo.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_channel.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_class.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_device.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_gldefs.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_grobj.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_notifier.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_push.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_pushbuf.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_resource.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_stateobj.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_util.h [new file with mode: 0644]
src/gallium/drivers/nouveau/nouveau_winsys.h [new file with mode: 0644]
src/gallium/drivers/nv04/Makefile [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_clear.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_context.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_context.h [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_fragprog.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_fragtex.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_miptree.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_prim_vbuf.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_screen.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_screen.h [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_state.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_state.h [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_state_emit.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_surface.c [new file with mode: 0644]
src/gallium/drivers/nv04/nv04_vbo.c [new file with mode: 0644]
src/gallium/drivers/nv10/Makefile [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_clear.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_context.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_context.h [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_fragprog.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_fragtex.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_miptree.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_prim_vbuf.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_screen.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_screen.h [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_state.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_state.h [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_state_emit.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_surface.c [new file with mode: 0644]
src/gallium/drivers/nv10/nv10_vbo.c [new file with mode: 0644]
src/gallium/drivers/nv30/Makefile [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_clear.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_context.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_context.h [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_draw.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_fragprog.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_fragtex.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_miptree.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_query.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_screen.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_screen.h [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_shader.h [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state.h [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_blend.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_emit.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_fb.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_rasterizer.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_scissor.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_stipple.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_viewport.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_state_zsa.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_surface.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_vbo.c [new file with mode: 0644]
src/gallium/drivers/nv30/nv30_vertprog.c [new file with mode: 0644]
src/gallium/drivers/nv40/Makefile [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_clear.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_context.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_context.h [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_draw.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_fragprog.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_fragtex.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_miptree.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_query.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_screen.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_screen.h [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_shader.h [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state.h [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_blend.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_emit.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_fb.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_rasterizer.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_scissor.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_stipple.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_viewport.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_state_zsa.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_surface.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_vbo.c [new file with mode: 0644]
src/gallium/drivers/nv40/nv40_vertprog.c [new file with mode: 0644]
src/gallium/drivers/nv50/Makefile [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_clear.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_context.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_context.h [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_draw.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_miptree.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_program.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_program.h [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_query.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_screen.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_screen.h [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_state.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_state_validate.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_surface.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_tex.c [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_texture.h [new file with mode: 0644]
src/gallium/drivers/nv50/nv50_vbo.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/Makefile [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/.gitignore [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/Makefile [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_context.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/tests/test_surface.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_context.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_context.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_data.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_data.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_defs.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_shader_build.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_shader_build.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_surface.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_surface.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_types.h [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_util.c [new file with mode: 0644]
src/gallium/state_trackers/g3dvl/vl_util.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/Makefile [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_bo.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_channel.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_context.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_context.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_device.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_dma.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_dma.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_dri.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_drmif.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_fence.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_grobj.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_local.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_lock.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_notifier.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_resource.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_screen.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_screen.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_winsys.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nv04_surface.c [new file with mode: 0644]
src/gallium/winsys/dri/nouveau/nv50_surface.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/xsp_winsys.c [new file with mode: 0644]
src/gallium/winsys/g3dvl/xsp_winsys.h [new file with mode: 0644]
src/libXvMC/Makefile [new file with mode: 0644]
src/libXvMC/attributes.c [new file with mode: 0644]
src/libXvMC/block.c [new file with mode: 0644]
src/libXvMC/context.c [new file with mode: 0644]
src/libXvMC/subpicture.c [new file with mode: 0644]
src/libXvMC/surface.c [new file with mode: 0644]
src/libXvMC/tests/.gitignore [new file with mode: 0644]
src/libXvMC/tests/Makefile [new file with mode: 0644]
src/libXvMC/tests/test_blocks.c [new file with mode: 0644]
src/libXvMC/tests/test_context.c [new file with mode: 0644]
src/libXvMC/tests/test_rendering.c [new file with mode: 0644]
src/libXvMC/tests/test_surface.c [new file with mode: 0644]
src/libXvMC/tests/testlib.c [new file with mode: 0644]
src/libXvMC/tests/testlib.h [new file with mode: 0644]
src/mesa/x86-64/glapi_x86-64.S

index ef9c5fda1eba59dc1e0717cc7bf769e1fe5a1e79..8c6ae8484066401cb5b9cf3c5f436ac776e5d195 100644 (file)
@@ -70,7 +70,7 @@ PROGRAM_DIRS = demos redbook samples glsl xdemos
 # Gallium directories and 
 GALLIUM_AUXILIARY_DIRS = draw translate cso_cache pipebuffer tgsi sct rtasm util
 GALLIUM_AUXILIARIES = $(foreach DIR,$(GALLIUM_AUXILIARY_DIRS),$(TOP)/src/gallium/auxiliary/$(DIR)/lib$(DIR).a)
-GALLIUM_DRIVER_DIRS = softpipe i915simple i965simple failover
+GALLIUM_DRIVER_DIRS = softpipe i915simple i965simple nv04 nv10 nv30 nv40 nv50 failover
 GALLIUM_WINSYS_COMMON_DIRS =
 GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVER_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)
 GALLIUM_WINSYS_DIRS = xlib egl_xlib
index 380cd3812ff377b505410bd593e050cbdb274df4..ae9098c49399a390544747c0cde7d2d8dd033a21 100644 (file)
@@ -58,4 +58,4 @@ GALLIUM_WINSYS_COMMON_DIRS = intel_drm
 
 # gamma are missing because they have not been converted to use the new
 # interface.
-DRI_DIRS = intel 
+DRI_DIRS = nouveau
index 2f263cf06a9866c3226002687239485f0c6b2ab8..678c70e478247180f082a2542045d4a6266d3ea4 100644 (file)
@@ -63,8 +63,10 @@ struct draw_context *draw_create( void )
    if (!draw_pt_init( draw ))
       goto fail;
 
+#ifdef PIPE_ARCH_X86
    if (!draw_vs_init( draw ))
       goto fail;
+#endif
 
    return draw;
 
diff --git a/src/gallium/drivers/nouveau/nouveau_bo.h b/src/gallium/drivers/nouveau/nouveau_bo.h
new file mode 100644 (file)
index 0000000..65b1382
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_BO_H__
+#define __NOUVEAU_BO_H__
+
+/* Relocation/Buffer type flags */
+#define NOUVEAU_BO_VRAM  (1 << 0)
+#define NOUVEAU_BO_GART  (1 << 1)
+#define NOUVEAU_BO_RD    (1 << 2)
+#define NOUVEAU_BO_WR    (1 << 3)
+#define NOUVEAU_BO_RDWR  (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
+#define NOUVEAU_BO_MAP   (1 << 4)
+#define NOUVEAU_BO_PIN   (1 << 5)
+#define NOUVEAU_BO_LOW   (1 << 6)
+#define NOUVEAU_BO_HIGH  (1 << 7)
+#define NOUVEAU_BO_OR    (1 << 8)
+#define NOUVEAU_BO_LOCAL (1 << 9)
+#define NOUVEAU_BO_TILED (1 << 10)
+#define NOUVEAU_BO_ZTILE (1 << 11)
+#define NOUVEAU_BO_DUMMY (1 << 31)
+
+struct nouveau_bo {
+       struct nouveau_device *device;
+       uint64_t handle;
+
+       uint64_t size;
+       void *map;
+
+       uint32_t flags;
+       uint64_t offset;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_channel.h b/src/gallium/drivers/nouveau/nouveau_channel.h
new file mode 100644 (file)
index 0000000..cd99a67
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_CHANNEL_H__
+#define __NOUVEAU_CHANNEL_H__
+
+struct nouveau_channel {
+       struct nouveau_device *device;
+       int id;
+
+       struct nouveau_pushbuf *pushbuf;
+
+       struct nouveau_grobj *nullobj;
+       struct nouveau_grobj *vram;
+       struct nouveau_grobj *gart;
+
+       void *user_private;
+       void (*hang_notify)(struct nouveau_channel *);
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_class.h b/src/gallium/drivers/nouveau/nouveau_class.h
new file mode 100644 (file)
index 0000000..749fbf0
--- /dev/null
@@ -0,0 +1,6258 @@
+/*************************************************************************
+
+   Autogenerated file, do not edit !
+
+**************************************************************************
+
+   Copyright (C) 2006-2008 :
+   Dmitry Baryshkov,
+   Laurent Carlier,
+   Matthieu Castet,
+   Dawid Gajownik,
+   Jeremy Kolb,
+   Stephane Loeuillet,
+   Patrice Mandin,
+   Stephane Marchesin,
+   Serge Martin,
+   Sylvain Munaut,
+   Simon Raffeiner,
+   Ben Skeggs,
+   Erik Waling,
+   koala_br,
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, 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.
+
+*************************************************************************/
+
+
+#ifndef NOUVEAU_REG_H
+#define NOUVEAU_REG_H 1
+
+
+#define NV01_ROOT                                                                      0x00000001
+
+
+
+#define NV01_CONTEXT_DMA                                                               0x00000002
+
+
+
+#define NV01_DEVICE                                                                    0x00000003
+
+
+
+#define NV01_TIMER                                                                     0x00000004
+
+#define  NV01_TIMER_SYNCHRONIZE                                                                0x00000100
+#define  NV01_TIMER_STOP_ALARM                                                         0x00000104
+#define  NV01_TIMER_DMA_NOTIFY                                                         0x00000180
+#define  NV01_TIMER_TIME(x)                                                            (0x00000300+((x)*4))
+#define  NV01_TIMER_TIME__SIZE                                                         0x00000002
+#define  NV01_TIMER_ALARM_NOTIFY                                                       0x00000308
+
+
+#define NV_IMAGE_STENCIL                                                               0x00000010
+
+#define  NV_IMAGE_STENCIL_NOTIFY                                                       0x00000104
+#define  NV_IMAGE_STENCIL_DMA_NOTIFY                                                   0x00000180
+#define  NV_IMAGE_STENCIL_IMAGE_OUTPUT                                                 0x00000200
+#define  NV_IMAGE_STENCIL_IMAGE_INPUT(x)                                               (0x00000204+((x)*4))
+#define  NV_IMAGE_STENCIL_IMAGE_INPUT__SIZE                                            0x00000002
+
+
+#define NV_IMAGE_BLEND_AND                                                             0x00000011
+
+#define  NV_IMAGE_BLEND_AND_NOP                                                                0x00000100
+#define  NV_IMAGE_BLEND_AND_NOTIFY                                                     0x00000104
+#define  NV_IMAGE_BLEND_AND_DMA_NOTIFY                                                 0x00000180
+#define  NV_IMAGE_BLEND_AND_IMAGE_OUTPUT                                               0x00000200
+#define  NV_IMAGE_BLEND_AND_BETA_INPUT                                                 0x00000204
+#define  NV_IMAGE_BLEND_AND_IMAGE_INPUT                                                        0x00000208
+
+
+#define NV01_CONTEXT_BETA1                                                             0x00000012
+
+#define  NV01_CONTEXT_BETA1_NOP                                                                0x00000100
+#define  NV01_CONTEXT_BETA1_NOTIFY                                                     0x00000104
+#define  NV01_CONTEXT_BETA1_DMA_NOTIFY                                                 0x00000180
+#define  NV01_CONTEXT_BETA1_BETA_1D31                                                  0x00000300
+
+
+#define NV_IMAGE_ROP_AND                                                               0x00000013
+
+#define  NV_IMAGE_ROP_AND_NOTIFY                                                       0x00000104
+#define  NV_IMAGE_ROP_AND_DMA_NOTIFY                                                   0x00000180
+#define  NV_IMAGE_ROP_AND_IMAGE_OUTPUT                                                 0x00000200
+#define  NV_IMAGE_ROP_AND_ROP_INPUT                                                    0x00000204
+#define  NV_IMAGE_ROP_AND_IMAGE_INPUT(x)                                               (0x00000208+((x)*4))
+#define  NV_IMAGE_ROP_AND_IMAGE_INPUT__SIZE                                            0x00000002
+
+
+#define NV_IMAGE_COLOR_KEY                                                             0x00000015
+
+
+
+#define NV01_CONTEXT_COLOR_KEY                                                         0x00000017
+
+#define  NV01_CONTEXT_COLOR_KEY_NOP                                                    0x00000100
+#define  NV01_CONTEXT_COLOR_KEY_NOTIFY                                                 0x00000104
+#define  NV01_CONTEXT_COLOR_KEY_DMA_NOTIFY                                             0x00000180
+#define  NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT                                           0x00000300
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16A8Y8                                  0x00000001
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X24Y8                                    0x00000002
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16A1R5G5B5                              0x00000003
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X17R5G5B5                                        0x00000004
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A8R8G8B8                                 0x00000005
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X8R8G8B8                                 0x00000006
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A16Y16                                   0x00000007
+#define   NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16Y16                                   0x00000008
+#define  NV01_CONTEXT_COLOR_KEY_COLOR                                                  0x00000304
+
+
+#define NV01_CONTEXT_PATTERN                                                           0x00000018
+
+#define  NV01_CONTEXT_PATTERN_NOP                                                      0x00000100
+#define  NV01_CONTEXT_PATTERN_NOTIFY                                                   0x00000104
+#define  NV01_CONTEXT_PATTERN_DMA_NOTIFY                                               0x00000180
+#define  NV01_CONTEXT_PATTERN_COLOR_FORMAT                                             0x00000300
+#define  NV01_CONTEXT_PATTERN_MONOCHROME_FORMAT                                                0x00000304
+#define  NV01_CONTEXT_PATTERN_SHAPE                                                    0x00000308
+#define  NV01_CONTEXT_PATTERN_COLOR(x)                                                 (0x00000310+((x)*4))
+#define  NV01_CONTEXT_PATTERN_COLOR__SIZE                                              0x00000002
+#define  NV01_CONTEXT_PATTERN_PATTERN(x)                                               (0x00000318+((x)*4))
+#define  NV01_CONTEXT_PATTERN_PATTERN__SIZE                                            0x00000002
+
+
+#define NV01_CONTEXT_CLIP_RECTANGLE                                                    0x00000019
+
+#define  NV01_CONTEXT_CLIP_RECTANGLE_NOP                                               0x00000100
+#define  NV01_CONTEXT_CLIP_RECTANGLE_NOTIFY                                            0x00000104
+#define  NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY                                                0x00000180
+#define  NV01_CONTEXT_CLIP_RECTANGLE_POINT                                             0x00000300
+#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_X_SHIFT                                    0
+#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_X_MASK                                     0x0000ffff
+#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y_SHIFT                                    16
+#define   NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y_MASK                                     0xffff0000
+#define  NV01_CONTEXT_CLIP_RECTANGLE_SIZE                                              0x00000304
+#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W_SHIFT                                     0
+#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W_MASK                                      0x0000ffff
+#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H_SHIFT                                     16
+#define   NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H_MASK                                      0xffff0000
+
+
+#define NV01_RENDER_SOLID_LINE                                                         0x0000001c
+
+#define  NV01_RENDER_SOLID_LINE_NOP                                                    0x00000100
+#define  NV01_RENDER_SOLID_LINE_NOTIFY                                                 0x00000104
+#define  NV01_RENDER_SOLID_LINE_PATCH                                                  0x0000010c
+#define  NV01_RENDER_SOLID_LINE_DMA_NOTIFY                                             0x00000180
+#define  NV01_RENDER_SOLID_LINE_CLIP_RECTANGLE                                         0x00000184
+#define  NV01_RENDER_SOLID_LINE_PATTERN                                                        0x00000188
+#define  NV01_RENDER_SOLID_LINE_ROP                                                    0x0000018c
+#define  NV01_RENDER_SOLID_LINE_BETA1                                                  0x00000190
+#define  NV01_RENDER_SOLID_LINE_SURFACE                                                        0x00000194
+#define  NV01_RENDER_SOLID_LINE_OPERATION                                              0x000002fc
+#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_AND                                 0x00000000
+#define   NV01_RENDER_SOLID_LINE_OPERATION_ROP_AND                                     0x00000001
+#define   NV01_RENDER_SOLID_LINE_OPERATION_BLEND_AND                                   0x00000002
+#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY                                     0x00000003
+#define   NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_PREMULT                             0x00000004
+#define   NV01_RENDER_SOLID_LINE_OPERATION_BLEND_PREMULT                               0x00000005
+#define  NV01_RENDER_SOLID_LINE_COLOR_FORMAT                                           0x00000300
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16A8Y8                                  0x00000001
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X24Y8                                    0x00000002
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16A1R5G5B5                              0x00000003
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X17R5G5B5                                        0x00000004
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A8R8G8B8                                 0x00000005
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X8R8G8B8                                 0x00000006
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A16Y16                                   0x00000007
+#define   NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16Y16                                   0x00000008
+#define  NV01_RENDER_SOLID_LINE_COLOR                                                  0x00000304
+#define  NV01_RENDER_SOLID_LINE_LINE_POINT0(x)                                         (0x00000400+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_LINE_POINT0__SIZE                                      0x00000010
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_X_SHIFT                                   0
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_X_MASK                                    0x0000ffff
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_Y_SHIFT                                   16
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT0_Y_MASK                                    0xffff0000
+#define  NV01_RENDER_SOLID_LINE_LINE_POINT1(x)                                         (0x00000404+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_LINE_POINT1__SIZE                                      0x00000010
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_X_SHIFT                                   0
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_X_MASK                                    0x0000ffff
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_Y_SHIFT                                   16
+#define   NV01_RENDER_SOLID_LINE_LINE_POINT1_Y_MASK                                    0xffff0000
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_X(x)                                     (0x00000480+((x)*16))
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_X__SIZE                                  0x00000010
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y(x)                                     (0x00000484+((x)*16))
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y__SIZE                                  0x00000010
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_X(x)                                     (0x00000488+((x)*16))
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_X__SIZE                                  0x00000010
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y(x)                                     (0x0000048c+((x)*16))
+#define  NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y__SIZE                                  0x00000010
+#define  NV01_RENDER_SOLID_LINE_POLYLINE(x)                                            (0x00000500+((x)*4))
+#define  NV01_RENDER_SOLID_LINE_POLYLINE__SIZE                                         0x00000020
+#define   NV01_RENDER_SOLID_LINE_POLYLINE_X_SHIFT                                      0
+#define   NV01_RENDER_SOLID_LINE_POLYLINE_X_MASK                                       0x0000ffff
+#define   NV01_RENDER_SOLID_LINE_POLYLINE_Y_SHIFT                                      16
+#define   NV01_RENDER_SOLID_LINE_POLYLINE_Y_MASK                                       0xffff0000
+#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X(x)                                  (0x00000580+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X__SIZE                               0x00000010
+#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y(x)                                  (0x00000584+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y__SIZE                               0x00000010
+#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR(x)                                     (0x00000600+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR__SIZE                                  0x00000010
+#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT(x)                                     (0x00000604+((x)*8))
+#define  NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT__SIZE                                  0x00000010
+#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X_SHIFT                               0
+#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X_MASK                                        0x0000ffff
+#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y_SHIFT                               16
+#define   NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y_MASK                                        0xffff0000
+
+
+#define NV01_RENDER_SOLID_TRIANGLE                                                     0x0000001d
+
+#define  NV01_RENDER_SOLID_TRIANGLE_NOP                                                        0x00000100
+#define  NV01_RENDER_SOLID_TRIANGLE_NOTIFY                                             0x00000104
+#define  NV01_RENDER_SOLID_TRIANGLE_PATCH                                              0x0000010c
+#define  NV01_RENDER_SOLID_TRIANGLE_DMA_NOTIFY                                         0x00000180
+#define  NV01_RENDER_SOLID_TRIANGLE_CLIP_RECTANGLE                                     0x00000184
+#define  NV01_RENDER_SOLID_TRIANGLE_PATTERN                                            0x00000188
+#define  NV01_RENDER_SOLID_TRIANGLE_ROP                                                        0x0000018c
+#define  NV01_RENDER_SOLID_TRIANGLE_BETA1                                              0x00000190
+#define  NV01_RENDER_SOLID_TRIANGLE_SURFACE                                            0x00000194
+#define  NV01_RENDER_SOLID_TRIANGLE_OPERATION                                          0x000002fc
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_AND                             0x00000000
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_ROP_AND                                 0x00000001
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_AND                               0x00000002
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY                                 0x00000003
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_PREMULT                         0x00000004
+#define   NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_PREMULT                           0x00000005
+#define  NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT                                       0x00000300
+#define  NV01_RENDER_SOLID_TRIANGLE_COLOR                                              0x00000304
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0                                    0x00000310
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X_SHIFT                           0
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X_MASK                            0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y_SHIFT                           16
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y_MASK                            0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1                                    0x00000314
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X_SHIFT                           0
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X_MASK                            0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y_SHIFT                           16
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y_MASK                            0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2                                    0x00000318
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X_SHIFT                           0
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X_MASK                            0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y_SHIFT                           16
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y_MASK                            0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_X                                        0x00000320
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_Y                                        0x00000324
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_X                                        0x00000328
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_Y                                        0x0000032c
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_X                                        0x00000330
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_Y                                        0x00000334
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH(x)                                         (0x00000400+((x)*4))
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH__SIZE                                      0x00000020
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X_SHIFT                                   0
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X_MASK                                    0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y_SHIFT                                   16
+#define   NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y_MASK                                    0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X(x)                               (0x00000480+((x)*8))
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X__SIZE                            0x00000010
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y(x)                               (0x00000484+((x)*8))
+#define  NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y__SIZE                            0x00000010
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR(x)                                 (0x00000500+((x)*16))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR__SIZE                              0x00000008
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0(x)                                        (0x00000504+((x)*16))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0__SIZE                             0x00000008
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X_SHIFT                          0
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X_MASK                           0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y_SHIFT                          16
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y_MASK                           0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1(x)                                        (0x00000508+((x)*16))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1__SIZE                             0x00000008
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X_SHIFT                          0
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X_MASK                           0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y_SHIFT                          16
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y_MASK                           0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2(x)                                        (0x0000050c+((x)*16))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2__SIZE                             0x00000008
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X_SHIFT                          0
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X_MASK                           0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y_SHIFT                          16
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y_MASK                           0xffff0000
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR(x)                                  (0x00000580+((x)*8))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR__SIZE                               0x00000010
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT(x)                                  (0x00000584+((x)*8))
+#define  NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT__SIZE                               0x00000010
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X_SHIFT                            0
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X_MASK                             0x0000ffff
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y_SHIFT                            16
+#define   NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y_MASK                             0xffff0000
+
+
+#define NV01_RENDER_SOLID_RECTANGLE                                                    0x0000001e
+
+#define  NV01_RENDER_SOLID_RECTANGLE_NOP                                               0x00000100
+#define  NV01_RENDER_SOLID_RECTANGLE_NOTIFY                                            0x00000104
+#define  NV01_RENDER_SOLID_RECTANGLE_PATCH                                             0x0000010c
+#define  NV01_RENDER_SOLID_RECTANGLE_DMA_NOTIFY                                                0x00000180
+#define  NV01_RENDER_SOLID_RECTANGLE_CLIP_RECTANGLE                                    0x00000184
+#define  NV01_RENDER_SOLID_RECTANGLE_PATTERN                                           0x00000188
+#define  NV01_RENDER_SOLID_RECTANGLE_ROP                                               0x0000018c
+#define  NV01_RENDER_SOLID_RECTANGLE_BETA1                                             0x00000190
+#define  NV01_RENDER_SOLID_RECTANGLE_SURFACE                                           0x00000194
+#define  NV01_RENDER_SOLID_RECTANGLE_OPERATION                                         0x000002fc
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_AND                            0x00000000
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_ROP_AND                                        0x00000001
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_AND                              0x00000002
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY                                        0x00000003
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_PREMULT                                0x00000004
+#define   NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_PREMULT                          0x00000005
+#define  NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT                                      0x00000300
+#define  NV01_RENDER_SOLID_RECTANGLE_COLOR                                             0x00000304
+#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT(x)                                        (0x00000400+((x)*8))
+#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT__SIZE                             0x00000010
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X_SHIFT                          0
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X_MASK                           0x0000ffff
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y_SHIFT                          16
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y_MASK                           0xffff0000
+#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE(x)                                 (0x00000404+((x)*8))
+#define  NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE__SIZE                              0x00000010
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W_SHIFT                           0
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W_MASK                            0x0000ffff
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H_SHIFT                           16
+#define   NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H_MASK                            0xffff0000
+
+
+#define NV01_IMAGE_BLIT                                                                        0x0000001f
+
+#define  NV01_IMAGE_BLIT_NOP                                                           0x00000100
+#define  NV01_IMAGE_BLIT_NOTIFY                                                                0x00000104
+#define  NV01_IMAGE_BLIT_PATCH                                                         0x0000010c
+#define  NV01_IMAGE_BLIT_DMA_NOTIFY                                                    0x00000180
+#define  NV01_IMAGE_BLIT_COLOR_KEY                                                     0x00000184
+#define  NV01_IMAGE_BLIT_CLIP_RECTANGLE                                                        0x00000188
+#define  NV01_IMAGE_BLIT_PATTERN                                                       0x0000018c
+#define  NV01_IMAGE_BLIT_ROP                                                           0x00000190
+#define  NV01_IMAGE_BLIT_BETA1                                                         0x00000194
+#define  NV01_IMAGE_BLIT_SURFACE                                                       0x0000019c
+#define  NV01_IMAGE_BLIT_OPERATION                                                     0x000002fc
+#define  NV01_IMAGE_BLIT_IMAGE_INPUT                                                   0x00000204
+#define  NV01_IMAGE_BLIT_POINT_IN                                                      0x00000300
+#define   NV01_IMAGE_BLIT_POINT_IN_X_SHIFT                                             0
+#define   NV01_IMAGE_BLIT_POINT_IN_X_MASK                                              0x0000ffff
+#define   NV01_IMAGE_BLIT_POINT_IN_Y_SHIFT                                             16
+#define   NV01_IMAGE_BLIT_POINT_IN_Y_MASK                                              0xffff0000
+#define  NV01_IMAGE_BLIT_POINT_OUT                                                     0x00000304
+#define   NV01_IMAGE_BLIT_POINT_OUT_X_SHIFT                                            0
+#define   NV01_IMAGE_BLIT_POINT_OUT_X_MASK                                             0x0000ffff
+#define   NV01_IMAGE_BLIT_POINT_OUT_Y_SHIFT                                            16
+#define   NV01_IMAGE_BLIT_POINT_OUT_Y_MASK                                             0xffff0000
+#define  NV01_IMAGE_BLIT_SIZE                                                          0x00000308
+#define   NV01_IMAGE_BLIT_SIZE_W_SHIFT                                                 0
+#define   NV01_IMAGE_BLIT_SIZE_W_MASK                                                  0x0000ffff
+#define   NV01_IMAGE_BLIT_SIZE_H_SHIFT                                                 16
+#define   NV01_IMAGE_BLIT_SIZE_H_MASK                                                  0xffff0000
+
+
+#define NV01_IMAGE_FROM_CPU                                                            0x00000021
+
+#define  NV01_IMAGE_FROM_CPU_NOP                                                       0x00000100
+#define  NV01_IMAGE_FROM_CPU_NOTIFY                                                    0x00000104
+#define  NV01_IMAGE_FROM_CPU_PATCH                                                     0x0000010c
+#define  NV01_IMAGE_FROM_CPU_DMA_NOTIFY                                                        0x00000180
+#define  NV01_IMAGE_FROM_CPU_COLOR_KEY                                                 0x00000184
+#define  NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE                                            0x00000188
+#define  NV01_IMAGE_FROM_CPU_PATTERN                                                   0x0000018c
+#define  NV01_IMAGE_FROM_CPU_ROP                                                       0x00000190
+#define  NV01_IMAGE_FROM_CPU_BETA1                                                     0x00000194
+#define  NV01_IMAGE_FROM_CPU_SURFACE                                                   0x00000198
+#define  NV01_IMAGE_FROM_CPU_OPERATION                                                 0x000002fc
+#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_AND                                    0x00000000
+#define   NV01_IMAGE_FROM_CPU_OPERATION_ROP_AND                                                0x00000001
+#define   NV01_IMAGE_FROM_CPU_OPERATION_BLEND_AND                                      0x00000002
+#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY                                                0x00000003
+#define   NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_PREMULT                                        0x00000004
+#define   NV01_IMAGE_FROM_CPU_OPERATION_BLEND_PREMULT                                  0x00000005
+#define  NV01_IMAGE_FROM_CPU_COLOR_FORMAT                                              0x00000300
+#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_Y8                                          0x00000001
+#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A1R5G5B5                                    0x00000002
+#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X1R5G5B5                                    0x00000003
+#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A8R8G8B8                                    0x00000004
+#define   NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X8R8G8B8                                    0x00000005
+#define  NV01_IMAGE_FROM_CPU_POINT                                                     0x00000304
+#define   NV01_IMAGE_FROM_CPU_POINT_X_SHIFT                                            0
+#define   NV01_IMAGE_FROM_CPU_POINT_X_MASK                                             0x0000ffff
+#define   NV01_IMAGE_FROM_CPU_POINT_Y_SHIFT                                            16
+#define   NV01_IMAGE_FROM_CPU_POINT_Y_MASK                                             0xffff0000
+#define  NV01_IMAGE_FROM_CPU_SIZE_OUT                                                  0x00000308
+#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_W_SHIFT                                         0
+#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_W_MASK                                          0x0000ffff
+#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_H_SHIFT                                         16
+#define   NV01_IMAGE_FROM_CPU_SIZE_OUT_H_MASK                                          0xffff0000
+#define  NV01_IMAGE_FROM_CPU_SIZE_IN                                                   0x0000030c
+#define   NV01_IMAGE_FROM_CPU_SIZE_IN_W_SHIFT                                          0
+#define   NV01_IMAGE_FROM_CPU_SIZE_IN_W_MASK                                           0x0000ffff
+#define   NV01_IMAGE_FROM_CPU_SIZE_IN_H_SHIFT                                          16
+#define   NV01_IMAGE_FROM_CPU_SIZE_IN_H_MASK                                           0xffff0000
+#define  NV01_IMAGE_FROM_CPU_COLOR(x)                                                  (0x00000400+((x)*4))
+#define  NV01_IMAGE_FROM_CPU_COLOR__SIZE                                               0x00000020
+
+
+#define NV01_NULL                                                                      0x00000030
+
+
+
+#define NV03_STRETCHED_IMAGE_FROM_CPU                                                  0x00000036
+
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_NOP                                             0x00000100
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_NOTIFY                                          0x00000104
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_PATCH                                           0x0000010c
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_DMA_NOTIFY                                      0x00000180
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_KEY                                       0x00000184
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_PATTERN                                         0x00000188
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_ROP                                             0x0000018c
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_BETA1                                           0x00000190
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_SURFACE                                         0x00000194
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_OPERATION                                       0x000002fc
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_FORMAT                                    0x00000300
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN                                         0x00000304
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W_SHIFT                                        0
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W_MASK                                 0x0000ffff
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H_SHIFT                                        16
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H_MASK                                 0xffff0000
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_DX_DU                                           0x00000308
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_DY_DV                                           0x0000030c
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT                                      0x00000310
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X_SHIFT                             0
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X_MASK                              0x0000ffff
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y_SHIFT                             16
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y_MASK                              0xffff0000
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE                                       0x00000314
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W_SHIFT                              0
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W_MASK                               0x0000ffff
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H_SHIFT                              16
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H_MASK                               0xffff0000
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4                                       0x00000318
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X_SHIFT                              0
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X_MASK                               0x0000ffff
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y_SHIFT                              16
+#define   NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y_MASK                               0xffff0000
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR(x)                                                (0x00000400+((x)*4))
+#define  NV03_STRETCHED_IMAGE_FROM_CPU_COLOR__SIZE                                     0x00000020
+
+
+#define NV03_SCALED_IMAGE_FROM_MEMORY                                                  0x00000037
+
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_NOP                                             0x00000100
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_NOTIFY                                          0x00000104
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY                                      0x00000180
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE                                       0x00000184
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_PATTERN                                         0x00000188
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_ROP                                             0x0000018c
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_BETA1                                           0x00000190
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_SURFACE                                         0x00000194
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT                                    0x00000300
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5                          0x00000001
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5                          0x00000002
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8                          0x00000003
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8                          0x00000004
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8                                0x00000005
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8                                0x00000006
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5                            0x00000007
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8                                        0x00000008
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8                               0x00000009
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION                                       0x00000304
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_AND                          0x00000000
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_ROP_AND                              0x00000001
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_AND                            0x00000002
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY                              0x00000003
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_PREMULT                      0x00000004
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_PREMULT                                0x00000005
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT                                      0x00000308
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_SHIFT                             0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_MASK                              0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT                             16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_MASK                              0xffff0000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE                                       0x0000030c
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_SHIFT                              0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_MASK                               0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT                              16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_MASK                               0xffff0000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT                                 0x00000310
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_X_SHIFT                                0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_X_MASK                         0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_Y_SHIFT                                16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_POINT_Y_MASK                         0xffff0000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE                                  0x00000314
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_W_SHIFT                         0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_W_MASK                          0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_H_SHIFT                         16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_OUT_SIZE_H_MASK                          0xffff0000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_DELTA_DU_DX                                     0x00000318
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_DELTA_DV_DY                                     0x0000031c
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE                                   0x00000400
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_W_SHIFT                          0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_W_MASK                           0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_H_SHIFT                          16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_SIZE_H_MASK                           0xffff0000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT                                 0x00000404
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_PITCH_SHIFT                    0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_PITCH_MASK                     0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_SHIFT                   16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_MASK                    0x00ff0000
+#define    NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_CENTER                 0x00010000
+#define    NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_ORIGIN_CORNER                 0x00020000
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_INTERPOLATOR_SHIFT             24
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_FORMAT_INTERPOLATOR_MASK              0xff000000
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_OFFSET                                 0x00000408
+#define  NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT                                  0x0000040c
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_U_SHIFT                         0
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_U_MASK                          0x0000ffff
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_V_SHIFT                         16
+#define   NV03_SCALED_IMAGE_FROM_MEMORY_IMAGE_IN_POINT_V_MASK                          0xffff0000
+
+
+#define NV04_DVD_SUBPICTURE                                                            0x00000038
+
+#define  NV04_DVD_SUBPICTURE_NOP                                                       0x00000100
+#define  NV04_DVD_SUBPICTURE_NOTIFY                                                    0x00000104
+#define  NV04_DVD_SUBPICTURE_WAIT_FOR_IDLE                                             0x00000108
+#define  NV04_DVD_SUBPICTURE_DMA_NOTIFY                                                        0x00000180
+#define  NV04_DVD_SUBPICTURE_DMA_OVERLAY                                               0x00000184
+#define  NV04_DVD_SUBPICTURE_DMA_IMAGEIN                                               0x00000188
+#define  NV04_DVD_SUBPICTURE_DMA_IMAGEOUT                                              0x0000018c
+#define  NV04_DVD_SUBPICTURE_IMAGEOUT_POINT                                            0x00000300
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_X_SHIFT                                   0
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_X_MASK                                    0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_Y_SHIFT                                   16
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_POINT_Y_MASK                                    0xffff0000
+#define  NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE                                             0x00000304
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_W_SHIFT                                    0
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_W_MASK                                     0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_H_SHIFT                                    16
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_SIZE_H_MASK                                     0xffff0000
+#define  NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT                                           0x00000308
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_PITCH_SHIFT                              0
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_PITCH_MASK                               0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_COLOR_SHIFT                              16
+#define   NV04_DVD_SUBPICTURE_IMAGEOUT_FORMAT_COLOR_MASK                               0xffff0000
+#define  NV04_DVD_SUBPICTURE_IMAGEOUT_OFFSET                                           0x0000030c
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_DELTA_DU_DX                                       0x00000310
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_DELTA_DV_DY                                       0x00000314
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_SIZE                                              0x00000318
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_W_SHIFT                                     0
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_W_MASK                                      0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_H_SHIFT                                     16
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_SIZE_H_MASK                                      0xffff0000
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT                                            0x0000031c
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_PITCH_SHIFT                               0
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_PITCH_MASK                                        0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_COLOR_SHIFT                               16
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_FORMAT_COLOR_MASK                                        0xffff0000
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_OFFSET                                            0x00000320
+#define  NV04_DVD_SUBPICTURE_IMAGEIN_POINT                                             0x00000324
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_U_SHIFT                                    0
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_U_MASK                                     0x0000ffff
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_V_SHIFT                                    16
+#define   NV04_DVD_SUBPICTURE_IMAGEIN_POINT_V_MASK                                     0xffff0000
+#define  NV04_DVD_SUBPICTURE_OVERLAY_DELTA_DU_DX                                       0x00000328
+#define  NV04_DVD_SUBPICTURE_OVERLAY_DELTA_DV_DY                                       0x0000032c
+#define  NV04_DVD_SUBPICTURE_OVERLAY_SIZE                                              0x00000330
+#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_W_SHIFT                                     0
+#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_W_MASK                                      0x0000ffff
+#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_H_SHIFT                                     16
+#define   NV04_DVD_SUBPICTURE_OVERLAY_SIZE_H_MASK                                      0xffff0000
+#define  NV04_DVD_SUBPICTURE_OVERLAY_FORMAT                                            0x00000334
+#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_PITCH_SHIFT                               0
+#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_PITCH_MASK                                        0x0000ffff
+#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_COLOR_SHIFT                               16
+#define   NV04_DVD_SUBPICTURE_OVERLAY_FORMAT_COLOR_MASK                                        0xffff0000
+#define  NV04_DVD_SUBPICTURE_OVERLAY_OFFSET                                            0x00000338
+#define  NV04_DVD_SUBPICTURE_OVERLAY_POINT                                             0x0000033c
+#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_U_SHIFT                                    0
+#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_U_MASK                                     0x0000ffff
+#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_V_SHIFT                                    16
+#define   NV04_DVD_SUBPICTURE_OVERLAY_POINT_V_MASK                                     0xffff0000
+
+
+#define NV04_MEMORY_TO_MEMORY_FORMAT                                                   0x00000039
+
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_NOP                                              0x00000100
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY                                           0x00000104
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY                                       0x00000180
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN                                    0x00000184
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT                                   0x00000188
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN                                                0x0000030c
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT                                       0x00000310
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN                                         0x00000314
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT                                                0x00000318
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN                                   0x0000031c
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_LINE_COUNT                                       0x00000320
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT                                           0x00000324
+#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_INPUT_INC_SHIFT                          0
+#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_INPUT_INC_MASK                           0x0000000f
+#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_OUTPUT_INC_SHIFT                         8
+#define   NV04_MEMORY_TO_MEMORY_FORMAT_FORMAT_OUTPUT_INC_MASK                          0x00000f00
+#define  NV04_MEMORY_TO_MEMORY_FORMAT_BUF_NOTIFY                                       0x00000328
+
+
+#define NV01_MEMORY_LOCAL_BANKED                                                       0x0000003d
+
+
+
+#define NV01_MAPPING_SYSTEM                                                            0x0000003e
+
+
+
+#define NV03_MEMORY_LOCAL_CURSOR                                                       0x0000003f
+
+
+
+#define NV01_MEMORY_LOCAL_LINEAR                                                       0x00000040
+
+
+
+#define NV01_MAPPING_LOCAL                                                             0x00000041
+
+
+
+#define NV04_CONTEXT_SURFACES_2D                                                       0x00000042
+
+#define  NV04_CONTEXT_SURFACES_2D_NOP                                                  0x00000100
+#define  NV04_CONTEXT_SURFACES_2D_NOTIFY                                               0x00000104
+#define  NV04_CONTEXT_SURFACES_2D_PM_TRIGGER                                           0x00000140
+#define  NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY                                           0x00000180
+#define  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE                                     0x00000184
+#define  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_DESTIN                                     0x00000188
+#define  NV04_CONTEXT_SURFACES_2D_FORMAT                                               0x00000300
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y8                                           0x00000001
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_Z1R5G5B5                            0x00000002
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5                            0x00000003
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5                                       0x00000004
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y16                                          0x00000005
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8                            0x00000006
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8                            0x00000007
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_Z1A7R8G8B8                                0x00000008
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_X1A7R8G8B8                                0x00000009
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8                                     0x0000000a
+#define   NV04_CONTEXT_SURFACES_2D_FORMAT_Y32                                          0x0000000b
+#define  NV04_CONTEXT_SURFACES_2D_PITCH                                                        0x00000304
+#define   NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE_SHIFT                                  0
+#define   NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE_MASK                                   0x0000ffff
+#define   NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN_SHIFT                                  16
+#define   NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN_MASK                                   0xffff0000
+#define  NV04_CONTEXT_SURFACES_2D_OFFSET_SOURCE                                                0x00000308
+#define  NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN                                                0x0000030c
+
+
+#define NV03_CONTEXT_ROP                                                               0x00000043
+
+#define  NV03_CONTEXT_ROP_NOP                                                          0x00000100
+#define  NV03_CONTEXT_ROP_NOTIFY                                                       0x00000104
+#define  NV03_CONTEXT_ROP_DMA_NOTIFY                                                   0x00000180
+#define  NV03_CONTEXT_ROP_ROP                                                          0x00000300
+#define   NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_SHIFT                                      0
+#define   NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_MASK                                       0x0000000f
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_CLEAR                                     0x00000000
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NOR                                       0x00000001
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND_INVERTED                              0x00000002
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_COPY_INVERTED                             0x00000003
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND_REVERSE                               0x00000004
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_INVERT                                    0x00000005
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_XOR                                       0x00000006
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NAND                                      0x00000007
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_AND                                       0x00000008
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_EQUI                                      0x00000009
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_NOOP                                      0x0000000a
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR_INVERTED                               0x0000000b
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_COPY                                      0x0000000c
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR_REVERSE                                        0x0000000d
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_OR                                                0x0000000e
+#define    NV03_CONTEXT_ROP_ROP_DST_LOGIC_OP_SET                                       0x0000000f
+#define   NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_SHIFT                                      4
+#define   NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_MASK                                       0x000000f0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_CLEAR                                     0x00000000
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NOR                                       0x00000010
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND_INVERTED                              0x00000020
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_COPY_INVERTED                             0x00000030
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND_REVERSE                               0x00000040
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_INVERT                                    0x00000050
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_XOR                                       0x00000060
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NAND                                      0x00000070
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_AND                                       0x00000080
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_EQUI                                      0x00000090
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_NOOP                                      0x000000a0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR_INVERTED                               0x000000b0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_COPY                                      0x000000c0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR_REVERSE                                        0x000000d0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_OR                                                0x000000e0
+#define    NV03_CONTEXT_ROP_ROP_SRC_LOGIC_OP_SET                                       0x000000f0
+
+
+#define NV04_IMAGE_PATTERN                                                             0x00000044
+
+#define  NV04_IMAGE_PATTERN_NOP                                                                0x00000100
+#define  NV04_IMAGE_PATTERN_NOTIFY                                                     0x00000104
+#define  NV04_IMAGE_PATTERN_DMA_NOTIFY                                                 0x00000180
+#define  NV04_IMAGE_PATTERN_COLOR_FORMAT                                               0x00000300
+#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_A16R5G6B5                                    0x00000001
+#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_X16A1R5G5B5                                  0x00000002
+#define   NV04_IMAGE_PATTERN_COLOR_FORMAT_A8R8G8B8                                     0x00000003
+#define  NV04_IMAGE_PATTERN_MONOCHROME_FORMAT                                          0x00000304
+#define   NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6                                    0x00000001
+#define   NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE                                      0x00000002
+#define  NV04_IMAGE_PATTERN_MONOCHROME_SHAPE                                           0x00000308
+#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8                                      0x00000000
+#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_64X1                                     0x00000001
+#define   NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_1X64                                     0x00000002
+#define  NV04_IMAGE_PATTERN_PATTERN_SELECT                                             0x0000030c
+#define   NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO                                       0x00000001
+#define   NV04_IMAGE_PATTERN_PATTERN_SELECT_COLOR                                      0x00000002
+#define  NV04_IMAGE_PATTERN_MONOCHROME_COLOR0                                          0x00000310
+#define  NV04_IMAGE_PATTERN_MONOCHROME_COLOR1                                          0x00000314
+#define  NV04_IMAGE_PATTERN_MONOCHROME_PATTERN0                                                0x00000318
+#define  NV04_IMAGE_PATTERN_MONOCHROME_PATTERN1                                                0x0000031c
+#define  NV04_IMAGE_PATTERN_PATTERN_Y8(x)                                              (0x00000400+((x)*4))
+#define  NV04_IMAGE_PATTERN_PATTERN_Y8__SIZE                                           0x00000010
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y0_SHIFT                                       0
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y0_MASK                                                0x000000ff
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y1_SHIFT                                       8
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y1_MASK                                                0x0000ff00
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y2_SHIFT                                       16
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y2_MASK                                                0x00ff0000
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y3_SHIFT                                       24
+#define   NV04_IMAGE_PATTERN_PATTERN_Y8_Y3_MASK                                                0xff000000
+#define  NV04_IMAGE_PATTERN_PATTERN_R5G6B5(x)                                          (0x00000500+((x)*4))
+#define  NV04_IMAGE_PATTERN_PATTERN_R5G6B5__SIZE                                       0x00000020
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0_SHIFT                                   0
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0_MASK                                    0x0000001f
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0_SHIFT                                   5
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0_MASK                                    0x000007e0
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0_SHIFT                                   11
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0_MASK                                    0x0000f800
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1_SHIFT                                   16
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1_MASK                                    0x001f0000
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1_SHIFT                                   21
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1_MASK                                    0x07e00000
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1_SHIFT                                   27
+#define   NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1_MASK                                    0xf8000000
+#define  NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5(x)                                                (0x00000600+((x)*4))
+#define  NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5__SIZE                                     0x00000020
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0_SHIFT                                 0
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0_MASK                                  0x0000001f
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0_SHIFT                                 5
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0_MASK                                  0x000003e0
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0_SHIFT                                 10
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0_MASK                                  0x00007c00
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1_SHIFT                                 16
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1_MASK                                  0x001f0000
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1_SHIFT                                 21
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1_MASK                                  0x03e00000
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1_SHIFT                                 26
+#define   NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1_MASK                                  0x7c000000
+#define  NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8(x)                                                (0x00000700+((x)*4))
+#define  NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8__SIZE                                     0x00000040
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B_SHIFT                                  0
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B_MASK                                   0x000000ff
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G_SHIFT                                  8
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G_MASK                                   0x0000ff00
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R_SHIFT                                  16
+#define   NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R_MASK                                   0x00ff0000
+
+
+#define NV03_VIDEO_LUT_CURSOR_DAC                                                      0x00000046
+
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SYNCHRONIZE                                         0x00000100
+#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_IMAGE                                          0x00000104
+#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_CURSOR                                         0x00000108
+#define  NV03_VIDEO_LUT_CURSOR_DAC_STOP_DAC                                            0x0000010c
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_NOTIFY                                          0x00000180
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_IMAGE(x)                                                (0x00000184+((x)*4))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_IMAGE__SIZE                                     0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_LUT(x)                                          (0x0000018c+((x)*4))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_LUT__SIZE                                       0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_CURSOR(x)                                       (0x00000194+((x)*4))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_DMA_CURSOR__SIZE                                    0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_GET                                                 0x000002fc
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_OFFSET(x)                                 (0x00000300+((x)*8))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_OFFSET__SIZE                              0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT(x)                                 (0x00000304+((x)*8))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT__SIZE                              0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_PITCH_SHIFT                       0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_PITCH_MASK                                0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_COLOR_SHIFT                       16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_COLOR_MASK                                0x0fff0000
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_NOTIFY_SHIFT                      28
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_IMAGE_FORMAT_NOTIFY_MASK                       0xf0000000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_OFFSET(x)                                        (0x00000340+((x)*12))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_OFFSET__SIZE                             0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT(x)                             (0x00000344+((x)*12))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT__SIZE                          0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_X_SHIFT                       0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_X_MASK                                0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_Y_SHIFT                       16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_Y_MASK                                0xffff0000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_FORMAT(x)                                        (0x00000348+((x)*12))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_FORMAT__SIZE                             0x00000002
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A                              0x00000358
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_X_SHIFT                     0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_X_MASK                      0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_Y_SHIFT                     16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_CURSOR_POINT_OUT_A_Y_MASK                      0xffff0000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE(x)                               (0x00000380+((x)*16))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE__SIZE                            0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_W_SHIFT                         0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_W_MASK                          0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_H_SHIFT                         16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_IMAGE_SIZE_H_MASK                          0xffff0000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC(x)                                    (0x00000384+((x)*16))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC__SIZE                                 0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_START_SHIFT                          0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_START_MASK                           0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_WIDTH_SHIFT                          16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_WIDTH_MASK                           0x0fff0000
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_POLARITY_SHIFT                       28
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_HSYNC_POLARITY_MASK                                0xf0000000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC(x)                                    (0x00000388+((x)*16))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC__SIZE                                 0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_START_SHIFT                          0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_START_MASK                           0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_WIDTH_SHIFT                          16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_WIDTH_MASK                           0x0fff0000
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_POLARITY_SHIFT                       28
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_VSYNC_POLARITY_MASK                                0xf0000000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE(x)                               (0x0000038c+((x)*16))
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE__SIZE                            0x00000002
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_WIDTH_SHIFT                     0
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_WIDTH_MASK                      0x0000ffff
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_HEIGHT_SHIFT                    16
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_HEIGHT_MASK                     0x0fff0000
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_NOTIFY_SHIFT                    28
+#define   NV03_VIDEO_LUT_CURSOR_DAC_SET_DAC_TOTAL_SIZE_NOTIFY_MASK                     0xf0000000
+#define  NV03_VIDEO_LUT_CURSOR_DAC_SET_PIXEL_CLOCK                                     0x000003a0
+
+
+#define NV03_DX3_TEXTURED_TRIANGLE                                                     0x00000048
+
+#define  NV03_DX3_TEXTURED_TRIANGLE_NOP                                                        0x00000100
+#define  NV03_DX3_TEXTURED_TRIANGLE_NOTIFY                                             0x00000104
+#define  NV03_DX3_TEXTURED_TRIANGLE_PATCH                                              0x0000010c
+#define  NV03_DX3_TEXTURED_TRIANGLE_DMA_NOTIFY                                         0x00000180
+#define  NV03_DX3_TEXTURED_TRIANGLE_DMA_TEXTURE                                                0x00000184
+#define  NV03_DX3_TEXTURED_TRIANGLE_CLIP_RECTANGLE                                     0x00000188
+#define  NV03_DX3_TEXTURED_TRIANGLE_SURFACE                                            0x0000018c
+#define  NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_OFFSET                                     0x00000304
+#define  NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT                                     0x00000308
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_MASK_SHIFT               0
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_MASK_MASK                        0x0000ffff
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_ENABLE_SHIFT             16
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_KEY_ENABLE_MASK              0x000f0000
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_SHIFT                                20
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_COLOR_MASK                         0x00f00000
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MIN_SHIFT                     24
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MIN_MASK                      0x0f000000
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MAX_SHIFT                     28
+#define   NV03_DX3_TEXTURED_TRIANGLE_TEXTURE_FORMAT_SIZE_MAX_MASK                      0xf0000000
+#define  NV03_DX3_TEXTURED_TRIANGLE_FILTER                                             0x0000030c
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_X_SHIFT                             0
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_X_MASK                              0x0000001f
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_Y_SHIFT                             8
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SPREAD_Y_MASK                              0x00001f00
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SIZE_ADJUST_SHIFT                          16
+#define   NV03_DX3_TEXTURED_TRIANGLE_FILTER_SIZE_ADJUST_MASK                           0x00ff0000
+#define  NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR                                          0x00000310
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_B_SHIFT                                 0
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_B_MASK                                  0x000000ff
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_G_SHIFT                                 8
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_G_MASK                                  0x0000ff00
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_R_SHIFT                                 16
+#define   NV03_DX3_TEXTURED_TRIANGLE_FOG_COLOR_R_MASK                                  0x00ff0000
+#define  NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT                                                0x00000314
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_INTERPOLATOR_SHIFT                    0
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_INTERPOLATOR_MASK                     0x0000000f
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_U_SHIFT                          4
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_U_MASK                           0x00000030
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_V_SHIFT                          6
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_WRAP_V_MASK                           0x000000c0
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SOURCE_COLOR_SHIFT                    8
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SOURCE_COLOR_MASK                     0x00000f00
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_CULLING_SHIFT                         12
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_CULLING_MASK                          0x00007000
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_PERSPECTIVE_ENABLE                  (1 << 15)
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_FUNC_SHIFT                          16
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_FUNC_MASK                           0x000f0000
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_WRITE_ENABLE_SHIFT                  20
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_Z_WRITE_ENABLE_MASK                   0x00f00000
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_COLOR_WRITE_ENABLE_SHIFT              24
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_COLOR_WRITE_ENABLE_MASK               0x07000000
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_ROP_SHIFT                             27
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_ROP_MASK                              0x18000000
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_BETA                                  (1 << 29)
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_DST_BLEND                             (1 << 30)
+#define   NV03_DX3_TEXTURED_TRIANGLE_CONTROL_OUT_SRC_BLEND                             (1 << 31)
+#define  NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL                                      0x00000318
+#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_REF_SHIFT                     0
+#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_REF_MASK                      0x000000ff
+#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_FUNC_SHIFT                    8
+#define   NV03_DX3_TEXTURED_TRIANGLE_ALPHA_CONTROL_ALPHA_FUNC_MASK                     0xffffff00
+#define  NV03_DX3_TEXTURED_TRIANGLE_SPECULAR(x)                                                (0x00001000+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_SPECULAR__SIZE                                     0x00000040
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I0_SHIFT                                 0
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I0_MASK                                  0x0000000f
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I1_SHIFT                                 4
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I1_MASK                                  0x000000f0
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I2_SHIFT                                 8
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I2_MASK                                  0x00000f00
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I3_SHIFT                                 12
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I3_MASK                                  0x0000f000
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I4_SHIFT                                 16
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I4_MASK                                  0x000f0000
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I5_SHIFT                                 20
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_I5_MASK                                  0x00f00000
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_FOG_SHIFT                                        24
+#define   NV03_DX3_TEXTURED_TRIANGLE_SPECULAR_FOG_MASK                                 0xff000000
+#define  NV03_DX3_TEXTURED_TRIANGLE_COLOR(x)                                           (0x00001004+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_COLOR__SIZE                                                0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_X(x)                                               (0x00001008+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_X__SIZE                                            0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_Y(x)                                               (0x0000100c+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_Y__SIZE                                            0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_Z(x)                                               (0x00001010+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_Z__SIZE                                            0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_M(x)                                               (0x00001014+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_M__SIZE                                            0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_U(x)                                               (0x00001018+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_U__SIZE                                            0x00000040
+#define  NV03_DX3_TEXTURED_TRIANGLE_V(x)                                               (0x0000101c+((x)*32))
+#define  NV03_DX3_TEXTURED_TRIANGLE_V__SIZE                                            0x00000040
+
+
+#define NV04_GDI_RECTANGLE_TEXT                                                                0x0000004a
+
+#define  NV04_GDI_RECTANGLE_TEXT_NOP                                                   0x00000100
+#define  NV04_GDI_RECTANGLE_TEXT_NOTIFY                                                        0x00000104
+#define  NV04_GDI_RECTANGLE_TEXT_PATCH                                                 0x0000010c
+#define  NV04_GDI_RECTANGLE_TEXT_PM_TRIGGER                                            0x00000140
+#define  NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY                                            0x00000180
+#define  NV04_GDI_RECTANGLE_TEXT_DMA_FONTS                                             0x00000184
+#define  NV04_GDI_RECTANGLE_TEXT_PATTERN                                               0x00000188
+#define  NV04_GDI_RECTANGLE_TEXT_ROP                                                   0x0000018c
+#define  NV04_GDI_RECTANGLE_TEXT_BETA1                                                 0x00000190
+#define  NV04_GDI_RECTANGLE_TEXT_BETA4                                                 0x00000194
+#define  NV04_GDI_RECTANGLE_TEXT_SURFACE                                               0x00000198
+#define  NV04_GDI_RECTANGLE_TEXT_OPERATION                                             0x000002fc
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_AND                                        0x00000000
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND                                    0x00000001
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_AND                                  0x00000002
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY                                    0x00000003
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_PREMULT                            0x00000004
+#define   NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_PREMULT                              0x00000005
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT                                          0x00000300
+#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5                               0x00000001
+#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_X16A1R5G5B5                             0x00000002
+#define   NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8                                        0x00000003
+#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT                                     0x00000304
+#define   NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6                               0x00000001
+#define   NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE                                 0x00000002
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_A                                              0x000003fc
+#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(x)                          (0x00000400+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT__SIZE                       0x00000020
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_SHIFT                    0
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_MASK                     0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_SHIFT                    16
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_MASK                     0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE(x)                           (0x00000404+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE__SIZE                                0x00000020
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_SHIFT                     0
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_MASK                      0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_SHIFT                     16
+#define   NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_MASK                      0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0                                         0x000005f4
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1                                         0x000005f8
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_B                                              0x000005fc
+#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0(x)                          (0x00000600+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0__SIZE                       0x00000020
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_SHIFT                    0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_MASK                     0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_SHIFT                    16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_MASK                     0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1(x)                          (0x00000604+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1__SIZE                       0x00000020
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_SHIFT                    0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_MASK                     0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_SHIFT                    16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_MASK                     0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0                                         0x000007ec
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1                                         0x000007f0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_C                                              0x000007f4
+#define  NV04_GDI_RECTANGLE_TEXT_SIZE_C                                                        0x000007f8
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_W_SHIFT                                       0
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_W_MASK                                                0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_H_SHIFT                                       16
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_C_H_MASK                                                0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_POINT_C                                               0x000007fc
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_X_SHIFT                                      0
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_X_MASK                                       0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_Y_SHIFT                                      16
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_C_Y_MASK                                       0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(x)                                        (0x00000800+((x)*4))
+#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__SIZE                             0x00000080
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0                                         0x00000be4
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1                                         0x00000be8
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR0_E                                              0x00000bec
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_E                                              0x00000bf0
+#define  NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E                                             0x00000bf4
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_SHIFT                                    0
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_MASK                                     0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_SHIFT                                    16
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_MASK                                     0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E                                            0x00000bf8
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_SHIFT                                   0
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_MASK                                    0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_SHIFT                                   16
+#define   NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_MASK                                    0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_POINT_E                                               0x00000bfc
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_X_SHIFT                                      0
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_X_MASK                                       0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_Y_SHIFT                                      16
+#define   NV04_GDI_RECTANGLE_TEXT_POINT_E_Y_MASK                                       0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(x)                               (0x00000c00+((x)*4))
+#define  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__SIZE                            0x00000080
+#define  NV04_GDI_RECTANGLE_TEXT_FONT_F                                                        0x00000ff0
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET_SHIFT                                  0
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET_MASK                                   0x0fffffff
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH_SHIFT                                   28
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH_MASK                                    0xf0000000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0                                         0x00000ff4
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1                                         0x00000ff8
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_F                                              0x00000ffc
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F(x)                                 (0x00001000+((x)*4))
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F__SIZE                              0x00000100
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX_SHIFT                       0
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX_MASK                                0x000000ff
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X_SHIFT                           8
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X_MASK                            0x000fff00
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y_SHIFT                           20
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y_MASK                            0xfff00000
+#define  NV04_GDI_RECTANGLE_TEXT_FONT_G                                                        0x000017f0
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET_SHIFT                                  0
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET_MASK                                   0x0fffffff
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH_SHIFT                                   28
+#define   NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH_MASK                                    0xf0000000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0                                         0x000017f4
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1                                         0x000017f8
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R_SHIFT                                        0
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R_MASK                                 0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B_SHIFT                                        16
+#define   NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B_MASK                                 0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_COLOR1_G                                              0x000017fc
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT(x)                           (0x00001800+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT__SIZE                                0x00000100
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X_SHIFT                     0
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X_MASK                      0x0000ffff
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y_SHIFT                     16
+#define   NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y_MASK                      0xffff0000
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX(x)                           (0x00001804+((x)*8))
+#define  NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX__SIZE                                0x00000100
+
+
+#define NV03_GDI_RECTANGLE_TEXT                                                                0x0000004b
+
+#define  NV03_GDI_RECTANGLE_TEXT_NOP                                                   0x00000100
+#define  NV03_GDI_RECTANGLE_TEXT_NOTIFY                                                        0x00000104
+#define  NV03_GDI_RECTANGLE_TEXT_DMA_NOTIFY                                            0x00000180
+#define  NV03_GDI_RECTANGLE_TEXT_PATTERN                                               0x00000184
+#define  NV03_GDI_RECTANGLE_TEXT_ROP                                                   0x00000188
+#define  NV03_GDI_RECTANGLE_TEXT_BETA1                                                 0x0000018c
+#define  NV03_GDI_RECTANGLE_TEXT_SURFACE                                               0x00000190
+#define  NV03_GDI_RECTANGLE_TEXT_OPERATION                                             0x000002fc
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR_FORMAT                                          0x00000300
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT                                     0x00000304
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_A                                              0x000003fc
+#define  NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT                             0x00000400
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_SHIFT                    0
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y_MASK                     0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_SHIFT                    16
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X_MASK                     0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE                              0x00000404
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_SHIFT                     0
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H_MASK                      0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_SHIFT                     16
+#define   NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W_MASK                      0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B                                         0x000007f4
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B                                         0x000007f8
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_B                                              0x000007fc
+#define  NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0                             0x00000800
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_SHIFT                    0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L_MASK                     0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_SHIFT                    16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T_MASK                     0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1                             0x00000804
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_SHIFT                    0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R_MASK                     0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_SHIFT                    16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B_MASK                     0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0                                         0x00000bec
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1                                         0x00000bf0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_C                                              0x00000bf4
+#define  NV03_GDI_RECTANGLE_TEXT_SIZE_C                                                        0x00000bf8
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_W_SHIFT                                       0
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_W_MASK                                                0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_H_SHIFT                                       16
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_C_H_MASK                                                0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_POINT_C                                               0x00000bfc
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_X_SHIFT                                      0
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_X_MASK                                       0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_Y_SHIFT                                      16
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_C_Y_MASK                                       0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(x)                                        (0x00000c00+((x)*4))
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__SIZE                             0x00000020
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0                                         0x00000fe8
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1                                         0x00000fec
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_D                                              0x00000ff0
+#define  NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D                                             0x00000ff4
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W_SHIFT                                    0
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W_MASK                                     0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H_SHIFT                                    16
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H_MASK                                     0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D                                            0x00000ff8
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W_SHIFT                                   0
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W_MASK                                    0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H_SHIFT                                   16
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H_MASK                                    0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_POINT_D                                               0x00000ffc
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_X_SHIFT                                      0
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_X_MASK                                       0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_Y_SHIFT                                      16
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_D_Y_MASK                                       0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D(x)                                        (0x00001000+((x)*4))
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D__SIZE                             0x00000020
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0                                         0x000013e4
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1                                         0x000013e8
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_SHIFT                                        0
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R_MASK                                 0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_SHIFT                                        16
+#define   NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B_MASK                                 0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR0_E                                              0x000013ec
+#define  NV03_GDI_RECTANGLE_TEXT_COLOR1_E                                              0x000013f0
+#define  NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E                                             0x000013f4
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_SHIFT                                    0
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W_MASK                                     0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_SHIFT                                    16
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H_MASK                                     0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E                                            0x000013f8
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_SHIFT                                   0
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W_MASK                                    0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_SHIFT                                   16
+#define   NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H_MASK                                    0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_POINT_E                                               0x000013fc
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_X_SHIFT                                      0
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_X_MASK                                       0x0000ffff
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_Y_SHIFT                                      16
+#define   NV03_GDI_RECTANGLE_TEXT_POINT_E_Y_MASK                                       0xffff0000
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(x)                               (0x00001400+((x)*4))
+#define  NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__SIZE                            0x00000020
+
+
+#define NV04_SWIZZLED_SURFACE                                                          0x00000052
+
+#define  NV04_SWIZZLED_SURFACE_NOP                                                     0x00000100
+#define  NV04_SWIZZLED_SURFACE_NOTIFY                                                  0x00000104
+#define  NV04_SWIZZLED_SURFACE_DMA_NOTIFY                                              0x00000180
+#define  NV04_SWIZZLED_SURFACE_DMA_IMAGE                                               0x00000184
+#define  NV04_SWIZZLED_SURFACE_FORMAT                                                  0x00000300
+#define   NV04_SWIZZLED_SURFACE_FORMAT_COLOR_SHIFT                                     0
+#define   NV04_SWIZZLED_SURFACE_FORMAT_COLOR_MASK                                      0x000000ff
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8                                       0x00000001
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5                                0x00000002
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_X1R5G5B5                                0x00000003
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5                                   0x00000004
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y16                                      0x00000005
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8                                0x00000006
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_X8R8G8B8                                0x00000007
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8                    0x00000008
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8                    0x00000009
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8                                 0x0000000a
+#define    NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y32                                      0x0000000b
+#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT                               16
+#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_MASK                                        0x00ff0000
+#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT                               24
+#define   NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_MASK                                        0xff000000
+#define  NV04_SWIZZLED_SURFACE_OFFSET                                                  0x00000304
+
+
+#define NV04_CONTEXT_SURFACES_3D                                                       0x00000053
+
+#define  NV04_CONTEXT_SURFACES_3D_NOP                                                  0x00000100
+#define  NV04_CONTEXT_SURFACES_3D_NOTIFY                                               0x00000104
+#define  NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY                                           0x00000180
+#define  NV04_CONTEXT_SURFACES_3D_DMA_COLOR                                            0x00000184
+#define  NV04_CONTEXT_SURFACES_3D_DMA_ZETA                                             0x00000188
+#define  NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL                                      0x000002f8
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X_SHIFT                             0
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X_MASK                              0x0000ffff
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W_SHIFT                             16
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W_MASK                              0xffff0000
+#define  NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL                                                0x000002fc
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y_SHIFT                               0
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y_MASK                                        0x0000ffff
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H_SHIFT                               16
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H_MASK                                        0xffff0000
+#define  NV04_CONTEXT_SURFACES_3D_FORMAT                                               0x00000300
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_SHIFT                                  0
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_MASK                                   0x000000ff
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5                     0x00000001
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_X1R5G5B5                     0x00000002
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_R5G6B5                                        0x00000003
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8                     0x00000004
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_X8R8G8B8                     0x00000005
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8                 0x00000006
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8                 0x00000007
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_A8R8G8B8                              0x00000008
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_SHIFT                                   8
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_MASK                                    0x0000ff00
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH                                  0x00000100
+#define    NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_SWIZZLE                                        0x00000200
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U_SHIFT                            16
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U_MASK                             0x00ff0000
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V_SHIFT                            24
+#define   NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V_MASK                             0xff000000
+#define  NV04_CONTEXT_SURFACES_3D_CLIP_SIZE                                            0x00000304
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W_SHIFT                                   0
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W_MASK                                    0x0000ffff
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H_SHIFT                                   16
+#define   NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H_MASK                                    0xffff0000
+#define  NV04_CONTEXT_SURFACES_3D_PITCH                                                        0x00000308
+#define   NV04_CONTEXT_SURFACES_3D_PITCH_COLOR_SHIFT                                   0
+#define   NV04_CONTEXT_SURFACES_3D_PITCH_COLOR_MASK                                    0x0000ffff
+#define   NV04_CONTEXT_SURFACES_3D_PITCH_ZETA_SHIFT                                    16
+#define   NV04_CONTEXT_SURFACES_3D_PITCH_ZETA_MASK                                     0xffff0000
+#define  NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR                                         0x0000030c
+#define  NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA                                          0x00000310
+
+
+#define NV04_DX5_TEXTURED_TRIANGLE                                                     0x00000054
+
+#define  NV04_DX5_TEXTURED_TRIANGLE_NOP                                                        0x00000100
+#define  NV04_DX5_TEXTURED_TRIANGLE_NOTIFY                                             0x00000104
+#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_NOTIFY                                         0x00000180
+#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_A                                              0x00000184
+#define  NV04_DX5_TEXTURED_TRIANGLE_DMA_B                                              0x00000188
+#define  NV04_DX5_TEXTURED_TRIANGLE_SURFACE                                            0x0000018c
+#define  NV04_DX5_TEXTURED_TRIANGLE_COLORKEY                                           0x00000300
+#define  NV04_DX5_TEXTURED_TRIANGLE_OFFSET                                             0x00000304
+#define  NV04_DX5_TEXTURED_TRIANGLE_FORMAT                                             0x00000308
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_DMA_SHIFT                                  0
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_DMA_MASK                                   0x00000003
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_KEY_MATCH_SHIFT                      2
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_KEY_MATCH_MASK                       0x0000000c
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_SHIFT                           4
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_MASK                            0x00000030
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CENTER                         0x00000010
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER                         0x00000020
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_SHIFT                           6
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_MASK                            0x000000c0
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CENTER                         0x00000040
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER                         0x00000080
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_SHIFT                                        8
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_MASK                                 0x00000f00
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8                                  0x00000100
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5                            0x00000200
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_X1R5G5B5                            0x00000300
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A4R4G4B4                            0x00000400
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5                              0x00000500
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8                            0x00000600
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_X8R8G8B8                            0x00000700
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT                                12
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_MASK                         0x0000f000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT                          16
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_MASK                           0x000f0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT                          20
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_MASK                           0x00f00000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT                             24
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MASK                              0x07000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT                           0x01000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT                  0x02000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE                    0x03000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER                  0x04000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP                            0x05000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_WRAPU                                      (1 << 27)
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT                             28
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_MASK                              0x70000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_REPEAT                           0x10000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_MIRRORED_REPEAT                  0x20000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE                    0x30000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_BORDER                  0x40000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP                            0x50000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FORMAT_WRAPV                                      (1 << 31)
+#define  NV04_DX5_TEXTURED_TRIANGLE_FILTER                                             0x0000030c
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X_SHIFT                                0
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X_MASK                         0x000000ff
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y_SHIFT                                8
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y_MASK                         0x00007f00
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE                       (1 << 15)
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS_SHIFT                       16
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS_MASK                                0x00ff0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_SHIFT                               24
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_MASK                                        0x07000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST                            0x01000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR                             0x02000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST             0x03000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST              0x04000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR              0x05000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR               0x06000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE                  (1 << 27)
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_SHIFT                              28
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_MASK                               0x70000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST                           0x10000000
+#define    NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR                            0x20000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE                 (1 << 31)
+#define  NV04_DX5_TEXTURED_TRIANGLE_BLEND                                              0x00000310
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_SHIFT                           0
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_MASK                            0x0000000f
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_MASK_BIT_SHIFT                              4
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MASK                               0x00000030
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_SHIFT                            6
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_MASK                             0x000000c0
+#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT                            0x00000040
+#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD                         0x00000080
+#define    NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_PHONG                           0x000000c0
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_SHIFT            8
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_MASK             0x00000f00
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE_SHIFT                       12
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE_MASK                                0x0000f000
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE_SHIFT                            16
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE_MASK                             0x000f0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_ALPHA_ENABLE_SHIFT                          20
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_ALPHA_ENABLE_MASK                           0x00f00000
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SRC_SHIFT                                   24
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_SRC_MASK                                    0x0f000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_DST_SHIFT                                   28
+#define   NV04_DX5_TEXTURED_TRIANGLE_BLEND_DST_MASK                                    0xf0000000
+#define  NV04_DX5_TEXTURED_TRIANGLE_CONTROL                                            0x00000314
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF_SHIFT                           0
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF_MASK                            0x000000ff
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT                          8
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_MASK                           0x00000f00
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE                         (1 << 12)
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN                                    (1 << 13)
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT                            14
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_MASK                             0x0000c000
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT                              16
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_MASK                               0x000f0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT                           20
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_MASK                            0x00300000
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE                             (1 << 22)
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE                      (1 << 23)
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT                      24
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_MASK                       0x3f000000
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT                            30
+#define   NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_MASK                             0xc0000000
+#define  NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR                                           0x00000318
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_B_SHIFT                                  0
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_B_MASK                                   0x000000ff
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_G_SHIFT                                  8
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_G_MASK                                   0x0000ff00
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_R_SHIFT                                  16
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_R_MASK                                   0x00ff0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_A_SHIFT                                  24
+#define   NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR_A_MASK                                   0xff000000
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(x)                                     (0x00000400+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX__SIZE                                  0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY(x)                                     (0x00000404+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SY__SIZE                                  0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ(x)                                     (0x00000408+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SZ__SIZE                                  0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_RHW(x)                                    (0x0000040c+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_RHW__SIZE                                 0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR(x)                                  (0x00000410+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR__SIZE                               0x00000010
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B_SHIFT                            0
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B_MASK                             0x000000ff
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G_SHIFT                            8
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G_MASK                             0x0000ff00
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R_SHIFT                            16
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R_MASK                             0x00ff0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A_SHIFT                            24
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A_MASK                             0xff000000
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR(x)                               (0x00000414+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR__SIZE                            0x00000010
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B_SHIFT                         0
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B_MASK                          0x000000ff
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G_SHIFT                         8
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G_MASK                          0x0000ff00
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R_SHIFT                         16
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R_MASK                          0x00ff0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG_SHIFT                       24
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG_MASK                                0xff000000
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TU(x)                                     (0x00000418+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TU__SIZE                                  0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TV(x)                                     (0x0000041c+((x)*32))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_TV__SIZE                                  0x00000010
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(x)                          (0x00000600+((x)*4))
+#define  NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE__SIZE                       0x00000040
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I0_SHIFT                   0
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I0_MASK                    0x0000000f
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I1_SHIFT                   4
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I1_MASK                    0x000000f0
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I2_SHIFT                   8
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I2_MASK                    0x00000f00
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I3_SHIFT                   12
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I3_MASK                    0x0000f000
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I4_SHIFT                   16
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I4_MASK                    0x000f0000
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I5_SHIFT                   20
+#define   NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE_I5_MASK                    0x00f00000
+
+
+#define NV04_DX6_MULTITEX_TRIANGLE                                                     0x00000055
+
+#define  NV04_DX6_MULTITEX_TRIANGLE_NOP                                                        0x00000100
+#define  NV04_DX6_MULTITEX_TRIANGLE_NOTIFY                                             0x00000104
+#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_NOTIFY                                         0x00000180
+#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_A                                              0x00000184
+#define  NV04_DX6_MULTITEX_TRIANGLE_DMA_B                                              0x00000188
+#define  NV04_DX6_MULTITEX_TRIANGLE_SURFACE                                            0x0000018c
+#define  NV04_DX6_MULTITEX_TRIANGLE_OFFSET(x)                                          (0x00000308+((x)*4))
+#define  NV04_DX6_MULTITEX_TRIANGLE_OFFSET__SIZE                                       0x00000002
+#define  NV04_DX6_MULTITEX_TRIANGLE_FORMAT(x)                                          (0x00000310+((x)*4))
+#define  NV04_DX6_MULTITEX_TRIANGLE_FORMAT__SIZE                                       0x00000002
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_DMA_SHIFT                                  0
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_DMA_MASK                                   0x0000000f
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_SHIFT                           4
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_MASK                            0x00000030
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_SHIFT                           6
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_MASK                            0x000000c0
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_COLOR_SHIFT                                        8
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_COLOR_MASK                                 0x00000f00
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT                                12
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS_MASK                         0x0000f000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT                          16
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U_MASK                           0x000f0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT                          20
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V_MASK                           0x00f00000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_SHIFT                             24
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_MASK                              0x07000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_WRAPU                                      (1 << 27)
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_SHIFT                             28
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_MASK                              0x70000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FORMAT_WRAPV                                      (1 << 31)
+#define  NV04_DX6_MULTITEX_TRIANGLE_FILTER(x)                                          (0x00000318+((x)*4))
+#define  NV04_DX6_MULTITEX_TRIANGLE_FILTER__SIZE                                       0x00000002
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X_SHIFT                                0
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X_MASK                         0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y_SHIFT                                8
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y_MASK                         0x00007f00
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE                       (1 << 15)
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS_SHIFT                       16
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS_MASK                                0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MINIFY_SHIFT                               24
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MINIFY_MASK                                        0x07000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE                  (1 << 27)
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MAGNIFY_SHIFT                              28
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_MAGNIFY_MASK                               0x70000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE                 (1 << 31)
+#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA                                    0x00000320
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE0                          (1 <<  0)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA0                            (1 <<  1)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT0_SHIFT                   2
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT0_MASK                    0x000000fc
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE1                          (1 <<  8)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA1                            (1 <<  9)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT1_SHIFT                   10
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT1_MASK                    0x0000fc00
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE2                          (1 << 16)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA2                            (1 << 17)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT2_SHIFT                   18
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT2_MASK                    0x00fc0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_INVERSE3                          (1 << 24)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ALPHA3                            (1 << 25)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT3_SHIFT                   26
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_ARGUMENT3_MASK                    0x1c000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_OPERATION_SHIFT                   29
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_ALPHA_OPERATION_MASK                    0xe0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR                                    0x00000324
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE0                          (1 <<  0)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA0                            (1 <<  1)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT0_SHIFT                   2
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT0_MASK                    0x000000fc
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE1                          (1 <<  8)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA1                            (1 <<  9)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT1_SHIFT                   10
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT1_MASK                    0x0000fc00
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE2                          (1 << 16)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA2                            (1 << 17)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT2_SHIFT                   18
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT2_MASK                    0x00fc0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_INVERSE3                          (1 << 24)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ALPHA3                            (1 << 25)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT3_SHIFT                   26
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_ARGUMENT3_MASK                    0x1c000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_OPERATION_SHIFT                   29
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_0_COLOR_OPERATION_MASK                    0xe0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA                                    0x0000032c
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE0                          (1 <<  0)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA0                            (1 <<  1)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT0_SHIFT                   2
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT0_MASK                    0x000000fc
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE1                          (1 <<  8)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA1                            (1 <<  9)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT1_SHIFT                   10
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT1_MASK                    0x0000fc00
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE2                          (1 << 16)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA2                            (1 << 17)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT2_SHIFT                   18
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT2_MASK                    0x00fc0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_INVERSE3                          (1 << 24)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ALPHA3                            (1 << 25)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT3_SHIFT                   26
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_ARGUMENT3_MASK                    0x1c000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_OPERATION_SHIFT                   29
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_ALPHA_OPERATION_MASK                    0xe0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR                                    0x00000330
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE0                          (1 <<  0)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA0                            (1 <<  1)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT0_SHIFT                   2
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT0_MASK                    0x000000fc
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE1                          (1 <<  8)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA1                            (1 <<  9)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT1_SHIFT                   10
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT1_MASK                    0x0000fc00
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE2                          (1 << 16)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA2                            (1 << 17)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT2_SHIFT                   18
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT2_MASK                    0x00fc0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_INVERSE3                          (1 << 24)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ALPHA3                            (1 << 25)
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT3_SHIFT                   26
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_ARGUMENT3_MASK                    0x1c000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_OPERATION_SHIFT                   29
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_1_COLOR_OPERATION_MASK                    0xe0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR                                     0x00000334
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_B_SHIFT                            0
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_B_MASK                             0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_G_SHIFT                            8
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_G_MASK                             0x0000ff00
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_R_SHIFT                            16
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_R_MASK                             0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_A_SHIFT                            24
+#define   NV04_DX6_MULTITEX_TRIANGLE_COMBINE_FACTOR_A_MASK                             0xff000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_BLEND                                              0x00000338
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_MASK_BIT_SHIFT                              4
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_MASK_BIT_MASK                               0x00000030
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_SHIFT                            6
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_MASK                             0x000000c0
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_SHIFT            8
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE_MASK             0x00000f00
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE_SHIFT                       12
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE_MASK                                0x0000f000
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE_SHIFT                            16
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE_MASK                             0x000f0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_ALPHA_ENABLE_SHIFT                          20
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_ALPHA_ENABLE_MASK                           0x00f00000
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SRC_SHIFT                                   24
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_SRC_MASK                                    0x0f000000
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_DST_SHIFT                                   28
+#define   NV04_DX6_MULTITEX_TRIANGLE_BLEND_DST_MASK                                    0xf0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL0                                           0x0000033c
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF_SHIFT                          0
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF_MASK                           0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_SHIFT                         8
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_MASK                          0x00000f00
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_TEST_ENABLE                                (1 << 12)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ORIGIN                                   (1 << 13)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE_SHIFT                           14
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE_MASK                            0x0000c000
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_SHIFT                             16
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_MASK                              0x000f0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_SHIFT                          20
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_MASK                           0x00300000
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE                            (1 << 22)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_PERSPECTIVE_ENABLE                     (1 << 23)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE_ENABLE                           (1 << 24)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE_ENABLE                     (1 << 25)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE_ENABLE                       (1 << 26)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE_ENABLE                         (1 << 27)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE_ENABLE                       (1 << 28)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE_ENABLE                                (1 << 29)
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_SHIFT                           30
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_MASK                            0xc0000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL1                                           0x00000340
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_TEST_ENABLE_SHIFT                        0
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_TEST_ENABLE_MASK                 0x0000000f
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC_SHIFT                       4
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC_MASK                                0x000000f0
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF_SHIFT                                8
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF_MASK                         0x0000ff00
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ_SHIFT                  16
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ_MASK                   0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE_SHIFT                 24
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE_MASK                  0xff000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_CONTROL2                                           0x00000344
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL_SHIFT                    0
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL_MASK                     0x0000000f
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL_SHIFT                   4
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL_MASK                    0x000000f0
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS_SHIFT                   8
+#define   NV04_DX6_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS_MASK                    0x00000f00
+#define  NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR                                           0x00000348
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_B_SHIFT                                  0
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_B_MASK                                   0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_G_SHIFT                                  8
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_G_MASK                                   0x0000ff00
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_R_SHIFT                                  16
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_R_MASK                                   0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_A_SHIFT                                  24
+#define   NV04_DX6_MULTITEX_TRIANGLE_FOGCOLOR_A_MASK                                   0xff000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SX(x)                                   (0x00000400+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SX__SIZE                                        0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SY(x)                                   (0x00000404+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SY__SIZE                                        0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SZ(x)                                   (0x00000408+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SZ__SIZE                                        0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_RHW(x)                                  (0x0000040c+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_RHW__SIZE                               0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR(x)                                        (0x00000410+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR__SIZE                             0x00000008
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B_SHIFT                          0
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B_MASK                           0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G_SHIFT                          8
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G_MASK                           0x0000ff00
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R_SHIFT                          16
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R_MASK                           0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A_SHIFT                          24
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A_MASK                           0xff000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR(x)                             (0x00000414+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR__SIZE                          0x00000008
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B_SHIFT                       0
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B_MASK                                0x000000ff
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G_SHIFT                       8
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G_MASK                                0x0000ff00
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R_SHIFT                       16
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R_MASK                                0x00ff0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG_SHIFT                     24
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG_MASK                      0xff000000
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU0(x)                                  (0x00000418+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU0__SIZE                               0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV0(x)                                  (0x0000041c+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV0__SIZE                               0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU1(x)                                  (0x00000420+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TU1__SIZE                               0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV1(x)                                  (0x00000424+((x)*40))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_TV1__SIZE                               0x00000008
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE(x)                                (0x00000540+((x)*4))
+#define  NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE__SIZE                     0x00000030
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I0_SHIFT                 0
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I0_MASK                  0x0000000f
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I1_SHIFT                 4
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I1_MASK                  0x000000f0
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I2_SHIFT                 8
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I2_MASK                  0x00000f00
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I3_SHIFT                 12
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I3_MASK                  0x0000f000
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I4_SHIFT                 16
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I4_MASK                  0x000f0000
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I5_SHIFT                 20
+#define   NV04_DX6_MULTITEX_TRIANGLE_TLMTVERTEX_DRAWPRIMITIVE_I5_MASK                  0x00f00000
+
+
+#define NV10_DX5_TEXTURED_TRIANGLE                                                     0x00000094
+
+
+
+#define NV10TCL                                                                                0x00000056
+
+#define  NV10TCL_NOP                                                                   0x00000100
+#define  NV10TCL_NOTIFY                                                                        0x00000104
+#define  NV10TCL_DMA_NOTIFY                                                            0x00000180
+#define  NV10TCL_DMA_IN_MEMORY0                                                                0x00000184
+#define  NV10TCL_DMA_IN_MEMORY1                                                                0x00000188
+#define  NV10TCL_DMA_VTXBUF0                                                           0x0000018c
+#define  NV10TCL_DMA_IN_MEMORY2                                                                0x00000194
+#define  NV10TCL_DMA_IN_MEMORY3                                                                0x00000198
+#define  NV10TCL_RT_HORIZ                                                              0x00000200
+#define   NV10TCL_RT_HORIZ_X_SHIFT                                                     0
+#define   NV10TCL_RT_HORIZ_X_MASK                                                      0x0000ffff
+#define   NV10TCL_RT_HORIZ_W_SHIFT                                                     16
+#define   NV10TCL_RT_HORIZ_W_MASK                                                      0xffff0000
+#define  NV10TCL_RT_VERT                                                               0x00000204
+#define   NV10TCL_RT_VERT_Y_SHIFT                                                      0
+#define   NV10TCL_RT_VERT_Y_MASK                                                       0x0000ffff
+#define   NV10TCL_RT_VERT_H_SHIFT                                                      16
+#define   NV10TCL_RT_VERT_H_MASK                                                       0xffff0000
+#define  NV10TCL_RT_FORMAT                                                             0x00000208
+#define   NV10TCL_RT_FORMAT_TYPE_SHIFT                                                 8
+#define   NV10TCL_RT_FORMAT_TYPE_MASK                                                  0x00000f00
+#define    NV10TCL_RT_FORMAT_TYPE_LINEAR                                               0x00000100
+#define    NV10TCL_RT_FORMAT_TYPE_SWIZZLED                                             0x00000200
+#define   NV10TCL_RT_FORMAT_COLOR_SHIFT                                                        0
+#define   NV10TCL_RT_FORMAT_COLOR_MASK                                                 0x0000001f
+#define    NV10TCL_RT_FORMAT_COLOR_R5G6B5                                              0x00000003
+#define    NV10TCL_RT_FORMAT_COLOR_X8R8G8B8                                            0x00000005
+#define    NV10TCL_RT_FORMAT_COLOR_A8R8G8B8                                            0x00000008
+#define    NV10TCL_RT_FORMAT_COLOR_B8                                                  0x00000009
+#define    NV10TCL_RT_FORMAT_COLOR_X8B8G8R8                                            0x0000000f
+#define    NV10TCL_RT_FORMAT_COLOR_A8B8G8R8                                            0x00000010
+#define  NV10TCL_RT_PITCH                                                              0x0000020c
+#define   NV10TCL_RT_PITCH_COLOR_PITCH_SHIFT                                           0
+#define   NV10TCL_RT_PITCH_COLOR_PITCH_MASK                                            0x0000ffff
+#define   NV10TCL_RT_PITCH_ZETA_PITCH_SHIFT                                            16
+#define   NV10TCL_RT_PITCH_ZETA_PITCH_MASK                                             0xffff0000
+#define  NV10TCL_COLOR_OFFSET                                                          0x00000210
+#define  NV10TCL_ZETA_OFFSET                                                           0x00000214
+#define  NV10TCL_TX_OFFSET(x)                                                          (0x00000218+((x)*4))
+#define  NV10TCL_TX_OFFSET__SIZE                                                       0x00000002
+#define  NV10TCL_TX_FORMAT(x)                                                          (0x00000220+((x)*4))
+#define  NV10TCL_TX_FORMAT__SIZE                                                       0x00000002
+#define   NV10TCL_TX_FORMAT_DMA0                                                       (1 <<  0)
+#define   NV10TCL_TX_FORMAT_DMA1                                                       (1 <<  1)
+#define   NV10TCL_TX_FORMAT_CUBE_MAP                                                   (1 <<  2)
+#define   NV10TCL_TX_FORMAT_FORMAT_SHIFT                                               7
+#define   NV10TCL_TX_FORMAT_FORMAT_MASK                                                        0x00000780
+#define    NV10TCL_TX_FORMAT_FORMAT_L8                                                 0x00000000
+#define    NV10TCL_TX_FORMAT_FORMAT_A8                                                 0x00000080
+#define    NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5                                           0x00000100
+#define    NV10TCL_TX_FORMAT_FORMAT_A8_RECT                                            0x00000180
+#define    NV10TCL_TX_FORMAT_FORMAT_A4R4G4B4                                           0x00000200
+#define    NV10TCL_TX_FORMAT_FORMAT_R5G6B5                                             0x00000280
+#define    NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8                                           0x00000300
+#define    NV10TCL_TX_FORMAT_FORMAT_X8R8G8B8                                           0x00000380
+#define    NV10TCL_TX_FORMAT_FORMAT_INDEX8                                             0x00000580
+#define    NV10TCL_TX_FORMAT_FORMAT_DXT1                                               0x00000600
+#define    NV10TCL_TX_FORMAT_FORMAT_DXT3                                               0x00000700
+#define    NV10TCL_TX_FORMAT_FORMAT_DXT5                                               0x00000780
+#define    NV10TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT                                      0x00000800
+#define    NV10TCL_TX_FORMAT_FORMAT_R5G6B5_RECT                                                0x00000880
+#define    NV10TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT                                      0x00000900
+#define    NV10TCL_TX_FORMAT_FORMAT_L8_RECT                                            0x00000980
+#define    NV10TCL_TX_FORMAT_FORMAT_A8L8                                               0x00000d00
+#define    NV10TCL_TX_FORMAT_FORMAT_A8_RECT2                                           0x00000d80
+#define    NV10TCL_TX_FORMAT_FORMAT_A4R4G4B4_RECT                                      0x00000e80
+#define    NV10TCL_TX_FORMAT_FORMAT_R8G8B8_RECT                                                0x00000f00
+#define    NV10TCL_TX_FORMAT_FORMAT_L8A8_RECT                                          0x00001000
+#define    NV10TCL_TX_FORMAT_FORMAT_A16                                                        0x00001900
+#define    NV10TCL_TX_FORMAT_FORMAT_HILO16                                             0x00001980
+#define    NV10TCL_TX_FORMAT_FORMAT_A16_RECT                                           0x00001a80
+#define    NV10TCL_TX_FORMAT_FORMAT_HILO16_RECT                                                0x00001b00
+#define    NV10TCL_TX_FORMAT_FORMAT_HILO8                                              0x00002200
+#define    NV10TCL_TX_FORMAT_FORMAT_SIGNED_HILO8                                       0x00002280
+#define    NV10TCL_TX_FORMAT_FORMAT_HILO8_RECT                                         0x00002300
+#define    NV10TCL_TX_FORMAT_FORMAT_SIGNED_HILO8_RECT                                  0x00002380
+#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_RGBA16_NV                                    0x00002500
+#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_RGBA32_NV                                    0x00002580
+#define    NV10TCL_TX_FORMAT_FORMAT_FLOAT_R32_NV                                       0x00002600
+#define   NV10TCL_TX_FORMAT_NPOT                                                       (1 << 11)
+#define   NV10TCL_TX_FORMAT_MIPMAP_LEVELS_SHIFT                                                12
+#define   NV10TCL_TX_FORMAT_MIPMAP_LEVELS_MASK                                         0x0000f000
+#define   NV10TCL_TX_FORMAT_BASE_SIZE_U_SHIFT                                          16
+#define   NV10TCL_TX_FORMAT_BASE_SIZE_U_MASK                                           0x000f0000
+#define   NV10TCL_TX_FORMAT_BASE_SIZE_V_SHIFT                                          20
+#define   NV10TCL_TX_FORMAT_BASE_SIZE_V_MASK                                           0x00f00000
+#define   NV10TCL_TX_FORMAT_WRAP_S_SHIFT                                               24
+#define   NV10TCL_TX_FORMAT_WRAP_S_MASK                                                        0x0f000000
+#define    NV10TCL_TX_FORMAT_WRAP_S_REPEAT                                             0x01000000
+#define    NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT                                    0x02000000
+#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE                                      0x03000000
+#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER                                    0x04000000
+#define    NV10TCL_TX_FORMAT_WRAP_S_CLAMP                                              0x05000000
+#define   NV10TCL_TX_FORMAT_WRAP_T_SHIFT                                               28
+#define   NV10TCL_TX_FORMAT_WRAP_T_MASK                                                        0xf0000000
+#define    NV10TCL_TX_FORMAT_WRAP_T_REPEAT                                             0x10000000
+#define    NV10TCL_TX_FORMAT_WRAP_T_MIRRORED_REPEAT                                    0x20000000
+#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE                                      0x30000000
+#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_BORDER                                    0x40000000
+#define    NV10TCL_TX_FORMAT_WRAP_T_CLAMP                                              0x50000000
+#define  NV10TCL_TX_ENABLE(x)                                                          (0x00000228+((x)*4))
+#define  NV10TCL_TX_ENABLE__SIZE                                                       0x00000002
+#define   NV10TCL_TX_ENABLE_ANISOTROPY_SHIFT                                           4
+#define   NV10TCL_TX_ENABLE_ANISOTROPY_MASK                                            0x00000030
+#define   NV10TCL_TX_ENABLE_ENABLE                                                     (1 << 30)
+#define  NV10TCL_TX_NPOT_PITCH(x)                                                      (0x00000230+((x)*4))
+#define  NV10TCL_TX_NPOT_PITCH__SIZE                                                   0x00000002
+#define   NV10TCL_TX_NPOT_PITCH_PITCH_SHIFT                                            16
+#define   NV10TCL_TX_NPOT_PITCH_PITCH_MASK                                             0xffff0000
+#define  NV10TCL_TX_NPOT_SIZE(x)                                                       (0x00000240+((x)*4))
+#define  NV10TCL_TX_NPOT_SIZE__SIZE                                                    0x00000002
+#define   NV10TCL_TX_NPOT_SIZE_H_SHIFT                                                 0
+#define   NV10TCL_TX_NPOT_SIZE_H_MASK                                                  0x0000ffff
+#define   NV10TCL_TX_NPOT_SIZE_W_SHIFT                                                 16
+#define   NV10TCL_TX_NPOT_SIZE_W_MASK                                                  0xffff0000
+#define  NV10TCL_TX_FILTER(x)                                                          (0x00000248+((x)*4))
+#define  NV10TCL_TX_FILTER__SIZE                                                       0x00000002
+#define   NV10TCL_TX_FILTER_MINIFY_SHIFT                                               24
+#define   NV10TCL_TX_FILTER_MINIFY_MASK                                                        0x0f000000
+#define    NV10TCL_TX_FILTER_MINIFY_NEAREST                                            0x01000000
+#define    NV10TCL_TX_FILTER_MINIFY_LINEAR                                             0x02000000
+#define    NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST                             0x03000000
+#define    NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST                              0x04000000
+#define    NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR                              0x05000000
+#define    NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR                               0x06000000
+#define   NV10TCL_TX_FILTER_MAGNIFY_SHIFT                                              28
+#define   NV10TCL_TX_FILTER_MAGNIFY_MASK                                               0xf0000000
+#define    NV10TCL_TX_FILTER_MAGNIFY_NEAREST                                           0x10000000
+#define    NV10TCL_TX_FILTER_MAGNIFY_LINEAR                                            0x20000000
+#define  NV10TCL_TX_PALETTE_OFFSET(x)                                                  (0x00000250+((x)*4))
+#define  NV10TCL_TX_PALETTE_OFFSET__SIZE                                               0x00000002
+#define  NV10TCL_RC_IN_ALPHA(x)                                                                (0x00000260+((x)*4))
+#define  NV10TCL_RC_IN_ALPHA__SIZE                                                     0x00000002
+#define   NV10TCL_RC_IN_ALPHA_D_INPUT_SHIFT                                            0
+#define   NV10TCL_RC_IN_ALPHA_D_INPUT_MASK                                             0x0000000f
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_ZERO                                            0x00000000
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR0_NV                              0x00000001
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR1_NV                              0x00000002
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_FOG                                             0x00000003
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_PRIMARY_COLOR_NV                                        0x00000004
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SECONDARY_COLOR_NV                              0x00000005
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_TEXTURE0_ARB                                    0x00000008
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_TEXTURE1_ARB                                    0x00000009
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE0_NV                                       0x0000000c
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE1_NV                                       0x0000000d
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                  0x0000000e
+#define    NV10TCL_RC_IN_ALPHA_D_INPUT_E_TIMES_F_NV                                    0x0000000f
+#define   NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE                                                (1 <<  4)
+#define    NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE_BLUE                                  0x00000000
+#define    NV10TCL_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA                                 0x00000010
+#define   NV10TCL_RC_IN_ALPHA_D_MAPPING_SHIFT                                          5
+#define   NV10TCL_RC_IN_ALPHA_D_MAPPING_MASK                                           0x000000e0
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_UNSIGNED_IDENTITY_NV                          0x00000000
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT_NV                            0x00000020
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_EXPAND_NORMAL_NV                              0x00000040
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_EXPAND_NEGATE_NV                              0x00000060
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NORMAL_NV                           0x00000080
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NEGATE_NV                           0x000000a0
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_SIGNED_IDENTITY_NV                            0x000000c0
+#define    NV10TCL_RC_IN_ALPHA_D_MAPPING_SIGNED_NEGATE_NV                              0x000000e0
+#define   NV10TCL_RC_IN_ALPHA_C_INPUT_SHIFT                                            8
+#define   NV10TCL_RC_IN_ALPHA_C_INPUT_MASK                                             0x00000f00
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_ZERO                                            0x00000000
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR0_NV                              0x00000100
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR1_NV                              0x00000200
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_FOG                                             0x00000300
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_PRIMARY_COLOR_NV                                        0x00000400
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SECONDARY_COLOR_NV                              0x00000500
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_TEXTURE0_ARB                                    0x00000800
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_TEXTURE1_ARB                                    0x00000900
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE0_NV                                       0x00000c00
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE1_NV                                       0x00000d00
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                  0x00000e00
+#define    NV10TCL_RC_IN_ALPHA_C_INPUT_E_TIMES_F_NV                                    0x00000f00
+#define   NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE                                                (1 << 12)
+#define    NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE_BLUE                                  0x00000000
+#define    NV10TCL_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA                                 0x00001000
+#define   NV10TCL_RC_IN_ALPHA_C_MAPPING_SHIFT                                          13
+#define   NV10TCL_RC_IN_ALPHA_C_MAPPING_MASK                                           0x0000e000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_UNSIGNED_IDENTITY_NV                          0x00000000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT_NV                            0x00002000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_EXPAND_NORMAL_NV                              0x00004000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_EXPAND_NEGATE_NV                              0x00006000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NORMAL_NV                           0x00008000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NEGATE_NV                           0x0000a000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_SIGNED_IDENTITY_NV                            0x0000c000
+#define    NV10TCL_RC_IN_ALPHA_C_MAPPING_SIGNED_NEGATE_NV                              0x0000e000
+#define   NV10TCL_RC_IN_ALPHA_B_INPUT_SHIFT                                            16
+#define   NV10TCL_RC_IN_ALPHA_B_INPUT_MASK                                             0x000f0000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_ZERO                                            0x00000000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR0_NV                              0x00010000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR1_NV                              0x00020000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_FOG                                             0x00030000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_PRIMARY_COLOR_NV                                        0x00040000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SECONDARY_COLOR_NV                              0x00050000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_TEXTURE0_ARB                                    0x00080000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_TEXTURE1_ARB                                    0x00090000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE0_NV                                       0x000c0000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE1_NV                                       0x000d0000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                  0x000e0000
+#define    NV10TCL_RC_IN_ALPHA_B_INPUT_E_TIMES_F_NV                                    0x000f0000
+#define   NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE                                                (1 << 20)
+#define    NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE_BLUE                                  0x00000000
+#define    NV10TCL_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA                                 0x00100000
+#define   NV10TCL_RC_IN_ALPHA_B_MAPPING_SHIFT                                          21
+#define   NV10TCL_RC_IN_ALPHA_B_MAPPING_MASK                                           0x00e00000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_UNSIGNED_IDENTITY_NV                          0x00000000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT_NV                            0x00200000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_EXPAND_NORMAL_NV                              0x00400000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_EXPAND_NEGATE_NV                              0x00600000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NORMAL_NV                           0x00800000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NEGATE_NV                           0x00a00000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_SIGNED_IDENTITY_NV                            0x00c00000
+#define    NV10TCL_RC_IN_ALPHA_B_MAPPING_SIGNED_NEGATE_NV                              0x00e00000
+#define   NV10TCL_RC_IN_ALPHA_A_INPUT_SHIFT                                            24
+#define   NV10TCL_RC_IN_ALPHA_A_INPUT_MASK                                             0x0f000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_ZERO                                            0x00000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR0_NV                              0x01000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR1_NV                              0x02000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_FOG                                             0x03000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_PRIMARY_COLOR_NV                                        0x04000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SECONDARY_COLOR_NV                              0x05000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE0_ARB                                    0x08000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_TEXTURE1_ARB                                    0x09000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE0_NV                                       0x0c000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE1_NV                                       0x0d000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                  0x0e000000
+#define    NV10TCL_RC_IN_ALPHA_A_INPUT_E_TIMES_F_NV                                    0x0f000000
+#define   NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE                                                (1 << 28)
+#define    NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_BLUE                                  0x00000000
+#define    NV10TCL_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA                                 0x10000000
+#define   NV10TCL_RC_IN_ALPHA_A_MAPPING_SHIFT                                          29
+#define   NV10TCL_RC_IN_ALPHA_A_MAPPING_MASK                                           0xe0000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_UNSIGNED_IDENTITY_NV                          0x00000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT_NV                            0x20000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_EXPAND_NORMAL_NV                              0x40000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_EXPAND_NEGATE_NV                              0x60000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NORMAL_NV                           0x80000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NEGATE_NV                           0xa0000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_SIGNED_IDENTITY_NV                            0xc0000000
+#define    NV10TCL_RC_IN_ALPHA_A_MAPPING_SIGNED_NEGATE_NV                              0xe0000000
+#define  NV10TCL_RC_IN_RGB(x)                                                          (0x00000268+((x)*4))
+#define  NV10TCL_RC_IN_RGB__SIZE                                                       0x00000002
+#define   NV10TCL_RC_IN_RGB_D_INPUT_SHIFT                                              0
+#define   NV10TCL_RC_IN_RGB_D_INPUT_MASK                                               0x0000000f
+#define    NV10TCL_RC_IN_RGB_D_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_IN_RGB_D_INPUT_CONSTANT_COLOR0_NV                                        0x00000001
+#define    NV10TCL_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1_NV                                        0x00000002
+#define    NV10TCL_RC_IN_RGB_D_INPUT_FOG                                               0x00000003
+#define    NV10TCL_RC_IN_RGB_D_INPUT_PRIMARY_COLOR_NV                                  0x00000004
+#define    NV10TCL_RC_IN_RGB_D_INPUT_SECONDARY_COLOR_NV                                        0x00000005
+#define    NV10TCL_RC_IN_RGB_D_INPUT_TEXTURE0_ARB                                      0x00000008
+#define    NV10TCL_RC_IN_RGB_D_INPUT_TEXTURE1_ARB                                      0x00000009
+#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE0_NV                                         0x0000000c
+#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE1_NV                                         0x0000000d
+#define    NV10TCL_RC_IN_RGB_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x0000000e
+#define    NV10TCL_RC_IN_RGB_D_INPUT_E_TIMES_F_NV                                      0x0000000f
+#define   NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE                                          (1 <<  4)
+#define    NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_IN_RGB_D_COMPONENT_USAGE_ALPHA                                   0x00000010
+#define   NV10TCL_RC_IN_RGB_D_MAPPING_SHIFT                                            5
+#define   NV10TCL_RC_IN_RGB_D_MAPPING_MASK                                             0x000000e0
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT_NV                              0x00000020
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_EXPAND_NORMAL_NV                                        0x00000040
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_EXPAND_NEGATE_NV                                        0x00000060
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_HALF_BIAS_NORMAL_NV                             0x00000080
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_HALF_BIAS_NEGATE_NV                             0x000000a0
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_SIGNED_IDENTITY_NV                              0x000000c0
+#define    NV10TCL_RC_IN_RGB_D_MAPPING_SIGNED_NEGATE_NV                                        0x000000e0
+#define   NV10TCL_RC_IN_RGB_C_INPUT_SHIFT                                              8
+#define   NV10TCL_RC_IN_RGB_C_INPUT_MASK                                               0x00000f00
+#define    NV10TCL_RC_IN_RGB_C_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_IN_RGB_C_INPUT_CONSTANT_COLOR0_NV                                        0x00000100
+#define    NV10TCL_RC_IN_RGB_C_INPUT_CONSTANT_COLOR1_NV                                        0x00000200
+#define    NV10TCL_RC_IN_RGB_C_INPUT_FOG                                               0x00000300
+#define    NV10TCL_RC_IN_RGB_C_INPUT_PRIMARY_COLOR_NV                                  0x00000400
+#define    NV10TCL_RC_IN_RGB_C_INPUT_SECONDARY_COLOR_NV                                        0x00000500
+#define    NV10TCL_RC_IN_RGB_C_INPUT_TEXTURE0_ARB                                      0x00000800
+#define    NV10TCL_RC_IN_RGB_C_INPUT_TEXTURE1_ARB                                      0x00000900
+#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE0_NV                                         0x00000c00
+#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE1_NV                                         0x00000d00
+#define    NV10TCL_RC_IN_RGB_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x00000e00
+#define    NV10TCL_RC_IN_RGB_C_INPUT_E_TIMES_F_NV                                      0x00000f00
+#define   NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE                                          (1 << 12)
+#define    NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA                                   0x00001000
+#define   NV10TCL_RC_IN_RGB_C_MAPPING_SHIFT                                            13
+#define   NV10TCL_RC_IN_RGB_C_MAPPING_MASK                                             0x0000e000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT_NV                              0x00002000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_EXPAND_NORMAL_NV                                        0x00004000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_EXPAND_NEGATE_NV                                        0x00006000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_HALF_BIAS_NORMAL_NV                             0x00008000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_HALF_BIAS_NEGATE_NV                             0x0000a000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_SIGNED_IDENTITY_NV                              0x0000c000
+#define    NV10TCL_RC_IN_RGB_C_MAPPING_SIGNED_NEGATE_NV                                        0x0000e000
+#define   NV10TCL_RC_IN_RGB_B_INPUT_SHIFT                                              16
+#define   NV10TCL_RC_IN_RGB_B_INPUT_MASK                                               0x000f0000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0_NV                                        0x00010000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_CONSTANT_COLOR1_NV                                        0x00020000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_FOG                                               0x00030000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_PRIMARY_COLOR_NV                                  0x00040000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_SECONDARY_COLOR_NV                                        0x00050000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE0_ARB                                      0x00080000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_TEXTURE1_ARB                                      0x00090000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE0_NV                                         0x000c0000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE1_NV                                         0x000d0000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x000e0000
+#define    NV10TCL_RC_IN_RGB_B_INPUT_E_TIMES_F_NV                                      0x000f0000
+#define   NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE                                          (1 << 20)
+#define    NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA                                   0x00100000
+#define   NV10TCL_RC_IN_RGB_B_MAPPING_SHIFT                                            21
+#define   NV10TCL_RC_IN_RGB_B_MAPPING_MASK                                             0x00e00000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT_NV                              0x00200000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_EXPAND_NORMAL_NV                                        0x00400000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_EXPAND_NEGATE_NV                                        0x00600000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_HALF_BIAS_NORMAL_NV                             0x00800000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_HALF_BIAS_NEGATE_NV                             0x00a00000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_SIGNED_IDENTITY_NV                              0x00c00000
+#define    NV10TCL_RC_IN_RGB_B_MAPPING_SIGNED_NEGATE_NV                                        0x00e00000
+#define   NV10TCL_RC_IN_RGB_A_INPUT_SHIFT                                              24
+#define   NV10TCL_RC_IN_RGB_A_INPUT_MASK                                               0x0f000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_CONSTANT_COLOR0_NV                                        0x01000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_CONSTANT_COLOR1_NV                                        0x02000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_FOG                                               0x03000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_PRIMARY_COLOR_NV                                  0x04000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_SECONDARY_COLOR_NV                                        0x05000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE0_ARB                                      0x08000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_TEXTURE1_ARB                                      0x09000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE0_NV                                         0x0c000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE1_NV                                         0x0d000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x0e000000
+#define    NV10TCL_RC_IN_RGB_A_INPUT_E_TIMES_F_NV                                      0x0f000000
+#define   NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE                                          (1 << 28)
+#define    NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA                                   0x10000000
+#define   NV10TCL_RC_IN_RGB_A_MAPPING_SHIFT                                            29
+#define   NV10TCL_RC_IN_RGB_A_MAPPING_MASK                                             0xe0000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT_NV                              0x20000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_EXPAND_NORMAL_NV                                        0x40000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_EXPAND_NEGATE_NV                                        0x60000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_HALF_BIAS_NORMAL_NV                             0x80000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_HALF_BIAS_NEGATE_NV                             0xa0000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_SIGNED_IDENTITY_NV                              0xc0000000
+#define    NV10TCL_RC_IN_RGB_A_MAPPING_SIGNED_NEGATE_NV                                        0xe0000000
+#define  NV10TCL_RC_COLOR(x)                                                           (0x00000270+((x)*4))
+#define  NV10TCL_RC_COLOR__SIZE                                                                0x00000002
+#define   NV10TCL_RC_COLOR_B_SHIFT                                                     0
+#define   NV10TCL_RC_COLOR_B_MASK                                                      0x000000ff
+#define   NV10TCL_RC_COLOR_G_SHIFT                                                     8
+#define   NV10TCL_RC_COLOR_G_MASK                                                      0x0000ff00
+#define   NV10TCL_RC_COLOR_R_SHIFT                                                     16
+#define   NV10TCL_RC_COLOR_R_MASK                                                      0x00ff0000
+#define   NV10TCL_RC_COLOR_A_SHIFT                                                     24
+#define   NV10TCL_RC_COLOR_A_MASK                                                      0xff000000
+#define  NV10TCL_RC_OUT_ALPHA(x)                                                       (0x00000278+((x)*4))
+#define  NV10TCL_RC_OUT_ALPHA__SIZE                                                    0x00000002
+#define   NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SHIFT                                         0
+#define   NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_MASK                                          0x0000000f
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_ZERO                                         0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR0_NV                           0x00000001
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR1_NV                           0x00000002
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_FOG                                          0x00000003
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_PRIMARY_COLOR_NV                             0x00000004
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SECONDARY_COLOR_NV                           0x00000005
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE0_ARB                                 0x00000008
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE1_ARB                                 0x00000009
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_NV                                    0x0000000c
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE1_NV                                    0x0000000d
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV               0x0000000e
+#define    NV10TCL_RC_OUT_ALPHA_CD_OUTPUT_E_TIMES_F_NV                                 0x0000000f
+#define   NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SHIFT                                         4
+#define   NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_MASK                                          0x000000f0
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_ZERO                                         0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR0_NV                           0x00000010
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR1_NV                           0x00000020
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_FOG                                          0x00000030
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_PRIMARY_COLOR_NV                             0x00000040
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SECONDARY_COLOR_NV                           0x00000050
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE0_ARB                                 0x00000080
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE1_ARB                                 0x00000090
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_NV                                    0x000000c0
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE1_NV                                    0x000000d0
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV               0x000000e0
+#define    NV10TCL_RC_OUT_ALPHA_AB_OUTPUT_E_TIMES_F_NV                                 0x000000f0
+#define   NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SHIFT                                                8
+#define   NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_MASK                                         0x00000f00
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_ZERO                                                0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR0_NV                          0x00000100
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR1_NV                          0x00000200
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_FOG                                         0x00000300
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_PRIMARY_COLOR_NV                            0x00000400
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SECONDARY_COLOR_NV                          0x00000500
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE0_ARB                                        0x00000800
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE1_ARB                                        0x00000900
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_NV                                   0x00000c00
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE1_NV                                   0x00000d00
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV              0x00000e00
+#define    NV10TCL_RC_OUT_ALPHA_SUM_OUTPUT_E_TIMES_F_NV                                        0x00000f00
+#define   NV10TCL_RC_OUT_ALPHA_CD_DOT_PRODUCT                                          (1 << 12)
+#define   NV10TCL_RC_OUT_ALPHA_AB_DOT_PRODUCT                                          (1 << 13)
+#define   NV10TCL_RC_OUT_ALPHA_MUX_SUM                                                 (1 << 14)
+#define   NV10TCL_RC_OUT_ALPHA_BIAS                                                    (1 << 15)
+#define    NV10TCL_RC_OUT_ALPHA_BIAS_NONE                                              0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_BIAS_BIAS_BY_NEGATIVE_ONE_HALF_NV                      0x00008000
+#define   NV10TCL_RC_OUT_ALPHA_SCALE_SHIFT                                             17
+#define   NV10TCL_RC_OUT_ALPHA_SCALE_MASK                                              0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_SCALE_NONE                                             0x00000000
+#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_TWO_NV                                  0x00020000
+#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_FOUR_NV                                 0x00040000
+#define    NV10TCL_RC_OUT_ALPHA_SCALE_SCALE_BY_ONE_HALF_NV                             0x00060000
+#define  NV10TCL_RC_OUT_RGB(x)                                                         (0x00000280+((x)*4))
+#define  NV10TCL_RC_OUT_RGB__SIZE                                                      0x00000002
+#define   NV10TCL_RC_OUT_RGB_CD_OUTPUT_SHIFT                                           0
+#define   NV10TCL_RC_OUT_RGB_CD_OUTPUT_MASK                                            0x0000000f
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_ZERO                                           0x00000000
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR0_NV                             0x00000001
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR1_NV                             0x00000002
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_FOG                                            0x00000003
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_PRIMARY_COLOR_NV                               0x00000004
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SECONDARY_COLOR_NV                             0x00000005
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_TEXTURE0_ARB                                   0x00000008
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_TEXTURE1_ARB                                   0x00000009
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE0_NV                                      0x0000000c
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE1_NV                                      0x0000000d
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                 0x0000000e
+#define    NV10TCL_RC_OUT_RGB_CD_OUTPUT_E_TIMES_F_NV                                   0x0000000f
+#define   NV10TCL_RC_OUT_RGB_AB_OUTPUT_SHIFT                                           4
+#define   NV10TCL_RC_OUT_RGB_AB_OUTPUT_MASK                                            0x000000f0
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_ZERO                                           0x00000000
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR0_NV                             0x00000010
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR1_NV                             0x00000020
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_FOG                                            0x00000030
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_PRIMARY_COLOR_NV                               0x00000040
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SECONDARY_COLOR_NV                             0x00000050
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_TEXTURE0_ARB                                   0x00000080
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_TEXTURE1_ARB                                   0x00000090
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0_NV                                      0x000000c0
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE1_NV                                      0x000000d0
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                 0x000000e0
+#define    NV10TCL_RC_OUT_RGB_AB_OUTPUT_E_TIMES_F_NV                                   0x000000f0
+#define   NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SHIFT                                          8
+#define   NV10TCL_RC_OUT_RGB_SUM_OUTPUT_MASK                                           0x00000f00
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_ZERO                                          0x00000000
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR0_NV                            0x00000100
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR1_NV                            0x00000200
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_FOG                                           0x00000300
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_PRIMARY_COLOR_NV                              0x00000400
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SECONDARY_COLOR_NV                            0x00000500
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_TEXTURE0_ARB                                  0x00000800
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_TEXTURE1_ARB                                  0x00000900
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE0_NV                                     0x00000c00
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE1_NV                                     0x00000d00
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                        0x00000e00
+#define    NV10TCL_RC_OUT_RGB_SUM_OUTPUT_E_TIMES_F_NV                                  0x00000f00
+#define   NV10TCL_RC_OUT_RGB_CD_DOT_PRODUCT                                            (1 << 12)
+#define   NV10TCL_RC_OUT_RGB_AB_DOT_PRODUCT                                            (1 << 13)
+#define   NV10TCL_RC_OUT_RGB_MUX_SUM                                                   (1 << 14)
+#define   NV10TCL_RC_OUT_RGB_BIAS                                                      (1 << 15)
+#define    NV10TCL_RC_OUT_RGB_BIAS_NONE                                                        0x00000000
+#define    NV10TCL_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF_NV                                0x00008000
+#define   NV10TCL_RC_OUT_RGB_SCALE_SHIFT                                               17
+#define   NV10TCL_RC_OUT_RGB_SCALE_MASK                                                        0x00000000
+#define    NV10TCL_RC_OUT_RGB_SCALE_NONE                                               0x00000000
+#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_TWO_NV                                    0x00020000
+#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_FOUR_NV                                   0x00040000
+#define    NV10TCL_RC_OUT_RGB_SCALE_SCALE_BY_ONE_HALF_NV                               0x00060000
+#define   NV10TCL_RC_OUT_RGB_OPERATION_SHIFT                                           27
+#define   NV10TCL_RC_OUT_RGB_OPERATION_MASK                                            0x38000000
+#define  NV10TCL_RC_FINAL0                                                             0x00000288
+#define   NV10TCL_RC_FINAL0_D_INPUT_SHIFT                                              0
+#define   NV10TCL_RC_FINAL0_D_INPUT_MASK                                               0x0000000f
+#define    NV10TCL_RC_FINAL0_D_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL0_D_INPUT_CONSTANT_COLOR0_NV                                        0x00000001
+#define    NV10TCL_RC_FINAL0_D_INPUT_CONSTANT_COLOR1_NV                                        0x00000002
+#define    NV10TCL_RC_FINAL0_D_INPUT_FOG                                               0x00000003
+#define    NV10TCL_RC_FINAL0_D_INPUT_PRIMARY_COLOR_NV                                  0x00000004
+#define    NV10TCL_RC_FINAL0_D_INPUT_SECONDARY_COLOR_NV                                        0x00000005
+#define    NV10TCL_RC_FINAL0_D_INPUT_TEXTURE0_ARB                                      0x00000008
+#define    NV10TCL_RC_FINAL0_D_INPUT_TEXTURE1_ARB                                      0x00000009
+#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE0_NV                                         0x0000000c
+#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE1_NV                                         0x0000000d
+#define    NV10TCL_RC_FINAL0_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x0000000e
+#define    NV10TCL_RC_FINAL0_D_INPUT_E_TIMES_F_NV                                      0x0000000f
+#define   NV10TCL_RC_FINAL0_D_COMPONENT_USAGE                                          (1 <<  4)
+#define    NV10TCL_RC_FINAL0_D_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL0_D_COMPONENT_USAGE_ALPHA                                   0x00000010
+#define   NV10TCL_RC_FINAL0_D_MAPPING_SHIFT                                            5
+#define   NV10TCL_RC_FINAL0_D_MAPPING_MASK                                             0x000000e0
+#define    NV10TCL_RC_FINAL0_D_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL0_D_MAPPING_UNSIGNED_INVERT_NV                              0x00000020
+#define    NV10TCL_RC_FINAL0_D_MAPPING_EXPAND_NORMAL_NV                                        0x00000040
+#define    NV10TCL_RC_FINAL0_D_MAPPING_EXPAND_NEGATE_NV                                        0x00000060
+#define    NV10TCL_RC_FINAL0_D_MAPPING_HALF_BIAS_NORMAL_NV                             0x00000080
+#define    NV10TCL_RC_FINAL0_D_MAPPING_HALF_BIAS_NEGATE_NV                             0x000000a0
+#define    NV10TCL_RC_FINAL0_D_MAPPING_SIGNED_IDENTITY_NV                              0x000000c0
+#define    NV10TCL_RC_FINAL0_D_MAPPING_SIGNED_NEGATE_NV                                        0x000000e0
+#define   NV10TCL_RC_FINAL0_C_INPUT_SHIFT                                              8
+#define   NV10TCL_RC_FINAL0_C_INPUT_MASK                                               0x00000f00
+#define    NV10TCL_RC_FINAL0_C_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL0_C_INPUT_CONSTANT_COLOR0_NV                                        0x00000100
+#define    NV10TCL_RC_FINAL0_C_INPUT_CONSTANT_COLOR1_NV                                        0x00000200
+#define    NV10TCL_RC_FINAL0_C_INPUT_FOG                                               0x00000300
+#define    NV10TCL_RC_FINAL0_C_INPUT_PRIMARY_COLOR_NV                                  0x00000400
+#define    NV10TCL_RC_FINAL0_C_INPUT_SECONDARY_COLOR_NV                                        0x00000500
+#define    NV10TCL_RC_FINAL0_C_INPUT_TEXTURE0_ARB                                      0x00000800
+#define    NV10TCL_RC_FINAL0_C_INPUT_TEXTURE1_ARB                                      0x00000900
+#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE0_NV                                         0x00000c00
+#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE1_NV                                         0x00000d00
+#define    NV10TCL_RC_FINAL0_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x00000e00
+#define    NV10TCL_RC_FINAL0_C_INPUT_E_TIMES_F_NV                                      0x00000f00
+#define   NV10TCL_RC_FINAL0_C_COMPONENT_USAGE                                          (1 << 12)
+#define    NV10TCL_RC_FINAL0_C_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL0_C_COMPONENT_USAGE_ALPHA                                   0x00001000
+#define   NV10TCL_RC_FINAL0_C_MAPPING_SHIFT                                            13
+#define   NV10TCL_RC_FINAL0_C_MAPPING_MASK                                             0x0000e000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_UNSIGNED_INVERT_NV                              0x00002000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_EXPAND_NORMAL_NV                                        0x00004000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_EXPAND_NEGATE_NV                                        0x00006000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_HALF_BIAS_NORMAL_NV                             0x00008000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_HALF_BIAS_NEGATE_NV                             0x0000a000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_SIGNED_IDENTITY_NV                              0x0000c000
+#define    NV10TCL_RC_FINAL0_C_MAPPING_SIGNED_NEGATE_NV                                        0x0000e000
+#define   NV10TCL_RC_FINAL0_B_INPUT_SHIFT                                              16
+#define   NV10TCL_RC_FINAL0_B_INPUT_MASK                                               0x000f0000
+#define    NV10TCL_RC_FINAL0_B_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL0_B_INPUT_CONSTANT_COLOR0_NV                                        0x00010000
+#define    NV10TCL_RC_FINAL0_B_INPUT_CONSTANT_COLOR1_NV                                        0x00020000
+#define    NV10TCL_RC_FINAL0_B_INPUT_FOG                                               0x00030000
+#define    NV10TCL_RC_FINAL0_B_INPUT_PRIMARY_COLOR_NV                                  0x00040000
+#define    NV10TCL_RC_FINAL0_B_INPUT_SECONDARY_COLOR_NV                                        0x00050000
+#define    NV10TCL_RC_FINAL0_B_INPUT_TEXTURE0_ARB                                      0x00080000
+#define    NV10TCL_RC_FINAL0_B_INPUT_TEXTURE1_ARB                                      0x00090000
+#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE0_NV                                         0x000c0000
+#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE1_NV                                         0x000d0000
+#define    NV10TCL_RC_FINAL0_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x000e0000
+#define    NV10TCL_RC_FINAL0_B_INPUT_E_TIMES_F_NV                                      0x000f0000
+#define   NV10TCL_RC_FINAL0_B_COMPONENT_USAGE                                          (1 << 20)
+#define    NV10TCL_RC_FINAL0_B_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL0_B_COMPONENT_USAGE_ALPHA                                   0x00100000
+#define   NV10TCL_RC_FINAL0_B_MAPPING_SHIFT                                            21
+#define   NV10TCL_RC_FINAL0_B_MAPPING_MASK                                             0x00e00000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_UNSIGNED_INVERT_NV                              0x00200000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_EXPAND_NORMAL_NV                                        0x00400000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_EXPAND_NEGATE_NV                                        0x00600000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_HALF_BIAS_NORMAL_NV                             0x00800000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_HALF_BIAS_NEGATE_NV                             0x00a00000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_SIGNED_IDENTITY_NV                              0x00c00000
+#define    NV10TCL_RC_FINAL0_B_MAPPING_SIGNED_NEGATE_NV                                        0x00e00000
+#define   NV10TCL_RC_FINAL0_A_INPUT_SHIFT                                              24
+#define   NV10TCL_RC_FINAL0_A_INPUT_MASK                                               0x0f000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_CONSTANT_COLOR0_NV                                        0x01000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_CONSTANT_COLOR1_NV                                        0x02000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_FOG                                               0x03000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_PRIMARY_COLOR_NV                                  0x04000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_SECONDARY_COLOR_NV                                        0x05000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_TEXTURE0_ARB                                      0x08000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_TEXTURE1_ARB                                      0x09000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE0_NV                                         0x0c000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE1_NV                                         0x0d000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x0e000000
+#define    NV10TCL_RC_FINAL0_A_INPUT_E_TIMES_F_NV                                      0x0f000000
+#define   NV10TCL_RC_FINAL0_A_COMPONENT_USAGE                                          (1 << 28)
+#define    NV10TCL_RC_FINAL0_A_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL0_A_COMPONENT_USAGE_ALPHA                                   0x10000000
+#define   NV10TCL_RC_FINAL0_A_MAPPING_SHIFT                                            29
+#define   NV10TCL_RC_FINAL0_A_MAPPING_MASK                                             0xe0000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_UNSIGNED_INVERT_NV                              0x20000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_EXPAND_NORMAL_NV                                        0x40000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_EXPAND_NEGATE_NV                                        0x60000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_HALF_BIAS_NORMAL_NV                             0x80000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_HALF_BIAS_NEGATE_NV                             0xa0000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_SIGNED_IDENTITY_NV                              0xc0000000
+#define    NV10TCL_RC_FINAL0_A_MAPPING_SIGNED_NEGATE_NV                                        0xe0000000
+#define  NV10TCL_RC_FINAL1                                                             0x0000028c
+#define   NV10TCL_RC_FINAL1_COLOR_SUM_CLAMP                                            (1 <<  7)
+#define   NV10TCL_RC_FINAL1_G_INPUT_SHIFT                                              8
+#define   NV10TCL_RC_FINAL1_G_INPUT_MASK                                               0x00000f00
+#define    NV10TCL_RC_FINAL1_G_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL1_G_INPUT_CONSTANT_COLOR0_NV                                        0x00000100
+#define    NV10TCL_RC_FINAL1_G_INPUT_CONSTANT_COLOR1_NV                                        0x00000200
+#define    NV10TCL_RC_FINAL1_G_INPUT_FOG                                               0x00000300
+#define    NV10TCL_RC_FINAL1_G_INPUT_PRIMARY_COLOR_NV                                  0x00000400
+#define    NV10TCL_RC_FINAL1_G_INPUT_SECONDARY_COLOR_NV                                        0x00000500
+#define    NV10TCL_RC_FINAL1_G_INPUT_TEXTURE0_ARB                                      0x00000800
+#define    NV10TCL_RC_FINAL1_G_INPUT_TEXTURE1_ARB                                      0x00000900
+#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE0_NV                                         0x00000c00
+#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE1_NV                                         0x00000d00
+#define    NV10TCL_RC_FINAL1_G_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x00000e00
+#define    NV10TCL_RC_FINAL1_G_INPUT_E_TIMES_F_NV                                      0x00000f00
+#define   NV10TCL_RC_FINAL1_G_COMPONENT_USAGE                                          (1 << 12)
+#define    NV10TCL_RC_FINAL1_G_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL1_G_COMPONENT_USAGE_ALPHA                                   0x00001000
+#define   NV10TCL_RC_FINAL1_G_MAPPING_SHIFT                                            13
+#define   NV10TCL_RC_FINAL1_G_MAPPING_MASK                                             0x0000e000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_UNSIGNED_INVERT_NV                              0x00002000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_EXPAND_NORMAL_NV                                        0x00004000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_EXPAND_NEGATE_NV                                        0x00006000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_HALF_BIAS_NORMAL_NV                             0x00008000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_HALF_BIAS_NEGATE_NV                             0x0000a000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_SIGNED_IDENTITY_NV                              0x0000c000
+#define    NV10TCL_RC_FINAL1_G_MAPPING_SIGNED_NEGATE_NV                                        0x0000e000
+#define   NV10TCL_RC_FINAL1_F_INPUT_SHIFT                                              16
+#define   NV10TCL_RC_FINAL1_F_INPUT_MASK                                               0x000f0000
+#define    NV10TCL_RC_FINAL1_F_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL1_F_INPUT_CONSTANT_COLOR0_NV                                        0x00010000
+#define    NV10TCL_RC_FINAL1_F_INPUT_CONSTANT_COLOR1_NV                                        0x00020000
+#define    NV10TCL_RC_FINAL1_F_INPUT_FOG                                               0x00030000
+#define    NV10TCL_RC_FINAL1_F_INPUT_PRIMARY_COLOR_NV                                  0x00040000
+#define    NV10TCL_RC_FINAL1_F_INPUT_SECONDARY_COLOR_NV                                        0x00050000
+#define    NV10TCL_RC_FINAL1_F_INPUT_TEXTURE0_ARB                                      0x00080000
+#define    NV10TCL_RC_FINAL1_F_INPUT_TEXTURE1_ARB                                      0x00090000
+#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE0_NV                                         0x000c0000
+#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE1_NV                                         0x000d0000
+#define    NV10TCL_RC_FINAL1_F_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x000e0000
+#define    NV10TCL_RC_FINAL1_F_INPUT_E_TIMES_F_NV                                      0x000f0000
+#define   NV10TCL_RC_FINAL1_F_COMPONENT_USAGE                                          (1 << 20)
+#define    NV10TCL_RC_FINAL1_F_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL1_F_COMPONENT_USAGE_ALPHA                                   0x00100000
+#define   NV10TCL_RC_FINAL1_F_MAPPING_SHIFT                                            21
+#define   NV10TCL_RC_FINAL1_F_MAPPING_MASK                                             0x00e00000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_UNSIGNED_INVERT_NV                              0x00200000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_EXPAND_NORMAL_NV                                        0x00400000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_EXPAND_NEGATE_NV                                        0x00600000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_HALF_BIAS_NORMAL_NV                             0x00800000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_HALF_BIAS_NEGATE_NV                             0x00a00000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_SIGNED_IDENTITY_NV                              0x00c00000
+#define    NV10TCL_RC_FINAL1_F_MAPPING_SIGNED_NEGATE_NV                                        0x00e00000
+#define   NV10TCL_RC_FINAL1_E_INPUT_SHIFT                                              24
+#define   NV10TCL_RC_FINAL1_E_INPUT_MASK                                               0x0f000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_ZERO                                              0x00000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_CONSTANT_COLOR0_NV                                        0x01000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_CONSTANT_COLOR1_NV                                        0x02000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_FOG                                               0x03000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_PRIMARY_COLOR_NV                                  0x04000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_SECONDARY_COLOR_NV                                        0x05000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_TEXTURE0_ARB                                      0x08000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_TEXTURE1_ARB                                      0x09000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE0_NV                                         0x0c000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE1_NV                                         0x0d000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_SPARE0_PLUS_SECONDARY_COLOR_NV                    0x0e000000
+#define    NV10TCL_RC_FINAL1_E_INPUT_E_TIMES_F_NV                                      0x0f000000
+#define   NV10TCL_RC_FINAL1_E_COMPONENT_USAGE                                          (1 << 28)
+#define    NV10TCL_RC_FINAL1_E_COMPONENT_USAGE_RGB                                     0x00000000
+#define    NV10TCL_RC_FINAL1_E_COMPONENT_USAGE_ALPHA                                   0x10000000
+#define   NV10TCL_RC_FINAL1_E_MAPPING_SHIFT                                            29
+#define   NV10TCL_RC_FINAL1_E_MAPPING_MASK                                             0xe0000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_UNSIGNED_IDENTITY_NV                            0x00000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_UNSIGNED_INVERT_NV                              0x20000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_EXPAND_NORMAL_NV                                        0x40000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_EXPAND_NEGATE_NV                                        0x60000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_HALF_BIAS_NORMAL_NV                             0x80000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_HALF_BIAS_NEGATE_NV                             0xa0000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_SIGNED_IDENTITY_NV                              0xc0000000
+#define    NV10TCL_RC_FINAL1_E_MAPPING_SIGNED_NEGATE_NV                                        0xe0000000
+#define  NV10TCL_LIGHT_MODEL                                                           0x00000294
+#define   NV10TCL_LIGHT_MODEL_COLOR_CONTROL                                            (1 <<  1)
+#define   NV10TCL_LIGHT_MODEL_LOCAL_VIEWER                                             (1 << 16)
+#define  NV10TCL_COLOR_MATERIAL_ENABLE                                                 0x00000298
+#define   NV10TCL_COLOR_MATERIAL_ENABLE_SPECULAR                                       (1 <<  0)
+#define   NV10TCL_COLOR_MATERIAL_ENABLE_DIFFUSE                                                (1 <<  1)
+#define   NV10TCL_COLOR_MATERIAL_ENABLE_AMBIENT                                                (1 <<  2)
+#define   NV10TCL_COLOR_MATERIAL_ENABLE_EMISSION                                       (1 <<  3)
+#define  NV10TCL_FOG_MODE                                                              0x0000029c
+#define   NV10TCL_FOG_MODE_EXP                                                         0x00000800
+#define   NV10TCL_FOG_MODE_EXP_2                                                       0x00000802
+#define   NV10TCL_FOG_MODE_EXP2                                                                0x00000803
+#define   NV10TCL_FOG_MODE_LINEAR                                                      0x00000804
+#define   NV10TCL_FOG_MODE_LINEAR_2                                                    0x00002601
+#define  NV10TCL_FOG_COORD_DIST                                                                0x000002a0
+#define  NV10TCL_FOG_ENABLE                                                            0x000002a4
+#define  NV10TCL_FOG_COLOR                                                             0x000002a8
+#define   NV10TCL_FOG_COLOR_R_SHIFT                                                    0
+#define   NV10TCL_FOG_COLOR_R_MASK                                                     0x000000ff
+#define   NV10TCL_FOG_COLOR_G_SHIFT                                                    8
+#define   NV10TCL_FOG_COLOR_G_MASK                                                     0x0000ff00
+#define   NV10TCL_FOG_COLOR_B_SHIFT                                                    16
+#define   NV10TCL_FOG_COLOR_B_MASK                                                     0x00ff0000
+#define   NV10TCL_FOG_COLOR_A_SHIFT                                                    24
+#define   NV10TCL_FOG_COLOR_A_MASK                                                     0xff000000
+#define  NV10TCL_VIEWPORT_CLIP_MODE                                                    0x000002b4
+#define  NV10TCL_VIEWPORT_CLIP_HORIZ(x)                                                        (0x000002c0+((x)*4))
+#define  NV10TCL_VIEWPORT_CLIP_HORIZ__SIZE                                             0x00000008
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_L_SHIFT                                     0
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_L_MASK                                      0x000007ff
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_LEFT_ENABLE                                 (1 << 11)
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_R_SHIFT                                     16
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_R_MASK                                      0x07ff0000
+#define   NV10TCL_VIEWPORT_CLIP_HORIZ_CLIP_RIGHT_ENABLE                                        (1 << 27)
+#define  NV10TCL_VIEWPORT_CLIP_VERT(x)                                                 (0x000002e0+((x)*4))
+#define  NV10TCL_VIEWPORT_CLIP_VERT__SIZE                                              0x00000008
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_T_SHIFT                                      0
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_T_MASK                                       0x000007ff
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_TOP_ENABLE                                   (1 << 11)
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_B_SHIFT                                      16
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_B_MASK                                       0x07ff0000
+#define   NV10TCL_VIEWPORT_CLIP_VERT_CLIP_BOTTOM_ENABLE                                        (1 << 27)
+#define  NV10TCL_ALPHA_FUNC_ENABLE                                                     0x00000300
+#define  NV10TCL_BLEND_FUNC_ENABLE                                                     0x00000304
+#define  NV10TCL_CULL_FACE_ENABLE                                                      0x00000308
+#define  NV10TCL_DEPTH_TEST_ENABLE                                                     0x0000030c
+#define  NV10TCL_DITHER_ENABLE                                                         0x00000310
+#define  NV10TCL_LIGHTING_ENABLE                                                       0x00000314
+#define  NV10TCL_POINT_PARAMETERS_ENABLE                                               0x00000318
+#define  NV10TCL_POINT_SMOOTH_ENABLE                                                   0x0000031c
+#define  NV10TCL_LINE_SMOOTH_ENABLE                                                    0x00000320
+#define  NV10TCL_POLYGON_SMOOTH_ENABLE                                                 0x00000324
+#define  NV10TCL_VERTEX_WEIGHT_ENABLE                                                  0x00000328
+#define  NV10TCL_STENCIL_ENABLE                                                                0x0000032c
+#define  NV10TCL_POLYGON_OFFSET_POINT_ENABLE                                           0x00000330
+#define  NV10TCL_POLYGON_OFFSET_LINE_ENABLE                                            0x00000334
+#define  NV10TCL_POLYGON_OFFSET_FILL_ENABLE                                            0x00000338
+#define  NV10TCL_ALPHA_FUNC_FUNC                                                       0x0000033c
+#define   NV10TCL_ALPHA_FUNC_FUNC_NEVER                                                        0x00000200
+#define   NV10TCL_ALPHA_FUNC_FUNC_LESS                                                 0x00000201
+#define   NV10TCL_ALPHA_FUNC_FUNC_EQUAL                                                        0x00000202
+#define   NV10TCL_ALPHA_FUNC_FUNC_LEQUAL                                               0x00000203
+#define   NV10TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV10TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV10TCL_ALPHA_FUNC_FUNC_NOTEQUAL                                             0x00000205
+#define   NV10TCL_ALPHA_FUNC_FUNC_GEQUAL                                               0x00000206
+#define   NV10TCL_ALPHA_FUNC_FUNC_ALWAYS                                               0x00000207
+#define  NV10TCL_ALPHA_FUNC_REF                                                                0x00000340
+#define  NV10TCL_BLEND_FUNC_SRC                                                                0x00000344
+#define   NV10TCL_BLEND_FUNC_SRC_ZERO                                                  0x00000000
+#define   NV10TCL_BLEND_FUNC_SRC_ONE                                                   0x00000001
+#define   NV10TCL_BLEND_FUNC_SRC_SRC_COLOR                                             0x00000300
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR                                   0x00000301
+#define   NV10TCL_BLEND_FUNC_SRC_SRC_ALPHA                                             0x00000302
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA                                   0x00000303
+#define   NV10TCL_BLEND_FUNC_SRC_DST_ALPHA                                             0x00000304
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA                                   0x00000305
+#define   NV10TCL_BLEND_FUNC_SRC_DST_COLOR                                             0x00000306
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR                                   0x00000307
+#define   NV10TCL_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE                                    0x00000308
+#define   NV10TCL_BLEND_FUNC_SRC_CONSTANT_COLOR                                                0x00008001
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR                              0x00008002
+#define   NV10TCL_BLEND_FUNC_SRC_CONSTANT_ALPHA                                                0x00008003
+#define   NV10TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA                              0x00008004
+#define  NV10TCL_BLEND_FUNC_DST                                                                0x00000348
+#define   NV10TCL_BLEND_FUNC_DST_ZERO                                                  0x00000000
+#define   NV10TCL_BLEND_FUNC_DST_ONE                                                   0x00000001
+#define   NV10TCL_BLEND_FUNC_DST_SRC_COLOR                                             0x00000300
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR                                   0x00000301
+#define   NV10TCL_BLEND_FUNC_DST_SRC_ALPHA                                             0x00000302
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA                                   0x00000303
+#define   NV10TCL_BLEND_FUNC_DST_DST_ALPHA                                             0x00000304
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA                                   0x00000305
+#define   NV10TCL_BLEND_FUNC_DST_DST_COLOR                                             0x00000306
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR                                   0x00000307
+#define   NV10TCL_BLEND_FUNC_DST_SRC_ALPHA_SATURATE                                    0x00000308
+#define   NV10TCL_BLEND_FUNC_DST_CONSTANT_COLOR                                                0x00008001
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR                              0x00008002
+#define   NV10TCL_BLEND_FUNC_DST_CONSTANT_ALPHA                                                0x00008003
+#define   NV10TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA                              0x00008004
+#define  NV10TCL_BLEND_COLOR                                                           0x0000034c
+#define   NV10TCL_BLEND_COLOR_B_SHIFT                                                  0
+#define   NV10TCL_BLEND_COLOR_B_MASK                                                   0x000000ff
+#define   NV10TCL_BLEND_COLOR_G_SHIFT                                                  8
+#define   NV10TCL_BLEND_COLOR_G_MASK                                                   0x0000ff00
+#define   NV10TCL_BLEND_COLOR_R_SHIFT                                                  16
+#define   NV10TCL_BLEND_COLOR_R_MASK                                                   0x00ff0000
+#define   NV10TCL_BLEND_COLOR_A_SHIFT                                                  24
+#define   NV10TCL_BLEND_COLOR_A_MASK                                                   0xff000000
+#define  NV10TCL_BLEND_EQUATION                                                                0x00000350
+#define   NV10TCL_BLEND_EQUATION_FUNC_ADD                                              0x00008006
+#define   NV10TCL_BLEND_EQUATION_MIN                                                   0x00008007
+#define   NV10TCL_BLEND_EQUATION_MAX                                                   0x00008008
+#define   NV10TCL_BLEND_EQUATION_FUNC_SUBTRACT                                         0x0000800a
+#define   NV10TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT                                 0x0000800b
+#define  NV10TCL_DEPTH_FUNC                                                            0x00000354
+#define   NV10TCL_DEPTH_FUNC_NEVER                                                     0x00000200
+#define   NV10TCL_DEPTH_FUNC_LESS                                                      0x00000201
+#define   NV10TCL_DEPTH_FUNC_EQUAL                                                     0x00000202
+#define   NV10TCL_DEPTH_FUNC_LEQUAL                                                    0x00000203
+#define   NV10TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV10TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV10TCL_DEPTH_FUNC_NOTEQUAL                                                  0x00000205
+#define   NV10TCL_DEPTH_FUNC_GEQUAL                                                    0x00000206
+#define   NV10TCL_DEPTH_FUNC_ALWAYS                                                    0x00000207
+#define  NV10TCL_COLOR_MASK                                                            0x00000358
+#define   NV10TCL_COLOR_MASK_B                                                         (1 <<  0)
+#define   NV10TCL_COLOR_MASK_G                                                         (1 <<  8)
+#define   NV10TCL_COLOR_MASK_R                                                         (1 << 16)
+#define   NV10TCL_COLOR_MASK_A                                                         (1 << 24)
+#define  NV10TCL_DEPTH_WRITE_ENABLE                                                    0x0000035c
+#define  NV10TCL_STENCIL_MASK                                                          0x00000360
+#define  NV10TCL_STENCIL_FUNC_FUNC                                                     0x00000364
+#define   NV10TCL_STENCIL_FUNC_FUNC_NEVER                                              0x00000200
+#define   NV10TCL_STENCIL_FUNC_FUNC_LESS                                               0x00000201
+#define   NV10TCL_STENCIL_FUNC_FUNC_EQUAL                                              0x00000202
+#define   NV10TCL_STENCIL_FUNC_FUNC_LEQUAL                                             0x00000203
+#define   NV10TCL_STENCIL_FUNC_FUNC_GREATER                                            0x00000204
+#define   NV10TCL_STENCIL_FUNC_FUNC_GREATER                                            0x00000204
+#define   NV10TCL_STENCIL_FUNC_FUNC_NOTEQUAL                                           0x00000205
+#define   NV10TCL_STENCIL_FUNC_FUNC_GEQUAL                                             0x00000206
+#define   NV10TCL_STENCIL_FUNC_FUNC_ALWAYS                                             0x00000207
+#define  NV10TCL_STENCIL_FUNC_REF                                                      0x00000368
+#define  NV10TCL_STENCIL_FUNC_MASK                                                     0x0000036c
+#define  NV10TCL_STENCIL_OP_FAIL                                                       0x00000370
+#define   NV10TCL_STENCIL_OP_FAIL_ZERO                                                 0x00000000
+#define   NV10TCL_STENCIL_OP_FAIL_INVERT                                               0x0000150a
+#define   NV10TCL_STENCIL_OP_FAIL_KEEP                                                 0x00001e00
+#define   NV10TCL_STENCIL_OP_FAIL_REPLACE                                              0x00001e01
+#define   NV10TCL_STENCIL_OP_FAIL_INCR                                                 0x00001e02
+#define   NV10TCL_STENCIL_OP_FAIL_DECR                                                 0x00001e03
+#define   NV10TCL_STENCIL_OP_FAIL_INCR_WRAP                                            0x00008507
+#define   NV10TCL_STENCIL_OP_FAIL_DECR_WRAP                                            0x00008508
+#define  NV10TCL_STENCIL_OP_ZFAIL                                                      0x00000374
+#define   NV10TCL_STENCIL_OP_ZFAIL_ZERO                                                        0x00000000
+#define   NV10TCL_STENCIL_OP_ZFAIL_INVERT                                              0x0000150a
+#define   NV10TCL_STENCIL_OP_ZFAIL_KEEP                                                        0x00001e00
+#define   NV10TCL_STENCIL_OP_ZFAIL_REPLACE                                             0x00001e01
+#define   NV10TCL_STENCIL_OP_ZFAIL_INCR                                                        0x00001e02
+#define   NV10TCL_STENCIL_OP_ZFAIL_DECR                                                        0x00001e03
+#define   NV10TCL_STENCIL_OP_ZFAIL_INCR_WRAP                                           0x00008507
+#define   NV10TCL_STENCIL_OP_ZFAIL_DECR_WRAP                                           0x00008508
+#define  NV10TCL_STENCIL_OP_ZPASS                                                      0x00000378
+#define   NV10TCL_STENCIL_OP_ZPASS_ZERO                                                        0x00000000
+#define   NV10TCL_STENCIL_OP_ZPASS_INVERT                                              0x0000150a
+#define   NV10TCL_STENCIL_OP_ZPASS_KEEP                                                        0x00001e00
+#define   NV10TCL_STENCIL_OP_ZPASS_REPLACE                                             0x00001e01
+#define   NV10TCL_STENCIL_OP_ZPASS_INCR                                                        0x00001e02
+#define   NV10TCL_STENCIL_OP_ZPASS_DECR                                                        0x00001e03
+#define   NV10TCL_STENCIL_OP_ZPASS_INCR_WRAP                                           0x00008507
+#define   NV10TCL_STENCIL_OP_ZPASS_DECR_WRAP                                           0x00008508
+#define  NV10TCL_SHADE_MODEL                                                           0x0000037c
+#define   NV10TCL_SHADE_MODEL_FLAT                                                     0x00001d00
+#define   NV10TCL_SHADE_MODEL_SMOOTH                                                   0x00001d01
+#define  NV10TCL_LINE_WIDTH                                                            0x00000380
+#define  NV10TCL_POLYGON_OFFSET_FACTOR                                                 0x00000384
+#define  NV10TCL_POLYGON_OFFSET_UNITS                                                  0x00000388
+#define  NV10TCL_POLYGON_MODE_FRONT                                                    0x0000038c
+#define   NV10TCL_POLYGON_MODE_FRONT_POINT                                             0x00001b00
+#define   NV10TCL_POLYGON_MODE_FRONT_LINE                                              0x00001b01
+#define   NV10TCL_POLYGON_MODE_FRONT_FILL                                              0x00001b02
+#define  NV10TCL_POLYGON_MODE_BACK                                                     0x00000390
+#define   NV10TCL_POLYGON_MODE_BACK_POINT                                              0x00001b00
+#define   NV10TCL_POLYGON_MODE_BACK_LINE                                               0x00001b01
+#define   NV10TCL_POLYGON_MODE_BACK_FILL                                               0x00001b02
+#define  NV10TCL_DEPTH_RANGE_NEAR                                                      0x00000394
+#define  NV10TCL_DEPTH_RANGE_FAR                                                       0x00000398
+#define  NV10TCL_CULL_FACE                                                             0x0000039c
+#define   NV10TCL_CULL_FACE_FRONT                                                      0x00000404
+#define   NV10TCL_CULL_FACE_BACK                                                       0x00000405
+#define   NV10TCL_CULL_FACE_FRONT_AND_BACK                                             0x00000408
+#define  NV10TCL_FRONT_FACE                                                            0x000003a0
+#define   NV10TCL_FRONT_FACE_CW                                                                0x00000900
+#define   NV10TCL_FRONT_FACE_CCW                                                       0x00000901
+#define  NV10TCL_NORMALIZE_ENABLE                                                      0x000003a4
+#define  NV10TCL_COLOR_MATERIAL_R                                                      0x000003a8
+#define  NV10TCL_COLOR_MATERIAL_G                                                      0x000003ac
+#define  NV10TCL_COLOR_MATERIAL_B                                                      0x000003b0
+#define  NV10TCL_COLOR_MATERIAL_A                                                      0x000003b4
+#define  NV10TCL_COLOR_CONTROL                                                         0x000003b8
+#define  NV10TCL_ENABLED_LIGHTS                                                                0x000003bc
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT0                                                        (1 <<  0)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT1                                                        (1 <<  2)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT2                                                        (1 <<  4)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT3                                                        (1 <<  6)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT4                                                        (1 <<  8)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT5                                                        (1 << 10)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT6                                                        (1 << 12)
+#define   NV10TCL_ENABLED_LIGHTS_LIGHT7                                                        (1 << 14)
+#define  NV10TCL_CLIP_PLANE_ENABLE(x)                                                  (0x000003c0+((x)*4))
+#define  NV10TCL_CLIP_PLANE_ENABLE__SIZE                                               0x00000008
+#define   NV10TCL_CLIP_PLANE_ENABLE_FALSE                                              0x00000000
+#define   NV10TCL_CLIP_PLANE_ENABLE_EYE_LINEAR                                         0x00002400
+#define   NV10TCL_CLIP_PLANE_ENABLE_OBJECT_LINEAR                                      0x00002401
+#define  NV10TCL_TX_MATRIX_ENABLE(x)                                                   (0x000003e0+((x)*4))
+#define  NV10TCL_TX_MATRIX_ENABLE__SIZE                                                        0x00000002
+#define  NV10TCL_VIEW_MATRIX_ENABLE                                                    0x000003e8
+#define   NV10TCL_VIEW_MATRIX_ENABLE_MODELVIEW1                                                (1 <<  0)
+#define   NV10TCL_VIEW_MATRIX_ENABLE_MODELVIEW0                                                (1 <<  1)
+#define   NV10TCL_VIEW_MATRIX_ENABLE_PROJECTION                                                (1 <<  2)
+#define  NV10TCL_POINT_SIZE                                                            0x000003ec
+#define  NV10TCL_MODELVIEW0_MATRIX(x)                                                  (0x00000400+((x)*4))
+#define  NV10TCL_MODELVIEW0_MATRIX__SIZE                                               0x00000010
+#define  NV10TCL_MODELVIEW1_MATRIX(x)                                                  (0x00000440+((x)*4))
+#define  NV10TCL_MODELVIEW1_MATRIX__SIZE                                               0x00000010
+#define  NV10TCL_INVERSE_MODELVIEW0_MATRIX(x)                                          (0x00000480+((x)*4))
+#define  NV10TCL_INVERSE_MODELVIEW0_MATRIX__SIZE                                       0x00000010
+#define  NV10TCL_INVERSE_MODELVIEW1_MATRIX(x)                                          (0x000004c0+((x)*4))
+#define  NV10TCL_INVERSE_MODELVIEW1_MATRIX__SIZE                                       0x00000010
+#define  NV10TCL_PROJECTION_MATRIX(x)                                                  (0x00000500+((x)*4))
+#define  NV10TCL_PROJECTION_MATRIX__SIZE                                               0x00000010
+#define  NV10TCL_TX0_MATRIX(x)                                                         (0x00000540+((x)*4))
+#define  NV10TCL_TX0_MATRIX__SIZE                                                      0x00000010
+#define  NV10TCL_TX1_MATRIX(x)                                                         (0x00000580+((x)*4))
+#define  NV10TCL_TX1_MATRIX__SIZE                                                      0x00000010
+#define  NV10TCL_CLIP_PLANE_A(x)                                                       (0x00000600+((x)*16))
+#define  NV10TCL_CLIP_PLANE_A__SIZE                                                    0x00000008
+#define  NV10TCL_CLIP_PLANE_B(x)                                                       (0x00000604+((x)*16))
+#define  NV10TCL_CLIP_PLANE_B__SIZE                                                    0x00000008
+#define  NV10TCL_CLIP_PLANE_C(x)                                                       (0x00000608+((x)*16))
+#define  NV10TCL_CLIP_PLANE_C__SIZE                                                    0x00000008
+#define  NV10TCL_CLIP_PLANE_D(x)                                                       (0x0000060c+((x)*16))
+#define  NV10TCL_CLIP_PLANE_D__SIZE                                                    0x00000008
+#define  NV10TCL_FOG_EQUATION_CONSTANT                                                 0x00000680
+#define  NV10TCL_FOG_EQUATION_LINEAR                                                   0x00000684
+#define  NV10TCL_FOG_EQUATION_QUADRATIC                                                        0x00000688
+#define  NV10TCL_FRONT_MATERIAL_SHININESS(x)                                           (0x000006a0+((x)*4))
+#define  NV10TCL_FRONT_MATERIAL_SHININESS__SIZE                                                0x00000006
+#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R                        0x000006c4
+#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G                        0x000006c8
+#define  NV10TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B                        0x000006cc
+#define  NV10TCL_VIEWPORT_SCALE_X                                                      0x000006e8
+#define  NV10TCL_VIEWPORT_SCALE_Y                                                      0x000006ec
+#define  NV10TCL_VIEWPORT_SCALE_Z                                                      0x000006f0
+#define  NV10TCL_VIEWPORT_SCALE_W                                                      0x000006f4
+#define  NV10TCL_POINT_PARAMETER(x)                                                    (0x000006f8+((x)*4))
+#define  NV10TCL_POINT_PARAMETER__SIZE                                                 0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(x)                                 (0x00000800+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(x)                                 (0x00000804+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(x)                                 (0x00000808+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(x)                                 (0x0000080c+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(x)                                 (0x00000810+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(x)                                 (0x00000814+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B__SIZE                              0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(x)                                        (0x00000818+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R__SIZE                             0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(x)                                        (0x0000081c+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G__SIZE                             0x00000008
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(x)                                        (0x00000820+((x)*128))
+#define  NV10TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B__SIZE                             0x00000008
+#define  NV10TCL_LIGHT_HALF_VECTOR_X(x)                                                        (0x00000828+((x)*128))
+#define  NV10TCL_LIGHT_HALF_VECTOR_X__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_HALF_VECTOR_Y(x)                                                        (0x0000082c+((x)*128))
+#define  NV10TCL_LIGHT_HALF_VECTOR_Y__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_HALF_VECTOR_Z(x)                                                        (0x00000830+((x)*128))
+#define  NV10TCL_LIGHT_HALF_VECTOR_Z__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_DIRECTION_X(x)                                                  (0x00000834+((x)*128))
+#define  NV10TCL_LIGHT_DIRECTION_X__SIZE                                               0x00000008
+#define  NV10TCL_LIGHT_DIRECTION_Y(x)                                                  (0x00000838+((x)*128))
+#define  NV10TCL_LIGHT_DIRECTION_Y__SIZE                                               0x00000008
+#define  NV10TCL_LIGHT_DIRECTION_Z(x)                                                  (0x0000083c+((x)*128))
+#define  NV10TCL_LIGHT_DIRECTION_Z__SIZE                                               0x00000008
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_A(x)                                                        (0x00000840+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_A__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_B(x)                                                        (0x00000844+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_B__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_C(x)                                                        (0x00000848+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_C__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_SPOT_DIR_X(x)                                                   (0x0000084c+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_DIR_X__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_SPOT_DIR_Y(x)                                                   (0x00000850+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_DIR_Y__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_SPOT_DIR_Z(x)                                                   (0x00000854+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_DIR_Z__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_D(x)                                                        (0x00000858+((x)*128))
+#define  NV10TCL_LIGHT_SPOT_CUTOFF_D__SIZE                                             0x00000008
+#define  NV10TCL_LIGHT_POSITION_X(x)                                                   (0x0000085c+((x)*128))
+#define  NV10TCL_LIGHT_POSITION_X__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_POSITION_Y(x)                                                   (0x00000860+((x)*128))
+#define  NV10TCL_LIGHT_POSITION_Y__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_POSITION_Z(x)                                                   (0x00000864+((x)*128))
+#define  NV10TCL_LIGHT_POSITION_Z__SIZE                                                        0x00000008
+#define  NV10TCL_LIGHT_ATTENUATION_CONSTANT(x)                                         (0x00000868+((x)*128))
+#define  NV10TCL_LIGHT_ATTENUATION_CONSTANT__SIZE                                      0x00000008
+#define  NV10TCL_LIGHT_ATTENUATION_LINEAR(x)                                           (0x0000086c+((x)*128))
+#define  NV10TCL_LIGHT_ATTENUATION_LINEAR__SIZE                                                0x00000008
+#define  NV10TCL_LIGHT_ATTENUATION_QUADRATIC(x)                                                (0x00000870+((x)*128))
+#define  NV10TCL_LIGHT_ATTENUATION_QUADRATIC__SIZE                                     0x00000008
+#define  NV10TCL_VERTEX_POS_3F_X                                                       0x00000c00
+#define  NV10TCL_VERTEX_POS_3F_Y                                                       0x00000c04
+#define  NV10TCL_VERTEX_POS_3F_Z                                                       0x00000c08
+#define  NV10TCL_VERTEX_POS_4F_X                                                       0x00000c18
+#define  NV10TCL_VERTEX_POS_4F_Y                                                       0x00000c1c
+#define  NV10TCL_VERTEX_POS_4F_Z                                                       0x00000c20
+#define  NV10TCL_VERTEX_POS_4F_W                                                       0x00000c24
+#define  NV10TCL_VERTEX_NOR_3F_X                                                       0x00000c30
+#define  NV10TCL_VERTEX_NOR_3F_Y                                                       0x00000c34
+#define  NV10TCL_VERTEX_NOR_3F_Z                                                       0x00000c38
+#define  NV10TCL_VERTEX_NOR_3I_XY                                                      0x00000c40
+#define   NV10TCL_VERTEX_NOR_3I_XY_X_SHIFT                                             0
+#define   NV10TCL_VERTEX_NOR_3I_XY_X_MASK                                              0x0000ffff
+#define   NV10TCL_VERTEX_NOR_3I_XY_Y_SHIFT                                             16
+#define   NV10TCL_VERTEX_NOR_3I_XY_Y_MASK                                              0xffff0000
+#define  NV10TCL_VERTEX_NOR_3I_Z                                                       0x00000c44
+#define   NV10TCL_VERTEX_NOR_3I_Z_Z_SHIFT                                              0
+#define   NV10TCL_VERTEX_NOR_3I_Z_Z_MASK                                               0x0000ffff
+#define  NV10TCL_VERTEX_COL_4F_R                                                       0x00000c50
+#define  NV10TCL_VERTEX_COL_4F_G                                                       0x00000c54
+#define  NV10TCL_VERTEX_COL_4F_B                                                       0x00000c58
+#define  NV10TCL_VERTEX_COL_4F_A                                                       0x00000c5c
+#define  NV10TCL_VERTEX_COL_3F_R                                                       0x00000c60
+#define  NV10TCL_VERTEX_COL_3F_G                                                       0x00000c64
+#define  NV10TCL_VERTEX_COL_3F_B                                                       0x00000c68
+#define  NV10TCL_VERTEX_COL_4I                                                         0x00000c6c
+#define   NV10TCL_VERTEX_COL_4I_R_SHIFT                                                        0
+#define   NV10TCL_VERTEX_COL_4I_R_MASK                                                 0x000000ff
+#define   NV10TCL_VERTEX_COL_4I_G_SHIFT                                                        8
+#define   NV10TCL_VERTEX_COL_4I_G_MASK                                                 0x0000ff00
+#define   NV10TCL_VERTEX_COL_4I_B_SHIFT                                                        16
+#define   NV10TCL_VERTEX_COL_4I_B_MASK                                                 0x00ff0000
+#define   NV10TCL_VERTEX_COL_4I_A_SHIFT                                                        24
+#define   NV10TCL_VERTEX_COL_4I_A_MASK                                                 0xff000000
+#define  NV10TCL_VERTEX_COL2_3F_R                                                      0x00000c80
+#define  NV10TCL_VERTEX_COL2_3F_G                                                      0x00000c84
+#define  NV10TCL_VERTEX_COL2_3F_B                                                      0x00000c88
+#define  NV10TCL_VERTEX_COL2_3I                                                                0x00000c8c
+#define   NV10TCL_VERTEX_COL2_3I_R_SHIFT                                               0
+#define   NV10TCL_VERTEX_COL2_3I_R_MASK                                                        0x000000ff
+#define   NV10TCL_VERTEX_COL2_3I_G_SHIFT                                               8
+#define   NV10TCL_VERTEX_COL2_3I_G_MASK                                                        0x0000ff00
+#define   NV10TCL_VERTEX_COL2_3I_B_SHIFT                                               16
+#define   NV10TCL_VERTEX_COL2_3I_B_MASK                                                        0x00ff0000
+#define  NV10TCL_VERTEX_TX0_2F_S                                                       0x00000c90
+#define  NV10TCL_VERTEX_TX0_2F_T                                                       0x00000c94
+#define  NV10TCL_VERTEX_TX0_2I                                                         0x00000c98
+#define   NV10TCL_VERTEX_TX0_2I_S_SHIFT                                                        0
+#define   NV10TCL_VERTEX_TX0_2I_S_MASK                                                 0x0000ffff
+#define   NV10TCL_VERTEX_TX0_2I_T_SHIFT                                                        16
+#define   NV10TCL_VERTEX_TX0_2I_T_MASK                                                 0xffff0000
+#define  NV10TCL_VERTEX_TX0_4F_S                                                       0x00000ca0
+#define  NV10TCL_VERTEX_TX0_4F_T                                                       0x00000ca4
+#define  NV10TCL_VERTEX_TX0_4F_R                                                       0x00000ca8
+#define  NV10TCL_VERTEX_TX0_4F_Q                                                       0x00000cac
+#define  NV10TCL_VERTEX_TX0_4I_ST                                                      0x00000cb0
+#define   NV10TCL_VERTEX_TX0_4I_ST_S_SHIFT                                             0
+#define   NV10TCL_VERTEX_TX0_4I_ST_S_MASK                                              0x0000ffff
+#define   NV10TCL_VERTEX_TX0_4I_ST_T_SHIFT                                             16
+#define   NV10TCL_VERTEX_TX0_4I_ST_T_MASK                                              0xffff0000
+#define  NV10TCL_VERTEX_TX0_4I_RQ                                                      0x00000cb4
+#define   NV10TCL_VERTEX_TX0_4I_RQ_R_SHIFT                                             0
+#define   NV10TCL_VERTEX_TX0_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV10TCL_VERTEX_TX0_4I_RQ_Q_SHIFT                                             16
+#define   NV10TCL_VERTEX_TX0_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV10TCL_VERTEX_TX1_2F_S                                                       0x00000cb8
+#define  NV10TCL_VERTEX_TX1_2F_T                                                       0x00000cbc
+#define  NV10TCL_VERTEX_TX1_2I                                                         0x00000cc0
+#define   NV10TCL_VERTEX_TX1_2I_S_SHIFT                                                        0
+#define   NV10TCL_VERTEX_TX1_2I_S_MASK                                                 0x0000ffff
+#define   NV10TCL_VERTEX_TX1_2I_T_SHIFT                                                        16
+#define   NV10TCL_VERTEX_TX1_2I_T_MASK                                                 0xffff0000
+#define  NV10TCL_VERTEX_TX1_4F_S                                                       0x00000cc8
+#define  NV10TCL_VERTEX_TX1_4F_T                                                       0x00000ccc
+#define  NV10TCL_VERTEX_TX1_4F_R                                                       0x00000cd0
+#define  NV10TCL_VERTEX_TX1_4F_Q                                                       0x00000cd4
+#define  NV10TCL_VERTEX_TX1_4I_ST                                                      0x00000cd8
+#define   NV10TCL_VERTEX_TX1_4I_ST_S_SHIFT                                             0
+#define   NV10TCL_VERTEX_TX1_4I_ST_S_MASK                                              0x0000ffff
+#define   NV10TCL_VERTEX_TX1_4I_ST_T_SHIFT                                             16
+#define   NV10TCL_VERTEX_TX1_4I_ST_T_MASK                                              0xffff0000
+#define  NV10TCL_VERTEX_TX1_4I_RQ                                                      0x00000cdc
+#define   NV10TCL_VERTEX_TX1_4I_RQ_R_SHIFT                                             0
+#define   NV10TCL_VERTEX_TX1_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV10TCL_VERTEX_TX1_4I_RQ_Q_SHIFT                                             16
+#define   NV10TCL_VERTEX_TX1_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV10TCL_VERTEX_FOG_1F                                                         0x00000ce0
+#define  NV10TCL_VERTEX_WGH_1F                                                         0x00000ce4
+#define  NV10TCL_EDGEFLAG_ENABLE                                                       0x00000cec
+#define  NV10TCL_VERTEX_ARRAY_VALIDATE                                                 0x00000cf0
+#define  NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(x)                                         (0x00000d00+((x)*8))
+#define  NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET__SIZE                                      0x00000008
+#define  NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(x)                                         (0x00000d04+((x)*8))
+#define  NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT__SIZE                                      0x00000008
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_TYPE_SHIFT                                        0
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_TYPE_MASK                                 0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_FIELDS_SHIFT                              4
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_FIELDS_MASK                               0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_STRIDE_SHIFT                              8
+#define   NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT_STRIDE_MASK                               0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_POS                                               0x00000d00
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_POS                                               0x00000d04
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_POS_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_COL                                               0x00000d08
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_COL                                               0x00000d0c
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_COL2                                              0x00000d10
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_COL2                                              0x00000d14
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_TYPE_SHIFT                                  0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_TYPE_MASK                                   0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_FIELDS_SHIFT                                        4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_FIELDS_MASK                                 0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_STRIDE_SHIFT                                        8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_COL2_STRIDE_MASK                                 0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_TX0                                               0x00000d18
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_TX0                                               0x00000d1c
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX0_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_TX1                                               0x00000d20
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_TX1                                               0x00000d24
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_TX1_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_NOR                                               0x00000d28
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_NOR                                               0x00000d2c
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_NOR_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_WGH                                               0x00000d30
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_WGH                                               0x00000d34
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_WGH_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_ARRAY_OFFSET_FOG                                               0x00000d38
+#define  NV10TCL_VERTEX_ARRAY_FORMAT_FOG                                               0x00000d3c
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_TYPE_SHIFT                                   0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_TYPE_MASK                                    0x0000000f
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_FIELDS_SHIFT                                 4
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_FIELDS_MASK                                  0x000000f0
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_STRIDE_SHIFT                                 8
+#define   NV10TCL_VERTEX_ARRAY_FORMAT_FOG_STRIDE_MASK                                  0x0000ff00
+#define  NV10TCL_VERTEX_BEGIN_END                                                      0x00000dfc
+#define   NV10TCL_VERTEX_BEGIN_END_STOP                                                        0x00000000
+#define   NV10TCL_VERTEX_BEGIN_END_POINTS                                              0x00000001
+#define   NV10TCL_VERTEX_BEGIN_END_LINES                                               0x00000002
+#define   NV10TCL_VERTEX_BEGIN_END_LINE_LOOP                                           0x00000003
+#define   NV10TCL_VERTEX_BEGIN_END_LINE_STRIP                                          0x00000004
+#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLES                                           0x00000005
+#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLE_STRIP                                      0x00000006
+#define   NV10TCL_VERTEX_BEGIN_END_TRIANGLE_FAN                                                0x00000007
+#define   NV10TCL_VERTEX_BEGIN_END_QUADS                                               0x00000008
+#define   NV10TCL_VERTEX_BEGIN_END_QUAD_STRIP                                          0x00000009
+#define   NV10TCL_VERTEX_BEGIN_END_POLYGON                                             0x0000000a
+#define  NV10TCL_VB_ELEMENT_U16                                                                0x00000e00
+#define   NV10TCL_VB_ELEMENT_U16_I0_SHIFT                                              0
+#define   NV10TCL_VB_ELEMENT_U16_I0_MASK                                               0x0000ffff
+#define   NV10TCL_VB_ELEMENT_U16_I1_SHIFT                                              16
+#define   NV10TCL_VB_ELEMENT_U16_I1_MASK                                               0xffff0000
+#define  NV10TCL_VB_ELEMENT_U32                                                                0x00001100
+#define  NV10TCL_VERTEX_BUFFER_BEGIN_END                                               0x000013fc
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_STOP                                         0x00000000
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_POINTS                                       0x00000001
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINES                                                0x00000002
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINE_LOOP                                    0x00000003
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_LINE_STRIP                                   0x00000004
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLES                                    0x00000005
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLE_STRIP                               0x00000006
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_TRIANGLE_FAN                                 0x00000007
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_QUADS                                                0x00000008
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_QUAD_STRIP                                   0x00000009
+#define   NV10TCL_VERTEX_BUFFER_BEGIN_END_POLYGON                                      0x0000000a
+#define  NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS                                             0x00001400
+#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_FIRST_SHIFT                                        0
+#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_FIRST_MASK                                 0x0000ffff
+#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_LAST_SHIFT                                 24
+#define   NV10TCL_VERTEX_BUFFER_DRAW_ARRAYS_LAST_MASK                                  0xff000000
+#define  NV10TCL_VERTEX_ARRAY_DATA                                                     0x00001800
+
+
+#define NV04_CONTEXT_COLOR_KEY                                                         0x00000057
+
+
+
+#define NV03_CONTEXT_SURFACES_2D                                                       0x00000058
+
+#define  NV03_CONTEXT_SURFACES_2D_SYNCHRONIZE                                          0x00000100
+#define  NV03_CONTEXT_SURFACES_2D_DMA_NOTIFY                                           0x00000180
+#define  NV03_CONTEXT_SURFACES_2D_DMA_SOURCE                                           0x00000184
+#define  NV03_CONTEXT_SURFACES_2D_DMA_DESTIN                                           0x00000188
+#define  NV03_CONTEXT_SURFACES_2D_COLOR_FORMAT                                         0x00000300
+#define  NV03_CONTEXT_SURFACES_2D_PITCH                                                        0x00000304
+#define   NV03_CONTEXT_SURFACES_2D_PITCH_SOURCE_SHIFT                                  0
+#define   NV03_CONTEXT_SURFACES_2D_PITCH_SOURCE_MASK                                   0x0000ffff
+#define   NV03_CONTEXT_SURFACES_2D_PITCH_DESTIN_SHIFT                                  16
+#define   NV03_CONTEXT_SURFACES_2D_PITCH_DESTIN_MASK                                   0xffff0000
+#define  NV03_CONTEXT_SURFACES_2D_OFFSET_SOURCE                                                0x00000308
+#define  NV03_CONTEXT_SURFACES_2D_OFFSET_DESTIN                                                0x0000030c
+
+
+#define NV03_CONTEXT_SURFACES_3D                                                       0x0000005a
+
+#define  NV03_CONTEXT_SURFACES_3D_SYNCHRONIZE                                          0x00000100
+#define  NV03_CONTEXT_SURFACES_3D_DMA_NOTIFY                                           0x00000180
+#define  NV03_CONTEXT_SURFACES_3D_DMA_SURFACE                                          0x00000184
+#define  NV03_CONTEXT_SURFACES_3D_PITCH                                                        0x00000300
+#define  NV03_CONTEXT_SURFACES_3D_OFFSET_COLOR                                         0x00000304
+#define  NV03_CONTEXT_SURFACES_3D_OFFSET_ZETA                                          0x00000308
+
+
+#define NV04_RENDER_SOLID_LINE                                                         0x0000005c
+
+#define  NV04_RENDER_SOLID_LINE_SURFACE                                                        0x00000198
+
+
+#define NV04_RENDER_SOLID_TRIANGLE                                                     0x0000005d
+
+
+
+#define NV04_RENDER_SOLID_RECTANGLE                                                    0x0000005e
+
+#define  NV04_RENDER_SOLID_RECTANGLE_SURFACE                                           0x00000198
+
+
+#define NV04_IMAGE_BLIT                                                                        0x0000005f
+
+#define  NV04_IMAGE_BLIT_NOP                                                           0x00000100
+#define  NV04_IMAGE_BLIT_NOTIFY                                                                0x00000104
+#define  NV04_IMAGE_BLIT_DMA_NOTIFY                                                    0x00000180
+#define  NV04_IMAGE_BLIT_COLOR_KEY                                                     0x00000184
+#define  NV04_IMAGE_BLIT_CLIP_RECTANGLE                                                        0x00000188
+#define  NV04_IMAGE_BLIT_PATTERN                                                       0x0000018c
+#define  NV04_IMAGE_BLIT_ROP                                                           0x00000190
+#define  NV04_IMAGE_BLIT_BETA4                                                         0x00000198
+#define  NV04_IMAGE_BLIT_SURFACE                                                       0x0000019c
+#define  NV04_IMAGE_BLIT_OPERATION                                                     0x000002fc
+#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY_AND                                                0x00000000
+#define   NV04_IMAGE_BLIT_OPERATION_ROP_AND                                            0x00000001
+#define   NV04_IMAGE_BLIT_OPERATION_BLEND_AND                                          0x00000002
+#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY                                            0x00000003
+#define   NV04_IMAGE_BLIT_OPERATION_SRCCOPY_PREMULT                                    0x00000004
+#define   NV04_IMAGE_BLIT_OPERATION_BLEND_PREMULT                                      0x00000005
+
+
+#define NV04_INDEXED_IMAGE_FROM_CPU                                                    0x00000060
+
+#define  NV04_INDEXED_IMAGE_FROM_CPU_NOP                                               0x00000100
+#define  NV04_INDEXED_IMAGE_FROM_CPU_NOTIFY                                            0x00000104
+#define  NV04_INDEXED_IMAGE_FROM_CPU_PATCH                                             0x0000010c
+#define  NV04_INDEXED_IMAGE_FROM_CPU_DMA_NOTIFY                                                0x00000180
+#define  NV04_INDEXED_IMAGE_FROM_CPU_DMA_LUT                                           0x00000184
+#define  NV04_INDEXED_IMAGE_FROM_CPU_COLOR_FORMAT                                      0x000003e8
+#define  NV04_INDEXED_IMAGE_FROM_CPU_INDEX_FORMAT                                      0x000003ec
+#define  NV04_INDEXED_IMAGE_FROM_CPU_LUT_OFFSET                                                0x000003f0
+#define  NV04_INDEXED_IMAGE_FROM_CPU_POINT                                             0x000003f4
+#define  NV04_INDEXED_IMAGE_FROM_CPU_SIZE_OUT                                          0x000003f8
+#define  NV04_INDEXED_IMAGE_FROM_CPU_SIZE_IN                                           0x000003fc
+#define  NV04_INDEXED_IMAGE_FROM_CPU_COLOR                                             0x00000400
+
+
+#define NV04_IMAGE_FROM_CPU                                                            0x00000061
+
+#define  NV04_IMAGE_FROM_CPU_BETA4                                                     0x00000198
+#define  NV04_IMAGE_FROM_CPU_SURFACE                                                   0x0000019c
+
+
+#define NV10_CONTEXT_SURFACES_2D                                                       0x00000062
+
+
+
+#define NV05_SCALED_IMAGE_FROM_MEMORY                                                  0x00000063
+
+#define  NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION                                        0x000002fc
+#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER                                0x00000000
+#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE                      0x00000001
+#define   NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_SUBTR_TRUNCATE                        0x00000002
+
+
+#define NV01_IMAGE_SRCCOPY_AND                                                         0x00000064
+
+#define  NV01_IMAGE_SRCCOPY_AND_NOTIFY                                                 0x00000104
+#define  NV01_IMAGE_SRCCOPY_AND_DMA_NOTIFY                                             0x00000180
+#define  NV01_IMAGE_SRCCOPY_AND_IMAGE_OUTPUT                                           0x00000200
+#define  NV01_IMAGE_SRCCOPY_AND_IMAGE_INPUT                                            0x00000204
+
+
+#define NV05_INDEXED_IMAGE_FROM_CPU                                                    0x00000064
+
+#define  NV05_INDEXED_IMAGE_FROM_CPU_COLOR_KEY                                         0x00000188
+#define  NV05_INDEXED_IMAGE_FROM_CPU_CLIP_RECTANGLE                                    0x0000018c
+#define  NV05_INDEXED_IMAGE_FROM_CPU_PATTERN                                           0x00000190
+#define  NV05_INDEXED_IMAGE_FROM_CPU_ROP                                               0x00000194
+#define  NV05_INDEXED_IMAGE_FROM_CPU_BETA1                                             0x00000198
+#define  NV05_INDEXED_IMAGE_FROM_CPU_BETA4                                             0x0000019c
+#define  NV05_INDEXED_IMAGE_FROM_CPU_SURFACE                                           0x000001a0
+#define  NV05_INDEXED_IMAGE_FROM_CPU_COLOR_CONVERSION                                  0x000003e0
+#define  NV05_INDEXED_IMAGE_FROM_CPU_OPERATION                                         0x000003e4
+#define  NV05_INDEXED_IMAGE_FROM_CPU_INDICES                                           0x00000400
+
+
+#define NV05_IMAGE_FROM_CPU                                                            0x00000065
+
+#define  NV05_IMAGE_FROM_CPU_BETA4                                                     0x00000198
+#define  NV05_IMAGE_FROM_CPU_SURFACE                                                   0x0000019c
+
+
+#define NV05_STRETCHED_IMAGE_FROM_CPU                                                  0x00000066
+
+#define  NV05_STRETCHED_IMAGE_FROM_CPU_BETA4                                           0x00000194
+#define  NV05_STRETCHED_IMAGE_FROM_CPU_SURFACE                                         0x00000198
+#define  NV05_STRETCHED_IMAGE_FROM_CPU_COLOR_CONVERSION                                        0x000002f8
+
+
+#define NV04_IMAGE_BLEND_PREMULT                                                       0x00000067
+
+#define  NV04_IMAGE_BLEND_PREMULT_NOP                                                  0x00000100
+#define  NV04_IMAGE_BLEND_PREMULT_NOTIFY                                               0x00000104
+#define  NV04_IMAGE_BLEND_PREMULT_DMA_NOTIFY                                           0x00000180
+#define  NV04_IMAGE_BLEND_PREMULT_IMAGE_OUTPUT                                         0x00000200
+#define  NV04_IMAGE_BLEND_PREMULT_BETA_INPUT                                           0x00000204
+#define  NV04_IMAGE_BLEND_PREMULT_IMAGE_INPUT                                          0x00000208
+
+
+#define NV03_CHANNEL_PIO                                                               0x0000006a
+
+
+
+#define NV03_CHANNEL_DMA                                                               0x0000006b
+
+
+
+#define NV04_BETA_SOLID                                                                        0x00000072
+
+#define  NV04_BETA_SOLID_NOP                                                           0x00000100
+#define  NV04_BETA_SOLID_NOTIFY                                                                0x00000104
+#define  NV04_BETA_SOLID_DMA_NOTIFY                                                    0x00000180
+#define  NV04_BETA_SOLID_BETA_OUTPUT                                                   0x00000200
+#define  NV04_BETA_SOLID_BETA_FACTOR                                                   0x00000300
+
+
+#define NV04_STRETCHED_IMAGE_FROM_CPU                                                  0x00000076
+
+
+
+#define NV04_SCALED_IMAGE_FROM_MEMORY                                                  0x00000077
+
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_NOP                                             0x00000100
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_NOTIFY                                          0x00000104
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY                                      0x00000180
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE                                       0x00000184
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN                                         0x00000188
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_ROP                                             0x0000018c
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_BETA1                                           0x00000190
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_BETA4                                           0x00000194
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE                                         0x00000198
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION                                        0x000002fc
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER                                0x00000000
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE                      0x00000001
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_SUBTR_TRUNCATE                        0x00000002
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT                                    0x00000300
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5                          0x00000001
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5                          0x00000002
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8                          0x00000003
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8                          0x00000004
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8                                0x00000005
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8                                0x00000006
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5                            0x00000007
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8                                        0x00000008
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8                               0x00000009
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION                                       0x00000304
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_AND                          0x00000000
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_ROP_AND                              0x00000001
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_AND                            0x00000002
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY                              0x00000003
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_PREMULT                      0x00000004
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_PREMULT                                0x00000005
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT                                      0x00000308
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_SHIFT                             0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X_MASK                              0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT                             16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_MASK                              0xffff0000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE                                       0x0000030c
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_SHIFT                              0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W_MASK                               0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT                              16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_MASK                               0xffff0000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT                                       0x00000310
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X_SHIFT                              0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X_MASK                               0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT                              16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_MASK                               0xffff0000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE                                                0x00000314
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W_SHIFT                               0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W_MASK                                        0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT                               16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_MASK                                        0xffff0000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_DU_DX                                           0x00000318
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_DV_DY                                           0x0000031c
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_SIZE                                            0x00000400
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_W_SHIFT                                   0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_W_MASK                                    0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT                                   16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_H_MASK                                    0xffff0000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT                                          0x00000404
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH_SHIFT                             0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH_MASK                              0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_SHIFT                            16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_MASK                             0x00ff0000
+#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER                          0x00010000
+#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CORNER                          0x00020000
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_SHIFT                            24
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_MASK                             0xff000000
+#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE                    0x00000000
+#define    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR                                0x01000000
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_ADDRESS                                         0x00000408
+#define  NV04_SCALED_IMAGE_FROM_MEMORY_POINT                                           0x0000040c
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_X_SHIFT                                  0
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_X_MASK                                   0x0000ffff
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_Y_SHIFT                                  16
+#define   NV04_SCALED_IMAGE_FROM_MEMORY_POINT_Y_MASK                                   0xffff0000
+
+
+#define NV10_TEXTURE_FROM_CPU                                                          0x0000007b
+
+#define  NV10_TEXTURE_FROM_CPU_NOP                                                     0x00000100
+#define  NV10_TEXTURE_FROM_CPU_NOTIFY                                                  0x00000104
+#define  NV10_TEXTURE_FROM_CPU_WAIT_FOR_IDLE                                           0x00000108
+#define  NV10_TEXTURE_FROM_CPU_PM_TRIGGER                                              0x00000140
+#define  NV10_TEXTURE_FROM_CPU_DMA_NOTIFY                                              0x00000180
+#define  NV10_TEXTURE_FROM_CPU_SURFACE                                                 0x00000184
+#define  NV10_TEXTURE_FROM_CPU_COLOR_FORMAT                                            0x00000300
+#define  NV10_TEXTURE_FROM_CPU_POINT                                                   0x00000304
+#define   NV10_TEXTURE_FROM_CPU_POINT_X_SHIFT                                          0
+#define   NV10_TEXTURE_FROM_CPU_POINT_X_MASK                                           0x0000ffff
+#define   NV10_TEXTURE_FROM_CPU_POINT_Y_SHIFT                                          16
+#define   NV10_TEXTURE_FROM_CPU_POINT_Y_MASK                                           0xffff0000
+#define  NV10_TEXTURE_FROM_CPU_SIZE                                                    0x00000308
+#define   NV10_TEXTURE_FROM_CPU_SIZE_W_SHIFT                                           0
+#define   NV10_TEXTURE_FROM_CPU_SIZE_W_MASK                                            0x0000ffff
+#define   NV10_TEXTURE_FROM_CPU_SIZE_H_SHIFT                                           16
+#define   NV10_TEXTURE_FROM_CPU_SIZE_H_MASK                                            0xffff0000
+#define  NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL                                         0x0000030c
+#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X_SHIFT                                        0
+#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X_MASK                                 0x0000ffff
+#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W_SHIFT                                        16
+#define   NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W_MASK                                 0xffff0000
+#define  NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL                                           0x00000310
+#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y_SHIFT                                  0
+#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y_MASK                                   0x0000ffff
+#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H_SHIFT                                  16
+#define   NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H_MASK                                   0xffff0000
+#define  NV10_TEXTURE_FROM_CPU_COLOR(x)                                                        (0x00000400+((x)*4))
+#define  NV10_TEXTURE_FROM_CPU_COLOR__SIZE                                             0x00000700
+
+
+#define NV10_VIDEO_DISPLAY                                                             0x0000007c
+
+
+
+#define NV10_DVD_SUBPICTURE                                                            0x00000088
+
+
+
+#define NV10_SCALED_IMAGE_FROM_MEMORY                                                  0x00000089
+
+#define  NV10_SCALED_IMAGE_FROM_MEMORY_WAIT_FOR_IDLE                                   0x00000108
+
+
+#define NV10_IMAGE_FROM_CPU                                                            0x0000008a
+
+#define  NV10_IMAGE_FROM_CPU_COLOR_CONVERSION                                          0x000002f8
+
+
+#define NV10_CONTEXT_SURFACES_3D                                                       0x00000093
+
+
+
+#define NV10_DX5_TEXTURE_TRIANGLE                                                      0x00000094
+
+
+
+#define NV10_DX6_MULTI_TEXTURE_TRIANGLE                                                        0x00000095
+
+
+
+#define NV11TCL                                                                                0x00000096
+
+#define  NV11TCL_COLOR_LOGIC_OP_ENABLE                                                 0x00000d40
+#define  NV11TCL_COLOR_LOGIC_OP_OP                                                     0x00000d44
+#define   NV11TCL_COLOR_LOGIC_OP_OP_CLEAR                                              0x00001500
+#define   NV11TCL_COLOR_LOGIC_OP_OP_AND                                                        0x00001501
+#define   NV11TCL_COLOR_LOGIC_OP_OP_AND_REVERSE                                                0x00001502
+#define   NV11TCL_COLOR_LOGIC_OP_OP_COPY                                               0x00001503
+#define   NV11TCL_COLOR_LOGIC_OP_OP_AND_INVERTED                                       0x00001504
+#define   NV11TCL_COLOR_LOGIC_OP_OP_NOOP                                               0x00001505
+#define   NV11TCL_COLOR_LOGIC_OP_OP_XOR                                                        0x00001506
+#define   NV11TCL_COLOR_LOGIC_OP_OP_OR                                                 0x00001507
+#define   NV11TCL_COLOR_LOGIC_OP_OP_NOR                                                        0x00001508
+#define   NV11TCL_COLOR_LOGIC_OP_OP_EQUIV                                              0x00001509
+#define   NV11TCL_COLOR_LOGIC_OP_OP_INVERT                                             0x0000150a
+#define   NV11TCL_COLOR_LOGIC_OP_OP_OR_REVERSE                                         0x0000150b
+#define   NV11TCL_COLOR_LOGIC_OP_OP_COPY_INVERTED                                      0x0000150c
+#define   NV11TCL_COLOR_LOGIC_OP_OP_OR_INVERTED                                                0x0000150d
+#define   NV11TCL_COLOR_LOGIC_OP_OP_NAND                                               0x0000150e
+#define   NV11TCL_COLOR_LOGIC_OP_OP_SET                                                        0x0000150f
+
+
+#define NV20TCL                                                                                0x00000097
+
+#define  NV20TCL_NOP                                                                   0x00000100
+#define  NV20TCL_NOTIFY                                                                        0x00000104
+#define  NV20TCL_DMA_NOTIFY                                                            0x00000180
+#define  NV20TCL_DMA_IN_MEMORY0                                                                0x00000184
+#define  NV20TCL_DMA_IN_MEMORY1                                                                0x00000188
+#define  NV20TCL_DMA_IN_MEMORY2                                                                0x00000194
+#define  NV20TCL_DMA_IN_MEMORY3                                                                0x00000198
+#define  NV20TCL_DMA_IN_MEMORY6                                                                0x000001a4
+#define  NV20TCL_DMA_IN_MEMORY7                                                                0x000001a8
+#define  NV20TCL_VIEWPORT_HORIZ                                                                0x00000200
+#define  NV20TCL_VIEWPORT_VERT                                                         0x00000204
+#define  NV20TCL_BUFFER_FORMAT                                                         0x00000208
+#define  NV20TCL_BUFFER_PITCH                                                          0x0000020c
+#define  NV20TCL_COLOR_OFFSET                                                          0x00000210
+#define  NV20TCL_ZETA_OFFSET                                                           0x00000214
+#define  NV20TCL_RC_IN_ALPHA(x)                                                                (0x00000260+((x)*4))
+#define  NV20TCL_RC_IN_ALPHA__SIZE                                                     0x00000008
+#define  NV20TCL_RC_FINAL0                                                             0x00000288
+#define  NV20TCL_RC_FINAL1                                                             0x0000028c
+#define  NV20TCL_LIGHT_CONTROL                                                         0x00000294
+#define  NV20TCL_FOG_MODE                                                              0x0000029c
+#define  NV20TCL_FOG_COORD_DIST                                                                0x000002a0
+#define  NV20TCL_FOG_ENABLE                                                            0x000002a4
+#define  NV20TCL_FOG_COLOR                                                             0x000002a8
+#define  NV20TCL_VIEWPORT_CLIP_MODE                                                    0x000002b4
+#define  NV20TCL_VIEWPORT_CLIP_HORIZ(x)                                                        (0x000002c0+((x)*4))
+#define  NV20TCL_VIEWPORT_CLIP_HORIZ__SIZE                                             0x00000008
+#define  NV20TCL_VIEWPORT_CLIP_VERT(x)                                                 (0x000002e0+((x)*4))
+#define  NV20TCL_VIEWPORT_CLIP_VERT__SIZE                                              0x00000008
+#define  NV20TCL_ALPHA_FUNC_ENABLE                                                     0x00000300
+#define  NV20TCL_BLEND_FUNC_ENABLE                                                     0x00000304
+#define  NV20TCL_CULL_FACE_ENABLE                                                      0x00000308
+#define  NV20TCL_DEPTH_TEST_ENABLE                                                     0x0000030c
+#define  NV20TCL_DITHER_ENABLE                                                         0x00000310
+#define  NV20TCL_LIGHTING_ENABLE                                                       0x00000314
+#define  NV20TCL_POINT_PARAMETERS_ENABLE                                               0x00000318
+#define  NV20TCL_LINE_SMOOTH_ENABLE                                                    0x00000320
+#define  NV20TCL_POLYGON_SMOOTH_ENABLE                                                 0x00000324
+#define  NV20TCL_STENCIL_ENABLE                                                                0x0000032c
+#define  NV20TCL_POLYGON_OFFSET_POINT_ENABLE                                           0x00000330
+#define  NV20TCL_POLYGON_OFFSET_LINE_ENABLE                                            0x00000334
+#define  NV20TCL_POLYGON_OFFSET_FILL_ENABLE                                            0x00000338
+#define  NV20TCL_ALPHA_FUNC_FUNC                                                       0x0000033c
+#define   NV20TCL_ALPHA_FUNC_FUNC_NEVER                                                        0x00000200
+#define   NV20TCL_ALPHA_FUNC_FUNC_LESS                                                 0x00000201
+#define   NV20TCL_ALPHA_FUNC_FUNC_EQUAL                                                        0x00000202
+#define   NV20TCL_ALPHA_FUNC_FUNC_LEQUAL                                               0x00000203
+#define   NV20TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV20TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV20TCL_ALPHA_FUNC_FUNC_NOTEQUAL                                             0x00000205
+#define   NV20TCL_ALPHA_FUNC_FUNC_GEQUAL                                               0x00000206
+#define   NV20TCL_ALPHA_FUNC_FUNC_ALWAYS                                               0x00000207
+#define  NV20TCL_ALPHA_FUNC_REF                                                                0x00000340
+#define  NV20TCL_BLEND_FUNC_SRC                                                                0x00000344
+#define   NV20TCL_BLEND_FUNC_SRC_ZERO                                                  0x00000000
+#define   NV20TCL_BLEND_FUNC_SRC_ONE                                                   0x00000001
+#define   NV20TCL_BLEND_FUNC_SRC_SRC_COLOR                                             0x00000300
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR                                   0x00000301
+#define   NV20TCL_BLEND_FUNC_SRC_SRC_ALPHA                                             0x00000302
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA                                   0x00000303
+#define   NV20TCL_BLEND_FUNC_SRC_DST_ALPHA                                             0x00000304
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA                                   0x00000305
+#define   NV20TCL_BLEND_FUNC_SRC_DST_COLOR                                             0x00000306
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR                                   0x00000307
+#define   NV20TCL_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE                                    0x00000308
+#define   NV20TCL_BLEND_FUNC_SRC_CONSTANT_COLOR                                                0x00008001
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR                              0x00008002
+#define   NV20TCL_BLEND_FUNC_SRC_CONSTANT_ALPHA                                                0x00008003
+#define   NV20TCL_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA                              0x00008004
+#define  NV20TCL_BLEND_FUNC_DST                                                                0x00000348
+#define   NV20TCL_BLEND_FUNC_DST_ZERO                                                  0x00000000
+#define   NV20TCL_BLEND_FUNC_DST_ONE                                                   0x00000001
+#define   NV20TCL_BLEND_FUNC_DST_SRC_COLOR                                             0x00000300
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR                                   0x00000301
+#define   NV20TCL_BLEND_FUNC_DST_SRC_ALPHA                                             0x00000302
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA                                   0x00000303
+#define   NV20TCL_BLEND_FUNC_DST_DST_ALPHA                                             0x00000304
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA                                   0x00000305
+#define   NV20TCL_BLEND_FUNC_DST_DST_COLOR                                             0x00000306
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR                                   0x00000307
+#define   NV20TCL_BLEND_FUNC_DST_SRC_ALPHA_SATURATE                                    0x00000308
+#define   NV20TCL_BLEND_FUNC_DST_CONSTANT_COLOR                                                0x00008001
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR                              0x00008002
+#define   NV20TCL_BLEND_FUNC_DST_CONSTANT_ALPHA                                                0x00008003
+#define   NV20TCL_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA                              0x00008004
+#define  NV20TCL_BLEND_COLOR                                                           0x0000034c
+#define  NV20TCL_BLEND_EQUATION                                                                0x00000350
+#define   NV20TCL_BLEND_EQUATION_FUNC_ADD                                              0x00008006
+#define   NV20TCL_BLEND_EQUATION_MIN                                                   0x00008007
+#define   NV20TCL_BLEND_EQUATION_MAX                                                   0x00008008
+#define   NV20TCL_BLEND_EQUATION_FUNC_SUBTRACT                                         0x0000800a
+#define   NV20TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT                                 0x0000800b
+#define  NV20TCL_DEPTH_FUNC                                                            0x00000354
+#define   NV20TCL_DEPTH_FUNC_NEVER                                                     0x00000200
+#define   NV20TCL_DEPTH_FUNC_LESS                                                      0x00000201
+#define   NV20TCL_DEPTH_FUNC_EQUAL                                                     0x00000202
+#define   NV20TCL_DEPTH_FUNC_LEQUAL                                                    0x00000203
+#define   NV20TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV20TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV20TCL_DEPTH_FUNC_NOTEQUAL                                                  0x00000205
+#define   NV20TCL_DEPTH_FUNC_GEQUAL                                                    0x00000206
+#define   NV20TCL_DEPTH_FUNC_ALWAYS                                                    0x00000207
+#define  NV20TCL_COLOR_MASK                                                            0x00000358
+#define  NV20TCL_DEPTH_WRITE_ENABLE                                                    0x0000035c
+#define  NV20TCL_STENCIL_MASK                                                          0x00000360
+#define  NV20TCL_STENCIL_FUNC_FUNC                                                     0x00000364
+#define   NV20TCL_STENCIL_FUNC_FUNC_NEVER                                              0x00000200
+#define   NV20TCL_STENCIL_FUNC_FUNC_LESS                                               0x00000201
+#define   NV20TCL_STENCIL_FUNC_FUNC_EQUAL                                              0x00000202
+#define   NV20TCL_STENCIL_FUNC_FUNC_LEQUAL                                             0x00000203
+#define   NV20TCL_STENCIL_FUNC_FUNC_GREATER                                            0x00000204
+#define   NV20TCL_STENCIL_FUNC_FUNC_GREATER                                            0x00000204
+#define   NV20TCL_STENCIL_FUNC_FUNC_NOTEQUAL                                           0x00000205
+#define   NV20TCL_STENCIL_FUNC_FUNC_GEQUAL                                             0x00000206
+#define   NV20TCL_STENCIL_FUNC_FUNC_ALWAYS                                             0x00000207
+#define  NV20TCL_STENCIL_FUNC_REF                                                      0x00000368
+#define  NV20TCL_STENCIL_FUNC_MASK                                                     0x0000036c
+#define  NV20TCL_STENCIL_OP_FAIL                                                       0x00000370
+#define   NV20TCL_STENCIL_OP_FAIL_ZERO                                                 0x00000000
+#define   NV20TCL_STENCIL_OP_FAIL_INVERT                                               0x0000150a
+#define   NV20TCL_STENCIL_OP_FAIL_KEEP                                                 0x00001e00
+#define   NV20TCL_STENCIL_OP_FAIL_REPLACE                                              0x00001e01
+#define   NV20TCL_STENCIL_OP_FAIL_INCR                                                 0x00001e02
+#define   NV20TCL_STENCIL_OP_FAIL_DECR                                                 0x00001e03
+#define   NV20TCL_STENCIL_OP_FAIL_INCR_WRAP                                            0x00008507
+#define   NV20TCL_STENCIL_OP_FAIL_DECR_WRAP                                            0x00008508
+#define  NV20TCL_STENCIL_OP_ZFAIL                                                      0x00000374
+#define   NV20TCL_STENCIL_OP_ZFAIL_ZERO                                                        0x00000000
+#define   NV20TCL_STENCIL_OP_ZFAIL_INVERT                                              0x0000150a
+#define   NV20TCL_STENCIL_OP_ZFAIL_KEEP                                                        0x00001e00
+#define   NV20TCL_STENCIL_OP_ZFAIL_REPLACE                                             0x00001e01
+#define   NV20TCL_STENCIL_OP_ZFAIL_INCR                                                        0x00001e02
+#define   NV20TCL_STENCIL_OP_ZFAIL_DECR                                                        0x00001e03
+#define   NV20TCL_STENCIL_OP_ZFAIL_INCR_WRAP                                           0x00008507
+#define   NV20TCL_STENCIL_OP_ZFAIL_DECR_WRAP                                           0x00008508
+#define  NV20TCL_STENCIL_OP_ZPASS                                                      0x00000378
+#define   NV20TCL_STENCIL_OP_ZPASS_ZERO                                                        0x00000000
+#define   NV20TCL_STENCIL_OP_ZPASS_INVERT                                              0x0000150a
+#define   NV20TCL_STENCIL_OP_ZPASS_KEEP                                                        0x00001e00
+#define   NV20TCL_STENCIL_OP_ZPASS_REPLACE                                             0x00001e01
+#define   NV20TCL_STENCIL_OP_ZPASS_INCR                                                        0x00001e02
+#define   NV20TCL_STENCIL_OP_ZPASS_DECR                                                        0x00001e03
+#define   NV20TCL_STENCIL_OP_ZPASS_INCR_WRAP                                           0x00008507
+#define   NV20TCL_STENCIL_OP_ZPASS_DECR_WRAP                                           0x00008508
+#define  NV20TCL_SHADE_MODEL                                                           0x0000037c
+#define   NV20TCL_SHADE_MODEL_FLAT                                                     0x00001d00
+#define   NV20TCL_SHADE_MODEL_SMOOTH                                                   0x00001d01
+#define  NV20TCL_LINE_WIDTH                                                            0x00000380
+#define  NV20TCL_POLYGON_OFFSET_FACTOR                                                 0x00000384
+#define  NV20TCL_POLYGON_OFFSET_UNITS                                                  0x00000388
+#define  NV20TCL_POLYGON_MODE_FRONT                                                    0x0000038c
+#define   NV20TCL_POLYGON_MODE_FRONT_POINT                                             0x00001b00
+#define   NV20TCL_POLYGON_MODE_FRONT_LINE                                              0x00001b01
+#define   NV20TCL_POLYGON_MODE_FRONT_FILL                                              0x00001b02
+#define  NV20TCL_POLYGON_MODE_BACK                                                     0x00000390
+#define   NV20TCL_POLYGON_MODE_BACK_POINT                                              0x00001b00
+#define   NV20TCL_POLYGON_MODE_BACK_LINE                                               0x00001b01
+#define   NV20TCL_POLYGON_MODE_BACK_FILL                                               0x00001b02
+#define  NV20TCL_DEPTH_RANGE_NEAR                                                      0x00000394
+#define  NV20TCL_DEPTH_RANGE_FAR                                                       0x00000398
+#define  NV20TCL_CULL_FACE                                                             0x0000039c
+#define   NV20TCL_CULL_FACE_FRONT                                                      0x00000404
+#define   NV20TCL_CULL_FACE_BACK                                                       0x00000405
+#define   NV20TCL_CULL_FACE_FRONT_AND_BACK                                             0x00000408
+#define  NV20TCL_FRONT_FACE                                                            0x000003a0
+#define   NV20TCL_FRONT_FACE_CW                                                                0x00000900
+#define   NV20TCL_FRONT_FACE_CCW                                                       0x00000901
+#define  NV20TCL_NORMALIZE_ENABLE                                                      0x000003a4
+#define  NV20TCL_SEPARATE_SPECULAR_ENABLE                                              0x000003b8
+#define  NV20TCL_ENABLED_LIGHTS                                                                0x000003bc
+#define  NV20TCL_CLIP_PLANE_ENABLE(x)                                                  (0x000003c0+((x)*4))
+#define  NV20TCL_CLIP_PLANE_ENABLE__SIZE                                               0x00000010
+#define  NV20TCL_TX_MATRIX_ENABLE(x)                                                   (0x00000420+((x)*4))
+#define  NV20TCL_TX_MATRIX_ENABLE__SIZE                                                        0x00000004
+#define  NV20TCL_POINT_SIZE                                                            0x0000043c
+#define  NV20TCL_MODELVIEW_MATRIX(x)                                                   (0x00000480+((x)*4))
+#define  NV20TCL_MODELVIEW_MATRIX__SIZE                                                        0x00000010
+#define  NV20TCL_PROJECTION_MATRIX(x)                                                  (0x00000680+((x)*4))
+#define  NV20TCL_PROJECTION_MATRIX__SIZE                                               0x00000010
+#define  NV20TCL_TX0_MATRIX(x)                                                         (0x000006c0+((x)*4))
+#define  NV20TCL_TX0_MATRIX__SIZE                                                      0x00000010
+#define  NV20TCL_TX1_MATRIX(x)                                                         (0x00000700+((x)*4))
+#define  NV20TCL_TX1_MATRIX__SIZE                                                      0x00000010
+#define  NV20TCL_TX2_MATRIX(x)                                                         (0x00000740+((x)*4))
+#define  NV20TCL_TX2_MATRIX__SIZE                                                      0x00000010
+#define  NV20TCL_TX3_MATRIX(x)                                                         (0x00000780+((x)*4))
+#define  NV20TCL_TX3_MATRIX__SIZE                                                      0x00000010
+#define  NV20TCL_FOG_EQUATION_CONSTANT                                                 0x000009c0
+#define  NV20TCL_FOG_EQUATION_LINEAR                                                   0x000009c4
+#define  NV20TCL_FOG_EQUATION_QUADRATIC                                                        0x000009c8
+#define  NV20TCL_VIEWPORT_SCALE0_X                                                     0x00000a20
+#define  NV20TCL_VIEWPORT_SCALE0_Y                                                     0x00000a24
+#define  NV20TCL_VIEWPORT_SCALE0_Z                                                     0x00000a28
+#define  NV20TCL_VIEWPORT_SCALE0_W                                                     0x00000a2c
+#define  NV20TCL_POINT_PARAMETER(x)                                                    (0x00000a30+((x)*4))
+#define  NV20TCL_POINT_PARAMETER__SIZE                                                 0x00000007
+#define  NV20TCL_RC_CONSTANT_COLOR0(x)                                                 (0x00000a60+((x)*4))
+#define  NV20TCL_RC_CONSTANT_COLOR0__SIZE                                              0x00000008
+#define  NV20TCL_RC_CONSTANT_COLOR1(x)                                                 (0x00000a80+((x)*4))
+#define  NV20TCL_RC_CONSTANT_COLOR1__SIZE                                              0x00000008
+#define  NV20TCL_RC_OUT_ALPHA(x)                                                       (0x00000aa0+((x)*4))
+#define  NV20TCL_RC_OUT_ALPHA__SIZE                                                    0x00000008
+#define  NV20TCL_RC_IN_RGB(x)                                                          (0x00000ac0+((x)*4))
+#define  NV20TCL_RC_IN_RGB__SIZE                                                       0x00000008
+#define  NV20TCL_VIEWPORT_SCALE1_X                                                     0x00000af0
+#define  NV20TCL_VIEWPORT_SCALE1_Y                                                     0x00000af4
+#define  NV20TCL_VIEWPORT_SCALE1_Z                                                     0x00000af8
+#define  NV20TCL_VIEWPORT_SCALE1_W                                                     0x00000afc
+#define  NV20TCL_VP_UPLOAD_INST(x)                                                     (0x00000b00+((x)*4))
+#define  NV20TCL_VP_UPLOAD_INST__SIZE                                                  0x00000004
+#define  NV20TCL_VP_UPLOAD_CONST(x)                                                    (0x00000b80+((x)*4))
+#define  NV20TCL_VP_UPLOAD_CONST__SIZE                                                 0x00000004
+#define  NV20TCL_POLYGON_STIPPLE_ENABLE                                                        0x0000147c
+#define  NV20TCL_POLYGON_STIPPLE_PATTERN(x)                                            (0x00001480+((x)*4))
+#define  NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE                                         0x00000020
+#define  NV20TCL_VERTEX_POS_3F_X                                                       0x00001500
+#define  NV20TCL_VERTEX_POS_3F_Y                                                       0x00001504
+#define  NV20TCL_VERTEX_POS_3F_Z                                                       0x00001508
+#define  NV20TCL_VERTEX_POS_4F_X                                                       0x00001518
+#define  NV20TCL_VERTEX_POS_4F_Y                                                       0x0000151c
+#define  NV20TCL_VERTEX_POS_4F_Z                                                       0x00001520
+#define  NV20TCL_VERTEX_POS_3I_XY                                                      0x00001528
+#define   NV20TCL_VERTEX_POS_3I_XY_X_SHIFT                                             0
+#define   NV20TCL_VERTEX_POS_3I_XY_X_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_POS_3I_XY_Y_SHIFT                                             16
+#define   NV20TCL_VERTEX_POS_3I_XY_Y_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_POS_3I_Z                                                       0x0000152c
+#define   NV20TCL_VERTEX_POS_3I_Z_Z_SHIFT                                              0
+#define   NV20TCL_VERTEX_POS_3I_Z_Z_MASK                                               0x0000ffff
+#define  NV20TCL_VERTEX_NOR_3F_X                                                       0x00001530
+#define  NV20TCL_VERTEX_NOR_3F_Y                                                       0x00001534
+#define  NV20TCL_VERTEX_NOR_3F_Z                                                       0x00001538
+#define  NV20TCL_VERTEX_NOR_3I_XY                                                      0x00001540
+#define   NV20TCL_VERTEX_NOR_3I_XY_X_SHIFT                                             0
+#define   NV20TCL_VERTEX_NOR_3I_XY_X_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_NOR_3I_XY_Y_SHIFT                                             16
+#define   NV20TCL_VERTEX_NOR_3I_XY_Y_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_NOR_3I_Z                                                       0x00001544
+#define   NV20TCL_VERTEX_NOR_3I_Z_Z_SHIFT                                              0
+#define   NV20TCL_VERTEX_NOR_3I_Z_Z_MASK                                               0x0000ffff
+#define  NV20TCL_VERTEX_COL_4F_X                                                       0x00001550
+#define  NV20TCL_VERTEX_COL_4F_Y                                                       0x00001554
+#define  NV20TCL_VERTEX_COL_4F_Z                                                       0x00001558
+#define  NV20TCL_VERTEX_COL_4F_W                                                       0x0000155c
+#define  NV20TCL_VERTEX_COL_3F_X                                                       0x00001560
+#define  NV20TCL_VERTEX_COL_3F_Y                                                       0x00001564
+#define  NV20TCL_VERTEX_COL_3F_Z                                                       0x00001568
+#define  NV20TCL_VERTEX_COL_4I                                                         0x0000156c
+#define   NV20TCL_VERTEX_COL_4I_R_SHIFT                                                        0
+#define   NV20TCL_VERTEX_COL_4I_R_MASK                                                 0x000000ff
+#define   NV20TCL_VERTEX_COL_4I_G_SHIFT                                                        8
+#define   NV20TCL_VERTEX_COL_4I_G_MASK                                                 0x0000ff00
+#define   NV20TCL_VERTEX_COL_4I_B_SHIFT                                                        16
+#define   NV20TCL_VERTEX_COL_4I_B_MASK                                                 0x00ff0000
+#define   NV20TCL_VERTEX_COL_4I_A_SHIFT                                                        24
+#define   NV20TCL_VERTEX_COL_4I_A_MASK                                                 0xff000000
+#define  NV20TCL_VERTEX_COL2_3F_X                                                      0x00001580
+#define  NV20TCL_VERTEX_COL2_3F_Y                                                      0x00001584
+#define  NV20TCL_VERTEX_COL2_3F_Z                                                      0x00001588
+#define  NV20TCL_VERTEX_COL2_4I                                                                0x0000158c
+#define   NV20TCL_VERTEX_COL2_4I_R_SHIFT                                               0
+#define   NV20TCL_VERTEX_COL2_4I_R_MASK                                                        0x000000ff
+#define   NV20TCL_VERTEX_COL2_4I_G_SHIFT                                               8
+#define   NV20TCL_VERTEX_COL2_4I_G_MASK                                                        0x0000ff00
+#define   NV20TCL_VERTEX_COL2_4I_B_SHIFT                                               16
+#define   NV20TCL_VERTEX_COL2_4I_B_MASK                                                        0x00ff0000
+#define   NV20TCL_VERTEX_COL2_4I_A_SHIFT                                               24
+#define   NV20TCL_VERTEX_COL2_4I_A_MASK                                                        0xff000000
+#define  NV20TCL_VERTEX_TX0_2F_S                                                       0x00001590
+#define  NV20TCL_VERTEX_TX0_2F_T                                                       0x00001594
+#define  NV20TCL_VERTEX_TX0_2I                                                         0x00001598
+#define   NV20TCL_VERTEX_TX0_2I_S_SHIFT                                                        0
+#define   NV20TCL_VERTEX_TX0_2I_S_MASK                                                 0x0000ffff
+#define   NV20TCL_VERTEX_TX0_2I_T_SHIFT                                                        16
+#define   NV20TCL_VERTEX_TX0_2I_T_MASK                                                 0xffff0000
+#define  NV20TCL_VERTEX_TX0_4F_S                                                       0x000015a0
+#define  NV20TCL_VERTEX_TX0_4F_T                                                       0x000015a4
+#define  NV20TCL_VERTEX_TX0_4F_R                                                       0x000015a8
+#define  NV20TCL_VERTEX_TX0_4F_Q                                                       0x000015ac
+#define  NV20TCL_VERTEX_TX0_4I_ST                                                      0x000015b0
+#define   NV20TCL_VERTEX_TX0_4I_ST_S_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX0_4I_ST_S_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX0_4I_ST_T_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX0_4I_ST_T_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX0_4I_RQ                                                      0x000015b4
+#define   NV20TCL_VERTEX_TX0_4I_RQ_R_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX0_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX0_4I_RQ_Q_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX0_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX1_2F_S                                                       0x000015b8
+#define  NV20TCL_VERTEX_TX1_2F_T                                                       0x000015bc
+#define  NV20TCL_VERTEX_TX1_2I                                                         0x000015c0
+#define   NV20TCL_VERTEX_TX1_2I_S_SHIFT                                                        0
+#define   NV20TCL_VERTEX_TX1_2I_S_MASK                                                 0x0000ffff
+#define   NV20TCL_VERTEX_TX1_2I_T_SHIFT                                                        16
+#define   NV20TCL_VERTEX_TX1_2I_T_MASK                                                 0xffff0000
+#define  NV20TCL_VERTEX_TX1_4F_S                                                       0x000015c8
+#define  NV20TCL_VERTEX_TX1_4F_T                                                       0x000015cc
+#define  NV20TCL_VERTEX_TX1_4F_R                                                       0x000015d0
+#define  NV20TCL_VERTEX_TX1_4F_Q                                                       0x000015d4
+#define  NV20TCL_VERTEX_TX1_4I_ST                                                      0x000015d8
+#define   NV20TCL_VERTEX_TX1_4I_ST_S_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX1_4I_ST_S_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX1_4I_ST_T_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX1_4I_ST_T_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX1_4I_RQ                                                      0x000015dc
+#define   NV20TCL_VERTEX_TX1_4I_RQ_R_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX1_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX1_4I_RQ_Q_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX1_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX2_2F_S                                                       0x000015e0
+#define  NV20TCL_VERTEX_TX2_2F_T                                                       0x000015e4
+#define  NV20TCL_VERTEX_TX2_2I                                                         0x000015e8
+#define   NV20TCL_VERTEX_TX2_2I_S_SHIFT                                                        0
+#define   NV20TCL_VERTEX_TX2_2I_S_MASK                                                 0x0000ffff
+#define   NV20TCL_VERTEX_TX2_2I_T_SHIFT                                                        16
+#define   NV20TCL_VERTEX_TX2_2I_T_MASK                                                 0xffff0000
+#define  NV20TCL_VERTEX_TX2_4F_S                                                       0x000015f0
+#define  NV20TCL_VERTEX_TX2_4F_T                                                       0x000015f4
+#define  NV20TCL_VERTEX_TX2_4F_R                                                       0x000015f8
+#define  NV20TCL_VERTEX_TX2_4F_Q                                                       0x000015fc
+#define  NV20TCL_VERTEX_TX2_4I_ST                                                      0x00001600
+#define   NV20TCL_VERTEX_TX2_4I_ST_S_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX2_4I_ST_S_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX2_4I_ST_T_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX2_4I_ST_T_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX2_4I_RQ                                                      0x00001604
+#define   NV20TCL_VERTEX_TX2_4I_RQ_R_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX2_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX2_4I_RQ_Q_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX2_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX3_2F_S                                                       0x00001608
+#define  NV20TCL_VERTEX_TX3_2F_T                                                       0x0000160c
+#define  NV20TCL_VERTEX_TX3_2I                                                         0x00001610
+#define   NV20TCL_VERTEX_TX3_2I_S_SHIFT                                                        0
+#define   NV20TCL_VERTEX_TX3_2I_S_MASK                                                 0x0000ffff
+#define   NV20TCL_VERTEX_TX3_2I_T_SHIFT                                                        16
+#define   NV20TCL_VERTEX_TX3_2I_T_MASK                                                 0xffff0000
+#define  NV20TCL_VERTEX_TX3_4F_S                                                       0x00001620
+#define  NV20TCL_VERTEX_TX3_4F_T                                                       0x00001624
+#define  NV20TCL_VERTEX_TX3_4F_R                                                       0x00001628
+#define  NV20TCL_VERTEX_TX3_4F_Q                                                       0x0000162c
+#define  NV20TCL_VERTEX_TX3_4I_ST                                                      0x00001630
+#define   NV20TCL_VERTEX_TX3_4I_ST_S_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX3_4I_ST_S_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX3_4I_ST_T_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX3_4I_ST_T_MASK                                              0xffff0000
+#define  NV20TCL_VERTEX_TX3_4I_RQ                                                      0x00001634
+#define   NV20TCL_VERTEX_TX3_4I_RQ_R_SHIFT                                             0
+#define   NV20TCL_VERTEX_TX3_4I_RQ_R_MASK                                              0x0000ffff
+#define   NV20TCL_VERTEX_TX3_4I_RQ_Q_SHIFT                                             16
+#define   NV20TCL_VERTEX_TX3_4I_RQ_Q_MASK                                              0xffff0000
+#define  NV20TCL_EDGEFLAG_ENABLE                                                       0x000016bc
+#define  NV20TCL_VERTEX_ATTR_OFFSET(x)                                                 (0x00001720+((x)*4))
+#define  NV20TCL_VERTEX_ATTR_OFFSET__SIZE                                              0x00000010
+#define  NV20TCL_VERTEX_ARRAY_FORMAT(x)                                                        (0x00001760+((x)*4))
+#define  NV20TCL_VERTEX_ARRAY_FORMAT__SIZE                                             0x00000010
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_TYPE_SHIFT                                       0
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_TYPE_MASK                                                0x0000000f
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_FIELDS_SHIFT                                     4
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_FIELDS_MASK                                      0x000000f0
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_STRIDE_SHIFT                                     8
+#define   NV20TCL_VERTEX_ARRAY_FORMAT_STRIDE_MASK                                      0x0000ff00
+#define  NV20TCL_COLOR_LOGIC_OP_ENABLE                                                 0x000017bc
+#define  NV20TCL_COLOR_LOGIC_OP_OP                                                     0x000017c0
+#define  NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE                                           0x000017c4
+#define  NV20TCL_TX_SHADER_CULL_MODE                                                   0x000017f8
+#define  NV20TCL_VERTEX_BEGIN_END                                                      0x000017fc
+#define  NV20TCL_VERTEX_BUFFER_DRAW_ARRAYS                                             0x00001810
+#define  NV20TCL_VERTEX_ARRAY_DATA                                                     0x00001818
+#define  NV20TCL_TX_OFFSET(x)                                                          (0x00001b00+((x)*64))
+#define  NV20TCL_TX_OFFSET__SIZE                                                       0x00000004
+#define  NV20TCL_TX_FORMAT(x)                                                          (0x00001b04+((x)*64))
+#define  NV20TCL_TX_FORMAT__SIZE                                                       0x00000004
+#define  NV20TCL_TX_WRAP(x)                                                            (0x00001b08+((x)*64))
+#define  NV20TCL_TX_WRAP__SIZE                                                         0x00000004
+#define  NV20TCL_TX_ENABLE(x)                                                          (0x00001b0c+((x)*64))
+#define  NV20TCL_TX_ENABLE__SIZE                                                       0x00000004
+#define  NV20TCL_TX_FILTER(x)                                                          (0x00001b14+((x)*64))
+#define  NV20TCL_TX_FILTER__SIZE                                                       0x00000004
+#define  NV20TCL_TX_BORDER_COLOR(x)                                                    (0x00001b24+((x)*64))
+#define  NV20TCL_TX_BORDER_COLOR__SIZE                                                 0x00000004
+#define  NV20TCL_SCISSOR_HORIZ                                                         0x00001c30
+#define  NV20TCL_SCISSOR_VERT                                                          0x00001c50
+#define  NV20TCL_MULTISAMPLE_CONTROL                                                   0x00001d7c
+#define  NV20TCL_CLEAR_VALUE                                                           0x00001d90
+#define  NV20TCL_CLEAR_BUFFERS                                                         0x00001d94
+#define  NV20TCL_RC_COLOR0                                                             0x00001e20
+#define  NV20TCL_RC_COLOR1                                                             0x00001e24
+#define  NV20TCL_RC_OUT_RGB(x)                                                         (0x00001e40+((x)*4))
+#define  NV20TCL_RC_OUT_RGB__SIZE                                                      0x00000008
+#define  NV20TCL_RC_ENABLE                                                             0x00001e60
+#define  NV20TCL_TX_SHADER_OP                                                          0x00001e70
+#define  NV20TCL_VP_UPLOAD_CONST_ID                                                    0x00001ea4
+
+
+#define NV17TCL                                                                                0x00000099
+
+#define  NV17TCL_DMA_IN_MEMORY4                                                                0x000001ac
+#define  NV17TCL_DMA_IN_MEMORY5                                                                0x000001b0
+#define  NV17TCL_COLOR_MASK_ENABLE                                                     0x000002bc
+#define  NV17TCL_LMA_DEPTH_BUFFER_PITCH                                                        0x00000d5c
+#define  NV17TCL_LMA_DEPTH_BUFFER_OFFSET                                               0x00000d60
+#define  NV17TCL_LMA_DEPTH_FILL_VALUE                                                  0x00000d68
+#define  NV17TCL_LMA_DEPTH_BUFFER_CLEAR                                                        0x00000d6c
+#define  NV17TCL_LMA_DEPTH_ENABLE                                                      0x00001658
+
+
+#define NV20_SWIZZLED_SURFACE                                                          0x0000009e
+
+
+
+#define NV12_IMAGE_BLIT                                                                        0x0000009f
+
+
+
+#define NV30_CONTEXT_SURFACES_2D                                                       0x00000362
+
+
+
+#define NV30_STRETCHED_IMAGE_FROM_CPU                                                  0x00000366
+
+
+
+#define NV30_TEXTURE_FROM_CPU                                                          0x0000037b
+
+
+
+#define NV30_SCALED_IMAGE_FROM_MEMORY                                                  0x00000389
+
+
+
+#define NV30_IMAGE_FROM_CPU                                                            0x0000038a
+
+
+
+#define NV30TCL                                                                                0x00000397
+
+
+
+#define NV30_SWIZZLED_SURFACE                                                          0x0000039e
+
+
+
+#define NV35TCL                                                                                0x00000497
+
+
+
+#define NV25TCL                                                                                0x00000597
+
+#define  NV25TCL_DMA_IN_MEMORY4                                                                0x0000019c
+#define  NV25TCL_DMA_IN_MEMORY5                                                                0x000001a0
+#define  NV25TCL_DMA_IN_MEMORY8                                                                0x000001ac
+#define  NV25TCL_DMA_IN_MEMORY9                                                                0x000001b0
+
+
+#define NV34TCL                                                                                0x00000697
+
+#define  NV34TCL_NOP                                                                   0x00000100
+#define  NV34TCL_NOTIFY                                                                        0x00000104
+#define  NV34TCL_DMA_NOTIFY                                                            0x00000180
+#define  NV34TCL_DMA_TEXTURE0                                                          0x00000184
+#define  NV34TCL_DMA_TEXTURE1                                                          0x00000188
+#define  NV34TCL_DMA_COLOR1                                                            0x0000018c
+#define  NV34TCL_DMA_COLOR0                                                            0x00000194
+#define  NV34TCL_DMA_ZETA                                                              0x00000198
+#define  NV34TCL_DMA_VTXBUF0                                                           0x0000019c
+#define  NV34TCL_DMA_VTXBUF1                                                           0x000001a0
+#define  NV34TCL_DMA_FENCE                                                             0x000001a4
+#define  NV34TCL_DMA_QUERY                                                             0x000001a8
+#define  NV34TCL_DMA_IN_MEMORY7                                                                0x000001ac
+#define  NV34TCL_DMA_IN_MEMORY8                                                                0x000001b0
+#define  NV34TCL_RT_HORIZ                                                              0x00000200
+#define   NV34TCL_RT_HORIZ_X_SHIFT                                                     0
+#define   NV34TCL_RT_HORIZ_X_MASK                                                      0x0000ffff
+#define   NV34TCL_RT_HORIZ_W_SHIFT                                                     16
+#define   NV34TCL_RT_HORIZ_W_MASK                                                      0xffff0000
+#define  NV34TCL_RT_VERT                                                               0x00000204
+#define   NV34TCL_RT_VERT_Y_SHIFT                                                      0
+#define   NV34TCL_RT_VERT_Y_MASK                                                       0x0000ffff
+#define   NV34TCL_RT_VERT_H_SHIFT                                                      16
+#define   NV34TCL_RT_VERT_H_MASK                                                       0xffff0000
+#define  NV34TCL_RT_FORMAT                                                             0x00000208
+#define   NV34TCL_RT_FORMAT_TYPE_SHIFT                                                 8
+#define   NV34TCL_RT_FORMAT_TYPE_MASK                                                  0x00000f00
+#define    NV34TCL_RT_FORMAT_TYPE_LINEAR                                               0x00000100
+#define    NV34TCL_RT_FORMAT_TYPE_SWIZZLED                                             0x00000200
+#define   NV34TCL_RT_FORMAT_ZETA_SHIFT                                                 5
+#define   NV34TCL_RT_FORMAT_ZETA_MASK                                                  0x000000e0
+#define    NV34TCL_RT_FORMAT_ZETA_Z16                                                  0x00000020
+#define    NV34TCL_RT_FORMAT_ZETA_Z24S8                                                        0x00000040
+#define   NV34TCL_RT_FORMAT_COLOR_SHIFT                                                        0
+#define   NV34TCL_RT_FORMAT_COLOR_MASK                                                 0x0000001f
+#define    NV34TCL_RT_FORMAT_COLOR_R5G6B5                                              0x00000003
+#define    NV34TCL_RT_FORMAT_COLOR_X8R8G8B8                                            0x00000005
+#define    NV34TCL_RT_FORMAT_COLOR_A8R8G8B8                                            0x00000008
+#define    NV34TCL_RT_FORMAT_COLOR_B8                                                  0x00000009
+#define    NV34TCL_RT_FORMAT_COLOR_X8B8G8R8                                            0x0000000f
+#define    NV34TCL_RT_FORMAT_COLOR_A8B8G8R8                                            0x00000010
+#define  NV34TCL_COLOR0_PITCH                                                          0x0000020c
+#define   NV34TCL_COLOR0_PITCH_COLOR0_SHIFT                                            0
+#define   NV34TCL_COLOR0_PITCH_COLOR0_MASK                                             0x0000ffff
+#define   NV34TCL_COLOR0_PITCH_ZETA_SHIFT                                              16
+#define   NV34TCL_COLOR0_PITCH_ZETA_MASK                                               0xffff0000
+#define  NV34TCL_COLOR0_OFFSET                                                         0x00000210
+#define  NV34TCL_ZETA_OFFSET                                                           0x00000214
+#define  NV34TCL_COLOR1_OFFSET                                                         0x00000218
+#define  NV34TCL_COLOR1_PITCH                                                          0x0000021c
+#define  NV34TCL_RT_ENABLE                                                             0x00000220
+#define   NV34TCL_RT_ENABLE_MRT                                                                (1 <<  4)
+#define   NV34TCL_RT_ENABLE_COLOR1                                                     (1 <<  1)
+#define   NV34TCL_RT_ENABLE_COLOR0                                                     (1 <<  0)
+#define  NV34TCL_LMA_DEPTH_PITCH                                                       0x0000022c
+#define  NV34TCL_LMA_DEPTH_OFFSET                                                      0x00000230
+#define  NV34TCL_TX_UNITS_ENABLE                                                       0x0000023c
+#define   NV34TCL_TX_UNITS_ENABLE_TX0                                                  (1 <<  0)
+#define   NV34TCL_TX_UNITS_ENABLE_TX1                                                  (1 <<  1)
+#define   NV34TCL_TX_UNITS_ENABLE_TX2                                                  (1 <<  2)
+#define   NV34TCL_TX_UNITS_ENABLE_TX3                                                  (1 <<  3)
+#define  NV34TCL_TX_MATRIX_ENABLE(x)                                                   (0x00000240+((x)*4))
+#define  NV34TCL_TX_MATRIX_ENABLE__SIZE                                                        0x00000004
+#define  NV34TCL_UNK0250(x)                                                            (0x00000250+((x)*4))
+#define  NV34TCL_UNK0250__SIZE                                                         0x00000004
+#define  NV34TCL_VIEWPORT_TX_ORIGIN                                                    0x000002b8
+#define   NV34TCL_VIEWPORT_TX_ORIGIN_X_SHIFT                                           0
+#define   NV34TCL_VIEWPORT_TX_ORIGIN_X_MASK                                            0x0000ffff
+#define   NV34TCL_VIEWPORT_TX_ORIGIN_Y_SHIFT                                           16
+#define   NV34TCL_VIEWPORT_TX_ORIGIN_Y_MASK                                            0xffff0000
+#define  NV34TCL_VIEWPORT_CLIP_HORIZ(x)                                                        (0x000002c0+((x)*8))
+#define  NV34TCL_VIEWPORT_CLIP_HORIZ__SIZE                                             0x00000008
+#define   NV34TCL_VIEWPORT_CLIP_HORIZ_L_SHIFT                                          0
+#define   NV34TCL_VIEWPORT_CLIP_HORIZ_L_MASK                                           0x0000ffff
+#define   NV34TCL_VIEWPORT_CLIP_HORIZ_R_SHIFT                                          16
+#define   NV34TCL_VIEWPORT_CLIP_HORIZ_R_MASK                                           0xffff0000
+#define  NV34TCL_VIEWPORT_CLIP_VERT(x)                                                 (0x000002c4+((x)*8))
+#define  NV34TCL_VIEWPORT_CLIP_VERT__SIZE                                              0x00000008
+#define   NV34TCL_VIEWPORT_CLIP_VERT_T_SHIFT                                           0
+#define   NV34TCL_VIEWPORT_CLIP_VERT_T_MASK                                            0x0000ffff
+#define   NV34TCL_VIEWPORT_CLIP_VERT_D_SHIFT                                           16
+#define   NV34TCL_VIEWPORT_CLIP_VERT_D_MASK                                            0xffff0000
+#define  NV34TCL_DITHER_ENABLE                                                         0x00000300
+#define  NV34TCL_ALPHA_FUNC_ENABLE                                                     0x00000304
+#define  NV34TCL_ALPHA_FUNC_FUNC                                                       0x00000308
+#define   NV34TCL_ALPHA_FUNC_FUNC_NEVER                                                        0x00000200
+#define   NV34TCL_ALPHA_FUNC_FUNC_LESS                                                 0x00000201
+#define   NV34TCL_ALPHA_FUNC_FUNC_EQUAL                                                        0x00000202
+#define   NV34TCL_ALPHA_FUNC_FUNC_LEQUAL                                               0x00000203
+#define   NV34TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV34TCL_ALPHA_FUNC_FUNC_GREATER                                              0x00000204
+#define   NV34TCL_ALPHA_FUNC_FUNC_NOTEQUAL                                             0x00000205
+#define   NV34TCL_ALPHA_FUNC_FUNC_GEQUAL                                               0x00000206
+#define   NV34TCL_ALPHA_FUNC_FUNC_ALWAYS                                               0x00000207
+#define  NV34TCL_ALPHA_FUNC_REF                                                                0x0000030c
+#define  NV34TCL_BLEND_FUNC_ENABLE                                                     0x00000310
+#define  NV34TCL_BLEND_FUNC_SRC                                                                0x00000314
+#define   NV34TCL_BLEND_FUNC_SRC_RGB_SHIFT                                             0
+#define   NV34TCL_BLEND_FUNC_SRC_RGB_MASK                                              0x0000ffff
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ZERO                                             0x00000000
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE                                              0x00000001
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR                                                0x00000300
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR                              0x00000301
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA                                                0x00000302
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA                              0x00000303
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA                                                0x00000304
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA                              0x00000305
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_DST_COLOR                                                0x00000306
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR                              0x00000307
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE                               0x00000308
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR                                   0x00008001
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR                         0x00008002
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA                                   0x00008003
+#define    NV34TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA                         0x00008004
+#define   NV34TCL_BLEND_FUNC_SRC_ALPHA_SHIFT                                           16
+#define   NV34TCL_BLEND_FUNC_SRC_ALPHA_MASK                                            0xffff0000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ZERO                                           0x00000000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE                                            0x00010000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR                                      0x03000000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR                            0x03010000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA                                      0x03020000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA                            0x03030000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA                                      0x03040000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA                            0x03050000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR                                      0x03060000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR                            0x03070000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE                             0x03080000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR                                 0x80010000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR                       0x80020000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA                                 0x80030000
+#define    NV34TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA                       0x80040000
+#define  NV34TCL_BLEND_FUNC_DST                                                                0x00000318
+#define   NV34TCL_BLEND_FUNC_DST_RGB_SHIFT                                             0
+#define   NV34TCL_BLEND_FUNC_DST_RGB_MASK                                              0x0000ffff
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ZERO                                             0x00000000
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE                                              0x00000001
+#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_COLOR                                                0x00000300
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR                              0x00000301
+#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA                                                0x00000302
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA                              0x00000303
+#define    NV34TCL_BLEND_FUNC_DST_RGB_DST_ALPHA                                                0x00000304
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA                              0x00000305
+#define    NV34TCL_BLEND_FUNC_DST_RGB_DST_COLOR                                                0x00000306
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR                              0x00000307
+#define    NV34TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE                               0x00000308
+#define    NV34TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR                                   0x00008001
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR                         0x00008002
+#define    NV34TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA                                   0x00008003
+#define    NV34TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA                         0x00008004
+#define   NV34TCL_BLEND_FUNC_DST_ALPHA_SHIFT                                           16
+#define   NV34TCL_BLEND_FUNC_DST_ALPHA_MASK                                            0xffff0000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ZERO                                           0x00000000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE                                            0x00010000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR                                      0x03000000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR                            0x03010000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA                                      0x03020000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA                            0x03030000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA                                      0x03040000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA                            0x03050000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR                                      0x03060000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR                            0x03070000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE                             0x03080000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR                                 0x80010000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR                       0x80020000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA                                 0x80030000
+#define    NV34TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA                       0x80040000
+#define  NV34TCL_BLEND_COLOR                                                           0x0000031c
+#define   NV34TCL_BLEND_COLOR_B_SHIFT                                                  0
+#define   NV34TCL_BLEND_COLOR_B_MASK                                                   0x000000ff
+#define   NV34TCL_BLEND_COLOR_G_SHIFT                                                  8
+#define   NV34TCL_BLEND_COLOR_G_MASK                                                   0x0000ff00
+#define   NV34TCL_BLEND_COLOR_R_SHIFT                                                  16
+#define   NV34TCL_BLEND_COLOR_R_MASK                                                   0x00ff0000
+#define   NV34TCL_BLEND_COLOR_A_SHIFT                                                  24
+#define   NV34TCL_BLEND_COLOR_A_MASK                                                   0xff000000
+#define  NV34TCL_BLEND_EQUATION                                                                0x00000320
+#define   NV34TCL_BLEND_EQUATION_FUNC_ADD                                              0x00008006
+#define   NV34TCL_BLEND_EQUATION_MIN                                                   0x00008007
+#define   NV34TCL_BLEND_EQUATION_MAX                                                   0x00008008
+#define   NV34TCL_BLEND_EQUATION_FUNC_SUBTRACT                                         0x0000800a
+#define   NV34TCL_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT                                 0x0000800b
+#define  NV34TCL_COLOR_MASK                                                            0x00000324
+#define   NV34TCL_COLOR_MASK_B_SHIFT                                                   0
+#define   NV34TCL_COLOR_MASK_B_MASK                                                    0x000000ff
+#define   NV34TCL_COLOR_MASK_G_SHIFT                                                   8
+#define   NV34TCL_COLOR_MASK_G_MASK                                                    0x0000ff00
+#define   NV34TCL_COLOR_MASK_R_SHIFT                                                   16
+#define   NV34TCL_COLOR_MASK_R_MASK                                                    0x00ff0000
+#define   NV34TCL_COLOR_MASK_A_SHIFT                                                   24
+#define   NV34TCL_COLOR_MASK_A_MASK                                                    0xff000000
+#define  NV34TCL_STENCIL_BACK_ENABLE                                                   0x00000328
+#define  NV34TCL_STENCIL_BACK_MASK                                                     0x0000032c
+#define  NV34TCL_STENCIL_BACK_FUNC_FUNC                                                        0x00000330
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_NEVER                                         0x00000200
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_LESS                                          0x00000201
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_EQUAL                                         0x00000202
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL                                                0x00000203
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL                                      0x00000205
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL                                                0x00000206
+#define   NV34TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS                                                0x00000207
+#define  NV34TCL_STENCIL_BACK_FUNC_REF                                                 0x00000334
+#define  NV34TCL_STENCIL_BACK_FUNC_MASK                                                        0x00000338
+#define  NV34TCL_STENCIL_BACK_OP_FAIL                                                  0x0000033c
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_ZERO                                            0x00000000
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_INVERT                                          0x0000150a
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_KEEP                                            0x00001e00
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_REPLACE                                         0x00001e01
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_INCR                                            0x00001e02
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_DECR                                            0x00001e03
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP                                       0x00008507
+#define   NV34TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP                                       0x00008508
+#define  NV34TCL_STENCIL_BACK_OP_ZFAIL                                                 0x00000340
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_ZERO                                           0x00000000
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INVERT                                         0x0000150a
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_KEEP                                           0x00001e00
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_REPLACE                                                0x00001e01
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INCR                                           0x00001e02
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_DECR                                           0x00001e03
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP                                      0x00008507
+#define   NV34TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP                                      0x00008508
+#define  NV34TCL_STENCIL_BACK_OP_ZPASS                                                 0x00000344
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_ZERO                                           0x00000000
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INVERT                                         0x0000150a
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_KEEP                                           0x00001e00
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_REPLACE                                                0x00001e01
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INCR                                           0x00001e02
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_DECR                                           0x00001e03
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP                                      0x00008507
+#define   NV34TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP                                      0x00008508
+#define  NV34TCL_STENCIL_FRONT_ENABLE                                                  0x00000348
+#define  NV34TCL_STENCIL_FRONT_MASK                                                    0x0000034c
+#define  NV34TCL_STENCIL_FRONT_FUNC_FUNC                                               0x00000350
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_NEVER                                                0x00000200
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_LESS                                         0x00000201
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL                                                0x00000202
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL                                       0x00000203
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL                                     0x00000205
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL                                       0x00000206
+#define   NV34TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS                                       0x00000207
+#define  NV34TCL_STENCIL_FRONT_FUNC_REF                                                        0x00000354
+#define  NV34TCL_STENCIL_FRONT_FUNC_MASK                                               0x00000358
+#define  NV34TCL_STENCIL_FRONT_OP_FAIL                                                 0x0000035c
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_ZERO                                           0x00000000
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INVERT                                         0x0000150a
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_KEEP                                           0x00001e00
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_REPLACE                                                0x00001e01
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INCR                                           0x00001e02
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_DECR                                           0x00001e03
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP                                      0x00008507
+#define   NV34TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP                                      0x00008508
+#define  NV34TCL_STENCIL_FRONT_OP_ZFAIL                                                        0x00000360
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_ZERO                                          0x00000000
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INVERT                                                0x0000150a
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_KEEP                                          0x00001e00
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE                                       0x00001e01
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INCR                                          0x00001e02
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_DECR                                          0x00001e03
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP                                     0x00008507
+#define   NV34TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP                                     0x00008508
+#define  NV34TCL_STENCIL_FRONT_OP_ZPASS                                                        0x00000364
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_ZERO                                          0x00000000
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INVERT                                                0x0000150a
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_KEEP                                          0x00001e00
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_REPLACE                                       0x00001e01
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INCR                                          0x00001e02
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_DECR                                          0x00001e03
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP                                     0x00008507
+#define   NV34TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP                                     0x00008508
+#define  NV34TCL_SHADE_MODEL                                                           0x00000368
+#define   NV34TCL_SHADE_MODEL_FLAT                                                     0x00001d00
+#define   NV34TCL_SHADE_MODEL_SMOOTH                                                   0x00001d01
+#define  NV34TCL_FOG_ENABLE                                                            0x0000036c
+#define  NV34TCL_FOG_COLOR                                                             0x00000370
+#define  NV34TCL_COLOR_LOGIC_OP_ENABLE                                                 0x00000374
+#define  NV34TCL_COLOR_LOGIC_OP_OP                                                     0x00000378
+#define   NV34TCL_COLOR_LOGIC_OP_OP_CLEAR                                              0x00001500
+#define   NV34TCL_COLOR_LOGIC_OP_OP_AND                                                        0x00001501
+#define   NV34TCL_COLOR_LOGIC_OP_OP_AND_REVERSE                                                0x00001502
+#define   NV34TCL_COLOR_LOGIC_OP_OP_COPY                                               0x00001503
+#define   NV34TCL_COLOR_LOGIC_OP_OP_AND_INVERTED                                       0x00001504
+#define   NV34TCL_COLOR_LOGIC_OP_OP_NOOP                                               0x00001505
+#define   NV34TCL_COLOR_LOGIC_OP_OP_XOR                                                        0x00001506
+#define   NV34TCL_COLOR_LOGIC_OP_OP_OR                                                 0x00001507
+#define   NV34TCL_COLOR_LOGIC_OP_OP_NOR                                                        0x00001508
+#define   NV34TCL_COLOR_LOGIC_OP_OP_EQUIV                                              0x00001509
+#define   NV34TCL_COLOR_LOGIC_OP_OP_INVERT                                             0x0000150a
+#define   NV34TCL_COLOR_LOGIC_OP_OP_OR_REVERSE                                         0x0000150b
+#define   NV34TCL_COLOR_LOGIC_OP_OP_COPY_INVERTED                                      0x0000150c
+#define   NV34TCL_COLOR_LOGIC_OP_OP_OR_INVERTED                                                0x0000150d
+#define   NV34TCL_COLOR_LOGIC_OP_OP_NAND                                               0x0000150e
+#define   NV34TCL_COLOR_LOGIC_OP_OP_SET                                                        0x0000150f
+#define  NV34TCL_NORMALIZE_ENABLE                                                      0x0000037c
+#define  NV34TCL_COLOR_MATERIAL                                                                0x00000390
+#define   NV34TCL_COLOR_MATERIAL_FRONT_EMISSION_ENABLE                                 (1 <<  0)
+#define   NV34TCL_COLOR_MATERIAL_FRONT_AMBIENT_ENABLE                                  (1 <<  2)
+#define   NV34TCL_COLOR_MATERIAL_FRONT_DIFFUSE_ENABLE                                  (1 <<  4)
+#define   NV34TCL_COLOR_MATERIAL_FRONT_SPECULAR_ENABLE                                 (1 <<  6)
+#define   NV34TCL_COLOR_MATERIAL_BACK_EMISSION_ENABLE                                  (1 <<  8)
+#define   NV34TCL_COLOR_MATERIAL_BACK_AMBIENT_ENABLE                                   (1 << 10)
+#define   NV34TCL_COLOR_MATERIAL_BACK_DIFFUSE_ENABLE                                   (1 << 12)
+#define   NV34TCL_COLOR_MATERIAL_BACK_SPECULAR_ENABLE                                  (1 << 14)
+#define  NV34TCL_DEPTH_RANGE_NEAR                                                      0x00000394
+#define  NV34TCL_DEPTH_RANGE_FAR                                                       0x00000398
+#define  NV34TCL_COLOR_MATERIAL_FRONT_R                                                        0x000003a0
+#define  NV34TCL_COLOR_MATERIAL_FRONT_G                                                        0x000003a4
+#define  NV34TCL_COLOR_MATERIAL_FRONT_B                                                        0x000003a8
+#define  NV34TCL_COLOR_MATERIAL_FRONT_A                                                        0x000003b4
+#define  NV34TCL_LINE_WIDTH                                                            0x000003b8
+#define  NV34TCL_LINE_SMOOTH_ENABLE                                                    0x000003bc
+#define  NV34TCL_CLIP_PLANE_ENABLE(x)                                                  (0x00000400+((x)*4))
+#define  NV34TCL_CLIP_PLANE_ENABLE__SIZE                                               0x00000020
+#define   NV34TCL_CLIP_PLANE_ENABLE_FALSE                                              0x00000000
+#define   NV34TCL_CLIP_PLANE_ENABLE_EYE_LINEAR                                         0x00002400
+#define   NV34TCL_CLIP_PLANE_ENABLE_OBJECT_LINEAR                                      0x00002401
+#define  NV34TCL_MODELVIEW_MATRIX(x)                                                   (0x00000480+((x)*4))
+#define  NV34TCL_MODELVIEW_MATRIX__SIZE                                                        0x00000010
+#define  NV34TCL_INVERSE_MODELVIEW_MATRIX(x)                                           (0x00000580+((x)*4))
+#define  NV34TCL_INVERSE_MODELVIEW_MATRIX__SIZE                                                0x0000000c
+#define  NV34TCL_PROJECTION_MATRIX(x)                                                  (0x00000680+((x)*4))
+#define  NV34TCL_PROJECTION_MATRIX__SIZE                                               0x00000010
+#define  NV34TCL_TX0_MATRIX(x)                                                         (0x000006c0+((x)*4))
+#define  NV34TCL_TX0_MATRIX__SIZE                                                      0x00000010
+#define  NV34TCL_TX1_MATRIX(x)                                                         (0x00000700+((x)*4))
+#define  NV34TCL_TX1_MATRIX__SIZE                                                      0x00000010
+#define  NV34TCL_TX2_MATRIX(x)                                                         (0x00000740+((x)*4))
+#define  NV34TCL_TX2_MATRIX__SIZE                                                      0x00000010
+#define  NV34TCL_TX3_MATRIX(x)                                                         (0x00000780+((x)*4))
+#define  NV34TCL_TX3_MATRIX__SIZE                                                      0x00000010
+#define  NV34TCL_SCISSOR_HORIZ                                                         0x000008c0
+#define   NV34TCL_SCISSOR_HORIZ_X_SHIFT                                                        0
+#define   NV34TCL_SCISSOR_HORIZ_X_MASK                                                 0x0000ffff
+#define   NV34TCL_SCISSOR_HORIZ_W_SHIFT                                                        16
+#define   NV34TCL_SCISSOR_HORIZ_W_MASK                                                 0xffff0000
+#define  NV34TCL_SCISSOR_VERT                                                          0x000008c4
+#define   NV34TCL_SCISSOR_VERT_Y_SHIFT                                                 0
+#define   NV34TCL_SCISSOR_VERT_Y_MASK                                                  0x0000ffff
+#define   NV34TCL_SCISSOR_VERT_H_SHIFT                                                 16
+#define   NV34TCL_SCISSOR_VERT_H_MASK                                                  0xffff0000
+#define  NV34TCL_FOG_COORD_DIST                                                                0x000008c8
+#define  NV34TCL_FOG_MODE                                                              0x000008cc
+#define   NV34TCL_FOG_MODE_EXP                                                         0x00000800
+#define   NV34TCL_FOG_MODE_EXP_2                                                       0x00000802
+#define   NV34TCL_FOG_MODE_EXP2                                                                0x00000803
+#define   NV34TCL_FOG_MODE_LINEAR                                                      0x00000804
+#define   NV34TCL_FOG_MODE_LINEAR_2                                                    0x00002601
+#define  NV34TCL_FOG_EQUATION_CONSTANT                                                 0x000008d0
+#define  NV34TCL_FOG_EQUATION_LINEAR                                                   0x000008d4
+#define  NV34TCL_FOG_EQUATION_QUADRATIC                                                        0x000008d8
+#define  NV34TCL_FP_ACTIVE_PROGRAM                                                     0x000008e4
+#define   NV34TCL_FP_ACTIVE_PROGRAM_DMA0                                               (1 <<  0)
+#define   NV34TCL_FP_ACTIVE_PROGRAM_DMA1                                               (1 <<  1)
+#define   NV34TCL_FP_ACTIVE_PROGRAM_OFFSET_SHIFT                                       2
+#define   NV34TCL_FP_ACTIVE_PROGRAM_OFFSET_MASK                                                0xfffffffc
+#define  NV34TCL_RC_COLOR0                                                             0x000008ec
+#define   NV34TCL_RC_COLOR0_B_SHIFT                                                    0
+#define   NV34TCL_RC_COLOR0_B_MASK                                                     0x000000ff
+#define   NV34TCL_RC_COLOR0_G_SHIFT                                                    8
+#define   NV34TCL_RC_COLOR0_G_MASK                                                     0x0000ff00
+#define   NV34TCL_RC_COLOR0_R_SHIFT                                                    16
+#define   NV34TCL_RC_COLOR0_R_MASK                                                     0x00ff0000
+#define   NV34TCL_RC_COLOR0_A_SHIFT                                                    24
+#define   NV34TCL_RC_COLOR0_A_MASK                                                     0xff000000
+#define  NV34TCL_RC_COLOR1                                                             0x000008f0
+#define   NV34TCL_RC_COLOR1_B_SHIFT                                                    0
+#define   NV34TCL_RC_COLOR1_B_MASK                                                     0x000000ff
+#define   NV34TCL_RC_COLOR1_G_SHIFT                                                    8
+#define   NV34TCL_RC_COLOR1_G_MASK                                                     0x0000ff00
+#define   NV34TCL_RC_COLOR1_R_SHIFT                                                    16
+#define   NV34TCL_RC_COLOR1_R_MASK                                                     0x00ff0000
+#define   NV34TCL_RC_COLOR1_A_SHIFT                                                    24
+#define   NV34TCL_RC_COLOR1_A_MASK                                                     0xff000000
+#define  NV34TCL_RC_FINAL0                                                             0x000008f4
+#define  NV34TCL_RC_FINAL1                                                             0x000008f8
+#define  NV34TCL_RC_ENABLE                                                             0x000008fc
+#define  NV34TCL_RC_IN_ALPHA(x)                                                                (0x00000900+((x)*32))
+#define  NV34TCL_RC_IN_ALPHA__SIZE                                                     0x00000008
+#define  NV34TCL_RC_IN_RGB(x)                                                          (0x00000904+((x)*32))
+#define  NV34TCL_RC_IN_RGB__SIZE                                                       0x00000008
+#define  NV34TCL_RC_CONSTANT_COLOR0(x)                                                 (0x00000908+((x)*32))
+#define  NV34TCL_RC_CONSTANT_COLOR0__SIZE                                              0x00000008
+#define   NV34TCL_RC_CONSTANT_COLOR0_B_SHIFT                                           0
+#define   NV34TCL_RC_CONSTANT_COLOR0_B_MASK                                            0x000000ff
+#define   NV34TCL_RC_CONSTANT_COLOR0_G_SHIFT                                           8
+#define   NV34TCL_RC_CONSTANT_COLOR0_G_MASK                                            0x0000ff00
+#define   NV34TCL_RC_CONSTANT_COLOR0_R_SHIFT                                           16
+#define   NV34TCL_RC_CONSTANT_COLOR0_R_MASK                                            0x00ff0000
+#define   NV34TCL_RC_CONSTANT_COLOR0_A_SHIFT                                           24
+#define   NV34TCL_RC_CONSTANT_COLOR0_A_MASK                                            0xff000000
+#define  NV34TCL_RC_CONSTANT_COLOR1(x)                                                 (0x0000090c+((x)*32))
+#define  NV34TCL_RC_CONSTANT_COLOR1__SIZE                                              0x00000008
+#define   NV34TCL_RC_CONSTANT_COLOR1_B_SHIFT                                           0
+#define   NV34TCL_RC_CONSTANT_COLOR1_B_MASK                                            0x000000ff
+#define   NV34TCL_RC_CONSTANT_COLOR1_G_SHIFT                                           8
+#define   NV34TCL_RC_CONSTANT_COLOR1_G_MASK                                            0x0000ff00
+#define   NV34TCL_RC_CONSTANT_COLOR1_R_SHIFT                                           16
+#define   NV34TCL_RC_CONSTANT_COLOR1_R_MASK                                            0x00ff0000
+#define   NV34TCL_RC_CONSTANT_COLOR1_A_SHIFT                                           24
+#define   NV34TCL_RC_CONSTANT_COLOR1_A_MASK                                            0xff000000
+#define  NV34TCL_RC_OUT_ALPHA(x)                                                       (0x00000910+((x)*32))
+#define  NV34TCL_RC_OUT_ALPHA__SIZE                                                    0x00000008
+#define  NV34TCL_RC_OUT_RGB(x)                                                         (0x00000914+((x)*32))
+#define  NV34TCL_RC_OUT_RGB__SIZE                                                      0x00000008
+#define  NV34TCL_VIEWPORT_HORIZ                                                                0x00000a00
+#define   NV34TCL_VIEWPORT_HORIZ_X_SHIFT                                               0
+#define   NV34TCL_VIEWPORT_HORIZ_X_MASK                                                        0x0000ffff
+#define   NV34TCL_VIEWPORT_HORIZ_W_SHIFT                                               16
+#define   NV34TCL_VIEWPORT_HORIZ_W_MASK                                                        0xffff0000
+#define  NV34TCL_VIEWPORT_VERT                                                         0x00000a04
+#define   NV34TCL_VIEWPORT_VERT_Y_SHIFT                                                        0
+#define   NV34TCL_VIEWPORT_VERT_Y_MASK                                                 0x0000ffff
+#define   NV34TCL_VIEWPORT_VERT_H_SHIFT                                                        16
+#define   NV34TCL_VIEWPORT_VERT_H_MASK                                                 0xffff0000
+#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R                        0x00000a10
+#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G                        0x00000a14
+#define  NV34TCL_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B                        0x00000a18
+#define  NV34TCL_VIEWPORT_TRANSLATE_X                                                  0x00000a20
+#define  NV34TCL_VIEWPORT_TRANSLATE_Y                                                  0x00000a24
+#define  NV34TCL_VIEWPORT_TRANSLATE_Z                                                  0x00000a28
+#define  NV34TCL_VIEWPORT_TRANSLATE_W                                                  0x00000a2c
+#define  NV34TCL_VIEWPORT_SCALE_X                                                      0x00000a30
+#define  NV34TCL_VIEWPORT_SCALE_Y                                                      0x00000a34
+#define  NV34TCL_VIEWPORT_SCALE_Z                                                      0x00000a38
+#define  NV34TCL_VIEWPORT_SCALE_W                                                      0x00000a3c
+#define  NV34TCL_POLYGON_OFFSET_POINT_ENABLE                                           0x00000a60
+#define  NV34TCL_POLYGON_OFFSET_LINE_ENABLE                                            0x00000a64
+#define  NV34TCL_POLYGON_OFFSET_FILL_ENABLE                                            0x00000a68
+#define  NV34TCL_DEPTH_FUNC                                                            0x00000a6c
+#define   NV34TCL_DEPTH_FUNC_NEVER                                                     0x00000200
+#define   NV34TCL_DEPTH_FUNC_LESS                                                      0x00000201
+#define   NV34TCL_DEPTH_FUNC_EQUAL                                                     0x00000202
+#define   NV34TCL_DEPTH_FUNC_LEQUAL                                                    0x00000203
+#define   NV34TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV34TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV34TCL_DEPTH_FUNC_NOTEQUAL                                                  0x00000205
+#define   NV34TCL_DEPTH_FUNC_GEQUAL                                                    0x00000206
+#define   NV34TCL_DEPTH_FUNC_ALWAYS                                                    0x00000207
+#define  NV34TCL_DEPTH_WRITE_ENABLE                                                    0x00000a70
+#define  NV34TCL_DEPTH_TEST_ENABLE                                                     0x00000a74
+#define  NV34TCL_POLYGON_OFFSET_FACTOR                                                 0x00000a78
+#define  NV34TCL_POLYGON_OFFSET_UNITS                                                  0x00000a7c
+#define  NV34TCL_VTX_ATTR_3I_XY(x)                                                     (0x00000a80+((x)*8))
+#define  NV34TCL_VTX_ATTR_3I_XY__SIZE                                                  0x00000010
+#define   NV34TCL_VTX_ATTR_3I_XY_X_SHIFT                                               0
+#define   NV34TCL_VTX_ATTR_3I_XY_X_MASK                                                        0x0000ffff
+#define   NV34TCL_VTX_ATTR_3I_XY_Y_SHIFT                                               16
+#define   NV34TCL_VTX_ATTR_3I_XY_Y_MASK                                                        0xffff0000
+#define  NV34TCL_VTX_ATTR_3I_Z(x)                                                      (0x00000a84+((x)*8))
+#define  NV34TCL_VTX_ATTR_3I_Z__SIZE                                                   0x00000010
+#define   NV34TCL_VTX_ATTR_3I_Z_Z_SHIFT                                                        0
+#define   NV34TCL_VTX_ATTR_3I_Z_Z_MASK                                                 0x0000ffff
+#define  NV34TCL_VP_UPLOAD_INST(x)                                                     (0x00000b80+((x)*4))
+#define  NV34TCL_VP_UPLOAD_INST__SIZE                                                  0x00000004
+#define  NV34TCL_CLIP_PLANE_A(x)                                                       (0x00000e00+((x)*16))
+#define  NV34TCL_CLIP_PLANE_A__SIZE                                                    0x00000020
+#define  NV34TCL_CLIP_PLANE_B(x)                                                       (0x00000e04+((x)*16))
+#define  NV34TCL_CLIP_PLANE_B__SIZE                                                    0x00000020
+#define  NV34TCL_CLIP_PLANE_C(x)                                                       (0x00000e08+((x)*16))
+#define  NV34TCL_CLIP_PLANE_C__SIZE                                                    0x00000020
+#define  NV34TCL_CLIP_PLANE_D(x)                                                       (0x00000e0c+((x)*16))
+#define  NV34TCL_CLIP_PLANE_D__SIZE                                                    0x00000020
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(x)                                 (0x00001000+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G(x)                                 (0x00001004+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_G__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B(x)                                 (0x00001008+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_B__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(x)                                 (0x0000100c+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G(x)                                 (0x00001010+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_G__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B(x)                                 (0x00001014+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_B__SIZE                              0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(x)                                        (0x00001018+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R__SIZE                             0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G(x)                                        (0x0000101c+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_G__SIZE                             0x00000008
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B(x)                                        (0x00001020+((x)*64))
+#define  NV34TCL_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_B__SIZE                             0x00000008
+#define  NV34TCL_LIGHT_HALF_VECTOR_X(x)                                                        (0x00001028+((x)*64))
+#define  NV34TCL_LIGHT_HALF_VECTOR_X__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_HALF_VECTOR_Y(x)                                                        (0x0000102c+((x)*64))
+#define  NV34TCL_LIGHT_HALF_VECTOR_Y__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_HALF_VECTOR_Z(x)                                                        (0x00001030+((x)*64))
+#define  NV34TCL_LIGHT_HALF_VECTOR_Z__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_DIRECTION_X(x)                                                  (0x00001034+((x)*64))
+#define  NV34TCL_LIGHT_DIRECTION_X__SIZE                                               0x00000008
+#define  NV34TCL_LIGHT_DIRECTION_Y(x)                                                  (0x00001038+((x)*64))
+#define  NV34TCL_LIGHT_DIRECTION_Y__SIZE                                               0x00000008
+#define  NV34TCL_LIGHT_DIRECTION_Z(x)                                                  (0x0000103c+((x)*64))
+#define  NV34TCL_LIGHT_DIRECTION_Z__SIZE                                               0x00000008
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_A(x)                                                        (0x00001200+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_A__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_B(x)                                                        (0x00001204+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_B__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_C(x)                                                        (0x00001208+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_C__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_SPOT_DIR_X(x)                                                   (0x0000120c+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_DIR_X__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_SPOT_DIR_Y(x)                                                   (0x00001210+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_DIR_Y__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_SPOT_DIR_Z(x)                                                   (0x00001214+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_DIR_Z__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_D(x)                                                        (0x00001218+((x)*64))
+#define  NV34TCL_LIGHT_SPOT_CUTOFF_D__SIZE                                             0x00000008
+#define  NV34TCL_LIGHT_POSITION_X(x)                                                   (0x0000121c+((x)*64))
+#define  NV34TCL_LIGHT_POSITION_X__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_POSITION_Y(x)                                                   (0x00001220+((x)*64))
+#define  NV34TCL_LIGHT_POSITION_Y__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_POSITION_Z(x)                                                   (0x00001224+((x)*64))
+#define  NV34TCL_LIGHT_POSITION_Z__SIZE                                                        0x00000008
+#define  NV34TCL_LIGHT_ATTENUATION_CONSTANT(x)                                         (0x00001228+((x)*64))
+#define  NV34TCL_LIGHT_ATTENUATION_CONSTANT__SIZE                                      0x00000008
+#define  NV34TCL_LIGHT_ATTENUATION_LINEAR(x)                                           (0x0000122c+((x)*64))
+#define  NV34TCL_LIGHT_ATTENUATION_LINEAR__SIZE                                                0x00000008
+#define  NV34TCL_LIGHT_ATTENUATION_QUADRATIC(x)                                                (0x00001230+((x)*64))
+#define  NV34TCL_LIGHT_ATTENUATION_QUADRATIC__SIZE                                     0x00000008
+#define  NV34TCL_FRONT_MATERIAL_SHININESS(x)                                           (0x00001400+((x)*4))
+#define  NV34TCL_FRONT_MATERIAL_SHININESS__SIZE                                                0x00000006
+#define  NV34TCL_ENABLED_LIGHTS                                                                0x00001420
+#define  NV34TCL_FP_REG_CONTROL                                                                0x00001450
+#define   NV34TCL_FP_REG_CONTROL_UNK1_SHIFT                                            16
+#define   NV34TCL_FP_REG_CONTROL_UNK1_MASK                                             0xffff0000
+#define   NV34TCL_FP_REG_CONTROL_UNK0_SHIFT                                            0
+#define   NV34TCL_FP_REG_CONTROL_UNK0_MASK                                             0x0000ffff
+#define  NV34TCL_VP_CLIP_PLANES_ENABLE                                                 0x00001478
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0                                         (1 <<  1)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1                                         (1 <<  5)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2                                         (1 <<  9)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3                                         (1 << 13)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4                                         (1 << 17)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5                                         (1 << 21)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE6                                         (1 << 25)
+#define   NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE7                                         (1 << 29)
+#define  NV34TCL_POLYGON_STIPPLE_ENABLE                                                        0x0000147c
+#define  NV34TCL_POLYGON_STIPPLE_PATTERN(x)                                            (0x00001480+((x)*4))
+#define  NV34TCL_POLYGON_STIPPLE_PATTERN__SIZE                                         0x00000020
+#define  NV34TCL_VTX_ATTR_3F_X(x)                                                      (0x00001500+((x)*16))
+#define  NV34TCL_VTX_ATTR_3F_X__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_3F_Y(x)                                                      (0x00001504+((x)*16))
+#define  NV34TCL_VTX_ATTR_3F_Y__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_3F_Z(x)                                                      (0x00001508+((x)*16))
+#define  NV34TCL_VTX_ATTR_3F_Z__SIZE                                                   0x00000010
+#define  NV34TCL_VP_CLIP_PLANE_A(x)                                                    (0x00001600+((x)*16))
+#define  NV34TCL_VP_CLIP_PLANE_A__SIZE                                                 0x00000006
+#define  NV34TCL_VP_CLIP_PLANE_B(x)                                                    (0x00001604+((x)*16))
+#define  NV34TCL_VP_CLIP_PLANE_B__SIZE                                                 0x00000006
+#define  NV34TCL_VP_CLIP_PLANE_C(x)                                                    (0x00001608+((x)*16))
+#define  NV34TCL_VP_CLIP_PLANE_C__SIZE                                                 0x00000006
+#define  NV34TCL_VP_CLIP_PLANE_D(x)                                                    (0x0000160c+((x)*16))
+#define  NV34TCL_VP_CLIP_PLANE_D__SIZE                                                 0x00000006
+#define  NV34TCL_VTXBUF_ADDRESS(x)                                                     (0x00001680+((x)*4))
+#define  NV34TCL_VTXBUF_ADDRESS__SIZE                                                  0x00000010
+#define   NV34TCL_VTXBUF_ADDRESS_DMA1                                                  (1 << 31)
+#define   NV34TCL_VTXBUF_ADDRESS_OFFSET_SHIFT                                          0
+#define   NV34TCL_VTXBUF_ADDRESS_OFFSET_MASK                                           0x0fffffff
+#define  NV34TCL_VTXFMT(x)                                                             (0x00001740+((x)*4))
+#define  NV34TCL_VTXFMT__SIZE                                                          0x00000010
+#define   NV34TCL_VTXFMT_TYPE_SHIFT                                                    0
+#define   NV34TCL_VTXFMT_TYPE_MASK                                                     0x0000000f
+#define    NV34TCL_VTXFMT_TYPE_FLOAT                                                   0x00000002
+#define    NV34TCL_VTXFMT_TYPE_UBYTE                                                   0x00000004
+#define    NV34TCL_VTXFMT_TYPE_USHORT                                                  0x00000005
+#define   NV34TCL_VTXFMT_SIZE_SHIFT                                                    4
+#define   NV34TCL_VTXFMT_SIZE_MASK                                                     0x000000f0
+#define   NV34TCL_VTXFMT_STRIDE_SHIFT                                                  8
+#define   NV34TCL_VTXFMT_STRIDE_MASK                                                   0x0000ff00
+#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R                 0x000017a0
+#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_G                 0x000017a4
+#define  NV34TCL_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_B                 0x000017a8
+#define  NV34TCL_COLOR_MATERIAL_BACK_R                                                 0x000017b0
+#define  NV34TCL_COLOR_MATERIAL_BACK_G                                                 0x000017b4
+#define  NV34TCL_COLOR_MATERIAL_BACK_B                                                 0x000017b8
+#define  NV34TCL_COLOR_MATERIAL_BACK_A                                                 0x000017c0
+#define  NV34TCL_QUERY_RESET                                                           0x000017c8
+#define  NV34TCL_QUERY_UNK17CC                                                         0x000017cc
+#define  NV34TCL_QUERY_GET                                                             0x00001800
+#define   NV34TCL_QUERY_GET_UNK24_SHIFT                                                        24
+#define   NV34TCL_QUERY_GET_UNK24_MASK                                                 0xff000000
+#define   NV34TCL_QUERY_GET_OFFSET_SHIFT                                               0
+#define   NV34TCL_QUERY_GET_OFFSET_MASK                                                        0x00ffffff
+#define  NV34TCL_VERTEX_BEGIN_END                                                      0x00001808
+#define   NV34TCL_VERTEX_BEGIN_END_STOP                                                        0x00000000
+#define   NV34TCL_VERTEX_BEGIN_END_POINTS                                              0x00000001
+#define   NV34TCL_VERTEX_BEGIN_END_LINES                                               0x00000002
+#define   NV34TCL_VERTEX_BEGIN_END_LINE_LOOP                                           0x00000003
+#define   NV34TCL_VERTEX_BEGIN_END_LINE_STRIP                                          0x00000004
+#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLES                                           0x00000005
+#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLE_STRIP                                      0x00000006
+#define   NV34TCL_VERTEX_BEGIN_END_TRIANGLE_FAN                                                0x00000007
+#define   NV34TCL_VERTEX_BEGIN_END_QUADS                                               0x00000008
+#define   NV34TCL_VERTEX_BEGIN_END_QUAD_STRIP                                          0x00000009
+#define   NV34TCL_VERTEX_BEGIN_END_POLYGON                                             0x0000000a
+#define  NV34TCL_VB_ELEMENT_U16                                                                0x0000180c
+#define   NV34TCL_VB_ELEMENT_U16_I0_SHIFT                                              0
+#define   NV34TCL_VB_ELEMENT_U16_I0_MASK                                               0x0000ffff
+#define   NV34TCL_VB_ELEMENT_U16_I1_SHIFT                                              16
+#define   NV34TCL_VB_ELEMENT_U16_I1_MASK                                               0xffff0000
+#define  NV34TCL_VB_ELEMENT_U32                                                                0x00001810
+#define  NV34TCL_VB_VERTEX_BATCH                                                       0x00001814
+#define   NV34TCL_VB_VERTEX_BATCH_OFFSET_SHIFT                                         0
+#define   NV34TCL_VB_VERTEX_BATCH_OFFSET_MASK                                          0x00ffffff
+#define   NV34TCL_VB_VERTEX_BATCH_COUNT_SHIFT                                          24
+#define   NV34TCL_VB_VERTEX_BATCH_COUNT_MASK                                           0xff000000
+#define  NV34TCL_VERTEX_DATA                                                           0x00001818
+#define  NV34TCL_IDXBUF_ADDRESS                                                                0x0000181c
+#define  NV34TCL_IDXBUF_FORMAT                                                         0x00001820
+#define   NV34TCL_IDXBUF_FORMAT_TYPE_SHIFT                                             4
+#define   NV34TCL_IDXBUF_FORMAT_TYPE_MASK                                              0x000000f0
+#define    NV34TCL_IDXBUF_FORMAT_TYPE_U32                                              0x00000000
+#define    NV34TCL_IDXBUF_FORMAT_TYPE_U16                                              0x00000010
+#define   NV34TCL_IDXBUF_FORMAT_DMA1                                                   (1 <<  0)
+#define  NV34TCL_VB_INDEX_BATCH                                                                0x00001824
+#define   NV34TCL_VB_INDEX_BATCH_COUNT_SHIFT                                           24
+#define   NV34TCL_VB_INDEX_BATCH_COUNT_MASK                                            0xff000000
+#define   NV34TCL_VB_INDEX_BATCH_START_SHIFT                                           0
+#define   NV34TCL_VB_INDEX_BATCH_START_MASK                                            0x00ffffff
+#define  NV34TCL_POLYGON_MODE_FRONT                                                    0x00001828
+#define   NV34TCL_POLYGON_MODE_FRONT_POINT                                             0x00001b00
+#define   NV34TCL_POLYGON_MODE_FRONT_LINE                                              0x00001b01
+#define   NV34TCL_POLYGON_MODE_FRONT_FILL                                              0x00001b02
+#define  NV34TCL_POLYGON_MODE_BACK                                                     0x0000182c
+#define   NV34TCL_POLYGON_MODE_BACK_POINT                                              0x00001b00
+#define   NV34TCL_POLYGON_MODE_BACK_LINE                                               0x00001b01
+#define   NV34TCL_POLYGON_MODE_BACK_FILL                                               0x00001b02
+#define  NV34TCL_CULL_FACE                                                             0x00001830
+#define   NV34TCL_CULL_FACE_FRONT                                                      0x00000404
+#define   NV34TCL_CULL_FACE_BACK                                                       0x00000405
+#define   NV34TCL_CULL_FACE_FRONT_AND_BACK                                             0x00000408
+#define  NV34TCL_FRONT_FACE                                                            0x00001834
+#define   NV34TCL_FRONT_FACE_CW                                                                0x00000900
+#define   NV34TCL_FRONT_FACE_CCW                                                       0x00000901
+#define  NV34TCL_POLYGON_SMOOTH_ENABLE                                                 0x00001838
+#define  NV34TCL_CULL_FACE_ENABLE                                                      0x0000183c
+#define  NV34TCL_TX_PALETTE_OFFSET(x)                                                  (0x00001840+((x)*4))
+#define  NV34TCL_TX_PALETTE_OFFSET__SIZE                                               0x00000004
+#define  NV34TCL_VTX_ATTR_2F_X(x)                                                      (0x00001880+((x)*8))
+#define  NV34TCL_VTX_ATTR_2F_X__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_2F_Y(x)                                                      (0x00001884+((x)*8))
+#define  NV34TCL_VTX_ATTR_2F_Y__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_2I(x)                                                                (0x00001900+((x)*4))
+#define  NV34TCL_VTX_ATTR_2I__SIZE                                                     0x00000010
+#define   NV34TCL_VTX_ATTR_2I_X_SHIFT                                                  0
+#define   NV34TCL_VTX_ATTR_2I_X_MASK                                                   0x0000ffff
+#define   NV34TCL_VTX_ATTR_2I_Y_SHIFT                                                  16
+#define   NV34TCL_VTX_ATTR_2I_Y_MASK                                                   0xffff0000
+#define  NV34TCL_VTX_ATTR_4UB(x)                                                       (0x00001940+((x)*4))
+#define  NV34TCL_VTX_ATTR_4UB__SIZE                                                    0x00000010
+#define   NV34TCL_VTX_ATTR_4UB_X_SHIFT                                                 0
+#define   NV34TCL_VTX_ATTR_4UB_X_MASK                                                  0x000000ff
+#define   NV34TCL_VTX_ATTR_4UB_Y_SHIFT                                                 8
+#define   NV34TCL_VTX_ATTR_4UB_Y_MASK                                                  0x0000ff00
+#define   NV34TCL_VTX_ATTR_4UB_Z_SHIFT                                                 16
+#define   NV34TCL_VTX_ATTR_4UB_Z_MASK                                                  0x00ff0000
+#define   NV34TCL_VTX_ATTR_4UB_W_SHIFT                                                 24
+#define   NV34TCL_VTX_ATTR_4UB_W_MASK                                                  0xff000000
+#define  NV34TCL_VTX_ATTR_4I_XY(x)                                                     (0x00001980+((x)*8))
+#define  NV34TCL_VTX_ATTR_4I_XY__SIZE                                                  0x00000010
+#define   NV34TCL_VTX_ATTR_4I_XY_X_SHIFT                                               0
+#define   NV34TCL_VTX_ATTR_4I_XY_X_MASK                                                        0x0000ffff
+#define   NV34TCL_VTX_ATTR_4I_XY_Y_SHIFT                                               16
+#define   NV34TCL_VTX_ATTR_4I_XY_Y_MASK                                                        0xffff0000
+#define  NV34TCL_VTX_ATTR_4I_ZW(x)                                                     (0x00001984+((x)*8))
+#define  NV34TCL_VTX_ATTR_4I_ZW__SIZE                                                  0x00000010
+#define   NV34TCL_VTX_ATTR_4I_ZW_Z_SHIFT                                               0
+#define   NV34TCL_VTX_ATTR_4I_ZW_Z_MASK                                                        0x0000ffff
+#define   NV34TCL_VTX_ATTR_4I_ZW_W_SHIFT                                               16
+#define   NV34TCL_VTX_ATTR_4I_ZW_W_MASK                                                        0xffff0000
+#define  NV34TCL_TX_OFFSET(x)                                                          (0x00001a00+((x)*32))
+#define  NV34TCL_TX_OFFSET__SIZE                                                       0x00000004
+#define  NV34TCL_TX_FORMAT(x)                                                          (0x00001a04+((x)*32))
+#define  NV34TCL_TX_FORMAT__SIZE                                                       0x00000004
+#define   NV34TCL_TX_FORMAT_DMA0                                                       (1 <<  0)
+#define   NV34TCL_TX_FORMAT_DMA1                                                       (1 <<  1)
+#define   NV34TCL_TX_FORMAT_CUBIC                                                      (1 <<  2)
+#define   NV34TCL_TX_FORMAT_NO_BORDER                                                  (1 <<  3)
+#define   NV34TCL_TX_FORMAT_DIMS_SHIFT                                                 4
+#define   NV34TCL_TX_FORMAT_DIMS_MASK                                                  0x000000f0
+#define    NV34TCL_TX_FORMAT_DIMS_1D                                                   0x00000010
+#define    NV34TCL_TX_FORMAT_DIMS_2D                                                   0x00000020
+#define    NV34TCL_TX_FORMAT_DIMS_3D                                                   0x00000030
+#define   NV34TCL_TX_FORMAT_FORMAT_SHIFT                                               8
+#define   NV34TCL_TX_FORMAT_FORMAT_MASK                                                        0x0000ff00
+#define    NV34TCL_TX_FORMAT_FORMAT_L8                                                 0x00000000
+#define    NV34TCL_TX_FORMAT_FORMAT_A8                                                 0x00000100
+#define    NV34TCL_TX_FORMAT_FORMAT_A1R5G5B5                                           0x00000200
+#define    NV34TCL_TX_FORMAT_FORMAT_A8_RECT                                            0x00000300
+#define    NV34TCL_TX_FORMAT_FORMAT_A4R4G4B4                                           0x00000400
+#define    NV34TCL_TX_FORMAT_FORMAT_R5G6B5                                             0x00000500
+#define    NV34TCL_TX_FORMAT_FORMAT_A8R8G8B8                                           0x00000600
+#define    NV34TCL_TX_FORMAT_FORMAT_X8R8G8B8                                           0x00000700
+#define    NV34TCL_TX_FORMAT_FORMAT_INDEX8                                             0x00000b00
+#define    NV34TCL_TX_FORMAT_FORMAT_DXT1                                               0x00000c00
+#define    NV34TCL_TX_FORMAT_FORMAT_DXT3                                               0x00000e00
+#define    NV34TCL_TX_FORMAT_FORMAT_DXT5                                               0x00000f00
+#define    NV34TCL_TX_FORMAT_FORMAT_A1R5G5B5_RECT                                      0x00001000
+#define    NV34TCL_TX_FORMAT_FORMAT_R5G6B5_RECT                                                0x00001100
+#define    NV34TCL_TX_FORMAT_FORMAT_A8R8G8B8_RECT                                      0x00001200
+#define    NV34TCL_TX_FORMAT_FORMAT_L8_RECT                                            0x00001300
+#define    NV34TCL_TX_FORMAT_FORMAT_A8L8                                               0x00001a00
+#define    NV34TCL_TX_FORMAT_FORMAT_A8_RECT2                                           0x00001b00
+#define    NV34TCL_TX_FORMAT_FORMAT_A4R4G4B4_RECT                                      0x00001d00
+#define    NV34TCL_TX_FORMAT_FORMAT_R8G8B8_RECT                                                0x00001e00
+#define    NV34TCL_TX_FORMAT_FORMAT_L8A8_RECT                                          0x00002000
+#define    NV34TCL_TX_FORMAT_FORMAT_A16                                                        0x00003200
+#define    NV34TCL_TX_FORMAT_FORMAT_HILO16                                             0x00003300
+#define    NV34TCL_TX_FORMAT_FORMAT_A16_RECT                                           0x00003500
+#define    NV34TCL_TX_FORMAT_FORMAT_HILO16_RECT                                                0x00003600
+#define    NV34TCL_TX_FORMAT_FORMAT_HILO8                                              0x00004400
+#define    NV34TCL_TX_FORMAT_FORMAT_SIGNED_HILO8                                       0x00004500
+#define    NV34TCL_TX_FORMAT_FORMAT_HILO8_RECT                                         0x00004600
+#define    NV34TCL_TX_FORMAT_FORMAT_SIGNED_HILO8_RECT                                  0x00004700
+#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_RGBA16_NV                                    0x00004a00
+#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_RGBA32_NV                                    0x00004b00
+#define    NV34TCL_TX_FORMAT_FORMAT_FLOAT_R32_NV                                       0x00004c00
+#define   NV34TCL_TX_FORMAT_MIPMAP                                                     (1 << 19)
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT                                          20
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_U_MASK                                           0x00f00000
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT                                          24
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_V_MASK                                           0x0f000000
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT                                          28
+#define   NV34TCL_TX_FORMAT_BASE_SIZE_W_MASK                                           0xf0000000
+#define  NV34TCL_TX_WRAP(x)                                                            (0x00001a08+((x)*32))
+#define  NV34TCL_TX_WRAP__SIZE                                                         0x00000004
+#define   NV34TCL_TX_WRAP_S_SHIFT                                                      0
+#define   NV34TCL_TX_WRAP_S_MASK                                                       0x000000ff
+#define    NV34TCL_TX_WRAP_S_REPEAT                                                    0x00000001
+#define    NV34TCL_TX_WRAP_S_MIRRORED_REPEAT                                           0x00000002
+#define    NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE                                             0x00000003
+#define    NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER                                           0x00000004
+#define    NV34TCL_TX_WRAP_S_CLAMP                                                     0x00000005
+#define   NV34TCL_TX_WRAP_T_SHIFT                                                      8
+#define   NV34TCL_TX_WRAP_T_MASK                                                       0x00000f00
+#define    NV34TCL_TX_WRAP_T_REPEAT                                                    0x00000100
+#define    NV34TCL_TX_WRAP_T_MIRRORED_REPEAT                                           0x00000200
+#define    NV34TCL_TX_WRAP_T_CLAMP_TO_EDGE                                             0x00000300
+#define    NV34TCL_TX_WRAP_T_CLAMP_TO_BORDER                                           0x00000400
+#define    NV34TCL_TX_WRAP_T_CLAMP                                                     0x00000500
+#define   NV34TCL_TX_WRAP_EXPAND_NORMAL_SHIFT                                          12
+#define   NV34TCL_TX_WRAP_EXPAND_NORMAL_MASK                                           0x0000f000
+#define   NV34TCL_TX_WRAP_R_SHIFT                                                      16
+#define   NV34TCL_TX_WRAP_R_MASK                                                       0x00ff0000
+#define    NV34TCL_TX_WRAP_R_REPEAT                                                    0x00010000
+#define    NV34TCL_TX_WRAP_R_MIRRORED_REPEAT                                           0x00020000
+#define    NV34TCL_TX_WRAP_R_CLAMP_TO_EDGE                                             0x00030000
+#define    NV34TCL_TX_WRAP_R_CLAMP_TO_BORDER                                           0x00040000
+#define    NV34TCL_TX_WRAP_R_CLAMP                                                     0x00050000
+#define   NV34TCL_TX_WRAP_RCOMP_SHIFT                                                  28
+#define   NV34TCL_TX_WRAP_RCOMP_MASK                                                   0xf0000000
+#define    NV34TCL_TX_WRAP_RCOMP_NEVER                                                 0x00000000
+#define    NV34TCL_TX_WRAP_RCOMP_GREATER                                               0x10000000
+#define    NV34TCL_TX_WRAP_RCOMP_EQUAL                                                 0x20000000
+#define    NV34TCL_TX_WRAP_RCOMP_GEQUAL                                                        0x30000000
+#define    NV34TCL_TX_WRAP_RCOMP_LESS                                                  0x40000000
+#define    NV34TCL_TX_WRAP_RCOMP_NOTEQUAL                                              0x50000000
+#define    NV34TCL_TX_WRAP_RCOMP_LEQUAL                                                        0x60000000
+#define    NV34TCL_TX_WRAP_RCOMP_ALWAYS                                                        0x70000000
+#define  NV34TCL_TX_ENABLE(x)                                                          (0x00001a0c+((x)*32))
+#define  NV34TCL_TX_ENABLE__SIZE                                                       0x00000004
+#define   NV34TCL_TX_ENABLE_ANISO_SHIFT                                                        4
+#define   NV34TCL_TX_ENABLE_ANISO_MASK                                                 0x00000030
+#define    NV34TCL_TX_ENABLE_ANISO_NONE                                                        0x00000000
+#define    NV34TCL_TX_ENABLE_ANISO_2X                                                  0x00000010
+#define    NV34TCL_TX_ENABLE_ANISO_4X                                                  0x00000020
+#define    NV34TCL_TX_ENABLE_ANISO_8X                                                  0x00000030
+#define   NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT                                       14
+#define   NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_MASK                                                0x0003c000
+#define   NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT                                       26
+#define   NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_MASK                                                0x3c000000
+#define   NV34TCL_TX_ENABLE_ENABLE                                                     (1 << 30)
+#define  NV34TCL_TX_SWIZZLE(x)                                                         (0x00001a10+((x)*32))
+#define  NV34TCL_TX_SWIZZLE__SIZE                                                      0x00000004
+#define   NV34TCL_TX_SWIZZLE_S0_X_SHIFT                                                        14
+#define   NV34TCL_TX_SWIZZLE_S0_X_MASK                                                 0x0000c000
+#define    NV34TCL_TX_SWIZZLE_S0_X_ZERO                                                        0x00000000
+#define    NV34TCL_TX_SWIZZLE_S0_X_ONE                                                 0x00004000
+#define    NV34TCL_TX_SWIZZLE_S0_X_S1                                                  0x00008000
+#define   NV34TCL_TX_SWIZZLE_S0_Y_SHIFT                                                        12
+#define   NV34TCL_TX_SWIZZLE_S0_Y_MASK                                                 0x00003000
+#define    NV34TCL_TX_SWIZZLE_S0_Y_ZERO                                                        0x00000000
+#define    NV34TCL_TX_SWIZZLE_S0_Y_ONE                                                 0x00001000
+#define    NV34TCL_TX_SWIZZLE_S0_Y_S1                                                  0x00002000
+#define   NV34TCL_TX_SWIZZLE_S0_Z_SHIFT                                                        10
+#define   NV34TCL_TX_SWIZZLE_S0_Z_MASK                                                 0x00000c00
+#define    NV34TCL_TX_SWIZZLE_S0_Z_ZERO                                                        0x00000000
+#define    NV34TCL_TX_SWIZZLE_S0_Z_ONE                                                 0x00000400
+#define    NV34TCL_TX_SWIZZLE_S0_Z_S1                                                  0x00000800
+#define   NV34TCL_TX_SWIZZLE_S0_W_SHIFT                                                        8
+#define   NV34TCL_TX_SWIZZLE_S0_W_MASK                                                 0x00000300
+#define    NV34TCL_TX_SWIZZLE_S0_W_ZERO                                                        0x00000000
+#define    NV34TCL_TX_SWIZZLE_S0_W_ONE                                                 0x00000100
+#define    NV34TCL_TX_SWIZZLE_S0_W_S1                                                  0x00000200
+#define   NV34TCL_TX_SWIZZLE_S1_X_SHIFT                                                        6
+#define   NV34TCL_TX_SWIZZLE_S1_X_MASK                                                 0x000000c0
+#define    NV34TCL_TX_SWIZZLE_S1_X_W                                                   0x00000000
+#define    NV34TCL_TX_SWIZZLE_S1_X_Z                                                   0x00000040
+#define    NV34TCL_TX_SWIZZLE_S1_X_Y                                                   0x00000080
+#define    NV34TCL_TX_SWIZZLE_S1_X_X                                                   0x000000c0
+#define   NV34TCL_TX_SWIZZLE_S1_Y_SHIFT                                                        4
+#define   NV34TCL_TX_SWIZZLE_S1_Y_MASK                                                 0x00000030
+#define    NV34TCL_TX_SWIZZLE_S1_Y_W                                                   0x00000000
+#define    NV34TCL_TX_SWIZZLE_S1_Y_Z                                                   0x00000010
+#define    NV34TCL_TX_SWIZZLE_S1_Y_Y                                                   0x00000020
+#define    NV34TCL_TX_SWIZZLE_S1_Y_X                                                   0x00000030
+#define   NV34TCL_TX_SWIZZLE_S1_Z_SHIFT                                                        2
+#define   NV34TCL_TX_SWIZZLE_S1_Z_MASK                                                 0x0000000c
+#define    NV34TCL_TX_SWIZZLE_S1_Z_W                                                   0x00000000
+#define    NV34TCL_TX_SWIZZLE_S1_Z_Z                                                   0x00000004
+#define    NV34TCL_TX_SWIZZLE_S1_Z_Y                                                   0x00000008
+#define    NV34TCL_TX_SWIZZLE_S1_Z_X                                                   0x0000000c
+#define   NV34TCL_TX_SWIZZLE_S1_W_SHIFT                                                        0
+#define   NV34TCL_TX_SWIZZLE_S1_W_MASK                                                 0x00000003
+#define    NV34TCL_TX_SWIZZLE_S1_W_W                                                   0x00000000
+#define    NV34TCL_TX_SWIZZLE_S1_W_Z                                                   0x00000001
+#define    NV34TCL_TX_SWIZZLE_S1_W_Y                                                   0x00000002
+#define    NV34TCL_TX_SWIZZLE_S1_W_X                                                   0x00000003
+#define   NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT                                          16
+#define   NV34TCL_TX_SWIZZLE_RECT_PITCH_MASK                                           0xffff0000
+#define  NV34TCL_TX_FILTER(x)                                                          (0x00001a14+((x)*32))
+#define  NV34TCL_TX_FILTER__SIZE                                                       0x00000004
+#define   NV34TCL_TX_FILTER_LOD_BIAS_SHIFT                                             8
+#define   NV34TCL_TX_FILTER_LOD_BIAS_MASK                                              0x00000f00
+#define   NV34TCL_TX_FILTER_MINIFY_SHIFT                                               16
+#define   NV34TCL_TX_FILTER_MINIFY_MASK                                                        0x000f0000
+#define    NV34TCL_TX_FILTER_MINIFY_NEAREST                                            0x00010000
+#define    NV34TCL_TX_FILTER_MINIFY_LINEAR                                             0x00020000
+#define    NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST                             0x00030000
+#define    NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST                              0x00040000
+#define    NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR                              0x00050000
+#define    NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR                               0x00060000
+#define   NV34TCL_TX_FILTER_MAGNIFY_SHIFT                                              24
+#define   NV34TCL_TX_FILTER_MAGNIFY_MASK                                               0x0f000000
+#define    NV34TCL_TX_FILTER_MAGNIFY_NEAREST                                           0x01000000
+#define    NV34TCL_TX_FILTER_MAGNIFY_LINEAR                                            0x02000000
+#define   NV34TCL_TX_FILTER_SIGNED_BLUE                                                        (1 << 28)
+#define   NV34TCL_TX_FILTER_SIGNED_GREEN                                               (1 << 29)
+#define   NV34TCL_TX_FILTER_SIGNED_RED                                                 (1 << 30)
+#define   NV34TCL_TX_FILTER_SIGNED_ALPHA                                               (1 << 31)
+#define  NV34TCL_TX_NPOT_SIZE(x)                                                       (0x00001a18+((x)*32))
+#define  NV34TCL_TX_NPOT_SIZE__SIZE                                                    0x00000004
+#define   NV34TCL_TX_NPOT_SIZE_H_SHIFT                                                 0
+#define   NV34TCL_TX_NPOT_SIZE_H_MASK                                                  0x0000ffff
+#define   NV34TCL_TX_NPOT_SIZE_W_SHIFT                                                 16
+#define   NV34TCL_TX_NPOT_SIZE_W_MASK                                                  0xffff0000
+#define  NV34TCL_TX_BORDER_COLOR(x)                                                    (0x00001a1c+((x)*32))
+#define  NV34TCL_TX_BORDER_COLOR__SIZE                                                 0x00000004
+#define   NV34TCL_TX_BORDER_COLOR_B_SHIFT                                              0
+#define   NV34TCL_TX_BORDER_COLOR_B_MASK                                               0x000000ff
+#define   NV34TCL_TX_BORDER_COLOR_G_SHIFT                                              8
+#define   NV34TCL_TX_BORDER_COLOR_G_MASK                                               0x0000ff00
+#define   NV34TCL_TX_BORDER_COLOR_R_SHIFT                                              16
+#define   NV34TCL_TX_BORDER_COLOR_R_MASK                                               0x00ff0000
+#define   NV34TCL_TX_BORDER_COLOR_A_SHIFT                                              24
+#define   NV34TCL_TX_BORDER_COLOR_A_MASK                                               0xff000000
+#define  NV34TCL_VTX_ATTR_4F_X(x)                                                      (0x00001c00+((x)*16))
+#define  NV34TCL_VTX_ATTR_4F_X__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_4F_Y(x)                                                      (0x00001c04+((x)*16))
+#define  NV34TCL_VTX_ATTR_4F_Y__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_4F_Z(x)                                                      (0x00001c08+((x)*16))
+#define  NV34TCL_VTX_ATTR_4F_Z__SIZE                                                   0x00000010
+#define  NV34TCL_VTX_ATTR_4F_W(x)                                                      (0x00001c0c+((x)*16))
+#define  NV34TCL_VTX_ATTR_4F_W__SIZE                                                   0x00000010
+#define  NV34TCL_FP_CONTROL                                                            0x00001d60
+#define   NV34TCL_FP_CONTROL_USES_KIL                                                  (1 <<  7)
+#define   NV34TCL_FP_CONTROL_USED_REGS_MINUS1_DIV2_SHIFT                               0
+#define   NV34TCL_FP_CONTROL_USED_REGS_MINUS1_DIV2_MASK                                        0x0000000f
+#define  NV34TCL_MULTISAMPLE_CONTROL                                                   0x00001d7c
+#define   NV34TCL_MULTISAMPLE_CONTROL_ENABLE                                           (1 <<  0)
+#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_COVERAGE                         (1 <<  4)
+#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_ALPHA_TO_ONE                              (1 <<  8)
+#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE_SHIFT                            16
+#define   NV34TCL_MULTISAMPLE_CONTROL_SAMPLE_COVERAGE_MASK                             0xffff0000
+#define  NV34TCL_CLEAR_DEPTH_VALUE                                                     0x00001d8c
+#define  NV34TCL_CLEAR_COLOR_VALUE                                                     0x00001d90
+#define   NV34TCL_CLEAR_COLOR_VALUE_B_SHIFT                                            0
+#define   NV34TCL_CLEAR_COLOR_VALUE_B_MASK                                             0x000000ff
+#define   NV34TCL_CLEAR_COLOR_VALUE_G_SHIFT                                            8
+#define   NV34TCL_CLEAR_COLOR_VALUE_G_MASK                                             0x0000ff00
+#define   NV34TCL_CLEAR_COLOR_VALUE_R_SHIFT                                            16
+#define   NV34TCL_CLEAR_COLOR_VALUE_R_MASK                                             0x00ff0000
+#define   NV34TCL_CLEAR_COLOR_VALUE_A_SHIFT                                            24
+#define   NV34TCL_CLEAR_COLOR_VALUE_A_MASK                                             0xff000000
+#define  NV34TCL_CLEAR_BUFFERS                                                         0x00001d94
+#define   NV34TCL_CLEAR_BUFFERS_COLOR_A                                                        (1 <<  7)
+#define   NV34TCL_CLEAR_BUFFERS_COLOR_B                                                        (1 <<  6)
+#define   NV34TCL_CLEAR_BUFFERS_COLOR_G                                                        (1 <<  5)
+#define   NV34TCL_CLEAR_BUFFERS_COLOR_R                                                        (1 <<  4)
+#define   NV34TCL_CLEAR_BUFFERS_STENCIL                                                        (1 <<  1)
+#define   NV34TCL_CLEAR_BUFFERS_DEPTH                                                  (1 <<  0)
+#define  NV34TCL_DO_VERTICES                                                           0x00001dac
+#define  NV34TCL_LINE_STIPPLE_ENABLE                                                   0x00001db4
+#define  NV34TCL_LINE_STIPPLE_PATTERN                                                  0x00001db8
+#define   NV34TCL_LINE_STIPPLE_PATTERN_FACTOR_SHIFT                                    0
+#define   NV34TCL_LINE_STIPPLE_PATTERN_FACTOR_MASK                                     0x0000ffff
+#define   NV34TCL_LINE_STIPPLE_PATTERN_PATTERN_SHIFT                                   16
+#define   NV34TCL_LINE_STIPPLE_PATTERN_PATTERN_MASK                                    0xffff0000
+#define  NV34TCL_BACK_MATERIAL_SHININESS(x)                                            (0x00001e20+((x)*4))
+#define  NV34TCL_BACK_MATERIAL_SHININESS__SIZE                                         0x00000006
+#define  NV34TCL_VTX_ATTR_1F(x)                                                                (0x00001e40+((x)*4))
+#define  NV34TCL_VTX_ATTR_1F__SIZE                                                     0x00000010
+#define  NV34TCL_VP_UPLOAD_FROM_ID                                                     0x00001e9c
+#define  NV34TCL_VP_START_FROM_ID                                                      0x00001ea0
+#define  NV34TCL_POINT_PARAMETERS(x)                                                   (0x00001ec0+((x)*4))
+#define  NV34TCL_POINT_PARAMETERS__SIZE                                                        0x00000008
+#define  NV34TCL_POINT_SIZE                                                            0x00001ee0
+#define  NV34TCL_POINT_PARAMETERS_ENABLE                                               0x00001ee4
+#define  NV34TCL_POINT_SPRITE                                                          0x00001ee8
+#define   NV34TCL_POINT_SPRITE_ENABLE                                                  (1 <<  0)
+#define   NV34TCL_POINT_SPRITE_R_MODE_SHIFT                                            1
+#define   NV34TCL_POINT_SPRITE_R_MODE_MASK                                             0x00000006
+#define    NV34TCL_POINT_SPRITE_R_MODE_GL_ZERO                                         0x00000000
+#define    NV34TCL_POINT_SPRITE_R_MODE_GL_R                                            0x00000002
+#define    NV34TCL_POINT_SPRITE_R_MODE_GL_S                                            0x00000004
+#define   NV34TCL_POINT_SPRITE_COORD_REPLACE                                           (1 << 11)
+#define  NV34TCL_VP_UPLOAD_CONST_ID                                                    0x00001efc
+#define  NV34TCL_VP_UPLOAD_CONST_X(x)                                                  (0x00001f00+((x)*16))
+#define  NV34TCL_VP_UPLOAD_CONST_X__SIZE                                               0x00000004
+#define  NV34TCL_VP_UPLOAD_CONST_Y(x)                                                  (0x00001f04+((x)*16))
+#define  NV34TCL_VP_UPLOAD_CONST_Y__SIZE                                               0x00000004
+#define  NV34TCL_VP_UPLOAD_CONST_Z(x)                                                  (0x00001f08+((x)*16))
+#define  NV34TCL_VP_UPLOAD_CONST_Z__SIZE                                               0x00000004
+#define  NV34TCL_VP_UPLOAD_CONST_W(x)                                                  (0x00001f0c+((x)*16))
+#define  NV34TCL_VP_UPLOAD_CONST_W__SIZE                                               0x00000004
+#define  NV34TCL_UNK1f80(x)                                                            (0x00001f80+((x)*4))
+#define  NV34TCL_UNK1f80__SIZE                                                         0x00000010
+
+
+#define NV40_CONTEXT_SURFACES_2D                                                       0x00003062
+
+
+
+#define NV40_STRETCHED_IMAGE_FROM_CPU                                                  0x00003066
+
+
+
+#define NV40_TEXTURE_FROM_CPU                                                          0x0000307b
+
+
+
+#define NV40_SCALED_IMAGE_FROM_MEMORY                                                  0x00003089
+
+
+
+#define NV40_IMAGE_FROM_CPU                                                            0x0000308a
+
+
+
+#define NV40_SWIZZLED_SURFACE                                                          0x0000309e
+
+
+
+#define NV40TCL                                                                                0x00004097
+
+#define  NV40TCL_REF_CNT                                                               0x00000050
+#define  NV40TCL_NOP                                                                   0x00000100
+#define  NV40TCL_NOTIFY                                                                        0x00000104
+#define  NV40TCL_DMA_NOTIFY                                                            0x00000180
+#define  NV40TCL_DMA_TEXTURE0                                                          0x00000184
+#define  NV40TCL_DMA_TEXTURE1                                                          0x00000188
+#define  NV40TCL_DMA_COLOR1                                                            0x0000018c
+#define  NV40TCL_DMA_COLOR0                                                            0x00000194
+#define  NV40TCL_DMA_ZETA                                                              0x00000198
+#define  NV40TCL_DMA_VTXBUF0                                                           0x0000019c
+#define  NV40TCL_DMA_VTXBUF1                                                           0x000001a0
+#define  NV40TCL_DMA_FENCE                                                             0x000001a4
+#define  NV40TCL_DMA_QUERY                                                             0x000001a8
+#define  NV40TCL_DMA_UNK01AC                                                           0x000001ac
+#define  NV40TCL_DMA_UNK01B0                                                           0x000001b0
+#define  NV40TCL_DMA_COLOR2                                                            0x000001b4
+#define  NV40TCL_DMA_COLOR3                                                            0x000001b8
+#define  NV40TCL_RT_HORIZ                                                              0x00000200
+#define   NV40TCL_RT_HORIZ_W_SHIFT                                                     16
+#define   NV40TCL_RT_HORIZ_W_MASK                                                      0xffff0000
+#define   NV40TCL_RT_HORIZ_X_SHIFT                                                     0
+#define   NV40TCL_RT_HORIZ_X_MASK                                                      0x0000ffff
+#define  NV40TCL_RT_VERT                                                               0x00000204
+#define   NV40TCL_RT_VERT_H_SHIFT                                                      16
+#define   NV40TCL_RT_VERT_H_MASK                                                       0xffff0000
+#define   NV40TCL_RT_VERT_Y_SHIFT                                                      0
+#define   NV40TCL_RT_VERT_Y_MASK                                                       0x0000ffff
+#define  NV40TCL_RT_FORMAT                                                             0x00000208
+#define   NV40TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT                                          24
+#define   NV40TCL_RT_FORMAT_LOG2_HEIGHT_MASK                                           0xff000000
+#define   NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT                                           16
+#define   NV40TCL_RT_FORMAT_LOG2_WIDTH_MASK                                            0x00ff0000
+#define   NV40TCL_RT_FORMAT_TYPE_SHIFT                                                 8
+#define   NV40TCL_RT_FORMAT_TYPE_MASK                                                  0x00000f00
+#define    NV40TCL_RT_FORMAT_TYPE_LINEAR                                               0x00000100
+#define    NV40TCL_RT_FORMAT_TYPE_SWIZZLED                                             0x00000200
+#define   NV40TCL_RT_FORMAT_ZETA_SHIFT                                                 5
+#define   NV40TCL_RT_FORMAT_ZETA_MASK                                                  0x000000e0
+#define    NV40TCL_RT_FORMAT_ZETA_Z16                                                  0x00000020
+#define    NV40TCL_RT_FORMAT_ZETA_Z24S8                                                        0x00000040
+#define   NV40TCL_RT_FORMAT_COLOR_SHIFT                                                        0
+#define   NV40TCL_RT_FORMAT_COLOR_MASK                                                 0x0000001f
+#define    NV40TCL_RT_FORMAT_COLOR_R5G6B5                                              0x00000003
+#define    NV40TCL_RT_FORMAT_COLOR_X8R8G8B8                                            0x00000005
+#define    NV40TCL_RT_FORMAT_COLOR_A8R8G8B8                                            0x00000008
+#define    NV40TCL_RT_FORMAT_COLOR_B8                                                  0x00000009
+#define    NV40TCL_RT_FORMAT_COLOR_X8B8G8R8                                            0x0000000f
+#define    NV40TCL_RT_FORMAT_COLOR_A8B8G8R8                                            0x00000010
+#define  NV40TCL_COLOR0_PITCH                                                          0x0000020c
+#define  NV40TCL_COLOR0_OFFSET                                                         0x00000210
+#define  NV40TCL_ZETA_OFFSET                                                           0x00000214
+#define  NV40TCL_COLOR1_OFFSET                                                         0x00000218
+#define  NV40TCL_COLOR1_PITCH                                                          0x0000021c
+#define  NV40TCL_RT_ENABLE                                                             0x00000220
+#define   NV40TCL_RT_ENABLE_MRT                                                                (1 <<  4)
+#define   NV40TCL_RT_ENABLE_COLOR3                                                     (1 <<  3)
+#define   NV40TCL_RT_ENABLE_COLOR2                                                     (1 <<  2)
+#define   NV40TCL_RT_ENABLE_COLOR1                                                     (1 <<  1)
+#define   NV40TCL_RT_ENABLE_COLOR0                                                     (1 <<  0)
+#define  NV40TCL_ZETA_PITCH                                                            0x0000022c
+#define  NV40TCL_COLOR2_PITCH                                                          0x00000280
+#define  NV40TCL_COLOR3_PITCH                                                          0x00000284
+#define  NV40TCL_COLOR2_OFFSET                                                         0x00000288
+#define  NV40TCL_COLOR3_OFFSET                                                         0x0000028c
+#define  NV40TCL_VIEWPORT_CLIP_HORIZ(x)                                                        (0x000002c0+((x)*8))
+#define  NV40TCL_VIEWPORT_CLIP_HORIZ__SIZE                                             0x00000008
+#define  NV40TCL_VIEWPORT_CLIP_VERT(x)                                                 (0x000002c4+((x)*8))
+#define  NV40TCL_VIEWPORT_CLIP_VERT__SIZE                                              0x00000008
+#define  NV40TCL_DITHER_ENABLE                                                         0x00000300
+#define  NV40TCL_ALPHA_TEST_ENABLE                                                     0x00000304
+#define  NV40TCL_ALPHA_TEST_FUNC                                                       0x00000308
+#define   NV40TCL_ALPHA_TEST_FUNC_NEVER                                                        0x00000200
+#define   NV40TCL_ALPHA_TEST_FUNC_LESS                                                 0x00000201
+#define   NV40TCL_ALPHA_TEST_FUNC_EQUAL                                                        0x00000202
+#define   NV40TCL_ALPHA_TEST_FUNC_LEQUAL                                               0x00000203
+#define   NV40TCL_ALPHA_TEST_FUNC_GREATER                                              0x00000204
+#define   NV40TCL_ALPHA_TEST_FUNC_GREATER                                              0x00000204
+#define   NV40TCL_ALPHA_TEST_FUNC_NOTEQUAL                                             0x00000205
+#define   NV40TCL_ALPHA_TEST_FUNC_GEQUAL                                               0x00000206
+#define   NV40TCL_ALPHA_TEST_FUNC_ALWAYS                                               0x00000207
+#define  NV40TCL_ALPHA_TEST_REF                                                                0x0000030c
+#define  NV40TCL_BLEND_ENABLE                                                          0x00000310
+#define  NV40TCL_BLEND_FUNC_SRC                                                                0x00000314
+#define   NV40TCL_BLEND_FUNC_SRC_RGB_SHIFT                                             0
+#define   NV40TCL_BLEND_FUNC_SRC_RGB_MASK                                              0x0000ffff
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ZERO                                             0x00000000
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE                                              0x00000001
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR                                                0x00000300
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR                              0x00000301
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA                                                0x00000302
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA                              0x00000303
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA                                                0x00000304
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA                              0x00000305
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_DST_COLOR                                                0x00000306
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR                              0x00000307
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE                               0x00000308
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR                                   0x00008001
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR                         0x00008002
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA                                   0x00008003
+#define    NV40TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA                         0x00008004
+#define   NV40TCL_BLEND_FUNC_SRC_ALPHA_SHIFT                                           16
+#define   NV40TCL_BLEND_FUNC_SRC_ALPHA_MASK                                            0xffff0000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ZERO                                           0x00000000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE                                            0x00010000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR                                      0x03000000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR                            0x03010000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA                                      0x03020000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA                            0x03030000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA                                      0x03040000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA                            0x03050000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR                                      0x03060000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR                            0x03070000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE                             0x03080000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR                                 0x80010000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR                       0x80020000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA                                 0x80030000
+#define    NV40TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA                       0x80040000
+#define  NV40TCL_BLEND_FUNC_DST                                                                0x00000318
+#define   NV40TCL_BLEND_FUNC_DST_RGB_SHIFT                                             0
+#define   NV40TCL_BLEND_FUNC_DST_RGB_MASK                                              0x0000ffff
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ZERO                                             0x00000000
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE                                              0x00000001
+#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_COLOR                                                0x00000300
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR                              0x00000301
+#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA                                                0x00000302
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA                              0x00000303
+#define    NV40TCL_BLEND_FUNC_DST_RGB_DST_ALPHA                                                0x00000304
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA                              0x00000305
+#define    NV40TCL_BLEND_FUNC_DST_RGB_DST_COLOR                                                0x00000306
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR                              0x00000307
+#define    NV40TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE                               0x00000308
+#define    NV40TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR                                   0x00008001
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR                         0x00008002
+#define    NV40TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA                                   0x00008003
+#define    NV40TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA                         0x00008004
+#define   NV40TCL_BLEND_FUNC_DST_ALPHA_SHIFT                                           16
+#define   NV40TCL_BLEND_FUNC_DST_ALPHA_MASK                                            0xffff0000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ZERO                                           0x00000000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE                                            0x00010000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR                                      0x03000000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR                            0x03010000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA                                      0x03020000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA                            0x03030000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA                                      0x03040000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA                            0x03050000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR                                      0x03060000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR                            0x03070000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE                             0x03080000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR                                 0x80010000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR                       0x80020000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA                                 0x80030000
+#define    NV40TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA                       0x80040000
+#define  NV40TCL_BLEND_COLOR                                                           0x0000031c
+#define  NV40TCL_BLEND_EQUATION                                                                0x00000320
+#define   NV40TCL_BLEND_EQUATION_RGB_SHIFT                                             0
+#define   NV40TCL_BLEND_EQUATION_RGB_MASK                                              0x0000ffff
+#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_ADD                                         0x00008006
+#define    NV40TCL_BLEND_EQUATION_RGB_MIN                                              0x00008007
+#define    NV40TCL_BLEND_EQUATION_RGB_MAX                                              0x00008008
+#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_SUBTRACT                                    0x0000800a
+#define    NV40TCL_BLEND_EQUATION_RGB_FUNC_REVERSE_SUBTRACT                            0x0000800b
+#define   NV40TCL_BLEND_EQUATION_ALPHA_SHIFT                                           16
+#define   NV40TCL_BLEND_EQUATION_ALPHA_MASK                                            0xffff0000
+#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_ADD                                       0x80060000
+#define    NV40TCL_BLEND_EQUATION_ALPHA_MIN                                            0x80070000
+#define    NV40TCL_BLEND_EQUATION_ALPHA_MAX                                            0x80080000
+#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_SUBTRACT                                  0x800a0000
+#define    NV40TCL_BLEND_EQUATION_ALPHA_FUNC_REVERSE_SUBTRACT                          0x800b0000
+#define  NV40TCL_COLOR_MASK                                                            0x00000324
+#define   NV40TCL_COLOR_MASK_BUFFER0_B_SHIFT                                           0
+#define   NV40TCL_COLOR_MASK_BUFFER0_B_MASK                                            0x000000ff
+#define   NV40TCL_COLOR_MASK_BUFFER0_G_SHIFT                                           8
+#define   NV40TCL_COLOR_MASK_BUFFER0_G_MASK                                            0x0000ff00
+#define   NV40TCL_COLOR_MASK_BUFFER0_R_SHIFT                                           16
+#define   NV40TCL_COLOR_MASK_BUFFER0_R_MASK                                            0x00ff0000
+#define   NV40TCL_COLOR_MASK_BUFFER0_A_SHIFT                                           24
+#define   NV40TCL_COLOR_MASK_BUFFER0_A_MASK                                            0xff000000
+#define  NV40TCL_STENCIL_FRONT_ENABLE                                                  0x00000328
+#define  NV40TCL_STENCIL_FRONT_MASK                                                    0x0000032c
+#define  NV40TCL_STENCIL_FRONT_FUNC_FUNC                                               0x00000330
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_NEVER                                                0x00000200
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_LESS                                         0x00000201
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL                                                0x00000202
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL                                       0x00000203
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL                                     0x00000205
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL                                       0x00000206
+#define   NV40TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS                                       0x00000207
+#define  NV40TCL_STENCIL_FRONT_FUNC_REF                                                        0x00000334
+#define  NV40TCL_STENCIL_FRONT_FUNC_MASK                                               0x00000338
+#define  NV40TCL_STENCIL_FRONT_OP_FAIL                                                 0x0000033c
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_ZERO                                           0x00000000
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INVERT                                         0x0000150a
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_KEEP                                           0x00001e00
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_REPLACE                                                0x00001e01
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INCR                                           0x00001e02
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_DECR                                           0x00001e03
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP                                      0x00008507
+#define   NV40TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP                                      0x00008508
+#define  NV40TCL_STENCIL_FRONT_OP_ZFAIL                                                        0x00000340
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_ZERO                                          0x00000000
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INVERT                                                0x0000150a
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_KEEP                                          0x00001e00
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE                                       0x00001e01
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INCR                                          0x00001e02
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_DECR                                          0x00001e03
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP                                     0x00008507
+#define   NV40TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP                                     0x00008508
+#define  NV40TCL_STENCIL_FRONT_OP_ZPASS                                                        0x00000344
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_ZERO                                          0x00000000
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INVERT                                                0x0000150a
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_KEEP                                          0x00001e00
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_REPLACE                                       0x00001e01
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INCR                                          0x00001e02
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_DECR                                          0x00001e03
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP                                     0x00008507
+#define   NV40TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP                                     0x00008508
+#define  NV40TCL_STENCIL_BACK_ENABLE                                                   0x00000348
+#define  NV40TCL_STENCIL_BACK_MASK                                                     0x0000034c
+#define  NV40TCL_STENCIL_BACK_FUNC_FUNC                                                        0x00000350
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_NEVER                                         0x00000200
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_LESS                                          0x00000201
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_EQUAL                                         0x00000202
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL                                                0x00000203
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL                                      0x00000205
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL                                                0x00000206
+#define   NV40TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS                                                0x00000207
+#define  NV40TCL_STENCIL_BACK_FUNC_REF                                                 0x00000354
+#define  NV40TCL_STENCIL_BACK_FUNC_MASK                                                        0x00000358
+#define  NV40TCL_STENCIL_BACK_OP_FAIL                                                  0x0000035c
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_ZERO                                            0x00000000
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_INVERT                                          0x0000150a
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_KEEP                                            0x00001e00
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_REPLACE                                         0x00001e01
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_INCR                                            0x00001e02
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_DECR                                            0x00001e03
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP                                       0x00008507
+#define   NV40TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP                                       0x00008508
+#define  NV40TCL_STENCIL_BACK_OP_ZFAIL                                                 0x00000360
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_ZERO                                           0x00000000
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INVERT                                         0x0000150a
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_KEEP                                           0x00001e00
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_REPLACE                                                0x00001e01
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INCR                                           0x00001e02
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_DECR                                           0x00001e03
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP                                      0x00008507
+#define   NV40TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP                                      0x00008508
+#define  NV40TCL_STENCIL_BACK_OP_ZPASS                                                 0x00000364
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_ZERO                                           0x00000000
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INVERT                                         0x0000150a
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_KEEP                                           0x00001e00
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_REPLACE                                                0x00001e01
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INCR                                           0x00001e02
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_DECR                                           0x00001e03
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP                                      0x00008507
+#define   NV40TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP                                      0x00008508
+#define  NV40TCL_SHADE_MODEL                                                           0x00000368
+#define   NV40TCL_SHADE_MODEL_FLAT                                                     0x00001d00
+#define   NV40TCL_SHADE_MODEL_SMOOTH                                                   0x00001d01
+#define  NV40TCL_MRT_COLOR_MASK                                                                0x00000370
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_A                                             (1 <<  4)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_R                                             (1 <<  5)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_G                                             (1 <<  6)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER1_B                                             (1 <<  7)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_A                                             (1 <<  8)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_R                                             (1 <<  9)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_G                                             (1 << 10)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER2_B                                             (1 << 11)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_A                                             (1 << 12)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_R                                             (1 << 13)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_G                                             (1 << 14)
+#define   NV40TCL_MRT_COLOR_MASK_BUFFER3_B                                             (1 << 15)
+#define  NV40TCL_COLOR_LOGIC_OP_ENABLE                                                 0x00000374
+#define  NV40TCL_COLOR_LOGIC_OP                                                                0x00000378
+#define   NV40TCL_COLOR_LOGIC_OP_CLEAR                                                 0x00001500
+#define   NV40TCL_COLOR_LOGIC_OP_AND                                                   0x00001501
+#define   NV40TCL_COLOR_LOGIC_OP_AND_REVERSE                                           0x00001502
+#define   NV40TCL_COLOR_LOGIC_OP_COPY                                                  0x00001503
+#define   NV40TCL_COLOR_LOGIC_OP_AND_INVERTED                                          0x00001504
+#define   NV40TCL_COLOR_LOGIC_OP_NOOP                                                  0x00001505
+#define   NV40TCL_COLOR_LOGIC_OP_XOR                                                   0x00001506
+#define   NV40TCL_COLOR_LOGIC_OP_OR                                                    0x00001507
+#define   NV40TCL_COLOR_LOGIC_OP_NOR                                                   0x00001508
+#define   NV40TCL_COLOR_LOGIC_OP_EQUIV                                                 0x00001509
+#define   NV40TCL_COLOR_LOGIC_OP_INVERT                                                        0x0000150a
+#define   NV40TCL_COLOR_LOGIC_OP_OR_REVERSE                                            0x0000150b
+#define   NV40TCL_COLOR_LOGIC_OP_COPY_INVERTED                                         0x0000150c
+#define   NV40TCL_COLOR_LOGIC_OP_OR_INVERTED                                           0x0000150d
+#define   NV40TCL_COLOR_LOGIC_OP_NAND                                                  0x0000150e
+#define   NV40TCL_COLOR_LOGIC_OP_SET                                                   0x0000150f
+#define  NV40TCL_DEPTH_RANGE_NEAR                                                      0x00000394
+#define  NV40TCL_DEPTH_RANGE_FAR                                                       0x00000398
+#define  NV40TCL_LINE_WIDTH                                                            0x000003b8
+#define  NV40TCL_LINE_SMOOTH_ENABLE                                                    0x000003bc
+#define  NV40TCL_UNK03C0(x)                                                            (0x000003c0+((x)*4))
+#define  NV40TCL_UNK03C0__SIZE                                                         0x00000010
+#define  NV40TCL_UNK0400(x)                                                            (0x00000400+((x)*4))
+#define  NV40TCL_UNK0400__SIZE                                                         0x00000010
+#define  NV40TCL_UNK0440(x)                                                            (0x00000440+((x)*4))
+#define  NV40TCL_UNK0440__SIZE                                                         0x00000020
+#define  NV40TCL_SCISSOR_HORIZ                                                         0x000008c0
+#define   NV40TCL_SCISSOR_HORIZ_X_SHIFT                                                        0
+#define   NV40TCL_SCISSOR_HORIZ_X_MASK                                                 0x0000ffff
+#define   NV40TCL_SCISSOR_HORIZ_W_SHIFT                                                        16
+#define   NV40TCL_SCISSOR_HORIZ_W_MASK                                                 0xffff0000
+#define  NV40TCL_SCISSOR_VERT                                                          0x000008c4
+#define   NV40TCL_SCISSOR_VERT_Y_SHIFT                                                 0
+#define   NV40TCL_SCISSOR_VERT_Y_MASK                                                  0x0000ffff
+#define   NV40TCL_SCISSOR_VERT_H_SHIFT                                                 16
+#define   NV40TCL_SCISSOR_VERT_H_MASK                                                  0xffff0000
+#define  NV40TCL_FOG_MODE                                                              0x000008cc
+#define  NV40TCL_FOG_EQUATION_CONSTANT                                                 0x000008d0
+#define  NV40TCL_FOG_EQUATION_LINEAR                                                   0x000008d4
+#define  NV40TCL_FOG_EQUATION_QUADRATIC                                                        0x000008d8
+#define  NV40TCL_FP_ADDRESS                                                            0x000008e4
+#define   NV40TCL_FP_ADDRESS_OFFSET_SHIFT                                              8
+#define   NV40TCL_FP_ADDRESS_OFFSET_MASK                                               0xffffff00
+#define   NV40TCL_FP_ADDRESS_DMA1                                                      (1 <<  1)
+#define   NV40TCL_FP_ADDRESS_DMA0                                                      (1 <<  0)
+#define  NV40TCL_VIEWPORT_HORIZ                                                                0x00000a00
+#define   NV40TCL_VIEWPORT_HORIZ_W_SHIFT                                               16
+#define   NV40TCL_VIEWPORT_HORIZ_W_MASK                                                        0xffff0000
+#define   NV40TCL_VIEWPORT_HORIZ_X_SHIFT                                               0
+#define   NV40TCL_VIEWPORT_HORIZ_X_MASK                                                        0x0000ffff
+#define  NV40TCL_VIEWPORT_VERT                                                         0x00000a04
+#define   NV40TCL_VIEWPORT_VERT_H_SHIFT                                                        16
+#define   NV40TCL_VIEWPORT_VERT_H_MASK                                                 0xffff0000
+#define   NV40TCL_VIEWPORT_VERT_Y_SHIFT                                                        0
+#define   NV40TCL_VIEWPORT_VERT_Y_MASK                                                 0x0000ffff
+#define  NV40TCL_VIEWPORT_TRANSLATE_X                                                  0x00000a20
+#define  NV40TCL_VIEWPORT_TRANSLATE_Y                                                  0x00000a24
+#define  NV40TCL_VIEWPORT_TRANSLATE_Z                                                  0x00000a28
+#define  NV40TCL_VIEWPORT_TRANSLATE_W                                                  0x00000a2c
+#define  NV40TCL_VIEWPORT_SCALE_X                                                      0x00000a30
+#define  NV40TCL_VIEWPORT_SCALE_Y                                                      0x00000a34
+#define  NV40TCL_VIEWPORT_SCALE_Z                                                      0x00000a38
+#define  NV40TCL_VIEWPORT_SCALE_W                                                      0x00000a3c
+#define  NV40TCL_POLYGON_OFFSET_POINT_ENABLE                                           0x00000a60
+#define  NV40TCL_POLYGON_OFFSET_LINE_ENABLE                                            0x00000a64
+#define  NV40TCL_POLYGON_OFFSET_FILL_ENABLE                                            0x00000a68
+#define  NV40TCL_DEPTH_FUNC                                                            0x00000a6c
+#define   NV40TCL_DEPTH_FUNC_NEVER                                                     0x00000200
+#define   NV40TCL_DEPTH_FUNC_LESS                                                      0x00000201
+#define   NV40TCL_DEPTH_FUNC_EQUAL                                                     0x00000202
+#define   NV40TCL_DEPTH_FUNC_LEQUAL                                                    0x00000203
+#define   NV40TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV40TCL_DEPTH_FUNC_GREATER                                                   0x00000204
+#define   NV40TCL_DEPTH_FUNC_NOTEQUAL                                                  0x00000205
+#define   NV40TCL_DEPTH_FUNC_GEQUAL                                                    0x00000206
+#define   NV40TCL_DEPTH_FUNC_ALWAYS                                                    0x00000207
+#define  NV40TCL_DEPTH_WRITE_ENABLE                                                    0x00000a70
+#define  NV40TCL_DEPTH_TEST_ENABLE                                                     0x00000a74
+#define  NV40TCL_POLYGON_OFFSET_FACTOR                                                 0x00000a78
+#define  NV40TCL_POLYGON_OFFSET_UNITS                                                  0x00000a7c
+#define  NV40TCL_VTX_ATTR_3I_XY(x)                                                     (0x00000a80+((x)*8))
+#define  NV40TCL_VTX_ATTR_3I_XY__SIZE                                                  0x00000010
+#define   NV40TCL_VTX_ATTR_3I_XY_X_SHIFT                                               0
+#define   NV40TCL_VTX_ATTR_3I_XY_X_MASK                                                        0x0000ffff
+#define   NV40TCL_VTX_ATTR_3I_XY_Y_SHIFT                                               16
+#define   NV40TCL_VTX_ATTR_3I_XY_Y_MASK                                                        0xffff0000
+#define  NV40TCL_VTX_ATTR_3I_Z(x)                                                      (0x00000a84+((x)*8))
+#define  NV40TCL_VTX_ATTR_3I_Z__SIZE                                                   0x00000010
+#define   NV40TCL_VTX_ATTR_3I_Z_Z_SHIFT                                                        0
+#define   NV40TCL_VTX_ATTR_3I_Z_Z_MASK                                                 0x0000ffff
+#define  NV40TCL_UNK0B40(x)                                                            (0x00000b40+((x)*4))
+#define  NV40TCL_UNK0B40__SIZE                                                         0x00000008
+#define  NV40TCL_VP_UPLOAD_INST(x)                                                     (0x00000b80+((x)*4))
+#define  NV40TCL_VP_UPLOAD_INST__SIZE                                                  0x00000004
+#define  NV40TCL_CLIP_PLANE_ENABLE                                                     0x00001478
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE0                                             (1 <<  1)
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE1                                             (1 <<  5)
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE2                                             (1 <<  9)
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE3                                             (1 << 13)
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE4                                             (1 << 17)
+#define   NV40TCL_CLIP_PLANE_ENABLE_PLANE5                                             (1 << 21)
+#define  NV40TCL_POLYGON_STIPPLE_ENABLE                                                        0x0000147c
+#define  NV40TCL_POLYGON_STIPPLE_PATTERN(x)                                            (0x00001480+((x)*4))
+#define  NV40TCL_POLYGON_STIPPLE_PATTERN__SIZE                                         0x00000020
+#define  NV40TCL_VTX_ATTR_3F_X(x)                                                      (0x00001500+((x)*16))
+#define  NV40TCL_VTX_ATTR_3F_X__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_3F_Y(x)                                                      (0x00001504+((x)*16))
+#define  NV40TCL_VTX_ATTR_3F_Y__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_3F_Z(x)                                                      (0x00001508+((x)*16))
+#define  NV40TCL_VTX_ATTR_3F_Z__SIZE                                                   0x00000010
+#define  NV40TCL_VTXBUF_ADDRESS(x)                                                     (0x00001680+((x)*4))
+#define  NV40TCL_VTXBUF_ADDRESS__SIZE                                                  0x00000010
+#define   NV40TCL_VTXBUF_ADDRESS_DMA1                                                  (1 << 31)
+#define   NV40TCL_VTXBUF_ADDRESS_OFFSET_SHIFT                                          0
+#define   NV40TCL_VTXBUF_ADDRESS_OFFSET_MASK                                           0x0fffffff
+#define  NV40TCL_VTX_CACHE_INVALIDATE                                                  0x00001714
+#define  NV40TCL_VTXFMT(x)                                                             (0x00001740+((x)*4))
+#define  NV40TCL_VTXFMT__SIZE                                                          0x00000010
+#define   NV40TCL_VTXFMT_TYPE_SHIFT                                                    0
+#define   NV40TCL_VTXFMT_TYPE_MASK                                                     0x0000000f
+#define    NV40TCL_VTXFMT_TYPE_FLOAT                                                   0x00000002
+#define    NV40TCL_VTXFMT_TYPE_UBYTE                                                   0x00000004
+#define    NV40TCL_VTXFMT_TYPE_USHORT                                                  0x00000005
+#define   NV40TCL_VTXFMT_SIZE_SHIFT                                                    4
+#define   NV40TCL_VTXFMT_SIZE_MASK                                                     0x000000f0
+#define   NV40TCL_VTXFMT_STRIDE_SHIFT                                                  8
+#define   NV40TCL_VTXFMT_STRIDE_MASK                                                   0x0000ff00
+#define  NV40TCL_QUERY_RESET                                                           0x000017c8
+#define  NV40TCL_QUERY_UNK17CC                                                         0x000017cc
+#define  NV40TCL_QUERY_GET                                                             0x00001800
+#define   NV40TCL_QUERY_GET_UNK24_SHIFT                                                        24
+#define   NV40TCL_QUERY_GET_UNK24_MASK                                                 0xff000000
+#define   NV40TCL_QUERY_GET_OFFSET_SHIFT                                               0
+#define   NV40TCL_QUERY_GET_OFFSET_MASK                                                        0x00ffffff
+#define  NV40TCL_BEGIN_END                                                             0x00001808
+#define   NV40TCL_BEGIN_END_STOP                                                       0x00000000
+#define   NV40TCL_BEGIN_END_POINTS                                                     0x00000001
+#define   NV40TCL_BEGIN_END_LINES                                                      0x00000002
+#define   NV40TCL_BEGIN_END_LINE_LOOP                                                  0x00000003
+#define   NV40TCL_BEGIN_END_LINE_STRIP                                                 0x00000004
+#define   NV40TCL_BEGIN_END_TRIANGLES                                                  0x00000005
+#define   NV40TCL_BEGIN_END_TRIANGLE_STRIP                                             0x00000006
+#define   NV40TCL_BEGIN_END_TRIANGLE_FAN                                               0x00000007
+#define   NV40TCL_BEGIN_END_QUADS                                                      0x00000008
+#define   NV40TCL_BEGIN_END_QUAD_STRIP                                                 0x00000009
+#define   NV40TCL_BEGIN_END_POLYGON                                                    0x0000000a
+#define  NV40TCL_VB_ELEMENT_U16                                                                0x0000180c
+#define   NV40TCL_VB_ELEMENT_U16_1_SHIFT                                               16
+#define   NV40TCL_VB_ELEMENT_U16_1_MASK                                                        0xffff0000
+#define   NV40TCL_VB_ELEMENT_U16_0_SHIFT                                               0
+#define   NV40TCL_VB_ELEMENT_U16_0_MASK                                                        0x0000ffff
+#define  NV40TCL_VB_ELEMENT_U32                                                                0x00001810
+#define  NV40TCL_VB_VERTEX_BATCH                                                       0x00001814
+#define   NV40TCL_VB_VERTEX_BATCH_COUNT_SHIFT                                          24
+#define   NV40TCL_VB_VERTEX_BATCH_COUNT_MASK                                           0xff000000
+#define   NV40TCL_VB_VERTEX_BATCH_START_SHIFT                                          0
+#define   NV40TCL_VB_VERTEX_BATCH_START_MASK                                           0x00ffffff
+#define  NV40TCL_VERTEX_DATA                                                           0x00001818
+#define  NV40TCL_IDXBUF_ADDRESS                                                                0x0000181c
+#define  NV40TCL_IDXBUF_FORMAT                                                         0x00001820
+#define   NV40TCL_IDXBUF_FORMAT_TYPE_SHIFT                                             4
+#define   NV40TCL_IDXBUF_FORMAT_TYPE_MASK                                              0x000000f0
+#define    NV40TCL_IDXBUF_FORMAT_TYPE_U32                                              0x00000000
+#define    NV40TCL_IDXBUF_FORMAT_TYPE_U16                                              0x00000010
+#define   NV40TCL_IDXBUF_FORMAT_DMA1                                                   (1 <<  0)
+#define  NV40TCL_VB_INDEX_BATCH                                                                0x00001824
+#define   NV40TCL_VB_INDEX_BATCH_COUNT_SHIFT                                           24
+#define   NV40TCL_VB_INDEX_BATCH_COUNT_MASK                                            0xff000000
+#define   NV40TCL_VB_INDEX_BATCH_START_SHIFT                                           0
+#define   NV40TCL_VB_INDEX_BATCH_START_MASK                                            0x00ffffff
+#define  NV40TCL_POLYGON_MODE_FRONT                                                    0x00001828
+#define   NV40TCL_POLYGON_MODE_FRONT_POINT                                             0x00001b00
+#define   NV40TCL_POLYGON_MODE_FRONT_LINE                                              0x00001b01
+#define   NV40TCL_POLYGON_MODE_FRONT_FILL                                              0x00001b02
+#define  NV40TCL_POLYGON_MODE_BACK                                                     0x0000182c
+#define   NV40TCL_POLYGON_MODE_BACK_POINT                                              0x00001b00
+#define   NV40TCL_POLYGON_MODE_BACK_LINE                                               0x00001b01
+#define   NV40TCL_POLYGON_MODE_BACK_FILL                                               0x00001b02
+#define  NV40TCL_CULL_FACE                                                             0x00001830
+#define   NV40TCL_CULL_FACE_FRONT                                                      0x00000404
+#define   NV40TCL_CULL_FACE_BACK                                                       0x00000405
+#define   NV40TCL_CULL_FACE_FRONT_AND_BACK                                             0x00000408
+#define  NV40TCL_FRONT_FACE                                                            0x00001834
+#define   NV40TCL_FRONT_FACE_CW                                                                0x00000900
+#define   NV40TCL_FRONT_FACE_CCW                                                       0x00000901
+#define  NV40TCL_POLYGON_SMOOTH_ENABLE                                                 0x00001838
+#define  NV40TCL_CULL_FACE_ENABLE                                                      0x0000183c
+#define  NV40TCL_TEX_SIZE1(x)                                                          (0x00001840+((x)*4))
+#define  NV40TCL_TEX_SIZE1__SIZE                                                       0x00000008
+#define   NV40TCL_TEX_SIZE1_DEPTH_SHIFT                                                        20
+#define   NV40TCL_TEX_SIZE1_DEPTH_MASK                                                 0xfff00000
+#define   NV40TCL_TEX_SIZE1_PITCH_SHIFT                                                        0
+#define   NV40TCL_TEX_SIZE1_PITCH_MASK                                                 0x0000ffff
+#define  NV40TCL_VTX_ATTR_2F_X(x)                                                      (0x00001880+((x)*8))
+#define  NV40TCL_VTX_ATTR_2F_X__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_2F_Y(x)                                                      (0x00001884+((x)*8))
+#define  NV40TCL_VTX_ATTR_2F_Y__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_2I(x)                                                                (0x00001900+((x)*4))
+#define  NV40TCL_VTX_ATTR_2I__SIZE                                                     0x00000010
+#define   NV40TCL_VTX_ATTR_2I_X_SHIFT                                                  0
+#define   NV40TCL_VTX_ATTR_2I_X_MASK                                                   0x0000ffff
+#define   NV40TCL_VTX_ATTR_2I_Y_SHIFT                                                  16
+#define   NV40TCL_VTX_ATTR_2I_Y_MASK                                                   0xffff0000
+#define  NV40TCL_VTX_ATTR_4UB(x)                                                       (0x00001940+((x)*4))
+#define  NV40TCL_VTX_ATTR_4UB__SIZE                                                    0x00000010
+#define   NV40TCL_VTX_ATTR_4UB_X_SHIFT                                                 0
+#define   NV40TCL_VTX_ATTR_4UB_X_MASK                                                  0x000000ff
+#define   NV40TCL_VTX_ATTR_4UB_Y_SHIFT                                                 8
+#define   NV40TCL_VTX_ATTR_4UB_Y_MASK                                                  0x0000ff00
+#define   NV40TCL_VTX_ATTR_4UB_Z_SHIFT                                                 16
+#define   NV40TCL_VTX_ATTR_4UB_Z_MASK                                                  0x00ff0000
+#define   NV40TCL_VTX_ATTR_4UB_W_SHIFT                                                 24
+#define   NV40TCL_VTX_ATTR_4UB_W_MASK                                                  0xff000000
+#define  NV40TCL_VTX_ATTR_4I_XY(x)                                                     (0x00001980+((x)*8))
+#define  NV40TCL_VTX_ATTR_4I_XY__SIZE                                                  0x00000010
+#define   NV40TCL_VTX_ATTR_4I_XY_X_SHIFT                                               0
+#define   NV40TCL_VTX_ATTR_4I_XY_X_MASK                                                        0x0000ffff
+#define   NV40TCL_VTX_ATTR_4I_XY_Y_SHIFT                                               16
+#define   NV40TCL_VTX_ATTR_4I_XY_Y_MASK                                                        0xffff0000
+#define  NV40TCL_VTX_ATTR_4I_ZW(x)                                                     (0x00001984+((x)*8))
+#define  NV40TCL_VTX_ATTR_4I_ZW__SIZE                                                  0x00000010
+#define   NV40TCL_VTX_ATTR_4I_ZW_Z_SHIFT                                               0
+#define   NV40TCL_VTX_ATTR_4I_ZW_Z_MASK                                                        0x0000ffff
+#define   NV40TCL_VTX_ATTR_4I_ZW_W_SHIFT                                               16
+#define   NV40TCL_VTX_ATTR_4I_ZW_W_MASK                                                        0xffff0000
+#define  NV40TCL_TEX_OFFSET(x)                                                         (0x00001a00+((x)*32))
+#define  NV40TCL_TEX_OFFSET__SIZE                                                      0x00000010
+#define  NV40TCL_TEX_FORMAT(x)                                                         (0x00001a04+((x)*32))
+#define  NV40TCL_TEX_FORMAT__SIZE                                                      0x00000010
+#define   NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT                                                16
+#define   NV40TCL_TEX_FORMAT_MIPMAP_COUNT_MASK                                         0x000f0000
+#define   NV40TCL_TEX_FORMAT_RECT                                                      (1 << 14)
+#define   NV40TCL_TEX_FORMAT_LINEAR                                                    (1 << 13)
+#define   NV40TCL_TEX_FORMAT_FORMAT_SHIFT                                              8
+#define   NV40TCL_TEX_FORMAT_FORMAT_MASK                                               0x00001f00
+#define    NV40TCL_TEX_FORMAT_FORMAT_L8                                                        0x00000100
+#define    NV40TCL_TEX_FORMAT_FORMAT_A1R5G5B5                                          0x00000200
+#define    NV40TCL_TEX_FORMAT_FORMAT_A4R4G4B4                                          0x00000300
+#define    NV40TCL_TEX_FORMAT_FORMAT_R5G6B5                                            0x00000400
+#define    NV40TCL_TEX_FORMAT_FORMAT_A8R8G8B8                                          0x00000500
+#define    NV40TCL_TEX_FORMAT_FORMAT_DXT1                                              0x00000600
+#define    NV40TCL_TEX_FORMAT_FORMAT_DXT3                                              0x00000700
+#define    NV40TCL_TEX_FORMAT_FORMAT_DXT5                                              0x00000800
+#define    NV40TCL_TEX_FORMAT_FORMAT_A8L8                                              0x00000b00
+#define    NV40TCL_TEX_FORMAT_FORMAT_Z24                                               0x00001000
+#define    NV40TCL_TEX_FORMAT_FORMAT_Z16                                               0x00001200
+#define    NV40TCL_TEX_FORMAT_FORMAT_HILO8                                             0x00001800
+#define    NV40TCL_TEX_FORMAT_FORMAT_RGBA16F                                           0x00001a00
+#define    NV40TCL_TEX_FORMAT_FORMAT_RGBA32F                                           0x00001b00
+#define   NV40TCL_TEX_FORMAT_DIMS_SHIFT                                                        4
+#define   NV40TCL_TEX_FORMAT_DIMS_MASK                                                 0x000000f0
+#define    NV40TCL_TEX_FORMAT_DIMS_1D                                                  0x00000010
+#define    NV40TCL_TEX_FORMAT_DIMS_2D                                                  0x00000020
+#define    NV40TCL_TEX_FORMAT_DIMS_3D                                                  0x00000030
+#define   NV40TCL_TEX_FORMAT_NO_BORDER                                                 (1 <<  3)
+#define   NV40TCL_TEX_FORMAT_CUBIC                                                     (1 <<  2)
+#define   NV40TCL_TEX_FORMAT_DMA1                                                      (1 <<  1)
+#define   NV40TCL_TEX_FORMAT_DMA0                                                      (1 <<  0)
+#define  NV40TCL_TEX_WRAP(x)                                                           (0x00001a08+((x)*32))
+#define  NV40TCL_TEX_WRAP__SIZE                                                                0x00000010
+#define   NV40TCL_TEX_WRAP_S_SHIFT                                                     0
+#define   NV40TCL_TEX_WRAP_S_MASK                                                      0x000000ff
+#define    NV40TCL_TEX_WRAP_S_REPEAT                                                   0x00000001
+#define    NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT                                          0x00000002
+#define    NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE                                            0x00000003
+#define    NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER                                          0x00000004
+#define    NV40TCL_TEX_WRAP_S_CLAMP                                                    0x00000005
+#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE                                     0x00000006
+#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER                                   0x00000007
+#define    NV40TCL_TEX_WRAP_S_MIRROR_CLAMP                                             0x00000008
+#define   NV40TCL_TEX_WRAP_T_SHIFT                                                     8
+#define   NV40TCL_TEX_WRAP_T_MASK                                                      0x0000ff00
+#define    NV40TCL_TEX_WRAP_T_REPEAT                                                   0x00000100
+#define    NV40TCL_TEX_WRAP_T_MIRRORED_REPEAT                                          0x00000200
+#define    NV40TCL_TEX_WRAP_T_CLAMP_TO_EDGE                                            0x00000300
+#define    NV40TCL_TEX_WRAP_T_CLAMP_TO_BORDER                                          0x00000400
+#define    NV40TCL_TEX_WRAP_T_CLAMP                                                    0x00000500
+#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP_TO_EDGE                                     0x00000600
+#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP_TO_BORDER                                   0x00000700
+#define    NV40TCL_TEX_WRAP_T_MIRROR_CLAMP                                             0x00000800
+#define   NV40TCL_TEX_WRAP_R_SHIFT                                                     16
+#define   NV40TCL_TEX_WRAP_R_MASK                                                      0x00ff0000
+#define    NV40TCL_TEX_WRAP_R_REPEAT                                                   0x00010000
+#define    NV40TCL_TEX_WRAP_R_MIRRORED_REPEAT                                          0x00020000
+#define    NV40TCL_TEX_WRAP_R_CLAMP_TO_EDGE                                            0x00030000
+#define    NV40TCL_TEX_WRAP_R_CLAMP_TO_BORDER                                          0x00040000
+#define    NV40TCL_TEX_WRAP_R_CLAMP                                                    0x00050000
+#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP_TO_EDGE                                     0x00060000
+#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP_TO_BORDER                                   0x00070000
+#define    NV40TCL_TEX_WRAP_R_MIRROR_CLAMP                                             0x00080000
+#define   NV40TCL_TEX_WRAP_RCOMP_SHIFT                                                 28
+#define   NV40TCL_TEX_WRAP_RCOMP_MASK                                                  0xf0000000
+#define    NV40TCL_TEX_WRAP_RCOMP_NEVER                                                        0x00000000
+#define    NV40TCL_TEX_WRAP_RCOMP_GREATER                                              0x10000000
+#define    NV40TCL_TEX_WRAP_RCOMP_EQUAL                                                        0x20000000
+#define    NV40TCL_TEX_WRAP_RCOMP_GEQUAL                                               0x30000000
+#define    NV40TCL_TEX_WRAP_RCOMP_LESS                                                 0x40000000
+#define    NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL                                             0x50000000
+#define    NV40TCL_TEX_WRAP_RCOMP_LEQUAL                                               0x60000000
+#define    NV40TCL_TEX_WRAP_RCOMP_ALWAYS                                               0x70000000
+#define  NV40TCL_TEX_ENABLE(x)                                                         (0x00001a0c+((x)*32))
+#define  NV40TCL_TEX_ENABLE__SIZE                                                      0x00000010
+#define   NV40TCL_TEX_ENABLE_ENABLE                                                    (1 << 31)
+#define   NV40TCL_TEX_ENABLE_ANISO_SHIFT                                               4
+#define   NV40TCL_TEX_ENABLE_ANISO_MASK                                                        0x000000f0
+#define    NV40TCL_TEX_ENABLE_ANISO_NONE                                               0x00000000
+#define    NV40TCL_TEX_ENABLE_ANISO_2X                                                 0x00000010
+#define    NV40TCL_TEX_ENABLE_ANISO_4X                                                 0x00000020
+#define    NV40TCL_TEX_ENABLE_ANISO_6X                                                 0x00000030
+#define    NV40TCL_TEX_ENABLE_ANISO_8X                                                 0x00000040
+#define    NV40TCL_TEX_ENABLE_ANISO_10X                                                        0x00000050
+#define    NV40TCL_TEX_ENABLE_ANISO_12X                                                        0x00000060
+#define    NV40TCL_TEX_ENABLE_ANISO_16X                                                        0x00000070
+#define  NV40TCL_TEX_SWIZZLE(x)                                                                (0x00001a10+((x)*32))
+#define  NV40TCL_TEX_SWIZZLE__SIZE                                                     0x00000010
+#define   NV40TCL_TEX_SWIZZLE_S0_X_SHIFT                                               14
+#define   NV40TCL_TEX_SWIZZLE_S0_X_MASK                                                        0x0000c000
+#define    NV40TCL_TEX_SWIZZLE_S0_X_ZERO                                               0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S0_X_ONE                                                        0x00004000
+#define    NV40TCL_TEX_SWIZZLE_S0_X_S1                                                 0x00008000
+#define   NV40TCL_TEX_SWIZZLE_S0_Y_SHIFT                                               12
+#define   NV40TCL_TEX_SWIZZLE_S0_Y_MASK                                                        0x00003000
+#define    NV40TCL_TEX_SWIZZLE_S0_Y_ZERO                                               0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S0_Y_ONE                                                        0x00001000
+#define    NV40TCL_TEX_SWIZZLE_S0_Y_S1                                                 0x00002000
+#define   NV40TCL_TEX_SWIZZLE_S0_Z_SHIFT                                               10
+#define   NV40TCL_TEX_SWIZZLE_S0_Z_MASK                                                        0x00000c00
+#define    NV40TCL_TEX_SWIZZLE_S0_Z_ZERO                                               0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S0_Z_ONE                                                        0x00000400
+#define    NV40TCL_TEX_SWIZZLE_S0_Z_S1                                                 0x00000800
+#define   NV40TCL_TEX_SWIZZLE_S0_W_SHIFT                                               8
+#define   NV40TCL_TEX_SWIZZLE_S0_W_MASK                                                        0x00000300
+#define    NV40TCL_TEX_SWIZZLE_S0_W_ZERO                                               0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S0_W_ONE                                                        0x00000100
+#define    NV40TCL_TEX_SWIZZLE_S0_W_S1                                                 0x00000200
+#define   NV40TCL_TEX_SWIZZLE_S1_X_SHIFT                                               6
+#define   NV40TCL_TEX_SWIZZLE_S1_X_MASK                                                        0x000000c0
+#define    NV40TCL_TEX_SWIZZLE_S1_X_W                                                  0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S1_X_Z                                                  0x00000040
+#define    NV40TCL_TEX_SWIZZLE_S1_X_Y                                                  0x00000080
+#define    NV40TCL_TEX_SWIZZLE_S1_X_X                                                  0x000000c0
+#define   NV40TCL_TEX_SWIZZLE_S1_Y_SHIFT                                               4
+#define   NV40TCL_TEX_SWIZZLE_S1_Y_MASK                                                        0x00000030
+#define    NV40TCL_TEX_SWIZZLE_S1_Y_W                                                  0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S1_Y_Z                                                  0x00000010
+#define    NV40TCL_TEX_SWIZZLE_S1_Y_Y                                                  0x00000020
+#define    NV40TCL_TEX_SWIZZLE_S1_Y_X                                                  0x00000030
+#define   NV40TCL_TEX_SWIZZLE_S1_Z_SHIFT                                               2
+#define   NV40TCL_TEX_SWIZZLE_S1_Z_MASK                                                        0x0000000c
+#define    NV40TCL_TEX_SWIZZLE_S1_Z_W                                                  0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S1_Z_Z                                                  0x00000004
+#define    NV40TCL_TEX_SWIZZLE_S1_Z_Y                                                  0x00000008
+#define    NV40TCL_TEX_SWIZZLE_S1_Z_X                                                  0x0000000c
+#define   NV40TCL_TEX_SWIZZLE_S1_W_SHIFT                                               0
+#define   NV40TCL_TEX_SWIZZLE_S1_W_MASK                                                        0x00000003
+#define    NV40TCL_TEX_SWIZZLE_S1_W_W                                                  0x00000000
+#define    NV40TCL_TEX_SWIZZLE_S1_W_Z                                                  0x00000001
+#define    NV40TCL_TEX_SWIZZLE_S1_W_Y                                                  0x00000002
+#define    NV40TCL_TEX_SWIZZLE_S1_W_X                                                  0x00000003
+#define  NV40TCL_TEX_FILTER(x)                                                         (0x00001a14+((x)*32))
+#define  NV40TCL_TEX_FILTER__SIZE                                                      0x00000010
+#define   NV40TCL_TEX_FILTER_SIGNED_ALPHA                                              (1 << 31)
+#define   NV40TCL_TEX_FILTER_SIGNED_RED                                                        (1 << 30)
+#define   NV40TCL_TEX_FILTER_SIGNED_GREEN                                              (1 << 29)
+#define   NV40TCL_TEX_FILTER_SIGNED_BLUE                                               (1 << 28)
+#define   NV40TCL_TEX_FILTER_MIN_SHIFT                                                 16
+#define   NV40TCL_TEX_FILTER_MIN_MASK                                                  0x000f0000
+#define    NV40TCL_TEX_FILTER_MIN_NEAREST                                              0x00010000
+#define    NV40TCL_TEX_FILTER_MIN_LINEAR                                               0x00020000
+#define    NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST                               0x00030000
+#define    NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST                                        0x00040000
+#define    NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR                                        0x00050000
+#define    NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR                                 0x00060000
+#define   NV40TCL_TEX_FILTER_MAG_SHIFT                                                 24
+#define   NV40TCL_TEX_FILTER_MAG_MASK                                                  0x0f000000
+#define    NV40TCL_TEX_FILTER_MAG_NEAREST                                              0x01000000
+#define    NV40TCL_TEX_FILTER_MAG_LINEAR                                               0x02000000
+#define  NV40TCL_TEX_SIZE0(x)                                                          (0x00001a18+((x)*32))
+#define  NV40TCL_TEX_SIZE0__SIZE                                                       0x00000010
+#define   NV40TCL_TEX_SIZE0_H_SHIFT                                                    0
+#define   NV40TCL_TEX_SIZE0_H_MASK                                                     0x0000ffff
+#define   NV40TCL_TEX_SIZE0_W_SHIFT                                                    16
+#define   NV40TCL_TEX_SIZE0_W_MASK                                                     0xffff0000
+#define  NV40TCL_TEX_BORDER_COLOR(x)                                                   (0x00001a1c+((x)*32))
+#define  NV40TCL_TEX_BORDER_COLOR__SIZE                                                        0x00000010
+#define   NV40TCL_TEX_BORDER_COLOR_B_SHIFT                                             0
+#define   NV40TCL_TEX_BORDER_COLOR_B_MASK                                              0x000000ff
+#define   NV40TCL_TEX_BORDER_COLOR_G_SHIFT                                             8
+#define   NV40TCL_TEX_BORDER_COLOR_G_MASK                                              0x0000ff00
+#define   NV40TCL_TEX_BORDER_COLOR_R_SHIFT                                             16
+#define   NV40TCL_TEX_BORDER_COLOR_R_MASK                                              0x00ff0000
+#define   NV40TCL_TEX_BORDER_COLOR_A_SHIFT                                             24
+#define   NV40TCL_TEX_BORDER_COLOR_A_MASK                                              0xff000000
+#define  NV40TCL_VTX_ATTR_4F_X(x)                                                      (0x00001c00+((x)*16))
+#define  NV40TCL_VTX_ATTR_4F_X__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_4F_Y(x)                                                      (0x00001c04+((x)*16))
+#define  NV40TCL_VTX_ATTR_4F_Y__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_4F_Z(x)                                                      (0x00001c08+((x)*16))
+#define  NV40TCL_VTX_ATTR_4F_Z__SIZE                                                   0x00000010
+#define  NV40TCL_VTX_ATTR_4F_W(x)                                                      (0x00001c0c+((x)*16))
+#define  NV40TCL_VTX_ATTR_4F_W__SIZE                                                   0x00000010
+#define  NV40TCL_FP_CONTROL                                                            0x00001d60
+#define   NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT                                          24
+#define   NV40TCL_FP_CONTROL_TEMP_COUNT_MASK                                           0xff000000
+#define   NV40TCL_FP_CONTROL_KIL                                                       (1 <<  7)
+#define  NV40TCL_MULTISAMPLE_CONTROL                                                   0x00001d7c
+#define  NV40TCL_CLEAR_VALUE_DEPTH                                                     0x00001d8c
+#define  NV40TCL_CLEAR_VALUE_COLOR                                                     0x00001d90
+#define  NV40TCL_CLEAR_BUFFERS                                                         0x00001d94
+#define   NV40TCL_CLEAR_BUFFERS_COLOR_A                                                        (1 <<  7)
+#define   NV40TCL_CLEAR_BUFFERS_COLOR_B                                                        (1 <<  6)
+#define   NV40TCL_CLEAR_BUFFERS_COLOR_G                                                        (1 <<  5)
+#define   NV40TCL_CLEAR_BUFFERS_COLOR_R                                                        (1 <<  4)
+#define   NV40TCL_CLEAR_BUFFERS_STENCIL                                                        (1 <<  1)
+#define   NV40TCL_CLEAR_BUFFERS_DEPTH                                                  (1 <<  0)
+#define  NV40TCL_LINE_STIPPLE_ENABLE                                                   0x00001db4
+#define  NV40TCL_LINE_STIPPLE_PATTERN                                                  0x00001db8
+#define   NV40TCL_LINE_STIPPLE_PATTERN_FACTOR_SHIFT                                    0
+#define   NV40TCL_LINE_STIPPLE_PATTERN_FACTOR_MASK                                     0x0000ffff
+#define   NV40TCL_LINE_STIPPLE_PATTERN_PATTERN_SHIFT                                   16
+#define   NV40TCL_LINE_STIPPLE_PATTERN_PATTERN_MASK                                    0xffff0000
+#define  NV40TCL_VTX_ATTR_1F(x)                                                                (0x00001e40+((x)*4))
+#define  NV40TCL_VTX_ATTR_1F__SIZE                                                     0x00000010
+#define  NV40TCL_VP_UPLOAD_FROM_ID                                                     0x00001e9c
+#define  NV40TCL_VP_START_FROM_ID                                                      0x00001ea0
+#define  NV40TCL_POINT_SIZE                                                            0x00001ee0
+#define  NV40TCL_POINT_SPRITE                                                          0x00001ee8
+#define  NV40TCL_VP_UPLOAD_CONST_ID                                                    0x00001efc
+#define  NV40TCL_VP_UPLOAD_CONST_X(x)                                                  (0x00001f00+((x)*16))
+#define  NV40TCL_VP_UPLOAD_CONST_X__SIZE                                               0x00000004
+#define  NV40TCL_VP_UPLOAD_CONST_Y(x)                                                  (0x00001f04+((x)*16))
+#define  NV40TCL_VP_UPLOAD_CONST_Y__SIZE                                               0x00000004
+#define  NV40TCL_VP_UPLOAD_CONST_Z(x)                                                  (0x00001f08+((x)*16))
+#define  NV40TCL_VP_UPLOAD_CONST_Z__SIZE                                               0x00000004
+#define  NV40TCL_VP_UPLOAD_CONST_W(x)                                                  (0x00001f0c+((x)*16))
+#define  NV40TCL_VP_UPLOAD_CONST_W__SIZE                                               0x00000004
+#define  NV40TCL_TEX_CACHE_CTL                                                         0x00001fd8
+#define  NV40TCL_VP_ATTRIB_EN                                                          0x00001ff0
+#define  NV40TCL_VP_RESULT_EN                                                          0x00001ff4
+
+
+#define NV44TCL                                                                                0x00004497
+
+
+
+#define NV50_2D                                                                                0x0000502d
+
+#define  NV50_2D_NOP                                                                   0x00000100
+#define  NV50_2D_NOTIFY                                                                        0x00000104
+#define  NV50_2D_DMA_NOTIFY                                                            0x00000180
+#define  NV50_2D_DMA_IN_MEMORY0                                                                0x00000184
+#define  NV50_2D_DMA_IN_MEMORY1                                                                0x00000188
+#define  NV50_2D_DMA_IN_MEMORY2                                                                0x0000018c
+#define  NV50_2D_DST_FORMAT                                                            0x00000200
+#define   NV50_2D_DST_FORMAT_32BPP                                                     0x000000cf
+#define   NV50_2D_DST_FORMAT_24BPP                                                     0x000000e6
+#define   NV50_2D_DST_FORMAT_16BPP                                                     0x000000e8
+#define   NV50_2D_DST_FORMAT_8BPP                                                      0x000000f3
+#define   NV50_2D_DST_FORMAT_15BPP                                                     0x000000f8
+#define  NV50_2D_DST_PITCH                                                             0x00000214
+#define  NV50_2D_DST_WIDTH                                                             0x00000218
+#define  NV50_2D_DST_HEIGHT                                                            0x0000021c
+#define  NV50_2D_DST_ADDRESS_HIGH                                                      0x00000220
+#define  NV50_2D_DST_ADDRESS_LOW                                                       0x00000224
+#define  NV50_2D_SRC_FORMAT                                                            0x00000230
+#define   NV50_2D_SRC_FORMAT_32BPP                                                     0x000000cf
+#define   NV50_2D_SRC_FORMAT_24BPP                                                     0x000000e6
+#define   NV50_2D_SRC_FORMAT_16BPP                                                     0x000000e8
+#define   NV50_2D_SRC_FORMAT_8BPP                                                      0x000000f3
+#define   NV50_2D_SRC_FORMAT_15BPP                                                     0x000000f8
+#define  NV50_2D_SRC_PITCH                                                             0x00000244
+#define  NV50_2D_SRC_WIDTH                                                             0x00000248
+#define  NV50_2D_SRC_HEIGHT                                                            0x0000024c
+#define  NV50_2D_SRC_ADDRESS_HIGH                                                      0x00000250
+#define  NV50_2D_SRC_ADDRESS_LOW                                                       0x00000254
+#define  NV50_2D_CLIP_X                                                                        0x00000280
+#define  NV50_2D_CLIP_Y                                                                        0x00000284
+#define  NV50_2D_CLIP_Z                                                                        0x00000288
+#define  NV50_2D_CLIP_W                                                                        0x0000028c
+#define  NV50_2D_ROP                                                                   0x000002a0
+#define  NV50_2D_OPERATION                                                             0x000002ac
+#define   NV50_2D_OPERATION_SRCCOPY_AND                                                        0x00000000
+#define   NV50_2D_OPERATION_ROP_AND                                                    0x00000001
+#define   NV50_2D_OPERATION_BLEND_AND                                                  0x00000002
+#define   NV50_2D_OPERATION_SRCCOPY                                                    0x00000003
+#define   NV50_2D_OPERATION_SRCCOPY_PREMULT                                            0x00000004
+#define   NV50_2D_OPERATION_BLEND_PREMULT                                              0x00000005
+#define  NV50_2D_PATTERN_FORMAT                                                                0x000002e8
+#define   NV50_2D_PATTERN_FORMAT_16BPP                                                 0x00000000
+#define   NV50_2D_PATTERN_FORMAT_15BPP                                                 0x00000001
+#define   NV50_2D_PATTERN_FORMAT_32BPP                                                 0x00000002
+#define   NV50_2D_PATTERN_FORMAT_8BPP                                                  0x00000003
+#define  NV50_2D_PATTERN_COLOR(x)                                                      (0x000002f0+((x)*4))
+#define  NV50_2D_PATTERN_COLOR__SIZE                                                   0x00000002
+#define  NV50_2D_PATTERN_BITMAP(x)                                                     (0x000002f8+((x)*4))
+#define  NV50_2D_PATTERN_BITMAP__SIZE                                                  0x00000002
+#define  NV50_2D_RECT_FORMAT                                                           0x00000584
+#define   NV50_2D_RECT_FORMAT_32BPP                                                    0x000000cf
+#define   NV50_2D_RECT_FORMAT_24BPP                                                    0x000000e6
+#define   NV50_2D_RECT_FORMAT_16BPP                                                    0x000000e8
+#define   NV50_2D_RECT_FORMAT_8BPP                                                     0x000000f3
+#define   NV50_2D_RECT_FORMAT_15BPP                                                    0x000000f8
+#define  NV50_2D_RECT_COLOR                                                            0x00000588
+#define  NV50_2D_RECT_X1                                                               0x00000600
+#define  NV50_2D_RECT_Y1                                                               0x00000604
+#define  NV50_2D_RECT_X2                                                               0x00000608
+#define  NV50_2D_RECT_Y2                                                               0x0000060c
+#define  NV50_2D_SIFC_UNK0800                                                          0x00000800
+#define  NV50_2D_SIFC_FORMAT                                                           0x00000804
+#define   NV50_2D_SIFC_FORMAT_32BPP                                                    0x000000cf
+#define   NV50_2D_SIFC_FORMAT_24BPP                                                    0x000000e6
+#define   NV50_2D_SIFC_FORMAT_16BPP                                                    0x000000e8
+#define   NV50_2D_SIFC_FORMAT_8BPP                                                     0x000000f3
+#define   NV50_2D_SIFC_FORMAT_15BPP                                                    0x000000f8
+#define  NV50_2D_SIFC_WIDTH                                                            0x00000838
+#define  NV50_2D_SIFC_HEIGHT                                                           0x0000083c
+#define  NV50_2D_SIFC_SCALE_UNK0840                                                    0x00000840
+#define  NV50_2D_SIFC_SCALE_UNK0844                                                    0x00000844
+#define  NV50_2D_SIFC_SCALE_UNK0848                                                    0x00000848
+#define  NV50_2D_SIFC_SCALE_UNK084C                                                    0x0000084c
+#define  NV50_2D_SIFC_UNK0850                                                          0x00000850
+#define  NV50_2D_SIFC_DST_X                                                            0x00000854
+#define  NV50_2D_SIFC_UNK0858                                                          0x00000858
+#define  NV50_2D_SIFC_DST_Y                                                            0x0000085c
+#define  NV50_2D_SIFC_DATA                                                             0x00000860
+#define  NV50_2D_BLIT_DST_X                                                            0x000008b0
+#define  NV50_2D_BLIT_DST_Y                                                            0x000008b4
+#define  NV50_2D_BLIT_DST_W                                                            0x000008b8
+#define  NV50_2D_BLIT_DST_H                                                            0x000008bc
+#define  NV50_2D_BLIT_SRC_X                                                            0x000008d4
+#define  NV50_2D_BLIT_SRC_Y                                                            0x000008dc
+
+
+#define NV50_MEMORY_TO_MEMORY_FORMAT                                                   0x00005039
+
+#define  NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH                                   0x00000238
+#define  NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH                                  0x0000023c
+
+
+#define NV50TCL                                                                                0x00005097
+
+#define  NV50TCL_NOP                                                                   0x00000100
+#define  NV50TCL_NOTIFY                                                                        0x00000104
+#define  NV50TCL_DMA_NOTIFY                                                            0x00000180
+#define  NV50TCL_DMA_UNK0(x)                                                           (0x00000184+((x)*4))
+#define  NV50TCL_DMA_UNK0__SIZE                                                                0x0000000b
+#define  NV50TCL_DMA_UNK1(x)                                                           (0x000001c0+((x)*4))
+#define  NV50TCL_DMA_UNK1__SIZE                                                                0x00000008
+#define  NV50TCL_RT_ADDRESS_HIGH(x)                                                    (0x00000200+((x)*32))
+#define  NV50TCL_RT_ADDRESS_HIGH__SIZE                                                 0x00000008
+#define  NV50TCL_RT_ADDRESS_LOW(x)                                                     (0x00000204+((x)*32))
+#define  NV50TCL_RT_ADDRESS_LOW__SIZE                                                  0x00000008
+#define  NV50TCL_RT_FORMAT(x)                                                          (0x00000208+((x)*32))
+#define  NV50TCL_RT_FORMAT__SIZE                                                       0x00000008
+#define   NV50TCL_RT_FORMAT_32BPP                                                      0x000000cf
+#define   NV50TCL_RT_FORMAT_24BPP                                                      0x000000e6
+#define   NV50TCL_RT_FORMAT_16BPP                                                      0x000000e8
+#define   NV50TCL_RT_FORMAT_8BPP                                                       0x000000f3
+#define   NV50TCL_RT_FORMAT_15BPP                                                      0x000000f8
+#define  NV50TCL_RT_TILE_UNK(x)                                                                (0x0000020c+((x)*32))
+#define  NV50TCL_RT_TILE_UNK__SIZE                                                     0x00000008
+#define  NV50TCL_RT_UNK4(x)                                                            (0x00000210+((x)*32))
+#define  NV50TCL_RT_UNK4__SIZE                                                         0x00000008
+#define  NV50TCL_VTX_ATTR_1F(x)                                                                (0x00000300+((x)*4))
+#define  NV50TCL_VTX_ATTR_1F__SIZE                                                     0x00000010
+#define  NV50TCL_VTX_ATTR_2F_X(x)                                                      (0x00000380+((x)*8))
+#define  NV50TCL_VTX_ATTR_2F_X__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_2F_Y(x)                                                      (0x00000384+((x)*8))
+#define  NV50TCL_VTX_ATTR_2F_Y__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_3F_X(x)                                                      (0x00000400+((x)*16))
+#define  NV50TCL_VTX_ATTR_3F_X__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_3F_Y(x)                                                      (0x00000404+((x)*16))
+#define  NV50TCL_VTX_ATTR_3F_Y__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_3F_Z(x)                                                      (0x00000408+((x)*16))
+#define  NV50TCL_VTX_ATTR_3F_Z__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_3F_W(x)                                                      (0x0000040c+((x)*16))
+#define  NV50TCL_VTX_ATTR_3F_W__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_4F_X(x)                                                      (0x00000500+((x)*16))
+#define  NV50TCL_VTX_ATTR_4F_X__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_4F_Y(x)                                                      (0x00000504+((x)*16))
+#define  NV50TCL_VTX_ATTR_4F_Y__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_4F_Z(x)                                                      (0x00000508+((x)*16))
+#define  NV50TCL_VTX_ATTR_4F_Z__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_4F_W(x)                                                      (0x0000050c+((x)*16))
+#define  NV50TCL_VTX_ATTR_4F_W__SIZE                                                   0x00000010
+#define  NV50TCL_VTX_ATTR_2I(x)                                                                (0x00000680+((x)*4))
+#define  NV50TCL_VTX_ATTR_2I__SIZE                                                     0x00000010
+#define   NV50TCL_VTX_ATTR_2I_X_SHIFT                                                  0
+#define   NV50TCL_VTX_ATTR_2I_X_MASK                                                   0x0000ffff
+#define   NV50TCL_VTX_ATTR_2I_Y_SHIFT                                                  16
+#define   NV50TCL_VTX_ATTR_2I_Y_MASK                                                   0xffff0000
+#define  NV50TCL_VTX_ATTR_4I_0(x)                                                      (0x00000700+((x)*8))
+#define  NV50TCL_VTX_ATTR_4I_0__SIZE                                                   0x00000010
+#define   NV50TCL_VTX_ATTR_4I_0_X_SHIFT                                                        0
+#define   NV50TCL_VTX_ATTR_4I_0_X_MASK                                                 0x0000ffff
+#define   NV50TCL_VTX_ATTR_4I_0_Y_SHIFT                                                        16
+#define   NV50TCL_VTX_ATTR_4I_0_Y_MASK                                                 0xffff0000
+#define  NV50TCL_VTX_ATTR_4I_1(x)                                                      (0x00000704+((x)*8))
+#define  NV50TCL_VTX_ATTR_4I_1__SIZE                                                   0x00000010
+#define   NV50TCL_VTX_ATTR_4I_1_Z_SHIFT                                                        0
+#define   NV50TCL_VTX_ATTR_4I_1_Z_MASK                                                 0x0000ffff
+#define   NV50TCL_VTX_ATTR_4I_1_W_SHIFT                                                        16
+#define   NV50TCL_VTX_ATTR_4I_1_W_MASK                                                 0xffff0000
+#define  NV50TCL_VTX_ATTR_4NI_0(x)                                                     (0x00000780+((x)*8))
+#define  NV50TCL_VTX_ATTR_4NI_0__SIZE                                                  0x00000010
+#define   NV50TCL_VTX_ATTR_4NI_0_X_SHIFT                                               0
+#define   NV50TCL_VTX_ATTR_4NI_0_X_MASK                                                        0x0000ffff
+#define   NV50TCL_VTX_ATTR_4NI_0_Y_SHIFT                                               16
+#define   NV50TCL_VTX_ATTR_4NI_0_Y_MASK                                                        0xffff0000
+#define  NV50TCL_VTX_ATTR_4NI_1(x)                                                     (0x00000784+((x)*8))
+#define  NV50TCL_VTX_ATTR_4NI_1__SIZE                                                  0x00000010
+#define   NV50TCL_VTX_ATTR_4NI_1_Z_SHIFT                                               0
+#define   NV50TCL_VTX_ATTR_4NI_1_Z_MASK                                                        0x0000ffff
+#define   NV50TCL_VTX_ATTR_4NI_1_W_SHIFT                                               16
+#define   NV50TCL_VTX_ATTR_4NI_1_W_MASK                                                        0xffff0000
+#define  NV50TCL_VERTEX_ARRAY_FORMAT(x)                                                        (0x00000900+((x)*16))
+#define  NV50TCL_VERTEX_ARRAY_FORMAT__SIZE                                             0x00000010
+#define  NV50TCL_VIEWPORT_UNK0(x)                                                      (0x00000a00+((x)*4))
+#define  NV50TCL_VIEWPORT_UNK0__SIZE                                                   0x00000003
+#define  NV50TCL_VIEWPORT_UNK1(x)                                                      (0x00000a0c+((x)*4))
+#define  NV50TCL_VIEWPORT_UNK1__SIZE                                                   0x00000003
+#define  NV50TCL_VIEWPORT_HORIZ                                                                0x00000c00
+#define   NV50TCL_VIEWPORT_HORIZ_X_SHIFT                                               0
+#define   NV50TCL_VIEWPORT_HORIZ_X_MASK                                                        0x0000ffff
+#define   NV50TCL_VIEWPORT_HORIZ_W_SHIFT                                               16
+#define   NV50TCL_VIEWPORT_HORIZ_W_MASK                                                        0xffff0000
+#define  NV50TCL_VIEWPORT_VERT                                                         0x00000c04
+#define   NV50TCL_VIEWPORT_VERT_Y_SHIFT                                                        0
+#define   NV50TCL_VIEWPORT_VERT_Y_MASK                                                 0x0000ffff
+#define   NV50TCL_VIEWPORT_VERT_H_SHIFT                                                        16
+#define   NV50TCL_VIEWPORT_VERT_H_MASK                                                 0xffff0000
+#define  NV50TCL_DEPTH_RANGE_NEAR                                                      0x00000c08
+#define  NV50TCL_DEPTH_RANGE_FAR                                                       0x00000c0c
+#define  NV50TCL_VIEWPORT_CLIP_HORIZ(x)                                                        (0x00000d00+((x)*8))
+#define  NV50TCL_VIEWPORT_CLIP_HORIZ__SIZE                                             0x00000008
+#define  NV50TCL_VIEWPORT_CLIP_VERT(x)                                                 (0x00000d04+((x)*8))
+#define  NV50TCL_VIEWPORT_CLIP_VERT__SIZE                                              0x00000008
+#define  NV50TCL_VERTEX_BUFFER_FIRST                                                   0x00000d74
+#define  NV50TCL_VERTEX_BUFFER_COUNT                                                   0x00000d78
+#define  NV50TCL_CLEAR_COLOR(x)                                                                (0x00000d80+((x)*4))
+#define  NV50TCL_CLEAR_COLOR__SIZE                                                     0x00000004
+#define  NV50TCL_CLEAR_DEPTH                                                           0x00000d90
+#define  NV50TCL_CLEAR_STENCIL                                                         0x00000da0
+#define  NV50TCL_POLYGON_MODE_FRONT                                                    0x00000dac
+#define   NV50TCL_POLYGON_MODE_FRONT_POINT                                             0x00001b00
+#define   NV50TCL_POLYGON_MODE_FRONT_LINE                                              0x00001b01
+#define   NV50TCL_POLYGON_MODE_FRONT_FILL                                              0x00001b02
+#define  NV50TCL_POLYGON_MODE_BACK                                                     0x00000db0
+#define   NV50TCL_POLYGON_MODE_BACK_POINT                                              0x00001b00
+#define   NV50TCL_POLYGON_MODE_BACK_LINE                                               0x00001b01
+#define   NV50TCL_POLYGON_MODE_BACK_FILL                                               0x00001b02
+#define  NV50TCL_POLYGON_SMOOTH_ENABLE                                                 0x00000db4
+#define  NV50TCL_POLYGON_OFFSET_POINT_ENABLE                                           0x00000dc0
+#define  NV50TCL_POLYGON_OFFSET_LINE_ENABLE                                            0x00000dc4
+#define  NV50TCL_POLYGON_OFFSET_FILL_ENABLE                                            0x00000dc8
+#define  NV50TCL_SCISSOR_HORIZ                                                         0x00000e04
+#define   NV50TCL_SCISSOR_HORIZ_L_SHIFT                                                        0
+#define   NV50TCL_SCISSOR_HORIZ_L_MASK                                                 0x0000ffff
+#define   NV50TCL_SCISSOR_HORIZ_R_SHIFT                                                        16
+#define   NV50TCL_SCISSOR_HORIZ_R_MASK                                                 0xffff0000
+#define  NV50TCL_SCISSOR_VERT                                                          0x00000e08
+#define   NV50TCL_SCISSOR_VERT_T_SHIFT                                                 0
+#define   NV50TCL_SCISSOR_VERT_T_MASK                                                  0x0000ffff
+#define   NV50TCL_SCISSOR_VERT_B_SHIFT                                                 16
+#define   NV50TCL_SCISSOR_VERT_B_MASK                                                  0xffff0000
+#define  NV50TCL_CB_ADDR                                                               0x00000f00
+#define   NV50TCL_CB_ADDR_ID_SHIFT                                                     8
+#define   NV50TCL_CB_ADDR_ID_MASK                                                      0xffffff00
+#define   NV50TCL_CB_ADDR_BUFFER_SHIFT                                                 0
+#define   NV50TCL_CB_ADDR_BUFFER_MASK                                                  0x000000ff
+#define  NV50TCL_CB_DATA(x)                                                            (0x00000f04+((x)*4))
+#define  NV50TCL_CB_DATA__SIZE                                                         0x00000010
+#define  NV50TCL_STENCIL_FRONT_FUNC_REF                                                        0x00000f54
+#define  NV50TCL_STENCIL_FRONT_MASK                                                    0x00000f58
+#define  NV50TCL_STENCIL_FRONT_FUNC_MASK                                               0x00000f5c
+#define  NV50TCL_GP_ADDRESS_HIGH                                                       0x00000f70
+#define  NV50TCL_GP_ADDRESS_LOW                                                                0x00000f74
+#define  NV50TCL_VP_ADDRESS_HIGH                                                       0x00000f7c
+#define  NV50TCL_VP_ADDRESS_LOW                                                                0x00000f80
+#define  NV50TCL_FP_ADDRESS_HIGH                                                       0x00000fa4
+#define  NV50TCL_FP_ADDRESS_LOW                                                                0x00000fa8
+#define  NV50TCL_ZETA_ADDRESS_HIGH                                                     0x00000fe0
+#define  NV50TCL_ZETA_ADDRESS_LOW                                                      0x00000fe4
+#define  NV50TCL_UNKFF4                                                                        0x00000ff4
+#define   NV50TCL_UNKFF4_W_SHIFT                                                       16
+#define   NV50TCL_UNKFF4_W_MASK                                                                0xffff0000
+#define  NV50TCL_UNKFF8                                                                        0x00000ff8
+#define   NV50TCL_UNKFF8_H_SHIFT                                                       16
+#define   NV50TCL_UNKFF8_H_MASK                                                                0xffff0000
+#define  NV50TCL_RT_HORIZ(x)                                                           (0x00001240+((x)*8))
+#define  NV50TCL_RT_HORIZ__SIZE                                                                0x00000008
+#define  NV50TCL_RT_VERT(x)                                                            (0x00001244+((x)*8))
+#define  NV50TCL_RT_VERT__SIZE                                                         0x00000008
+#define  NV50TCL_CB_DEF_ADDRESS_HIGH                                                   0x00001280
+#define  NV50TCL_CB_DEF_ADDRESS_LOW                                                    0x00001284
+#define  NV50TCL_CB_DEF_SET                                                            0x00001288
+#define   NV50TCL_CB_DEF_SET_SIZE_SHIFT                                                        0
+#define   NV50TCL_CB_DEF_SET_SIZE_MASK                                                 0x0000ffff
+#define   NV50TCL_CB_DEF_SET_BUFFER_SHIFT                                              16
+#define   NV50TCL_CB_DEF_SET_BUFFER_MASK                                               0xffff0000
+#define  NV50TCL_DEPTH_TEST_ENABLE                                                     0x000012cc
+#define  NV50TCL_SHADE_MODEL                                                           0x000012d4
+#define   NV50TCL_SHADE_MODEL_FLAT                                                     0x00001d00
+#define   NV50TCL_SHADE_MODEL_SMOOTH                                                   0x00001d01
+#define  NV50TCL_DEPTH_WRITE_ENABLE                                                    0x000012e8
+#define  NV50TCL_ALPHA_TEST_ENABLE                                                     0x000012ec
+#define  NV50TCL_DEPTH_TEST_FUNC                                                       0x0000130c
+#define   NV50TCL_DEPTH_TEST_FUNC_NEVER                                                        0x00000200
+#define   NV50TCL_DEPTH_TEST_FUNC_LESS                                                 0x00000201
+#define   NV50TCL_DEPTH_TEST_FUNC_EQUAL                                                        0x00000202
+#define   NV50TCL_DEPTH_TEST_FUNC_LEQUAL                                               0x00000203
+#define   NV50TCL_DEPTH_TEST_FUNC_GREATER                                              0x00000204
+#define   NV50TCL_DEPTH_TEST_FUNC_GREATER                                              0x00000204
+#define   NV50TCL_DEPTH_TEST_FUNC_NOTEQUAL                                             0x00000205
+#define   NV50TCL_DEPTH_TEST_FUNC_GEQUAL                                               0x00000206
+#define   NV50TCL_DEPTH_TEST_FUNC_ALWAYS                                               0x00000207
+#define  NV50TCL_ALPHA_TEST_REF                                                                0x00001310
+#define  NV50TCL_ALPHA_TEST_FUNC                                                       0x00001314
+#define   NV50TCL_ALPHA_TEST_FUNC_NEVER                                                        0x00000200
+#define   NV50TCL_ALPHA_TEST_FUNC_LESS                                                 0x00000201
+#define   NV50TCL_ALPHA_TEST_FUNC_EQUAL                                                        0x00000202
+#define   NV50TCL_ALPHA_TEST_FUNC_LEQUAL                                               0x00000203
+#define   NV50TCL_ALPHA_TEST_FUNC_GREATER                                              0x00000204
+#define   NV50TCL_ALPHA_TEST_FUNC_GREATER                                              0x00000204
+#define   NV50TCL_ALPHA_TEST_FUNC_NOTEQUAL                                             0x00000205
+#define   NV50TCL_ALPHA_TEST_FUNC_GEQUAL                                               0x00000206
+#define   NV50TCL_ALPHA_TEST_FUNC_ALWAYS                                               0x00000207
+#define  NV50TCL_BLEND_COLOR(x)                                                                (0x0000131c+((x)*4))
+#define  NV50TCL_BLEND_COLOR__SIZE                                                     0x00000004
+#define  NV50TCL_BLEND_EQUATION_RGB                                                    0x00001340
+#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_ADD                                          0x00008006
+#define   NV50TCL_BLEND_EQUATION_RGB_MIN                                               0x00008007
+#define   NV50TCL_BLEND_EQUATION_RGB_MAX                                               0x00008008
+#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_SUBTRACT                                     0x0000800a
+#define   NV50TCL_BLEND_EQUATION_RGB_FUNC_REVERSE_SUBTRACT                             0x0000800b
+#define  NV50TCL_BLEND_FUNC_SRC_RGB                                                    0x00001344
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ZERO                                              0x00000000
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE                                               0x00000001
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_COLOR                                         0x00000300
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_COLOR                               0x00000301
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA                                         0x00000302
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_SRC_ALPHA                               0x00000303
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_DST_ALPHA                                         0x00000304
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_ALPHA                               0x00000305
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_DST_COLOR                                         0x00000306
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_DST_COLOR                               0x00000307
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_SRC_ALPHA_SATURATE                                        0x00000308
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_COLOR                                    0x00008001
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_COLOR                          0x00008002
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_CONSTANT_ALPHA                                    0x00008003
+#define   NV50TCL_BLEND_FUNC_SRC_RGB_ONE_MINUS_CONSTANT_ALPHA                          0x00008004
+#define  NV50TCL_BLEND_FUNC_DST_RGB                                                    0x00001348
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ZERO                                              0x00000000
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE                                               0x00000001
+#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_COLOR                                         0x00000300
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_COLOR                               0x00000301
+#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA                                         0x00000302
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_SRC_ALPHA                               0x00000303
+#define   NV50TCL_BLEND_FUNC_DST_RGB_DST_ALPHA                                         0x00000304
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_ALPHA                               0x00000305
+#define   NV50TCL_BLEND_FUNC_DST_RGB_DST_COLOR                                         0x00000306
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_DST_COLOR                               0x00000307
+#define   NV50TCL_BLEND_FUNC_DST_RGB_SRC_ALPHA_SATURATE                                        0x00000308
+#define   NV50TCL_BLEND_FUNC_DST_RGB_CONSTANT_COLOR                                    0x00008001
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_COLOR                          0x00008002
+#define   NV50TCL_BLEND_FUNC_DST_RGB_CONSTANT_ALPHA                                    0x00008003
+#define   NV50TCL_BLEND_FUNC_DST_RGB_ONE_MINUS_CONSTANT_ALPHA                          0x00008004
+#define  NV50TCL_BLEND_EQUATION_ALPHA                                                  0x0000134c
+#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_ADD                                                0x00008006
+#define   NV50TCL_BLEND_EQUATION_ALPHA_MIN                                             0x00008007
+#define   NV50TCL_BLEND_EQUATION_ALPHA_MAX                                             0x00008008
+#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_SUBTRACT                                   0x0000800a
+#define   NV50TCL_BLEND_EQUATION_ALPHA_FUNC_REVERSE_SUBTRACT                           0x0000800b
+#define  NV50TCL_BLEND_FUNC_SRC_ALPHA                                                  0x00001350
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ZERO                                            0x00000000
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE                                             0x00000001
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_COLOR                                       0x00000300
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_COLOR                             0x00000301
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA                                       0x00000302
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_SRC_ALPHA                             0x00000303
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_DST_ALPHA                                       0x00000304
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_ALPHA                             0x00000305
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_DST_COLOR                                       0x00000306
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_DST_COLOR                             0x00000307
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_SRC_ALPHA_SATURATE                              0x00000308
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_COLOR                                  0x00008001
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_COLOR                                0x00008002
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_CONSTANT_ALPHA                                  0x00008003
+#define   NV50TCL_BLEND_FUNC_SRC_ALPHA_ONE_MINUS_CONSTANT_ALPHA                                0x00008004
+#define  NV50TCL_BLEND_FUNC_DST_ALPHA                                                  0x00001358
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ZERO                                            0x00000000
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE                                             0x00000001
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_COLOR                                       0x00000300
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_COLOR                             0x00000301
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA                                       0x00000302
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_SRC_ALPHA                             0x00000303
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_DST_ALPHA                                       0x00000304
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_ALPHA                             0x00000305
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_DST_COLOR                                       0x00000306
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_DST_COLOR                             0x00000307
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_SRC_ALPHA_SATURATE                              0x00000308
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_COLOR                                  0x00008001
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_COLOR                                0x00008002
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_CONSTANT_ALPHA                                  0x00008003
+#define   NV50TCL_BLEND_FUNC_DST_ALPHA_ONE_MINUS_CONSTANT_ALPHA                                0x00008004
+#define  NV50TCL_BLEND_ENABLE(x)                                                       (0x00001360+((x)*4))
+#define  NV50TCL_BLEND_ENABLE__SIZE                                                    0x00000008
+#define  NV50TCL_STENCIL_BACK_ENABLE                                                   0x00001380
+#define  NV50TCL_STENCIL_BACK_OP_FAIL                                                  0x00001384
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_ZERO                                            0x00000000
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_INVERT                                          0x0000150a
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_KEEP                                            0x00001e00
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_REPLACE                                         0x00001e01
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_INCR                                            0x00001e02
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_DECR                                            0x00001e03
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_INCR_WRAP                                       0x00008507
+#define   NV50TCL_STENCIL_BACK_OP_FAIL_DECR_WRAP                                       0x00008508
+#define  NV50TCL_STENCIL_BACK_OP_ZFAIL                                                 0x00001388
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_ZERO                                           0x00000000
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INVERT                                         0x0000150a
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_KEEP                                           0x00001e00
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_REPLACE                                                0x00001e01
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INCR                                           0x00001e02
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_DECR                                           0x00001e03
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_INCR_WRAP                                      0x00008507
+#define   NV50TCL_STENCIL_BACK_OP_ZFAIL_DECR_WRAP                                      0x00008508
+#define  NV50TCL_STENCIL_BACK_OP_ZPASS                                                 0x0000138c
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_ZERO                                           0x00000000
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INVERT                                         0x0000150a
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_KEEP                                           0x00001e00
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_REPLACE                                                0x00001e01
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INCR                                           0x00001e02
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_DECR                                           0x00001e03
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_INCR_WRAP                                      0x00008507
+#define   NV50TCL_STENCIL_BACK_OP_ZPASS_DECR_WRAP                                      0x00008508
+#define  NV50TCL_STENCIL_BACK_FUNC_FUNC                                                        0x00001390
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_NEVER                                         0x00000200
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_LESS                                          0x00000201
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_EQUAL                                         0x00000202
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_LEQUAL                                                0x00000203
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GREATER                                       0x00000204
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_NOTEQUAL                                      0x00000205
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_GEQUAL                                                0x00000206
+#define   NV50TCL_STENCIL_BACK_FUNC_FUNC_ALWAYS                                                0x00000207
+#define  NV50TCL_STENCIL_BACK_FUNC_REF                                                 0x00001394
+#define  NV50TCL_STENCIL_BACK_MASK                                                     0x00001398
+#define  NV50TCL_STENCIL_BACK_FUNC_MASK                                                        0x0000139c
+#define  NV50TCL_LINE_WIDTH                                                            0x000013b0
+#define  NV50TCL_VP_START_ID                                                           0x0000140c
+#define  NV50TCL_GP_START_ID                                                           0x00001410
+#define  NV50TCL_FP_START_ID                                                           0x00001414
+#define  NV50TCL_POINT_SIZE                                                            0x00001518
+#define  NV50TCL_TSC_ADDRESS_HIGH                                                      0x0000155c
+#define  NV50TCL_TSC_ADDRESS_LOW                                                       0x00001560
+#define  NV50TCL_POLYGON_OFFSET_FACTOR                                                 0x0000156c
+#define  NV50TCL_LINE_SMOOTH_ENABLE                                                    0x00001570
+#define  NV50TCL_TIC_ADDRESS_HIGH                                                      0x00001574
+#define  NV50TCL_TIC_ADDRESS_LOW                                                       0x00001578
+#define  NV50TCL_STENCIL_FRONT_ENABLE                                                  0x00001594
+#define  NV50TCL_STENCIL_FRONT_OP_FAIL                                                 0x00001598
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_ZERO                                           0x00000000
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INVERT                                         0x0000150a
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_KEEP                                           0x00001e00
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_REPLACE                                                0x00001e01
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INCR                                           0x00001e02
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_DECR                                           0x00001e03
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_INCR_WRAP                                      0x00008507
+#define   NV50TCL_STENCIL_FRONT_OP_FAIL_DECR_WRAP                                      0x00008508
+#define  NV50TCL_STENCIL_FRONT_OP_ZFAIL                                                        0x0000159c
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_ZERO                                          0x00000000
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INVERT                                                0x0000150a
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_KEEP                                          0x00001e00
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_REPLACE                                       0x00001e01
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INCR                                          0x00001e02
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_DECR                                          0x00001e03
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_INCR_WRAP                                     0x00008507
+#define   NV50TCL_STENCIL_FRONT_OP_ZFAIL_DECR_WRAP                                     0x00008508
+#define  NV50TCL_STENCIL_FRONT_OP_ZPASS                                                        0x000015a0
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_ZERO                                          0x00000000
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INVERT                                                0x0000150a
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_KEEP                                          0x00001e00
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_REPLACE                                       0x00001e01
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INCR                                          0x00001e02
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_DECR                                          0x00001e03
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_INCR_WRAP                                     0x00008507
+#define   NV50TCL_STENCIL_FRONT_OP_ZPASS_DECR_WRAP                                     0x00008508
+#define  NV50TCL_STENCIL_FRONT_FUNC_FUNC                                               0x000015a4
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_NEVER                                                0x00000200
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_LESS                                         0x00000201
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_EQUAL                                                0x00000202
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_LEQUAL                                       0x00000203
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GREATER                                      0x00000204
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_NOTEQUAL                                     0x00000205
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_GEQUAL                                       0x00000206
+#define   NV50TCL_STENCIL_FRONT_FUNC_FUNC_ALWAYS                                       0x00000207
+#define  NV50TCL_POLYGON_OFFSET_UNITS                                                  0x000015bc
+#define  NV50TCL_VERTEX_BEGIN                                                          0x000015dc
+#define   NV50TCL_VERTEX_BEGIN_POINTS                                                  0x00000000
+#define   NV50TCL_VERTEX_BEGIN_LINES                                                   0x00000001
+#define   NV50TCL_VERTEX_BEGIN_LINE_LOOP                                               0x00000002
+#define   NV50TCL_VERTEX_BEGIN_LINE_STRIP                                              0x00000003
+#define   NV50TCL_VERTEX_BEGIN_TRIANGLES                                               0x00000004
+#define   NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP                                          0x00000005
+#define   NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN                                            0x00000006
+#define   NV50TCL_VERTEX_BEGIN_QUADS                                                   0x00000007
+#define   NV50TCL_VERTEX_BEGIN_QUAD_STRIP                                              0x00000008
+#define   NV50TCL_VERTEX_BEGIN_POLYGON                                                 0x00000009
+#define  NV50TCL_VERTEX_END                                                            0x000015e0
+#define  NV50TCL_VERTEX_DATA                                                           0x00001640
+#define  NV50TCL_VP_ATTR_EN_0                                                          0x00001650
+#define   NV50TCL_VP_ATTR_EN_0_7_SHIFT                                                 28
+#define   NV50TCL_VP_ATTR_EN_0_7_MASK                                                  0xf0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XNNN                                                 0x10000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NYNN                                                 0x20000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XYNN                                                 0x30000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NNZN                                                 0x40000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XNZN                                                 0x50000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NYZN                                                 0x60000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XYZN                                                 0x70000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NNNW                                                 0x80000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XNNW                                                 0x90000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NYNW                                                 0xa0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XYNW                                                 0xb0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NNZW                                                 0xc0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XNZW                                                 0xd0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_NYZW                                                 0xe0000000
+#define    NV50TCL_VP_ATTR_EN_0_7_XYZW                                                 0xf0000000
+#define   NV50TCL_VP_ATTR_EN_0_6_SHIFT                                                 24
+#define   NV50TCL_VP_ATTR_EN_0_6_MASK                                                  0x0f000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XNNN                                                 0x01000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NYNN                                                 0x02000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XYNN                                                 0x03000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NNZN                                                 0x04000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XNZN                                                 0x05000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NYZN                                                 0x06000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XYZN                                                 0x07000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NNNW                                                 0x08000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XNNW                                                 0x09000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NYNW                                                 0x0a000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XYNW                                                 0x0b000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NNZW                                                 0x0c000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XNZW                                                 0x0d000000
+#define    NV50TCL_VP_ATTR_EN_0_6_NYZW                                                 0x0e000000
+#define    NV50TCL_VP_ATTR_EN_0_6_XYZW                                                 0x0f000000
+#define   NV50TCL_VP_ATTR_EN_0_5_SHIFT                                                 20
+#define   NV50TCL_VP_ATTR_EN_0_5_MASK                                                  0x00f00000
+#define    NV50TCL_VP_ATTR_EN_0_5_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_5_XNNN                                                 0x00100000
+#define    NV50TCL_VP_ATTR_EN_0_5_NYNN                                                 0x00200000
+#define    NV50TCL_VP_ATTR_EN_0_5_XYNN                                                 0x00300000
+#define    NV50TCL_VP_ATTR_EN_0_5_NNZN                                                 0x00400000
+#define    NV50TCL_VP_ATTR_EN_0_5_XNZN                                                 0x00500000
+#define    NV50TCL_VP_ATTR_EN_0_5_NYZN                                                 0x00600000
+#define    NV50TCL_VP_ATTR_EN_0_5_XYZN                                                 0x00700000
+#define    NV50TCL_VP_ATTR_EN_0_5_NNNW                                                 0x00800000
+#define    NV50TCL_VP_ATTR_EN_0_5_XNNW                                                 0x00900000
+#define    NV50TCL_VP_ATTR_EN_0_5_NYNW                                                 0x00a00000
+#define    NV50TCL_VP_ATTR_EN_0_5_XYNW                                                 0x00b00000
+#define    NV50TCL_VP_ATTR_EN_0_5_NNZW                                                 0x00c00000
+#define    NV50TCL_VP_ATTR_EN_0_5_XNZW                                                 0x00d00000
+#define    NV50TCL_VP_ATTR_EN_0_5_NYZW                                                 0x00e00000
+#define    NV50TCL_VP_ATTR_EN_0_5_XYZW                                                 0x00f00000
+#define   NV50TCL_VP_ATTR_EN_0_4_SHIFT                                                 16
+#define   NV50TCL_VP_ATTR_EN_0_4_MASK                                                  0x000f0000
+#define    NV50TCL_VP_ATTR_EN_0_4_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_4_XNNN                                                 0x00010000
+#define    NV50TCL_VP_ATTR_EN_0_4_NYNN                                                 0x00020000
+#define    NV50TCL_VP_ATTR_EN_0_4_XYNN                                                 0x00030000
+#define    NV50TCL_VP_ATTR_EN_0_4_NNZN                                                 0x00040000
+#define    NV50TCL_VP_ATTR_EN_0_4_XNZN                                                 0x00050000
+#define    NV50TCL_VP_ATTR_EN_0_4_NYZN                                                 0x00060000
+#define    NV50TCL_VP_ATTR_EN_0_4_XYZN                                                 0x00070000
+#define    NV50TCL_VP_ATTR_EN_0_4_NNNW                                                 0x00080000
+#define    NV50TCL_VP_ATTR_EN_0_4_XNNW                                                 0x00090000
+#define    NV50TCL_VP_ATTR_EN_0_4_NYNW                                                 0x000a0000
+#define    NV50TCL_VP_ATTR_EN_0_4_XYNW                                                 0x000b0000
+#define    NV50TCL_VP_ATTR_EN_0_4_NNZW                                                 0x000c0000
+#define    NV50TCL_VP_ATTR_EN_0_4_XNZW                                                 0x000d0000
+#define    NV50TCL_VP_ATTR_EN_0_4_NYZW                                                 0x000e0000
+#define    NV50TCL_VP_ATTR_EN_0_4_XYZW                                                 0x000f0000
+#define   NV50TCL_VP_ATTR_EN_0_3_SHIFT                                                 12
+#define   NV50TCL_VP_ATTR_EN_0_3_MASK                                                  0x0000f000
+#define    NV50TCL_VP_ATTR_EN_0_3_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_3_XNNN                                                 0x00001000
+#define    NV50TCL_VP_ATTR_EN_0_3_NYNN                                                 0x00002000
+#define    NV50TCL_VP_ATTR_EN_0_3_XYNN                                                 0x00003000
+#define    NV50TCL_VP_ATTR_EN_0_3_NNZN                                                 0x00004000
+#define    NV50TCL_VP_ATTR_EN_0_3_XNZN                                                 0x00005000
+#define    NV50TCL_VP_ATTR_EN_0_3_NYZN                                                 0x00006000
+#define    NV50TCL_VP_ATTR_EN_0_3_XYZN                                                 0x00007000
+#define    NV50TCL_VP_ATTR_EN_0_3_NNNW                                                 0x00008000
+#define    NV50TCL_VP_ATTR_EN_0_3_XNNW                                                 0x00009000
+#define    NV50TCL_VP_ATTR_EN_0_3_NYNW                                                 0x0000a000
+#define    NV50TCL_VP_ATTR_EN_0_3_XYNW                                                 0x0000b000
+#define    NV50TCL_VP_ATTR_EN_0_3_NNZW                                                 0x0000c000
+#define    NV50TCL_VP_ATTR_EN_0_3_XNZW                                                 0x0000d000
+#define    NV50TCL_VP_ATTR_EN_0_3_NYZW                                                 0x0000e000
+#define    NV50TCL_VP_ATTR_EN_0_3_XYZW                                                 0x0000f000
+#define   NV50TCL_VP_ATTR_EN_0_2_SHIFT                                                 8
+#define   NV50TCL_VP_ATTR_EN_0_2_MASK                                                  0x00000f00
+#define    NV50TCL_VP_ATTR_EN_0_2_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_2_XNNN                                                 0x00000100
+#define    NV50TCL_VP_ATTR_EN_0_2_NYNN                                                 0x00000200
+#define    NV50TCL_VP_ATTR_EN_0_2_XYNN                                                 0x00000300
+#define    NV50TCL_VP_ATTR_EN_0_2_NNZN                                                 0x00000400
+#define    NV50TCL_VP_ATTR_EN_0_2_XNZN                                                 0x00000500
+#define    NV50TCL_VP_ATTR_EN_0_2_NYZN                                                 0x00000600
+#define    NV50TCL_VP_ATTR_EN_0_2_XYZN                                                 0x00000700
+#define    NV50TCL_VP_ATTR_EN_0_2_NNNW                                                 0x00000800
+#define    NV50TCL_VP_ATTR_EN_0_2_XNNW                                                 0x00000900
+#define    NV50TCL_VP_ATTR_EN_0_2_NYNW                                                 0x00000a00
+#define    NV50TCL_VP_ATTR_EN_0_2_XYNW                                                 0x00000b00
+#define    NV50TCL_VP_ATTR_EN_0_2_NNZW                                                 0x00000c00
+#define    NV50TCL_VP_ATTR_EN_0_2_XNZW                                                 0x00000d00
+#define    NV50TCL_VP_ATTR_EN_0_2_NYZW                                                 0x00000e00
+#define    NV50TCL_VP_ATTR_EN_0_2_XYZW                                                 0x00000f00
+#define   NV50TCL_VP_ATTR_EN_0_1_SHIFT                                                 4
+#define   NV50TCL_VP_ATTR_EN_0_1_MASK                                                  0x000000f0
+#define    NV50TCL_VP_ATTR_EN_0_1_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_1_XNNN                                                 0x00000010
+#define    NV50TCL_VP_ATTR_EN_0_1_NYNN                                                 0x00000020
+#define    NV50TCL_VP_ATTR_EN_0_1_XYNN                                                 0x00000030
+#define    NV50TCL_VP_ATTR_EN_0_1_NNZN                                                 0x00000040
+#define    NV50TCL_VP_ATTR_EN_0_1_XNZN                                                 0x00000050
+#define    NV50TCL_VP_ATTR_EN_0_1_NYZN                                                 0x00000060
+#define    NV50TCL_VP_ATTR_EN_0_1_XYZN                                                 0x00000070
+#define    NV50TCL_VP_ATTR_EN_0_1_NNNW                                                 0x00000080
+#define    NV50TCL_VP_ATTR_EN_0_1_XNNW                                                 0x00000090
+#define    NV50TCL_VP_ATTR_EN_0_1_NYNW                                                 0x000000a0
+#define    NV50TCL_VP_ATTR_EN_0_1_XYNW                                                 0x000000b0
+#define    NV50TCL_VP_ATTR_EN_0_1_NNZW                                                 0x000000c0
+#define    NV50TCL_VP_ATTR_EN_0_1_XNZW                                                 0x000000d0
+#define    NV50TCL_VP_ATTR_EN_0_1_NYZW                                                 0x000000e0
+#define    NV50TCL_VP_ATTR_EN_0_1_XYZW                                                 0x000000f0
+#define   NV50TCL_VP_ATTR_EN_0_0_SHIFT                                                 0
+#define   NV50TCL_VP_ATTR_EN_0_0_MASK                                                  0x0000000f
+#define    NV50TCL_VP_ATTR_EN_0_0_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_0_0_XNNN                                                 0x00000001
+#define    NV50TCL_VP_ATTR_EN_0_0_NYNN                                                 0x00000002
+#define    NV50TCL_VP_ATTR_EN_0_0_XYNN                                                 0x00000003
+#define    NV50TCL_VP_ATTR_EN_0_0_NNZN                                                 0x00000004
+#define    NV50TCL_VP_ATTR_EN_0_0_XNZN                                                 0x00000005
+#define    NV50TCL_VP_ATTR_EN_0_0_NYZN                                                 0x00000006
+#define    NV50TCL_VP_ATTR_EN_0_0_XYZN                                                 0x00000007
+#define    NV50TCL_VP_ATTR_EN_0_0_NNNW                                                 0x00000008
+#define    NV50TCL_VP_ATTR_EN_0_0_XNNW                                                 0x00000009
+#define    NV50TCL_VP_ATTR_EN_0_0_NYNW                                                 0x0000000a
+#define    NV50TCL_VP_ATTR_EN_0_0_XYNW                                                 0x0000000b
+#define    NV50TCL_VP_ATTR_EN_0_0_NNZW                                                 0x0000000c
+#define    NV50TCL_VP_ATTR_EN_0_0_XNZW                                                 0x0000000d
+#define    NV50TCL_VP_ATTR_EN_0_0_NYZW                                                 0x0000000e
+#define    NV50TCL_VP_ATTR_EN_0_0_XYZW                                                 0x0000000f
+#define  NV50TCL_VP_ATTR_EN_1                                                          0x00001654
+#define   NV50TCL_VP_ATTR_EN_1_15_SHIFT                                                        28
+#define   NV50TCL_VP_ATTR_EN_1_15_MASK                                                 0xf0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XNNN                                                        0x10000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NYNN                                                        0x20000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XYNN                                                        0x30000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NNZN                                                        0x40000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XNZN                                                        0x50000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NYZN                                                        0x60000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XYZN                                                        0x70000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NNNW                                                        0x80000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XNNW                                                        0x90000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NYNW                                                        0xa0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XYNW                                                        0xb0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NNZW                                                        0xc0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XNZW                                                        0xd0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_NYZW                                                        0xe0000000
+#define    NV50TCL_VP_ATTR_EN_1_15_XYZW                                                        0xf0000000
+#define   NV50TCL_VP_ATTR_EN_1_14_SHIFT                                                        24
+#define   NV50TCL_VP_ATTR_EN_1_14_MASK                                                 0x0f000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XNNN                                                        0x01000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NYNN                                                        0x02000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XYNN                                                        0x03000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NNZN                                                        0x04000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XNZN                                                        0x05000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NYZN                                                        0x06000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XYZN                                                        0x07000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NNNW                                                        0x08000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XNNW                                                        0x09000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NYNW                                                        0x0a000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XYNW                                                        0x0b000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NNZW                                                        0x0c000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XNZW                                                        0x0d000000
+#define    NV50TCL_VP_ATTR_EN_1_14_NYZW                                                        0x0e000000
+#define    NV50TCL_VP_ATTR_EN_1_14_XYZW                                                        0x0f000000
+#define   NV50TCL_VP_ATTR_EN_1_13_SHIFT                                                        20
+#define   NV50TCL_VP_ATTR_EN_1_13_MASK                                                 0x00f00000
+#define    NV50TCL_VP_ATTR_EN_1_13_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_13_XNNN                                                        0x00100000
+#define    NV50TCL_VP_ATTR_EN_1_13_NYNN                                                        0x00200000
+#define    NV50TCL_VP_ATTR_EN_1_13_XYNN                                                        0x00300000
+#define    NV50TCL_VP_ATTR_EN_1_13_NNZN                                                        0x00400000
+#define    NV50TCL_VP_ATTR_EN_1_13_XNZN                                                        0x00500000
+#define    NV50TCL_VP_ATTR_EN_1_13_NYZN                                                        0x00600000
+#define    NV50TCL_VP_ATTR_EN_1_13_XYZN                                                        0x00700000
+#define    NV50TCL_VP_ATTR_EN_1_13_NNNW                                                        0x00800000
+#define    NV50TCL_VP_ATTR_EN_1_13_XNNW                                                        0x00900000
+#define    NV50TCL_VP_ATTR_EN_1_13_NYNW                                                        0x00a00000
+#define    NV50TCL_VP_ATTR_EN_1_13_XYNW                                                        0x00b00000
+#define    NV50TCL_VP_ATTR_EN_1_13_NNZW                                                        0x00c00000
+#define    NV50TCL_VP_ATTR_EN_1_13_XNZW                                                        0x00d00000
+#define    NV50TCL_VP_ATTR_EN_1_13_NYZW                                                        0x00e00000
+#define    NV50TCL_VP_ATTR_EN_1_13_XYZW                                                        0x00f00000
+#define   NV50TCL_VP_ATTR_EN_1_12_SHIFT                                                        16
+#define   NV50TCL_VP_ATTR_EN_1_12_MASK                                                 0x000f0000
+#define    NV50TCL_VP_ATTR_EN_1_12_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_12_XNNN                                                        0x00010000
+#define    NV50TCL_VP_ATTR_EN_1_12_NYNN                                                        0x00020000
+#define    NV50TCL_VP_ATTR_EN_1_12_XYNN                                                        0x00030000
+#define    NV50TCL_VP_ATTR_EN_1_12_NNZN                                                        0x00040000
+#define    NV50TCL_VP_ATTR_EN_1_12_XNZN                                                        0x00050000
+#define    NV50TCL_VP_ATTR_EN_1_12_NYZN                                                        0x00060000
+#define    NV50TCL_VP_ATTR_EN_1_12_XYZN                                                        0x00070000
+#define    NV50TCL_VP_ATTR_EN_1_12_NNNW                                                        0x00080000
+#define    NV50TCL_VP_ATTR_EN_1_12_XNNW                                                        0x00090000
+#define    NV50TCL_VP_ATTR_EN_1_12_NYNW                                                        0x000a0000
+#define    NV50TCL_VP_ATTR_EN_1_12_XYNW                                                        0x000b0000
+#define    NV50TCL_VP_ATTR_EN_1_12_NNZW                                                        0x000c0000
+#define    NV50TCL_VP_ATTR_EN_1_12_XNZW                                                        0x000d0000
+#define    NV50TCL_VP_ATTR_EN_1_12_NYZW                                                        0x000e0000
+#define    NV50TCL_VP_ATTR_EN_1_12_XYZW                                                        0x000f0000
+#define   NV50TCL_VP_ATTR_EN_1_11_SHIFT                                                        12
+#define   NV50TCL_VP_ATTR_EN_1_11_MASK                                                 0x0000f000
+#define    NV50TCL_VP_ATTR_EN_1_11_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_11_XNNN                                                        0x00001000
+#define    NV50TCL_VP_ATTR_EN_1_11_NYNN                                                        0x00002000
+#define    NV50TCL_VP_ATTR_EN_1_11_XYNN                                                        0x00003000
+#define    NV50TCL_VP_ATTR_EN_1_11_NNZN                                                        0x00004000
+#define    NV50TCL_VP_ATTR_EN_1_11_XNZN                                                        0x00005000
+#define    NV50TCL_VP_ATTR_EN_1_11_NYZN                                                        0x00006000
+#define    NV50TCL_VP_ATTR_EN_1_11_XYZN                                                        0x00007000
+#define    NV50TCL_VP_ATTR_EN_1_11_NNNW                                                        0x00008000
+#define    NV50TCL_VP_ATTR_EN_1_11_XNNW                                                        0x00009000
+#define    NV50TCL_VP_ATTR_EN_1_11_NYNW                                                        0x0000a000
+#define    NV50TCL_VP_ATTR_EN_1_11_XYNW                                                        0x0000b000
+#define    NV50TCL_VP_ATTR_EN_1_11_NNZW                                                        0x0000c000
+#define    NV50TCL_VP_ATTR_EN_1_11_XNZW                                                        0x0000d000
+#define    NV50TCL_VP_ATTR_EN_1_11_NYZW                                                        0x0000e000
+#define    NV50TCL_VP_ATTR_EN_1_11_XYZW                                                        0x0000f000
+#define   NV50TCL_VP_ATTR_EN_1_10_SHIFT                                                        8
+#define   NV50TCL_VP_ATTR_EN_1_10_MASK                                                 0x00000f00
+#define    NV50TCL_VP_ATTR_EN_1_10_NONE                                                        0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_10_XNNN                                                        0x00000100
+#define    NV50TCL_VP_ATTR_EN_1_10_NYNN                                                        0x00000200
+#define    NV50TCL_VP_ATTR_EN_1_10_XYNN                                                        0x00000300
+#define    NV50TCL_VP_ATTR_EN_1_10_NNZN                                                        0x00000400
+#define    NV50TCL_VP_ATTR_EN_1_10_XNZN                                                        0x00000500
+#define    NV50TCL_VP_ATTR_EN_1_10_NYZN                                                        0x00000600
+#define    NV50TCL_VP_ATTR_EN_1_10_XYZN                                                        0x00000700
+#define    NV50TCL_VP_ATTR_EN_1_10_NNNW                                                        0x00000800
+#define    NV50TCL_VP_ATTR_EN_1_10_XNNW                                                        0x00000900
+#define    NV50TCL_VP_ATTR_EN_1_10_NYNW                                                        0x00000a00
+#define    NV50TCL_VP_ATTR_EN_1_10_XYNW                                                        0x00000b00
+#define    NV50TCL_VP_ATTR_EN_1_10_NNZW                                                        0x00000c00
+#define    NV50TCL_VP_ATTR_EN_1_10_XNZW                                                        0x00000d00
+#define    NV50TCL_VP_ATTR_EN_1_10_NYZW                                                        0x00000e00
+#define    NV50TCL_VP_ATTR_EN_1_10_XYZW                                                        0x00000f00
+#define   NV50TCL_VP_ATTR_EN_1_9_SHIFT                                                 4
+#define   NV50TCL_VP_ATTR_EN_1_9_MASK                                                  0x000000f0
+#define    NV50TCL_VP_ATTR_EN_1_9_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_9_XNNN                                                 0x00000010
+#define    NV50TCL_VP_ATTR_EN_1_9_NYNN                                                 0x00000020
+#define    NV50TCL_VP_ATTR_EN_1_9_XYNN                                                 0x00000030
+#define    NV50TCL_VP_ATTR_EN_1_9_NNZN                                                 0x00000040
+#define    NV50TCL_VP_ATTR_EN_1_9_XNZN                                                 0x00000050
+#define    NV50TCL_VP_ATTR_EN_1_9_NYZN                                                 0x00000060
+#define    NV50TCL_VP_ATTR_EN_1_9_XYZN                                                 0x00000070
+#define    NV50TCL_VP_ATTR_EN_1_9_NNNW                                                 0x00000080
+#define    NV50TCL_VP_ATTR_EN_1_9_XNNW                                                 0x00000090
+#define    NV50TCL_VP_ATTR_EN_1_9_NYNW                                                 0x000000a0
+#define    NV50TCL_VP_ATTR_EN_1_9_XYNW                                                 0x000000b0
+#define    NV50TCL_VP_ATTR_EN_1_9_NNZW                                                 0x000000c0
+#define    NV50TCL_VP_ATTR_EN_1_9_XNZW                                                 0x000000d0
+#define    NV50TCL_VP_ATTR_EN_1_9_NYZW                                                 0x000000e0
+#define    NV50TCL_VP_ATTR_EN_1_9_XYZW                                                 0x000000f0
+#define   NV50TCL_VP_ATTR_EN_1_8_SHIFT                                                 0
+#define   NV50TCL_VP_ATTR_EN_1_8_MASK                                                  0x0000000f
+#define    NV50TCL_VP_ATTR_EN_1_8_NONE                                                 0x00000000
+#define    NV50TCL_VP_ATTR_EN_1_8_XNNN                                                 0x00000001
+#define    NV50TCL_VP_ATTR_EN_1_8_NYNN                                                 0x00000002
+#define    NV50TCL_VP_ATTR_EN_1_8_XYNN                                                 0x00000003
+#define    NV50TCL_VP_ATTR_EN_1_8_NNZN                                                 0x00000004
+#define    NV50TCL_VP_ATTR_EN_1_8_XNZN                                                 0x00000005
+#define    NV50TCL_VP_ATTR_EN_1_8_NYZN                                                 0x00000006
+#define    NV50TCL_VP_ATTR_EN_1_8_XYZN                                                 0x00000007
+#define    NV50TCL_VP_ATTR_EN_1_8_NNNW                                                 0x00000008
+#define    NV50TCL_VP_ATTR_EN_1_8_XNNW                                                 0x00000009
+#define    NV50TCL_VP_ATTR_EN_1_8_NYNW                                                 0x0000000a
+#define    NV50TCL_VP_ATTR_EN_1_8_XYNW                                                 0x0000000b
+#define    NV50TCL_VP_ATTR_EN_1_8_NNZW                                                 0x0000000c
+#define    NV50TCL_VP_ATTR_EN_1_8_XNZW                                                 0x0000000d
+#define    NV50TCL_VP_ATTR_EN_1_8_NYZW                                                 0x0000000e
+#define    NV50TCL_VP_ATTR_EN_1_8_XYZW                                                 0x0000000f
+#define  NV50TCL_LINE_STIPPLE_ENABLE                                                   0x0000166c
+#define  NV50TCL_LINE_STIPPLE_PATTERN                                                  0x00001680
+#define  NV50TCL_POLYGON_STIPPLE_ENABLE                                                        0x0000168c
+#define  NV50TCL_VP_REG_HPOS                                                           0x000016bc
+#define   NV50TCL_VP_REG_HPOS_X_SHIFT                                                  0
+#define   NV50TCL_VP_REG_HPOS_X_MASK                                                   0x000000ff
+#define   NV50TCL_VP_REG_HPOS_Y_SHIFT                                                  8
+#define   NV50TCL_VP_REG_HPOS_Y_MASK                                                   0x0000ff00
+#define   NV50TCL_VP_REG_HPOS_Z_SHIFT                                                  16
+#define   NV50TCL_VP_REG_HPOS_Z_MASK                                                   0x00ff0000
+#define   NV50TCL_VP_REG_HPOS_W_SHIFT                                                  24
+#define   NV50TCL_VP_REG_HPOS_W_MASK                                                   0xff000000
+#define  NV50TCL_VP_REG_COL0                                                           0x000016c0
+#define   NV50TCL_VP_REG_COL0_X_SHIFT                                                  0
+#define   NV50TCL_VP_REG_COL0_X_MASK                                                   0x000000ff
+#define   NV50TCL_VP_REG_COL0_Y_SHIFT                                                  8
+#define   NV50TCL_VP_REG_COL0_Y_MASK                                                   0x0000ff00
+#define   NV50TCL_VP_REG_COL0_Z_SHIFT                                                  16
+#define   NV50TCL_VP_REG_COL0_Z_MASK                                                   0x00ff0000
+#define   NV50TCL_VP_REG_COL0_W_SHIFT                                                  24
+#define   NV50TCL_VP_REG_COL0_W_MASK                                                   0xff000000
+#define  NV50TCL_POLYGON_STIPPLE_PATTERN(x)                                            (0x00001700+((x)*4))
+#define  NV50TCL_POLYGON_STIPPLE_PATTERN__SIZE                                         0x00000020
+#define  NV50TCL_CULL_FACE_ENABLE                                                      0x00001918
+#define  NV50TCL_FRONT_FACE                                                            0x0000191c
+#define   NV50TCL_FRONT_FACE_CW                                                                0x00000900
+#define   NV50TCL_FRONT_FACE_CCW                                                       0x00000901
+#define  NV50TCL_CULL_FACE                                                             0x00001920
+#define   NV50TCL_CULL_FACE_FRONT                                                      0x00000404
+#define   NV50TCL_CULL_FACE_BACK                                                       0x00000405
+#define   NV50TCL_CULL_FACE_FRONT_AND_BACK                                             0x00000408
+#define  NV50TCL_LOGIC_OP_ENABLE                                                       0x000019c4
+#define  NV50TCL_LOGIC_OP                                                              0x000019c8
+#define   NV50TCL_LOGIC_OP_CLEAR                                                       0x00001500
+#define   NV50TCL_LOGIC_OP_AND                                                         0x00001501
+#define   NV50TCL_LOGIC_OP_AND_REVERSE                                                 0x00001502
+#define   NV50TCL_LOGIC_OP_COPY                                                                0x00001503
+#define   NV50TCL_LOGIC_OP_AND_INVERTED                                                        0x00001504
+#define   NV50TCL_LOGIC_OP_NOOP                                                                0x00001505
+#define   NV50TCL_LOGIC_OP_XOR                                                         0x00001506
+#define   NV50TCL_LOGIC_OP_OR                                                          0x00001507
+#define   NV50TCL_LOGIC_OP_NOR                                                         0x00001508
+#define   NV50TCL_LOGIC_OP_EQUIV                                                       0x00001509
+#define   NV50TCL_LOGIC_OP_INVERT                                                      0x0000150a
+#define   NV50TCL_LOGIC_OP_OR_REVERSE                                                  0x0000150b
+#define   NV50TCL_LOGIC_OP_COPY_INVERTED                                               0x0000150c
+#define   NV50TCL_LOGIC_OP_OR_INVERTED                                                 0x0000150d
+#define   NV50TCL_LOGIC_OP_NAND                                                                0x0000150e
+#define   NV50TCL_LOGIC_OP_SET                                                         0x0000150f
+#define  NV50TCL_CLEAR_BUFFERS                                                         0x000019d0
+#define  NV50TCL_COLOR_MASK(x)                                                         (0x00001a00+((x)*4))
+#define  NV50TCL_COLOR_MASK__SIZE                                                      0x00000008
+#define   NV50TCL_COLOR_MASK_R_SHIFT                                                   0
+#define   NV50TCL_COLOR_MASK_R_MASK                                                    0x0000000f
+#define   NV50TCL_COLOR_MASK_G_SHIFT                                                   4
+#define   NV50TCL_COLOR_MASK_G_MASK                                                    0x000000f0
+#define   NV50TCL_COLOR_MASK_B_SHIFT                                                   8
+#define   NV50TCL_COLOR_MASK_B_MASK                                                    0x00000f00
+#define   NV50TCL_COLOR_MASK_A_SHIFT                                                   12
+#define   NV50TCL_COLOR_MASK_A_MASK                                                    0x0000f000
+
+
+#define NV50_COMPUTE                                                                   0x000050c0
+
+#define  NV50_COMPUTE_DMA_UNK0                                                         0x000001a0
+#define  NV50_COMPUTE_DMA_STATUS                                                       0x000001a4
+#define  NV50_COMPUTE_DMA_UNK1                                                         0x000001b8
+#define  NV50_COMPUTE_DMA_UNK2                                                         0x000001bc
+#define  NV50_COMPUTE_DMA_UNK3                                                         0x000001c0
+#define  NV50_COMPUTE_UNK4_HIGH                                                                0x00000210
+#define  NV50_COMPUTE_UNK4_LOW                                                         0x00000214
+#define  NV50_COMPUTE_UNK5_HIGH                                                                0x00000218
+#define  NV50_COMPUTE_UNK5_LOW                                                         0x0000021c
+#define  NV50_COMPUTE_UNK6_HIGH                                                                0x00000294
+#define  NV50_COMPUTE_UNK6_LOW                                                         0x00000298
+#define  NV50_COMPUTE_CONST_BASE_HIGH                                                  0x000002a4
+#define  NV50_COMPUTE_CONST_BASE_LO                                                    0x000002a8
+#define  NV50_COMPUTE_CONST_SIZE_SEG                                                   0x000002ac
+#define  NV50_COMPUTE_REG_COUNT                                                                0x000002c0
+#define  NV50_COMPUTE_STATUS_HIGH                                                      0x00000310
+#define  NV50_COMPUTE_STATUS_LOW                                                       0x00000314
+#define  NV50_COMPUTE_EXECUTE                                                          0x0000031c
+#define  NV50_COMPUTE_USER_PARAM_COUNT                                                 0x00000374
+#define  NV50_COMPUTE_GRIDDIM_YX                                                       0x000003a4
+#define  NV50_COMPUTE_SHARED_SIZE                                                      0x000003a8
+#define  NV50_COMPUTE_BLOCKDIM_YX                                                      0x000003ac
+#define  NV50_COMPUTE_BLOCKDIM_Z                                                       0x000003b0
+#define  NV50_COMPUTE_CALL_ADDRESS                                                     0x000003b4
+#define  NV50_COMPUTE_GLOBAL_BASE_HIGH(x)                                              (0x00000400+((x)*32))
+#define  NV50_COMPUTE_GLOBAL_BASE_HIGH__SIZE                                           0x00000010
+#define  NV50_COMPUTE_GLOBAL_BASE_LOW(x)                                               (0x00000404+((x)*32))
+#define  NV50_COMPUTE_GLOBAL_BASE_LOW__SIZE                                            0x00000010
+#define  NV50_COMPUTE_GLOBAL_LIMIT_HIGH(x)                                             (0x00000408+((x)*32))
+#define  NV50_COMPUTE_GLOBAL_LIMIT_HIGH__SIZE                                          0x00000010
+#define  NV50_COMPUTE_GLOBAL_LIMIT_LOW(x)                                              (0x0000040c+((x)*32))
+#define  NV50_COMPUTE_GLOBAL_LIMIT_LOW__SIZE                                           0x00000010
+#define  NV50_COMPUTE_GLOBAL_UNK(x)                                                    (0x00000410+((x)*32))
+#define  NV50_COMPUTE_GLOBAL_UNK__SIZE                                                 0x00000010
+#define  NV50_COMPUTE_USER_PARAM(x)                                                    (0x00000600+((x)*4))
+#define  NV50_COMPUTE_USER_PARAM__SIZE                                                 0x00000040
+
+
+#define NV54TCL                                                                                0x00008297
+
+
+
+#endif /* NOUVEAU_REG_H */
diff --git a/src/gallium/drivers/nouveau/nouveau_device.h b/src/gallium/drivers/nouveau/nouveau_device.h
new file mode 100644 (file)
index 0000000..e25e89f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_DEVICE_H__
+#define __NOUVEAU_DEVICE_H__
+
+struct nouveau_device {
+       unsigned chipset;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_gldefs.h b/src/gallium/drivers/nouveau/nouveau_gldefs.h
new file mode 100644 (file)
index 0000000..e1015c9
--- /dev/null
@@ -0,0 +1,196 @@
+#ifndef __NOUVEAU_GLDEFS_H__
+#define __NOUVEAU_GLDEFS_H__
+
+static INLINE unsigned
+nvgl_blend_func(unsigned factor)
+{
+       switch (factor) {
+       case PIPE_BLENDFACTOR_ZERO:
+               return 0x0000;
+       case PIPE_BLENDFACTOR_ONE:
+               return 0x0001;
+       case PIPE_BLENDFACTOR_SRC_COLOR:
+               return 0x0300;
+       case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+               return 0x0301;
+       case PIPE_BLENDFACTOR_SRC_ALPHA:
+               return 0x0302;
+       case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+               return 0x0303;
+       case PIPE_BLENDFACTOR_DST_ALPHA:
+               return 0x0304;
+       case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+               return 0x0305;
+       case PIPE_BLENDFACTOR_DST_COLOR:
+               return 0x0306;
+       case PIPE_BLENDFACTOR_INV_DST_COLOR:
+               return 0x0307;
+       case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+               return 0x0308;
+       case PIPE_BLENDFACTOR_CONST_COLOR:
+               return 0x8001;
+       case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+               return 0x8002;
+       case PIPE_BLENDFACTOR_CONST_ALPHA:
+               return 0x8003;
+       case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+               return 0x8004;
+       default:
+               return 0x0000;
+       }
+}
+
+static INLINE unsigned
+nvgl_blend_eqn(unsigned func)
+{
+       switch (func) {
+       case PIPE_BLEND_ADD:
+               return 0x8006;
+       case PIPE_BLEND_MIN:
+               return 0x8007;
+       case PIPE_BLEND_MAX:
+               return 0x8008;
+       case PIPE_BLEND_SUBTRACT:
+               return 0x800a;
+       case PIPE_BLEND_REVERSE_SUBTRACT:
+               return 0x800b;
+       default:
+               return 0x8006;
+       }
+}
+
+static INLINE unsigned
+nvgl_logicop_func(unsigned func)
+{
+       switch (func) {
+       case PIPE_LOGICOP_CLEAR:
+               return 0x1500;
+       case PIPE_LOGICOP_NOR:
+               return 0x1508;
+       case PIPE_LOGICOP_AND_INVERTED:
+               return 0x1504;
+       case PIPE_LOGICOP_COPY_INVERTED:
+               return 0x150c;
+       case PIPE_LOGICOP_AND_REVERSE:
+               return 0x1502;
+       case PIPE_LOGICOP_INVERT:
+               return 0x150a;
+       case PIPE_LOGICOP_XOR:
+               return 0x1506;
+       case PIPE_LOGICOP_NAND:
+               return 0x150e;
+       case PIPE_LOGICOP_AND:
+               return 0x1501;
+       case PIPE_LOGICOP_EQUIV:
+               return 0x1509;
+       case PIPE_LOGICOP_NOOP:
+               return 0x1505;
+       case PIPE_LOGICOP_OR_INVERTED:
+               return 0x150d;
+       case PIPE_LOGICOP_COPY:
+               return 0x1503;
+       case PIPE_LOGICOP_OR_REVERSE:
+               return 0x150b;
+       case PIPE_LOGICOP_OR:
+               return 0x1507;
+       case PIPE_LOGICOP_SET:
+               return 0x150f;
+       default:
+               return 0x1505;
+       }
+}
+
+static INLINE unsigned
+nvgl_comparison_op(unsigned op)
+{
+       switch (op) {
+       case PIPE_FUNC_NEVER:
+               return 0x0200;
+       case PIPE_FUNC_LESS:
+               return 0x0201;
+       case PIPE_FUNC_EQUAL:
+               return 0x0202;
+       case PIPE_FUNC_LEQUAL:
+               return 0x0203;
+       case PIPE_FUNC_GREATER:
+               return 0x0204;
+       case PIPE_FUNC_NOTEQUAL:
+               return 0x0205;
+       case PIPE_FUNC_GEQUAL:
+               return 0x0206;
+       case PIPE_FUNC_ALWAYS:
+               return 0x0207;
+       default:
+               return 0x0207;
+       }
+}
+
+static INLINE unsigned
+nvgl_polygon_mode(unsigned mode)
+{
+       switch (mode) {
+       case PIPE_POLYGON_MODE_POINT:
+               return 0x1b00;
+       case PIPE_POLYGON_MODE_LINE:
+               return 0x1b01;
+       case PIPE_POLYGON_MODE_FILL:
+               return 0x1b02;
+       default:
+               return 0x1b02;
+       }
+}
+
+static INLINE unsigned
+nvgl_stencil_op(unsigned op)
+{
+       switch (op) {
+       case PIPE_STENCIL_OP_ZERO:
+               return 0x0000;
+       case PIPE_STENCIL_OP_INVERT:
+               return 0x150a;
+       case PIPE_STENCIL_OP_KEEP:
+               return 0x1e00;
+       case PIPE_STENCIL_OP_REPLACE:
+               return 0x1e01;
+       case PIPE_STENCIL_OP_INCR:
+               return 0x1e02;
+       case PIPE_STENCIL_OP_DECR:
+               return 0x1e03;
+       case PIPE_STENCIL_OP_INCR_WRAP:
+               return 0x8507;
+       case PIPE_STENCIL_OP_DECR_WRAP:
+               return 0x8508;
+       default:
+               return 0x1e00;
+       }
+}
+
+static INLINE unsigned
+nvgl_primitive(unsigned prim) {
+       switch (prim) {
+       case PIPE_PRIM_POINTS:
+               return 0x0001;
+       case PIPE_PRIM_LINES:
+               return 0x0002;
+       case PIPE_PRIM_LINE_LOOP:
+               return 0x0003;
+       case PIPE_PRIM_LINE_STRIP:
+               return 0x0004;
+       case PIPE_PRIM_TRIANGLES:
+               return 0x0005;
+       case PIPE_PRIM_TRIANGLE_STRIP:
+               return 0x0006;
+       case PIPE_PRIM_TRIANGLE_FAN:
+               return 0x0007;
+       case PIPE_PRIM_QUADS:
+               return 0x0008;
+       case PIPE_PRIM_QUAD_STRIP:
+               return 0x0009;
+       case PIPE_PRIM_POLYGON:
+               return 0x000a;
+       default:
+               return 0x0001;
+       }
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_grobj.h b/src/gallium/drivers/nouveau/nouveau_grobj.h
new file mode 100644 (file)
index 0000000..8f5abf9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_GROBJ_H__
+#define __NOUVEAU_GROBJ_H__
+
+#include "nouveau_channel.h"
+
+struct nouveau_grobj {
+       struct nouveau_channel *channel;
+       int grclass;
+       uint32_t handle;
+       int subc;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_notifier.h b/src/gallium/drivers/nouveau/nouveau_notifier.h
new file mode 100644 (file)
index 0000000..35adde1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_NOTIFIER_H__
+#define __NOUVEAU_NOTIFIER_H__
+
+#define NV_NOTIFIER_SIZE                                                      32
+#define NV_NOTIFY_TIME_0                                              0x00000000
+#define NV_NOTIFY_TIME_1                                              0x00000004
+#define NV_NOTIFY_RETURN_VALUE                                        0x00000008
+#define NV_NOTIFY_STATE                                               0x0000000C
+#define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000
+#define NV_NOTIFY_STATE_STATUS_SHIFT                                          24
+#define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00
+#define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01
+#define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF
+#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0
+
+struct nouveau_notifier {
+       struct nouveau_channel *channel;
+       uint32_t handle;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h
new file mode 100644 (file)
index 0000000..54ef1c1
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __NOUVEAU_PUSH_H__
+#define __NOUVEAU_PUSH_H__
+
+#include "nouveau/nouveau_winsys.h"
+
+#ifndef NOUVEAU_PUSH_CONTEXT
+#error undefined push context
+#endif
+
+#define OUT_RING(data) do {                                                    \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       (*pc->nvws->channel->pushbuf->cur++) = (data);                         \
+} while(0)
+
+#define OUT_RINGp(src,size) do {                                               \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       memcpy(pc->nvws->channel->pushbuf->cur, (src), (size) * 4);            \
+       pc->nvws->channel->pushbuf->cur += (size);                             \
+} while(0)
+
+#define OUT_RINGf(data) do {                                                   \
+       union { float v; uint32_t u; } c;                                      \
+       c.v = (data);                                                          \
+       OUT_RING(c.u);                                                         \
+} while(0)
+
+#define BEGIN_RING(obj,mthd,size) do {                                         \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       if (pc->nvws->channel->pushbuf->remaining < ((size) + 1))              \
+               pc->nvws->push_flush(pc->nvws, ((size) + 1), NULL);            \
+       OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd));             \
+       pc->nvws->channel->pushbuf->remaining -= ((size) + 1);                 \
+} while(0)
+
+#define BEGIN_RING_NI(obj,mthd,size) do {                                      \
+       BEGIN_RING(obj, (mthd) | 0x40000000, (size));                          \
+} while(0)
+
+#define FIRE_RING(fence) do {                                                  \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       pc->nvws->push_flush(pc->nvws, 0, fence);                              \
+} while(0)
+
+#define OUT_RELOC(bo,data,flags,vor,tor) do {                                  \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       pc->nvws->push_reloc(pc->nvws, pc->nvws->channel->pushbuf->cur++,      \
+                            (bo), (data), (flags), (vor), (tor));             \
+} while(0)
+
+/* Raw data + flags depending on FB/TT buffer */
+#define OUT_RELOCd(bo,data,flags,vor,tor) do {                                 \
+       OUT_RELOC((bo), (data), (flags) | NOUVEAU_BO_OR, (vor), (tor));        \
+} while(0)
+
+/* FB/TT object handle */
+#define OUT_RELOCo(bo,flags) do {                                              \
+       OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR,                            \
+                 pc->nvws->channel->vram->handle,                             \
+                 pc->nvws->channel->gart->handle);                            \
+} while(0)
+
+/* Low 32-bits of offset */
+#define OUT_RELOCl(bo,delta,flags) do {                                        \
+       OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_LOW, 0, 0);              \
+} while(0)
+
+/* High 32-bits of offset */
+#define OUT_RELOCh(bo,delta,flags) do {                                        \
+       OUT_RELOC((bo), (delta), (flags) | NOUVEAU_BO_HIGH, 0, 0);             \
+} while(0)
+
+/* A reloc which'll recombine into a NV_DMA_METHOD packet header */
+#define OUT_RELOCm(bo, flags, obj, mthd, size) do {                            \
+       NOUVEAU_PUSH_CONTEXT(pc);                                              \
+       if (pc->nvws->channel->pushbuf->remaining < ((size) + 1))              \
+               pc->nvws->push_flush(pc->nvws->channel, ((size) + 1), NULL);   \
+       OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd),      \
+                  (flags), 0, 0);                                             \
+       pc->nvws->channel->pushbuf->remaining -= ((size) + 1);                 \
+} while(0)
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_pushbuf.h b/src/gallium/drivers/nouveau/nouveau_pushbuf.h
new file mode 100644 (file)
index 0000000..1909765
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_PUSHBUF_H__
+#define __NOUVEAU_PUSHBUF_H__
+
+struct nouveau_pushbuf {
+       struct nouveau_channel *channel;
+       unsigned remaining;
+       uint32_t *cur;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_resource.h b/src/gallium/drivers/nouveau/nouveau_resource.h
new file mode 100644 (file)
index 0000000..1af7961
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_RESOURCE_H__
+#define __NOUVEAU_RESOURCE_H__
+
+struct nouveau_resource {
+       struct nouveau_resource *prev;
+       struct nouveau_resource *next;
+
+       int in_use;
+       void *priv;
+
+       unsigned int start;
+       unsigned int size;
+};
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
new file mode 100644 (file)
index 0000000..998ec2d
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef __NOUVEAU_STATEOBJ_H__
+#define __NOUVEAU_STATEOBJ_H__
+
+#include "pipe/p_util.h"
+#include "pipe/p_debug.h"
+
+struct nouveau_stateobj_reloc {
+       struct pipe_buffer *bo;
+
+       unsigned offset;
+       unsigned packet;
+
+       unsigned data;
+       unsigned flags;
+       unsigned vor;
+       unsigned tor;
+};
+
+struct nouveau_stateobj {
+       int refcount;
+
+       unsigned *push;
+       struct nouveau_stateobj_reloc *reloc;
+
+       unsigned *cur;
+       unsigned cur_packet;
+       unsigned cur_reloc;
+};
+
+static INLINE struct nouveau_stateobj *
+so_new(unsigned push, unsigned reloc)
+{
+       struct nouveau_stateobj *so;
+
+       so = MALLOC(sizeof(struct nouveau_stateobj));
+       so->refcount = 0;
+       so->push = MALLOC(sizeof(unsigned) * push);
+       so->reloc = MALLOC(sizeof(struct nouveau_stateobj_reloc) * reloc);
+
+       so->cur = so->push;
+       so->cur_reloc = so->cur_packet = 0;
+
+       return so;
+}
+
+static INLINE void
+so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso)
+{
+       struct nouveau_stateobj *so = *pso;
+
+       if (ref) {
+               ref->refcount++;
+       }
+
+       if (so && --so->refcount <= 0) {
+               free(so->push);
+               free(so->reloc);
+               free(so);
+       }
+
+       *pso = ref;
+}
+
+static INLINE void
+so_data(struct nouveau_stateobj *so, unsigned data)
+{
+       (*so->cur++) = (data);
+       so->cur_packet += 4;
+}
+
+static INLINE void
+so_datap(struct nouveau_stateobj *so, unsigned *data, unsigned size)
+{
+       so->cur_packet += (4 * size);
+       while (size--)
+               (*so->cur++) = (*data++);
+}
+
+static INLINE void
+so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
+         unsigned mthd, unsigned size)
+{
+       so->cur_packet = (gr->subc << 13) | (1 << 18) | (mthd - 4);
+       so_data(so, (gr->subc << 13) | (size << 18) | mthd);
+}
+
+static INLINE void
+so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo,
+        unsigned data, unsigned flags, unsigned vor, unsigned tor)
+{
+       struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
+       
+       r->bo = bo;
+       r->offset = so->cur - so->push;
+       r->packet = so->cur_packet;
+       r->data = data;
+       r->flags = flags;
+       r->vor = vor;
+       r->tor = tor;
+       so_data(so, data);
+}
+
+static INLINE void
+so_dump(struct nouveau_stateobj *so)
+{
+       unsigned i, nr = so->cur - so->push;
+
+       for (i = 0; i < nr; i++)
+               debug_printf("+0x%04x: 0x%08x\n", i, so->push[i]);
+}
+
+static INLINE void
+so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+{
+       struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+       unsigned nr, i;
+
+       nr = so->cur - so->push;
+       if (pb->remaining < nr)
+               nvws->push_flush(nvws, nr, NULL);
+       pb->remaining -= nr;
+
+       memcpy(pb->cur, so->push, nr * 4);
+       for (i = 0; i < so->cur_reloc; i++) {
+               struct nouveau_stateobj_reloc *r = &so->reloc[i];
+
+               nvws->push_reloc(nvws, pb->cur + r->offset, r->bo,
+                                r->data, r->flags, r->vor, r->tor);
+       }
+       pb->cur += nr;
+}
+
+static INLINE void
+so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+{
+       struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+       unsigned i;
+
+       if (!so)
+               return;
+
+       i = so->cur_reloc << 1;
+       if (nvws->channel->pushbuf->remaining < i)
+               nvws->push_flush(nvws, i, NULL);
+       nvws->channel->pushbuf->remaining -= i;
+
+       for (i = 0; i < so->cur_reloc; i++) {
+               struct nouveau_stateobj_reloc *r = &so->reloc[i];
+
+               nvws->push_reloc(nvws, pb->cur++, r->bo, r->packet,
+                                (r->flags &
+                                 (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) |
+                                NOUVEAU_BO_DUMMY, 0, 0);
+               nvws->push_reloc(nvws, pb->cur++, r->bo, r->data,
+                                r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor);
+       }
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h
new file mode 100644 (file)
index 0000000..c92041e
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __NOUVEAU_UTIL_H__
+#define __NOUVEAU_UTIL_H__
+
+/* Determine how many vertices can be pushed into the command stream.
+ * Where the remaining space isn't large enough to represent all verices,
+ * split the buffer at primitive boundaries.
+ *
+ * Returns a count of vertices that can be rendered, and an index to
+ * restart drawing at after a flush.
+ */
+static INLINE unsigned
+nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp,
+                  unsigned mode, unsigned start, unsigned count,
+                  unsigned *restart)
+{
+       int max, adj = 0;
+
+       max  = remaining - overhead;
+       if (max < 0)
+               return 0;
+
+       max *= vpp;
+       if (max >= count)
+               return count;
+
+       switch (mode) {
+       case PIPE_PRIM_POINTS:
+               break;
+       case PIPE_PRIM_LINES:
+               max = max & 1;
+               break;
+       case PIPE_PRIM_TRIANGLES:
+               max = max - (max % 3);
+               break;
+       case PIPE_PRIM_QUADS:
+               max = max & 3;
+               break;
+       case PIPE_PRIM_LINE_LOOP:
+       case PIPE_PRIM_LINE_STRIP:
+               if (max < 2)
+                       max = 0;
+               adj = 1;
+               break;
+       case PIPE_PRIM_POLYGON:
+       case PIPE_PRIM_TRIANGLE_STRIP:
+       case PIPE_PRIM_TRIANGLE_FAN:
+               if (max < 3)
+                       max = 0;
+               adj = 2;
+               break;
+       case PIPE_PRIM_QUAD_STRIP:
+               if (max < 4)
+                       max = 0;
+               adj = 3;
+               break;
+       default:
+               assert(0);
+       }
+
+       *restart = start + max - adj;
+       return max;
+}
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
new file mode 100644 (file)
index 0000000..48feeba
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef NOUVEAU_WINSYS_H
+#define NOUVEAU_WINSYS_H
+
+#include <stdint.h>
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+
+#include "nouveau/nouveau_bo.h"
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_class.h"
+#include "nouveau/nouveau_device.h"
+#include "nouveau/nouveau_grobj.h"
+#include "nouveau/nouveau_notifier.h"
+#include "nouveau/nouveau_resource.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+#define NOUVEAU_CAP_HW_VTXBUF (0xbeef0000)
+#define NOUVEAU_CAP_HW_IDXBUF (0xbeef0001)
+
+#define NOUVEAU_BUFFER_USAGE_TEXTURE (1 << 16)
+#define NOUVEAU_BUFFER_USAGE_ZETA    (1 << 17)
+
+struct nouveau_winsys {
+       struct nouveau_context *nv;
+
+       struct nouveau_channel *channel;
+
+       int  (*res_init)(struct nouveau_resource **heap, unsigned start,
+                        unsigned size);
+       int  (*res_alloc)(struct nouveau_resource *heap, int size, void *priv,
+                         struct nouveau_resource **);
+       void (*res_free)(struct nouveau_resource **);
+
+       int  (*push_reloc)(struct nouveau_winsys *, void *ptr,
+                          struct pipe_buffer *, uint32_t data,
+                          uint32_t flags, uint32_t vor, uint32_t tor);
+       int  (*push_flush)(struct nouveau_winsys *, unsigned size,
+                          struct pipe_fence_handle **fence);
+                              
+       int       (*grobj_alloc)(struct nouveau_winsys *, int grclass,
+                                struct nouveau_grobj **);
+       void      (*grobj_free)(struct nouveau_grobj **);
+
+       int       (*notifier_alloc)(struct nouveau_winsys *, int count,
+                                   struct nouveau_notifier **);
+       void      (*notifier_free)(struct nouveau_notifier **);
+       void      (*notifier_reset)(struct nouveau_notifier *, int id);
+       uint32_t  (*notifier_status)(struct nouveau_notifier *, int id);
+       uint32_t  (*notifier_retval)(struct nouveau_notifier *, int id);
+       int       (*notifier_wait)(struct nouveau_notifier *, int id,
+                                  int status, int timeout);
+
+       int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *,
+                           unsigned, unsigned, struct pipe_surface *,
+                           unsigned, unsigned, unsigned, unsigned);
+       int (*surface_fill)(struct nouveau_winsys *, struct pipe_surface *,
+                           unsigned, unsigned, unsigned, unsigned, unsigned);
+};
+
+extern struct pipe_screen *
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv04_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv10_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv30_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv40_create(struct pipe_screen *, unsigned pctx_id);
+
+extern struct pipe_screen *
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv50_create(struct pipe_screen *, unsigned pctx_id);
+
+#endif
diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile
new file mode 100644 (file)
index 0000000..5ea51a2
--- /dev/null
@@ -0,0 +1,28 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv04
+
+DRIVER_SOURCES = \
+       nv04_clear.c \
+       nv04_context.c \
+       nv04_fragprog.c \
+       nv04_fragtex.c \
+       nv04_miptree.c \
+       nv04_prim_vbuf.c \
+       nv04_screen.c \
+       nv04_state.c \
+       nv04_state_emit.c \
+       nv04_surface.c \
+       nv04_vbo.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv04/nv04_clear.c b/src/gallium/drivers/nv04/nv04_clear.c
new file mode 100644 (file)
index 0000000..01cacd3
--- /dev/null
@@ -0,0 +1,12 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv04_context.h"
+
+void
+nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+          unsigned clearValue)
+{
+       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+}
diff --git a/src/gallium/drivers/nv04/nv04_context.c b/src/gallium/drivers/nv04/nv04_context.c
new file mode 100644 (file)
index 0000000..852a8ed
--- /dev/null
@@ -0,0 +1,107 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_util.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static void
+nv04_flush(struct pipe_context *pipe, unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       draw_flush(nv04->draw);
+
+       FIRE_RING(fence);
+}
+
+static void
+nv04_destroy(struct pipe_context *pipe)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       if (nv04->draw)
+               draw_destroy(nv04->draw);
+
+       FREE(nv04);
+}
+
+static void
+nv04_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+static boolean
+nv04_init_hwctx(struct nv04_context *nv04)
+{
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOTIFY, 1);
+       OUT_RING(0);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_NOP, 1);
+       OUT_RING(0);
+
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+       OUT_RING(0x40182800);
+//     OUT_RING(1<<20/*no cull*/);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1);
+//     OUT_RING(0x24|(1<<6)|(1<<8));
+       OUT_RING(0x120001a4);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FORMAT, 1);
+       OUT_RING(0x332213a1);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FILTER, 1);
+       OUT_RING(0x11001010);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_COLORKEY, 1);
+       OUT_RING(0x0);
+//     BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 1);
+//     OUT_RING(SCREEN_OFFSET);
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_FOGCOLOR, 1);
+       OUT_RING(0xff000000);
+
+
+
+       FIRE_RING (NULL);
+       return TRUE;
+}
+
+struct pipe_context *
+nv04_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+       struct nv04_screen *screen = nv04_screen(pscreen);
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv04_context *nv04;
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nv04 = CALLOC(1, sizeof(struct nv04_context));
+       if (!nv04)
+               return NULL;
+       nv04->screen = screen;
+       nv04->pctx_id = pctx_id;
+
+       nv04->nvws = nvws;
+
+       nv04->pipe.winsys = ws;
+       nv04->pipe.screen = pscreen;
+       nv04->pipe.destroy = nv04_destroy;
+       nv04->pipe.set_edgeflags = nv04_set_edgeflags;
+       nv04->pipe.draw_arrays = nv04_draw_arrays;
+       nv04->pipe.draw_elements = nv04_draw_elements;
+       nv04->pipe.clear = nv04_clear;
+       nv04->pipe.flush = nv04_flush;
+
+       nv04_init_surface_functions(nv04);
+       nv04_init_state_functions(nv04);
+
+       nv04->draw = draw_create();
+       assert(nv04->draw);
+       draw_wide_point_threshold(nv04->draw, 0.0);
+       draw_wide_line_threshold(nv04->draw, 0.0);
+       draw_enable_line_stipple(nv04->draw, FALSE);
+       draw_enable_point_sprites(nv04->draw, FALSE);
+       draw_set_rasterize_stage(nv04->draw, nv04_draw_vbuf_stage(nv04));
+
+       nv04_init_hwctx(nv04);
+
+       return &nv04->pipe;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_context.h b/src/gallium/drivers/nv04/nv04_context.h
new file mode 100644 (file)
index 0000000..5ba1d4e
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __NV04_CONTEXT_H__
+#define __NV04_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \
+       struct nv04_screen *ctx = nv04->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv04_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+
+#include "nv04_screen.h"
+
+#define NV04_NEW_VERTPROG      (1 << 1)
+#define NV04_NEW_FRAGPROG      (1 << 2)
+#define NV04_NEW_BLEND         (1 << 3)
+#define NV04_NEW_RAST          (1 << 4)
+#define NV04_NEW_CONTROL       (1 << 5)
+#define NV04_NEW_VIEWPORT      (1 << 6)
+#define NV04_NEW_SAMPLER       (1 << 7)
+
+struct nv04_context {
+       struct pipe_context pipe;
+
+       struct nouveau_winsys *nvws;
+       struct nv04_screen *screen;
+       unsigned pctx_id;
+
+       struct draw_context *draw;
+
+       int chipset;
+       struct nouveau_notifier *sync;
+
+       uint32_t dirty;
+
+       struct nv04_blend_state *blend;
+       struct nv04_sampler_state *sampler[PIPE_MAX_SAMPLERS];
+       struct nv04_fragtex_state fragtex;
+       struct nv04_rasterizer_state *rast;
+       struct nv04_depth_stencil_alpha_state *dsa;
+
+       struct nv04_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+       unsigned dirty_samplers;
+       unsigned fp_samplers;
+       unsigned vp_samplers;
+
+       uint32_t rt_enable;
+       struct pipe_buffer *rt[4];
+       struct pipe_buffer *zeta;
+
+       struct {
+               struct pipe_buffer *buffer;
+               uint32_t format;
+       } tex[16];
+
+       unsigned vb_enable;
+       struct {
+               struct pipe_buffer *buffer;
+               unsigned delta;
+       } vb[16];
+
+       struct vertex_info vertex_info;
+       struct {
+       
+               struct nouveau_resource *exec_heap;
+               struct nouveau_resource *data_heap;
+
+               struct nv04_vertex_program *active;
+
+               struct nv04_vertex_program *current;
+               struct pipe_buffer *constant_buf;
+       } vertprog;
+
+       struct {
+               struct nv04_fragment_program *active;
+
+               struct nv04_fragment_program *current;
+               struct pipe_buffer *constant_buf;
+       } fragprog;
+
+       struct pipe_vertex_buffer  vertex_buffer[PIPE_MAX_ATTRIBS];
+       unsigned num_vertex_buffers;
+       unsigned num_vertex_elements;
+
+       struct pipe_viewport_state viewport;
+};
+
+static INLINE struct nv04_context *
+nv04_context(struct pipe_context *pipe)
+{
+       return (struct nv04_context *)pipe;
+}
+
+extern void nv04_init_state_functions(struct nv04_context *nv04);
+extern void nv04_init_surface_functions(struct nv04_context *nv04);
+extern void nv04_init_miptree_functions(struct pipe_screen *screen);
+
+/* nv04_clear.c */
+extern void nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+                      unsigned clearValue);
+
+/* nv04_draw.c */
+extern struct draw_stage *nv04_draw_render_stage(struct nv04_context *nv04);
+
+/* nv04_fragprog.c */
+extern void nv04_fragprog_bind(struct nv04_context *,
+                              struct nv04_fragment_program *);
+extern void nv04_fragprog_destroy(struct nv04_context *,
+                                 struct nv04_fragment_program *);
+
+/* nv04_fragtex.c */
+extern void nv04_fragtex_bind(struct nv04_context *);
+
+/* nv04_prim_vbuf.c */
+struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 );
+
+/* nv04_state.c and friends */
+extern void nv04_emit_hw_state(struct nv04_context *nv04);
+extern void nv04_state_tex_update(struct nv04_context *nv04);
+
+/* nv04_vbo.c */
+extern boolean nv04_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+extern boolean nv04_draw_elements( struct pipe_context *pipe,
+                    struct pipe_buffer *indexBuffer,
+                    unsigned indexSize,
+                    unsigned prim, unsigned start, unsigned count);
+
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_fragprog.c b/src/gallium/drivers/nv04/nv04_fragprog.c
new file mode 100644 (file)
index 0000000..11f4360
--- /dev/null
@@ -0,0 +1,22 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv04_context.h"
+
+void
+nv04_fragprog_bind(struct nv04_context *nv04, struct nv04_fragment_program *fp)
+{
+}
+
+void
+nv04_fragprog_destroy(struct nv04_context *nv04,
+                     struct nv04_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_fragtex.c b/src/gallium/drivers/nv04/nv04_fragtex.c
new file mode 100644 (file)
index 0000000..3db673c
--- /dev/null
@@ -0,0 +1,100 @@
+#include "nv04_context.h"
+
+static INLINE int log2i(int i)
+{
+       int r = 0;
+
+       if (i & 0xffff0000) {
+               i >>= 16;
+               r += 16;
+       }
+       if (i & 0x0000ff00) {
+               i >>= 8;
+               r += 8;
+       }
+       if (i & 0x000000f0) {
+               i >>= 4;
+               r += 4;
+       }
+       if (i & 0x0000000c) {
+               i >>= 2;
+               r += 2;
+       }
+       if (i & 0x00000002) {
+               r += 1;
+       }
+       return r;
+}
+
+#define _(m,tf)                                                                \
+{                                                                              \
+  PIPE_FORMAT_##m,                                                             \
+  NV04_DX5_TEXTURED_TRIANGLE_FORMAT_COLOR_##tf,                                               \
+}
+
+struct nv04_texture_format {
+       uint    pipe;
+       int     format;
+};
+
+static struct nv04_texture_format
+nv04_texture_formats[] = {
+       _(A8R8G8B8_UNORM, A8R8G8B8),
+       _(X8R8G8B8_UNORM, X8R8G8B8),
+       _(A1R5G5B5_UNORM, A1R5G5B5),
+       _(A4R4G4B4_UNORM, A4R4G4B4),
+       _(L8_UNORM,       Y8      ),
+       _(A8_UNORM,       Y8      ),
+};
+
+static uint32_t
+nv04_fragtex_format(uint pipe_format)
+{
+       struct nv04_texture_format *tf = nv04_texture_formats;
+       char fs[128];
+       int i;
+
+       for (i=0; i< sizeof(nv04_texture_formats)/sizeof(nv04_texture_formats[0]); i++) {
+               if (tf->pipe == pipe_format)
+                       return tf->format;
+               tf++;
+       }
+
+       pf_sprint_name(fs, pipe_format);
+       NOUVEAU_ERR("unknown texture format %s\n", fs);
+       return 0;
+}
+
+
+static void
+nv04_fragtex_build(struct nv04_context *nv04, int unit)
+{
+       struct nv04_miptree *nv04mt = nv04->tex_miptree[unit];
+       struct pipe_texture *pt = &nv04mt->base;
+
+       switch (pt->target) {
+       case PIPE_TEXTURE_2D:
+               break;
+       default:
+               NOUVEAU_ERR("Unknown target %d\n", pt->target);
+               return;
+       }
+
+       nv04->fragtex.format = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER 
+               | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER
+               | nv04_fragtex_format(pt->format)
+               | ( (pt->last_level + 1) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT )
+               | ( log2i(pt->width[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT )
+               | ( log2i(pt->height[0]) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT )
+               | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE
+               | NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE
+               ;
+}
+
+
+void
+nv04_fragtex_bind(struct nv04_context *nv04)
+{
+       nv04_fragtex_build(nv04, 0);
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c
new file mode 100644 (file)
index 0000000..97f6797
--- /dev/null
@@ -0,0 +1,138 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static void
+nv04_miptree_layout(struct nv04_miptree *nv04mt)
+{
+       struct pipe_texture *pt = &nv04mt->base;
+       uint width = pt->width[0], height = pt->height[0];
+       uint offset = 0;
+       int nr_faces, l, f;
+
+       nr_faces = 1;
+
+       for (l = 0; l <= pt->last_level; l++) {
+               pt->width[l] = width;
+               pt->height[l] = height;
+
+               pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+               pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+               
+               nv04mt->level[l].pitch = pt->width[0] * pt->block.size;
+               nv04mt->level[l].pitch = (nv04mt->level[l].pitch + 63) & ~63;
+
+               nv04mt->level[l].image_offset =
+                       CALLOC(nr_faces, sizeof(unsigned));
+
+               width  = MAX2(1, width  >> 1);
+               height = MAX2(1, height >> 1);
+
+       }
+
+       for (f = 0; f < nr_faces; f++) {
+               for (l = 0; l <= pt->last_level; l++) {
+                       nv04mt->level[l].image_offset[f] = offset;
+                       offset += nv04mt->level[l].pitch * pt->height[l];
+               }
+       }
+
+       nv04mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv04_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt)
+{
+       struct pipe_winsys *ws = screen->winsys;
+       struct nv04_miptree *mt;
+
+       mt = MALLOC(sizeof(struct nv04_miptree));
+       if (!mt)
+               return NULL;
+       mt->base = *pt;
+       mt->base.refcount = 1;
+       mt->base.screen = screen;
+
+       nv04_miptree_layout(mt);
+
+       mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL,
+                                          mt->total_size);
+       if (!mt->buffer) {
+               FREE(mt);
+               return NULL;
+       }
+       
+       return &mt->base;
+}
+
+static void
+nv04_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt)
+{
+       struct pipe_winsys *ws = screen->winsys;
+       struct pipe_texture *mt = *pt;
+
+       *pt = NULL;
+       if (--mt->refcount <= 0) {
+               struct nv04_miptree *nv04mt = (struct nv04_miptree *)mt;
+               int l;
+
+               pipe_buffer_reference(ws, &nv04mt->buffer, NULL);
+               for (l = 0; l <= mt->last_level; l++) {
+                       if (nv04mt->level[l].image_offset)
+                               FREE(nv04mt->level[l].image_offset);
+               }
+               FREE(nv04mt);
+       }
+}
+
+static struct pipe_surface *
+nv04_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv04_miptree *nv04mt = (struct nv04_miptree *)pt;
+       struct pipe_surface *ps;
+
+       ps = ws->surface_alloc(ws);
+       if (!ps)
+               return NULL;
+       pipe_buffer_reference(ws, &ps->buffer, nv04mt->buffer);
+       ps->format = pt->format;
+               ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->block = pt->block;
+       ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->nblocksx = pt->nblocksx[level];
+       ps->nblocksy = pt->nblocksy[level];
+       ps->stride = nv04mt->level[level].pitch;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               ps->offset = nv04mt->level[level].image_offset[face];
+       } else {
+               ps->offset = nv04mt->level[level].image_offset[0];
+       }
+
+       return ps;
+}
+
+static void
+nv04_miptree_surface_del(struct pipe_screen *pscreen,
+                        struct pipe_surface **psurface)
+{
+}
+
+void
+nv04_init_miptree_functions(struct pipe_screen *pscreen)
+{
+       pscreen->texture_create = nv04_miptree_create;
+       pscreen->texture_release = nv04_miptree_release;
+       pscreen->get_tex_surface = nv04_miptree_surface_new;
+       pscreen->tex_surface_release = nv04_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_prim_vbuf.c b/src/gallium/drivers/nv04/nv04_prim_vbuf.c
new file mode 100644 (file)
index 0000000..d3963d1
--- /dev/null
@@ -0,0 +1,308 @@
+
+#include "draw/draw_vbuf.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+#define VERTEX_SIZE 40
+#define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each
+
+/**
+ * Primitive renderer for nv04.
+ */
+struct nv04_vbuf_render {
+       struct vbuf_render base;
+
+       struct nv04_context *nv04;   
+
+       /** Vertex buffer */
+       unsigned char* buffer;
+
+       /** Vertex size in bytes */
+       unsigned vertex_size;
+
+       /** Current primitive */
+       unsigned prim;
+};
+
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv04_vbuf_render *
+nv04_vbuf_render( struct vbuf_render *render )
+{
+       assert(render);
+       return (struct nv04_vbuf_render *)render;
+}
+
+
+static const struct vertex_info *
+nv04_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+       struct nv04_context *nv04 = nv04_render->nv04;
+       return &nv04->vertex_info;
+}
+
+
+static void *
+nv04_vbuf_render_allocate_vertices( struct vbuf_render *render,
+               ushort vertex_size,
+               ushort nr_vertices )
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+       nv04_render->buffer = (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE);
+       assert(!nv04_render->buffer);
+
+       return nv04_render->buffer;
+}
+
+
+static boolean 
+nv04_vbuf_render_set_primitive( struct vbuf_render *render, 
+               unsigned prim )
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+       if (prim <= PIPE_PRIM_LINE_STRIP)
+               return FALSE;
+
+       nv04_render->prim = prim;
+       return TRUE;
+}
+
+static INLINE void nv04_2triangles(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5)
+{
+       BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
+       OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v3,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v4,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v5,8);
+       OUT_RING(0xFEDCBA);
+}
+
+static INLINE void nv04_1triangle(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2)
+{
+       BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
+       OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+       OUT_RING(0xFED);
+}
+
+static INLINE void nv04_1quad(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3)
+{
+       BEGIN_RING(fahrenheit,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
+       OUT_RINGp(buffer + VERTEX_SIZE * v0,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v1,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v2,8);
+       OUT_RINGp(buffer + VERTEX_SIZE * v3,8);
+       OUT_RING(0xFECEDC);
+}
+
+static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render * render, const ushort * indices, uint nr_indices)
+{
+       unsigned char* buffer = render->buffer;
+       struct nv04_context* nv04 = render->nv04;
+       int i;
+
+       for( i=0; i< nr_indices-5; i+=6)
+               nv04_2triangles(nv04,
+                               buffer,
+                               indices[i+0],
+                               indices[i+1],
+                               indices[i+2],
+                               indices[i+3],
+                               indices[i+4],
+                               indices[i+5]
+                              );
+       if (i != nr_indices)
+       {
+               nv04_1triangle(nv04,
+                               buffer,
+                               indices[i+0],
+                               indices[i+1],
+                               indices[i+2]
+                              );
+               i+=3;
+       }
+       if (i != nr_indices)
+               NOUVEAU_ERR("Houston, we have lost some vertices\n");
+}
+
+static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+       const uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
+       unsigned char* buffer = render->buffer;
+       struct nv04_context* nv04 = render->nv04;
+       int i,j;
+
+       for(i = 0; i<nr_indices; i+=14) 
+       {
+               int numvert = MIN2(16, nr_indices - i);
+               int numtri = numvert - 2;
+               if (numvert<3)
+                       break;
+
+               BEGIN_RING( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert*8 );
+               for(j = 0; j<numvert; j++)
+                       OUT_RINGp( buffer + VERTEX_SIZE * indices [i+j], 8 );
+
+               BEGIN_RING_NI( fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2 );
+               for(j = 0; j<numtri/2; j++ )
+                       OUT_RING(striptbl[j]);
+               if (numtri%2)
+                       OUT_RING(striptbl[numtri/2]&0xFFF);
+       }
+}
+
+static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+       const uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
+       unsigned char* buffer = render->buffer;
+       struct nv04_context* nv04 = render->nv04;
+       int i,j;
+
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8);
+       OUT_RINGp(buffer + VERTEX_SIZE * indices[0], 8);
+
+       for(i = 1; i<nr_indices; i+=14)
+       {
+               int numvert=MIN2(15, nr_indices - i);
+               int numtri=numvert-2;
+               if (numvert < 3)
+                       break;
+
+               BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert*8);
+
+               for(j=0;j<numvert;j++)
+                       OUT_RINGp( buffer + VERTEX_SIZE * indices[ i+j ], 8 );
+
+               BEGIN_RING_NI(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri+1)/2);
+               for(j = 0; j<numtri/2; j++)
+                       OUT_RING(fantbl[j]);
+               if (numtri%2)
+                       OUT_RING(fantbl[numtri/2]&0xFFF);
+       }
+}
+
+static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices)
+{
+       unsigned char* buffer = render->buffer;
+       struct nv04_context* nv04 = render->nv04;
+       int i;
+
+       for(i = 0; i < nr_indices; i += 4)
+               nv04_1quad(nv04,
+                               buffer,
+                               indices[i+0],
+                               indices[i+1],
+                               indices[i+2],
+                               indices[i+3]
+                              );
+}
+
+
+static void 
+nv04_vbuf_render_draw( struct vbuf_render *render,
+               const ushort *indices,
+               uint nr_indices)
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+       // emit the indices
+       switch( nv04_render->prim )
+       {
+               case PIPE_PRIM_TRIANGLES:
+                       nv04_vbuf_render_triangles_elts(nv04_render, indices, nr_indices);
+                       break;
+               case PIPE_PRIM_QUAD_STRIP:
+               case PIPE_PRIM_TRIANGLE_STRIP:
+                       nv04_vbuf_render_tri_strip_elts(nv04_render, indices, nr_indices);
+                       break;
+               case PIPE_PRIM_TRIANGLE_FAN:
+               case PIPE_PRIM_POLYGON:
+                       nv04_vbuf_render_tri_fan_elts(nv04_render, indices, nr_indices);
+                       break;
+               case PIPE_PRIM_QUADS:
+                       nv04_vbuf_render_quads_elts(nv04_render, indices, nr_indices);
+                       break;
+               default:
+                       NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render->prim);
+                       break;
+       }
+}
+
+
+static void
+nv04_vbuf_render_release_vertices( struct vbuf_render *render,
+               void *vertices, 
+               unsigned vertex_size,
+               unsigned vertices_used )
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+
+       free(nv04_render->buffer);
+       nv04_render->buffer = NULL;
+}
+
+
+static void
+nv04_vbuf_render_destroy( struct vbuf_render *render )
+{
+       struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render);
+       FREE(nv04_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv04_vbuf_render_create( struct nv04_context *nv04 )
+{
+       struct nv04_vbuf_render *nv04_render = CALLOC_STRUCT(nv04_vbuf_render);
+
+       nv04_render->nv04 = nv04;
+
+       nv04_render->base.max_vertex_buffer_bytes = VERTEX_BUFFER_SIZE;
+       nv04_render->base.max_indices = 65536; 
+       nv04_render->base.get_vertex_info = nv04_vbuf_render_get_vertex_info;
+       nv04_render->base.allocate_vertices = nv04_vbuf_render_allocate_vertices;
+       nv04_render->base.set_primitive = nv04_vbuf_render_set_primitive;
+       nv04_render->base.draw = nv04_vbuf_render_draw;
+       nv04_render->base.release_vertices = nv04_vbuf_render_release_vertices;
+       nv04_render->base.destroy = nv04_vbuf_render_destroy;
+
+       return &nv04_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 )
+{
+       struct vbuf_render *render;
+       struct draw_stage *stage;
+
+       render = nv04_vbuf_render_create(nv04);
+       if(!render)
+               return NULL;
+
+       stage = draw_vbuf_stage( nv04->draw, render );
+       if(!stage) {
+               render->destroy(render);
+               return NULL;
+       }
+
+       return stage;
+}
diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c
new file mode 100644 (file)
index 0000000..9f34117
--- /dev/null
@@ -0,0 +1,216 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv04_context.h"
+#include "nv04_screen.h"
+
+static const char *
+nv04_screen_get_name(struct pipe_screen *screen)
+{
+       struct nv04_screen *nv04screen = nv04_screen(screen);
+       struct nouveau_device *dev = nv04screen->nvws->channel->device;
+       static char buffer[128];
+
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+       return buffer;
+}
+
+static const char *
+nv04_screen_get_vendor(struct pipe_screen *screen)
+{
+       return "nouveau";
+}
+
+static int
+nv04_screen_get_param(struct pipe_screen *screen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+               return 1;
+       case PIPE_CAP_NPOT_TEXTURES:
+               return 0;
+       case PIPE_CAP_TWO_SIDED_STENCIL:
+               return 0;
+       case PIPE_CAP_GLSL:
+               return 0;
+       case PIPE_CAP_S3TC:
+               return 0;
+       case PIPE_CAP_ANISOTROPIC_FILTER:
+               return 0;
+       case PIPE_CAP_POINT_SPRITE:
+               return 0;
+       case PIPE_CAP_MAX_RENDER_TARGETS:
+               return 1;
+       case PIPE_CAP_OCCLUSION_QUERY:
+               return 0;
+       case PIPE_CAP_TEXTURE_SHADOW_MAP:
+               return 0;
+       case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+               return 10;
+       case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+               return 0;
+       case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+               return 0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0;
+       }
+}
+
+static float
+nv04_screen_get_paramf(struct pipe_screen *screen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_LINE_WIDTH:
+       case PIPE_CAP_MAX_LINE_WIDTH_AA:
+               return 0.0;
+       case PIPE_CAP_MAX_POINT_WIDTH:
+       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+               return 0.0;
+       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+               return 0.0;
+       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+               return 0.0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0.0;
+       }
+}
+
+static boolean
+nv04_screen_is_format_supported(struct pipe_screen *screen,
+                               enum pipe_format format, uint type)
+{
+       switch (type) {
+       case PIPE_SURFACE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_Z16_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       case PIPE_TEXTURE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_X8R8G8B8_UNORM:
+               case PIPE_FORMAT_A1R5G5B5_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       default:
+               assert(0);
+       };
+
+       return FALSE;
+}
+
+static void *
+nv04_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+                unsigned flags )
+{
+       struct pipe_winsys *ws = screen->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, surface->buffer, flags);
+       if (!map)
+               return NULL;
+
+       return map + surface->offset;
+}
+
+static void
+nv04_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+       struct pipe_winsys *ws = screen->winsys;
+
+       ws->buffer_unmap(ws, surface->buffer);
+}
+
+static void
+nv04_screen_destroy(struct pipe_screen *pscreen)
+{
+       struct nv04_screen *screen = nv04_screen(pscreen);
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nvws->notifier_free(&screen->sync);
+       nvws->grobj_free(&screen->fahrenheit);
+
+       FREE(pscreen);
+}
+
+struct pipe_screen *
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+       struct nv04_screen *screen = CALLOC_STRUCT(nv04_screen);
+       unsigned fahrenheit_class = 0, sub3d_class = 0;
+       unsigned chipset = nvws->channel->device->chipset;
+       int ret;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       if (chipset>=0x20) {
+               fahrenheit_class = 0;
+               sub3d_class = 0;
+       } else if (chipset>=0x10) {
+               fahrenheit_class = NV10_DX5_TEXTURED_TRIANGLE;
+               sub3d_class = NV10_CONTEXT_SURFACES_3D;
+       } else {
+               fahrenheit_class=NV04_DX5_TEXTURED_TRIANGLE;
+               sub3d_class = NV04_CONTEXT_SURFACES_3D;
+       }
+
+       if (!fahrenheit_class) {
+               NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", chipset);
+               return NULL;
+       }
+
+       /* 3D object */
+       ret = nvws->grobj_alloc(nvws, fahrenheit_class, &screen->fahrenheit);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               return NULL;
+       }
+
+       /* 3D surface object */
+       ret = nvws->grobj_alloc(nvws, sub3d_class, &screen->context_surfaces_3d);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D surface object: %d\n", ret);
+               return NULL;
+       }
+
+       /* Notifier for sync purposes */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv04_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       screen->pipe.winsys = ws;
+       screen->pipe.destroy = nv04_screen_destroy;
+
+       screen->pipe.get_name = nv04_screen_get_name;
+       screen->pipe.get_vendor = nv04_screen_get_vendor;
+       screen->pipe.get_param = nv04_screen_get_param;
+       screen->pipe.get_paramf = nv04_screen_get_paramf;
+
+       screen->pipe.is_format_supported = nv04_screen_is_format_supported;
+
+       screen->pipe.surface_map = nv04_surface_map;
+       screen->pipe.surface_unmap = nv04_surface_unmap;
+
+       nv04_screen_init_miptree_functions(&screen->pipe);
+
+       return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h
new file mode 100644 (file)
index 0000000..99a49cd
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __NV04_SCREEN_H__
+#define __NV04_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv04_screen {
+       struct pipe_screen pipe;
+
+       struct nouveau_winsys *nvws;
+       unsigned chipset;
+
+       /* HW graphics objects */
+       struct nouveau_grobj *fahrenheit;
+       struct nouveau_grobj *context_surfaces_3d;
+       struct nouveau_notifier *sync;
+
+};
+
+static INLINE struct nv04_screen *
+nv04_screen(struct pipe_screen *screen)
+{
+       return (struct nv04_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c
new file mode 100644 (file)
index 0000000..d618465
--- /dev/null
@@ -0,0 +1,494 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_shader_tokens.h"
+
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+static void *
+nv04_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+{
+       struct nv04_blend_state *cb;
+
+       cb = MALLOC(sizeof(struct nv04_blend_state));
+
+       cb->b_enable = cso->blend_enable ? 1 : 0;
+       cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
+                        (nvgl_blend_func(cso->rgb_src_factor)));
+       cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
+                        (nvgl_blend_func(cso->rgb_dst_factor)));
+       
+
+       return (void *)cb;
+}
+
+static void
+nv04_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       nv04->blend = (struct nv04_blend_state*)blend;
+
+       nv04->dirty |= NV04_NEW_BLEND;
+}
+
+static void
+nv04_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       free(hwcso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+       unsigned ret;
+
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_CLAMP:
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               ret = NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP;
+       }
+       return ret >> NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT;
+}
+
+static void *
+nv04_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+
+       struct nv04_sampler_state *ss;
+       uint32_t filter = 0;
+
+       ss = MALLOC(sizeof(struct nv04_sampler_state));
+
+       ss->format = ((wrap_mode(cso->wrap_s) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT) |
+                   (wrap_mode(cso->wrap_t) << NV04_DX5_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT));
+
+       if (cso->max_anisotropy > 1.0) {
+               filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE | NV04_DX5_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE;
+       }
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST;
+               break;
+       }
+
+       switch (cso->min_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+                       break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR;
+                       break;
+               }
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+               break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV04_DX5_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST;
+                       break;
+               }
+               break;
+       }
+
+       ss->filter = filter;
+
+       return (void *)ss;
+}
+
+static void
+nv04_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv04->sampler[unit] = sampler[unit];
+               nv04->dirty_samplers |= (1 << unit);
+       }
+}
+
+static void
+nv04_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       free(hwcso);
+}
+
+static void
+nv04_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+                        struct pipe_texture **miptree)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv04->tex_miptree[unit] = (struct nv04_miptree *)miptree[unit];
+               nv04->dirty_samplers |= (1 << unit);
+       }
+}
+
+static void *
+nv04_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+{
+       struct nv04_rasterizer_state *rs;
+
+       /*XXX: ignored:
+        *      scissor
+        *      points/lines (no hw support, emulated with tris in gallium)
+        */
+       rs = MALLOC(sizeof(struct nv04_rasterizer_state));
+
+       rs->blend = cso->flatshade ? NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT : NV04_DX5_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
+
+       return (void *)rs;
+}
+
+static void
+nv04_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       nv04->rast = (struct nv04_rasterizer_state*)rast;
+
+       draw_set_rasterizer_state(nv04->draw, (nv04->rast ? nv04->rast->templ : NULL));
+
+       nv04->dirty |= NV04_NEW_RAST | NV04_NEW_BLEND;
+}
+
+static void
+nv04_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       free(hwcso);
+}
+
+static INLINE uint32_t nv04_compare_func(uint32_t f)
+{
+       switch ( f ) {
+               case PIPE_FUNC_NEVER:           return 1;
+               case PIPE_FUNC_LESS:            return 2;
+               case PIPE_FUNC_EQUAL:           return 3;
+               case PIPE_FUNC_LEQUAL:          return 4;
+               case PIPE_FUNC_GREATER:         return 5;
+               case PIPE_FUNC_NOTEQUAL:        return 6;
+               case PIPE_FUNC_GEQUAL:          return 7;
+               case PIPE_FUNC_ALWAYS:          return 8;
+       }
+       NOUVEAU_MSG("Unable to find the function\n");
+       return 0;
+}
+
+static void *
+nv04_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+{
+       struct nv04_depth_stencil_alpha_state *hw;
+
+       hw = MALLOC(sizeof(struct nv04_depth_stencil_alpha_state));
+
+       hw->control = float_to_ubyte(cso->alpha.ref);
+       hw->control |= ( nv04_compare_func(cso->alpha.func) << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT );
+       hw->control |= cso->alpha.enabled ? NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ALPHA_TEST_ENABLE : 0;
+       hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_ORIGIN;
+       hw->control |= cso->depth.enabled ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE_SHIFT) : 0;
+       hw->control |= ( nv04_compare_func(cso->depth.func)<< NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT );
+       hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT; // no culling, handled by the draw module
+       hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
+       hw->control |= NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE;
+       hw->control |= cso->depth.writemask ? (1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_WRITE_ENABLE_SHIFT) : 0;
+       hw->control |= 1 << NV04_DX5_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT; // integer zbuffer format
+
+       return (void *)hw;
+}
+
+static void
+nv04_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       nv04->dsa = hwcso;
+       nv04->dirty |= NV04_NEW_CONTROL;
+}
+
+static void
+nv04_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       free(hwcso);
+}
+
+static void *
+nv04_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *templ)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       return draw_create_vertex_shader(nv04->draw, templ);
+}
+
+static void
+nv04_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       draw_bind_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
+
+       nv04->dirty |= NV04_NEW_VERTPROG;
+}
+
+static void
+nv04_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       draw_delete_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv04_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv04_fragment_program *fp;
+
+       fp = CALLOC(1, sizeof(struct nv04_fragment_program));
+       fp->pipe = cso;
+
+       return (void *)fp;
+}
+
+static void
+nv04_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct nv04_fragment_program *fp = hwcso;
+
+       nv04->fragprog.current = fp;
+       nv04->dirty |= NV04_NEW_FRAGPROG;
+}
+
+static void
+nv04_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct nv04_fragment_program *fp = hwcso;
+
+       nv04_fragprog_destroy(nv04, fp);
+       free(fp);
+}
+
+static void
+nv04_set_blend_color(struct pipe_context *pipe,
+                    const struct pipe_blend_color *bcol)
+{
+}
+
+static void
+nv04_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        const struct pipe_constant_buffer *buf )
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       if (shader == PIPE_SHADER_VERTEX) {
+               nv04->vertprog.constant_buf = buf->buffer;
+               nv04->dirty |= NV04_NEW_VERTPROG;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nv04->fragprog.constant_buf = buf->buffer;
+               nv04->dirty |= NV04_NEW_FRAGPROG;
+       }
+}
+
+static void
+nv04_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct pipe_surface *rt, *zeta;
+       uint32_t rt_format, w, h;
+       int colour_format = 0, zeta_format = 0;
+
+       w = fb->cbufs[0]->width;
+       h = fb->cbufs[0]->height;
+       colour_format = fb->cbufs[0]->format;
+       rt = fb->cbufs[0];
+
+       if (fb->zsbuf) {
+               if (colour_format) {
+                       assert(w == fb->zsbuf->width);
+                       assert(h == fb->zsbuf->height);
+               } else {
+                       w = fb->zsbuf->width;
+                       h = fb->zsbuf->height;
+               }
+
+               zeta_format = fb->zsbuf->format;
+               zeta = fb->zsbuf;
+       }
+
+       switch (colour_format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case 0:
+               rt_format = 0x108;
+               break;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               rt_format = 0x103;
+               break;
+       default:
+               assert(0);
+       }
+
+       BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1);
+       OUT_RING(rt_format);
+
+       /* FIXME pitches have to be aligned ! */
+       BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
+       OUT_RING(rt->stride|(zeta->stride<<16));
+       OUT_RELOCl(rt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       if (fb->zsbuf) {
+               BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
+               OUT_RELOCl(zeta->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       }
+}
+
+static void
+nv04_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+{
+       NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv04_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+{
+/*     struct nv04_context *nv04 = nv04_context(pipe);
+
+       // XXX
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2);
+       OUT_RING  (((s->maxx - s->minx) << 16) | s->minx);
+       OUT_RING  (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void
+nv04_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *viewport)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       nv04->viewport = *viewport;
+
+       draw_set_viewport_state(nv04->draw, &nv04->viewport);
+}
+
+static void
+nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                      const struct pipe_vertex_buffer *buffers)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       draw_flush(nv04->draw);
+
+       memcpy(nv04->vertex_buffer, buffers, count * sizeof(buffers[0]));
+       nv04->num_vertex_buffers = count;
+
+       draw_set_vertex_buffers(nv04->draw, count, buffers);
+}
+
+static void
+nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_element *elements)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+
+       draw_flush(nv04->draw);
+
+       nv04->num_vertex_elements = count;
+       draw_set_vertex_elements(nv04->draw, count, elements);
+}
+
+void
+nv04_init_state_functions(struct nv04_context *nv04)
+{
+       nv04->pipe.create_blend_state = nv04_blend_state_create;
+       nv04->pipe.bind_blend_state = nv04_blend_state_bind;
+       nv04->pipe.delete_blend_state = nv04_blend_state_delete;
+
+       nv04->pipe.create_sampler_state = nv04_sampler_state_create;
+       nv04->pipe.bind_sampler_states = nv04_sampler_state_bind;
+       nv04->pipe.delete_sampler_state = nv04_sampler_state_delete;
+       nv04->pipe.set_sampler_textures = nv04_set_sampler_texture;
+
+       nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create;
+       nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind;
+       nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete;
+
+       nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create;
+       nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind;
+       nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete;
+
+       nv04->pipe.create_vs_state = nv04_vp_state_create;
+       nv04->pipe.bind_vs_state = nv04_vp_state_bind;
+       nv04->pipe.delete_vs_state = nv04_vp_state_delete;
+
+       nv04->pipe.create_fs_state = nv04_fp_state_create;
+       nv04->pipe.bind_fs_state = nv04_fp_state_bind;
+       nv04->pipe.delete_fs_state = nv04_fp_state_delete;
+
+       nv04->pipe.set_blend_color = nv04_set_blend_color;
+       nv04->pipe.set_clip_state = nv04_set_clip_state;
+       nv04->pipe.set_constant_buffer = nv04_set_constant_buffer;
+       nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state;
+       nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple;
+       nv04->pipe.set_scissor_state = nv04_set_scissor_state;
+       nv04->pipe.set_viewport_state = nv04_set_viewport_state;
+
+       nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers;
+       nv04->pipe.set_vertex_elements = nv04_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h
new file mode 100644 (file)
index 0000000..7487819
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __NV04_STATE_H__
+#define __NV04_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
+
+struct nv04_blend_state {
+       uint32_t b_enable;
+       uint32_t b_src;
+       uint32_t b_dst;
+};
+
+struct nv04_fragtex_state {
+       uint32_t format;
+};
+
+struct nv04_sampler_state {
+       uint32_t filter;
+       uint32_t format;
+};
+
+struct nv04_depth_stencil_alpha_state {
+       uint32_t control;
+};
+
+struct nv04_rasterizer_state {
+       uint32_t blend;
+
+       const struct pipe_rasterizer_state *templ;
+};
+
+struct nv04_miptree {
+       struct pipe_texture base;
+
+       struct pipe_buffer *buffer;
+       uint total_size;
+
+       struct {
+               uint pitch;
+               uint *image_offset;
+       } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+struct nv04_fragment_program_data {
+       unsigned offset;
+       unsigned index;
+};
+
+struct nv04_fragment_program {
+       const struct pipe_shader_state *pipe;
+       struct tgsi_shader_info info;
+
+       boolean translated;
+       boolean on_hw;
+       unsigned samplers;
+
+       uint32_t *insn;
+       int       insn_len;
+
+       struct nv04_fragment_program_data *consts;
+       unsigned nr_consts;
+
+       struct pipe_buffer *buffer;
+
+       uint32_t fp_control;
+       uint32_t fp_reg_control;
+};
+
+
+
+#endif
diff --git a/src/gallium/drivers/nv04/nv04_state_emit.c b/src/gallium/drivers/nv04/nv04_state_emit.c
new file mode 100644 (file)
index 0000000..0ad40a0
--- /dev/null
@@ -0,0 +1,156 @@
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+static void nv04_vertex_layout(struct pipe_context* pipe)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct nv04_fragment_program *fp = nv04->fragprog.current;
+       uint32_t src = 0;
+       int i;
+       struct vertex_info vinfo;
+
+       memset(&vinfo, 0, sizeof(vinfo));
+
+       for (i = 0; i < fp->info.num_inputs; i++) {
+               switch (i) {
+                       case TGSI_SEMANTIC_POSITION:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+                               break;
+                       case TGSI_SEMANTIC_COLOR:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+                               break;
+                       default:
+                       case TGSI_SEMANTIC_GENERIC:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+                               break;
+                       case TGSI_SEMANTIC_FOG:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+                               break;
+               }
+       }
+       draw_compute_vertex_size(&vinfo);
+}
+
+static uint32_t nv04_blend_func(uint32_t f)
+{
+       switch ( f ) {
+               case PIPE_BLENDFACTOR_ZERO:                     return 0x1;
+               case PIPE_BLENDFACTOR_ONE:                      return 0x2;
+               case PIPE_BLENDFACTOR_SRC_COLOR:                return 0x3;
+               case PIPE_BLENDFACTOR_INV_SRC_COLOR:            return 0x4;
+               case PIPE_BLENDFACTOR_SRC_ALPHA:                return 0x5;
+               case PIPE_BLENDFACTOR_INV_SRC_ALPHA:            return 0x6;
+               case PIPE_BLENDFACTOR_DST_ALPHA:                return 0x7;
+               case PIPE_BLENDFACTOR_INV_DST_ALPHA:            return 0x8;
+               case PIPE_BLENDFACTOR_DST_COLOR:                return 0x9;
+               case PIPE_BLENDFACTOR_INV_DST_COLOR:            return 0xA;
+               case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:       return 0xB;
+       }
+       NOUVEAU_MSG("Unable to find the blend function 0x%x\n",f);
+       return 0;
+}
+
+static void nv04_emit_control(struct nv04_context* nv04)
+{
+       uint32_t control = nv04->dsa->control;
+
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+       OUT_RING(control);
+}
+
+static void nv04_emit_blend(struct nv04_context* nv04)
+{
+       uint32_t blend;
+
+       blend=0x4; // texture MODULATE_ALPHA
+       blend|=0x20; // alpha is MSB
+       blend|=(2<<6); // flat shading
+       blend|=(1<<8); // persp correct
+       blend|=(0<<16); // no fog
+       blend|=(nv04->blend->b_enable<<20);
+       blend|=(nv04_blend_func(nv04->blend->b_src)<<24);
+       blend|=(nv04_blend_func(nv04->blend->b_dst)<<28);
+
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1);
+       OUT_RING(blend);
+}
+
+static void nv04_emit_sampler(struct nv04_context *nv04, int unit)
+{
+       struct nv04_miptree *nv04mt = nv04->tex_miptree[unit];
+       struct pipe_texture *pt = &nv04mt->base;
+
+       BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 3);
+       OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+       OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[unit]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+       OUT_RING(nv04->sampler[unit]->filter);
+}
+
+void
+nv04_emit_hw_state(struct nv04_context *nv04)
+{
+       int i;
+
+       if (nv04->dirty & NV04_NEW_VERTPROG) {
+               //nv04_vertprog_bind(nv04, nv04->vertprog.current);
+               nv04->dirty &= ~NV04_NEW_VERTPROG;
+       }
+
+       if (nv04->dirty & NV04_NEW_FRAGPROG) {
+               nv04_fragprog_bind(nv04, nv04->fragprog.current);
+               /*XXX: clear NV04_NEW_FRAGPROG if no new program uploaded */
+               nv04->dirty_samplers |= (1<<10);
+               nv04->dirty_samplers = 0;
+       }
+
+       if (nv04->dirty & NV04_NEW_CONTROL) {
+               nv04->dirty &= ~NV04_NEW_CONTROL;
+
+               BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1);
+               OUT_RING(nv04->dsa->control);
+       }
+
+       if (nv04->dirty & NV04_NEW_BLEND) {
+               nv04->dirty &= ~NV04_NEW_BLEND;
+
+               nv04_emit_blend(nv04);
+       }
+
+       if (nv04->dirty & NV04_NEW_SAMPLER) {
+               nv04->dirty &= ~NV04_NEW_SAMPLER;
+
+               nv04_emit_sampler(nv04, 0);
+       }
+
+       if (nv04->dirty & NV04_NEW_VIEWPORT) {
+               nv04->dirty &= ~NV04_NEW_VIEWPORT;
+//             nv04_state_emit_viewport(nv04);
+       }
+
+       /* Emit relocs for every referenced buffer.
+        * This is to ensure the bufmgr has an accurate idea of how
+        * the buffer is used.  This isn't very efficient, but we don't
+        * seem to take a significant performance hit.  Will be improved
+        * at some point.  Vertex arrays are emitted by nv04_vbo.c
+        */
+
+       /* Render target */
+/*     BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2);
+       OUT_RING(rt->stride|(zeta->stride<<16));
+       OUT_RELOCl(rt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       if (fb->zsbuf) {
+               BEGIN_RING(context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1);
+               OUT_RELOCl(zeta->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       }*/
+
+       /* Texture images */
+       for (i = 0; i < 1; i++) {
+               if (!(nv04->fp_samplers & (1 << i)))
+                       continue;
+               struct nv04_miptree *nv04mt = nv04->tex_miptree[i];
+               BEGIN_RING(fahrenheit, NV04_DX5_TEXTURED_TRIANGLE_OFFSET, 2);
+               OUT_RELOCl(nv04mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+               OUT_RELOCd(nv04mt->buffer, (nv04->fragtex.format | nv04->sampler[i]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+       }
+}
+
diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c
new file mode 100644 (file)
index 0000000..b13ebf9
--- /dev/null
@@ -0,0 +1,65 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "nv04_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/p_tile.h"
+
+static void
+nv04_surface_copy(struct pipe_context *pipe, unsigned do_flip,
+                 struct pipe_surface *dest, unsigned destx, unsigned desty,
+                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
+                 unsigned width, unsigned height)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct nouveau_winsys *nvws = nv04->nvws;
+
+       nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+                          width, height);
+}
+
+static void
+nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+                 unsigned destx, unsigned desty, unsigned width,
+                 unsigned height, unsigned value)
+{
+       struct nv04_context *nv04 = nv04_context(pipe);
+       struct nouveau_winsys *nvws = nv04->nvws;
+
+       nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+void
+nv04_init_surface_functions(struct nv04_context *nv04)
+{
+       nv04->pipe.surface_copy = nv04_surface_copy;
+       nv04->pipe.surface_fill = nv04_surface_fill;
+}
diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c
new file mode 100644 (file)
index 0000000..fbfe0cf
--- /dev/null
@@ -0,0 +1,72 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv04_context.h"
+#include "nv04_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv04_draw_elements( struct pipe_context *pipe,
+                    struct pipe_buffer *indexBuffer,
+                    unsigned indexSize,
+                    unsigned prim, unsigned start, unsigned count)
+{
+       struct nv04_context *nv04 = nv04_context( pipe );
+       struct draw_context *draw = nv04->draw;
+       unsigned i;
+
+       /*
+        * Map vertex buffers
+        */
+       for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+               if (nv04->vertex_buffer[i].buffer) {
+                       void *buf
+                               = pipe->winsys->buffer_map(pipe->winsys,
+                                               nv04->vertex_buffer[i].buffer,
+                                               PIPE_BUFFER_USAGE_CPU_READ);
+                       draw_set_mapped_vertex_buffer(draw, i, buf);
+               }
+       }
+       /* Map index buffer, if present */
+       if (indexBuffer) {
+               void *mapped_indexes
+                       = pipe->winsys->buffer_map(pipe->winsys, indexBuffer,
+                                       PIPE_BUFFER_USAGE_CPU_READ);
+               draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+       }
+       else {
+               /* no index/element buffer */
+               draw_set_mapped_element_buffer(draw, 0, NULL);
+       }
+
+       /* draw! */
+       draw_arrays(nv04->draw, prim, start, count);
+
+       /*
+        * unmap vertex/index buffers
+        */
+       for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+               if (nv04->vertex_buffer[i].buffer) {
+                       pipe->winsys->buffer_unmap(pipe->winsys, nv04->vertex_buffer[i].buffer);
+                       draw_set_mapped_vertex_buffer(draw, i, NULL);
+               }
+       }
+       if (indexBuffer) {
+               pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer);
+               draw_set_mapped_element_buffer(draw, 0, NULL);
+       }
+
+       return TRUE;
+}
+
+boolean nv04_draw_arrays( struct pipe_context *pipe,
+                                unsigned prim, unsigned start, unsigned count)
+{
+       return nv04_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile
new file mode 100644 (file)
index 0000000..4ba7ce5
--- /dev/null
@@ -0,0 +1,28 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv10
+
+DRIVER_SOURCES = \
+       nv10_clear.c \
+       nv10_context.c \
+       nv10_fragprog.c \
+       nv10_fragtex.c \
+       nv10_miptree.c \
+       nv10_prim_vbuf.c \
+       nv10_screen.c \
+       nv10_state.c \
+       nv10_state_emit.c \
+       nv10_surface.c \
+       nv10_vbo.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c
new file mode 100644 (file)
index 0000000..be7e09c
--- /dev/null
@@ -0,0 +1,12 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv10_context.h"
+
+void
+nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+          unsigned clearValue)
+{
+       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+}
diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c
new file mode 100644 (file)
index 0000000..9fcd0b0
--- /dev/null
@@ -0,0 +1,297 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_util.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static void
+nv10_flush(struct pipe_context *pipe, unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       draw_flush(nv10->draw);
+
+       FIRE_RING(fence);
+}
+
+static void
+nv10_destroy(struct pipe_context *pipe)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       if (nv10->draw)
+               draw_destroy(nv10->draw);
+
+       FREE(nv10);
+}
+
+static void nv10_init_hwctx(struct nv10_context *nv10)
+{
+       struct nv10_screen *screen = nv10->screen;
+       struct nouveau_winsys *nvws = screen->nvws;
+       int i;
+       float projectionmatrix[16];
+
+       BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1);
+       OUT_RING  (screen->sync->handle);
+       BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2);
+       OUT_RING  (nvws->channel->vram->handle);
+       OUT_RING  (nvws->channel->gart->handle);
+       BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2);
+       OUT_RING  (nvws->channel->vram->handle);
+       OUT_RING  (nvws->channel->vram->handle);
+
+       BEGIN_RING(celsius, NV10TCL_NOP, 1);
+       OUT_RING  (0);
+
+       BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+
+       BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+       OUT_RING  ((0x7ff<<16)|0x800);
+       BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
+       OUT_RING  ((0x7ff<<16)|0x800);
+
+       for (i=1;i<8;i++) {
+               BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+               OUT_RING  (0);
+               BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
+               OUT_RING  (0);
+       }
+
+       BEGIN_RING(celsius, 0x290, 1);
+       OUT_RING  ((0x10<<16)|1);
+       BEGIN_RING(celsius, 0x3f4, 1);
+       OUT_RING  (0);
+
+       BEGIN_RING(celsius, NV10TCL_NOP, 1);
+       OUT_RING  (0);
+
+       if (nv10->screen->celsius->grclass != NV10TCL) {
+               /* For nv11, nv17 */
+               BEGIN_RING(celsius, 0x120, 3);
+               OUT_RING  (0);
+               OUT_RING  (1);
+               OUT_RING  (2);
+
+               BEGIN_RING(celsius, NV10TCL_NOP, 1);
+               OUT_RING  (0);
+       }
+
+       BEGIN_RING(celsius, NV10TCL_NOP, 1);
+       OUT_RING  (0);
+
+       /* Set state */
+       BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 2);
+       OUT_RING  (0x207);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_TX_ENABLE(0), 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+
+       BEGIN_RING(celsius, NV10TCL_RC_IN_ALPHA(0), 12);
+       OUT_RING  (0x30141010);
+       OUT_RING  (0);
+       OUT_RING  (0x20040000);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RING  (0x00000c00);
+       OUT_RING  (0);
+       OUT_RING  (0x00000c00);
+       OUT_RING  (0x18000000);
+       OUT_RING  (0x300e0300);
+       OUT_RING  (0x0c091c80);
+
+       BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 2);
+       OUT_RING  (1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_SRC, 4);
+       OUT_RING  (1);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RING  (0x8006);
+       BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 8);
+       OUT_RING  (0xff);
+       OUT_RING  (0x207);
+       OUT_RING  (0);
+       OUT_RING  (0xff);
+       OUT_RING  (0x1e00);
+       OUT_RING  (0x1e00);
+       OUT_RING  (0x1e00);
+       OUT_RING  (0x1d01);
+       BEGIN_RING(celsius, NV10TCL_NORMALIZE_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_FOG_ENABLE, 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_LIGHT_MODEL, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_COLOR_CONTROL, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_ENABLED_LIGHTS, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1);
+       OUT_RING  (0x201);
+       BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1);
+       OUT_RING  (8);
+       BEGIN_RING(celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_LINE_WIDTH, 1);
+       OUT_RING  (8);
+       BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+       OUT_RING  (0x1b02);
+       OUT_RING  (0x1b02);
+       BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2);
+       OUT_RING  (0x405);
+       OUT_RING  (0x901);
+       BEGIN_RING(celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_CLIP_PLANE_ENABLE(0), 8);
+       for (i=0;i<8;i++) {
+               OUT_RING  (0);
+       }
+       BEGIN_RING(celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
+       OUT_RING  (0x3fc00000); /* -1.50 */
+       OUT_RING  (0xbdb8aa0a); /* -0.09 */
+       OUT_RING  (0);          /*  0.00 */
+
+       BEGIN_RING(celsius, NV10TCL_NOP, 1);
+       OUT_RING  (0);
+
+       BEGIN_RING(celsius, NV10TCL_FOG_MODE, 2);
+       OUT_RING  (0x802);
+       OUT_RING  (2);
+       /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
+        * using texturing, except when using the texture matrix
+        */
+       BEGIN_RING(celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1);
+       OUT_RING  (6);
+       BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1);
+       OUT_RING  (0x01010101);
+
+       /* Set vertex component */
+       BEGIN_RING(celsius, NV10TCL_VERTEX_COL_4F_R, 4);
+       OUT_RINGf (1.0);
+       OUT_RINGf (1.0);
+       OUT_RINGf (1.0);
+       OUT_RINGf (1.0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_COL2_3F_R, 3);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_NOR_3F_X, 3);
+       OUT_RING  (0);
+       OUT_RING  (0);
+       OUT_RINGf (1.0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_TX0_4F_S, 4);
+       OUT_RINGf (0.0);
+       OUT_RINGf (0.0);
+       OUT_RINGf (0.0);
+       OUT_RINGf (1.0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_TX1_4F_S, 4);
+       OUT_RINGf (0.0);
+       OUT_RINGf (0.0);
+       OUT_RINGf (0.0);
+       OUT_RINGf (1.0);
+       BEGIN_RING(celsius, NV10TCL_VERTEX_FOG_1F, 1);
+       OUT_RINGf (0.0);
+       BEGIN_RING(celsius, NV10TCL_EDGEFLAG_ENABLE, 1);
+       OUT_RING  (1);
+
+       memset(projectionmatrix, 0, sizeof(projectionmatrix));
+       BEGIN_RING(celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
+       projectionmatrix[0*4+0] = 1.0;
+       projectionmatrix[1*4+1] = 1.0;
+       projectionmatrix[2*4+2] = 1.0;
+       projectionmatrix[3*4+3] = 1.0;
+       for (i=0;i<16;i++) {
+               OUT_RINGf  (projectionmatrix[i]);
+       }
+
+       BEGIN_RING(celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
+       OUT_RING  (0.0);
+       OUT_RINGf  (16777216.0);
+
+       BEGIN_RING(celsius, NV10TCL_VIEWPORT_SCALE_X, 4);
+       OUT_RINGf  (-2048.0);
+       OUT_RINGf  (-2048.0);
+       OUT_RINGf  (16777215.0 * 0.5);
+       OUT_RING  (0);
+
+       FIRE_RING (NULL);
+}
+
+static void
+nv10_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+struct pipe_context *
+nv10_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+       struct nv10_screen *screen = nv10_screen(pscreen);
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv10_context *nv10;
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nv10 = CALLOC(1, sizeof(struct nv10_context));
+       if (!nv10)
+               return NULL;
+       nv10->screen = screen;
+       nv10->pctx_id = pctx_id;
+
+       nv10->nvws = nvws;
+
+       nv10->pipe.winsys = ws;
+       nv10->pipe.screen = pscreen;
+       nv10->pipe.destroy = nv10_destroy;
+       nv10->pipe.set_edgeflags = nv10_set_edgeflags;
+       nv10->pipe.draw_arrays = nv10_draw_arrays;
+       nv10->pipe.draw_elements = nv10_draw_elements;
+       nv10->pipe.clear = nv10_clear;
+       nv10->pipe.flush = nv10_flush;
+
+       nv10_init_surface_functions(nv10);
+       nv10_init_state_functions(nv10);
+
+       nv10->draw = draw_create();
+       assert(nv10->draw);
+       draw_set_rasterize_stage(nv10->draw, nv10_draw_vbuf_stage(nv10));
+
+       nv10_init_hwctx(nv10);
+
+       return &nv10->pipe;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h
new file mode 100644 (file)
index 0000000..2bdba53
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef __NV10_CONTEXT_H__
+#define __NV10_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \
+       struct nv10_screen *ctx = nv10->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv10_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+
+#define NV10_NEW_VERTPROG      (1 << 0)
+#define NV10_NEW_FRAGPROG      (1 << 1)
+#define NV10_NEW_VTXARRAYS     (1 << 2)
+#define NV10_NEW_BLEND         (1 << 3)
+#define NV10_NEW_BLENDCOL      (1 << 4)
+#define NV10_NEW_RAST          (1 << 5)
+#define NV10_NEW_DSA           (1 << 6)
+#define NV10_NEW_VIEWPORT      (1 << 7)
+#define NV10_NEW_SCISSOR       (1 << 8)
+#define NV10_NEW_FRAMEBUFFER   (1 << 9)
+
+#include "nv10_screen.h"
+
+struct nv10_context {
+       struct pipe_context pipe;
+
+       struct nouveau_winsys *nvws;
+       struct nv10_screen *screen;
+       unsigned pctx_id;
+
+       struct draw_context *draw;
+
+       uint32_t dirty;
+
+       struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+       struct nv10_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+       unsigned dirty_samplers;
+       unsigned fp_samplers;
+       unsigned vp_samplers;
+
+       uint32_t rt_enable;
+       struct pipe_buffer *rt[4];
+       struct pipe_buffer *zeta;
+       uint32_t lma_offset;
+
+       struct nv10_blend_state *blend;
+       struct pipe_blend_color *blend_color;
+       struct nv10_rasterizer_state *rast;
+       struct nv10_depth_stencil_alpha_state *dsa;
+       struct pipe_viewport_state *viewport;
+       struct pipe_scissor_state *scissor;
+       struct pipe_framebuffer_state *framebuffer;
+
+       //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+       float *constbuf[PIPE_SHADER_TYPES][32][4];
+       unsigned constbuf_nr[PIPE_SHADER_TYPES];
+
+       struct vertex_info vertex_info;
+
+       struct {
+               struct pipe_buffer *buffer;
+               uint32_t format;
+       } tex[2];
+
+       unsigned vb_enable;
+       struct {
+               struct pipe_buffer *buffer;
+               unsigned delta;
+       } vb[16];
+
+/*     struct {
+       
+               struct nouveau_resource *exec_heap;
+               struct nouveau_resource *data_heap;
+
+               struct nv10_vertex_program *active;
+
+               struct nv10_vertex_program *current;
+       } vertprog;
+*/
+       struct {
+               struct nv10_fragment_program *active;
+
+               struct nv10_fragment_program *current;
+               struct pipe_buffer *constant_buf;
+       } fragprog;
+
+       struct pipe_vertex_buffer  vtxbuf[PIPE_MAX_ATTRIBS];
+       struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+};
+
+static INLINE struct nv10_context *
+nv10_context(struct pipe_context *pipe)
+{
+       return (struct nv10_context *)pipe;
+}
+
+extern void nv10_init_state_functions(struct nv10_context *nv10);
+extern void nv10_init_surface_functions(struct nv10_context *nv10);
+
+extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv10_clear.c */
+extern void nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+                      unsigned clearValue);
+
+/* nv10_draw.c */
+extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10);
+
+/* nv10_fragprog.c */
+extern void nv10_fragprog_bind(struct nv10_context *,
+                              struct nv10_fragment_program *);
+extern void nv10_fragprog_destroy(struct nv10_context *,
+                                 struct nv10_fragment_program *);
+
+/* nv10_fragtex.c */
+extern void nv10_fragtex_bind(struct nv10_context *);
+
+/* nv10_prim_vbuf.c */
+struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 );
+extern void nv10_vtxbuf_bind(struct nv10_context* nv10);
+
+/* nv10_state.c and friends */
+extern void nv10_emit_hw_state(struct nv10_context *nv10);
+extern void nv10_state_tex_update(struct nv10_context *nv10);
+
+/* nv10_vbo.c */
+extern boolean nv10_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+extern boolean nv10_draw_elements( struct pipe_context *pipe,
+                    struct pipe_buffer *indexBuffer,
+                    unsigned indexSize,
+                    unsigned prim, unsigned start, unsigned count);
+
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_fragprog.c b/src/gallium/drivers/nv10/nv10_fragprog.c
new file mode 100644 (file)
index 0000000..2a63c8a
--- /dev/null
@@ -0,0 +1,22 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv10_context.h"
+
+void
+nv10_fragprog_bind(struct nv10_context *nv10, struct nv10_fragment_program *fp)
+{
+}
+
+void
+nv10_fragprog_destroy(struct nv10_context *nv10,
+                     struct nv10_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_fragtex.c b/src/gallium/drivers/nv10/nv10_fragtex.c
new file mode 100644 (file)
index 0000000..238634d
--- /dev/null
@@ -0,0 +1,149 @@
+#include "nv10_context.h"
+
+static INLINE int log2i(int i)
+{
+       int r = 0;
+
+       if (i & 0xffff0000) {
+               i >>= 16;
+               r += 16;
+       }
+       if (i & 0x0000ff00) {
+               i >>= 8;
+               r += 8;
+       }
+       if (i & 0x000000f0) {
+               i >>= 4;
+               r += 4;
+       }
+       if (i & 0x0000000c) {
+               i >>= 2;
+               r += 2;
+       }
+       if (i & 0x00000002) {
+               r += 1;
+       }
+       return r;
+}
+
+#define _(m,tf)                                                                \
+{                                                                              \
+  TRUE,                                                                        \
+  PIPE_FORMAT_##m,                                                             \
+  NV10TCL_TX_FORMAT_FORMAT_##tf,                                               \
+}
+
+struct nv10_texture_format {
+       boolean defined;
+       uint    pipe;
+       int     format;
+};
+
+static struct nv10_texture_format
+nv10_texture_formats[] = {
+       _(A8R8G8B8_UNORM, A8R8G8B8),
+       _(A1R5G5B5_UNORM, A1R5G5B5),
+       _(A4R4G4B4_UNORM, A4R4G4B4),
+       _(L8_UNORM      , L8      ),
+       _(A8_UNORM      , A8      ),
+       _(A8L8_UNORM    , A8L8    ),
+//     _(RGB_DXT1      , DXT1,   ),
+//     _(RGBA_DXT1     , DXT1,   ),
+//     _(RGBA_DXT3     , DXT3,   ),
+//     _(RGBA_DXT5     , DXT5,   ),
+       {},
+};
+
+static struct nv10_texture_format *
+nv10_fragtex_format(uint pipe_format)
+{
+       struct nv10_texture_format *tf = nv10_texture_formats;
+
+       while (tf->defined) {
+               if (tf->pipe == pipe_format)
+                       return tf;
+               tf++;
+       }
+
+       return NULL;
+}
+
+
+static void
+nv10_fragtex_build(struct nv10_context *nv10, int unit)
+{
+#if 0
+       struct nv10_sampler_state *ps = nv10->tex_sampler[unit];
+       struct nv10_miptree *nv10mt = nv10->tex_miptree[unit];
+       struct pipe_texture *pt = &nv10mt->base;
+       struct nv10_texture_format *tf;
+       uint32_t txf, txs, txp;
+
+       tf = nv10_fragtex_format(pt->format);
+       if (!tf || !tf->defined) {
+               NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format);
+               return;
+       }
+
+       txf  = tf->format << 8;
+       txf |= (pt->last_level + 1) << 16;
+       txf |= log2i(pt->width[0]) << 20;
+       txf |= log2i(pt->height[0]) << 24;
+       txf |= log2i(pt->depth[0]) << 28;
+       txf |= 8;
+
+       switch (pt->target) {
+       case PIPE_TEXTURE_CUBE:
+               txf |= NV10TCL_TX_FORMAT_CUBE_MAP;
+               /* fall-through */
+       case PIPE_TEXTURE_2D:
+               txf |= (2<<4);
+               break;
+       case PIPE_TEXTURE_1D:
+               txf |= (1<<4);
+               break;
+       default:
+               NOUVEAU_ERR("Unknown target %d\n", pt->target);
+               return;
+       }
+
+       BEGIN_RING(celsius, NV10TCL_TX_OFFSET(unit), 8);
+       OUT_RELOCl(nv10mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+       OUT_RELOCd(nv10mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
+       OUT_RING  (ps->wrap);
+       OUT_RING  (0x40000000); /* enable */
+       OUT_RING  (txs);
+       OUT_RING  (ps->filt | 0x2000 /* magic */);
+       OUT_RING  ((pt->width[0] << 16) | pt->height[0]);
+       OUT_RING  (ps->bcol);
+#endif
+}
+
+void
+nv10_fragtex_bind(struct nv10_context *nv10)
+{
+#if 0
+       struct nv10_fragment_program *fp = nv10->fragprog.active;
+       unsigned samplers, unit;
+
+       samplers = nv10->fp_samplers & ~fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               BEGIN_RING(celsius, NV10TCL_TX_ENABLE(unit), 1);
+               OUT_RING  (0);
+       }
+
+       samplers = nv10->dirty_samplers & fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               nv10_fragtex_build(nv10, unit);
+       }
+
+       nv10->fp_samplers = fp->samplers;
+#endif
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c
new file mode 100644 (file)
index 0000000..9a68df2
--- /dev/null
@@ -0,0 +1,149 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static void
+nv10_miptree_layout(struct nv10_miptree *nv10mt)
+{
+       struct pipe_texture *pt = &nv10mt->base;
+       boolean swizzled = FALSE;
+       uint width = pt->width[0], height = pt->height[0];
+       uint offset = 0;
+       int nr_faces, l, f;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               nr_faces = 6;
+       } else {
+               nr_faces = 1;
+       }
+       
+       for (l = 0; l <= pt->last_level; l++) {
+               pt->width[l] = width;
+               pt->height[l] = height;
+               pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+               pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+               if (swizzled)
+                       nv10mt->level[l].pitch = pt->nblocksx[l] * pt->block.size;
+               else
+                       nv10mt->level[l].pitch = pt->nblocksx[0] * pt->block.size;
+               nv10mt->level[l].pitch = (nv10mt->level[l].pitch + 63) & ~63;
+
+               nv10mt->level[l].image_offset =
+                       CALLOC(nr_faces, sizeof(unsigned));
+
+               width  = MAX2(1, width  >> 1);
+               height = MAX2(1, height >> 1);
+
+       }
+
+       for (f = 0; f < nr_faces; f++) {
+               for (l = 0; l <= pt->last_level; l++) {
+                       nv10mt->level[l].image_offset[f] = offset;
+                       offset += nv10mt->level[l].pitch * pt->height[l];
+               }
+       }
+
+       nv10mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv10_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt)
+{
+       struct pipe_winsys *ws = screen->winsys;
+       struct nv10_miptree *mt;
+
+       mt = MALLOC(sizeof(struct nv10_miptree));
+       if (!mt)
+               return NULL;
+       mt->base = *pt;
+       mt->base.refcount = 1;
+       mt->base.screen = screen;
+
+       nv10_miptree_layout(mt);
+
+       mt->buffer = ws->buffer_create(ws, 256, PIPE_BUFFER_USAGE_PIXEL,
+                                          mt->total_size);
+       if (!mt->buffer) {
+               FREE(mt);
+               return NULL;
+       }
+       
+       return &mt->base;
+}
+
+static void
+nv10_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt)
+{
+       struct pipe_winsys *ws = screen->winsys;
+       struct pipe_texture *mt = *pt;
+
+       *pt = NULL;
+       if (--mt->refcount <= 0) {
+               struct nv10_miptree *nv10mt = (struct nv10_miptree *)mt;
+               int l;
+
+               pipe_buffer_reference(ws, &nv10mt->buffer, NULL);
+               for (l = 0; l <= mt->last_level; l++) {
+                       if (nv10mt->level[l].image_offset)
+                               FREE(nv10mt->level[l].image_offset);
+               }
+               FREE(nv10mt);
+       }
+}
+
+static void
+nv10_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt,
+                   uint face, uint levels)
+{
+}
+
+
+static struct pipe_surface *
+nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags)
+{
+       struct pipe_winsys *ws = screen->winsys;
+       struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt;
+       struct pipe_surface *ps;
+
+       ps = ws->surface_alloc(ws);
+       if (!ps)
+               return NULL;
+       pipe_buffer_reference(ws, &ps->buffer, nv10mt->buffer);
+       ps->format = pt->format;
+       ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->block = pt->block;
+       ps->nblocksx = pt->nblocksx[level];
+       ps->nblocksy = pt->nblocksy[level];
+       ps->stride = nv10mt->level[level].pitch;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               ps->offset = nv10mt->level[level].image_offset[face];
+       } else {
+               ps->offset = nv10mt->level[level].image_offset[0];
+       }
+
+       return ps;
+}
+
+static void
+nv10_miptree_surface_release(struct pipe_screen *screen,
+                            struct pipe_surface **surface)
+{
+}
+
+void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+       pscreen->texture_create = nv10_miptree_create;
+       pscreen->texture_release = nv10_miptree_release;
+       pscreen->get_tex_surface = nv10_miptree_surface_get;
+       pscreen->tex_surface_release = nv10_miptree_surface_release;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c
new file mode 100644 (file)
index 0000000..930536b
--- /dev/null
@@ -0,0 +1,240 @@
+/**************************************************************************
+ * 
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+/**
+ * \file
+ * Build post-transformation, post-clipping vertex buffers and element
+ * lists by hooking into the end of the primitive pipeline and
+ * manipulating the vertex_id field in the vertex headers.
+ *
+ * XXX: work in progress 
+ * 
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "draw/draw_vbuf.h"
+#include "pipe/p_debug.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+
+/**
+ * Primitive renderer for nv10.
+ */
+struct nv10_vbuf_render {
+       struct vbuf_render base;
+
+       struct nv10_context *nv10;   
+
+       /** Vertex buffer */
+       struct pipe_buffer* buffer;
+
+       /** Vertex size in bytes */
+       unsigned vertex_size;
+
+       /** Hardware primitive */
+       unsigned hwprim;
+};
+
+
+void nv10_vtxbuf_bind( struct nv10_context* nv10 )
+{
+       int i;
+       for(i = 0; i < 8; i++) {
+               BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1);
+               OUT_RING(0/*nv10->vtxbuf*/);
+               BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1);
+               OUT_RING(0/*XXX*/);
+       }
+}
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv10_vbuf_render *
+nv10_vbuf_render( struct vbuf_render *render )
+{
+       assert(render);
+       return (struct nv10_vbuf_render *)render;
+}
+
+
+static const struct vertex_info *
+nv10_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       struct nv10_context *nv10 = nv10_render->nv10;
+
+       nv10_emit_hw_state(nv10);
+
+       return &nv10->vertex_info;
+}
+
+
+static void *
+nv10_vbuf_render_allocate_vertices( struct vbuf_render *render,
+               ushort vertex_size,
+               ushort nr_vertices )
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       struct nv10_context *nv10 = nv10_render->nv10;
+       struct pipe_winsys *winsys = nv10->pipe.winsys;
+       size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+
+       assert(!nv10_render->buffer);
+       nv10_render->buffer = winsys->buffer_create(winsys, 64, PIPE_BUFFER_USAGE_VERTEX, size);
+
+       nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+       return winsys->buffer_map(winsys, 
+                       nv10_render->buffer, 
+                       PIPE_BUFFER_USAGE_CPU_WRITE);
+}
+
+
+static void 
+nv10_vbuf_render_set_primitive( struct vbuf_render *render, 
+               unsigned prim )
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       nv10_render->hwprim = prim + 1;
+}
+
+
+static void 
+nv10_vbuf_render_draw( struct vbuf_render *render,
+               const ushort *indices,
+               uint nr_indices)
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       struct nv10_context *nv10 = nv10_render->nv10;
+       int push, i;
+
+       nv10_emit_hw_state(nv10);
+
+       BEGIN_RING(celsius, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1);
+       OUT_RELOCl(nv10_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+
+       BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+       OUT_RING(nv10_render->hwprim);
+
+       if (nr_indices & 1) {
+               BEGIN_RING(celsius, NV10TCL_VB_ELEMENT_U32, 1);
+               OUT_RING  (indices[0]);
+               indices++; nr_indices--;
+       }
+
+       while (nr_indices) {
+               // XXX too big/small ? check the size
+               push = MIN2(nr_indices, 1200 * 2);
+
+               BEGIN_RING_NI(celsius, NV10TCL_VB_ELEMENT_U16, push >> 1);
+               for (i = 0; i < push; i+=2)
+                       OUT_RING((indices[i+1] << 16) | indices[i]);
+
+               nr_indices -= push;
+               indices  += push;
+       }
+
+       BEGIN_RING(celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+       OUT_RING  (0);
+}
+
+
+static void
+nv10_vbuf_render_release_vertices( struct vbuf_render *render,
+               void *vertices, 
+               unsigned vertex_size,
+               unsigned vertices_used )
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       struct nv10_context *nv10 = nv10_render->nv10;
+       struct pipe_winsys *winsys = nv10->pipe.winsys;
+
+       assert(nv10_render->buffer);
+       winsys->buffer_unmap(winsys, nv10_render->buffer);
+       pipe_buffer_reference(winsys, &nv10_render->buffer, NULL);
+}
+
+
+static void
+nv10_vbuf_render_destroy( struct vbuf_render *render )
+{
+       struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render);
+       FREE(nv10_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv10_vbuf_render_create( struct nv10_context *nv10 )
+{
+       struct nv10_vbuf_render *nv10_render = CALLOC_STRUCT(nv10_vbuf_render);
+
+       nv10_render->nv10 = nv10;
+
+       nv10_render->base.max_vertex_buffer_bytes = 16*1024;
+       nv10_render->base.max_indices = 1024;
+       nv10_render->base.get_vertex_info = nv10_vbuf_render_get_vertex_info;
+       nv10_render->base.allocate_vertices = nv10_vbuf_render_allocate_vertices;
+       nv10_render->base.set_primitive = nv10_vbuf_render_set_primitive;
+       nv10_render->base.draw = nv10_vbuf_render_draw;
+       nv10_render->base.release_vertices = nv10_vbuf_render_release_vertices;
+       nv10_render->base.destroy = nv10_vbuf_render_destroy;
+
+       return &nv10_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 )
+{
+       struct vbuf_render *render;
+       struct draw_stage *stage;
+
+       render = nv10_vbuf_render_create(nv10);
+       if(!render)
+               return NULL;
+
+       stage = draw_vbuf_stage( nv10->draw, render );
+       if(!stage) {
+               render->destroy(render);
+               return NULL;
+       }
+
+       return stage;
+}
diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c
new file mode 100644 (file)
index 0000000..67787d8
--- /dev/null
@@ -0,0 +1,212 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv10_context.h"
+#include "nv10_screen.h"
+
+static const char *
+nv10_screen_get_name(struct pipe_screen *screen)
+{
+       struct nv10_screen *nv10screen = nv10_screen(screen);
+       struct nouveau_device *dev = nv10screen->nvws->channel->device;
+       static char buffer[128];
+
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+       return buffer;
+}
+
+static const char *
+nv10_screen_get_vendor(struct pipe_screen *screen)
+{
+       return "nouveau";
+}
+
+static int
+nv10_screen_get_param(struct pipe_screen *screen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+               return 2;
+       case PIPE_CAP_NPOT_TEXTURES:
+               return 0;
+       case PIPE_CAP_TWO_SIDED_STENCIL:
+               return 0;
+       case PIPE_CAP_GLSL:
+               return 0;
+       case PIPE_CAP_S3TC:
+               return 0;
+       case PIPE_CAP_ANISOTROPIC_FILTER:
+               return 1;
+       case PIPE_CAP_POINT_SPRITE:
+               return 0;
+       case PIPE_CAP_MAX_RENDER_TARGETS:
+               return 1;
+       case PIPE_CAP_OCCLUSION_QUERY:
+               return 0;
+       case PIPE_CAP_TEXTURE_SHADOW_MAP:
+               return 0;
+       case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
+               return 12;
+       case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
+               return 0;
+       case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
+               return 12;
+       case NOUVEAU_CAP_HW_VTXBUF:
+       case NOUVEAU_CAP_HW_IDXBUF:
+               return 0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0;
+       }
+}
+
+static float
+nv10_screen_get_paramf(struct pipe_screen *screen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_LINE_WIDTH:
+       case PIPE_CAP_MAX_LINE_WIDTH_AA:
+               return 10.0;
+       case PIPE_CAP_MAX_POINT_WIDTH:
+       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+               return 64.0;
+       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+               return 2.0;
+       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+               return 4.0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0.0;
+       }
+}
+
+static boolean
+nv10_screen_is_format_supported(struct pipe_screen *screen,
+                               enum pipe_format format, uint type)
+{
+       switch (type) {
+       case PIPE_SURFACE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_Z24S8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       case PIPE_TEXTURE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_A1R5G5B5_UNORM:
+               case PIPE_FORMAT_A4R4G4B4_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+               case PIPE_FORMAT_I8_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       default:
+               assert(0);
+       };
+
+       return FALSE;
+}
+
+static void *
+nv10_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+                unsigned flags )
+{
+       struct pipe_winsys *ws = screen->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, surface->buffer, flags);
+       if (!map)
+               return NULL;
+
+       return map + surface->offset;
+}
+
+static void
+nv10_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+       struct pipe_winsys *ws = screen->winsys;
+
+       ws->buffer_unmap(ws, surface->buffer);
+}
+
+static void
+nv10_screen_destroy(struct pipe_screen *pscreen)
+{
+       struct nv10_screen *screen = nv10_screen(pscreen);
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nvws->notifier_free(&screen->sync);
+       nvws->grobj_free(&screen->celsius);
+
+       FREE(pscreen);
+}
+
+struct pipe_screen *
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+       struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen);
+       unsigned celsius_class;
+       unsigned chipset = nvws->channel->device->chipset;
+       int ret;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       /* 3D object */
+       if (chipset>=0x20)
+               celsius_class=NV11TCL;
+       else if (chipset>=0x17)
+               celsius_class=NV17TCL;
+       else if (chipset>=0x11)
+               celsius_class=NV11TCL;
+       else
+               celsius_class=NV10TCL;
+
+       if (!celsius_class) {
+               NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", chipset);
+               return NULL;
+       }
+
+       ret = nvws->grobj_alloc(nvws, celsius_class, &screen->celsius);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               return FALSE;
+       }
+
+       /* Notifier for sync purposes */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv10_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       screen->pipe.winsys = ws;
+       screen->pipe.destroy = nv10_screen_destroy;
+
+       screen->pipe.get_name = nv10_screen_get_name;
+       screen->pipe.get_vendor = nv10_screen_get_vendor;
+       screen->pipe.get_param = nv10_screen_get_param;
+       screen->pipe.get_paramf = nv10_screen_get_paramf;
+
+       screen->pipe.is_format_supported = nv10_screen_is_format_supported;
+
+       screen->pipe.surface_map = nv10_surface_map;
+       screen->pipe.surface_unmap = nv10_surface_unmap;
+
+       nv10_screen_init_miptree_functions(&screen->pipe);
+
+       return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h
new file mode 100644 (file)
index 0000000..3f8750a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __NV10_SCREEN_H__
+#define __NV10_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv10_screen {
+       struct pipe_screen pipe;
+
+       struct nouveau_winsys *nvws;
+
+       /* HW graphics objects */
+       struct nouveau_grobj *celsius;
+       struct nouveau_notifier *sync;
+};
+
+static INLINE struct nv10_screen *
+nv10_screen(struct pipe_screen *screen)
+{
+       return (struct nv10_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c
new file mode 100644 (file)
index 0000000..9b8b780
--- /dev/null
@@ -0,0 +1,587 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_shader_tokens.h"
+
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+static void *
+nv10_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+{
+       struct nv10_blend_state *cb;
+
+       cb = MALLOC(sizeof(struct nv10_blend_state));
+
+       cb->b_enable = cso->blend_enable ? 1 : 0;
+       cb->b_srcfunc = ((nvgl_blend_func(cso->alpha_src_factor)<<16) |
+                        (nvgl_blend_func(cso->rgb_src_factor)));
+       cb->b_dstfunc = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) |
+                        (nvgl_blend_func(cso->rgb_dst_factor)));
+
+       cb->c_mask = (((cso->colormask & PIPE_MASK_A) ? (0x01<<24) : 0) |
+                     ((cso->colormask & PIPE_MASK_R) ? (0x01<<16) : 0) |
+                     ((cso->colormask & PIPE_MASK_G) ? (0x01<< 8) : 0) |
+                     ((cso->colormask & PIPE_MASK_B) ? (0x01<< 0) : 0));
+
+       cb->d_enable = cso->dither ? 1 : 0;
+
+       return (void *)cb;
+}
+
+static void
+nv10_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->blend = (struct nv10_blend_state*)blend;
+
+       nv10->dirty |= NV10_NEW_BLEND;
+}
+
+static void
+nv10_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+       unsigned ret;
+
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               ret = NV10TCL_TX_FORMAT_WRAP_S_MIRRORED_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_CLAMP:
+               ret = NV10TCL_TX_FORMAT_WRAP_S_CLAMP;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               ret = NV10TCL_TX_FORMAT_WRAP_S_REPEAT;
+               break;
+       }
+
+       return ret >> NV10TCL_TX_FORMAT_WRAP_S_SHIFT;
+}
+
+static void *
+nv10_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+       struct nv10_sampler_state *ps;
+       uint32_t filter = 0;
+
+       ps = MALLOC(sizeof(struct nv10_sampler_state));
+
+       ps->wrap = ((wrap_mode(cso->wrap_s) << NV10TCL_TX_FORMAT_WRAP_S_SHIFT) |
+                   (wrap_mode(cso->wrap_t) << NV10TCL_TX_FORMAT_WRAP_T_SHIFT));
+
+       ps->en = 0;
+       if (cso->max_anisotropy > 1.0) {
+               /* no idea, binary driver sets it, works without it.. meh.. */
+               ps->wrap |= (1 << 5);
+
+/*             if (cso->max_anisotropy >= 16.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_16X;
+               } else
+               if (cso->max_anisotropy >= 12.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_12X;
+               } else
+               if (cso->max_anisotropy >= 10.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_10X;
+               } else
+               if (cso->max_anisotropy >= 8.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_8X;
+               } else
+               if (cso->max_anisotropy >= 6.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_6X;
+               } else
+               if (cso->max_anisotropy >= 4.0) {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_4X;
+               } else {
+                       ps->en |= NV10TCL_TX_ENABLE_ANISO_2X;
+               }*/
+       }
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               filter |= NV10TCL_TX_FILTER_MAGNIFY_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               filter |= NV10TCL_TX_FILTER_MAGNIFY_NEAREST;
+               break;
+       }
+
+       switch (cso->min_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+                       break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_LINEAR;
+                       break;
+               }
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+               break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV10TCL_TX_FILTER_MINIFY_NEAREST;
+                       break;
+               }
+               break;
+       }
+
+       ps->filt = filter;
+
+/*     if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+               switch (cso->compare_func) {
+               case PIPE_FUNC_NEVER:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NEVER;
+                       break;
+               case PIPE_FUNC_GREATER:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GREATER;
+                       break;
+               case PIPE_FUNC_EQUAL:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_EQUAL;
+                       break;
+               case PIPE_FUNC_GEQUAL:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_GEQUAL;
+                       break;
+               case PIPE_FUNC_LESS:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LESS;
+                       break;
+               case PIPE_FUNC_NOTEQUAL:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_NOTEQUAL;
+                       break;
+               case PIPE_FUNC_LEQUAL:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_LEQUAL;
+                       break;
+               case PIPE_FUNC_ALWAYS:
+                       ps->wrap |= NV10TCL_TX_WRAP_RCOMP_ALWAYS;
+                       break;
+               default:
+                       break;
+               }
+       }*/
+
+       ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+                   (float_to_ubyte(cso->border_color[0]) << 16) |
+                   (float_to_ubyte(cso->border_color[1]) <<  8) |
+                   (float_to_ubyte(cso->border_color[2]) <<  0));
+
+       return (void *)ps;
+}
+
+static void
+nv10_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv10->tex_sampler[unit] = sampler[unit];
+               nv10->dirty_samplers |= (1 << unit);
+       }
+}
+
+static void
+nv10_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void
+nv10_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+                        struct pipe_texture **miptree)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv10->tex_miptree[unit] = (struct nv10_miptree *)miptree[unit];
+               nv10->dirty_samplers |= (1 << unit);
+       }
+}
+
+static void *
+nv10_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+{
+       struct nv10_rasterizer_state *rs;
+       int i;
+
+       /*XXX: ignored:
+        *      light_twoside
+        *      offset_cw/ccw -nohw
+        *      scissor
+        *      point_smooth -nohw
+        *      multisample
+        *      offset_units / offset_scale
+        */
+       rs = MALLOC(sizeof(struct nv10_rasterizer_state));
+
+       rs->templ = cso;
+       
+       rs->shade_model = cso->flatshade ? 0x1d00 : 0x1d01;
+
+       rs->line_width = (unsigned char)(cso->line_width * 8.0) & 0xff;
+       rs->line_smooth_en = cso->line_smooth ? 1 : 0;
+
+       rs->point_size = *(uint32_t*)&cso->point_size;
+
+       rs->poly_smooth_en = cso->poly_smooth ? 1 : 0;
+
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               rs->front_face = NV10TCL_FRONT_FACE_CCW;
+               rs->poly_mode_front = nvgl_polygon_mode(cso->fill_ccw);
+               rs->poly_mode_back  = nvgl_polygon_mode(cso->fill_cw);
+       } else {
+               rs->front_face = NV10TCL_FRONT_FACE_CW;
+               rs->poly_mode_front = nvgl_polygon_mode(cso->fill_cw);
+               rs->poly_mode_back  = nvgl_polygon_mode(cso->fill_ccw);
+       }
+
+       switch (cso->cull_mode) {
+       case PIPE_WINDING_CCW:
+               rs->cull_face_en = 1;
+               if (cso->front_winding == PIPE_WINDING_CCW)
+                       rs->cull_face    = NV10TCL_CULL_FACE_FRONT;
+               else
+                       rs->cull_face    = NV10TCL_CULL_FACE_BACK;
+               break;
+       case PIPE_WINDING_CW:
+               rs->cull_face_en = 1;
+               if (cso->front_winding == PIPE_WINDING_CW)
+                       rs->cull_face    = NV10TCL_CULL_FACE_FRONT;
+               else
+                       rs->cull_face    = NV10TCL_CULL_FACE_BACK;
+               break;
+       case PIPE_WINDING_BOTH:
+               rs->cull_face_en = 1;
+               rs->cull_face    = NV10TCL_CULL_FACE_FRONT_AND_BACK;
+               break;
+       case PIPE_WINDING_NONE:
+       default:
+               rs->cull_face_en = 0;
+               rs->cull_face    = 0;
+               break;
+       }
+
+       if (cso->point_sprite) {
+               rs->point_sprite = (1 << 0);
+               for (i = 0; i < 8; i++) {
+                       if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+                               rs->point_sprite |= (1 << (8 + i));
+               }
+       } else {
+               rs->point_sprite = 0;
+       }
+
+       return (void *)rs;
+}
+
+static void
+nv10_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->rast = (struct nv10_rasterizer_state*)rast;
+
+       draw_set_rasterizer_state(nv10->draw, (nv10->rast ? nv10->rast->templ : NULL));
+
+       nv10->dirty |= NV10_NEW_RAST;
+}
+
+static void
+nv10_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void *
+nv10_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+{
+       struct nv10_depth_stencil_alpha_state *hw;
+
+       hw = MALLOC(sizeof(struct nv10_depth_stencil_alpha_state));
+
+       hw->depth.func          = nvgl_comparison_op(cso->depth.func);
+       hw->depth.write_enable  = cso->depth.writemask ? 1 : 0;
+       hw->depth.test_enable   = cso->depth.enabled ? 1 : 0;
+
+       hw->stencil.enable = cso->stencil[0].enabled ? 1 : 0;
+       hw->stencil.wmask = cso->stencil[0].write_mask;
+       hw->stencil.func = nvgl_comparison_op(cso->stencil[0].func);
+       hw->stencil.ref = cso->stencil[0].ref_value;
+       hw->stencil.vmask = cso->stencil[0].value_mask;
+       hw->stencil.fail = nvgl_stencil_op(cso->stencil[0].fail_op);
+       hw->stencil.zfail = nvgl_stencil_op(cso->stencil[0].zfail_op);
+       hw->stencil.zpass = nvgl_stencil_op(cso->stencil[0].zpass_op);
+
+       hw->alpha.enabled = cso->alpha.enabled ? 1 : 0;
+       hw->alpha.func = nvgl_comparison_op(cso->alpha.func);
+       hw->alpha.ref  = float_to_ubyte(cso->alpha.ref);
+
+       return (void *)hw;
+}
+
+static void
+nv10_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->dsa = (struct nv10_depth_stencil_alpha_state*)dsa;
+
+       nv10->dirty |= NV10_NEW_DSA;
+}
+
+static void
+nv10_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void *
+nv10_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *templ)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       return draw_create_vertex_shader(nv10->draw, templ);
+}
+
+static void
+nv10_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       draw_bind_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader);
+
+       nv10->dirty |= NV10_NEW_VERTPROG;
+}
+
+static void
+nv10_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       draw_delete_vertex_shader(nv10->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv10_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv10_fragment_program *fp;
+
+       fp = CALLOC(1, sizeof(struct nv10_fragment_program));
+       fp->pipe = cso;
+       
+       tgsi_scan_shader(cso->tokens, &fp->info);
+
+       return (void *)fp;
+}
+
+static void
+nv10_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       struct nv10_fragment_program *fp = hwcso;
+
+       nv10->fragprog.current = fp;
+       nv10->dirty |= NV10_NEW_FRAGPROG;
+}
+
+static void
+nv10_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       struct nv10_fragment_program *fp = hwcso;
+
+       nv10_fragprog_destroy(nv10, fp);
+       FREE(fp);
+}
+
+static void
+nv10_set_blend_color(struct pipe_context *pipe,
+                    const struct pipe_blend_color *bcol)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->blend_color = (struct pipe_blend_color*)bcol;
+
+       nv10->dirty |= NV10_NEW_BLENDCOL;
+}
+
+static void
+nv10_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       draw_set_clip_state(nv10->draw, clip);
+}
+
+static void
+nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        const struct pipe_constant_buffer *buf )
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       struct pipe_winsys *ws = pipe->winsys;
+
+       assert(shader < PIPE_SHADER_TYPES);
+       assert(index == 0);
+
+       if (buf) {
+               void *mapped;
+               if (buf->size && (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+               {
+                       memcpy(nv10->constbuf[shader], mapped, buf->size);
+                       nv10->constbuf_nr[shader] =
+                               buf->size / (4 * sizeof(float));
+                       ws->buffer_unmap(ws, buf->buffer);
+               }
+       }
+}
+
+static void
+nv10_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->framebuffer = (struct pipe_framebuffer_state*)fb;
+
+       nv10->dirty |= NV10_NEW_FRAMEBUFFER;
+}
+
+static void
+nv10_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+{
+       NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv10_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->scissor = (struct pipe_scissor_state*)s;
+
+       nv10->dirty |= NV10_NEW_SCISSOR;
+}
+
+static void
+nv10_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *vpt)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       nv10->viewport = (struct pipe_viewport_state*)vpt;
+
+       draw_set_viewport_state(nv10->draw, nv10->viewport);
+
+       nv10->dirty |= NV10_NEW_VIEWPORT;
+}
+
+static void
+nv10_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       memcpy(nv10->vtxbuf, vb, sizeof(*vb) * count);
+       nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+       draw_set_vertex_buffers(nv10->draw, count, vb);
+}
+
+static void
+nv10_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+                        const struct pipe_vertex_element *ve)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+
+       memcpy(nv10->vtxelt, ve, sizeof(*ve) * count);
+       nv10->dirty |= NV10_NEW_VTXARRAYS;
+
+       draw_set_vertex_elements(nv10->draw, count, ve);
+}
+
+void
+nv10_init_state_functions(struct nv10_context *nv10)
+{
+       nv10->pipe.create_blend_state = nv10_blend_state_create;
+       nv10->pipe.bind_blend_state = nv10_blend_state_bind;
+       nv10->pipe.delete_blend_state = nv10_blend_state_delete;
+
+       nv10->pipe.create_sampler_state = nv10_sampler_state_create;
+       nv10->pipe.bind_sampler_states = nv10_sampler_state_bind;
+       nv10->pipe.delete_sampler_state = nv10_sampler_state_delete;
+       nv10->pipe.set_sampler_textures = nv10_set_sampler_texture;
+
+       nv10->pipe.create_rasterizer_state = nv10_rasterizer_state_create;
+       nv10->pipe.bind_rasterizer_state = nv10_rasterizer_state_bind;
+       nv10->pipe.delete_rasterizer_state = nv10_rasterizer_state_delete;
+
+       nv10->pipe.create_depth_stencil_alpha_state =
+               nv10_depth_stencil_alpha_state_create;
+       nv10->pipe.bind_depth_stencil_alpha_state =
+               nv10_depth_stencil_alpha_state_bind;
+       nv10->pipe.delete_depth_stencil_alpha_state =
+               nv10_depth_stencil_alpha_state_delete;
+
+       nv10->pipe.create_vs_state = nv10_vp_state_create;
+       nv10->pipe.bind_vs_state = nv10_vp_state_bind;
+       nv10->pipe.delete_vs_state = nv10_vp_state_delete;
+
+       nv10->pipe.create_fs_state = nv10_fp_state_create;
+       nv10->pipe.bind_fs_state = nv10_fp_state_bind;
+       nv10->pipe.delete_fs_state = nv10_fp_state_delete;
+
+       nv10->pipe.set_blend_color = nv10_set_blend_color;
+       nv10->pipe.set_clip_state = nv10_set_clip_state;
+       nv10->pipe.set_constant_buffer = nv10_set_constant_buffer;
+       nv10->pipe.set_framebuffer_state = nv10_set_framebuffer_state;
+       nv10->pipe.set_polygon_stipple = nv10_set_polygon_stipple;
+       nv10->pipe.set_scissor_state = nv10_set_scissor_state;
+       nv10->pipe.set_viewport_state = nv10_set_viewport_state;
+
+       nv10->pipe.set_vertex_buffers = nv10_set_vertex_buffers;
+       nv10->pipe.set_vertex_elements = nv10_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_state.h b/src/gallium/drivers/nv10/nv10_state.h
new file mode 100644 (file)
index 0000000..3ca501d
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef __NV10_STATE_H__
+#define __NV10_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
+
+struct nv10_blend_state {
+       uint32_t b_enable;
+       uint32_t b_srcfunc;
+       uint32_t b_dstfunc;
+
+       uint32_t c_mask;
+
+       uint32_t d_enable;
+};
+
+struct nv10_sampler_state {
+       uint32_t wrap;
+       uint32_t en;
+       uint32_t filt;
+       uint32_t bcol;
+};
+
+struct nv10_rasterizer_state {
+       uint32_t shade_model;
+
+       uint32_t line_width;
+       uint32_t line_smooth_en;
+
+       uint32_t point_size;
+
+       uint32_t poly_smooth_en;
+       
+       uint32_t poly_mode_front;
+       uint32_t poly_mode_back;
+
+       uint32_t front_face;
+       uint32_t cull_face;
+       uint32_t cull_face_en;
+
+       uint32_t point_sprite;
+
+       const struct pipe_rasterizer_state *templ;
+};
+
+struct nv10_vertex_program_exec {
+       uint32_t data[4];
+       boolean has_branch_offset;
+       int const_index;
+};
+
+struct nv10_vertex_program_data {
+       int index; /* immediates == -1 */
+       float value[4];
+};
+
+struct nv10_vertex_program {
+       const struct pipe_shader_state *pipe;
+
+       boolean translated;
+       struct nv10_vertex_program_exec *insns;
+       unsigned nr_insns;
+       struct nv10_vertex_program_data *consts;
+       unsigned nr_consts;
+
+       struct nouveau_resource *exec;
+       unsigned exec_start;
+       struct nouveau_resource *data;
+       unsigned data_start;
+       unsigned data_start_min;
+
+       uint32_t ir;
+       uint32_t or;
+};
+
+struct nv10_fragment_program_data {
+       unsigned offset;
+       unsigned index;
+};
+
+struct nv10_fragment_program {
+       const struct pipe_shader_state *pipe;
+       struct tgsi_shader_info info;
+
+       boolean translated;
+       boolean on_hw;
+       unsigned samplers;
+
+       uint32_t *insn;
+       int       insn_len;
+
+       struct nv10_fragment_program_data *consts;
+       unsigned nr_consts;
+
+       struct pipe_buffer *buffer;
+
+       uint32_t fp_control;
+       uint32_t fp_reg_control;
+};
+
+
+struct nv10_depth_stencil_alpha_state {
+       struct {
+               uint32_t func;
+               uint32_t write_enable;
+               uint32_t test_enable;
+       } depth;
+
+       struct {
+               uint32_t enable;
+               uint32_t wmask;
+               uint32_t func;
+               uint32_t ref;
+               uint32_t vmask;
+               uint32_t fail;
+               uint32_t zfail;
+               uint32_t zpass;
+       } stencil;
+
+       struct {
+               uint32_t enabled;
+               uint32_t func;
+               uint32_t ref;
+       } alpha;
+};
+
+struct nv10_miptree {
+       struct pipe_texture base;
+
+       struct pipe_buffer *buffer;
+       uint total_size;
+
+       struct {
+               uint pitch;
+               uint *image_offset;
+       } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c
new file mode 100644 (file)
index 0000000..d21368d
--- /dev/null
@@ -0,0 +1,305 @@
+#include "pipe/p_util.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+static void nv10_state_emit_blend(struct nv10_context* nv10)
+{
+       struct nv10_blend_state *b = nv10->blend;
+
+       BEGIN_RING(celsius, NV10TCL_DITHER_ENABLE, 1);
+       OUT_RING  (b->d_enable);
+
+       BEGIN_RING(celsius, NV10TCL_BLEND_FUNC_ENABLE, 3);
+       OUT_RING  (b->b_enable);
+       OUT_RING  (b->b_srcfunc);
+       OUT_RING  (b->b_dstfunc);
+
+       BEGIN_RING(celsius, NV10TCL_COLOR_MASK, 1);
+       OUT_RING  (b->c_mask);
+}
+
+static void nv10_state_emit_blend_color(struct nv10_context* nv10)
+{
+       struct pipe_blend_color *c = nv10->blend_color;
+
+       BEGIN_RING(celsius, NV10TCL_BLEND_COLOR, 1);
+       OUT_RING  ((float_to_ubyte(c->color[3]) << 24)|
+                  (float_to_ubyte(c->color[0]) << 16)|
+                  (float_to_ubyte(c->color[1]) << 8) |
+                  (float_to_ubyte(c->color[2]) << 0));
+}
+
+static void nv10_state_emit_rast(struct nv10_context* nv10)
+{
+       struct nv10_rasterizer_state *r = nv10->rast;
+
+       BEGIN_RING(celsius, NV10TCL_SHADE_MODEL, 2);
+       OUT_RING  (r->shade_model);
+       OUT_RING  (r->line_width);
+
+
+       BEGIN_RING(celsius, NV10TCL_POINT_SIZE, 1);
+       OUT_RING  (r->point_size);
+
+       BEGIN_RING(celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
+       OUT_RING  (r->poly_mode_front);
+       OUT_RING  (r->poly_mode_back);
+
+
+       BEGIN_RING(celsius, NV10TCL_CULL_FACE, 2);
+       OUT_RING  (r->cull_face);
+       OUT_RING  (r->front_face);
+
+       BEGIN_RING(celsius, NV10TCL_LINE_SMOOTH_ENABLE, 2);
+       OUT_RING  (r->line_smooth_en);
+       OUT_RING  (r->poly_smooth_en);
+
+       BEGIN_RING(celsius, NV10TCL_CULL_FACE_ENABLE, 1);
+       OUT_RING  (r->cull_face_en);
+}
+
+static void nv10_state_emit_dsa(struct nv10_context* nv10)
+{
+       struct nv10_depth_stencil_alpha_state *d = nv10->dsa;
+
+       BEGIN_RING(celsius, NV10TCL_DEPTH_FUNC, 1);
+       OUT_RING (d->depth.func);
+
+       BEGIN_RING(celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+       OUT_RING (d->depth.write_enable);
+
+       BEGIN_RING(celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
+       OUT_RING (d->depth.test_enable);
+
+#if 0
+       BEGIN_RING(celsius, NV10TCL_STENCIL_ENABLE, 1);
+       OUT_RING (d->stencil.enable);
+       BEGIN_RING(celsius, NV10TCL_STENCIL_MASK, 7);
+       OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7);
+#endif
+
+       BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+       OUT_RING (d->alpha.enabled);
+
+       BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_FUNC, 1);
+       OUT_RING (d->alpha.func);
+
+       BEGIN_RING(celsius, NV10TCL_ALPHA_FUNC_REF, 1);
+       OUT_RING (d->alpha.ref);
+}
+
+static void nv10_state_emit_viewport(struct nv10_context* nv10)
+{
+}
+
+static void nv10_state_emit_scissor(struct nv10_context* nv10)
+{
+       // XXX this is so not working
+/*     struct pipe_scissor_state *s = nv10->scissor;
+       BEGIN_RING(celsius, NV10TCL_SCISSOR_HORIZ, 2);
+       OUT_RING  (((s->maxx - s->minx) << 16) | s->minx);
+       OUT_RING  (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void nv10_state_emit_framebuffer(struct nv10_context* nv10)
+{
+       struct pipe_framebuffer_state* fb = nv10->framebuffer;
+       struct pipe_surface *rt, *zeta = NULL;
+       uint32_t rt_format, w, h;
+       int colour_format = 0, zeta_format = 0;
+
+       w = fb->cbufs[0]->width;
+       h = fb->cbufs[0]->height;
+       colour_format = fb->cbufs[0]->format;
+       rt = fb->cbufs[0];
+
+       if (fb->zsbuf) {
+               if (colour_format) {
+                       assert(w == fb->zsbuf->width);
+                       assert(h == fb->zsbuf->height);
+               } else {
+                       w = fb->zsbuf->width;
+                       h = fb->zsbuf->height;
+               }
+
+               zeta_format = fb->zsbuf->format;
+               zeta = fb->zsbuf;
+       }
+
+       rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR;
+
+       switch (colour_format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case 0:
+               rt_format |= NV10TCL_RT_FORMAT_COLOR_A8R8G8B8;
+               break;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               rt_format |= NV10TCL_RT_FORMAT_COLOR_R5G6B5;
+               break;
+       default:
+               assert(0);
+       }
+
+       if (zeta) {
+               BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1);
+               OUT_RING  (rt->stride | (zeta->stride << 16));
+       } else {
+               BEGIN_RING(celsius, NV10TCL_RT_PITCH, 1);
+               OUT_RING  (rt->stride | (rt->stride << 16));
+       }
+
+       nv10->rt[0] = rt->buffer;
+
+       if (zeta_format)
+       {
+               nv10->zeta = zeta->buffer;
+       }
+
+       BEGIN_RING(celsius, NV10TCL_RT_HORIZ, 3);
+       OUT_RING  ((w << 16) | 0);
+       OUT_RING  ((h << 16) | 0);
+       OUT_RING  (rt_format);
+       BEGIN_RING(celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+       OUT_RING  (((w - 1) << 16) | 0 | 0x08000800);
+       OUT_RING  (((h - 1) << 16) | 0 | 0x08000800);
+}
+
+static void nv10_vertex_layout(struct nv10_context *nv10)
+{
+       struct nv10_fragment_program *fp = nv10->fragprog.current;
+       uint32_t src = 0;
+       int i;
+       struct vertex_info vinfo;
+
+       memset(&vinfo, 0, sizeof(vinfo));
+
+       for (i = 0; i < fp->info.num_inputs; i++) {
+               switch (fp->info.input_semantic_name[i]) {
+                       case TGSI_SEMANTIC_POSITION:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+                               break;
+                       case TGSI_SEMANTIC_COLOR:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++);
+                               break;
+                       default:
+                       case TGSI_SEMANTIC_GENERIC:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+                               break;
+                       case TGSI_SEMANTIC_FOG:
+                               draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++);
+                               break;
+               }
+       }
+       draw_compute_vertex_size(&vinfo);
+}
+
+void
+nv10_emit_hw_state(struct nv10_context *nv10)
+{
+       int i;
+
+       if (nv10->dirty & NV10_NEW_VERTPROG) {
+               //nv10_vertprog_bind(nv10, nv10->vertprog.current);
+               nv10->dirty &= ~NV10_NEW_VERTPROG;
+       }
+
+       if (nv10->dirty & NV10_NEW_FRAGPROG) {
+               nv10_fragprog_bind(nv10, nv10->fragprog.current);
+               /*XXX: clear NV10_NEW_FRAGPROG if no new program uploaded */
+               nv10->dirty_samplers |= (1<<10);
+               nv10->dirty_samplers = 0;
+       }
+
+       if (nv10->dirty_samplers || (nv10->dirty & NV10_NEW_FRAGPROG)) {
+               nv10_fragtex_bind(nv10);
+               nv10->dirty &= ~NV10_NEW_FRAGPROG;
+       }
+
+       if (nv10->dirty & NV10_NEW_VTXARRAYS) {
+               nv10->dirty &= ~NV10_NEW_VTXARRAYS;
+               nv10_vertex_layout(nv10);
+               nv10_vtxbuf_bind(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_BLEND) {
+               nv10->dirty &= ~NV10_NEW_BLEND;
+               nv10_state_emit_blend(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_BLENDCOL) {
+               nv10->dirty &= ~NV10_NEW_BLENDCOL;
+               nv10_state_emit_blend_color(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_RAST) {
+               nv10->dirty &= ~NV10_NEW_RAST;
+               nv10_state_emit_rast(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_DSA) {
+               nv10->dirty &= ~NV10_NEW_DSA;
+               nv10_state_emit_dsa(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_VIEWPORT) {
+               nv10->dirty &= ~NV10_NEW_VIEWPORT;
+               nv10_state_emit_viewport(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_SCISSOR) {
+               nv10->dirty &= ~NV10_NEW_SCISSOR;
+               nv10_state_emit_scissor(nv10);
+       }
+
+       if (nv10->dirty & NV10_NEW_FRAMEBUFFER) {
+               nv10->dirty &= ~NV10_NEW_FRAMEBUFFER;
+               nv10_state_emit_framebuffer(nv10);
+       }
+
+       /* Emit relocs for every referenced buffer.
+        * This is to ensure the bufmgr has an accurate idea of how
+        * the buffer is used.  This isn't very efficient, but we don't
+        * seem to take a significant performance hit.  Will be improved
+        * at some point.  Vertex arrays are emitted by nv10_vbo.c
+        */
+
+       /* Render target */
+// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly
+//     BEGIN_RING(celsius, NV10TCL_DMA_COLOR0, 1);
+//     OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1);
+       OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       if (nv10->zeta) {
+// XXX
+//             BEGIN_RING(celsius, NV10TCL_DMA_ZETA, 1);
+//             OUT_RELOCo(nv10->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+               BEGIN_RING(celsius, NV10TCL_ZETA_OFFSET, 1);
+               OUT_RELOCl(nv10->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+               /* XXX for when we allocate LMA on nv17 */
+/*             BEGIN_RING(celsius, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1);
+               OUT_RELOCl(nv10->zeta + lma_offset);*/
+       }
+
+       /* Vertex buffer */
+       BEGIN_RING(celsius, NV10TCL_DMA_VTXBUF0, 1);
+       OUT_RELOCo(nv10->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       BEGIN_RING(celsius, NV10TCL_COLOR_OFFSET, 1);
+       OUT_RELOCl(nv10->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       /* Texture images */
+       for (i = 0; i < 2; i++) {
+               if (!(nv10->fp_samplers & (1 << i)))
+                       continue;
+               BEGIN_RING(celsius, NV10TCL_TX_OFFSET(i), 1);
+               OUT_RELOCl(nv10->tex[i].buffer, 0, NOUVEAU_BO_VRAM |
+                          NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+               BEGIN_RING(celsius, NV10TCL_TX_FORMAT(i), 1);
+               OUT_RELOCd(nv10->tex[i].buffer, nv10->tex[i].format,
+                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
+                          NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0,
+                          NV10TCL_TX_FORMAT_DMA1);
+       }
+}
+
diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c
new file mode 100644 (file)
index 0000000..2e230eb
--- /dev/null
@@ -0,0 +1,65 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "nv10_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/p_tile.h"
+
+static void
+nv10_surface_copy(struct pipe_context *pipe, unsigned do_flip,
+                 struct pipe_surface *dest, unsigned destx, unsigned desty,
+                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
+                 unsigned width, unsigned height)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       struct nouveau_winsys *nvws = nv10->nvws;
+
+       nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+                          width, height);
+}
+
+static void
+nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+                 unsigned destx, unsigned desty, unsigned width,
+                 unsigned height, unsigned value)
+{
+       struct nv10_context *nv10 = nv10_context(pipe);
+       struct nouveau_winsys *nvws = nv10->nvws;
+
+       nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+void
+nv10_init_surface_functions(struct nv10_context *nv10)
+{
+       nv10->pipe.surface_copy = nv10_surface_copy;
+       nv10->pipe.surface_fill = nv10_surface_fill;
+}
diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c
new file mode 100644 (file)
index 0000000..f024f53
--- /dev/null
@@ -0,0 +1,78 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv10_draw_elements( struct pipe_context *pipe,
+                    struct pipe_buffer *indexBuffer,
+                    unsigned indexSize,
+                    unsigned prim, unsigned start, unsigned count)
+{
+       struct nv10_context *nv10 = nv10_context( pipe );
+       struct draw_context *draw = nv10->draw;
+       unsigned i;
+
+       nv10_emit_hw_state(nv10);
+
+       /*
+        * Map vertex buffers
+        */
+       for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+               if (nv10->vtxbuf[i].buffer) {
+                       void *buf
+                               = pipe->winsys->buffer_map(pipe->winsys,
+                                               nv10->vtxbuf[i].buffer,
+                                               PIPE_BUFFER_USAGE_CPU_READ);
+                       draw_set_mapped_vertex_buffer(draw, i, buf);
+               }
+       }
+       /* Map index buffer, if present */
+       if (indexBuffer) {
+               void *mapped_indexes
+                       = pipe->winsys->buffer_map(pipe->winsys, indexBuffer,
+                                       PIPE_BUFFER_USAGE_CPU_READ);
+               draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+       }
+       else {
+               /* no index/element buffer */
+               draw_set_mapped_element_buffer(draw, 0, NULL);
+       }
+
+       draw_set_mapped_constant_buffer(draw,
+                                       nv10->constbuf[PIPE_SHADER_VERTEX],
+                                       nv10->constbuf_nr[PIPE_SHADER_VERTEX]);
+
+       /* draw! */
+       draw_arrays(nv10->draw, prim, start, count);
+
+       /*
+        * unmap vertex/index buffers
+        */
+       for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+               if (nv10->vtxbuf[i].buffer) {
+                       pipe->winsys->buffer_unmap(pipe->winsys, nv10->vtxbuf[i].buffer);
+                       draw_set_mapped_vertex_buffer(draw, i, NULL);
+               }
+       }
+       if (indexBuffer) {
+               pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer);
+               draw_set_mapped_element_buffer(draw, 0, NULL);
+       }
+
+       return TRUE;
+}
+
+boolean nv10_draw_arrays( struct pipe_context *pipe,
+                                unsigned prim, unsigned start, unsigned count)
+{
+       return nv10_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile
new file mode 100644 (file)
index 0000000..69f2790
--- /dev/null
@@ -0,0 +1,37 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv30
+
+DRIVER_SOURCES = \
+       nv30_clear.c \
+       nv30_context.c \
+       nv30_draw.c \
+       nv30_fragprog.c \
+       nv30_fragtex.c \
+       nv30_miptree.c \
+       nv30_query.c \
+       nv30_screen.c \
+       nv30_state.c \
+       nv30_state_blend.c \
+       nv30_state_emit.c \
+       nv30_state_fb.c \
+       nv30_state_rasterizer.c \
+       nv30_state_scissor.c \
+       nv30_state_stipple.c \
+       nv30_state_viewport.c \
+       nv30_state_zsa.c \
+       nv30_surface.c \
+       nv30_vbo.c \
+       nv30_vertprog.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c
new file mode 100644 (file)
index 0000000..8c3ca20
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv30_context.h"
+
+void
+nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+          unsigned clearValue)
+{
+       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+       ps->status = PIPE_SURFACE_STATUS_CLEAR;
+}
diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c
new file mode 100644 (file)
index 0000000..eefc614
--- /dev/null
@@ -0,0 +1,73 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_util.h"
+
+#include "nv30_context.h"
+#include "nv30_screen.h"
+
+static void
+nv30_flush(struct pipe_context *pipe, unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       
+       if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
+               BEGIN_RING(rankine, 0x1fd8, 1);
+               OUT_RING  (2);
+               BEGIN_RING(rankine, 0x1fd8, 1);
+               OUT_RING  (1);
+       }
+
+       FIRE_RING(fence);
+}
+
+static void
+nv30_destroy(struct pipe_context *pipe)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       if (nv30->draw)
+               draw_destroy(nv30->draw);
+       FREE(nv30);
+}
+
+struct pipe_context *
+nv30_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+       struct nv30_screen *screen = nv30_screen(pscreen);
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv30_context *nv30;
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nv30 = CALLOC(1, sizeof(struct nv30_context));
+       if (!nv30)
+               return NULL;
+       nv30->screen = screen;
+       nv30->pctx_id = pctx_id;
+
+       nv30->nvws = nvws;
+
+       nv30->pipe.winsys = ws;
+       nv30->pipe.screen = pscreen;
+       nv30->pipe.destroy = nv30_destroy;
+       nv30->pipe.draw_arrays = nv30_draw_arrays;
+       nv30->pipe.draw_elements = nv30_draw_elements;
+       nv30->pipe.clear = nv30_clear;
+       nv30->pipe.flush = nv30_flush;
+
+       nv30_init_query_functions(nv30);
+       nv30_init_surface_functions(nv30);
+       nv30_init_state_functions(nv30);
+
+       /* Create, configure, and install fallback swtnl path */
+       nv30->draw = draw_create();
+       draw_wide_point_threshold(nv30->draw, 9999999.0);
+       draw_wide_line_threshold(nv30->draw, 9999999.0);
+       draw_enable_line_stipple(nv30->draw, FALSE);
+       draw_enable_point_sprites(nv30->draw, FALSE);
+       draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30));
+
+       return &nv30->pipe;
+}
+       
diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h
new file mode 100644 (file)
index 0000000..823b34a
--- /dev/null
@@ -0,0 +1,208 @@
+#ifndef __NV30_CONTEXT_H__
+#define __NV30_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \
+       struct nv30_screen *ctx = nv30->screen
+#include "nouveau/nouveau_push.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#include "nv30_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+
+enum nv30_state_index {
+       NV30_STATE_FB = 0,
+       NV30_STATE_VIEWPORT = 1,
+       NV30_STATE_BLEND = 2,
+       NV30_STATE_RAST = 3,
+       NV30_STATE_ZSA = 4,
+       NV30_STATE_BCOL = 5,
+       NV30_STATE_CLIP = 6,
+       NV30_STATE_SCISSOR = 7,
+       NV30_STATE_STIPPLE = 8,
+       NV30_STATE_FRAGPROG = 9,
+       NV30_STATE_VERTPROG = 10,
+       NV30_STATE_FRAGTEX0 = 11,
+       NV30_STATE_FRAGTEX1 = 12,
+       NV30_STATE_FRAGTEX2 = 13,
+       NV30_STATE_FRAGTEX3 = 14,
+       NV30_STATE_FRAGTEX4 = 15,
+       NV30_STATE_FRAGTEX5 = 16,
+       NV30_STATE_FRAGTEX6 = 17,
+       NV30_STATE_FRAGTEX7 = 18,
+       NV30_STATE_FRAGTEX8 = 19,
+       NV30_STATE_FRAGTEX9 = 20,
+       NV30_STATE_FRAGTEX10 = 21,
+       NV30_STATE_FRAGTEX11 = 22,
+       NV30_STATE_FRAGTEX12 = 23,
+       NV30_STATE_FRAGTEX13 = 24,
+       NV30_STATE_FRAGTEX14 = 25,
+       NV30_STATE_FRAGTEX15 = 26,
+       NV30_STATE_VERTTEX0 = 27,
+       NV30_STATE_VERTTEX1 = 28,
+       NV30_STATE_VERTTEX2 = 29,
+       NV30_STATE_VERTTEX3 = 30,
+       NV30_STATE_VTXBUF = 31,
+       NV30_STATE_VTXFMT = 32,
+       NV30_STATE_VTXATTR = 33,
+       NV30_STATE_MAX = 34
+};
+
+#include "nv30_screen.h"
+
+#define NV30_NEW_BLEND         (1 <<  0)
+#define NV30_NEW_RAST          (1 <<  1)
+#define NV30_NEW_ZSA           (1 <<  2)
+#define NV30_NEW_SAMPLER       (1 <<  3)
+#define NV30_NEW_FB            (1 <<  4)
+#define NV30_NEW_STIPPLE       (1 <<  5)
+#define NV30_NEW_SCISSOR       (1 <<  6)
+#define NV30_NEW_VIEWPORT      (1 <<  7)
+#define NV30_NEW_BCOL          (1 <<  8)
+#define NV30_NEW_VERTPROG      (1 <<  9)
+#define NV30_NEW_FRAGPROG      (1 << 10)
+#define NV30_NEW_ARRAYS                (1 << 11)
+#define NV30_NEW_UCP           (1 << 12)
+
+struct nv30_rasterizer_state {
+       struct pipe_rasterizer_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv30_zsa_state {
+       struct pipe_depth_stencil_alpha_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv30_blend_state {
+       struct pipe_blend_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+
+struct nv30_state {
+       unsigned scissor_enabled;
+       unsigned stipple_enabled;
+       unsigned viewport_bypass;
+       unsigned fp_samplers;
+
+       uint64_t dirty;
+       struct nouveau_stateobj *hw[NV30_STATE_MAX];
+};
+
+struct nv30_context {
+       struct pipe_context pipe;
+
+       struct nouveau_winsys *nvws;
+       struct nv30_screen *screen;
+       unsigned pctx_id;
+
+       struct draw_context *draw;
+
+       /* HW state derived from pipe states */
+       struct nv30_state state;
+
+       /* Context state */
+       unsigned dirty;
+       struct pipe_scissor_state scissor;
+       unsigned stipple[32];
+       struct nv30_vertex_program *vertprog;
+       struct nv30_fragment_program *fragprog;
+       struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+       unsigned constbuf_nr[PIPE_SHADER_TYPES];
+       struct nv30_rasterizer_state *rasterizer;
+       struct nv30_zsa_state *zsa;
+       struct nv30_blend_state *blend;
+       struct pipe_blend_color blend_colour;
+       struct pipe_viewport_state viewport;
+       struct pipe_framebuffer_state framebuffer;
+       struct pipe_buffer *idxbuf;
+       unsigned idxbuf_format;
+       struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+       struct nv30_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+       unsigned nr_samplers;
+       unsigned nr_textures;
+       unsigned dirty_samplers;
+       struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+       unsigned vtxbuf_nr;
+       struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+       unsigned vtxelt_nr;
+       const unsigned *edgeflags;
+};
+
+static INLINE struct nv30_context *
+nv30_context(struct pipe_context *pipe)
+{
+       return (struct nv30_context *)pipe;
+}
+
+struct nv30_state_entry {
+       boolean (*validate)(struct nv30_context *nv30);
+       struct {
+               unsigned pipe;
+               unsigned hw;
+       } dirty;
+};
+
+extern void nv30_init_state_functions(struct nv30_context *nv30);
+extern void nv30_init_surface_functions(struct nv30_context *nv30);
+extern void nv30_init_query_functions(struct nv30_context *nv30);
+
+extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv30_draw.c */
+extern struct draw_stage *nv30_draw_render_stage(struct nv30_context *nv30);
+
+/* nv30_vertprog.c */
+extern void nv30_vertprog_destroy(struct nv30_context *,
+                                 struct nv30_vertex_program *);
+
+/* nv30_fragprog.c */
+extern void nv30_fragprog_destroy(struct nv30_context *,
+                                 struct nv30_fragment_program *);
+
+/* nv30_fragtex.c */
+extern void nv30_fragtex_bind(struct nv30_context *);
+
+/* nv30_state.c and friends */
+extern boolean nv30_state_validate(struct nv30_context *nv30);
+extern void nv30_state_emit(struct nv30_context *nv30);
+extern struct nv30_state_entry nv30_state_rasterizer;
+extern struct nv30_state_entry nv30_state_scissor;
+extern struct nv30_state_entry nv30_state_stipple;
+extern struct nv30_state_entry nv30_state_fragprog;
+extern struct nv30_state_entry nv30_state_vertprog;
+extern struct nv30_state_entry nv30_state_blend;
+extern struct nv30_state_entry nv30_state_blend_colour;
+extern struct nv30_state_entry nv30_state_zsa;
+extern struct nv30_state_entry nv30_state_viewport;
+extern struct nv30_state_entry nv30_state_framebuffer;
+extern struct nv30_state_entry nv30_state_fragtex;
+extern struct nv30_state_entry nv30_state_vbo;
+
+/* nv30_vbo.c */
+extern boolean nv30_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+extern boolean nv30_draw_elements(struct pipe_context *pipe,
+                                 struct pipe_buffer *indexBuffer,
+                                 unsigned indexSize,
+                                 unsigned mode, unsigned start,
+                                 unsigned count);
+
+/* nv30_clear.c */
+extern void nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+                      unsigned clearValue);
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c
new file mode 100644 (file)
index 0000000..aeeaf58
--- /dev/null
@@ -0,0 +1,62 @@
+#include "draw/draw_pipe.h"
+#include "pipe/p_util.h"
+
+#include "nv30_context.h"
+
+struct nv30_draw_stage {
+       struct draw_stage draw;
+       struct nv30_context *nv30;
+};
+
+static void
+nv30_draw_point(struct draw_stage *draw, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_line(struct draw_stage *draw, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_tri(struct draw_stage *draw, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_flush(struct draw_stage *draw, unsigned flags)
+{
+}
+
+static void
+nv30_draw_reset_stipple_counter(struct draw_stage *draw)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv30_draw_destroy(struct draw_stage *draw)
+{
+       FREE(draw);
+}
+
+struct draw_stage *
+nv30_draw_render_stage(struct nv30_context *nv30)
+{
+       struct nv30_draw_stage *nv30draw = CALLOC_STRUCT(nv30_draw_stage);
+
+       nv30draw->nv30 = nv30;
+       nv30draw->draw.draw = nv30->draw;
+       nv30draw->draw.point = nv30_draw_point;
+       nv30draw->draw.line = nv30_draw_line;
+       nv30draw->draw.tri = nv30_draw_tri;
+       nv30draw->draw.flush = nv30_draw_flush;
+       nv30draw->draw.reset_stipple_counter = nv30_draw_reset_stipple_counter;
+       nv30draw->draw.destroy = nv30_draw_destroy;
+
+       return &nv30draw->draw;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c
new file mode 100644 (file)
index 0000000..59e79d6
--- /dev/null
@@ -0,0 +1,898 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv30_context.h"
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 1
+#define MASK_Y 2
+#define MASK_Z 4
+#define MASK_W 8
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE NV30_FP_OP_DST_SCALE_1X
+#define DEF_CTEST NV30_FP_OP_COND_TR
+#include "nv30_shader.h"
+
+#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv30_sr_neg((s))
+#define abs(s) nv30_sr_abs((s))
+#define scale(s,v) nv30_sr_scale((s), NV30_FP_OP_DST_SCALE_##v)
+
+#define MAX_CONSTS 128
+#define MAX_IMM 32
+struct nv30_fpc {
+       struct nv30_fragment_program *fp;
+
+       uint attrib_map[PIPE_MAX_SHADER_INPUTS];
+
+       int high_temp;
+       int temp_temp_count;
+       int num_regs;
+
+       uint depth_id;
+       uint colour_id;
+
+       unsigned inst_offset;
+
+       struct {
+               int pipe;
+               float vals[4];
+       } consts[MAX_CONSTS];
+       int nr_consts;
+
+       struct nv30_sreg imm[MAX_IMM];
+       unsigned nr_imm;
+};
+
+static INLINE struct nv30_sreg
+temp(struct nv30_fpc *fpc)
+{
+       int idx;
+
+       idx  = fpc->temp_temp_count++;
+       idx += fpc->high_temp + 1;
+       return nv30_sr(NV30SR_TEMP, idx);
+}
+
+static INLINE struct nv30_sreg
+constant(struct nv30_fpc *fpc, int pipe, float vals[4])
+{
+       int idx;
+
+       if (fpc->nr_consts == MAX_CONSTS)
+               assert(0);
+       idx = fpc->nr_consts++;
+
+       fpc->consts[idx].pipe = pipe;
+       if (pipe == -1)
+               memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
+       return nv30_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+       nv30_fp_arith((cc), (s), NV30_FP_OP_OPCODE_##o, \
+                       (d), (m), (s0), (s1), (s2))
+#define tex(cc,s,o,u,d,m,s0,s1,s2) \
+       nv30_fp_tex((cc), (s), NV30_FP_OP_OPCODE_##o, (u), \
+                   (d), (m), (s0), none, none)
+
+static void
+grow_insns(struct nv30_fpc *fpc, int size)
+{
+       struct nv30_fragment_program *fp = fpc->fp;
+
+       fp->insn_len += size;
+       fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
+}
+
+static void
+emit_src(struct nv30_fpc *fpc, int pos, struct nv30_sreg src)
+{
+       struct nv30_fragment_program *fp = fpc->fp;
+       uint32_t *hw = &fp->insn[fpc->inst_offset];
+       uint32_t sr = 0;
+
+       switch (src.type) {
+       case NV30SR_INPUT:
+               sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+               hw[0] |= (src.index << NV30_FP_OP_INPUT_SRC_SHIFT);
+               break;
+       case NV30SR_OUTPUT:
+               sr |= NV30_FP_REG_SRC_HALF;
+               /* fall-through */
+       case NV30SR_TEMP:
+               sr |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT);
+               sr |= (src.index << NV30_FP_REG_SRC_SHIFT);
+               break;
+       case NV30SR_CONST:
+               grow_insns(fpc, 4);
+               hw = &fp->insn[fpc->inst_offset];
+               if (fpc->consts[src.index].pipe >= 0) {
+                       struct nv30_fragment_program_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 = fpc->consts[src.index].pipe;
+                       memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
+               } else {
+                       memcpy(&fp->insn[fpc->inst_offset + 4],
+                               fpc->consts[src.index].vals,
+                               sizeof(uint32_t) * 4);
+               }
+
+               sr |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT);       
+               break;
+       case NV30SR_NONE:
+               sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT);
+               break;
+       default:
+               assert(0);
+       }
+
+       if (src.negate)
+               sr |= NV30_FP_REG_NEGATE;
+
+       if (src.abs)
+               hw[1] |= (1 << (29 + pos));
+
+       sr |= ((src.swz[0] << NV30_FP_REG_SWZ_X_SHIFT) |
+              (src.swz[1] << NV30_FP_REG_SWZ_Y_SHIFT) |
+              (src.swz[2] << NV30_FP_REG_SWZ_Z_SHIFT) |
+              (src.swz[3] << NV30_FP_REG_SWZ_W_SHIFT));
+
+       hw[pos + 1] |= sr;
+}
+
+static void
+emit_dst(struct nv30_fpc *fpc, struct nv30_sreg dst)
+{
+       struct nv30_fragment_program *fp = fpc->fp;
+       uint32_t *hw = &fp->insn[fpc->inst_offset];
+
+       switch (dst.type) {
+       case NV30SR_TEMP:
+               if (fpc->num_regs < (dst.index + 1))
+                       fpc->num_regs = dst.index + 1;
+               break;
+       case NV30SR_OUTPUT:
+               if (dst.index == 1) {
+                       fp->fp_control |= 0xe;
+               } else {
+                       hw[0] |= NV30_FP_OP_OUT_REG_HALF;
+               }
+               break;
+       case NV30SR_NONE:
+               hw[0] |= (1 << 30);
+               break;
+       default:
+               assert(0);
+       }
+
+       hw[0] |= (dst.index << NV30_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+nv30_fp_arith(struct nv30_fpc *fpc, int sat, int op,
+             struct nv30_sreg dst, int mask,
+             struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2)
+{
+       struct nv30_fragment_program *fp = fpc->fp;
+       uint32_t *hw;
+
+       fpc->inst_offset = fp->insn_len;
+       grow_insns(fpc, 4);
+       hw = &fp->insn[fpc->inst_offset];
+       memset(hw, 0, sizeof(uint32_t) * 4);
+
+       if (op == NV30_FP_OP_OPCODE_KIL)
+               fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL;
+       hw[0] |= (op << NV30_FP_OP_OPCODE_SHIFT);
+       hw[0] |= (mask << NV30_FP_OP_OUTMASK_SHIFT);
+       hw[2] |= (dst.dst_scale << NV30_FP_OP_DST_SCALE_SHIFT);
+
+       if (sat)
+               hw[0] |= NV30_FP_OP_OUT_SAT;
+
+       if (dst.cc_update)
+               hw[0] |= NV30_FP_OP_COND_WRITE_ENABLE;
+       hw[1] |= (dst.cc_test << NV30_FP_OP_COND_SHIFT);
+       hw[1] |= ((dst.cc_swz[0] << NV30_FP_OP_COND_SWZ_X_SHIFT) |
+                 (dst.cc_swz[1] << NV30_FP_OP_COND_SWZ_Y_SHIFT) |
+                 (dst.cc_swz[2] << NV30_FP_OP_COND_SWZ_Z_SHIFT) |
+                 (dst.cc_swz[3] << NV30_FP_OP_COND_SWZ_W_SHIFT));
+
+       emit_dst(fpc, dst);
+       emit_src(fpc, 0, s0);
+       emit_src(fpc, 1, s1);
+       emit_src(fpc, 2, s2);
+}
+
+static void
+nv30_fp_tex(struct nv30_fpc *fpc, int sat, int op, int unit,
+           struct nv30_sreg dst, int mask,
+           struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2)
+{
+       struct nv30_fragment_program *fp = fpc->fp;
+
+       nv30_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
+
+       fp->insn[fpc->inst_offset] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT);
+       fp->samplers |= (1 << unit);
+}
+
+static INLINE struct nv30_sreg
+tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc)
+{
+       struct nv30_sreg src;
+
+       switch (fsrc->SrcRegister.File) {
+       case TGSI_FILE_INPUT:
+               src = nv30_sr(NV30SR_INPUT,
+                             fpc->attrib_map[fsrc->SrcRegister.Index]);
+               break;
+       case TGSI_FILE_CONSTANT:
+               src = constant(fpc, fsrc->SrcRegister.Index, NULL);
+               break;
+       case TGSI_FILE_IMMEDIATE:
+               assert(fsrc->SrcRegister.Index < fpc->nr_imm);
+               src = fpc->imm[fsrc->SrcRegister.Index];
+               break;
+       case TGSI_FILE_TEMPORARY:
+               src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index + 1);
+               if (fpc->high_temp < src.index)
+                       fpc->high_temp = src.index;
+               break;
+       /* This is clearly insane, but gallium hands us shaders like this.
+        * Luckily fragprog results are just temp regs..
+        */
+       case TGSI_FILE_OUTPUT:
+               if (fsrc->SrcRegister.Index == fpc->colour_id)
+                       return nv30_sr(NV30SR_OUTPUT, 0);
+               else
+                       return nv30_sr(NV30SR_OUTPUT, 1);
+               break;
+       default:
+               NOUVEAU_ERR("bad src file\n");
+               break;
+       }
+
+       src.abs = fsrc->SrcRegisterExtMod.Absolute;
+       src.negate = fsrc->SrcRegister.Negate;
+       src.swz[0] = fsrc->SrcRegister.SwizzleX;
+       src.swz[1] = fsrc->SrcRegister.SwizzleY;
+       src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+       src.swz[3] = fsrc->SrcRegister.SwizzleW;
+       return src;
+}
+
+static INLINE struct nv30_sreg
+tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
+       int idx;
+
+       switch (fdst->DstRegister.File) {
+       case TGSI_FILE_OUTPUT:
+               if (fdst->DstRegister.Index == fpc->colour_id)
+                       return nv30_sr(NV30SR_OUTPUT, 0);
+               else
+                       return nv30_sr(NV30SR_OUTPUT, 1);
+               break;
+       case TGSI_FILE_TEMPORARY:
+               idx = fdst->DstRegister.Index + 1;
+               if (fpc->high_temp < idx)
+                       fpc->high_temp = idx;
+               return nv30_sr(NV30SR_TEMP, idx);
+       case TGSI_FILE_NULL:
+               return nv30_sr(NV30SR_NONE, 0);
+       default:
+               NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
+               return nv30_sr(NV30SR_NONE, 0);
+       }
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+       int mask = 0;
+
+       if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+       if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+       if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+       if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+       return mask;
+}
+
+static boolean
+src_native_swz(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc,
+              struct nv30_sreg *src)
+{
+       const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+       struct nv30_sreg tgsi = tgsi_src(fpc, fsrc);
+       uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+       uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+                       fsrc->SrcRegisterExtSwz.NegateY,
+                       fsrc->SrcRegisterExtSwz.NegateZ,
+                       fsrc->SrcRegisterExtSwz.NegateW };
+       uint c;
+
+       for (c = 0; c < 4; c++) {
+               switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+               case TGSI_EXTSWIZZLE_X:
+               case TGSI_EXTSWIZZLE_Y:
+               case TGSI_EXTSWIZZLE_Z:
+               case TGSI_EXTSWIZZLE_W:
+                       mask |= (1 << c);
+                       break;
+               case TGSI_EXTSWIZZLE_ZERO:
+                       zero_mask |= (1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               case TGSI_EXTSWIZZLE_ONE:
+                       one_mask |= (1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               default:
+                       assert(0);
+               }
+
+               if (!tgsi.negate && neg[c])
+                       neg_mask |= (1 << c);
+       }
+
+       if (mask == MASK_ALL && !neg_mask)
+               return TRUE;
+
+       *src = temp(fpc);
+
+       if (mask)
+               arith(fpc, 0, MOV, *src, mask, tgsi, none, none);
+
+       if (zero_mask)
+               arith(fpc, 0, SFL, *src, zero_mask, *src, none, none);
+
+       if (one_mask)
+               arith(fpc, 0, STR, *src, one_mask, *src, none, none);
+
+       if (neg_mask) {
+               struct nv30_sreg one = temp(fpc);
+               arith(fpc, 0, STR, one, neg_mask, one, none, none);
+               arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none);
+       }
+
+       return FALSE;
+}
+
+static boolean
+nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
+                               const struct tgsi_full_instruction *finst)
+{
+       const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+       struct nv30_sreg src[3], dst, tmp;
+       int mask, sat, unit = 0;
+       int ai = -1, ci = -1;
+       int i;
+
+       if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+               return TRUE;
+
+       fpc->temp_temp_count = 0;
+       for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+               const struct tgsi_full_src_register *fsrc;
+
+               fsrc = &finst->FullSrcRegisters[i];
+               if (fsrc->SrcRegister.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->FullSrcRegisters[i];
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+               case TGSI_FILE_CONSTANT:
+               case TGSI_FILE_TEMPORARY:
+                       if (!src_native_swz(fpc, fsrc, &src[i]))
+                               continue;
+                       break;
+               default:
+                       break;
+               }
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+                       if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+                               ai = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(fpc, fsrc);
+                       } else {
+                               NOUVEAU_MSG("extra src attr %d\n",
+                                        fsrc->SrcRegister.Index);
+                               src[i] = temp(fpc);
+                               arith(fpc, 0, MOV, src[i], MASK_ALL,
+                                     tgsi_src(fpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_CONSTANT:
+               case TGSI_FILE_IMMEDIATE:
+                       if (ci == -1 || ci == fsrc->SrcRegister.Index) {
+                               ci = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(fpc, fsrc);
+                       } else {
+                               src[i] = temp(fpc);
+                               arith(fpc, 0, MOV, src[i], MASK_ALL,
+                                     tgsi_src(fpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_TEMPORARY:
+                       /* handled above */
+                       break;
+               case TGSI_FILE_SAMPLER:
+                       unit = fsrc->SrcRegister.Index;
+                       break;
+               case TGSI_FILE_OUTPUT:
+                       break;
+               default:
+                       NOUVEAU_ERR("bad src file\n");
+                       return FALSE;
+               }
+       }
+
+       dst  = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
+       mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+       sat  = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+
+       switch (finst->Instruction.Opcode) {
+       case TGSI_OPCODE_ABS:
+               arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
+               break;
+       case TGSI_OPCODE_ADD:
+               arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_CMP:
+               tmp = temp(fpc);
+               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+               tmp.cc_update = 1;
+               arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+               dst.cc_test = NV30_VP_INST_COND_LT;
+               arith(fpc, sat, MOV, dst, mask, src[1], none, none);
+               break;
+       case TGSI_OPCODE_COS:
+               arith(fpc, sat, COS, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_DP3:
+               arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DP4:
+               arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DPH:
+               tmp = temp(fpc);
+               arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none);
+               arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
+                     swz(src[1], W, W, W, W), none);
+               break;
+       case TGSI_OPCODE_DST:
+               arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_EX2:
+               arith(fpc, sat, EX2, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FLR:
+               arith(fpc, sat, FLR, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FRC:
+               arith(fpc, sat, FRC, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_KIL:
+               arith(fpc, 0, KIL, none, 0, none, none, none);
+               break;
+       case TGSI_OPCODE_KILP:
+               dst = nv30_sr(NV30SR_NONE, 0);
+               dst.cc_update = 1;
+               arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
+               dst.cc_update = 0; dst.cc_test = NV30_FP_OP_COND_LT;
+               arith(fpc, 0, KIL, dst, 0, none, none, none);
+               break;
+       case TGSI_OPCODE_LG2:
+               arith(fpc, sat, LG2, dst, mask, src[0], none, none);
+               break;
+//     case TGSI_OPCODE_LIT:
+       case TGSI_OPCODE_LRP:
+               arith(fpc, sat, LRP, dst, mask, src[0], src[1], src[2]);
+               break;
+       case TGSI_OPCODE_MAD:
+               arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
+               break;
+       case TGSI_OPCODE_MAX:
+               arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MIN:
+               arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MOV:
+               arith(fpc, sat, MOV, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_MUL:
+               arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_POW:
+               arith(fpc, sat, POW, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_RCP:
+               arith(fpc, sat, RCP, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_RET:
+               assert(0);
+               break;
+       case TGSI_OPCODE_RFL:
+               arith(fpc, 0, RFL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_RSQ:
+               arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none);
+               break;
+       case TGSI_OPCODE_SCS:
+               if (mask & MASK_X) {
+                       arith(fpc, sat, COS, dst, MASK_X,
+                             swz(src[0], X, X, X, X), none, none);
+               }
+               if (mask & MASK_Y) {
+                       arith(fpc, sat, SIN, dst, MASK_Y,
+                             swz(src[0], X, X, X, X), none, none);
+               }
+               break;
+       case TGSI_OPCODE_SIN:
+               arith(fpc, sat, SIN, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_SGE:
+               arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SLT:
+               arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SUB:
+               arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
+               break;
+       case TGSI_OPCODE_TEX:
+               tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_TXB:
+               tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_TXP:
+               tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_XPD:
+               tmp = temp(fpc);
+               arith(fpc, 0, MUL, tmp, mask,
+                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+               arith(fpc, sat, MAD, dst, (mask & ~MASK_W),
+                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+                     neg(tmp));
+               break;
+       default:
+               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static boolean
+nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       int hw;
+
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               hw = NV30_FP_OP_INPUT_SRC_POSITION;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV30_FP_OP_INPUT_SRC_COL0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV30_FP_OP_INPUT_SRC_COL1;
+               } else {
+                       NOUVEAU_ERR("bad colour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_FOG:
+               hw = NV30_FP_OP_INPUT_SRC_FOGC;
+               break;
+       case TGSI_SEMANTIC_GENERIC:
+               if (fdec->Semantic.SemanticIndex <= 7) {
+                       hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic.
+                                                    SemanticIndex);
+               } else {
+                       NOUVEAU_ERR("bad generic semantic index\n");
+                       return FALSE;
+               }
+               break;
+       default:
+               NOUVEAU_ERR("bad input semantic\n");
+               return FALSE;
+       }
+
+       fpc->attrib_map[fdec->DeclarationRange.First] = hw;
+       return TRUE;
+}
+
+static boolean
+nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               fpc->depth_id = fdec->DeclarationRange.First;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               fpc->colour_id = fdec->DeclarationRange.First;
+               break;
+       default:
+               NOUVEAU_ERR("bad output semantic\n");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static boolean
+nv30_fragprog_prepare(struct nv30_fpc *fpc)
+{
+       struct tgsi_parse_context p;
+       /*int high_temp = -1, i;*/
+
+       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 (!nv30_fragprog_parse_decl_attrib(fpc, fdec))
+                                       goto out_err;
+                               break;
+                       case TGSI_FILE_OUTPUT:
+                               if (!nv30_fragprog_parse_decl_output(fpc, fdec))
+                                       goto out_err;
+                               break;
+                       /*case TGSI_FILE_TEMPORARY:
+                               if (fdec->DeclarationRange.Last > high_temp) {
+                                       high_temp =
+                                               fdec->DeclarationRange.Last;
+                               }
+                               break;*/
+                       default:
+                               break;
+                       }
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_IMMEDIATE:
+               {
+                       struct tgsi_full_immediate *imm;
+                       float vals[4];
+                       
+                       imm = &p.FullToken.FullImmediate;
+                       assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+                       assert(fpc->nr_imm < MAX_IMM);
+
+                       vals[0] = imm->u.ImmediateFloat32[0].Float;
+                       vals[1] = imm->u.ImmediateFloat32[1].Float;
+                       vals[2] = imm->u.ImmediateFloat32[2].Float;
+                       vals[3] = imm->u.ImmediateFloat32[3].Float;
+                       fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+       tgsi_parse_free(&p);
+
+       /*if (++high_temp) {
+               fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg));
+               for (i = 0; i < high_temp; i++)
+                       fpc->r_temp[i] = temp(fpc);
+               fpc->r_temps_discard = 0;
+       }*/
+
+       return TRUE;
+
+out_err:
+       /*if (fpc->r_temp)
+               FREE(fpc->r_temp);*/
+       tgsi_parse_free(&p);
+       return FALSE;
+}
+
+static void
+nv30_fragprog_translate(struct nv30_context *nv30,
+                       struct nv30_fragment_program *fp)
+{
+       struct tgsi_parse_context parse;
+       struct nv30_fpc *fpc = NULL;
+
+       fpc = CALLOC(1, sizeof(struct nv30_fpc));
+       if (!fpc)
+               return;
+       fpc->fp = fp;
+       fpc->high_temp = -1;
+       fpc->num_regs = 2;
+
+       if (!nv30_fragprog_prepare(fpc)) {
+               FREE(fpc);
+               return;
+       }
+
+       tgsi_parse_init(&parse, fp->pipe.tokens);
+
+       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;
+
+                       finst = &parse.FullToken.FullInstruction;
+                       if (!nv30_fragprog_parse_instruction(fpc, finst))
+                               goto out_err;
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       fp->fp_control |= (fpc->num_regs-1)/2;
+       fp->fp_reg_control = (1<<16)|0x4;
+
+       /* Terminate final instruction */
+       fp->insn[fpc->inst_offset] |= 0x00000001;
+
+       /* Append NOP + END instruction, may or may not be necessary. */
+       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;
+       
+       fp->translated = TRUE;
+       fp->on_hw = FALSE;
+out_err:
+       tgsi_parse_free(&parse);
+       FREE(fpc);
+}
+
+static void
+nv30_fragprog_upload(struct nv30_context *nv30,
+                    struct nv30_fragment_program *fp)
+{
+       struct pipe_winsys *ws = nv30->pipe.winsys;
+       const uint32_t le = 1;
+       uint32_t *map;
+       int i;
+
+       map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+       for (i = 0; i < fp->insn_len; i++) {
+               fflush(stdout); fflush(stderr);
+               NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+               fflush(stdout); fflush(stderr);
+       }
+#endif
+
+       if ((*(const uint8_t *)&le)) {
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = fp->insn[i];
+               }
+       } else {
+               /* Weird swapping for big-endian chips */
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = ((fp->insn[i] & 0xffff) << 16) |
+                                 ((fp->insn[i] >> 16) & 0xffff);
+               }
+       }
+
+       ws->buffer_unmap(ws, fp->buffer);
+}
+
+static boolean
+nv30_fragprog_validate(struct nv30_context *nv30)
+{
+       struct nv30_fragment_program *fp = nv30->fragprog;
+       struct pipe_buffer *constbuf =
+               nv30->constbuf[PIPE_SHADER_FRAGMENT];
+       struct pipe_winsys *ws = nv30->pipe.winsys;
+       struct nouveau_stateobj *so;
+       boolean new_consts = FALSE;
+       int i;
+
+       if (fp->translated)
+               goto update_constants;
+
+       /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/
+       nv30_fragprog_translate(nv30, fp);
+       if (!fp->translated) {
+               /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/
+               return FALSE;
+       }
+
+       fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+       nv30_fragprog_upload(nv30, fp);
+
+       so = so_new(6, 1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
+       so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                 NV34TCL_FP_ACTIVE_PROGRAM_DMA0, NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1);
+       so_data  (so, fp->fp_control);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1);
+       so_data  (so, fp->fp_reg_control);
+       so_ref(so, &fp->so);
+
+update_constants:
+       if (fp->nr_consts) {
+               float *map;
+               
+               map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
+               for (i = 0; i < fp->nr_consts; i++) {
+                       struct nv30_fragment_program_data *fpd = &fp->consts[i];
+                       uint32_t *p = &fp->insn[fpd->offset];
+                       uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+                       if (!memcmp(p, cb, 4 * sizeof(float)))
+                               continue;
+                       memcpy(p, cb, 4 * sizeof(float));
+                       new_consts = TRUE;
+               }
+               ws->buffer_unmap(ws, constbuf);
+
+               if (new_consts)
+                       nv30_fragprog_upload(nv30, fp);
+       }
+
+       if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) {
+               so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+nv30_fragprog_destroy(struct nv30_context *nv30,
+                     struct nv30_fragment_program *fp)
+{
+       if (fp->insn_len)
+               FREE(fp->insn);
+}
+
+struct nv30_state_entry nv30_state_fragprog = {
+       .validate = nv30_fragprog_validate,
+       .dirty = {
+               .pipe = NV30_NEW_FRAGPROG,
+               .hw = NV30_STATE_FRAGPROG
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
new file mode 100644 (file)
index 0000000..4242f86
--- /dev/null
@@ -0,0 +1,183 @@
+#include "nv30_context.h"
+
+static INLINE int log2i(int i)
+{
+       int r = 0;
+
+       if (i & 0xffff0000) {
+               i >>= 16;
+               r += 16;
+       }
+       if (i & 0x0000ff00) {
+               i >>= 8;
+               r += 8;
+       }
+       if (i & 0x000000f0) {
+               i >>= 4;
+               r += 4;
+       }
+       if (i & 0x0000000c) {
+               i >>= 2;
+               r += 2;
+       }
+       if (i & 0x00000002) {
+               r += 1;
+       }
+       return r;
+}
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                        \
+{                                                                              \
+  TRUE,                                                                        \
+  PIPE_FORMAT_##m,                                                             \
+  NV34TCL_TX_FORMAT_FORMAT_##tf,                                               \
+  (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |           \
+   NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |           \
+   NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |           \
+   NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w),           \
+}
+
+struct nv30_texture_format {
+       boolean defined;
+       uint    pipe;
+       int     format;
+       int     swizzle;
+};
+
+static struct nv30_texture_format
+nv30_texture_formats[] = {
+       _(A8R8G8B8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(A1R5G5B5_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(A4R4G4B4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(R5G6B5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
+       _(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X),
+       _(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X),
+       _(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X),
+       _(A8L8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y),
+//     _(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X),
+//     _(Z24S8_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X),
+       _(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
+       _(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       {},
+};
+
+static struct nv30_texture_format *
+nv30_fragtex_format(uint pipe_format)
+{
+       struct nv30_texture_format *tf = nv30_texture_formats;
+       char fs[128];
+
+       while (tf->defined) {
+               if (tf->pipe == pipe_format)
+                       return tf;
+               tf++;
+       }
+
+       pf_sprint_name(fs, pipe_format);
+       NOUVEAU_ERR("unknown texture format %s\n", fs);
+       return NULL;
+}
+
+
+static struct nouveau_stateobj *
+nv30_fragtex_build(struct nv30_context *nv30, int unit)
+{
+       struct nv30_sampler_state *ps = nv30->tex_sampler[unit];
+       struct nv30_miptree *nv30mt = nv30->tex_miptree[unit];
+       struct pipe_texture *pt = &nv30mt->base;
+       struct nv30_texture_format *tf;
+       struct nouveau_stateobj *so;
+       uint32_t txf, txs /*, txp*/;
+       /*int swizzled = 0;*/ /*XXX: implement in region code? */
+       unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+       tf = nv30_fragtex_format(pt->format);
+       if (!tf)
+               assert(0);
+
+       txf  = tf->format;
+       txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
+       txf |= log2i(pt->width[0]) << 20;
+       txf |= log2i(pt->height[0]) << 24;
+       txf |= log2i(pt->depth[0]) << 28;
+       txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
+
+       switch (pt->target) {
+       case PIPE_TEXTURE_CUBE:
+               txf |= NV34TCL_TX_FORMAT_CUBIC;
+               /* fall-through */
+       case PIPE_TEXTURE_2D:
+               txf |= NV34TCL_TX_FORMAT_DIMS_2D;
+               break;
+       case PIPE_TEXTURE_3D:
+               txf |= NV34TCL_TX_FORMAT_DIMS_3D;
+               break;
+       case PIPE_TEXTURE_1D:
+               txf |= NV34TCL_TX_FORMAT_DIMS_1D;
+               break;
+       default:
+               NOUVEAU_ERR("Unknown target %d\n", pt->target);
+               return NULL;
+       }
+
+       txs = tf->swizzle;
+
+       so = so_new(16, 2);
+       so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8);
+       so_reloc (so, nv30mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+       so_reloc (so, nv30mt->buffer, txf, tex_flags | NOUVEAU_BO_OR,
+                 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
+       so_data  (so, ps->wrap);
+       so_data  (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
+       so_data  (so, txs);
+       so_data  (so, ps->filt | 0x2000 /*voodoo*/);
+       so_data  (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
+                      pt->height[0]);
+       so_data  (so, ps->bcol);
+
+       return so;
+}
+
+static boolean
+nv30_fragtex_validate(struct nv30_context *nv30)
+{
+       struct nv30_fragment_program *fp = nv30->fragprog;
+       struct nv30_state *state = &nv30->state;
+       struct nouveau_stateobj *so;
+       unsigned samplers, unit;
+
+       samplers = state->fp_samplers & ~fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               so = so_new(2, 0);
+               so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1);
+               so_data  (so, 0);
+               so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
+               state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
+       }
+
+       samplers = nv30->dirty_samplers & fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               so = nv30_fragtex_build(nv30, unit);
+               so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
+               state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
+       }
+
+       nv30->state.fp_samplers = fp->samplers;
+       return FALSE;
+}
+
+struct nv30_state_entry nv30_state_fragtex = {
+       .validate = nv30_fragtex_validate,
+       .dirty = {
+               .pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG,
+               .hw = 0
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c
new file mode 100644 (file)
index 0000000..a0e488c
--- /dev/null
@@ -0,0 +1,163 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv30_context.h"
+
+static void
+nv30_miptree_layout(struct nv30_miptree *nv30mt)
+{
+       struct pipe_texture *pt = &nv30mt->base;
+       boolean swizzled = FALSE;
+       uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+       uint offset = 0;
+       int nr_faces, l, f, pitch;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               nr_faces = 6;
+       } else
+       if (pt->target == PIPE_TEXTURE_3D) {
+               nr_faces = pt->depth[0];
+       } else {
+               nr_faces = 1;
+       }
+       
+       pitch = pt->width[0];
+       for (l = 0; l <= pt->last_level; l++) {
+               pt->width[l] = width;
+               pt->height[l] = height;
+               pt->depth[l] = depth;
+               pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+               pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+               if (swizzled)
+                       pitch = pt->nblocksx[l];
+               pitch = align_int(pitch, 64);
+
+               nv30mt->level[l].pitch = pitch * pt->block.size;
+               nv30mt->level[l].image_offset =
+                       CALLOC(nr_faces, sizeof(unsigned));
+
+               width  = MAX2(1, width  >> 1);
+               height = MAX2(1, height >> 1);
+               depth  = MAX2(1, depth  >> 1);
+       }
+
+       for (f = 0; f < nr_faces; f++) {
+               for (l = 0; l <= pt->last_level; l++) {
+                       nv30mt->level[l].image_offset[f] = offset;
+                       offset += nv30mt->level[l].pitch * pt->height[l];
+               }
+       }
+
+       nv30mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv30_miptree *mt;
+
+       mt = MALLOC(sizeof(struct nv30_miptree));
+       if (!mt)
+               return NULL;
+       mt->base = *pt;
+       mt->base.refcount = 1;
+       mt->base.screen = pscreen;
+
+       nv30_miptree_layout(mt);
+
+       mt->buffer = ws->buffer_create(ws, 256,
+                                      PIPE_BUFFER_USAGE_PIXEL |
+                                      NOUVEAU_BUFFER_USAGE_TEXTURE,
+                                      mt->total_size);
+       if (!mt->buffer) {
+               FREE(mt);
+               return NULL;
+       }
+
+       return &mt->base;
+}
+
+static void
+nv30_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct pipe_texture *mt = *pt;
+
+       *pt = NULL;
+       if (--mt->refcount <= 0) {
+               struct nv30_miptree *nv30mt = (struct nv30_miptree *)mt;
+               int l;
+
+               pipe_buffer_reference(ws, &nv30mt->buffer, NULL);
+               for (l = 0; l <= mt->last_level; l++) {
+                       if (nv30mt->level[l].image_offset)
+                               FREE(nv30mt->level[l].image_offset);
+               }
+               FREE(nv30mt);
+       }
+}
+
+static struct pipe_surface *
+nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt;
+       struct pipe_surface *ps;
+
+       ps = CALLOC_STRUCT(pipe_surface);
+       if (!ps)
+               return NULL;
+       pipe_texture_reference(&ps->texture, pt);
+       pipe_buffer_reference(ws, &ps->buffer, nv30mt->buffer);
+       ps->format = pt->format;
+       ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->block = pt->block;
+       ps->nblocksx = pt->nblocksx[level];
+       ps->nblocksy = pt->nblocksy[level];
+       ps->stride = nv30mt->level[level].pitch;
+       ps->usage = flags;
+       ps->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               ps->offset = nv30mt->level[level].image_offset[face];
+       } else
+       if (pt->target == PIPE_TEXTURE_3D) {
+               ps->offset = nv30mt->level[level].image_offset[zslice];
+       } else {
+               ps->offset = nv30mt->level[level].image_offset[0];
+       }
+
+       return ps;
+}
+
+static void
+nv30_miptree_surface_del(struct pipe_screen *pscreen,
+                        struct pipe_surface **psurface)
+{
+       struct pipe_surface *ps = *psurface;
+
+       *psurface = NULL;
+       if (--ps->refcount > 0)
+               return;
+
+       pipe_texture_reference(&ps->texture, NULL);
+       pipe_buffer_reference(pscreen->winsys, &ps->buffer, NULL);
+       FREE(ps);
+}
+
+void
+nv30_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+       pscreen->texture_create = nv30_miptree_create;
+       pscreen->texture_release = nv30_miptree_release;
+       pscreen->get_tex_surface = nv30_miptree_surface_new;
+       pscreen->tex_surface_release = nv30_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c
new file mode 100644 (file)
index 0000000..d40d75f
--- /dev/null
@@ -0,0 +1,122 @@
+#include "pipe/p_context.h"
+
+#include "nv30_context.h"
+
+struct nv30_query {
+       struct nouveau_resource *object;
+       unsigned type;
+       boolean ready;
+       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 query_type)
+{
+       struct nv30_query *q;
+
+       q = CALLOC(1, sizeof(struct nv30_query));
+       q->type = query_type;
+
+       return (struct pipe_query *)q;
+}
+
+static void
+nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_query *q = nv30_query(pq);
+
+       if (q->object)
+               nv30->nvws->res_free(&q->object);
+       FREE(q);
+}
+
+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);
+
+       assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+       /* Happens when end_query() is called, then another begin_query()
+        * without querying the result in-between.  For now we'll wait for
+        * the existing query to notify completion, but it could be better.
+        */
+       if (q->object) {
+               uint64 tmp;
+               pipe->get_query_result(pipe, pq, 1, &tmp);
+       }
+
+       if (nv30->nvws->res_alloc(nv30->screen->query_heap, 1, NULL, &q->object))
+               assert(0);
+       nv30->nvws->notifier_reset(nv30->screen->query, q->object->start);
+
+       BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1);
+       OUT_RING  (1);
+       BEGIN_RING(rankine, NV34TCL_QUERY_UNK17CC, 1);
+       OUT_RING  (1);
+
+       q->ready = FALSE;
+}
+
+static void
+nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_query *q = nv30_query(pq);
+
+       BEGIN_RING(rankine, NV34TCL_QUERY_GET, 1);
+       OUT_RING  ((0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) |
+                  ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT));
+       FIRE_RING(NULL);
+}
+
+static boolean
+nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+                 boolean wait, uint64 *result)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_query *q = nv30_query(pq);
+       struct nouveau_winsys *nvws = nv30->nvws;
+
+       assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+       if (!q->ready) {
+               unsigned status;
+
+               status = nvws->notifier_status(nv30->screen->query,
+                                              q->object->start);
+               if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
+                       if (wait == FALSE)
+                               return FALSE;
+                       nvws->notifier_wait(nv30->screen->query, q->object->start,
+                                           NV_NOTIFY_STATE_STATUS_COMPLETED,
+                                           0);
+               }
+
+               q->result = nvws->notifier_retval(nv30->screen->query,
+                                                 q->object->start);
+               q->ready = TRUE;
+               nvws->res_free(&q->object);
+       }
+
+       *result = q->result;
+       return TRUE;
+}
+
+void
+nv30_init_query_functions(struct nv30_context *nv30)
+{
+       nv30->pipe.create_query = nv30_query_create;
+       nv30->pipe.destroy_query = nv30_query_destroy;
+       nv30->pipe.begin_query = nv30_query_begin;
+       nv30->pipe.end_query = nv30_query_end;
+       nv30->pipe.get_query_result = nv30_query_result;
+}
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
new file mode 100644 (file)
index 0000000..b216a70
--- /dev/null
@@ -0,0 +1,332 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv30_context.h"
+#include "nv30_screen.h"
+
+#define NV30TCL_CHIPSET_3X_MASK 0x00000003
+#define NV34TCL_CHIPSET_3X_MASK 0x00000010
+#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
+
+static const char *
+nv30_screen_get_name(struct pipe_screen *pscreen)
+{
+       struct nv30_screen *screen = nv30_screen(pscreen);
+       struct nouveau_device *dev = screen->nvws->channel->device;
+       static char buffer[128];
+
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+       return buffer;
+}
+
+static const char *
+nv30_screen_get_vendor(struct pipe_screen *pscreen)
+{
+       return "nouveau";
+}
+
+static int
+nv30_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+               return 16;
+       case PIPE_CAP_NPOT_TEXTURES:
+               return 0;
+       case PIPE_CAP_TWO_SIDED_STENCIL:
+               return 1;
+       case PIPE_CAP_GLSL:
+               return 0;
+       case PIPE_CAP_S3TC:
+               return 0;
+       case PIPE_CAP_ANISOTROPIC_FILTER:
+               return 1;
+       case PIPE_CAP_POINT_SPRITE:
+               return 1;
+       case PIPE_CAP_MAX_RENDER_TARGETS:
+               return 2;
+       case PIPE_CAP_OCCLUSION_QUERY:
+               return 1;
+       case PIPE_CAP_TEXTURE_SHADOW_MAP:
+               return 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 NOUVEAU_CAP_HW_VTXBUF:
+       case NOUVEAU_CAP_HW_IDXBUF:
+               return 1;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0;
+       }
+}
+
+static float
+nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_LINE_WIDTH:
+       case PIPE_CAP_MAX_LINE_WIDTH_AA:
+               return 10.0;
+       case PIPE_CAP_MAX_POINT_WIDTH:
+       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+               return 64.0;
+       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+               return 8.0;
+       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+               return 4.0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0.0;
+       }
+}
+
+static boolean
+nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
+                                    enum pipe_format format, uint type)
+{
+       switch (type) {
+       case PIPE_SURFACE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_Z24S8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       case PIPE_TEXTURE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_A1R5G5B5_UNORM:
+               case PIPE_FORMAT_A4R4G4B4_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+               case PIPE_FORMAT_I8_UNORM:
+               case PIPE_FORMAT_A8L8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+               case PIPE_FORMAT_Z24S8_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       default:
+               assert(0);
+       };
+
+       return FALSE;
+}
+
+static void *
+nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+                unsigned flags )
+{
+       struct pipe_winsys *ws = screen->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, surface->buffer, flags);
+       if (!map)
+               return NULL;
+
+       return map + surface->offset;
+}
+
+static void
+nv30_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+       struct pipe_winsys *ws = screen->winsys;
+
+       ws->buffer_unmap(ws, surface->buffer);
+}
+
+static void
+nv30_screen_destroy(struct pipe_screen *pscreen)
+{
+       struct nv30_screen *screen = nv30_screen(pscreen);
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nvws->res_free(&screen->vp_exec_heap);
+       nvws->res_free(&screen->vp_data_heap);
+       nvws->res_free(&screen->query_heap);
+       nvws->notifier_free(&screen->query);
+       nvws->notifier_free(&screen->sync);
+       nvws->grobj_free(&screen->rankine);
+
+       FREE(pscreen);
+}
+
+struct pipe_screen *
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+       struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
+       struct nouveau_stateobj *so;
+       unsigned rankine_class = 0;
+       unsigned chipset = nvws->channel->device->chipset;
+       int ret, i;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       /* 3D object */
+       switch (chipset & 0xf0) {
+       case 0x30:
+               if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0397;
+               else
+               if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0697;
+               else
+               if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
+                       rankine_class = 0x0497;
+               break;
+       default:
+               break;
+       }
+
+       if (!rankine_class) {
+               NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", chipset);
+               return NULL;
+       }
+
+       ret = nvws->grobj_alloc(nvws, rankine_class, &screen->rankine);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               return FALSE;
+       }
+
+       /* Notifier for sync purposes */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Query objects */
+       ret = nvws->notifier_alloc(nvws, 32, &screen->query);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       ret = nvws->res_init(&screen->query_heap, 0, 32);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Vtxprog resources */
+       if (nvws->res_init(&screen->vp_exec_heap, 0, 256) ||
+           nvws->res_init(&screen->vp_data_heap, 0, 256)) {
+               nv30_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Static rankine initialisation */
+       so = so_new(128, 0);
+       so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1);
+       so_data  (so, screen->sync->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+/*     so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2);
+       so_data  (so, 0);
+       so_data  (so, screen->query->handle);*/
+       so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1);
+       so_data  (so, nvws->channel->vram->handle);
+
+       for (i=1; i<8; i++) {
+               so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+               so_data  (so, 0);
+               so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, screen->rankine, 0x220, 1);
+       so_data  (so, 1);
+
+       so_method(so, screen->rankine, 0x03b0, 1);
+       so_data  (so, 0x00100000);
+       so_method(so, screen->rankine, 0x1454, 1);
+       so_data  (so, 0);
+       so_method(so, screen->rankine, 0x1d80, 1);
+       so_data  (so, 3);
+       so_method(so, screen->rankine, 0x1450, 1);
+       so_data  (so, 0x00030004);
+       
+       /* NEW */
+       so_method(so, screen->rankine, 0x1e98, 1);
+       so_data  (so, 0);
+       so_method(so, screen->rankine, 0x17e0, 3);
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(1.0));
+       so_method(so, screen->rankine, 0x1f80, 16);
+       for (i=0; i<16; i++) {
+               so_data  (so, (i==8) ? 0x0000ffff : 0);
+       }
+
+       so_method(so, screen->rankine, 0x120, 3);
+       so_data  (so, 0);
+       so_data  (so, 1);
+       so_data  (so, 2);
+
+       so_method(so, screen->rankine, 0x1d88, 1);
+       so_data  (so, 0x00001200);
+
+       so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1);
+       so_data  (so, 0);
+
+       so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2);
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(1.0));
+
+       so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
+       so_data  (so, 0xffff0000);
+
+       /* enables use of vp rather than fixed-function somehow */
+       so_method(so, screen->rankine, 0x1e94, 1);
+       so_data  (so, 0x13);
+
+       so_emit(nvws, so);
+       so_ref(NULL, &so);
+       nvws->push_flush(nvws, 0, NULL);
+
+       screen->pipe.winsys = ws;
+       screen->pipe.destroy = nv30_screen_destroy;
+
+       screen->pipe.get_name = nv30_screen_get_name;
+       screen->pipe.get_vendor = nv30_screen_get_vendor;
+       screen->pipe.get_param = nv30_screen_get_param;
+       screen->pipe.get_paramf = nv30_screen_get_paramf;
+
+       screen->pipe.is_format_supported = nv30_screen_surface_format_supported;
+
+       screen->pipe.surface_map = nv30_surface_map;
+       screen->pipe.surface_unmap = nv30_surface_unmap;
+
+       nv30_screen_init_miptree_functions(&screen->pipe);
+
+       return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h
new file mode 100644 (file)
index 0000000..b7ddc2a
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __NV30_SCREEN_H__
+#define __NV30_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv30_screen {
+       struct pipe_screen pipe;
+
+       struct nouveau_winsys *nvws;
+
+       unsigned cur_pctx;
+
+       /* HW graphics objects */
+       struct nouveau_grobj *rankine;
+       struct nouveau_notifier *sync;
+
+       /* Query object resources */
+       struct nouveau_notifier *query;
+       struct nouveau_resource *query_heap;
+
+       /* Vtxprog resources */
+       struct nouveau_resource *vp_exec_heap;
+       struct nouveau_resource *vp_data_heap;
+
+       /* Current 3D state of channel */
+       struct nouveau_stateobj *state[NV30_STATE_MAX];
+};
+
+static INLINE struct nv30_screen *
+nv30_screen(struct pipe_screen *screen)
+{
+       return (struct nv30_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_shader.h b/src/gallium/drivers/nv30/nv30_shader.h
new file mode 100644 (file)
index 0000000..dd3a36f
--- /dev/null
@@ -0,0 +1,490 @@
+#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 */
+
+#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      (0xF << 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_FL  0 /* guess */  
+#  define NV30_VP_INST_COND_LT  1  
+#  define NV30_VP_INST_COND_EQ  2
+#  define NV30_VP_INST_COND_LE  3
+#  define NV30_VP_INST_COND_GT  4
+#  define NV30_VP_INST_COND_NE  5
+#  define NV30_VP_INST_COND_GE  6
+#  define NV30_VP_INST_COND_TR  7 /* guess */
+#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_OP_NOP  0x00
+#  define NV30_VP_INST_OP_RCP  0x02
+#  define NV30_VP_INST_OP_RCC  0x03
+#  define NV30_VP_INST_OP_RSQ  0x04
+#  define NV30_VP_INST_OP_EXP  0x05
+#  define NV30_VP_INST_OP_LOG  0x06
+#  define NV30_VP_INST_OP_LIT  0x07
+#  define NV30_VP_INST_OP_BRA  0x09
+#  define NV30_VP_INST_OP_CAL  0x0B
+#  define NV30_VP_INST_OP_RET  0x0C
+#  define NV30_VP_INST_OP_LG2  0x0D
+#  define NV30_VP_INST_OP_EX2  0x0E
+#  define NV30_VP_INST_OP_SIN  0x0F
+#  define NV30_VP_INST_OP_COS  0x10
+#define NV30_VP_INST_VEC_OPCODE_SHIFT        23
+#define NV30_VP_INST_VEC_OPCODE_MASK        (0x1F << 23)
+#  define NV30_VP_INST_OP_NOPV  0x00
+#  define NV30_VP_INST_OP_MOV  0x01
+#  define NV30_VP_INST_OP_MUL  0x02
+#  define NV30_VP_INST_OP_ADD  0x03
+#  define NV30_VP_INST_OP_MAD  0x04
+#  define NV30_VP_INST_OP_DP3  0x05
+#  define NV30_VP_INST_OP_DP4  0x07
+#  define NV30_VP_INST_OP_DPH  0x06
+#  define NV30_VP_INST_OP_DST  0x08
+#  define NV30_VP_INST_OP_MIN  0x09
+#  define NV30_VP_INST_OP_MAX  0x0A
+#  define NV30_VP_INST_OP_SLT  0x0B
+#  define NV30_VP_INST_OP_SGE  0x0C
+#  define NV30_VP_INST_OP_ARL  0x0D
+#  define NV30_VP_INST_OP_FRC  0x0E
+#  define NV30_VP_INST_OP_FLR  0x0F
+#  define NV30_VP_INST_OP_SEQ  0x10
+#  define NV30_VP_INST_OP_SFL  0x11
+#  define NV30_VP_INST_OP_SGT  0x12
+#  define NV30_VP_INST_OP_SLE  0x13
+#  define NV30_VP_INST_OP_SNE  0x14
+#  define NV30_VP_INST_OP_STR  0x15
+#  define NV30_VP_INST_OP_SSG  0x16
+#  define NV30_VP_INST_OP_ARR  0x17
+#  define NV30_VP_INST_OP_ARA  0x18
+#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_IN_POS  0    /* These seem to match the bindings specified in */
+#  define NV30_VP_INST_IN_WEIGHT  1    /* the ARB_v_p spec (2.14.3.1) */
+#  define NV30_VP_INST_IN_NORMAL  2    
+#  define NV30_VP_INST_IN_COL0  3    /* Should probably confirm them all though */
+#  define NV30_VP_INST_IN_COL1  4
+#  define NV30_VP_INST_IN_FOGC  5
+#  define NV30_VP_INST_IN_TC0  8
+#  define NV30_VP_INST_IN_TC(n)  (8+n)
+#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          (0xF <<  28)   /* 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        (0x0F <<  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_LAST                           (1 << 0)
+
+/* 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 */
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ *   0 - Opcode, output reg/mask, ATTRIB source
+ *   1 - Source 0
+ *   2 - Source 1
+ *   3 - Source 2
+ *
+ * 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
+ */
+
+//== Opcode / Destination selection ==
+#define NV30_FP_OP_PROGRAM_END          (1 << 0)
+#define NV30_FP_OP_OUT_REG_SHIFT        1
+#define NV30_FP_OP_OUT_REG_MASK          (31 << 1)  /* uncertain */
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV30_FP_OP_OUT_REG_HALF          (1 << 7)
+#define NV30_FP_OP_COND_WRITE_ENABLE        (1 << 8)
+#define NV30_FP_OP_OUTMASK_SHIFT        9
+#define NV30_FP_OP_OUTMASK_MASK          (0xF << 9)
+#  define NV30_FP_OP_OUT_X  (1<<9)
+#  define NV30_FP_OP_OUT_Y  (1<<10)
+#  define NV30_FP_OP_OUT_Z  (1<<11)
+#  define NV30_FP_OP_OUT_W  (1<<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV30_FP_OP_INPUT_SRC_SHIFT        13
+#define NV30_FP_OP_INPUT_SRC_MASK        (15 << 13)
+#  define NV30_FP_OP_INPUT_SRC_POSITION  0x0
+#  define NV30_FP_OP_INPUT_SRC_COL0  0x1
+#  define NV30_FP_OP_INPUT_SRC_COL1  0x2
+#  define NV30_FP_OP_INPUT_SRC_FOGC  0x3
+#  define NV30_FP_OP_INPUT_SRC_TC0    0x4
+#  define NV30_FP_OP_INPUT_SRC_TC(n)  (0x4 + n)
+#define NV30_FP_OP_TEX_UNIT_SHIFT        17
+#define NV30_FP_OP_TEX_UNIT_MASK        (0xF << 17) /* guess */
+#define NV30_FP_OP_PRECISION_SHIFT        22
+#define NV30_FP_OP_PRECISION_MASK        (3 << 22)
+#   define NV30_FP_PRECISION_FP32  0
+#   define NV30_FP_PRECISION_FP16  1
+#   define NV30_FP_PRECISION_FX12  2
+#define NV30_FP_OP_OPCODE_SHIFT          24
+#define NV30_FP_OP_OPCODE_MASK          (0x3F << 24)
+#  define NV30_FP_OP_OPCODE_NOP  0x00
+#  define NV30_FP_OP_OPCODE_MOV  0x01
+#  define NV30_FP_OP_OPCODE_MUL  0x02
+#  define NV30_FP_OP_OPCODE_ADD  0x03
+#  define NV30_FP_OP_OPCODE_MAD  0x04
+#  define NV30_FP_OP_OPCODE_DP3  0x05
+#  define NV30_FP_OP_OPCODE_DP4  0x06
+#  define NV30_FP_OP_OPCODE_DST  0x07
+#  define NV30_FP_OP_OPCODE_MIN  0x08
+#  define NV30_FP_OP_OPCODE_MAX  0x09
+#  define NV30_FP_OP_OPCODE_SLT  0x0A
+#  define NV30_FP_OP_OPCODE_SGE  0x0B
+#  define NV30_FP_OP_OPCODE_SLE  0x0C
+#  define NV30_FP_OP_OPCODE_SGT  0x0D
+#  define NV30_FP_OP_OPCODE_SNE  0x0E
+#  define NV30_FP_OP_OPCODE_SEQ  0x0F
+#  define NV30_FP_OP_OPCODE_FRC  0x10
+#  define NV30_FP_OP_OPCODE_FLR  0x11
+#  define NV30_FP_OP_OPCODE_KIL  0x12
+#  define NV30_FP_OP_OPCODE_PK4B   0x13
+#  define NV30_FP_OP_OPCODE_UP4B   0x14
+#  define NV30_FP_OP_OPCODE_DDX  0x15 /* can only write XY */
+#  define NV30_FP_OP_OPCODE_DDY  0x16 /* can only write XY */
+#  define NV30_FP_OP_OPCODE_TEX  0x17
+#  define NV30_FP_OP_OPCODE_TXP  0x18
+#  define NV30_FP_OP_OPCODE_TXD  0x19
+#  define NV30_FP_OP_OPCODE_RCP  0x1A
+#  define NV30_FP_OP_OPCODE_RSQ  0x1B
+#  define NV30_FP_OP_OPCODE_EX2  0x1C
+#  define NV30_FP_OP_OPCODE_LG2  0x1D
+#  define NV30_FP_OP_OPCODE_LIT  0x1E
+#  define NV30_FP_OP_OPCODE_LRP  0x1F
+#  define NV30_FP_OP_OPCODE_STR  0x20 
+#  define NV30_FP_OP_OPCODE_SFL  0x21
+#  define NV30_FP_OP_OPCODE_COS  0x22
+#  define NV30_FP_OP_OPCODE_SIN  0x23
+#  define NV30_FP_OP_OPCODE_PK2H   0x24
+#  define NV30_FP_OP_OPCODE_UP2H   0x25
+#  define NV30_FP_OP_OPCODE_POW  0x26
+#  define NV30_FP_OP_OPCODE_PK4UB  0x27
+#  define NV30_FP_OP_OPCODE_UP4UB  0x28
+#  define NV30_FP_OP_OPCODE_PK2US  0x29
+#  define NV30_FP_OP_OPCODE_UP2US  0x2A
+#  define NV30_FP_OP_OPCODE_DP2A   0x2E
+#  define NV30_FP_OP_OPCODE_TXB  0x31
+#  define NV30_FP_OP_OPCODE_RFL  0x36
+#  define NV30_FP_OP_OPCODE_DIV  0x3A
+#define NV30_FP_OP_OUT_SAT          (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV30_FP_OP_OUT_ABS          (1 << 29)
+#define NV30_FP_OP_COND_SWZ_W_SHIFT        27
+#define NV30_FP_OP_COND_SWZ_W_MASK        (3 << 27)
+#define NV30_FP_OP_COND_SWZ_Z_SHIFT        25
+#define NV30_FP_OP_COND_SWZ_Z_MASK        (3 << 25)
+#define NV30_FP_OP_COND_SWZ_Y_SHIFT        23
+#define NV30_FP_OP_COND_SWZ_Y_MASK        (3 << 23)
+#define NV30_FP_OP_COND_SWZ_X_SHIFT        21
+#define NV30_FP_OP_COND_SWZ_X_MASK        (3 << 21)
+#define NV30_FP_OP_COND_SWZ_ALL_SHIFT        21
+#define NV30_FP_OP_COND_SWZ_ALL_MASK        (0xFF << 21)
+#define NV30_FP_OP_COND_SHIFT          18
+#define NV30_FP_OP_COND_MASK          (0x07 << 18)
+#  define NV30_FP_OP_COND_FL  0
+#  define NV30_FP_OP_COND_LT  1
+#  define NV30_FP_OP_COND_EQ  2
+#  define NV30_FP_OP_COND_LE  3
+#  define NV30_FP_OP_COND_GT  4
+#  define NV30_FP_OP_COND_NE  5
+#  define NV30_FP_OP_COND_GE  6
+#  define NV30_FP_OP_COND_TR  7
+
+/* high order bits of SRC1 */
+#define NV30_FP_OP_DST_SCALE_SHIFT        28
+#define NV30_FP_OP_DST_SCALE_MASK        (3 << 28)
+#define NV30_FP_OP_DST_SCALE_1X                                                0
+#define NV30_FP_OP_DST_SCALE_2X                                                1
+#define NV30_FP_OP_DST_SCALE_4X                                                2
+#define NV30_FP_OP_DST_SCALE_8X                                                3
+#define NV30_FP_OP_DST_SCALE_INV_2X                                            5
+#define NV30_FP_OP_DST_SCALE_INV_4X                                            6
+#define NV30_FP_OP_DST_SCALE_INV_8X                                            7
+
+
+/* high order bits of SRC2 */
+#define NV30_FP_OP_INDEX_INPUT          (1 << 30)
+
+//== Register selection ==
+#define NV30_FP_REG_TYPE_SHIFT          0
+#define NV30_FP_REG_TYPE_MASK          (3 << 0)
+#  define NV30_FP_REG_TYPE_TEMP  0
+#  define NV30_FP_REG_TYPE_INPUT  1
+#  define NV30_FP_REG_TYPE_CONST  2
+#define NV30_FP_REG_SRC_SHIFT          2 /* uncertain */
+#define NV30_FP_REG_SRC_MASK          (31 << 2)
+#define NV30_FP_REG_SRC_HALF          (1 << 8)
+#define NV30_FP_REG_SWZ_ALL_SHIFT        9
+#define NV30_FP_REG_SWZ_ALL_MASK        (255 << 9)
+#define NV30_FP_REG_SWZ_X_SHIFT          9
+#define NV30_FP_REG_SWZ_X_MASK          (3 << 9)
+#define NV30_FP_REG_SWZ_Y_SHIFT          11
+#define NV30_FP_REG_SWZ_Y_MASK          (3 << 11)
+#define NV30_FP_REG_SWZ_Z_SHIFT          13
+#define NV30_FP_REG_SWZ_Z_MASK          (3 << 13)
+#define NV30_FP_REG_SWZ_W_SHIFT          15
+#define NV30_FP_REG_SWZ_W_MASK          (3 << 15)
+#  define NV30_FP_SWIZZLE_X  0
+#  define NV30_FP_SWIZZLE_Y  1
+#  define NV30_FP_SWIZZLE_Z  2
+#  define NV30_FP_SWIZZLE_W  3
+#define NV30_FP_REG_NEGATE          (1 << 17)
+
+#define NV30SR_NONE    0
+#define NV30SR_OUTPUT  1
+#define NV30SR_INPUT   2
+#define NV30SR_TEMP    3
+#define NV30SR_CONST   4
+
+struct nv30_sreg {
+       int type;
+       int index;
+
+       int dst_scale;
+
+       int negate;
+       int abs;
+       int swz[4];
+
+       int cc_update;
+       int cc_update_reg;
+       int cc_test;
+       int cc_test_reg;
+       int cc_swz[4];
+};
+
+static INLINE struct nv30_sreg
+nv30_sr(int type, int index)
+{
+       struct nv30_sreg temp = {
+               .type = type,
+               .index = index,
+               .dst_scale = DEF_SCALE,
+               .abs = 0,
+               .negate = 0,
+               .swz = { 0, 1, 2, 3 },
+               .cc_update = 0,
+               .cc_update_reg = 0,
+               .cc_test = DEF_CTEST,
+               .cc_test_reg = 0,
+               .cc_swz = { 0, 1, 2, 3 },
+       };
+       return temp;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_swz(struct nv30_sreg src, int x, int y, int z, int w)
+{
+       struct nv30_sreg dst = src;
+
+       dst.swz[SWZ_X] = src.swz[x];
+       dst.swz[SWZ_Y] = src.swz[y];
+       dst.swz[SWZ_Z] = src.swz[z];
+       dst.swz[SWZ_W] = src.swz[w];
+       return dst;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_neg(struct nv30_sreg src)
+{
+       src.negate = !src.negate;
+       return src;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_abs(struct nv30_sreg src)
+{
+       src.abs = 1;
+       return src;
+}
+
+static INLINE struct nv30_sreg
+nv30_sr_scale(struct nv30_sreg src, int scale)
+{
+       src.dst_scale = scale;
+       return src;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c
new file mode 100644 (file)
index 0000000..4d6303e
--- /dev/null
@@ -0,0 +1,719 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+static void *
+nv30_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+       struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso));
+       struct nouveau_stateobj *so = so_new(16, 0);
+
+       if (cso->blend_enable) {
+               so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3);
+               so_data  (so, 1);
+               so_data  (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
+                              nvgl_blend_func(cso->rgb_src_factor));
+               so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
+                             nvgl_blend_func(cso->rgb_dst_factor));
+               so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1);
+               so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
+                             nvgl_blend_eqn(cso->rgb_func));
+       } else {
+               so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, rankine, NV34TCL_COLOR_MASK, 1);
+       so_data  (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
+                      ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
+                      ((cso->colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) |
+                      ((cso->colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0)));
+
+       if (cso->logicop_enable) {
+               so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2);
+               so_data  (so, 1);
+               so_data  (so, nvgl_logicop_func(cso->logicop_func));
+       } else {
+               so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, rankine, NV34TCL_DITHER_ENABLE, 1);
+       so_data  (so, cso->dither ? 1 : 0);
+
+       so_ref(so, &bso->so);
+       bso->pipe = *cso;
+       return (void *)bso;
+}
+
+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)
+{
+       struct nv30_blend_state *bso = hwcso;
+
+       so_ref(NULL, &bso->so);
+       FREE(bso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+       unsigned ret;
+
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               ret = NV34TCL_TX_WRAP_S_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_CLAMP:
+               ret = NV34TCL_TX_WRAP_S_CLAMP;
+               break;
+/*     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+               ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+               ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+               ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP;
+               break;*/
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               ret = NV34TCL_TX_WRAP_S_REPEAT;
+               break;
+       }
+
+       return ret >> NV34TCL_TX_WRAP_S_SHIFT;
+}
+
+static void *
+nv30_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+       struct nv30_sampler_state *ps;
+       uint32_t filter = 0;
+
+       ps = MALLOC(sizeof(struct nv30_sampler_state));
+
+       ps->fmt = 0;
+       /* TODO: Not all RECTs formats have this bit set, bits 15-8 of format
+          are the tx format to use. We should store normalized coord flag
+          in sampler state structure, and set appropriate format in
+          nvxx_fragtex_build()
+        */
+       if (!cso->normalized_coords)
+               ps->fmt |= (1<<14) /*NV34TCL_TX_FORMAT_RECT*/;
+
+       ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
+                   (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
+                   (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT));
+
+       ps->en = 0;
+
+       if (cso->max_anisotropy >= 8.0) {
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
+       } else
+       if (cso->max_anisotropy >= 4.0) {
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
+       } else
+       if (cso->max_anisotropy >= 2.0) {
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
+       }
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST;
+               break;
+       }
+
+       switch (cso->min_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST;
+                       break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR;
+                       break;
+               }
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST;
+               break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST;
+                       break;
+               }
+               break;
+       }
+
+       ps->filt = filter;
+
+       {
+               float limit;
+
+               limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+               ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+
+               limit = CLAMP(cso->max_lod, 0.0, 15.0);
+               ps->en |= (int)(limit * 256.0) << 7;
+
+               limit = CLAMP(cso->min_lod, 0.0, 15.0);
+               ps->en |= (int)(limit * 256.0) << 19;
+       }
+
+       if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+               switch (cso->compare_func) {
+               case PIPE_FUNC_NEVER:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER;
+                       break;
+               case PIPE_FUNC_GREATER:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GREATER;
+                       break;
+               case PIPE_FUNC_EQUAL:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_EQUAL;
+                       break;
+               case PIPE_FUNC_GEQUAL:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GEQUAL;
+                       break;
+               case PIPE_FUNC_LESS:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LESS;
+                       break;
+               case PIPE_FUNC_NOTEQUAL:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NOTEQUAL;
+                       break;
+               case PIPE_FUNC_LEQUAL:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LEQUAL;
+                       break;
+               case PIPE_FUNC_ALWAYS:
+                       ps->wrap |= NV34TCL_TX_WRAP_RCOMP_ALWAYS;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+                   (float_to_ubyte(cso->border_color[0]) << 16) |
+                   (float_to_ubyte(cso->border_color[1]) <<  8) |
+                   (float_to_ubyte(cso->border_color[2]) <<  0));
+
+       return (void *)ps;
+}
+
+static void
+nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv30->tex_sampler[unit] = sampler[unit];
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nv30->nr_samplers; unit++) {
+               nv30->tex_sampler[unit] = NULL;
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       nv30->nr_samplers = nr;
+       nv30->dirty |= NV30_NEW_SAMPLER;
+}
+
+static void
+nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void
+nv30_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+                        struct pipe_texture **miptree)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv30->tex_miptree[unit], miptree[unit]);
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nv30->nr_textures; unit++) {
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv30->tex_miptree[unit], NULL);
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       nv30->nr_textures = nr;
+       nv30->dirty |= NV30_NEW_SAMPLER;
+}
+
+static void *
+nv30_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
+       struct nouveau_stateobj *so = so_new(32, 0);
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+
+       /*XXX: ignored:
+        *      light_twoside
+        *      point_smooth -nohw
+        *      multisample
+        */
+
+       so_method(so, rankine, NV34TCL_SHADE_MODEL, 1);
+       so_data  (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT :
+                                      NV34TCL_SHADE_MODEL_SMOOTH);
+
+       so_method(so, rankine, NV34TCL_LINE_WIDTH, 2);
+       so_data  (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+       so_data  (so, cso->line_smooth ? 1 : 0);
+       so_method(so, rankine, NV34TCL_LINE_STIPPLE_ENABLE, 2);
+       so_data  (so, cso->line_stipple_enable ? 1 : 0);
+       so_data  (so, (cso->line_stipple_pattern << 16) |
+                      cso->line_stipple_factor);
+
+       so_method(so, rankine, NV34TCL_POINT_SIZE, 1);
+       so_data  (so, fui(cso->point_size));
+
+       so_method(so, rankine, NV34TCL_POLYGON_MODE_FRONT, 6);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV34TCL_FRONT_FACE_CCW);
+       } else {
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV34TCL_FRONT_FACE_CW);
+       }
+       so_data(so, cso->poly_smooth ? 1 : 0);
+       so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0);
+
+       so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+       so_data  (so, cso->poly_stipple_enable ? 1 : 0);
+
+       so_method(so, rankine, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if (cso->offset_cw || cso->offset_ccw) {
+               so_method(so, rankine, NV34TCL_POLYGON_OFFSET_FACTOR, 2);
+               so_data  (so, fui(cso->offset_scale));
+               so_data  (so, fui(cso->offset_units * 2));
+       }
+
+       so_method(so, rankine, NV34TCL_POINT_SPRITE, 1);
+       if (cso->point_sprite) {
+               unsigned psctl = (1 << 0), i;
+
+               for (i = 0; i < 8; i++) {
+                       if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+                               psctl |= (1 << (8 + i));
+               }
+
+               so_data(so, psctl);
+       } else {
+               so_data(so, 0);
+       }
+
+       so_ref(so, &rsso->so);
+       rsso->pipe = *cso;
+       return (void *)rsso;
+}
+
+static void
+nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->rasterizer = hwcso;
+       nv30->dirty |= NV30_NEW_RAST;
+       /*nv30->draw_dirty |= NV30_NEW_RAST;*/
+}
+
+static void
+nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_rasterizer_state *rsso = hwcso;
+
+       so_ref(NULL, &rsso->so);
+       FREE(rsso);
+}
+
+static void *
+nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
+       struct nouveau_stateobj *so = so_new(32, 0);
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+
+       so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3);
+       so_data  (so, nvgl_comparison_op(cso->depth.func));
+       so_data  (so, cso->depth.writemask ? 1 : 0);
+       so_data  (so, cso->depth.enabled ? 1 : 0);
+
+       so_method(so, rankine, NV34TCL_ALPHA_FUNC_ENABLE, 3);
+       so_data  (so, cso->alpha.enabled ? 1 : 0);
+       so_data  (so, nvgl_comparison_op(cso->alpha.func));
+       so_data  (so, float_to_ubyte(cso->alpha.ref));
+
+       if (cso->stencil[0].enabled) {
+               so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 8);
+               so_data  (so, cso->stencil[0].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[0].write_mask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
+               so_data  (so, cso->stencil[0].ref_value);
+               so_data  (so, cso->stencil[0].value_mask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+       } else {
+               so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       if (cso->stencil[1].enabled) {
+               so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 8);
+               so_data  (so, cso->stencil[1].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[1].write_mask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
+               so_data  (so, cso->stencil[1].ref_value);
+               so_data  (so, cso->stencil[1].value_mask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+       } else {
+               so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_ref(so, &zsaso->so);
+       zsaso->pipe = *cso;
+       return (void *)zsaso;
+}
+
+static void
+nv30_depth_stencil_alpha_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_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_zsa_state *zsaso = hwcso;
+
+       so_ref(NULL, &zsaso->so);
+       FREE(zsaso);
+}
+
+static void *
+nv30_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       /*struct nv30_context *nv30 = nv30_context(pipe);*/
+       struct nv30_vertex_program *vp;
+
+       vp = CALLOC(1, sizeof(struct nv30_vertex_program));
+       vp->pipe = *cso;
+       /*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/
+
+       return (void *)vp;
+}
+
+static void
+nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->vertprog = hwcso;
+       nv30->dirty |= NV30_NEW_VERTPROG;
+       /*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/
+}
+
+static void
+nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_vertex_program *vp = hwcso;
+
+       /*draw_delete_vertex_shader(nv30->draw, vp->draw);*/
+       nv30_vertprog_destroy(nv30, vp);
+       FREE(vp);
+}
+
+static void *
+nv30_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv30_fragment_program *fp;
+
+       fp = CALLOC(1, sizeof(struct nv30_fragment_program));
+       fp->pipe = *cso;
+
+       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+
+       return (void *)fp;
+}
+
+static void
+nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->fragprog = hwcso;
+       nv30->dirty |= NV30_NEW_FRAGPROG;
+}
+
+static void
+nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nv30_fragment_program *fp = hwcso;
+
+       nv30_fragprog_destroy(nv30, fp);
+       FREE(fp);
+}
+
+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_BCOL;
+}
+
+static void
+nv30_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        const struct pipe_constant_buffer *buf )
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->constbuf[shader] = buf->buffer;
+       nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
+
+       if (shader == PIPE_SHADER_VERTEX) {
+               nv30->dirty |= NV30_NEW_VERTPROG;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nv30->dirty |= NV30_NEW_FRAGPROG;
+       }
+}
+
+static void
+nv30_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->framebuffer = *fb;
+       nv30->dirty |= NV30_NEW_FB;
+}
+
+static void
+nv30_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       memcpy(nv30->stipple, stipple->stipple, 4 * 32);
+       nv30->dirty |= NV30_NEW_STIPPLE;
+}
+
+static void
+nv30_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->scissor = *s;
+       nv30->dirty |= NV30_NEW_SCISSOR;
+}
+
+static void
+nv30_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *vpt)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->viewport = *vpt;
+       nv30->dirty |= NV30_NEW_VIEWPORT;
+       /*nv30->draw_dirty |= NV30_NEW_VIEWPORT;*/
+}
+
+static void
+nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count);
+       nv30->vtxbuf_nr = count;
+
+       nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+static void
+nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+                        const struct pipe_vertex_element *ve)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       memcpy(nv30->vtxelt, ve, sizeof(*ve) * count);
+       nv30->vtxelt_nr = count;
+
+       nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+static void
+nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->edgeflags = bitfield;
+       nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+void
+nv30_init_state_functions(struct nv30_context *nv30)
+{
+       nv30->pipe.create_blend_state = nv30_blend_state_create;
+       nv30->pipe.bind_blend_state = nv30_blend_state_bind;
+       nv30->pipe.delete_blend_state = nv30_blend_state_delete;
+
+       nv30->pipe.create_sampler_state = nv30_sampler_state_create;
+       nv30->pipe.bind_sampler_states = nv30_sampler_state_bind;
+       nv30->pipe.delete_sampler_state = nv30_sampler_state_delete;
+       nv30->pipe.set_sampler_textures = nv30_set_sampler_texture;
+
+       nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create;
+       nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind;
+       nv30->pipe.delete_rasterizer_state = nv30_rasterizer_state_delete;
+
+       nv30->pipe.create_depth_stencil_alpha_state =
+               nv30_depth_stencil_alpha_state_create;
+       nv30->pipe.bind_depth_stencil_alpha_state =
+               nv30_depth_stencil_alpha_state_bind;
+       nv30->pipe.delete_depth_stencil_alpha_state =
+               nv30_depth_stencil_alpha_state_delete;
+
+       nv30->pipe.create_vs_state = nv30_vp_state_create;
+       nv30->pipe.bind_vs_state = nv30_vp_state_bind;
+       nv30->pipe.delete_vs_state = nv30_vp_state_delete;
+
+       nv30->pipe.create_fs_state = nv30_fp_state_create;
+       nv30->pipe.bind_fs_state = nv30_fp_state_bind;
+       nv30->pipe.delete_fs_state = nv30_fp_state_delete;
+
+       nv30->pipe.set_blend_color = nv30_set_blend_color;
+       nv30->pipe.set_clip_state = nv30_set_clip_state;
+       nv30->pipe.set_constant_buffer = nv30_set_constant_buffer;
+       nv30->pipe.set_framebuffer_state = nv30_set_framebuffer_state;
+       nv30->pipe.set_polygon_stipple = nv30_set_polygon_stipple;
+       nv30->pipe.set_scissor_state = nv30_set_scissor_state;
+       nv30->pipe.set_viewport_state = nv30_set_viewport_state;
+
+       nv30->pipe.set_edgeflags = nv30_set_edgeflags;
+       nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers;
+       nv30->pipe.set_vertex_elements = nv30_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h
new file mode 100644 (file)
index 0000000..20c5176
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef __NV30_STATE_H__
+#define __NV30_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
+
+struct nv30_sampler_state {
+       uint32_t fmt;
+       uint32_t wrap;
+       uint32_t en;
+       uint32_t filt;
+       uint32_t bcol;
+};
+
+struct nv30_vertex_program_exec {
+       uint32_t data[4];
+       boolean has_branch_offset;
+       int const_index;
+};
+
+struct nv30_vertex_program_data {
+       int index; /* immediates == -1 */
+       float value[4];
+};
+
+struct nv30_vertex_program {
+       struct pipe_shader_state pipe;
+
+       boolean translated;
+
+       struct nv30_vertex_program_exec *insns;
+       unsigned nr_insns;
+       struct nv30_vertex_program_data *consts;
+       unsigned nr_consts;
+
+       struct nouveau_resource *exec;
+       unsigned exec_start;
+       struct nouveau_resource *data;
+       unsigned data_start;
+       unsigned data_start_min;
+
+       uint32_t ir;
+       uint32_t or;
+       struct nouveau_stateobj *so;
+};
+
+struct nv30_fragment_program_data {
+       unsigned offset;
+       unsigned index;
+};
+
+struct nv30_fragment_program {
+       struct pipe_shader_state pipe;
+       struct tgsi_shader_info info;
+
+       boolean translated;
+       boolean on_hw;
+       unsigned samplers;
+
+       uint32_t *insn;
+       int       insn_len;
+
+       struct nv30_fragment_program_data *consts;
+       unsigned nr_consts;
+
+       struct pipe_buffer *buffer;
+
+       uint32_t fp_control;
+       uint32_t fp_reg_control;
+       struct nouveau_stateobj *so;
+};
+
+struct nv30_miptree {
+       struct pipe_texture base;
+
+       struct pipe_buffer *buffer;
+       uint total_size;
+
+       struct {
+               uint pitch;
+               uint *image_offset;
+       } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c
new file mode 100644 (file)
index 0000000..44d43e1
--- /dev/null
@@ -0,0 +1,40 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_blend_validate(struct nv30_context *nv30)
+{
+       so_ref(nv30->blend->so, &nv30->state.hw[NV30_STATE_BLEND]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_blend = {
+       .validate = nv30_state_blend_validate,
+       .dirty = {
+               .pipe = NV30_NEW_BLEND,
+               .hw = NV30_STATE_BLEND
+       }
+};
+
+static boolean
+nv30_state_blend_colour_validate(struct nv30_context *nv30)
+{
+       struct nouveau_stateobj *so = so_new(2, 0);
+       struct pipe_blend_color *bcol = &nv30->blend_colour;
+
+       so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1);
+       so_data  (so, ((float_to_ubyte(bcol->color[3]) << 24) |
+                      (float_to_ubyte(bcol->color[0]) << 16) |
+                      (float_to_ubyte(bcol->color[1]) <<  8) |
+                      (float_to_ubyte(bcol->color[2]) <<  0)));
+
+       so_ref(so, &nv30->state.hw[NV30_STATE_BCOL]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_blend_colour = {
+       .validate = nv30_state_blend_colour_validate,
+       .dirty = {
+               .pipe = NV30_NEW_BCOL,
+               .hw = NV30_STATE_BCOL
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c
new file mode 100644 (file)
index 0000000..40fed62
--- /dev/null
@@ -0,0 +1,118 @@
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+static struct nv30_state_entry *render_states[] = {
+       &nv30_state_framebuffer,
+       &nv30_state_rasterizer,
+       &nv30_state_scissor,
+       &nv30_state_stipple,
+       &nv30_state_fragprog,
+       &nv30_state_fragtex,
+       &nv30_state_vertprog,
+       &nv30_state_blend,
+       &nv30_state_blend_colour,
+       &nv30_state_zsa,
+       &nv30_state_viewport,
+       &nv30_state_vbo,
+       NULL
+};
+
+static void
+nv30_state_do_validate(struct nv30_context *nv30,
+                      struct nv30_state_entry **states)
+{
+       const struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+       unsigned i;
+
+       for (i = 0; i < fb->num_cbufs; i++)
+               fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
+       if (fb->zsbuf)
+               fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       while (*states) {
+               struct nv30_state_entry *e = *states;
+
+               if (nv30->dirty & e->dirty.pipe) {
+                       if (e->validate(nv30)) {
+                               nv30->state.dirty |= (1ULL << e->dirty.hw);
+                       }
+               }
+
+               states++;
+       }
+       nv30->dirty = 0;
+}
+
+void
+nv30_state_emit(struct nv30_context *nv30)
+{
+       struct nv30_state *state = &nv30->state;
+       struct nv30_screen *screen = nv30->screen;
+       unsigned i, samplers;
+       uint64 states;
+
+       if (nv30->pctx_id != screen->cur_pctx) {
+               for (i = 0; i < NV30_STATE_MAX; i++) {
+                       if (state->hw[i] && screen->state[i] != state->hw[i])
+                               state->dirty |= (1ULL << i);
+               }
+
+               screen->cur_pctx = nv30->pctx_id;
+       }
+
+       for (i = 0, states = state->dirty; states; i++) {
+               if (!(states & (1ULL << i)))
+                       continue;
+               so_ref (state->hw[i], &nv30->screen->state[i]);
+               if (state->hw[i])
+                       so_emit(nv30->nvws, nv30->screen->state[i]);
+               states &= ~(1ULL << i);
+       }
+
+       state->dirty = 0;
+
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]);
+       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+               if (!(samplers & (1 << i)))
+                       continue;
+               so_emit_reloc_markers(nv30->nvws,
+                                     state->hw[NV30_STATE_FRAGTEX0+i]);
+               samplers &= ~(1ULL << i);
+       }
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]);
+       if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/)
+               so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_VTXBUF]);
+}
+
+boolean
+nv30_state_validate(struct nv30_context *nv30)
+{
+#if 0
+       boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE;
+
+       if (nv30->render_mode != HW) {
+               /* Don't even bother trying to go back to hw if none
+                * of the states that caused swtnl previously have changed.
+                */
+               if ((nv30->fallback_swtnl & nv30->dirty)
+                               != nv30->fallback_swtnl)
+                       return FALSE;
+
+               /* Attempt to go to hwtnl again */
+               nv30->pipe.flush(&nv30->pipe, 0, NULL);
+               nv30->dirty |= (NV30_NEW_VIEWPORT |
+                               NV30_NEW_VERTPROG |
+                               NV30_NEW_ARRAYS);
+               nv30->render_mode = HW;
+       }
+#endif
+       nv30_state_do_validate(nv30, render_states);
+#if 0
+       if (nv30->fallback_swtnl || nv30->fallback_swrast)
+               return FALSE;
+       
+       if (was_sw)
+               NOUVEAU_ERR("swtnl->hw\n");
+#endif
+       return TRUE;
+}
diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c
new file mode 100644 (file)
index 0000000..d93e2bb
--- /dev/null
@@ -0,0 +1,128 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_framebuffer_validate(struct nv30_context *nv30)
+{
+       struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+       struct pipe_surface *rt[2], *zeta = NULL;
+       uint32_t rt_enable, rt_format;
+       int i, colour_format = 0, zeta_format = 0;
+       struct nouveau_stateobj *so = so_new(64, 10);
+       unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+       unsigned w = fb->width;
+       unsigned h = fb->height;
+
+       rt_enable = 0;
+       for (i = 0; i < fb->num_cbufs; i++) {
+               if (colour_format) {
+                       assert(colour_format == fb->cbufs[i]->format);
+               } else {
+                       colour_format = fb->cbufs[i]->format;
+                       rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
+                       rt[i] = fb->cbufs[i];
+               }
+       }
+
+       if (rt_enable & NV34TCL_RT_ENABLE_COLOR1)
+               rt_enable |= NV34TCL_RT_ENABLE_MRT;
+
+       if (fb->zsbuf) {
+               zeta_format = fb->zsbuf->format;
+               zeta = fb->zsbuf;
+       }
+
+       rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;
+
+       switch (colour_format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case 0:
+               rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
+               break;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5;
+               break;
+       default:
+               assert(0);
+       }
+
+       switch (zeta_format) {
+       case PIPE_FORMAT_Z16_UNORM:
+               rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16;
+               break;
+       case PIPE_FORMAT_Z24S8_UNORM:
+       case 0:
+               rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8;
+               break;
+       default:
+               assert(0);
+       }
+
+       if (rt_enable & NV34TCL_RT_ENABLE_COLOR0) {
+               uint32_t pitch = rt[0]->stride;
+               if (zeta) {
+                       pitch |= (zeta->stride << 16);
+               } else {
+                       pitch |= (pitch << 16);
+               }
+
+               so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1);
+               so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv30->nvws->channel->vram->handle,
+                         nv30->nvws->channel->gart->handle);
+               so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2);
+               so_data  (so, pitch);
+               so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+       }
+
+       if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
+               so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1);
+               so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv30->nvws->channel->vram->handle,
+                         nv30->nvws->channel->gart->handle);
+               so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2);
+               so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               so_data  (so, rt[1]->stride);
+       }
+
+       if (zeta_format) {
+               so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1);
+               so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv30->nvws->channel->vram->handle,
+                         nv30->nvws->channel->gart->handle);
+               so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1);
+               so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               /* TODO: allocate LMA depth buffer */
+       }
+
+       so_method(so, nv30->screen->rankine, NV34TCL_RT_ENABLE, 1);
+       so_data  (so, rt_enable);
+       so_method(so, nv30->screen->rankine, NV34TCL_RT_HORIZ, 3);
+       so_data  (so, (w << 16) | 0);
+       so_data  (so, (h << 16) | 0);
+       so_data  (so, rt_format);
+       so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_HORIZ, 2);
+       so_data  (so, (w << 16) | 0);
+       so_data  (so, (h << 16) | 0);
+       so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+       so_data  (so, ((w - 1) << 16) | 0);
+       so_data  (so, ((h - 1) << 16) | 0);
+       so_method(so, nv30->screen->rankine, 0x1d88, 1);
+       so_data  (so, (1 << 12) | h);
+       /* Wonder why this is needed, context should all be set to zero on init */
+       so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
+       so_data  (so, 0);
+
+       so_ref(so, &nv30->state.hw[NV30_STATE_FB]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_framebuffer = {
+       .validate = nv30_state_framebuffer_validate,
+       .dirty = {
+               .pipe = NV30_NEW_FB,
+               .hw = NV30_STATE_FB
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_rasterizer.c b/src/gallium/drivers/nv30/nv30_state_rasterizer.c
new file mode 100644 (file)
index 0000000..6d1b60e
--- /dev/null
@@ -0,0 +1,17 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_rasterizer_validate(struct nv30_context *nv30)
+{
+       so_ref(nv30->rasterizer->so,
+              &nv30->state.hw[NV30_STATE_RAST]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_rasterizer = {
+       .validate = nv30_state_rasterizer_validate,
+       .dirty = {
+               .pipe = NV30_NEW_RAST,
+               .hw = NV30_STATE_RAST
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c
new file mode 100644 (file)
index 0000000..1db9bc1
--- /dev/null
@@ -0,0 +1,35 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_scissor_validate(struct nv30_context *nv30)
+{
+       struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe;
+       struct pipe_scissor_state *s = &nv30->scissor;
+       struct nouveau_stateobj *so;
+
+       if (nv30->state.hw[NV30_STATE_SCISSOR] &&
+           (rast->scissor == 0 && nv30->state.scissor_enabled == 0))
+               return FALSE;
+       nv30->state.scissor_enabled = rast->scissor;
+
+       so = so_new(3, 0);
+       so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2);
+       if (nv30->state.scissor_enabled) {
+               so_data  (so, ((s->maxx - s->minx) << 16) | s->minx);
+               so_data  (so, ((s->maxy - s->miny) << 16) | s->miny);
+       } else {
+               so_data  (so, 4096 << 16);
+               so_data  (so, 4096 << 16);
+       }
+
+       so_ref(so, &nv30->state.hw[NV30_STATE_SCISSOR]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_scissor = {
+       .validate = nv30_state_scissor_validate,
+       .dirty = {
+               .pipe = NV30_NEW_SCISSOR | NV30_NEW_RAST,
+               .hw = NV30_STATE_SCISSOR
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c
new file mode 100644 (file)
index 0000000..41b4281
--- /dev/null
@@ -0,0 +1,39 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_stipple_validate(struct nv30_context *nv30)
+{
+       struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe;
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+       struct nouveau_stateobj *so;
+
+       if (nv30->state.hw[NV30_STATE_STIPPLE] &&
+          (rast->poly_stipple_enable == 0 && nv30->state.stipple_enabled == 0))
+               return FALSE;
+
+       if (rast->poly_stipple_enable) {
+               unsigned i;
+
+               so = so_new(35, 0);
+               so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+               for (i = 0; i < 32; i++)
+                       so_data(so, nv30->stipple[i]);
+       } else {
+               so = so_new(2, 0);
+               so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_ref(so, &nv30->state.hw[NV30_STATE_STIPPLE]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_stipple = {
+       .validate = nv30_state_stipple_validate,
+       .dirty = {
+               .pipe = NV30_NEW_STIPPLE | NV30_NEW_RAST,
+               .hw = NV30_STATE_STIPPLE,
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c
new file mode 100644 (file)
index 0000000..951d40e
--- /dev/null
@@ -0,0 +1,70 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_viewport_validate(struct nv30_context *nv30)
+{
+       struct pipe_viewport_state *vpt = &nv30->viewport;
+       struct nouveau_stateobj *so;
+       unsigned bypass;
+
+       if (/*nv30->render_mode == HW &&*/ !nv30->rasterizer->pipe.bypass_clipping)
+               bypass = 0;
+       else
+               bypass = 1;
+
+       if (nv30->state.hw[NV30_STATE_VIEWPORT] &&
+           (bypass || !(nv30->dirty & NV30_NEW_VIEWPORT)) &&
+           nv30->state.viewport_bypass == bypass)
+               return FALSE;
+       nv30->state.viewport_bypass = bypass;
+
+       so = so_new(11, 0);
+       if (!bypass) {
+               so_method(so, nv30->screen->rankine,
+                         NV34TCL_VIEWPORT_TRANSLATE_X, 8);
+               so_data  (so, fui(vpt->translate[0]));
+               so_data  (so, fui(vpt->translate[1]));
+               so_data  (so, fui(vpt->translate[2]));
+               so_data  (so, fui(vpt->translate[3]));
+               so_data  (so, fui(vpt->scale[0]));
+               so_data  (so, fui(vpt->scale[1]));
+               so_data  (so, fui(vpt->scale[2]));
+               so_data  (so, fui(vpt->scale[3]));
+/*             so_method(so, nv30->screen->rankine, 0x1d78, 1);
+               so_data  (so, 1);
+*/     } else {
+               so_method(so, nv30->screen->rankine,
+                         NV34TCL_VIEWPORT_TRANSLATE_X, 8);
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(0.0));
+               /* Not entirely certain what this is yet.  The DDX uses this
+                * value also as it fixes rendering when you pass
+                * pre-transformed vertices to the GPU.  My best gusss is that
+                * this bypasses some culling/clipping stage.  Might be worth
+                * noting that points/lines are uneffected by whatever this
+                * value fixes, only filled polygons are effected.
+                */
+/*             so_method(so, nv30->screen->rankine, 0x1d78, 1);
+               so_data  (so, 0x110);
+*/     }
+       /* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */
+       so_method(so, nv30->screen->rankine, 0x1d78, 1);
+       so_data  (so, 1);
+
+       so_ref(so, &nv30->state.hw[NV30_STATE_VIEWPORT]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_viewport = {
+       .validate = nv30_state_viewport_validate,
+       .dirty = {
+               .pipe = NV30_NEW_VIEWPORT | NV30_NEW_RAST,
+               .hw = NV30_STATE_VIEWPORT
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_state_zsa.c b/src/gallium/drivers/nv30/nv30_state_zsa.c
new file mode 100644 (file)
index 0000000..0940b72
--- /dev/null
@@ -0,0 +1,17 @@
+#include "nv30_context.h"
+
+static boolean
+nv30_state_zsa_validate(struct nv30_context *nv30)
+{
+       so_ref(nv30->zsa->so,
+              &nv30->state.hw[NV30_STATE_ZSA]);
+       return TRUE;
+}
+
+struct nv30_state_entry nv30_state_zsa = {
+       .validate = nv30_state_zsa_validate,
+       .dirty = {
+               .pipe = NV30_NEW_ZSA,
+               .hw = NV30_STATE_ZSA
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c
new file mode 100644 (file)
index 0000000..b22211a
--- /dev/null
@@ -0,0 +1,77 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "nv30_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/p_tile.h"
+
+static void
+nv30_surface_copy(struct pipe_context *pipe, unsigned do_flip,
+                 struct pipe_surface *dest, unsigned destx, unsigned desty,
+                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
+                 unsigned width, unsigned height)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nouveau_winsys *nvws = nv30->nvws;
+
+       if (do_flip) {
+               /*XXX: This dodgyness will do for now for correctness.  But,
+                *     need to investigate whether the 2D engine is able to
+                *     manage a flip (perhaps SIFM?), if not, use the 3D engine
+                */
+               desty += height;
+               while (height--) {
+                       nvws->surface_copy(nvws, dest, destx, desty--, src,
+                                          srcx, srcy++, width, 1);
+               }
+       } else {
+               nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+                                  width, height);
+       }
+}
+
+static void
+nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+                 unsigned destx, unsigned desty, unsigned width,
+                 unsigned height, unsigned value)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nouveau_winsys *nvws = nv30->nvws;
+
+       nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+void
+nv30_init_surface_functions(struct nv30_context *nv30)
+{
+       nv30->pipe.surface_copy = nv30_surface_copy;
+       nv30->pipe.surface_fill = nv30_surface_fill;
+}
diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c
new file mode 100644 (file)
index 0000000..d930557
--- /dev/null
@@ -0,0 +1,561 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+#include "nouveau/nouveau_util.h"
+
+#define FORCE_SWTNL 0
+
+static INLINE int
+nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
+{
+       char fs[128];
+
+       switch (pipe) {
+       case PIPE_FORMAT_R32_FLOAT:
+       case PIPE_FORMAT_R32G32_FLOAT:
+       case PIPE_FORMAT_R32G32B32_FLOAT:
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+               *fmt = NV34TCL_VTXFMT_TYPE_FLOAT;
+               break;
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R8G8_UNORM:
+       case PIPE_FORMAT_R8G8B8_UNORM:
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+               *fmt = NV34TCL_VTXFMT_TYPE_UBYTE;
+               break;
+       case PIPE_FORMAT_R16_SSCALED:
+       case PIPE_FORMAT_R16G16_SSCALED:
+       case PIPE_FORMAT_R16G16B16_SSCALED:
+       case PIPE_FORMAT_R16G16B16A16_SSCALED:
+               *fmt = NV34TCL_VTXFMT_TYPE_USHORT;
+               break;
+       default:
+               pf_sprint_name(fs, pipe);
+               NOUVEAU_ERR("Unknown format %s\n", fs);
+               return 1;
+       }
+
+       switch (pipe) {
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R32_FLOAT:
+       case PIPE_FORMAT_R16_SSCALED:
+               *ncomp = 1;
+               break;
+       case PIPE_FORMAT_R8G8_UNORM:
+       case PIPE_FORMAT_R32G32_FLOAT:
+       case PIPE_FORMAT_R16G16_SSCALED:
+               *ncomp = 2;
+               break;
+       case PIPE_FORMAT_R8G8B8_UNORM:
+       case PIPE_FORMAT_R32G32B32_FLOAT:
+       case PIPE_FORMAT_R16G16B16_SSCALED:
+               *ncomp = 3;
+               break;
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+       case PIPE_FORMAT_R16G16B16A16_SSCALED:
+               *ncomp = 4;
+               break;
+       default:
+               pf_sprint_name(fs, pipe);
+               NOUVEAU_ERR("Unknown format %s\n", fs);
+               return 1;
+       }
+
+       return 0;
+}
+
+static boolean
+nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib,
+                   unsigned ib_size)
+{
+       struct pipe_screen *pscreen = &nv30->screen->pipe;
+       unsigned type;
+
+       if (!ib) {
+               nv30->idxbuf = NULL;
+               nv30->idxbuf_format = 0xdeadbeef;
+               return FALSE;
+       }
+
+       if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
+               return FALSE;
+
+       switch (ib_size) {
+       case 2:
+               type = NV34TCL_IDXBUF_FORMAT_TYPE_U16;
+               break;
+       case 4:
+               type = NV34TCL_IDXBUF_FORMAT_TYPE_U32;
+               break;
+       default:
+               return FALSE;
+       }
+
+       if (ib != nv30->idxbuf ||
+           type != nv30->idxbuf_format) {
+               nv30->dirty |= NV30_NEW_ARRAYS;
+               nv30->idxbuf = ib;
+               nv30->idxbuf_format = type;
+       }
+
+       return TRUE;
+}
+
+static boolean
+nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so,
+                      int attrib, struct pipe_vertex_element *ve,
+                      struct pipe_vertex_buffer *vb)
+{
+       struct pipe_winsys *ws = nv30->pipe.winsys;
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+       unsigned type, ncomp;
+       void *map;
+
+       if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp))
+               return FALSE;
+
+       map  = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+       map += vb->buffer_offset + ve->src_offset;
+
+       switch (type) {
+       case NV34TCL_VTXFMT_TYPE_FLOAT:
+       {
+               float *v = map;
+
+               switch (ncomp) {
+               case 4:
+                       so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       so_data  (so, fui(v[2]));
+                       so_data  (so, fui(v[3]));
+                       break;
+               case 3:
+                       so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       so_data  (so, fui(v[2]));
+                       break;
+               case 2:
+                       so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       break;
+               case 1:
+                       so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1);
+                       so_data  (so, fui(v[0]));
+                       break;
+               default:
+                       ws->buffer_unmap(ws, vb->buffer);
+                       return FALSE;
+               }
+       }
+               break;
+       default:
+               ws->buffer_unmap(ws, vb->buffer);
+               return FALSE;
+       }
+
+       ws->buffer_unmap(ws, vb->buffer);
+
+       return TRUE;
+}
+
+boolean
+nv30_draw_arrays(struct pipe_context *pipe,
+                unsigned mode, unsigned start, unsigned count)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nouveau_channel *chan = nv30->nvws->channel;
+       unsigned restart = 0;
+
+       nv30_vbo_set_idxbuf(nv30, NULL, 0);
+       if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
+               /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
+                                               mode, start, count);*/
+               return FALSE;
+       }
+
+       while (count) {
+               unsigned vc, nr;
+
+               nv30_state_emit(nv30);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+                                       mode, start, count, &restart);
+               if (!vc) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               nr = (vc & 0xff);
+               if (nr) {
+                       BEGIN_RING(rankine, NV34TCL_VB_VERTEX_BATCH, 1);
+                       OUT_RING  (((nr - 1) << 24) | start);
+                       start += nr;
+               }
+
+               nr = vc >> 8;
+               while (nr) {
+                       unsigned push = nr > 2047 ? 2047 : nr;
+
+                       nr -= push;
+
+                       BEGIN_RING_NI(rankine, NV34TCL_VB_VERTEX_BATCH, push);
+                       while (push--) {
+                               OUT_RING(((0x100 - 1) << 24) | start);
+                               start += 0x100;
+                       }
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               count -= vc;
+               start = restart;
+       }
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+static INLINE void
+nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv30->nvws->channel;
+
+       while (count) {
+               uint8_t *elts = (uint8_t *)ib + start;
+               unsigned vc, push, restart = 0;
+
+               nv30_state_emit(nv30);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               if (vc & 1) {
+                       BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
+                       OUT_RING  (elts[0]);
+                       elts++; vc--;
+               }
+
+               while (vc) {
+                       unsigned i;
+
+                       push = MIN2(vc, 2047 * 2);
+
+                       BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+                       for (i = 0; i < push; i+=2)
+                               OUT_RING((elts[i+1] << 16) | elts[i]);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static INLINE void
+nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv30->nvws->channel;
+
+       while (count) {
+               uint16_t *elts = (uint16_t *)ib + start;
+               unsigned vc, push, restart = 0;
+
+               nv30_state_emit(nv30);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               if (vc & 1) {
+                       BEGIN_RING(rankine, NV34TCL_VB_ELEMENT_U32, 1);
+                       OUT_RING  (elts[0]);
+                       elts++; vc--;
+               }
+
+               while (vc) {
+                       unsigned i;
+
+                       push = MIN2(vc, 2047 * 2);
+
+                       BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U16, push >> 1);
+                       for (i = 0; i < push; i+=2)
+                               OUT_RING((elts[i+1] << 16) | elts[i]);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static INLINE void
+nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv30->nvws->channel;
+
+       while (count) {
+               uint32_t *elts = (uint32_t *)ib + start;
+               unsigned vc, push, restart = 0;
+
+               nv30_state_emit(nv30);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               while (vc) {
+                       push = MIN2(vc, 2047);
+
+                       BEGIN_RING_NI(rankine, NV34TCL_VB_ELEMENT_U32, push);
+                       OUT_RINGp    (elts, push);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static boolean
+nv30_draw_elements_inline(struct pipe_context *pipe,
+                         struct pipe_buffer *ib, unsigned ib_size,
+                         unsigned mode, unsigned start, unsigned count)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct pipe_winsys *ws = pipe->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
+       if (!ib) {
+               NOUVEAU_ERR("failed mapping ib\n");
+               return FALSE;
+       }
+
+       switch (ib_size) {
+       case 1:
+               nv30_draw_elements_u08(nv30, map, mode, start, count);
+               break;
+       case 2:
+               nv30_draw_elements_u16(nv30, map, mode, start, count);
+               break;
+       case 4:
+               nv30_draw_elements_u32(nv30, map, mode, start, count);
+               break;
+       default:
+               NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
+               break;
+       }
+
+       ws->buffer_unmap(ws, ib);
+       return TRUE;
+}
+
+static boolean
+nv30_draw_elements_vbo(struct pipe_context *pipe,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       struct nouveau_channel *chan = nv30->nvws->channel;
+       unsigned restart = 0;
+
+       while (count) {
+               unsigned nr, vc;
+
+               nv30_state_emit(nv30);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+                                       mode, start, count, &restart);
+               if (!vc) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               nr = (vc & 0xff);
+               if (nr) {
+                       BEGIN_RING(rankine, NV34TCL_VB_INDEX_BATCH, 1);
+                       OUT_RING  (((nr - 1) << 24) | start);
+                       start += nr;
+               }
+
+               nr = vc >> 8;
+               while (nr) {
+                       unsigned push = nr > 2047 ? 2047 : nr;
+
+                       nr -= push;
+
+                       BEGIN_RING_NI(rankine, NV34TCL_VB_INDEX_BATCH, push);
+                       while (push--) {
+                               OUT_RING(((0x100 - 1) << 24) | start);
+                               start += 0x100;
+                       }
+               }
+
+               BEGIN_RING(rankine, NV34TCL_VERTEX_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               count -= vc;
+               start = restart;
+       }
+
+       return TRUE;
+}
+
+boolean
+nv30_draw_elements(struct pipe_context *pipe,
+                  struct pipe_buffer *indexBuffer, unsigned indexSize,
+                  unsigned mode, unsigned start, unsigned count)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+       boolean idxbuf;
+
+       idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize);
+       if (FORCE_SWTNL || !nv30_state_validate(nv30)) {
+               /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
+                                               mode, start, count);*/
+               return FALSE;   
+       }
+
+       if (idxbuf) {
+               nv30_draw_elements_vbo(pipe, mode, start, count);
+       } else {
+               nv30_draw_elements_inline(pipe, indexBuffer, indexSize,
+                                         mode, start, count);
+       }
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+static boolean
+nv30_vbo_validate(struct nv30_context *nv30)
+{
+       struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+       struct pipe_buffer *ib = nv30->idxbuf;
+       unsigned ib_format = nv30->idxbuf_format;
+       unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+       int hw;
+
+       if (nv30->edgeflags) {
+               /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
+               return FALSE;
+       }
+
+       vtxbuf = so_new(20, 18);
+       so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
+       vtxfmt = so_new(17, 0);
+       so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt_nr);
+
+       for (hw = 0; hw < nv30->vtxelt_nr; hw++) {
+               struct pipe_vertex_element *ve;
+               struct pipe_vertex_buffer *vb;
+               unsigned type, ncomp;
+
+               ve = &nv30->vtxelt[hw];
+               vb = &nv30->vtxbuf[ve->vertex_buffer_index];
+
+               if (!vb->pitch) {
+                       if (!sattr)
+                               sattr = so_new(16 * 5, 0);
+
+                       if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) {
+                               so_data(vtxbuf, 0);
+                               so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT);
+                               continue;
+                       }
+               }
+
+               if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
+                       /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
+                       so_ref(NULL, &vtxbuf);
+                       so_ref(NULL, &vtxfmt);
+                       return FALSE;
+               }
+
+               so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
+                        vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                        0, NV34TCL_VTXBUF_ADDRESS_DMA1);
+               so_data (vtxfmt, ((vb->pitch << NV34TCL_VTXFMT_STRIDE_SHIFT) |
+                                 (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type));
+       }
+
+       if (ib) {
+               so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2);
+               so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+               so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
+                         0, NV34TCL_IDXBUF_FORMAT_DMA1);
+       }
+
+       so_method(vtxbuf, rankine, 0x1710, 1);
+       so_data  (vtxbuf, 0);
+
+       so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]);
+       nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF);
+       so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]);
+       nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT);
+       so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]);
+       nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR);
+       return FALSE;
+}
+
+struct nv30_state_entry nv30_state_vbo = {
+       .validate = nv30_vbo_validate,
+       .dirty = {
+               .pipe = NV30_NEW_ARRAYS,
+               .hw = 0,
+       }
+};
diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c
new file mode 100644 (file)
index 0000000..39852ce
--- /dev/null
@@ -0,0 +1,832 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+
+#include "nv30_context.h"
+#include "nv30_state.h"
+
+/* TODO (at least...):
+ *  1. Indexed consts  + ARL
+ *  2. Arb. swz/negation
+ *  3. NV_vp11, NV_vp2, NV_vp3 features
+ *       - extra arith opcodes
+ *       - branching
+ *       - texture sampling
+ *       - indexed attribs
+ *       - indexed results
+ *  4. bugs
+ */
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 8
+#define MASK_Y 4
+#define MASK_Z 2
+#define MASK_W 1
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE 0
+#define DEF_CTEST 0
+#include "nv30_shader.h"
+
+#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv30_sr_neg((s))
+#define abs(s) nv30_sr_abs((s))
+
+struct nv30_vpc {
+       struct nv30_vertex_program *vp;
+
+       struct nv30_vertex_program_exec *vpi;
+
+       unsigned output_map[PIPE_MAX_SHADER_OUTPUTS];
+
+       int high_temp;
+       int temp_temp_count;
+
+       struct nv30_sreg *imm;
+       unsigned nr_imm;
+};
+
+static struct nv30_sreg
+temp(struct nv30_vpc *vpc)
+{
+       int idx;
+
+       idx  = vpc->temp_temp_count++;
+       idx += vpc->high_temp + 1;
+       return nv30_sr(NV30SR_TEMP, idx);
+}
+
+static struct nv30_sreg
+constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+       struct nv30_vertex_program *vp = vpc->vp;
+       struct nv30_vertex_program_data *vpd;
+       int idx;
+
+       if (pipe >= 0) {
+               for (idx = 0; idx < vp->nr_consts; idx++) {
+                       if (vp->consts[idx].index == pipe)
+                               return nv30_sr(NV30SR_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 nv30_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+       nv30_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nv30_sreg src)
+{
+       struct nv30_vertex_program *vp = vpc->vp;
+       uint32_t sr = 0;
+
+       switch (src.type) {
+       case NV30SR_TEMP:
+               sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT);
+               sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT);
+               break;
+       case NV30SR_INPUT:
+               sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+                      NV30_VP_SRC_REG_TYPE_SHIFT);
+               vp->ir |= (1 << src.index);
+               hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT);
+               break;
+       case NV30SR_CONST:
+               sr |= (NV30_VP_SRC_REG_TYPE_CONST <<
+                      NV30_VP_SRC_REG_TYPE_SHIFT);
+               assert(vpc->vpi->const_index == -1 ||
+                      vpc->vpi->const_index == src.index);
+               vpc->vpi->const_index = src.index;
+               break;
+       case NV30SR_NONE:
+               sr |= (NV30_VP_SRC_REG_TYPE_INPUT <<
+                      NV30_VP_SRC_REG_TYPE_SHIFT);
+               break;
+       default:
+               assert(0);
+       }
+
+       if (src.negate)
+               sr |= NV30_VP_SRC_NEGATE;
+
+       if (src.abs)
+               hw[0] |= (1 << (21 + pos));
+
+       sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) |
+              (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) |
+              (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) |
+              (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT));
+
+/*
+ * |VVV|
+ * d�.�b
+ *  \u/
+ *
+ */
+
+       switch (pos) {
+       case 0:
+               hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >>
+                         NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT;
+               hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) <<
+                         NV30_VP_INST_SRC0L_SHIFT;
+               break;
+       case 1:
+               hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT;
+               break;
+       case 2:
+               hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >>
+                         NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT;
+               hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) <<
+                         NV30_VP_INST_SRC2L_SHIFT;
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nv30_sreg dst)
+{
+       struct nv30_vertex_program *vp = vpc->vp;
+
+       switch (dst.type) {
+       case NV30SR_TEMP:
+               hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT);
+               break;
+       case NV30SR_OUTPUT:
+               switch (dst.index) {
+               case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break;
+               case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break;
+               case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break;
+               case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break;
+               case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break;
+               case NV30_VP_INST_DEST_PSZ  : vp->or |= (1 << 5); break;
+               case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
+               case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
+               case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
+               case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
+               case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
+               case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
+               case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
+               case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
+               default:
+                       break;
+               }
+
+               hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT);
+               hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20);
+
+               /*XXX: no way this is entirely correct, someone needs to
+                *     figure out what exactly it is.
+                */
+               hw[3] |= 0x800;
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op,
+             struct nv30_sreg dst, int mask,
+             struct nv30_sreg s0, struct nv30_sreg s1,
+             struct nv30_sreg s2)
+{
+       struct nv30_vertex_program *vp = vpc->vp;
+       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));
+       vpc->vpi->const_index = -1;
+
+       hw = vpc->vpi->data;
+
+       hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT);
+       hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) |
+                 (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) |
+                 (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) |
+                 (3 << NV30_VP_INST_COND_SWZ_W_SHIFT));
+
+       hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT);
+//     hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK;
+//     hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT);
+
+       if (dst.type == NV30SR_OUTPUT) {
+               if (slot)
+                       hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT);
+               else
+                       hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT);
+       } else {
+               if (slot)
+                       hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT);
+               else
+                       hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT);
+       }
+
+       emit_dst(vpc, hw, slot, dst);
+       emit_src(vpc, hw, 0, s0);
+       emit_src(vpc, hw, 1, s1);
+       emit_src(vpc, hw, 2, s2);
+}
+
+static INLINE struct nv30_sreg
+tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+       struct nv30_sreg src;
+
+       switch (fsrc->SrcRegister.File) {
+       case TGSI_FILE_INPUT:
+               src = nv30_sr(NV30SR_INPUT, fsrc->SrcRegister.Index);
+               break;
+       case TGSI_FILE_CONSTANT:
+               src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+               break;
+       case TGSI_FILE_IMMEDIATE:
+               src = vpc->imm[fsrc->SrcRegister.Index];
+               break;
+       case TGSI_FILE_TEMPORARY:
+               if (vpc->high_temp < fsrc->SrcRegister.Index)
+                       vpc->high_temp = fsrc->SrcRegister.Index;
+               src = nv30_sr(NV30SR_TEMP, fsrc->SrcRegister.Index);
+               break;
+       default:
+               NOUVEAU_ERR("bad src file\n");
+               break;
+       }
+
+       src.abs = fsrc->SrcRegisterExtMod.Absolute;
+       src.negate = fsrc->SrcRegister.Negate;
+       src.swz[0] = fsrc->SrcRegister.SwizzleX;
+       src.swz[1] = fsrc->SrcRegister.SwizzleY;
+       src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+       src.swz[3] = fsrc->SrcRegister.SwizzleW;
+       return src;
+}
+
+static INLINE struct nv30_sreg
+tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+       struct nv30_sreg dst;
+
+       switch (fdst->DstRegister.File) {
+       case TGSI_FILE_OUTPUT:
+               dst = nv30_sr(NV30SR_OUTPUT,
+                             vpc->output_map[fdst->DstRegister.Index]);
+
+               break;
+       case TGSI_FILE_TEMPORARY:
+               dst = nv30_sr(NV30SR_TEMP, fdst->DstRegister.Index);
+               if (vpc->high_temp < dst.index)
+                       vpc->high_temp = dst.index;
+               break;
+       default:
+               NOUVEAU_ERR("bad dst file\n");
+               break;
+       }
+
+       return dst;
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+       int mask = 0;
+
+       if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+       if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+       if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+       if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+       return mask;
+}
+
+static boolean
+nv30_vertprog_parse_instruction(struct nv30_vpc *vpc,
+                               const struct tgsi_full_instruction *finst)
+{
+       struct nv30_sreg src[3], dst, tmp;
+       struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0);
+       int mask;
+       int ai = -1, ci = -1;
+       int i;
+
+       if (finst->Instruction.Opcode == TGSI_OPCODE_END)
+               return TRUE;
+
+       vpc->temp_temp_count = 0;
+       for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
+               const struct tgsi_full_src_register *fsrc;
+
+               fsrc = &finst->FullSrcRegisters[i];
+               if (fsrc->SrcRegister.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->FullSrcRegisters[i];
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+                       if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+                               ai = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(vpc, fsrc);
+                       } else {
+                               src[i] = temp(vpc);
+                               arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+                                     tgsi_src(vpc, fsrc), none, none);
+                       }
+                       break;
+               /*XXX: index comparison is broken now that consts come from
+                *     two different register files.
+                */
+               case TGSI_FILE_CONSTANT:
+               case TGSI_FILE_IMMEDIATE:
+                       if (ci == -1 || ci == fsrc->SrcRegister.Index) {
+                               ci = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(vpc, fsrc);
+                       } else {
+                               src[i] = temp(vpc);
+                               arith(vpc, 0, OP_MOV, src[i], 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;
+               }
+       }
+
+       dst  = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
+       mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+
+       switch (finst->Instruction.Opcode) {
+       case TGSI_OPCODE_ABS:
+               arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none);
+               break;
+       case TGSI_OPCODE_ADD:
+               arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]);
+               break;
+       case TGSI_OPCODE_ARL:
+               arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_DP3:
+               arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DP4:
+               arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DPH:
+               arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DST:
+               arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_EX2:
+               arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_EXP:
+               arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_FLR:
+               arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FRC:
+               arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_LG2:
+               arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_LIT:
+               arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_LOG:
+               arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_MAD:
+               arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]);
+               break;
+       case TGSI_OPCODE_MAX:
+               arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MIN:
+               arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MOV:
+               arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_MUL:
+               arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_POW:
+               tmp = temp(vpc);
+               arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none,
+                     swz(src[0], X, X, X, X));
+               arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+                     swz(src[1], X, X, X, X), none);
+               arith(vpc, 1, OP_EX2, dst, mask, none, none,
+                     swz(tmp, X, X, X, X));
+               break;
+       case TGSI_OPCODE_RCP:
+               arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_RET:
+               break;
+       case TGSI_OPCODE_RSQ:
+               arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_SGE:
+               arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SLT:
+               arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SUB:
+               arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1]));
+               break;
+       case TGSI_OPCODE_XPD:
+               tmp = temp(vpc);
+               arith(vpc, 0, OP_MUL, tmp, mask,
+                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+               arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W),
+                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+                     neg(tmp));
+               break;
+       default:
+               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static boolean
+nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       int hw;
+
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               hw = NV30_VP_INST_DEST_POS;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV30_VP_INST_DEST_COL0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV30_VP_INST_DEST_COL1;
+               } else {
+                       NOUVEAU_ERR("bad colour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_BCOLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV30_VP_INST_DEST_BFC0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV30_VP_INST_DEST_BFC1;
+               } else {
+                       NOUVEAU_ERR("bad bcolour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_FOG:
+               hw = NV30_VP_INST_DEST_FOGC;
+               break;
+       case TGSI_SEMANTIC_PSIZE:
+               hw = NV30_VP_INST_DEST_PSZ;
+               break;
+       case TGSI_SEMANTIC_GENERIC:
+               if (fdec->Semantic.SemanticIndex <= 7) {
+                       hw = NV30_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+               } else {
+                       NOUVEAU_ERR("bad generic semantic index\n");
+                       return FALSE;
+               }
+               break;
+       default:
+               NOUVEAU_ERR("bad output semantic\n");
+               return FALSE;
+       }
+
+       vpc->output_map[fdec->DeclarationRange.First] = hw;
+       return TRUE;
+}
+
+static boolean
+nv30_vertprog_prepare(struct nv30_vpc *vpc)
+{
+       struct tgsi_parse_context p;
+       int nr_imm = 0;
+
+       tgsi_parse_init(&p, vpc->vp->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;
+               default:
+                       break;
+               }
+       }
+       tgsi_parse_free(&p);
+
+       if (nr_imm) {
+               vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg));
+               assert(vpc->imm);
+       }
+
+       return TRUE;
+}
+
+static void
+nv30_vertprog_translate(struct nv30_context *nv30,
+                       struct nv30_vertex_program *vp)
+{
+       struct tgsi_parse_context parse;
+       struct nv30_vpc *vpc = NULL;
+
+       vpc = CALLOC(1, sizeof(struct nv30_vpc));
+       if (!vpc)
+               return;
+       vpc->vp = vp;
+       vpc->high_temp = -1;
+
+       if (!nv30_vertprog_prepare(vpc)) {
+               FREE(vpc);
+               return;
+       }
+
+       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_DECLARATION:
+               {
+                       const struct tgsi_full_declaration *fdec;
+                       fdec = &parse.FullToken.FullDeclaration;
+                       switch (fdec->Declaration.File) {
+                       case TGSI_FILE_OUTPUT:
+                               if (!nv30_vertprog_parse_decl_output(vpc, fdec))
+                                       goto out_err;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+                       break;
+               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.Size == 4);
+                       vpc->imm[vpc->nr_imm++] =
+                               constant(vpc, -1,
+                                        imm->u.ImmediateFloat32[0].Float,
+                                        imm->u.ImmediateFloat32[1].Float,
+                                        imm->u.ImmediateFloat32[2].Float,
+                                        imm->u.ImmediateFloat32[3].Float);
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
+               {
+                       const struct tgsi_full_instruction *finst;
+                       finst = &parse.FullToken.FullInstruction;
+                       if (!nv30_vertprog_parse_instruction(vpc, finst))
+                               goto out_err;
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST;
+       vp->translated = TRUE;
+out_err:
+       tgsi_parse_free(&parse);
+       FREE(vpc);
+}
+
+static boolean
+nv30_vertprog_validate(struct nv30_context *nv30)
+{ 
+       struct nouveau_winsys *nvws = nv30->nvws;
+       struct pipe_winsys *ws = nv30->pipe.winsys;
+       struct nouveau_grobj *rankine = nv30->screen->rankine;
+       struct nv30_vertex_program *vp;
+       struct pipe_buffer *constbuf;
+       boolean upload_code = FALSE, upload_data = FALSE;
+       int i;
+
+       vp = nv30->vertprog;
+       constbuf = nv30->constbuf[PIPE_SHADER_VERTEX];
+
+       /* Translate TGSI shader into hw bytecode */
+       if (!vp->translated) {
+               nv30_vertprog_translate(nv30, vp);
+               if (!vp->translated)
+                       return FALSE;
+       }
+
+       /* Allocate hw vtxprog exec slots */
+       if (!vp->exec) {
+               struct nouveau_resource *heap = nv30->screen->vp_exec_heap;
+               struct nouveau_stateobj *so;
+               uint vplen = vp->nr_insns;
+
+               if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) {
+                       while (heap->next && heap->size < vplen) {
+                               struct nv30_vertex_program *evict;
+                               
+                               evict = heap->next->priv;
+                               nvws->res_free(&evict->exec);
+                       }
+
+                       if (nvws->res_alloc(heap, vplen, vp, &vp->exec))
+                               assert(0);
+               }
+
+               so = so_new(2, 0);
+               so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1);
+               so_data  (so, vp->exec->start);
+               so_ref(so, &vp->so);
+
+               upload_code = TRUE;
+       }
+
+       /* Allocate hw vtxprog const slots */
+       if (vp->nr_consts && !vp->data) {
+               struct nouveau_resource *heap = nv30->screen->vp_data_heap;
+
+               if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+                       while (heap->next && heap->size < vp->nr_consts) {
+                               struct nv30_vertex_program *evict;
+                               
+                               evict = heap->next->priv;
+                               nvws->res_free(&evict->data);
+                       }
+
+                       if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data))
+                               assert(0);
+               }
+
+               /*XXX: handle this some day */
+               assert(vp->data->start >= vp->data_start_min);
+
+               upload_data = TRUE;
+               if (vp->data_start != vp->data->start)
+                       upload_code = TRUE;
+       }
+
+       /* If exec or data segments moved we need to patch the program to
+        * fixup offsets and register IDs.
+        */
+       if (vp->exec_start != vp->exec->start) {
+               for (i = 0; i < vp->nr_insns; i++) {
+                       struct nv30_vertex_program_exec *vpi = &vp->insns[i];
+
+                       if (vpi->has_branch_offset) {
+                               assert(0);
+                       }
+               }
+
+               vp->exec_start = vp->exec->start;
+       }
+
+       if (vp->nr_consts && vp->data_start != vp->data->start) {
+               for (i = 0; i < vp->nr_insns; i++) {
+                       struct nv30_vertex_program_exec *vpi = &vp->insns[i];
+
+                       if (vpi->const_index >= 0) {
+                               vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK;
+                               vpi->data[1] |=
+                                       (vpi->const_index + vp->data->start) <<
+                                       NV30_VP_INST_CONST_SRC_SHIFT;
+
+                       }
+               }
+
+               vp->data_start = vp->data->start;
+       }
+
+       /* Update + Upload constant values */
+       if (vp->nr_consts) {
+               float *map = NULL;
+
+               if (constbuf) {
+                       map = ws->buffer_map(ws, constbuf,
+                                            PIPE_BUFFER_USAGE_CPU_READ);
+               }
+
+               for (i = 0; i < vp->nr_consts; i++) {
+                       struct nv30_vertex_program_data *vpd = &vp->consts[i];
+
+                       if (vpd->index >= 0) {
+                               if (!upload_data &&
+                                   !memcmp(vpd->value, &map[vpd->index * 4],
+                                           4 * sizeof(float)))
+                                       continue;
+                               memcpy(vpd->value, &map[vpd->index * 4],
+                                      4 * sizeof(float));
+                       }
+
+                       BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5);
+                       OUT_RING  (i + vp->data->start);
+                       OUT_RINGp ((uint32_t *)vpd->value, 4);
+               }
+
+               if (constbuf) {
+                       ws->buffer_unmap(ws, constbuf);
+               }
+       }
+
+       /* Upload vtxprog */
+       if (upload_code) {
+#if 0
+               for (i = 0; i < vp->nr_insns; i++) {
+                       NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                               i, vp->insns[i].data[0], vp->insns[i].data[1],
+                               vp->insns[i].data[2], vp->insns[i].data[3]);
+               }
+#endif
+               BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1);
+               OUT_RING  (vp->exec->start);
+               for (i = 0; i < vp->nr_insns; i++) {
+                       BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4);
+                       OUT_RINGp (vp->insns[i].data, 4);
+               }
+       }
+
+       if (vp->so != nv30->state.hw[NV30_STATE_VERTPROG]) {
+               so_ref(vp->so, &nv30->state.hw[NV30_STATE_VERTPROG]);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp)
+{
+       struct nouveau_winsys *nvws = nv30->screen->nvws;
+
+       vp->translated = FALSE;
+
+       if (vp->nr_insns) {
+               FREE(vp->insns);
+               vp->insns = NULL;
+               vp->nr_insns = 0;
+       }
+
+       if (vp->nr_consts) {
+               FREE(vp->consts);
+               vp->consts = NULL;
+               vp->nr_consts = 0;
+       }
+
+       nvws->res_free(&vp->exec);
+       vp->exec_start = 0;
+       nvws->res_free(&vp->data);
+       vp->data_start = 0;
+       vp->data_start_min = 0;
+
+       vp->ir = vp->or = 0;
+       so_ref(NULL, &vp->so);
+}
+
+struct nv30_state_entry nv30_state_vertprog = {
+       .validate = nv30_vertprog_validate,
+       .dirty = {
+               .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/,
+               .hw = NV30_STATE_VERTPROG,
+       }
+};
diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile
new file mode 100644 (file)
index 0000000..9c8eadf
--- /dev/null
@@ -0,0 +1,37 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv40
+
+DRIVER_SOURCES = \
+       nv40_clear.c \
+       nv40_context.c \
+       nv40_draw.c \
+       nv40_fragprog.c \
+       nv40_fragtex.c \
+       nv40_miptree.c \
+       nv40_query.c \
+       nv40_screen.c \
+       nv40_state.c \
+       nv40_state_blend.c \
+       nv40_state_emit.c \
+       nv40_state_fb.c \
+       nv40_state_rasterizer.c \
+       nv40_state_scissor.c \
+       nv40_state_stipple.c \
+       nv40_state_viewport.c \
+       nv40_state_zsa.c \
+       nv40_surface.c \
+       nv40_vbo.c \
+       nv40_vertprog.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nv40/nv40_clear.c
new file mode 100644 (file)
index 0000000..59efd62
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv40_context.h"
+
+void
+nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+          unsigned clearValue)
+{
+       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+       ps->status = PIPE_SURFACE_STATUS_CLEAR;
+}
diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c
new file mode 100644 (file)
index 0000000..a40f148
--- /dev/null
@@ -0,0 +1,73 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_util.h"
+
+#include "nv40_context.h"
+#include "nv40_screen.h"
+
+static void
+nv40_flush(struct pipe_context *pipe, unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       
+       if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
+               BEGIN_RING(curie, 0x1fd8, 1);
+               OUT_RING  (2);
+               BEGIN_RING(curie, 0x1fd8, 1);
+               OUT_RING  (1);
+       }
+
+       FIRE_RING(fence);
+}
+
+static void
+nv40_destroy(struct pipe_context *pipe)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       if (nv40->draw)
+               draw_destroy(nv40->draw);
+       FREE(nv40);
+}
+
+struct pipe_context *
+nv40_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+       struct nv40_screen *screen = nv40_screen(pscreen);
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv40_context *nv40;
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nv40 = CALLOC(1, sizeof(struct nv40_context));
+       if (!nv40)
+               return NULL;
+       nv40->screen = screen;
+       nv40->pctx_id = pctx_id;
+
+       nv40->nvws = nvws;
+
+       nv40->pipe.winsys = ws;
+       nv40->pipe.screen = pscreen;
+       nv40->pipe.destroy = nv40_destroy;
+       nv40->pipe.draw_arrays = nv40_draw_arrays;
+       nv40->pipe.draw_elements = nv40_draw_elements;
+       nv40->pipe.clear = nv40_clear;
+       nv40->pipe.flush = nv40_flush;
+
+       nv40_init_query_functions(nv40);
+       nv40_init_surface_functions(nv40);
+       nv40_init_state_functions(nv40);
+
+       /* Create, configure, and install fallback swtnl path */
+       nv40->draw = draw_create();
+       draw_wide_point_threshold(nv40->draw, 9999999.0);
+       draw_wide_line_threshold(nv40->draw, 9999999.0);
+       draw_enable_line_stipple(nv40->draw, FALSE);
+       draw_enable_point_sprites(nv40->draw, FALSE);
+       draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40));
+
+       return &nv40->pipe;
+}
+       
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
new file mode 100644 (file)
index 0000000..8e60a81
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef __NV40_CONTEXT_H__
+#define __NV40_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \
+       struct nv40_screen *ctx = nv40->screen
+#include "nouveau/nouveau_push.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#include "nv40_state.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+
+enum nv40_state_index {
+       NV40_STATE_FB = 0,
+       NV40_STATE_VIEWPORT = 1,
+       NV40_STATE_BLEND = 2,
+       NV40_STATE_RAST = 3,
+       NV40_STATE_ZSA = 4,
+       NV40_STATE_BCOL = 5,
+       NV40_STATE_CLIP = 6,
+       NV40_STATE_SCISSOR = 7,
+       NV40_STATE_STIPPLE = 8,
+       NV40_STATE_FRAGPROG = 9,
+       NV40_STATE_VERTPROG = 10,
+       NV40_STATE_FRAGTEX0 = 11,
+       NV40_STATE_FRAGTEX1 = 12,
+       NV40_STATE_FRAGTEX2 = 13,
+       NV40_STATE_FRAGTEX3 = 14,
+       NV40_STATE_FRAGTEX4 = 15,
+       NV40_STATE_FRAGTEX5 = 16,
+       NV40_STATE_FRAGTEX6 = 17,
+       NV40_STATE_FRAGTEX7 = 18,
+       NV40_STATE_FRAGTEX8 = 19,
+       NV40_STATE_FRAGTEX9 = 20,
+       NV40_STATE_FRAGTEX10 = 21,
+       NV40_STATE_FRAGTEX11 = 22,
+       NV40_STATE_FRAGTEX12 = 23,
+       NV40_STATE_FRAGTEX13 = 24,
+       NV40_STATE_FRAGTEX14 = 25,
+       NV40_STATE_FRAGTEX15 = 26,
+       NV40_STATE_VERTTEX0 = 27,
+       NV40_STATE_VERTTEX1 = 28,
+       NV40_STATE_VERTTEX2 = 29,
+       NV40_STATE_VERTTEX3 = 30,
+       NV40_STATE_VTXBUF = 31,
+       NV40_STATE_VTXFMT = 32,
+       NV40_STATE_VTXATTR = 33,
+       NV40_STATE_MAX = 34
+};
+
+#include "nv40_screen.h"
+
+#define NV40_NEW_BLEND         (1 <<  0)
+#define NV40_NEW_RAST          (1 <<  1)
+#define NV40_NEW_ZSA           (1 <<  2)
+#define NV40_NEW_SAMPLER       (1 <<  3)
+#define NV40_NEW_FB            (1 <<  4)
+#define NV40_NEW_STIPPLE       (1 <<  5)
+#define NV40_NEW_SCISSOR       (1 <<  6)
+#define NV40_NEW_VIEWPORT      (1 <<  7)
+#define NV40_NEW_BCOL          (1 <<  8)
+#define NV40_NEW_VERTPROG      (1 <<  9)
+#define NV40_NEW_FRAGPROG      (1 << 10)
+#define NV40_NEW_ARRAYS                (1 << 11)
+#define NV40_NEW_UCP           (1 << 12)
+
+struct nv40_rasterizer_state {
+       struct pipe_rasterizer_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv40_zsa_state {
+       struct pipe_depth_stencil_alpha_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv40_blend_state {
+       struct pipe_blend_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+
+struct nv40_state {
+       unsigned scissor_enabled;
+       unsigned stipple_enabled;
+       unsigned viewport_bypass;
+       unsigned fp_samplers;
+
+       uint64_t dirty;
+       struct nouveau_stateobj *hw[NV40_STATE_MAX];
+};
+
+struct nv40_context {
+       struct pipe_context pipe;
+
+       struct nouveau_winsys *nvws;
+       struct nv40_screen *screen;
+       unsigned pctx_id;
+
+       struct draw_context *draw;
+
+       /* HW state derived from pipe states */
+       struct nv40_state state;
+       struct {
+               struct nv40_vertex_program *vertprog;
+
+               unsigned nr_attribs;
+               unsigned hw[PIPE_MAX_SHADER_INPUTS];
+               unsigned draw[PIPE_MAX_SHADER_INPUTS];
+               unsigned emit[PIPE_MAX_SHADER_INPUTS];
+       } swtnl;
+
+       enum {
+               HW, SWTNL, SWRAST
+       } render_mode;
+       unsigned fallback_swtnl;
+       unsigned fallback_swrast;
+
+       /* Context state */
+       unsigned dirty, draw_dirty;
+       struct pipe_scissor_state scissor;
+       unsigned stipple[32];
+       struct pipe_clip_state clip;
+       struct nv40_vertex_program *vertprog;
+       struct nv40_fragment_program *fragprog;
+       struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+       unsigned constbuf_nr[PIPE_SHADER_TYPES];
+       struct nv40_rasterizer_state *rasterizer;
+       struct nv40_zsa_state *zsa;
+       struct nv40_blend_state *blend;
+       struct pipe_blend_color blend_colour;
+       struct pipe_viewport_state viewport;
+       struct pipe_framebuffer_state framebuffer;
+       struct pipe_buffer *idxbuf;
+       unsigned idxbuf_format;
+       struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+       struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
+       unsigned nr_samplers;
+       unsigned nr_textures;
+       unsigned dirty_samplers;
+       struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+       unsigned vtxbuf_nr;
+       struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+       unsigned vtxelt_nr;
+       const unsigned *edgeflags;
+};
+
+static INLINE struct nv40_context *
+nv40_context(struct pipe_context *pipe)
+{
+       return (struct nv40_context *)pipe;
+}
+
+struct nv40_state_entry {
+       boolean (*validate)(struct nv40_context *nv40);
+       struct {
+               unsigned pipe;
+               unsigned hw;
+       } dirty;
+};
+
+extern void nv40_init_state_functions(struct nv40_context *nv40);
+extern void nv40_init_surface_functions(struct nv40_context *nv40);
+extern void nv40_init_query_functions(struct nv40_context *nv40);
+
+extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv40_draw.c */
+extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40);
+extern boolean nv40_draw_elements_swtnl(struct pipe_context *pipe,
+                                       struct pipe_buffer *idxbuf,
+                                       unsigned ib_size, unsigned mode,
+                                       unsigned start, unsigned count);
+
+/* nv40_vertprog.c */
+extern void nv40_vertprog_destroy(struct nv40_context *,
+                                 struct nv40_vertex_program *);
+
+/* nv40_fragprog.c */
+extern void nv40_fragprog_destroy(struct nv40_context *,
+                                 struct nv40_fragment_program *);
+
+/* nv40_fragtex.c */
+extern void nv40_fragtex_bind(struct nv40_context *);
+
+/* nv40_state.c and friends */
+extern boolean nv40_state_validate(struct nv40_context *nv40);
+extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40);
+extern void nv40_state_emit(struct nv40_context *nv40);
+extern struct nv40_state_entry nv40_state_rasterizer;
+extern struct nv40_state_entry nv40_state_scissor;
+extern struct nv40_state_entry nv40_state_stipple;
+extern struct nv40_state_entry nv40_state_fragprog;
+extern struct nv40_state_entry nv40_state_vertprog;
+extern struct nv40_state_entry nv40_state_blend;
+extern struct nv40_state_entry nv40_state_blend_colour;
+extern struct nv40_state_entry nv40_state_zsa;
+extern struct nv40_state_entry nv40_state_viewport;
+extern struct nv40_state_entry nv40_state_framebuffer;
+extern struct nv40_state_entry nv40_state_fragtex;
+extern struct nv40_state_entry nv40_state_vbo;
+extern struct nv40_state_entry nv40_state_vtxfmt;
+
+/* nv40_vbo.c */
+extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+extern boolean nv40_draw_elements(struct pipe_context *pipe,
+                                 struct pipe_buffer *indexBuffer,
+                                 unsigned indexSize,
+                                 unsigned mode, unsigned start,
+                                 unsigned count);
+
+/* nv40_clear.c */
+extern void nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+                      unsigned clearValue);
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c
new file mode 100644 (file)
index 0000000..2cf58e2
--- /dev/null
@@ -0,0 +1,348 @@
+#include "pipe/p_util.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "draw/draw_context.h"
+#include "draw/draw_vertex.h"
+#include "draw/draw_pipe.h"
+
+#include "nv40_context.h"
+#define NV40_SHADER_NO_FUCKEDNESS
+#include "nv40_shader.h"
+
+/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
+ * often at all.  Uses "quadro style" vertex submission + a fixed vertex
+ * layout to avoid the need to generate a vertex program or vtxfmt.
+ */
+
+struct nv40_render_stage {
+       struct draw_stage stage;
+       struct nv40_context *nv40;
+       unsigned prim;
+};
+
+static INLINE struct nv40_render_stage *
+nv40_render_stage(struct draw_stage *stage)
+{
+       return (struct nv40_render_stage *)stage;
+}
+
+static INLINE void
+nv40_render_vertex(struct nv40_context *nv40, const struct vertex_header *v)
+{
+       unsigned i;
+
+       for (i = 0; i < nv40->swtnl.nr_attribs; i++) {
+               unsigned idx = nv40->swtnl.draw[i];
+               unsigned hw = nv40->swtnl.hw[i];
+
+               switch (nv40->swtnl.emit[i]) {
+               case EMIT_OMIT:
+                       break;
+               case EMIT_1F:
+                       BEGIN_RING(curie, NV40TCL_VTX_ATTR_1F(hw), 1);
+                       OUT_RING  (fui(v->data[idx][0]));
+                       break;
+               case EMIT_2F:
+                       BEGIN_RING(curie, NV40TCL_VTX_ATTR_2F_X(hw), 2);
+                       OUT_RING  (fui(v->data[idx][0]));
+                       OUT_RING  (fui(v->data[idx][1]));
+                       break;
+               case EMIT_3F:
+                       BEGIN_RING(curie, NV40TCL_VTX_ATTR_3F_X(hw), 3);
+                       OUT_RING  (fui(v->data[idx][0]));
+                       OUT_RING  (fui(v->data[idx][1]));
+                       OUT_RING  (fui(v->data[idx][2]));
+                       break;
+               case EMIT_4F:
+                       BEGIN_RING(curie, NV40TCL_VTX_ATTR_4F_X(hw), 4);
+                       OUT_RING  (fui(v->data[idx][0]));
+                       OUT_RING  (fui(v->data[idx][1]));
+                       OUT_RING  (fui(v->data[idx][2]));
+                       OUT_RING  (fui(v->data[idx][3]));
+                       break;
+               case EMIT_4UB:
+                       BEGIN_RING(curie, NV40TCL_VTX_ATTR_4UB(hw), 1);
+                       OUT_RING  (pack_ub4(float_to_ubyte(v->data[idx][0]),
+                                           float_to_ubyte(v->data[idx][1]),
+                                           float_to_ubyte(v->data[idx][2]),
+                                           float_to_ubyte(v->data[idx][3])));
+                       break;
+               default:
+                       assert(0);
+                       break;
+               }
+       }
+}
+
+static INLINE void
+nv40_render_prim(struct draw_stage *stage, struct prim_header *prim,
+              unsigned mode, unsigned count)
+{
+       struct nv40_render_stage *rs = nv40_render_stage(stage);
+       struct nv40_context *nv40 = rs->nv40;
+       struct nouveau_pushbuf *pb = nv40->nvws->channel->pushbuf;
+       unsigned i;
+
+       /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
+       if (pb->remaining < ((count * 20) + 6)) {
+               if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+                       NOUVEAU_ERR("AIII, missed flush\n");
+                       assert(0);
+               }
+               FIRE_RING(NULL);
+               nv40_state_emit(nv40);
+       }
+
+       /* Switch primitive modes if necessary */
+       if (rs->prim != mode) {
+               if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+                       BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+                       OUT_RING  (NV40TCL_BEGIN_END_STOP);     
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (mode);
+               rs->prim = mode;
+       }
+
+       /* Emit vertex data */
+       for (i = 0; i < count; i++)
+               nv40_render_vertex(nv40, prim->v[i]);
+
+       /* If it's likely we'll need to empty the push buffer soon, finish
+        * off the primitive now.
+        */
+       if (pb->remaining < ((count * 20) + 6)) {
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (NV40TCL_BEGIN_END_STOP);
+               rs->prim = NV40TCL_BEGIN_END_STOP;
+       }
+}
+
+static void
+nv40_render_point(struct draw_stage *draw, struct prim_header *prim)
+{
+       nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_POINTS, 1);
+}
+
+static void
+nv40_render_line(struct draw_stage *draw, struct prim_header *prim)
+{
+       nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_LINES, 2);
+}
+
+static void
+nv40_render_tri(struct draw_stage *draw, struct prim_header *prim)
+{
+       nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_TRIANGLES, 3);
+}
+
+static void
+nv40_render_flush(struct draw_stage *draw, unsigned flags)
+{
+       struct nv40_render_stage *rs = nv40_render_stage(draw);
+       struct nv40_context *nv40 = rs->nv40;
+
+       if (rs->prim != NV40TCL_BEGIN_END_STOP) {
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (NV40TCL_BEGIN_END_STOP);
+               rs->prim = NV40TCL_BEGIN_END_STOP;
+       }
+}
+
+static void
+nv40_render_reset_stipple_counter(struct draw_stage *draw)
+{
+}
+
+static void
+nv40_render_destroy(struct draw_stage *draw)
+{
+       FREE(draw);
+}
+
+static INLINE void
+emit_mov(struct nv40_vertex_program *vp,
+        unsigned dst, unsigned src, unsigned vor, unsigned mask)
+{
+       struct nv40_vertex_program_exec *inst;
+
+       vp->insns = realloc(vp->insns,
+                           sizeof(struct nv40_vertex_program_exec) *
+                           ++vp->nr_insns);
+       inst = &vp->insns[vp->nr_insns - 1];
+
+       inst->data[0] = 0x401f9c6c;
+       inst->data[1] = 0x0040000d | (src << 8);
+       inst->data[2] = 0x8106c083;
+       inst->data[3] = 0x6041ff80 | (dst << 2) | (mask << 13);
+       inst->const_index = -1;
+       inst->has_branch_offset = FALSE;
+
+       vp->ir |= (1 << src);
+       if (vor != ~0)
+               vp->or |= (1 << vor);
+}
+
+static struct nv40_vertex_program *
+create_drawvp(struct nv40_context *nv40)
+{
+       struct nv40_vertex_program *vp = CALLOC_STRUCT(nv40_vertex_program);
+       unsigned i;
+
+       emit_mov(vp, NV40_VP_INST_DEST_POS, 0, ~0, 0xf);
+       emit_mov(vp, NV40_VP_INST_DEST_COL0, 3, 0, 0xf);
+       emit_mov(vp, NV40_VP_INST_DEST_COL1, 4, 1, 0xf);
+       emit_mov(vp, NV40_VP_INST_DEST_BFC0, 3, 2, 0xf);
+       emit_mov(vp, NV40_VP_INST_DEST_BFC1, 4, 3, 0xf);
+       emit_mov(vp, NV40_VP_INST_DEST_FOGC, 5, 4, 0x8);
+       for (i = 0; i < 8; i++)
+               emit_mov(vp, NV40_VP_INST_DEST_TC(i), 8 + i, 14 + i, 0xf);
+
+       vp->insns[vp->nr_insns - 1].data[3] |= 1;
+       vp->translated = TRUE;
+       return vp;
+}
+
+struct draw_stage *
+nv40_draw_render_stage(struct nv40_context *nv40)
+{
+       struct nv40_render_stage *render = CALLOC_STRUCT(nv40_render_stage);
+
+       if (!nv40->swtnl.vertprog)
+               nv40->swtnl.vertprog = create_drawvp(nv40);
+
+       render->nv40 = nv40;
+       render->stage.draw = nv40->draw;
+       render->stage.point = nv40_render_point;
+       render->stage.line = nv40_render_line;
+       render->stage.tri = nv40_render_tri;
+       render->stage.flush = nv40_render_flush;
+       render->stage.reset_stipple_counter = nv40_render_reset_stipple_counter;
+       render->stage.destroy = nv40_render_destroy;
+
+       return &render->stage;
+}
+
+boolean
+nv40_draw_elements_swtnl(struct pipe_context *pipe,
+                        struct pipe_buffer *idxbuf, unsigned idxbuf_size,
+                        unsigned mode, unsigned start, unsigned count)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct pipe_winsys *ws = pipe->winsys;
+       unsigned i;
+       void *map;
+
+       if (!nv40_state_validate_swtnl(nv40))
+               return FALSE;
+       nv40->state.dirty &= ~(1ULL << NV40_STATE_VTXBUF);
+       nv40_state_emit(nv40);
+
+       for (i = 0; i < nv40->vtxbuf_nr; i++) {
+               map = ws->buffer_map(ws, nv40->vtxbuf[i].buffer,
+                                    PIPE_BUFFER_USAGE_CPU_READ);
+               draw_set_mapped_vertex_buffer(nv40->draw, i, map);
+       }
+
+       if (idxbuf) {
+               map = ws->buffer_map(ws, idxbuf, PIPE_BUFFER_USAGE_CPU_READ);
+               draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map);
+       } else {
+               draw_set_mapped_element_buffer(nv40->draw, 0, NULL);
+       }
+
+       if (nv40->constbuf[PIPE_SHADER_VERTEX]) {
+               const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX];
+
+               map = ws->buffer_map(ws, nv40->constbuf[PIPE_SHADER_VERTEX],
+                                    PIPE_BUFFER_USAGE_CPU_READ);
+               draw_set_mapped_constant_buffer(nv40->draw, map, nr);
+       }
+
+       draw_arrays(nv40->draw, mode, start, count);
+
+       for (i = 0; i < nv40->vtxbuf_nr; i++)
+               ws->buffer_unmap(ws, nv40->vtxbuf[i].buffer);
+
+       if (idxbuf)
+               ws->buffer_unmap(ws, idxbuf);
+
+       if (nv40->constbuf[PIPE_SHADER_VERTEX])
+               ws->buffer_unmap(ws, nv40->constbuf[PIPE_SHADER_VERTEX]);
+
+       draw_flush(nv40->draw);
+       pipe->flush(pipe, 0, NULL);
+
+       return TRUE;
+}
+
+static INLINE void
+emit_attrib(struct nv40_context *nv40, unsigned hw, unsigned emit,
+           unsigned semantic, unsigned index)
+{
+       unsigned draw_out = draw_find_vs_output(nv40->draw, semantic, index);
+       unsigned a = nv40->swtnl.nr_attribs++;
+
+       nv40->swtnl.hw[a] = hw;
+       nv40->swtnl.emit[a] = emit;
+       nv40->swtnl.draw[a] = draw_out;
+}
+
+static boolean
+nv40_state_vtxfmt_validate(struct nv40_context *nv40)
+{
+       struct nv40_fragment_program *fp = nv40->fragprog;
+       unsigned colour = 0, texcoords = 0, fog = 0, i;
+
+       /* Determine needed fragprog inputs */
+       for (i = 0; i < fp->info.num_inputs; i++) {
+               switch (fp->info.input_semantic_name[i]) {
+               case TGSI_SEMANTIC_POSITION:
+                       break;
+               case TGSI_SEMANTIC_COLOR:
+                       colour |= (1 << fp->info.input_semantic_index[i]);
+                       break;
+               case TGSI_SEMANTIC_GENERIC:
+                       texcoords |= (1 << fp->info.input_semantic_index[i]);
+                       break;
+               case TGSI_SEMANTIC_FOG:
+                       fog = 1;
+                       break;
+               default:
+                       assert(0);
+               }
+       }
+
+       nv40->swtnl.nr_attribs = 0;
+
+       /* Map draw vtxprog output to hw attribute IDs */
+       for (i = 0; i < 2; i++) {
+               if (!(colour & (1 << i)))
+                       continue;
+               emit_attrib(nv40, 3 + i, EMIT_4UB, TGSI_SEMANTIC_COLOR, i);
+       }
+
+       for (i = 0; i < 8; i++) {
+               if (!(texcoords & (1 << i)))
+                       continue;
+               emit_attrib(nv40, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i);
+       }
+
+       if (fog) {
+               emit_attrib(nv40, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0);
+       }
+
+       emit_attrib(nv40, 0, EMIT_3F, TGSI_SEMANTIC_POSITION, 0);
+
+       return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vtxfmt = {
+       .validate = nv40_state_vtxfmt_validate,
+       .dirty = {
+               .pipe = NV40_NEW_ARRAYS | NV40_NEW_FRAGPROG,
+               .hw = 0
+       }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c
new file mode 100644 (file)
index 0000000..428348c
--- /dev/null
@@ -0,0 +1,991 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv40_context.h"
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 1
+#define MASK_Y 2
+#define MASK_Z 4
+#define MASK_W 8
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE NV40_FP_OP_DST_SCALE_1X
+#define DEF_CTEST NV40_FP_OP_COND_TR
+#include "nv40_shader.h"
+
+#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv40_sr_neg((s))
+#define abs(s) nv40_sr_abs((s))
+#define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v)
+
+#define MAX_CONSTS 128
+#define MAX_IMM 32
+struct nv40_fpc {
+       struct nv40_fragment_program *fp;
+
+       uint attrib_map[PIPE_MAX_SHADER_INPUTS];
+
+       unsigned r_temps;
+       unsigned r_temps_discard;
+       struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
+       struct nv40_sreg *r_temp;
+
+       int num_regs;
+
+       unsigned inst_offset;
+       unsigned have_const;
+
+       struct {
+               int pipe;
+               float vals[4];
+       } consts[MAX_CONSTS];
+       int nr_consts;
+
+       struct nv40_sreg imm[MAX_IMM];
+       unsigned nr_imm;
+};
+
+static INLINE struct nv40_sreg
+temp(struct nv40_fpc *fpc)
+{
+       int idx = ffs(~fpc->r_temps) - 1;
+
+       if (idx < 0) {
+               NOUVEAU_ERR("out of temps!!\n");
+               assert(0);
+               return nv40_sr(NV40SR_TEMP, 0);
+       }
+
+       fpc->r_temps |= (1 << idx);
+       fpc->r_temps_discard |= (1 << idx);
+       return nv40_sr(NV40SR_TEMP, idx);
+}
+
+static INLINE void
+release_temps(struct nv40_fpc *fpc)
+{
+       fpc->r_temps &= ~fpc->r_temps_discard;
+       fpc->r_temps_discard = 0;
+}
+
+static INLINE struct nv40_sreg
+constant(struct nv40_fpc *fpc, int pipe, float vals[4])
+{
+       int idx;
+
+       if (fpc->nr_consts == MAX_CONSTS)
+               assert(0);
+       idx = fpc->nr_consts++;
+
+       fpc->consts[idx].pipe = pipe;
+       if (pipe == -1)
+               memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
+       return nv40_sr(NV40SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+       nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \
+                       (d), (m), (s0), (s1), (s2))
+#define tex(cc,s,o,u,d,m,s0,s1,s2) \
+       nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \
+                   (d), (m), (s0), none, none)
+
+static void
+grow_insns(struct nv40_fpc *fpc, int size)
+{
+       struct nv40_fragment_program *fp = fpc->fp;
+
+       fp->insn_len += size;
+       fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
+}
+
+static void
+emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src)
+{
+       struct nv40_fragment_program *fp = fpc->fp;
+       uint32_t *hw = &fp->insn[fpc->inst_offset];
+       uint32_t sr = 0;
+
+       switch (src.type) {
+       case NV40SR_INPUT:
+               sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
+               hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT);
+               break;
+       case NV40SR_OUTPUT:
+               sr |= NV40_FP_REG_SRC_HALF;
+               /* fall-through */
+       case NV40SR_TEMP:
+               sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT);
+               sr |= (src.index << NV40_FP_REG_SRC_SHIFT);
+               break;
+       case NV40SR_CONST:
+               if (!fpc->have_const) {
+                       grow_insns(fpc, 4);
+                       fpc->have_const = 1;
+               }
+
+               hw = &fp->insn[fpc->inst_offset];
+               if (fpc->consts[src.index].pipe >= 0) {
+                       struct nv40_fragment_program_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 = fpc->consts[src.index].pipe;
+                       memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
+               } else {
+                       memcpy(&fp->insn[fpc->inst_offset + 4],
+                               fpc->consts[src.index].vals,
+                               sizeof(uint32_t) * 4);
+               }
+
+               sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT);       
+               break;
+       case NV40SR_NONE:
+               sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
+               break;
+       default:
+               assert(0);
+       }
+
+       if (src.negate)
+               sr |= NV40_FP_REG_NEGATE;
+
+       if (src.abs)
+               hw[1] |= (1 << (29 + pos));
+
+       sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) |
+              (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) |
+              (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) |
+              (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT));
+
+       hw[pos + 1] |= sr;
+}
+
+static void
+emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst)
+{
+       struct nv40_fragment_program *fp = fpc->fp;
+       uint32_t *hw = &fp->insn[fpc->inst_offset];
+
+       switch (dst.type) {
+       case NV40SR_TEMP:
+               if (fpc->num_regs < (dst.index + 1))
+                       fpc->num_regs = dst.index + 1;
+               break;
+       case NV40SR_OUTPUT:
+               if (dst.index == 1) {
+                       fp->fp_control |= 0xe;
+               } else {
+                       hw[0] |= NV40_FP_OP_OUT_REG_HALF;
+               }
+               break;
+       case NV40SR_NONE:
+               hw[0] |= (1 << 30);
+               break;
+       default:
+               assert(0);
+       }
+
+       hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT);
+}
+
+static void
+nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op,
+             struct nv40_sreg dst, int mask,
+             struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
+{
+       struct nv40_fragment_program *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 (op == NV40_FP_OP_OPCODE_KIL)
+               fp->fp_control |= NV40TCL_FP_CONTROL_KIL;
+       hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT);
+       hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT);
+       hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT);
+
+       if (sat)
+               hw[0] |= NV40_FP_OP_OUT_SAT;
+
+       if (dst.cc_update)
+               hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE;
+       hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT);
+       hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) |
+                 (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) |
+                 (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) |
+                 (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT));
+
+       emit_dst(fpc, dst);
+       emit_src(fpc, 0, s0);
+       emit_src(fpc, 1, s1);
+       emit_src(fpc, 2, s2);
+}
+
+static void
+nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit,
+           struct nv40_sreg dst, int mask,
+           struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
+{
+       struct nv40_fragment_program *fp = fpc->fp;
+
+       nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
+
+       fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT);
+       fp->samplers |= (1 << unit);
+}
+
+static INLINE struct nv40_sreg
+tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc)
+{
+       struct nv40_sreg src;
+
+       switch (fsrc->SrcRegister.File) {
+       case TGSI_FILE_INPUT:
+               src = nv40_sr(NV40SR_INPUT,
+                             fpc->attrib_map[fsrc->SrcRegister.Index]);
+               break;
+       case TGSI_FILE_CONSTANT:
+               src = constant(fpc, fsrc->SrcRegister.Index, NULL);
+               break;
+       case TGSI_FILE_IMMEDIATE:
+               assert(fsrc->SrcRegister.Index < fpc->nr_imm);
+               src = fpc->imm[fsrc->SrcRegister.Index];
+               break;
+       case TGSI_FILE_TEMPORARY:
+               src = fpc->r_temp[fsrc->SrcRegister.Index];
+               break;
+       /* NV40 fragprog result regs are just temps, so this is simple */
+       case TGSI_FILE_OUTPUT:
+               src = fpc->r_result[fsrc->SrcRegister.Index];
+               break;
+       default:
+               NOUVEAU_ERR("bad src file\n");
+               break;
+       }
+
+       src.abs = fsrc->SrcRegisterExtMod.Absolute;
+       src.negate = fsrc->SrcRegister.Negate;
+       src.swz[0] = fsrc->SrcRegister.SwizzleX;
+       src.swz[1] = fsrc->SrcRegister.SwizzleY;
+       src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+       src.swz[3] = fsrc->SrcRegister.SwizzleW;
+       return src;
+}
+
+static INLINE struct nv40_sreg
+tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
+       switch (fdst->DstRegister.File) {
+       case TGSI_FILE_OUTPUT:
+               return fpc->r_result[fdst->DstRegister.Index];
+       case TGSI_FILE_TEMPORARY:
+               return fpc->r_temp[fdst->DstRegister.Index];
+       case TGSI_FILE_NULL:
+               return nv40_sr(NV40SR_NONE, 0);
+       default:
+               NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
+               return nv40_sr(NV40SR_NONE, 0);
+       }
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+       int mask = 0;
+
+       if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+       if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+       if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+       if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+       return mask;
+}
+
+static boolean
+src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc,
+              struct nv40_sreg *src)
+{
+       const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+       struct nv40_sreg tgsi = tgsi_src(fpc, fsrc);
+       uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+       uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+                       fsrc->SrcRegisterExtSwz.NegateY,
+                       fsrc->SrcRegisterExtSwz.NegateZ,
+                       fsrc->SrcRegisterExtSwz.NegateW };
+       uint c;
+
+       for (c = 0; c < 4; c++) {
+               switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+               case TGSI_EXTSWIZZLE_X:
+               case TGSI_EXTSWIZZLE_Y:
+               case TGSI_EXTSWIZZLE_Z:
+               case TGSI_EXTSWIZZLE_W:
+                       mask |= (1 << c);
+                       break;
+               case TGSI_EXTSWIZZLE_ZERO:
+                       zero_mask |= (1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               case TGSI_EXTSWIZZLE_ONE:
+                       one_mask |= (1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               default:
+                       assert(0);
+               }
+
+               if (!tgsi.negate && neg[c])
+                       neg_mask |= (1 << c);
+       }
+
+       if (mask == MASK_ALL && !neg_mask)
+               return TRUE;
+
+       *src = temp(fpc);
+
+       if (mask)
+               arith(fpc, 0, MOV, *src, mask, tgsi, none, none);
+
+       if (zero_mask)
+               arith(fpc, 0, SFL, *src, zero_mask, *src, none, none);
+
+       if (one_mask)
+               arith(fpc, 0, STR, *src, one_mask, *src, none, none);
+
+       if (neg_mask) {
+               struct nv40_sreg one = temp(fpc);
+               arith(fpc, 0, STR, one, neg_mask, one, none, none);
+               arith(fpc, 0, MUL, *src, neg_mask, *src, neg(one), none);
+       }
+
+       return FALSE;
+}
+
+static boolean
+nv40_fragprog_parse_instruction(struct nv40_fpc *fpc,
+                               const struct tgsi_full_instruction *finst)
+{
+       const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+       struct nv40_sreg src[3], dst, tmp;
+       int mask, sat, unit;
+       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->FullSrcRegisters[i];
+               if (fsrc->SrcRegister.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->FullSrcRegisters[i];
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+               case TGSI_FILE_CONSTANT:
+               case TGSI_FILE_TEMPORARY:
+                       if (!src_native_swz(fpc, fsrc, &src[i]))
+                               continue;
+                       break;
+               default:
+                       break;
+               }
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+                       if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+                               ai = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(fpc, fsrc);
+                       } else {
+                               src[i] = temp(fpc);
+                               arith(fpc, 0, MOV, src[i], MASK_ALL,
+                                     tgsi_src(fpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_CONSTANT:
+                       if ((ci == -1 && ii == -1) ||
+                           ci == fsrc->SrcRegister.Index) {
+                               ci = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(fpc, fsrc);
+                       } else {
+                               src[i] = temp(fpc);
+                               arith(fpc, 0, MOV, src[i], MASK_ALL,
+                                     tgsi_src(fpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_IMMEDIATE:
+                       if ((ci == -1 && ii == -1) ||
+                           ii == fsrc->SrcRegister.Index) {
+                               ii = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(fpc, fsrc);
+                       } else {
+                               src[i] = temp(fpc);
+                               arith(fpc, 0, MOV, src[i], MASK_ALL,
+                                     tgsi_src(fpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_TEMPORARY:
+                       /* handled above */
+                       break;
+               case TGSI_FILE_SAMPLER:
+                       unit = fsrc->SrcRegister.Index;
+                       break;
+               case TGSI_FILE_OUTPUT:
+                       break;
+               default:
+                       NOUVEAU_ERR("bad src file\n");
+                       return FALSE;
+               }
+       }
+
+       dst  = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
+       mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+       sat  = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
+
+       switch (finst->Instruction.Opcode) {
+       case TGSI_OPCODE_ABS:
+               arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
+               break;
+       case TGSI_OPCODE_ADD:
+               arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_CMP:
+               tmp = temp(fpc);
+               arith(fpc, sat, MOV, dst, mask, src[2], none, none);
+               tmp.cc_update = 1;
+               arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
+               dst.cc_test = NV40_VP_INST_COND_LT;
+               arith(fpc, sat, MOV, dst, mask, src[1], none, none);
+               break;
+       case TGSI_OPCODE_COS:
+               arith(fpc, sat, COS, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_DDX:
+               if (mask & (MASK_Z | MASK_W)) {
+                       tmp = temp(fpc);
+                       arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y,
+                             swz(src[0], Z, W, Z, W), none, none);
+                       arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
+                             swz(tmp, X, Y, X, Y), none, none);
+                       arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0],
+                             none, none);
+                       arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+               } else {
+                       arith(fpc, sat, DDX, dst, mask, src[0], none, none);
+               }
+               break;
+       case TGSI_OPCODE_DDY:
+               if (mask & (MASK_Z | MASK_W)) {
+                       tmp = temp(fpc);
+                       arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y,
+                             swz(src[0], Z, W, Z, W), none, none);
+                       arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
+                             swz(tmp, X, Y, X, Y), none, none);
+                       arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0],
+                             none, none);
+                       arith(fpc, 0, MOV, dst, mask, tmp, none, none);
+               } else {
+                       arith(fpc, sat, DDY, dst, mask, src[0], none, none);
+               }
+               break;
+       case TGSI_OPCODE_DP3:
+               arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DP4:
+               arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DPH:
+               tmp = temp(fpc);
+               arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none);
+               arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
+                     swz(src[1], W, W, W, W), none);
+               break;
+       case TGSI_OPCODE_DST:
+               arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_EX2:
+               arith(fpc, sat, EX2, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FLR:
+               arith(fpc, sat, FLR, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FRC:
+               arith(fpc, sat, FRC, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_KIL:
+               arith(fpc, 0, KIL, none, 0, none, none, none);
+               break;
+       case TGSI_OPCODE_KILP:
+               dst = nv40_sr(NV40SR_NONE, 0);
+               dst.cc_update = 1;
+               arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
+               dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT;
+               arith(fpc, 0, KIL, dst, 0, none, none, none);
+               break;
+       case TGSI_OPCODE_LG2:
+               arith(fpc, sat, LG2, dst, mask, src[0], none, none);
+               break;
+//     case TGSI_OPCODE_LIT:
+       case TGSI_OPCODE_LRP:
+               tmp = temp(fpc);
+               arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]);
+               arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp);
+               break;
+       case TGSI_OPCODE_MAD:
+               arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
+               break;
+       case TGSI_OPCODE_MAX:
+               arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MIN:
+               arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MOV:
+               arith(fpc, sat, MOV, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_MUL:
+               arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_NOISE1:
+       case TGSI_OPCODE_NOISE2:
+       case TGSI_OPCODE_NOISE3:
+       case TGSI_OPCODE_NOISE4:
+               arith(fpc, sat, SFL, dst, mask, none, none, none);
+               break;
+       case TGSI_OPCODE_POW:
+               tmp = temp(fpc);
+               arith(fpc, 0, LG2, tmp, MASK_X,
+                     swz(src[0], X, X, X, X), none, none);
+               arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+                     swz(src[1], X, X, X, X), none);
+               arith(fpc, sat, EX2, dst, mask,
+                     swz(tmp, X, X, X, X), none, none);
+               break;
+       case TGSI_OPCODE_RCP:
+               arith(fpc, sat, RCP, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_RET:
+               assert(0);
+               break;
+       case TGSI_OPCODE_RFL:
+               tmp = temp(fpc);
+               arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none);
+               arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none);
+               arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z,
+                     swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
+               arith(fpc, sat, MAD, dst, mask,
+                     swz(tmp, Z, Z, Z, Z), src[0], neg(src[1]));
+               break;
+       case TGSI_OPCODE_RSQ:
+               tmp = temp(fpc);
+               arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X,
+                     abs(swz(src[0], X, X, X, X)), none, none);
+               arith(fpc, sat, EX2, dst, mask,
+                     neg(swz(tmp, X, X, X, X)), none, none);
+               break;
+       case TGSI_OPCODE_SCS:
+               if (mask & MASK_X) {
+                       arith(fpc, sat, COS, dst, MASK_X,
+                             swz(src[0], X, X, X, X), none, none);
+               }
+               if (mask & MASK_Y) {
+                       arith(fpc, sat, SIN, dst, MASK_Y,
+                             swz(src[0], X, X, X, X), none, none);
+               }
+               break;
+       case TGSI_OPCODE_SEQ:
+               arith(fpc, sat, SEQ, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SFL:
+               arith(fpc, sat, SFL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SGE:
+               arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SGT:
+               arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SIN:
+               arith(fpc, sat, SIN, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_SLE:
+               arith(fpc, sat, SLE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SLT:
+               arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SNE:
+               arith(fpc, sat, SNE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_STR:
+               arith(fpc, sat, STR, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SUB:
+               arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
+               break;
+       case TGSI_OPCODE_TEX:
+               tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_TXB:
+               tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_TXP:
+               tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_XPD:
+               tmp = temp(fpc);
+               arith(fpc, 0, MUL, tmp, mask,
+                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+               arith(fpc, sat, MAD, dst, (mask & ~MASK_W),
+                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+                     neg(tmp));
+               break;
+       default:
+               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+               return FALSE;
+       }
+
+       release_temps(fpc);
+       return TRUE;
+}
+
+static boolean
+nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       int hw;
+
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               hw = NV40_FP_OP_INPUT_SRC_POSITION;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV40_FP_OP_INPUT_SRC_COL0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV40_FP_OP_INPUT_SRC_COL1;
+               } else {
+                       NOUVEAU_ERR("bad colour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_FOG:
+               hw = NV40_FP_OP_INPUT_SRC_FOGC;
+               break;
+       case TGSI_SEMANTIC_GENERIC:
+               if (fdec->Semantic.SemanticIndex <= 7) {
+                       hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic.
+                                                    SemanticIndex);
+               } else {
+                       NOUVEAU_ERR("bad generic semantic index\n");
+                       return FALSE;
+               }
+               break;
+       default:
+               NOUVEAU_ERR("bad input semantic\n");
+               return FALSE;
+       }
+
+       fpc->attrib_map[fdec->DeclarationRange.First] = hw;
+       return TRUE;
+}
+
+static boolean
+nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       unsigned idx = fdec->DeclarationRange.First;
+       unsigned hw;
+
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               hw = 1;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               switch (fdec->Semantic.SemanticIndex) {
+               case 0: hw = 0; break;
+               case 1: hw = 2; break;
+               case 2: hw = 3; break;
+               case 3: hw = 4; break;
+               default:
+                       NOUVEAU_ERR("bad rcol index\n");
+                       return FALSE;
+               }
+               break;
+       default:
+               NOUVEAU_ERR("bad output semantic\n");
+               return FALSE;
+       }
+
+       fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw);
+       fpc->r_temps |= (1 << hw);
+       return TRUE;
+}
+
+static boolean
+nv40_fragprog_prepare(struct nv40_fpc *fpc)
+{
+       struct tgsi_parse_context p;
+       int high_temp = -1, i;
+
+       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 (!nv40_fragprog_parse_decl_attrib(fpc, fdec))
+                                       goto out_err;
+                               break;
+                       case TGSI_FILE_OUTPUT:
+                               if (!nv40_fragprog_parse_decl_output(fpc, fdec))
+                                       goto out_err;
+                               break;
+                       case TGSI_FILE_TEMPORARY:
+                               if (fdec->DeclarationRange.Last > high_temp) {
+                                       high_temp =
+                                               fdec->DeclarationRange.Last;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_IMMEDIATE:
+               {
+                       struct tgsi_full_immediate *imm;
+                       float vals[4];
+                       
+                       imm = &p.FullToken.FullImmediate;
+                       assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
+                       assert(fpc->nr_imm < MAX_IMM);
+
+                       vals[0] = imm->u.ImmediateFloat32[0].Float;
+                       vals[1] = imm->u.ImmediateFloat32[1].Float;
+                       vals[2] = imm->u.ImmediateFloat32[2].Float;
+                       vals[3] = imm->u.ImmediateFloat32[3].Float;
+                       fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+       tgsi_parse_free(&p);
+
+       if (++high_temp) {
+               fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg));
+               for (i = 0; i < high_temp; i++)
+                       fpc->r_temp[i] = temp(fpc);
+               fpc->r_temps_discard = 0;
+       }
+
+       return TRUE;
+
+out_err:
+       if (fpc->r_temp)
+               FREE(fpc->r_temp);
+       tgsi_parse_free(&p);
+       return FALSE;
+}
+
+static void
+nv40_fragprog_translate(struct nv40_context *nv40,
+                       struct nv40_fragment_program *fp)
+{
+       struct tgsi_parse_context parse;
+       struct nv40_fpc *fpc = NULL;
+
+       fpc = CALLOC(1, sizeof(struct nv40_fpc));
+       if (!fpc)
+               return;
+       fpc->fp = fp;
+       fpc->num_regs = 2;
+
+       if (!nv40_fragprog_prepare(fpc)) {
+               FREE(fpc);
+               return;
+       }
+
+       tgsi_parse_init(&parse, fp->pipe.tokens);
+
+       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;
+
+                       finst = &parse.FullToken.FullInstruction;
+                       if (!nv40_fragprog_parse_instruction(fpc, finst))
+                               goto out_err;
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT;
+
+       /* Terminate final instruction */
+       fp->insn[fpc->inst_offset] |= 0x00000001;
+
+       /* Append NOP + END instruction, may or may not be necessary. */
+       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;
+       
+       fp->translated = TRUE;
+out_err:
+       tgsi_parse_free(&parse);
+       if (fpc->r_temp)
+               FREE(fpc->r_temp);
+       FREE(fpc);
+}
+
+static void
+nv40_fragprog_upload(struct nv40_context *nv40,
+                    struct nv40_fragment_program *fp)
+{
+       struct pipe_winsys *ws = nv40->pipe.winsys;
+       const uint32_t le = 1;
+       uint32_t *map;
+       int i;
+
+       map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+       for (i = 0; i < fp->insn_len; i++) {
+               fflush(stdout); fflush(stderr);
+               NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+               fflush(stdout); fflush(stderr);
+       }
+#endif
+
+       if ((*(const uint8_t *)&le)) {
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = fp->insn[i];
+               }
+       } else {
+               /* Weird swapping for big-endian chips */
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = ((fp->insn[i] & 0xffff) << 16) |
+                                 ((fp->insn[i] >> 16) & 0xffff);
+               }
+       }
+
+       ws->buffer_unmap(ws, fp->buffer);
+}
+
+static boolean
+nv40_fragprog_validate(struct nv40_context *nv40)
+{
+       struct nv40_fragment_program *fp = nv40->fragprog;
+       struct pipe_buffer *constbuf =
+               nv40->constbuf[PIPE_SHADER_FRAGMENT];
+       struct pipe_winsys *ws = nv40->pipe.winsys;
+       struct nouveau_stateobj *so;
+       boolean new_consts = FALSE;
+       int i;
+
+       if (fp->translated)
+               goto update_constants;
+
+       nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG;
+       nv40_fragprog_translate(nv40, fp);
+       if (!fp->translated) {
+               nv40->fallback_swrast |= NV40_NEW_FRAGPROG;
+               return FALSE;
+       }
+
+       fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+       nv40_fragprog_upload(nv40, fp);
+
+       so = so_new(4, 1);
+       so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1);
+       so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                 NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1);
+       so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1);
+       so_data  (so, fp->fp_control);
+       so_ref(so, &fp->so);
+
+update_constants:
+       if (fp->nr_consts) {
+               float *map;
+               
+               map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
+               for (i = 0; i < fp->nr_consts; i++) {
+                       struct nv40_fragment_program_data *fpd = &fp->consts[i];
+                       uint32_t *p = &fp->insn[fpd->offset];
+                       uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+                       if (!memcmp(p, cb, 4 * sizeof(float)))
+                               continue;
+                       memcpy(p, cb, 4 * sizeof(float));
+                       new_consts = TRUE;
+               }
+               ws->buffer_unmap(ws, constbuf);
+
+               if (new_consts)
+                       nv40_fragprog_upload(nv40, fp);
+       }
+
+       if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) {
+               so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+nv40_fragprog_destroy(struct nv40_context *nv40,
+                     struct nv40_fragment_program *fp)
+{
+       if (fp->insn_len)
+               FREE(fp->insn);
+}
+
+struct nv40_state_entry nv40_state_fragprog = {
+       .validate = nv40_fragprog_validate,
+       .dirty = {
+               .pipe = NV40_NEW_FRAGPROG,
+               .hw = NV40_STATE_FRAGPROG
+       }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c
new file mode 100644 (file)
index 0000000..c79ea8b
--- /dev/null
@@ -0,0 +1,167 @@
+#include "nv40_context.h"
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                        \
+{                                                                              \
+  TRUE,                                                                        \
+  PIPE_FORMAT_##m,                                                             \
+  NV40TCL_TEX_FORMAT_FORMAT_##tf,                                              \
+  (NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y |         \
+   NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w |         \
+   NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y |         \
+   NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w),         \
+}
+
+struct nv40_texture_format {
+       boolean defined;
+       uint    pipe;
+       int     format;
+       int     swizzle;
+};
+
+static struct nv40_texture_format
+nv40_texture_formats[] = {
+       _(A8R8G8B8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(A1R5G5B5_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(A4R4G4B4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(R5G6B5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
+       _(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X),
+       _(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X),
+       _(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X),
+       _(A8L8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y),
+       _(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X),
+       _(Z24S8_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X),
+       _(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
+       _(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       _(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
+       {},
+};
+
+static struct nv40_texture_format *
+nv40_fragtex_format(uint pipe_format)
+{
+       struct nv40_texture_format *tf = nv40_texture_formats;
+       char fs[128];
+
+       while (tf->defined) {
+               if (tf->pipe == pipe_format)
+                       return tf;
+               tf++;
+       }
+
+       pf_sprint_name(fs, pipe_format);
+       NOUVEAU_ERR("unknown texture format %s\n", fs);
+       return NULL;
+}
+
+
+static struct nouveau_stateobj *
+nv40_fragtex_build(struct nv40_context *nv40, int unit)
+{
+       struct nv40_sampler_state *ps = nv40->tex_sampler[unit];
+       struct nv40_miptree *nv40mt = nv40->tex_miptree[unit];
+       struct pipe_texture *pt = &nv40mt->base;
+       struct nv40_texture_format *tf;
+       struct nouveau_stateobj *so;
+       uint32_t txf, txs, txp;
+       int swizzled = 0; /*XXX: implement in region code? */
+       unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+       tf = nv40_fragtex_format(pt->format);
+       if (!tf)
+               assert(0);
+
+       txf  = ps->fmt;
+       txf |= tf->format | 0x8000;
+       txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
+
+       if (1) /* XXX */
+               txf |= NV40TCL_TEX_FORMAT_NO_BORDER;
+
+       switch (pt->target) {
+       case PIPE_TEXTURE_CUBE:
+               txf |= NV40TCL_TEX_FORMAT_CUBIC;
+               /* fall-through */
+       case PIPE_TEXTURE_2D:
+               txf |= NV40TCL_TEX_FORMAT_DIMS_2D;
+               break;
+       case PIPE_TEXTURE_3D:
+               txf |= NV40TCL_TEX_FORMAT_DIMS_3D;
+               break;
+       case PIPE_TEXTURE_1D:
+               txf |= NV40TCL_TEX_FORMAT_DIMS_1D;
+               break;
+       default:
+               NOUVEAU_ERR("Unknown target %d\n", pt->target);
+               return NULL;
+       }
+
+       if (swizzled) {
+               txp = 0;
+       } else {
+               txp  = nv40mt->level[0].pitch;
+               txf |= NV40TCL_TEX_FORMAT_LINEAR;
+       }
+
+       txs = tf->swizzle;
+
+       so = so_new(16, 2);
+       so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8);
+       so_reloc (so, nv40mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
+       so_reloc (so, nv40mt->buffer, txf, tex_flags | NOUVEAU_BO_OR,
+                 NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1);
+       so_data  (so, ps->wrap);
+       so_data  (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
+       so_data  (so, txs);
+       so_data  (so, ps->filt | 0x2000 /*voodoo*/);
+       so_data  (so, (pt->width[0] << NV40TCL_TEX_SIZE0_W_SHIFT) |
+                      pt->height[0]);
+       so_data  (so, ps->bcol);
+       so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1);
+       so_data  (so, (pt->depth[0] << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
+
+       return so;
+}
+
+static boolean
+nv40_fragtex_validate(struct nv40_context *nv40)
+{
+       struct nv40_fragment_program *fp = nv40->fragprog;
+       struct nv40_state *state = &nv40->state;
+       struct nouveau_stateobj *so;
+       unsigned samplers, unit;
+
+       samplers = state->fp_samplers & ~fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               so = so_new(2, 0);
+               so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1);
+               so_data  (so, 0);
+               so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+               state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
+       }
+
+       samplers = nv40->dirty_samplers & fp->samplers;
+       while (samplers) {
+               unit = ffs(samplers) - 1;
+               samplers &= ~(1 << unit);
+
+               so = nv40_fragtex_build(nv40, unit);
+               so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
+               state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
+       }
+
+       nv40->state.fp_samplers = fp->samplers;
+       return FALSE;
+}
+
+struct nv40_state_entry nv40_state_fragtex = {
+       .validate = nv40_fragtex_validate,
+       .dirty = {
+               .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG,
+               .hw = 0
+       }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c
new file mode 100644 (file)
index 0000000..38e1a5f
--- /dev/null
@@ -0,0 +1,163 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv40_context.h"
+
+static void
+nv40_miptree_layout(struct nv40_miptree *nv40mt)
+{
+       struct pipe_texture *pt = &nv40mt->base;
+       boolean swizzled = FALSE;
+       uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
+       uint offset = 0;
+       int nr_faces, l, f, pitch;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               nr_faces = 6;
+       } else
+       if (pt->target == PIPE_TEXTURE_3D) {
+               nr_faces = pt->depth[0];
+       } else {
+               nr_faces = 1;
+       }
+
+       pitch = pt->width[0];
+       for (l = 0; l <= pt->last_level; l++) {
+               pt->width[l] = width;
+               pt->height[l] = height;
+               pt->depth[l] = depth;
+               pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width);
+               pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
+
+               if (swizzled)
+                       pitch = pt->nblocksx[l];
+               pitch = align_int(pitch, 64);
+
+               nv40mt->level[l].pitch = pitch * pt->block.size;
+               nv40mt->level[l].image_offset =
+                       CALLOC(nr_faces, sizeof(unsigned));
+
+               width  = MAX2(1, width  >> 1);
+               height = MAX2(1, height >> 1);
+               depth  = MAX2(1, depth  >> 1);
+       }
+
+       for (f = 0; f < nr_faces; f++) {
+               for (l = 0; l <= pt->last_level; l++) {
+                       nv40mt->level[l].image_offset[f] = offset;
+                       offset += nv40mt->level[l].pitch * pt->height[l];
+               }
+       }
+
+       nv40mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv40_miptree *mt;
+
+       mt = MALLOC(sizeof(struct nv40_miptree));
+       if (!mt)
+               return NULL;
+       mt->base = *pt;
+       mt->base.refcount = 1;
+       mt->base.screen = pscreen;
+
+       nv40_miptree_layout(mt);
+
+       mt->buffer = ws->buffer_create(ws, 256,
+                                      PIPE_BUFFER_USAGE_PIXEL |
+                                      NOUVEAU_BUFFER_USAGE_TEXTURE,
+                                      mt->total_size);
+       if (!mt->buffer) {
+               FREE(mt);
+               return NULL;
+       }
+
+       return &mt->base;
+}
+
+static void
+nv40_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **pt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct pipe_texture *mt = *pt;
+
+       *pt = NULL;
+       if (--mt->refcount <= 0) {
+               struct nv40_miptree *nv40mt = (struct nv40_miptree *)mt;
+               int l;
+
+               pipe_buffer_reference(ws, &nv40mt->buffer, NULL);
+               for (l = 0; l <= mt->last_level; l++) {
+                       if (nv40mt->level[l].image_offset)
+                               FREE(nv40mt->level[l].image_offset);
+               }
+               FREE(nv40mt);
+       }
+}
+
+static struct pipe_surface *
+nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv40_miptree *nv40mt = (struct nv40_miptree *)pt;
+       struct pipe_surface *ps;
+
+       ps = CALLOC_STRUCT(pipe_surface);
+       if (!ps)
+               return NULL;
+       pipe_texture_reference(&ps->texture, pt);
+       pipe_buffer_reference(ws, &ps->buffer, nv40mt->buffer);
+       ps->format = pt->format;
+       ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->block = pt->block;
+       ps->nblocksx = pt->nblocksx[level];
+       ps->nblocksy = pt->nblocksy[level];
+       ps->stride = nv40mt->level[level].pitch;
+       ps->usage = flags;
+       ps->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       if (pt->target == PIPE_TEXTURE_CUBE) {
+               ps->offset = nv40mt->level[level].image_offset[face];
+       } else
+       if (pt->target == PIPE_TEXTURE_3D) {
+               ps->offset = nv40mt->level[level].image_offset[zslice];
+       } else {
+               ps->offset = nv40mt->level[level].image_offset[0];
+       }
+
+       return ps;
+}
+
+static void
+nv40_miptree_surface_del(struct pipe_screen *pscreen,
+                        struct pipe_surface **psurface)
+{
+       struct pipe_surface *ps = *psurface;
+
+       *psurface = NULL;
+       if (--ps->refcount > 0)
+               return;
+
+       pipe_texture_reference(&ps->texture, NULL);
+       pipe_buffer_reference(pscreen->winsys, &ps->buffer, NULL);
+       FREE(ps);
+}
+
+void
+nv40_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+       pscreen->texture_create = nv40_miptree_create;
+       pscreen->texture_release = nv40_miptree_release;
+       pscreen->get_tex_surface = nv40_miptree_surface_new;
+       pscreen->tex_surface_release = nv40_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c
new file mode 100644 (file)
index 0000000..57f39cf
--- /dev/null
@@ -0,0 +1,122 @@
+#include "pipe/p_context.h"
+
+#include "nv40_context.h"
+
+struct nv40_query {
+       struct nouveau_resource *object;
+       unsigned type;
+       boolean ready;
+       uint64_t result;
+};
+
+static INLINE struct nv40_query *
+nv40_query(struct pipe_query *pipe)
+{
+       return (struct nv40_query *)pipe;
+}
+
+static struct pipe_query *
+nv40_query_create(struct pipe_context *pipe, unsigned query_type)
+{
+       struct nv40_query *q;
+
+       q = CALLOC(1, sizeof(struct nv40_query));
+       q->type = query_type;
+
+       return (struct pipe_query *)q;
+}
+
+static void
+nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_query *q = nv40_query(pq);
+
+       if (q->object)
+               nv40->nvws->res_free(&q->object);
+       FREE(q);
+}
+
+static void
+nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_query *q = nv40_query(pq);
+
+       assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+       /* Happens when end_query() is called, then another begin_query()
+        * without querying the result in-between.  For now we'll wait for
+        * the existing query to notify completion, but it could be better.
+        */
+       if (q->object) {
+               uint64 tmp;
+               pipe->get_query_result(pipe, pq, 1, &tmp);
+       }
+
+       if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object))
+               assert(0);
+       nv40->nvws->notifier_reset(nv40->screen->query, q->object->start);
+
+       BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1);
+       OUT_RING  (1);
+       BEGIN_RING(curie, NV40TCL_QUERY_UNK17CC, 1);
+       OUT_RING  (1);
+
+       q->ready = FALSE;
+}
+
+static void
+nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_query *q = nv40_query(pq);
+
+       BEGIN_RING(curie, NV40TCL_QUERY_GET, 1);
+       OUT_RING  ((0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) |
+                  ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT));
+       FIRE_RING(NULL);
+}
+
+static boolean
+nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq,
+                 boolean wait, uint64 *result)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_query *q = nv40_query(pq);
+       struct nouveau_winsys *nvws = nv40->nvws;
+
+       assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+
+       if (!q->ready) {
+               unsigned status;
+
+               status = nvws->notifier_status(nv40->screen->query,
+                                              q->object->start);
+               if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) {
+                       if (wait == FALSE)
+                               return FALSE;
+                       nvws->notifier_wait(nv40->screen->query, q->object->start,
+                                           NV_NOTIFY_STATE_STATUS_COMPLETED,
+                                           0);
+               }
+
+               q->result = nvws->notifier_retval(nv40->screen->query,
+                                                 q->object->start);
+               q->ready = TRUE;
+               nvws->res_free(&q->object);
+       }
+
+       *result = q->result;
+       return TRUE;
+}
+
+void
+nv40_init_query_functions(struct nv40_context *nv40)
+{
+       nv40->pipe.create_query = nv40_query_create;
+       nv40->pipe.destroy_query = nv40_query_destroy;
+       nv40->pipe.begin_query = nv40_query_begin;
+       nv40->pipe.end_query = nv40_query_end;
+       nv40->pipe.get_query_result = nv40_query_result;
+}
diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c
new file mode 100644 (file)
index 0000000..ed0215b
--- /dev/null
@@ -0,0 +1,314 @@
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv40_context.h"
+#include "nv40_screen.h"
+
+#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf
+#define NV4X_GRCLASS4497_CHIPSETS 0x00005450
+#define NV6X_GRCLASS4497_CHIPSETS 0x00000088
+
+static const char *
+nv40_screen_get_name(struct pipe_screen *pscreen)
+{
+       struct nv40_screen *screen = nv40_screen(pscreen);
+       struct nouveau_device *dev = screen->nvws->channel->device;
+       static char buffer[128];
+
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+       return buffer;
+}
+
+static const char *
+nv40_screen_get_vendor(struct pipe_screen *pscreen)
+{
+       return "nouveau";
+}
+
+static int
+nv40_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+       struct nv40_screen *screen = nv40_screen(pscreen);
+
+       switch (param) {
+       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+               return 16;
+       case PIPE_CAP_NPOT_TEXTURES:
+               return 1;
+       case PIPE_CAP_TWO_SIDED_STENCIL:
+               return 1;
+       case PIPE_CAP_GLSL:
+               return 0;
+       case PIPE_CAP_S3TC:
+               return 1;
+       case PIPE_CAP_ANISOTROPIC_FILTER:
+               return 1;
+       case PIPE_CAP_POINT_SPRITE:
+               return 1;
+       case PIPE_CAP_MAX_RENDER_TARGETS:
+               return 4;
+       case PIPE_CAP_OCCLUSION_QUERY:
+               return 1;
+       case PIPE_CAP_TEXTURE_SHADOW_MAP:
+               return 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 NOUVEAU_CAP_HW_VTXBUF:
+               return 1;
+       case NOUVEAU_CAP_HW_IDXBUF:
+               if (screen->curie->grclass == NV40TCL)
+                       return 1;
+               return 0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0;
+       }
+}
+
+static float
+nv40_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_LINE_WIDTH:
+       case PIPE_CAP_MAX_LINE_WIDTH_AA:
+               return 10.0;
+       case PIPE_CAP_MAX_POINT_WIDTH:
+       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+               return 64.0;
+       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+               return 16.0;
+       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+               return 16.0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0.0;
+       }
+}
+
+static boolean
+nv40_screen_surface_format_supported(struct pipe_screen *pscreen,
+                                    enum pipe_format format, uint type)
+{
+       switch (type) {
+       case PIPE_SURFACE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_Z24S8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       case PIPE_TEXTURE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_A1R5G5B5_UNORM:
+               case PIPE_FORMAT_A4R4G4B4_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM: 
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+               case PIPE_FORMAT_I8_UNORM:
+               case PIPE_FORMAT_A8L8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+               case PIPE_FORMAT_Z24S8_UNORM:
+               case PIPE_FORMAT_DXT1_RGB:
+               case PIPE_FORMAT_DXT1_RGBA:
+               case PIPE_FORMAT_DXT3_RGBA:
+               case PIPE_FORMAT_DXT5_RGBA:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       default:
+               assert(0);
+       };
+
+       return FALSE;
+}
+
+static void *
+nv40_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
+                unsigned flags )
+{
+       struct pipe_winsys *ws = screen->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, surface->buffer, flags);
+       if (!map)
+               return NULL;
+
+       return map + surface->offset;
+}
+
+static void
+nv40_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+       struct pipe_winsys *ws = screen->winsys;
+
+       ws->buffer_unmap(ws, surface->buffer);
+}
+
+static void
+nv40_screen_destroy(struct pipe_screen *pscreen)
+{
+       struct nv40_screen *screen = nv40_screen(pscreen);
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       nvws->res_free(&screen->vp_exec_heap);
+       nvws->res_free(&screen->vp_data_heap);
+       nvws->res_free(&screen->query_heap);
+       nvws->notifier_free(&screen->query);
+       nvws->notifier_free(&screen->sync);
+       nvws->grobj_free(&screen->curie);
+
+       FREE(pscreen);
+}
+
+struct pipe_screen *
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+       struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen);
+       struct nouveau_stateobj *so;
+       unsigned curie_class;
+       unsigned chipset = nvws->channel->device->chipset;
+       int ret;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       /* 3D object */
+       switch (chipset & 0xf0) {
+       case 0x40:
+               if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f)))
+                       curie_class = NV40TCL;
+               else
+               if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+                       curie_class = NV44TCL;
+               break;
+       case 0x60:
+               if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f)))
+                       curie_class = NV44TCL;
+               break;
+       default:
+               break;
+       }
+
+       if (!curie_class) {
+               NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset);
+               return NULL;
+       }
+
+       ret = nvws->grobj_alloc(nvws, curie_class, &screen->curie);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               return FALSE;
+       }
+
+       /* Notifier for sync purposes */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv40_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Query objects */
+       ret = nvws->notifier_alloc(nvws, 32, &screen->query);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
+               nv40_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       ret = nvws->res_init(&screen->query_heap, 0, 32);
+       if (ret) {
+               NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
+               nv40_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Vtxprog resources */
+       if (nvws->res_init(&screen->vp_exec_heap, 0, 512) ||
+           nvws->res_init(&screen->vp_data_heap, 0, 256)) {
+               nv40_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Static curie initialisation */
+       so = so_new(128, 0);
+       so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1);
+       so_data  (so, screen->sync->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->gart->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2);
+       so_data  (so, 0);
+       so_data  (so, screen->query->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->vram->handle);
+       so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2);
+       so_data  (so, nvws->channel->vram->handle);
+       so_data  (so, nvws->channel->vram->handle);
+
+       so_method(so, screen->curie, 0x1ea4, 3);
+       so_data  (so, 0x00000010);
+       so_data  (so, 0x01000100);
+       so_data  (so, 0xff800006);
+
+       /* vtxprog output routing */
+       so_method(so, screen->curie, 0x1fc4, 1);
+       so_data  (so, 0x06144321);
+       so_method(so, screen->curie, 0x1fc8, 2);
+       so_data  (so, 0xedcba987);
+       so_data  (so, 0x00000021);
+       so_method(so, screen->curie, 0x1fd0, 1);
+       so_data  (so, 0x00171615);
+       so_method(so, screen->curie, 0x1fd4, 1);
+       so_data  (so, 0x001b1a19);
+
+       so_method(so, screen->curie, 0x1ef8, 1);
+       so_data  (so, 0x0020ffff);
+       so_method(so, screen->curie, 0x1d64, 1);
+       so_data  (so, 0x00d30000);
+       so_method(so, screen->curie, 0x1e94, 1);
+       so_data  (so, 0x00000001);
+
+       so_emit(nvws, so);
+       so_ref(NULL, &so);
+       nvws->push_flush(nvws, 0, NULL);
+
+       screen->pipe.winsys = ws;
+       screen->pipe.destroy = nv40_screen_destroy;
+
+       screen->pipe.get_name = nv40_screen_get_name;
+       screen->pipe.get_vendor = nv40_screen_get_vendor;
+       screen->pipe.get_param = nv40_screen_get_param;
+       screen->pipe.get_paramf = nv40_screen_get_paramf;
+
+       screen->pipe.is_format_supported = nv40_screen_surface_format_supported;
+
+       screen->pipe.surface_map = nv40_surface_map;
+       screen->pipe.surface_unmap = nv40_surface_unmap;
+
+       nv40_screen_init_miptree_functions(&screen->pipe);
+
+       return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h
new file mode 100644 (file)
index 0000000..c04a127
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __NV40_SCREEN_H__
+#define __NV40_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv40_screen {
+       struct pipe_screen pipe;
+
+       struct nouveau_winsys *nvws;
+
+       unsigned cur_pctx;
+
+       /* HW graphics objects */
+       struct nouveau_grobj *curie;
+       struct nouveau_notifier *sync;
+
+       /* Query object resources */
+       struct nouveau_notifier *query;
+       struct nouveau_resource *query_heap;
+
+       /* Vtxprog resources */
+       struct nouveau_resource *vp_exec_heap;
+       struct nouveau_resource *vp_data_heap;
+
+       /* Current 3D state of channel */
+       struct nouveau_stateobj *state[NV40_STATE_MAX];
+};
+
+static INLINE struct nv40_screen *
+nv40_screen(struct pipe_screen *screen)
+{
+       return (struct nv40_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_shader.h b/src/gallium/drivers/nv40/nv40_shader.h
new file mode 100644 (file)
index 0000000..854dccf
--- /dev/null
@@ -0,0 +1,556 @@
+#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_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                             (0x1F << 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_FL                                               0
+#    define NV40_VP_INST_COND_LT                                               1
+#    define NV40_VP_INST_COND_EQ                                               2
+#    define NV40_VP_INST_COND_LE                                               3
+#    define NV40_VP_INST_COND_GT                                               4
+#    define NV40_VP_INST_COND_NE                                               5
+#    define NV40_VP_INST_COND_GE                                               6
+#    define NV40_VP_INST_COND_TR                                               7
+#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_OP_NOP                                             0x00
+#    define NV40_VP_INST_OP_MOV                                             0x01
+#    define NV40_VP_INST_OP_MUL                                             0x02
+#    define NV40_VP_INST_OP_ADD                                             0x03
+#    define NV40_VP_INST_OP_MAD                                             0x04
+#    define NV40_VP_INST_OP_DP3                                             0x05
+#    define NV40_VP_INST_OP_DPH                                             0x06
+#    define NV40_VP_INST_OP_DP4                                             0x07
+#    define NV40_VP_INST_OP_DST                                             0x08
+#    define NV40_VP_INST_OP_MIN                                             0x09
+#    define NV40_VP_INST_OP_MAX                                             0x0A
+#    define NV40_VP_INST_OP_SLT                                             0x0B
+#    define NV40_VP_INST_OP_SGE                                             0x0C
+#    define NV40_VP_INST_OP_ARL                                             0x0D
+#    define NV40_VP_INST_OP_FRC                                             0x0E
+#    define NV40_VP_INST_OP_FLR                                             0x0F
+#    define NV40_VP_INST_OP_SEQ                                             0x10
+#    define NV40_VP_INST_OP_SFL                                             0x11
+#    define NV40_VP_INST_OP_SGT                                             0x12
+#    define NV40_VP_INST_OP_SLE                                             0x13
+#    define NV40_VP_INST_OP_SNE                                             0x14
+#    define NV40_VP_INST_OP_STR                                             0x15
+#    define NV40_VP_INST_OP_SSG                                             0x16
+#    define NV40_VP_INST_OP_ARR                                             0x17
+#    define NV40_VP_INST_OP_ARA                                             0x18
+#    define NV40_VP_INST_OP_TXL                                             0x19
+#define NV40_VP_INST_SCA_OPCODE_SHIFT                                         27
+#define NV40_VP_INST_SCA_OPCODE_MASK                                (0x1F << 27)
+#    define NV40_VP_INST_OP_NOP                                             0x00
+#    define NV40_VP_INST_OP_MOV                                             0x01
+#    define NV40_VP_INST_OP_RCP                                             0x02
+#    define NV40_VP_INST_OP_RCC                                             0x03
+#    define NV40_VP_INST_OP_RSQ                                             0x04
+#    define NV40_VP_INST_OP_EXP                                             0x05
+#    define NV40_VP_INST_OP_LOG                                             0x06
+#    define NV40_VP_INST_OP_LIT                                             0x07
+#    define NV40_VP_INST_OP_BRA                                             0x09
+#    define NV40_VP_INST_OP_CAL                                             0x0B
+#    define NV40_VP_INST_OP_RET                                             0x0C
+#    define NV40_VP_INST_OP_LG2                                             0x0D
+#    define NV40_VP_INST_OP_EX2                                             0x0E
+#    define NV40_VP_INST_OP_SIN                                             0x0F
+#    define NV40_VP_INST_OP_COS                                             0x10
+#    define NV40_VP_INST_OP_PUSHA                                           0x13
+#    define NV40_VP_INST_OP_POPA                                            0x14
+#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_IN_POS                                                0
+#    define NV40_VP_INST_IN_WEIGHT                                             1
+#    define NV40_VP_INST_IN_NORMAL                                             2
+#    define NV40_VP_INST_IN_COL0                                               3
+#    define NV40_VP_INST_IN_COL1                                               4
+#    define NV40_VP_INST_IN_FOGC                                               5
+#    define NV40_VP_INST_IN_TC0                                                8
+#    define NV40_VP_INST_IN_TC(n)                                          (8+n)
+#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                                     (0x1F << 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_INST_LAST                                               (1 << 0)
+#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
+
+
+/*
+ * Each fragment program opcode appears to be comprised of 4 32-bit values.
+ *
+ *         0 - Opcode, output reg/mask, ATTRIB source
+ *         1 - Source 0
+ *         2 - Source 1
+ *         3 - Source 2
+ *
+ * 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 and
+ * 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.
+ *
+ * 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.
+ *
+ * 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
+ *         DP2 - MUL + ADD
+ *         NRM
+ */
+
+//== Opcode / Destination selection ==
+#define NV40_FP_OP_PROGRAM_END                                          (1 << 0)
+#define NV40_FP_OP_OUT_REG_SHIFT                                               1
+#define NV40_FP_OP_OUT_REG_MASK                                        (63 << 1)
+/* Needs to be set when writing outputs to get expected result.. */
+#define NV40_FP_OP_OUT_REG_HALF                                         (1 << 7)
+#define NV40_FP_OP_COND_WRITE_ENABLE                                    (1 << 8)
+#define NV40_FP_OP_OUTMASK_SHIFT                                               9
+#define NV40_FP_OP_OUTMASK_MASK                                       (0xF << 9)
+#    define NV40_FP_OP_OUT_X                                            (1 << 9)
+#    define NV40_FP_OP_OUT_Y                                            (1 <<10)
+#    define NV40_FP_OP_OUT_Z                                            (1 <<11)
+#    define NV40_FP_OP_OUT_W                                            (1 <<12)
+/* Uncertain about these, especially the input_src values.. it's possible that
+ * they can be dynamically changed.
+ */
+#define NV40_FP_OP_INPUT_SRC_SHIFT                                            13
+#define NV40_FP_OP_INPUT_SRC_MASK                                     (15 << 13)
+#    define NV40_FP_OP_INPUT_SRC_POSITION                                    0x0
+#    define NV40_FP_OP_INPUT_SRC_COL0                                        0x1
+#    define NV40_FP_OP_INPUT_SRC_COL1                                        0x2
+#    define NV40_FP_OP_INPUT_SRC_FOGC                                        0x3
+#    define NV40_FP_OP_INPUT_SRC_TC0                                         0x4
+#    define NV40_FP_OP_INPUT_SRC_TC(n)                                 (0x4 + n)
+#    define NV40_FP_OP_INPUT_SRC_FACING                                      0xE
+#define NV40_FP_OP_TEX_UNIT_SHIFT                                             17
+#define NV40_FP_OP_TEX_UNIT_MASK                                     (0xF << 17)
+#define NV40_FP_OP_PRECISION_SHIFT                                            22
+#define NV40_FP_OP_PRECISION_MASK                                      (3 << 22)
+#   define NV40_FP_PRECISION_FP32                                              0
+#   define NV40_FP_PRECISION_FP16                                              1
+#   define NV40_FP_PRECISION_FX12                                              2
+#define NV40_FP_OP_OPCODE_SHIFT                                               24
+#define NV40_FP_OP_OPCODE_MASK                                      (0x3F << 24)
+#        define NV40_FP_OP_OPCODE_NOP                                       0x00
+#        define NV40_FP_OP_OPCODE_MOV                                       0x01
+#        define NV40_FP_OP_OPCODE_MUL                                       0x02
+#        define NV40_FP_OP_OPCODE_ADD                                       0x03
+#        define NV40_FP_OP_OPCODE_MAD                                       0x04
+#        define NV40_FP_OP_OPCODE_DP3                                       0x05
+#        define NV40_FP_OP_OPCODE_DP4                                       0x06
+#        define NV40_FP_OP_OPCODE_DST                                       0x07
+#        define NV40_FP_OP_OPCODE_MIN                                       0x08
+#        define NV40_FP_OP_OPCODE_MAX                                       0x09
+#        define NV40_FP_OP_OPCODE_SLT                                       0x0A
+#        define NV40_FP_OP_OPCODE_SGE                                       0x0B
+#        define NV40_FP_OP_OPCODE_SLE                                       0x0C
+#        define NV40_FP_OP_OPCODE_SGT                                       0x0D
+#        define NV40_FP_OP_OPCODE_SNE                                       0x0E
+#        define NV40_FP_OP_OPCODE_SEQ                                       0x0F
+#        define NV40_FP_OP_OPCODE_FRC                                       0x10
+#        define NV40_FP_OP_OPCODE_FLR                                       0x11
+#        define NV40_FP_OP_OPCODE_KIL                                       0x12
+#        define NV40_FP_OP_OPCODE_PK4B                                      0x13
+#        define NV40_FP_OP_OPCODE_UP4B                                      0x14
+/* DDX/DDY can only write to XY */
+#        define NV40_FP_OP_OPCODE_DDX                                       0x15
+#        define NV40_FP_OP_OPCODE_DDY                                       0x16
+#        define NV40_FP_OP_OPCODE_TEX                                       0x17
+#        define NV40_FP_OP_OPCODE_TXP                                       0x18
+#        define NV40_FP_OP_OPCODE_TXD                                       0x19
+#        define NV40_FP_OP_OPCODE_RCP                                       0x1A
+#        define NV40_FP_OP_OPCODE_EX2                                       0x1C
+#        define NV40_FP_OP_OPCODE_LG2                                       0x1D
+#        define NV40_FP_OP_OPCODE_STR                                       0x20
+#        define NV40_FP_OP_OPCODE_SFL                                       0x21
+#        define NV40_FP_OP_OPCODE_COS                                       0x22
+#        define NV40_FP_OP_OPCODE_SIN                                       0x23
+#        define NV40_FP_OP_OPCODE_PK2H                                      0x24
+#        define NV40_FP_OP_OPCODE_UP2H                                      0x25
+#        define NV40_FP_OP_OPCODE_PK4UB                                     0x27
+#        define NV40_FP_OP_OPCODE_UP4UB                                     0x28
+#        define NV40_FP_OP_OPCODE_PK2US                                     0x29
+#        define NV40_FP_OP_OPCODE_UP2US                                     0x2A
+#        define NV40_FP_OP_OPCODE_DP2A                                      0x2E
+#        define NV40_FP_OP_OPCODE_TXL                                       0x2F
+#        define NV40_FP_OP_OPCODE_TXB                                       0x31
+#        define NV40_FP_OP_OPCODE_DIV                                       0x3A
+#        define NV40_FP_OP_OPCODE_UNK_LIT                                   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_SAT                                             (1 << 31)
+
+/* high order bits of SRC0 */
+#define NV40_FP_OP_OUT_ABS                                             (1 << 29)
+#define NV40_FP_OP_COND_SWZ_W_SHIFT                                           27
+#define NV40_FP_OP_COND_SWZ_W_MASK                                     (3 << 27)
+#define NV40_FP_OP_COND_SWZ_Z_SHIFT                                           25
+#define NV40_FP_OP_COND_SWZ_Z_MASK                                     (3 << 25)
+#define NV40_FP_OP_COND_SWZ_Y_SHIFT                                           23
+#define NV40_FP_OP_COND_SWZ_Y_MASK                                     (3 << 23)
+#define NV40_FP_OP_COND_SWZ_X_SHIFT                                           21
+#define NV40_FP_OP_COND_SWZ_X_MASK                                     (3 << 21)
+#define NV40_FP_OP_COND_SWZ_ALL_SHIFT                                         21
+#define NV40_FP_OP_COND_SWZ_ALL_MASK                                (0xFF << 21)
+#define NV40_FP_OP_COND_SHIFT                                                 18
+#define NV40_FP_OP_COND_MASK                                        (0x07 << 18)
+#        define NV40_FP_OP_COND_FL                                             0
+#        define NV40_FP_OP_COND_LT                                             1
+#        define NV40_FP_OP_COND_EQ                                             2
+#        define NV40_FP_OP_COND_LE                                             3
+#        define NV40_FP_OP_COND_GT                                             4
+#        define NV40_FP_OP_COND_NE                                             5
+#        define NV40_FP_OP_COND_GE                                             6
+#        define NV40_FP_OP_COND_TR                                             7
+
+/* high order bits of SRC1 */
+#define NV40_FP_OP_OPCODE_IS_BRANCH                                      (1<<31)
+#define NV40_FP_OP_DST_SCALE_SHIFT                                            28
+#define NV40_FP_OP_DST_SCALE_MASK                                      (3 << 28)
+#define NV40_FP_OP_DST_SCALE_1X                                                0
+#define NV40_FP_OP_DST_SCALE_2X                                                1
+#define NV40_FP_OP_DST_SCALE_4X                                                2
+#define NV40_FP_OP_DST_SCALE_8X                                                3
+#define NV40_FP_OP_DST_SCALE_INV_2X                                            5
+#define NV40_FP_OP_DST_SCALE_INV_4X                                            6
+#define NV40_FP_OP_DST_SCALE_INV_8X                                            7
+
+/* 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 */
+#define NV40_FP_OP_ELSE_ID_SHIFT                                               2
+#define NV40_FP_OP_ELSE_ID_MASK                                      (0xFF << 2)
+
+/* SRC1 CAL */
+#define NV40_FP_OP_IADDR_SHIFT                                                 2
+#define NV40_FP_OP_IADDR_MASK                                        (0xFF << 2)
+
+/* 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 */
+#define NV40_FP_OP_END_ID_SHIFT                                                2
+#define NV40_FP_OP_END_ID_MASK                                       (0xFF << 2)
+
+// SRC2 high-order
+#define NV40_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 NV40_FP_REG_TYPE_SHIFT                                                 0
+#define NV40_FP_REG_TYPE_MASK                                           (3 << 0)
+#        define NV40_FP_REG_TYPE_TEMP                                          0
+#        define NV40_FP_REG_TYPE_INPUT                                         1
+#        define NV40_FP_REG_TYPE_CONST                                         2
+#define NV40_FP_REG_SRC_SHIFT                                                  2
+#define NV40_FP_REG_SRC_MASK                                           (63 << 2)
+#define NV40_FP_REG_SRC_HALF                                            (1 << 8)
+#define NV40_FP_REG_SWZ_ALL_SHIFT                                              9
+#define NV40_FP_REG_SWZ_ALL_MASK                                      (255 << 9)
+#define NV40_FP_REG_SWZ_X_SHIFT                                                9
+#define NV40_FP_REG_SWZ_X_MASK                                          (3 << 9)
+#define NV40_FP_REG_SWZ_Y_SHIFT                                               11
+#define NV40_FP_REG_SWZ_Y_MASK                                         (3 << 11)
+#define NV40_FP_REG_SWZ_Z_SHIFT                                               13
+#define NV40_FP_REG_SWZ_Z_MASK                                         (3 << 13)
+#define NV40_FP_REG_SWZ_W_SHIFT                                               15
+#define NV40_FP_REG_SWZ_W_MASK                                         (3 << 15)
+#        define NV40_FP_SWIZZLE_X                                              0
+#        define NV40_FP_SWIZZLE_Y                                              1
+#        define NV40_FP_SWIZZLE_Z                                              2
+#        define NV40_FP_SWIZZLE_W                                              3
+#define NV40_FP_REG_NEGATE                                             (1 << 17)
+
+#ifndef NV40_SHADER_NO_FUCKEDNESS
+#define NV40SR_NONE    0
+#define NV40SR_OUTPUT  1
+#define NV40SR_INPUT   2
+#define NV40SR_TEMP    3
+#define NV40SR_CONST   4
+
+struct nv40_sreg {
+       int type;
+       int index;
+
+       int dst_scale;
+
+       int negate;
+       int abs;
+       int swz[4];
+
+       int cc_update;
+       int cc_update_reg;
+       int cc_test;
+       int cc_test_reg;
+       int cc_swz[4];
+};
+
+static INLINE struct nv40_sreg
+nv40_sr(int type, int index)
+{
+       struct nv40_sreg temp = {
+               .type = type,
+               .index = index,
+               .dst_scale = DEF_SCALE,
+               .abs = 0,
+               .negate = 0,
+               .swz = { 0, 1, 2, 3 },
+               .cc_update = 0,
+               .cc_update_reg = 0,
+               .cc_test = DEF_CTEST,
+               .cc_test_reg = 0,
+               .cc_swz = { 0, 1, 2, 3 },
+       };
+       return temp;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_swz(struct nv40_sreg src, int x, int y, int z, int w)
+{
+       struct nv40_sreg dst = src;
+
+       dst.swz[SWZ_X] = src.swz[x];
+       dst.swz[SWZ_Y] = src.swz[y];
+       dst.swz[SWZ_Z] = src.swz[z];
+       dst.swz[SWZ_W] = src.swz[w];
+       return dst;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_neg(struct nv40_sreg src)
+{
+       src.negate = !src.negate;
+       return src;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_abs(struct nv40_sreg src)
+{
+       src.abs = 1;
+       return src;
+}
+
+static INLINE struct nv40_sreg
+nv40_sr_scale(struct nv40_sreg src, int scale)
+{
+       src.dst_scale = scale;
+       return src;
+}
+#endif
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
new file mode 100644 (file)
index 0000000..afcf336
--- /dev/null
@@ -0,0 +1,737 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "draw/draw_context.h"
+
+#include "nv40_context.h"
+#include "nv40_state.h"
+
+static void *
+nv40_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nouveau_grobj *curie = nv40->screen->curie;
+       struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso));
+       struct nouveau_stateobj *so = so_new(16, 0);
+
+       if (cso->blend_enable) {
+               so_method(so, curie, NV40TCL_BLEND_ENABLE, 3);
+               so_data  (so, 1);
+               so_data  (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
+                              nvgl_blend_func(cso->rgb_src_factor));
+               so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
+                             nvgl_blend_func(cso->rgb_dst_factor));
+               so_method(so, curie, NV40TCL_BLEND_EQUATION, 1);
+               so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
+                             nvgl_blend_eqn(cso->rgb_func));
+       } else {
+               so_method(so, curie, NV40TCL_BLEND_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, curie, NV40TCL_COLOR_MASK, 1);
+       so_data  (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
+                      ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
+                      ((cso->colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) |
+                      ((cso->colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0)));
+
+       if (cso->logicop_enable) {
+               so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
+               so_data  (so, 1);
+               so_data  (so, nvgl_logicop_func(cso->logicop_func));
+       } else {
+               so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, curie, NV40TCL_DITHER_ENABLE, 1);
+       so_data  (so, cso->dither ? 1 : 0);
+
+       so_ref(so, &bso->so);
+       bso->pipe = *cso;
+       return (void *)bso;
+}
+
+static void
+nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->blend = hwcso;
+       nv40->dirty |= NV40_NEW_BLEND;
+}
+
+static void
+nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_blend_state *bso = hwcso;
+
+       so_ref(NULL, &bso->so);
+       FREE(bso);
+}
+
+
+static INLINE unsigned
+wrap_mode(unsigned wrap) {
+       unsigned ret;
+
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               ret = NV40TCL_TEX_WRAP_S_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_CLAMP:
+               ret = NV40TCL_TEX_WRAP_S_CLAMP;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+               ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+               ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER;
+               break;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+               ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP;
+               break;
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               ret = NV40TCL_TEX_WRAP_S_REPEAT;
+               break;
+       }
+
+       return ret >> NV40TCL_TEX_WRAP_S_SHIFT;
+}
+
+static void *
+nv40_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+       struct nv40_sampler_state *ps;
+       uint32_t filter = 0;
+
+       ps = MALLOC(sizeof(struct nv40_sampler_state));
+
+       ps->fmt = 0;
+       if (!cso->normalized_coords)
+               ps->fmt |= NV40TCL_TEX_FORMAT_RECT;
+
+       ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) |
+                   (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) |
+                   (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT));
+
+       ps->en = 0;
+       if (cso->max_anisotropy >= 2.0) {
+               /* no idea, binary driver sets it, works without it.. meh.. */
+               ps->wrap |= (1 << 5);
+
+               if (cso->max_anisotropy >= 16.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
+               } else
+               if (cso->max_anisotropy >= 12.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
+               } else
+               if (cso->max_anisotropy >= 10.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
+               } else
+               if (cso->max_anisotropy >= 8.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
+               } else
+               if (cso->max_anisotropy >= 6.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
+               } else
+               if (cso->max_anisotropy >= 4.0) {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
+               } else {
+                       ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
+               }
+       }
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               filter |= NV40TCL_TEX_FILTER_MAG_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               filter |= NV40TCL_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 |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST;
+                       break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV40TCL_TEX_FILTER_MIN_LINEAR;
+                       break;
+               }
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               switch (cso->min_mip_filter) {
+               case PIPE_TEX_MIPFILTER_NEAREST:
+                       filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST;
+               break;
+               case PIPE_TEX_MIPFILTER_LINEAR:
+                       filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR;
+                       break;
+               case PIPE_TEX_MIPFILTER_NONE:
+               default:
+                       filter |= NV40TCL_TEX_FILTER_MIN_NEAREST;
+                       break;
+               }
+               break;
+       }
+
+       ps->filt = filter;
+
+       {
+               float limit;
+
+               limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+               ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+
+               limit = CLAMP(cso->max_lod, 0.0, 15.0);
+               ps->en |= (int)(limit * 256.0) << 7;
+
+               limit = CLAMP(cso->min_lod, 0.0, 15.0);
+               ps->en |= (int)(limit * 256.0) << 19;
+       }
+
+
+       if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+               switch (cso->compare_func) {
+               case PIPE_FUNC_NEVER:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER;
+                       break;
+               case PIPE_FUNC_GREATER:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER;
+                       break;
+               case PIPE_FUNC_EQUAL:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL;
+                       break;
+               case PIPE_FUNC_GEQUAL:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL;
+                       break;
+               case PIPE_FUNC_LESS:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS;
+                       break;
+               case PIPE_FUNC_NOTEQUAL:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL;
+                       break;
+               case PIPE_FUNC_LEQUAL:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL;
+                       break;
+               case PIPE_FUNC_ALWAYS:
+                       ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
+                   (float_to_ubyte(cso->border_color[0]) << 16) |
+                   (float_to_ubyte(cso->border_color[1]) <<  8) |
+                   (float_to_ubyte(cso->border_color[2]) <<  0));
+
+       return (void *)ps;
+}
+
+static void
+nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               nv40->tex_sampler[unit] = sampler[unit];
+               nv40->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nv40->nr_samplers; unit++) {
+               nv40->tex_sampler[unit] = NULL;
+               nv40->dirty_samplers |= (1 << unit);
+       }
+
+       nv40->nr_samplers = nr;
+       nv40->dirty |= NV40_NEW_SAMPLER;
+}
+
+static void
+nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void
+nv40_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+                        struct pipe_texture **miptree)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       unsigned unit;
+
+       for (unit = 0; unit < nr; unit++) {
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv40->tex_miptree[unit], miptree[unit]);
+               nv40->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nv40->nr_textures; unit++) {
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv40->tex_miptree[unit], NULL);
+               nv40->dirty_samplers |= (1 << unit);
+       }
+
+       nv40->nr_textures = nr;
+       nv40->dirty |= NV40_NEW_SAMPLER;
+}
+
+static void *
+nv40_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
+       struct nouveau_stateobj *so = so_new(32, 0);
+       struct nouveau_grobj *curie = nv40->screen->curie;
+
+       /*XXX: ignored:
+        *      light_twoside
+        *      point_smooth -nohw
+        *      multisample
+        */
+
+       so_method(so, curie, NV40TCL_SHADE_MODEL, 1);
+       so_data  (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT :
+                                      NV40TCL_SHADE_MODEL_SMOOTH);
+
+       so_method(so, curie, NV40TCL_LINE_WIDTH, 2);
+       so_data  (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+       so_data  (so, cso->line_smooth ? 1 : 0);
+       so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2);
+       so_data  (so, cso->line_stipple_enable ? 1 : 0);
+       so_data  (so, (cso->line_stipple_pattern << 16) |
+                      cso->line_stipple_factor);
+
+       so_method(so, curie, NV40TCL_POINT_SIZE, 1);
+       so_data  (so, fui(cso->point_size));
+
+       so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV40TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV40TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV40TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV40TCL_FRONT_FACE_CCW);
+       } else {
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV40TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV40TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV40TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV40TCL_FRONT_FACE_CW);
+       }
+       so_data(so, cso->poly_smooth ? 1 : 0);
+       so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0);
+
+       so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+       so_data  (so, cso->poly_stipple_enable ? 1 : 0);
+
+       so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if (cso->offset_cw || cso->offset_ccw) {
+               so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2);
+               so_data  (so, fui(cso->offset_scale));
+               so_data  (so, fui(cso->offset_units * 2));
+       }
+
+       so_method(so, curie, NV40TCL_POINT_SPRITE, 1);
+       if (cso->point_sprite) {
+               unsigned psctl = (1 << 0), i;
+
+               for (i = 0; i < 8; i++) {
+                       if (cso->sprite_coord_mode[i] != PIPE_SPRITE_COORD_NONE)
+                               psctl |= (1 << (8 + i));
+               }
+
+               so_data(so, psctl);
+       } else {
+               so_data(so, 0);
+       }
+
+       so_ref(so, &rsso->so);
+       rsso->pipe = *cso;
+       return (void *)rsso;
+}
+
+static void
+nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->rasterizer = hwcso;
+       nv40->dirty |= NV40_NEW_RAST;
+       nv40->draw_dirty |= NV40_NEW_RAST;
+}
+
+static void
+nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_rasterizer_state *rsso = hwcso;
+
+       so_ref(NULL, &rsso->so);
+       FREE(rsso);
+}
+
+static void *
+nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
+       struct nouveau_stateobj *so = so_new(32, 0);
+       struct nouveau_grobj *curie = nv40->screen->curie;
+
+       so_method(so, curie, NV40TCL_DEPTH_FUNC, 3);
+       so_data  (so, nvgl_comparison_op(cso->depth.func));
+       so_data  (so, cso->depth.writemask ? 1 : 0);
+       so_data  (so, cso->depth.enabled ? 1 : 0);
+
+       so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3);
+       so_data  (so, cso->alpha.enabled ? 1 : 0);
+       so_data  (so, nvgl_comparison_op(cso->alpha.func));
+       so_data  (so, float_to_ubyte(cso->alpha.ref));
+
+       if (cso->stencil[0].enabled) {
+               so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 8);
+               so_data  (so, cso->stencil[0].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[0].write_mask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
+               so_data  (so, cso->stencil[0].ref_value);
+               so_data  (so, cso->stencil[0].value_mask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+       } else {
+               so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       if (cso->stencil[1].enabled) {
+               so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 8);
+               so_data  (so, cso->stencil[1].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[1].write_mask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
+               so_data  (so, cso->stencil[1].ref_value);
+               so_data  (so, cso->stencil[1].value_mask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+       } else {
+               so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_ref(so, &zsaso->so);
+       zsaso->pipe = *cso;
+       return (void *)zsaso;
+}
+
+static void
+nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->zsa = hwcso;
+       nv40->dirty |= NV40_NEW_ZSA;
+}
+
+static void
+nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_zsa_state *zsaso = hwcso;
+
+       so_ref(NULL, &zsaso->so);
+       FREE(zsaso);
+}
+
+static void *
+nv40_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_vertex_program *vp;
+
+       vp = CALLOC(1, sizeof(struct nv40_vertex_program));
+       vp->pipe = *cso;
+       vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe);
+
+       return (void *)vp;
+}
+
+static void
+nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->vertprog = hwcso;
+       nv40->dirty |= NV40_NEW_VERTPROG;
+       nv40->draw_dirty |= NV40_NEW_VERTPROG;
+}
+
+static void
+nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_vertex_program *vp = hwcso;
+
+       draw_delete_vertex_shader(nv40->draw, vp->draw);
+       nv40_vertprog_destroy(nv40, vp);
+       FREE(vp);
+}
+
+static void *
+nv40_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv40_fragment_program *fp;
+
+       fp = CALLOC(1, sizeof(struct nv40_fragment_program));
+       fp->pipe = *cso;
+
+       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+
+       return (void *)fp;
+}
+
+static void
+nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->fragprog = hwcso;
+       nv40->dirty |= NV40_NEW_FRAGPROG;
+}
+
+static void
+nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nv40_fragment_program *fp = hwcso;
+
+       nv40_fragprog_destroy(nv40, fp);
+       FREE(fp);
+}
+
+static void
+nv40_set_blend_color(struct pipe_context *pipe,
+                    const struct pipe_blend_color *bcol)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->blend_colour = *bcol;
+       nv40->dirty |= NV40_NEW_BCOL;
+}
+
+static void
+nv40_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->clip = *clip;
+       nv40->dirty |= NV40_NEW_UCP;
+       nv40->draw_dirty |= NV40_NEW_UCP;
+}
+
+static void
+nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        const struct pipe_constant_buffer *buf )
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->constbuf[shader] = buf->buffer;
+       nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
+
+       if (shader == PIPE_SHADER_VERTEX) {
+               nv40->dirty |= NV40_NEW_VERTPROG;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nv40->dirty |= NV40_NEW_FRAGPROG;
+       }
+}
+
+static void
+nv40_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->framebuffer = *fb;
+       nv40->dirty |= NV40_NEW_FB;
+}
+
+static void
+nv40_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       memcpy(nv40->stipple, stipple->stipple, 4 * 32);
+       nv40->dirty |= NV40_NEW_STIPPLE;
+}
+
+static void
+nv40_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->scissor = *s;
+       nv40->dirty |= NV40_NEW_SCISSOR;
+}
+
+static void
+nv40_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *vpt)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->viewport = *vpt;
+       nv40->dirty |= NV40_NEW_VIEWPORT;
+       nv40->draw_dirty |= NV40_NEW_VIEWPORT;
+}
+
+static void
+nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count);
+       nv40->vtxbuf_nr = count;
+
+       nv40->dirty |= NV40_NEW_ARRAYS;
+       nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+static void
+nv40_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+                        const struct pipe_vertex_element *ve)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       memcpy(nv40->vtxelt, ve, sizeof(*ve) * count);
+       nv40->vtxelt_nr = count;
+
+       nv40->dirty |= NV40_NEW_ARRAYS;
+       nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+static void
+nv40_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+
+       nv40->edgeflags = bitfield;
+       nv40->dirty |= NV40_NEW_ARRAYS;
+       nv40->draw_dirty |= NV40_NEW_ARRAYS;
+}
+
+void
+nv40_init_state_functions(struct nv40_context *nv40)
+{
+       nv40->pipe.create_blend_state = nv40_blend_state_create;
+       nv40->pipe.bind_blend_state = nv40_blend_state_bind;
+       nv40->pipe.delete_blend_state = nv40_blend_state_delete;
+
+       nv40->pipe.create_sampler_state = nv40_sampler_state_create;
+       nv40->pipe.bind_sampler_states = nv40_sampler_state_bind;
+       nv40->pipe.delete_sampler_state = nv40_sampler_state_delete;
+       nv40->pipe.set_sampler_textures = nv40_set_sampler_texture;
+
+       nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create;
+       nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind;
+       nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete;
+
+       nv40->pipe.create_depth_stencil_alpha_state =
+               nv40_depth_stencil_alpha_state_create;
+       nv40->pipe.bind_depth_stencil_alpha_state =
+               nv40_depth_stencil_alpha_state_bind;
+       nv40->pipe.delete_depth_stencil_alpha_state =
+               nv40_depth_stencil_alpha_state_delete;
+
+       nv40->pipe.create_vs_state = nv40_vp_state_create;
+       nv40->pipe.bind_vs_state = nv40_vp_state_bind;
+       nv40->pipe.delete_vs_state = nv40_vp_state_delete;
+
+       nv40->pipe.create_fs_state = nv40_fp_state_create;
+       nv40->pipe.bind_fs_state = nv40_fp_state_bind;
+       nv40->pipe.delete_fs_state = nv40_fp_state_delete;
+
+       nv40->pipe.set_blend_color = nv40_set_blend_color;
+       nv40->pipe.set_clip_state = nv40_set_clip_state;
+       nv40->pipe.set_constant_buffer = nv40_set_constant_buffer;
+       nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state;
+       nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple;
+       nv40->pipe.set_scissor_state = nv40_set_scissor_state;
+       nv40->pipe.set_viewport_state = nv40_set_viewport_state;
+
+       nv40->pipe.set_edgeflags = nv40_set_edgeflags;
+       nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers;
+       nv40->pipe.set_vertex_elements = nv40_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h
new file mode 100644 (file)
index 0000000..2b4225d
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __NV40_STATE_H__
+#define __NV40_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
+
+struct nv40_sampler_state {
+       uint32_t fmt;
+       uint32_t wrap;
+       uint32_t en;
+       uint32_t filt;
+       uint32_t bcol;
+};
+
+struct nv40_vertex_program_exec {
+       uint32_t data[4];
+       boolean has_branch_offset;
+       int const_index;
+};
+
+struct nv40_vertex_program_data {
+       int index; /* immediates == -1 */
+       float value[4];
+};
+
+struct nv40_vertex_program {
+       struct pipe_shader_state pipe;
+
+       struct draw_vertex_shader *draw;
+
+       boolean translated;
+
+       struct pipe_clip_state ucp;
+
+       struct nv40_vertex_program_exec *insns;
+       unsigned nr_insns;
+       struct nv40_vertex_program_data *consts;
+       unsigned nr_consts;
+
+       struct nouveau_resource *exec;
+       unsigned exec_start;
+       struct nouveau_resource *data;
+       unsigned data_start;
+       unsigned data_start_min;
+
+       uint32_t ir;
+       uint32_t or;
+       uint32_t clip_ctrl;
+       struct nouveau_stateobj *so;
+};
+
+struct nv40_fragment_program_data {
+       unsigned offset;
+       unsigned index;
+};
+
+struct nv40_fragment_program {
+       struct pipe_shader_state pipe;
+       struct tgsi_shader_info info;
+
+       boolean translated;
+       unsigned samplers;
+
+       uint32_t *insn;
+       int       insn_len;
+
+       struct nv40_fragment_program_data *consts;
+       unsigned nr_consts;
+
+       struct pipe_buffer *buffer;
+
+       uint32_t fp_control;
+       struct nouveau_stateobj *so;
+};
+
+struct nv40_miptree {
+       struct pipe_texture base;
+
+       struct pipe_buffer *buffer;
+       uint total_size;
+
+       struct {
+               uint pitch;
+               uint *image_offset;
+       } level[PIPE_MAX_TEXTURE_LEVELS];
+};
+
+#endif
diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c
new file mode 100644 (file)
index 0000000..95e6d73
--- /dev/null
@@ -0,0 +1,40 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_blend_validate(struct nv40_context *nv40)
+{
+       so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend = {
+       .validate = nv40_state_blend_validate,
+       .dirty = {
+               .pipe = NV40_NEW_BLEND,
+               .hw = NV40_STATE_BLEND
+       }
+};
+
+static boolean
+nv40_state_blend_colour_validate(struct nv40_context *nv40)
+{
+       struct nouveau_stateobj *so = so_new(2, 0);
+       struct pipe_blend_color *bcol = &nv40->blend_colour;
+
+       so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1);
+       so_data  (so, ((float_to_ubyte(bcol->color[3]) << 24) |
+                      (float_to_ubyte(bcol->color[0]) << 16) |
+                      (float_to_ubyte(bcol->color[1]) <<  8) |
+                      (float_to_ubyte(bcol->color[2]) <<  0)));
+
+       so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_blend_colour = {
+       .validate = nv40_state_blend_colour_validate,
+       .dirty = {
+               .pipe = NV40_NEW_BCOL,
+               .hw = NV40_STATE_BCOL
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
new file mode 100644 (file)
index 0000000..ab88dc4
--- /dev/null
@@ -0,0 +1,184 @@
+#include "nv40_context.h"
+#include "nv40_state.h"
+#include "draw/draw_context.h"
+
+static struct nv40_state_entry *render_states[] = {
+       &nv40_state_framebuffer,
+       &nv40_state_rasterizer,
+       &nv40_state_scissor,
+       &nv40_state_stipple,
+       &nv40_state_fragprog,
+       &nv40_state_fragtex,
+       &nv40_state_vertprog,
+       &nv40_state_blend,
+       &nv40_state_blend_colour,
+       &nv40_state_zsa,
+       &nv40_state_viewport,
+       &nv40_state_vbo,
+       NULL
+};
+
+static struct nv40_state_entry *swtnl_states[] = {
+       &nv40_state_framebuffer,
+       &nv40_state_rasterizer,
+       &nv40_state_scissor,
+       &nv40_state_stipple,
+       &nv40_state_fragprog,
+       &nv40_state_fragtex,
+       &nv40_state_vertprog,
+       &nv40_state_blend,
+       &nv40_state_blend_colour,
+       &nv40_state_zsa,
+       &nv40_state_viewport,
+       &nv40_state_vtxfmt,
+       NULL
+};
+
+static void
+nv40_state_do_validate(struct nv40_context *nv40,
+                      struct nv40_state_entry **states)
+{
+       const struct pipe_framebuffer_state *fb = &nv40->framebuffer;
+       unsigned i;
+
+       for (i = 0; i < fb->num_cbufs; i++)
+               fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
+       if (fb->zsbuf)
+               fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       while (*states) {
+               struct nv40_state_entry *e = *states;
+
+               if (nv40->dirty & e->dirty.pipe) {
+                       if (e->validate(nv40))
+                               nv40->state.dirty |= (1ULL << e->dirty.hw);
+               }
+
+               states++;
+       }
+       nv40->dirty = 0;
+}
+
+void
+nv40_state_emit(struct nv40_context *nv40)
+{
+       struct nv40_state *state = &nv40->state;
+       struct nv40_screen *screen = nv40->screen;
+       unsigned i, samplers;
+       uint64 states;
+
+       if (nv40->pctx_id != screen->cur_pctx) {
+               for (i = 0; i < NV40_STATE_MAX; i++) {
+                       if (state->hw[i] && screen->state[i] != state->hw[i])
+                               state->dirty |= (1ULL << i);
+               }
+
+               screen->cur_pctx = nv40->pctx_id;
+       }
+
+       for (i = 0, states = state->dirty; states; i++) {
+               if (!(states & (1ULL << i)))
+                       continue;
+               so_ref (state->hw[i], &nv40->screen->state[i]);
+               if (state->hw[i])
+                       so_emit(nv40->nvws, nv40->screen->state[i]);
+               states &= ~(1ULL << i);
+       }
+
+       if (state->dirty & ((1ULL << NV40_STATE_FRAGPROG) |
+                           (1ULL << NV40_STATE_FRAGTEX0))) {
+               BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+               OUT_RING  (2);
+               BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
+               OUT_RING  (1);
+       }
+
+       state->dirty = 0;
+
+       so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]);
+       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+               if (!(samplers & (1 << i)))
+                       continue;
+               so_emit_reloc_markers(nv40->nvws,
+                                     state->hw[NV40_STATE_FRAGTEX0+i]);
+               samplers &= ~(1ULL << i);
+       }
+       so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]);
+       if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW)
+               so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]);
+}
+
+boolean
+nv40_state_validate(struct nv40_context *nv40)
+{
+       boolean was_sw = nv40->fallback_swtnl ? TRUE : FALSE;
+
+       if (nv40->render_mode != HW) {
+               /* Don't even bother trying to go back to hw if none
+                * of the states that caused swtnl previously have changed.
+                */
+               if ((nv40->fallback_swtnl & nv40->dirty)
+                               != nv40->fallback_swtnl)
+                       return FALSE;
+
+               /* Attempt to go to hwtnl again */
+               nv40->pipe.flush(&nv40->pipe, 0, NULL);
+               nv40->dirty |= (NV40_NEW_VIEWPORT |
+                               NV40_NEW_VERTPROG |
+                               NV40_NEW_ARRAYS);
+               nv40->render_mode = HW;
+       }
+
+       nv40_state_do_validate(nv40, render_states);
+       if (nv40->fallback_swtnl || nv40->fallback_swrast)
+               return FALSE;
+       
+       if (was_sw)
+               NOUVEAU_ERR("swtnl->hw\n");
+
+       return TRUE;
+}
+
+boolean
+nv40_state_validate_swtnl(struct nv40_context *nv40)
+{
+       struct draw_context *draw = nv40->draw;
+
+       /* Setup for swtnl */
+       if (nv40->render_mode == HW) {
+               NOUVEAU_ERR("hw->swtnl 0x%08x\n", nv40->fallback_swtnl);
+               nv40->pipe.flush(&nv40->pipe, 0, NULL);
+               nv40->dirty |= (NV40_NEW_VIEWPORT |
+                               NV40_NEW_VERTPROG |
+                               NV40_NEW_ARRAYS);
+               nv40->render_mode = SWTNL;
+       }
+
+       if (nv40->draw_dirty & NV40_NEW_VERTPROG)
+               draw_bind_vertex_shader(draw, nv40->vertprog->draw);
+
+       if (nv40->draw_dirty & NV40_NEW_RAST)
+               draw_set_rasterizer_state(draw, &nv40->rasterizer->pipe);
+
+       if (nv40->draw_dirty & NV40_NEW_UCP)
+               draw_set_clip_state(draw, &nv40->clip);
+
+       if (nv40->draw_dirty & NV40_NEW_VIEWPORT)
+               draw_set_viewport_state(draw, &nv40->viewport);
+
+       if (nv40->draw_dirty & NV40_NEW_ARRAYS) {
+               draw_set_edgeflags(draw, nv40->edgeflags);
+               draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf);
+               draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt);  
+       }
+
+       nv40_state_do_validate(nv40, swtnl_states);
+       if (nv40->fallback_swrast) {
+               NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nv40->fallback_swrast);
+               return FALSE;
+       }
+
+       nv40->draw_dirty = 0;
+       return TRUE;
+}
+
diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c
new file mode 100644 (file)
index 0000000..0e4e60e
--- /dev/null
@@ -0,0 +1,144 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_framebuffer_validate(struct nv40_context *nv40)
+{
+       struct pipe_framebuffer_state *fb = &nv40->framebuffer;
+       struct pipe_surface *rt[4], *zeta;
+       uint32_t rt_enable, rt_format;
+       int i, colour_format = 0, zeta_format = 0;
+       struct nouveau_stateobj *so = so_new(64, 10);
+       unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
+       unsigned w = fb->width;
+       unsigned h = fb->height;
+
+       rt_enable = 0;
+       for (i = 0; i < fb->num_cbufs; i++) {
+               if (colour_format) {
+                       assert(colour_format == fb->cbufs[i]->format);
+               } else {
+                       colour_format = fb->cbufs[i]->format;
+                       rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i);
+                       rt[i] = fb->cbufs[i];
+               }
+       }
+
+       if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 |
+                        NV40TCL_RT_ENABLE_COLOR3))
+               rt_enable |= NV40TCL_RT_ENABLE_MRT;
+
+       if (fb->zsbuf) {
+               zeta_format = fb->zsbuf->format;
+               zeta = fb->zsbuf;
+       }
+
+       rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR;
+
+       switch (colour_format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case 0:
+               rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8;
+               break;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5;
+               break;
+       default:
+               assert(0);
+       }
+
+       switch (zeta_format) {
+       case PIPE_FORMAT_Z16_UNORM:
+               rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16;
+               break;
+       case PIPE_FORMAT_Z24S8_UNORM:
+       case 0:
+               rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8;
+               break;
+       default:
+               assert(0);
+       }
+
+       if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
+               so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1);
+               so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv40->nvws->channel->vram->handle,
+                         nv40->nvws->channel->gart->handle);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2);
+               so_data  (so, rt[0]->stride);
+               so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+       }
+
+       if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
+               so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1);
+               so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv40->nvws->channel->vram->handle,
+                         nv40->nvws->channel->gart->handle);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2);
+               so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               so_data  (so, rt[1]->stride);
+       }
+
+       if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
+               so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1);
+               so_reloc (so, rt[2]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv40->nvws->channel->vram->handle,
+                         nv40->nvws->channel->gart->handle);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1);
+               so_reloc (so, rt[2]->buffer, rt[2]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1);
+               so_data  (so, rt[2]->stride);
+       }
+
+       if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
+               so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1);
+               so_reloc (so, rt[3]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv40->nvws->channel->vram->handle,
+                         nv40->nvws->channel->gart->handle);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1);
+               so_reloc (so, rt[3]->buffer, rt[3]->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1);
+               so_data  (so, rt[3]->stride);
+       }
+
+       if (zeta_format) {
+               so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1);
+               so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
+                         nv40->nvws->channel->vram->handle,
+                         nv40->nvws->channel->gart->handle);
+               so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1);
+               so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
+                         NOUVEAU_BO_LOW, 0, 0);
+               so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1);
+               so_data  (so, zeta->stride);
+       }
+
+       so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1);
+       so_data  (so, rt_enable);
+       so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3);
+       so_data  (so, (w << 16) | 0);
+       so_data  (so, (h << 16) | 0);
+       so_data  (so, rt_format);
+       so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2);
+       so_data  (so, (w << 16) | 0);
+       so_data  (so, (h << 16) | 0);
+       so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+       so_data  (so, ((w - 1) << 16) | 0);
+       so_data  (so, ((h - 1) << 16) | 0);
+       so_method(so, nv40->screen->curie, 0x1d88, 1);
+       so_data  (so, (1 << 12) | h);
+
+       so_ref(so, &nv40->state.hw[NV40_STATE_FB]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_framebuffer = {
+       .validate = nv40_state_framebuffer_validate,
+       .dirty = {
+               .pipe = NV40_NEW_FB,
+               .hw = NV40_STATE_FB
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
new file mode 100644 (file)
index 0000000..9ecda59
--- /dev/null
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_rasterizer_validate(struct nv40_context *nv40)
+{
+       so_ref(nv40->rasterizer->so,
+              &nv40->state.hw[NV40_STATE_RAST]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_rasterizer = {
+       .validate = nv40_state_rasterizer_validate,
+       .dirty = {
+               .pipe = NV40_NEW_RAST,
+               .hw = NV40_STATE_RAST
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c
new file mode 100644 (file)
index 0000000..285239e
--- /dev/null
@@ -0,0 +1,35 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_scissor_validate(struct nv40_context *nv40)
+{
+       struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+       struct pipe_scissor_state *s = &nv40->scissor;
+       struct nouveau_stateobj *so;
+
+       if (nv40->state.hw[NV40_STATE_SCISSOR] &&
+           (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
+               return FALSE;
+       nv40->state.scissor_enabled = rast->scissor;
+
+       so = so_new(3, 0);
+       so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2);
+       if (nv40->state.scissor_enabled) {
+               so_data  (so, ((s->maxx - s->minx) << 16) | s->minx);
+               so_data  (so, ((s->maxy - s->miny) << 16) | s->miny);
+       } else {
+               so_data  (so, 4096 << 16);
+               so_data  (so, 4096 << 16);
+       }
+
+       so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_scissor = {
+       .validate = nv40_state_scissor_validate,
+       .dirty = {
+               .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
+               .hw = NV40_STATE_SCISSOR
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c
new file mode 100644 (file)
index 0000000..b51024a
--- /dev/null
@@ -0,0 +1,39 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_stipple_validate(struct nv40_context *nv40)
+{
+       struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+       struct nouveau_grobj *curie = nv40->screen->curie;
+       struct nouveau_stateobj *so;
+
+       if (nv40->state.hw[NV40_STATE_STIPPLE] &&
+          (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0))
+               return FALSE;
+
+       if (rast->poly_stipple_enable) {
+               unsigned i;
+
+               so = so_new(35, 0);
+               so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+               for (i = 0; i < 32; i++)
+                       so_data(so, nv40->stipple[i]);
+       } else {
+               so = so_new(2, 0);
+               so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_stipple = {
+       .validate = nv40_state_stipple_validate,
+       .dirty = {
+               .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST,
+               .hw = NV40_STATE_STIPPLE,
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c
new file mode 100644 (file)
index 0000000..869a55b
--- /dev/null
@@ -0,0 +1,67 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_viewport_validate(struct nv40_context *nv40)
+{
+       struct pipe_viewport_state *vpt = &nv40->viewport;
+       struct nouveau_stateobj *so;
+       unsigned bypass;
+
+       if (nv40->render_mode == HW && !nv40->rasterizer->pipe.bypass_clipping)
+               bypass = 0;
+       else
+               bypass = 1;
+
+       if (nv40->state.hw[NV40_STATE_VIEWPORT] &&
+           (bypass || !(nv40->dirty & NV40_NEW_VIEWPORT)) &&
+           nv40->state.viewport_bypass == bypass)
+               return FALSE;
+       nv40->state.viewport_bypass = bypass;
+
+       so = so_new(11, 0);
+       if (!bypass) {
+               so_method(so, nv40->screen->curie,
+                         NV40TCL_VIEWPORT_TRANSLATE_X, 8);
+               so_data  (so, fui(vpt->translate[0]));
+               so_data  (so, fui(vpt->translate[1]));
+               so_data  (so, fui(vpt->translate[2]));
+               so_data  (so, fui(vpt->translate[3]));
+               so_data  (so, fui(vpt->scale[0]));
+               so_data  (so, fui(vpt->scale[1]));
+               so_data  (so, fui(vpt->scale[2]));
+               so_data  (so, fui(vpt->scale[3]));
+               so_method(so, nv40->screen->curie, 0x1d78, 1);
+               so_data  (so, 1);
+       } else {
+               so_method(so, nv40->screen->curie,
+                         NV40TCL_VIEWPORT_TRANSLATE_X, 8);
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(0.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(1.0));
+               so_data  (so, fui(0.0));
+               /* Not entirely certain what this is yet.  The DDX uses this
+                * value also as it fixes rendering when you pass
+                * pre-transformed vertices to the GPU.  My best gusss is that
+                * this bypasses some culling/clipping stage.  Might be worth
+                * noting that points/lines are uneffected by whatever this
+                * value fixes, only filled polygons are effected.
+                */
+               so_method(so, nv40->screen->curie, 0x1d78, 1);
+               so_data  (so, 0x110);
+       }
+
+       so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_viewport = {
+       .validate = nv40_state_viewport_validate,
+       .dirty = {
+               .pipe = NV40_NEW_VIEWPORT | NV40_NEW_RAST,
+               .hw = NV40_STATE_VIEWPORT
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c
new file mode 100644 (file)
index 0000000..fb76067
--- /dev/null
@@ -0,0 +1,17 @@
+#include "nv40_context.h"
+
+static boolean
+nv40_state_zsa_validate(struct nv40_context *nv40)
+{
+       so_ref(nv40->zsa->so,
+              &nv40->state.hw[NV40_STATE_ZSA]);
+       return TRUE;
+}
+
+struct nv40_state_entry nv40_state_zsa = {
+       .validate = nv40_state_zsa_validate,
+       .dirty = {
+               .pipe = NV40_NEW_ZSA,
+               .hw = NV40_STATE_ZSA
+       }
+};
diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c
new file mode 100644 (file)
index 0000000..0916555
--- /dev/null
@@ -0,0 +1,77 @@
+
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "nv40_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/p_tile.h"
+
+static void
+nv40_surface_copy(struct pipe_context *pipe, boolean do_flip,
+                 struct pipe_surface *dest, unsigned destx, unsigned desty,
+                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
+                 unsigned width, unsigned height)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nouveau_winsys *nvws = nv40->nvws;
+
+       if (do_flip) {
+               /*XXX: This dodgyness will do for now for correctness.  But,
+                *     need to investigate whether the 2D engine is able to
+                *     manage a flip (perhaps SIFM?), if not, use the 3D engine
+                */
+               desty += height;
+               while (height--) {
+                       nvws->surface_copy(nvws, dest, destx, desty--, src,
+                                          srcx, srcy++, width, 1);
+               }
+       } else {
+               nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+                                  width, height);
+       }
+}
+
+static void
+nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+                 unsigned destx, unsigned desty, unsigned width,
+                 unsigned height, unsigned value)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nouveau_winsys *nvws = nv40->nvws;
+
+       nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+void
+nv40_init_surface_functions(struct nv40_context *nv40)
+{
+       nv40->pipe.surface_copy = nv40_surface_copy;
+       nv40->pipe.surface_fill = nv40_surface_fill;
+}
diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c
new file mode 100644 (file)
index 0000000..93669e6
--- /dev/null
@@ -0,0 +1,560 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv40_context.h"
+#include "nv40_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+#include "nouveau/nouveau_util.h"
+
+#define FORCE_SWTNL 0
+
+static INLINE int
+nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp)
+{
+       char fs[128];
+
+       switch (pipe) {
+       case PIPE_FORMAT_R32_FLOAT:
+       case PIPE_FORMAT_R32G32_FLOAT:
+       case PIPE_FORMAT_R32G32B32_FLOAT:
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+               *fmt = NV40TCL_VTXFMT_TYPE_FLOAT;
+               break;
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R8G8_UNORM:
+       case PIPE_FORMAT_R8G8B8_UNORM:
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+               *fmt = NV40TCL_VTXFMT_TYPE_UBYTE;
+               break;
+       case PIPE_FORMAT_R16_SSCALED:
+       case PIPE_FORMAT_R16G16_SSCALED:
+       case PIPE_FORMAT_R16G16B16_SSCALED:
+       case PIPE_FORMAT_R16G16B16A16_SSCALED:
+               *fmt = NV40TCL_VTXFMT_TYPE_USHORT;
+               break;
+       default:
+               pf_sprint_name(fs, pipe);
+               NOUVEAU_ERR("Unknown format %s\n", fs);
+               return 1;
+       }
+
+       switch (pipe) {
+       case PIPE_FORMAT_R8_UNORM:
+       case PIPE_FORMAT_R32_FLOAT:
+       case PIPE_FORMAT_R16_SSCALED:
+               *ncomp = 1;
+               break;
+       case PIPE_FORMAT_R8G8_UNORM:
+       case PIPE_FORMAT_R32G32_FLOAT:
+       case PIPE_FORMAT_R16G16_SSCALED:
+               *ncomp = 2;
+               break;
+       case PIPE_FORMAT_R8G8B8_UNORM:
+       case PIPE_FORMAT_R32G32B32_FLOAT:
+       case PIPE_FORMAT_R16G16B16_SSCALED:
+               *ncomp = 3;
+               break;
+       case PIPE_FORMAT_R8G8B8A8_UNORM:
+       case PIPE_FORMAT_R32G32B32A32_FLOAT:
+       case PIPE_FORMAT_R16G16B16A16_SSCALED:
+               *ncomp = 4;
+               break;
+       default:
+               pf_sprint_name(fs, pipe);
+               NOUVEAU_ERR("Unknown format %s\n", fs);
+               return 1;
+       }
+
+       return 0;
+}
+
+static boolean
+nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib,
+                   unsigned ib_size)
+{
+       struct pipe_screen *pscreen = &nv40->screen->pipe;
+       unsigned type;
+
+       if (!ib) {
+               nv40->idxbuf = NULL;
+               nv40->idxbuf_format = 0xdeadbeef;
+               return FALSE;
+       }
+
+       if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1)
+               return FALSE;
+
+       switch (ib_size) {
+       case 2:
+               type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
+               break;
+       case 4:
+               type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
+               break;
+       default:
+               return FALSE;
+       }
+
+       if (ib != nv40->idxbuf ||
+           type != nv40->idxbuf_format) {
+               nv40->dirty |= NV40_NEW_ARRAYS;
+               nv40->idxbuf = ib;
+               nv40->idxbuf_format = type;
+       }
+
+       return TRUE;
+}
+
+static boolean
+nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so,
+                      int attrib, struct pipe_vertex_element *ve,
+                      struct pipe_vertex_buffer *vb)
+{
+       struct pipe_winsys *ws = nv40->pipe.winsys;
+       struct nouveau_grobj *curie = nv40->screen->curie;
+       unsigned type, ncomp;
+       void *map;
+
+       if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp))
+               return FALSE;
+
+       map  = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ);
+       map += vb->buffer_offset + ve->src_offset;
+
+       switch (type) {
+       case NV40TCL_VTXFMT_TYPE_FLOAT:
+       {
+               float *v = map;
+
+               switch (ncomp) {
+               case 4:
+                       so_method(so, curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       so_data  (so, fui(v[2]));
+                       so_data  (so, fui(v[3]));
+                       break;
+               case 3:
+                       so_method(so, curie, NV40TCL_VTX_ATTR_3F_X(attrib), 3);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       so_data  (so, fui(v[2]));
+                       break;
+               case 2:
+                       so_method(so, curie, NV40TCL_VTX_ATTR_2F_X(attrib), 2);
+                       so_data  (so, fui(v[0]));
+                       so_data  (so, fui(v[1]));
+                       break;
+               case 1:
+                       so_method(so, curie, NV40TCL_VTX_ATTR_1F(attrib), 1);
+                       so_data  (so, fui(v[0]));
+                       break;
+               default:
+                       ws->buffer_unmap(ws, vb->buffer);
+                       return FALSE;
+               }
+       }
+               break;
+       default:
+               ws->buffer_unmap(ws, vb->buffer);
+               return FALSE;
+       }
+
+       ws->buffer_unmap(ws, vb->buffer);
+
+       return TRUE;
+}
+
+boolean
+nv40_draw_arrays(struct pipe_context *pipe,
+                unsigned mode, unsigned start, unsigned count)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nouveau_channel *chan = nv40->nvws->channel;
+       unsigned restart;
+
+       nv40_vbo_set_idxbuf(nv40, NULL, 0);
+       if (FORCE_SWTNL || !nv40_state_validate(nv40)) {
+               return nv40_draw_elements_swtnl(pipe, NULL, 0,
+                                               mode, start, count);
+       }
+
+       while (count) {
+               unsigned vc, nr;
+
+               nv40_state_emit(nv40);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+                                       mode, start, count, &restart);
+               if (!vc) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               nr = (vc & 0xff);
+               if (nr) {
+                       BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1);
+                       OUT_RING  (((nr - 1) << 24) | start);
+                       start += nr;
+               }
+
+               nr = vc >> 8;
+               while (nr) {
+                       unsigned push = nr > 2047 ? 2047 : nr;
+
+                       nr -= push;
+
+                       BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, push);
+                       while (push--) {
+                               OUT_RING(((0x100 - 1) << 24) | start);
+                               start += 0x100;
+                       }
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               count -= vc;
+               start = restart;
+       }
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+static INLINE void
+nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv40->nvws->channel;
+
+       while (count) {
+               uint8_t *elts = (uint8_t *)ib + start;
+               unsigned vc, push, restart;
+
+               nv40_state_emit(nv40);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               if (vc & 1) {
+                       BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+                       OUT_RING  (elts[0]);
+                       elts++; vc--;
+               }
+
+               while (vc) {
+                       unsigned i;
+
+                       push = MIN2(vc, 2047 * 2);
+
+                       BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
+                       for (i = 0; i < push; i+=2)
+                               OUT_RING((elts[i+1] << 16) | elts[i]);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static INLINE void
+nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv40->nvws->channel;
+
+       while (count) {
+               uint16_t *elts = (uint16_t *)ib + start;
+               unsigned vc, push, restart;
+
+               nv40_state_emit(nv40);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 2,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               if (vc & 1) {
+                       BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
+                       OUT_RING  (elts[0]);
+                       elts++; vc--;
+               }
+
+               while (vc) {
+                       unsigned i;
+
+                       push = MIN2(vc, 2047 * 2);
+
+                       BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push >> 1);
+                       for (i = 0; i < push; i+=2)
+                               OUT_RING((elts[i+1] << 16) | elts[i]);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static INLINE void
+nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nouveau_channel *chan = nv40->nvws->channel;
+
+       while (count) {
+               uint32_t *elts = (uint32_t *)ib + start;
+               unsigned vc, push, restart;
+
+               nv40_state_emit(nv40);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 5, 1,
+                                       mode, start, count, &restart);
+               if (vc == 0) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               count -= vc;
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               while (vc) {
+                       push = MIN2(vc, 2047);
+
+                       BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
+                       OUT_RINGp    (elts, push);
+
+                       vc -= push;
+                       elts += push;
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               start = restart;
+       }
+}
+
+static boolean
+nv40_draw_elements_inline(struct pipe_context *pipe,
+                         struct pipe_buffer *ib, unsigned ib_size,
+                         unsigned mode, unsigned start, unsigned count)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct pipe_winsys *ws = pipe->winsys;
+       void *map;
+
+       map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
+       if (!ib) {
+               NOUVEAU_ERR("failed mapping ib\n");
+               return FALSE;
+       }
+
+       switch (ib_size) {
+       case 1:
+               nv40_draw_elements_u08(nv40, map, mode, start, count);
+               break;
+       case 2:
+               nv40_draw_elements_u16(nv40, map, mode, start, count);
+               break;
+       case 4:
+               nv40_draw_elements_u32(nv40, map, mode, start, count);
+               break;
+       default:
+               NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
+               break;
+       }
+
+       ws->buffer_unmap(ws, ib);
+       return TRUE;
+}
+
+static boolean
+nv40_draw_elements_vbo(struct pipe_context *pipe,
+                      unsigned mode, unsigned start, unsigned count)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       struct nouveau_channel *chan = nv40->nvws->channel;
+       unsigned restart;
+
+       while (count) {
+               unsigned nr, vc;
+
+               nv40_state_emit(nv40);
+
+               vc = nouveau_vbuf_split(chan->pushbuf->remaining, 6, 256,
+                                       mode, start, count, &restart);
+               if (!vc) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+               
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (nvgl_primitive(mode));
+
+               nr = (vc & 0xff);
+               if (nr) {
+                       BEGIN_RING(curie, NV40TCL_VB_INDEX_BATCH, 1);
+                       OUT_RING  (((nr - 1) << 24) | start);
+                       start += nr;
+               }
+
+               nr = vc >> 8;
+               while (nr) {
+                       unsigned push = nr > 2047 ? 2047 : nr;
+
+                       nr -= push;
+
+                       BEGIN_RING_NI(curie, NV40TCL_VB_INDEX_BATCH, push);
+                       while (push--) {
+                               OUT_RING(((0x100 - 1) << 24) | start);
+                               start += 0x100;
+                       }
+               }
+
+               BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
+               OUT_RING  (0);
+
+               count -= vc;
+               start = restart;
+       }
+
+       return TRUE;
+}
+
+boolean
+nv40_draw_elements(struct pipe_context *pipe,
+                  struct pipe_buffer *indexBuffer, unsigned indexSize,
+                  unsigned mode, unsigned start, unsigned count)
+{
+       struct nv40_context *nv40 = nv40_context(pipe);
+       boolean idxbuf;
+
+       idxbuf = nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize);
+       if (FORCE_SWTNL || !nv40_state_validate(nv40)) {
+               return nv40_draw_elements_swtnl(pipe, NULL, 0,
+                                               mode, start, count);
+       }
+
+       if (idxbuf) {
+               nv40_draw_elements_vbo(pipe, mode, start, count);
+       } else {
+               nv40_draw_elements_inline(pipe, indexBuffer, indexSize,
+                                         mode, start, count);
+       }
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+static boolean
+nv40_vbo_validate(struct nv40_context *nv40)
+{
+       struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL;
+       struct nouveau_grobj *curie = nv40->screen->curie;
+       struct pipe_buffer *ib = nv40->idxbuf;
+       unsigned ib_format = nv40->idxbuf_format;
+       unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+       int hw;
+
+       if (nv40->edgeflags) {
+               nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
+               return FALSE;
+       }
+
+       vtxbuf = so_new(20, 18);
+       so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr);
+       vtxfmt = so_new(17, 0);
+       so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt_nr);
+
+       for (hw = 0; hw < nv40->vtxelt_nr; hw++) {
+               struct pipe_vertex_element *ve;
+               struct pipe_vertex_buffer *vb;
+               unsigned type, ncomp;
+
+               ve = &nv40->vtxelt[hw];
+               vb = &nv40->vtxbuf[ve->vertex_buffer_index];
+
+               if (!vb->pitch) {
+                       if (!sattr)
+                               sattr = so_new(16 * 5, 0);
+
+                       if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) {
+                               so_data(vtxbuf, 0);
+                               so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+                               continue;
+                       }
+               }
+
+               if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) {
+                       nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
+                       so_ref(NULL, &vtxbuf);
+                       so_ref(NULL, &vtxfmt);
+                       return FALSE;
+               }
+
+               so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
+                        vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                        0, NV40TCL_VTXBUF_ADDRESS_DMA1);
+               so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
+                                 (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type));
+       }
+
+       if (ib) {
+               so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2);
+               so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+               so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
+                         0, NV40TCL_IDXBUF_FORMAT_DMA1);
+       }
+
+       so_method(vtxbuf, curie, 0x1710, 1);
+       so_data  (vtxbuf, 0);
+
+       so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]);
+       nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF);
+       so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]);
+       nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT);
+       so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]);
+       nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR);
+       return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vbo = {
+       .validate = nv40_vbo_validate,
+       .dirty = {
+               .pipe = NV40_NEW_ARRAYS,
+               .hw = 0,
+       }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c
new file mode 100644 (file)
index 0000000..1e486a6
--- /dev/null
@@ -0,0 +1,1070 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv40_context.h"
+#include "nv40_state.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
+ */
+
+#define SWZ_X 0
+#define SWZ_Y 1
+#define SWZ_Z 2
+#define SWZ_W 3
+#define MASK_X 8
+#define MASK_Y 4
+#define MASK_Z 2
+#define MASK_W 1
+#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
+#define DEF_SCALE 0
+#define DEF_CTEST 0
+#include "nv40_shader.h"
+
+#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv40_sr_neg((s))
+#define abs(s) nv40_sr_abs((s))
+
+#define NV40_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n))
+
+struct nv40_vpc {
+       struct nv40_vertex_program *vp;
+
+       struct nv40_vertex_program_exec *vpi;
+
+       unsigned r_temps;
+       unsigned r_temps_discard;
+       struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
+       struct nv40_sreg *r_address;
+       struct nv40_sreg *r_temp;
+
+       struct nv40_sreg *imm;
+       unsigned nr_imm;
+
+       unsigned hpos_idx;
+};
+
+static struct nv40_sreg
+temp(struct nv40_vpc *vpc)
+{
+       int idx = ffs(~vpc->r_temps) - 1;
+
+       if (idx < 0) {
+               NOUVEAU_ERR("out of temps!!\n");
+               assert(0);
+               return nv40_sr(NV40SR_TEMP, 0);
+       }
+
+       vpc->r_temps |= (1 << idx);
+       vpc->r_temps_discard |= (1 << idx);
+       return nv40_sr(NV40SR_TEMP, idx);
+}
+
+static INLINE void
+release_temps(struct nv40_vpc *vpc)
+{
+       vpc->r_temps &= ~vpc->r_temps_discard;
+       vpc->r_temps_discard = 0;
+}
+
+static struct nv40_sreg
+constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+       struct nv40_vertex_program *vp = vpc->vp;
+       struct nv40_vertex_program_data *vpd;
+       int idx;
+
+       if (pipe >= 0) {
+               for (idx = 0; idx < vp->nr_consts; idx++) {
+                       if (vp->consts[idx].index == pipe)
+                               return nv40_sr(NV40SR_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 nv40_sr(NV40SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+       nv40_vp_arith((cc), (s), NV40_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src)
+{
+       struct nv40_vertex_program *vp = vpc->vp;
+       uint32_t sr = 0;
+
+       switch (src.type) {
+       case NV40SR_TEMP:
+               sr |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT);
+               sr |= (src.index << NV40_VP_SRC_TEMP_SRC_SHIFT);
+               break;
+       case NV40SR_INPUT:
+               sr |= (NV40_VP_SRC_REG_TYPE_INPUT <<
+                      NV40_VP_SRC_REG_TYPE_SHIFT);
+               vp->ir |= (1 << src.index);
+               hw[1] |= (src.index << NV40_VP_INST_INPUT_SRC_SHIFT);
+               break;
+       case NV40SR_CONST:
+               sr |= (NV40_VP_SRC_REG_TYPE_CONST <<
+                      NV40_VP_SRC_REG_TYPE_SHIFT);
+               assert(vpc->vpi->const_index == -1 ||
+                      vpc->vpi->const_index == src.index);
+               vpc->vpi->const_index = src.index;
+               break;
+       case NV40SR_NONE:
+               sr |= (NV40_VP_SRC_REG_TYPE_INPUT <<
+                      NV40_VP_SRC_REG_TYPE_SHIFT);
+               break;
+       default:
+               assert(0);
+       }
+
+       if (src.negate)
+               sr |= NV40_VP_SRC_NEGATE;
+
+       if (src.abs)
+               hw[0] |= (1 << (21 + pos));
+
+       sr |= ((src.swz[0] << NV40_VP_SRC_SWZ_X_SHIFT) |
+              (src.swz[1] << NV40_VP_SRC_SWZ_Y_SHIFT) |
+              (src.swz[2] << NV40_VP_SRC_SWZ_Z_SHIFT) |
+              (src.swz[3] << NV40_VP_SRC_SWZ_W_SHIFT));
+
+       switch (pos) {
+       case 0:
+               hw[1] |= ((sr & NV40_VP_SRC0_HIGH_MASK) >>
+                         NV40_VP_SRC0_HIGH_SHIFT) << NV40_VP_INST_SRC0H_SHIFT;
+               hw[2] |= (sr & NV40_VP_SRC0_LOW_MASK) <<
+                         NV40_VP_INST_SRC0L_SHIFT;
+               break;
+       case 1:
+               hw[2] |= sr << NV40_VP_INST_SRC1_SHIFT;
+               break;
+       case 2:
+               hw[2] |= ((sr & NV40_VP_SRC2_HIGH_MASK) >>
+                         NV40_VP_SRC2_HIGH_SHIFT) << NV40_VP_INST_SRC2H_SHIFT;
+               hw[3] |= (sr & NV40_VP_SRC2_LOW_MASK) <<
+                         NV40_VP_INST_SRC2L_SHIFT;
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst)
+{
+       struct nv40_vertex_program *vp = vpc->vp;
+
+       switch (dst.type) {
+       case NV40SR_TEMP:
+               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 NV40SR_OUTPUT:
+               switch (dst.index) {
+               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;
+               case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break;
+               case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break;
+               case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break;
+               case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break;
+               case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break;
+               case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break;
+               case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break;
+               case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break;
+               case NV40_VP_INST_DEST_CLIP(0):
+                       vp->or |= (1 << 6);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE0;
+                       dst.index = NV40_VP_INST_DEST_FOGC;
+                       break;
+               case NV40_VP_INST_DEST_CLIP(1):
+                       vp->or |= (1 << 7);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE1;
+                       dst.index = NV40_VP_INST_DEST_FOGC;
+                       break;
+               case NV40_VP_INST_DEST_CLIP(2):
+                       vp->or |= (1 << 8);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE2;
+                       dst.index = NV40_VP_INST_DEST_FOGC;
+                       break;
+               case NV40_VP_INST_DEST_CLIP(3):
+                       vp->or |= (1 << 9);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE3;
+                       dst.index = NV40_VP_INST_DEST_PSZ;
+                       break;
+               case NV40_VP_INST_DEST_CLIP(4):
+                       vp->or |= (1 << 10);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE4;
+                       dst.index = NV40_VP_INST_DEST_PSZ;
+                       break;
+               case NV40_VP_INST_DEST_CLIP(5):
+                       vp->or |= (1 << 11);
+                       vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE5;
+                       dst.index = NV40_VP_INST_DEST_PSZ;
+                       break;
+               default:
+                       break;
+               }
+
+               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 | (1<<20);
+               } else {
+                       hw[3] |= NV40_VP_INST_SCA_RESULT;
+                       hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+               }
+               break;
+       default:
+               assert(0);
+       }
+}
+
+static void
+nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op,
+             struct nv40_sreg dst, int mask,
+             struct nv40_sreg s0, struct nv40_sreg s1,
+             struct nv40_sreg s2)
+{
+       struct nv40_vertex_program *vp = vpc->vp;
+       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));
+       vpc->vpi->const_index = -1;
+
+       hw = vpc->vpi->data;
+
+       hw[0] |= (NV40_VP_INST_COND_TR << NV40_VP_INST_COND_SHIFT);
+       hw[0] |= ((0 << NV40_VP_INST_COND_SWZ_X_SHIFT) |
+                 (1 << NV40_VP_INST_COND_SWZ_Y_SHIFT) |
+                 (2 << NV40_VP_INST_COND_SWZ_Z_SHIFT) |
+                 (3 << NV40_VP_INST_COND_SWZ_W_SHIFT));
+
+       if (slot == 0) {
+               hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT);
+               hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK;
+               hw[3] |= (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 | (1 << 20));
+               hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT);
+       }
+
+       emit_dst(vpc, hw, slot, dst);
+       emit_src(vpc, hw, 0, s0);
+       emit_src(vpc, hw, 1, s1);
+       emit_src(vpc, hw, 2, s2);
+}
+
+static INLINE struct nv40_sreg
+tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+       struct nv40_sreg src;
+
+       switch (fsrc->SrcRegister.File) {
+       case TGSI_FILE_INPUT:
+               src = nv40_sr(NV40SR_INPUT, fsrc->SrcRegister.Index);
+               break;
+       case TGSI_FILE_CONSTANT:
+               src = constant(vpc, fsrc->SrcRegister.Index, 0, 0, 0, 0);
+               break;
+       case TGSI_FILE_IMMEDIATE:
+               src = vpc->imm[fsrc->SrcRegister.Index];
+               break;
+       case TGSI_FILE_TEMPORARY:
+               src = vpc->r_temp[fsrc->SrcRegister.Index];
+               break;
+       default:
+               NOUVEAU_ERR("bad src file\n");
+               break;
+       }
+
+       src.abs = fsrc->SrcRegisterExtMod.Absolute;
+       src.negate = fsrc->SrcRegister.Negate;
+       src.swz[0] = fsrc->SrcRegister.SwizzleX;
+       src.swz[1] = fsrc->SrcRegister.SwizzleY;
+       src.swz[2] = fsrc->SrcRegister.SwizzleZ;
+       src.swz[3] = fsrc->SrcRegister.SwizzleW;
+       return src;
+}
+
+static INLINE struct nv40_sreg
+tgsi_dst(struct nv40_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+       struct nv40_sreg dst;
+
+       switch (fdst->DstRegister.File) {
+       case TGSI_FILE_OUTPUT:
+               dst = vpc->r_result[fdst->DstRegister.Index];
+               break;
+       case TGSI_FILE_TEMPORARY:
+               dst = vpc->r_temp[fdst->DstRegister.Index];
+               break;
+       case TGSI_FILE_ADDRESS:
+               dst = vpc->r_address[fdst->DstRegister.Index];
+               break;
+       default:
+               NOUVEAU_ERR("bad dst file\n");
+               break;
+       }
+
+       return dst;
+}
+
+static INLINE int
+tgsi_mask(uint tgsi)
+{
+       int mask = 0;
+
+       if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
+       if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
+       if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
+       if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
+       return mask;
+}
+
+static boolean
+src_native_swz(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc,
+              struct nv40_sreg *src)
+{
+       const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+       struct nv40_sreg tgsi = tgsi_src(vpc, fsrc);
+       uint mask = 0, zero_mask = 0, one_mask = 0, neg_mask = 0;
+       uint neg[4] = { fsrc->SrcRegisterExtSwz.NegateX,
+                       fsrc->SrcRegisterExtSwz.NegateY,
+                       fsrc->SrcRegisterExtSwz.NegateZ,
+                       fsrc->SrcRegisterExtSwz.NegateW };
+       uint c;
+
+       for (c = 0; c < 4; c++) {
+               switch (tgsi_util_get_full_src_register_extswizzle(fsrc, c)) {
+               case TGSI_EXTSWIZZLE_X:
+               case TGSI_EXTSWIZZLE_Y:
+               case TGSI_EXTSWIZZLE_Z:
+               case TGSI_EXTSWIZZLE_W:
+                       mask |= tgsi_mask(1 << c);
+                       break;
+               case TGSI_EXTSWIZZLE_ZERO:
+                       zero_mask |= tgsi_mask(1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               case TGSI_EXTSWIZZLE_ONE:
+                       one_mask |= tgsi_mask(1 << c);
+                       tgsi.swz[c] = SWZ_X;
+                       break;
+               default:
+                       assert(0);
+               }
+
+               if (!tgsi.negate && neg[c])
+                       neg_mask |= tgsi_mask(1 << c);
+       }
+
+       if (mask == MASK_ALL && !neg_mask)
+               return TRUE;
+
+       *src = temp(vpc);
+
+       if (mask)
+               arith(vpc, 0, OP_MOV, *src, mask, tgsi, none, none);
+
+       if (zero_mask)
+               arith(vpc, 0, OP_SFL, *src, zero_mask, *src, none, none);
+
+       if (one_mask)
+               arith(vpc, 0, OP_STR, *src, one_mask, *src, none, none);
+
+       if (neg_mask) {
+               struct nv40_sreg one = temp(vpc);
+               arith(vpc, 0, OP_STR, one, neg_mask, one, none, none);
+               arith(vpc, 0, OP_MUL, *src, neg_mask, *src, neg(one), none);
+       }
+
+       return FALSE;
+}
+
+static boolean
+nv40_vertprog_parse_instruction(struct nv40_vpc *vpc,
+                               const struct tgsi_full_instruction *finst)
+{
+       struct nv40_sreg src[3], dst, tmp;
+       struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+       int mask;
+       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->FullSrcRegisters[i];
+               if (fsrc->SrcRegister.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->FullSrcRegisters[i];
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+               case TGSI_FILE_CONSTANT:
+               case TGSI_FILE_TEMPORARY:
+                       if (!src_native_swz(vpc, fsrc, &src[i]))
+                               continue;
+                       break;
+               default:
+                       break;
+               }
+
+               switch (fsrc->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+                       if (ai == -1 || ai == fsrc->SrcRegister.Index) {
+                               ai = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(vpc, fsrc);
+                       } else {
+                               src[i] = temp(vpc);
+                               arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+                                     tgsi_src(vpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_CONSTANT:
+                       if ((ci == -1 && ii == -1) ||
+                           ci == fsrc->SrcRegister.Index) {
+                               ci = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(vpc, fsrc);
+                       } else {
+                               src[i] = temp(vpc);
+                               arith(vpc, 0, OP_MOV, src[i], MASK_ALL,
+                                     tgsi_src(vpc, fsrc), none, none);
+                       }
+                       break;
+               case TGSI_FILE_IMMEDIATE:
+                       if ((ci == -1 && ii == -1) ||
+                           ii == fsrc->SrcRegister.Index) {
+                               ii = fsrc->SrcRegister.Index;
+                               src[i] = tgsi_src(vpc, fsrc);
+                       } else {
+                               src[i] = temp(vpc);
+                               arith(vpc, 0, OP_MOV, src[i], 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;
+               }
+       }
+
+       dst  = tgsi_dst(vpc, &finst->FullDstRegisters[0]);
+       mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
+
+       switch (finst->Instruction.Opcode) {
+       case TGSI_OPCODE_ABS:
+               arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none);
+               break;
+       case TGSI_OPCODE_ADD:
+               arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]);
+               break;
+       case TGSI_OPCODE_ARL:
+               arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_DP3:
+               arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DP4:
+               arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DPH:
+               arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_DST:
+               arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_EX2:
+               arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_EXP:
+               arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_FLR:
+               arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_FRC:
+               arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_LG2:
+               arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_LIT:
+               arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_LOG:
+               arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_MAD:
+               arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]);
+               break;
+       case TGSI_OPCODE_MAX:
+               arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MIN:
+               arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_MOV:
+               arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none);
+               break;
+       case TGSI_OPCODE_MUL:
+               arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_POW:
+               tmp = temp(vpc);
+               arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none,
+                     swz(src[0], X, X, X, X));
+               arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
+                     swz(src[1], X, X, X, X), none);
+               arith(vpc, 1, OP_EX2, dst, mask, none, none,
+                     swz(tmp, X, X, X, X));
+               break;
+       case TGSI_OPCODE_RCP:
+               arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_RET:
+               break;
+       case TGSI_OPCODE_RSQ:
+               arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]);
+               break;
+       case TGSI_OPCODE_SGE:
+               arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SLT:
+               arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none);
+               break;
+       case TGSI_OPCODE_SUB:
+               arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1]));
+               break;
+       case TGSI_OPCODE_XPD:
+               tmp = temp(vpc);
+               arith(vpc, 0, OP_MUL, tmp, mask,
+                     swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
+               arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W),
+                     swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
+                     neg(tmp));
+               break;
+       default:
+               NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
+               return FALSE;
+       }
+
+       release_temps(vpc);
+       return TRUE;
+}
+
+static boolean
+nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc,
+                               const struct tgsi_full_declaration *fdec)
+{
+       unsigned idx = fdec->DeclarationRange.First;
+       int hw;
+
+       switch (fdec->Semantic.SemanticName) {
+       case TGSI_SEMANTIC_POSITION:
+               hw = NV40_VP_INST_DEST_POS;
+               vpc->hpos_idx = idx;
+               break;
+       case TGSI_SEMANTIC_COLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV40_VP_INST_DEST_COL0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV40_VP_INST_DEST_COL1;
+               } else {
+                       NOUVEAU_ERR("bad colour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_BCOLOR:
+               if (fdec->Semantic.SemanticIndex == 0) {
+                       hw = NV40_VP_INST_DEST_BFC0;
+               } else
+               if (fdec->Semantic.SemanticIndex == 1) {
+                       hw = NV40_VP_INST_DEST_BFC1;
+               } else {
+                       NOUVEAU_ERR("bad bcolour semantic index\n");
+                       return FALSE;
+               }
+               break;
+       case TGSI_SEMANTIC_FOG:
+               hw = NV40_VP_INST_DEST_FOGC;
+               break;
+       case TGSI_SEMANTIC_PSIZE:
+               hw = NV40_VP_INST_DEST_PSZ;
+               break;
+       case TGSI_SEMANTIC_GENERIC:
+               if (fdec->Semantic.SemanticIndex <= 7) {
+                       hw = NV40_VP_INST_DEST_TC(fdec->Semantic.SemanticIndex);
+               } else {
+                       NOUVEAU_ERR("bad generic semantic index\n");
+                       return FALSE;
+               }
+               break;
+       default:
+               NOUVEAU_ERR("bad output semantic\n");
+               return FALSE;
+       }
+
+       vpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw);
+       return TRUE;
+}
+
+static boolean
+nv40_vertprog_prepare(struct nv40_vpc *vpc)
+{
+       struct tgsi_parse_context p;
+       int high_temp = -1, high_addr = -1, nr_imm = 0, i;
+
+       tgsi_parse_init(&p, vpc->vp->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->DeclarationRange.Last > high_temp) {
+                                       high_temp =
+                                               fdec->DeclarationRange.Last;
+                               }
+                               break;
+#if 0 /* this would be nice.. except gallium doesn't track it */
+                       case TGSI_FILE_ADDRESS:
+                               if (fdec->DeclarationRange.Last > high_addr) {
+                                       high_addr =
+                                               fdec->DeclarationRange.Last;
+                               }
+                               break;
+#endif
+                       case TGSI_FILE_OUTPUT:
+                               if (!nv40_vertprog_parse_decl_output(vpc, fdec))
+                                       return FALSE;
+                               break;
+                       default:
+                               break;
+                       }
+               }
+                       break;
+#if 1 /* yay, parse instructions looking for address regs instead */
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
+               {
+                       const struct tgsi_full_instruction *finst;
+                       const struct tgsi_full_dst_register *fdst;
+
+                       finst = &p.FullToken.FullInstruction;
+                       fdst = &finst->FullDstRegisters[0];
+
+                       if (fdst->DstRegister.File == TGSI_FILE_ADDRESS) {
+                               if (fdst->DstRegister.Index > high_addr)
+                                       high_addr = fdst->DstRegister.Index;
+                       }
+               
+               }
+                       break;
+#endif
+               default:
+                       break;
+               }
+       }
+       tgsi_parse_free(&p);
+
+       if (nr_imm) {
+               vpc->imm = CALLOC(nr_imm, sizeof(struct nv40_sreg));
+               assert(vpc->imm);
+       }
+
+       if (++high_temp) {
+               vpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg));
+               for (i = 0; i < high_temp; i++)
+                       vpc->r_temp[i] = temp(vpc);
+       }
+
+       if (++high_addr) {
+               vpc->r_address = CALLOC(high_addr, sizeof(struct nv40_sreg));
+               for (i = 0; i < high_addr; i++)
+                       vpc->r_address[i] = temp(vpc);
+       }
+
+       vpc->r_temps_discard = 0;
+       return TRUE;
+}
+
+static void
+nv40_vertprog_translate(struct nv40_context *nv40,
+                       struct nv40_vertex_program *vp)
+{
+       struct tgsi_parse_context parse;
+       struct nv40_vpc *vpc = NULL;
+       struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
+       int i;
+
+       vpc = CALLOC(1, sizeof(struct nv40_vpc));
+       if (!vpc)
+               return;
+       vpc->vp = vp;
+
+       if (!nv40_vertprog_prepare(vpc)) {
+               FREE(vpc);
+               return;
+       }
+
+       /* Redirect post-transform vertex position to a temp if user clip
+        * planes are enabled.  We need to append code the the vtxprog
+        * to handle clip planes later.
+        */
+       if (vp->ucp.nr)  {
+               vpc->r_result[vpc->hpos_idx] = temp(vpc);
+               vpc->r_temps_discard = 0;
+       }
+
+       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.Size == 4);
+                       vpc->imm[vpc->nr_imm++] =
+                               constant(vpc, -1,
+                                        imm->u.ImmediateFloat32[0].Float,
+                                        imm->u.ImmediateFloat32[1].Float,
+                                        imm->u.ImmediateFloat32[2].Float,
+                                        imm->u.ImmediateFloat32[3].Float);
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
+               {
+                       const struct tgsi_full_instruction *finst;
+                       finst = &parse.FullToken.FullInstruction;
+                       if (!nv40_vertprog_parse_instruction(vpc, finst))
+                               goto out_err;
+               }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Write out HPOS if it was redirected to a temp earlier */
+       if (vpc->r_result[vpc->hpos_idx].type != NV40SR_OUTPUT) {
+               struct nv40_sreg hpos = nv40_sr(NV40SR_OUTPUT,
+                                               NV40_VP_INST_DEST_POS);
+               struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx];
+
+               arith(vpc, 0, OP_MOV, hpos, MASK_ALL, htmp, none, none);
+       }
+
+       /* Insert code to handle user clip planes */
+       for (i = 0; i < vp->ucp.nr; i++) {
+               struct nv40_sreg cdst = nv40_sr(NV40SR_OUTPUT,
+                                               NV40_VP_INST_DEST_CLIP(i));
+               struct nv40_sreg ceqn = constant(vpc, -1,
+                                                nv40->clip.ucp[i][0],
+                                                nv40->clip.ucp[i][1],
+                                                nv40->clip.ucp[i][2],
+                                                nv40->clip.ucp[i][3]);
+               struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx];
+               unsigned mask;
+
+               switch (i) {
+               case 0: case 3: mask = MASK_Y; break;
+               case 1: case 4: mask = MASK_Z; break;
+               case 2: case 5: mask = MASK_W; break;
+               default:
+                       NOUVEAU_ERR("invalid clip dist #%d\n", i);
+                       goto out_err;
+               }
+
+               arith(vpc, 0, OP_DP4, cdst, mask, htmp, ceqn, none);
+       }
+
+       vp->insns[vp->nr_insns - 1].data[3] |= NV40_VP_INST_LAST;
+       vp->translated = TRUE;
+out_err:
+       tgsi_parse_free(&parse);
+       if (vpc->r_temp)
+               FREE(vpc->r_temp); 
+       if (vpc->r_address)
+               FREE(vpc->r_address); 
+       if (vpc->imm)   
+               FREE(vpc->imm); 
+       FREE(vpc);
+}
+
+static boolean
+nv40_vertprog_validate(struct nv40_context *nv40)
+{ 
+       struct nouveau_winsys *nvws = nv40->nvws;
+       struct pipe_winsys *ws = nv40->pipe.winsys;
+       struct nouveau_grobj *curie = nv40->screen->curie;
+       struct nv40_vertex_program *vp;
+       struct pipe_buffer *constbuf;
+       boolean upload_code = FALSE, upload_data = FALSE;
+       int i;
+
+       if (nv40->render_mode == HW) {
+               vp = nv40->vertprog;
+               constbuf = nv40->constbuf[PIPE_SHADER_VERTEX];
+
+               if ((nv40->dirty & NV40_NEW_UCP) ||
+                   memcmp(&nv40->clip, &vp->ucp, sizeof(vp->ucp))) {
+                       nv40_vertprog_destroy(nv40, vp);
+                       memcpy(&vp->ucp, &nv40->clip, sizeof(vp->ucp));
+               }
+       } else {
+               vp = nv40->swtnl.vertprog;
+               constbuf = NULL;
+       }
+
+       /* Translate TGSI shader into hw bytecode */
+       if (vp->translated)
+               goto check_gpu_resources;
+
+       nv40->fallback_swtnl &= ~NV40_NEW_VERTPROG;
+       nv40_vertprog_translate(nv40, vp);
+       if (!vp->translated) {
+               nv40->fallback_swtnl |= NV40_NEW_VERTPROG;
+               return FALSE;
+       }
+
+check_gpu_resources:
+       /* Allocate hw vtxprog exec slots */
+       if (!vp->exec) {
+               struct nouveau_resource *heap = nv40->screen->vp_exec_heap;
+               struct nouveau_stateobj *so;
+               uint vplen = vp->nr_insns;
+
+               if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) {
+                       while (heap->next && heap->size < vplen) {
+                               struct nv40_vertex_program *evict;
+                               
+                               evict = heap->next->priv;
+                               nvws->res_free(&evict->exec);
+                       }
+
+                       if (nvws->res_alloc(heap, vplen, vp, &vp->exec))
+                               assert(0);
+               }
+
+               so = so_new(7, 0);
+               so_method(so, curie, NV40TCL_VP_START_FROM_ID, 1);
+               so_data  (so, vp->exec->start);
+               so_method(so, curie, NV40TCL_VP_ATTRIB_EN, 2);
+               so_data  (so, vp->ir);
+               so_data  (so, vp->or);
+               so_method(so, curie,  NV40TCL_CLIP_PLANE_ENABLE, 1);
+               so_data  (so, vp->clip_ctrl);
+               so_ref(so, &vp->so);
+
+               upload_code = TRUE;
+       }
+
+       /* Allocate hw vtxprog const slots */
+       if (vp->nr_consts && !vp->data) {
+               struct nouveau_resource *heap = nv40->screen->vp_data_heap;
+
+               if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+                       while (heap->next && heap->size < vp->nr_consts) {
+                               struct nv40_vertex_program *evict;
+                               
+                               evict = heap->next->priv;
+                               nvws->res_free(&evict->data);
+                       }
+
+                       if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data))
+                               assert(0);
+               }
+
+               /*XXX: handle this some day */
+               assert(vp->data->start >= vp->data_start_min);
+
+               upload_data = TRUE;
+               if (vp->data_start != vp->data->start)
+                       upload_code = TRUE;
+       }
+
+       /* If exec or data segments moved we need to patch the program to
+        * fixup offsets and register IDs.
+        */
+       if (vp->exec_start != vp->exec->start) {
+               for (i = 0; i < vp->nr_insns; i++) {
+                       struct nv40_vertex_program_exec *vpi = &vp->insns[i];
+
+                       if (vpi->has_branch_offset) {
+                               assert(0);
+                       }
+               }
+
+               vp->exec_start = vp->exec->start;
+       }
+
+       if (vp->nr_consts && vp->data_start != vp->data->start) {
+               for (i = 0; i < vp->nr_insns; i++) {
+                       struct nv40_vertex_program_exec *vpi = &vp->insns[i];
+
+                       if (vpi->const_index >= 0) {
+                               vpi->data[1] &= ~NV40_VP_INST_CONST_SRC_MASK;
+                               vpi->data[1] |=
+                                       (vpi->const_index + vp->data->start) <<
+                                       NV40_VP_INST_CONST_SRC_SHIFT;
+
+                       }
+               }
+
+               vp->data_start = vp->data->start;
+       }
+
+       /* Update + Upload constant values */
+       if (vp->nr_consts) {
+               float *map = NULL;
+
+               if (constbuf) {
+                       map = ws->buffer_map(ws, constbuf,
+                                            PIPE_BUFFER_USAGE_CPU_READ);
+               }
+
+               for (i = 0; i < vp->nr_consts; i++) {
+                       struct nv40_vertex_program_data *vpd = &vp->consts[i];
+
+                       if (vpd->index >= 0) {
+                               if (!upload_data &&
+                                   !memcmp(vpd->value, &map[vpd->index * 4],
+                                           4 * sizeof(float)))
+                                       continue;
+                               memcpy(vpd->value, &map[vpd->index * 4],
+                                      4 * sizeof(float));
+                       }
+
+                       BEGIN_RING(curie, NV40TCL_VP_UPLOAD_CONST_ID, 5);
+                       OUT_RING  (i + vp->data->start);
+                       OUT_RINGp ((uint32_t *)vpd->value, 4);
+               }
+
+               if (constbuf)
+                       ws->buffer_unmap(ws, constbuf);
+       }
+
+       /* Upload vtxprog */
+       if (upload_code) {
+#if 0
+               for (i = 0; i < vp->nr_insns; i++) {
+                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]);
+                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]);
+                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]);
+                       NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]);
+               }
+#endif
+               BEGIN_RING(curie, NV40TCL_VP_UPLOAD_FROM_ID, 1);
+               OUT_RING  (vp->exec->start);
+               for (i = 0; i < vp->nr_insns; i++) {
+                       BEGIN_RING(curie, NV40TCL_VP_UPLOAD_INST(0), 4);
+                       OUT_RINGp (vp->insns[i].data, 4);
+               }
+       }
+
+       if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) {
+               so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void
+nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp)
+{
+       struct nouveau_winsys *nvws = nv40->screen->nvws;
+
+       vp->translated = FALSE;
+
+       if (vp->nr_insns) {
+               FREE(vp->insns);
+               vp->insns = NULL;
+               vp->nr_insns = 0;
+       }
+
+       if (vp->nr_consts) {
+               FREE(vp->consts);
+               vp->consts = NULL;
+               vp->nr_consts = 0;
+       }
+
+       nvws->res_free(&vp->exec);
+       vp->exec_start = 0;
+       nvws->res_free(&vp->data);
+       vp->data_start = 0;
+       vp->data_start_min = 0;
+
+       vp->ir = vp->or = vp->clip_ctrl = 0;
+       so_ref(NULL, &vp->so);
+}
+
+struct nv40_state_entry nv40_state_vertprog = {
+       .validate = nv40_vertprog_validate,
+       .dirty = {
+               .pipe = NV40_NEW_VERTPROG | NV40_NEW_UCP,
+               .hw = NV40_STATE_VERTPROG,
+       }
+};
+
diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile
new file mode 100644 (file)
index 0000000..be30400
--- /dev/null
@@ -0,0 +1,29 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv50
+
+DRIVER_SOURCES = \
+       nv50_clear.c \
+       nv50_context.c \
+       nv50_draw.c \
+       nv50_miptree.c \
+       nv50_query.c \
+       nv50_program.c \
+       nv50_screen.c \
+       nv50_state.c \
+       nv50_state_validate.c \
+       nv50_surface.c \
+       nv50_tex.c \
+       nv50_vbo.c
+
+C_SOURCES = \
+       $(COMMON_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
new file mode 100644 (file)
index 0000000..fbc6cd0
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv50_context.h"
+
+void
+nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+          unsigned clearValue)
+{
+       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+       ps->status = PIPE_SURFACE_STATUS_CLEAR;
+}
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
new file mode 100644 (file)
index 0000000..07987c7
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_util.h"
+
+#include "nv50_context.h"
+#include "nv50_screen.h"
+
+static void
+nv50_flush(struct pipe_context *pipe, unsigned flags,
+          struct pipe_fence_handle **fence)
+{
+       struct nv50_context *nv50 = (struct nv50_context *)pipe;
+       
+       FIRE_RING(fence);
+}
+
+static void
+nv50_destroy(struct pipe_context *pipe)
+{
+       struct nv50_context *nv50 = (struct nv50_context *)pipe;
+
+       draw_destroy(nv50->draw);
+       FREE(nv50);
+}
+
+
+static void
+nv50_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+struct pipe_context *
+nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+       struct pipe_winsys *pipe_winsys = pscreen->winsys;
+       struct nv50_screen *screen = nv50_screen(pscreen);
+       struct nv50_context *nv50;
+
+       nv50 = CALLOC_STRUCT(nv50_context);
+       if (!nv50)
+               return NULL;
+       nv50->screen = screen;
+       nv50->pctx_id = pctx_id;
+
+       nv50->pipe.winsys = pipe_winsys;
+       nv50->pipe.screen = pscreen;
+
+       nv50->pipe.destroy = nv50_destroy;
+
+       nv50->pipe.set_edgeflags = nv50_set_edgeflags;
+       nv50->pipe.draw_arrays = nv50_draw_arrays;
+       nv50->pipe.draw_elements = nv50_draw_elements;
+       nv50->pipe.clear = nv50_clear;
+
+       nv50->pipe.flush = nv50_flush;
+
+       nv50_init_surface_functions(nv50);
+       nv50_init_state_functions(nv50);
+       nv50_init_query_functions(nv50);
+
+       nv50->draw = draw_create();
+       assert(nv50->draw);
+       draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50));
+
+       return &nv50->pipe;
+}
+
+               
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
new file mode 100644 (file)
index 0000000..1c069f1
--- /dev/null
@@ -0,0 +1,181 @@
+#ifndef __NV50_CONTEXT_H__
+#define __NV50_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+#include "nouveau/nouveau_stateobj.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx)                                              \
+       struct nv50_screen *ctx = nv50->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv50_screen.h"
+#include "nv50_program.h"
+
+#define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+#define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+
+/* Constant buffer assignment */
+#define NV50_CB_PMISC          0
+#define NV50_CB_PVP            1
+#define NV50_CB_PFP            2
+#define NV50_CB_PGP            3
+#define NV50_CB_TIC            4
+#define NV50_CB_TSC            5
+#define NV50_CB_PUPLOAD         6
+
+#define NV50_NEW_BLEND         (1 << 0)
+#define NV50_NEW_ZSA           (1 << 1)
+#define NV50_NEW_BLEND_COLOUR  (1 << 2)
+#define NV50_NEW_STIPPLE       (1 << 3)
+#define NV50_NEW_SCISSOR       (1 << 4)
+#define NV50_NEW_VIEWPORT      (1 << 5)
+#define NV50_NEW_RASTERIZER    (1 << 6)
+#define NV50_NEW_FRAMEBUFFER   (1 << 7)
+#define NV50_NEW_VERTPROG      (1 << 8)
+#define NV50_NEW_VERTPROG_CB   (1 << 9)
+#define NV50_NEW_FRAGPROG      (1 << 10)
+#define NV50_NEW_FRAGPROG_CB   (1 << 11)
+#define NV50_NEW_ARRAYS                (1 << 12)
+#define NV50_NEW_SAMPLER       (1 << 13)
+#define NV50_NEW_TEXTURE       (1 << 14)
+
+struct nv50_blend_stateobj {
+       struct pipe_blend_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv50_zsa_stateobj {
+       struct pipe_depth_stencil_alpha_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv50_rasterizer_stateobj {
+       struct pipe_rasterizer_state pipe;
+       struct nouveau_stateobj *so;
+};
+
+struct nv50_miptree {
+       struct pipe_texture base;
+       struct pipe_buffer *buffer;
+};
+
+static INLINE struct nv50_miptree *
+nv50_miptree(struct pipe_texture *pt)
+{
+       return (struct nv50_miptree *)pt;
+}
+
+struct nv50_surface {
+       struct pipe_surface base;
+       struct pipe_buffer *untiled;
+};
+
+static INLINE struct nv50_surface *
+nv50_surface(struct pipe_surface *pt)
+{
+       return (struct nv50_surface *)pt;
+}
+
+struct nv50_state {
+       unsigned dirty;
+
+       struct nouveau_stateobj *fb;
+       struct nouveau_stateobj *blend;
+       struct nouveau_stateobj *blend_colour;
+       struct nouveau_stateobj *zsa;
+       struct nouveau_stateobj *rast;
+       struct nouveau_stateobj *stipple;
+       struct nouveau_stateobj *scissor;
+       unsigned scissor_enabled;
+       struct nouveau_stateobj *viewport;
+       unsigned viewport_bypass;
+       struct nouveau_stateobj *tsc_upload;
+       struct nouveau_stateobj *tic_upload;
+       struct nouveau_stateobj *vertprog;
+       struct nouveau_stateobj *fragprog;
+       struct nouveau_stateobj *vtxfmt;
+       struct nouveau_stateobj *vtxbuf;
+};
+
+struct nv50_context {
+       struct pipe_context pipe;
+
+       struct nv50_screen *screen;
+       unsigned pctx_id;
+
+       struct draw_context *draw;
+
+       struct nv50_state state;
+
+       unsigned dirty;
+       struct nv50_blend_stateobj *blend;
+       struct nv50_zsa_stateobj *zsa;
+       struct nv50_rasterizer_stateobj *rasterizer;
+       struct pipe_blend_color blend_colour;
+       struct pipe_poly_stipple stipple;
+       struct pipe_scissor_state scissor;
+       struct pipe_viewport_state viewport;
+       struct pipe_framebuffer_state framebuffer;
+       struct nv50_program *vertprog;
+       struct nv50_program *fragprog;
+       struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+       struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+       unsigned vtxbuf_nr;
+       struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
+       unsigned vtxelt_nr;
+       unsigned *sampler[PIPE_MAX_SAMPLERS];
+       unsigned sampler_nr;
+       struct nv50_miptree *miptree[PIPE_MAX_SAMPLERS];
+       unsigned miptree_nr;
+};
+
+static INLINE struct nv50_context *
+nv50_context(struct pipe_context *pipe)
+{
+       return (struct nv50_context *)pipe;
+}
+
+extern void nv50_init_surface_functions(struct nv50_context *nv50);
+extern void nv50_init_state_functions(struct nv50_context *nv50);
+extern void nv50_init_query_functions(struct nv50_context *nv50);
+
+extern void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv50_draw.c */
+extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50);
+
+/* nv50_vbo.c */
+extern boolean nv50_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+extern boolean nv50_draw_elements(struct pipe_context *pipe,
+                                 struct pipe_buffer *indexBuffer,
+                                 unsigned indexSize,
+                                 unsigned mode, unsigned start,
+                                 unsigned count);
+extern void nv50_vbo_validate(struct nv50_context *nv50);
+
+/* nv50_clear.c */
+extern void nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+                      unsigned clearValue);
+
+/* nv50_program.c */
+extern void nv50_vertprog_validate(struct nv50_context *nv50);
+extern void nv50_fragprog_validate(struct nv50_context *nv50);
+extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p);
+
+/* nv50_state_validate.c */
+extern boolean nv50_state_validate(struct nv50_context *nv50);
+
+/* nv50_tex.c */
+extern void nv50_tex_validate(struct nv50_context *);
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_draw.c b/src/gallium/drivers/nv50/nv50_draw.c
new file mode 100644 (file)
index 0000000..4fd81bd
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "draw/draw_pipe.h"
+#include "pipe/p_util.h"
+
+#include "nv50_context.h"
+
+struct nv50_render_stage {
+       struct draw_stage stage;
+       struct nv50_context *nv50;
+};
+
+static INLINE struct nv50_render_stage *
+nv50_render_stage(struct draw_stage *stage)
+{
+       return (struct nv50_render_stage *)stage;
+}
+
+static void
+nv50_render_point(struct draw_stage *stage, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_line(struct draw_stage *stage, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_tri(struct draw_stage *stage, struct prim_header *prim)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_flush(struct draw_stage *stage, unsigned flags)
+{
+}
+
+static void
+nv50_render_reset_stipple_counter(struct draw_stage *stage)
+{
+       NOUVEAU_ERR("\n");
+}
+
+static void
+nv50_render_destroy(struct draw_stage *stage)
+{
+       FREE(stage);
+}
+
+struct draw_stage *
+nv50_draw_render_stage(struct nv50_context *nv50)
+{
+       struct nv50_render_stage *rs = CALLOC_STRUCT(nv50_render_stage);
+
+       rs->nv50 = nv50;
+       rs->stage.draw = nv50->draw;
+       rs->stage.destroy = nv50_render_destroy;
+       rs->stage.point = nv50_render_point;
+       rs->stage.line = nv50_render_line;
+       rs->stage.tri = nv50_render_tri;
+       rs->stage.flush = nv50_render_flush;
+       rs->stage.reset_stipple_counter = nv50_render_reset_stipple_counter;
+
+       return &rs->stage;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
new file mode 100644 (file)
index 0000000..a02ad41
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+
+static struct pipe_texture *
+nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
+       unsigned usage, pitch;
+
+       mt->base = *pt;
+       mt->base.refcount = 1;
+       mt->base.screen = pscreen;
+
+       usage = PIPE_BUFFER_USAGE_PIXEL;
+       switch (pt->format) {
+       case PIPE_FORMAT_Z24S8_UNORM:
+       case PIPE_FORMAT_Z16_UNORM:
+               usage |= NOUVEAU_BUFFER_USAGE_ZETA;
+               break;
+       default:
+               break;
+       }
+
+       pitch = ((pt->width[0] + 63) & ~63) * pt->block.size;
+
+       mt->buffer = ws->buffer_create(ws, 256, usage, pitch * pt->height[0]);
+       if (!mt->buffer) {
+               FREE(mt);
+               return NULL;
+       }
+
+       return &mt->base;
+}
+
+static void
+nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct pipe_texture *pt = *ppt;
+
+       *ppt = NULL;
+
+       if (--pt->refcount <= 0) {
+               struct nv50_miptree *mt = nv50_miptree(pt);
+
+               pipe_buffer_reference(ws, &mt->buffer, NULL);
+               FREE(mt);
+       }
+}
+
+static struct pipe_surface *
+nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
+                        unsigned face, unsigned level, unsigned zslice,
+                        unsigned flags)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct nv50_miptree *mt = nv50_miptree(pt);
+       struct nv50_surface *s;
+       struct pipe_surface *ps;
+
+       s = CALLOC_STRUCT(nv50_surface);
+       if (!s)
+               return NULL;
+       ps = &s->base;
+
+       ps->refcount = 1;
+       ps->winsys = ws;
+       ps->format = pt->format;
+       ps->width = pt->width[level];
+       ps->height = pt->height[level];
+       ps->block = pt->block;
+       ps->nblocksx = pt->nblocksx[level];
+       ps->nblocksy = pt->nblocksy[level];
+       ps->stride = ps->width * ps->block.size;
+       ps->offset = 0;
+       ps->usage = flags;
+       ps->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       pipe_texture_reference(&ps->texture, pt);
+       pipe_buffer_reference(ws, &ps->buffer, mt->buffer);
+
+       return ps;
+}
+
+static void
+nv50_miptree_surface_del(struct pipe_screen *pscreen,
+                        struct pipe_surface **psurface)
+{
+       struct pipe_winsys *ws = pscreen->winsys;
+       struct pipe_surface *ps = *psurface;
+       struct nv50_surface *s = nv50_surface(ps);
+
+       *psurface = NULL;
+
+       if (--ps->refcount <= 0) {
+               pipe_texture_reference(&ps->texture, NULL);
+               pipe_buffer_reference(ws, &ps->buffer, NULL);
+               FREE(s);
+       }
+}
+
+void
+nv50_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+       pscreen->texture_create = nv50_miptree_create;
+       pscreen->texture_release = nv50_miptree_release;
+       pscreen->get_tex_surface = nv50_miptree_surface_new;
+       pscreen->tex_surface_release = nv50_miptree_surface_del;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
new file mode 100644 (file)
index 0000000..0d3ddb8
--- /dev/null
@@ -0,0 +1,1708 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_util.h"
+
+#include "nv50_context.h"
+
+#define NV50_SU_MAX_TEMP 64
+#define NV50_PROGRAM_DUMP
+
+/* ARL - gallium craps itself on progs/vp/arl.txt
+ *
+ * MSB - Like MAD, but MUL+SUB
+ *     - Fuck it off, introduce a way to negate args for ops that
+ *       support it.
+ *
+ * Look into inlining IMMD for ops other than MOV (make it general?)
+ *     - Maybe even relax restrictions a bit, can't do P_RESULT + P_IMMD,
+ *       but can emit to P_TEMP first - then MOV later. NVIDIA does this
+ *
+ * In ops such as ADD it's possible to construct a bad opcode in the !is_long()
+ * case, if the emit_src() causes the inst to suddenly become long.
+ *
+ * Verify half-insns work where expected - and force disable them where they
+ * don't work - MUL has it forcibly disabled atm as it fixes POW..
+ *
+ * FUCK! watch dst==src vectors, can overwrite components that are needed.
+ *     ie. SUB R0, R0.yzxw, R0
+ *
+ * Things to check with renouveau:
+ *     FP attr/result assignment - how?
+ *             attrib
+ *                     - 0x16bc maps vp output onto fp hpos
+ *                     - 0x16c0 maps vp output onto fp col0
+ *             result
+ *                     - colr always 0-3
+ *                     - depr always 4
+ * 0x16bc->0x16e8 --> some binding between vp/fp regs
+ * 0x16b8 --> VP output count
+ *
+ * 0x1298 --> "MOV rcol.x, fcol.y" "MOV depr, fcol.y" = 0x00000005
+ *           "MOV rcol.x, fcol.y" = 0x00000004
+ * 0x19a8 --> as above but 0x00000100 and 0x00000000
+ *     - 0x00100000 used when KIL used
+ * 0x196c --> as above but 0x00000011 and 0x00000000
+ *
+ * 0x1988 --> 0xXXNNNNNN
+ *     - XX == FP high something
+ */
+struct nv50_reg {
+       enum {
+               P_TEMP,
+               P_ATTR,
+               P_RESULT,
+               P_CONST,
+               P_IMMD
+       } type;
+       int index;
+
+       int hw;
+       int neg;
+};
+
+struct nv50_pc {
+       struct nv50_program *p;
+
+       /* hw resources */
+       struct nv50_reg *r_temp[NV50_SU_MAX_TEMP];
+
+       /* tgsi resources */
+       struct nv50_reg *temp;
+       int temp_nr;
+       struct nv50_reg *attr;
+       int attr_nr;
+       struct nv50_reg *result;
+       int result_nr;
+       struct nv50_reg *param;
+       int param_nr;
+       struct nv50_reg *immd;
+       float *immd_buf;
+       int immd_nr;
+
+       struct nv50_reg *temp_temp[16];
+       unsigned temp_temp_nr;
+};
+
+static void
+alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg)
+{
+       int i;
+
+       if (reg->type == P_RESULT) {
+               if (pc->p->cfg.high_result < (reg->hw + 1))
+                       pc->p->cfg.high_result = reg->hw + 1;
+       }
+
+       if (reg->type != P_TEMP)
+               return;
+
+       if (reg->hw >= 0) {
+               /*XXX: do this here too to catch FP temp-as-attr usage..
+                *     not clean, but works */
+               if (pc->p->cfg.high_temp < (reg->hw + 1))
+                       pc->p->cfg.high_temp = reg->hw + 1;
+               return;
+       }
+
+       for (i = 0; i < NV50_SU_MAX_TEMP; i++) {
+               if (!(pc->r_temp[i])) {
+                       pc->r_temp[i] = reg;
+                       reg->hw = i;
+                       if (pc->p->cfg.high_temp < (i + 1))
+                               pc->p->cfg.high_temp = i + 1;
+                       return;
+               }
+       }
+
+       assert(0);
+}
+
+static struct nv50_reg *
+alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst)
+{
+       struct nv50_reg *r;
+       int i;
+
+       if (dst && dst->type == P_TEMP && dst->hw == -1)
+               return dst;
+
+       for (i = 0; i < NV50_SU_MAX_TEMP; i++) {
+               if (!pc->r_temp[i]) {
+                       r = CALLOC_STRUCT(nv50_reg);
+                       r->type = P_TEMP;
+                       r->index = -1;
+                       r->hw = i;
+                       pc->r_temp[i] = r;
+                       return r;
+               }
+       }
+
+       assert(0);
+       return NULL;
+}
+
+static void
+free_temp(struct nv50_pc *pc, struct nv50_reg *r)
+{
+       if (r->index == -1) {
+               unsigned hw = r->hw;
+
+               FREE(pc->r_temp[hw]);
+               pc->r_temp[hw] = NULL;
+       }
+}
+
+static struct nv50_reg *
+temp_temp(struct nv50_pc *pc)
+{
+       if (pc->temp_temp_nr >= 16)
+               assert(0);
+
+       pc->temp_temp[pc->temp_temp_nr] = alloc_temp(pc, NULL);
+       return pc->temp_temp[pc->temp_temp_nr++];
+}
+
+static void
+kill_temp_temp(struct nv50_pc *pc)
+{
+       int i;
+       
+       for (i = 0; i < pc->temp_temp_nr; i++)
+               free_temp(pc, pc->temp_temp[i]);
+       pc->temp_temp_nr = 0;
+}
+
+static int
+ctor_immd(struct nv50_pc *pc, float x, float y, float z, float w)
+{
+       pc->immd_buf = REALLOC(pc->immd_buf, (pc->immd_nr * r * sizeof(float)),
+                              (pc->immd_nr + 1) * 4 * sizeof(float));
+       pc->immd_buf[(pc->immd_nr * 4) + 0] = x;
+       pc->immd_buf[(pc->immd_nr * 4) + 1] = y;
+       pc->immd_buf[(pc->immd_nr * 4) + 2] = z;
+       pc->immd_buf[(pc->immd_nr * 4) + 3] = w;
+       
+       return pc->immd_nr++;
+}
+
+static struct nv50_reg *
+alloc_immd(struct nv50_pc *pc, float f)
+{
+       struct nv50_reg *r = CALLOC_STRUCT(nv50_reg);
+       unsigned hw;
+
+       hw = ctor_immd(pc, f, 0, 0, 0) * 4;
+       r->type = P_IMMD;
+       r->hw = hw;
+       r->index = -1;
+       return r;
+}
+
+static struct nv50_program_exec *
+exec(struct nv50_pc *pc)
+{
+       struct nv50_program_exec *e = CALLOC_STRUCT(nv50_program_exec);
+
+       e->param.index = -1;
+       return e;
+}
+
+static void
+emit(struct nv50_pc *pc, struct nv50_program_exec *e)
+{
+       struct nv50_program *p = pc->p;
+
+       if (p->exec_tail)
+               p->exec_tail->next = e;
+       if (!p->exec_head)
+               p->exec_head = e;
+       p->exec_tail = e;
+       p->exec_size += (e->inst[0] & 1) ? 2 : 1;
+}
+
+static INLINE void set_long(struct nv50_pc *, struct nv50_program_exec *);
+
+static boolean
+is_long(struct nv50_program_exec *e)
+{
+       if (e->inst[0] & 1)
+               return TRUE;
+       return FALSE;
+}
+
+static boolean
+is_immd(struct nv50_program_exec *e)
+{
+       if (is_long(e) && (e->inst[1] & 3) == 3)
+               return TRUE;
+       return FALSE;
+}
+
+static INLINE void
+set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx,
+        struct nv50_program_exec *e)
+{
+       set_long(pc, e);
+       e->inst[1] &= ~((0x1f << 7) | (0x3 << 12));
+       e->inst[1] |= (pred << 7) | (idx << 12);
+}
+
+static INLINE void
+set_pred_wr(struct nv50_pc *pc, unsigned on, unsigned idx,
+           struct nv50_program_exec *e)
+{
+       set_long(pc, e);
+       e->inst[1] &= ~((0x3 << 4) | (1 << 6));
+       e->inst[1] |= (idx << 4) | (on << 6);
+}
+
+static INLINE void
+set_long(struct nv50_pc *pc, struct nv50_program_exec *e)
+{
+       if (is_long(e))
+               return;
+
+       e->inst[0] |= 1;
+       set_pred(pc, 0xf, 0, e);
+       set_pred_wr(pc, 0, 0, e);
+}
+
+static INLINE void
+set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e)
+{
+       if (dst->type == P_RESULT) {
+               set_long(pc, e);
+               e->inst[1] |= 0x00000008;
+       }
+
+       alloc_reg(pc, dst);
+       e->inst[0] |= (dst->hw << 2);
+}
+
+static INLINE void
+set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e)
+{
+       unsigned val = fui(pc->immd_buf[imm->hw]); /* XXX */
+
+       set_long(pc, e);
+       /*XXX: can't be predicated - bits overlap.. catch cases where both
+        *     are required and avoid them. */
+       set_pred(pc, 0, 0, e);
+       set_pred_wr(pc, 0, 0, e);
+
+       e->inst[1] |= 0x00000002 | 0x00000001;
+       e->inst[0] |= (val & 0x3f) << 16;
+       e->inst[1] |= (val >> 6) << 2;
+}
+
+static void
+emit_interp(struct nv50_pc *pc, struct nv50_reg *dst,
+           struct nv50_reg *src, struct nv50_reg *iv)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0x80000000;
+       set_dst(pc, dst, e);
+       alloc_reg(pc, src);
+       e->inst[0] |= (src->hw << 16);
+       if (iv) {
+               e->inst[0] |= (1 << 25);
+               alloc_reg(pc, iv);
+               e->inst[0] |= (iv->hw << 9);
+       }
+
+       emit(pc, e);
+}
+
+static void
+set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s,
+        struct nv50_program_exec *e)
+{
+       set_long(pc, e);
+#if 1
+       e->inst[1] |= (1 << 22);
+#else
+       if (src->type == P_IMMD) {
+               e->inst[1] |= (NV50_CB_PMISC << 22);
+       } else {
+               if (pc->p->type == PIPE_SHADER_VERTEX)
+                       e->inst[1] |= (NV50_CB_PVP << 22);
+               else
+                       e->inst[1] |= (NV50_CB_PFP << 22);
+       }
+#endif
+
+       e->param.index = src->hw;
+       e->param.shift = s;
+       e->param.mask = m << (s % 32);
+}
+
+static void
+emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0x10000000;
+
+       set_dst(pc, dst, e);
+
+       if (0 && dst->type != P_RESULT && src->type == P_IMMD) {
+               set_immd(pc, src, e);
+               /*XXX: 32-bit, but steals part of "half" reg space - need to
+                *     catch and handle this case if/when we do half-regs
+                */
+               e->inst[0] |= 0x00008000;
+       } else
+       if (src->type == P_IMMD || src->type == P_CONST) {
+               set_long(pc, e);
+               set_data(pc, src, 0x7f, 9, e);
+               e->inst[1] |= 0x20000000; /* src0 const? */
+       } else {
+               if (src->type == P_ATTR) {
+                       set_long(pc, e);
+                       e->inst[1] |= 0x00200000;
+               }
+
+               alloc_reg(pc, src);
+               e->inst[0] |= (src->hw << 9);
+       }
+
+       /* We really should support "half" instructions here at some point,
+        * but I don't feel confident enough about them yet.
+        */
+       set_long(pc, e);
+       if (is_long(e) && !is_immd(e)) {
+               e->inst[1] |= 0x04000000; /* 32-bit */
+               e->inst[1] |= 0x0003c000; /* "subsubop" 0xf == mov */
+       }
+
+       emit(pc, e);
+}
+
+static boolean
+check_swap_src_0_1(struct nv50_pc *pc,
+                  struct nv50_reg **s0, struct nv50_reg **s1)
+{
+       struct nv50_reg *src0 = *s0, *src1 = *s1;
+
+       if (src0->type == P_CONST) {
+               if (src1->type != P_CONST) {
+                       *s0 = src1;
+                       *s1 = src0;
+                       return TRUE;
+               }
+       } else
+       if (src1->type == P_ATTR) {
+               if (src0->type != P_ATTR) {
+                       *s0 = src1;
+                       *s1 = src0;
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+static void
+set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+       if (src->type == P_ATTR) {
+               set_long(pc, e);
+               e->inst[1] |= 0x00200000;
+       } else
+       if (src->type == P_CONST || src->type == P_IMMD) {
+               struct nv50_reg *temp = temp_temp(pc);
+
+               emit_mov(pc, temp, src);
+               src = temp;
+       }
+
+       alloc_reg(pc, src);
+       e->inst[0] |= (src->hw << 9);
+}
+
+static void
+set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+       if (src->type == P_ATTR) {
+               struct nv50_reg *temp = temp_temp(pc);
+
+               emit_mov(pc, temp, src);
+               src = temp;
+       } else
+       if (src->type == P_CONST || src->type == P_IMMD) {
+               assert(!(e->inst[0] & 0x00800000));
+               if (e->inst[0] & 0x01000000) {
+                       struct nv50_reg *temp = temp_temp(pc);
+
+                       emit_mov(pc, temp, src);
+                       src = temp;
+               } else {
+                       set_data(pc, src, 0x7f, 16, e);
+                       e->inst[0] |= 0x00800000;
+               }
+       }
+
+       alloc_reg(pc, src);
+       e->inst[0] |= (src->hw << 16);
+}
+
+static void
+set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
+{
+       set_long(pc, e);
+
+       if (src->type == P_ATTR) {
+               struct nv50_reg *temp = temp_temp(pc);
+
+               emit_mov(pc, temp, src);
+               src = temp;
+       } else
+       if (src->type == P_CONST || src->type == P_IMMD) {
+               assert(!(e->inst[0] & 0x01000000));
+               if (e->inst[0] & 0x00800000) {
+                       struct nv50_reg *temp = temp_temp(pc);
+
+                       emit_mov(pc, temp, src);
+                       src = temp;
+               } else {
+                       set_data(pc, src, 0x7f, 32+14, e);
+                       e->inst[0] |= 0x01000000;
+               }
+       }
+
+       alloc_reg(pc, src);
+       e->inst[1] |= (src->hw << 14);
+}
+
+static void
+emit_mul(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+        struct nv50_reg *src1)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xc0000000;
+       set_long(pc, e);
+
+       check_swap_src_0_1(pc, &src0, &src1);
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_1(pc, src1, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_add(struct nv50_pc *pc, struct nv50_reg *dst,
+        struct nv50_reg *src0, struct nv50_reg *src1)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xb0000000;
+
+       check_swap_src_0_1(pc, &src0, &src1);
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       if (is_long(e))
+               set_src_2(pc, src1, e);
+       else
+               set_src_1(pc, src1, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst,
+           struct nv50_reg *src0, struct nv50_reg *src1)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       set_long(pc, e);
+       e->inst[0] |= 0xb0000000;
+       e->inst[1] |= (sub << 29);
+
+       check_swap_src_0_1(pc, &src0, &src1);
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_1(pc, src1, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+        struct nv50_reg *src1)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xb0000000;
+
+       set_long(pc, e);
+       if (check_swap_src_0_1(pc, &src0, &src1))
+               e->inst[1] |= 0x04000000;
+       else
+               e->inst[1] |= 0x08000000;
+
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_2(pc, src1, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+        struct nv50_reg *src1, struct nv50_reg *src2)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xe0000000;
+
+       check_swap_src_0_1(pc, &src0, &src1);
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_1(pc, src1, e);
+       set_src_2(pc, src2, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+        struct nv50_reg *src1, struct nv50_reg *src2)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xe0000000;
+       set_long(pc, e);
+       e->inst[1] |= 0x08000000; /* src0 * src1 - src2 */
+
+       check_swap_src_0_1(pc, &src0, &src1);
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_1(pc, src1, e);
+       set_src_2(pc, src2, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_flop(struct nv50_pc *pc, unsigned sub,
+         struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0x90000000;
+       if (sub) {
+               set_long(pc, e);
+               e->inst[1] |= (sub << 29);
+       }
+
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_preex2(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xb0000000;
+
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+       set_long(pc, e);
+       e->inst[1] |= (6 << 29) | 0x00004000;
+
+       emit(pc, e);
+}
+
+static void
+emit_precossin(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] |= 0xb0000000;
+
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+       set_long(pc, e);
+       e->inst[1] |= (6 << 29);
+
+       emit(pc, e);
+}
+
+static void
+emit_set(struct nv50_pc *pc, unsigned c_op, struct nv50_reg *dst,
+        struct nv50_reg *src0, struct nv50_reg *src1)
+{
+       struct nv50_program_exec *e = exec(pc);
+       unsigned inv_cop[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+       struct nv50_reg *rdst;
+
+       assert(c_op <= 7);
+       if (check_swap_src_0_1(pc, &src0, &src1))
+               c_op = inv_cop[c_op];
+
+       rdst = dst;
+       if (dst->type != P_TEMP)
+               dst = alloc_temp(pc, NULL);
+
+       /* set.u32 */
+       set_long(pc, e);
+       e->inst[0] |= 0xb0000000;
+       e->inst[1] |= (3 << 29);
+       e->inst[1] |= (c_op << 14);
+       /*XXX: breaks things, .u32 by default?
+        *     decuda will disasm as .u16 and use .lo/.hi regs, but this
+        *     doesn't seem to match what the hw actually does.
+       inst[1] |= 0x04000000; << breaks things.. .u32 by default?
+        */
+       set_dst(pc, dst, e);
+       set_src_0(pc, src0, e);
+       set_src_1(pc, src1, e);
+       emit(pc, e);
+
+       /* cvt.f32.u32 */
+       e = exec(pc);
+       e->inst[0] = 0xa0000001;
+       e->inst[1] = 0x64014780;
+       set_dst(pc, rdst, e);
+       set_src_0(pc, dst, e);
+       emit(pc, e);
+
+       if (dst != rdst)
+               free_temp(pc, dst);
+}
+
+static void
+emit_flr(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] = 0xa0000000; /* cvt */
+       set_long(pc, e);
+       e->inst[1] |= (6 << 29); /* cvt */
+       e->inst[1] |= 0x08000000; /* integer mode */
+       e->inst[1] |= 0x04000000; /* 32 bit */
+       e->inst[1] |= ((0x1 << 3)) << 14; /* .rn */
+       e->inst[1] |= (1 << 14); /* src .f32 */
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_pow(struct nv50_pc *pc, struct nv50_reg *dst,
+        struct nv50_reg *v, struct nv50_reg *e)
+{
+       struct nv50_reg *temp = alloc_temp(pc, NULL);
+
+       emit_flop(pc, 3, temp, v);
+       emit_mul(pc, temp, temp, e);
+       emit_preex2(pc, temp, temp);
+       emit_flop(pc, 6, dst, temp);
+
+       free_temp(pc, temp);
+}
+
+static void
+emit_abs(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       e->inst[0] = 0xa0000000; /* cvt */
+       set_long(pc, e);
+       e->inst[1] |= (6 << 29); /* cvt */
+       e->inst[1] |= 0x04000000; /* 32 bit */
+       e->inst[1] |= (1 << 14); /* src .f32 */
+       e->inst[1] |= ((1 << 6) << 14); /* .abs */
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+
+       emit(pc, e);
+}
+
+static void
+emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
+        struct nv50_reg **src)
+{
+       struct nv50_reg *one = alloc_immd(pc, 1.0);
+       struct nv50_reg *zero = alloc_immd(pc, 0.0);
+       struct nv50_reg *neg128 = alloc_immd(pc, -127.999999);
+       struct nv50_reg *pos128 = alloc_immd(pc,  127.999999);
+       struct nv50_reg *tmp[4];
+
+       if (mask & (1 << 0))
+               emit_mov(pc, dst[0], one);
+
+       if (mask & (1 << 3))
+               emit_mov(pc, dst[3], one);
+
+       if (mask & (3 << 1)) {
+               if (mask & (1 << 1))
+                       tmp[0] = dst[1];
+               else
+                       tmp[0] = temp_temp(pc);
+               emit_minmax(pc, 4, tmp[0], src[0], zero);
+       }
+
+       if (mask & (1 << 2)) {
+               set_pred_wr(pc, 1, 0, pc->p->exec_tail);
+
+               tmp[1] = temp_temp(pc);
+               emit_minmax(pc, 4, tmp[1], src[1], zero);
+
+               tmp[3] = temp_temp(pc);
+               emit_minmax(pc, 4, tmp[3], src[3], neg128);
+               emit_minmax(pc, 5, tmp[3], tmp[3], pos128);
+
+               emit_pow(pc, dst[2], tmp[1], tmp[3]);
+               emit_mov(pc, dst[2], zero);
+               set_pred(pc, 3, 0, pc->p->exec_tail);
+       }
+}
+
+static void
+emit_neg(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+       struct nv50_program_exec *e = exec(pc);
+
+       set_long(pc, e);
+       e->inst[0] |= 0xa0000000; /* delta */
+       e->inst[1] |= (7 << 29); /* delta */
+       e->inst[1] |= 0x04000000; /* negate arg0? probably not */
+       e->inst[1] |= (1 << 14); /* src .f32 */
+       set_dst(pc, dst, e);
+       set_src_0(pc, src, e);
+
+       emit(pc, e);
+}
+
+static struct nv50_reg *
+tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst)
+{
+       switch (dst->DstRegister.File) {
+       case TGSI_FILE_TEMPORARY:
+               return &pc->temp[dst->DstRegister.Index * 4 + c];
+       case TGSI_FILE_OUTPUT:
+               return &pc->result[dst->DstRegister.Index * 4 + c];
+       case TGSI_FILE_NULL:
+               return NULL;
+       default:
+               break;
+       }
+
+       return NULL;
+}
+
+static struct nv50_reg *
+tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src)
+{
+       struct nv50_reg *r = NULL;
+       struct nv50_reg *temp;
+       unsigned c;
+
+       c = tgsi_util_get_full_src_register_extswizzle(src, chan);
+       switch (c) {
+       case TGSI_EXTSWIZZLE_X:
+       case TGSI_EXTSWIZZLE_Y:
+       case TGSI_EXTSWIZZLE_Z:
+       case TGSI_EXTSWIZZLE_W:
+               switch (src->SrcRegister.File) {
+               case TGSI_FILE_INPUT:
+                       r = &pc->attr[src->SrcRegister.Index * 4 + c];
+                       break;
+               case TGSI_FILE_TEMPORARY:
+                       r = &pc->temp[src->SrcRegister.Index * 4 + c];
+                       break;
+               case TGSI_FILE_CONSTANT:
+                       r = &pc->param[src->SrcRegister.Index * 4 + c];
+                       break;
+               case TGSI_FILE_IMMEDIATE:
+                       r = &pc->immd[src->SrcRegister.Index * 4 + c];
+                       break;
+               case TGSI_FILE_SAMPLER:
+                       break;
+               default:
+                       assert(0);
+                       break;
+               }
+               break;
+       case TGSI_EXTSWIZZLE_ZERO:
+               r = alloc_immd(pc, 0.0);
+               break;
+       case TGSI_EXTSWIZZLE_ONE:
+               r = alloc_immd(pc, 1.0);
+               break;
+       default:
+               assert(0);
+               break;
+       }
+
+       switch (tgsi_util_get_full_src_register_sign_mode(src, chan)) {
+       case TGSI_UTIL_SIGN_KEEP:
+               break;
+       case TGSI_UTIL_SIGN_CLEAR:
+               temp = temp_temp(pc);
+               emit_abs(pc, temp, r);
+               r = temp;
+               break;
+       case TGSI_UTIL_SIGN_TOGGLE:
+               temp = temp_temp(pc);
+               emit_neg(pc, temp, r);
+               r = temp;
+               break;
+       case TGSI_UTIL_SIGN_SET:
+               temp = temp_temp(pc);
+               emit_abs(pc, temp, r);
+               emit_neg(pc, temp, r);
+               r = temp;
+               break;
+       default:
+               assert(0);
+               break;
+       }
+
+       return r;
+}
+
+static boolean
+nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
+{
+       const struct tgsi_full_instruction *inst = &tok->FullInstruction;
+       struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp;
+       unsigned mask, sat;
+       int i, c;
+
+       mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+       sat = inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE;
+
+       for (c = 0; c < 4; c++) {
+               if (mask & (1 << c))
+                       dst[c] = tgsi_dst(pc, c, &inst->FullDstRegisters[0]);
+               else
+                       dst[c] = NULL;
+       }
+
+       for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
+               for (c = 0; c < 4; c++)
+                       src[i][c] = tgsi_src(pc, c, &inst->FullSrcRegisters[i]);
+       }
+
+       if (sat) {
+               for (c = 0; c < 4; c++) {
+                       rdst[c] = dst[c];
+                       dst[c] = temp_temp(pc);
+               }
+       }
+
+       switch (inst->Instruction.Opcode) {
+       case TGSI_OPCODE_ABS:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_abs(pc, dst[c], src[0][c]);
+               }
+               break;
+       case TGSI_OPCODE_ADD:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_add(pc, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_COS:
+               temp = alloc_temp(pc, NULL);
+               emit_precossin(pc, temp, src[0][0]);
+               emit_flop(pc, 5, temp, temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               break;
+       case TGSI_OPCODE_DP3:
+               temp = alloc_temp(pc, NULL);
+               emit_mul(pc, temp, src[0][0], src[1][0]);
+               emit_mad(pc, temp, src[0][1], src[1][1], temp);
+               emit_mad(pc, temp, src[0][2], src[1][2], temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_DP4:
+               temp = alloc_temp(pc, NULL);
+               emit_mul(pc, temp, src[0][0], src[1][0]);
+               emit_mad(pc, temp, src[0][1], src[1][1], temp);
+               emit_mad(pc, temp, src[0][2], src[1][2], temp);
+               emit_mad(pc, temp, src[0][3], src[1][3], temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_DPH:
+               temp = alloc_temp(pc, NULL);
+               emit_mul(pc, temp, src[0][0], src[1][0]);
+               emit_mad(pc, temp, src[0][1], src[1][1], temp);
+               emit_mad(pc, temp, src[0][2], src[1][2], temp);
+               emit_add(pc, temp, src[1][3], temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_DST:
+       {
+               struct nv50_reg *one = alloc_immd(pc, 1.0);
+               if (mask & (1 << 0))
+                       emit_mov(pc, dst[0], one);
+               if (mask & (1 << 1))
+                       emit_mul(pc, dst[1], src[0][1], src[1][1]);
+               if (mask & (1 << 2))
+                       emit_mov(pc, dst[2], src[0][2]);
+               if (mask & (1 << 3))
+                       emit_mov(pc, dst[3], src[1][3]);
+               FREE(one);
+       }
+               break;
+       case TGSI_OPCODE_EX2:
+               temp = alloc_temp(pc, NULL);
+               emit_preex2(pc, temp, src[0][0]);
+               emit_flop(pc, 6, temp, temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_FLR:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_flr(pc, dst[c], src[0][c]);
+               }
+               break;
+       case TGSI_OPCODE_FRC:
+               temp = alloc_temp(pc, NULL);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_flr(pc, temp, src[0][c]);
+                       emit_sub(pc, dst[c], src[0][c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_LIT:
+               emit_lit(pc, &dst[0], mask, &src[0][0]);
+               break;
+       case TGSI_OPCODE_LG2:
+               temp = alloc_temp(pc, NULL);
+               emit_flop(pc, 3, temp, src[0][0]);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               break;
+       case TGSI_OPCODE_LRP:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       /*XXX: we can do better than this */
+                       temp = alloc_temp(pc, NULL);
+                       emit_neg(pc, temp, src[0][c]);
+                       emit_mad(pc, temp, temp, src[2][c], src[2][c]);
+                       emit_mad(pc, dst[c], src[0][c], src[1][c], temp);
+                       free_temp(pc, temp);
+               }
+               break;
+       case TGSI_OPCODE_MAD:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mad(pc, dst[c], src[0][c], src[1][c], src[2][c]);
+               }
+               break;
+       case TGSI_OPCODE_MAX:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_minmax(pc, 4, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_MIN:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_minmax(pc, 5, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_MOV:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], src[0][c]);
+               }
+               break;
+       case TGSI_OPCODE_MUL:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mul(pc, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_POW:
+               temp = alloc_temp(pc, NULL);
+               emit_pow(pc, temp, src[0][0], src[1][0]);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_RCP:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_flop(pc, 0, dst[c], src[0][0]);
+               }
+               break;
+       case TGSI_OPCODE_RSQ:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_flop(pc, 2, dst[c], src[0][0]);
+               }
+               break;
+       case TGSI_OPCODE_SCS:
+               temp = alloc_temp(pc, NULL);
+               emit_precossin(pc, temp, src[0][0]);
+               if (mask & (1 << 0))
+                       emit_flop(pc, 5, dst[0], temp);
+               if (mask & (1 << 1))
+                       emit_flop(pc, 4, dst[1], temp);
+               break;
+       case TGSI_OPCODE_SGE:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_set(pc, 6, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_SIN:
+               temp = alloc_temp(pc, NULL);
+               emit_precossin(pc, temp, src[0][0]);
+               emit_flop(pc, 4, temp, temp);
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_mov(pc, dst[c], temp);
+               }
+               break;
+       case TGSI_OPCODE_SLT:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_set(pc, 1, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_SUB:
+               for (c = 0; c < 4; c++) {
+                       if (!(mask & (1 << c)))
+                               continue;
+                       emit_sub(pc, dst[c], src[0][c], src[1][c]);
+               }
+               break;
+       case TGSI_OPCODE_TEX:
+               {
+                       struct nv50_reg *t0, *t1, *t2, *t3;
+                       struct nv50_program_exec *e;
+
+                       t0 = alloc_temp(pc, NULL);
+                       t0 = alloc_temp(pc, NULL);
+                       t1 = alloc_temp(pc, NULL);
+                       t2 = alloc_temp(pc, NULL);
+                       t3 = alloc_temp(pc, NULL);
+                       emit_mov(pc, t0, src[0][0]);
+                       emit_mov(pc, t1, src[0][1]);
+
+                       e = exec(pc);
+                       e->inst[0] = 0xf6400000;
+                       set_long(pc, e);
+                       e->inst[1] |= 0x0000c004;
+                       set_dst(pc, t0, e);
+                       emit(pc, e);
+
+                       if (mask & (1 << 0)) emit_mov(pc, dst[0], t0);
+                       if (mask & (1 << 1)) emit_mov(pc, dst[1], t1);
+                       if (mask & (1 << 2)) emit_mov(pc, dst[2], t2);
+                       if (mask & (1 << 3)) emit_mov(pc, dst[3], t3);
+
+                       free_temp(pc, t0);
+                       free_temp(pc, t1);
+                       free_temp(pc, t2);
+                       free_temp(pc, t3);
+               }
+               break;
+       case TGSI_OPCODE_XPD:
+               temp = alloc_temp(pc, NULL);
+               if (mask & (1 << 0)) {
+                       emit_mul(pc, temp, src[0][2], src[1][1]);
+                       emit_msb(pc, dst[0], src[0][1], src[1][2], temp);
+               }
+               if (mask & (1 << 1)) {
+                       emit_mul(pc, temp, src[0][0], src[1][2]);
+                       emit_msb(pc, dst[1], src[0][2], src[1][0], temp);
+               }
+               if (mask & (1 << 2)) {
+                       emit_mul(pc, temp, src[0][1], src[1][0]);
+                       emit_msb(pc, dst[2], src[0][0], src[1][1], temp);
+               }
+               free_temp(pc, temp);
+               break;
+       case TGSI_OPCODE_END:
+               break;
+       default:
+               NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode);
+               return FALSE;
+       }
+
+       if (sat) {
+               for (c = 0; c < 4; c++) {
+                       struct nv50_program_exec *e;
+
+                       if (!(mask & (1 << c)))
+                               continue;
+                       e = exec(pc);
+
+                       e->inst[0] = 0xa0000000; /* cvt */
+                       set_long(pc, e);
+                       e->inst[1] |= (6 << 29); /* cvt */
+                       e->inst[1] |= 0x04000000; /* 32 bit */
+                       e->inst[1] |= (1 << 14); /* src .f32 */
+                       e->inst[1] |= ((1 << 5) << 14); /* .sat */
+                       set_dst(pc, rdst[c], e);
+                       set_src_0(pc, dst[c], e);
+                       emit(pc, e);
+               }
+       }
+
+       kill_temp_temp(pc);
+       return TRUE;
+}
+
+static boolean
+nv50_program_tx_prep(struct nv50_pc *pc)
+{
+       struct tgsi_parse_context p;
+       boolean ret = FALSE;
+       unsigned i, c;
+
+       tgsi_parse_init(&p, pc->p->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:
+               {
+                       const struct tgsi_full_immediate *imm =
+                               &p.FullToken.FullImmediate;
+
+                       ctor_immd(pc, imm->u.ImmediateFloat32[0].Float,
+                                     imm->u.ImmediateFloat32[1].Float,
+                                     imm->u.ImmediateFloat32[2].Float,
+                                     imm->u.ImmediateFloat32[3].Float);
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_DECLARATION:
+               {
+                       const struct tgsi_full_declaration *d;
+                       unsigned last;
+
+                       d = &p.FullToken.FullDeclaration;
+                       last = d->DeclarationRange.Last;
+
+                       switch (d->Declaration.File) {
+                       case TGSI_FILE_TEMPORARY:
+                               if (pc->temp_nr < (last + 1))
+                                       pc->temp_nr = last + 1;
+                               break;
+                       case TGSI_FILE_OUTPUT:
+                               if (pc->result_nr < (last + 1))
+                                       pc->result_nr = last + 1;
+                               break;
+                       case TGSI_FILE_INPUT:
+                               if (pc->attr_nr < (last + 1))
+                                       pc->attr_nr = last + 1;
+                               break;
+                       case TGSI_FILE_CONSTANT:
+                               if (pc->param_nr < (last + 1))
+                                       pc->param_nr = last + 1;
+                               break;
+                       case TGSI_FILE_SAMPLER:
+                               break;
+                       default:
+                               NOUVEAU_ERR("bad decl file %d\n",
+                                           d->Declaration.File);
+                               goto out_err;
+                       }
+               }
+                       break;
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (pc->temp_nr) {
+               pc->temp = CALLOC(pc->temp_nr * 4, sizeof(struct nv50_reg));
+               if (!pc->temp)
+                       goto out_err;
+
+               for (i = 0; i < pc->temp_nr; i++) {
+                       for (c = 0; c < 4; c++) {
+                               pc->temp[i*4+c].type = P_TEMP;
+                               pc->temp[i*4+c].hw = -1;
+                               pc->temp[i*4+c].index = i;
+                       }
+               }
+       }
+
+       if (pc->attr_nr) {
+               struct nv50_reg *iv = NULL;
+               int aid = 0;
+
+               pc->attr = CALLOC(pc->attr_nr * 4, sizeof(struct nv50_reg));
+               if (!pc->attr)
+                       goto out_err;
+
+               if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+                       iv = alloc_temp(pc, NULL);
+                       emit_interp(pc, iv, iv, NULL);
+                       emit_flop(pc, 0, iv, iv);
+                       aid++;
+               }
+
+               for (i = 0; i < pc->attr_nr; i++) {
+                       struct nv50_reg *a = &pc->attr[i*4];
+
+                       for (c = 0; c < 4; c++) {
+                               if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+                                       struct nv50_reg *at =
+                                               alloc_temp(pc, NULL);
+                                       pc->attr[i*4+c].type = at->type;
+                                       pc->attr[i*4+c].hw = at->hw;
+                                       pc->attr[i*4+c].index = at->index;
+                               } else {
+                                       pc->p->cfg.vp.attr[aid/32] |=
+                                               (1 << (aid % 32));
+                                       pc->attr[i*4+c].type = P_ATTR;
+                                       pc->attr[i*4+c].hw = aid++;
+                                       pc->attr[i*4+c].index = i;
+                               }
+                       }
+
+                       if (pc->p->type != PIPE_SHADER_FRAGMENT)
+                               continue;
+
+                       emit_interp(pc, &a[0], &a[0], iv);
+                       emit_interp(pc, &a[1], &a[1], iv);
+                       emit_interp(pc, &a[2], &a[2], iv);
+                       emit_interp(pc, &a[3], &a[3], iv);
+               }
+
+               if (iv)
+                       free_temp(pc, iv);
+       }
+
+       if (pc->result_nr) {
+               int rid = 0;
+
+               pc->result = CALLOC(pc->result_nr * 4, sizeof(struct nv50_reg));
+               if (!pc->result)
+                       goto out_err;
+
+               for (i = 0; i < pc->result_nr; i++) {
+                       for (c = 0; c < 4; c++) {
+                               if (pc->p->type == PIPE_SHADER_FRAGMENT) {
+                                       pc->result[i*4+c].type = P_TEMP;
+                                       pc->result[i*4+c].hw = -1;
+                               } else {
+                                       pc->result[i*4+c].type = P_RESULT;
+                                       pc->result[i*4+c].hw = rid++;
+                               }
+                               pc->result[i*4+c].index = i;
+                       }
+               }
+       }
+
+       if (pc->param_nr) {
+               int rid = 0;
+
+               pc->param = CALLOC(pc->param_nr * 4, sizeof(struct nv50_reg));
+               if (!pc->param)
+                       goto out_err;
+
+               for (i = 0; i < pc->param_nr; i++) {
+                       for (c = 0; c < 4; c++) {
+                               pc->param[i*4+c].type = P_CONST;
+                               pc->param[i*4+c].hw = rid++;
+                               pc->param[i*4+c].index = i;
+                       }
+               }
+       }
+
+       if (pc->immd_nr) {
+               int rid = pc->param_nr * 4;
+
+               pc->immd = CALLOC(pc->immd_nr * 4, sizeof(struct nv50_reg));
+               if (!pc->immd)
+                       goto out_err;
+
+               for (i = 0; i < pc->immd_nr; i++) {
+                       for (c = 0; c < 4; c++) {
+                               pc->immd[i*4+c].type = P_IMMD;
+                               pc->immd[i*4+c].hw = rid++;
+                               pc->immd[i*4+c].index = i;
+                       }
+               }
+       }
+
+       ret = TRUE;
+out_err:
+       tgsi_parse_free(&p);
+       return ret;
+}
+
+static boolean
+nv50_program_tx(struct nv50_program *p)
+{
+       struct tgsi_parse_context parse;
+       struct nv50_pc *pc;
+       boolean ret;
+
+       pc = CALLOC_STRUCT(nv50_pc);
+       if (!pc)
+               return FALSE;
+       pc->p = p;
+       pc->p->cfg.high_temp = 4;
+
+       ret = nv50_program_tx_prep(pc);
+       if (ret == FALSE)
+               goto out_cleanup;
+
+       tgsi_parse_init(&parse, pc->p->pipe.tokens);
+       while (!tgsi_parse_end_of_tokens(&parse)) {
+               const union tgsi_full_token *tok = &parse.FullToken;
+
+               tgsi_parse_token(&parse);
+
+               switch (tok->Token.Type) {
+               case TGSI_TOKEN_TYPE_INSTRUCTION:
+                       ret = nv50_program_tx_insn(pc, tok);
+                       if (ret == FALSE)
+                               goto out_err;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (p->type == PIPE_SHADER_FRAGMENT) {
+               struct nv50_reg out;
+
+               out.type = P_TEMP;
+               for (out.hw = 0; out.hw < pc->result_nr * 4; out.hw++)
+                       emit_mov(pc, &out, &pc->result[out.hw]);
+       }
+
+       assert(is_long(pc->p->exec_tail) && !is_immd(pc->p->exec_head));
+       pc->p->exec_tail->inst[1] |= 0x00000001;
+
+       p->param_nr = pc->param_nr * 4;
+       p->immd_nr = pc->immd_nr * 4;
+       p->immd = pc->immd_buf;
+
+out_err:
+       tgsi_parse_free(&parse);
+
+out_cleanup:
+       return ret;
+}
+
+static void
+nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p)
+{
+       if (nv50_program_tx(p) == FALSE)
+               assert(0);
+       p->translated = TRUE;
+}
+
+static void
+nv50_program_upload_data(struct nv50_context *nv50, float *map,
+                        unsigned start, unsigned count)
+{
+       while (count) {
+               unsigned nr = count > 2047 ? 2047 : count;
+
+               BEGIN_RING(tesla, 0x00000f00, 1);
+               OUT_RING  ((NV50_CB_PMISC << 0) | (start << 8));
+               BEGIN_RING(tesla, 0x40000f04, nr);
+               OUT_RINGp (map, nr);
+
+               map += nr;
+               start += nr;
+               count -= nr;
+       }
+}
+
+static void
+nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
+{
+       struct nouveau_winsys *nvws = nv50->screen->nvws;
+       struct pipe_winsys *ws = nv50->pipe.winsys;
+       unsigned nr = p->param_nr + p->immd_nr;
+
+       if (!p->data && nr) {
+               struct nouveau_resource *heap = nv50->screen->vp_data_heap;
+
+               if (nvws->res_alloc(heap, nr, p, &p->data)) {
+                       while (heap->next && heap->size < nr) {
+                               struct nv50_program *evict = heap->next->priv;
+                               nvws->res_free(&evict->data);
+                       }
+
+                       if (nvws->res_alloc(heap, nr, p, &p->data))
+                               assert(0);
+               }
+       }
+
+       if (p->param_nr) {
+               float *map = ws->buffer_map(ws, nv50->constbuf[p->type],
+                                           PIPE_BUFFER_USAGE_CPU_READ);
+               nv50_program_upload_data(nv50, map, p->data->start,
+                                        p->param_nr);
+               ws->buffer_unmap(ws, nv50->constbuf[p->type]);
+       }
+
+       if (p->immd_nr) {
+               nv50_program_upload_data(nv50, p->immd,
+                                        p->data->start + p->param_nr,
+                                        p->immd_nr);
+       }
+}
+
+static void
+nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p)
+{
+       struct pipe_winsys *ws = nv50->pipe.winsys;
+       struct nv50_program_exec *e;
+       struct nouveau_stateobj *so;
+       const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
+       unsigned start, count, *up, *ptr;
+       boolean upload = FALSE;
+
+       if (!p->buffer) {
+               p->buffer = ws->buffer_create(ws, 0x100, 0, p->exec_size * 4);
+               upload = TRUE;
+       }
+
+       if (p->data && p->data->start != p->data_start) {
+               for (e = p->exec_head; e; e = e->next) {
+                       unsigned ei, ci;
+
+                       if (e->param.index < 0)
+                               continue;
+                       ei = e->param.shift >> 5;
+                       ci = e->param.index + p->data->start;
+
+                       e->inst[ei] &= ~e->param.mask;
+                       e->inst[ei] |= (ci << e->param.shift);
+               }
+
+               p->data_start = p->data->start;
+               upload = TRUE;
+       }
+
+       if (!upload)
+               return;
+
+       up = ptr = MALLOC(p->exec_size * 4);
+       for (e = p->exec_head; e; e = e->next) {
+               *(ptr++) = e->inst[0];
+               if (is_long(e))
+                       *(ptr++) = e->inst[1];
+       }
+
+       so = so_new(4,2);
+       so_method(so, nv50->screen->tesla, 0x1280, 3);
+       so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, (NV50_CB_PUPLOAD << 16) | 0x0800); //(p->exec_size * 4));
+
+       start = 0; count = p->exec_size;
+       while (count) {
+               struct nouveau_winsys *nvws = nv50->screen->nvws;
+               unsigned nr;
+
+               so_emit(nvws, so);
+
+               nr = MIN2(count, 2047);
+               nr = MIN2(nvws->channel->pushbuf->remaining, nr);
+               if (nvws->channel->pushbuf->remaining < (nr + 3)) {
+                       FIRE_RING(NULL);
+                       continue;
+               }
+
+               BEGIN_RING(tesla, 0x0f00, 1);
+               OUT_RING  ((start << 8) | NV50_CB_PUPLOAD);
+               BEGIN_RING(tesla, 0x40000f04, nr);      
+               OUT_RINGp (up + start, nr);
+
+               start += nr;
+               count -= nr;
+       }
+
+       FREE(up);
+       so_ref(NULL, &so);
+}
+
+void
+nv50_vertprog_validate(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nv50_program *p = nv50->vertprog;
+       struct nouveau_stateobj *so;
+
+       if (!p->translated) {
+               nv50_program_validate(nv50, p);
+               if (!p->translated)
+                       assert(0);
+       }
+
+       nv50_program_validate_data(nv50, p);
+       nv50_program_validate_code(nv50, p);
+
+       so = so_new(13, 2);
+       so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
+       so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+                 NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+                 NOUVEAU_BO_LOW, 0, 0);
+       so_method(so, tesla, 0x1650, 2);
+       so_data  (so, p->cfg.vp.attr[0]);
+       so_data  (so, p->cfg.vp.attr[1]);
+       so_method(so, tesla, 0x16b8, 1);
+       so_data  (so, p->cfg.high_result);
+       so_method(so, tesla, 0x16ac, 2);
+       so_data  (so, p->cfg.high_result); //8);
+       so_data  (so, p->cfg.high_temp);
+       so_method(so, tesla, 0x140c, 1);
+       so_data  (so, 0); /* program start offset */
+       so_ref(so, &nv50->state.vertprog);
+}
+
+void
+nv50_fragprog_validate(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nv50_program *p = nv50->fragprog;
+       struct nouveau_stateobj *so;
+
+       if (!p->translated) {
+               nv50_program_validate(nv50, p);
+               if (!p->translated)
+                       assert(0);
+       }
+
+       nv50_program_validate_data(nv50, p);
+       nv50_program_validate_code(nv50, p);
+
+       so = so_new(64, 2);
+       so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2);
+       so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+                 NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+                 NOUVEAU_BO_LOW, 0, 0);
+       so_method(so, tesla, 0x1904, 4);
+       so_data  (so, 0x01040404); /* p: 0x01000404 */
+       so_data  (so, 0x00000004);
+       so_data  (so, 0x00000000);
+       so_data  (so, 0x00000000);
+       so_method(so, tesla, 0x16bc, 3); /*XXX: fixme */
+       so_data  (so, 0x03020100);
+       so_data  (so, 0x07060504);
+       so_data  (so, 0x0b0a0908);
+       so_method(so, tesla, 0x1988, 2);
+       so_data  (so, 0x08080408); //0x08040404); /* p: 0x0f000401 */
+       so_data  (so, p->cfg.high_temp);
+       so_method(so, tesla, 0x1414, 1);
+       so_data  (so, 0); /* program start offset */
+       so_ref(so, &nv50->state.fragprog);
+}
+
+void
+nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p)
+{
+       struct pipe_winsys *ws = nv50->pipe.winsys;
+
+       while (p->exec_head) {
+               struct nv50_program_exec *e = p->exec_head;
+
+               p->exec_head = e->next;
+               FREE(e);
+       }
+       p->exec_tail = NULL;
+       p->exec_size = 0;
+
+       if (p->buffer)
+               pipe_buffer_reference(ws, &p->buffer, NULL);
+
+       nv50->screen->nvws->res_free(&p->data);
+
+       p->translated = 0;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
new file mode 100644 (file)
index 0000000..d643e8d
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __NV50_PROGRAM_H__
+#define __NV50_PROGRAM_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/util/tgsi_scan.h"
+
+struct nv50_program_exec {
+       struct nv50_program_exec *next;
+
+       unsigned inst[2];
+       struct {
+               int index;
+               unsigned mask;
+               unsigned shift;
+       } param;
+};
+
+struct nv50_program {
+       struct pipe_shader_state pipe;
+       struct tgsi_shader_info info;
+       boolean translated;
+
+       unsigned type;
+       struct nv50_program_exec *exec_head;
+       struct nv50_program_exec *exec_tail;
+       unsigned exec_size;
+       struct nouveau_resource *data;
+       unsigned data_start;
+
+       struct pipe_buffer *buffer;
+
+       float *immd;
+       unsigned immd_nr;
+       unsigned param_nr;
+
+       struct {
+               unsigned high_temp;
+               unsigned high_result;
+               struct {
+                       unsigned attr[2];
+               } vp;
+       } cfg;
+};
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
new file mode 100644 (file)
index 0000000..26bd90c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+
+#include "nv50_context.h"
+
+static struct pipe_query *
+nv50_query_create(struct pipe_context *pipe, unsigned type)
+{
+       NOUVEAU_ERR("unimplemented\n");
+       return NULL;
+}
+
+static void
+nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *q)
+{
+       NOUVEAU_ERR("unimplemented\n");
+}
+
+static void
+nv50_query_begin(struct pipe_context *pipe, struct pipe_query *q)
+{
+       NOUVEAU_ERR("unimplemented\n");
+}
+
+static void
+nv50_query_end(struct pipe_context *pipe, struct pipe_query *q)
+{
+       NOUVEAU_ERR("unimplemented\n");
+}
+
+static boolean
+nv50_query_result(struct pipe_context *pipe, struct pipe_query *q,
+                 boolean wait, uint64 *result)
+{
+       NOUVEAU_ERR("unimplemented\n");
+       *result = 0xdeadcafe;
+       return TRUE;
+}
+
+void
+nv50_init_query_functions(struct nv50_context *nv50)
+{
+       nv50->pipe.create_query = nv50_query_create;
+       nv50->pipe.destroy_query = nv50_query_destroy;
+       nv50->pipe.begin_query = nv50_query_begin;
+       nv50->pipe.end_query = nv50_query_end;
+       nv50->pipe.get_query_result = nv50_query_result;
+}
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
new file mode 100644 (file)
index 0000000..bba5ca4
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_screen.h"
+#include "pipe/p_util.h"
+
+#include "nv50_context.h"
+#include "nv50_screen.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+#define NV5X_GRCLASS5097_CHIPSETS 0x00000001
+#define NV8X_GRCLASS8297_CHIPSETS 0x00000010
+#define NV9X_GRCLASS8297_CHIPSETS 0x00000004
+
+static boolean
+nv50_screen_is_format_supported(struct pipe_screen *pscreen,
+                               enum pipe_format format, uint type)
+{
+       switch (type) {
+       case PIPE_SURFACE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM:
+               case PIPE_FORMAT_Z24S8_UNORM:
+               case PIPE_FORMAT_Z16_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       case PIPE_TEXTURE:
+               switch (format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+               case PIPE_FORMAT_A1R5G5B5_UNORM:
+               case PIPE_FORMAT_A4R4G4B4_UNORM:
+               case PIPE_FORMAT_R5G6B5_UNORM:
+               case PIPE_FORMAT_L8_UNORM:
+               case PIPE_FORMAT_A8_UNORM:
+               case PIPE_FORMAT_I8_UNORM:
+               case PIPE_FORMAT_A8L8_UNORM:
+                       return TRUE;
+               default:
+                       break;
+               }
+               break;
+       default:
+               assert(0);
+       }
+
+       return FALSE;
+}
+
+static const char *
+nv50_screen_get_name(struct pipe_screen *pscreen)
+{
+       struct nv50_screen *screen = nv50_screen(pscreen);
+       struct nouveau_device *dev = screen->nvws->channel->device;
+       static char buffer[128];
+
+       snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+       return buffer;
+}
+
+static const char *
+nv50_screen_get_vendor(struct pipe_screen *pscreen)
+{
+       return "nouveau";
+}
+
+static int
+nv50_screen_get_param(struct pipe_screen *pscreen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
+               return 32;
+       case PIPE_CAP_NPOT_TEXTURES:
+               return 0;
+       case PIPE_CAP_TWO_SIDED_STENCIL:
+               return 1;
+       case PIPE_CAP_GLSL:
+               return 0;
+       case PIPE_CAP_S3TC:
+               return 0;
+       case PIPE_CAP_ANISOTROPIC_FILTER:
+               return 0;
+       case PIPE_CAP_POINT_SPRITE:
+               return 0;
+       case PIPE_CAP_MAX_RENDER_TARGETS:
+               return 8;
+       case PIPE_CAP_OCCLUSION_QUERY:
+               return 0;
+       case PIPE_CAP_TEXTURE_SHADOW_MAP:
+               return 0;
+       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 NOUVEAU_CAP_HW_VTXBUF:     
+               return 1;
+       case NOUVEAU_CAP_HW_IDXBUF:     
+               return 0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0;
+       }
+}
+
+static float
+nv50_screen_get_paramf(struct pipe_screen *pscreen, int param)
+{
+       switch (param) {
+       case PIPE_CAP_MAX_LINE_WIDTH:
+       case PIPE_CAP_MAX_LINE_WIDTH_AA:
+               return 10.0;
+       case PIPE_CAP_MAX_POINT_WIDTH:
+       case PIPE_CAP_MAX_POINT_WIDTH_AA:
+               return 64.0;
+       case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
+               return 16.0;
+       case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
+               return 4.0;
+       default:
+               NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
+               return 0.0;
+       }
+}
+
+static void
+nv50_screen_destroy(struct pipe_screen *pscreen)
+{
+       FREE(pscreen);
+}
+
+struct pipe_screen *
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+       struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
+       struct nouveau_stateobj *so;
+       unsigned tesla_class = 0, ret;
+       unsigned chipset = nvws->channel->device->chipset;
+       int i;
+
+       if (!screen)
+               return NULL;
+       screen->nvws = nvws;
+
+       /* 3D object */
+       if ((chipset & 0xf0) != 0x50 && (chipset & 0xf0) != 0x80) {
+               NOUVEAU_ERR("Not a G8x chipset\n");
+               nv50_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       switch (chipset & 0xf0) {
+       case 0x50:
+               if (NV5X_GRCLASS5097_CHIPSETS & (1 << (chipset & 0x0f)))
+                       tesla_class = 0x5097;
+               break;
+       case 0x80:
+               if (NV8X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f)))
+                       tesla_class = 0x8297;
+               break;
+       case 0x90:
+               if (NV9X_GRCLASS8297_CHIPSETS & (1 << (chipset & 0x0f)))
+                       tesla_class = 0x8297;
+               break;
+       default:
+               break;
+       }
+
+       if (tesla_class == 0) {
+               NOUVEAU_ERR("Unknown G8x chipset: NV%02x\n", chipset);
+               nv50_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       ret = nvws->grobj_alloc(nvws, tesla_class, &screen->tesla);
+       if (ret) {
+               NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
+               nv50_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Sync notifier */
+       ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
+       if (ret) {
+               NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
+               nv50_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       /* Static tesla init */
+       so = so_new(256, 20);
+
+       so_method(so, screen->tesla, 0x1558, 1);
+       so_data  (so, 1);
+       so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1);
+       so_data  (so, screen->sync->handle);
+       so_method(so, screen->tesla, NV50TCL_DMA_UNK0(0),
+                                    NV50TCL_DMA_UNK0__SIZE);
+       for (i = 0; i < NV50TCL_DMA_UNK0__SIZE; i++)
+               so_data(so, nvws->channel->vram->handle);
+       so_method(so, screen->tesla, NV50TCL_DMA_UNK1(0),
+                                    NV50TCL_DMA_UNK1__SIZE);
+       for (i = 0; i < NV50TCL_DMA_UNK1__SIZE; i++)
+               so_data(so, nvws->channel->vram->handle);
+       so_method(so, screen->tesla, 0x121c, 1);
+       so_data  (so, 1);
+
+       so_method(so, screen->tesla, 0x13bc, 1);
+       so_data  (so, 0x54);
+       so_method(so, screen->tesla, 0x13ac, 1);
+       so_data  (so, 1);
+       so_method(so, screen->tesla, 0x16b8, 1);
+       so_data  (so, 8);
+
+       /* Shared constant buffer */
+       screen->constbuf = ws->buffer_create(ws, 0, 0, 128 * 4 * 4);
+       if (nvws->res_init(&screen->vp_data_heap, 0, 128)) {
+               NOUVEAU_ERR("Error initialising constant buffer\n");
+               nv50_screen_destroy(&screen->pipe);
+               return NULL;
+       }
+
+       so_method(so, screen->tesla, 0x1280, 3);
+       so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, (NV50_CB_PMISC << 16) | 0x00001000);
+
+       /* Texture sampler/image unit setup - we abuse the constant buffer
+        * upload mechanism for the moment to upload data to the tex config
+        * blocks.  At some point we *may* want to go the NVIDIA way of doing
+        * things?
+        */
+       screen->tic = ws->buffer_create(ws, 0, 0, 32 * 8 * 4);
+       so_method(so, screen->tesla, 0x1280, 3);
+       so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, (NV50_CB_TIC << 16) | 0x0800);
+       so_method(so, screen->tesla, 0x1574, 3);
+       so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, 0x00000800);
+
+       screen->tsc = ws->buffer_create(ws, 0, 0, 32 * 8 * 4);
+       so_method(so, screen->tesla, 0x1280, 3);
+       so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, (NV50_CB_TSC << 16) | 0x0800);
+       so_method(so, screen->tesla, 0x155c, 3);
+       so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+       so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
+                 NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       so_data  (so, 0x00000800);
+
+
+       /* Vertex array limits - max them out */
+       for (i = 0; i < 16; i++) {
+               so_method(so, screen->tesla, 0x1080 + (i * 8), 2);
+               so_data  (so, 0x000000ff);
+               so_data  (so, 0xffffffff);
+       }
+
+       so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR, 2);
+       so_data  (so, fui(0.0));
+       so_data  (so, fui(1.0));
+
+       so_method(so, screen->tesla, 0x1234, 1);
+       so_data  (so, 1);
+       so_method(so, screen->tesla, 0x1458, 1);
+       so_data  (so, 1);
+
+       so_emit(nvws, so);
+       so_ref(so, &screen->static_init);
+       nvws->push_flush(nvws, 0, NULL);
+
+       screen->pipe.winsys = ws;
+
+       screen->pipe.destroy = nv50_screen_destroy;
+
+       screen->pipe.get_name = nv50_screen_get_name;
+       screen->pipe.get_vendor = nv50_screen_get_vendor;
+       screen->pipe.get_param = nv50_screen_get_param;
+       screen->pipe.get_paramf = nv50_screen_get_paramf;
+
+       screen->pipe.is_format_supported = nv50_screen_is_format_supported;
+
+       nv50_screen_init_miptree_functions(&screen->pipe);
+       nv50_surface_init_screen_functions(&screen->pipe);
+
+       return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
new file mode 100644 (file)
index 0000000..400ddce
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __NV50_SCREEN_H__
+#define __NV50_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv50_screen {
+       struct pipe_screen pipe;
+
+       struct nouveau_winsys *nvws;
+
+       unsigned cur_pctx;
+
+       struct nouveau_grobj *tesla;
+       struct nouveau_notifier *sync;
+
+       struct pipe_buffer *constbuf;
+       struct nouveau_resource *vp_data_heap;
+
+       struct pipe_buffer *tic;
+       struct pipe_buffer *tsc;
+
+       struct nouveau_stateobj *static_init;
+};
+
+static INLINE struct nv50_screen *
+nv50_screen(struct pipe_screen *screen)
+{
+       return (struct nv50_screen *)screen;
+}
+
+void nv50_surface_init_screen_functions(struct pipe_screen *);
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
new file mode 100644 (file)
index 0000000..c552a0b
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nv50_context.h"
+#include "nv50_texture.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+static void *
+nv50_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+{
+       struct nouveau_stateobj *so = so_new(64, 0);
+       struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+       struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
+       unsigned cmask = 0, i;
+
+       /*XXX ignored:
+        *      - dither
+        */
+
+       if (cso->blend_enable == 0) {
+               so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+               for (i = 0; i < 8; i++)
+                       so_data(so, 0);
+       } else {
+               so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
+               for (i = 0; i < 8; i++)
+                       so_data(so, 1);
+               so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
+               so_data  (so, nvgl_blend_eqn(cso->rgb_func));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor));
+               so_data  (so, nvgl_blend_eqn(cso->alpha_func));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor));
+               so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor));
+       }
+
+       if (cso->logicop_enable == 0 ) {
+               so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
+               so_data  (so, 0);
+       } else {
+               so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
+               so_data  (so, 1);
+               so_data  (so, nvgl_logicop_func(cso->logicop_func));
+       }
+
+       if (cso->colormask & PIPE_MASK_R)
+               cmask |= (1 << 0);
+       if (cso->colormask & PIPE_MASK_G)
+               cmask |= (1 << 4);
+       if (cso->colormask & PIPE_MASK_B)
+               cmask |= (1 << 8);
+       if (cso->colormask & PIPE_MASK_A)
+               cmask |= (1 << 12);
+       so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
+       for (i = 0; i < 8; i++)
+               so_data(so, cmask);
+
+       bso->pipe = *cso;
+       so_ref(so, &bso->so);
+       return (void *)bso;
+}
+
+static void
+nv50_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->blend = hwcso;
+       nv50->dirty |= NV50_NEW_BLEND;
+}
+
+static void
+nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_blend_stateobj *bso = hwcso;
+
+       so_ref(NULL, &bso->so);
+       FREE(bso);
+}
+
+static INLINE unsigned
+wrap_mode(unsigned wrap)
+{
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               return NV50TSC_1_0_WRAPS_REPEAT;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               return NV50TSC_1_0_WRAPS_MIRROR_REPEAT;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER;
+       case PIPE_TEX_WRAP_CLAMP:
+               return NV50TSC_1_0_WRAPS_CLAMP;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP;
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               return NV50TSC_1_0_WRAPS_REPEAT;
+       }
+}
+static void *
+nv50_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+{
+       unsigned *tsc = CALLOC(8, sizeof(unsigned));
+
+       tsc[0] = (0x00024000 |
+                 (wrap_mode(cso->wrap_s) << 0) |
+                 (wrap_mode(cso->wrap_t) << 3) |
+                 (wrap_mode(cso->wrap_r) << 6));
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MAGF_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               tsc[1] |= NV50TSC_1_1_MAGF_NEAREST;
+               break;
+       }
+
+       switch (cso->min_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MINF_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               tsc[1] |= NV50TSC_1_1_MINF_NEAREST;
+               break;
+       }
+
+       switch (cso->min_mip_filter) {
+       case PIPE_TEX_MIPFILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MIPF_LINEAR;
+               break;
+       case PIPE_TEX_MIPFILTER_NEAREST:
+               tsc[1] |= NV50TSC_1_1_MIPF_NEAREST;
+               break;
+       case PIPE_TEX_MIPFILTER_NONE:
+       default:
+               tsc[1] |= NV50TSC_1_1_MIPF_NONE;
+               break;
+       }
+
+       return (void *)tsc;
+}
+
+static void
+nv50_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+       int i;
+
+       nv50->sampler_nr = nr;
+       for (i = 0; i < nv50->sampler_nr; i++)
+               nv50->sampler[i] = sampler[i];
+
+       nv50->dirty |= NV50_NEW_SAMPLER;
+}
+
+static void
+nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       FREE(hwcso);
+}
+
+static void
+nv50_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+                        struct pipe_texture **pt)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+       int i;
+
+       for (i = 0; i < nr; i++)
+               pipe_texture_reference((void *)&nv50->miptree[i], pt[i]);
+       for (i = nr; i < nv50->miptree_nr; i++)
+               pipe_texture_reference((void *)&nv50->miptree[i], NULL);
+
+       nv50->miptree_nr = nr;
+       nv50->dirty |= NV50_NEW_TEXTURE;
+}
+
+static void *
+nv50_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+{
+       struct nouveau_stateobj *so = so_new(64, 0);
+       struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+       struct nv50_rasterizer_stateobj *rso =
+               CALLOC_STRUCT(nv50_rasterizer_stateobj);
+
+       /*XXX: ignored
+        *      - light_twosize
+        *      - point_smooth
+        *      - multisample
+        *      - point_sprite / sprite_coord_mode
+        */
+
+       so_method(so, tesla, NV50TCL_SHADE_MODEL, 1);
+       so_data  (so, cso->flatshade ? NV50TCL_SHADE_MODEL_FLAT :
+                                      NV50TCL_SHADE_MODEL_SMOOTH);
+
+       so_method(so, tesla, NV50TCL_LINE_WIDTH, 1);
+       so_data  (so, fui(cso->line_width));
+       so_method(so, tesla, NV50TCL_LINE_SMOOTH_ENABLE, 1);
+       so_data  (so, cso->line_smooth ? 1 : 0);
+       if (cso->line_stipple_enable) {
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
+               so_data  (so, (cso->line_stipple_pattern << 8) |
+                              cso->line_stipple_factor);
+       } else {
+               so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       so_method(so, tesla, NV50TCL_POINT_SIZE, 1);
+       so_data  (so, fui(cso->point_size));
+
+       so_method(so, tesla, NV50TCL_POLYGON_MODE_FRONT, 3);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+       } else {
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+       }
+       so_data(so, cso->poly_smooth ? 1 : 0);
+
+       so_method(so, tesla, NV50TCL_CULL_FACE_ENABLE, 3);
+       so_data  (so, cso->cull_mode != PIPE_WINDING_NONE);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, NV50TCL_FRONT_FACE_CCW);
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               }
+       } else {
+               so_data(so, NV50TCL_FRONT_FACE_CW);
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV50TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV50TCL_CULL_FACE_BACK);
+                       break;
+               }
+       }
+
+       so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_ENABLE, 1);
+       so_data  (so, cso->poly_stipple_enable ? 1 : 0);
+
+       so_method(so, tesla, NV50TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+
+       if (cso->offset_cw || cso->offset_ccw) {
+               so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
+               so_data  (so, fui(cso->offset_scale));
+               so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
+               so_data  (so, fui(cso->offset_units));
+       }
+
+       rso->pipe = *cso;
+       so_ref(so, &rso->so);
+       return (void *)rso;
+}
+
+static void
+nv50_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->rasterizer = hwcso;
+       nv50->dirty |= NV50_NEW_RASTERIZER;
+}
+
+static void
+nv50_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_rasterizer_stateobj *rso = hwcso;
+
+       so_ref(NULL, &rso->so);
+       FREE(rso);
+}
+
+static void *
+nv50_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+{
+       struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
+       struct nv50_zsa_stateobj *zsa = CALLOC_STRUCT(nv50_zsa_stateobj);
+       struct nouveau_stateobj *so = so_new(64, 0);
+
+       so_method(so, tesla, NV50TCL_DEPTH_WRITE_ENABLE, 1);
+       so_data  (so, cso->depth.writemask ? 1 : 0);
+       if (cso->depth.enabled) {
+               so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, tesla, NV50TCL_DEPTH_TEST_FUNC, 1);
+               so_data  (so, nvgl_comparison_op(cso->depth.func));
+       } else {
+               so_method(so, tesla, NV50TCL_DEPTH_TEST_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       /*XXX: yes, I know they're backwards.. header needs fixing */
+       if (cso->stencil[0].enabled) {
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 5);
+               so_data  (so, 1);
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+               so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 3);
+               so_data  (so, cso->stencil[0].ref_value);
+               so_data  (so, cso->stencil[0].write_mask);
+               so_data  (so, cso->stencil[0].value_mask);
+       } else {
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       if (cso->stencil[1].enabled) {
+               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 8);
+               so_data  (so, 1);
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+               so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
+               so_data  (so, cso->stencil[1].ref_value);
+               so_data  (so, cso->stencil[1].write_mask);
+               so_data  (so, cso->stencil[1].value_mask);
+       } else {
+               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       if (cso->alpha.enabled) {
+               so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
+               so_data  (so, 1);
+               so_method(so, tesla, NV50TCL_ALPHA_TEST_REF, 2);
+               so_data  (so, fui(cso->alpha.ref));
+               so_data  (so, nvgl_comparison_op(cso->alpha.func));
+       } else {
+               so_method(so, tesla, NV50TCL_ALPHA_TEST_ENABLE, 1);
+               so_data  (so, 0);
+       }
+
+       zsa->pipe = *cso;
+       so_ref(so, &zsa->so);
+       return (void *)zsa;
+}
+
+static void
+nv50_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->zsa = hwcso;
+       nv50->dirty |= NV50_NEW_ZSA;
+}
+
+static void
+nv50_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_zsa_stateobj *zsa = hwcso;
+
+       so_ref(NULL, &zsa->so);
+       FREE(zsa);
+}
+
+static void *
+nv50_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+       p->pipe = *cso;
+       p->type = PIPE_SHADER_VERTEX;
+       tgsi_scan_shader(p->pipe.tokens, &p->info);
+       return (void *)p;
+}
+
+static void
+nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->vertprog = hwcso;
+       nv50->dirty |= NV50_NEW_VERTPROG;
+}
+
+static void
+nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50_program_destroy(nv50, hwcso);
+       FREE(hwcso);
+}
+
+static void *
+nv50_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+{
+       struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+       p->pipe = *cso;
+       p->type = PIPE_SHADER_FRAGMENT;
+       tgsi_scan_shader(p->pipe.tokens, &p->info);
+       return (void *)p;
+}
+
+static void
+nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->fragprog = hwcso;
+       nv50->dirty |= NV50_NEW_FRAGPROG;
+}
+
+static void
+nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50_program_destroy(nv50, hwcso);
+       FREE(hwcso);
+}
+
+static void
+nv50_set_blend_color(struct pipe_context *pipe,
+                    const struct pipe_blend_color *bcol)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->blend_colour = *bcol;
+       nv50->dirty |= NV50_NEW_BLEND_COLOUR;
+}
+
+static void
+nv50_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+{
+}
+
+static void
+nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        const struct pipe_constant_buffer *buf )
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       if (shader == PIPE_SHADER_VERTEX) {
+               nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+               nv50->dirty |= NV50_NEW_VERTPROG_CB;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+               nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+       }
+}
+
+static void
+nv50_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->framebuffer = *fb;
+       nv50->dirty |= NV50_NEW_FRAMEBUFFER;
+}
+
+static void
+nv50_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->stipple = *stipple;
+       nv50->dirty |= NV50_NEW_STIPPLE;
+}
+
+static void
+nv50_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->scissor = *s;
+       nv50->dirty |= NV50_NEW_SCISSOR;
+}
+
+static void
+nv50_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *vpt)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->viewport = *vpt;
+       nv50->dirty |= NV50_NEW_VIEWPORT;
+}
+
+static void
+nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
+       nv50->vtxbuf_nr = count;
+
+       nv50->dirty |= NV50_NEW_ARRAYS;
+}
+
+static void
+nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+                        const struct pipe_vertex_element *ve)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       memcpy(nv50->vtxelt, ve, sizeof(*ve) * count);
+       nv50->vtxelt_nr = count;
+
+       nv50->dirty |= NV50_NEW_ARRAYS;
+}
+
+void
+nv50_init_state_functions(struct nv50_context *nv50)
+{
+       nv50->pipe.create_blend_state = nv50_blend_state_create;
+       nv50->pipe.bind_blend_state = nv50_blend_state_bind;
+       nv50->pipe.delete_blend_state = nv50_blend_state_delete;
+
+       nv50->pipe.create_sampler_state = nv50_sampler_state_create;
+       nv50->pipe.bind_sampler_states = nv50_sampler_state_bind;
+       nv50->pipe.delete_sampler_state = nv50_sampler_state_delete;
+       nv50->pipe.set_sampler_textures = nv50_set_sampler_texture;
+
+       nv50->pipe.create_rasterizer_state = nv50_rasterizer_state_create;
+       nv50->pipe.bind_rasterizer_state = nv50_rasterizer_state_bind;
+       nv50->pipe.delete_rasterizer_state = nv50_rasterizer_state_delete;
+
+       nv50->pipe.create_depth_stencil_alpha_state =
+               nv50_depth_stencil_alpha_state_create;
+       nv50->pipe.bind_depth_stencil_alpha_state =
+               nv50_depth_stencil_alpha_state_bind;
+       nv50->pipe.delete_depth_stencil_alpha_state =
+               nv50_depth_stencil_alpha_state_delete;
+
+       nv50->pipe.create_vs_state = nv50_vp_state_create;
+       nv50->pipe.bind_vs_state = nv50_vp_state_bind;
+       nv50->pipe.delete_vs_state = nv50_vp_state_delete;
+
+       nv50->pipe.create_fs_state = nv50_fp_state_create;
+       nv50->pipe.bind_fs_state = nv50_fp_state_bind;
+       nv50->pipe.delete_fs_state = nv50_fp_state_delete;
+
+       nv50->pipe.set_blend_color = nv50_set_blend_color;
+       nv50->pipe.set_clip_state = nv50_set_clip_state;
+       nv50->pipe.set_constant_buffer = nv50_set_constant_buffer;
+       nv50->pipe.set_framebuffer_state = nv50_set_framebuffer_state;
+       nv50->pipe.set_polygon_stipple = nv50_set_polygon_stipple;
+       nv50->pipe.set_scissor_state = nv50_set_scissor_state;
+       nv50->pipe.set_viewport_state = nv50_set_viewport_state;
+
+       nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers;
+       nv50->pipe.set_vertex_elements = nv50_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
new file mode 100644 (file)
index 0000000..8f9ee05
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "nv50_context.h"
+#include "nouveau/nouveau_stateobj.h"
+
+static void
+nv50_state_validate_fb(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nouveau_stateobj *so = so_new(128, 18);
+       struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+       unsigned i, w, h, gw = 0;
+
+       for (i = 0; i < fb->num_cbufs; i++) {
+               if (!gw) {
+                       w = fb->cbufs[i]->width;
+                       h = fb->cbufs[i]->height;
+                       gw = 1;
+               } else {
+                       assert(w == fb->cbufs[i]->width);
+                       assert(h == fb->cbufs[i]->height);
+               }
+
+               so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2);
+               so_data  (so, fb->cbufs[i]->width);
+               so_data  (so, fb->cbufs[i]->height);
+
+               so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
+               so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
+               so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
+               switch (fb->cbufs[i]->format) {
+               case PIPE_FORMAT_A8R8G8B8_UNORM:
+                       so_data(so, 0xcf);
+                       break;
+               case PIPE_FORMAT_R5G6B5_UNORM:
+                       so_data(so, 0xe8);
+                       break;
+               default:
+                       {
+                               char fmt[128];
+                               pf_sprint_name(fmt, fb->cbufs[i]->format);
+                               NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
+                       }                   
+                       so_data(so, 0xe6);
+                       break;
+               }
+               so_data(so, 0x00000000);
+               so_data(so, 0x00000000);
+
+               so_method(so, tesla, 0x1224, 1);
+               so_data  (so, 1);
+       }
+
+       if (fb->zsbuf) {
+               if (!gw) {
+                       w = fb->zsbuf->width;
+                       h = fb->zsbuf->height;
+                       gw = 1;
+               } else {
+                       assert(w == fb->zsbuf->width);
+                       assert(h == fb->zsbuf->height);
+               }
+
+               so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
+               so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
+               so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
+                         NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
+               switch (fb->zsbuf->format) {
+               case PIPE_FORMAT_Z24S8_UNORM:
+                       so_data(so, 0x16);
+                       break;
+               case PIPE_FORMAT_Z16_UNORM:
+                       so_data(so, 0x15);
+                       break;
+               default:
+                       {
+                               char fmt[128];
+                               pf_sprint_name(fmt, fb->zsbuf->format);
+                               NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
+                       }                   
+                       so_data(so, 0x16);
+                       break;
+               }
+               so_data(so, 0x00000000);
+               so_data(so, 0x00000000);
+
+               so_method(so, tesla, 0x1538, 1);
+               so_data  (so, 1);
+               so_method(so, tesla, 0x1228, 3);
+               so_data  (so, fb->zsbuf->width);
+               so_data  (so, fb->zsbuf->height);
+               so_data  (so, 0x00010001);
+       }
+
+       so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2);
+       so_data  (so, w << 16);
+       so_data  (so, h << 16);
+       so_method(so, tesla, 0x0e04, 2);
+       so_data  (so, w << 16);
+       so_data  (so, h << 16);
+       so_method(so, tesla, 0xdf8, 2);
+       so_data  (so, 0);
+       so_data  (so, h);
+
+       so_ref(so, &nv50->state.fb);
+}
+
+static void
+nv50_state_emit(struct nv50_context *nv50)
+{
+       struct nv50_screen *screen = nv50->screen;
+       struct nouveau_winsys *nvws = screen->nvws;
+
+       if (nv50->pctx_id != screen->cur_pctx) {
+               nv50->state.dirty |= 0xffffffff;
+               screen->cur_pctx = nv50->pctx_id;
+       }
+
+       if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER)
+               so_emit(nvws, nv50->state.fb);
+       if (nv50->state.dirty & NV50_NEW_BLEND)
+               so_emit(nvws, nv50->state.blend);
+       if (nv50->state.dirty & NV50_NEW_ZSA)
+               so_emit(nvws, nv50->state.zsa);
+       if (nv50->state.dirty & NV50_NEW_VERTPROG)
+               so_emit(nvws, nv50->state.vertprog);
+       if (nv50->state.dirty & NV50_NEW_FRAGPROG)
+               so_emit(nvws, nv50->state.fragprog);
+       if (nv50->state.dirty & NV50_NEW_RASTERIZER)
+               so_emit(nvws, nv50->state.rast);
+       if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
+               so_emit(nvws, nv50->state.blend_colour);
+       if (nv50->state.dirty & NV50_NEW_STIPPLE)
+               so_emit(nvws, nv50->state.stipple);
+       if (nv50->state.dirty & NV50_NEW_SCISSOR)
+               so_emit(nvws, nv50->state.scissor);
+       if (nv50->state.dirty & NV50_NEW_VIEWPORT)
+               so_emit(nvws, nv50->state.viewport);
+       if (nv50->state.dirty & NV50_NEW_SAMPLER)
+               so_emit(nvws, nv50->state.tsc_upload);
+       if (nv50->state.dirty & NV50_NEW_TEXTURE)
+               so_emit(nvws, nv50->state.tic_upload);
+       if (nv50->state.dirty & NV50_NEW_ARRAYS) {
+               so_emit(nvws, nv50->state.vtxfmt);
+               so_emit(nvws, nv50->state.vtxbuf);
+       }
+       nv50->state.dirty = 0;
+
+       so_emit_reloc_markers(nvws, nv50->state.fb);
+       so_emit_reloc_markers(nvws, nv50->state.vertprog);
+       so_emit_reloc_markers(nvws, nv50->state.fragprog);
+       so_emit_reloc_markers(nvws, nv50->state.vtxbuf);
+       so_emit_reloc_markers(nvws, nv50->screen->static_init);
+}
+
+boolean
+nv50_state_validate(struct nv50_context *nv50)
+{
+       const struct pipe_framebuffer_state *fb = &nv50->framebuffer;
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nouveau_stateobj *so;
+       unsigned i;
+
+       for (i = 0; i < fb->num_cbufs; i++)
+               fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       if (fb->zsbuf)
+               fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       if (nv50->dirty & NV50_NEW_FRAMEBUFFER)
+               nv50_state_validate_fb(nv50);
+
+       if (nv50->dirty & NV50_NEW_BLEND)
+               so_ref(nv50->blend->so, &nv50->state.blend);
+
+       if (nv50->dirty & NV50_NEW_ZSA)
+               so_ref(nv50->zsa->so, &nv50->state.zsa);
+
+       if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB))
+               nv50_vertprog_validate(nv50);
+
+       if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB))
+               nv50_fragprog_validate(nv50);
+
+       if (nv50->dirty & NV50_NEW_RASTERIZER)
+               so_ref(nv50->rasterizer->so, &nv50->state.rast);
+
+       if (nv50->dirty & NV50_NEW_BLEND_COLOUR) {
+               so = so_new(5, 0);
+               so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4);
+               so_data  (so, fui(nv50->blend_colour.color[0]));
+               so_data  (so, fui(nv50->blend_colour.color[1]));
+               so_data  (so, fui(nv50->blend_colour.color[2]));
+               so_data  (so, fui(nv50->blend_colour.color[3]));
+               so_ref(so, &nv50->state.blend_colour);
+       }
+
+       if (nv50->dirty & NV50_NEW_STIPPLE) {
+               so = so_new(33, 0);
+               so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32);
+               for (i = 0; i < 32; i++)
+                       so_data(so, nv50->stipple.stipple[i]);
+               so_ref(so, &nv50->state.stipple);
+       }
+
+       if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) {
+               struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe;
+               struct pipe_scissor_state *s = &nv50->scissor;
+
+               if (nv50->state.scissor &&
+                   (rast->scissor == 0 && nv50->state.scissor_enabled == 0))
+                       goto scissor_uptodate;
+               nv50->state.scissor_enabled = rast->scissor;
+
+               so = so_new(3, 0);
+               so_method(so, tesla, 0x0ff4, 2);
+               if (nv50->state.scissor_enabled) {
+                       so_data(so, ((s->maxx - s->minx) << 16) | s->minx);
+                       so_data(so, ((s->maxy - s->miny) << 16) | s->miny);
+               } else {
+                       so_data(so, (8192 << 16));
+                       so_data(so, (8192 << 16));
+               }
+               so_ref(so, &nv50->state.scissor);
+               nv50->state.dirty |= NV50_NEW_SCISSOR;
+       }
+scissor_uptodate:
+
+       if (nv50->dirty & NV50_NEW_VIEWPORT) {
+               unsigned bypass;
+
+               if (!nv50->rasterizer->pipe.bypass_clipping)
+                       bypass = 0;
+               else
+                       bypass = 1;
+
+               if (nv50->state.viewport &&
+                   (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) &&
+                   nv50->state.viewport_bypass == bypass)
+                       goto viewport_uptodate;
+               nv50->state.viewport_bypass = bypass;
+
+               so = so_new(12, 0);
+               if (!bypass) {
+                       so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3);
+                       so_data  (so, fui(nv50->viewport.translate[0]));
+                       so_data  (so, fui(nv50->viewport.translate[1]));
+                       so_data  (so, fui(nv50->viewport.translate[2]));
+                       so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3);
+                       so_data  (so, fui(nv50->viewport.scale[0]));
+                       so_data  (so, fui(-nv50->viewport.scale[1]));
+                       so_data  (so, fui(nv50->viewport.scale[2]));
+                       so_method(so, tesla, 0x192c, 1);
+                       so_data  (so, 1);
+                       so_method(so, tesla, 0x0f90, 1);
+                       so_data  (so, 0);
+               } else {
+                       so_method(so, tesla, 0x192c, 1);
+                       so_data  (so, 0);
+                       so_method(so, tesla, 0x0f90, 1);
+                       so_data  (so, 1);
+               }
+
+               so_ref(so, &nv50->state.viewport);
+       }
+viewport_uptodate:
+
+       if (nv50->dirty & NV50_NEW_SAMPLER) {
+               int i;
+
+               so = so_new(nv50->sampler_nr * 8 + 3, 0);
+               so_method(so, tesla, 0x0f00, 1);
+               so_data  (so, NV50_CB_TSC);
+               so_method(so, tesla, 0x40000f04, nv50->sampler_nr * 8);
+               for (i = 0; i < nv50->sampler_nr; i++)
+                       so_datap (so, nv50->sampler[i], 8);
+               so_ref(so, &nv50->state.tsc_upload);
+       }
+
+       if (nv50->dirty & NV50_NEW_TEXTURE)
+               nv50_tex_validate(nv50);
+
+       if (nv50->dirty & NV50_NEW_ARRAYS)
+               nv50_vbo_validate(nv50);
+
+       nv50->state.dirty |= nv50->dirty;
+       nv50->dirty = 0;
+       nv50_state_emit(nv50);
+
+       return TRUE;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
new file mode 100644 (file)
index 0000000..a9daeee
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "nv50_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/p_tile.h"
+
+static void
+nv50_surface_copy(struct pipe_context *pipe, boolean flip,
+                 struct pipe_surface *dest, unsigned destx, unsigned desty,
+                 struct pipe_surface *src, unsigned srcx, unsigned srcy,
+                 unsigned width, unsigned height)
+{
+       struct nv50_context *nv50 = (struct nv50_context *)pipe;
+       struct nouveau_winsys *nvws = nv50->screen->nvws;
+
+       if (flip) {
+               desty += height;
+               while (height--) {
+                       nvws->surface_copy(nvws, dest, destx, desty--, src,
+                                          srcx, srcy++, width, 1);
+               }
+       } else {
+               nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+                                  width, height);
+       }
+}
+
+static void
+nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+                 unsigned destx, unsigned desty, unsigned width,
+                 unsigned height, unsigned value)
+{
+       struct nv50_context *nv50 = (struct nv50_context *)pipe;
+       struct nouveau_winsys *nvws = nv50->screen->nvws;
+
+       nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+static void *
+nv50_surface_map(struct pipe_screen *screen, struct pipe_surface *ps,
+                unsigned flags )
+{
+       struct nouveau_winsys *nvws = nv50_screen(screen)->nvws;
+       struct pipe_winsys *ws = screen->winsys;
+       struct nv50_surface *s = nv50_surface(ps);
+       struct nv50_surface m = *s;
+       void *map;
+
+       if (!s->untiled) {
+               s->untiled = ws->buffer_create(ws, 0, 0, ps->buffer->size);
+
+               m.base.buffer = s->untiled;
+               nvws->surface_copy(nvws, &m.base, 0, 0, &s->base, 0, 0,
+                                        ps->width, ps->height);
+       }
+
+       /* Map original tiled surface to disallow it being validated while
+        * untiled mirror is mapped.
+        */
+       ws->buffer_map(ws, ps->buffer, flags);
+
+       map = ws->buffer_map(ws, s->untiled, flags);
+       if (!map)
+               return NULL;
+
+       return map;
+}
+
+static void
+nv50_surface_unmap(struct pipe_screen *screen, struct pipe_surface *ps)
+{
+       struct nouveau_winsys *nvws = nv50_screen(screen)->nvws;
+       struct pipe_winsys *ws = screen->winsys;
+       struct nv50_surface *s = nv50_surface(ps);
+       struct nv50_surface m = *s;
+
+       ws->buffer_unmap(ws, s->untiled);
+       ws->buffer_unmap(ws, ps->buffer);
+
+       m.base.buffer = s->untiled;
+       nvws->surface_copy(nvws, &s->base, 0, 0, &m.base, 0, 0,
+                                ps->width, ps->height);
+
+       pipe_buffer_reference(ws, &s->untiled, NULL);
+}
+
+void
+nv50_init_surface_functions(struct nv50_context *nv50)
+{
+       nv50->pipe.surface_copy = nv50_surface_copy;
+       nv50->pipe.surface_fill = nv50_surface_fill;
+}
+
+void
+nv50_surface_init_screen_functions(struct pipe_screen *pscreen)
+{
+       pscreen->surface_map = nv50_surface_map;
+       pscreen->surface_unmap = nv50_surface_unmap;
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
new file mode 100644 (file)
index 0000000..fde3c97
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "nv50_context.h"
+#include "nv50_texture.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+static int
+nv50_tex_construct(struct nouveau_stateobj *so, struct nv50_miptree *mt)
+{
+       switch (mt->base.format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_8_8_8_8);
+               break;
+       case PIPE_FORMAT_A1R5G5B5_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_1_5_5_5);
+               break;
+       case PIPE_FORMAT_A4R4G4B4_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_4_4_4_4);
+               break;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_5_6_5);
+               break;
+       case PIPE_FORMAT_L8_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_8);
+               break;
+       case PIPE_FORMAT_A8_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_8);
+               break;
+       case PIPE_FORMAT_I8_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_8);
+               break;
+       case PIPE_FORMAT_A8L8_UNORM:
+               so_data(so, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM |
+                           NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
+                           NV50TIC_0_0_MAPG_C0 | NV50TIC_0_0_TYPEG_UNORM |
+                           NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM |
+                           NV50TIC_0_0_FMT_8_8);
+               break;
+       default:
+               return 1;
+       }
+
+       so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
+       so_data (so, 0xd0005000);
+       so_data (so, 0x00300000);
+       so_data (so, mt->base.width[0]);
+       so_data (so, (mt->base.depth[0] << 16) | mt->base.height[0]);
+       so_data (so, 0x03000000);
+       so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
+
+       return 0;
+}
+
+void
+nv50_tex_validate(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nouveau_stateobj *so;
+       int i;
+
+       so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2);
+       so_method(so, tesla, 0x0f00, 1);
+       so_data  (so, NV50_CB_TIC);
+       so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8);
+       for (i = 0; i < nv50->miptree_nr; i++) {
+               if (nv50_tex_construct(so, nv50->miptree[i])) {
+                       NOUVEAU_ERR("failed tex validate\n");
+                       so_ref(NULL, &so);
+                       return;
+               }
+       }
+
+       so_ref(so, &nv50->state.tic_upload);
+}
+
diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h
new file mode 100644 (file)
index 0000000..6861d67
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef __NV50_TEXTURE_H__
+#define __NV50_TEXTURE_H__
+
+/* It'd be really nice to have these in nouveau_class.h generated by
+ * renouveau like the rest of the object header - but not sure it can
+ * handle non-object stuff nicely - need to look into it.
+ */
+
+/* Texture image control block */
+#define NV50TIC_0_0_MAPA_MASK                                     0x38000000
+#define NV50TIC_0_0_MAPA_ZERO                                     0x00000000
+#define NV50TIC_0_0_MAPA_C0                                       0x10000000
+#define NV50TIC_0_0_MAPA_C1                                       0x18000000
+#define NV50TIC_0_0_MAPA_C2                                       0x20000000
+#define NV50TIC_0_0_MAPA_C3                                       0x28000000
+#define NV50TIC_0_0_MAPA_ONE                                      0x38000000
+#define NV50TIC_0_0_MAPR_MASK                                     0x07000000
+#define NV50TIC_0_0_MAPR_ZERO                                     0x00000000
+#define NV50TIC_0_0_MAPR_C0                                       0x02000000
+#define NV50TIC_0_0_MAPR_C1                                       0x03000000
+#define NV50TIC_0_0_MAPR_C2                                       0x04000000
+#define NV50TIC_0_0_MAPR_C3                                       0x05000000
+#define NV50TIC_0_0_MAPR_ONE                                      0x07000000
+#define NV50TIC_0_0_MAPG_MASK                                     0x00e00000
+#define NV50TIC_0_0_MAPG_ZERO                                     0x00000000
+#define NV50TIC_0_0_MAPG_C0                                       0x00400000
+#define NV50TIC_0_0_MAPG_C1                                       0x00600000
+#define NV50TIC_0_0_MAPG_C2                                       0x00800000
+#define NV50TIC_0_0_MAPG_C3                                       0x00a00000
+#define NV50TIC_0_0_MAPG_ONE                                      0x00e00000
+#define NV50TIC_0_0_MAPB_MASK                                     0x001c0000
+#define NV50TIC_0_0_MAPB_ZERO                                     0x00000000
+#define NV50TIC_0_0_MAPB_C0                                       0x00080000
+#define NV50TIC_0_0_MAPB_C1                                       0x000c0000
+#define NV50TIC_0_0_MAPB_C2                                       0x00100000
+#define NV50TIC_0_0_MAPB_C3                                       0x00140000
+#define NV50TIC_0_0_MAPB_ONE                                      0x001c0000
+#define NV50TIC_0_0_TYPEA_MASK                                    0x00038000
+#define NV50TIC_0_0_TYPEA_UNORM                                   0x00010000
+#define NV50TIC_0_0_TYPER_MASK                                    0x00007000
+#define NV50TIC_0_0_TYPER_UNORM                                   0x00002000
+#define NV50TIC_0_0_TYPEG_MASK                                    0x00000e00
+#define NV50TIC_0_0_TYPEG_UNORM                                   0x00000400
+#define NV50TIC_0_0_TYPEB_MASK                                    0x000001c0
+#define NV50TIC_0_0_TYPEB_UNORM                                   0x00000080
+#define NV50TIC_0_0_FMT_MASK                                      0x0000003c
+#define NV50TIC_0_0_FMT_8_8_8_8                                   0x00000008
+#define NV50TIC_0_0_FMT_4_4_4_4                                   0x00000012
+#define NV50TIC_0_0_FMT_1_5_5_5                                   0x00000013
+#define NV50TIC_0_0_FMT_5_6_5                                     0x00000015
+#define NV50TIC_0_0_FMT_8_8                                       0x00000018
+#define NV50TIC_0_0_FMT_8                                         0x0000001d
+
+#define NV50TIC_0_1_OFFSET_LOW_MASK                               0xffffffff
+#define NV50TIC_0_1_OFFSET_LOW_SHIFT                                       0
+
+#define NV50TIC_0_2_UNKNOWN_MASK                                  0xffffffff
+
+#define NV50TIC_0_3_UNKNOWN_MASK                                  0xffffffff
+
+#define NV50TIC_0_4_WIDTH_MASK                                    0x0000ffff
+#define NV50TIC_0_4_WIDTH_SHIFT                                            0
+
+#define NV50TIC_0_5_DEPTH_MASK                                    0xffff0000
+#define NV50TIC_0_5_DEPTH_SHIFT                                           16
+#define NV50TIC_0_5_HEIGHT_MASK                                   0x0000ffff
+#define NV50TIC_0_5_HEIGHT_SHIFT                                           0
+
+#define NV50TIC_0_6_UNKNOWN_MASK                                  0xffffffff
+
+#define NV50TIC_0_7_OFFSET_HIGH_MASK                              0xffffffff
+#define NV50TIC_0_7_OFFSET_HIGH_SHIFT                                      0
+
+/* Texture sampler control block */
+#define NV50TSC_1_0_WRAPS_MASK                                   0x00000007
+#define NV50TSC_1_0_WRAPS_REPEAT                                 0x00000000
+#define NV50TSC_1_0_WRAPS_MIRROR_REPEAT                          0x00000001
+#define NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE                          0x00000002
+#define NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER                        0x00000003
+#define NV50TSC_1_0_WRAPS_CLAMP                                  0x00000004
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE                   0x00000005
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER                 0x00000006
+#define NV50TSC_1_0_WRAPS_MIRROR_CLAMP                           0x00000007
+#define NV50TSC_1_0_WRAPT_MASK                                   0x00000038
+#define NV50TSC_1_0_WRAPT_REPEAT                                 0x00000000
+#define NV50TSC_1_0_WRAPT_MIRROR_REPEAT                          0x00000008
+#define NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE                          0x00000010
+#define NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER                        0x00000018
+#define NV50TSC_1_0_WRAPT_CLAMP                                  0x00000020
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_EDGE                   0x00000028
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP_TO_BORDER                 0x00000030
+#define NV50TSC_1_0_WRAPT_MIRROR_CLAMP                           0x00000038
+#define NV50TSC_1_0_WRAPR_MASK                                   0x000001c0
+#define NV50TSC_1_0_WRAPR_REPEAT                                 0x00000000
+#define NV50TSC_1_0_WRAPR_MIRROR_REPEAT                          0x00000040
+#define NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE                          0x00000080
+#define NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER                        0x000000c0
+#define NV50TSC_1_0_WRAPR_CLAMP                                  0x00000100
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_EDGE                   0x00000140
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_BORDER                 0x00000180
+#define NV50TSC_1_0_WRAPR_MIRROR_CLAMP                           0x000001c0
+
+#define NV50TSC_1_1_MAGF_MASK                                    0x00000003
+#define NV50TSC_1_1_MAGF_NEAREST                                 0x00000001
+#define NV50TSC_1_1_MAGF_LINEAR                                  0x00000002
+#define NV50TSC_1_1_MINF_MASK                                    0x00000030
+#define NV50TSC_1_1_MINF_NEAREST                                 0x00000010
+#define NV50TSC_1_1_MINF_LINEAR                                  0x00000020
+#define NV50TSC_1_1_MIPF_MASK                                    0x000000c0
+#define NV50TSC_1_1_MIPF_NONE                                    0x00000040
+#define NV50TSC_1_1_MIPF_NEAREST                                 0x00000080
+#define NV50TSC_1_1_MIPF_LINEAR                                  0x000000c0
+
+#define NV50TSC_1_2_UNKNOWN_MASK                                 0xffffffff
+
+#define NV50TSC_1_3_UNKNOWN_MASK                                 0xffffffff
+
+#define NV50TSC_1_4_UNKNOWN_MASK                                 0xffffffff
+
+#define NV50TSC_1_5_UNKNOWN_MASK                                 0xffffffff
+
+#define NV50TSC_1_6_UNKNOWN_MASK                                 0xffffffff
+
+#define NV50TSC_1_7_UNKNOWN_MASK                                 0xffffffff
+
+#endif
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
new file mode 100644 (file)
index 0000000..8e420ad
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+
+#include "nv50_context.h"
+
+static INLINE unsigned
+nv50_prim(unsigned mode)
+{
+       switch (mode) {
+       case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS;
+       case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES;
+       case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP;
+       case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP;
+       case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES;
+       case PIPE_PRIM_TRIANGLE_STRIP:
+               return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP;
+       case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN;
+       case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
+       case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
+       case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
+       default:
+               break;
+       }
+
+       NOUVEAU_ERR("invalid primitive type %d\n", mode);
+       return NV50TCL_VERTEX_BEGIN_POINTS;
+}
+
+boolean
+nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
+                unsigned count)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50_state_validate(nv50);
+
+       BEGIN_RING(tesla, 0x142c, 1);
+       OUT_RING  (0);
+       BEGIN_RING(tesla, 0x142c, 1);
+       OUT_RING  (0);
+
+       BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1);
+       OUT_RING  (nv50_prim(mode));
+       BEGIN_RING(tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2);
+       OUT_RING  (start);
+       OUT_RING  (count);
+       BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1);
+       OUT_RING  (0);
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+static INLINE void
+nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map,
+                             unsigned start, unsigned count)
+{
+       map += start;
+
+       if (count & 1) {
+               BEGIN_RING(tesla, 0x15e8, 1);
+               OUT_RING  (map[0]);
+               map++;
+               count--;
+       }
+
+       while (count) {
+               unsigned nr = count > 2046 ? 2046 : count;
+               int i;
+
+               BEGIN_RING(tesla, 0x400015f0, nr >> 1);
+               for (i = 0; i < nr; i += 2)
+                       OUT_RING  ((map[1] << 16) | map[0]);
+
+               count -= nr;
+               map += nr;
+       }
+}
+
+static INLINE void
+nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map,
+                             unsigned start, unsigned count)
+{
+       map += start;
+
+       if (count & 1) {
+               BEGIN_RING(tesla, 0x15e8, 1);
+               OUT_RING  (map[0]);
+               map++;
+               count--;
+       }
+
+       while (count) {
+               unsigned nr = count > 2046 ? 2046 : count;
+               int i;
+
+               BEGIN_RING(tesla, 0x400015f0, nr >> 1);
+               for (i = 0; i < nr; i += 2)
+                       OUT_RING  ((map[1] << 16) | map[0]);
+
+               count -= nr;
+               map += nr;
+       }
+}
+
+static INLINE void
+nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint8_t *map,
+                             unsigned start, unsigned count)
+{
+       map += start;
+
+       while (count) {
+               unsigned nr = count > 2047 ? 2047 : count;
+
+               BEGIN_RING(tesla, 0x400015e8, nr);
+               OUT_RINGp (map, nr);
+
+               count -= nr;
+               map += nr;
+       }
+}
+
+boolean
+nv50_draw_elements(struct pipe_context *pipe,
+                  struct pipe_buffer *indexBuffer, unsigned indexSize,
+                  unsigned mode, unsigned start, unsigned count)
+{
+       struct nv50_context *nv50 = nv50_context(pipe);
+       struct pipe_winsys *ws = pipe->winsys;
+       void *map = ws->buffer_map(ws, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
+
+       nv50_state_validate(nv50);
+
+       BEGIN_RING(tesla, 0x142c, 1);
+       OUT_RING  (0);
+       BEGIN_RING(tesla, 0x142c, 1);
+       OUT_RING  (0);
+
+       BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1);
+       OUT_RING  (nv50_prim(mode));
+       switch (indexSize) {
+       case 1:
+               nv50_draw_elements_inline_u08(nv50, map, start, count);
+               break;
+       case 2:
+               nv50_draw_elements_inline_u16(nv50, map, start, count);
+               break;
+       case 4:
+               nv50_draw_elements_inline_u32(nv50, map, start, count);
+               break;
+       default:
+               assert(0);
+       }
+       BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1);
+       OUT_RING  (0);
+
+       pipe->flush(pipe, 0, NULL);
+       return TRUE;
+}
+
+void
+nv50_vbo_validate(struct nv50_context *nv50)
+{
+       struct nouveau_grobj *tesla = nv50->screen->tesla;
+       struct nouveau_stateobj *vtxbuf, *vtxfmt;
+       int i, vpi = 0;
+
+       vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2);
+       vtxfmt = so_new(nv50->vtxelt_nr + 1, 0);
+       so_method(vtxfmt, tesla, 0x1ac0, nv50->vtxelt_nr);
+
+       for (i = 0; i < nv50->vtxelt_nr; i++) {
+               struct pipe_vertex_element *ve = &nv50->vtxelt[i];
+               struct pipe_vertex_buffer *vb =
+                       &nv50->vtxbuf[ve->vertex_buffer_index];
+
+               switch (ve->src_format) {
+               case PIPE_FORMAT_R32G32B32A32_FLOAT:
+                       so_data(vtxfmt, 0x7e080000 | i);
+                       break;
+               case PIPE_FORMAT_R32G32B32_FLOAT:
+                       so_data(vtxfmt, 0x7e100000 | i);
+                       break;
+               case PIPE_FORMAT_R32G32_FLOAT:
+                       so_data(vtxfmt, 0x7e200000 | i);
+                       break;
+               case PIPE_FORMAT_R32_FLOAT:
+                       so_data(vtxfmt, 0x7e900000 | i);
+                       break;
+               case PIPE_FORMAT_R8G8B8A8_UNORM:
+                       so_data(vtxfmt, 0x24500000 | i);
+                       break;
+               default:
+               {
+                       char fmt[128];
+                       pf_sprint_name(fmt, ve->src_format);
+                       NOUVEAU_ERR("invalid vbo format %s\n", fmt);
+                       assert(0);
+                       return;
+               }
+               }
+
+               so_method(vtxbuf, tesla, 0x900 + (i * 16), 3);
+               so_data  (vtxbuf, 0x20000000 | vb->pitch);
+               so_reloc (vtxbuf, vb->buffer, vb->buffer_offset +
+                         ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+                         NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+               so_reloc (vtxbuf, vb->buffer, vb->buffer_offset +
+                         ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
+                         NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+       }
+
+       so_ref (vtxfmt, &nv50->state.vtxfmt);
+       so_ref (vtxbuf, &nv50->state.vtxbuf);
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile
new file mode 100644 (file)
index 0000000..50e3c84
--- /dev/null
@@ -0,0 +1,18 @@
+TARGET         = libg3dvl.a
+OBJECTS                = vl_context.o vl_data.o vl_surface.o vl_shader_build.o vl_util.o
+GALLIUMDIR     = ../..
+
+CFLAGS         += -g -Wall -fPIC -Werror -I${GALLIUMDIR}/include -I${GALLIUMDIR}/auxiliary
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+       ar rcs $@ $^
+
+clean:
+       rm -rf ${OBJECTS} ${TARGET}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/.gitignore b/src/gallium/state_trackers/g3dvl/tests/.gitignore
new file mode 100644 (file)
index 0000000..9b1ec4e
--- /dev/null
@@ -0,0 +1,6 @@
+test_context
+test_surface
+test_i_rendering
+test_p_rendering
+test_pf_rendering
+test_b_rendering
diff --git a/src/gallium/state_trackers/g3dvl/tests/Makefile b/src/gallium/state_trackers/g3dvl/tests/Makefile
new file mode 100644 (file)
index 0000000..45cefa2
--- /dev/null
@@ -0,0 +1,45 @@
+GALLIUMDIR     = ../../..
+
+CFLAGS += -g -Wall -Werror                             \
+          -I${GALLIUMDIR}/state_trackers/g3dvl         \
+          -I${GALLIUMDIR}/winsys/g3dvl                 \
+          -I${GALLIUMDIR}/include                      \
+          -I${GALLIUMDIR}/auxiliary                    \
+          -I${GALLIUMDIR}/drivers
+LDFLAGS        += -L${GALLIUMDIR}/state_trackers/g3dvl         \
+          -L${GALLIUMDIR}/drivers/softpipe             \
+          -L${GALLIUMDIR}/auxiliary/tgsi               \
+          -L${GALLIUMDIR}/auxiliary/draw               \
+          -L${GALLIUMDIR}/auxiliary/util               \
+          -L${GALLIUMDIR}/auxiliary/translate          \
+          -L${GALLIUMDIR}/auxiliary/cso_cache          \
+          -L${GALLIUMDIR}/auxiliary/rtasm
+LIBS   += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lX11 -lm
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_i_rendering test_p_rendering test_pf_rendering test_b_rendering
+
+test_context: test_context.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_surface: test_surface.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_i_rendering: test_i_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_p_rendering: test_p_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_pf_rendering: test_pf_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_b_rendering: test_b_rendering.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf *.o test_context test_surface test_i_rendering test_p_rendering test_pf_rendering test_b_rendering
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_b_rendering.c
new file mode 100644 (file)
index 0000000..b78cc85
--- /dev/null
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+static const signed short ycbcr16x16_420_2[8*8*6] =
+{
+       -0x00A5,-0x00A5,-0x00A5,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x00A5,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5,
+       -0x0072,-0x0072,-0x0072,-0x0072,-0x00A5,-0x00A5,-0x00A5,-0x00A5,
+       
+       -0x004F,-0x004F,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x004F,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F,
+       -0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x00B2,-0x004F,-0x004F,
+       
+       -0x003E,-0x003E,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x003E,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E,
+       -0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x0060,-0x003E,-0x003E
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc, *past_sfc, *future_sfc;
+       struct VL_MOTION_VECTOR motion_vector[2] =
+       {
+               {
+                       {0, 0}, {0, 0}
+               },
+               {
+                       {0, 0}, {0, 0}
+               }
+       };
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlCreateSurface(ctx, &past_sfc);
+       vlCreateSurface(ctx, &future_sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, past_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, future_sfc);
+       vlRenderBMacroBlock
+       (
+               VL_FRAME_PICTURE,
+               VL_FIELD_FIRST,
+               0,
+               0,
+               VL_FRAME_MC,
+               motion_vector,
+               0x3F,
+               VL_DCT_FRAME_CODED,
+               (short*)ycbcr16x16_420_2,
+               past_sfc,
+               future_sfc,
+               sfc
+       );
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroySurface(past_sfc);
+       vlDestroySurface(future_sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_context.c b/src/gallium/state_trackers/g3dvl/tests/test_context.c
new file mode 100644 (file)
index 0000000..2002977
--- /dev/null
@@ -0,0 +1,22 @@
+#include <vl_context.h>
+#include <xsp_winsys.h>
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       
+       Display                 *display;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       
+       display = XOpenDisplay(NULL);
+       pipe = create_pipe_context(display);
+       
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlDestroyContext(ctx);
+       
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_i_rendering.c
new file mode 100644 (file)
index 0000000..1f96471
--- /dev/null
@@ -0,0 +1,137 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc;
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, sfc);
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_p_rendering.c
new file mode 100644 (file)
index 0000000..2203349
--- /dev/null
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+static const signed short ycbcr16x16_420_2[8*8*6] =
+{
+       -51,-51,-51,  0,-51,  0,  0,  0,
+         0,-51,  0,  0,-51,  0,  0,  0,
+         0,-51,  0,  0,-51,-51,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+       
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+        99, 99, 99,  0,  0,  0,  0,  0,
+         0,  0, 99,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+        33, 33, 33,  0,  0,  0,  0,  0,
+         0,  0, 33,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc, *ref_sfc;
+       struct VL_MOTION_VECTOR motion_vector =
+       {
+               {0, 0}, {0, 0}
+       };
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlCreateSurface(ctx, &ref_sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderPMacroBlock
+       (
+               VL_FRAME_PICTURE,
+               VL_FIELD_FIRST,
+               0,
+               0,
+               VL_FRAME_MC,
+               &motion_vector,
+               0x3F,
+               VL_DCT_FRAME_CODED,
+               (short*)ycbcr16x16_420_2,
+               ref_sfc,
+               sfc
+       );
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroySurface(ref_sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c b/src/gallium/state_trackers/g3dvl/tests/test_pf_rendering.c
new file mode 100644 (file)
index 0000000..43586fc
--- /dev/null
@@ -0,0 +1,214 @@
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+static const unsigned short ycbcr16x16_420[8*8*6] =
+{
+       0x00A5,0x00A5,0x00A5,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x0072,0x0072,0x0072,
+       0x0072,0x00A5,0x0072,0x0072,0x00A5,0x00A5,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,
+       0x0072,0x0072,0x0072,0x0072,0x00A5,0x00A5,0x00A5,0x00A5,
+       
+       0x004F,0x004F,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x004F,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,
+       0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x00B2,0x004F,0x004F,
+       
+       0x003E,0x003E,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x003E,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,
+       0x0060,0x0060,0x0060,0x0060,0x0060,0x0060,0x003E,0x003E
+};
+
+static const signed short ycbcr16x16_420_2[8*8*6] =
+{
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+       
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0
+};
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       const unsigned int      window_width = video_width * 2, window_height = video_height * 2;
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc, *ref_sfc;
+       struct VL_MOTION_VECTOR motion_vector =
+       {
+               {0, 0}, {32, 32}
+       };
+       
+       display = XOpenDisplay(NULL);
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, window_width, window_height, 0, 0, 0);
+       framebuffer = XCreatePixmap(display, root, window_width, window_height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       pipe = create_pipe_context(display);
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlCreateSurface(ctx, &ref_sfc);
+       
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 0, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 0, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderIMacroBlock(VL_FRAME_PICTURE, VL_FIELD_FIRST, 1, 1, 0x3F, VL_DCT_FRAME_CODED, (short*)ycbcr16x16_420, ref_sfc);
+       vlRenderPMacroBlock
+       (
+               VL_FRAME_PICTURE,
+               VL_FIELD_FIRST,
+               0,
+               0,
+               VL_FIELD_MC,
+               &motion_vector,
+               0x3F,
+               VL_DCT_FRAME_CODED,
+               (short*)ycbcr16x16_420_2,
+               ref_sfc,
+               sfc
+       );
+       vlPutSurface(sfc, framebuffer, 0, 0, video_width, video_height, 0, 0, window_width, window_height, VL_FRAME_PICTURE);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       window_width,
+                                       window_height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       vlDestroySurface(sfc);
+       vlDestroySurface(ref_sfc);
+       vlDestroyContext(ctx);
+       
+       XFreePixmap(display, framebuffer);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/tests/test_surface.c b/src/gallium/state_trackers/g3dvl/tests/test_surface.c
new file mode 100644 (file)
index 0000000..4d19463
--- /dev/null
@@ -0,0 +1,26 @@
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <xsp_winsys.h>
+
+int main(int argc, char **argv)
+{
+       const unsigned int      video_width = 32, video_height = 32;
+       
+       Display                 *display;
+       struct pipe_context     *pipe;
+       struct VL_CONTEXT       *ctx;
+       struct VL_SURFACE       *sfc;
+       
+       display = XOpenDisplay(NULL);
+       pipe = create_pipe_context(display);
+       
+       vlCreateContext(display, pipe, video_width, video_height, VL_FORMAT_YCBCR_420, &ctx);
+       vlCreateSurface(ctx, &sfc);
+       vlDestroySurface(sfc);
+       vlDestroyContext(ctx);
+       
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c
new file mode 100644 (file)
index 0000000..1668ad1
--- /dev/null
@@ -0,0 +1,2258 @@
+#include "vl_context.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <pipe/p_shader_tokens.h>
+#include <tgsi/util/tgsi_parse.h>
+#include <tgsi/util/tgsi_build.h>
+#include "vl_shader_build.h"
+#include "vl_data.h"
+#include "vl_defs.h"
+#include "vl_util.h"
+
+static int vlCreateVertexShaderFrameIDCT(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+       
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Vertex texcoords
+        */
+       for (i = 0; i < 2; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Vertex texcoords
+        */
+       for (i = 0; i < 2; i++)
+       {
+               decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * mov o0, i0           ; Move pos in to pos out
+        * mov o1, i1           ; Move texcoord in to texcoord out */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       //context->states.idct.frame_vs = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderFrameIDCT(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /* decl i0              ; Texcoords for s0 */
+       decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0              ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /* decl s0              ; Sampler for tex containing picture to display */
+       decl = vl_decl_samplers(0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /* tex2d t0, i0, s0     ; Read src pixel */
+       inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c0       ; Subtract bias vector from pixel */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * dp4 o0.x, t0, c1     ; Multiply pixel by the color conversion matrix
+        * dp4 o0.y, t0, c2
+        * dp4 o0.z, t0, c3
+        * dp4 o0.w, t0, c4     ; XXX: Don't need 4th coefficient
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       //context->states.idct.frame_fs = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlInitIDCT(struct VL_CONTEXT *context)
+{
+       struct pipe_context             *pipe;
+       struct pipe_sampler_state       sampler;
+       struct pipe_texture             template;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       context->states.idct.viewport.scale[0] = VL_BLOCK_WIDTH;
+       context->states.idct.viewport.scale[1] = VL_BLOCK_HEIGHT;
+       context->states.idct.viewport.scale[2] = 1;
+       context->states.idct.viewport.scale[3] = 1;
+       context->states.idct.viewport.translate[0] = 0;
+       context->states.idct.viewport.translate[1] = 0;
+       context->states.idct.viewport.translate[2] = 0;
+       context->states.idct.viewport.translate[3] = 0;
+       
+       context->states.idct.render_target.width = VL_BLOCK_WIDTH;
+       context->states.idct.render_target.height = VL_BLOCK_HEIGHT;
+       context->states.idct.render_target.num_cbufs = 1;
+       context->states.idct.render_target.zsbuf = NULL;
+       
+       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+       sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+       sampler.compare_func = PIPE_FUNC_ALWAYS;
+       sampler.normalized_coords = 1;
+       /*sampler.prefilter = ;*/
+       /*sampler.shadow_ambient = ;*/
+       /*sampler.lod_bias = ;*/
+       sampler.min_lod = 0;
+       /*sampler.max_lod = ;*/
+       /*sampler.border_color[i] = ;*/
+       /*sampler.max_anisotropy = ;*/
+       context->states.idct.sampler = pipe->create_sampler_state(pipe, &sampler);
+       
+       memset(&template, 0, sizeof(struct pipe_texture));
+       template.target = PIPE_TEXTURE_2D;
+       template.format = PIPE_FORMAT_A8L8_UNORM;
+       template.last_level = 0;
+       template.width[0] = 8;
+       template.height[0] = 8;
+       template.depth[0] = 1;
+       template.compressed = 0;
+       pf_get_block(template.format, &template.block);
+       
+       context->states.idct.texture = pipe->screen->texture_create(pipe->screen, &template);
+       
+       template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+       template.width[0] = 16;
+       template.height[0] = 1;
+       
+       context->states.idct.basis = pipe->screen->texture_create(pipe->screen, &template);
+       
+       for (i = 0; i < 2; ++i)
+       {
+               context->states.idct.vertex_bufs[i] = &context->states.csc.vertex_bufs[i];
+               context->states.idct.vertex_buf_elems[i] = &context->states.csc.vertex_buf_elems[i];
+               /*
+               context->states.idct.vertex_bufs[i].pitch = sizeof(struct VL_VERTEX2F);
+               context->states.idct.vertex_bufs[i].max_index = 3;
+               context->states.idct.vertex_bufs[i].buffer_offset = 0;
+               context->states.idct.vertex_bufs[i].buffer = pipe->winsys->buffer_create
+               (
+                       pipe->winsys,
+                       1,
+                       PIPE_BUFFER_USAGE_VERTEX,
+                       sizeof(struct VL_VERTEX2F) * 4
+               );
+       
+               context->states.idct.vertex_buf_elems[i].src_offset = 0;
+               context->states.idct.vertex_buf_elems[i].vertex_buffer_index = i;
+               context->states.idct.vertex_buf_elems[i].nr_components = 2;
+               context->states.idct.vertex_buf_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT;
+               */
+       }
+       
+       vlCreateVertexShaderFrameIDCT(context);
+       vlCreateFragmentShaderFrameIDCT(context);
+       
+       return 0;
+}
+
+static int vlDestroyIDCT(struct VL_CONTEXT *context)
+{
+       //unsigned int i;
+       
+       assert(context);
+       
+       context->pipe->delete_sampler_state(context->pipe, context->states.idct.sampler);
+       
+       //for (i = 0; i < 2; ++i)
+               //context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.vertex_bufs[i].buffer);
+       
+       pipe_texture_release(&context->states.idct.texture);
+       pipe_texture_release(&context->states.idct.basis);
+       
+       //context->pipe->delete_vs_state(context->pipe, context->states.idct.frame_vs);
+       //context->pipe->delete_fs_state(context->pipe, context->states.idct.frame_fs);
+       
+       //context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.vs_const_buf.buffer);
+       //context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.idct.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderIMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Luma texcoords
+        * decl i2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale unit rect to macroblock size
+        * decl c1              ; Translation vector to move macroblock into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Luma texcoords
+        * decl o2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t0, i0, c0       ; Scale unit rect to normalized MB size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add o0, t0, c1       ; Translate rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * mov o1, i1           ; Move input luma texcoords to output
+        * mov o2, i2           ; Move input chroma texcoords to output
+        */
+       for (i = 1; i < 3; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.mc.i_vs = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderIMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /*
+        * decl i0                      ; Texcoords for s0
+        * decl i1                      ; Texcoords for s1, s2
+        */
+       for (i = 0; i < 2; ++i)
+       {
+               decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* decl o0                      ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl s0                      ; Sampler for luma texture
+        * decl s1                      ; Sampler for chroma Cb texture
+        * decl s2                      ; Sampler for chroma Cr texture
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               decl = vl_decl_samplers(i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header,max_tokens - ti);
+       }
+       
+       /*
+        * tex2d o0.x, i0, s0           ; Read texel from luma texture into .x channel
+        * tex2d o0.y, i1, s1           ; Read texel from chroma Cb texture into .y channel
+        * tex2d o0.z, i1, s2           ; Read texel from chroma Cr texture into .z channel
+       */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_OUTPUT, 0, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.mc.i_fs = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderFramePMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Luma texcoords
+        * decl i2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale unit rect to macroblock size
+        * decl c1              ; Translation vector to move macroblock into position
+        * decl c2              ; Unused
+        * decl c3              ; Translation vector to move ref macroblock texcoords into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Luma texcoords
+        * decl o2              ; Chroma texcoords
+        * decl o3              ; Ref macroblock texcoords
+        */
+       for (i = 0; i < 4; i++)
+       {
+               decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t0, i0, c0       ; Scale unit rect to normalized MB size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add o0, t0, c1       ; Translate rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * mov o1, i1           ; Move input luma texcoords to output
+        * mov o2, i2           ; Move input chroma texcoords to output
+        */
+       for (i = 1; i < 3; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* add o3, t0, c3       ; Translate rect into position on ref macroblock */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.mc.p_vs[0] = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderFieldPMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Luma texcoords
+        * decl i2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration
+               (
+                       &decl,
+                       &tokens[ti],
+                       header,
+                       max_tokens - ti
+               );
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale unit rect to macroblock size
+        * decl c1              ; Translation vector to move macroblock into position
+        * decl c2              ; Denorm coefficients
+        * decl c3              ; Translation vector to move top field ref macroblock texcoords into position
+        * decl c4              ; Translation vector to move bottom field ref macroblock texcoords into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Luma texcoords
+        * decl o2              ; Chroma texcoords
+        * decl o3              ; Top field ref macroblock texcoords
+        * decl o4              ; Bottom field ref macroblock texcoords
+        * decl o5              ; Denormalized vertex pos
+        */
+       for (i = 0; i < 6; i++)
+       {
+               decl = vl_decl_output((i == 0 || i == 5) ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t0, i0, c0       ; Scale unit rect to normalized MB size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add t1, t0, c1       ; Translate rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mov o0, t1           ; Move vertex pos to output */
+       inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+       mov o1, i1              ; Move input luma texcoords to output
+       mov o2, i2              ; Move input chroma texcoords to output
+       */
+       for (i = 1; i < 3; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* add o3, t0, c3       ; Translate top field rect into position on ref macroblock
+          add o4, t0, c4       ; Translate bottom field rect into position on ref macroblock */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul o5, t1, c2       ; Denorm vertex pos */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 5, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.mc.p_vs[1] = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderFramePMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /*
+        * decl i0                      ; Texcoords for s0
+        * decl i1                      ; Texcoords for s1, s2
+        * decl i2                      ; Texcoords for s3
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0                      ; Multiplier to shift 9th bit of differential into place
+        * decl c1                      ; Bias to get differential back to a signed value
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0                      ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl s0                      ; Sampler for luma texture
+        * decl s1                      ; Sampler for chroma Cb texture
+        * decl s2                      ; Sampler for chroma Cr texture
+        * decl s3                      ; Sampler for ref surface texture
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               decl = vl_decl_samplers(i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * tex2d t0.xw, i0, s0          ; Read texel from luma texture into .x and .w channels
+        * mov t1.x, t0.w               ; Move 9th bit from .w channel to .x
+        * tex2d t0.yw, i1, s1          ; Read texel from chroma Cb texture into .y and .w channels
+        * mov t1.y, t0.w               ; Move 9th bit from .w channel to .y
+        * tex2d t0.zw, i1, s2          ; Read texel from chroma Cr texture into .z and .w channels
+        * mov t1.z, t0.w               ; Move 9th bit from .w channel to .z
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+               
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t1, t1, c0               ; Muliply 9th bit by multiplier to shift it into place */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add t0, t0, t1               ; Add luma and chroma low and high parts to get normalized unsigned 9-bit values */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c1               ; Subtract bias to get back signed values */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* tex2d t1, i2, s3             ; Read texel from ref macroblock */
+       inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 2, TGSI_FILE_SAMPLER, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add o0, t0, t1               ; Add ref and differential to form final output */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.mc.p_fs[0] = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderFieldPMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 200;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /*
+        * decl i0                      ; Texcoords for s0
+        * decl i1                      ; Texcoords for s1, s2
+        * decl i2                      ; Texcoords for s3
+        * decl i3                      ; Texcoords for s3
+        * decl i4                      ; Denormalized vertex pos
+        */
+       for (i = 0; i < 5; ++i)
+       {
+               decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0                      ; Multiplier to shift 9th bit of differential into place
+        * decl c1                      ; Bias to get differential back to a signed value
+        * decl c2                      ; Constants 1/2 & 2 in .x, .y channels for Y-mod-2 top/bottom field selection
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 2);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0                      ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl s0                      ; Sampler for luma texture
+        * decl s1                      ; Sampler for chroma Cb texture
+        * decl s2                      ; Sampler for chroma Cr texture
+        * decl s3                      ; Sampler for ref surface texture
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               decl = vl_decl_samplers(i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * tex2d t0.xw, i0, s0          ; Read texel from luma texture into .x and .w channels
+        * mov t1.x, t0.w               ; Move 9th bit from .w channel to .x
+        * tex2d t0.yw, i1, s1          ; Read texel from chroma Cb texture into .y and .w channels
+        * mov t1.y, t0.w               ; Move 9th bit from .w channel to .y
+        * tex2d t0.zw, i1, s2          ; Read texel from chroma Cr texture into .z and .w channels
+        * mov t1.z, t0.w               ; Move 9th bit from .w channel to .z
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+               
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t1, t1, c0               ; Muliply 9th bit by multiplier to shift it into place */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add t0, t0, t1               ; Add luma and chroma low and high parts to get normalized unsigned 9-bit values */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c1               ; Subtract bias to get back signed values */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* tex2d t1, i2, s3             ; Read texel from ref macroblock top field
+          tex2d t2, i3, s3             ; Read texel from ref macroblock bottom field */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* XXX: Pos values off by 0.5? */
+       /* sub t4, i4.y, c2.x           ; Sub 0.5 from denormalized pos */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 4, TGSI_FILE_INPUT, 2);
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mul t3, t4, c2.x             ; Multiply pos Y-coord by 1/2 */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 2);
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* floor t3, t3                 ; Get rid of fractional part */
+       inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mul t3, t3, c2.y             ; Multiply by 2 */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 2);
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t3, t4, t3               ; Subtract from original Y to get Y % 2 */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+       /* lerp t1, t3, t1, t2          ; Choose between top and bottom fields based on Y % 2 */
+       inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add o0, t0, t1               ; Add ref and differential to form final output */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.mc.p_fs[1] = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderFrameBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Luma texcoords
+        * decl i2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale unit rect to macroblock size
+        * decl c1              ; Translation vector to move macroblock into position
+        * decl c2              ; Unused
+        * decl c3              ; Translation vector to move past ref macroblock texcoords into position
+        * decl c4              ; Unused
+        * decl c5              ; Translation vector to move future ref macroblock texcoords into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 5);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Luma texcoords
+        * decl o2              ; Chroma texcoords
+        * decl o3              ; Past ref macroblock texcoords
+        * decl o4              ; Future ref macroblock texcoords
+        */
+       for (i = 0; i < 5; i++)
+       {
+               decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t0, i0, c0       ; Scale unit rect to normalized MB size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add o0, t0, c1       ; Translate rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * mov o1, i1           ; Move input luma texcoords to output
+        * mov o2, i2           ; Move input chroma texcoords to output
+        */
+       for (i = 1; i < 3; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* add o3, t0, c3       ; Translate rect into position on past ref macroblock
+          add o4, t0, c5       ; Translate rect into position on future ref macroblock */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i * 2 + 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.mc.b_vs[0] = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderFieldBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;   
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Luma texcoords
+        * decl i2              ; Chroma texcoords
+        */
+       for (i = 0; i < 3; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale unit rect to macroblock size
+        * decl c1              ; Translation vector to move macroblock into position
+        * decl c2              ; Denorm coefficients
+        * decl c3              ; Translation vector to move top field past ref macroblock texcoords into position
+        * decl c4              ; Translation vector to move bottom field past ref macroblock texcoords into position
+        * decl c5              ; Translation vector to move top field future ref macroblock texcoords into position
+        * decl c6              ; Translation vector to move bottom field future ref macroblock texcoords into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 6);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Luma texcoords
+        * decl o2              ; Chroma texcoords
+        * decl o3              ; Top field past ref macroblock texcoords
+        * decl o4              ; Bottom field past ref macroblock texcoords
+        * decl o5              ; Top field future ref macroblock texcoords
+        * decl o6              ; Bottom field future ref macroblock texcoords
+        * decl o7              ; Denormalized vertex pos
+        */
+       for (i = 0; i < 8; i++)
+       {
+               decl = vl_decl_output((i == 0 || i == 7) ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t0, i0, c0       ; Scale unit rect to normalized MB size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add t1, t0, c1       ; Translate rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mov o0, t1           ; Move vertex pos to output */
+       inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * mov o1, i1           ; Move input luma texcoords to output
+        * mov o2, i2           ; Move input chroma texcoords to output
+        */
+       for (i = 1; i < 3; ++i)
+       {
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /*
+        * add o3, t0, c3       ; Translate top field rect into position on past ref macroblock
+        * add o4, t0, c4       ; Translate bottom field rect into position on past ref macroblock
+        * add o5, t0, c5       ; Translate top field rect into position on future ref macroblock
+        * add o6, t0, c6       ; Translate bottom field rect into position on future ref macroblock
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 3, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul o7, t1, c2       ; Denorm vertex pos */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 7, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.mc.b_vs[1] = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderFrameBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 100;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /*
+        * decl i0                      ; Texcoords for s0
+        * decl i1                      ; Texcoords for s1, s2
+        * decl i2                      ; Texcoords for s3
+        * decl i3                      ; Texcoords for s4
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0                      ; Multiplier to shift 9th bit of differential into place
+        * decl c1                      ; Bias to get differential back to a signed value
+        * decl c2                      ; Constant 1/2 in .x channel to use as weight to blend past and future texels
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 2);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0                      ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl s0                      ; Sampler for luma texture
+        * decl s1                      ; Sampler for chroma Cb texture
+        * decl s2                      ; Sampler for chroma Cr texture
+        * decl s3                      ; Sampler for past ref surface texture
+        * decl s4                      ; Sampler for future ref surface texture
+        */
+       for (i = 0; i < 5; ++i)
+       {
+               decl = vl_decl_samplers(i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * tex2d t0.xw, i0, s0          ; Read texel from luma texture into .x and .w channels
+        * mov t1.x, t0.w               ; Move 9th bit from .w channel to .x
+        * tex2d t0.yw, i1, s1          ; Read texel from chroma Cb texture into .y and .w channels
+        * mov t1.y, t0.w               ; Move 9th bit from .w channel to .y
+        * tex2d t0.zw, i1, s2          ; Read texel from chroma Cr texture into .z and .w channels
+        * mov t1.z, t0.w               ; Move 9th bit from .w channel to .z
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+               
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t1, t1, c0               ; Muliply 9th bit by multiplier to shift it into place */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add t0, t0, t1               ; Add luma and chroma low and high parts to get normalized unsigned 9-bit values */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c1               ; Subtract bias to get back signed values */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * tex2d t1, i2, s3             ; Read texel from past ref macroblock
+        * tex2d t2, i3, s4             ; Read texel from future ref macroblock
+        */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, i + 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* lerp t1, c2.x, t1, t2        ; Blend past and future texels */
+       inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add o0, t0, t1               ; Add past/future ref and differential to form final output */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.mc.b_fs[0] = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderFieldBMC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 200;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /*
+        * decl i0                      ; Texcoords for s0
+        * decl i1                      ; Texcoords for s1, s2
+        * decl i2                      ; Texcoords for s3
+        * decl i3                      ; Texcoords for s3
+        * decl i4                      ; Texcoords for s4
+        * decl i5                      ; Texcoords for s4
+        * decl i6                      ; Denormalized vertex pos
+        */
+       for (i = 0; i < 7; ++i)
+       {
+               decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0                      ; Multiplier to shift 9th bit of differential into place
+        * decl c1                      ; Bias to get differential back to a signed value
+        * decl c2                      ; Constants 1/2 & 2 in .x, .y channels to use as weight to blend past and future texels
+        *                              ; and for Y-mod-2 top/bottom field selection
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 2);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0                      ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl s0                      ; Sampler for luma texture
+        * decl s1                      ; Sampler for chroma Cb texture
+        * decl s2                      ; Sampler for chroma Cr texture
+        * decl s3                      ; Sampler for past ref surface texture
+        * decl s4                      ; Sampler for future ref surface texture
+        */
+       for (i = 0; i < 5; ++i)
+       {
+               decl = vl_decl_samplers(i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * tex2d t0.xw, i0, s0          ; Read texel from luma texture into .x and .w channels
+        * mov t1.x, t0.w               ; Move 9th bit from .w channel to .x
+        * tex2d t0.yw, i1, s1          ; Read texel from chroma Cb texture into .y and .w channels
+        * mov t1.y, t0.w               ; Move 9th bit from .w channel to .y
+        * tex2d t0.zw, i1, s2          ; Read texel from chroma Cr texture into .z and .w channels
+        * mov t1.z, t0.w               ; Move 9th bit from .w channel to .z
+        */
+       for (i = 0; i < 3; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = (TGSI_WRITEMASK_X << i) | TGSI_WRITEMASK_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+               
+               inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 0);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
+               inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mul t1, t1, c0               ; Muliply 9th bit by multiplier to shift it into place */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add t0, t0, t1               ; Add luma and chroma low and high parts to get normalized unsigned 9-bit values */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c1               ; Subtract bias to get back signed values */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* XXX: Pos values off by 0.5? */
+       /* sub t4, i6.y, c2.x           ; Sub 0.5 from denormalized pos */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 6, TGSI_FILE_CONSTANT, 2);
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mul t3, t4, c2.x             ; Multiply pos Y-coord by 1/2 */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 2);
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* floor t3, t3                 ; Get rid of fractional part */
+       inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mul t3, t3, c2.y             ; Multiply by 2 */
+       inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 2);
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
+       inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t3, t4, t3               ; Subtract from original Y to get Y % 2 */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * tex2d t1, i2, s3             ; Read texel from past ref macroblock top field
+        * tex2d t2, i3, s3             ; Read texel from past ref macroblock bottom field
+        */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 2, TGSI_FILE_SAMPLER, 3);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+       /* lerp t1, t3, t1, t2          ; Choose between top and bottom fields based on Y % 2 */
+       inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * tex2d t4, i4, s4             ; Read texel from future ref macroblock top field
+        * tex2d t5, i5, s4             ; Read texel from future ref macroblock bottom field
+        */
+       for (i = 0; i < 2; ++i)
+       {
+               inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 4, TGSI_FILE_INPUT, i + 4, TGSI_FILE_SAMPLER, 4);
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* TODO: Move to conditional tex fetch on t3 instead of lerp */
+       /* lerp t2, t3, t4, t5          ; Choose between top and bottom fields based on Y % 2 */
+       inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* lerp t1, c2.x, t1, t2        ; Blend past and future texels */
+       inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 2, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
+       inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* add o0, t0, t1               ; Add past/future ref and differential to form final output */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.mc.b_fs[1] = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+int vlCreateDataBufsMC(struct VL_CONTEXT *context)
+{
+       struct pipe_context     *pipe;
+       unsigned int            i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Create our vertex buffer and vertex buffer element */
+       context->states.mc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F);
+       context->states.mc.vertex_bufs[0].max_index = 23;
+       context->states.mc.vertex_bufs[0].buffer_offset = 0;
+       context->states.mc.vertex_bufs[0].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_VERTEX2F) * 24
+       );
+       
+       context->states.mc.vertex_buf_elems[0].src_offset = 0;
+       context->states.mc.vertex_buf_elems[0].vertex_buffer_index = 0;
+       context->states.mc.vertex_buf_elems[0].nr_components = 2;
+       context->states.mc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /* Create our texcoord buffers and texcoord buffer elements */
+       for (i = 1; i < 3; ++i)
+       {
+               context->states.mc.vertex_bufs[i].pitch = sizeof(struct VL_TEXCOORD2F);
+               context->states.mc.vertex_bufs[i].max_index = 23;
+               context->states.mc.vertex_bufs[i].buffer_offset = 0;
+               context->states.mc.vertex_bufs[i].buffer = pipe->winsys->buffer_create
+               (
+                       pipe->winsys,
+                       1,
+                       PIPE_BUFFER_USAGE_VERTEX,
+                       sizeof(struct VL_TEXCOORD2F) * 24
+               );
+       
+               context->states.mc.vertex_buf_elems[i].src_offset = 0;
+               context->states.mc.vertex_buf_elems[i].vertex_buffer_index = i;
+               context->states.mc.vertex_buf_elems[i].nr_components = 2;
+               context->states.mc.vertex_buf_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       }
+       
+       /* Fill buffers */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_chroma_420_texcoords,
+               sizeof(struct VL_VERTEX2F) * 24
+       );
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_luma_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       /* TODO: Accomodate 422, 444 */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.vertex_bufs[2].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_chroma_420_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 24
+       );
+       
+       for (i = 0; i < 3; ++i)
+               pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.vertex_bufs[i].buffer);
+       
+       /* Create our constant buffer */
+       context->states.mc.vs_const_buf.size = sizeof(struct VL_MC_VS_CONSTS);
+       context->states.mc.vs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.mc.vs_const_buf.size
+       );
+       
+       context->states.mc.fs_const_buf.size = sizeof(struct VL_MC_FS_CONSTS);
+       context->states.mc.fs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.mc.fs_const_buf.size
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.mc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               &vl_mc_fs_consts,
+               sizeof(struct VL_MC_FS_CONSTS)
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.mc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitMC(struct VL_CONTEXT *context)
+{      
+       struct pipe_context             *pipe;
+       struct pipe_sampler_state       sampler;
+       struct pipe_texture             template;
+       unsigned int                    filters[5];
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* For MC we render to textures, which are rounded up to nearest POT */
+       context->states.mc.viewport.scale[0] = vlRoundUpPOT(context->video_width);
+       context->states.mc.viewport.scale[1] = vlRoundUpPOT(context->video_height);
+       context->states.mc.viewport.scale[2] = 1;
+       context->states.mc.viewport.scale[3] = 1;
+       context->states.mc.viewport.translate[0] = 0;
+       context->states.mc.viewport.translate[1] = 0;
+       context->states.mc.viewport.translate[2] = 0;
+       context->states.mc.viewport.translate[3] = 0;
+       
+       context->states.mc.render_target.width = context->video_width;
+       context->states.mc.render_target.height = context->video_height;
+       context->states.mc.render_target.num_cbufs = 1;
+       /* FB for MC stage is a VL_SURFACE, set in vlSetRenderSurface() */
+       context->states.mc.render_target.zsbuf = NULL;
+       
+       filters[0] = PIPE_TEX_FILTER_NEAREST;
+       filters[1] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+       filters[2] = context->video_format == VL_FORMAT_YCBCR_444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+       filters[3] = PIPE_TEX_FILTER_LINEAR;
+       filters[4] = PIPE_TEX_FILTER_LINEAR;
+       
+       for (i = 0; i < 5; ++i)
+       {
+               sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+               sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+               sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+               sampler.min_img_filter = filters[i];
+               sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+               sampler.mag_img_filter = filters[i];
+               sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+               sampler.compare_func = PIPE_FUNC_ALWAYS;
+               sampler.normalized_coords = 1;
+               /*sampler.prefilter = ;*/
+               /*sampler.shadow_ambient = ;*/
+               /*sampler.lod_bias = ;*/
+               sampler.min_lod = 0;
+               /*sampler.max_lod = ;*/
+               /*sampler.border_color[i] = ;*/
+               /*sampler.max_anisotropy = ;*/
+               context->states.mc.samplers[i] = pipe->create_sampler_state(pipe, &sampler);
+       }
+       
+       memset(&template, 0, sizeof(struct pipe_texture));
+       template.target = PIPE_TEXTURE_2D;
+       template.format = PIPE_FORMAT_A8L8_UNORM;
+       template.last_level = 0;
+       template.width[0] = 8;
+       template.height[0] = 8 * 4;
+       template.depth[0] = 1;
+       template.compressed = 0;
+       pf_get_block(template.format, &template.block);
+       
+       context->states.mc.textures[0] = pipe->screen->texture_create(pipe->screen, &template);
+       
+       if (context->video_format == VL_FORMAT_YCBCR_420)
+               template.height[0] = 8;
+       else if (context->video_format == VL_FORMAT_YCBCR_422)
+               template.height[0] = 8 * 2;
+       else if (context->video_format == VL_FORMAT_YCBCR_444)
+               template.height[0] = 8 * 4;
+       else
+               assert(0);
+               
+       context->states.mc.textures[1] = pipe->screen->texture_create(pipe->screen, &template);
+       context->states.mc.textures[2] = pipe->screen->texture_create(pipe->screen, &template);
+       
+       /* textures[3] & textures[4] are assigned from VL_SURFACEs for P and B macroblocks at render time */
+       
+       vlCreateVertexShaderIMC(context);
+       vlCreateFragmentShaderIMC(context);
+       vlCreateVertexShaderFramePMC(context);
+       vlCreateVertexShaderFieldPMC(context);
+       vlCreateFragmentShaderFramePMC(context);
+       vlCreateFragmentShaderFieldPMC(context);
+       vlCreateVertexShaderFrameBMC(context);
+       vlCreateVertexShaderFieldBMC(context);
+       vlCreateFragmentShaderFrameBMC(context);
+       vlCreateFragmentShaderFieldBMC(context);
+       vlCreateDataBufsMC(context);
+       
+       return 0;
+}
+
+static int vlDestroyMC(struct VL_CONTEXT *context)
+{
+       unsigned int i;
+       
+       assert(context);
+       
+       for (i = 0; i < 5; ++i)
+               context->pipe->delete_sampler_state(context->pipe, context->states.mc.samplers[i]);
+       
+       for (i = 0; i < 3; ++i)
+               context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vertex_bufs[i].buffer);
+       
+       /* Textures 3 & 4 are not created directly, no need to release them here */
+       for (i = 0; i < 3; ++i)
+               pipe_texture_release(&context->states.mc.textures[i]);
+       
+       context->pipe->delete_vs_state(context->pipe, context->states.mc.i_vs);
+       context->pipe->delete_fs_state(context->pipe, context->states.mc.i_fs);
+       
+       for (i = 0; i < 2; ++i)
+       {
+               context->pipe->delete_vs_state(context->pipe, context->states.mc.p_vs[i]);
+               context->pipe->delete_fs_state(context->pipe, context->states.mc.p_fs[i]);
+               context->pipe->delete_vs_state(context->pipe, context->states.mc.b_vs[i]);
+               context->pipe->delete_fs_state(context->pipe, context->states.mc.b_fs[i]);
+       }
+       
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.vs_const_buf.buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.mc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlCreateVertexShaderCSC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+       
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        vs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+       
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
+
+       ti = 3;
+
+       /*
+        * decl i0              ; Vertex pos
+        * decl i1              ; Vertex texcoords
+        */
+       for (i = 0; i < 2; i++)
+       {
+               decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /*
+        * decl c0              ; Scaling vector to scale texcoord rect to source size
+        * decl c1              ; Translation vector to move texcoord rect into position
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /*
+        * decl o0              ; Vertex pos
+        * decl o1              ; Vertex texcoords
+        */
+       for (i = 0; i < 2; i++)
+       {
+               decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
+               ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       }
+       
+       /* mov o0, i0           ; Move pos in to pos out */
+       inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, 0, TGSI_FILE_INPUT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* mul t0, i1, c0       ; Scale unit texcoord rect to source size */
+       inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 1, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* add o1, t0, c1       ; Translate texcoord rect into position */
+       inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 1, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 1);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       vs.tokens = tokens;
+       context->states.csc.vertex_shader = pipe->create_vs_state(pipe, &vs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateFragmentShaderCSC(struct VL_CONTEXT *context)
+{
+       const unsigned int              max_tokens = 50;
+
+       struct pipe_context             *pipe;
+       struct pipe_shader_state        fs;
+       struct tgsi_token               *tokens;
+       struct tgsi_header              *header;
+
+       struct tgsi_full_declaration    decl;
+       struct tgsi_full_instruction    inst;
+       
+       unsigned int                    ti;
+       unsigned int                    i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token));
+
+       /* Version */
+       *(struct tgsi_version*)&tokens[0] = tgsi_build_version();
+       /* Header */
+       header = (struct tgsi_header*)&tokens[1];
+       *header = tgsi_build_header();
+       /* Processor */
+       *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
+
+       ti = 3;
+
+       /* decl i0              ; Texcoords for s0 */
+       decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * decl c0              ; Bias vector for CSC
+        * decl c1-c4           ; CSC matrix c1-c4
+        */
+       decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+       /* decl o0              ; Fragment color */
+       decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /* decl s0              ; Sampler for tex containing picture to display */
+       decl = vl_decl_samplers(0, 0);
+       ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+       
+       /* tex2d t0, i0, s0     ; Read src pixel */
+       inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /* sub t0, t0, c0       ; Subtract bias vector from pixel */
+       inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       
+       /*
+        * dp4 o0.x, t0, c1     ; Multiply pixel by the color conversion matrix
+        * dp4 o0.y, t0, c2
+        * dp4 o0.z, t0, c3
+        * dp4 o0.w, t0, c4     ; XXX: Don't need 4th coefficient
+        */
+       for (i = 0; i < 4; ++i)
+       {
+               inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1);
+               inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+               ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+       }
+
+       /* end */
+       inst = vl_end();
+       ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+       fs.tokens = tokens;
+       context->states.csc.fragment_shader = pipe->create_fs_state(pipe, &fs);
+       free(tokens);
+       
+       return 0;
+}
+
+static int vlCreateDataBufsCSC(struct VL_CONTEXT *context)
+{
+       struct pipe_context *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /*
+       Create our vertex buffer and vertex buffer element
+       VB contains 4 vertices that render a quad covering the entire window
+       to display a rendered surface
+       Quad is rendered as a tri strip
+       */
+       context->states.csc.vertex_bufs[0].pitch = sizeof(struct VL_VERTEX2F);
+       context->states.csc.vertex_bufs[0].max_index = 3;
+       context->states.csc.vertex_bufs[0].buffer_offset = 0;
+       context->states.csc.vertex_bufs[0].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_VERTEX2F) * 4
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_surface_vertex_positions,
+               sizeof(struct VL_VERTEX2F) * 4
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[0].buffer);
+       
+       context->states.csc.vertex_buf_elems[0].src_offset = 0;
+       context->states.csc.vertex_buf_elems[0].vertex_buffer_index = 0;
+       context->states.csc.vertex_buf_elems[0].nr_components = 2;
+       context->states.csc.vertex_buf_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /*
+       Create our texcoord buffer and texcoord buffer element
+       Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
+       */
+       context->states.csc.vertex_bufs[1].pitch = sizeof(struct VL_TEXCOORD2F);
+       context->states.csc.vertex_bufs[1].max_index = 3;
+       context->states.csc.vertex_bufs[1].buffer_offset = 0;
+       context->states.csc.vertex_bufs[1].buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_VERTEX,
+               sizeof(struct VL_TEXCOORD2F) * 4
+       );
+       
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               vl_surface_texcoords,
+               sizeof(struct VL_TEXCOORD2F) * 4
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.vertex_bufs[1].buffer);
+       
+       context->states.csc.vertex_buf_elems[1].src_offset = 0;
+       context->states.csc.vertex_buf_elems[1].vertex_buffer_index = 1;
+       context->states.csc.vertex_buf_elems[1].nr_components = 2;
+       context->states.csc.vertex_buf_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+       
+       /*
+       Create our vertex shader's constant buffer
+       Const buffer contains scaling and translation vectors
+       */
+       context->states.csc.vs_const_buf.size = sizeof(struct VL_CSC_VS_CONSTS);
+       context->states.csc.vs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.csc.vs_const_buf.size
+       );
+       
+       /*
+       Create our fragment shader's constant buffer
+       Const buffer contains the color conversion matrix and bias vectors
+       */
+       context->states.csc.fs_const_buf.size = sizeof(struct VL_CSC_FS_CONSTS);
+       context->states.csc.fs_const_buf.buffer = pipe->winsys->buffer_create
+       (
+               pipe->winsys,
+               1,
+               PIPE_BUFFER_USAGE_CONSTANT,
+               context->states.csc.fs_const_buf.size
+       );
+       
+       /*
+       TODO: Refactor this into a seperate function,
+       allow changing the CSC matrix at runtime to switch between regular & full versions
+       */
+       memcpy
+       (
+               pipe->winsys->buffer_map(pipe->winsys, context->states.csc.fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+               &vl_csc_fs_consts_601,
+               sizeof(struct VL_CSC_FS_CONSTS)
+       );
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, context->states.csc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitCSC(struct VL_CONTEXT *context)
+{      
+       struct pipe_context             *pipe;
+       struct pipe_sampler_state       sampler;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Delay creating the FB until vlPutSurface() so we know window size */
+       context->states.csc.framebuffer.num_cbufs = 1;
+       context->states.csc.framebuffer.cbufs[0] = NULL;
+       context->states.csc.framebuffer.zsbuf = NULL;
+
+       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+       sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+       sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+       sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
+       sampler.compare_func = PIPE_FUNC_ALWAYS;
+       sampler.normalized_coords = 1;
+       /*sampler.prefilter = ;*/
+       /*sampler.shadow_ambient = ;*/
+       /*sampler.lod_bias = ;*/
+       /*sampler.min_lod = ;*/
+       /*sampler.max_lod = ;*/
+       /*sampler.border_color[i] = ;*/
+       /*sampler.max_anisotropy = ;*/
+       context->states.csc.sampler = pipe->create_sampler_state(pipe, &sampler);
+       
+       vlCreateVertexShaderCSC(context);
+       vlCreateFragmentShaderCSC(context);
+       vlCreateDataBufsCSC(context);
+       
+       return 0;
+}
+
+static int vlDestroyCSC(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       /*
+       Since we create the final FB when we display our first surface,
+       it may not be created if vlPutSurface() is never called
+       */
+       if (context->states.csc.framebuffer.cbufs[0])
+               context->pipe->winsys->surface_release(context->pipe->winsys, &context->states.csc.framebuffer.cbufs[0]);
+       context->pipe->delete_sampler_state(context->pipe, context->states.csc.sampler);
+       context->pipe->delete_vs_state(context->pipe, context->states.csc.vertex_shader);
+       context->pipe->delete_fs_state(context->pipe, context->states.csc.fragment_shader);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[0].buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vertex_bufs[1].buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.vs_const_buf.buffer);
+       context->pipe->winsys->buffer_destroy(context->pipe->winsys, context->states.csc.fs_const_buf.buffer);
+       
+       return 0;
+}
+
+static int vlInitCommon(struct VL_CONTEXT *context)
+{
+       struct pipe_context                     *pipe;
+       struct pipe_rasterizer_state            rast;
+       struct pipe_blend_state                 blend;
+       struct pipe_depth_stencil_alpha_state   dsa;
+       unsigned int                            i;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       rast.flatshade = 1;
+       rast.flatshade_first = 0;
+       rast.light_twoside = 0;
+       rast.front_winding = PIPE_WINDING_CCW;
+       rast.cull_mode = PIPE_WINDING_CW;
+       rast.fill_cw = PIPE_POLYGON_MODE_FILL;
+       rast.fill_ccw = PIPE_POLYGON_MODE_FILL;
+       rast.offset_cw = 0;
+       rast.offset_ccw = 0;
+       rast.scissor = 0;
+       rast.poly_smooth = 0;
+       rast.poly_stipple_enable = 0;
+       rast.point_sprite = 0;
+       rast.point_size_per_vertex = 0;
+       rast.multisample = 0;
+       rast.line_smooth = 0;
+       rast.line_stipple_enable = 0;
+       rast.line_stipple_factor = 0;
+       rast.line_stipple_pattern = 0;
+       rast.line_last_pixel = 0;
+       /* Don't need clipping, but viewport mapping done here */
+       rast.bypass_clipping = 0;
+       rast.bypass_vs = 0;
+       rast.origin_lower_left = 0;
+       rast.line_width = 1;
+       rast.point_smooth = 0;
+       rast.point_size = 1;
+       rast.offset_units = 1;
+       rast.offset_scale = 1;
+       /*rast.sprite_coord_mode[i] = ;*/
+       context->states.common.raster = pipe->create_rasterizer_state(pipe, &rast);
+       pipe->bind_rasterizer_state(pipe, context->states.common.raster);
+       
+       blend.blend_enable = 0;
+       blend.rgb_func = PIPE_BLEND_ADD;
+       blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+       blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+       blend.alpha_func = PIPE_BLEND_ADD;
+       blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+       blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
+       blend.logicop_enable = 0;
+       blend.logicop_func = PIPE_LOGICOP_CLEAR;
+       /* Needed to allow color writes to FB, even if blending disabled */
+       blend.colormask = PIPE_MASK_RGBA;
+       blend.dither = 0;
+       context->states.common.blend = pipe->create_blend_state(pipe, &blend);
+       pipe->bind_blend_state(pipe, context->states.common.blend);
+       
+       dsa.depth.enabled = 0;
+       dsa.depth.writemask = 0;
+       dsa.depth.func = PIPE_FUNC_ALWAYS;
+       dsa.depth.occlusion_count = 0;
+       for (i = 0; i < 2; ++i)
+       {
+               dsa.stencil[i].enabled = 0;
+               dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
+               dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
+               dsa.stencil[i].ref_value = 0;
+               dsa.stencil[i].value_mask = 0;
+               dsa.stencil[i].write_mask = 0;
+       }
+       dsa.alpha.enabled = 0;
+       dsa.alpha.func = PIPE_FUNC_ALWAYS;
+       dsa.alpha.ref = 0;
+       context->states.common.dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+       pipe->bind_depth_stencil_alpha_state(pipe, context->states.common.dsa);
+       
+       return 0;
+}
+
+static int vlDestroyCommon(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       context->pipe->delete_blend_state(context->pipe, context->states.common.blend);
+       context->pipe->delete_rasterizer_state(context->pipe, context->states.common.raster);
+       context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->states.common.dsa);
+       
+       return 0;
+}
+
+static int vlInit(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       vlInitCommon(context);
+       vlInitCSC(context);
+       vlInitMC(context);
+       vlInitIDCT(context);
+       
+       return 0;
+}
+
+static int vlDestroy(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       /* XXX: Must unbind shaders before we can delete them for some reason */
+       context->pipe->bind_vs_state(context->pipe, NULL);
+       context->pipe->bind_fs_state(context->pipe, NULL);
+       
+       vlDestroyCommon(context);
+       vlDestroyCSC(context);
+       vlDestroyMC(context);
+       vlDestroyIDCT(context);
+       
+       return 0;
+}
+
+int vlCreateContext
+(
+       Display *display,
+       struct pipe_context *pipe,
+       unsigned int video_width,
+       unsigned int video_height,
+       enum VL_FORMAT video_format,
+       struct VL_CONTEXT **context
+)
+{
+       struct VL_CONTEXT *ctx;
+       
+       assert(display);
+       assert(pipe);
+       assert(context);
+       
+       ctx = calloc(1, sizeof(struct VL_CONTEXT));
+       
+       ctx->display = display;
+       ctx->pipe = pipe;
+       ctx->video_width = video_width;
+       ctx->video_height = video_height;
+       ctx->video_format = video_format;
+       
+       vlInit(ctx);
+       
+       /* Since we only change states in vlPutSurface() we need to start in render mode */
+       vlBeginRender(ctx);
+       
+       *context = ctx;
+       
+       return 0;
+}
+
+int vlDestroyContext(struct VL_CONTEXT *context)
+{
+       assert(context);
+       
+       vlDestroy(context);
+       
+       context->pipe->destroy(context->pipe);
+       
+       free(context);
+       
+       return 0;
+}
+
+int vlBeginRender(struct VL_CONTEXT *context)
+{
+       struct pipe_context     *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       /* Frame buffer set in vlRender*Macroblock() */
+       /* Shaders, samplers, textures set in vlRender*Macroblock() */
+       pipe->set_vertex_buffers(pipe, 3, context->states.mc.vertex_bufs);
+       pipe->set_vertex_elements(pipe, 3, context->states.mc.vertex_buf_elems);
+       pipe->set_viewport_state(pipe, &context->states.mc.viewport);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->states.mc.vs_const_buf);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.mc.fs_const_buf);
+       
+       return 0;
+}
+
+int vlEndRender(struct VL_CONTEXT *context)
+{
+       struct pipe_context *pipe;
+       
+       assert(context);
+       
+       pipe = context->pipe;
+       
+       pipe->set_framebuffer_state(pipe, &context->states.csc.framebuffer);
+       pipe->set_viewport_state(pipe, &context->states.csc.viewport);
+       pipe->bind_sampler_states(pipe, 1, (void**)&context->states.csc.sampler);
+       /* Source texture set in vlPutSurface() */
+       pipe->bind_vs_state(pipe, context->states.csc.vertex_shader);
+       pipe->bind_fs_state(pipe, context->states.csc.fragment_shader);
+       pipe->set_vertex_buffers(pipe, 2, context->states.csc.vertex_bufs);
+       pipe->set_vertex_elements(pipe, 2, context->states.csc.vertex_buf_elems);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &context->states.csc.vs_const_buf);
+       pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &context->states.csc.fs_const_buf);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h
new file mode 100644 (file)
index 0000000..bff3188
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef vl_context_h
+#define vl_context_h
+
+#include <X11/Xlib.h>
+#include <pipe/p_state.h>
+#include "vl_types.h"
+
+struct pipe_context;
+
+struct VL_CONTEXT
+{
+       Display                 *display;
+       struct pipe_context     *pipe;
+       unsigned int            video_width;
+       unsigned int            video_height;
+       enum VL_FORMAT          video_format;
+       
+       struct
+       {
+               struct
+               {
+                       struct pipe_rasterizer_state            *raster;
+                       struct pipe_depth_stencil_alpha_state   *dsa;
+                       struct pipe_blend_state                 *blend;
+               } common;
+               
+               struct
+               {
+                       struct pipe_viewport_state              viewport;
+                       struct pipe_framebuffer_state           render_target;
+                       struct pipe_sampler_state               *sampler;
+                       struct pipe_texture                     *texture;
+                       struct pipe_texture                     *basis;
+                       struct pipe_shader_state                *frame_vs;
+                       struct pipe_shader_state                *frame_fs;
+                       struct pipe_vertex_buffer               *vertex_bufs[2];
+                       struct pipe_vertex_element              *vertex_buf_elems[2];
+                       //struct pipe_constant_buffer           vs_const_buf, fs_const_buf;
+               } idct;
+               
+               struct
+               {
+                       struct pipe_viewport_state              viewport;
+                       struct pipe_framebuffer_state           render_target;
+                       struct pipe_sampler_state               *samplers[5];
+                       struct pipe_texture                     *textures[5];
+                       struct pipe_shader_state                *i_vs, *p_vs[2], *b_vs[2];
+                       struct pipe_shader_state                *i_fs, *p_fs[2], *b_fs[2];
+                       struct pipe_vertex_buffer               vertex_bufs[3];
+                       struct pipe_vertex_element              vertex_buf_elems[3];
+                       struct pipe_constant_buffer             vs_const_buf, fs_const_buf;
+               } mc;
+               
+               struct
+               {
+                       struct pipe_viewport_state              viewport;
+                       struct pipe_framebuffer_state           framebuffer;
+                       struct pipe_sampler_state               *sampler;
+                       struct pipe_shader_state                *vertex_shader, *fragment_shader;
+                       struct pipe_vertex_buffer               vertex_bufs[2];
+                       struct pipe_vertex_element              vertex_buf_elems[2];
+                       struct pipe_constant_buffer             vs_const_buf, fs_const_buf;
+               } csc;
+       } states;
+};
+
+int vlCreateContext
+(
+       Display *display,
+       struct pipe_context *pipe,
+       unsigned int video_width,
+       unsigned int video_height,
+       enum VL_FORMAT video_format,
+       struct VL_CONTEXT **context
+);
+
+int vlDestroyContext(struct VL_CONTEXT *context);
+
+int vlBeginRender(struct VL_CONTEXT *context);
+int vlEndRender(struct VL_CONTEXT *context);
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_data.c b/src/gallium/state_trackers/g3dvl/vl_data.c
new file mode 100644 (file)
index 0000000..7e6ee8a
--- /dev/null
@@ -0,0 +1,181 @@
+#include "vl_data.h"
+
+/*
+ * Represents 8 triangles (4 quads, 1 per block) in noormalized coords
+ * that render a macroblock.
+ * Need to be scaled to cover mbW*mbH macroblock pixels and translated into
+ * position on target surface.
+ */
+const struct VL_VERTEX2F vl_mb_vertex_positions[24] =
+{
+       {0.0f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.0f},
+       {0.5f, 0.0f}, {0.0f, 0.5f}, {0.5f, 0.5f},
+       
+       {0.5f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.0f},
+       {1.0f, 0.0f}, {0.5f, 0.5f}, {1.0f, 0.5f},
+       
+       {0.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 0.5f},
+       {0.5f, 0.5f}, {0.0f, 1.0f}, {0.5f, 1.0f},
+       
+       {0.5f, 0.5f}, {0.5f, 1.0f}, {1.0f, 0.5f},
+       {1.0f, 0.5f}, {0.5f, 1.0f}, {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above for rendering 4 luma blocks arranged
+ * in a bW*(bH*4) texture. First luma block located at 0,0->bW,bH; second at
+ * 0,bH->bW,2bH; third at 0,2bH->bW,3bH; fourth at 0,3bH->bW,4bH.
+ */
+const struct VL_TEXCOORD2F vl_luma_texcoords[24] =
+{
+       {0.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.0f},
+       {1.0f, 0.0f}, {0.0f, 0.25f}, {1.0f, 0.25f},
+       
+       {0.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.25f},
+       {1.0f, 0.25f}, {0.0f, 0.5f}, {1.0f, 0.5f},
+       
+       {0.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.5f},
+       {1.0f, 0.5f}, {0.0f, 0.75f}, {1.0f, 0.75f},
+       
+       {0.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 0.75f},
+       {1.0f, 0.75f}, {0.0f, 1.0f}, {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above for rendering 1 chroma block.
+ * Straight forward 0,0->1,1 mapping so we can reuse the MB pos vectors.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_420_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions;
+
+/*
+ * Represents texcoords for the above for rendering 2 chroma blocks arranged
+ * in a bW*(bH*2) texture. First chroma block located at 0,0->bW,bH; second at
+ * 0,bH->bW,2bH. We can render this with 0,0->1,1 mapping.
+ * Straight forward 0,0->1,1 mapping so we can reuse MB pos vectors.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_422_texcoords = (const struct VL_TEXCOORD2F*)vl_mb_vertex_positions;
+
+/*
+ * Represents texcoords for the above for rendering 4 chroma blocks.
+ * Same case as 4 luma blocks.
+ */
+const struct VL_TEXCOORD2F *vl_chroma_444_texcoords = vl_luma_texcoords;
+
+/*
+ * Represents 2 triangles in a strip in normalized coords.
+ * Used to render the surface onto the frame buffer.
+ */
+const struct VL_VERTEX2F vl_surface_vertex_positions[4] =
+{
+       {0.0f, 0.0f},
+       {0.0f, 1.0f},
+       {1.0f, 0.0f},
+       {1.0f, 1.0f}
+};
+
+/*
+ * Represents texcoords for the above. We can use the position values directly.
+ */
+const struct VL_TEXCOORD2F *vl_surface_texcoords = (const struct VL_TEXCOORD2F*)vl_surface_vertex_positions;
+
+/*
+ * Used when rendering P and B macroblocks, multiplier is applied to the A channel,
+ * which is then added to the L channel, then the bias is subtracted from that to
+ * get back the differential. The differential is then added to the samples from the
+ * reference surface(s).
+ */
+const struct VL_MC_FS_CONSTS vl_mc_fs_consts =
+{
+       {256.0f, 256.0f, 256.0f, 0.0f},
+       {256.0f / 255.0f, 256.0f / 255.0f, 256.0f / 255.0f, 0.0f},
+       {0.5f, 2.0f, 0.0f, 0.0f}
+};
+
+/*
+ * Identity color conversion constants, for debugging
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity =
+{
+       {
+               0.0f, 0.0f, 0.0f, 0.0f
+       },
+       {
+               1.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 1.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 1.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601 =
+{
+       {
+               0.0f,           0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.0f,           0.0f,           1.371f,         0.0f,
+               1.0f,           -0.336f,        -0.698f,        0.0f,
+               1.0f,           1.732f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full =
+{
+       {
+               0.062745098f,   0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.164f,         0.0f,           1.596f,         0.0f,
+               1.164f,         -0.391f,        -0.813f,        0.0f,
+               1.164f,         2.018f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [16,235]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709 =
+{
+       {
+               0.0f,           0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.0f,           0.0f,           1.540f,         0.0f,
+               1.0f,           -0.183f,        -0.459f,        0.0f,
+               1.0f,           1.816f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
+/*
+ * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
+ * Y is in [16,235], Cb and Cr are in [16,240]
+ * R, G, and B are in [0,255]
+ */
+const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full =
+{
+       {
+               0.062745098f,   0.501960784f,   0.501960784f,   0.0f
+       },
+       {
+               1.164f,         0.0f,           1.793f,         0.0f,
+               1.164f,         -0.213f,        -0.534f,        0.0f,
+               1.164f,         2.115f,         0.0f,           0.0f,
+               0.0f,           0.0f,           0.0f,           1.0f
+       }
+};
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_data.h b/src/gallium/state_trackers/g3dvl/vl_data.h
new file mode 100644 (file)
index 0000000..8f34727
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef vl_data_h
+#define vl_data_h
+
+#include "vl_types.h"
+
+extern const struct VL_VERTEX2F vl_mb_vertex_positions[24];
+extern const struct VL_TEXCOORD2F vl_luma_texcoords[24];
+extern const struct VL_TEXCOORD2F *vl_chroma_420_texcoords;
+extern const struct VL_TEXCOORD2F *vl_chroma_422_texcoords;
+extern const struct VL_TEXCOORD2F *vl_chroma_444_texcoords;
+
+extern const struct VL_VERTEX2F vl_surface_vertex_positions[4];
+extern const struct VL_TEXCOORD2F *vl_surface_texcoords;
+
+extern const struct VL_MC_FS_CONSTS vl_mc_fs_consts;
+
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_identity;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_601_full;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709;
+extern const struct VL_CSC_FS_CONSTS vl_csc_fs_consts_709_full;
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_defs.h b/src/gallium/state_trackers/g3dvl/vl_defs.h
new file mode 100644 (file)
index 0000000..e668a7a
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef vl_defs_h
+#define vl_defs_h
+
+#define VL_BLOCK_WIDTH         8
+#define VL_BLOCK_HEIGHT                8
+#define VL_BLOCK_SIZE          (VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT)
+#define VL_MACROBLOCK_WIDTH    16
+#define VL_MACROBLOCK_HEIGHT   16
+#define VL_MACROBLOCK_SIZE     (VL_MACROBLOCK_WIDTH * VL_MACROBLOCK_HEIGHT)
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.c b/src/gallium/state_trackers/g3dvl/vl_shader_build.c
new file mode 100644 (file)
index 0000000..365ad69
--- /dev/null
@@ -0,0 +1,204 @@
+#include "vl_shader_build.h"
+#include <assert.h>
+#include <tgsi/util/tgsi_parse.h>
+#include <tgsi/util/tgsi_build.h>
+
+struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+       struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+       decl.Declaration.File = TGSI_FILE_INPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = name;
+       decl.Semantic.SemanticIndex = index;
+       decl.DeclarationRange.First = first;
+       decl.DeclarationRange.Last = last;
+       
+       return decl;
+}
+
+struct tgsi_full_declaration vl_decl_interpolated_input
+(
+       unsigned int name,
+       unsigned int index,
+       unsigned int first,
+       unsigned int last,
+       int interpolation
+)
+{
+       struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+       
+       assert
+       (
+               interpolation == TGSI_INTERPOLATE_CONSTANT ||
+               interpolation == TGSI_INTERPOLATE_LINEAR ||
+               interpolation == TGSI_INTERPOLATE_PERSPECTIVE
+       );
+
+       decl.Declaration.File = TGSI_FILE_INPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = name;
+       decl.Semantic.SemanticIndex = index;
+       decl.Declaration.Interpolate = interpolation;;
+       decl.DeclarationRange.First = first;
+       decl.DeclarationRange.Last = last;
+       
+       return decl;
+}
+
+struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+       struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+       
+       decl.Declaration.File = TGSI_FILE_CONSTANT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = name;
+       decl.Semantic.SemanticIndex = index;
+       decl.DeclarationRange.First = first;
+       decl.DeclarationRange.Last = last;
+       
+       return decl;
+}
+
+struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
+{
+       struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+       decl.Declaration.File = TGSI_FILE_OUTPUT;
+       decl.Declaration.Semantic = 1;
+       decl.Semantic.SemanticName = name;
+       decl.Semantic.SemanticIndex = index;
+       decl.DeclarationRange.First = first;
+       decl.DeclarationRange.Last = last;
+       
+       return decl;
+}
+
+struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last)
+{
+       struct tgsi_full_declaration decl = tgsi_default_full_declaration();
+
+       decl = tgsi_default_full_declaration();
+       decl.Declaration.File = TGSI_FILE_SAMPLER;
+       decl.DeclarationRange.First = first;
+       decl.DeclarationRange.Last = last;
+       
+       return decl;
+}
+
+struct tgsi_full_instruction vl_inst2
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src_file,
+       unsigned int src_index
+)
+{
+       struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+       
+       inst.Instruction.Opcode = opcode;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = dst_file;
+       inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+       inst.Instruction.NumSrcRegs = 1;
+       inst.FullSrcRegisters[0].SrcRegister.File = src_file;
+       inst.FullSrcRegisters[0].SrcRegister.Index = src_index;
+       
+       return inst;
+}
+
+struct tgsi_full_instruction vl_inst3
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index
+)
+{
+       struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+       
+       inst.Instruction.Opcode = opcode;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = dst_file;
+       inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+       inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+       inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+       inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+       
+       return inst;
+}
+
+struct tgsi_full_instruction vl_tex
+(
+       int tex,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index
+)
+{
+       struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+       
+       inst.Instruction.Opcode = TGSI_OPCODE_TEX;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = dst_file;
+       inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+       inst.Instruction.NumSrcRegs = 2;
+       inst.InstructionExtTexture.Texture = tex;
+       inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+       inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+       inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+       inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+       
+       return inst;
+}
+
+struct tgsi_full_instruction vl_inst4
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index,
+       enum tgsi_file_type src3_file,
+       unsigned int src3_index
+)
+{
+       struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+       
+       inst.Instruction.Opcode = opcode;
+       inst.Instruction.NumDstRegs = 1;
+       inst.FullDstRegisters[0].DstRegister.File = dst_file;
+       inst.FullDstRegisters[0].DstRegister.Index = dst_index;
+       inst.Instruction.NumSrcRegs = 3;
+       inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
+       inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
+       inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
+       inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
+       inst.FullSrcRegisters[2].SrcRegister.File = src3_file;
+       inst.FullSrcRegisters[2].SrcRegister.Index = src3_index;
+       
+       return inst;
+}
+
+struct tgsi_full_instruction vl_end(void)
+{
+       struct tgsi_full_instruction inst = tgsi_default_full_instruction();
+       
+       inst.Instruction.Opcode = TGSI_OPCODE_END;
+       inst.Instruction.NumDstRegs = 0;
+       inst.Instruction.NumSrcRegs = 0;
+       
+       return inst;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.h b/src/gallium/state_trackers/g3dvl/vl_shader_build.h
new file mode 100644 (file)
index 0000000..9e64bbe
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef vl_shader_build_h
+#define vl_shader_build_h
+
+#include <pipe/p_shader_tokens.h>
+
+struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_interpolated_input
+(
+       unsigned int name,
+       unsigned int index,
+       unsigned int first,
+       unsigned int last,
+       int interpolation
+);
+struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
+struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last);
+struct tgsi_full_instruction vl_inst2
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src_file,
+       unsigned int src_index
+);
+struct tgsi_full_instruction vl_inst3
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index
+);
+struct tgsi_full_instruction vl_tex
+(
+       int tex,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index
+);
+struct tgsi_full_instruction vl_inst4
+(
+       int opcode,
+       enum tgsi_file_type dst_file,
+       unsigned int dst_index,
+       enum tgsi_file_type src1_file,
+       unsigned int src1_index,
+       enum tgsi_file_type src2_file,
+       unsigned int src2_index,
+       enum tgsi_file_type src3_file,
+       unsigned int src3_index
+);
+struct tgsi_full_instruction vl_end(void);
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c
new file mode 100644 (file)
index 0000000..145ea32
--- /dev/null
@@ -0,0 +1,726 @@
+#include "vl_surface.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_state.h>
+#include <pipe/p_format.h>
+#include <pipe/p_inlines.h>
+#include "vl_context.h"
+#include "vl_defs.h"
+#include "vl_util.h"
+
+static int vlTransformBlock(short *src, short *dst, short bias)
+{
+       static const float basis[8][8] =
+       {
+               {0.3536,   0.4904,   0.4619,   0.4157,   0.3536,   0.2778,   0.1913,   0.0975},
+               {0.3536,   0.4157,   0.1913,  -0.0975,  -0.3536,  -0.4904,  -0.4619,  -0.2778},
+               {0.3536,   0.2778,  -0.1913,  -0.4904,  -0.3536,   0.0975,   0.4619,   0.4157},
+               {0.3536,   0.0975,  -0.4619,  -0.2778,   0.3536,   0.4157,  -0.1913,  -0.4904},
+               {0.3536,  -0.0975,  -0.4619,   0.2778,   0.3536,  -0.4157,  -0.1913,   0.4904},
+               {0.3536,  -0.2778,  -0.1913,   0.4904,  -0.3536,  -0.0975,   0.4619,  -0.4157},
+               {0.3536,  -0.4157,   0.1913,   0.0975,  -0.3536,   0.4904,  -0.4619,   0.2778},
+               {0.3536,  -0.4904,   0.4619,  -0.4157,   0.3536,  -0.2778,   0.1913,  -0.0975}
+       };
+       
+       unsigned int    x, y;
+       short           tmp[64];
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+               for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+                       tmp[y * VL_BLOCK_WIDTH + x] = (short)
+                       (
+                               src[y * VL_BLOCK_WIDTH + 0] * basis[x][0] +
+                               src[y * VL_BLOCK_WIDTH + 1] * basis[x][1] +
+                               src[y * VL_BLOCK_WIDTH + 2] * basis[x][2] +
+                               src[y * VL_BLOCK_WIDTH + 3] * basis[x][3] +
+                               src[y * VL_BLOCK_WIDTH + 4] * basis[x][4] +
+                               src[y * VL_BLOCK_WIDTH + 5] * basis[x][5] +
+                               src[y * VL_BLOCK_WIDTH + 6] * basis[x][6] +
+                               src[y * VL_BLOCK_WIDTH + 7] * basis[x][7]
+                       );
+
+       for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+               for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+               {
+                       dst[y * VL_BLOCK_WIDTH + x] = bias + (short)
+                       (
+                               tmp[0 * VL_BLOCK_WIDTH + x] * basis[y][0] +
+                               tmp[1 * VL_BLOCK_WIDTH + x] * basis[y][1] +
+                               tmp[2 * VL_BLOCK_WIDTH + x] * basis[y][2] +
+                               tmp[3 * VL_BLOCK_WIDTH + x] * basis[y][3] +
+                               tmp[4 * VL_BLOCK_WIDTH + x] * basis[y][4] +
+                               tmp[5 * VL_BLOCK_WIDTH + x] * basis[y][5] +
+                               tmp[6 * VL_BLOCK_WIDTH + x] * basis[y][6] +
+                               tmp[7 * VL_BLOCK_WIDTH + x] * basis[y][7]
+                       );
+                       if (dst[y * VL_BLOCK_WIDTH + x] > 255)
+                               dst[y * VL_BLOCK_WIDTH + x] = 255;
+                       else if (bias > 0 && dst[y * VL_BLOCK_WIDTH + x] < 0)
+                               dst[y * VL_BLOCK_WIDTH + x] = 0;
+               }
+       return 0;
+}
+
+static int vlGrabFrameCodedFullBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+       unsigned int y;
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+               memcpy
+               (
+                       dst + y * dst_pitch,
+                       src + y * VL_BLOCK_WIDTH,
+                       VL_BLOCK_WIDTH * 2
+               );
+       
+       return 0;
+}
+
+static int vlGrabFrameCodedDiffBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+       unsigned int x, y;
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+               for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+                       dst[y * dst_pitch + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
+       
+       return 0;
+}
+
+static int vlGrabFieldCodedFullBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+       unsigned int y;
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT / 2; ++y)
+               memcpy
+               (
+                       dst + y * dst_pitch * 2,
+                       src + y * VL_BLOCK_WIDTH,
+                       VL_BLOCK_WIDTH * 2
+               );
+       
+       dst += VL_BLOCK_HEIGHT * dst_pitch;
+       
+       for (; y < VL_BLOCK_HEIGHT; ++y)
+               memcpy
+               (
+                       dst + y * dst_pitch * 2,
+                       src + y * VL_BLOCK_WIDTH,
+                       VL_BLOCK_WIDTH * 2
+               );
+       
+       return 0;
+}
+
+static int vlGrabFieldCodedDiffBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+       unsigned int x, y;
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT / 2; ++y)
+               for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+                       dst[y * dst_pitch * 2 + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
+       
+       dst += VL_BLOCK_HEIGHT * dst_pitch;
+       
+       for (; y < VL_BLOCK_HEIGHT; ++y)
+               for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+                       dst[y * dst_pitch * 2 + x] = src[y * VL_BLOCK_WIDTH + x] + 0x100;
+       
+       return 0;
+}
+
+static int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
+{
+       unsigned int x, y;
+       
+       for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+               for (x = 0; x < VL_BLOCK_WIDTH; ++x)
+                       dst[y * dst_pitch + x] = 0x100;
+       
+       return 0;
+}
+
+static int vlGrabBlocks
+(
+       struct VL_CONTEXT *context,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       enum VL_SAMPLE_TYPE sample_type,
+       short *blocks
+)
+{
+       struct pipe_surface     *tex_surface;
+       short                   *texels;
+       unsigned int            tex_pitch;
+       unsigned int            tb, sb = 0;
+       
+       const int               do_idct = 1;
+       short                   temp_block[64];
+       
+       assert(context);
+       assert(blocks);
+       
+       tex_surface = context->pipe->screen->get_tex_surface
+       (
+               context->pipe->screen,
+               context->states.mc.textures[0],
+               0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+       );
+       
+       texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+       tex_pitch = tex_surface->stride / tex_surface->block.size;
+       
+       for (tb = 0; tb < 4; ++tb)
+       {
+               if ((coded_block_pattern >> (5 - tb)) & 1)
+               {
+                       if (dct_type == VL_DCT_FRAME_CODED)
+                               if (sample_type == VL_FULL_SAMPLE)
+                                       if (do_idct)
+                                       {
+                                               vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
+                                               vlGrabFrameCodedFullBlock
+                                               (
+                                                       temp_block,
+                                                       texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
+                                                       tex_pitch
+                                               );
+                                       }
+                                       else
+                                       vlGrabFrameCodedFullBlock
+                                       (
+                                               blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                               texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
+                                               tex_pitch
+                                       );
+                               else
+                                       if (do_idct)
+                                       {
+                                               vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
+                                               vlGrabFrameCodedDiffBlock
+                                               (
+                                                       temp_block,
+                                                       texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
+                                                       tex_pitch
+                                               );
+                                       }
+                                       else
+                                       vlGrabFrameCodedDiffBlock
+                                       (
+                                               blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                               texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
+                                               tex_pitch
+                                       );
+                       else
+                               if (sample_type == VL_FULL_SAMPLE)
+                                       if (do_idct)
+                                       {
+                                               vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
+                                               vlGrabFieldCodedFullBlock
+                                               (
+                                                       temp_block,
+                                                       texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
+                                                       tex_pitch
+                                               );
+                                       }
+                                       else
+                                       vlGrabFieldCodedFullBlock
+                                       (
+                                               blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                               texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
+                                               tex_pitch
+                                       );
+                               else
+                                       if (do_idct)
+                                       {
+                                               vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
+                                               vlGrabFieldCodedDiffBlock
+                                               (
+                                                       temp_block,
+                                                       texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
+                                                       tex_pitch
+                                               );
+                                       }
+                                       else
+                                       vlGrabFieldCodedDiffBlock
+                                       (
+                                               blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                               texels + (tb % 2) * tex_pitch * VL_BLOCK_HEIGHT + (tb / 2) * tex_pitch,
+                                               tex_pitch
+                                       );
+                       ++sb;
+               }
+               else
+                       vlGrabNoBlock(texels + tb * tex_pitch * VL_BLOCK_HEIGHT, tex_pitch);
+       }
+       
+       pipe_surface_unmap(tex_surface);
+       
+       /* TODO: Implement 422, 444 */
+       for (tb = 0; tb < 2; ++tb)
+       {
+               tex_surface = context->pipe->screen->get_tex_surface
+                       (
+                               context->pipe->screen,
+                               context->states.mc.textures[tb + 1],
+                               0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
+                       );
+       
+               texels = pipe_surface_map(tex_surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+               tex_pitch = tex_surface->stride / tex_surface->block.size;
+               
+               if ((coded_block_pattern >> (1 - tb)) & 1)
+               {                       
+                       if (sample_type == VL_FULL_SAMPLE)
+                               if (do_idct)
+                               {
+                                       vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 128);
+                                       vlGrabFrameCodedFullBlock
+                                       (
+                                               temp_block,
+                                               texels,
+                                               tex_pitch
+                                       );
+                               }
+                               else
+                               vlGrabFrameCodedFullBlock
+                               (
+                                       blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                       texels,
+                                       tex_pitch
+                               );
+                       else
+                               if (do_idct)
+                               {
+                                       vlTransformBlock(blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT, temp_block, 0);
+                                       vlGrabFrameCodedDiffBlock
+                                       (
+                                               temp_block,
+                                               texels,
+                                               tex_pitch
+                                       );
+                               }
+                               else
+                               vlGrabFrameCodedDiffBlock
+                               (
+                                       blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT,
+                                       texels,
+                                       tex_pitch
+                               );
+                       
+                       ++sb;
+               }
+               else
+                       vlGrabNoBlock(texels, tex_pitch);
+               
+               pipe_surface_unmap(tex_surface);
+       }
+       
+       return 0;
+}
+
+int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface)
+{
+       struct pipe_context     *pipe;
+       struct pipe_texture     template;
+       struct VL_SURFACE       *sfc;
+       
+       assert(context);
+       assert(surface);
+       
+       pipe = context->pipe;
+       
+       sfc = calloc(1, sizeof(struct VL_SURFACE));
+       
+       sfc->context = context;
+       sfc->width = vlRoundUpPOT(context->video_width);
+       sfc->height = vlRoundUpPOT(context->video_height);
+       sfc->format = context->video_format;
+       
+       memset(&template, 0, sizeof(struct pipe_texture));
+       template.target = PIPE_TEXTURE_2D;
+       template.format = PIPE_FORMAT_A8R8G8B8_UNORM;
+       template.last_level = 0;
+       template.width[0] = sfc->width;
+       template.height[0] = sfc->height;
+       template.depth[0] = 1;
+       template.compressed = 0;
+       pf_get_block(template.format, &template.block);
+       /* XXX: Needed? */
+       template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET;
+       
+       sfc->texture = pipe->screen->texture_create(pipe->screen, &template);
+       
+       *surface = sfc;
+       
+       return 0;
+}
+
+int vlDestroySurface(struct VL_SURFACE *surface)
+{
+       assert(surface);
+       pipe_texture_release(&surface->texture);
+       free(surface);
+       
+       return 0;
+}
+
+int vlRenderIMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *surface
+)
+{
+       struct pipe_context     *pipe;
+       struct VL_MC_VS_CONSTS  *vs_consts;
+       
+       assert(blocks);
+       assert(surface);
+       
+       /* TODO: Implement interlaced rendering */
+       if (picture_type != VL_FRAME_PICTURE)
+               return 0;
+       
+       vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_FULL_SAMPLE, blocks);
+       
+       pipe = surface->context->pipe;
+       
+       vs_consts = pipe->winsys->buffer_map
+       (
+               pipe->winsys,
+               surface->context->states.mc.vs_const_buf.buffer,
+               PIPE_BUFFER_USAGE_CPU_WRITE
+       );
+       
+       vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+       vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+       vs_consts->scale.z = 1.0f;
+       vs_consts->scale.w = 1.0f;
+       vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+       vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+       vs_consts->mb_pos_trans.z = 0.0f;
+       vs_consts->mb_pos_trans.w = 0.0f;
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+       
+       surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+       (
+               pipe->screen,
+               surface->texture,
+               0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+       );
+       pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+       pipe->set_sampler_textures(pipe, 3, surface->context->states.mc.textures);
+       pipe->bind_sampler_states(pipe, 3, (void**)surface->context->states.mc.samplers);
+       pipe->bind_vs_state(pipe, surface->context->states.mc.i_vs);
+       pipe->bind_fs_state(pipe, surface->context->states.mc.i_fs);
+       
+       pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+       
+       return 0;
+}
+
+int vlRenderPMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       enum VL_MC_TYPE mc_type,
+       struct VL_MOTION_VECTOR *motion_vector,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *ref_surface,
+       struct VL_SURFACE *surface
+)
+{
+       struct pipe_context     *pipe;
+       struct VL_MC_VS_CONSTS  *vs_consts;
+       
+       assert(motion_vectors);
+       assert(blocks);
+       assert(ref_surface);
+       assert(surface);
+       
+       /* TODO: Implement interlaced rendering */
+       if (picture_type != VL_FRAME_PICTURE)
+               return 0;
+       /* TODO: Implement other MC types */
+       if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC)
+               return 0;
+       
+       vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
+       
+       pipe = surface->context->pipe;
+       
+       vs_consts = pipe->winsys->buffer_map
+       (
+               pipe->winsys,
+               surface->context->states.mc.vs_const_buf.buffer,
+               PIPE_BUFFER_USAGE_CPU_WRITE
+       );
+       
+       vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+       vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+       vs_consts->scale.z = 1.0f;
+       vs_consts->scale.w = 1.0f;
+       vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+       vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+       vs_consts->mb_pos_trans.z = 0.0f;
+       vs_consts->mb_pos_trans.w = 0.0f;
+       vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->top_field.x * 0.5f) / (float)surface->width;
+       vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->top_field.y * 0.5f) / (float)surface->height;
+       vs_consts->mb_tc_trans[0].top_field.z = 0.0f;
+       vs_consts->mb_tc_trans[0].top_field.w = 0.0f;
+       
+       if (mc_type == VL_FIELD_MC)
+       {
+               vs_consts->denorm.x = (float)surface->width;
+               vs_consts->denorm.y = (float)surface->height;
+               
+               vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector->bottom_field.x * 0.5f) / (float)surface->width;
+               vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector->bottom_field.y * 0.5f) / (float)surface->height;
+               vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f;
+               vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f;
+               
+               pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[1]);
+               pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[1]);
+       }
+       else
+       {
+               pipe->bind_vs_state(pipe, surface->context->states.mc.p_vs[0]);
+               pipe->bind_fs_state(pipe, surface->context->states.mc.p_fs[0]);
+       }
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+       
+       surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+       (
+               pipe->screen,
+               surface->texture,
+               0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+       );
+       pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+       
+       surface->context->states.mc.textures[3] = ref_surface->texture;
+       pipe->set_sampler_textures(pipe, 4, surface->context->states.mc.textures);
+       pipe->bind_sampler_states(pipe, 4, (void**)surface->context->states.mc.samplers);
+       
+       pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+       
+       return 0;
+}
+
+int vlRenderBMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       enum VL_MC_TYPE mc_type,
+       struct VL_MOTION_VECTOR *motion_vector,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *past_surface,
+       struct VL_SURFACE *future_surface,
+       struct VL_SURFACE *surface
+)
+{
+       struct pipe_context     *pipe;
+       struct VL_MC_VS_CONSTS  *vs_consts;
+       
+       assert(motion_vectors);
+       assert(blocks);
+       assert(ref_surface);
+       assert(surface);
+       
+       /* TODO: Implement interlaced rendering */
+       if (picture_type != VL_FRAME_PICTURE)
+               return 0;
+       /* TODO: Implement other MC types */
+       if (mc_type != VL_FRAME_MC && mc_type != VL_FIELD_MC)
+               return 0;
+       
+       vlGrabBlocks(surface->context, coded_block_pattern, dct_type, VL_DIFFERENCE_SAMPLE, blocks);
+       
+       pipe = surface->context->pipe;
+       
+       vs_consts = pipe->winsys->buffer_map
+       (
+               pipe->winsys,
+               surface->context->states.mc.vs_const_buf.buffer,
+               PIPE_BUFFER_USAGE_CPU_WRITE
+       );
+       
+       vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->width;
+       vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->height;
+       vs_consts->scale.z = 1.0f;
+       vs_consts->scale.w = 1.0f;
+       vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->width;
+       vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->height;
+       vs_consts->mb_pos_trans.z = 0.0f;
+       vs_consts->mb_pos_trans.w = 0.0f;
+       vs_consts->mb_tc_trans[0].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].top_field.x * 0.5f) / (float)surface->width;
+       vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].top_field.y * 0.5f) / (float)surface->height;
+       vs_consts->mb_tc_trans[0].top_field.z = 0.0f;
+       vs_consts->mb_tc_trans[0].top_field.w = 0.0f;
+       vs_consts->mb_tc_trans[1].top_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].top_field.x * 0.5f) / (float)surface->width;
+       vs_consts->mb_tc_trans[1].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].top_field.y * 0.5f) / (float)surface->height;
+       vs_consts->mb_tc_trans[1].top_field.z = 0.0f;
+       vs_consts->mb_tc_trans[1].top_field.w = 0.0f;
+       
+       if (mc_type == VL_FIELD_MC)
+       {
+               vs_consts->denorm.x = (float)surface->width;
+               vs_consts->denorm.y = (float)surface->height;
+               
+               vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[0].bottom_field.x * 0.5f) / (float)surface->width;
+               vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[0].bottom_field.y * 0.5f) / (float)surface->height;
+               vs_consts->mb_tc_trans[0].bottom_field.z = 0.0f;
+               vs_consts->mb_tc_trans[0].bottom_field.w = 0.0f;
+               vs_consts->mb_tc_trans[1].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + motion_vector[1].bottom_field.x * 0.5f) / (float)surface->width;
+               vs_consts->mb_tc_trans[1].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + motion_vector[1].bottom_field.y * 0.5f) / (float)surface->height;
+               vs_consts->mb_tc_trans[1].bottom_field.z = 0.0f;
+               vs_consts->mb_tc_trans[1].bottom_field.w = 0.0f;
+               
+               pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[1]);
+               pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[1]);
+       }
+       else
+       {
+               pipe->bind_vs_state(pipe, surface->context->states.mc.b_vs[0]);
+               pipe->bind_fs_state(pipe, surface->context->states.mc.b_fs[0]);
+       }
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.mc.vs_const_buf.buffer);
+       
+       surface->context->states.mc.render_target.cbufs[0] = pipe->screen->get_tex_surface
+       (
+               pipe->screen,
+               surface->texture,
+               0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+       );
+       pipe->set_framebuffer_state(pipe, &surface->context->states.mc.render_target);
+       
+       surface->context->states.mc.textures[3] = past_surface->texture;
+       surface->context->states.mc.textures[4] = future_surface->texture;
+       pipe->set_sampler_textures(pipe, 5, surface->context->states.mc.textures);
+       pipe->bind_sampler_states(pipe, 5, (void**)surface->context->states.mc.samplers);
+       
+       pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+       
+       return 0;
+}
+
+int vlPutSurface
+(
+       struct VL_SURFACE *surface,
+       Drawable drawable,
+       unsigned int srcx,
+       unsigned int srcy,
+       unsigned int srcw,
+       unsigned int srch,
+       unsigned int destx,
+       unsigned int desty,
+       unsigned int destw,
+       unsigned int desth,
+       enum VL_PICTURE picture_type
+)
+{
+       unsigned int            create_fb = 0;
+       struct pipe_context     *pipe;
+       struct VL_CSC_VS_CONSTS *vs_consts;
+       
+       assert(surface);
+       
+       pipe = surface->context->pipe;
+       
+       if (!surface->context->states.csc.framebuffer.cbufs[0])
+               create_fb = 1;
+       else if
+       (
+               surface->context->states.csc.framebuffer.width != destw ||
+               surface->context->states.csc.framebuffer.height != desth
+       )
+       {
+               pipe->winsys->surface_release
+               (
+                       pipe->winsys,
+                       &surface->context->states.csc.framebuffer.cbufs[0]
+               );
+               
+               create_fb = 1;
+       }
+       
+       if (create_fb)
+       {
+               surface->context->states.csc.viewport.scale[0] = destw;
+               surface->context->states.csc.viewport.scale[1] = desth;
+               surface->context->states.csc.viewport.scale[2] = 1;
+               surface->context->states.csc.viewport.scale[3] = 1;
+               surface->context->states.csc.viewport.translate[0] = 0;
+               surface->context->states.csc.viewport.translate[1] = 0;
+               surface->context->states.csc.viewport.translate[2] = 0;
+               surface->context->states.csc.viewport.translate[3] = 0;
+               
+               surface->context->states.csc.framebuffer.width = destw;
+               surface->context->states.csc.framebuffer.height = desth;
+               surface->context->states.csc.framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys);
+               pipe->winsys->surface_alloc_storage
+               (
+                       pipe->winsys,
+                       surface->context->states.csc.framebuffer.cbufs[0],
+                       destw,
+                       desth,
+                       PIPE_FORMAT_A8R8G8B8_UNORM,
+                       /* XXX: SoftPipe doesn't change GPU usage to CPU like it does for textures */
+                       PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE,
+                       0
+               );
+       }
+       
+       vlEndRender(surface->context);
+       
+       vs_consts = pipe->winsys->buffer_map
+       (
+               pipe->winsys,
+               surface->context->states.csc.vs_const_buf.buffer,
+               PIPE_BUFFER_USAGE_CPU_WRITE
+       );
+       
+       vs_consts->src_scale.x = srcw / (float)surface->width;
+       vs_consts->src_scale.y = srch / (float)surface->height;
+       vs_consts->src_scale.z = 1;
+       vs_consts->src_scale.w = 1;
+       vs_consts->src_trans.x = srcx / (float)surface->width;
+       vs_consts->src_trans.y = srcy / (float)surface->height;
+       vs_consts->src_trans.z = 0;
+       vs_consts->src_trans.w = 0;
+       
+       pipe->winsys->buffer_unmap(pipe->winsys, surface->context->states.csc.vs_const_buf.buffer);
+       
+       pipe->set_sampler_textures(pipe, 1, &surface->texture);
+       pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+       pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+       /* TODO: Need to take destx, desty into consideration */
+       pipe->winsys->flush_frontbuffer
+       (
+               pipe->winsys,
+               surface->context->states.csc.framebuffer.cbufs[0],
+               &drawable
+       );
+       
+       vlBeginRender(surface->context);
+       
+       return 0;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h
new file mode 100644 (file)
index 0000000..9f56b77
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef vl_surface_h
+#define vl_surface_h
+
+#include <X11/Xlib.h>
+#include "vl_types.h"
+
+struct pipe_texture;
+
+struct VL_SURFACE
+{
+       struct VL_CONTEXT       *context;
+       unsigned int            width;
+       unsigned int            height;
+       enum VL_FORMAT          format;
+       struct pipe_texture     *texture;
+};
+
+int vlCreateSurface(struct VL_CONTEXT *context, struct VL_SURFACE **surface);
+
+int vlDestroySurface(struct VL_SURFACE *surface);
+
+int vlRenderIMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *surface
+);
+
+int vlRenderPMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       enum VL_MC_TYPE mc_type,
+       struct VL_MOTION_VECTOR *motion_vector,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *ref_surface,
+       struct VL_SURFACE *surface
+);
+
+int vlRenderBMacroBlock
+(
+       enum VL_PICTURE picture_type,
+       enum VL_FIELD_ORDER field_order,
+       unsigned int mbx,
+       unsigned int mby,
+       enum VL_MC_TYPE mc_type,
+       struct VL_MOTION_VECTOR *motion_vector,
+       unsigned int coded_block_pattern,
+       enum VL_DCT_TYPE dct_type,
+       short *blocks,
+       struct VL_SURFACE *past_surface,
+       struct VL_SURFACE *future_surface,
+       struct VL_SURFACE *surface
+);
+
+int vlPutSurface
+(
+       struct VL_SURFACE *surface,
+       Drawable drawable,
+       unsigned int srcx,
+       unsigned int srcy,
+       unsigned int srcw,
+       unsigned int srch,
+       unsigned int destx,
+       unsigned int desty,
+       unsigned int destw,
+       unsigned int desth,
+       enum VL_PICTURE picture_type
+);
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_types.h b/src/gallium/state_trackers/g3dvl/vl_types.h
new file mode 100644 (file)
index 0000000..4d210c9
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef vl_types_h
+#define vl_types_h
+
+enum VL_FORMAT
+{
+       VL_FORMAT_YCBCR_420,
+       VL_FORMAT_YCBCR_422,
+       VL_FORMAT_YCBCR_444
+};
+
+enum VL_PICTURE
+{
+       VL_TOP_FIELD,
+       VL_BOTTOM_FIELD,
+       VL_FRAME_PICTURE
+};
+
+enum VL_FIELD_ORDER
+{
+       VL_FIELD_FIRST,
+       VL_FIELD_SECOND
+};
+
+enum VL_DCT_TYPE
+{
+       VL_DCT_FIELD_CODED,
+       VL_DCT_FRAME_CODED
+};
+
+enum VL_SAMPLE_TYPE
+{
+       VL_FULL_SAMPLE,
+       VL_DIFFERENCE_SAMPLE
+};
+
+enum VL_MC_TYPE
+{
+       VL_FIELD_MC,
+       VL_FRAME_MC,
+       VL_DUAL_PRIME_MC,
+       VL_16x8_MC = VL_FRAME_MC
+};
+
+struct VL_VERTEX4F
+{
+       float x, y, z, w;
+};
+
+struct VL_VERTEX2F
+{
+       float x, y;
+};
+
+struct VL_TEXCOORD2F
+{
+       float s, t;
+};
+
+struct VL_MC_VS_CONSTS
+{
+       struct VL_VERTEX4F      scale;
+       struct VL_VERTEX4F      mb_pos_trans;
+       struct VL_VERTEX4F      denorm;
+       struct
+       {
+               struct VL_VERTEX4F      top_field;
+               struct VL_VERTEX4F      bottom_field;
+       } mb_tc_trans[2];
+};
+
+struct VL_MC_FS_CONSTS
+{
+       struct VL_VERTEX4F      multiplier;
+       struct VL_VERTEX4F      bias;
+       struct VL_VERTEX4F      y_divider;
+};
+
+struct VL_CSC_VS_CONSTS
+{
+       struct VL_VERTEX4F      src_scale;
+       struct VL_VERTEX4F      src_trans;
+};
+
+struct VL_CSC_FS_CONSTS
+{
+       struct VL_VERTEX4F      bias;
+       float                   matrix[16];
+};
+
+struct VL_MOTION_VECTOR
+{
+       struct
+       {
+               int x, y;
+       } top_field, bottom_field;
+};
+
+struct VL_CONTEXT;
+struct VL_SURFACE;
+
+#endif
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_util.c b/src/gallium/state_trackers/g3dvl/vl_util.c
new file mode 100644 (file)
index 0000000..2421ae2
--- /dev/null
@@ -0,0 +1,17 @@
+#include "vl_util.h"
+#include <assert.h>
+
+unsigned int vlRoundUpPOT(unsigned int x)
+{
+       unsigned int i;
+       
+       assert(x > 0);
+       
+       --x;
+       
+       for (i = 1; i < sizeof(unsigned int) * 8; i <<= 1)
+               x |= x >> i;
+       
+       return x + 1;
+}
+
diff --git a/src/gallium/state_trackers/g3dvl/vl_util.h b/src/gallium/state_trackers/g3dvl/vl_util.h
new file mode 100644 (file)
index 0000000..e4b72c4
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef vl_util_h
+#define vl_util_h
+
+unsigned int vlRoundUpPOT(unsigned int x);
+
+#endif
+
diff --git a/src/gallium/winsys/dri/nouveau/Makefile b/src/gallium/winsys/dri/nouveau/Makefile
new file mode 100644 (file)
index 0000000..be630ff
--- /dev/null
@@ -0,0 +1,45 @@
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau_dri.so
+
+MINIGLX_SOURCES =
+
+PIPE_DRIVERS = \
+       $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
+       $(TOP)/src/gallium/drivers/nv04/libnv04.a \
+       $(TOP)/src/gallium/drivers/nv10/libnv10.a \
+       $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+       $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+       $(TOP)/src/gallium/drivers/nv50/libnv50.a
+
+DRIVER_SOURCES = \
+       nouveau_bo.c \
+       nouveau_channel.c \
+       nouveau_context.c \
+       nouveau_device.c \
+       nouveau_dma.c \
+       nouveau_fence.c \
+       nouveau_grobj.c \
+       nouveau_lock.c \
+       nouveau_notifier.c \
+       nouveau_pushbuf.c \
+       nouveau_resource.c \
+       nouveau_screen.c \
+       nouveau_swapbuffers.c \
+       nouveau_winsys.c \
+       nouveau_winsys_pipe.c \
+       nouveau_winsys_softpipe.c \
+       nv04_surface.c \
+       nv50_surface.c
+
+C_SOURCES = \
+       $(COMMON_GALLIUM_SOURCES) \
+       $(DRIVER_SOURCES)
+
+ASM_SOURCES = 
+
+include ../Makefile.template
+
+symlinks:
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_bo.c b/src/gallium/winsys/dri/nouveau/nouveau_bo.c
new file mode 100644 (file)
index 0000000..b594299
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+#include "nouveau_local.h"
+
+static void
+nouveau_mem_free(struct nouveau_device *dev, struct drm_nouveau_mem_alloc *ma,
+                void **map)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct drm_nouveau_mem_free mf;
+
+       if (map && *map) {
+               drmUnmap(*map, ma->size);
+               *map = NULL;
+       }
+
+       if (ma->size) {
+               mf.offset = ma->offset;
+               mf.flags = ma->flags;
+               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_MEM_FREE,
+                               &mf, sizeof(mf));
+               ma->size = 0;
+       }
+}
+
+static int
+nouveau_mem_alloc(struct nouveau_device *dev, unsigned size, unsigned align,
+                 uint32_t flags, struct drm_nouveau_mem_alloc *ma, void **map)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       int ret;
+
+       ma->alignment = align;
+       ma->size = size;
+       ma->flags = flags;
+       if (map)
+               ma->flags |= NOUVEAU_MEM_MAPPED;
+       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_MEM_ALLOC, ma,
+                                 sizeof(struct drm_nouveau_mem_alloc));
+       if (ret)
+               return ret;
+
+       if (map) {
+               ret = drmMap(nvdev->fd, ma->map_handle, ma->size, map);
+               if (ret) {
+                       *map = NULL;
+                       nouveau_mem_free(dev, ma, map);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static void
+nouveau_bo_tmp_del(void *priv)
+{
+       struct nouveau_resource *r = priv;
+
+       nouveau_fence_ref(NULL, (struct nouveau_fence **)&r->priv);
+       nouveau_resource_free(&r);
+}
+
+static unsigned
+nouveau_bo_tmp_max(struct nouveau_device_priv *nvdev)
+{
+       struct nouveau_resource *r = nvdev->sa_heap;
+       unsigned max = 0;
+
+       while (r) {
+               if (r->in_use && !nouveau_fence(r->priv)->emitted) {
+                       r = r->next;
+                       continue;
+               }
+
+               if (max < r->size)
+                       max = r->size;
+               r = r->next;
+       }
+
+       return max;
+}
+
+static struct nouveau_resource *
+nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size,
+              struct nouveau_fence *fence)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
+       struct nouveau_resource *r = NULL;
+       struct nouveau_fence *ref = NULL;
+
+       if (fence)
+               nouveau_fence_ref(fence, &ref);
+       else
+               nouveau_fence_new(chan, &ref);
+       assert(ref);
+
+       while (nouveau_resource_alloc(nvdev->sa_heap, size, ref, &r)) {
+               if (nouveau_bo_tmp_max(nvdev) < size) {
+                       nouveau_fence_ref(NULL, &ref);
+                       return NULL;
+               }
+
+               nouveau_fence_flush(chan);
+       }
+       nouveau_fence_signal_cb(ref, nouveau_bo_tmp_del, r);
+
+       return r;
+}
+
+int
+nouveau_bo_init(struct nouveau_device *dev)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       int ret;
+
+       ret = nouveau_mem_alloc(dev, 128*1024, 0, NOUVEAU_MEM_AGP |
+                               NOUVEAU_MEM_PCI, &nvdev->sa, &nvdev->sa_map);
+       if (ret)
+               return ret;
+
+       ret = nouveau_resource_init(&nvdev->sa_heap, 0, nvdev->sa.size);
+       if (ret) {
+               nouveau_mem_free(dev, &nvdev->sa, &nvdev->sa_map);
+               return ret;
+       }
+
+       return 0;
+}
+
+void
+nouveau_bo_takedown(struct nouveau_device *dev)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+
+       nouveau_mem_free(dev, &nvdev->sa, &nvdev->sa_map);
+}
+
+int
+nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
+              int size, struct nouveau_bo **bo)
+{
+       struct nouveau_bo_priv *nvbo;
+       int ret;
+
+       if (!dev || !bo || *bo)
+               return -EINVAL;
+
+       nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
+       if (!nvbo)
+               return -ENOMEM;
+       nvbo->base.device = dev;
+       nvbo->base.size = size;
+       nvbo->base.handle = bo_to_ptr(nvbo);
+       nvbo->drm.alignment = align;
+       nvbo->refcount = 1;
+
+       if (flags & NOUVEAU_BO_TILED) {
+               nvbo->tiled = 1;
+               if (flags & NOUVEAU_BO_ZTILE)
+                       nvbo->tiled |= 2;
+               flags &= ~NOUVEAU_BO_TILED;
+       }
+
+       ret = nouveau_bo_set_status(&nvbo->base, flags);
+       if (ret) {
+               free(nvbo);
+               return ret;
+       }
+
+       *bo = &nvbo->base;
+       return 0;
+}
+
+int
+nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
+               struct nouveau_bo **bo)
+{
+       struct nouveau_bo_priv *nvbo;
+
+       if (!dev || !bo || *bo)
+               return -EINVAL;
+
+       nvbo = calloc(1, sizeof(*nvbo));
+       if (!nvbo)
+               return -ENOMEM;
+       nvbo->base.device = dev;
+       
+       nvbo->sysmem = ptr;
+       nvbo->user = 1;
+
+       nvbo->base.size = size;
+       nvbo->base.offset = nvbo->drm.offset;
+       nvbo->base.handle = bo_to_ptr(nvbo);
+       nvbo->refcount = 1;
+       *bo = &nvbo->base;
+       return 0;
+}
+
+int
+nouveau_bo_ref(struct nouveau_device *dev, uint64_t handle,
+              struct nouveau_bo **bo)
+{
+       struct nouveau_bo_priv *nvbo = ptr_to_bo(handle);
+
+       if (!dev || !bo || *bo)
+               return -EINVAL;
+
+       nvbo->refcount++;
+       *bo = &nvbo->base;
+       return 0;
+}
+
+static void
+nouveau_bo_del_cb(void *priv)
+{
+       struct nouveau_bo_priv *nvbo = priv;
+
+       nouveau_fence_ref(NULL, &nvbo->fence);
+       nouveau_mem_free(nvbo->base.device, &nvbo->drm, &nvbo->map);
+       if (nvbo->sysmem && !nvbo->user)
+               free(nvbo->sysmem);
+       free(nvbo);
+}
+
+void
+nouveau_bo_del(struct nouveau_bo **bo)
+{
+       struct nouveau_bo_priv *nvbo;
+
+       if (!bo || !*bo)
+               return;
+       nvbo = nouveau_bo(*bo);
+       *bo = NULL;
+
+       if (--nvbo->refcount)
+               return;
+
+       if (nvbo->pending)
+               nouveau_pushbuf_flush(nvbo->pending->channel, 0);
+
+       if (nvbo->fence)
+               nouveau_fence_signal_cb(nvbo->fence, nouveau_bo_del_cb, nvbo);
+       else
+               nouveau_bo_del_cb(nvbo);
+}
+
+int
+nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+
+       if (!nvbo)
+               return -EINVAL;
+
+       if (nvbo->pending &&
+           (nvbo->pending->flags & NOUVEAU_BO_WR || flags & NOUVEAU_BO_WR)) {
+               nouveau_pushbuf_flush(nvbo->pending->channel, 0);
+       }
+
+       if (flags & NOUVEAU_BO_WR)
+               nouveau_fence_wait(&nvbo->fence);
+       else
+               nouveau_fence_wait(&nvbo->wr_fence);
+
+       if (nvbo->sysmem)
+               bo->map = nvbo->sysmem;
+       else
+               bo->map = nvbo->map;
+       return 0;
+}
+
+void
+nouveau_bo_unmap(struct nouveau_bo *bo)
+{
+       bo->map = NULL;
+}
+
+static int
+nouveau_bo_upload(struct nouveau_bo_priv *nvbo)
+{
+       if (nvbo->fence)
+               nouveau_fence_wait(&nvbo->fence);
+       memcpy(nvbo->map, nvbo->sysmem, nvbo->drm.size);
+       return 0;
+}
+
+int
+nouveau_bo_set_status(struct nouveau_bo *bo, uint32_t flags)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct drm_nouveau_mem_alloc new;
+       void *new_map = NULL, *new_sysmem = NULL;
+       unsigned new_flags = 0, ret;
+
+       assert(!bo->map);
+
+       /* Check current memtype vs requested, if they match do nothing */
+       if ((nvbo->drm.flags & NOUVEAU_MEM_FB) && (flags & NOUVEAU_BO_VRAM))
+               return 0;
+       if ((nvbo->drm.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI)) &&
+           (flags & NOUVEAU_BO_GART))
+               return 0;
+       if (nvbo->drm.size == 0 && nvbo->sysmem && (flags & NOUVEAU_BO_LOCAL))
+               return 0;
+
+       memset(&new, 0x00, sizeof(new));
+
+       /* Allocate new memory */
+       if (flags & NOUVEAU_BO_VRAM)
+               new_flags |= NOUVEAU_MEM_FB;
+       else
+       if (flags & NOUVEAU_BO_GART)
+               new_flags |= (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI);
+       
+       if (nvbo->tiled && flags) {
+               new_flags |= NOUVEAU_MEM_TILE;
+               if (nvbo->tiled & 2)
+                       new_flags |= NOUVEAU_MEM_TILE_ZETA;
+       }
+
+       if (new_flags) {
+               ret = nouveau_mem_alloc(bo->device, bo->size,
+                                       nvbo->drm.alignment, new_flags,
+                                       &new, &new_map);
+               if (ret)
+                       return ret;
+       } else
+       if (!nvbo->user) {
+               new_sysmem = malloc(bo->size);
+       }
+
+       /* Copy old -> new */
+       /*XXX: use M2MF */
+       if (nvbo->sysmem || nvbo->map) {
+               struct nouveau_pushbuf_bo *pbo = nvbo->pending;
+               nvbo->pending = NULL;
+               nouveau_bo_map(bo, NOUVEAU_BO_RD);
+               memcpy(new_map, bo->map, bo->size);
+               nouveau_bo_unmap(bo);
+               nvbo->pending = pbo;
+       }
+
+       /* Free old memory */
+       if (nvbo->fence)
+               nouveau_fence_wait(&nvbo->fence);
+       nouveau_mem_free(bo->device, &nvbo->drm, &nvbo->map);
+       if (nvbo->sysmem && !nvbo->user)
+               free(nvbo->sysmem);
+
+       nvbo->drm = new;
+       nvbo->map = new_map;
+       if (!nvbo->user)
+               nvbo->sysmem = new_sysmem;
+       bo->flags = flags;
+       bo->offset = nvbo->drm.offset;
+       return 0;
+}
+
+static int
+nouveau_bo_validate_user(struct nouveau_channel *chan, struct nouveau_bo *bo,
+                        struct nouveau_fence *fence, uint32_t flags)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct nouveau_resource *r;
+
+       if (nvchan->user_charge + bo->size > nvdev->sa.size)
+               return 1;
+
+       if (!(flags & NOUVEAU_BO_GART))
+               return 1;
+
+       r = nouveau_bo_tmp(chan, bo->size, fence);
+       if (!r)
+               return 1;
+       nvchan->user_charge += bo->size;
+
+       memcpy(nvdev->sa_map + r->start, nvbo->sysmem, bo->size);
+
+       nvbo->offset = nvdev->sa.offset + r->start;
+       nvbo->flags = NOUVEAU_BO_GART;
+       return 0;
+}
+
+static int
+nouveau_bo_validate_bo(struct nouveau_channel *chan, struct nouveau_bo *bo,
+                      struct nouveau_fence *fence, uint32_t flags)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       int ret;
+
+       ret = nouveau_bo_set_status(bo, flags);
+       if (ret) {
+               nouveau_fence_flush(chan);
+
+               ret = nouveau_bo_set_status(bo, flags);
+               if (ret)
+                       return ret;
+       }
+
+       if (nvbo->user)
+               nouveau_bo_upload(nvbo);
+
+       nvbo->offset = nvbo->drm.offset;
+       if (nvbo->drm.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI))
+               nvbo->flags = NOUVEAU_BO_GART;
+       else
+               nvbo->flags = NOUVEAU_BO_VRAM;
+
+       return 0;
+}
+
+int
+nouveau_bo_validate(struct nouveau_channel *chan, struct nouveau_bo *bo,
+                   uint32_t flags)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct nouveau_fence *fence = nouveau_pushbuf(chan->pushbuf)->fence;
+       int ret;
+
+       assert(bo->map == NULL);
+
+       if (nvbo->user) {
+               ret = nouveau_bo_validate_user(chan, bo, fence, flags);
+               if (ret) {
+                       ret = nouveau_bo_validate_bo(chan, bo, fence, flags);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               ret = nouveau_bo_validate_bo(chan, bo, fence, flags);
+               if (ret)
+                       return ret;
+       }
+
+       if (flags & NOUVEAU_BO_WR)
+               nouveau_fence_ref(fence, &nvbo->wr_fence);
+       nouveau_fence_ref(fence, &nvbo->fence);
+       return 0;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_channel.c b/src/gallium/winsys/dri/nouveau/nouveau_channel.c
new file mode 100644 (file)
index 0000000..3b4dcd1
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+
+int
+nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma,
+                     uint32_t tt_ctxdma, struct nouveau_channel **chan)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct nouveau_channel_priv *nvchan;
+       int ret;
+
+       if (!nvdev || !chan || *chan)
+           return -EINVAL;
+
+       nvchan = calloc(1, sizeof(struct nouveau_channel_priv));
+       if (!nvchan)
+               return -ENOMEM;
+       nvchan->base.device = dev;
+
+       nvchan->drm.fb_ctxdma_handle = fb_ctxdma;
+       nvchan->drm.tt_ctxdma_handle = tt_ctxdma;
+       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+                                 &nvchan->drm, sizeof(nvchan->drm));
+       if (ret) {
+               free(nvchan);
+               return ret;
+       }
+
+       nvchan->base.id = nvchan->drm.channel;
+       if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle,
+                             &nvchan->base.vram) ||
+           nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle,
+                             &nvchan->base.gart)) {
+               nouveau_channel_free((void *)&nvchan);
+               return -EINVAL;
+       }
+
+       ret = drmMap(nvdev->fd, nvchan->drm.ctrl, nvchan->drm.ctrl_size,
+                    (void*)&nvchan->user);
+       if (ret) {
+               nouveau_channel_free((void *)&nvchan);
+               return ret;
+       }
+       nvchan->put     = &nvchan->user[0x40/4];
+       nvchan->get     = &nvchan->user[0x44/4];
+       nvchan->ref_cnt = &nvchan->user[0x48/4];
+
+       ret = drmMap(nvdev->fd, nvchan->drm.notifier, nvchan->drm.notifier_size,
+                    (drmAddressPtr)&nvchan->notifier_block);
+       if (ret) {
+               nouveau_channel_free((void *)&nvchan);
+               return ret;
+       }
+
+       ret = drmMap(nvdev->fd, nvchan->drm.cmdbuf, nvchan->drm.cmdbuf_size,
+                    (void*)&nvchan->pushbuf);
+       if (ret) {
+               nouveau_channel_free((void *)&nvchan);
+               return ret;
+       }
+
+       ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030,
+                                 &nvchan->base.nullobj);
+       if (ret) {
+               nouveau_channel_free((void *)&nvchan);
+               return ret;
+       }
+
+       nouveau_dma_channel_init(&nvchan->base);
+       nouveau_pushbuf_init(&nvchan->base);
+
+       *chan = &nvchan->base;
+       return 0;
+}
+
+void
+nouveau_channel_free(struct nouveau_channel **chan)
+{
+       struct nouveau_channel_priv *nvchan;
+       struct nouveau_device_priv *nvdev;
+       struct drm_nouveau_channel_free cf;
+
+       if (!chan || !*chan)
+               return;
+       nvchan = nouveau_channel(*chan);
+       *chan = NULL;
+       nvdev = nouveau_device(nvchan->base.device);
+       
+       FIRE_RING_CH(&nvchan->base);
+
+       nouveau_grobj_free(&nvchan->base.vram);
+       nouveau_grobj_free(&nvchan->base.gart);
+       nouveau_grobj_free(&nvchan->base.nullobj);
+
+       cf.channel = nvchan->drm.channel;
+       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf));
+       free(nvchan);
+}
+
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.c b/src/gallium/winsys/dri/nouveau/nouveau_context.c
new file mode 100644 (file)
index 0000000..74413c4
--- /dev/null
@@ -0,0 +1,346 @@
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
+#include "utils.h"
+
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+
+#include "nouveau_context.h"
+#include "nouveau_dri.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_winsys_pipe.h"
+
+#ifdef DEBUG
+static const struct dri_debug_control debug_control[] = {
+       { "bo", DEBUG_BO },
+       { NULL, 0 }
+};
+int __nouveau_debug = 0;
+#endif
+
+static void
+nouveau_channel_context_destroy(struct nouveau_channel_context *nvc)
+{
+       nouveau_grobj_free(&nvc->NvCtxSurf2D);
+       nouveau_grobj_free(&nvc->NvImageBlit);
+       nouveau_grobj_free(&nvc->NvGdiRect);
+       nouveau_grobj_free(&nvc->NvM2MF);
+       nouveau_grobj_free(&nvc->Nv2D);
+       nouveau_grobj_free(&nvc->NvSwzSurf);
+       nouveau_grobj_free(&nvc->NvSIFM);
+
+       nouveau_notifier_free(&nvc->sync_notifier);
+
+       nouveau_channel_free(&nvc->channel);
+
+       FREE(nvc);
+}
+
+static struct nouveau_channel_context *
+nouveau_channel_context_create(struct nouveau_device *dev)
+{
+       struct nouveau_channel_context *nvc;
+       int ret;
+
+       nvc = CALLOC_STRUCT(nouveau_channel_context);
+       if (!nvc)
+               return NULL;
+
+       if ((ret = nouveau_channel_alloc(dev, 0x8003d001, 0x8003d002,
+                                        &nvc->channel))) {
+               NOUVEAU_ERR("Error creating GPU channel: %d\n", ret);
+               nouveau_channel_context_destroy(nvc);
+               return NULL;
+       }
+
+       nvc->next_handle = 0x80000000;
+
+       if ((ret = nouveau_notifier_alloc(nvc->channel, nvc->next_handle++, 1,
+                                         &nvc->sync_notifier))) {
+               NOUVEAU_ERR("Error creating channel sync notifier: %d\n", ret);
+               nouveau_channel_context_destroy(nvc);
+               return NULL;
+       }
+
+       switch (dev->chipset & 0xf0) {
+       case 0x50:
+       case 0x80:
+       case 0x90:
+               ret = nouveau_surface_channel_create_nv50(nvc);
+               break;
+       default:
+               ret = nouveau_surface_channel_create_nv04(nvc);
+               break;
+       }
+
+       if (ret) {
+               NOUVEAU_ERR("Error initialising surface objects: %d\n", ret);
+               nouveau_channel_context_destroy(nvc);
+               return NULL;
+       }
+
+       return nvc;
+}
+
+GLboolean
+nouveau_context_create(const __GLcontextModes *glVis,
+                      __DRIcontextPrivate *driContextPriv,
+                      void *sharedContextPrivate)
+{
+       __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv;
+       struct nouveau_screen  *nv_screen = driScrnPriv->private;
+       struct nouveau_context *nv = CALLOC_STRUCT(nouveau_context);
+       struct pipe_context *pipe = NULL;
+       struct st_context *st_share = NULL;
+       struct nouveau_channel_context *nvc = NULL;
+       struct nouveau_device *dev = nv_screen->device;
+       int i;
+
+       if (sharedContextPrivate) {
+               st_share = ((struct nouveau_context *)sharedContextPrivate)->st;
+       }
+
+       switch (dev->chipset & 0xf0) {
+       case 0x10:
+       case 0x20:
+               /* NV10 */
+       case 0x30:
+               /* NV30 */
+       case 0x40:
+       case 0x60:
+               /* NV40 */
+       case 0x50:
+       case 0x80:
+       case 0x90:
+               /* G80 */
+               break;
+       default:
+               NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev->chipset);
+               return GL_FALSE;
+       }
+
+       driContextPriv->driverPrivate = (void *)nv;
+       nv->nv_screen  = nv_screen;
+       nv->dri_screen = driScrnPriv;
+
+       {
+               struct nouveau_device_priv *nvdev = nouveau_device(dev);
+
+               nvdev->ctx  = driContextPriv->hHWContext;
+               nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock;
+       }
+
+       driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache,
+                           nv->dri_screen->myNum, "nouveau");
+#ifdef DEBUG
+       __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"),
+                                             debug_control);
+#endif
+
+       /*XXX: Hack up a fake region and buffer object for front buffer.
+        *     This will go away with TTM, replaced with a simple reference
+        *     of the front buffer handle passed to us by the DDX.
+        */
+       {
+               struct pipe_surface *fb_surf;
+               struct nouveau_pipe_buffer *fb_buf;
+               struct nouveau_bo_priv *fb_bo;
+
+               fb_bo = calloc(1, sizeof(struct nouveau_bo_priv));
+               fb_bo->drm.offset = nv_screen->front_offset;
+               fb_bo->drm.flags = NOUVEAU_MEM_FB;
+               fb_bo->drm.size = nv_screen->front_pitch * 
+                                 nv_screen->front_height;
+               fb_bo->refcount = 1;
+               fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM;
+               fb_bo->base.offset = fb_bo->drm.offset;
+               fb_bo->base.handle = (unsigned long)fb_bo;
+               fb_bo->base.size = fb_bo->drm.size;
+               fb_bo->base.device = nv_screen->device;
+
+               fb_buf = calloc(1, sizeof(struct nouveau_pipe_buffer));
+               fb_buf->bo = &fb_bo->base;
+
+               fb_surf = calloc(1, sizeof(struct pipe_surface));
+               if (nv_screen->front_cpp == 2)
+                       fb_surf->format = PIPE_FORMAT_R5G6B5_UNORM;
+               else
+                       fb_surf->format = PIPE_FORMAT_A8R8G8B8_UNORM;
+               pf_get_block(fb_surf->format, &fb_surf->block);
+               fb_surf->width = nv_screen->front_pitch / nv_screen->front_cpp;
+               fb_surf->height = nv_screen->front_height;
+               fb_surf->stride = fb_surf->width * fb_surf->block.size;
+               fb_surf->refcount = 1;
+               fb_surf->buffer = &fb_buf->base;
+
+               nv->frontbuffer = fb_surf;
+       }
+
+       /* Attempt to share a single channel between multiple contexts from
+        * a single process.
+        */
+       nvc = nv_screen->nvc;
+       if (!nvc && st_share) {
+               struct nouveau_context *snv = st_share->pipe->priv;
+               if (snv) {
+                       nvc = snv->nvc;
+               }
+       }
+
+       /*XXX: temporary - disable multi-context/single-channel on pre-NV4x */
+       switch (dev->chipset & 0xf0) {
+       case 0x40:
+       case 0x60:
+               /* NV40 class */
+       case 0x50:
+       case 0x80:
+       case 0x90:
+               /* G80 class */
+               break;
+       default:
+               nvc = NULL;
+               break;
+       }
+
+       if (!nvc) {
+               nvc = nouveau_channel_context_create(dev);
+               if (!nvc) {
+                       NOUVEAU_ERR("Failed initialising GPU context\n");
+                       return GL_FALSE;
+               }
+               nv_screen->nvc = nvc;
+       }
+
+       nvc->refcount++;
+       nv->nvc = nvc;
+
+       /* Find a free slot for a pipe context, allocate a new one if needed */
+       nv->pctx_id = -1;
+       for (i = 0; i < nvc->nr_pctx; i++) {
+               if (nvc->pctx[i] == NULL) {
+                       nv->pctx_id = i;
+                       break;
+               }
+       }
+
+       if (nv->pctx_id < 0) {
+               nv->pctx_id = nvc->nr_pctx++;
+               nvc->pctx =
+                       realloc(nvc->pctx,
+                               sizeof(struct pipe_context *) * nvc->nr_pctx);
+       }
+
+       /* Create pipe */
+       switch (dev->chipset & 0xf0) {
+       case 0x50:
+       case 0x80:
+       case 0x90:
+               if (nouveau_surface_init_nv50(nv))
+                       return GL_FALSE;
+               break;
+       default:
+               if (nouveau_surface_init_nv04(nv))
+                       return GL_FALSE;
+               break;
+       }
+
+       if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) {
+               struct pipe_screen *pscreen;
+
+               pipe = nouveau_pipe_create(nv);
+               if (!pipe)
+                       NOUVEAU_ERR("Couldn't create hw pipe\n");
+               pscreen = nvc->pscreen;
+
+               nv->cap.hw_vertex_buffer =
+                       pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF);
+               nv->cap.hw_index_buffer =
+                       pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF);
+       }
+
+       if (!pipe) {
+               NOUVEAU_MSG("Using softpipe\n");
+               pipe = nouveau_create_softpipe(nv);
+               if (!pipe) {
+                       NOUVEAU_ERR("Error creating pipe, bailing\n");
+                       return GL_FALSE;
+               }
+       }
+
+       pipe->priv = nv;
+       nv->st = st_create_context(pipe, glVis, st_share);
+       return GL_TRUE;
+}
+
+void
+nouveau_context_destroy(__DRIcontextPrivate *driContextPriv)
+{
+       struct nouveau_context *nv = driContextPriv->driverPrivate;
+       struct nouveau_channel_context *nvc = nv->nvc;
+
+       assert(nv);
+
+       st_finish(nv->st);
+       st_destroy_context(nv->st);
+
+       if (nv->pctx_id >= 0) {
+               nvc->pctx[nv->pctx_id] = NULL;
+               if (--nvc->refcount <= 0) {
+                       nouveau_channel_context_destroy(nvc);
+                       nv->nv_screen->nvc = NULL;
+               }
+       }
+
+       free(nv);
+}
+
+GLboolean
+nouveau_context_bind(__DRIcontextPrivate *driContextPriv,
+                    __DRIdrawablePrivate *driDrawPriv,
+                    __DRIdrawablePrivate *driReadPriv)
+{
+       struct nouveau_context *nv;
+       struct nouveau_framebuffer *draw, *read;
+
+       if (!driContextPriv) {
+               st_make_current(NULL, NULL, NULL);
+               return GL_TRUE;
+       }
+
+       nv = driContextPriv->driverPrivate;
+       draw = driDrawPriv->driverPrivate;
+       read = driReadPriv->driverPrivate;
+
+       st_make_current(nv->st, draw->stfb, read->stfb);
+
+       if ((nv->dri_drawable != driDrawPriv) ||
+           (nv->last_stamp != driDrawPriv->lastStamp)) {
+               nv->dri_drawable = driDrawPriv;
+               st_resize_framebuffer(draw->stfb, driDrawPriv->w,
+                                     driDrawPriv->h);
+               nv->last_stamp = driDrawPriv->lastStamp;
+       }
+
+       if (driDrawPriv != driReadPriv) {
+               st_resize_framebuffer(read->stfb, driReadPriv->w,
+                                     driReadPriv->h);
+       }
+
+       return GL_TRUE;
+}
+
+GLboolean
+nouveau_context_unbind(__DRIcontextPrivate *driContextPriv)
+{
+       struct nouveau_context *nv = driContextPriv->driverPrivate;
+       (void)nv;
+
+       st_flush(nv->st, 0, NULL);
+       return GL_TRUE;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_context.h b/src/gallium/winsys/dri/nouveau/nouveau_context.h
new file mode 100644 (file)
index 0000000..77e2147
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef __NOUVEAU_CONTEXT_H__
+#define __NOUVEAU_CONTEXT_H__
+
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+
+struct nouveau_framebuffer {
+       struct st_framebuffer *stfb;
+};
+
+struct nouveau_channel_context {
+       struct pipe_screen *pscreen;
+       int refcount;
+
+       unsigned cur_pctx;
+       unsigned nr_pctx;
+       struct pipe_context **pctx;
+
+       struct nouveau_channel  *channel;
+
+       struct nouveau_notifier *sync_notifier;
+
+       /* Common */
+       struct nouveau_grobj    *NvM2MF;
+       /* NV04-NV40 */
+       struct nouveau_grobj    *NvCtxSurf2D;
+       struct nouveau_grobj    *NvSwzSurf;
+       struct nouveau_grobj    *NvImageBlit;
+       struct nouveau_grobj    *NvGdiRect;
+       struct nouveau_grobj    *NvSIFM;
+       /* G80 */
+       struct nouveau_grobj    *Nv2D;
+
+       uint32_t                 next_handle;
+       uint32_t                 next_subchannel;
+       uint32_t                 next_sequence;
+};
+
+struct nouveau_context {
+       struct st_context *st;
+
+       /* DRI stuff */
+       __DRIscreenPrivate    *dri_screen;
+       __DRIdrawablePrivate  *dri_drawable;
+       unsigned int           last_stamp;
+       driOptionCache         dri_option_cache;
+       drm_context_t          drm_context;
+       drmLock                drm_lock;
+       GLboolean              locked;
+       struct nouveau_screen *nv_screen;
+       struct pipe_surface *frontbuffer;
+
+       struct {
+               int hw_vertex_buffer;
+               int hw_index_buffer;
+       } cap;
+
+       /* Hardware context */
+       struct nouveau_channel_context *nvc;
+       int pctx_id;
+
+       /* pipe_surface accel */
+       struct pipe_surface *surf_src, *surf_dst;
+       unsigned surf_src_offset, surf_dst_offset;
+       int  (*surface_copy_prep)(struct nouveau_context *,
+                                 struct pipe_surface *dst,
+                                 struct pipe_surface *src);
+       void (*surface_copy)(struct nouveau_context *, unsigned dx, unsigned dy,
+                            unsigned sx, unsigned sy, unsigned w, unsigned h);
+       void (*surface_copy_done)(struct nouveau_context *);
+       int (*surface_fill)(struct nouveau_context *, struct pipe_surface *,
+                           unsigned, unsigned, unsigned, unsigned, unsigned);
+};
+
+extern GLboolean nouveau_context_create(const __GLcontextModes *,
+                                       __DRIcontextPrivate *, void *);
+extern void nouveau_context_destroy(__DRIcontextPrivate *);
+extern GLboolean nouveau_context_bind(__DRIcontextPrivate *,
+                                     __DRIdrawablePrivate *draw,
+                                     __DRIdrawablePrivate *read);
+extern GLboolean nouveau_context_unbind(__DRIcontextPrivate *);
+
+#ifdef DEBUG
+extern int __nouveau_debug;
+
+#define DEBUG_BO (1 << 0)
+
+#define DBG(flag, ...) do {                   \
+       if (__nouveau_debug & (DEBUG_##flag)) \
+               NOUVEAU_ERR(__VA_ARGS__);     \
+} while(0)
+#else
+#define DBG(flag, ...)
+#endif
+
+extern void LOCK_HARDWARE(struct nouveau_context *);
+extern void UNLOCK_HARDWARE(struct nouveau_context *);
+
+extern int
+nouveau_surface_channel_create_nv04(struct nouveau_channel_context *);
+extern int
+nouveau_surface_channel_create_nv50(struct nouveau_channel_context *);
+extern int nouveau_surface_init_nv04(struct nouveau_context *);
+extern int nouveau_surface_init_nv50(struct nouveau_context *);
+
+extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int);
+extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *);
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_device.c b/src/gallium/winsys/dri/nouveau/nouveau_device.c
new file mode 100644 (file)
index 0000000..0b452fc
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+
+int
+nouveau_device_open_existing(struct nouveau_device **dev, int close,
+                            int fd, drm_context_t ctx)
+{
+       struct nouveau_device_priv *nvdev;
+       int ret;
+
+       if (!dev || *dev)
+           return -EINVAL;
+
+       nvdev = calloc(1, sizeof(*nvdev));
+       if (!nvdev)
+           return -ENOMEM;
+       nvdev->fd = fd;
+       nvdev->ctx = ctx;
+       nvdev->needs_close = close;
+
+       drmCommandNone(nvdev->fd, DRM_NOUVEAU_CARD_INIT);
+
+       if ((ret = nouveau_bo_init(&nvdev->base))) {
+               nouveau_device_close((void *)&nvdev);
+               return ret;
+       }
+
+       {
+               uint64_t value;
+
+               ret = nouveau_device_get_param(&nvdev->base,
+                                              NOUVEAU_GETPARAM_CHIPSET_ID,
+                                              &value);
+               if (ret) {
+                       nouveau_device_close((void *)&nvdev);
+                       return ret;
+               }
+               nvdev->base.chipset = value;
+       }
+
+       *dev = &nvdev->base;
+       return 0;
+}
+
+int
+nouveau_device_open(struct nouveau_device **dev, const char *busid)
+{
+       drm_context_t ctx;
+       int fd, ret;
+
+       if (!dev || *dev)
+               return -EINVAL;
+
+       fd = drmOpen("nouveau", busid);
+       if (fd < 0)
+               return -EINVAL;
+
+       ret = drmCreateContext(fd, &ctx);
+       if (ret) {
+               drmClose(fd);
+               return ret;
+       }
+
+       ret = nouveau_device_open_existing(dev, 1, fd, ctx);
+       if (ret) {
+           drmDestroyContext(fd, ctx);
+           drmClose(fd);
+           return ret;
+       }
+
+       return 0;
+}
+
+void
+nouveau_device_close(struct nouveau_device **dev)
+{
+       struct nouveau_device_priv *nvdev;
+
+       if (dev || !*dev)
+               return;
+       nvdev = nouveau_device(*dev);
+       *dev = NULL;
+
+       nouveau_bo_takedown(&nvdev->base);
+
+       if (nvdev->needs_close) {
+               drmDestroyContext(nvdev->fd, nvdev->ctx);
+               drmClose(nvdev->fd);
+       }
+       free(nvdev);
+}
+
+int
+nouveau_device_get_param(struct nouveau_device *dev,
+                        uint64_t param, uint64_t *value)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct drm_nouveau_getparam g;
+       int ret;
+
+       if (!nvdev || !value)
+               return -EINVAL;
+
+       g.param = param;
+       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
+                                 &g, sizeof(g));
+       if (ret)
+               return ret;
+
+       *value = g.value;
+       return 0;
+}
+
+int
+nouveau_device_set_param(struct nouveau_device *dev,
+                        uint64_t param, uint64_t value)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct drm_nouveau_setparam s;
+       int ret;
+
+       if (!nvdev)
+               return -EINVAL;
+
+       s.param = param;
+       s.value = value;
+       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
+                                 &s, sizeof(s));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dma.c b/src/gallium/winsys/dri/nouveau/nouveau_dma.c
new file mode 100644 (file)
index 0000000..f8a8ba0
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+#include "nouveau_local.h"
+
+static inline uint32_t
+READ_GET(struct nouveau_channel_priv *nvchan)
+{
+       return *nvchan->get;
+}
+
+static inline void
+WRITE_PUT(struct nouveau_channel_priv *nvchan, uint32_t val)
+{
+       uint32_t put = ((val << 2) + nvchan->dma->base);
+       volatile int dum;
+
+       NOUVEAU_DMA_BARRIER;
+       dum = READ_GET(nvchan);
+
+       *nvchan->put = put;
+       nvchan->dma->put = val;
+#ifdef NOUVEAU_DMA_TRACE
+       NOUVEAU_MSG("WRITE_PUT %d/0x%08x\n", nvchan->drm.channel, put);
+#endif
+
+       NOUVEAU_DMA_BARRIER;
+}
+
+static inline int
+LOCAL_GET(struct nouveau_dma_priv *dma, uint32_t *val)
+{
+       uint32_t get = *val;
+
+       if (get >= dma->base && get <= (dma->base + (dma->max << 2))) {
+               *val = (get - dma->base) >> 2;
+               return 1;
+       }
+
+       return 0;
+}
+
+void
+nouveau_dma_channel_init(struct nouveau_channel *chan)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       int i;
+
+       nvchan->dma = &nvchan->dma_master;
+       nvchan->dma->base = nvchan->drm.put_base;
+       nvchan->dma->cur  = nvchan->dma->put = 0;
+       nvchan->dma->max  = (nvchan->drm.cmdbuf_size >> 2) - 2;
+       nvchan->dma->free = nvchan->dma->max - nvchan->dma->cur;
+
+       RING_SPACE_CH(chan, RING_SKIPS);
+       for (i = 0; i < RING_SKIPS; i++)
+               OUT_RING_CH(chan, 0);
+}
+
+#define CHECK_TIMEOUT() do {                                                   \
+       if ((NOUVEAU_TIME_MSEC() - t_start) > NOUVEAU_DMA_TIMEOUT)             \
+               return - EBUSY;                                                \
+} while(0)
+
+int
+nouveau_dma_wait(struct nouveau_channel *chan, int size)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+       uint32_t get, t_start;
+
+       FIRE_RING_CH(chan);
+
+       t_start = NOUVEAU_TIME_MSEC();
+       while (dma->free < size) {
+               CHECK_TIMEOUT();
+
+               get = READ_GET(nvchan);
+               if (!LOCAL_GET(dma, &get))
+                       continue;
+
+               if (dma->put >= get) {
+                       dma->free = dma->max - dma->cur;
+
+                       if (dma->free < size) {
+#ifdef NOUVEAU_DMA_DEBUG
+                               dma->push_free = 1;
+#endif
+                               OUT_RING_CH(chan, 0x20000000 | dma->base);
+                               if (get <= RING_SKIPS) {
+                                       /*corner case - will be idle*/
+                                       if (dma->put <= RING_SKIPS)
+                                               WRITE_PUT(nvchan,
+                                                         RING_SKIPS + 1);
+
+                                       do {
+                                               CHECK_TIMEOUT();
+                                               get = READ_GET(nvchan);
+                                               if (!LOCAL_GET(dma, &get))
+                                                       get = 0;
+                                       } while (get <= RING_SKIPS);
+                               }
+
+                               WRITE_PUT(nvchan, RING_SKIPS);
+                               dma->cur  = dma->put = RING_SKIPS;
+                               dma->free = get - (RING_SKIPS + 1);
+                       }
+               } else {
+                       dma->free = get - dma->cur - 1;
+               }
+       }
+
+       return 0;
+}
+
+#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
+static void
+nouveau_dma_parse_pushbuf(struct nouveau_channel *chan, int get, int put)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       unsigned mthd_count = 0;
+       
+       while (get != put) {
+               uint32_t gpuget = (get << 2) + nvchan->drm.put_base;
+               uint32_t data;
+
+               if (get < 0 || get >= nvchan->drm.cmdbuf_size) {
+                       NOUVEAU_ERR("DMA_PT 0x%08x\n", gpuget);
+                       assert(0);
+               }
+               data = nvchan->pushbuf[get++];
+
+               if (mthd_count) {
+                       NOUVEAU_MSG("0x%08x 0x%08x\n", gpuget, data);
+                       mthd_count--;
+                       continue;
+               }
+
+               switch (data & 0x60000000) {
+               case 0x00000000:
+                       mthd_count = (data >> 18) & 0x7ff;
+                       NOUVEAU_MSG("0x%08x 0x%08x MTHD "
+                                   "Sc %d Mthd 0x%04x Size %d\n",
+                                   gpuget, data, (data>>13) & 7, data & 0x1ffc,
+                                   mthd_count);
+                       break;
+               case 0x20000000:
+                       get = (data & 0x1ffffffc) >> 2;
+                       NOUVEAU_MSG("0x%08x 0x%08x JUMP 0x%08x\n",
+                                   gpuget, data, data & 0x1ffffffc);
+                       continue;
+               case 0x40000000:
+                       mthd_count = (data >> 18) & 0x7ff;
+                       NOUVEAU_MSG("0x%08x 0x%08x NINC "
+                                   "Sc %d Mthd 0x%04x Size %d\n",
+                                   gpuget, data, (data>>13) & 7, data & 0x1ffc,
+                                   mthd_count);
+                       break;
+               case 0x60000000:
+                       /* DMA_OPCODE_CALL apparently, doesn't seem to work on
+                        * my NV40 at least..
+                        */
+                       /* fall-through */
+               default:
+                       NOUVEAU_MSG("DMA_PUSHER 0x%08x 0x%08x\n",
+                                   gpuget, data);
+                       assert(0);
+               }
+       }
+}
+#endif
+
+void
+nouveau_dma_kickoff(struct nouveau_channel *chan)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+
+       if (dma->cur == dma->put)
+               return;
+
+#ifdef NOUVEAU_DMA_DEBUG
+       if (dma->push_free) {
+               NOUVEAU_ERR("Packet incomplete: %d left\n", dma->push_free);
+               return;
+       }
+#endif
+
+#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
+       nouveau_dma_parse_pushbuf(chan, dma->put, dma->cur);
+#endif
+
+       WRITE_PUT(nvchan, dma->cur);
+}
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dma.h b/src/gallium/winsys/dri/nouveau/nouveau_dma.h
new file mode 100644 (file)
index 0000000..cfa6d26
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_DMA_H__
+#define __NOUVEAU_DMA_H__
+
+#include <string.h>
+#include "nouveau_drmif.h"
+#include "nouveau_local.h"
+
+#define RING_SKIPS 8
+
+extern int  nouveau_dma_wait(struct nouveau_channel *chan, int size);
+extern void nouveau_dma_subc_bind(struct nouveau_grobj *);
+extern void nouveau_dma_channel_init(struct nouveau_channel *);
+extern void nouveau_dma_kickoff(struct nouveau_channel *);
+
+#ifdef NOUVEAU_DMA_DEBUG
+static char faulty[1024];
+#endif
+
+static inline void
+nouveau_dma_out(struct nouveau_channel *chan, uint32_t data)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+
+#ifdef NOUVEAU_DMA_DEBUG
+       if (dma->push_free == 0) {
+               NOUVEAU_ERR("No space left in packet at %s\n", faulty);
+               return;
+       }
+       dma->push_free--;
+#endif
+#ifdef NOUVEAU_DMA_TRACE
+       {
+               uint32_t offset = (dma->cur << 2) + dma->base;
+               NOUVEAU_MSG("\tOUT_RING %d/0x%08x -> 0x%08x\n",
+                           nvchan->drm.channel, offset, data);
+       }
+#endif
+       nvchan->pushbuf[dma->cur + (dma->base - nvchan->drm.put_base)/4] = data;
+       dma->cur++;
+}
+
+static inline void
+nouveau_dma_outp(struct nouveau_channel *chan, uint32_t *ptr, int size)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+       (void)dma;
+
+#ifdef NOUVEAU_DMA_DEBUG
+       if (dma->push_free < size) {
+               NOUVEAU_ERR("Packet too small.  Free=%d, Need=%d\n",
+                           dma->push_free, size);
+               return;
+       }
+#endif
+#ifdef NOUVEAU_DMA_TRACE
+       while (size--) {
+               nouveau_dma_out(chan, *ptr);
+               ptr++;
+       }
+#else
+       memcpy(&nvchan->pushbuf[dma->cur], ptr, size << 2);
+#ifdef NOUVEAU_DMA_DEBUG
+       dma->push_free -= size;
+#endif
+       dma->cur += size;
+#endif
+}
+
+static inline void
+nouveau_dma_space(struct nouveau_channel *chan, int size)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+
+       if (dma->free < size) {
+               if (nouveau_dma_wait(chan, size) && chan->hang_notify)
+                       chan->hang_notify(chan);
+       }
+       dma->free -= size;
+#ifdef NOUVEAU_DMA_DEBUG
+       dma->push_free = size;
+#endif
+}
+
+static inline void
+nouveau_dma_begin(struct nouveau_channel *chan, struct nouveau_grobj *grobj,
+                 int method, int size, const char* file, int line)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *dma = nvchan->dma;
+       (void)dma;
+
+#ifdef NOUVEAU_DMA_TRACE
+       NOUVEAU_MSG("BEGIN_RING %d/%08x/%d/0x%04x/%d\n", nvchan->drm.channel,
+                   grobj->handle, grobj->subc, method, size);
+#endif
+
+#ifdef NOUVEAU_DMA_DEBUG
+       if (dma->push_free) {
+               NOUVEAU_ERR("Previous packet incomplete: %d left at %s\n",
+                           dma->push_free, faulty);
+               return;
+       }
+       sprintf(faulty,"%s:%d",file,line);
+#endif
+
+       nouveau_dma_space(chan, (size + 1));
+       nouveau_dma_out(chan, (size << 18) | (grobj->subc << 13) | method);
+}
+
+#define RING_SPACE_CH(ch,sz)         nouveau_dma_space((ch), (sz))
+#define BEGIN_RING_CH(ch,gr,m,sz)    nouveau_dma_begin((ch), (gr), (m), (sz), __FUNCTION__, __LINE__ )
+#define OUT_RING_CH(ch, data)        nouveau_dma_out((ch), (data))
+#define OUT_RINGp_CH(ch,ptr,dwords)  nouveau_dma_outp((ch), (void*)(ptr),      \
+                                                     (dwords))
+#define FIRE_RING_CH(ch)             nouveau_dma_kickoff((ch))
+#define WAIT_RING_CH(ch,sz)          nouveau_dma_wait((ch), (sz))
+               
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_dri.h b/src/gallium/winsys/dri/nouveau/nouveau_dri.h
new file mode 100644 (file)
index 0000000..1207c2d
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _NOUVEAU_DRI_
+#define _NOUVEAU_DRI_
+
+#include "xf86drm.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+struct nouveau_dri {
+       uint32_t device_id;     /**< \brief PCI device ID */
+       uint32_t width;         /**< \brief width in pixels of display */
+       uint32_t height;        /**< \brief height in scanlines of display */
+       uint32_t depth;         /**< \brief depth of display (8, 15, 16, 24) */
+       uint32_t bpp;           /**< \brief bit depth of display (8, 16, 24, 32) */
+
+       uint32_t bus_type;      /**< \brief ths bus type */
+       uint32_t bus_mode;      /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */
+
+       uint32_t front_offset;  /**< \brief front buffer offset */
+       uint32_t front_pitch;   /**< \brief front buffer pitch */
+       uint32_t back_offset;   /**< \brief private back buffer offset */
+       uint32_t back_pitch;    /**< \brief private back buffer pitch */
+       uint32_t depth_offset;  /**< \brief private depth buffer offset */
+       uint32_t depth_pitch;   /**< \brief private depth buffer pitch */
+
+};
+
+#endif
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_drmif.h b/src/gallium/winsys/dri/nouveau/nouveau_drmif.h
new file mode 100644 (file)
index 0000000..dcd6a5e
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NOUVEAU_DRMIF_H__
+#define __NOUVEAU_DRMIF_H__
+
+#include <stdint.h>
+#include <xf86drm.h>
+#include <nouveau_drm.h>
+
+#include "nouveau/nouveau_device.h"
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_grobj.h"
+#include "nouveau/nouveau_notifier.h"
+#include "nouveau/nouveau_bo.h"
+#include "nouveau/nouveau_resource.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+struct nouveau_device_priv {
+       struct nouveau_device base;
+
+       int fd;
+       drm_context_t ctx;
+       drmLock *lock;
+       int needs_close;
+
+       struct drm_nouveau_mem_alloc sa;
+       void *sa_map;
+       struct nouveau_resource *sa_heap;
+};
+#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
+
+extern int
+nouveau_device_open_existing(struct nouveau_device **, int close,
+                            int fd, drm_context_t ctx);
+
+extern int
+nouveau_device_open(struct nouveau_device **, const char *busid);
+
+extern void
+nouveau_device_close(struct nouveau_device **);
+
+extern int
+nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
+
+extern int
+nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
+
+struct nouveau_fence {
+       struct nouveau_channel *channel;
+};
+
+struct nouveau_fence_cb {
+       struct nouveau_fence_cb *next;
+       void (*func)(void *);
+       void *priv;
+};
+
+struct nouveau_fence_priv {
+       struct nouveau_fence base;
+       int refcount;
+
+       struct nouveau_fence *next;
+       struct nouveau_fence_cb *signal_cb;
+
+       uint32_t sequence;
+       int emitted;
+       int signalled;
+};
+#define nouveau_fence(n) ((struct nouveau_fence_priv *)(n))
+
+extern int
+nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **);
+
+extern int
+nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **);
+
+extern int
+nouveau_fence_signal_cb(struct nouveau_fence *, void (*)(void *), void *);
+
+extern void
+nouveau_fence_emit(struct nouveau_fence *);
+
+extern int
+nouveau_fence_wait(struct nouveau_fence **);
+
+extern void
+nouveau_fence_flush(struct nouveau_channel *);
+
+struct nouveau_pushbuf_reloc {
+       struct nouveau_pushbuf_bo *pbbo;
+       uint32_t *ptr;
+       uint32_t flags;
+       uint32_t data;
+       uint32_t vor;
+       uint32_t tor;
+};
+
+struct nouveau_pushbuf_bo {
+       struct nouveau_channel *channel;
+       struct nouveau_bo *bo;
+       unsigned flags;
+       unsigned handled;
+};
+
+#define NOUVEAU_PUSHBUF_MAX_BUFFERS 1024
+#define NOUVEAU_PUSHBUF_MAX_RELOCS 1024
+struct nouveau_pushbuf_priv {
+       struct nouveau_pushbuf base;
+
+       struct nouveau_fence *fence;
+
+       unsigned nop_jump;
+       unsigned start;
+       unsigned size;
+
+       struct nouveau_pushbuf_bo *buffers;
+       unsigned nr_buffers;
+       struct nouveau_pushbuf_reloc *relocs;
+       unsigned nr_relocs;
+};
+#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
+
+#define pbbo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbbo(h) ((struct nouveau_pushbuf_bo *)(unsigned long)(h))
+#define pbrel_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbrel(h) ((struct nouveau_pushbuf_reloc *)(unsigned long)(h))
+#define bo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_bo(h) ((struct nouveau_bo_priv *)(unsigned long)(h))
+
+extern int
+nouveau_pushbuf_init(struct nouveau_channel *);
+
+extern int
+nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
+
+extern int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
+                          struct nouveau_bo *, uint32_t data, uint32_t flags,
+                          uint32_t vor, uint32_t tor);
+
+struct nouveau_dma_priv {
+       uint32_t base;
+       uint32_t max;
+       uint32_t cur;
+       uint32_t put;
+       uint32_t free;
+
+       int push_free;
+} dma;
+
+struct nouveau_channel_priv {
+       struct nouveau_channel base;
+
+       struct drm_nouveau_channel_alloc drm;
+
+       uint32_t *pushbuf;
+       void     *notifier_block;
+
+       volatile uint32_t *user;
+       volatile uint32_t *put;
+       volatile uint32_t *get;
+       volatile uint32_t *ref_cnt;
+
+       struct nouveau_dma_priv dma_master;
+       struct nouveau_dma_priv dma_bufmgr;
+       struct nouveau_dma_priv *dma;
+
+       struct nouveau_fence *fence_head;
+       struct nouveau_fence *fence_tail;
+       uint32_t fence_sequence;
+
+       struct nouveau_pushbuf_priv pb;
+
+       unsigned user_charge;
+};
+#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
+
+extern int
+nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt,
+                     struct nouveau_channel **);
+
+extern void
+nouveau_channel_free(struct nouveau_channel **);
+
+struct nouveau_grobj_priv {
+       struct nouveau_grobj base;
+};
+#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n))
+
+extern int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle,
+                              int class, struct nouveau_grobj **);
+extern int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle,
+                            struct nouveau_grobj **);
+extern void nouveau_grobj_free(struct nouveau_grobj **);
+
+
+struct nouveau_notifier_priv {
+       struct nouveau_notifier base;
+
+       struct drm_nouveau_notifierobj_alloc drm;
+       volatile void *map;
+};
+#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n))
+
+extern int
+nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count,
+                      struct nouveau_notifier **);
+
+extern void
+nouveau_notifier_free(struct nouveau_notifier **);
+
+extern void
+nouveau_notifier_reset(struct nouveau_notifier *, int id);
+
+extern uint32_t
+nouveau_notifier_status(struct nouveau_notifier *, int id);
+
+extern uint32_t
+nouveau_notifier_return_val(struct nouveau_notifier *, int id);
+
+extern int
+nouveau_notifier_wait_status(struct nouveau_notifier *, int id, int status,
+                            int timeout);
+
+struct nouveau_bo_priv {
+       struct nouveau_bo base;
+
+       struct nouveau_pushbuf_bo *pending;
+       struct nouveau_fence *fence;
+       struct nouveau_fence *wr_fence;
+
+       struct drm_nouveau_mem_alloc drm;
+       void *map;
+
+       void *sysmem;
+       int user;
+
+       int refcount;
+
+       uint64_t offset;
+       uint64_t flags;
+       int tiled;
+};
+#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
+
+extern int
+nouveau_bo_init(struct nouveau_device *);
+
+extern void
+nouveau_bo_takedown(struct nouveau_device *);
+
+extern int
+nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size,
+              struct nouveau_bo **);
+
+extern int
+nouveau_bo_user(struct nouveau_device *, void *ptr, int size,
+               struct nouveau_bo **);
+
+extern int
+nouveau_bo_ref(struct nouveau_device *, uint64_t handle, struct nouveau_bo **);
+
+extern int
+nouveau_bo_set_status(struct nouveau_bo *, uint32_t flags);
+
+extern void
+nouveau_bo_del(struct nouveau_bo **);
+
+extern int
+nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
+
+extern void
+nouveau_bo_unmap(struct nouveau_bo *);
+
+extern int
+nouveau_bo_validate(struct nouveau_channel *, struct nouveau_bo *,
+                   uint32_t flags);
+
+extern int
+nouveau_resource_init(struct nouveau_resource **heap, unsigned start,
+                     unsigned size);
+
+extern int
+nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
+                      struct nouveau_resource **);
+
+extern void
+nouveau_resource_free(struct nouveau_resource **);
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_fence.c b/src/gallium/winsys/dri/nouveau/nouveau_fence.c
new file mode 100644 (file)
index 0000000..e7b0b4f
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+#include "nouveau_local.h"
+
+static void
+nouveau_fence_del_unsignalled(struct nouveau_fence *fence)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel);
+       struct nouveau_fence *le;
+
+       if (nvchan->fence_head == fence) {
+               nvchan->fence_head = nouveau_fence(fence)->next;
+               if (nvchan->fence_head == NULL)
+                       nvchan->fence_tail = NULL;
+               return;
+       }
+
+       le = nvchan->fence_head;
+       while (le && nouveau_fence(le)->next != fence)
+               le = nouveau_fence(le)->next;
+       assert(le && nouveau_fence(le)->next == fence);
+       nouveau_fence(le)->next = nouveau_fence(fence)->next;
+       if (nvchan->fence_tail == fence)
+               nvchan->fence_tail = le;
+}
+
+static void
+nouveau_fence_del(struct nouveau_fence **fence)
+{
+       struct nouveau_fence_priv *nvfence;
+
+       if (!fence || !*fence)
+               return;
+       nvfence = nouveau_fence(*fence);
+       *fence = NULL;
+
+       if (--nvfence->refcount)
+               return;
+
+       if (nvfence->emitted && !nvfence->signalled) {
+               if (nvfence->signal_cb) {
+                       nvfence->refcount++;
+                       nouveau_fence_wait((void *)&nvfence);
+                       return;
+               }
+
+               nouveau_fence_del_unsignalled(&nvfence->base);
+       }
+       free(nvfence);
+}
+
+int
+nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **fence)
+{
+       struct nouveau_fence_priv *nvfence;
+
+       if (!chan || !fence || *fence)
+               return -EINVAL;
+       
+       nvfence = calloc(1, sizeof(struct nouveau_fence_priv));
+       if (!nvfence)
+               return -ENOMEM;
+       nvfence->base.channel = chan;
+       nvfence->refcount = 1;
+
+       *fence = &nvfence->base;
+       return 0;
+}
+
+int
+nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence)
+{
+       struct nouveau_fence_priv *nvfence;
+
+       if (!fence)
+               return -EINVAL;
+
+       if (*fence) {
+               nouveau_fence_del(fence);
+               *fence = NULL;
+       }
+
+       if (ref) {
+               nvfence = nouveau_fence(ref);
+               nvfence->refcount++;    
+               *fence = &nvfence->base;
+       }
+
+       return 0;
+}
+
+int
+nouveau_fence_signal_cb(struct nouveau_fence *fence, void (*func)(void *),
+                       void *priv)
+{
+       struct nouveau_fence_priv *nvfence = nouveau_fence(fence);
+       struct nouveau_fence_cb *cb;
+
+       if (!nvfence || !func)
+               return -EINVAL;
+
+       cb = malloc(sizeof(struct nouveau_fence_cb));
+       if (!cb)
+               return -ENOMEM;
+
+       cb->func = func;
+       cb->priv = priv;
+       cb->next = nvfence->signal_cb;
+       nvfence->signal_cb = cb;
+       return 0;
+}
+
+void
+nouveau_fence_emit(struct nouveau_fence *fence)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel);
+       struct nouveau_fence_priv *nvfence = nouveau_fence(fence);
+
+       nvfence->emitted = 1;
+       nvfence->sequence = ++nvchan->fence_sequence;
+       if (nvfence->sequence == 0xffffffff)
+               NOUVEAU_ERR("AII wrap unhandled\n");
+
+       /*XXX: assumes subc 0 is populated */
+       RING_SPACE_CH(fence->channel, 2);
+       OUT_RING_CH  (fence->channel, 0x00040050);
+       OUT_RING_CH  (fence->channel, nvfence->sequence);
+
+       if (nvchan->fence_tail) {
+               nouveau_fence(nvchan->fence_tail)->next = fence;
+       } else {
+               nvchan->fence_head = fence;
+       }
+       nvchan->fence_tail = fence;
+}
+
+void
+nouveau_fence_flush(struct nouveau_channel *chan)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       uint32_t sequence = *nvchan->ref_cnt;
+
+       while (nvchan->fence_head) {
+               struct nouveau_fence_priv *nvfence;
+       
+               nvfence = nouveau_fence(nvchan->fence_head);
+               if (nvfence->sequence > sequence)
+                       break;
+               nouveau_fence_del_unsignalled(&nvfence->base);
+               nvfence->signalled = 1;
+
+               if (nvfence->signal_cb) {
+                       struct nouveau_fence *fence = NULL;
+
+                       nouveau_fence_ref(&nvfence->base, &fence);
+
+                       while (nvfence->signal_cb) {
+                               struct nouveau_fence_cb *cb;
+                               
+                               cb = nvfence->signal_cb;
+                               nvfence->signal_cb = cb->next;
+                               cb->func(cb->priv);
+                               free(cb);
+                       }
+
+                       nouveau_fence_ref(NULL, &fence);
+               }
+       }
+}
+
+int
+nouveau_fence_wait(struct nouveau_fence **fence)
+{
+       struct nouveau_fence_priv *nvfence;
+       
+       if (!fence || !*fence)
+               return -EINVAL;
+       nvfence = nouveau_fence(*fence);
+
+       if (nvfence->emitted) {
+               while (!nvfence->signalled)
+                       nouveau_fence_flush(nvfence->base.channel);
+       }
+       nouveau_fence_ref(NULL, fence);
+
+       return 0;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_grobj.c b/src/gallium/winsys/dri/nouveau/nouveau_grobj.c
new file mode 100644 (file)
index 0000000..5152389
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+
+int
+nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle,
+                   int class, struct nouveau_grobj **grobj)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
+       struct nouveau_grobj_priv *nvgrobj;
+       struct drm_nouveau_grobj_alloc g;
+       int ret;
+
+       if (!nvdev || !grobj || *grobj)
+               return -EINVAL;
+
+       nvgrobj = calloc(1, sizeof(*nvgrobj));
+       if (!nvgrobj)
+               return -ENOMEM;
+       nvgrobj->base.channel = chan;
+       nvgrobj->base.handle  = handle;
+       nvgrobj->base.grclass = class;
+
+       g.channel = chan->id;
+       g.handle  = handle;
+       g.class   = class;
+       ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
+                             &g, sizeof(g));
+       if (ret) {
+               nouveau_grobj_free((void *)&nvgrobj);
+               return ret;
+       }
+
+       *grobj = &nvgrobj->base;
+       return 0;
+}
+
+int
+nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle,
+                 struct nouveau_grobj **grobj)
+{
+       struct nouveau_grobj_priv *nvgrobj;
+
+       if (!chan || !grobj || *grobj)
+               return -EINVAL;
+
+       nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv));
+       if (!nvgrobj)
+               return -ENOMEM;
+       nvgrobj->base.channel = chan;
+       nvgrobj->base.handle = handle;
+       nvgrobj->base.grclass = 0;
+
+       *grobj = &nvgrobj->base;
+       return 0;
+}
+
+void
+nouveau_grobj_free(struct nouveau_grobj **grobj)
+{
+       struct nouveau_device_priv *nvdev;
+       struct nouveau_channel_priv *chan;
+       struct nouveau_grobj_priv *nvgrobj;
+
+       if (!grobj || !*grobj)
+               return;
+       nvgrobj = nouveau_grobj(*grobj);
+       *grobj = NULL;
+
+
+       chan = nouveau_channel(nvgrobj->base.channel);
+       nvdev = nouveau_device(chan->base.device);
+
+       if (nvgrobj->base.grclass) {
+               struct drm_nouveau_gpuobj_free f;
+
+               f.channel = chan->drm.channel;
+               f.handle  = nvgrobj->base.handle;
+               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
+                               &f, sizeof(f)); 
+       }
+       free(nvgrobj);
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_local.h b/src/gallium/winsys/dri/nouveau/nouveau_local.h
new file mode 100644 (file)
index 0000000..e878a40
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __NOUVEAU_LOCAL_H__
+#define __NOUVEAU_LOCAL_H__
+
+#include "pipe/p_compiler.h"
+#include "nouveau_winsys_pipe.h"
+#include <stdio.h>
+
+struct pipe_buffer;
+
+/* Debug output */
+#define NOUVEAU_MSG(fmt, args...) do {                                         \
+       fprintf(stdout, "nouveau: "fmt, ##args);                               \
+       fflush(stdout);                                                        \
+} while(0)
+
+#define NOUVEAU_ERR(fmt, args...) do {                                         \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);           \
+       fflush(stderr);                                                        \
+} while(0)
+
+#define NOUVEAU_TIME_MSEC() 0
+
+/* User FIFO control */
+//#define NOUVEAU_DMA_TRACE
+//#define NOUVEAU_DMA_DEBUG
+//#define NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
+#define NOUVEAU_DMA_BARRIER 
+#define NOUVEAU_DMA_TIMEOUT 2000
+
+/* Push buffer access macros */
+static INLINE void
+OUT_RING(struct nouveau_channel *chan, unsigned data)
+{
+       *(chan->pushbuf->cur++) = (data);
+}
+
+static INLINE void
+OUT_RINGp(struct nouveau_channel *chan, uint32_t *data, unsigned size)
+{
+       memcpy(chan->pushbuf->cur, data, size * 4);
+       chan->pushbuf->cur += size;
+}
+
+static INLINE void
+OUT_RINGf(struct nouveau_channel *chan, float f)
+{
+       union { uint32_t i; float f; } c;
+       c.f = f;
+       OUT_RING(chan, c.i);
+}
+
+static INLINE void
+BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
+          unsigned mthd, unsigned size)
+{
+       if (chan->pushbuf->remaining < (size + 1))
+               nouveau_pushbuf_flush(chan, (size + 1));
+       OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
+       chan->pushbuf->remaining -= (size + 1);
+}
+
+static INLINE void
+FIRE_RING(struct nouveau_channel *chan)
+{
+       nouveau_pushbuf_flush(chan, 0);
+}
+
+static INLINE void
+BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned subc)
+{
+       gr->subc = subc;
+       BEGIN_RING(chan, gr, 0x0000, 1);
+       OUT_RING  (chan, gr->handle);
+}
+
+static INLINE void
+OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
+         unsigned data, unsigned flags, unsigned vor, unsigned tor)
+{
+       nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
+                                  data, flags, vor, tor);
+}
+
+/* Raw data + flags depending on FB/TT buffer */
+static INLINE void
+OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
+          unsigned data, unsigned flags, unsigned vor, unsigned tor)
+{
+       OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
+}
+
+/* FB/TT object handle */
+static INLINE void
+OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
+          unsigned flags)
+{
+       OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
+                 chan->vram->handle, chan->gart->handle);
+}
+
+/* Low 32-bits of offset */
+static INLINE void
+OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
+          unsigned delta, unsigned flags)
+{
+       OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
+}
+
+/* High 32-bits of offset */
+static INLINE void
+OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
+          unsigned delta, unsigned flags)
+{
+       OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
+}
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_lock.c b/src/gallium/winsys/dri/nouveau/nouveau_lock.c
new file mode 100644 (file)
index 0000000..9adb9ac
--- /dev/null
@@ -0,0 +1,94 @@
+/**************************************************************************
+ * 
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
+
+#include "nouveau_context.h"
+#include "nouveau_screen.h"
+
+_glthread_DECLARE_STATIC_MUTEX( lockMutex );
+
+static void
+nouveau_contended_lock(struct nouveau_context *nv, GLuint flags)
+{
+       __DRIdrawablePrivate *dPriv = nv->dri_drawable;
+       __DRIscreenPrivate *sPriv = nv->dri_screen;
+       struct nouveau_screen *nv_screen = nv->nv_screen;
+       struct nouveau_device *dev = nv_screen->device;
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+
+       drmGetLock(nvdev->fd, nvdev->ctx, flags);
+
+       /* If the window moved, may need to set a new cliprect now.
+        *
+        * NOTE: This releases and regains the hw lock, so all state
+        * checking must be done *after* this call:
+        */
+       if (dPriv)
+               DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+}
+
+/* Lock the hardware and validate our state.
+ */
+void
+LOCK_HARDWARE(struct nouveau_context *nv)
+{
+       struct nouveau_screen *nv_screen = nv->nv_screen;
+       struct nouveau_device *dev = nv_screen->device;
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       char __ret=0;
+
+       _glthread_LOCK_MUTEX(lockMutex);
+       assert(!nv->locked);
+       
+       DRM_CAS(nvdev->lock, nvdev->ctx,
+               (DRM_LOCK_HELD | nvdev->ctx), __ret);
+       
+       if (__ret)
+               nouveau_contended_lock(nv, 0);
+       nv->locked = GL_TRUE;
+}
+
+
+  /* Unlock the hardware using the global current context 
+   */
+void
+UNLOCK_HARDWARE(struct nouveau_context *nv)
+{
+       struct nouveau_screen *nv_screen = nv->nv_screen;
+       struct nouveau_device *dev = nv_screen->device;
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+
+       assert(nv->locked);
+       nv->locked = GL_FALSE;
+
+       DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx);
+
+       _glthread_UNLOCK_MUTEX(lockMutex);
+} 
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_notifier.c b/src/gallium/winsys/dri/nouveau/nouveau_notifier.c
new file mode 100644 (file)
index 0000000..01e8f38
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_local.h"
+
+#define NOTIFIER(__v)                                                          \
+       struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier);   \
+       volatile uint32_t *__v = (void*)nvnotify->map + (id * 32)
+
+int
+nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
+                      int count, struct nouveau_notifier **notifier)
+{
+       struct nouveau_notifier_priv *nvnotify;
+       int ret;
+
+       if (!chan || !notifier || *notifier)
+               return -EINVAL;
+
+       nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv));
+       if (!nvnotify)
+               return -ENOMEM;
+       nvnotify->base.channel = chan;
+       nvnotify->base.handle  = handle;
+
+       nvnotify->drm.channel = chan->id;
+       nvnotify->drm.handle  = handle;
+       nvnotify->drm.count   = count;
+       if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd,
+                                      DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
+                                      &nvnotify->drm,
+                                      sizeof(nvnotify->drm)))) {
+               nouveau_notifier_free((void *)&nvnotify);
+               return ret;
+       }
+
+       nvnotify->map = (void *)nouveau_channel(chan)->notifier_block +
+                               nvnotify->drm.offset;
+       *notifier = &nvnotify->base;
+       return 0;
+}
+
+void
+nouveau_notifier_free(struct nouveau_notifier **notifier)
+{
+
+       struct nouveau_notifier_priv *nvnotify;
+       struct nouveau_channel_priv *nvchan;
+       struct nouveau_device_priv *nvdev;
+       struct drm_nouveau_gpuobj_free f;
+
+       if (!notifier || !*notifier)
+               return;
+       nvnotify = nouveau_notifier(*notifier);
+       *notifier = NULL;
+
+       nvchan = nouveau_channel(nvnotify->base.channel);
+       nvdev   = nouveau_device(nvchan->base.device);
+
+       f.channel = nvchan->drm.channel;
+       f.handle  = nvnotify->base.handle;
+       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));             
+       free(nvnotify);
+}
+
+void
+nouveau_notifier_reset(struct nouveau_notifier *notifier, int id)
+{
+       NOTIFIER(n);
+
+       n[NV_NOTIFY_TIME_0      /4] = 0x00000000;
+       n[NV_NOTIFY_TIME_1      /4] = 0x00000000;
+       n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
+       n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
+                                      NV_NOTIFY_STATE_STATUS_SHIFT);
+}
+
+uint32_t
+nouveau_notifier_status(struct nouveau_notifier *notifier, int id)
+{
+       NOTIFIER(n);
+
+       return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
+}
+
+uint32_t
+nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id)
+{
+       NOTIFIER(n);
+
+       return n[NV_NOTIFY_RETURN_VALUE/4];
+}
+
+int
+nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id,
+                            int status, int timeout)
+{
+       NOTIFIER(n);
+       uint32_t time = 0, t_start = NOUVEAU_TIME_MSEC();
+
+       while (time <= timeout) {
+               uint32_t v;
+
+               v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
+               if (v == status)
+                       return 0;
+
+               if (timeout)
+                       time = NOUVEAU_TIME_MSEC() - t_start;
+       }
+
+       return -EBUSY;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c b/src/gallium/winsys/dri/nouveau/nouveau_pushbuf.c
new file mode 100644 (file)
index 0000000..815046b
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+
+#define PB_BUFMGR_DWORDS   (4096 / 2)
+#define PB_MIN_USER_DWORDS  2048
+
+static int
+nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+
+       assert((min + 1) <= nvchan->dma->max);
+
+       /* Wait for enough space in push buffer */
+       min = min < PB_MIN_USER_DWORDS ? PB_MIN_USER_DWORDS : min;
+       min += 1; /* a bit extra for the NOP */
+       if (nvchan->dma->free < min)
+               WAIT_RING_CH(chan, min);
+
+       /* Insert NOP, may turn into a jump later */
+       RING_SPACE_CH(chan, 1);
+       nvpb->nop_jump = nvchan->dma->cur;
+       OUT_RING_CH(chan, 0);
+
+       /* Any remaining space is available to the user */
+       nvpb->start = nvchan->dma->cur;
+       nvpb->size = nvchan->dma->free;
+       nvpb->base.channel = chan;
+       nvpb->base.remaining = nvpb->size;
+       nvpb->base.cur = &nvchan->pushbuf[nvpb->start];
+
+       /* Create a new fence object for this "frame" */
+       nouveau_fence_ref(NULL, &nvpb->fence);
+       nouveau_fence_new(chan, &nvpb->fence);
+
+       return 0;
+}
+
+int
+nouveau_pushbuf_init(struct nouveau_channel *chan)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_dma_priv *m = &nvchan->dma_master;
+       struct nouveau_dma_priv *b = &nvchan->dma_bufmgr;
+       int i;
+
+       if (!nvchan)
+               return -EINVAL;
+
+       /* Reassign last bit of push buffer for a "separate" bufmgr
+        * ring buffer
+        */
+       m->max -= PB_BUFMGR_DWORDS;
+       m->free -= PB_BUFMGR_DWORDS;
+
+       b->base = m->base + ((m->max + 2) << 2);
+       b->max = PB_BUFMGR_DWORDS - 2;
+       b->cur = b->put = 0;
+       b->free = b->max - b->cur;
+
+       /* Some NOPs just to be safe
+        *XXX: RING_SKIPS
+        */
+       nvchan->dma = b;
+       RING_SPACE_CH(chan, 8);
+       for (i = 0; i < 8; i++)
+               OUT_RING_CH(chan, 0);
+       nvchan->dma = m;
+
+       nouveau_pushbuf_space(chan, 0);
+       chan->pushbuf = &nvchan->pb.base;
+
+       nvchan->pb.buffers = calloc(NOUVEAU_PUSHBUF_MAX_BUFFERS,
+                                   sizeof(struct nouveau_pushbuf_bo));
+       nvchan->pb.relocs = calloc(NOUVEAU_PUSHBUF_MAX_RELOCS,
+                                  sizeof(struct nouveau_pushbuf_reloc));
+       return 0;
+}
+
+static uint32_t
+nouveau_pushbuf_calc_reloc(struct nouveau_bo *bo,
+                          struct nouveau_pushbuf_reloc *r)
+{
+       uint32_t push;
+
+       if (r->flags & NOUVEAU_BO_LOW) {
+               push = bo->offset + r->data;
+       } else
+       if (r->flags & NOUVEAU_BO_HIGH) {
+               push = (bo->offset + r->data) >> 32;
+       } else {
+               push = r->data;
+       }
+
+       if (r->flags & NOUVEAU_BO_OR) {
+               if (bo->flags & NOUVEAU_BO_VRAM)
+                       push |= r->vor;
+               else
+                       push |= r->tor;
+       }
+
+       return push;
+}
+
+/* This would be our TTM "superioctl" */
+int
+nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
+{
+       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
+       int ret, i;
+
+       if (nvpb->base.remaining == nvpb->size)
+               return 0;
+
+       nouveau_fence_flush(chan);
+
+       nvpb->size -= nvpb->base.remaining;
+       nvchan->dma->cur += nvpb->size;
+       nvchan->dma->free -= nvpb->size;
+       assert(nvchan->dma->cur <= nvchan->dma->max);
+
+       nvchan->dma = &nvchan->dma_bufmgr;
+       nvchan->pushbuf[nvpb->nop_jump] = 0x20000000 |
+               (nvchan->dma->base + (nvchan->dma->cur << 2));
+
+       /* Validate buffers + apply relocations */
+       nvchan->user_charge = 0;
+       for (i = 0; i < nvpb->nr_relocs; i++) {
+               struct nouveau_pushbuf_reloc *r = &nvpb->relocs[i];
+               struct nouveau_pushbuf_bo *pbbo = r->pbbo;
+               struct nouveau_bo *bo = pbbo->bo;
+
+               /* Validated, mem matches presumed, no relocation necessary */
+               if (pbbo->handled & 2) {
+                       if (!(pbbo->handled & 1))
+                               assert(0);
+                       continue;
+               }
+
+               /* Not yet validated, do it now */
+               if (!(pbbo->handled & 1)) {
+                       ret = nouveau_bo_validate(chan, bo, pbbo->flags);
+                       if (ret) {
+                               assert(0);
+                               return ret;
+                       }
+                       pbbo->handled |= 1;
+
+                       if (bo->offset == nouveau_bo(bo)->offset &&
+                           bo->flags == nouveau_bo(bo)->flags) {
+                               pbbo->handled |= 2;
+                               continue;
+                       }
+                       bo->offset = nouveau_bo(bo)->offset;
+                       bo->flags = nouveau_bo(bo)->flags;
+               }
+
+               /* Apply the relocation */
+               *r->ptr = nouveau_pushbuf_calc_reloc(bo, r);
+       }
+       nvpb->nr_relocs = 0;
+
+       /* Dereference all buffers on validate list */
+       for (i = 0; i < nvpb->nr_buffers; i++) {
+               struct nouveau_pushbuf_bo *pbbo = &nvpb->buffers[i];
+
+               nouveau_bo(pbbo->bo)->pending = NULL;
+               nouveau_bo_del(&pbbo->bo);
+       }
+       nvpb->nr_buffers = 0;
+
+       /* Switch back to user's ring */
+       RING_SPACE_CH(chan, 1);
+       OUT_RING_CH(chan, 0x20000000 | ((nvpb->start << 2) +
+                                       nvchan->dma_master.base));
+       nvchan->dma = &nvchan->dma_master;
+
+       /* Fence + kickoff */
+       nouveau_fence_emit(nvpb->fence);
+       FIRE_RING_CH(chan);
+
+       /* Allocate space for next push buffer */
+       ret = nouveau_pushbuf_space(chan, min);
+       assert(!ret);
+
+       return 0;
+}
+
+static struct nouveau_pushbuf_bo *
+nouveau_pushbuf_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct nouveau_pushbuf_bo *pbbo;
+
+       if (nvbo->pending)
+               return nvbo->pending;
+
+       if (nvpb->nr_buffers >= NOUVEAU_PUSHBUF_MAX_BUFFERS)
+               return NULL;
+       pbbo = nvpb->buffers + nvpb->nr_buffers++;
+       nvbo->pending = pbbo;
+
+       nouveau_bo_ref(bo->device, bo->handle, &pbbo->bo);
+       pbbo->channel = chan;
+       pbbo->flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+       pbbo->handled = 0;
+       return pbbo;
+}
+
+int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
+                          struct nouveau_bo *bo, uint32_t data, uint32_t flags,
+                          uint32_t vor, uint32_t tor)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+       struct nouveau_pushbuf_bo *pbbo;
+       struct nouveau_pushbuf_reloc *r;
+
+       if (nvpb->nr_relocs >= NOUVEAU_PUSHBUF_MAX_RELOCS)
+               return -ENOMEM;
+
+       pbbo = nouveau_pushbuf_emit_buffer(chan, bo);
+       if (!pbbo)
+               return -ENOMEM;
+       pbbo->flags |= (flags & NOUVEAU_BO_RDWR);
+       pbbo->flags &= (flags | NOUVEAU_BO_RDWR);
+
+       r = nvpb->relocs + nvpb->nr_relocs++;
+       r->pbbo = pbbo;
+       r->ptr = ptr;
+       r->flags = flags;
+       r->data = data;
+       r->vor = vor;
+       r->tor = tor;
+
+       if (flags & NOUVEAU_BO_DUMMY)
+               *(uint32_t *)ptr = 0;
+       else
+               *(uint32_t *)ptr = nouveau_pushbuf_calc_reloc(bo, r);
+       return 0;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_resource.c b/src/gallium/winsys/dri/nouveau/nouveau_resource.c
new file mode 100644 (file)
index 0000000..3bbcb5c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_local.h"
+
+int
+nouveau_resource_init(struct nouveau_resource **heap,
+                     unsigned start, unsigned size)
+{
+       struct nouveau_resource *r;
+
+       r = calloc(1, sizeof(struct nouveau_resource));
+       if (!r)
+               return 1;
+
+       r->start = start;
+       r->size  = size;
+       *heap = r;
+       return 0;
+}
+
+int
+nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
+                      struct nouveau_resource **res)
+{
+       struct nouveau_resource *r;
+
+       if (!heap || !size || !res || *res)
+               return 1;
+
+       while (heap) {
+               if (!heap->in_use && heap->size >= size) {
+                       r = calloc(1, sizeof(struct nouveau_resource));
+                       if (!r)
+                               return 1;
+
+                       r->start  = (heap->start + heap->size) - size;
+                       r->size   = size;
+                       r->in_use = 1;
+                       r->priv   = priv;
+
+                       heap->size -= size;
+
+                       r->next = heap->next;
+                       if (heap->next)
+                               heap->next->prev = r;
+                       r->prev = heap;
+                       heap->next = r;
+
+                       *res = r;
+                       return 0;
+               }
+                       
+               heap = heap->next;
+       }
+
+       return 1;
+}
+
+void
+nouveau_resource_free(struct nouveau_resource **res)
+{
+       struct nouveau_resource *r;
+
+       if (!res || !*res)
+               return;
+       r = *res;
+       *res = NULL;
+
+       r->in_use = 0;
+
+       if (r->next && !r->next->in_use) {
+               struct nouveau_resource *new = r->next;
+
+               new->prev = r->prev;
+               if (r->prev)
+                       r->prev->next = new;
+               new->size += r->size;
+               new->start = r->start;
+
+               free(r);
+               r = new;
+       }
+
+       if (r->prev && !r->prev->in_use) {
+               r->prev->next = r->next;
+               if (r->next)
+                       r->next->prev = r->prev;
+               r->prev->size += r->size;
+               free(r);
+       }
+       
+}
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.c b/src/gallium/winsys/dri/nouveau/nouveau_screen.c
new file mode 100644 (file)
index 0000000..df1fe7e
--- /dev/null
@@ -0,0 +1,310 @@
+#include "utils.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+#include "pipe/p_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_cb_fbo.h"
+
+#include "nouveau_context.h"
+#include "nouveau_drm.h"
+#include "nouveau_dri.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_swapbuffers.h"
+
+#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 11
+#error nouveau_drm.h version does not match expected version
+#endif
+
+/* Extension stuff, enabling of extensions handled by Gallium's GL state
+ * tracker.  But, we still need to define the entry points we want.
+ */
+#define need_GL_ARB_fragment_program
+#define need_GL_ARB_multisample
+#define need_GL_ARB_occlusion_query
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_shader_objects
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_vertex_shader
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_EXT_compiled_vertex_array
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_secondary_color
+#define need_GL_EXT_framebuffer_object
+#define need_GL_VERSION_2_0
+#define need_GL_VERSION_2_1
+#include "extension_helper.h"
+
+const struct dri_extension card_extensions[] =
+{
+       { "GL_ARB_multisample", GL_ARB_multisample_functions },
+       { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions },
+       { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions },
+       { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
+       { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions },
+       { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions },
+       { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
+       { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+       { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions },
+       { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
+       { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions },
+       { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+       { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
+       { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
+       { NULL, 0 }
+};
+
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 0;
+
+extern const struct dri_extension common_extensions[];
+extern const struct dri_extension nv40_extensions[];
+
+static GLboolean
+nouveau_screen_create(__DRIscreenPrivate *driScrnPriv)
+{
+       struct nouveau_dri *nv_dri = driScrnPriv->pDevPriv;
+       struct nouveau_screen *nv_screen;
+       int ret;
+
+       if (driScrnPriv->devPrivSize != sizeof(struct nouveau_dri)) {
+               NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n");
+               return GL_FALSE;
+       }
+
+       nv_screen = CALLOC_STRUCT(nouveau_screen);
+       if (!nv_screen)
+               return GL_FALSE;
+       nv_screen->driScrnPriv = driScrnPriv;
+       driScrnPriv->private = (void *)nv_screen;
+
+       driParseOptionInfo(&nv_screen->option_cache,
+                          __driConfigOptions, __driNConfigOptions);
+
+       if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
+                                               driScrnPriv->fd, 0))) {
+               NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret);
+               return GL_FALSE;
+       }
+
+       nv_screen->front_offset = nv_dri->front_offset;
+       nv_screen->front_pitch  = nv_dri->front_pitch * (nv_dri->bpp / 8);
+       nv_screen->front_cpp = nv_dri->bpp / 8;
+       nv_screen->front_height = nv_dri->height;
+
+       return GL_TRUE;
+}
+
+static void
+nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv)
+{
+       struct nouveau_screen *nv_screen = driScrnPriv->private;
+
+       driScrnPriv->private = NULL;
+       FREE(nv_screen);
+}
+
+static GLboolean
+nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv,
+                     __DRIdrawablePrivate * driDrawPriv,
+                     const __GLcontextModes *glVis, GLboolean pixmapBuffer)
+{
+       struct nouveau_framebuffer *nvfb;
+       enum pipe_format colour, depth, stencil;
+
+       if (pixmapBuffer)
+               return GL_FALSE;
+
+       nvfb = CALLOC_STRUCT(nouveau_framebuffer);
+       if (!nvfb)
+               return GL_FALSE;
+
+       if (glVis->redBits == 5)
+               colour = PIPE_FORMAT_R5G6B5_UNORM;
+       else
+               colour = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+       if (glVis->depthBits == 16)
+               depth = PIPE_FORMAT_Z16_UNORM;
+       else if (glVis->depthBits == 24)
+               depth = PIPE_FORMAT_Z24S8_UNORM;
+       else
+               depth = PIPE_FORMAT_NONE;
+
+       if (glVis->stencilBits == 8)
+               stencil = PIPE_FORMAT_Z24S8_UNORM;
+       else
+               stencil = PIPE_FORMAT_NONE;
+
+       nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil,
+                                          driDrawPriv->w, driDrawPriv->h,
+                                          (void*)nvfb);
+       if (!nvfb->stfb) {
+               free(nvfb);
+               return  GL_FALSE;
+       }
+
+       driDrawPriv->driverPrivate = (void *)nvfb;
+       return GL_TRUE;
+}
+
+static void
+nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv)
+{
+       struct nouveau_framebuffer *nvfb;
+       
+       nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate;
+       st_unreference_framebuffer(&nvfb->stfb);
+       free(nvfb);
+}
+
+static struct __DriverAPIRec
+nouveau_api = {
+       .InitDriver     = nouveau_screen_create,
+       .DestroyScreen  = nouveau_screen_destroy,
+       .CreateContext  = nouveau_context_create,
+       .DestroyContext = nouveau_context_destroy,
+       .CreateBuffer   = nouveau_create_buffer,
+       .DestroyBuffer  = nouveau_destroy_buffer,
+       .SwapBuffers    = nouveau_swap_buffers,
+       .MakeCurrent    = nouveau_context_bind,
+       .UnbindContext  = nouveau_context_unbind,
+       .GetSwapInfo    = NULL,
+       .GetMSC         = NULL,
+       .WaitForMSC     = NULL,
+       .WaitForSBC     = NULL,
+       .SwapBuffersMSC = NULL,
+       .CopySubBuffer  = nouveau_copy_sub_buffer,
+       .setTexOffset   = NULL
+};
+
+static __GLcontextModes *
+nouveau_fill_in_modes(unsigned pixel_bits, unsigned depth_bits,
+                     unsigned stencil_bits, GLboolean have_back_buffer)
+{
+       __GLcontextModes * modes;
+       __GLcontextModes * m;
+       unsigned num_modes;
+       unsigned depth_buffer_factor;
+       unsigned back_buffer_factor;
+       int i;
+
+       static const struct {
+               GLenum format;
+               GLenum type;
+       } fb_format_array[] = {
+               { GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
+               { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
+               { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
+       };
+
+       /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
+        * support pageflipping at all.
+        */
+       static const GLenum back_buffer_modes[] = {
+               GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+       };
+
+       uint8_t depth_bits_array[4]   = { 0, 16, 24, 24 };
+       uint8_t stencil_bits_array[4] = { 0,  0,  0, 8 };
+       uint8_t msaa_samples_array[1] = { 0 };
+
+       depth_buffer_factor = 4;
+       back_buffer_factor  = (have_back_buffer) ? 3 : 1;
+
+       num_modes = ((pixel_bits==16) ? 1 : 2) *
+               depth_buffer_factor * back_buffer_factor * 4;
+       modes = (*dri_interface->createContextModes)(num_modes,
+                                                    sizeof(__GLcontextModes));
+       m = modes;
+
+       for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
+               if (!driFillInModes(&m, fb_format_array[i].format,
+                                       fb_format_array[i].type,
+                                       depth_bits_array,
+                                       stencil_bits_array,
+                                       depth_buffer_factor,
+                                       back_buffer_modes,
+                                       back_buffer_factor,
+                                       msaa_samples_array, 1,
+                                       GLX_TRUE_COLOR)) {
+               fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+                               __func__, __LINE__ );
+               return NULL;
+               }
+
+               if (!driFillInModes(&m, fb_format_array[i].format,
+                                       fb_format_array[i].type,
+                                       depth_bits_array,
+                                       stencil_bits_array,
+                                       depth_buffer_factor,
+                                       back_buffer_modes,
+                                       back_buffer_factor,
+                                       msaa_samples_array, 1,
+                                       GLX_DIRECT_COLOR)) {
+               fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+                               __func__, __LINE__ );
+               return NULL;
+               }
+       }
+
+       return modes;
+}
+PUBLIC void *
+__driCreateNewScreen_20050727(__DRInativeDisplay *dpy, int scrn,
+                             __DRIscreen *psc, const __GLcontextModes * modes,
+                             const __DRIversion * ddx_version,
+                             const __DRIversion * dri_version,
+                             const __DRIversion * drm_version,
+                             const __DRIframebuffer * frame_buffer,
+                             void * pSAREA, int fd, int internal_api_version,
+                             const __DRIinterfaceMethods * interface,
+                             __GLcontextModes ** driver_modes)
+{
+       __DRIscreenPrivate *psp;
+       static const __DRIversion ddx_expected =
+               { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
+       static const __DRIversion dri_expected = { 4, 0, 0 };
+       static const __DRIversion drm_expected =
+               { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
+       struct nouveau_dri *nv_dri = NULL;
+
+       dri_interface = interface;
+
+       if (!driCheckDriDdxDrmVersions2("nouveau",
+                                       dri_version, &dri_expected,
+                                       ddx_version, &ddx_expected,
+                                       drm_version, &drm_expected)) {
+               return NULL;
+       }
+
+       if (drm_expected.patch != drm_version->patch) {
+               fprintf(stderr, "Incompatible DRM patch level.\n"
+                               "Expected: %d\n" "Current : %d\n",
+                       drm_expected.patch, drm_version->patch);
+               return NULL;
+       }
+
+       psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+                                      ddx_version, dri_version, drm_version,
+                                      frame_buffer, pSAREA, fd,
+                                      internal_api_version,
+                                      &nouveau_api);
+       if (psp == NULL)
+               return NULL;
+       nv_dri = psp->pDevPriv;
+
+       *driver_modes = nouveau_fill_in_modes(nv_dri->bpp,
+                                             (nv_dri->bpp == 16) ? 16 : 24,
+                                             (nv_dri->bpp == 16) ? 0 : 8,
+                                             1);
+
+       driInitExtensions(NULL, card_extensions, GL_FALSE);
+
+       return (void *)psp;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_screen.h b/src/gallium/winsys/dri/nouveau/nouveau_screen.h
new file mode 100644 (file)
index 0000000..388d6be
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+#include "xmlconfig.h"
+
+struct nouveau_screen {
+       __DRIscreenPrivate *driScrnPriv;
+       driOptionCache      option_cache;
+
+       struct nouveau_device *device;
+
+       uint32_t front_offset;
+       uint32_t front_pitch;
+       uint32_t front_cpp;
+       uint32_t front_height;
+
+       void *nvc;
+};
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.c
new file mode 100644 (file)
index 0000000..70e0104
--- /dev/null
@@ -0,0 +1,86 @@
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
+
+#include "pipe/p_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+
+#include "nouveau_context.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_swapbuffers.h"
+
+void
+nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
+                   const drm_clip_rect_t *rect)
+{
+       struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate;
+       drm_clip_rect_t *pbox;
+       int nbox, i;
+
+       LOCK_HARDWARE(nv);
+       if (!dPriv->numClipRects) {
+               UNLOCK_HARDWARE(nv);
+               return;
+       }
+       pbox = dPriv->pClipRects;
+       nbox = dPriv->numClipRects;
+
+       nv->surface_copy_prep(nv, nv->frontbuffer, surf);
+       for (i = 0; i < nbox; i++, pbox++) {
+               int sx, sy, dx, dy, w, h;
+
+               sx = pbox->x1 - dPriv->x;
+               sy = pbox->y1 - dPriv->y;
+               dx = pbox->x1;
+               dy = pbox->y1;
+               w  = pbox->x2 - pbox->x1;
+               h  = pbox->y2 - pbox->y1;
+
+               nv->surface_copy(nv, dx, dy, sx, sy, w, h);
+       }
+
+       FIRE_RING(nv->nvc->channel);
+       UNLOCK_HARDWARE(nv);
+
+       if (nv->last_stamp != dPriv->lastStamp) {
+               struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
+               st_resize_framebuffer(nvfb->stfb, dPriv->w, dPriv->h);
+               nv->last_stamp = dPriv->lastStamp;
+       }
+}
+
+void
+nouveau_copy_sub_buffer(__DRIdrawablePrivate *dPriv, int x, int y, int w, int h)
+{
+       struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
+       struct pipe_surface *surf;
+
+       surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT);
+       if (surf) {
+               drm_clip_rect_t rect;
+               rect.x1 = x;
+               rect.y1 = y;
+               rect.x2 = x + w;
+               rect.y2 = y + h;
+
+               st_notify_swapbuffers(nvfb->stfb);
+               nouveau_copy_buffer(dPriv, surf, &rect);
+       }
+}
+
+void
+nouveau_swap_buffers(__DRIdrawablePrivate *dPriv)
+{
+       struct nouveau_framebuffer *nvfb = dPriv->driverPrivate;
+       struct pipe_surface *surf;
+
+       surf = st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT);
+       if (surf) {
+               st_notify_swapbuffers(nvfb->stfb);
+               nouveau_copy_buffer(dPriv, surf, NULL);
+       }
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/dri/nouveau/nouveau_swapbuffers.h
new file mode 100644 (file)
index 0000000..825d3da
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __NOUVEAU_SWAPBUFFERS_H__
+#define __NOUVEAU_SWAPBUFFERS_H__
+
+extern void nouveau_copy_buffer(__DRIdrawablePrivate *, struct pipe_surface *,
+                               const drm_clip_rect_t *);
+extern void nouveau_copy_sub_buffer(__DRIdrawablePrivate *,
+                                   int x, int y, int w, int h);
+extern void nouveau_swap_buffers(__DRIdrawablePrivate *);
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys.c
new file mode 100644 (file)
index 0000000..5eabbc8
--- /dev/null
@@ -0,0 +1,158 @@
+#include "pipe/p_util.h"
+
+#include "nouveau_context.h"
+#include "nouveau_screen.h"
+#include "nouveau_winsys_pipe.h"
+
+#include "nouveau/nouveau_winsys.h"
+
+static int
+nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count,
+                           struct nouveau_notifier **notify)
+{
+       struct nouveau_context *nv = nvws->nv;
+
+       return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++,
+                                     count, notify);
+}
+
+static int
+nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
+                        struct nouveau_grobj **grobj)
+{
+       struct nouveau_context *nv = nvws->nv;
+       struct nouveau_channel *chan = nv->nvc->channel;
+       int ret;
+
+       ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++,
+                                 grclass, grobj);
+       if (ret)
+               return ret;
+
+       assert(nv->nvc->next_subchannel < 7);
+       BIND_RING(chan, *grobj, nv->nvc->next_subchannel++);
+       return 0;
+}
+
+static int
+nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst,
+                         unsigned dx, unsigned dy, struct pipe_surface *src,
+                         unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+       struct nouveau_context *nv = nvws->nv;
+
+       if (nv->surface_copy_prep(nv, dst, src))
+               return 1;
+       nv->surface_copy(nv, dx, dy, sx, sy, w, h);
+       nv->surface_copy_done(nv);
+
+       return 0;
+}
+
+static int
+nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst,
+                         unsigned dx, unsigned dy, unsigned w, unsigned h,
+                         unsigned value)
+{
+       if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value))
+               return 1;
+       return 0;
+}
+
+static int
+nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr,
+                       struct pipe_buffer *buf, uint32_t data,
+                       uint32_t flags, uint32_t vor, uint32_t tor)
+{
+       return nouveau_pushbuf_emit_reloc(nvws->channel, ptr,
+                                         nouveau_buffer(buf)->bo,
+                                         data, flags, vor, tor);
+}
+
+static int
+nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size,
+                       struct pipe_fence_handle **fence)
+{
+       if (fence) {
+               struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+               struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(pb);
+               struct nouveau_fence *ref = NULL;
+
+               nouveau_fence_ref(nvpb->fence, &ref);
+               *fence = (struct pipe_fence_handle *)ref;
+       }
+
+       return nouveau_pushbuf_flush(nvws->channel, size);
+}
+
+struct pipe_context *
+nouveau_pipe_create(struct nouveau_context *nv)
+{
+       struct nouveau_channel_context *nvc = nv->nvc;
+       struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys);
+       struct pipe_screen *(*hws_create)(struct pipe_winsys *,
+                                         struct nouveau_winsys *);
+       struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned);
+       struct pipe_winsys *ws;
+       unsigned chipset = nv->nv_screen->device->chipset;
+
+       if (!nvws)
+               return NULL;
+
+       switch (chipset & 0xf0) {
+       case 0x10:
+       case 0x20:
+               hws_create = nv10_screen_create;
+               hw_create = nv10_create;
+               break;
+       case 0x30:
+               hws_create = nv30_screen_create;
+               hw_create = nv30_create;
+               break;
+       case 0x40:
+       case 0x60:
+               hws_create = nv40_screen_create;
+               hw_create = nv40_create;
+               break;
+       case 0x50:
+       case 0x80:
+       case 0x90:
+               hws_create = nv50_screen_create;
+               hw_create = nv50_create;
+               break;
+       default:
+               NOUVEAU_ERR("Unknown chipset NV%02x\n", chipset);
+               return NULL;
+       }
+
+       nvws->nv                = nv;
+       nvws->channel           = nv->nvc->channel;
+
+       nvws->res_init          = nouveau_resource_init;
+       nvws->res_alloc         = nouveau_resource_alloc;
+       nvws->res_free          = nouveau_resource_free;
+
+       nvws->push_reloc        = nouveau_pipe_push_reloc;
+       nvws->push_flush        = nouveau_pipe_push_flush;
+
+       nvws->grobj_alloc       = nouveau_pipe_grobj_alloc;
+       nvws->grobj_free        = nouveau_grobj_free;
+
+       nvws->notifier_alloc    = nouveau_pipe_notifier_alloc;
+       nvws->notifier_free     = nouveau_notifier_free;
+       nvws->notifier_reset    = nouveau_notifier_reset;
+       nvws->notifier_status   = nouveau_notifier_status;
+       nvws->notifier_retval   = nouveau_notifier_return_val;
+       nvws->notifier_wait     = nouveau_notifier_wait_status;
+
+       nvws->surface_copy      = nouveau_pipe_surface_copy;
+       nvws->surface_fill      = nouveau_pipe_surface_fill;
+
+       ws = nouveau_create_pipe_winsys(nv);
+
+       if (!nvc->pscreen)
+               nvc->pscreen = hws_create(ws, nvws);
+       nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id);
+       return nvc->pctx[nv->pctx_id];
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.c
new file mode 100644 (file)
index 0000000..8a2870a
--- /dev/null
@@ -0,0 +1,205 @@
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "nouveau_context.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_swapbuffers.h"
+#include "nouveau_winsys_pipe.h"
+
+static void
+nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf,
+                         void *context_private)
+{
+       struct nouveau_context *nv = context_private;
+       __DRIdrawablePrivate *dPriv = nv->dri_drawable;
+
+       nouveau_copy_buffer(dPriv, surf, NULL);
+}
+
+static const char *
+nouveau_get_name(struct pipe_winsys *pws)
+{
+       return "Nouveau/DRI";
+}
+
+static struct pipe_buffer *
+nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
+                      unsigned usage, unsigned size)
+{
+       struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
+       struct nouveau_context *nv = nvpws->nv;
+       struct nouveau_device *dev = nv->nv_screen->device;
+       struct nouveau_pipe_buffer *nvbuf;
+       uint32_t flags;
+
+       nvbuf = calloc(1, sizeof(*nvbuf));
+       if (!nvbuf)
+               return NULL;
+       nvbuf->base.refcount = 1;
+       nvbuf->base.alignment = alignment;
+       nvbuf->base.usage = usage;
+       nvbuf->base.size = size;
+
+       flags = NOUVEAU_BO_LOCAL;
+
+       if (usage & PIPE_BUFFER_USAGE_PIXEL) {
+               if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
+                       flags |= NOUVEAU_BO_GART;
+               flags |= NOUVEAU_BO_VRAM;
+
+               switch (dev->chipset & 0xf0) {
+               case 0x50:
+               case 0x80:
+               case 0x90:
+                       flags |= NOUVEAU_BO_TILED;
+                       if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
+                               flags |= NOUVEAU_BO_ZTILE;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       if (usage & PIPE_BUFFER_USAGE_VERTEX) {
+               if (nv->cap.hw_vertex_buffer)
+                       flags |= NOUVEAU_BO_GART;
+       }
+
+       if (usage & PIPE_BUFFER_USAGE_INDEX) {
+               if (nv->cap.hw_index_buffer)
+                       flags |= NOUVEAU_BO_GART;
+       }
+
+       if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) {
+               free(nvbuf);
+               return NULL;
+       }
+
+       return &nvbuf->base;
+}
+
+static struct pipe_buffer *
+nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+       struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
+       struct nouveau_device *dev = nvpws->nv->nv_screen->device;
+       struct nouveau_pipe_buffer *nvbuf;
+
+       nvbuf = calloc(1, sizeof(*nvbuf));
+       if (!nvbuf)
+               return NULL;
+       nvbuf->base.refcount = 1;
+       nvbuf->base.size = bytes;
+
+       if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) {
+               free(nvbuf);
+               return NULL;
+       }
+
+       return &nvbuf->base;
+}
+
+static void
+nouveau_pipe_bo_del(struct pipe_winsys *ws, struct pipe_buffer *buf)
+{
+       struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
+
+       nouveau_bo_del(&nvbuf->bo);
+       free(nvbuf);
+}
+
+static void *
+nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
+                   unsigned flags)
+{
+       struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
+       uint32_t map_flags = 0;
+
+       if (flags & PIPE_BUFFER_USAGE_CPU_READ)
+               map_flags |= NOUVEAU_BO_RD;
+       if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
+               map_flags |= NOUVEAU_BO_WR;
+
+       if (nouveau_bo_map(nvbuf->bo, map_flags))
+               return NULL;
+       return nvbuf->bo->map;
+}
+
+static void
+nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+       struct nouveau_pipe_buffer *nvbuf = nouveau_buffer(buf);
+
+       nouveau_bo_unmap(nvbuf->bo);
+}
+
+static INLINE struct nouveau_fence *
+nouveau_pipe_fence(struct pipe_fence_handle *pfence)
+{
+       return (struct nouveau_fence *)pfence;
+}
+
+static void
+nouveau_pipe_fence_reference(struct pipe_winsys *ws,
+                            struct pipe_fence_handle **ptr,
+                            struct pipe_fence_handle *pfence)
+{
+       nouveau_fence_ref((void *)pfence, (void *)ptr);
+}
+
+static int
+nouveau_pipe_fence_signalled(struct pipe_winsys *ws,
+                            struct pipe_fence_handle *pfence, unsigned flag)
+{
+       struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)ws;
+       struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
+
+       if (nouveau_fence(fence)->signalled == 0)
+               nouveau_fence_flush(nvpws->nv->nvc->channel);
+
+       return !nouveau_fence(fence)->signalled;
+}
+
+static int
+nouveau_pipe_fence_finish(struct pipe_winsys *ws,
+                         struct pipe_fence_handle *pfence, unsigned flag)
+{
+       struct nouveau_fence *fence = nouveau_pipe_fence(pfence);
+       struct nouveau_fence *ref = NULL;
+
+       nouveau_fence_ref(fence, &ref);
+       return nouveau_fence_wait(&ref);
+}
+
+struct pipe_winsys *
+nouveau_create_pipe_winsys(struct nouveau_context *nv)
+{
+       struct nouveau_pipe_winsys *nvpws;
+       struct pipe_winsys *pws;
+
+       nvpws = CALLOC_STRUCT(nouveau_pipe_winsys);
+       if (!nvpws)
+               return NULL;
+       nvpws->nv = nv;
+       pws = &nvpws->pws;
+
+       pws->flush_frontbuffer = nouveau_flush_frontbuffer;
+
+       pws->buffer_create = nouveau_pipe_bo_create;
+       pws->buffer_destroy = nouveau_pipe_bo_del;
+       pws->user_buffer_create = nouveau_pipe_bo_user_create;
+       pws->buffer_map = nouveau_pipe_bo_map;
+       pws->buffer_unmap = nouveau_pipe_bo_unmap;
+
+       pws->fence_reference = nouveau_pipe_fence_reference;
+       pws->fence_signalled = nouveau_pipe_fence_signalled;
+       pws->fence_finish = nouveau_pipe_fence_finish;
+
+       pws->get_name = nouveau_get_name;
+
+       return &nvpws->pws;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h b/src/gallium/winsys/dri/nouveau/nouveau_winsys_pipe.h
new file mode 100644 (file)
index 0000000..6a03ac0
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef NOUVEAU_PIPE_WINSYS_H
+#define NOUVEAU_PIPE_WINSYS_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_winsys.h"
+#include "nouveau_context.h"
+
+struct nouveau_pipe_buffer {
+       struct pipe_buffer base;
+       struct nouveau_bo *bo;
+};
+
+static inline struct nouveau_pipe_buffer *
+nouveau_buffer(struct pipe_buffer *buf)
+{
+       return (struct nouveau_pipe_buffer *)buf;
+}
+
+struct nouveau_pipe_winsys {
+       struct pipe_winsys pws;
+
+       struct nouveau_context *nv;
+};
+
+extern struct pipe_winsys *
+nouveau_create_pipe_winsys(struct nouveau_context *nv);
+
+struct pipe_context *
+nouveau_create_softpipe(struct nouveau_context *nv);
+
+struct pipe_context *
+nouveau_pipe_create(struct nouveau_context *nv);
+
+#endif
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c b/src/gallium/winsys/dri/nouveau/nouveau_winsys_softpipe.c
new file mode 100644 (file)
index 0000000..704f6c7
--- /dev/null
@@ -0,0 +1,85 @@
+/**************************************************************************
+ * 
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * 
+ **************************************************************************/
+/*
+ * Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include "imports.h"
+
+#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "softpipe/sp_winsys.h"
+
+#include "nouveau_context.h"
+#include "nouveau_winsys_pipe.h"
+
+struct nouveau_softpipe_winsys {
+   struct softpipe_winsys sws;
+   struct nouveau_context *nv;
+};
+
+/**
+ * Return list of surface formats supported by this driver.
+ */
+static boolean
+nouveau_is_format_supported(struct softpipe_winsys *sws, uint format)
+{
+       switch (format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_R5G6B5_UNORM:
+       case PIPE_FORMAT_Z24S8_UNORM:
+               return TRUE;
+       default:
+               break;
+       };
+
+       return FALSE;
+}
+
+struct pipe_context *
+nouveau_create_softpipe(struct nouveau_context *nv)
+{
+       struct nouveau_softpipe_winsys *nvsws;
+       struct pipe_screen *pscreen;
+       struct pipe_winsys *ws;
+
+       ws = nouveau_create_pipe_winsys(nv);
+       if (!ws)
+               return NULL;
+       pscreen = softpipe_create_screen(ws);
+
+       nvsws = CALLOC_STRUCT(nouveau_softpipe_winsys);
+       if (!nvsws)
+               return NULL;
+
+       nvsws->sws.is_format_supported = nouveau_is_format_supported;
+       nvsws->nv = nv;
+
+       return softpipe_create(pscreen, ws, &nvsws->sws);
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nv04_surface.c b/src/gallium/winsys/dri/nouveau/nv04_surface.c
new file mode 100644 (file)
index 0000000..0085b1c
--- /dev/null
@@ -0,0 +1,310 @@
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+
+#include "nouveau_context.h"
+
+static INLINE int
+nv04_surface_format(enum pipe_format format)
+{
+       switch (format) {
+       case PIPE_FORMAT_A8_UNORM:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_Z24S8_UNORM:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
+       default:
+               return -1;
+       }
+}
+
+static INLINE int
+nv04_rect_format(enum pipe_format format)
+{
+       switch (format) {
+       case PIPE_FORMAT_A8_UNORM:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_Z24S8_UNORM:
+               return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
+
+static void
+nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
+                      unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct pipe_surface *dst = nv->surf_dst;
+       struct pipe_surface *src = nv->surf_src;
+       unsigned dst_offset, src_offset;
+
+       dst_offset = dst->offset + (dy * dst->stride) + (dx * dst->block.size);
+       src_offset = src->offset + (sy * src->stride) + (sx * src->block.size);
+
+       while (h) {
+               int count = (h > 2047) ? 2047 : h;
+
+               BEGIN_RING(chan, nv->nvc->NvM2MF,
+                          NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+               OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src_offset,
+                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+               OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst_offset,
+                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+               OUT_RING  (chan, src->stride);
+               OUT_RING  (chan, dst->stride);
+               OUT_RING  (chan, w * src->block.size);
+               OUT_RING  (chan, count);
+               OUT_RING  (chan, 0x0101);
+               OUT_RING  (chan, 0);
+
+               h -= count;
+               src_offset += src->stride * count;
+               dst_offset += dst->stride * count;
+       }
+}
+
+static void
+nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
+                      unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+
+       BEGIN_RING(chan, nv->nvc->NvImageBlit, 0x0300, 3);
+       OUT_RING  (chan, (sy << 16) | sx);
+       OUT_RING  (chan, (dy << 16) | dx);
+       OUT_RING  (chan, ( h << 16) |  w);
+}
+
+static int
+nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
+                      struct pipe_surface *src)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       int format;
+
+       if (src->format != dst->format)
+               return 1;
+
+       /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
+        * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
+        */
+       if ((src->offset & 63) || (dst->offset & 63)) {
+               BEGIN_RING(nv->nvc->channel, nv->nvc->NvM2MF,
+                          NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+               OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
+                          NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+               OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+                          NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+               nv->surface_copy = nv04_surface_copy_m2mf;
+               nv->surf_dst = dst;
+               nv->surf_src = src;
+               return 0;
+
+       }
+
+       if ((format = nv04_surface_format(dst->format)) < 0) {
+               NOUVEAU_ERR("Bad surface format 0x%x\n", dst->format);
+               return 1;
+       }
+       nv->surface_copy = nv04_surface_copy_blit;
+
+       BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
+                  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, nv->nvc->NvCtxSurf2D,
+                  NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING  (chan, format);
+       OUT_RING  (chan, (dst->stride << 16) | src->stride);
+       OUT_RELOCl(chan, nouveau_buffer(src->buffer)->bo, src->offset,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+       OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       return 0;
+}
+
+static void
+nv04_surface_copy_done(struct nouveau_context *nv)
+{
+       FIRE_RING(nv->nvc->channel);
+}
+
+static int
+nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
+                 unsigned dx, unsigned dy, unsigned w, unsigned h,
+                 unsigned value)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct nouveau_grobj *surf2d = nv->nvc->NvCtxSurf2D;
+       struct nouveau_grobj *rect = nv->nvc->NvGdiRect;
+       int cs2d_format, gdirect_format;
+
+       if ((cs2d_format = nv04_surface_format(dst->format)) < 0) {
+               NOUVEAU_ERR("Bad format = %d\n", dst->format);
+               return 1;
+       }
+
+       if ((gdirect_format = nv04_rect_format(dst->format)) < 0) {
+               NOUVEAU_ERR("Bad format = %d\n", dst->format);
+               return 1;
+       }
+
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
+       OUT_RING  (chan, cs2d_format);
+       OUT_RING  (chan, (dst->stride << 16) | dst->stride);
+       OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+       OUT_RELOCl(chan, nouveau_buffer(dst->buffer)->bo, dst->offset,
+                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
+       OUT_RING  (chan, gdirect_format);
+       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
+       OUT_RING  (chan, value);
+       BEGIN_RING(chan, rect,
+                  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
+       OUT_RING  (chan, (dx << 16) | dy);
+       OUT_RING  (chan, ( w << 16) |  h);
+
+       FIRE_RING(chan);
+       return 0;
+}
+
+int
+nouveau_surface_channel_create_nv04(struct nouveau_channel_context *nvc)
+{
+       struct nouveau_channel *chan = nvc->channel;
+       unsigned chipset = nvc->channel->device->chipset, class;
+       int ret;
+
+       if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, 0x39,
+                                      &nvc->NvM2MF))) {
+               NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
+               return 1;
+       }
+       BIND_RING (chan, nvc->NvM2MF, nvc->next_subchannel++);
+       BEGIN_RING(chan, nvc->NvM2MF,
+                  NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, nvc->sync_notifier->handle);
+
+       class = chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
+                                NV10_CONTEXT_SURFACES_2D;
+       if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
+                                      &nvc->NvCtxSurf2D))) {
+               NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
+               return 1;
+       }
+       BIND_RING (chan, nvc->NvCtxSurf2D, nvc->next_subchannel++);
+       BEGIN_RING(chan, nvc->NvCtxSurf2D,
+                  NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
+       OUT_RING  (chan, nvc->channel->vram->handle);
+       OUT_RING  (chan, nvc->channel->vram->handle);
+
+       class = chipset < 0x10 ? NV04_IMAGE_BLIT : NV12_IMAGE_BLIT;
+       if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
+                                      &nvc->NvImageBlit))) {
+               NOUVEAU_ERR("Error creating blit object: %d\n", ret);
+               return 1;
+       }
+       BIND_RING (chan, nvc->NvImageBlit, nvc->next_subchannel++);
+       BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, nvc->sync_notifier->handle);
+       BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
+       OUT_RING  (chan, nvc->NvCtxSurf2D->handle);
+       BEGIN_RING(chan, nvc->NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
+       OUT_RING  (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY);
+
+       class = NV04_GDI_RECTANGLE_TEXT;
+       if ((ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
+                                      &nvc->NvGdiRect))) {
+               NOUVEAU_ERR("Error creating rect object: %d\n", ret);
+               return 1;
+       }
+       BIND_RING (chan, nvc->NvGdiRect, nvc->next_subchannel++);
+       BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
+       OUT_RING  (chan, nvc->sync_notifier->handle);
+       BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
+       OUT_RING  (chan, nvc->NvCtxSurf2D->handle);
+       BEGIN_RING(chan, nvc->NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
+       BEGIN_RING(chan, nvc->NvGdiRect,
+                  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
+       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+
+       switch (chipset & 0xf0) {
+       case 0x00:
+       case 0x10:
+               class = NV04_SWIZZLED_SURFACE;
+               break;
+       case 0x20:
+               class = NV20_SWIZZLED_SURFACE;
+               break;
+       case 0x30:
+               class = NV30_SWIZZLED_SURFACE;
+               break;
+       case 0x40:
+       case 0x60:
+               class = NV40_SWIZZLED_SURFACE;
+               break;
+       default:
+               /* Famous last words: this really can't happen.. */
+               assert(0);
+               break;
+       }
+
+       ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
+                                 &nvc->NvSwzSurf);
+       if (ret) {
+               NOUVEAU_ERR("Error creating swizzled surface: %d\n", ret);
+               return 1;
+       }
+
+       BIND_RING (chan, nvc->NvSwzSurf, nvc->next_subchannel++);
+
+       if (chipset < 0x10) {
+               class = NV04_SCALED_IMAGE_FROM_MEMORY;
+       } else
+       if (chipset < 0x40) {
+               class = NV10_SCALED_IMAGE_FROM_MEMORY;
+       } else {
+               class = NV40_SCALED_IMAGE_FROM_MEMORY;
+       }
+
+       ret = nouveau_grobj_alloc(chan, nvc->next_handle++, class,
+                                 &nvc->NvSIFM);
+       if (ret) {
+               NOUVEAU_ERR("Error creating scaled image object: %d\n", ret);
+               return 1;
+       }
+
+       BIND_RING (chan, nvc->NvSIFM, nvc->next_subchannel++);
+
+       return 0;
+}
+
+int
+nouveau_surface_init_nv04(struct nouveau_context *nv)
+{
+       nv->surface_copy_prep = nv04_surface_copy_prep;
+       nv->surface_copy = nv04_surface_copy_blit;
+       nv->surface_copy_done = nv04_surface_copy_done;
+       nv->surface_fill = nv04_surface_fill;
+       return 0;
+}
+
diff --git a/src/gallium/winsys/dri/nouveau/nv50_surface.c b/src/gallium/winsys/dri/nouveau/nv50_surface.c
new file mode 100644 (file)
index 0000000..c8ab7f6
--- /dev/null
@@ -0,0 +1,194 @@
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+
+#include "nouveau_context.h"
+
+static INLINE int
+nv50_format(enum pipe_format format)
+{
+       switch (format) {
+       case PIPE_FORMAT_A8R8G8B8_UNORM:
+       case PIPE_FORMAT_Z24S8_UNORM:
+               return NV50_2D_DST_FORMAT_32BPP;
+       case PIPE_FORMAT_X8R8G8B8_UNORM:
+               return NV50_2D_DST_FORMAT_24BPP;
+       case PIPE_FORMAT_R5G6B5_UNORM:
+               return NV50_2D_DST_FORMAT_16BPP;
+       case PIPE_FORMAT_A8_UNORM:
+               return NV50_2D_DST_FORMAT_8BPP;
+       default:
+               return -1;
+       }
+}
+
+static int
+nv50_surface_set(struct nouveau_context *nv, struct pipe_surface *surf, int dst)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
+       struct nouveau_bo *bo = nouveau_buffer(surf->buffer)->bo;
+       int surf_format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
+       int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD);
+  
+       surf_format = nv50_format(surf->format);
+       if (surf_format < 0)
+               return 1;
+  
+       if (!nouveau_bo(bo)->tiled) {
+               BEGIN_RING(chan, eng2d, mthd, 2);
+               OUT_RING  (chan, surf_format);
+               OUT_RING  (chan, 1);
+               BEGIN_RING(chan, eng2d, mthd + 0x14, 5);
+               OUT_RING  (chan, surf->stride);
+               OUT_RING  (chan, surf->width);
+               OUT_RING  (chan, surf->height);
+               OUT_RELOCh(chan, bo, surf->offset, flags);
+               OUT_RELOCl(chan, bo, surf->offset, flags);
+       } else {
+               BEGIN_RING(chan, eng2d, mthd, 5);
+               OUT_RING  (chan, surf_format);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, 1);
+               OUT_RING  (chan, 0);
+               BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
+               OUT_RING  (chan, surf->width);
+               OUT_RING  (chan, surf->height);
+               OUT_RELOCh(chan, bo, surf->offset, flags);
+               OUT_RELOCl(chan, bo, surf->offset, flags);
+       }
+#if 0
+       if (dst) {
+               BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, 0);
+               OUT_RING  (chan, surf->width);
+               OUT_RING  (chan, surf->height);
+       }
+#endif
+  
+       return 0;
+}
+
+static int
+nv50_surface_copy_prep(struct nouveau_context *nv,
+                      struct pipe_surface *dst, struct pipe_surface *src)
+{
+       int ret;
+
+       assert(src->format == dst->format);
+
+       ret = nv50_surface_set(nv, dst, 1);
+       if (ret)
+               return ret;
+
+       ret = nv50_surface_set(nv, src, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void
+nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy,
+                 unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
+
+       BEGIN_RING(chan, eng2d, 0x088c, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 4);
+       OUT_RING  (chan, dx);
+       OUT_RING  (chan, dy);
+       OUT_RING  (chan, w);
+       OUT_RING  (chan, h);
+       BEGIN_RING(chan, eng2d, 0x08c0, 4);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 1);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, 1);
+       BEGIN_RING(chan, eng2d, 0x08d0, 4);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, sx);
+       OUT_RING  (chan, 0);
+       OUT_RING  (chan, sy);
+}
+
+static void
+nv50_surface_copy_done(struct nouveau_context *nv)
+{
+       FIRE_RING(nv->nvc->channel);
+}
+
+static int
+nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
+                 unsigned dx, unsigned dy, unsigned w, unsigned h,
+                 unsigned value)
+{
+       struct nouveau_channel *chan = nv->nvc->channel;
+       struct nouveau_grobj *eng2d = nv->nvc->Nv2D;
+       int rect_format, ret;
+
+       rect_format = nv50_format(dst->format);
+       if (rect_format < 0)
+               return 1;
+
+       ret = nv50_surface_set(nv, dst, 1);
+       if (ret)
+               return ret;
+
+       BEGIN_RING(chan, eng2d, 0x0580, 3);
+       OUT_RING  (chan, 4);
+       OUT_RING  (chan, rect_format);
+       OUT_RING  (chan, value);
+
+       BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
+       OUT_RING  (chan, dx);
+       OUT_RING  (chan, dy);
+       OUT_RING  (chan, dx + w);
+       OUT_RING  (chan, dy + h);
+
+       FIRE_RING(chan);
+       return 0;
+}
+
+int
+nouveau_surface_channel_create_nv50(struct nouveau_channel_context *nvc)
+{
+       struct nouveau_channel *chan = nvc->channel;
+       struct nouveau_grobj *eng2d = NULL;
+       int ret;
+
+       ret = nouveau_grobj_alloc(chan, nvc->next_handle++, NV50_2D, &eng2d);
+       if (ret)
+               return ret;
+       nvc->Nv2D = eng2d;
+
+       BIND_RING (chan, eng2d, nvc->next_subchannel++);
+       BEGIN_RING(chan, eng2d, NV50_2D_DMA_NOTIFY, 4);
+       OUT_RING  (chan, nvc->sync_notifier->handle);
+       OUT_RING  (chan, chan->vram->handle);
+       OUT_RING  (chan, chan->vram->handle);
+       OUT_RING  (chan, chan->vram->handle);
+       BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
+       OUT_RING  (chan, NV50_2D_OPERATION_SRCCOPY);
+       BEGIN_RING(chan, eng2d, 0x0290, 1);
+       OUT_RING  (chan, 0);
+       BEGIN_RING(chan, eng2d, 0x0888, 1);
+       OUT_RING  (chan, 1);
+
+       return 0;
+}
+
+int
+nouveau_surface_init_nv50(struct nouveau_context *nv)
+{
+       nv->surface_copy_prep = nv50_surface_copy_prep;
+       nv->surface_copy = nv50_surface_copy;
+       nv->surface_copy_done = nv50_surface_copy_done;
+       nv->surface_fill = nv50_surface_fill;
+       return 0;
+}
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c
new file mode 100644 (file)
index 0000000..d04c4be
--- /dev/null
@@ -0,0 +1,265 @@
+#include "xsp_winsys.h"
+#include <X11/Xutil.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_state.h>
+#include <pipe/p_util.h>
+#include <pipe/p_inlines.h>
+#include <softpipe/sp_winsys.h>
+
+/* pipe_winsys implementation */
+
+struct xsp_pipe_winsys
+{
+       struct pipe_winsys      base;
+       Display                 *display;
+       XImage                  fbimage;
+};
+
+struct xsp_buffer
+{
+       struct pipe_buffer      base;
+       boolean                 is_user_buffer;
+       void                    *data;
+       void                    *mapped_data;
+};
+
+static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
+{
+       struct xsp_buffer *buffer;
+       
+       assert(pws);
+       
+       buffer = calloc(1, sizeof(struct xsp_buffer));
+       buffer->base.refcount = 1;
+       buffer->base.alignment = alignment;
+       buffer->base.usage = usage;
+       buffer->base.size = size;
+       buffer->data = align_malloc(size, alignment);
+       
+       return (struct pipe_buffer*)buffer;
+}
+
+static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
+{
+       struct xsp_buffer *buffer;
+       
+       assert(pws);
+       
+       buffer = calloc(1, sizeof(struct xsp_buffer));
+       buffer->base.refcount = 1;
+       buffer->base.size = size;
+       buffer->is_user_buffer = TRUE;
+       buffer->data = data;
+       
+       return (struct pipe_buffer*)buffer;
+}
+
+static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       xsp_buf->mapped_data = xsp_buf->data;
+       return xsp_buf->mapped_data;
+}
+
+static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       xsp_buf->mapped_data = NULL;
+}
+
+static void xsp_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buffer)
+{
+       struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
+       
+       assert(pws);
+       assert(buffer);
+       
+       if (!xsp_buf->is_user_buffer)
+               align_free(xsp_buf->data);
+       
+       free(xsp_buf);
+}
+
+static struct pipe_surface* xsp_surface_alloc(struct pipe_winsys *pws)
+{
+       struct pipe_surface *surface;
+       
+       assert(pws);
+       
+       surface = calloc(1, sizeof(struct pipe_surface));
+       surface->refcount = 1;
+       surface->winsys = pws;
+       
+       return surface;
+}
+
+/* Borrowed from Mesa's xm_winsys */
+static unsigned int round_up(unsigned n, unsigned multiple)
+{
+   return (n + multiple - 1) & ~(multiple - 1);
+}
+
+static int xsp_surface_alloc_storage
+(
+       struct pipe_winsys *pws,
+       struct pipe_surface *surface,
+       unsigned width,
+       unsigned height,
+       enum pipe_format format,
+       unsigned flags,
+       unsigned tex_usage
+)
+{
+       const unsigned int ALIGNMENT = 1;
+       
+       assert(pws);
+       assert(surface);
+       
+       surface->width = width;
+       surface->height = height;
+       surface->format = format;
+       pf_get_block(format, &surface->block);
+       surface->nblocksx = pf_get_nblocksx(&surface->block, width);
+       surface->nblocksy = pf_get_nblocksy(&surface->block, height);
+       surface->stride = round_up(surface->nblocksx * surface->block.size, ALIGNMENT);
+       surface->usage = flags;
+       /* XXX: Need to consider block dims? See xm_winsys.c */
+       surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * height);
+       
+       return 0;
+}
+
+static void xsp_surface_release(struct pipe_winsys *pws, struct pipe_surface **surface)
+{
+       struct pipe_surface *s;
+       
+       assert(pws);
+       assert(surface);
+       assert(*surface);
+       
+       s = *surface;
+       
+       s->refcount--;
+       
+       if (s->refcount == 0)
+       {
+               pipe_buffer_reference(pws, &s->buffer, NULL);
+               free(s);
+       }
+       
+       *surface = NULL;
+}
+
+static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
+{      
+       struct xsp_pipe_winsys *xsp_winsys;
+       
+       assert(pws);
+       assert(surface);
+       assert(context_private);
+       
+       xsp_winsys = (struct xsp_pipe_winsys*)pws;
+       
+       xsp_winsys->fbimage.width = surface->width;
+       xsp_winsys->fbimage.height = surface->height;
+       xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3);
+       xsp_winsys->fbimage.data = pipe_surface_map(surface, 0);
+       
+       XPutImage
+       (
+               xsp_winsys->display,
+               *(Drawable*)context_private,
+               XDefaultGC(xsp_winsys->display, XDefaultScreen(xsp_winsys->display)),
+               &xsp_winsys->fbimage,
+               0,
+               0,
+               0,
+               0,
+               surface->width,
+               surface->height
+       );
+       XFlush(xsp_winsys->display);
+       pipe_surface_unmap(surface);
+}
+
+static const char* xsp_get_name(struct pipe_winsys *pws)
+{
+       assert(pws);
+       return "X11 SoftPipe";
+}
+
+/* softpipe_winsys implementation */
+
+static boolean xsp_is_format_supported(struct softpipe_winsys *spws, enum pipe_format format)
+{
+       assert(spws);
+       
+       /* TODO: Test that 'format' is equal to our output window's format */
+       return TRUE;
+}
+
+/* Show starts here */
+
+struct pipe_context* create_pipe_context(Display *display)
+{
+       struct xsp_pipe_winsys  *xsp_winsys;
+       struct softpipe_winsys  *sp_winsys;
+       struct pipe_screen      *p_screen;
+       struct pipe_context     *p_context;
+       
+       assert(display);
+       
+       xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys));
+       xsp_winsys->base.buffer_create = xsp_buffer_create;
+       xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
+       xsp_winsys->base.buffer_map = xsp_buffer_map;
+       xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
+       xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
+       xsp_winsys->base.surface_alloc = xsp_surface_alloc;
+       xsp_winsys->base.surface_alloc_storage = xsp_surface_alloc_storage;
+       xsp_winsys->base.surface_release = xsp_surface_release;
+       xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
+       xsp_winsys->base.get_name = xsp_get_name;
+       xsp_winsys->display = display;
+       
+       {
+               /* XXX: Can't use the returned XImage* directly,
+               since we don't have control over winsys destruction
+               and we wouldn't be able to free it */
+               XImage *template = XCreateImage
+               (
+                       display,
+                       XDefaultVisual(display, XDefaultScreen(display)),
+                       XDefaultDepth(display, XDefaultScreen(display)),
+                       ZPixmap,
+                       0,
+                       NULL,
+                       0,      /* Don't know the width and height until flush_frontbuffer */
+                       0,
+                       32,
+                       0
+               );
+               
+               memcpy(&xsp_winsys->fbimage, template, sizeof(XImage));
+               XInitImage(&xsp_winsys->fbimage);
+               
+               XDestroyImage(template);
+       }
+
+       sp_winsys = calloc(1, sizeof(struct softpipe_winsys));
+       sp_winsys->is_format_supported = xsp_is_format_supported;
+       
+       p_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
+       p_context = softpipe_create(p_screen, (struct pipe_winsys*)xsp_winsys, sp_winsys);
+       
+       return p_context;
+}
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.h b/src/gallium/winsys/g3dvl/xsp_winsys.h
new file mode 100644 (file)
index 0000000..47a6ac6
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef xsp_winsys_h
+#define xsp_winsys_h
+
+#include <X11/Xlib.h>
+
+struct pipe_context;
+
+struct pipe_context* create_pipe_context(Display *display);
+
+#endif
+
diff --git a/src/libXvMC/Makefile b/src/libXvMC/Makefile
new file mode 100644 (file)
index 0000000..4985ecd
--- /dev/null
@@ -0,0 +1,33 @@
+TARGET         = libXvMCg3dvl.so
+SONAME         = libXvMCg3dvl.so.1
+GALLIUMDIR     = ../gallium
+OBJECTS                = block.o surface.o context.o subpicture.o attributes.o ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+
+CFLAGS += -g -fPIC -Wall -Werror                       \
+          -I${GALLIUMDIR}/state_trackers/g3dvl         \
+          -I${GALLIUMDIR}/winsys/g3dvl                 \
+          -I${GALLIUMDIR}/include                      \
+          -I${GALLIUMDIR}/auxiliary                    \
+          -I${GALLIUMDIR}/drivers
+LDFLAGS        += -L${GALLIUMDIR}/state_trackers/g3dvl         \
+          -L${GALLIUMDIR}/drivers/softpipe             \
+          -L${GALLIUMDIR}/auxiliary/tgsi               \
+          -L${GALLIUMDIR}/auxiliary/draw               \
+          -L${GALLIUMDIR}/auxiliary/translate          \
+          -L${GALLIUMDIR}/auxiliary/cso_cache          \
+          -L${GALLIUMDIR}/auxiliary/util               \
+          -L${GALLIUMDIR}/auxiliary/rtasm
+LIBS   += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lm
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+       $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf ${OBJECTS} ${TARGET}
+
diff --git a/src/libXvMC/attributes.c b/src/libXvMC/attributes.c
new file mode 100644 (file)
index 0000000..674524b
--- /dev/null
@@ -0,0 +1,20 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+XvAttribute* XvMCQueryAttributes(Display *display, XvMCContext *context, int *number)
+{
+       return NULL;
+}
+
+Status XvMCSetAttribute(Display *display, XvMCContext *context, Atom attribute, int value)
+{
+       return BadImplementation;
+}
+
+Status XvMCGetAttribute(Display *display, XvMCContext *context, Atom attribute, int *value)
+{
+       return BadImplementation;
+}
+
diff --git a/src/libXvMC/block.c b/src/libXvMC/block.c
new file mode 100644 (file)
index 0000000..b56348d
--- /dev/null
@@ -0,0 +1,85 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_context.h>
+
+/*
+ * XvMC defines 64 element blocks (8x8 elements).
+ * Elements are 8 bits when they represent color values,
+ * 9 bits when they reprecent DCT coefficients, we
+ * store them in 2 bytes in either case. DCT coefficients
+ * can be signed or unsigned, at our option.
+ */
+#define BLOCK_SIZE (64 * 2)
+
+Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+       struct vl_context *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (num_blocks == 0)
+               return BadValue;
+       
+       assert(blocks);
+       
+       vl_ctx = context->privData;
+       assert(display == vl_ctx->display);
+
+       blocks->context_id = context->context_id;
+       blocks->num_blocks = num_blocks;
+       blocks->blocks = malloc(BLOCK_SIZE * num_blocks);
+       /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+       blocks->privData = display;
+       
+       return Success;
+}
+
+Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *blocks)
+{      
+       assert(display);
+       assert(blocks);
+       assert(display == blocks->privData);
+       free(blocks->blocks);
+       
+       return Success;
+}
+
+Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
+{
+       struct vl_context *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (num_blocks == 0)
+               return BadValue;
+       
+       assert(blocks);
+       
+       vl_ctx = context->privData;
+       assert(display == vl_ctx->display);
+       
+       blocks->context_id = context->context_id;
+       blocks->num_blocks = num_blocks;
+       blocks->macro_blocks = malloc(sizeof(XvMCMacroBlock) * num_blocks);
+       /* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
+       blocks->privData = display;
+       
+       return Success;
+}
+
+Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *blocks)
+{      
+       assert(display);
+       assert(blocks);
+       assert(display == blocks->privData);
+       free(blocks->macro_blocks);
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/context.c b/src/libXvMC/context.c
new file mode 100644 (file)
index 0000000..c835a6a
--- /dev/null
@@ -0,0 +1,154 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <vl_context.h>
+#include <xsp_winsys.h>
+
+static Status Validate(Display *display, XvPortID port, int surface_type_id, unsigned int width, unsigned int height, int flags, int *chroma_format)
+{
+       unsigned int    found_port = 0;
+       unsigned int    found_surface = 0;
+       XvAdaptorInfo   *adaptor_info;
+       unsigned int    num_adaptors;
+       int             num_types;
+       unsigned int    max_width, max_height;
+       Status          ret;
+       unsigned int    i, j, k;
+       
+       assert(display && chroma_format);
+       
+       ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
+       if (ret != Success)
+               return ret;
+       
+       /* Scan through all adaptors looking for this port and surface */
+       for (i = 0; i < num_adaptors && !found_port; ++i)
+       {
+               /* Scan through all ports of this adaptor looking for our port */
+               for (j = 0; j < adaptor_info[i].num_ports && !found_port; ++j)
+               {
+                       /* If this is our port, scan through all its surfaces looking for our surface */
+                       if (adaptor_info[i].base_id + j == port)
+                       {
+                               XvMCSurfaceInfo *surface_info;
+                               
+                               found_port = 1;
+                               surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+                               
+                               if (surface_info)
+                               {
+                                       for (k = 0; k < num_types && !found_surface; ++k)
+                                       {
+                                               if (surface_info[k].surface_type_id == surface_type_id)
+                                               {
+                                                       found_surface = 1;
+                                                       max_width = surface_info[k].max_width;
+                                                       max_height = surface_info[k].max_height;
+                                                       *chroma_format = surface_info[k].chroma_format;
+                                               }
+                                       }
+                                       
+                                       XFree(surface_info);
+                               }
+                               else
+                               {
+                                       XvFreeAdaptorInfo(adaptor_info);
+                                       return BadAlloc;
+                               }
+                       }
+               }
+       }
+       
+       XvFreeAdaptorInfo(adaptor_info);
+       
+       if (!found_port)
+               return XvBadPort;
+       if (!found_surface)
+               return BadMatch;
+       if (width > max_width || height > max_height)
+               return BadValue;
+       if (flags != XVMC_DIRECT && flags != 0)
+               return BadValue;
+       
+       return Success;
+}
+
+static enum VL_FORMAT FormatToVL(int xvmc_format)
+{
+       enum VL_FORMAT vl_format;
+       
+       switch (xvmc_format)
+       {
+               case XVMC_CHROMA_FORMAT_420:
+               {
+                       vl_format = VL_FORMAT_YCBCR_420;
+                       break;
+               }
+               case XVMC_CHROMA_FORMAT_422:
+               {
+                       vl_format = VL_FORMAT_YCBCR_422;
+                       break;
+               }
+               case XVMC_CHROMA_FORMAT_444:
+               {
+                       vl_format = VL_FORMAT_YCBCR_444;
+                       break;
+               }
+               default:
+                       assert(0);
+       }
+       
+       return vl_format;
+}
+
+Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
+{
+       int                     chroma_format;
+       Status                  ret;
+       struct VL_CONTEXT       *vl_ctx;
+       struct pipe_context     *pipe;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       
+       ret = Validate(display, port, surface_type_id, width, height, flags, &chroma_format);
+       if (ret != Success)
+               return ret;
+       
+       pipe = create_pipe_context(display);
+       
+       assert(pipe);
+       
+       vlCreateContext(display, pipe, width, height, FormatToVL(chroma_format), &vl_ctx);
+       
+       context->context_id = XAllocID(display);
+       context->surface_type_id = surface_type_id;
+       context->width = width;
+       context->height = height;
+       context->flags = flags;
+       context->port = port;
+       context->privData = vl_ctx;
+       
+       return Success;
+}
+
+Status XvMCDestroyContext(Display *display, XvMCContext *context)
+{
+       struct VL_CONTEXT *vl_ctx;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       vlDestroyContext(vl_ctx);
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/subpicture.c b/src/libXvMC/subpicture.c
new file mode 100644 (file)
index 0000000..38d9343
--- /dev/null
@@ -0,0 +1,110 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/XvMC.h>
+
+Status XvMCCreateSubpicture
+(
+       Display *display,
+       XvMCContext *context,
+       XvMCSubpicture *subpicture,
+       unsigned short width,
+       unsigned short height,
+       int xvimage_id
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCClearSubpicture
+(
+       Display *display,
+       XvMCSubpicture *subpicture,
+       short x,
+       short y,
+       unsigned short width,
+       unsigned short height,
+       unsigned int color
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCCompositeSubpicture
+(
+       Display *display,
+       XvMCSubpicture *subpicture,
+       XvImage *image,
+       short srcx,
+       short srcy,
+       unsigned short width,
+       unsigned short height,
+       short dstx,
+       short dsty
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+       return BadImplementation;
+}
+
+Status XvMCBlendSubpicture
+(
+       Display *display,
+       XvMCSurface *target_surface,
+       XvMCSubpicture *subpicture,
+       short subx,
+       short suby,
+       unsigned short subw,
+       unsigned short subh,
+       short surfx,
+       short surfy,
+       unsigned short surfw,
+       unsigned short surfh
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCBlendSubpicture2
+(
+       Display *display,
+       XvMCSurface *source_surface,
+       XvMCSurface *target_surface,
+       XvMCSubpicture *subpicture,
+       short subx,
+       short suby,
+       unsigned short subw,
+       unsigned short subh,
+       short surfx,
+       short surfy,
+       unsigned short surfw,
+       unsigned short surfh
+)
+{
+       return BadImplementation;
+}
+
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+       return BadImplementation;
+}
+
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status)
+{
+       return BadImplementation;
+}
+
diff --git a/src/libXvMC/surface.c b/src/libXvMC/surface.c
new file mode 100644 (file)
index 0000000..a550114
--- /dev/null
@@ -0,0 +1,403 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+
+static enum VL_PICTURE PictureToVL(int xvmc_pic)
+{
+       enum VL_PICTURE vl_pic;
+       
+       switch (xvmc_pic)
+       {
+               case XVMC_TOP_FIELD:
+               {
+                       vl_pic = VL_TOP_FIELD;
+                       break;
+               }
+               case XVMC_BOTTOM_FIELD:
+               {
+                       vl_pic = VL_BOTTOM_FIELD;
+                       break;
+               }
+               case XVMC_FRAME_PICTURE:
+               {
+                       vl_pic = VL_FRAME_PICTURE;
+                       break;
+               }
+               default:
+                       assert(0);
+       }
+       
+       return vl_pic;
+}
+
+static enum VL_MC_TYPE MotionToVL(int xvmc_motion_type)
+{
+       enum VL_MC_TYPE vl_mc_type;
+       
+       switch (xvmc_motion_type)
+       {
+               case XVMC_PREDICTION_FRAME:
+               {
+                       vl_mc_type = VL_FRAME_MC;
+                       break;
+               }
+               case XVMC_PREDICTION_FIELD:
+               {
+                       vl_mc_type = VL_FIELD_MC;
+                       break;
+               }
+               case XVMC_PREDICTION_DUAL_PRIME:
+               {
+                       vl_mc_type = VL_DUAL_PRIME_MC;
+                       break;
+               }
+               default:
+                       assert(0);
+       }
+       
+       return vl_mc_type;
+}
+
+Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       vlCreateSurface(vl_ctx, &vl_sfc);
+       
+       surface->surface_id = XAllocID(display);
+       surface->context_id = context->context_id;
+       surface->surface_type_id = context->surface_type_id;
+       surface->width = context->width;
+       surface->height = context->height;
+       surface->privData = vl_sfc;
+       
+       return Success;
+}
+
+Status XvMCRenderSurface
+(
+       Display *display,
+       XvMCContext *context,
+       unsigned int picture_structure,
+       XvMCSurface *target_surface,
+       XvMCSurface *past_surface,
+       XvMCSurface *future_surface,
+       unsigned int flags,
+       unsigned int num_macroblocks,
+       unsigned int first_macroblock,
+       XvMCMacroBlockArray *macroblocks,
+       XvMCBlockArray *blocks
+)
+{
+       struct VL_CONTEXT       *vl_ctx;
+       struct VL_SURFACE       *target_vl_surface;
+       struct VL_SURFACE       *past_vl_surface;
+       struct VL_SURFACE       *future_vl_surface;
+       unsigned int            i;
+       
+       assert(display);
+       
+       if (!context)
+               return XvMCBadContext;
+       if (!target_surface)
+               return XvMCBadSurface;
+       
+       if
+       (
+               picture_structure != XVMC_TOP_FIELD &&
+               picture_structure != XVMC_BOTTOM_FIELD &&
+               picture_structure != XVMC_FRAME_PICTURE
+       )
+               return BadValue;
+       if (future_surface && !past_surface)
+               return BadMatch;
+       
+       vl_ctx = context->privData;
+       
+       assert(display == vl_ctx->display);
+       
+       target_vl_surface = target_surface->privData;
+       past_vl_surface = past_surface ? past_surface->privData : NULL;
+       future_vl_surface = future_surface ? future_surface->privData : NULL;
+       
+       assert(vl_ctx == target_vl_surface->context);
+       assert(!past_vl_surface || vl_ctx == past_vl_surface->context);
+       assert(!future_vl_surface || vl_ctx == future_vl_surface->context);
+       
+       assert(macroblocks);
+       assert(blocks);
+       
+       assert(macroblocks->context_id == context->context_id);
+       assert(blocks->context_id == context->context_id);
+       
+       assert(flags == 0 || flags == XVMC_SECOND_FIELD);
+       
+       /* TODO: Batch macroblocks by type (I,P,B) */
+       
+       for (i = first_macroblock; i < first_macroblock + num_macroblocks; ++i)
+               if (macroblocks->macro_blocks[i].macroblock_type & XVMC_MB_TYPE_INTRA)
+                       vlRenderIMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               target_vl_surface
+                       );
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == XVMC_MB_TYPE_MOTION_FORWARD
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector =
+                       {
+                               {
+                                       macroblocks->macro_blocks[i].PMV[0][0][0],
+                                       macroblocks->macro_blocks[i].PMV[0][0][1],
+                               },
+                               {
+                                       macroblocks->macro_blocks[i].PMV[1][0][0],
+                                       macroblocks->macro_blocks[i].PMV[1][0][1],
+                               }
+                       };
+                                               
+                       vlRenderPMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               MotionToVL(macroblocks->macro_blocks[i].motion_type),
+                               &motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               past_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == XVMC_MB_TYPE_MOTION_BACKWARD
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector =
+                       {
+                               {
+                                       macroblocks->macro_blocks[i].PMV[0][1][0],
+                                       macroblocks->macro_blocks[i].PMV[0][1][1],
+                               },
+                               {
+                                       macroblocks->macro_blocks[i].PMV[1][1][0],
+                                       macroblocks->macro_blocks[i].PMV[1][1][1],
+                               }
+                       };
+                       
+                       vlRenderPMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               MotionToVL(macroblocks->macro_blocks[i].motion_type),
+                               &motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               future_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else if
+               (
+                       (macroblocks->macro_blocks[i].macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+                       == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)
+               )
+               {
+                       struct VL_MOTION_VECTOR motion_vector[2] =
+                       {
+                               {
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[0][0][0],
+                                               macroblocks->macro_blocks[i].PMV[0][0][1],
+                                       },
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[1][0][0],
+                                               macroblocks->macro_blocks[i].PMV[1][0][1],
+                                       }
+                               },
+                               {
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[0][1][0],
+                                               macroblocks->macro_blocks[i].PMV[0][1][1],
+                                       },
+                                       {
+                                               macroblocks->macro_blocks[i].PMV[1][1][0],
+                                               macroblocks->macro_blocks[i].PMV[1][1][1],
+                                       }
+                               }
+                       };
+                       
+                       vlRenderBMacroBlock
+                       (
+                               PictureToVL(picture_structure),
+                               flags == XVMC_SECOND_FIELD ? VL_FIELD_SECOND : VL_FIELD_FIRST,
+                               macroblocks->macro_blocks[i].x,
+                               macroblocks->macro_blocks[i].y,
+                               MotionToVL(macroblocks->macro_blocks[i].motion_type),
+                               motion_vector,
+                               macroblocks->macro_blocks[i].coded_block_pattern,
+                               macroblocks->macro_blocks[i].dct_type == XVMC_DCT_TYPE_FIELD ? VL_DCT_FIELD_CODED : VL_DCT_FRAME_CODED,
+                               blocks->blocks + (macroblocks->macro_blocks[i].index * 64),
+                               past_vl_surface,
+                               future_vl_surface,
+                               target_vl_surface
+                       );
+               }
+               else
+                       fprintf(stderr, "Unrecognized macroblock\n");
+       
+       return Success;
+}
+
+Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
+{
+       /* TODO: Check display & surface match */
+       return BadImplementation;
+}
+
+Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
+{
+       /* TODO: Check display & surface match */
+       return BadImplementation;
+}
+
+Status XvMCPutSurface
+(
+       Display *display,
+       XvMCSurface *surface,
+       Drawable drawable,
+       short srcx,
+       short srcy,
+       unsigned short srcw,
+       unsigned short srch,
+       short destx,
+       short desty,
+       unsigned short destw,
+       unsigned short desth,
+       int flags
+)
+{
+       Window                  root;
+       int                     x, y;
+       unsigned int            width, height;
+       unsigned int            border_width;
+       unsigned int            depth;
+       struct VL_SURFACE       *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+               
+       if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
+               return BadDrawable;
+       
+       assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
+       
+       /* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
+       
+       assert(srcx + srcw - 1 < surface->width);
+       assert(srcy + srch - 1 < surface->height);
+       assert(destx + destw - 1 < width);
+       assert(desty + desth - 1 < height);
+       
+       vl_sfc = surface->privData;
+       
+       vlPutSurface(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, PictureToVL(flags));
+       
+       return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+               
+       assert(status);
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       /* TODO */
+       *status = 0;
+       
+       return BadImplementation;
+}
+
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       vlDestroySurface(vl_sfc);
+       
+       return Success;
+}
+
+Status XvMCHideSurface(Display *display, XvMCSurface *surface)
+{
+       struct VL_CONTEXT *vl_ctx;
+       struct VL_SURFACE *vl_sfc;
+       
+       assert(display);
+       
+       if (!surface)
+               return XvMCBadSurface;
+       
+       vl_sfc = surface->privData;
+       vl_ctx = vl_sfc->context;
+       
+       assert(display == vl_ctx->display);
+       
+       /* No op, only for overlaid rendering */
+       
+       return Success;
+}
+
diff --git a/src/libXvMC/tests/.gitignore b/src/libXvMC/tests/.gitignore
new file mode 100644 (file)
index 0000000..eb1ef8a
--- /dev/null
@@ -0,0 +1,5 @@
+test_context
+test_surface
+test_blocks
+test_rendering
+
diff --git a/src/libXvMC/tests/Makefile b/src/libXvMC/tests/Makefile
new file mode 100644 (file)
index 0000000..2cbc97e
--- /dev/null
@@ -0,0 +1,25 @@
+CFLAGS += -g -Wall -Werror
+LDFLAGS        +=
+LIBS   += -lXvMCW -lXvMC -lXv
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_blocks test_rendering
+
+test_context: test_context.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_surface: test_surface.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_blocks: test_blocks.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+test_rendering: test_rendering.o testlib.o
+       $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+       rm -rf *.o test_context test_surface test_blocks test_rendering
+
diff --git a/src/libXvMC/tests/test_blocks.c b/src/libXvMC/tests/test_blocks.c
new file mode 100644 (file)
index 0000000..0b895ee
--- /dev/null
@@ -0,0 +1,95 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      min_required_blocks = 1, min_required_macroblocks = 1;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          blocks = {0};
+       XvMCMacroBlockArray     macroblocks = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       
+       /* Test NULL context */
+       assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext);
+       /* Test 0 blocks */
+       assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue);
+       /* Test too many blocks */
+       /*assert(XvMCCreateBlocks(display, &context, 16384, &blocks) == BadAlloc);*/
+       
+       /* Note: No XvMCBadBlock(s) error in spec */
+       
+       /* Test valid params */
+       assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success);
+       /* Test context id assigned and correct */
+       assert(blocks.context_id == context.context_id);
+       /* Test number of blocks assigned and correct */
+       assert(blocks.num_blocks == min_required_blocks);
+       /* Test block pointer valid */
+       assert(blocks.blocks != NULL);
+       /* Test NULL context */
+       assert(XvMCCreateMacroBlocks(display, NULL, 1, &macroblocks) == XvMCBadContext);
+       /* Test 0 macroblocks */
+       assert(XvMCCreateMacroBlocks(display, &context, 0, &macroblocks) == BadValue);
+       /* Test too many macroblocks */
+       /*assert(XvMCCreateMacroBlocks(display, &context, 16384, &macroblocks) == BadAlloc);*/
+
+       /* Note: No XvMCBadMacroBlock(s) error in spec */
+
+       /* Test valid params */
+       assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, &macroblocks) == Success);
+       /* Test context id assigned and correct */
+       assert(macroblocks.context_id == context.context_id);
+       /* Test macroblock pointer valid */
+       assert(macroblocks.macro_blocks != NULL);
+       /* Test valid params */
+       assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+       /* Test valid params */
+       assert(XvMCDestroyBlocks(display, &blocks) == Success);
+       
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_context.c b/src/libXvMC/tests/test_context.c
new file mode 100644 (file)
index 0000000..22afb7a
--- /dev/null
@@ -0,0 +1,94 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       /* Note: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+       /* Note: Nvidia binary driver segfaults on NULL context, halts with debug output on bad port */
+       
+       /* Test NULL context */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+       /* Test invalid port */
+       assert(XvMCCreateContext(display, port_num + 1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+       /* Test invalid surface */
+       assert(XvMCCreateContext(display, port_num, surface_type_id + 1, width, height, XVMC_DIRECT, &context) == BadMatch);
+       /* Test invalid flags */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue);
+       /* Test huge width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test huge width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue);
+       /* Test valid params */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       /* Test context id assigned */
+       assert(context.context_id != 0);
+       /* Test surface type id assigned and correct */
+       assert(context.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(context.width == width && context.height == height);
+       /* Test port assigned and correct */
+       assert(context.port == port_num);
+       /* Test flags assigned and correct */
+       assert(context.flags == XVMC_DIRECT);
+       /* Test NULL context */
+       assert(XvMCDestroyContext(display, NULL) == XvMCBadContext);
+       /* Test valid params */
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       /* Test awkward but valid width & height */
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success);
+       assert(context.width >= width + 1 && context.height >= height + 1);
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_rendering.c b/src/libXvMC/tests/test_rendering.c
new file mode 100644 (file)
index 0000000..1914b1f
--- /dev/null
@@ -0,0 +1,153 @@
+#include <assert.h>
+#include <stdio.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 32, height = 32;
+       const unsigned int      mwidth = width / 16, mheight = height / 16;
+       const unsigned int      num_macroblocks = mwidth * mheight;
+       const unsigned int      num_blocks = num_macroblocks * 6;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       int                     quit = 0;
+       Display                 *display;
+       Window                  root, window;
+       Pixmap                  framebuffer;
+       XEvent                  event;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface;
+       XvMCBlockArray          blocks;
+       XvMCMacroBlockArray     macroblocks;
+       unsigned int            b, x, y;
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       root = XDefaultRootWindow(display);
+       window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, colorkey);
+       framebuffer = XCreatePixmap(display, root, width, height, 24);
+       
+       XSelectInput(display, window, ExposureMask | KeyPressMask);
+       XMapWindow(display, window);
+       XSync(display, 0);
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       assert(XvMCCreateBlocks(display, &context, num_blocks, &blocks) == Success);
+       assert(XvMCCreateMacroBlocks(display, &context, num_macroblocks, &macroblocks) == Success);
+       
+       for (b = 0; b < 6; ++b)
+       {
+               for (y = 0; y < 8; ++y)
+               {
+                       for (x = 0; x < 8; ++x)
+                       {
+                               blocks.blocks[b * 64 + y * 8 + x] = 0xFFFF;
+                       }
+               }
+       }
+       
+       for (y = 0; y < mheight; ++y)
+       {
+               for (x = 0; x < mwidth; ++x)
+               {
+                       macroblocks.macro_blocks[y * mwidth + x].x = x;
+                       macroblocks.macro_blocks[y * mwidth + x].y = y;
+                       macroblocks.macro_blocks[y * mwidth + x].index = (y * mwidth + x) * 6;
+                       macroblocks.macro_blocks[y * mwidth + x].macroblock_type = XVMC_MB_TYPE_INTRA;
+                       macroblocks.macro_blocks[y * mwidth + x].coded_block_pattern = 0x3F;
+                       macroblocks.macro_blocks[y * mwidth + x].dct_type = XVMC_DCT_TYPE_FRAME;
+               }
+       }
+       
+       /* Test NULL context */
+       assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == XvMCBadSurface);
+       /* Test bad picture structure */
+       assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, 1, 0, &macroblocks, &blocks) == BadValue);
+       /* Test valid params */
+       assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, num_macroblocks, 0, &macroblocks, &blocks) == Success);
+       
+       /* Test NULL surface */
+       assert(XvMCPutSurface(display, NULL, window, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+       /* Test bad window */
+       /* X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
+       /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
+       /* Test valid params */
+       assert(XvMCPutSurface(display, &surface, framebuffer, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == Success);
+       
+       puts("Press any key to continue...");
+       
+       while (!quit)
+       {
+               XNextEvent(display, &event);
+               switch (event.type)
+               {
+                       case Expose:
+                       {
+                               XCopyArea
+                               (
+                                       display,
+                                       framebuffer,
+                                       window,
+                                       XDefaultGC(display, XDefaultScreen(display)),
+                                       0,
+                                       0,
+                                       width,
+                                       height,
+                                       0,
+                                       0
+                               );
+                               break;
+                       }
+                       case KeyPress:
+                       {
+                               quit = 1;
+                               break;
+                       }
+               }
+       }
+       
+       assert(XvMCDestroyBlocks(display, &blocks) == Success);
+       assert(XvMCDestroyMacroBlocks(display, &macroblocks) == Success);
+       assert(XvMCDestroySurface(display, &surface) == Success);       
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XFreePixmap(display, framebuffer);
+       XvUngrabPort(display, port_num, CurrentTime);
+       XDestroyWindow(display, window);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/test_surface.c b/src/libXvMC/tests/test_surface.c
new file mode 100644 (file)
index 0000000..25ebdcc
--- /dev/null
@@ -0,0 +1,72 @@
+#include <assert.h>
+#include <error.h>
+#include "testlib.h"
+
+int main(int argc, char **argv)
+{
+       const unsigned int      width = 16, height = 16;
+       const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+       
+       Display                 *display;
+       XvPortID                port_num;
+       int                     surface_type_id;
+       unsigned int            is_overlay, intra_unsigned;
+       int                     colorkey;
+       XvMCContext             context;
+       XvMCSurface             surface = {0};
+       
+       display = XOpenDisplay(NULL);
+       
+       if (!GetPort
+       (
+               display,
+               width,
+               height,
+               XVMC_CHROMA_FORMAT_420,
+               mc_types,
+               2,
+               &port_num,
+               &surface_type_id,
+               &is_overlay,
+               &intra_unsigned
+       ))
+       {
+               XCloseDisplay(display);
+               error(1, 0, "Error, unable to find a good port.\n");
+       }
+       
+       if (is_overlay)
+       {
+               Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
+               XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
+       }
+       
+       assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
+       
+       /* Test NULL context */
+       assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
+       /* Test NULL surface */
+       assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface);
+       /* Test valid params */
+       assert(XvMCCreateSurface(display, &context, &surface) == Success);
+       /* Test surface id assigned */
+       assert(surface.surface_id != 0);
+       /* Test context id assigned and correct */
+       assert(surface.context_id == context.context_id);
+       /* Test surface type id assigned and correct */
+       assert(surface.surface_type_id == surface_type_id);
+       /* Test width & height assigned and correct */
+       assert(surface.width == width && surface.height == height);
+       /* Test valid params */
+       assert(XvMCDestroySurface(display, &surface) == Success);
+       /* Test NULL surface */
+       assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
+       
+       assert(XvMCDestroyContext(display, &context) == Success);
+       
+       XvUngrabPort(display, port_num, CurrentTime);
+       XCloseDisplay(display);
+       
+       return 0;
+}
+
diff --git a/src/libXvMC/tests/testlib.c b/src/libXvMC/tests/testlib.c
new file mode 100644 (file)
index 0000000..8672aa9
--- /dev/null
@@ -0,0 +1,87 @@
+#include "testlib.h"
+#include <stdio.h>
+
+/*
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line)
+{
+       fputs(doc_string, stderr);
+       if (!pred)
+               fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line);
+       else
+               fputs(" PASS!\n", stderr);
+}
+*/
+
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+)
+{
+       unsigned int    found_port = 0;
+       XvAdaptorInfo   *adaptor_info;
+       unsigned int    num_adaptors;
+       int             num_types;
+       int             ev_base, err_base;
+       unsigned int    i, j, k, l;
+       
+       if (!XvMCQueryExtension(display, &ev_base, &err_base))
+               return 0;
+       if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success)
+               return 0;
+       
+       for (i = 0; i < num_adaptors && !found_port; ++i)
+       {
+               if (adaptor_info[i].type & XvImageMask)
+               {
+                       XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
+                       
+                       if (surface_info)
+                       {
+                               for (j = 0; j < num_types && !found_port; ++j)
+                               {
+                                       if
+                                       (
+                                               surface_info[j].chroma_format == chroma_format &&
+                                               surface_info[j].max_width >= width &&
+                                               surface_info[j].max_height >= height
+                                       )
+                                       {
+                                               for (k = 0; k < num_mc_types && !found_port; ++k)
+                                               {
+                                                       if (surface_info[j].mc_type == mc_types[k])
+                                                       {
+                                                               for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l)
+                                                               {
+                                                                       if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success)
+                                                                       {
+                                                                               *port_id = adaptor_info[i].base_id + l;
+                                                                               *surface_type_id = surface_info[j].surface_type_id;
+                                                                               *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE;
+                                                                               *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED;
+                                                                               found_port = 1;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               
+                               XFree(surface_info);
+                       }
+               }
+       }
+       
+       XvFreeAdaptorInfo(adaptor_info);
+       
+       return found_port;
+}
+
diff --git a/src/libXvMC/tests/testlib.h b/src/libXvMC/tests/testlib.h
new file mode 100644 (file)
index 0000000..c738458
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef testlib_h
+#define testlib_h
+
+/*
+#define TEST(pred, doc)        test(pred, #pred, doc, __FILE__, __LINE__)
+
+void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line);
+*/
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+
+/*
+ * display: IN                 A valid X display
+ * width, height: IN           Surface size that the port must display
+ * chroma_format: IN           Chroma format that the port must display
+ * mc_types, num_mc_types: IN  List of MC types that the port must support, first port that matches the first mc_type will be returned
+ * port_id: OUT                        Your port's ID
+ * surface_type_id: OUT                Your port's surface ID
+ * is_overlay: OUT             If 1, port uses overlay surfaces, you need to set a colorkey
+ * intra_unsigned: OUT         If 1, port uses unsigned values for intra-coded blocks
+ */
+int GetPort
+(
+       Display *display,
+       unsigned int width,
+       unsigned int height,
+       unsigned int chroma_format,
+       const unsigned int *mc_types,
+       unsigned int num_mc_types,
+       XvPortID *port_id,
+       int *surface_type_id,
+       unsigned int *is_overlay,
+       unsigned int *intra_unsigned
+);
+
+#endif
+
index f8337ff93eea14f5c15d2ca8ad55e88b4e9ebeef..cb34061b36cacbf625af0b381aeaed1ea16487ab 100644 (file)
@@ -73,7 +73,7 @@ _x86_64_get_dispatch:
 
        .p2align        4,,15
 _x86_64_get_dispatch:
-       movq    _gl_DispatchTSD@GOTPCREL(%rip), %rdi
+       movq    _gl_DispatchTSD(%rip), %rdi
        jmp     pthread_getspecific@PLT
 
 #elif defined(THREADS)