summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/default2
-rw-r--r--src/driclient/include/driclient.h97
-rw-r--r--src/driclient/include/xf86dri.h119
-rw-r--r--src/driclient/src/Makefile19
-rw-r--r--src/driclient/src/XF86dri.c619
-rw-r--r--src/driclient/src/driclient.c295
-rw-r--r--src/driclient/src/xf86dristr.h342
-rw-r--r--src/gallium/drivers/nouveau/nouveau_bo.h54
-rw-r--r--src/gallium/drivers/nouveau/nouveau_channel.h40
-rw-r--r--src/gallium/drivers/nouveau/nouveau_class.h6259
-rw-r--r--src/gallium/drivers/nouveau/nouveau_device.h30
-rw-r--r--src/gallium/drivers/nouveau/nouveau_gldefs.h196
-rw-r--r--src/gallium/drivers/nouveau/nouveau_grobj.h35
-rw-r--r--src/gallium/drivers/nouveau/nouveau_notifier.h43
-rw-r--r--src/gallium/drivers/nouveau/nouveau_push.h82
-rw-r--r--src/gallium/drivers/nouveau/nouveau_pushbuf.h32
-rw-r--r--src/gallium/drivers/nouveau/nouveau_resource.h37
-rw-r--r--src/gallium/drivers/nouveau/nouveau_stateobj.h158
-rw-r--r--src/gallium/drivers/nouveau/nouveau_util.h64
-rw-r--r--src/gallium/drivers/nouveau/nouveau_winsys.h96
-rw-r--r--src/gallium/drivers/nv04/Makefile28
-rw-r--r--src/gallium/drivers/nv04/nv04_clear.c12
-rw-r--r--src/gallium/drivers/nv04/nv04_context.c106
-rw-r--r--src/gallium/drivers/nv04/nv04_context.h146
-rw-r--r--src/gallium/drivers/nv04/nv04_fragprog.c21
-rw-r--r--src/gallium/drivers/nv04/nv04_fragtex.c98
-rw-r--r--src/gallium/drivers/nv04/nv04_miptree.c138
-rw-r--r--src/gallium/drivers/nv04/nv04_prim_vbuf.c309
-rw-r--r--src/gallium/drivers/nv04/nv04_screen.c212
-rw-r--r--src/gallium/drivers/nv04/nv04_screen.h25
-rw-r--r--src/gallium/drivers/nv04/nv04_state.c495
-rw-r--r--src/gallium/drivers/nv04/nv04_state.h71
-rw-r--r--src/gallium/drivers/nv04/nv04_state_emit.c156
-rw-r--r--src/gallium/drivers/nv04/nv04_surface.c64
-rw-r--r--src/gallium/drivers/nv04/nv04_vbo.c71
-rw-r--r--src/gallium/drivers/nv10/Makefile28
-rw-r--r--src/gallium/drivers/nv10/nv10_clear.c12
-rw-r--r--src/gallium/drivers/nv10/nv10_context.c296
-rw-r--r--src/gallium/drivers/nv10/nv10_context.h153
-rw-r--r--src/gallium/drivers/nv10/nv10_fragprog.c21
-rw-r--r--src/gallium/drivers/nv10/nv10_fragtex.c149
-rw-r--r--src/gallium/drivers/nv10/nv10_miptree.c149
-rw-r--r--src/gallium/drivers/nv10/nv10_prim_vbuf.c240
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.c208
-rw-r--r--src/gallium/drivers/nv10/nv10_screen.h22
-rw-r--r--src/gallium/drivers/nv10/nv10_state.c588
-rw-r--r--src/gallium/drivers/nv10/nv10_state.h139
-rw-r--r--src/gallium/drivers/nv10/nv10_state_emit.c303
-rw-r--r--src/gallium/drivers/nv10/nv10_surface.c64
-rw-r--r--src/gallium/drivers/nv10/nv10_vbo.c77
-rw-r--r--src/gallium/drivers/nv20/Makefile29
-rw-r--r--src/gallium/drivers/nv20/nv20_clear.c12
-rw-r--r--src/gallium/drivers/nv20/nv20_context.c296
-rw-r--r--src/gallium/drivers/nv20/nv20_context.h153
-rw-r--r--src/gallium/drivers/nv20/nv20_fragprog.c21
-rw-r--r--src/gallium/drivers/nv20/nv20_fragtex.c149
-rw-r--r--src/gallium/drivers/nv20/nv20_miptree.c156
-rw-r--r--src/gallium/drivers/nv20/nv20_prim_vbuf.c240
-rw-r--r--src/gallium/drivers/nv20/nv20_screen.c208
-rw-r--r--src/gallium/drivers/nv20/nv20_screen.h22
-rw-r--r--src/gallium/drivers/nv20/nv20_state.c588
-rw-r--r--src/gallium/drivers/nv20/nv20_state.h139
-rw-r--r--src/gallium/drivers/nv20/nv20_state_emit.c303
-rw-r--r--src/gallium/drivers/nv20/nv20_surface.c64
-rw-r--r--src/gallium/drivers/nv20/nv20_vbo.c77
-rw-r--r--src/gallium/drivers/nv20/nv20_vertprog.c838
-rw-r--r--src/gallium/drivers/nv30/Makefile37
-rw-r--r--src/gallium/drivers/nv30/nv30_clear.c13
-rw-r--r--src/gallium/drivers/nv30/nv30_context.c72
-rw-r--r--src/gallium/drivers/nv30/nv30_context.h212
-rw-r--r--src/gallium/drivers/nv30/nv30_draw.c61
-rw-r--r--src/gallium/drivers/nv30/nv30_fragprog.c911
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c186
-rw-r--r--src/gallium/drivers/nv30/nv30_miptree.c162
-rw-r--r--src/gallium/drivers/nv30/nv30_query.c122
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.c332
-rw-r--r--src/gallium/drivers/nv30/nv30_screen.h35
-rw-r--r--src/gallium/drivers/nv30/nv30_shader.h490
-rw-r--r--src/gallium/drivers/nv30/nv30_state.c724
-rw-r--r--src/gallium/drivers/nv30/nv30_state.h85
-rw-r--r--src/gallium/drivers/nv30/nv30_state_blend.c40
-rw-r--r--src/gallium/drivers/nv30/nv30_state_emit.c118
-rw-r--r--src/gallium/drivers/nv30/nv30_state_fb.c128
-rw-r--r--src/gallium/drivers/nv30/nv30_state_rasterizer.c17
-rw-r--r--src/gallium/drivers/nv30/nv30_state_scissor.c35
-rw-r--r--src/gallium/drivers/nv30/nv30_state_stipple.c39
-rw-r--r--src/gallium/drivers/nv30/nv30_state_viewport.c70
-rw-r--r--src/gallium/drivers/nv30/nv30_state_zsa.c17
-rw-r--r--src/gallium/drivers/nv30/nv30_surface.c77
-rw-r--r--src/gallium/drivers/nv30/nv30_vbo.c556
-rw-r--r--src/gallium/drivers/nv30/nv30_vertprog.c838
-rw-r--r--src/gallium/drivers/nv40/Makefile37
-rw-r--r--src/gallium/drivers/nv40/nv40_clear.c13
-rw-r--r--src/gallium/drivers/nv40/nv40_context.c72
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h233
-rw-r--r--src/gallium/drivers/nv40/nv40_draw.c349
-rw-r--r--src/gallium/drivers/nv40/nv40_fragprog.c991
-rw-r--r--src/gallium/drivers/nv40/nv40_fragtex.c169
-rw-r--r--src/gallium/drivers/nv40/nv40_miptree.c164
-rw-r--r--src/gallium/drivers/nv40/nv40_query.c122
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.c314
-rw-r--r--src/gallium/drivers/nv40/nv40_screen.h35
-rw-r--r--src/gallium/drivers/nv40/nv40_shader.h556
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c740
-rw-r--r--src/gallium/drivers/nv40/nv40_state.h88
-rw-r--r--src/gallium/drivers/nv40/nv40_state_blend.c40
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c184
-rw-r--r--src/gallium/drivers/nv40/nv40_state_fb.c144
-rw-r--r--src/gallium/drivers/nv40/nv40_state_rasterizer.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_state_scissor.c35
-rw-r--r--src/gallium/drivers/nv40/nv40_state_stipple.c39
-rw-r--r--src/gallium/drivers/nv40/nv40_state_viewport.c67
-rw-r--r--src/gallium/drivers/nv40/nv40_state_zsa.c17
-rw-r--r--src/gallium/drivers/nv40/nv40_surface.c77
-rw-r--r--src/gallium/drivers/nv40/nv40_vbo.c555
-rw-r--r--src/gallium/drivers/nv40/nv40_vertprog.c1070
-rw-r--r--src/gallium/drivers/nv50/Makefile29
-rw-r--r--src/gallium/drivers/nv50/nv50_clear.c90
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c90
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h185
-rw-r--r--src/gallium/drivers/nv50/nv50_draw.c89
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c135
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c1708
-rw-r--r--src/gallium/drivers/nv50/nv50_program.h45
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c69
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c323
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.h33
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c638
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c309
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c123
-rw-r--r--src/gallium/drivers/nv50/nv50_tex.c124
-rw-r--r--src/gallium/drivers/nv50/nv50_texture.h126
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c237
-rw-r--r--src/gallium/state_trackers/g3dvl/Makefile18
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_basic_csc.c707
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_basic_csc.h13
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_context.c210
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_context.h73
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_csc.h53
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_defs.h11
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_display.c48
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_display.h29
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.c2344
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.h18
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c2321
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h18
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_render.h38
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_screen.c115
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_screen.h63
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_shader_build.c215
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_shader_build.h61
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_surface.c237
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_surface.h86
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_types.h115
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_util.c16
-rw-r--r--src/gallium/state_trackers/g3dvl/vl_util.h6
-rw-r--r--src/gallium/winsys/drm/nouveau/Makefile46
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_bo.c470
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_channel.c126
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_context.c346
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_context.h113
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_device.c159
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_dma.c219
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_dma.h143
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_dri.h28
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_drmif.h310
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_fence.c214
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_grobj.c107
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_local.h117
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_lock.c94
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_notifier.c137
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_pushbuf.c271
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_resource.c116
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_screen.c265
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_screen.h20
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.c86
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.h10
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_winsys.c161
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.c206
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.h34
-rw-r--r--src/gallium/winsys/drm/nouveau/nouveau_winsys_softpipe.c85
-rw-r--r--src/gallium/winsys/drm/nouveau/nv04_surface.c413
-rw-r--r--src/gallium/winsys/drm/nouveau/nv50_surface.c194
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/Makefile50
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c1
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_context.c370
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_context.h105
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_device.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_local.h1
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c92
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c1
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c91
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h24
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c64
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h10
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c1
-rw-r--r--src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c260
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h1
l---------src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c1
l---------src/gallium/winsys/g3dvl/nouveau/nv04_surface.c1
l---------src/gallium/winsys/g3dvl/nouveau/nv50_surface.c1
-rw-r--r--src/gallium/winsys/g3dvl/vl_winsys.h14
-rw-r--r--src/gallium/winsys/g3dvl/xsp_winsys.c336
-rw-r--r--src/libXvMC/Makefile73
-rw-r--r--src/libXvMC/attributes.c20
-rw-r--r--src/libXvMC/block.c79
-rw-r--r--src/libXvMC/context.c201
-rw-r--r--src/libXvMC/subpicture.c215
-rw-r--r--src/libXvMC/surface.c350
-rw-r--r--src/libXvMC/tests/.gitignore5
-rw-r--r--src/libXvMC/tests/Makefile27
-rw-r--r--src/libXvMC/tests/test_blocks.c84
-rw-r--r--src/libXvMC/tests/test_context.c92
-rw-r--r--src/libXvMC/tests/test_rendering.c287
-rw-r--r--src/libXvMC/tests/test_surface.c72
-rw-r--r--src/libXvMC/tests/testlib.c119
-rw-r--r--src/libXvMC/tests/testlib.h42
-rw-r--r--src/libXvMC/tests/xvmc_bench.c271
-rw-r--r--src/mesa/x86-64/glapi_x86-64.S2
228 files changed, 46849 insertions, 2 deletions
diff --git a/configs/default b/configs/default
index 5fd4c26d37..d3efc4b3d0 100644
--- a/configs/default
+++ b/configs/default
@@ -89,7 +89,7 @@ EGL_DRIVERS_DIRS = demo
# 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 nv20 nv30 nv40 nv50 failover
GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVER_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)
GALLIUM_WINSYS_DIRS = xlib egl_xlib
diff --git a/src/driclient/include/driclient.h b/src/driclient/include/driclient.h
new file mode 100644
index 0000000000..d391525039
--- /dev/null
+++ b/src/driclient/include/driclient.h
@@ -0,0 +1,97 @@
+#ifndef driclient_h
+#define driclient_h
+
+#include <stdint.h>
+#include <X11/Xlib.h>
+#include <drm_sarea.h>
+#include "xf86dri.h"
+
+/* TODO: Bring in DRI XML options */
+
+typedef struct dri_version
+{
+ int major;
+ int minor;
+ int patch;
+} dri_version_t;
+
+typedef struct dri_screen
+{
+ Display *display;
+ unsigned int num;
+ dri_version_t ddx, dri, drm;
+ int draw_lock_id;
+ int fd;
+ drm_sarea_t *sarea;
+ void *drawable_hash;
+ void *private;
+} dri_screen_t;
+
+struct dri_context;
+
+typedef struct dri_drawable
+{
+ drm_drawable_t drm_drawable;
+ Drawable x_drawable;
+ unsigned int sarea_index;
+ unsigned int *sarea_stamp;
+ unsigned int last_sarea_stamp;
+ int x, y, w, h;
+ int back_x, back_y;
+ int num_cliprects, num_back_cliprects;
+ drm_clip_rect_t *cliprects, *back_cliprects;
+ dri_screen_t *dri_screen;
+ unsigned int refcount;
+ void *private;
+} dri_drawable_t;
+
+typedef struct dri_context
+{
+ XID id;
+ drm_context_t drm_context;
+ dri_screen_t *dri_screen;
+ void *private;
+} dri_context_t;
+
+typedef struct dri_framebuffer
+{
+ drm_handle_t drm_handle;
+ int base, size, stride;
+ int private_size;
+ void *private;
+} dri_framebuffer_t;
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf);
+int driDestroyScreen(dri_screen_t *dri_screen);
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable);
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable);
+int driDestroyDrawable(dri_drawable_t *dri_drawable);
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context);
+int driDestroyContext(dri_context_t *dri_context);
+
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable) \
+do \
+{ \
+ if (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp) \
+ driUpdateDrawableInfo(dri_drawable); \
+} while (0)
+
+#define DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable) \
+do \
+{ \
+ while (*(dri_drawable->sarea_stamp) != dri_drawable->last_sarea_stamp) \
+ { \
+ register unsigned int hwContext = dri_screen->sarea->lock.lock & \
+ ~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
+ DRM_UNLOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext); \
+ \
+ DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(dri_drawable); \
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id); \
+ \
+ DRM_LIGHT_LOCK(dri_screen->fd, &dri_screen->sarea->lock, hwContext); \
+ } \
+} while (0)
+
+#endif
+
diff --git a/src/driclient/include/xf86dri.h b/src/driclient/include/xf86dri.h
new file mode 100644
index 0000000000..baf80a7a9d
--- /dev/null
+++ b/src/driclient/include/xf86dri.h
@@ -0,0 +1,119 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/**
+ * \file xf86dri.h
+ * Protocol numbers and function prototypes for DRI X protocol.
+ *
+ * \author Kevin E. Martin <martin@valinux.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+#ifndef _XF86DRI_H_
+#define _XF86DRI_H_
+
+#include <X11/Xfuncproto.h>
+#include <xf86drm.h>
+
+#define X_XF86DRIQueryVersion 0
+#define X_XF86DRIQueryDirectRenderingCapable 1
+#define X_XF86DRIOpenConnection 2
+#define X_XF86DRICloseConnection 3
+#define X_XF86DRIGetClientDriverName 4
+#define X_XF86DRICreateContext 5
+#define X_XF86DRIDestroyContext 6
+#define X_XF86DRICreateDrawable 7
+#define X_XF86DRIDestroyDrawable 8
+#define X_XF86DRIGetDrawableInfo 9
+#define X_XF86DRIGetDeviceInfo 10
+#define X_XF86DRIAuthConnection 11
+#define X_XF86DRIOpenFullScreen 12 /* Deprecated */
+#define X_XF86DRICloseFullScreen 13 /* Deprecated */
+
+#define XF86DRINumberEvents 0
+
+#define XF86DRIClientNotLocal 0
+#define XF86DRIOperationNotSupported 1
+#define XF86DRINumberErrors (XF86DRIOperationNotSupported + 1)
+
+#ifndef _XF86DRI_SERVER_
+
+_XFUNCPROTOBEGIN
+
+Bool XF86DRIQueryExtension( Display *dpy, int *event_base, int *error_base );
+
+Bool XF86DRIQueryVersion( Display *dpy, int *majorVersion, int *minorVersion,
+ int *patchVersion );
+
+Bool XF86DRIQueryDirectRenderingCapable( Display *dpy, int screen,
+ Bool *isCapable );
+
+Bool XF86DRIOpenConnection( Display *dpy, int screen, drm_handle_t *hSAREA,
+ char **busIDString );
+
+Bool XF86DRIAuthConnection( Display *dpy, int screen, drm_magic_t magic );
+
+Bool XF86DRICloseConnection( Display *dpy, int screen );
+
+Bool XF86DRIGetClientDriverName( Display *dpy, int screen,
+ int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
+ int *ddxDriverPatchVersion, char **clientDriverName );
+
+Bool XF86DRICreateContext( Display *dpy, int screen, Visual *visual,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRICreateContextWithConfig( Display *dpy, int screen, int configID,
+ XID *ptr_to_returned_context_id, drm_context_t *hHWContext );
+
+Bool XF86DRIDestroyContext( Display *dpy, int screen,
+ XID context_id );
+
+Bool XF86DRICreateDrawable( Display *dpy, int screen,
+ Drawable drawable, drm_drawable_t *hHWDrawable );
+
+Bool XF86DRIDestroyDrawable( Display *dpy, int screen,
+ Drawable drawable);
+
+Bool XF86DRIGetDrawableInfo( Display *dpy, int screen, Drawable drawable,
+ unsigned int *index, unsigned int *stamp,
+ int *X, int *Y, int *W, int *H,
+ int *numClipRects, drm_clip_rect_t ** pClipRects,
+ int *backX, int *backY,
+ int *numBackClipRects, drm_clip_rect_t **pBackClipRects );
+
+Bool XF86DRIGetDeviceInfo( Display *dpy, int screen,
+ drm_handle_t *hFrameBuffer, int *fbOrigin, int *fbSize,
+ int *fbStride, int *devPrivateSize, void **pDevPrivate );
+
+_XFUNCPROTOEND
+
+#endif /* _XF86DRI_SERVER_ */
+
+#endif /* _XF86DRI_H_ */
+
diff --git a/src/driclient/src/Makefile b/src/driclient/src/Makefile
new file mode 100644
index 0000000000..34435a2086
--- /dev/null
+++ b/src/driclient/src/Makefile
@@ -0,0 +1,19 @@
+TARGET = libdriclient.a
+OBJECTS = driclient.o XF86dri.o
+DRMDIR ?= /usr
+
+CFLAGS += -g -Wall -fPIC -I../include -I${DRMDIR}/include -I${DRMDIR}/include/drm
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+ ar rcs $@ $^
+ if ! test -d ../lib; then mkdir ../lib; fi
+ cp ${TARGET} ../lib
+
+clean:
+ rm -rf ${OBJECTS} ${TARGET} ../lib/${TARGET}
diff --git a/src/driclient/src/XF86dri.c b/src/driclient/src/XF86dri.c
new file mode 100644
index 0000000000..9e359a9238
--- /dev/null
+++ b/src/driclient/src/XF86dri.c
@@ -0,0 +1,619 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "xf86dristr.h"
+
+static XExtensionInfo _xf86dri_info_data;
+static XExtensionInfo *xf86dri_info = &_xf86dri_info_data;
+static char xf86dri_extension_name[] = XF86DRINAME;
+
+#define XF86DRICheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, xf86dri_extension_name, val)
+
+/*****************************************************************************
+ * *
+ * private utility routines *
+ * *
+ *****************************************************************************/
+
+static int close_display(Display *dpy, XExtCodes *extCodes);
+static /* const */ XExtensionHooks xf86dri_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ NULL, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86dri_info,
+ xf86dri_extension_name,
+ &xf86dri_extension_hooks,
+ 0, NULL)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86dri_info)
+
+
+/*****************************************************************************
+ * *
+ * public XFree86-DRI Extension routines *
+ * *
+ *****************************************************************************/
+
+#if 0
+#include <stdio.h>
+#define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg);
+#else
+#define TRACE(msg)
+#endif
+
+#define PUBLIC
+
+PUBLIC Bool XF86DRIQueryExtension (dpy, event_basep, error_basep)
+ Display *dpy;
+ int *event_basep, *error_basep;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+
+ TRACE("QueryExtension...");
+ if (XextHasExtension(info)) {
+ *event_basep = info->codes->first_event;
+ *error_basep = info->codes->first_error;
+ TRACE("QueryExtension... return True");
+ return True;
+ } else {
+ TRACE("QueryExtension... return False");
+ return False;
+ }
+}
+
+PUBLIC Bool XF86DRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
+ Display* dpy;
+ int* majorVersion;
+ int* minorVersion;
+ int* patchVersion;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryVersionReply rep;
+ xXF86DRIQueryVersionReq *req;
+
+ TRACE("QueryVersion...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryVersion, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryVersion;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return False");
+ return False;
+ }
+ *majorVersion = rep.majorVersion;
+ *minorVersion = rep.minorVersion;
+ *patchVersion = rep.patchVersion;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryVersion... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIQueryDirectRenderingCapable(dpy, screen, isCapable)
+ Display* dpy;
+ int screen;
+ Bool* isCapable;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIQueryDirectRenderingCapableReply rep;
+ xXF86DRIQueryDirectRenderingCapableReq *req;
+
+ TRACE("QueryDirectRenderingCapable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIQueryDirectRenderingCapable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIQueryDirectRenderingCapable;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return False");
+ return False;
+ }
+ *isCapable = rep.isCapable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("QueryDirectRenderingCapable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIOpenConnection(dpy, screen, hSAREA, busIdString)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hSAREA;
+ char **busIdString;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIOpenConnectionReply rep;
+ xXF86DRIOpenConnectionReq *req;
+
+ TRACE("OpenConnection...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIOpenConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIOpenConnection;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+
+ *hSAREA = rep.hSAREALow;
+ if (sizeof(drm_handle_t) == 8) {
+ int shift = 32; /* var to prevent warning on next line */
+ *hSAREA |= ((drm_handle_t) rep.hSAREAHigh) << shift;
+ }
+
+ if (rep.length) {
+ if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) {
+ _XEatData(dpy, ((rep.busIdStringLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return False");
+ return False;
+ }
+ _XReadPad(dpy, *busIdString, rep.busIdStringLength);
+ } else {
+ *busIdString = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("OpenConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIAuthConnection(dpy, screen, magic)
+ Display* dpy;
+ int screen;
+ drm_magic_t magic;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIAuthConnectionReq *req;
+ xXF86DRIAuthConnectionReply rep;
+
+ TRACE("AuthConnection...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIAuthConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIAuthConnection;
+ req->screen = screen;
+ req->magic = magic;
+ rep.authenticated = 0;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.authenticated) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return False");
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("AuthConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICloseConnection(dpy, screen)
+ Display* dpy;
+ int screen;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICloseConnectionReq *req;
+
+ TRACE("CloseConnection...");
+
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICloseConnection, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICloseConnection;
+ req->screen = screen;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CloseConnection... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetClientDriverName(dpy, screen, ddxDriverMajorVersion,
+ ddxDriverMinorVersion, ddxDriverPatchVersion, clientDriverName)
+ Display* dpy;
+ int screen;
+ int* ddxDriverMajorVersion;
+ int* ddxDriverMinorVersion;
+ int* ddxDriverPatchVersion;
+ char** clientDriverName;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetClientDriverNameReply rep;
+ xXF86DRIGetClientDriverNameReq *req;
+
+ TRACE("GetClientDriverName...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetClientDriverName, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetClientDriverName;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+
+ *ddxDriverMajorVersion = rep.ddxDriverMajorVersion;
+ *ddxDriverMinorVersion = rep.ddxDriverMinorVersion;
+ *ddxDriverPatchVersion = rep.ddxDriverPatchVersion;
+
+ if (rep.length) {
+ if (!(*clientDriverName = (char *)Xcalloc(rep.clientDriverNameLength + 1, 1))) {
+ _XEatData(dpy, ((rep.clientDriverNameLength+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return False");
+ return False;
+ }
+ _XReadPad(dpy, *clientDriverName, rep.clientDriverNameLength);
+ } else {
+ *clientDriverName = NULL;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetClientDriverName... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateContextWithConfig(dpy, screen, configID, context,
+ hHWContext)
+ Display* dpy;
+ int screen;
+ int configID;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateContextReply rep;
+ xXF86DRICreateContextReq *req;
+
+ TRACE("CreateContext...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateContext;
+ req->visual = configID;
+ req->screen = screen;
+ *context = XAllocID(dpy);
+ req->context = *context;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return False");
+ return False;
+ }
+ *hHWContext = rep.hHWContext;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateContext... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateContext(dpy, screen, visual, context, hHWContext)
+ Display* dpy;
+ int screen;
+ Visual* visual;
+ XID* context;
+ drm_context_t * hHWContext;
+{
+ return XF86DRICreateContextWithConfig( dpy, screen, visual->visualid,
+ context, hHWContext );
+}
+
+PUBLIC Bool XF86DRIDestroyContext( Display * ndpy, int screen,
+ XID context )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyContextReq *req;
+
+ TRACE("DestroyContext...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyContext, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyContext;
+ req->screen = screen;
+ req->context = context;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyContext... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRICreateDrawable( Display * ndpy, int screen,
+ Drawable drawable, drm_drawable_t * hHWDrawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRICreateDrawableReply rep;
+ xXF86DRICreateDrawableReq *req;
+
+ TRACE("CreateDrawable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRICreateDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRICreateDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return False");
+ return False;
+ }
+ *hHWDrawable = rep.hHWDrawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("CreateDrawable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIDestroyDrawable( Display * ndpy, int screen,
+ Drawable drawable )
+{
+ Display * const dpy = (Display *) ndpy;
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIDestroyDrawableReq *req;
+
+ TRACE("DestroyDrawable...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIDestroyDrawable, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIDestroyDrawable;
+ req->screen = screen;
+ req->drawable = drawable;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("DestroyDrawable... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetDrawableInfo(Display* dpy, int screen, Drawable drawable,
+ unsigned int* index, unsigned int* stamp,
+ int* X, int* Y, int* W, int* H,
+ int* numClipRects, drm_clip_rect_t ** pClipRects,
+ int* backX, int* backY,
+ int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDrawableInfoReply rep;
+ xXF86DRIGetDrawableInfoReq *req;
+ int total_rects;
+
+ TRACE("GetDrawableInfo...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDrawableInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDrawableInfo;
+ req->screen = screen;
+ req->drawable = drawable;
+
+ if (!_XReply(dpy, (xReply *)&rep, 1, xFalse))
+ {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+ *index = rep.drawableTableIndex;
+ *stamp = rep.drawableTableStamp;
+ *X = (int)rep.drawableX;
+ *Y = (int)rep.drawableY;
+ *W = (int)rep.drawableWidth;
+ *H = (int)rep.drawableHeight;
+ *numClipRects = rep.numClipRects;
+ total_rects = *numClipRects;
+
+ *backX = rep.backX;
+ *backY = rep.backY;
+ *numBackClipRects = rep.numBackClipRects;
+ total_rects += *numBackClipRects;
+
+#if 0
+ /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
+ * backwards compatibility (Because of the >> 2 shift) but the fix
+ * enables multi-threaded apps to work.
+ */
+ if (rep.length != ((((SIZEOF(xXF86DRIGetDrawableInfoReply) -
+ SIZEOF(xGenericReply) +
+ total_rects * sizeof(drm_clip_rect_t)) + 3) & ~3) >> 2)) {
+ _XEatData(dpy, rep.length);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return False");
+ return False;
+ }
+#endif
+
+ if (*numClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numClipRects);
+
+ *pClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pClipRects)
+ _XRead(dpy, (char*)*pClipRects, len);
+ } else {
+ *pClipRects = NULL;
+ }
+
+ if (*numBackClipRects) {
+ int len = sizeof(drm_clip_rect_t) * (*numBackClipRects);
+
+ *pBackClipRects = (drm_clip_rect_t *)Xcalloc(len, 1);
+ if (*pBackClipRects)
+ _XRead(dpy, (char*)*pBackClipRects, len);
+ } else {
+ *pBackClipRects = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDrawableInfo... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIGetDeviceInfo(dpy, screen, hFrameBuffer,
+ fbOrigin, fbSize, fbStride, devPrivateSize, pDevPrivate)
+ Display* dpy;
+ int screen;
+ drm_handle_t * hFrameBuffer;
+ int* fbOrigin;
+ int* fbSize;
+ int* fbStride;
+ int* devPrivateSize;
+ void** pDevPrivate;
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXF86DRIGetDeviceInfoReply rep;
+ xXF86DRIGetDeviceInfoReq *req;
+
+ TRACE("GetDeviceInfo...");
+ XF86DRICheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(XF86DRIGetDeviceInfo, req);
+ req->reqType = info->codes->major_opcode;
+ req->driReqType = X_XF86DRIGetDeviceInfo;
+ req->screen = screen;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+
+ *hFrameBuffer = rep.hFrameBufferLow;
+ if (sizeof(drm_handle_t) == 8) {
+ int shift = 32; /* var to prevent warning on next line */
+ *hFrameBuffer |= ((drm_handle_t) rep.hFrameBufferHigh) << shift;
+ }
+
+ *fbOrigin = rep.framebufferOrigin;
+ *fbSize = rep.framebufferSize;
+ *fbStride = rep.framebufferStride;
+ *devPrivateSize = rep.devPrivateSize;
+
+ if (rep.length) {
+ if (!(*pDevPrivate = (void *)Xcalloc(rep.devPrivateSize, 1))) {
+ _XEatData(dpy, ((rep.devPrivateSize+3) & ~3));
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return False");
+ return False;
+ }
+ _XRead(dpy, (char*)*pDevPrivate, rep.devPrivateSize);
+ } else {
+ *pDevPrivate = NULL;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ TRACE("GetDeviceInfo... return True");
+ return True;
+}
+
+PUBLIC Bool XF86DRIOpenFullScreen(dpy, screen, drawable)
+ Display* dpy;
+ int screen;
+ Drawable drawable;
+{
+ /* This function and the underlying X protocol are deprecated.
+ */
+ (void) dpy;
+ (void) screen;
+ (void) drawable;
+ return False;
+}
+
+PUBLIC Bool XF86DRICloseFullScreen(dpy, screen, drawable)
+ Display* dpy;
+ int screen;
+ Drawable drawable;
+{
+ /* This function and the underlying X protocol are deprecated.
+ */
+ (void) dpy;
+ (void) screen;
+ (void) drawable;
+ return True;
+}
+
diff --git a/src/driclient/src/driclient.c b/src/driclient/src/driclient.c
new file mode 100644
index 0000000000..2d7514166f
--- /dev/null
+++ b/src/driclient/src/driclient.c
@@ -0,0 +1,295 @@
+#include "driclient.h"
+#include <assert.h>
+#include <stdlib.h>
+
+int driCreateScreen(Display *display, int screen, dri_screen_t **dri_screen, dri_framebuffer_t *dri_framebuf)
+{
+ int evbase, errbase;
+ char *driver_name;
+ int newly_opened;
+ drm_magic_t magic;
+ drmVersionPtr drm_version;
+ drm_handle_t sarea_handle;
+ char *bus_id;
+ dri_screen_t *dri_scrn;
+
+ assert(display);
+ assert(dri_screen);
+
+ if (!XF86DRIQueryExtension(display, &evbase, &errbase))
+ return 1;
+
+ dri_scrn = calloc(1, sizeof(dri_screen_t));
+
+ if (!dri_scrn)
+ return 1;
+
+ if (!XF86DRIQueryVersion(display, &dri_scrn->dri.major, &dri_scrn->dri.minor, &dri_scrn->dri.patch))
+ goto free_screen;
+
+ dri_scrn->display = display;
+ dri_scrn->num = screen;
+ dri_scrn->draw_lock_id = 1;
+
+ if (!XF86DRIOpenConnection(display, screen, &sarea_handle, &bus_id))
+ goto free_screen;
+
+ dri_scrn->fd = -1;
+ dri_scrn->fd = drmOpenOnce(NULL, bus_id, &newly_opened);
+ XFree(bus_id);
+
+ if (dri_scrn->fd < 0)
+ goto close_connection;
+
+ if (drmGetMagic(dri_scrn->fd, &magic))
+ goto close_drm;
+
+ drm_version = drmGetVersion(dri_scrn->fd);
+
+ if (!drm_version)
+ goto close_drm;
+
+ dri_scrn->drm.major = drm_version->version_major;
+ dri_scrn->drm.minor = drm_version->version_minor;
+ dri_scrn->drm.patch = drm_version->version_patchlevel;
+ drmFreeVersion(drm_version);
+
+ if (!XF86DRIAuthConnection(display, screen, magic))
+ goto close_drm;
+
+ if (!XF86DRIGetClientDriverName
+ (
+ display,
+ screen,
+ &dri_scrn->ddx.major,
+ &dri_scrn->ddx.minor,
+ &dri_scrn->ddx.patch,
+ &driver_name
+ ))
+ goto close_drm;
+
+ if (drmMap(dri_scrn->fd, sarea_handle, SAREA_MAX, (drmAddress)&dri_scrn->sarea))
+ goto close_drm;
+
+ dri_scrn->drawable_hash = drmHashCreate();
+
+ if (!dri_scrn->drawable_hash)
+ goto unmap_sarea;
+
+ if (dri_framebuf)
+ {
+ if (!XF86DRIGetDeviceInfo
+ (
+ display,
+ screen, &dri_framebuf->drm_handle,
+ &dri_framebuf->base,
+ &dri_framebuf->size,
+ &dri_framebuf->stride,
+ &dri_framebuf->private_size,
+ &dri_framebuf->private
+ ))
+ goto destroy_hash;
+ }
+
+ *dri_screen = dri_scrn;
+
+ return 0;
+
+destroy_hash:
+ drmHashDestroy(dri_scrn->drawable_hash);
+unmap_sarea:
+ drmUnmap(dri_scrn->sarea, SAREA_MAX);
+close_drm:
+ drmCloseOnce(dri_scrn->fd);
+close_connection:
+ XF86DRICloseConnection(display, screen);
+free_screen:
+ free(dri_scrn);
+
+ return 1;
+}
+
+int driDestroyScreen(dri_screen_t *dri_screen)
+{
+ assert(dri_screen);
+
+ drmHashDestroy(dri_screen->drawable_hash);
+ drmUnmap(dri_screen->sarea, SAREA_MAX);
+ drmCloseOnce(dri_screen->fd);
+ XF86DRICloseConnection(dri_screen->display, dri_screen->num);
+ free(dri_screen);
+
+ return 0;
+}
+
+int driCreateDrawable(dri_screen_t *dri_screen, Drawable drawable, dri_drawable_t **dri_drawable)
+{
+ int evbase, errbase;
+ dri_drawable_t *dri_draw;
+
+ assert(dri_screen);
+ assert(dri_drawable);
+
+ if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+ return 1;
+
+ if (!drmHashLookup(dri_screen->drawable_hash, drawable, (void**)dri_drawable))
+ {
+ /* Found */
+ (*dri_drawable)->refcount++;
+ return 0;
+ }
+
+ dri_draw = calloc(1, sizeof(dri_drawable_t));
+
+ if (!dri_draw)
+ return 1;
+
+ if (!XF86DRICreateDrawable(dri_screen->display, 0, drawable, &dri_draw->drm_drawable))
+ {
+ free(dri_draw);
+ return 1;
+ }
+
+ dri_draw->x_drawable = drawable;
+ dri_draw->sarea_index = 0;
+ dri_draw->sarea_stamp = NULL;
+ dri_draw->last_sarea_stamp = 0;
+ dri_draw->dri_screen = dri_screen;
+ dri_draw->refcount = 1;
+
+ if (drmHashInsert(dri_screen->drawable_hash, drawable, dri_draw))
+ {
+ XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+ free(dri_draw);
+ return 1;
+ }
+
+ if (!dri_draw->sarea_stamp || *dri_draw->sarea_stamp != dri_draw->last_sarea_stamp)
+ {
+ DRM_SPINLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+
+ if (driUpdateDrawableInfo(dri_draw))
+ {
+ XF86DRIDestroyDrawable(dri_screen->display, dri_screen->num, drawable);
+ free(dri_draw);
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+ return 1;
+ }
+
+ DRM_SPINUNLOCK(&dri_screen->sarea->drawable_lock, dri_screen->draw_lock_id);
+ }
+
+ *dri_drawable = dri_draw;
+
+ return 0;
+}
+
+int driUpdateDrawableInfo(dri_drawable_t *dri_drawable)
+{
+ assert(dri_drawable);
+
+ if (dri_drawable->cliprects)
+ {
+ XFree(dri_drawable->cliprects);
+ dri_drawable->cliprects = NULL;
+ }
+ if (dri_drawable->back_cliprects)
+ {
+ XFree(dri_drawable->back_cliprects);
+ dri_drawable->back_cliprects = NULL;
+ }
+
+ DRM_SPINUNLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+ if (!XF86DRIGetDrawableInfo
+ (
+ dri_drawable->dri_screen->display,
+ dri_drawable->dri_screen->num,
+ dri_drawable->x_drawable,
+ &dri_drawable->sarea_index,
+ &dri_drawable->last_sarea_stamp,
+ &dri_drawable->x,
+ &dri_drawable->y,
+ &dri_drawable->w,
+ &dri_drawable->h,
+ &dri_drawable->num_cliprects,
+ &dri_drawable->cliprects,
+ &dri_drawable->back_x,
+ &dri_drawable->back_y,
+ &dri_drawable->num_back_cliprects,
+ &dri_drawable->back_cliprects
+ ))
+ {
+ dri_drawable->sarea_stamp = &dri_drawable->last_sarea_stamp;
+ dri_drawable->num_cliprects = 0;
+ dri_drawable->cliprects = NULL;
+ dri_drawable->num_back_cliprects = 0;
+ dri_drawable->back_cliprects = 0;
+
+ return 1;
+ }
+ else
+ dri_drawable->sarea_stamp = &dri_drawable->dri_screen->sarea->drawableTable[dri_drawable->sarea_index].stamp;
+
+ DRM_SPINLOCK(&dri_drawable->dri_screen->sarea->drawable_lock, dri_drawable->dri_screen->draw_lock_id);
+
+ return 0;
+}
+
+int driDestroyDrawable(dri_drawable_t *dri_drawable)
+{
+ assert(dri_drawable);
+
+ if (--dri_drawable->refcount == 0)
+ {
+ if (dri_drawable->cliprects)
+ XFree(dri_drawable->cliprects);
+ if (dri_drawable->back_cliprects)
+ XFree(dri_drawable->back_cliprects);
+ drmHashDelete(dri_drawable->dri_screen->drawable_hash, dri_drawable->x_drawable);
+ XF86DRIDestroyDrawable(dri_drawable->dri_screen->display, dri_drawable->dri_screen->num, dri_drawable->x_drawable);
+ free(dri_drawable);
+ }
+
+ return 0;
+}
+
+int driCreateContext(dri_screen_t *dri_screen, Visual *visual, dri_context_t **dri_context)
+{
+ int evbase, errbase;
+ dri_context_t *dri_ctx;
+
+ assert(dri_screen);
+ assert(visual);
+ assert(dri_context);
+
+ if (!XF86DRIQueryExtension(dri_screen->display, &evbase, &errbase))
+ return 1;
+
+ dri_ctx = calloc(1, sizeof(dri_context_t));
+
+ if (!dri_ctx)
+ return 1;
+
+ if (!XF86DRICreateContext(dri_screen->display, dri_screen->num, visual, &dri_ctx->id, &dri_ctx->drm_context))
+ {
+ free(dri_ctx);
+ return 1;
+ }
+
+ dri_ctx->dri_screen = dri_screen;
+ *dri_context = dri_ctx;
+
+ return 0;
+}
+
+int driDestroyContext(dri_context_t *dri_context)
+{
+ assert(dri_context);
+
+ XF86DRIDestroyContext(dri_context->dri_screen->display, dri_context->dri_screen->num, dri_context->id);
+ free(dri_context);
+
+ return 0;
+}
diff --git a/src/driclient/src/xf86dristr.h b/src/driclient/src/xf86dristr.h
new file mode 100644
index 0000000000..b834bd1a1a
--- /dev/null
+++ b/src/driclient/src/xf86dristr.h
@@ -0,0 +1,342 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright 2000 VA Linux Systems, Inc.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <martin@valinux.com>
+ * Jens Owen <jens@tungstengraphics.com>
+ * Rickard E. (Rik) Fiath <faith@valinux.com>
+ *
+ */
+
+#ifndef _XF86DRISTR_H_
+#define _XF86DRISTR_H_
+
+#include "xf86dri.h"
+
+#define XF86DRINAME "XFree86-DRI"
+
+/* The DRI version number. This was originally set to be the same of the
+ * XFree86 version number. However, this version is really indepedent of
+ * the XFree86 version.
+ *
+ * Version History:
+ * 4.0.0: Original
+ * 4.0.1: Patch to bump clipstamp when windows are destroyed, 28 May 02
+ * 4.1.0: Add transition from single to multi in DRMInfo rec, 24 Jun 02
+ */
+#define XF86DRI_MAJOR_VERSION 4
+#define XF86DRI_MINOR_VERSION 1
+#define XF86DRI_PATCH_VERSION 0
+
+typedef struct _XF86DRIQueryVersion {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIQueryVersion */
+ CARD16 length B16;
+} xXF86DRIQueryVersionReq;
+#define sz_xXF86DRIQueryVersionReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 majorVersion B16; /* major version of DRI protocol */
+ CARD16 minorVersion B16; /* minor version of DRI protocol */
+ CARD32 patchVersion B32; /* patch version of DRI protocol */
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIQueryVersionReply;
+#define sz_xXF86DRIQueryVersionReply 32
+
+typedef struct _XF86DRIQueryDirectRenderingCapable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIQueryDirectRenderingCapableReq;
+#define sz_xXF86DRIQueryDirectRenderingCapableReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ BOOL isCapable;
+ BOOL pad2;
+ BOOL pad3;
+ BOOL pad4;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+ CARD32 pad9 B32;
+} xXF86DRIQueryDirectRenderingCapableReply;
+#define sz_xXF86DRIQueryDirectRenderingCapableReply 32
+
+typedef struct _XF86DRIOpenConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIOpenConnectionReq;
+#define sz_xXF86DRIOpenConnectionReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hSAREALow B32;
+ CARD32 hSAREAHigh B32;
+ CARD32 busIdStringLength B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xXF86DRIOpenConnectionReply;
+#define sz_xXF86DRIOpenConnectionReply 32
+
+typedef struct _XF86DRIAuthConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 magic B32;
+} xXF86DRIAuthConnectionReq;
+#define sz_xXF86DRIAuthConnectionReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 authenticated B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIAuthConnectionReply;
+#define zx_xXF86DRIAuthConnectionReply 32
+
+typedef struct _XF86DRICloseConnection {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseConnection */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRICloseConnectionReq;
+#define sz_xXF86DRICloseConnectionReq 8
+
+typedef struct _XF86DRIGetClientDriverName {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetClientDriverName */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetClientDriverNameReq;
+#define sz_xXF86DRIGetClientDriverNameReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ddxDriverMajorVersion B32;
+ CARD32 ddxDriverMinorVersion B32;
+ CARD32 ddxDriverPatchVersion B32;
+ CARD32 clientDriverNameLength B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIGetClientDriverNameReply;
+#define sz_xXF86DRIGetClientDriverNameReply 32
+
+typedef struct _XF86DRICreateContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 visual B32;
+ CARD32 context B32;
+} xXF86DRICreateContextReq;
+#define sz_xXF86DRICreateContextReq 16
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWContext B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateContextReply;
+#define sz_xXF86DRICreateContextReply 32
+
+typedef struct _XF86DRIDestroyContext {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyContext */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 context B32;
+} xXF86DRIDestroyContextReq;
+#define sz_xXF86DRIDestroyContextReq 12
+
+typedef struct _XF86DRICreateDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICreateDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICreateDrawableReq;
+#define sz_xXF86DRICreateDrawableReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hHWDrawable B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRICreateDrawableReply;
+#define sz_xXF86DRICreateDrawableReply 32
+
+typedef struct _XF86DRIDestroyDrawable {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIDestroyDrawable */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIDestroyDrawableReq;
+#define sz_xXF86DRIDestroyDrawableReq 12
+
+typedef struct _XF86DRIGetDrawableInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDrawableInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIGetDrawableInfoReq;
+#define sz_xXF86DRIGetDrawableInfoReq 12
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 drawableTableIndex B32;
+ CARD32 drawableTableStamp B32;
+ INT16 drawableX B16;
+ INT16 drawableY B16;
+ INT16 drawableWidth B16;
+ INT16 drawableHeight B16;
+ CARD32 numClipRects B32;
+ INT16 backX B16;
+ INT16 backY B16;
+ CARD32 numBackClipRects B32;
+} xXF86DRIGetDrawableInfoReply;
+
+#define sz_xXF86DRIGetDrawableInfoReply 36
+
+
+typedef struct _XF86DRIGetDeviceInfo {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIGetDeviceInfo */
+ CARD16 length B16;
+ CARD32 screen B32;
+} xXF86DRIGetDeviceInfoReq;
+#define sz_xXF86DRIGetDeviceInfoReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 hFrameBufferLow B32;
+ CARD32 hFrameBufferHigh B32;
+ CARD32 framebufferOrigin B32;
+ CARD32 framebufferSize B32;
+ CARD32 framebufferStride B32;
+ CARD32 devPrivateSize B32;
+} xXF86DRIGetDeviceInfoReply;
+#define sz_xXF86DRIGetDeviceInfoReply 32
+
+typedef struct _XF86DRIOpenFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRIOpenFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRIOpenFullScreenReq;
+#define sz_xXF86DRIOpenFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isFullScreen B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xXF86DRIOpenFullScreenReply;
+#define sz_xXF86DRIOpenFullScreenReply 32
+
+typedef struct _XF86DRICloseFullScreen {
+ CARD8 reqType; /* always DRIReqCode */
+ CARD8 driReqType; /* always X_DRICloseFullScreen */
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 drawable B32;
+} xXF86DRICloseFullScreenReq;
+#define sz_xXF86DRICloseFullScreenReq 12
+
+typedef struct {
+ BYTE type;
+ BOOL pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xXF86DRICloseFullScreenReply;
+#define sz_xXF86DRICloseFullScreenReply 32
+
+
+#endif /* _XF86DRISTR_H_ */
diff --git a/src/gallium/drivers/nouveau/nouveau_bo.h b/src/gallium/drivers/nouveau/nouveau_bo.h
new file mode 100644
index 0000000000..0ed3367815
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_bo.h
@@ -0,0 +1,54 @@
+/*
+ * 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_SWIZZLED (1 << 12)
+#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
index 0000000000..cd99a676bd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_channel.h
@@ -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
index 0000000000..c3d8d7539d
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_class.h
@@ -0,0 +1,6259 @@
+/*************************************************************************
+
+ 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_A16 0x00001400
+#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
index 0000000000..e25e89fedd
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_device.h
@@ -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
index 0000000000..e1015c93a2
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_gldefs.h
@@ -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
index 0000000000..8f5abf9051
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_grobj.h
@@ -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
index 0000000000..35adde1e32
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_notifier.h
@@ -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
index 0000000000..54ef1c1291
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_push.h
@@ -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
index 0000000000..1909765098
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_pushbuf.h
@@ -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
index 0000000000..1af7961d30
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_resource.h
@@ -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
index 0000000000..729988b095
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -0,0 +1,158 @@
+#ifndef __NOUVEAU_STATEOBJ_H__
+#define __NOUVEAU_STATEOBJ_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
index 0000000000..c92041ebeb
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_util.h
@@ -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
index 0000000000..a89b056244
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -0,0 +1,96 @@
+#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 *
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+
+extern struct pipe_context *
+nv20_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
index 0000000000..5ea51a2f42
--- /dev/null
+++ b/src/gallium/drivers/nv04/Makefile
@@ -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
index 0000000000..01cacd36fe
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_clear.c
@@ -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
index 0000000000..9f75253363
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_context.c
@@ -0,0 +1,106 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.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
index 0000000000..3e6a085270
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_context.h
@@ -0,0 +1,146 @@
+#ifndef __NV04_CONTEXT_H__
+#define __NV04_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.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
index 0000000000..8a2af41fe0
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/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
index 0000000000..1b866aae19
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_fragtex.c
@@ -0,0 +1,98 @@
+#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;
+ 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++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ 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
index 0000000000..0cbb91e187
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_miptree.c
@@ -0,0 +1,138 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.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_texture *mt = *pt;
+
+ *pt = NULL;
+ if (--mt->refcount <= 0) {
+ struct nv04_miptree *nv04mt = (struct nv04_miptree *)mt;
+ int l;
+
+ pipe_buffer_reference(screen, &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(pscreen, &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;
+ ps->refcount = 1;
+ ps->winsys = pscreen->winsys;
+
+ 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
index 0000000000..19979fff79
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_prim_vbuf.c
@@ -0,0 +1,309 @@
+
+#include "pipe/p_debug.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_compiler.h"
+
+#include "draw/draw_vbuf.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
index 0000000000..3966a29ffa
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_screen.c
@@ -0,0 +1,212 @@
+#include "pipe/p_screen.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,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ switch (format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_Z16_UNORM:
+ return TRUE;
+ default:
+ break;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ 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
index 0000000000..99a49cdf7a
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_screen.h
@@ -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
index 0000000000..ff1933b550
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state.c
@@ -0,0 +1,495 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_parse.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.tokens = tgsi_dup_tokens(cso->tokens);
+
+ 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((void*)fp->pipe.tokens);
+ 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
index 0000000000..399f750dbe
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state.h
@@ -0,0 +1,71 @@
+#ifndef __NV04_STATE_H__
+#define __NV04_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/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 {
+ 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
index 0000000000..0ad40a092e
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_state_emit.c
@@ -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
index 0000000000..57039483c6
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_surface.c
@@ -0,0 +1,64 @@
+
+/**************************************************************************
+ *
+ * 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_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/u_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
index 0000000000..91f919d48e
--- /dev/null
+++ b/src/gallium/drivers/nv04/nv04_vbo.c
@@ -0,0 +1,71 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.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
index 0000000000..4ba7ce586d
--- /dev/null
+++ b/src/gallium/drivers/nv10/Makefile
@@ -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
index 0000000000..be7e09cf4b
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_clear.c
@@ -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
index 0000000000..e9b61daae7
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_context.c
@@ -0,0 +1,296 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.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
index 0000000000..f3b56de25a
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_context.h
@@ -0,0 +1,153 @@
+#ifndef __NV10_CONTEXT_H__
+#define __NV10_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.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
index 0000000000..698db5a16a
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/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
index 0000000000..238634d0bb
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_fragtex.c
@@ -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
index 0000000000..943f9e21e9
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_miptree.c
@@ -0,0 +1,149 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.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_texture *mt = *pt;
+
+ *pt = NULL;
+ if (--mt->refcount <= 0) {
+ struct nv10_miptree *nv10mt = (struct nv10_miptree *)mt;
+ int l;
+
+ pipe_buffer_reference(screen, &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(screen, &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;
+ ps->refcount = 1;
+ ps->winsys = screen->winsys;
+
+ 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
index 0000000000..62a8f6d89d
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_prim_vbuf.c
@@ -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 "pipe/p_debug.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+
+#include "nv10_context.h"
+#include "nv10_state.h"
+
+#include "draw/draw_vbuf.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;
+ struct pipe_screen *pscreen = &nv10->screen->pipe;
+
+ assert(nv10_render->buffer);
+ winsys->buffer_unmap(winsys, nv10_render->buffer);
+ pipe_buffer_reference(pscreen, &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
index 0000000000..27a9edf9bb
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_screen.c
@@ -0,0 +1,208 @@
+#include "pipe/p_screen.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,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ 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;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ 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
index 0000000000..3f8750a13f
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_screen.h
@@ -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
index 0000000000..d2375aa2f6
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state.c
@@ -0,0 +1,588 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_parse.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.tokens = tgsi_dup_tokens(cso->tokens);
+
+ 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((void*)fp->pipe.tokens);
+ 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
index 0000000000..3a3fd0d4f4
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state.h
@@ -0,0 +1,139 @@
+#ifndef __NV10_STATE_H__
+#define __NV10_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/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 {
+ 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
index 0000000000..46c7e1d753
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_state_emit.c
@@ -0,0 +1,303 @@
+#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
index 0000000000..875e4c5858
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_surface.c
@@ -0,0 +1,64 @@
+
+/**************************************************************************
+ *
+ * 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_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/u_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
index 0000000000..d0e788ac03
--- /dev/null
+++ b/src/gallium/drivers/nv10/nv10_vbo.c
@@ -0,0 +1,77 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.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/nv20/Makefile b/src/gallium/drivers/nv20/Makefile
new file mode 100644
index 0000000000..d777fd3d8b
--- /dev/null
+++ b/src/gallium/drivers/nv20/Makefile
@@ -0,0 +1,29 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nv20
+
+DRIVER_SOURCES = \
+ nv20_clear.c \
+ nv20_context.c \
+ nv20_fragprog.c \
+ nv20_fragtex.c \
+ nv20_miptree.c \
+ nv20_prim_vbuf.c \
+ nv20_screen.c \
+ nv20_state.c \
+ nv20_state_emit.c \
+ nv20_surface.c \
+ nv20_vbo.c
+# nv20_vertprog.c
+
+C_SOURCES = \
+ $(COMMON_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+include ../../Makefile.template
+
+symlinks:
+
diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c
new file mode 100644
index 0000000000..81b6f3e78a
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_clear.c
@@ -0,0 +1,12 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "nv20_context.h"
+
+void
+nv20_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/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c
new file mode 100644
index 0000000000..2af5b0203e
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_context.c
@@ -0,0 +1,296 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static void
+nv20_flush(struct pipe_context *pipe, unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_flush(nv20->draw);
+
+ FIRE_RING(fence);
+}
+
+static void
+nv20_destroy(struct pipe_context *pipe)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ if (nv20->draw)
+ draw_destroy(nv20->draw);
+
+ FREE(nv20);
+}
+
+static void nv20_init_hwctx(struct nv20_context *nv20)
+{
+ struct nv20_screen *screen = nv20->screen;
+ struct nouveau_winsys *nvws = screen->nvws;
+ int i;
+ float projectionmatrix[16];
+
+ BEGIN_RING(kelvin, NV10TCL_DMA_NOTIFY, 1);
+ OUT_RING (screen->sync->handle);
+ BEGIN_RING(kelvin, NV10TCL_DMA_IN_MEMORY0, 2);
+ OUT_RING (nvws->channel->vram->handle);
+ OUT_RING (nvws->channel->gart->handle);
+ BEGIN_RING(kelvin, NV10TCL_DMA_IN_MEMORY2, 2);
+ OUT_RING (nvws->channel->vram->handle);
+ OUT_RING (nvws->channel->vram->handle);
+
+ BEGIN_RING(kelvin, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, NV10TCL_RT_HORIZ, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
+ OUT_RING ((0x7ff<<16)|0x800);
+ BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
+ OUT_RING ((0x7ff<<16)|0x800);
+
+ for (i=1;i<8;i++) {
+ BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(kelvin, 0x290, 1);
+ OUT_RING ((0x10<<16)|1);
+ BEGIN_RING(kelvin, 0x3f4, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ if (nv20->screen->kelvin->grclass != NV10TCL) {
+ /* For nv11, nv17 */
+ BEGIN_RING(kelvin, 0x120, 3);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (2);
+
+ BEGIN_RING(kelvin, NV10TCL_NOP, 1);
+ OUT_RING (0);
+ }
+
+ BEGIN_RING(kelvin, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ /* Set state */
+ BEGIN_RING(kelvin, NV10TCL_FOG_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_FUNC, 2);
+ OUT_RING (0x207);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_TX_ENABLE(0), 2);
+ OUT_RING (0);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, 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(kelvin, NV10TCL_BLEND_FUNC_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_DITHER_ENABLE, 2);
+ OUT_RING (1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_BLEND_FUNC_SRC, 4);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0x8006);
+ BEGIN_RING(kelvin, 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(kelvin, NV10TCL_NORMALIZE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_FOG_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_LIGHT_MODEL, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_COLOR_CONTROL, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_ENABLED_LIGHTS, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_FUNC, 1);
+ OUT_RING (0x201);
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_POINT_SIZE, 1);
+ OUT_RING (8);
+ BEGIN_RING(kelvin, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_LINE_WIDTH, 1);
+ OUT_RING (8);
+ BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (0x1b02);
+ OUT_RING (0x1b02);
+ BEGIN_RING(kelvin, NV10TCL_CULL_FACE, 2);
+ OUT_RING (0x405);
+ OUT_RING (0x901);
+ BEGIN_RING(kelvin, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_CLIP_PLANE_ENABLE(0), 8);
+ for (i=0;i<8;i++) {
+ OUT_RING (0);
+ }
+ BEGIN_RING(kelvin, NV10TCL_FOG_EQUATION_CONSTANT, 3);
+ OUT_RING (0x3fc00000); /* -1.50 */
+ OUT_RING (0xbdb8aa0a); /* -0.09 */
+ OUT_RING (0); /* 0.00 */
+
+ BEGIN_RING(kelvin, NV10TCL_NOP, 1);
+ OUT_RING (0);
+
+ BEGIN_RING(kelvin, 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(kelvin, NV10TCL_VIEW_MATRIX_ENABLE, 1);
+ OUT_RING (6);
+ BEGIN_RING(kelvin, NV10TCL_COLOR_MASK, 1);
+ OUT_RING (0x01010101);
+
+ /* Set vertex component */
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_COL_4F_R, 4);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_COL2_3F_R, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_NOR_3F_X, 3);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_TX0_4F_S, 4);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_TX1_4F_S, 4);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (0.0);
+ OUT_RINGf (1.0);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_FOG_1F, 1);
+ OUT_RINGf (0.0);
+ BEGIN_RING(kelvin, NV10TCL_EDGEFLAG_ENABLE, 1);
+ OUT_RING (1);
+
+ memset(projectionmatrix, 0, sizeof(projectionmatrix));
+ BEGIN_RING(kelvin, 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(kelvin, NV10TCL_DEPTH_RANGE_NEAR, 2);
+ OUT_RING (0.0);
+ OUT_RINGf (16777216.0);
+
+ BEGIN_RING(kelvin, 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
+nv20_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+}
+
+struct pipe_context *
+nv20_create(struct pipe_screen *pscreen, unsigned pctx_id)
+{
+ struct nv20_screen *screen = nv20_screen(pscreen);
+ struct pipe_winsys *ws = pscreen->winsys;
+ struct nv20_context *nv20;
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nv20 = CALLOC(1, sizeof(struct nv20_context));
+ if (!nv20)
+ return NULL;
+ nv20->screen = screen;
+ nv20->pctx_id = pctx_id;
+
+ nv20->nvws = nvws;
+
+ nv20->pipe.winsys = ws;
+ nv20->pipe.screen = pscreen;
+ nv20->pipe.destroy = nv20_destroy;
+ nv20->pipe.set_edgeflags = nv20_set_edgeflags;
+ nv20->pipe.draw_arrays = nv20_draw_arrays;
+ nv20->pipe.draw_elements = nv20_draw_elements;
+ nv20->pipe.clear = nv20_clear;
+ nv20->pipe.flush = nv20_flush;
+
+ nv20_init_surface_functions(nv20);
+ nv20_init_state_functions(nv20);
+
+ nv20->draw = draw_create();
+ assert(nv20->draw);
+ draw_set_rasterize_stage(nv20->draw, nv20_draw_vbuf_stage(nv20));
+
+ nv20_init_hwctx(nv20);
+
+ return &nv20->pipe;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h
new file mode 100644
index 0000000000..8ad926db20
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_context.h
@@ -0,0 +1,153 @@
+#ifndef __NV20_CONTEXT_H__
+#define __NV20_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#include "draw/draw_vertex.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_gldefs.h"
+
+#define NOUVEAU_PUSH_CONTEXT(ctx) \
+ struct nv20_screen *ctx = nv20->screen
+#include "nouveau/nouveau_push.h"
+
+#include "nv20_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 NV20_NEW_VERTPROG (1 << 0)
+#define NV20_NEW_FRAGPROG (1 << 1)
+#define NV20_NEW_VTXARRAYS (1 << 2)
+#define NV20_NEW_BLEND (1 << 3)
+#define NV20_NEW_BLENDCOL (1 << 4)
+#define NV20_NEW_RAST (1 << 5)
+#define NV20_NEW_DSA (1 << 6)
+#define NV20_NEW_VIEWPORT (1 << 7)
+#define NV20_NEW_SCISSOR (1 << 8)
+#define NV20_NEW_FRAMEBUFFER (1 << 9)
+
+#include "nv20_screen.h"
+
+struct nv20_context {
+ struct pipe_context pipe;
+
+ struct nouveau_winsys *nvws;
+ struct nv20_screen *screen;
+ unsigned pctx_id;
+
+ struct draw_context *draw;
+
+ uint32_t dirty;
+
+ struct nv20_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+ struct nv20_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 nv20_blend_state *blend;
+ struct pipe_blend_color *blend_color;
+ struct nv20_rasterizer_state *rast;
+ struct nv20_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 nv20_vertex_program *active;
+
+ struct nv20_vertex_program *current;
+ } vertprog;
+*/
+ struct {
+ struct nv20_fragment_program *active;
+
+ struct nv20_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 nv20_context *
+nv20_context(struct pipe_context *pipe)
+{
+ return (struct nv20_context *)pipe;
+}
+
+extern void nv20_init_state_functions(struct nv20_context *nv20);
+extern void nv20_init_surface_functions(struct nv20_context *nv20);
+
+extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen);
+
+/* nv20_clear.c */
+extern void nv20_clear(struct pipe_context *pipe, struct pipe_surface *ps,
+ unsigned clearValue);
+
+/* nv20_draw.c */
+extern struct draw_stage *nv20_draw_render_stage(struct nv20_context *nv20);
+
+/* nv20_fragprog.c */
+extern void nv20_fragprog_bind(struct nv20_context *,
+ struct nv20_fragment_program *);
+extern void nv20_fragprog_destroy(struct nv20_context *,
+ struct nv20_fragment_program *);
+
+/* nv20_fragtex.c */
+extern void nv20_fragtex_bind(struct nv20_context *);
+
+/* nv20_prim_vbuf.c */
+struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 );
+extern void nv20_vtxbuf_bind(struct nv20_context* nv20);
+
+/* nv20_state.c and friends */
+extern void nv20_emit_hw_state(struct nv20_context *nv20);
+extern void nv20_state_tex_update(struct nv20_context *nv20);
+
+/* nv20_vbo.c */
+extern boolean nv20_draw_arrays(struct pipe_context *, unsigned mode,
+ unsigned start, unsigned count);
+extern boolean nv20_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/nv20/nv20_fragprog.c b/src/gallium/drivers/nv20/nv20_fragprog.c
new file mode 100644
index 0000000000..4f496369dd
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_fragprog.c
@@ -0,0 +1,21 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
+
+#include "nv20_context.h"
+
+void
+nv20_fragprog_bind(struct nv20_context *nv20, struct nv20_fragment_program *fp)
+{
+}
+
+void
+nv20_fragprog_destroy(struct nv20_context *nv20,
+ struct nv20_fragment_program *fp)
+{
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_fragtex.c b/src/gallium/drivers/nv20/nv20_fragtex.c
new file mode 100644
index 0000000000..77c34897e2
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_fragtex.c
@@ -0,0 +1,149 @@
+#include "nv20_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 nv20_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+};
+
+static struct nv20_texture_format
+nv20_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 nv20_texture_format *
+nv20_fragtex_format(uint pipe_format)
+{
+ struct nv20_texture_format *tf = nv20_texture_formats;
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ return NULL;
+}
+
+
+static void
+nv20_fragtex_build(struct nv20_context *nv20, int unit)
+{
+#if 0
+ struct nv20_sampler_state *ps = nv20->tex_sampler[unit];
+ struct nv20_miptree *nv20mt = nv20->tex_miptree[unit];
+ struct pipe_texture *pt = &nv20mt->base;
+ struct nv20_texture_format *tf;
+ uint32_t txf, txs, txp;
+
+ tf = nv20_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(kelvin, NV10TCL_TX_OFFSET(unit), 8);
+ OUT_RELOCl(nv20mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ OUT_RELOCd(nv20mt->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
+nv20_fragtex_bind(struct nv20_context *nv20)
+{
+#if 0
+ struct nv20_fragment_program *fp = nv20->fragprog.active;
+ unsigned samplers, unit;
+
+ samplers = nv20->fp_samplers & ~fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ BEGIN_RING(kelvin, NV10TCL_TX_ENABLE(unit), 1);
+ OUT_RING (0);
+ }
+
+ samplers = nv20->dirty_samplers & fp->samplers;
+ while (samplers) {
+ unit = ffs(samplers) - 1;
+ samplers &= ~(1 << unit);
+
+ nv20_fragtex_build(nv20, unit);
+ }
+
+ nv20->fp_samplers = fp->samplers;
+#endif
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c
new file mode 100644
index 0000000000..c6106d58c4
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_miptree.c
@@ -0,0 +1,156 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static void
+nv20_miptree_layout(struct nv20_miptree *nv20mt)
+{
+ struct pipe_texture *pt = &nv20mt->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)
+ nv20mt->level[l].pitch = pt->nblocksx[l] * pt->block.size;
+ else
+ nv20mt->level[l].pitch = pt->nblocksx[0] * pt->block.size;
+ nv20mt->level[l].pitch = (nv20mt->level[l].pitch + 63) & ~63;
+
+ nv20mt->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++) {
+ nv20mt->level[l].image_offset[f] = offset;
+ offset += nv20mt->level[l].pitch * pt->height[l];
+ }
+ }
+
+ nv20mt->total_size = offset;
+}
+
+static struct pipe_texture *
+nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt)
+{
+ struct pipe_winsys *ws = screen->winsys;
+ struct nv20_miptree *mt;
+
+ mt = MALLOC(sizeof(struct nv20_miptree));
+ if (!mt)
+ return NULL;
+ mt->base = *pt;
+ mt->base.refcount = 1;
+ mt->base.screen = screen;
+
+ nv20_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
+nv20_miptree_release(struct pipe_screen *screen, struct pipe_texture **pt)
+{
+ struct pipe_texture *mt = *pt;
+
+ *pt = NULL;
+ if (--mt->refcount <= 0) {
+ struct nv20_miptree *nv20mt = (struct nv20_miptree *)mt;
+ int l;
+
+ pipe_buffer_reference(screen, &nv20mt->buffer, NULL);
+ for (l = 0; l <= mt->last_level; l++) {
+ if (nv20mt->level[l].image_offset)
+ FREE(nv20mt->level[l].image_offset);
+ }
+ FREE(nv20mt);
+ }
+}
+
+static struct pipe_surface *
+nv20_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt,
+ unsigned face, unsigned level, unsigned zslice,
+ unsigned flags)
+{
+ struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt;
+ struct pipe_surface *ps;
+
+ ps = CALLOC_STRUCT(pipe_surface);
+ if (!ps)
+ return NULL;
+ pipe_texture_reference(&ps->texture, pt);
+ pipe_buffer_reference(screen, &ps->buffer, nv20mt->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 = nv20mt->level[level].pitch;
+ ps->usage = flags;
+ ps->status = PIPE_SURFACE_STATUS_DEFINED;
+ ps->refcount = 1;
+ ps->winsys = screen->winsys;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset = nv20mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset = nv20mt->level[level].image_offset[zslice];
+ } else {
+ ps->offset = nv20mt->level[level].image_offset[0];
+ }
+
+ return ps;
+}
+
+static void
+nv20_miptree_surface_release(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, &ps->buffer, NULL);
+ FREE(ps);
+}
+
+void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen)
+{
+ pscreen->texture_create = nv20_miptree_create;
+ pscreen->texture_release = nv20_miptree_release;
+ pscreen->get_tex_surface = nv20_miptree_surface_get;
+ pscreen->tex_surface_release = nv20_miptree_surface_release;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_prim_vbuf.c b/src/gallium/drivers/nv20/nv20_prim_vbuf.c
new file mode 100644
index 0000000000..a51d657d27
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_prim_vbuf.c
@@ -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 "pipe/p_debug.h"
+#include "pipe/p_inlines.h"
+#include "pipe/p_winsys.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+#include "draw/draw_vbuf.h"
+
+/**
+ * Primitive renderer for nv20.
+ */
+struct nv20_vbuf_render {
+ struct vbuf_render base;
+
+ struct nv20_context *nv20;
+
+ /** Vertex buffer */
+ struct pipe_buffer* buffer;
+
+ /** Vertex size in bytes */
+ unsigned vertex_size;
+
+ /** Hardware primitive */
+ unsigned hwprim;
+};
+
+
+void nv20_vtxbuf_bind( struct nv20_context* nv20 )
+{
+ int i;
+ for(i = 0; i < 8; i++) {
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_ATTRIB_OFFSET(i), 1);
+ OUT_RING(0/*nv20->vtxbuf*/);
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_ATTRIB_FORMAT(i) ,1);
+ OUT_RING(0/*XXX*/);
+ }
+}
+
+/**
+ * Basically a cast wrapper.
+ */
+static INLINE struct nv20_vbuf_render *
+nv20_vbuf_render( struct vbuf_render *render )
+{
+ assert(render);
+ return (struct nv20_vbuf_render *)render;
+}
+
+
+static const struct vertex_info *
+nv20_vbuf_render_get_vertex_info( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+
+ nv20_emit_hw_state(nv20);
+
+ return &nv20->vertex_info;
+}
+
+
+static void *
+nv20_vbuf_render_allocate_vertices( struct vbuf_render *render,
+ ushort vertex_size,
+ ushort nr_vertices )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+ struct pipe_winsys *winsys = nv20->pipe.winsys;
+ size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+
+ assert(!nv20_render->buffer);
+ nv20_render->buffer = winsys->buffer_create(winsys, 64, PIPE_BUFFER_USAGE_VERTEX, size);
+
+ nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ return winsys->buffer_map(winsys,
+ nv20_render->buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+}
+
+
+static void
+nv20_vbuf_render_set_primitive( struct vbuf_render *render,
+ unsigned prim )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ nv20_render->hwprim = prim + 1;
+}
+
+
+static void
+nv20_vbuf_render_draw( struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices)
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+ int push, i;
+
+ nv20_emit_hw_state(nv20);
+
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1);
+ OUT_RELOCl(nv20_render->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+
+ BEGIN_RING(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING(nv20_render->hwprim);
+
+ if (nr_indices & 1) {
+ BEGIN_RING(kelvin, 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(kelvin, 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(kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1);
+ OUT_RING (0);
+}
+
+
+static void
+nv20_vbuf_render_release_vertices( struct vbuf_render *render,
+ void *vertices,
+ unsigned vertex_size,
+ unsigned vertices_used )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ struct nv20_context *nv20 = nv20_render->nv20;
+ struct pipe_winsys *winsys = nv20->pipe.winsys;
+ struct pipe_screen *pscreen = &nv20->screen->pipe;
+
+ assert(nv20_render->buffer);
+ winsys->buffer_unmap(winsys, nv20_render->buffer);
+ pipe_buffer_reference(pscreen, &nv20_render->buffer, NULL);
+}
+
+
+static void
+nv20_vbuf_render_destroy( struct vbuf_render *render )
+{
+ struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render);
+ FREE(nv20_render);
+}
+
+
+/**
+ * Create a new primitive render.
+ */
+static struct vbuf_render *
+nv20_vbuf_render_create( struct nv20_context *nv20 )
+{
+ struct nv20_vbuf_render *nv20_render = CALLOC_STRUCT(nv20_vbuf_render);
+
+ nv20_render->nv20 = nv20;
+
+ nv20_render->base.max_vertex_buffer_bytes = 16*1024;
+ nv20_render->base.max_indices = 1024;
+ nv20_render->base.get_vertex_info = nv20_vbuf_render_get_vertex_info;
+ nv20_render->base.allocate_vertices = nv20_vbuf_render_allocate_vertices;
+ nv20_render->base.set_primitive = nv20_vbuf_render_set_primitive;
+ nv20_render->base.draw = nv20_vbuf_render_draw;
+ nv20_render->base.release_vertices = nv20_vbuf_render_release_vertices;
+ nv20_render->base.destroy = nv20_vbuf_render_destroy;
+
+ return &nv20_render->base;
+}
+
+
+/**
+ * Create a new primitive vbuf/render stage.
+ */
+struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 )
+{
+ struct vbuf_render *render;
+ struct draw_stage *stage;
+
+ render = nv20_vbuf_render_create(nv20);
+ if(!render)
+ return NULL;
+
+ stage = draw_vbuf_stage( nv20->draw, render );
+ if(!stage) {
+ render->destroy(render);
+ return NULL;
+ }
+
+ return stage;
+}
diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c
new file mode 100644
index 0000000000..b7f5ea8512
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_screen.c
@@ -0,0 +1,208 @@
+#include "pipe/p_screen.h"
+
+#include "nv20_context.h"
+#include "nv20_screen.h"
+
+static const char *
+nv20_screen_get_name(struct pipe_screen *screen)
+{
+ struct nv20_screen *nv20screen = nv20_screen(screen);
+ struct nouveau_device *dev = nv20screen->nvws->channel->device;
+ static char buffer[128];
+
+ snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+ return buffer;
+}
+
+static const char *
+nv20_screen_get_vendor(struct pipe_screen *screen)
+{
+ return "nouveau";
+}
+
+static int
+nv20_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
+nv20_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
+nv20_screen_is_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ 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;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ return FALSE;
+}
+
+static void *
+nv20_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
+nv20_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
+{
+ struct pipe_winsys *ws = screen->winsys;
+
+ ws->buffer_unmap(ws, surface->buffer);
+}
+
+static void
+nv20_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct nv20_screen *screen = nv20_screen(pscreen);
+ struct nouveau_winsys *nvws = screen->nvws;
+
+ nvws->notifier_free(&screen->sync);
+ nvws->grobj_free(&screen->kelvin);
+
+ FREE(pscreen);
+}
+
+struct pipe_screen *
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+{
+ struct nv20_screen *screen = CALLOC_STRUCT(nv20_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->kelvin);
+ 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);
+ nv20_screen_destroy(&screen->pipe);
+ return NULL;
+ }
+
+ screen->pipe.winsys = ws;
+ screen->pipe.destroy = nv20_screen_destroy;
+
+ screen->pipe.get_name = nv20_screen_get_name;
+ screen->pipe.get_vendor = nv20_screen_get_vendor;
+ screen->pipe.get_param = nv20_screen_get_param;
+ screen->pipe.get_paramf = nv20_screen_get_paramf;
+
+ screen->pipe.is_format_supported = nv20_screen_is_format_supported;
+
+ screen->pipe.surface_map = nv20_surface_map;
+ screen->pipe.surface_unmap = nv20_surface_unmap;
+
+ nv20_screen_init_miptree_functions(&screen->pipe);
+
+ return &screen->pipe;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h
new file mode 100644
index 0000000000..8f2f2e341d
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_screen.h
@@ -0,0 +1,22 @@
+#ifndef __NV20_SCREEN_H__
+#define __NV20_SCREEN_H__
+
+#include "pipe/p_screen.h"
+
+struct nv20_screen {
+ struct pipe_screen pipe;
+
+ struct nouveau_winsys *nvws;
+
+ /* HW graphics objects */
+ struct nouveau_grobj *kelvin;
+ struct nouveau_notifier *sync;
+};
+
+static INLINE struct nv20_screen *
+nv20_screen(struct pipe_screen *screen)
+{
+ return (struct nv20_screen *)screen;
+}
+
+#endif
diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c
new file mode 100644
index 0000000000..c3b87230b7
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state.c
@@ -0,0 +1,588 @@
+#include "draw/draw_context.h"
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_shader_tokens.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+static void *
+nv20_blend_state_create(struct pipe_context *pipe,
+ const struct pipe_blend_state *cso)
+{
+ struct nv20_blend_state *cb;
+
+ cb = MALLOC(sizeof(struct nv20_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
+nv20_blend_state_bind(struct pipe_context *pipe, void *blend)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->blend = (struct nv20_blend_state*)blend;
+
+ nv20->dirty |= NV20_NEW_BLEND;
+}
+
+static void
+nv20_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 *
+nv20_sampler_state_create(struct pipe_context *pipe,
+ const struct pipe_sampler_state *cso)
+{
+ struct nv20_sampler_state *ps;
+ uint32_t filter = 0;
+
+ ps = MALLOC(sizeof(struct nv20_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
+nv20_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv20->tex_sampler[unit] = sampler[unit];
+ nv20->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void
+nv20_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void
+nv20_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
+ struct pipe_texture **miptree)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ unsigned unit;
+
+ for (unit = 0; unit < nr; unit++) {
+ nv20->tex_miptree[unit] = (struct nv20_miptree *)miptree[unit];
+ nv20->dirty_samplers |= (1 << unit);
+ }
+}
+
+static void *
+nv20_rasterizer_state_create(struct pipe_context *pipe,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct nv20_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 nv20_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
+nv20_rasterizer_state_bind(struct pipe_context *pipe, void *rast)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->rast = (struct nv20_rasterizer_state*)rast;
+
+ draw_set_rasterizer_state(nv20->draw, (nv20->rast ? nv20->rast->templ : NULL));
+
+ nv20->dirty |= NV20_NEW_RAST;
+}
+
+static void
+nv20_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv20_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct nv20_depth_stencil_alpha_state *hw;
+
+ hw = MALLOC(sizeof(struct nv20_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
+nv20_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *dsa)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->dsa = (struct nv20_depth_stencil_alpha_state*)dsa;
+
+ nv20->dirty |= NV20_NEW_DSA;
+}
+
+static void
+nv20_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ FREE(hwcso);
+}
+
+static void *
+nv20_vp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *templ)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ return draw_create_vertex_shader(nv20->draw, templ);
+}
+
+static void
+nv20_vp_state_bind(struct pipe_context *pipe, void *shader)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_bind_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader);
+
+ nv20->dirty |= NV20_NEW_VERTPROG;
+}
+
+static void
+nv20_vp_state_delete(struct pipe_context *pipe, void *shader)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_delete_vertex_shader(nv20->draw, (struct draw_vertex_shader *) shader);
+}
+
+static void *
+nv20_fp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv20_fragment_program *fp;
+
+ fp = CALLOC(1, sizeof(struct nv20_fragment_program));
+ fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+ tgsi_scan_shader(cso->tokens, &fp->info);
+
+ return (void *)fp;
+}
+
+static void
+nv20_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv20_fragment_program *fp = hwcso;
+
+ nv20->fragprog.current = fp;
+ nv20->dirty |= NV20_NEW_FRAGPROG;
+}
+
+static void
+nv20_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nv20_fragment_program *fp = hwcso;
+
+ nv20_fragprog_destroy(nv20, fp);
+ FREE((void*)fp->pipe.tokens);
+ FREE(fp);
+}
+
+static void
+nv20_set_blend_color(struct pipe_context *pipe,
+ const struct pipe_blend_color *bcol)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->blend_color = (struct pipe_blend_color*)bcol;
+
+ nv20->dirty |= NV20_NEW_BLENDCOL;
+}
+
+static void
+nv20_set_clip_state(struct pipe_context *pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ draw_set_clip_state(nv20->draw, clip);
+}
+
+static void
+nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+ const struct pipe_constant_buffer *buf )
+{
+ struct nv20_context *nv20 = nv20_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(nv20->constbuf[shader], mapped, buf->size);
+ nv20->constbuf_nr[shader] =
+ buf->size / (4 * sizeof(float));
+ ws->buffer_unmap(ws, buf->buffer);
+ }
+ }
+}
+
+static void
+nv20_set_framebuffer_state(struct pipe_context *pipe,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->framebuffer = (struct pipe_framebuffer_state*)fb;
+
+ nv20->dirty |= NV20_NEW_FRAMEBUFFER;
+}
+
+static void
+nv20_set_polygon_stipple(struct pipe_context *pipe,
+ const struct pipe_poly_stipple *stipple)
+{
+ NOUVEAU_ERR("line stipple hahaha\n");
+}
+
+static void
+nv20_set_scissor_state(struct pipe_context *pipe,
+ const struct pipe_scissor_state *s)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->scissor = (struct pipe_scissor_state*)s;
+
+ nv20->dirty |= NV20_NEW_SCISSOR;
+}
+
+static void
+nv20_set_viewport_state(struct pipe_context *pipe,
+ const struct pipe_viewport_state *vpt)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ nv20->viewport = (struct pipe_viewport_state*)vpt;
+
+ draw_set_viewport_state(nv20->draw, nv20->viewport);
+
+ nv20->dirty |= NV20_NEW_VIEWPORT;
+}
+
+static void
+nv20_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_buffer *vb)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ memcpy(nv20->vtxbuf, vb, sizeof(*vb) * count);
+ nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ draw_set_vertex_buffers(nv20->draw, count, vb);
+}
+
+static void
+nv20_set_vertex_elements(struct pipe_context *pipe, unsigned count,
+ const struct pipe_vertex_element *ve)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+
+ memcpy(nv20->vtxelt, ve, sizeof(*ve) * count);
+ nv20->dirty |= NV20_NEW_VTXARRAYS;
+
+ draw_set_vertex_elements(nv20->draw, count, ve);
+}
+
+void
+nv20_init_state_functions(struct nv20_context *nv20)
+{
+ nv20->pipe.create_blend_state = nv20_blend_state_create;
+ nv20->pipe.bind_blend_state = nv20_blend_state_bind;
+ nv20->pipe.delete_blend_state = nv20_blend_state_delete;
+
+ nv20->pipe.create_sampler_state = nv20_sampler_state_create;
+ nv20->pipe.bind_sampler_states = nv20_sampler_state_bind;
+ nv20->pipe.delete_sampler_state = nv20_sampler_state_delete;
+ nv20->pipe.set_sampler_textures = nv20_set_sampler_texture;
+
+ nv20->pipe.create_rasterizer_state = nv20_rasterizer_state_create;
+ nv20->pipe.bind_rasterizer_state = nv20_rasterizer_state_bind;
+ nv20->pipe.delete_rasterizer_state = nv20_rasterizer_state_delete;
+
+ nv20->pipe.create_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_create;
+ nv20->pipe.bind_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_bind;
+ nv20->pipe.delete_depth_stencil_alpha_state =
+ nv20_depth_stencil_alpha_state_delete;
+
+ nv20->pipe.create_vs_state = nv20_vp_state_create;
+ nv20->pipe.bind_vs_state = nv20_vp_state_bind;
+ nv20->pipe.delete_vs_state = nv20_vp_state_delete;
+
+ nv20->pipe.create_fs_state = nv20_fp_state_create;
+ nv20->pipe.bind_fs_state = nv20_fp_state_bind;
+ nv20->pipe.delete_fs_state = nv20_fp_state_delete;
+
+ nv20->pipe.set_blend_color = nv20_set_blend_color;
+ nv20->pipe.set_clip_state = nv20_set_clip_state;
+ nv20->pipe.set_constant_buffer = nv20_set_constant_buffer;
+ nv20->pipe.set_framebuffer_state = nv20_set_framebuffer_state;
+ nv20->pipe.set_polygon_stipple = nv20_set_polygon_stipple;
+ nv20->pipe.set_scissor_state = nv20_set_scissor_state;
+ nv20->pipe.set_viewport_state = nv20_set_viewport_state;
+
+ nv20->pipe.set_vertex_buffers = nv20_set_vertex_buffers;
+ nv20->pipe.set_vertex_elements = nv20_set_vertex_elements;
+}
+
diff --git a/src/gallium/drivers/nv20/nv20_state.h b/src/gallium/drivers/nv20/nv20_state.h
new file mode 100644
index 0000000000..34f402fdcb
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state.h
@@ -0,0 +1,139 @@
+#ifndef __NV20_STATE_H__
+#define __NV20_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_scan.h"
+
+struct nv20_blend_state {
+ uint32_t b_enable;
+ uint32_t b_srcfunc;
+ uint32_t b_dstfunc;
+
+ uint32_t c_mask;
+
+ uint32_t d_enable;
+};
+
+struct nv20_sampler_state {
+ uint32_t wrap;
+ uint32_t en;
+ uint32_t filt;
+ uint32_t bcol;
+};
+
+struct nv20_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 nv20_vertex_program_exec {
+ uint32_t data[4];
+ boolean has_branch_offset;
+ int const_index;
+};
+
+struct nv20_vertex_program_data {
+ int index; /* immediates == -1 */
+ float value[4];
+};
+
+struct nv20_vertex_program {
+ const struct pipe_shader_state *pipe;
+
+ boolean translated;
+ struct nv20_vertex_program_exec *insns;
+ unsigned nr_insns;
+ struct nv20_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 nv20_fragment_program_data {
+ unsigned offset;
+ unsigned index;
+};
+
+struct nv20_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 nv20_fragment_program_data *consts;
+ unsigned nr_consts;
+
+ struct pipe_buffer *buffer;
+
+ uint32_t fp_control;
+ uint32_t fp_reg_control;
+};
+
+
+struct nv20_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 nv20_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/nv20/nv20_state_emit.c b/src/gallium/drivers/nv20/nv20_state_emit.c
new file mode 100644
index 0000000000..e8dd22925c
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_state_emit.c
@@ -0,0 +1,303 @@
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+static void nv20_state_emit_blend(struct nv20_context* nv20)
+{
+ struct nv20_blend_state *b = nv20->blend;
+
+ BEGIN_RING(kelvin, NV10TCL_DITHER_ENABLE, 1);
+ OUT_RING (b->d_enable);
+
+ BEGIN_RING(kelvin, NV10TCL_BLEND_FUNC_ENABLE, 3);
+ OUT_RING (b->b_enable);
+ OUT_RING (b->b_srcfunc);
+ OUT_RING (b->b_dstfunc);
+
+ BEGIN_RING(kelvin, NV10TCL_COLOR_MASK, 1);
+ OUT_RING (b->c_mask);
+}
+
+static void nv20_state_emit_blend_color(struct nv20_context* nv20)
+{
+ struct pipe_blend_color *c = nv20->blend_color;
+
+ BEGIN_RING(kelvin, 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 nv20_state_emit_rast(struct nv20_context* nv20)
+{
+ struct nv20_rasterizer_state *r = nv20->rast;
+
+ BEGIN_RING(kelvin, NV10TCL_SHADE_MODEL, 2);
+ OUT_RING (r->shade_model);
+ OUT_RING (r->line_width);
+
+
+ BEGIN_RING(kelvin, NV10TCL_POINT_SIZE, 1);
+ OUT_RING (r->point_size);
+
+ BEGIN_RING(kelvin, NV10TCL_POLYGON_MODE_FRONT, 2);
+ OUT_RING (r->poly_mode_front);
+ OUT_RING (r->poly_mode_back);
+
+
+ BEGIN_RING(kelvin, NV10TCL_CULL_FACE, 2);
+ OUT_RING (r->cull_face);
+ OUT_RING (r->front_face);
+
+ BEGIN_RING(kelvin, NV10TCL_LINE_SMOOTH_ENABLE, 2);
+ OUT_RING (r->line_smooth_en);
+ OUT_RING (r->poly_smooth_en);
+
+ BEGIN_RING(kelvin, NV10TCL_CULL_FACE_ENABLE, 1);
+ OUT_RING (r->cull_face_en);
+}
+
+static void nv20_state_emit_dsa(struct nv20_context* nv20)
+{
+ struct nv20_depth_stencil_alpha_state *d = nv20->dsa;
+
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_FUNC, 1);
+ OUT_RING (d->depth.func);
+
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_WRITE_ENABLE, 1);
+ OUT_RING (d->depth.write_enable);
+
+ BEGIN_RING(kelvin, NV10TCL_DEPTH_TEST_ENABLE, 1);
+ OUT_RING (d->depth.test_enable);
+
+#if 0
+ BEGIN_RING(kelvin, NV10TCL_STENCIL_ENABLE, 1);
+ OUT_RING (d->stencil.enable);
+ BEGIN_RING(kelvin, NV10TCL_STENCIL_MASK, 7);
+ OUT_RINGp ((uint32_t *)&(d->stencil.wmask), 7);
+#endif
+
+ BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_ENABLE, 1);
+ OUT_RING (d->alpha.enabled);
+
+ BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_FUNC, 1);
+ OUT_RING (d->alpha.func);
+
+ BEGIN_RING(kelvin, NV10TCL_ALPHA_FUNC_REF, 1);
+ OUT_RING (d->alpha.ref);
+}
+
+static void nv20_state_emit_viewport(struct nv20_context* nv20)
+{
+}
+
+static void nv20_state_emit_scissor(struct nv20_context* nv20)
+{
+ // XXX this is so not working
+/* struct pipe_scissor_state *s = nv20->scissor;
+ BEGIN_RING(kelvin, NV10TCL_SCISSOR_HORIZ, 2);
+ OUT_RING (((s->maxx - s->minx) << 16) | s->minx);
+ OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/
+}
+
+static void nv20_state_emit_framebuffer(struct nv20_context* nv20)
+{
+ struct pipe_framebuffer_state* fb = nv20->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(kelvin, NV10TCL_RT_PITCH, 1);
+ OUT_RING (rt->stride | (zeta->stride << 16));
+ } else {
+ BEGIN_RING(kelvin, NV10TCL_RT_PITCH, 1);
+ OUT_RING (rt->stride | (rt->stride << 16));
+ }
+
+ nv20->rt[0] = rt->buffer;
+
+ if (zeta_format)
+ {
+ nv20->zeta = zeta->buffer;
+ }
+
+ BEGIN_RING(kelvin, NV10TCL_RT_HORIZ, 3);
+ OUT_RING ((w << 16) | 0);
+ OUT_RING ((h << 16) | 0);
+ OUT_RING (rt_format);
+ BEGIN_RING(kelvin, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+ OUT_RING (((w - 1) << 16) | 0 | 0x08000800);
+ OUT_RING (((h - 1) << 16) | 0 | 0x08000800);
+}
+
+static void nv20_vertex_layout(struct nv20_context *nv20)
+{
+ struct nv20_fragment_program *fp = nv20->fragprog.current;
+ uint32_t src = 0;
+ int i;
+ struct vertex_info *vinfo = &nv20->vertex_info;
+
+ 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
+nv20_emit_hw_state(struct nv20_context *nv20)
+{
+ int i;
+
+ if (nv20->dirty & NV20_NEW_VERTPROG) {
+ //nv20_vertprog_bind(nv20, nv20->vertprog.current);
+ nv20->dirty &= ~NV20_NEW_VERTPROG;
+ }
+
+ if (nv20->dirty & NV20_NEW_FRAGPROG) {
+ nv20_fragprog_bind(nv20, nv20->fragprog.current);
+ /*XXX: clear NV20_NEW_FRAGPROG if no new program uploaded */
+ nv20->dirty_samplers |= (1<<10);
+ nv20->dirty_samplers = 0;
+ }
+
+ if (nv20->dirty_samplers || (nv20->dirty & NV20_NEW_FRAGPROG)) {
+ nv20_fragtex_bind(nv20);
+ nv20->dirty &= ~NV20_NEW_FRAGPROG;
+ }
+
+ if (nv20->dirty & NV20_NEW_VTXARRAYS) {
+ nv20->dirty &= ~NV20_NEW_VTXARRAYS;
+ nv20_vertex_layout(nv20);
+ nv20_vtxbuf_bind(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_BLEND) {
+ nv20->dirty &= ~NV20_NEW_BLEND;
+ nv20_state_emit_blend(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_BLENDCOL) {
+ nv20->dirty &= ~NV20_NEW_BLENDCOL;
+ nv20_state_emit_blend_color(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_RAST) {
+ nv20->dirty &= ~NV20_NEW_RAST;
+ nv20_state_emit_rast(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_DSA) {
+ nv20->dirty &= ~NV20_NEW_DSA;
+ nv20_state_emit_dsa(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_VIEWPORT) {
+ nv20->dirty &= ~NV20_NEW_VIEWPORT;
+ nv20_state_emit_viewport(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_SCISSOR) {
+ nv20->dirty &= ~NV20_NEW_SCISSOR;
+ nv20_state_emit_scissor(nv20);
+ }
+
+ if (nv20->dirty & NV20_NEW_FRAMEBUFFER) {
+ nv20->dirty &= ~NV20_NEW_FRAMEBUFFER;
+ nv20_state_emit_framebuffer(nv20);
+ }
+
+ /* 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 nv20_vbo.c
+ */
+
+ /* Render target */
+// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly
+// BEGIN_RING(kelvin, NV10TCL_DMA_COLOR0, 1);
+// OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV10TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ if (nv20->zeta) {
+// XXX
+// BEGIN_RING(kelvin, NV10TCL_DMA_ZETA, 1);
+// OUT_RELOCo(nv20->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV10TCL_ZETA_OFFSET, 1);
+ OUT_RELOCl(nv20->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ /* XXX for when we allocate LMA on nv17 */
+/* BEGIN_RING(kelvin, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1);
+ OUT_RELOCl(nv20->zeta + lma_offset);*/
+ }
+
+ /* Vertex buffer */
+ BEGIN_RING(kelvin, NV10TCL_DMA_VTXBUF0, 1);
+ OUT_RELOCo(nv20->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(kelvin, NV10TCL_COLOR_OFFSET, 1);
+ OUT_RELOCl(nv20->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ /* Texture images */
+ for (i = 0; i < 2; i++) {
+ if (!(nv20->fp_samplers & (1 << i)))
+ continue;
+ BEGIN_RING(kelvin, NV10TCL_TX_OFFSET(i), 1);
+ OUT_RELOCl(nv20->tex[i].buffer, 0, NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART | NOUVEAU_BO_RD);
+ BEGIN_RING(kelvin, NV10TCL_TX_FORMAT(i), 1);
+ OUT_RELOCd(nv20->tex[i].buffer, nv20->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/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c
new file mode 100644
index 0000000000..41b6d6ad35
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_surface.c
@@ -0,0 +1,64 @@
+
+/**************************************************************************
+ *
+ * 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 "nv20_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
+#include "pipe/p_inlines.h"
+#include "util/u_tile.h"
+
+static void
+nv20_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 nv20_context *nv20 = nv20_context(pipe);
+ struct nouveau_winsys *nvws = nv20->nvws;
+
+ nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
+ width, height);
+}
+
+static void
+nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
+ unsigned destx, unsigned desty, unsigned width,
+ unsigned height, unsigned value)
+{
+ struct nv20_context *nv20 = nv20_context(pipe);
+ struct nouveau_winsys *nvws = nv20->nvws;
+
+ nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
+}
+
+void
+nv20_init_surface_functions(struct nv20_context *nv20)
+{
+ nv20->pipe.surface_copy = nv20_surface_copy;
+ nv20->pipe.surface_fill = nv20_surface_fill;
+}
diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c
new file mode 100644
index 0000000000..4edc4efebd
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_vbo.c
@@ -0,0 +1,77 @@
+#include "draw/draw_context.h"
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+#include "nv20_context.h"
+#include "nv20_state.h"
+
+#include "nouveau/nouveau_channel.h"
+#include "nouveau/nouveau_pushbuf.h"
+
+boolean nv20_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ struct nv20_context *nv20 = nv20_context( pipe );
+ struct draw_context *draw = nv20->draw;
+ unsigned i;
+
+ nv20_emit_hw_state(nv20);
+
+ /*
+ * Map vertex buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv20->vtxbuf[i].buffer) {
+ void *buf
+ = pipe->winsys->buffer_map(pipe->winsys,
+ nv20->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,
+ nv20->constbuf[PIPE_SHADER_VERTEX],
+ nv20->constbuf_nr[PIPE_SHADER_VERTEX]);
+
+ /* draw! */
+ draw_arrays(nv20->draw, prim, start, count);
+
+ /*
+ * unmap vertex/index buffers
+ */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ if (nv20->vtxbuf[i].buffer) {
+ pipe->winsys->buffer_unmap(pipe->winsys, nv20->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 nv20_draw_arrays( struct pipe_context *pipe,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return nv20_draw_elements(pipe, NULL, 0, prim, start, count);
+}
+
+
+
diff --git a/src/gallium/drivers/nv20/nv20_vertprog.c b/src/gallium/drivers/nv20/nv20_vertprog.c
new file mode 100644
index 0000000000..a885fcd7a5
--- /dev/null
+++ b/src/gallium/drivers/nv20/nv20_vertprog.c
@@ -0,0 +1,838 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "nv20_context.h"
+#include "nv20_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 "nv20_shader.h"
+
+#define swz(s,x,y,z,w) nv20_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
+#define neg(s) nv20_sr_neg((s))
+#define abs(s) nv20_sr_abs((s))
+
+struct nv20_vpc {
+ struct nv20_vertex_program *vp;
+
+ struct nv20_vertex_program_exec *vpi;
+
+ unsigned output_map[PIPE_MAX_SHADER_OUTPUTS];
+
+ int high_temp;
+ int temp_temp_count;
+
+ struct nv20_sreg *imm;
+ unsigned nr_imm;
+};
+
+static struct nv20_sreg
+temp(struct nv20_vpc *vpc)
+{
+ int idx;
+
+ idx = vpc->temp_temp_count++;
+ idx += vpc->high_temp + 1;
+ return nv20_sr(NV30SR_TEMP, idx);
+}
+
+static struct nv20_sreg
+constant(struct nv20_vpc *vpc, int pipe, float x, float y, float z, float w)
+{
+ struct nv20_vertex_program *vp = vpc->vp;
+ struct nv20_vertex_program_data *vpd;
+ int idx;
+
+ if (pipe >= 0) {
+ for (idx = 0; idx < vp->nr_consts; idx++) {
+ if (vp->consts[idx].index == pipe)
+ return nv20_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 nv20_sr(NV30SR_CONST, idx);
+}
+
+#define arith(cc,s,o,d,m,s0,s1,s2) \
+ nv20_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2))
+
+static void
+emit_src(struct nv20_vpc *vpc, uint32_t *hw, int pos, struct nv20_sreg src)
+{
+ struct nv20_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 nv20_vpc *vpc, uint32_t *hw, int slot, struct nv20_sreg dst)
+{
+ struct nv20_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
+nv20_vp_arith(struct nv20_vpc *vpc, int slot, int op,
+ struct nv20_sreg dst, int mask,
+ struct nv20_sreg s0, struct nv20_sreg s1,
+ struct nv20_sreg s2)
+{
+ struct nv20_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 nv20_sreg
+tgsi_src(struct nv20_vpc *vpc, const struct tgsi_full_src_register *fsrc) {
+ struct nv20_sreg src;
+
+ switch (fsrc->SrcRegister.File) {
+ case TGSI_FILE_INPUT:
+ src = nv20_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 = nv20_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 nv20_sreg
+tgsi_dst(struct nv20_vpc *vpc, const struct tgsi_full_dst_register *fdst) {
+ struct nv20_sreg dst;
+
+ switch (fdst->DstRegister.File) {
+ case TGSI_FILE_OUTPUT:
+ dst = nv20_sr(NV30SR_OUTPUT,
+ vpc->output_map[fdst->DstRegister.Index]);
+
+ break;
+ case TGSI_FILE_TEMPORARY:
+ dst = nv20_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
+nv20_vertprog_parse_instruction(struct nv20_vpc *vpc,
+ const struct tgsi_full_instruction *finst)
+{
+ struct nv20_sreg src[3], dst, tmp;
+ struct nv20_sreg none = nv20_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_SGT:
+ arith(vpc, 0, OP_SGT, 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
+nv20_vertprog_parse_decl_output(struct nv20_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
+nv20_vertprog_prepare(struct nv20_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 nv20_sreg));
+ assert(vpc->imm);
+ }
+
+ return TRUE;
+}
+
+static void
+nv20_vertprog_translate(struct nv20_context *nv20,
+ struct nv20_vertex_program *vp)
+{
+ struct tgsi_parse_context parse;
+ struct nv20_vpc *vpc = NULL;
+
+ tgsi_dump(vp->pipe.tokens,0);
+
+ vpc = CALLOC(1, sizeof(struct nv20_vpc));
+ if (!vpc)
+ return;
+ vpc->vp = vp;
+ vpc->high_temp = -1;
+
+ if (!nv20_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 (!nv20_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 (!nv20_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
+nv20_vertprog_validate(struct nv20_context *nv20)
+{
+ struct nouveau_winsys *nvws = nv20->nvws;
+ struct pipe_winsys *ws = nv20->pipe.winsys;
+ struct nouveau_grobj *rankine = nv20->screen->rankine;
+ struct nv20_vertex_program *vp;
+ struct pipe_buffer *constbuf;
+ boolean upload_code = FALSE, upload_data = FALSE;
+ int i;
+
+ vp = nv20->vertprog;
+ constbuf = nv20->constbuf[PIPE_SHADER_VERTEX];
+
+ /* Translate TGSI shader into hw bytecode */
+ if (!vp->translated) {
+ nv20_vertprog_translate(nv20, vp);
+ if (!vp->translated)
+ return FALSE;
+ }
+
+ /* Allocate hw vtxprog exec slots */
+ if (!vp->exec) {
+ struct nouveau_resource *heap = nv20->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 nv20_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 = nv20->screen->vp_data_heap;
+
+ if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) {
+ while (heap->next && heap->size < vp->nr_consts) {
+ struct nv20_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 nv20_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 nv20_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 nv20_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 != nv20->state.hw[NV30_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv20->state.hw[NV30_STATE_VERTPROG]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+nv20_vertprog_destroy(struct nv20_context *nv20, struct nv20_vertex_program *vp)
+{
+ struct nouveau_winsys *nvws = nv20->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 nv20_state_entry nv20_state_vertprog = {
+ .validate = nv20_vertprog_validate,
+ .dirty = {
+ .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/,
+ .hw = NV30_STATE_VERTPROG,
+ }
+};
diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile
new file mode 100644
index 0000000000..69f2790dfe
--- /dev/null
+++ b/src/gallium/drivers/nv30/Makefile
@@ -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
index 0000000000..8c3ca204d5
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_clear.c
@@ -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
index 0000000000..2bff28aca9
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_context.c
@@ -0,0 +1,72 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.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
index 0000000000..b933769700
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_context.h
@@ -0,0 +1,212 @@
+#ifndef __NV30_CONTEXT_H__
+#define __NV30_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.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
index 0000000000..74fc138c05
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_draw.c
@@ -0,0 +1,61 @@
+#include "draw/draw_pipe.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
index 0000000000..320ba3f4bf
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_fragprog.c
@@ -0,0 +1,911 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/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_KILP:
+ arith(fpc, 0, KIL, none, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_KIL:
+ 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_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:
+ 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_SGT:
+ arith(fpc, sat, SGT, 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;
+
+ tgsi_dump(fp->pipe.tokens,0);
+
+ 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(8, 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_method(so, nv30->screen->rankine, NV34TCL_TX_UNITS_ENABLE, 1);
+ so_data (so, fp->samplers);
+ 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
index 0000000000..9e6f746a42
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -0,0 +1,186 @@
+#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,swsurf) \
+{ \
+ 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), \
+ swsurf \
+}
+
+struct nv30_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+ int swizzle;
+ int swizzled_surface;
+};
+
+static struct nv30_texture_format
+nv30_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 1),
+ _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 1),
+ _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 1),
+ _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 1),
+ _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 1),
+ _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 1),
+ _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 1),
+ _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 1),
+// _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0),
+// _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0),
+ _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0),
+ _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0),
+ _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0),
+ _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0),
+ {},
+};
+
+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++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ 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);
+
+ tex_flags |= (tf->swizzled_surface ? NOUVEAU_BO_SWIZZLED : 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
index 0000000000..9124db03e8
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_miptree.c
@@ -0,0 +1,162 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.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(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_texture *mt = *pt;
+
+ *pt = NULL;
+ if (--mt->refcount <= 0) {
+ struct nv30_miptree *nv30mt = (struct nv30_miptree *)mt;
+ int l;
+
+ pipe_buffer_reference(pscreen, &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 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(pscreen, &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;
+ ps->refcount = 1;
+ ps->winsys = pscreen->winsys;
+
+ 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
index 0000000000..d40d75f264
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_query.c
@@ -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
index 0000000000..a595e2eb22
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -0,0 +1,332 @@
+#include "pipe/p_screen.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 PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ return 0;
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ 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,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ 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;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ 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
index 0000000000..b7ddc2a959
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_screen.h
@@ -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
index 0000000000..dd3a36f78f
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_shader.h
@@ -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
index 0000000000..fc66075c83
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state.c
@@ -0,0 +1,724 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.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()
+ */
+ /*NV34TCL_TX_FORMAT_RECT*/
+ /*if (!cso->normalized_coords) {
+ ps->fmt |= (1<<14) ;
+ }*/
+
+ 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) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/;
+
+ limit = CLAMP(cso->min_lod, 0.0, 15.0);
+ ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/;
+ }
+
+ 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.tokens = tgsi_dup_tokens(cso->tokens);
+ /*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((void*)vp->pipe.tokens);
+ 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.tokens = tgsi_dup_tokens(cso->tokens);
+
+ 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((void*)fp->pipe.tokens);
+ 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
index 0000000000..e6f23bf166
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state.h
@@ -0,0 +1,85 @@
+#ifndef __NV30_STATE_H__
+#define __NV30_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/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
index 0000000000..44d43e132a
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_blend.c
@@ -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
index 0000000000..40fed621b2
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_emit.c
@@ -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
index 0000000000..d93e2bb5c8
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_fb.c
@@ -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
index 0000000000..6d1b60e043
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_rasterizer.c
@@ -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
index 0000000000..1db9bc1795
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_scissor.c
@@ -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
index 0000000000..41b42813b4
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_stipple.c
@@ -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
index 0000000000..951d40ebfd
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_viewport.c
@@ -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
index 0000000000..0940b7269b
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_zsa.c
@@ -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
index 0000000000..36f4887750
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_surface.c
@@ -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_winsys.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_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
index 0000000000..556f981d4a
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_vbo.c
@@ -0,0 +1,556 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.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)
+{
+ 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:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ 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:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ 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
index 0000000000..72824559e8
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_vertprog.c
@@ -0,0 +1,838 @@
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+
+#include "pipe/p_shader_tokens.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_dump.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_SGT:
+ arith(vpc, 0, OP_SGT, 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;
+
+ tgsi_dump(vp->pipe.tokens,0);
+
+ 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
index 0000000000..9c8eadf7e4
--- /dev/null
+++ b/src/gallium/drivers/nv40/Makefile
@@ -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
index 0000000000..59efd620e3
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_clear.c
@@ -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
index 0000000000..cc63dd734b
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_context.c
@@ -0,0 +1,72 @@
+#include "draw/draw_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.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
index 0000000000..adcfbdd85a
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -0,0 +1,233 @@
+#ifndef __NV40_CONTEXT_H__
+#define __NV40_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.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
index 0000000000..8e56cdc2fe
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_draw.c
@@ -0,0 +1,349 @@
+#include "pipe/p_shader_tokens.h"
+
+#include "util/u_pack_color.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
index 0000000000..91dcbebda0
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_fragprog.c
@@ -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/tgsi_parse.h"
+#include "tgsi/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_KILP:
+ arith(fpc, 0, KIL, none, 0, none, none, none);
+ break;
+ case TGSI_OPCODE_KIL:
+ 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
index 0000000000..566d5a8d5b
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_fragtex.c
@@ -0,0 +1,169 @@
+#include "nv40_context.h"
+
+#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \
+{ \
+ 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), \
+ ((NV40TCL_TEX_FILTER_SIGNED_RED*sx) | (NV40TCL_TEX_FILTER_SIGNED_GREEN*sy) | \
+ (NV40TCL_TEX_FILTER_SIGNED_BLUE*sz) | (NV40TCL_TEX_FILTER_SIGNED_ALPHA*sw)) \
+}
+
+struct nv40_texture_format {
+ boolean defined;
+ uint pipe;
+ int format;
+ int swizzle;
+ int sign;
+};
+
+static struct nv40_texture_format
+nv40_texture_formats[] = {
+ _(A8R8G8B8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(A1R5G5B5_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(A4R4G4B4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(R5G6B5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
+ _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 0, 0, 0, 0),
+ _(R16_SNORM , A16 , ZERO, ZERO, S1, ONE, X, X, X, Y, 1, 1, 1, 1),
+ _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 0, 0, 0, 0),
+ _(A8L8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 0, 0, 0, 0),
+ _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(Z24S8_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
+ _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
+ {},
+};
+
+static struct nv40_texture_format *
+nv40_fragtex_format(uint pipe_format)
+{
+ struct nv40_texture_format *tf = nv40_texture_formats;
+
+ while (tf->defined) {
+ if (tf->pipe == pipe_format)
+ return tf;
+ tf++;
+ }
+
+ NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
+ 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 | tf->sign | 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
index 0000000000..f321b72149
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_miptree.c
@@ -0,0 +1,164 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "nv40_context.h"
+
+static void
+nv40_miptree_layout(struct nv40_miptree *mt)
+{
+ struct pipe_texture *pt = &mt->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(pitch, 64);
+
+ mt->level[l].pitch = pitch * pt->block.size;
+ mt->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++) {
+ mt->level[l].image_offset[f] = offset;
+ offset += mt->level[l].pitch * pt->height[l];
+ }
+ }
+
+ mt->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 **ppt)
+{
+ struct pipe_texture *pt = *ppt;
+ struct nv40_miptree *mt = (struct nv40_miptree *)pt;
+ int l;
+
+ *ppt = NULL;
+ if (--pt->refcount)
+ return;
+
+
+ pipe_buffer_reference(pscreen, &mt->buffer, NULL);
+ for (l = 0; l <= pt->last_level; l++) {
+ if (mt->level[l].image_offset)
+ FREE(mt->level[l].image_offset);
+ }
+
+ FREE(mt);
+}
+
+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 nv40_miptree *mt = (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(pscreen, &ps->buffer, mt->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 = mt->level[level].pitch;
+ ps->usage = flags;
+ ps->status = PIPE_SURFACE_STATUS_DEFINED;
+ ps->refcount = 1;
+ ps->winsys = pscreen->winsys;
+
+ if (pt->target == PIPE_TEXTURE_CUBE) {
+ ps->offset = mt->level[level].image_offset[face];
+ } else
+ if (pt->target == PIPE_TEXTURE_3D) {
+ ps->offset = mt->level[level].image_offset[zslice];
+ } else {
+ ps->offset = mt->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, &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
index 0000000000..57f39cfab0
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_query.c
@@ -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
index 0000000000..ada0238511
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.c
@@ -0,0 +1,314 @@
+#include "pipe/p_screen.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 PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ 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,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ 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;
+ }
+ } else {
+ 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_R16_SNORM:
+ 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;
+ }
+ }
+
+ 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
index 0000000000..c04a1275a0
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_screen.h
@@ -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
index 0000000000..854dccf548
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_shader.h
@@ -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
index 0000000000..255c4b294d
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -0,0 +1,740 @@
+#include "pipe/p_state.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "draw/draw_context.h"
+
+#include "tgsi/tgsi_parse.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.tokens = tgsi_dup_tokens(cso->tokens);
+ 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((void*)vp->pipe.tokens);
+ 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.tokens = tgsi_dup_tokens(cso->tokens);
+
+ 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((void*)fp->pipe.tokens);
+ 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
index 0000000000..8a9d8c8fdf
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state.h
@@ -0,0 +1,88 @@
+#ifndef __NV40_STATE_H__
+#define __NV40_STATE_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/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
index 0000000000..95e6d7394f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_blend.c
@@ -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
index 0000000000..ab88dc416e
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -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
index 0000000000..0e4e60eaa7
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_fb.c
@@ -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
index 0000000000..9ecda5990f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_rasterizer.c
@@ -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
index 0000000000..285239ef41
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_scissor.c
@@ -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
index 0000000000..b51024ad9b
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_stipple.c
@@ -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
index 0000000000..869a55b405
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_viewport.c
@@ -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
index 0000000000..fb760677c8
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_state_zsa.c
@@ -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
index 0000000000..576af7c59e
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_surface.c
@@ -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_winsys.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_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
index 0000000000..09f6e79d32
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_vbo.c
@@ -0,0 +1,555 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.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)
+{
+ 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:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ 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:
+ NOUVEAU_ERR("Unknown format %s\n", pf_name(pipe));
+ 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
index 0000000000..ff988e6a5f
--- /dev/null
+++ b/src/gallium/drivers/nv40/nv40_vertprog.c
@@ -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/tgsi_parse.h"
+#include "tgsi/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
index 0000000000..be30400c03
--- /dev/null
+++ b/src/gallium/drivers/nv50/Makefile
@@ -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
index 0000000000..a31a42d6b5
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -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 "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)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct pipe_framebuffer_state fb, s_fb = nv50->framebuffer;
+ struct pipe_scissor_state sc, s_sc = nv50->scissor;
+ unsigned dirty = nv50->dirty;
+
+ nv50->dirty = 0;
+
+ if (ps->format == PIPE_FORMAT_Z24S8_UNORM ||
+ ps->format == PIPE_FORMAT_Z16_UNORM) {
+ fb.num_cbufs = 0;
+ fb.zsbuf = ps;
+ } else {
+ fb.num_cbufs = 1;
+ fb.cbufs[0] = ps;
+ fb.zsbuf = NULL;
+ }
+ fb.width = ps->width;
+ fb.height = ps->height;
+ pipe->set_framebuffer_state(pipe, &fb);
+
+ sc.minx = sc.miny = 0;
+ sc.maxx = fb.width;
+ sc.maxy = fb.height;
+ pipe->set_scissor_state(pipe, &sc);
+
+ nv50_state_validate(nv50);
+
+ switch (ps->format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ BEGIN_RING(tesla, 0x0d80, 4);
+ OUT_RINGf (ubyte_to_float((clearValue >> 16) & 0xff));
+ OUT_RINGf (ubyte_to_float((clearValue >> 8) & 0xff));
+ OUT_RINGf (ubyte_to_float((clearValue >> 0) & 0xff));
+ OUT_RINGf (ubyte_to_float((clearValue >> 24) & 0xff));
+ BEGIN_RING(tesla, 0x19d0, 1);
+ OUT_RING (0x3c);
+ break;
+ case PIPE_FORMAT_Z24S8_UNORM:
+ BEGIN_RING(tesla, 0x0d90, 1);
+ OUT_RINGf ((float)(clearValue >> 8) * (1.0 / 16777215.0));
+ BEGIN_RING(tesla, 0x0da0, 1);
+ OUT_RING (clearValue & 0xff);
+ BEGIN_RING(tesla, 0x19d0, 1);
+ OUT_RING (0x03);
+ break;
+ default:
+ pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height,
+ clearValue);
+ break;
+ }
+
+ pipe->set_framebuffer_state(pipe, &s_fb);
+ pipe->set_scissor_state(pipe, &s_sc);
+ nv50->dirty |= dirty;
+
+ 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
index 0000000000..b02c53f209
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -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_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_winsys.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
index 0000000000..5d377f2d06
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -0,0 +1,185 @@
+#ifndef __NV50_CONTEXT_H__
+#define __NV50_CONTEXT_H__
+
+#include "pipe/p_context.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_compiler.h"
+
+#include "util/u_memory.h"
+#include "util/u_math.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
index 0000000000..2f6f607261
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_draw.c
@@ -0,0 +1,89 @@
+/*
+ * 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 "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
index 0000000000..28a8bdc0fa
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -0,0 +1,135 @@
+/*
+ * 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_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;
+ /*XXX*/
+ pitch *= 2;
+
+ 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_texture *pt = *ppt;
+
+ *ppt = NULL;
+
+ if (--pt->refcount <= 0) {
+ struct nv50_miptree *mt = nv50_miptree(pt);
+
+ pipe_buffer_reference(pscreen, &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 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 = pscreen->winsys;
+ 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(pscreen, &ps->buffer, mt->buffer);
+
+ return ps;
+}
+
+static void
+nv50_miptree_surface_del(struct pipe_screen *pscreen,
+ struct pipe_surface **psurface)
+{
+ 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(pscreen, &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
index 0000000000..d6fbdd1824
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -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/tgsi_parse.h"
+#include "tgsi/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
index 0000000000..78deed6a38
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -0,0 +1,45 @@
+#ifndef __NV50_PROGRAM_H__
+#define __NV50_PROGRAM_H__
+
+#include "pipe/p_state.h"
+#include "tgsi/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
index 0000000000..26bd90ccc5
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -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
index 0000000000..b5aef7dadd
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -0,0 +1,323 @@
+/*
+ * 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 "nv50_context.h"
+#include "nv50_screen.h"
+
+#include "nouveau/nouveau_stateobj.h"
+
+#define NV5X_GRCLASS5097_CHIPSETS 0x00000001
+#define NV8X_GRCLASS8297_CHIPSETS 0x00000050
+#define NV9X_GRCLASS8297_CHIPSETS 0x00000014
+
+static boolean
+nv50_screen_is_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned tex_usage, unsigned geom_flags)
+{
+ if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+ 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;
+ }
+ } else {
+ 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;
+ }
+ }
+
+ 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 PIPE_CAP_TEXTURE_MIRROR_CLAMP:
+ case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
+ return 1;
+ 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
index 0000000000..400ddcef06
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -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
index 0000000000..95f9d408b5
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -0,0 +1,638 @@
+/*
+ * 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_inlines.h"
+
+#include "tgsi/tgsi_parse.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.tokens = tgsi_dup_tokens(cso->tokens);
+ 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);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
+}
+
+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.tokens = tgsi_dup_tokens(cso->tokens);
+ 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);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
+}
+
+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
index 0000000000..198e25f448
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -0,0 +1,309 @@
+/*
+ * 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:
+ NOUVEAU_ERR("AIIII unknown format %s\n",
+ pf_name(fb->cbufs[i]->format));
+ 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:
+ NOUVEAU_ERR("AIIII unknown format %s\n",
+ pf_name(fb->zsbuf->format));
+ 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
index 0000000000..5bf97d3a6b
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -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_winsys.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_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 *pscreen, struct pipe_surface *ps)
+{
+ struct nouveau_winsys *nvws = nv50_screen(pscreen)->nvws;
+ struct pipe_winsys *ws = pscreen->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(pscreen, &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
index 0000000000..fde3c97c05
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -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
index 0000000000..6861d67b4d
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_texture.h
@@ -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
index 0000000000..584336682e
--- /dev/null
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -0,0 +1,237 @@
+/*
+ * 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 "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:
+ {
+ NOUVEAU_ERR("invalid vbo format %s\n",
+ pf_name(ve->src_format));
+ 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
index 0000000000..4f7a953484
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/Makefile
@@ -0,0 +1,18 @@
+TARGET = libg3dvl.a
+OBJECTS = vl_display.o vl_screen.o vl_context.o vl_surface.o vl_shader_build.o vl_util.o vl_basic_csc.o \
+ vl_r16snorm_mc.o vl_r16snorm_mc_buf.o
+GALLIUMDIR = ../..
+
+CFLAGS += -g -Wall -fPIC -I${GALLIUMDIR}/include -I${GALLIUMDIR}/auxiliary -I${GALLIUMDIR}/winsys/g3dvl
+
+#############################################
+
+.PHONY = all clean
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS}
+ ar rcs $@ $^
+
+clean:
+ rm -rf ${OBJECTS} ${TARGET}
diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
new file mode 100644
index 0000000000..9f9dafc8a9
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c
@@ -0,0 +1,707 @@
+#define VL_INTERNAL
+#include "vl_basic_csc.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_state.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include "vl_csc.h"
+#include "vl_surface.h"
+#include "vl_shader_build.h"
+#include "vl_types.h"
+
+struct vlVertexShaderConsts
+{
+ struct vlVertex4f dst_scale;
+ struct vlVertex4f dst_trans;
+ struct vlVertex4f src_scale;
+ struct vlVertex4f src_trans;
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f bias;
+ float matrix[16];
+};
+
+struct vlBasicCSC
+{
+ struct vlCSC base;
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state framebuffer;
+ void *sampler;
+ void *vertex_shader, *fragment_shader;
+ struct pipe_vertex_buffer vertex_bufs[2];
+ struct pipe_vertex_element vertex_elems[2];
+ struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+};
+
+static int vlResizeFrameBuffer
+(
+ struct vlCSC *csc,
+ unsigned int width,
+ unsigned int height
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ if (basic_csc->framebuffer.width == width && basic_csc->framebuffer.height == height)
+ return 0;
+
+ if (basic_csc->framebuffer.cbufs[0])
+ pipe->winsys->surface_release
+ (
+ pipe->winsys,
+ &basic_csc->framebuffer.cbufs[0]
+ );
+
+ basic_csc->viewport.scale[0] = width;
+ basic_csc->viewport.scale[1] = height;
+ basic_csc->viewport.scale[2] = 1;
+ basic_csc->viewport.scale[3] = 1;
+ basic_csc->viewport.translate[0] = 0;
+ basic_csc->viewport.translate[1] = 0;
+ basic_csc->viewport.translate[2] = 0;
+ basic_csc->viewport.translate[3] = 0;
+
+ basic_csc->framebuffer.width = width;
+ basic_csc->framebuffer.height = height;
+ basic_csc->framebuffer.cbufs[0] = pipe->winsys->surface_alloc(pipe->winsys);
+ pipe->winsys->surface_alloc_storage
+ (
+ pipe->winsys,
+ basic_csc->framebuffer.cbufs[0],
+ width,
+ height,
+ 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
+ );
+
+ /* Clear to black, in case video doesn't fill the entire window */
+ pipe->clear(pipe, basic_csc->framebuffer.cbufs[0], 0);
+
+ return 0;
+}
+
+static int vlBegin
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer);
+ pipe->set_viewport_state(pipe, &basic_csc->viewport);
+ pipe->bind_sampler_states(pipe, 1, (void**)&basic_csc->sampler);
+ /* Source texture set in vlPutSurface() */
+ pipe->bind_vs_state(pipe, basic_csc->vertex_shader);
+ pipe->bind_fs_state(pipe, basic_csc->fragment_shader);
+ pipe->set_vertex_buffers(pipe, 2, basic_csc->vertex_bufs);
+ pipe->set_vertex_elements(pipe, 2, basic_csc->vertex_elems);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &basic_csc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &basic_csc->fs_const_buf);
+
+ return 0;
+}
+
+static int vlPutPictureCSC
+(
+ struct vlCSC *csc,
+ struct vlSurface *surface,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ enum vlPictureType picture_type
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+
+ assert(csc);
+ assert(surface);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ basic_csc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->dst_scale.x = destw / (float)basic_csc->framebuffer.cbufs[0]->width;
+ vs_consts->dst_scale.y = desth / (float)basic_csc->framebuffer.cbufs[0]->height;
+ vs_consts->dst_scale.z = 1;
+ vs_consts->dst_scale.w = 1;
+ vs_consts->dst_trans.x = destx / (float)basic_csc->framebuffer.cbufs[0]->width;
+ vs_consts->dst_trans.y = desty / (float)basic_csc->framebuffer.cbufs[0]->height;
+ vs_consts->dst_trans.z = 0;
+ vs_consts->dst_trans.w = 0;
+
+ vs_consts->src_scale.x = srcw / (float)surface->texture->width[0];
+ vs_consts->src_scale.y = srch / (float)surface->texture->height[0];
+ vs_consts->src_scale.z = 1;
+ vs_consts->src_scale.w = 1;
+ vs_consts->src_trans.x = srcx / (float)surface->texture->width[0];
+ vs_consts->src_trans.y = srcy / (float)surface->texture->height[0];
+ vs_consts->src_trans.z = 0;
+ vs_consts->src_trans.w = 0;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, basic_csc->vs_const_buf.buffer);
+
+ pipe->set_sampler_textures(pipe, 1, &surface->texture);
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+
+ return 0;
+}
+
+static int vlEnd
+(
+ struct vlCSC *csc
+)
+{
+ assert(csc);
+
+ return 0;
+}
+
+static struct pipe_surface* vlGetFrameBuffer
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+
+ return basic_csc->framebuffer.cbufs[0];
+}
+
+static int vlDestroy
+(
+ struct vlCSC *csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(csc);
+
+ basic_csc = (struct vlBasicCSC*)csc;
+ pipe = basic_csc->pipe;
+
+ if (basic_csc->framebuffer.cbufs[0])
+ pipe->winsys->surface_release
+ (
+ pipe->winsys,
+ &basic_csc->framebuffer.cbufs[0]
+ );
+
+ pipe->delete_sampler_state(pipe, basic_csc->sampler);
+ pipe->delete_vs_state(pipe, basic_csc->vertex_shader);
+ pipe->delete_fs_state(pipe, basic_csc->fragment_shader);
+
+ for (i = 0; i < 2; ++i)
+ pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->vertex_bufs[i].buffer);
+
+ pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->vs_const_buf.buffer);
+ pipe->winsys->buffer_destroy(pipe->winsys, basic_csc->fs_const_buf.buffer);
+
+ free(basic_csc);
+
+ return 0;
+}
+
+/*
+ * Represents 2 triangles in a strip in normalized coords.
+ * Used to render the surface onto the frame buffer.
+ */
+static const struct vlVertex2f surface_verts[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.
+ * TODO: Duplicate these in the shader, no need to create a buffer.
+ */
+static const struct vlVertex2f *surface_texcoords = surface_verts;
+
+/*
+ * Identity color conversion constants, for debugging
+ */
+static const struct vlFragmentShaderConsts 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]
+ */
+static const struct vlFragmentShaderConsts bt_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]
+ */
+static const struct vlFragmentShaderConsts bt_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]
+ */
+static const struct vlFragmentShaderConsts bt_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 vlFragmentShaderConsts bt_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
+ }
+};
+
+static int vlCreateVertexShader
+(
+ struct vlBasicCSC *csc
+)
+{
+ 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 = csc->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 vertex pos rect to destination size
+ * decl c1 ; Translation vector to move vertex pos rect into position
+ * decl c2 ; Scaling vector to scale texcoord rect to source size
+ * decl c3 ; Translation vector to move texcoord rect 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 ; 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);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * madd o0, i0, c0, c1 ; Scale and translate unit output rect to destination size and pos
+ * madd o1, i1, c2, c3 ; Scale and translate unit texcoord rect to source size and pos
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst4(TGSI_OPCODE_MADD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 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;
+ csc->vertex_shader = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShader
+(
+ struct vlBasicCSC *csc
+)
+{
+ 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 = csc->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 t0 */
+ decl = vl_decl_temps(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
+ */
+ for (i = 0; i < 3; ++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;
+ csc->fragment_shader = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateDataBufs
+(
+ struct vlBasicCSC *csc
+)
+{
+ struct pipe_context *pipe;
+
+ assert(csc);
+
+ pipe = csc->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
+ */
+ csc->vertex_bufs[0].pitch = sizeof(struct vlVertex2f);
+ csc->vertex_bufs[0].max_index = 3;
+ csc->vertex_bufs[0].buffer_offset = 0;
+ csc->vertex_bufs[0].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, csc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ surface_verts,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, csc->vertex_bufs[0].buffer);
+
+ csc->vertex_elems[0].src_offset = 0;
+ csc->vertex_elems[0].vertex_buffer_index = 0;
+ csc->vertex_elems[0].nr_components = 2;
+ csc->vertex_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
+ */
+ csc->vertex_bufs[1].pitch = sizeof(struct vlVertex2f);
+ csc->vertex_bufs[1].max_index = 3;
+ csc->vertex_bufs[1].buffer_offset = 0;
+ csc->vertex_bufs[1].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, csc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ surface_texcoords,
+ sizeof(struct vlVertex2f) * 4
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, csc->vertex_bufs[1].buffer);
+
+ csc->vertex_elems[1].src_offset = 0;
+ csc->vertex_elems[1].vertex_buffer_index = 1;
+ csc->vertex_elems[1].nr_components = 2;
+ csc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /*
+ * Create our vertex shader's constant buffer
+ * Const buffer contains scaling and translation vectors
+ */
+ csc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
+ csc->vs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ csc->vs_const_buf.size
+ );
+
+ /*
+ * Create our fragment shader's constant buffer
+ * Const buffer contains the color conversion matrix and bias vectors
+ */
+ csc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
+ csc->fs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ 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, csc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &bt_601,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, csc->fs_const_buf.buffer);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlBasicCSC *csc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+
+ assert(csc);
+
+ pipe = csc->pipe;
+
+ /* Delay creating the FB until vlPutSurface() so we know window size */
+ csc->framebuffer.num_cbufs = 1;
+ csc->framebuffer.cbufs[0] = NULL;
+ 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 = ;*/
+ csc->sampler = pipe->create_sampler_state(pipe, &sampler);
+
+ vlCreateVertexShader(csc);
+ vlCreateFragmentShader(csc);
+ vlCreateDataBufs(csc);
+
+ return 0;
+}
+
+int vlCreateBasicCSC
+(
+ struct pipe_context *pipe,
+ struct vlCSC **csc
+)
+{
+ struct vlBasicCSC *basic_csc;
+
+ assert(pipe);
+ assert(csc);
+
+ basic_csc = calloc(1, sizeof(struct vlBasicCSC));
+
+ if (!basic_csc)
+ return 1;
+
+ basic_csc->base.vlResizeFrameBuffer = &vlResizeFrameBuffer;
+ basic_csc->base.vlBegin = &vlBegin;
+ basic_csc->base.vlPutPicture = &vlPutPictureCSC;
+ basic_csc->base.vlEnd = &vlEnd;
+ basic_csc->base.vlGetFrameBuffer = &vlGetFrameBuffer;
+ basic_csc->base.vlDestroy = &vlDestroy;
+ basic_csc->pipe = pipe;
+
+ vlInit(basic_csc);
+
+ *csc = &basic_csc->base;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.h b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h
new file mode 100644
index 0000000000..2e17f1d814
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h
@@ -0,0 +1,13 @@
+#ifndef vl_basic_csc_h
+#define vl_basic_csc_h
+
+struct pipe_context;
+struct vlCSC;
+
+int vlCreateBasicCSC
+(
+ struct pipe_context *pipe,
+ struct vlCSC **csc
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c
new file mode 100644
index 0000000000..fe107e406d
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_context.c
@@ -0,0 +1,210 @@
+#define VL_INTERNAL
+#include "vl_context.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_state.h>
+#include "vl_render.h"
+#include "vl_r16snorm_mc.h"
+#include "vl_r16snorm_mc_buf.h"
+#include "vl_csc.h"
+#include "vl_basic_csc.h"
+
+static int vlInitCommon(struct vlContext *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->raster = pipe->create_rasterizer_state(pipe, &rast);
+ pipe->bind_rasterizer_state(pipe, context->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->blend = pipe->create_blend_state(pipe, &blend);
+ pipe->bind_blend_state(pipe, context->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->dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa);
+ pipe->bind_depth_stencil_alpha_state(pipe, context->dsa);
+
+ return 0;
+}
+
+int vlCreateContext
+(
+ struct vlScreen *screen,
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ enum vlProfile profile,
+ enum vlEntryPoint entry_point,
+ struct vlContext **context
+)
+{
+ struct vlContext *ctx;
+
+ assert(screen);
+ assert(context);
+ assert(pipe);
+
+ ctx = calloc(1, sizeof(struct vlContext));
+
+ if (!ctx)
+ return 1;
+
+ ctx->screen = screen;
+ ctx->pipe = pipe;
+ ctx->picture_width = picture_width;
+ ctx->picture_height = picture_height;
+ ctx->picture_format = picture_format;
+ ctx->profile = profile;
+ ctx->entry_point = entry_point;
+
+ vlInitCommon(ctx);
+
+ /*vlCreateR16SNormMC(pipe, picture_width, picture_height, picture_format, &ctx->render);*/
+ vlCreateR16SNormBufferedMC(pipe, picture_width, picture_height, picture_format, &ctx->render);
+ vlCreateBasicCSC(pipe, &ctx->csc);
+
+ *context = ctx;
+
+ return 0;
+}
+
+int vlDestroyContext
+(
+ struct vlContext *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);
+
+ context->render->vlDestroy(context->render);
+ context->csc->vlDestroy(context->csc);
+
+ context->pipe->delete_blend_state(context->pipe, context->blend);
+ context->pipe->delete_rasterizer_state(context->pipe, context->raster);
+ context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->dsa);
+
+ free(context);
+
+ return 0;
+}
+
+struct vlScreen* vlContextGetScreen
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->screen;
+}
+
+struct pipe_context* vlGetPipeContext
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->pipe;
+}
+
+unsigned int vlGetPictureWidth
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_width;
+}
+
+unsigned int vlGetPictureHeight
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_height;
+}
+
+enum vlFormat vlGetPictureFormat
+(
+ struct vlContext *context
+)
+{
+ assert(context);
+
+ return context->picture_format;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h
new file mode 100644
index 0000000000..3d14634c44
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_context.h
@@ -0,0 +1,73 @@
+#ifndef vl_context_h
+#define vl_context_h
+
+#include "vl_types.h"
+
+struct pipe_context;
+
+#ifdef VL_INTERNAL
+struct vlRender;
+struct vlCSC;
+
+struct vlContext
+{
+ struct vlScreen *screen;
+ struct pipe_context *pipe;
+ unsigned int picture_width;
+ unsigned int picture_height;
+ enum vlFormat picture_format;
+ enum vlProfile profile;
+ enum vlEntryPoint entry_point;
+
+ void *raster;
+ void *dsa;
+ void *blend;
+
+ struct vlRender *render;
+ struct vlCSC *csc;
+};
+#endif
+
+int vlCreateContext
+(
+ struct vlScreen *screen,
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ enum vlProfile profile,
+ enum vlEntryPoint entry_point,
+ struct vlContext **context
+);
+
+int vlDestroyContext
+(
+ struct vlContext *context
+);
+
+struct vlScreen* vlContextGetScreen
+(
+ struct vlContext *context
+);
+
+struct pipe_context* vlGetPipeContext
+(
+ struct vlContext *context
+);
+
+unsigned int vlGetPictureWidth
+(
+ struct vlContext *context
+);
+
+unsigned int vlGetPictureHeight
+(
+ struct vlContext *context
+);
+
+enum vlFormat vlGetPictureFormat
+(
+ struct vlContext *context
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_csc.h b/src/gallium/state_trackers/g3dvl/vl_csc.h
new file mode 100644
index 0000000000..36417a2792
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_csc.h
@@ -0,0 +1,53 @@
+#ifndef vl_csc_h
+#define vl_csc_h
+
+#include "vl_types.h"
+
+struct pipe_surface;
+
+struct vlCSC
+{
+ int (*vlResizeFrameBuffer)
+ (
+ struct vlCSC *csc,
+ unsigned int width,
+ unsigned int height
+ );
+
+ int (*vlBegin)
+ (
+ struct vlCSC *csc
+ );
+
+ int (*vlPutPicture)
+ (
+ struct vlCSC *csc,
+ struct vlSurface *surface,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ enum vlPictureType picture_type
+ );
+
+ int (*vlEnd)
+ (
+ struct vlCSC *csc
+ );
+
+ struct pipe_surface* (*vlGetFrameBuffer)
+ (
+ struct vlCSC *csc
+ );
+
+ int (*vlDestroy)
+ (
+ struct vlCSC *csc
+ );
+};
+
+#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
index 0000000000..d612d02502
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_defs.h
@@ -0,0 +1,11 @@
+#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_display.c b/src/gallium/state_trackers/g3dvl/vl_display.c
new file mode 100644
index 0000000000..af80faa7f5
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_display.c
@@ -0,0 +1,48 @@
+#define VL_INTERNAL
+#include "vl_display.h"
+#include <assert.h>
+#include <stdlib.h>
+
+int vlCreateDisplay
+(
+ vlNativeDisplay native_display,
+ struct vlDisplay **display
+)
+{
+ struct vlDisplay *dpy;
+
+ assert(native_display);
+ assert(display);
+
+ dpy = calloc(1, sizeof(struct vlDisplay));
+
+ if (!dpy)
+ return 1;
+
+ dpy->native = native_display;
+ *display = dpy;
+
+ return 0;
+}
+
+int vlDestroyDisplay
+(
+ struct vlDisplay *display
+)
+{
+ assert(display);
+
+ free(display);
+
+ return 0;
+}
+
+vlNativeDisplay vlGetNativeDisplay
+(
+ struct vlDisplay *display
+)
+{
+ assert(display);
+
+ return display->native;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_display.h b/src/gallium/state_trackers/g3dvl/vl_display.h
new file mode 100644
index 0000000000..e11fd40799
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_display.h
@@ -0,0 +1,29 @@
+#ifndef vl_display_h
+#define vl_display_h
+
+#include "vl_types.h"
+
+#ifdef VL_INTERNAL
+struct vlDisplay
+{
+ vlNativeDisplay native;
+};
+#endif
+
+int vlCreateDisplay
+(
+ vlNativeDisplay native_display,
+ struct vlDisplay **display
+);
+
+int vlDestroyDisplay
+(
+ struct vlDisplay *display
+);
+
+vlNativeDisplay vlGetNativeDisplay
+(
+ struct vlDisplay *display
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.c
new file mode 100644
index 0000000000..3272220ef8
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.c
@@ -0,0 +1,2344 @@
+#define VL_INTERNAL
+#include "vl_r16snorm_mc.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <pipe/p_context.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include "vl_render.h"
+#include "vl_shader_build.h"
+#include "vl_surface.h"
+#include "vl_util.h"
+#include "vl_types.h"
+#include "vl_defs.h"
+
+#define NUM_BUFS 4 /* Number of rotating buffers to use */
+
+struct vlVertexShaderConsts
+{
+ /*struct vlVertex4f scale;
+ struct vlVertex4f denorm;*/
+ struct vlVertex4f scale;
+ struct vlVertex4f mb_pos_trans;
+ struct vlVertex4f denorm;
+ struct
+ {
+ struct vlVertex4f top_field;
+ struct vlVertex4f bottom_field;
+ } mb_tc_trans[2];
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f multiplier;
+ struct vlVertex4f div;
+};
+
+struct vlR16SnormMC
+{
+ struct vlRender base;
+
+ unsigned int video_width, video_height;
+ enum vlFormat video_format;
+ unsigned int cur_buf;
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state render_target;
+ struct pipe_sampler_state *samplers[5];
+ struct pipe_texture *textures[NUM_BUFS][5];
+ void *i_vs, *p_vs[2], *b_vs[2];
+ void *i_fs, *p_fs[2], *b_fs[2];
+ struct pipe_vertex_buffer vertex_bufs[3];
+ struct pipe_vertex_element vertex_elems[3];
+ struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+};
+
+static int vlBegin
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormMC *mc;
+ struct pipe_context *pipe;
+
+ assert(render);
+
+ mc = (struct vlR16SnormMC*)render;
+ pipe = mc->pipe;
+
+ /* Frame buffer set in vlRender*Macroblock() */
+ /* Shaders, samplers, textures set in vlRender*Macroblock() */
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs);
+ pipe->set_vertex_elements(pipe, 3, mc->vertex_elems);
+ pipe->set_viewport_state(pipe, &mc->viewport);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf);
+
+ return 0;
+}
+
+/*static int vlGrabMacroBlock
+(
+ struct vlR16SnormMC *mc,
+ struct vlMpeg2MacroBlock *macroblock
+)
+{
+ assert(mc);
+ assert(macroblock);
+
+
+
+ return 0;
+}*/
+
+/*#define DO_IDCT*/
+
+#ifdef DO_IDCT
+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;
+}
+#endif
+
+static int vlGrabFrameCodedBlock(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 vlGrabFieldCodedBlock(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 vlGrabNoBlock(short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memset
+ (
+ dst + y * dst_pitch,
+ 0,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+enum vlSampleType
+{
+ vlSampleTypeFull,
+ vlSampleTypeDiff
+};
+
+static int vlGrabBlocks
+(
+ struct vlR16SnormMC *mc,
+ unsigned int coded_block_pattern,
+ enum vlDCTType dct_type,
+ enum vlSampleType sample_type,
+ short *blocks
+)
+{
+ struct pipe_surface *tex_surface;
+ short *texels;
+ unsigned int tex_pitch;
+ unsigned int tb, sb = 0;
+
+ assert(mc);
+ assert(blocks);
+
+ tex_surface = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUFS][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)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+#ifdef DO_IDCT
+ vlTransformBlock(cur_block, cur_block, sample_type == vlSampleTypeFull ? 128 : 0);
+#endif
+
+ if (dct_type == vlDCTTypeFrameCoded)
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels + tb * tex_pitch * VL_BLOCK_HEIGHT,
+ tex_pitch
+ );
+ else
+ vlGrabFieldCodedBlock
+ (
+ cur_block,
+ 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 = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUFS][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)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+#ifdef DO_IDCT
+ vlTransformBlock(cur_block, cur_block, sample_type == vlSampleTypeFull ? 128 : 0);
+#endif
+
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels,
+ tex_pitch
+ );
+
+ ++sb;
+ }
+ else
+ vlGrabNoBlock(texels, tex_pitch);
+
+ pipe_surface_unmap(tex_surface);
+ }
+
+ return 0;
+}
+
+static int vlRenderIMacroBlock
+(
+ struct vlR16SnormMC *mc,
+ enum vlPictureType picture_type,
+ enum vlFieldOrder field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ unsigned int coded_block_pattern,
+ enum vlDCTType dct_type,
+ short *blocks,
+ struct vlSurface *surface
+)
+{
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+
+ assert(blocks);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ if (picture_type != vlPictureTypeFrame)
+ return 0;
+
+ vlGrabBlocks(mc, coded_block_pattern, dct_type, vlSampleTypeFull, blocks);
+
+ pipe = mc->pipe;
+
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->texture->width[0];
+ vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->texture->height[0];
+ vs_consts->scale.z = 1.0f;
+ vs_consts->scale.w = 1.0f;
+ vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->texture->width[0];
+ vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->texture->height[0];
+ vs_consts->mb_pos_trans.z = 0.0f;
+ vs_consts->mb_pos_trans.w = 0.0f;
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
+
+ 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, &mc->render_target);
+ pipe->set_sampler_textures(pipe, 3, mc->textures[mc->cur_buf % NUM_BUFS]);
+ pipe->bind_sampler_states(pipe, 3, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->i_vs);
+ pipe->bind_fs_state(pipe, mc->i_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ mc->cur_buf++;
+
+ return 0;
+}
+
+static int vlRenderPMacroBlock
+(
+ struct vlR16SnormMC *mc,
+ enum vlPictureType picture_type,
+ enum vlFieldOrder field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ enum vlMotionType mc_type,
+ short top_x,
+ short top_y,
+ short bottom_x,
+ short bottom_y,
+ unsigned int coded_block_pattern,
+ enum vlDCTType dct_type,
+ short *blocks,
+ struct vlSurface *ref_surface,
+ struct vlSurface *surface
+)
+{
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+
+ assert(motion_vectors);
+ assert(blocks);
+ assert(ref_surface);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ if (picture_type != vlPictureTypeFrame)
+ return 0;
+ /* TODO: Implement other MC types */
+ if (mc_type != vlMotionTypeFrame && mc_type != vlMotionTypeField)
+ return 0;
+
+ vlGrabBlocks(mc, coded_block_pattern, dct_type, vlSampleTypeDiff, blocks);
+
+ pipe = mc->pipe;
+
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->texture->width[0];
+ vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->texture->height[0];
+ vs_consts->scale.z = 1.0f;
+ vs_consts->scale.w = 1.0f;
+ vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->texture->width[0];
+ vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->texture->height[0];
+ 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 + top_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + top_y * 0.5f) / (float)surface->texture->height[0];
+ 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 == vlMotionTypeField)
+ {
+ vs_consts->denorm.x = (float)surface->texture->width[0];
+ vs_consts->denorm.y = (float)surface->texture->height[0];
+
+ vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + bottom_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + bottom_y * 0.5f) / (float)surface->texture->height[0];
+ 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, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+ }
+ else
+ {
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+ }
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
+
+ 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, &mc->render_target);
+
+ mc->textures[mc->cur_buf % NUM_BUFS][3] = ref_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUFS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ mc->cur_buf++;
+
+ return 0;
+}
+
+static int vlRenderBMacroBlock
+(
+ struct vlR16SnormMC *mc,
+ enum vlPictureType picture_type,
+ enum vlFieldOrder field_order,
+ unsigned int mbx,
+ unsigned int mby,
+ enum vlMotionType mc_type,
+ short top_past_x,
+ short top_past_y,
+ short bottom_past_x,
+ short bottom_past_y,
+ short top_future_x,
+ short top_future_y,
+ short bottom_future_x,
+ short bottom_future_y,
+ unsigned int coded_block_pattern,
+ enum vlDCTType dct_type,
+ short *blocks,
+ struct vlSurface *past_surface,
+ struct vlSurface *future_surface,
+ struct vlSurface *surface
+)
+{
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+
+ assert(motion_vectors);
+ assert(blocks);
+ assert(ref_surface);
+ assert(surface);
+
+ /* TODO: Implement interlaced rendering */
+ if (picture_type != vlPictureTypeFrame)
+ return 0;
+ /* TODO: Implement other MC types */
+ if (mc_type != vlMotionTypeFrame && mc_type != vlMotionTypeField)
+ return 0;
+
+ vlGrabBlocks(mc, coded_block_pattern, dct_type, vlSampleTypeDiff, blocks);
+
+ pipe = mc->pipe;
+
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->scale.x = VL_MACROBLOCK_WIDTH / (float)surface->texture->width[0];
+ vs_consts->scale.y = VL_MACROBLOCK_HEIGHT / (float)surface->texture->height[0];
+ vs_consts->scale.z = 1.0f;
+ vs_consts->scale.w = 1.0f;
+ vs_consts->mb_pos_trans.x = (mbx * VL_MACROBLOCK_WIDTH) / (float)surface->texture->width[0];
+ vs_consts->mb_pos_trans.y = (mby * VL_MACROBLOCK_HEIGHT) / (float)surface->texture->height[0];
+ 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 + top_past_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[0].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + top_past_y * 0.5f) / (float)surface->texture->height[0];
+ 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 + top_future_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[1].top_field.y = (mby * VL_MACROBLOCK_HEIGHT + top_future_y * 0.5f) / (float)surface->texture->height[0];
+ 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 == vlMotionTypeField)
+ {
+ vs_consts->denorm.x = (float)surface->texture->width[0];
+ vs_consts->denorm.y = (float)surface->texture->height[0];
+
+ vs_consts->mb_tc_trans[0].bottom_field.x = (mbx * VL_MACROBLOCK_WIDTH + bottom_past_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[0].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + bottom_past_y * 0.5f) / (float)surface->texture->height[0];
+ 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 + bottom_future_x * 0.5f) / (float)surface->texture->width[0];
+ vs_consts->mb_tc_trans[1].bottom_field.y = (mby * VL_MACROBLOCK_HEIGHT + bottom_future_y * 0.5f) / (float)surface->texture->height[0];
+ 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, mc->b_vs[1]);
+ pipe->bind_fs_state(pipe, mc->b_fs[1]);
+ }
+ else
+ {
+ pipe->bind_vs_state(pipe, mc->b_vs[0]);
+ pipe->bind_fs_state(pipe, mc->b_fs[0]);
+ }
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
+
+ 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, &mc->render_target);
+
+ mc->textures[mc->cur_buf % NUM_BUFS][3] = past_surface->texture;
+ mc->textures[mc->cur_buf % NUM_BUFS][4] = future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUFS]);
+ pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, 0, 24);
+
+ mc->cur_buf++;
+
+ return 0;
+}
+
+static int vlRenderMacroBlocksMpeg2R16Snorm
+(
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ struct vlR16SnormMC *mc;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormMC*)render;
+
+ /*for (i = 0; i < batch->num_macroblocks; ++i)
+ vlGrabMacroBlock(batch->macroblocks[i]);*/
+
+ for (i = 0; i < batch->num_macroblocks; ++i)
+ {
+ switch (batch->macroblocks[i].mb_type)
+ {
+ case vlMacroBlockTypeIntra:
+ {
+ vlRenderIMacroBlock
+ (
+ mc,
+ batch->picture_type,
+ batch->field_order,
+ batch->macroblocks[i].mbx,
+ batch->macroblocks[i].mby,
+ batch->macroblocks[i].cbp,
+ batch->macroblocks[i].dct_type,
+ batch->macroblocks[i].blocks,
+ surface
+ );
+ break;
+ }
+ case vlMacroBlockTypeFwdPredicted:
+ {
+ vlRenderPMacroBlock
+ (
+ mc,
+ batch->picture_type,
+ batch->field_order,
+ batch->macroblocks[i].mbx,
+ batch->macroblocks[i].mby,
+ batch->macroblocks[i].mo_type,
+ batch->macroblocks[i].PMV[0][0][0],
+ batch->macroblocks[i].PMV[0][0][1],
+ batch->macroblocks[i].PMV[1][0][0],
+ batch->macroblocks[i].PMV[1][0][1],
+ batch->macroblocks[i].cbp,
+ batch->macroblocks[i].dct_type,
+ batch->macroblocks[i].blocks,
+ batch->past_surface,
+ surface
+ );
+ break;
+ }
+ case vlMacroBlockTypeBkwdPredicted:
+ {
+ vlRenderPMacroBlock
+ (
+ mc,
+ batch->picture_type,
+ batch->field_order,
+ batch->macroblocks[i].mbx,
+ batch->macroblocks[i].mby,
+ batch->macroblocks[i].mo_type,
+ batch->macroblocks[i].PMV[0][1][0],
+ batch->macroblocks[i].PMV[0][1][1],
+ batch->macroblocks[i].PMV[1][1][0],
+ batch->macroblocks[i].PMV[1][1][1],
+ batch->macroblocks[i].cbp,
+ batch->macroblocks[i].dct_type,
+ batch->macroblocks[i].blocks,
+ batch->future_surface,
+ surface
+ );
+ break;
+ }
+ case vlMacroBlockTypeBiPredicted:
+ {
+ vlRenderBMacroBlock
+ (
+ mc,
+ batch->picture_type,
+ batch->field_order,
+ batch->macroblocks[i].mbx,
+ batch->macroblocks[i].mby,
+ batch->macroblocks[i].mo_type,
+ batch->macroblocks[i].PMV[0][0][0],
+ batch->macroblocks[i].PMV[0][0][1],
+ batch->macroblocks[i].PMV[1][0][0],
+ batch->macroblocks[i].PMV[1][0][1],
+ batch->macroblocks[i].PMV[0][1][0],
+ batch->macroblocks[i].PMV[0][1][1],
+ batch->macroblocks[i].PMV[1][1][0],
+ batch->macroblocks[i].PMV[1][1][1],
+ batch->macroblocks[i].cbp,
+ batch->macroblocks[i].dct_type,
+ batch->macroblocks[i].blocks,
+ batch->past_surface,
+ batch->future_surface,
+ surface
+ );
+ break;
+ }
+ default:
+ assert(0);
+ }
+ }
+
+ return 0;
+}
+
+static int vlEnd
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static int vlFlush
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static int vlDestroy
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormMC *mc;
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormMC*)render;
+ pipe = mc->pipe;
+
+ for (i = 0; i < 5; ++i)
+ pipe->delete_sampler_state(pipe, mc->samplers[i]);
+
+ for (i = 0; i < 3; ++i)
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs[i].buffer);
+
+ /* Textures 3 & 4 are not created directly, no need to release them here */
+ for (i = 0; i < NUM_BUFS; ++i)
+ {
+ pipe_texture_release(&mc->textures[i][0]);
+ pipe_texture_release(&mc->textures[i][1]);
+ pipe_texture_release(&mc->textures[i][2]);
+ }
+
+ pipe->delete_vs_state(pipe, mc->i_vs);
+ pipe->delete_fs_state(pipe, mc->i_fs);
+
+ for (i = 0; i < 2; ++i)
+ {
+ pipe->delete_vs_state(pipe, mc->p_vs[i]);
+ pipe->delete_fs_state(pipe, mc->p_fs[i]);
+ pipe->delete_vs_state(pipe, mc->b_vs[i]);
+ pipe->delete_fs_state(pipe, mc->b_fs[i]);
+ }
+
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vs_const_buf.buffer);
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->fs_const_buf.buffer);
+
+ free(mc);
+
+ return 0;
+}
+
+/*
+ * 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.
+ */
+static const struct vlVertex2f macroblock_verts[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.
+ */
+static const struct vlVertex2f macroblock_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.
+ */
+static const struct vlVertex2f *macroblock_chroma_420_texcoords = macroblock_verts;
+
+/*
+ * 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.
+ */
+static const struct vlVertex2f *macroblock_chroma_422_texcoords = macroblock_verts;
+
+/*
+ * Represents texcoords for the above for rendering 4 chroma blocks.
+ * Same case as 4 luma blocks.
+ */
+static const struct vlVertex2f *macroblock_chroma_444_texcoords = macroblock_luma_texcoords;
+
+/*
+ * 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).
+ */
+static const struct vlFragmentShaderConsts fs_consts =
+{
+ {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
+ {0.5f, 2.0f, 0.0f, 0.0f}
+};
+
+static int vlCreateVertexShaderIMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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);
+ }
+
+ /* decl t0 */
+ decl = vl_decl_temps(0, 0);
+ 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;
+ mc->i_vs = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderIMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ 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 t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i1, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ }
+
+ /* mul o0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ 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;
+ mc->i_fs = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFramePMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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);
+ }
+
+ /* decl t0 */
+ decl = vl_decl_temps(0, 0);
+ 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;
+ mc->p_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldPMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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;
+ mc->p_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFramePMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ 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 t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i1, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ 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;
+ mc->p_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldPMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t4 */
+ decl = vl_decl_temps(0, 4);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i1, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ 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, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 4, TGSI_FILE_CONSTANT, 1);
+ 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, c1.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, 1);
+ 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, c1.y ; Multiply by 2 */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ 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;
+ mc->p_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFrameBMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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);
+ }
+
+ /* decl t0 */
+ decl = vl_decl_temps(0, 0);
+ 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;
+ mc->b_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldBMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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;
+ mc->b_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFrameBMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t2 */
+ decl = vl_decl_temps(0, 2);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i1, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ 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, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, 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;
+ mc->b_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldBMB
+(
+ struct vlR16SnormMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t5 */
+ decl = vl_decl_temps(0, 5);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i1, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i > 0 ? 1 : 0, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* XXX: Pos values off by 0.5? */
+ /* sub t4, i6.y, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 6, TGSI_FILE_CONSTANT, 1);
+ 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, c1.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, 1);
+ 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, c1.y ; Multiply by 2 */
+ inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ 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, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, 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;
+ mc->b_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateDataBufs
+(
+ struct vlR16SnormMC *mc
+)
+{
+ struct pipe_context *pipe;
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* Create our vertex buffer and vertex buffer element */
+ mc->vertex_bufs[0].pitch = sizeof(struct vlVertex2f);
+ mc->vertex_bufs[0].max_index = 23;
+ mc->vertex_bufs[0].buffer_offset = 0;
+ mc->vertex_bufs[0].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 24
+ );
+
+ mc->vertex_elems[0].src_offset = 0;
+ mc->vertex_elems[0].vertex_buffer_index = 0;
+ mc->vertex_elems[0].nr_components = 2;
+ mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Create our texcoord buffers and texcoord buffer elements */
+ for (i = 1; i < 3; ++i)
+ {
+ mc->vertex_bufs[i].pitch = sizeof(struct vlVertex2f);
+ mc->vertex_bufs[i].max_index = 23;
+ mc->vertex_bufs[i].buffer_offset = 0;
+ mc->vertex_bufs[i].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 24
+ );
+
+ mc->vertex_elems[i].src_offset = 0;
+ mc->vertex_elems[i].vertex_buffer_index = i;
+ mc->vertex_elems[i].nr_components = 2;
+ mc->vertex_elems[i].src_format = PIPE_FORMAT_R32G32_FLOAT;
+ }
+
+ /* Fill buffers */
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ macroblock_verts,
+ sizeof(struct vlVertex2f) * 24
+ );
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ macroblock_luma_texcoords,
+ sizeof(struct vlVertex2f) * 24
+ );
+ /* TODO: Accomodate 422, 444 */
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->vertex_bufs[2].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ macroblock_chroma_420_texcoords,
+ sizeof(struct vlVertex2f) * 24
+ );
+
+ for (i = 0; i < 3; ++i)
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vertex_bufs[i].buffer);
+
+ /* Create our constant buffer */
+ mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
+ mc->vs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->vs_const_buf.size
+ );
+
+ mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
+ mc->fs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->fs_const_buf.size
+ );
+
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &fs_consts,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlR16SnormMC *mc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+ struct pipe_texture template;
+ unsigned int filters[5];
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* For MC we render to textures, which are rounded up to nearest POT */
+ mc->viewport.scale[0] = vlRoundUpPOT(mc->video_width);
+ mc->viewport.scale[1] = vlRoundUpPOT(mc->video_height);
+ mc->viewport.scale[2] = 1;
+ mc->viewport.scale[3] = 1;
+ mc->viewport.translate[0] = 0;
+ mc->viewport.translate[1] = 0;
+ mc->viewport.translate[2] = 0;
+ mc->viewport.translate[3] = 0;
+
+ mc->render_target.width = vlRoundUpPOT(mc->video_width);
+ mc->render_target.height = vlRoundUpPOT(mc->video_height);
+ mc->render_target.num_cbufs = 1;
+ /* FB for MC stage is a vlSurface, set in vlSetRenderSurface() */
+ mc->render_target.zsbuf = NULL;
+
+ filters[0] = PIPE_TEX_FILTER_NEAREST;
+ filters[1] = mc->video_format == vlFormatYCbCr444 ? PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
+ filters[2] = mc->video_format == vlFormatYCbCr444 ? 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 = ;*/
+ 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_R16_SNORM;
+ 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);
+
+ for (i = 0; i < NUM_BUFS; ++i)
+ mc->textures[i][0] = pipe->screen->texture_create(pipe->screen, &template);
+
+ if (mc->video_format == vlFormatYCbCr420)
+ template.height[0] = 8;
+ else if (mc->video_format == vlFormatYCbCr422)
+ template.height[0] = 8 * 2;
+ else if (mc->video_format == vlFormatYCbCr444)
+ template.height[0] = 8 * 4;
+ else
+ assert(0);
+
+ for (i = 0; i < NUM_BUFS; ++i)
+ {
+ mc->textures[i][1] = pipe->screen->texture_create(pipe->screen, &template);
+ mc->textures[i][2] = pipe->screen->texture_create(pipe->screen, &template);
+ }
+
+ /* textures[3] & textures[4] are assigned from vlSurfaces for P and B macroblocks at render time */
+
+ vlCreateVertexShaderIMB(mc);
+ vlCreateFragmentShaderIMB(mc);
+ vlCreateVertexShaderFramePMB(mc);
+ vlCreateVertexShaderFieldPMB(mc);
+ vlCreateFragmentShaderFramePMB(mc);
+ vlCreateFragmentShaderFieldPMB(mc);
+ vlCreateVertexShaderFrameBMB(mc);
+ vlCreateVertexShaderFieldBMB(mc);
+ vlCreateFragmentShaderFrameBMB(mc);
+ vlCreateFragmentShaderFieldBMB(mc);
+ vlCreateDataBufs(mc);
+
+ return 0;
+}
+
+int vlCreateR16SNormMC
+(
+ struct pipe_context *pipe,
+ unsigned int video_width,
+ unsigned int video_height,
+ enum vlFormat video_format,
+ struct vlRender **render
+)
+{
+ struct vlR16SnormMC *mc;
+
+ assert(pipe);
+ assert(render);
+
+ mc = calloc(1, sizeof(struct vlR16SnormMC));
+
+ mc->base.vlBegin = &vlBegin;
+ mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16Snorm;
+ mc->base.vlEnd = &vlEnd;
+ mc->base.vlFlush = &vlFlush;
+ mc->base.vlDestroy = &vlDestroy;
+ mc->pipe = pipe;
+ mc->video_width = video_width;
+ mc->video_height = video_height;
+ mc->cur_buf = 0;
+
+ vlInit(mc);
+
+ *render = &mc->base;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.h b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.h
new file mode 100644
index 0000000000..9842926bf7
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc.h
@@ -0,0 +1,18 @@
+#ifndef vl_r16snorm_mc_h
+#define vl_r16snorm_mc_h
+
+#include "vl_types.h"
+
+struct pipe_context;
+struct vlRender;
+
+int vlCreateR16SNormMC
+(
+ struct pipe_context *pipe,
+ unsigned int video_width,
+ unsigned int video_height,
+ enum vlFormat video_format,
+ struct vlRender **render
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
new file mode 100644
index 0000000000..e7a070ef4d
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
@@ -0,0 +1,2321 @@
+#define VL_INTERNAL
+#include "vl_r16snorm_mc_buf.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 <tgsi/tgsi_parse.h>
+#include <tgsi/tgsi_build.h>
+#include <util/u_math.h>
+#include "vl_render.h"
+#include "vl_shader_build.h"
+#include "vl_surface.h"
+#include "vl_util.h"
+#include "vl_types.h"
+#include "vl_defs.h"
+
+/*
+ * TODO: Dynamically determine number of buf sets to use, based on
+ * video size and available mem, since we can easily run out of memory
+ * for high res videos.
+ * Note: Destroying previous frame's buffers and creating new ones
+ * doesn't work, since the buffer are not actually destroyed until their
+ * fence is signalled, and if we render fast enough we will create faster
+ * than we destroy.
+ */
+#define NUM_BUF_SETS 4 /* Number of rotating buffer sets to use */
+
+enum vlMacroBlockTypeEx
+{
+ vlMacroBlockExTypeIntra,
+ vlMacroBlockExTypeFwdPredictedFrame,
+ vlMacroBlockExTypeFwdPredictedField,
+ vlMacroBlockExTypeBkwdPredictedFrame,
+ vlMacroBlockExTypeBkwdPredictedField,
+ vlMacroBlockExTypeBiPredictedFrame,
+ vlMacroBlockExTypeBiPredictedField,
+
+ vlNumMacroBlockExTypes
+};
+
+struct vlVertexShaderConsts
+{
+ struct vlVertex4f denorm;
+};
+
+struct vlFragmentShaderConsts
+{
+ struct vlVertex4f multiplier;
+ struct vlVertex4f div;
+};
+
+struct vlR16SnormBufferedMC
+{
+ struct vlRender base;
+
+ unsigned int picture_width, picture_height;
+ enum vlFormat picture_format;
+
+ unsigned int cur_buf;
+ struct vlSurface *buffered_surface;
+ struct vlSurface *past_surface, *future_surface;
+ struct vlVertex2f surface_tex_inv_size;
+ struct vlVertex2f zero_block[3];
+ unsigned int num_macroblocks;
+ struct vlMpeg2MacroBlock *macroblocks;
+
+ struct pipe_context *pipe;
+ struct pipe_viewport_state viewport;
+ struct pipe_framebuffer_state render_target;
+ struct pipe_sampler_state *samplers[5];
+ struct pipe_texture *textures[NUM_BUF_SETS][5];
+ void *i_vs, *p_vs[2], *b_vs[2];
+ void *i_fs, *p_fs[2], *b_fs[2];
+ struct pipe_vertex_buffer vertex_bufs[NUM_BUF_SETS][3];
+ struct pipe_vertex_element vertex_elems[8];
+ struct pipe_constant_buffer vs_const_buf, fs_const_buf;
+};
+
+static int vlBegin
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static inline int vlGrabFrameCodedBlock(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 inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memcpy
+ (
+ dst + y * dst_pitch * 2,
+ src + y * VL_BLOCK_WIDTH,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch)
+{
+ unsigned int y;
+
+ for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
+ memset
+ (
+ dst + y * dst_pitch,
+ 0,
+ VL_BLOCK_WIDTH * 2
+ );
+
+ return 0;
+}
+
+static inline int vlGrabBlocks
+(
+ struct vlR16SnormBufferedMC *mc,
+ unsigned int mbx,
+ unsigned int mby,
+ enum vlDCTType dct_type,
+ unsigned int coded_block_pattern,
+ short *blocks
+)
+{
+ struct pipe_surface *tex_surface;
+ short *texels;
+ unsigned int tex_pitch;
+ unsigned int x, y, tb = 0, sb = 0;
+ unsigned int mbpx = mbx * VL_MACROBLOCK_WIDTH, mbpy = mby * VL_MACROBLOCK_HEIGHT;
+
+ assert(mc);
+ assert(blocks);
+
+ tex_surface = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][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;
+
+ texels += mbpy * tex_pitch + mbpx;
+
+ for (y = 0; y < 2; ++y)
+ {
+ for (x = 0; x < 2; ++x, ++tb)
+ {
+ if ((coded_block_pattern >> (5 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ if (dct_type == vlDCTTypeFrameCoded)
+ {
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+ else
+ {
+ vlGrabFieldCodedBlock
+ (
+ cur_block,
+ texels + y * tex_pitch + x * VL_BLOCK_WIDTH,
+ tex_pitch
+ );
+ }
+
+ ++sb;
+ }
+ else if (mc->zero_block[0].x < 0.0f)
+ {
+ vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch);
+
+ mc->zero_block[0].x = (mbpx + x * 8) * mc->surface_tex_inv_size.x;
+ mc->zero_block[0].y = (mbpy + y * 8) * mc->surface_tex_inv_size.y;
+ }
+ }
+ }
+
+ pipe_surface_unmap(tex_surface);
+
+ /* TODO: Implement 422, 444 */
+ mbpx >>= 1;
+ mbpy >>= 1;
+
+ for (tb = 0; tb < 2; ++tb)
+ {
+ tex_surface = mc->pipe->screen->get_tex_surface
+ (
+ mc->pipe->screen,
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][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;
+
+ texels += mbpy * tex_pitch + mbpx;
+
+ if ((coded_block_pattern >> (1 - tb)) & 1)
+ {
+ short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
+
+ vlGrabFrameCodedBlock
+ (
+ cur_block,
+ texels,
+ tex_pitch
+ );
+
+ ++sb;
+ }
+ else if (mc->zero_block[tb + 1].x < 0.0f)
+ {
+ vlGrabNoBlock(texels, tex_pitch);
+
+ mc->zero_block[tb + 1].x = (mbpx << 1) * mc->surface_tex_inv_size.x;
+ mc->zero_block[tb + 1].y = (mbpy << 1) * mc->surface_tex_inv_size.y;
+ }
+
+ pipe_surface_unmap(tex_surface);
+ }
+
+ return 0;
+}
+
+static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb)
+{
+ assert(mb);
+
+ switch (mb->mb_type)
+ {
+ case vlMacroBlockTypeIntra:
+ return vlMacroBlockExTypeIntra;
+ case vlMacroBlockTypeFwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeFwdPredictedFrame : vlMacroBlockExTypeFwdPredictedField;
+ case vlMacroBlockTypeBkwdPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBkwdPredictedFrame : vlMacroBlockExTypeBkwdPredictedField;
+ case vlMacroBlockTypeBiPredicted:
+ return mb->mo_type == vlMotionTypeFrame ?
+ vlMacroBlockExTypeBiPredictedFrame : vlMacroBlockExTypeBiPredictedField;
+ default:
+ assert(0);
+ }
+
+ /* Unreachable */
+ return -1;
+}
+
+static inline int vlGrabMacroBlock
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock
+)
+{
+ assert(mc);
+ assert(macroblock);
+
+ mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx;
+ mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby;
+ mc->macroblocks[mc->num_macroblocks].mb_type = macroblock->mb_type;
+ mc->macroblocks[mc->num_macroblocks].mo_type = macroblock->mo_type;
+ mc->macroblocks[mc->num_macroblocks].dct_type = macroblock->dct_type;
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][0] = macroblock->PMV[0][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][0][1] = macroblock->PMV[0][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][0] = macroblock->PMV[0][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[0][1][1] = macroblock->PMV[0][1][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][0] = macroblock->PMV[1][0][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][0][1] = macroblock->PMV[1][0][1];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][0] = macroblock->PMV[1][1][0];
+ mc->macroblocks[mc->num_macroblocks].PMV[1][1][1] = macroblock->PMV[1][1][1];
+ mc->macroblocks[mc->num_macroblocks].cbp = macroblock->cbp;
+ mc->macroblocks[mc->num_macroblocks].blocks = macroblock->blocks;
+
+ vlGrabBlocks
+ (
+ mc,
+ macroblock->mbx,
+ macroblock->mby,
+ macroblock->dct_type,
+ macroblock->cbp,
+ macroblock->blocks
+ );
+
+ mc->num_macroblocks++;
+
+ return 0;
+}
+
+#define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \
+ (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \
+ \
+ if ((cbp) & (lm)) \
+ { \
+ (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \
+ (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \
+ (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \
+ (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \
+ (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \
+ } \
+ \
+ if ((cbp) & (cbm)) \
+ { \
+ (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \
+ (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \
+ (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \
+ (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \
+ (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \
+ } \
+ \
+ if ((cbp) & (crm)) \
+ { \
+ (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \
+ (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \
+ } \
+ else \
+ { \
+ (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \
+ (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \
+ (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \
+ (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \
+ (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \
+ }
+
+static inline int vlGrabMacroBlockVB
+(
+ struct vlR16SnormBufferedMC *mc,
+ struct vlMpeg2MacroBlock *macroblock,
+ unsigned int pos
+)
+{
+ struct vlVertex2f mo_vec[2];
+ unsigned int i;
+
+ assert(mc);
+ assert(macroblock);
+
+ switch (macroblock->mb_type)
+ {
+ case vlMacroBlockTypeBiPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 2 * 24;
+
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer);
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeFwdPredicted:
+ case vlMacroBlockTypeBkwdPredicted:
+ {
+ struct vlVertex2f *vb;
+
+ vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 2 * 24;
+
+ if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted)
+ {
+ mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+ else
+ {
+ mo_vec[0].x = macroblock->PMV[0][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[0].y = macroblock->PMV[0][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+
+ if (macroblock->mo_type == vlMotionTypeField)
+ {
+ mo_vec[1].x = macroblock->PMV[1][0][0] * 0.5f * mc->surface_tex_inv_size.x;
+ mo_vec[1].y = macroblock->PMV[1][0][1] * 0.5f * mc->surface_tex_inv_size.y;
+ }
+ }
+
+ if (macroblock->mo_type == vlMotionTypeFrame)
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 24 * 2; i += 2)
+ {
+ vb[i].x = mo_vec[0].x;
+ vb[i].y = mo_vec[0].y;
+ vb[i + 1].x = mo_vec[1].x;
+ vb[i + 1].y = mo_vec[1].y;
+ }
+ }
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer);
+
+ /* fall-through */
+ }
+ case vlMacroBlockTypeIntra:
+ {
+ const struct vlVertex2f unit =
+ {
+ mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH,
+ mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT
+ };
+ const struct vlVertex2f half =
+ {
+ mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2),
+ mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2)
+ };
+
+ struct vlMacroBlockVertexStream0
+ {
+ struct vlVertex2f pos;
+ struct vlVertex2f luma_tc;
+ struct vlVertex2f cb_tc;
+ struct vlVertex2f cr_tc;
+ } *vb;
+
+ vb = (struct vlMacroBlockVertexStream0*)mc->pipe->winsys->buffer_map
+ (
+ mc->pipe->winsys,
+ mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ ) + pos * 24;
+
+ SET_BLOCK
+ (
+ vb,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, 0, half.x, half.y,
+ 32, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 6,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, 0, half.x, half.y,
+ 16, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 12,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, 0, half.y, half.x, half.y,
+ 8, 2, 1, mc->zero_block
+ );
+
+ SET_BLOCK
+ (
+ vb + 18,
+ macroblock->cbp, macroblock->mbx, macroblock->mby,
+ unit.x, unit.y, half.x, half.y, half.x, half.y,
+ 4, 2, 1, mc->zero_block
+ );
+
+ mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer);
+
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ return 0;
+}
+
+static int vlFlush
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ struct vlVertexShaderConsts *vs_consts;
+ unsigned int num_macroblocks[vlNumMacroBlockExTypes] = {0};
+ unsigned int offset[vlNumMacroBlockExTypes];
+ unsigned int vb_start = 0;
+ unsigned int mbw;
+ unsigned int mbh;
+ unsigned int num_mb_per_frame;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (!mc->buffered_surface)
+ return 0;
+
+ mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
+ mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
+ num_mb_per_frame = mbw * mbh;
+
+ if (mc->num_macroblocks < num_mb_per_frame)
+ return 0;
+
+ pipe = mc->pipe;
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ num_macroblocks[mb_type_ex]++;
+ }
+
+ offset[0] = 0;
+
+ for (i = 1; i < vlNumMacroBlockExTypes; ++i)
+ offset[i] = offset[i - 1] + num_macroblocks[i - 1];
+
+ for (i = 0; i < mc->num_macroblocks; ++i)
+ {
+ enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]);
+
+ vlGrabMacroBlockVB(mc, &mc->macroblocks[i], offset[mb_type_ex]);
+
+ offset[mb_type_ex]++;
+ }
+
+ mc->render_target.cbufs[0] = pipe->screen->get_tex_surface
+ (
+ pipe->screen,
+ mc->buffered_surface->texture,
+ 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
+ );
+
+ pipe->set_framebuffer_state(pipe, &mc->render_target);
+ pipe->set_viewport_state(pipe, &mc->viewport);
+ vs_consts = pipe->winsys->buffer_map
+ (
+ pipe->winsys,
+ mc->vs_const_buf.buffer,
+ PIPE_BUFFER_USAGE_CPU_WRITE
+ );
+
+ vs_consts->denorm.x = mc->buffered_surface->texture->width[0];
+ vs_consts->denorm.y = mc->buffered_surface->texture->height[0];
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->vs_const_buf.buffer);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf);
+ pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf);
+
+ if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 4, mc->vertex_elems);
+ pipe->set_sampler_textures(pipe, 3, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 3, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->i_vs);
+ pipe->bind_fs_state(pipe, mc->i_fs);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[0]);
+ pipe->bind_fs_state(pipe, mc->p_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->p_vs[1]);
+ pipe->bind_fs_state(pipe, mc->p_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->b_vs[0]);
+ pipe->bind_fs_state(pipe, mc->b_fs[0]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24;
+ }
+
+ if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
+ {
+ pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
+ mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
+ pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
+ pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+ pipe->bind_vs_state(pipe, mc->b_vs[1]);
+ pipe->bind_fs_state(pipe, mc->b_fs[1]);
+
+ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24);
+ vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24;
+ }
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence);
+
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+
+ mc->buffered_surface = NULL;
+ mc->num_macroblocks = 0;
+ mc->cur_buf++;
+
+ return 0;
+}
+
+static int vlRenderMacroBlocksMpeg2R16SnormBuffered
+(
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ unsigned int i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+
+ if (mc->buffered_surface)
+ {
+ if (mc->buffered_surface != surface)
+ {
+ vlFlush(&mc->base);
+ mc->buffered_surface = surface;
+ mc->past_surface = batch->past_surface;
+ mc->future_surface = batch->future_surface;
+ mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
+ mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
+ }
+ }
+ else
+ {
+ mc->buffered_surface = surface;
+ mc->past_surface = batch->past_surface;
+ mc->future_surface = batch->future_surface;
+ mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
+ mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
+ }
+
+ for (i = 0; i < batch->num_macroblocks; ++i)
+ vlGrabMacroBlock(mc, &batch->macroblocks[i]);
+
+ return 0;
+}
+
+static int vlEnd
+(
+ struct vlRender *render
+)
+{
+ assert(render);
+
+ return 0;
+}
+
+static int vlDestroy
+(
+ struct vlRender *render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ struct pipe_context *pipe;
+ unsigned int h, i;
+
+ assert(render);
+
+ mc = (struct vlR16SnormBufferedMC*)render;
+ pipe = mc->pipe;
+
+ for (i = 0; i < 5; ++i)
+ pipe->delete_sampler_state(pipe, mc->samplers[i]);
+
+ for (h = 0; h < NUM_BUF_SETS; ++h)
+ for (i = 0; i < 3; ++i)
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs[h][i].buffer);
+
+ /* Textures 3 & 4 are not created directly, no need to release them here */
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ {
+ pipe_texture_release(&mc->textures[i][0]);
+ pipe_texture_release(&mc->textures[i][1]);
+ pipe_texture_release(&mc->textures[i][2]);
+ }
+
+ pipe->delete_vs_state(pipe, mc->i_vs);
+ pipe->delete_fs_state(pipe, mc->i_fs);
+
+ for (i = 0; i < 2; ++i)
+ {
+ pipe->delete_vs_state(pipe, mc->p_vs[i]);
+ pipe->delete_fs_state(pipe, mc->p_fs[i]);
+ pipe->delete_vs_state(pipe, mc->b_vs[i]);
+ pipe->delete_fs_state(pipe, mc->b_fs[i]);
+ }
+
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->vs_const_buf.buffer);
+ pipe->winsys->buffer_destroy(pipe->winsys, mc->fs_const_buf.buffer);
+
+ free(mc->macroblocks);
+ free(mc);
+
+ return 0;
+}
+
+/*
+ * Muliplier renormalizes block samples from 16 bits to 12 bits.
+ * Divider is used when calculating Y % 2 for choosing top or bottom
+ * field for P or B macroblocks.
+ * TODO: Use immediates.
+ */
+static const struct vlFragmentShaderConsts fs_consts =
+{
+ {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
+ {0.5f, 2.0f, 0.0f, 0.0f}
+};
+
+static int vlCreateVertexShaderIMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ */
+ for (i = 0; i < 4; 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 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr 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);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++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;
+ mc->i_vs = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderIMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ */
+ 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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ 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 t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ 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;
+ mc->i_fs = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFramePMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; Ref surface top field texcoords
+ * decl i5 ; Ref surface bottom field texcoords (unused, packed in the same stream)
+ */
+ for (i = 0; i < 6; 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 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; 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);
+ }
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++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 o4, i0, i4 ; Translate vertex pos by motion vec to form ref macroblock texcoords */
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, 4);
+ 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;
+ mc->p_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldPMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; Ref macroblock top field texcoords
+ * decl i5 ; Ref macroblock bottom field texcoords
+ */
+ for (i = 0; i < 6; 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 ; Render target dimensions */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; Ref macroblock top field texcoords
+ * decl o5 ; Ref macroblock bottom field texcoords
+ * decl o6 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 7; 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 input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++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 o4, i0, i4 ; Translate vertex pos by motion vec to form top field macroblock texcoords
+ * add o5, i0, i5 ; Translate vertex pos by motion vec to form bottom field macroblock texcoords
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o6, i0, c0 ; Denorm vertex pos */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 6, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+ 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;
+ mc->p_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFramePMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; Ref macroblock texcoords
+ */
+ 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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ 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 t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* tex2d t1, i3, s3 ; Read texel from ref macroblock */
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 3, 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;
+ mc->p_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldPMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; Ref macroblock top field texcoords
+ * decl i4 ; Ref macroblock bottom field texcoords
+ * decl i5 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 6; ++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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t4 */
+ decl = vl_decl_temps(0, 4);
+ 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t1, i3, s3 ; Read texel from ref macroblock top field
+ * tex2d t2, i4, 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 + 3, 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, i5.y, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 5, TGSI_FILE_CONSTANT, 1);
+ 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, c1.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, 1);
+ 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, c1.y ; Multiply by 2 */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ 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;
+ mc->p_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFrameBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; First ref macroblock top field texcoords
+ * decl i5 ; First ref macroblock bottom field texcoords (unused, packed in the same stream)
+ * decl i6 ; Second ref macroblock top field texcoords
+ * decl i7 ; Second ref macroblock bottom field texcoords (unused, packed in the same stream)
+ */
+ for (i = 0; i < 8; 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 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; First ref macroblock texcoords
+ * decl o5 ; Second ref macroblock texcoords
+ */
+ for (i = 0; i < 6; 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 input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++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 o4, i0, i4 ; Translate vertex pos by motion vec to form first ref macroblock texcoords
+ * add o5, i0, i6 ; Translate vertex pos by motion vec to form second ref macroblock texcoords
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, (i + 2) * 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;
+ mc->b_vs[0] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateVertexShaderFieldBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 Cb texcoords
+ * decl i3 ; Chroma Cr texcoords
+ * decl i4 ; First ref macroblock top field texcoords
+ * decl i5 ; First ref macroblock bottom field texcoords
+ * decl i6 ; Second ref macroblock top field texcoords
+ * decl i7 ; Second ref macroblock bottom field texcoords
+ */
+ for (i = 0; i < 8; 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 ; Render target dimensions */
+ decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * decl o0 ; Vertex pos
+ * decl o1 ; Luma texcoords
+ * decl o2 ; Chroma Cb texcoords
+ * decl o3 ; Chroma Cr texcoords
+ * decl o4 ; First ref macroblock top field texcoords
+ * decl o5 ; First ref macroblock Bottom field texcoords
+ * decl o6 ; Second ref macroblock top field texcoords
+ * decl o7 ; Second ref macroblock Bottom field texcoords
+ * decl o8 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 9; 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);
+ }
+
+ /* decl t0, t1 */
+ decl = vl_decl_temps(0, 1);
+ ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * mov o0, i0 ; Move input vertex pos to output
+ * mov o1, i1 ; Move input luma texcoords to output
+ * mov o2, i2 ; Move input chroma Cb texcoords to output
+ * mov o3, i3 ; Move input chroma Cr texcoords to output
+ */
+ for (i = 0; i < 4; ++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 o4, i0, i4 ; Translate vertex pos by motion vec to form first top field macroblock texcoords
+ * add o5, i0, i5 ; Translate vertex pos by motion vec to form first bottom field macroblock texcoords
+ * add o6, i0, i6 ; Translate vertex pos by motion vec to form second top field macroblock texcoords
+ * add o7, i0, i7 ; Translate vertex pos by motion vec to form second bottom field macroblock texcoords
+ */
+ for (i = 0; i < 4; ++i)
+ {
+ inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul o8, i0, c0 ; Denorm vertex pos */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 8, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0);
+ 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;
+ mc->b_vs[1] = pipe->create_vs_state(pipe, &vs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFrameBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; First ref macroblock texcoords
+ * decl i4 ; Second ref macroblock texcoords
+ */
+ 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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t2 */
+ decl = vl_decl_temps(0, 2);
+ 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 first ref surface texture
+ * decl s4 ; Sampler for second 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /*
+ * tex2d t1, i3, s3 ; Read texel from first ref macroblock
+ * tex2d t2, i4, s4 ; Read texel from second ref macroblock
+ */
+ for (i = 0; i < 2; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, i + 3);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* lerp t1, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, 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;
+ mc->b_fs[0] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateFragmentShaderFieldBMB
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ 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(mc);
+
+ pipe = mc->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 ; Luma texcoords
+ * decl i1 ; Chroma Cb texcoords
+ * decl i2 ; Chroma Cr texcoords
+ * decl i3 ; First ref macroblock top field texcoords
+ * decl i4 ; First ref macroblock bottom field texcoords
+ * decl i5 ; Second ref macroblock top field texcoords
+ * decl i6 ; Second ref macroblock bottom field texcoords
+ * decl i7 ; Denormalized vertex pos
+ */
+ for (i = 0; i < 8; ++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 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
+ * decl c1 ; 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, 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 t0-t5 */
+ decl = vl_decl_temps(0, 5);
+ 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 first ref surface texture
+ * decl s4 ; Sampler for second 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 t1, i0, s0 ; Read texel from luma texture
+ * mov t0.x, t1.x ; Move luma sample into .x component
+ * tex2d t1, i1, s1 ; Read texel from chroma Cb texture
+ * mov t0.y, t1.x ; Move Cb sample into .y component
+ * tex2d t1, i2, s2 ; Read texel from chroma Cr texture
+ * mov t0.z, t1.x ; Move Cr sample into .z component
+ */
+ for (i = 0; i < 3; ++i)
+ {
+ inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
+ 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.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+ }
+
+ /* mul t0, t0, c0 ; Rescale texel to correct range */
+ inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
+ ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+
+ /* XXX: Pos values off by 0.5? */
+ /* sub t4, i7.y, c1.x ; Sub 0.5 from denormalized pos */
+ inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 7, TGSI_FILE_CONSTANT, 1);
+ 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, c1.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, 1);
+ 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, c1.y ; Multiply by 2 */
+ inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1);
+ 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, i3, s3 ; Read texel from past ref macroblock top field
+ * tex2d t2, i4, 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 + 3, 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, i5, s4 ; Read texel from future ref macroblock top field
+ * tex2d t5, i6, 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 + 5, 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, c1.x, t1, t2 ; Blend past and future texels */
+ inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, 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;
+ mc->b_fs[1] = pipe->create_fs_state(pipe, &fs);
+ free(tokens);
+
+ return 0;
+}
+
+static int vlCreateDataBufs
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ const unsigned int mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
+ const unsigned int mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
+ const unsigned int num_mb_per_frame = mbw * mbh;
+
+ struct pipe_context *pipe;
+ unsigned int h, i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* Create our vertex buffers */
+ for (h = 0; h < NUM_BUF_SETS; ++h)
+ {
+ mc->vertex_bufs[h][0].pitch = sizeof(struct vlVertex2f) * 4;
+ mc->vertex_bufs[h][0].max_index = 24 * num_mb_per_frame - 1;
+ mc->vertex_bufs[h][0].buffer_offset = 0;
+ mc->vertex_bufs[h][0].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 4 * 24 * num_mb_per_frame
+ );
+
+ for (i = 1; i < 3; ++i)
+ {
+ mc->vertex_bufs[h][i].pitch = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_bufs[h][i].max_index = 24 * num_mb_per_frame - 1;
+ mc->vertex_bufs[h][i].buffer_offset = 0;
+ mc->vertex_bufs[h][i].buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_VERTEX,
+ sizeof(struct vlVertex2f) * 2 * 24 * num_mb_per_frame
+ );
+ }
+ }
+
+ /* Position element */
+ mc->vertex_elems[0].src_offset = 0;
+ mc->vertex_elems[0].vertex_buffer_index = 0;
+ mc->vertex_elems[0].nr_components = 2;
+ mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Luma, texcoord element */
+ mc->vertex_elems[1].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[1].vertex_buffer_index = 0;
+ mc->vertex_elems[1].nr_components = 2;
+ mc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cr texcoord element */
+ mc->vertex_elems[2].src_offset = sizeof(struct vlVertex2f) * 2;
+ mc->vertex_elems[2].vertex_buffer_index = 0;
+ mc->vertex_elems[2].nr_components = 2;
+ mc->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Chroma Cb texcoord element */
+ mc->vertex_elems[3].src_offset = sizeof(struct vlVertex2f) * 3;
+ mc->vertex_elems[3].vertex_buffer_index = 0;
+ mc->vertex_elems[3].nr_components = 2;
+ mc->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface top field texcoord element */
+ mc->vertex_elems[4].src_offset = 0;
+ mc->vertex_elems[4].vertex_buffer_index = 1;
+ mc->vertex_elems[4].nr_components = 2;
+ mc->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* First ref surface bottom field texcoord element */
+ mc->vertex_elems[5].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[5].vertex_buffer_index = 1;
+ mc->vertex_elems[5].nr_components = 2;
+ mc->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface top field texcoord element */
+ mc->vertex_elems[6].src_offset = 0;
+ mc->vertex_elems[6].vertex_buffer_index = 2;
+ mc->vertex_elems[6].nr_components = 2;
+ mc->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Second ref surface bottom field texcoord element */
+ mc->vertex_elems[7].src_offset = sizeof(struct vlVertex2f);
+ mc->vertex_elems[7].vertex_buffer_index = 2;
+ mc->vertex_elems[7].nr_components = 2;
+ mc->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* Create our constant buffer */
+ mc->vs_const_buf.size = sizeof(struct vlVertexShaderConsts);
+ mc->vs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->vs_const_buf.size
+ );
+
+ mc->fs_const_buf.size = sizeof(struct vlFragmentShaderConsts);
+ mc->fs_const_buf.buffer = pipe->winsys->buffer_create
+ (
+ pipe->winsys,
+ 1,
+ PIPE_BUFFER_USAGE_CONSTANT,
+ mc->fs_const_buf.size
+ );
+
+ memcpy
+ (
+ pipe->winsys->buffer_map(pipe->winsys, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
+ &fs_consts,
+ sizeof(struct vlFragmentShaderConsts)
+ );
+
+ pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer);
+
+ mc->macroblocks = malloc(sizeof(struct vlMpeg2MacroBlock) * num_mb_per_frame);
+
+ return 0;
+}
+
+static int vlInit
+(
+ struct vlR16SnormBufferedMC *mc
+)
+{
+ struct pipe_context *pipe;
+ struct pipe_sampler_state sampler;
+ struct pipe_texture template;
+ unsigned int filters[5];
+ unsigned int i;
+
+ assert(mc);
+
+ pipe = mc->pipe;
+
+ /* For MC we render to textures, which are rounded up to nearest POT */
+ mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width);
+ mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height);
+ mc->viewport.scale[2] = 1;
+ mc->viewport.scale[3] = 1;
+ mc->viewport.translate[0] = 0;
+ mc->viewport.translate[1] = 0;
+ mc->viewport.translate[2] = 0;
+ mc->viewport.translate[3] = 0;
+
+ mc->render_target.width = vlRoundUpPOT(mc->picture_width);
+ mc->render_target.height = vlRoundUpPOT(mc->picture_height);
+ mc->render_target.num_cbufs = 1;
+ /* FB for MC stage is a vlSurface created by the user, set at render time */
+ mc->render_target.zsbuf = NULL;
+
+ filters[0] = PIPE_TEX_FILTER_NEAREST;
+ /* FIXME: Linear causes discoloration around block edges */
+ filters[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/;
+ filters[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ 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 = ;*/
+ 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_R16_SNORM;
+ template.last_level = 0;
+ template.width[0] = vlRoundUpPOT(mc->picture_width);
+ template.height[0] = vlRoundUpPOT(mc->picture_height);
+ template.depth[0] = 1;
+ template.compressed = 0;
+ pf_get_block(template.format, &template.block);
+
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ mc->textures[i][0] = pipe->screen->texture_create(pipe->screen, &template);
+
+ if (mc->picture_format == vlFormatYCbCr420)
+ {
+ template.width[0] = vlRoundUpPOT(mc->picture_width / 2);
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+ }
+ else if (mc->picture_format == vlFormatYCbCr422)
+ template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
+
+ for (i = 0; i < NUM_BUF_SETS; ++i)
+ {
+ mc->textures[i][1] = pipe->screen->texture_create(pipe->screen, &template);
+ mc->textures[i][2] = pipe->screen->texture_create(pipe->screen, &template);
+ }
+
+ /* textures[3] & textures[4] are assigned from vlSurfaces for P and B macroblocks at render time */
+
+ vlCreateVertexShaderIMB(mc);
+ vlCreateFragmentShaderIMB(mc);
+ vlCreateVertexShaderFramePMB(mc);
+ vlCreateVertexShaderFieldPMB(mc);
+ vlCreateFragmentShaderFramePMB(mc);
+ vlCreateFragmentShaderFieldPMB(mc);
+ vlCreateVertexShaderFrameBMB(mc);
+ vlCreateVertexShaderFieldBMB(mc);
+ vlCreateFragmentShaderFrameBMB(mc);
+ vlCreateFragmentShaderFieldBMB(mc);
+ vlCreateDataBufs(mc);
+
+ return 0;
+}
+
+int vlCreateR16SNormBufferedMC
+(
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ struct vlRender **render
+)
+{
+ struct vlR16SnormBufferedMC *mc;
+ unsigned int i;
+
+ assert(pipe);
+ assert(render);
+
+ mc = calloc(1, sizeof(struct vlR16SnormBufferedMC));
+
+ mc->base.vlBegin = &vlBegin;
+ mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16SnormBuffered;
+ mc->base.vlEnd = &vlEnd;
+ mc->base.vlFlush = &vlFlush;
+ mc->base.vlDestroy = &vlDestroy;
+ mc->pipe = pipe;
+ mc->picture_width = picture_width;
+ mc->picture_height = picture_height;
+
+ mc->cur_buf = 0;
+ mc->buffered_surface = NULL;
+ mc->past_surface = NULL;
+ mc->future_surface = NULL;
+ for (i = 0; i < 3; ++i)
+ mc->zero_block[i].x = -1.0f;
+ mc->num_macroblocks = 0;
+
+ vlInit(mc);
+
+ *render = &mc->base;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h
new file mode 100644
index 0000000000..27177d64ca
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h
@@ -0,0 +1,18 @@
+#ifndef vl_r16snorm_mc_buf_h
+#define vl_r16snorm_mc_buf_h
+
+#include "vl_types.h"
+
+struct pipe_context;
+struct vlRender;
+
+int vlCreateR16SNormBufferedMC
+(
+ struct pipe_context *pipe,
+ unsigned int picture_width,
+ unsigned int picture_height,
+ enum vlFormat picture_format,
+ struct vlRender **render
+);
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_render.h b/src/gallium/state_trackers/g3dvl/vl_render.h
new file mode 100644
index 0000000000..166030b498
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_render.h
@@ -0,0 +1,38 @@
+#ifndef vl_render_h
+#define vl_render_h
+
+#include "vl_types.h"
+
+struct pipe_surface;
+
+struct vlRender
+{
+ int (*vlBegin)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlRenderMacroBlocksMpeg2)
+ (
+ struct vlRender *render,
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+ );
+
+ int (*vlEnd)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlFlush)
+ (
+ struct vlRender *render
+ );
+
+ int (*vlDestroy)
+ (
+ struct vlRender *render
+ );
+};
+
+#endif
diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.c b/src/gallium/state_trackers/g3dvl/vl_screen.c
new file mode 100644
index 0000000000..484f63b0d4
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_screen.c
@@ -0,0 +1,115 @@
+#define VL_INTERNAL
+#include "vl_screen.h"
+#include <assert.h>
+#include <stdlib.h>
+
+int vlCreateScreen
+(
+ struct vlDisplay *display,
+ int screen,
+ struct pipe_screen *pscreen,
+ struct vlScreen **vl_screen
+)
+{
+ struct vlScreen *scrn;
+
+ assert(display);
+ assert(pscreen);
+ assert(vl_screen);
+
+ scrn = calloc(1, sizeof(struct vlScreen));
+
+ if (!scrn)
+ return 1;
+
+ scrn->display = display;
+ scrn->ordinal = screen;
+ scrn->pscreen = pscreen;
+ *vl_screen = scrn;
+
+ return 0;
+}
+
+int vlDestroyScreen
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ free(screen);
+
+ return 0;
+}
+
+struct vlDisplay* vlGetDisplay
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return screen->display;
+}
+
+struct pipe_screen* vlGetPipeScreen
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return screen->pscreen;
+}
+
+unsigned int vlGetMaxProfiles
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return vlProfileCount;
+}
+
+int vlQueryProfiles
+(
+ struct vlScreen *screen,
+ enum vlProfile *profiles
+)
+{
+ assert(screen);
+ assert(profiles);
+
+ profiles[0] = vlProfileMpeg2Simple;
+ profiles[1] = vlProfileMpeg2Main;
+
+ return 0;
+}
+
+unsigned int vlGetMaxEntryPoints
+(
+ struct vlScreen *screen
+)
+{
+ assert(screen);
+
+ return vlEntryPointCount;
+}
+
+int vlQueryEntryPoints
+(
+ struct vlScreen *screen,
+ enum vlProfile profile,
+ enum vlEntryPoint *entry_points
+)
+{
+ assert(screen);
+ assert(entry_points);
+
+ entry_points[0] = vlEntryPointIDCT;
+ entry_points[1] = vlEntryPointMC;
+ entry_points[2] = vlEntryPointCSC;
+
+ return 0;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.h b/src/gallium/state_trackers/g3dvl/vl_screen.h
new file mode 100644
index 0000000000..98f3d429b6
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_screen.h
@@ -0,0 +1,63 @@
+#ifndef vl_screen_h
+#define vl_screen_h
+
+#include "vl_types.h"
+
+struct pipe_screen;
+
+#ifdef VL_INTERNAL
+struct vlScreen
+{
+ struct vlDisplay *display;
+ unsigned int ordinal;
+ struct pipe_screen *pscreen;
+};
+#endif
+
+int vlCreateScreen
+(
+ struct vlDisplay *display,
+ int screen,
+ struct pipe_screen *pscreen,
+ struct vlScreen **vl_screen
+);
+
+int vlDestroyScreen
+(
+ struct vlScreen *screen
+);
+
+struct vlDisplay* vlGetDisplay
+(
+ struct vlScreen *screen
+);
+
+struct pipe_screen* vlGetPipeScreen
+(
+ struct vlScreen *screen
+);
+
+unsigned int vlGetMaxProfiles
+(
+ struct vlScreen *screen
+);
+
+int vlQueryProfiles
+(
+ struct vlScreen *screen,
+ enum vlProfile *profiles
+);
+
+unsigned int vlGetMaxEntryPoints
+(
+ struct vlScreen *screen
+);
+
+int vlQueryEntryPoints
+(
+ struct vlScreen *screen,
+ enum vlProfile profile,
+ enum vlEntryPoint *entry_points
+);
+
+#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
index 0000000000..51f1721a33
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.c
@@ -0,0 +1,215 @@
+#include "vl_shader_build.h"
+#include <assert.h>
+#include <tgsi/tgsi_parse.h>
+#include <tgsi/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_temps(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_TEMPORARY;
+ 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
index 0000000000..dc615cb156
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.h
@@ -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_temps(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
index 0000000000..076bd40d41
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_surface.c
@@ -0,0 +1,237 @@
+#define VL_INTERNAL
+#include "vl_surface.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <vl_winsys.h>
+#include "vl_screen.h"
+#include "vl_context.h"
+#include "vl_render.h"
+#include "vl_csc.h"
+#include "vl_util.h"
+
+int vlCreateSurface
+(
+ struct vlScreen *screen,
+ unsigned int width,
+ unsigned int height,
+ enum vlFormat format,
+ struct vlSurface **surface
+)
+{
+ struct vlSurface *sfc;
+ struct pipe_texture template;
+
+ assert(screen);
+ assert(surface);
+
+ sfc = calloc(1, sizeof(struct vlSurface));
+
+ if (!sfc)
+ return 1;
+
+ sfc->screen = screen;
+ sfc->width = width;
+ sfc->height = height;
+ sfc->format = 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] = vlRoundUpPOT(sfc->width);
+ template.height[0] = vlRoundUpPOT(sfc->height);
+ template.depth[0] = 1;
+ template.compressed = 0;
+ pf_get_block(template.format, &template.block);
+ template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET;
+
+ sfc->texture = vlGetPipeScreen(screen)->texture_create(vlGetPipeScreen(screen), &template);
+
+ *surface = sfc;
+
+ return 0;
+}
+
+int vlDestroySurface
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+
+ pipe_texture_release(&surface->texture);
+ free(surface);
+
+ return 0;
+}
+
+int vlRenderMacroBlocksMpeg2
+(
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+)
+{
+ assert(batch);
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlBegin(surface->context->render);
+
+ surface->context->render->vlRenderMacroBlocksMpeg2
+ (
+ surface->context->render,
+ batch,
+ surface
+ );
+
+ surface->context->render->vlEnd(surface->context->render);
+
+ return 0;
+}
+
+int vlPutPicture
+(
+ struct vlSurface *surface,
+ vlNativeDrawable drawable,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ int drawable_w,
+ int drawable_h,
+ enum vlPictureType picture_type
+)
+{
+ struct vlCSC *csc;
+ struct pipe_context *pipe;
+
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlFlush(surface->context->render);
+
+ csc = surface->context->csc;
+ pipe = surface->context->pipe;
+
+ csc->vlResizeFrameBuffer(csc, drawable_w, drawable_h);
+
+ csc->vlBegin(csc);
+
+ csc->vlPutPicture
+ (
+ csc,
+ surface,
+ srcx,
+ srcy,
+ srcw,
+ srch,
+ destx,
+ desty,
+ destw,
+ desth,
+ picture_type
+ );
+
+ csc->vlEnd(csc);
+
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &surface->disp_fence);
+
+ bind_pipe_drawable(pipe, drawable);
+
+ pipe->winsys->flush_frontbuffer
+ (
+ pipe->winsys,
+ csc->vlGetFrameBuffer(csc),
+ pipe->priv
+ );
+
+ return 0;
+}
+
+int vlSurfaceGetStatus
+(
+ struct vlSurface *surface,
+ enum vlResourceStatus *status
+)
+{
+ assert(surface);
+ assert(surface->context);
+ assert(status);
+
+ if (surface->render_fence && !surface->context->pipe->winsys->fence_signalled(surface->context->pipe->winsys, surface->render_fence, 0))
+ {
+ *status = vlResourceStatusRendering;
+ return 0;
+ }
+
+ if (surface->disp_fence && !surface->context->pipe->winsys->fence_signalled(surface->context->pipe->winsys, surface->disp_fence, 0))
+ {
+ *status = vlResourceStatusDisplaying;
+ return 0;
+ }
+
+ *status = vlResourceStatusFree;
+
+ return 0;
+}
+
+int vlSurfaceFlush
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+ assert(surface->context);
+
+ surface->context->render->vlFlush(surface->context->render);
+
+ return 0;
+}
+
+int vlSurfaceSync
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+ assert(surface->context);
+ assert(surface->render_fence);
+
+ surface->context->pipe->winsys->fence_finish(surface->context->pipe->winsys, surface->render_fence, 0);
+
+ return 0;
+}
+
+struct vlScreen* vlSurfaceGetScreen
+(
+ struct vlSurface *surface
+)
+{
+ assert(surface);
+
+ return surface->screen;
+}
+
+struct vlContext* vlBindToContext
+(
+ struct vlSurface *surface,
+ struct vlContext *context
+)
+{
+ struct vlContext *old;
+
+ assert(surface);
+
+ old = surface->context;
+ surface->context = context;
+
+ return old;
+}
diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h
new file mode 100644
index 0000000000..133e1515ef
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_surface.h
@@ -0,0 +1,86 @@
+#ifndef vl_surface_h
+#define vl_surface_h
+
+#include "vl_types.h"
+
+#ifdef VL_INTERNAL
+struct pipe_texture;
+
+struct vlSurface
+{
+ struct vlScreen *screen;
+ struct vlContext *context;
+ unsigned int width;
+ unsigned int height;
+ enum vlFormat format;
+ struct pipe_texture *texture;
+ struct pipe_fence_handle *render_fence;
+ struct pipe_fence_handle *disp_fence;
+};
+#endif
+
+int vlCreateSurface
+(
+ struct vlScreen *screen,
+ unsigned int width,
+ unsigned int height,
+ enum vlFormat format,
+ struct vlSurface **surface
+);
+
+int vlDestroySurface
+(
+ struct vlSurface *surface
+);
+
+int vlRenderMacroBlocksMpeg2
+(
+ struct vlMpeg2MacroBlockBatch *batch,
+ struct vlSurface *surface
+);
+
+int vlPutPicture
+(
+ struct vlSurface *surface,
+ vlNativeDrawable drawable,
+ int srcx,
+ int srcy,
+ int srcw,
+ int srch,
+ int destx,
+ int desty,
+ int destw,
+ int desth,
+ int drawable_w,
+ int drawable_h,
+ enum vlPictureType picture_type
+);
+
+int vlSurfaceGetStatus
+(
+ struct vlSurface *surface,
+ enum vlResourceStatus *status
+);
+
+int vlSurfaceFlush
+(
+ struct vlSurface *surface
+);
+
+int vlSurfaceSync
+(
+ struct vlSurface *surface
+);
+
+struct vlScreen* vlSurfaceGetScreen
+(
+ struct vlSurface *surface
+);
+
+struct vlContext* vlBindToContext
+(
+ struct vlSurface *surface,
+ struct vlContext *context
+);
+
+#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
index 0000000000..274e1f7437
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_types.h
@@ -0,0 +1,115 @@
+#ifndef vl_types_h
+#define vl_types_h
+
+#if 1 /*#ifdef X11*/
+#include <X11/Xlib.h>
+
+typedef Display* vlNativeDisplay;
+typedef Drawable vlNativeDrawable;
+#endif
+
+struct vlDisplay;
+struct vlScreen;
+struct vlContext;
+struct vlSurface;
+
+enum vlResourceStatus
+{
+ vlResourceStatusFree,
+ vlResourceStatusRendering,
+ vlResourceStatusDisplaying
+};
+
+enum vlProfile
+{
+ vlProfileMpeg2Simple,
+ vlProfileMpeg2Main,
+
+ vlProfileCount
+};
+
+enum vlEntryPoint
+{
+ vlEntryPointIDCT,
+ vlEntryPointMC,
+ vlEntryPointCSC,
+
+ vlEntryPointCount
+};
+
+enum vlFormat
+{
+ vlFormatYCbCr420,
+ vlFormatYCbCr422,
+ vlFormatYCbCr444
+};
+
+enum vlPictureType
+{
+ vlPictureTypeTopField,
+ vlPictureTypeBottomField,
+ vlPictureTypeFrame
+};
+
+enum vlMotionType
+{
+ vlMotionTypeField,
+ vlMotionTypeFrame,
+ vlMotionTypeDualPrime,
+ vlMotionType16x8
+};
+
+enum vlFieldOrder
+{
+ vlFieldOrderFirst,
+ vlFieldOrderSecond
+};
+
+enum vlDCTType
+{
+ vlDCTTypeFrameCoded,
+ vlDCTTypeFieldCoded
+};
+
+struct vlVertex2f
+{
+ float x, y;
+};
+
+struct vlVertex4f
+{
+ float x, y, z, w;
+};
+
+enum vlMacroBlockType
+{
+ vlMacroBlockTypeIntra,
+ vlMacroBlockTypeFwdPredicted,
+ vlMacroBlockTypeBkwdPredicted,
+ vlMacroBlockTypeBiPredicted,
+
+ vlNumMacroBlockTypes
+};
+
+struct vlMpeg2MacroBlock
+{
+ unsigned int mbx, mby;
+ enum vlMacroBlockType mb_type;
+ enum vlMotionType mo_type;
+ enum vlDCTType dct_type;
+ int PMV[2][2][2];
+ unsigned int cbp;
+ short *blocks;
+};
+
+struct vlMpeg2MacroBlockBatch
+{
+ struct vlSurface *past_surface;
+ struct vlSurface *future_surface;
+ enum vlPictureType picture_type;
+ enum vlFieldOrder field_order;
+ unsigned int num_macroblocks;
+ struct vlMpeg2MacroBlock *macroblocks;
+};
+
+#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
index 0000000000..50aa9af66f
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_util.c
@@ -0,0 +1,16 @@
+#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
index 0000000000..bc98e79df4
--- /dev/null
+++ b/src/gallium/state_trackers/g3dvl/vl_util.h
@@ -0,0 +1,6 @@
+#ifndef vl_util_h
+#define vl_util_h
+
+unsigned int vlRoundUpPOT(unsigned int x);
+
+#endif
diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile
new file mode 100644
index 0000000000..81562ca78d
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/Makefile
@@ -0,0 +1,46 @@
+
+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/nv20/libnv20.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/drm/nouveau/nouveau_bo.c b/src/gallium/winsys/drm/nouveau/nouveau_bo.c
new file mode 100644
index 0000000000..b5942994d9
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_bo.c
@@ -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/drm/nouveau/nouveau_channel.c b/src/gallium/winsys/drm/nouveau/nouveau_channel.c
new file mode 100644
index 0000000000..3b4dcd1ecf
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_channel.c
@@ -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/drm/nouveau/nouveau_context.c b/src/gallium/winsys/drm/nouveau/nouveau_context.c
new file mode 100644
index 0000000000..74413c408f
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_context.c
@@ -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/drm/nouveau/nouveau_context.h b/src/gallium/winsys/drm/nouveau/nouveau_context.h
new file mode 100644
index 0000000000..77e2147a2c
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_context.h
@@ -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/drm/nouveau/nouveau_device.c b/src/gallium/winsys/drm/nouveau/nouveau_device.c
new file mode 100644
index 0000000000..0b452fcd02
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_device.c
@@ -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/drm/nouveau/nouveau_dma.c b/src/gallium/winsys/drm/nouveau/nouveau_dma.c
new file mode 100644
index 0000000000..f8a8ba04f6
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_dma.c
@@ -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/drm/nouveau/nouveau_dma.h b/src/gallium/winsys/drm/nouveau/nouveau_dma.h
new file mode 100644
index 0000000000..cfa6d26e82
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_dma.h
@@ -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/drm/nouveau/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/nouveau_dri.h
new file mode 100644
index 0000000000..1207c2d609
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_dri.h
@@ -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/drm/nouveau/nouveau_drmif.h b/src/gallium/winsys/drm/nouveau/nouveau_drmif.h
new file mode 100644
index 0000000000..dcd6a5eb0a
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_drmif.h
@@ -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/drm/nouveau/nouveau_fence.c b/src/gallium/winsys/drm/nouveau/nouveau_fence.c
new file mode 100644
index 0000000000..e7b0b4ff07
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_fence.c
@@ -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/drm/nouveau/nouveau_grobj.c b/src/gallium/winsys/drm/nouveau/nouveau_grobj.c
new file mode 100644
index 0000000000..51523897d5
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_grobj.c
@@ -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/drm/nouveau/nouveau_local.h b/src/gallium/winsys/drm/nouveau/nouveau_local.h
new file mode 100644
index 0000000000..e878a40803
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_local.h
@@ -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/drm/nouveau/nouveau_lock.c b/src/gallium/winsys/drm/nouveau/nouveau_lock.c
new file mode 100644
index 0000000000..9adb9ac854
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_lock.c
@@ -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/drm/nouveau/nouveau_notifier.c b/src/gallium/winsys/drm/nouveau/nouveau_notifier.c
new file mode 100644
index 0000000000..01e8f38440
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_notifier.c
@@ -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/drm/nouveau/nouveau_pushbuf.c b/src/gallium/winsys/drm/nouveau/nouveau_pushbuf.c
new file mode 100644
index 0000000000..815046ba85
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_pushbuf.c
@@ -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/drm/nouveau/nouveau_resource.c b/src/gallium/winsys/drm/nouveau/nouveau_resource.c
new file mode 100644
index 0000000000..3bbcb5c45e
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_resource.c
@@ -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/drm/nouveau/nouveau_screen.c b/src/gallium/winsys/drm/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..c6d0c53588
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_screen.c
@@ -0,0 +1,265 @@
+#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_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 __DRIconfig **
+nouveau_fill_in_modes(__DRIscreenPrivate *psp,
+ unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer)
+{
+ __DRIconfig **configs;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML,
+ };
+
+ uint8_t depth_bits_array[3];
+ uint8_t stencil_bits_array[3];
+ uint8_t msaa_samples_array[1];
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = depth_bits;
+ depth_bits_array[2] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer. It will be a sw fallback, but some apps won't
+ * care about that.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 0;
+ if (depth_bits == 24)
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+ stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ msaa_samples_array[0] = 0;
+
+ depth_buffer_factor =
+ ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
+ back_buffer_factor = (have_back_buffer) ? 3 : 1;
+
+ if (pixel_bits == 16) {
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ else {
+ fb_format = GL_BGRA;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ configs = driCreateConfigs(fb_format, fb_type,
+ depth_bits_array, stencil_bits_array,
+ depth_buffer_factor, back_buffer_modes,
+ back_buffer_factor, msaa_samples_array, 1);
+ if (configs == NULL) {
+ fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__);
+ return NULL;
+ }
+
+ return configs;
+}
+
+static const __DRIconfig **
+nouveau_screen_create(__DRIscreenPrivate *psp)
+{
+ struct nouveau_dri *nv_dri = psp->pDevPriv;
+ struct nouveau_screen *nv_screen;
+ 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 };
+ int ret;
+
+ if (!driCheckDriDdxDrmVersions2("nouveau",
+ &psp->dri_version, &dri_expected,
+ &psp->ddx_version, &ddx_expected,
+ &psp->drm_version, &drm_expected)) {
+ return NULL;
+ }
+
+ if (drm_expected.patch != psp->drm_version.patch) {
+ fprintf(stderr, "Incompatible DRM patch level.\n"
+ "Expected: %d\n" "Current : %d\n",
+ drm_expected.patch, psp->drm_version.patch);
+ return NULL;
+ }
+
+ driInitExtensions(NULL, card_extensions, GL_FALSE);
+
+ if (psp->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 = psp;
+ psp->private = (void *)nv_screen;
+
+ driParseOptionInfo(&nv_screen->option_cache,
+ __driConfigOptions, __driNConfigOptions);
+
+ if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
+ psp->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 (const __DRIconfig **)
+ nouveau_fill_in_modes(psp, nv_dri->bpp,
+ (nv_dri->bpp == 16) ? 16 : 24,
+ (nv_dri->bpp == 16) ? 0 : 8, 1);
+}
+
+static void
+nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv)
+{
+ struct nouveau_screen *nv_screen = driScrnPriv->private;
+
+ driScrnPriv->private = NULL;
+ FREE(nv_screen);
+}
+
+const struct __DriverAPIRec
+driDriverAPI = {
+ .InitScreen = 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,
+ .CopySubBuffer = nouveau_copy_sub_buffer,
+
+ .InitScreen2 = NULL, /* one day, I promise! */
+};
+
diff --git a/src/gallium/winsys/drm/nouveau/nouveau_screen.h b/src/gallium/winsys/drm/nouveau/nouveau_screen.h
new file mode 100644
index 0000000000..388d6be9bb
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_screen.h
@@ -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/drm/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.c
new file mode 100644
index 0000000000..70e0104e83
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.c
@@ -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/drm/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.h
new file mode 100644
index 0000000000..825d3da6da
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_swapbuffers.h
@@ -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/drm/nouveau/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/nouveau_winsys.c
new file mode 100644
index 0000000000..364340e1d3
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_winsys.c
@@ -0,0 +1,161 @@
+#include "util/u_memory.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:
+ hws_create = nv10_screen_create;
+ hw_create = nv10_create;
+ break;
+ case 0x20:
+ hws_create = nv20_screen_create;
+ hw_create = nv20_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/drm/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.c
new file mode 100644
index 0000000000..5276806de6
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.c
@@ -0,0 +1,206 @@
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+
+#include "util/u_memory.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/drm/nouveau/nouveau_winsys_pipe.h b/src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.h
new file mode 100644
index 0000000000..6a03ac0d77
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_winsys_pipe.h
@@ -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/drm/nouveau/nouveau_winsys_softpipe.c b/src/gallium/winsys/drm/nouveau/nouveau_winsys_softpipe.c
new file mode 100644
index 0000000000..704f6c7750
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nouveau_winsys_softpipe.c
@@ -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/drm/nouveau/nv04_surface.c b/src/gallium/winsys/drm/nouveau/nv04_surface.c
new file mode 100644
index 0000000000..d08955de71
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nv04_surface.c
@@ -0,0 +1,413 @@
+#include "pipe/p_context.h"
+#include "pipe/p_format.h"
+
+#include "nouveau_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;
+}
+
+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_swizzled(struct nouveau_context *nv,
+ struct pipe_surface *dst,
+ struct pipe_surface *src)
+{
+ struct nouveau_channel *chan = nv->nvc->channel;
+
+ BEGIN_RING(chan, nv->nvc->NvSwzSurf,
+ NV04_SWIZZLED_SURFACE_FORMAT, 2);
+ /* FIXME: read destination format from somewhere */
+ OUT_RING (chan,
+ NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8
+ | (log2i(dst->width)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT)
+ | (log2i(dst->height)<<NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT) );
+ OUT_RELOCo(chan, nouveau_buffer(dst->buffer)->bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(chan, nv->nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 13);
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+ /* FIXME: read source format from somewhere */
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8);
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, (src->height<<16) | src->width);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, (src->height<<16) | src->width);
+ OUT_RING (chan, 1<<20);
+ OUT_RING (chan, 1<<20);
+ OUT_RING (chan, (src->height<<16) | src->width);
+ OUT_RING (chan,
+ src->stride
+ | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
+ | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+ OUT_RELOCo(chan, nouveau_buffer(src->buffer)->bo,
+ NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, 0);
+
+ BEGIN_RING(chan, 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;
+}
+
+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;
+
+ /* Setup transfer to swizzle the texture to vram if needed */
+ /* FIXME/TODO: check proper limits of this operation */
+ if (nouveau_buffer(dst->buffer)->bo->flags & NOUVEAU_BO_SWIZZLED) {
+ /* FIXME: Disable it for the moment */
+ /*return nv04_surface_copy_prep_swizzled(nv, dst, src);*/
+ }
+
+ /* 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++);
+ BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_NOTIFY, 1);
+ OUT_RING (chan, nvc->sync_notifier->handle);
+ BEGIN_RING(chan, nvc->NvSwzSurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1);
+ OUT_RING (chan, nvc->channel->vram->handle);
+
+ 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++);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1);
+ OUT_RING (chan, nvc->channel->vram->handle);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
+ OUT_RING (chan, nvc->NvSwzSurf->handle);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_ROP, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_BETA1, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_BETA4, 1);
+ OUT_RING (chan, 0);
+ BEGIN_RING(chan, nvc->NvSIFM, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
+ OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+
+ 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/drm/nouveau/nv50_surface.c b/src/gallium/winsys/drm/nouveau/nv50_surface.c
new file mode 100644
index 0000000000..c8ab7f690f
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/nv50_surface.c
@@ -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/nouveau/Makefile b/src/gallium/winsys/g3dvl/nouveau/Makefile
new file mode 100644
index 0000000000..ff43327778
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/Makefile
@@ -0,0 +1,50 @@
+TARGET = libnouveau_dri.so
+GALLIUMDIR = ../../..
+DRMDIR ?= /usr
+DRIDIR = ../../../../driclient
+
+OBJECTS = nouveau_bo.o nouveau_fence.o nouveau_swapbuffers.o nouveau_channel.o \
+ nouveau_grobj.o nouveau_context.o nouveau_winsys.o nouveau_lock.o \
+ nouveau_winsys_pipe.o nouveau_device.o nouveau_notifier.o nouveau_dma.o \
+ nouveau_pushbuf.o nouveau_resource.o nouveau_screen.o nv04_surface.o \
+ nv50_surface.o #nouveau_winsys_softpipe.o
+
+CFLAGS += -g -Wall -fPIC \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/winsys/g3dvl \
+ -I${DRMDIR}/include \
+ -I${DRMDIR}/include/drm \
+ -I${GALLIUMDIR}/drivers \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${DRIDIR}/include
+
+LDFLAGS += -L${DRMDIR}/lib \
+ -L${DRIDIR}/lib \
+ -L${GALLIUMDIR}/auxiliary/draw \
+ -L${GALLIUMDIR}/auxiliary/tgsi \
+ -L${GALLIUMDIR}/auxiliary/translate \
+ -L${GALLIUMDIR}/auxiliary/rtasm \
+ -L${GALLIUMDIR}/auxiliary/cso_cache \
+ -L${GALLIUMDIR}/drivers/nv10 \
+ -L${GALLIUMDIR}/drivers/nv20 \
+ -L${GALLIUMDIR}/drivers/nv30 \
+ -L${GALLIUMDIR}/drivers/nv40 \
+ -L${GALLIUMDIR}/drivers/nv50
+
+LIBS += -ldriclient -ldrm -lnv10 -lnv20 -lnv30 -lnv40 -lnv50 -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lm
+
+#############################################
+
+.PHONY = all clean libdriclient
+
+all: ${TARGET}
+
+${TARGET}: ${OBJECTS} libdriclient
+ $(CC) ${LDFLAGS} -shared -o $@ ${OBJECTS} ${LIBS}
+
+libdriclient:
+ cd ${DRIDIR}/src; ${MAKE}
+
+clean:
+ cd ${DRIDIR}/src; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c
new file mode 120000
index 0000000000..1005282dd4
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_bo.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_bo.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c
new file mode 120000
index 0000000000..5af8202950
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_channel.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_channel.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c
new file mode 100644
index 0000000000..06a61fcda3
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.c
@@ -0,0 +1,370 @@
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+#include "pipe/p_screen.h"
+#include "util/u_memory.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
+*/
+
+/*
+ * TODO: Re-examine dri_screen, dri_context, nouveau_screen, nouveau_context
+ * relationships, seems like there is a lot of room for simplification there.
+ */
+
+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;
+}
+
+int
+nouveau_context_create(dri_context_t *dri_context)
+{
+ dri_screen_t *dri_screen = dri_context->dri_screen;
+ struct nouveau_screen *nv_screen = dri_screen->private;
+ struct nouveau_context *nv = CALLOC_STRUCT(nouveau_context);
+ struct pipe_context *pipe = NULL;
+ struct nouveau_channel_context *nvc = NULL;
+ struct nouveau_device *dev = nv_screen->device;
+ int i;
+
+ 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 1;
+ }
+
+ dri_context->private = (void*)nv;
+ nv->dri_context = dri_context;
+ nv->nv_screen = nv_screen;
+
+ {
+ struct nouveau_device_priv *nvdev = nouveau_device(dev);
+
+ nvdev->ctx = dri_context->drm_context;
+ nvdev->lock = (drmLock*)&dri_screen->sarea->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;
+ }
+
+ nvc = nv_screen->nvc;
+
+ if (!nvc) {
+ nvc = nouveau_channel_context_create(dev);
+ if (!nvc) {
+ NOUVEAU_ERR("Failed initialising GPU context\n");
+ return 1;
+ }
+ 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 1;
+ break;
+ default:
+ if (nouveau_surface_init_nv04(nv))
+ return 1;
+ 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);
+ }
+
+ /* XXX: nouveau_winsys_softpipe needs a mesa header removed before we can compile it. */
+ /*
+ if (!pipe) {
+ NOUVEAU_MSG("Using softpipe\n");
+ pipe = nouveau_create_softpipe(nv);
+ if (!pipe) {
+ NOUVEAU_ERR("Error creating pipe, bailing\n");
+ return 1;
+ }
+ }
+ */
+ if (!pipe) {
+ NOUVEAU_ERR("Error creating pipe, bailing\n");
+ return 1;
+ }
+
+ pipe->priv = nv;
+
+ return 0;
+}
+
+void
+nouveau_context_destroy(dri_context_t *dri_context)
+{
+ struct nouveau_context *nv = dri_context->private;
+ struct nouveau_channel_context *nvc = nv->nvc;
+
+ assert(nv);
+
+ 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);
+}
+
+int
+nouveau_context_bind(struct nouveau_context *nv, dri_drawable_t *dri_drawable)
+{
+ assert(nv);
+ assert(dri_drawable);
+
+ if (nv->dri_drawable != dri_drawable)
+ {
+ nv->dri_drawable = dri_drawable;
+ dri_drawable->private = nv;
+ }
+
+ return 0;
+}
+
+int
+nouveau_context_unbind(struct nouveau_context *nv)
+{
+ assert(nv);
+
+ nv->dri_drawable = NULL;
+
+ return 0;
+}
+
+/* Show starts here */
+
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
+{
+ struct nouveau_context *nv;
+ dri_drawable_t *dri_drawable;
+
+ nv = pipe->priv;
+
+ driCreateDrawable(nv->nv_screen->dri_screen, drawable, &dri_drawable);
+
+ nouveau_context_bind(nv, dri_drawable);
+
+ return 0;
+}
+
+int unbind_pipe_drawable(struct pipe_context *pipe)
+{
+ nouveau_context_unbind(pipe->priv);
+
+ return 0;
+}
+
+struct pipe_context* create_pipe_context(Display *display, int screen)
+{
+ dri_screen_t *dri_screen;
+ dri_framebuffer_t dri_framebuf;
+ dri_context_t *dri_context;
+ struct nouveau_context *nv;
+
+ driCreateScreen(display, screen, &dri_screen, &dri_framebuf);
+ driCreateContext(dri_screen, XDefaultVisual(display, screen), &dri_context);
+
+ nouveau_screen_create(dri_screen, &dri_framebuf);
+ nouveau_context_create(dri_context);
+
+ nv = dri_context->private;
+
+ return nv->nvc->pctx[nv->pctx_id];
+}
+
+int destroy_pipe_context(struct pipe_context *pipe)
+{
+ struct pipe_screen *screen;
+ struct pipe_winsys *winsys;
+ struct nouveau_context *nv;
+ dri_screen_t *dri_screen;
+ dri_context_t *dri_context;
+
+ assert(pipe);
+
+ screen = pipe->screen;
+ winsys = pipe->winsys;
+ nv = pipe->priv;
+ dri_context = nv->dri_context;
+ dri_screen = dri_context->dri_screen;
+
+ pipe->destroy(pipe);
+ screen->destroy(screen);
+ free(winsys);
+
+ nouveau_context_destroy(dri_context);
+ nouveau_screen_destroy(dri_screen);
+ driDestroyContext(dri_context);
+ driDestroyScreen(dri_screen);
+
+ return 0;
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h
new file mode 100644
index 0000000000..395a3ab790
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_context.h
@@ -0,0 +1,105 @@
+#ifndef __NOUVEAU_CONTEXT_H__
+#define __NOUVEAU_CONTEXT_H__
+
+/*#include "xmlconfig.h"*/
+
+#include <driclient.h>
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+
+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 {
+ /* DRI stuff */
+ dri_context_t *dri_context;
+ dri_drawable_t *dri_drawable;
+ unsigned int last_stamp;
+ /*driOptionCache dri_option_cache;*/
+ drm_context_t drm_context;
+ drmLock drm_lock;
+ int 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 int nouveau_context_create(dri_context_t *);
+extern void nouveau_context_destroy(dri_context_t *);
+extern int nouveau_context_bind(struct nouveau_context *, dri_drawable_t *);
+extern int nouveau_context_unbind(struct nouveau_context *);
+
+#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/g3dvl/nouveau/nouveau_device.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_device.c
new file mode 120000
index 0000000000..63f1fa040c
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_device.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_device.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c
new file mode 120000
index 0000000000..cd0d32e537
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_dma.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h
new file mode 120000
index 0000000000..e6c7d4bc96
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dma.h
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_dma.h \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h
new file mode 120000
index 0000000000..c8f9dbdc3a
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_dri.h
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_dri.h \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h
new file mode 120000
index 0000000000..27082c9d34
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_drmif.h
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_drmif.h \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c
new file mode 120000
index 0000000000..51a50527e6
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_fence.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_fence.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c
new file mode 120000
index 0000000000..db17c72e6d
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_grobj.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_grobj.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h
new file mode 120000
index 0000000000..4e9d3042cb
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_local.h
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_local.h \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c
new file mode 100644
index 0000000000..375634bd05
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_lock.c
@@ -0,0 +1,92 @@
+/**************************************************************************
+ *
+ * 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 <pthread.h>
+#include <driclient.h>
+#include "nouveau_context.h"
+#include "nouveau_screen.h"
+
+static pthread_mutex_t lockMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void
+nouveau_contended_lock(struct nouveau_context *nv, unsigned int flags)
+{
+ dri_drawable_t *dri_drawable = nv->dri_drawable;
+ dri_screen_t *dri_screen = nv->dri_context->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 (dri_drawable)
+ DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable);
+}
+
+/* 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;
+
+ pthread_mutex_lock(&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 = 1;
+}
+
+
+/* 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 = 0;
+
+ DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx);
+
+ pthread_mutex_unlock(&lockMutex);
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c
new file mode 120000
index 0000000000..703bc3ce4a
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_notifier.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_notifier.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c
new file mode 120000
index 0000000000..4ac137cada
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_pushbuf.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_pushbuf.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c
new file mode 120000
index 0000000000..2241af328f
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_resource.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_resource.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..f80d00050c
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.c
@@ -0,0 +1,91 @@
+#include "pipe/p_context.h"
+#include "util/u_memory.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
+
+/*
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 0;
+*/
+
+int nouveau_check_dri_drm_ddx(dri_version_t *dri, dri_version_t *drm, dri_version_t *ddx)
+{
+ static const dri_version_t ddx_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL};
+ static const dri_version_t dri_expected = {4, 0, 0};
+ static const dri_version_t drm_expected = {0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL};
+
+ assert(dri);
+ assert(drm);
+ assert(ddx);
+
+ if (dri->major != dri_expected.major || dri->minor < dri_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DRI version.\n");
+ return 1;
+ }
+ if (drm->major != drm_expected.major || drm->minor < drm_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DRM version.\n");
+ return 1;
+ }
+ if (ddx->major != ddx_expected.major || ddx->minor < ddx_expected.minor)
+ {
+ NOUVEAU_ERR("Unexpected DDX version.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf)
+{
+ struct nouveau_dri *nv_dri = dri_framebuf->private;
+ struct nouveau_screen *nv_screen;
+ int ret;
+
+ if (nouveau_check_dri_drm_ddx(&dri_screen->dri, &dri_screen->drm, &dri_screen->ddx))
+ return 1;
+
+ nv_screen = CALLOC_STRUCT(nouveau_screen);
+ if (!nv_screen)
+ return 1;
+ nv_screen->dri_screen = dri_screen;
+ dri_screen->private = (void*)nv_screen;
+
+ /*
+ driParseOptionInfo(&nv_screen->option_cache,
+ __driConfigOptions, __driNConfigOptions);
+ */
+
+ if ((ret = nouveau_device_open_existing(&nv_screen->device, 0,
+ dri_screen->fd, 0))) {
+ NOUVEAU_ERR("Failed opening nouveau device: %d.\n", ret);
+ return 1;
+ }
+
+ 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 0;
+}
+
+void
+nouveau_screen_destroy(dri_screen_t *dri_screen)
+{
+ struct nouveau_screen *nv_screen = dri_screen->private;
+
+ FREE(nv_screen);
+}
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h
new file mode 100644
index 0000000000..8a58bb7556
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_screen.h
@@ -0,0 +1,24 @@
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+/* TODO: Investigate using DRI options for interesting things */
+/*#include "xmlconfig.h"*/
+
+struct nouveau_screen {
+ dri_screen_t *dri_screen;
+ struct nouveau_device *device;
+ struct nouveau_channel_context *nvc;
+
+ uint32_t front_offset;
+ uint32_t front_pitch;
+ uint32_t front_cpp;
+ uint32_t front_height;
+
+ /*driOptionCache option_cache;*/
+};
+
+int nouveau_screen_create(dri_screen_t *dri_screen, dri_framebuffer_t *dri_framebuf);
+void nouveau_screen_destroy(dri_screen_t *dri_screen);
+
+#endif
+
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c
new file mode 100644
index 0000000000..7916c80615
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.c
@@ -0,0 +1,64 @@
+#include "pipe/p_context.h"
+#include "nouveau_context.h"
+#include "nouveau_local.h"
+#include "nouveau_screen.h"
+#include "nouveau_swapbuffers.h"
+
+void
+nouveau_copy_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf,
+ const drm_clip_rect_t *rect)
+{
+ struct nouveau_context *nv = dri_drawable->private;
+ drm_clip_rect_t *pbox;
+ int nbox, i;
+
+ LOCK_HARDWARE(nv);
+ if (!dri_drawable->num_cliprects) {
+ UNLOCK_HARDWARE(nv);
+ return;
+ }
+ pbox = dri_drawable->cliprects;
+ nbox = dri_drawable->num_cliprects;
+
+ 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 - dri_drawable->x;
+ sy = pbox->y1 - dri_drawable->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 != dri_drawable->last_sarea_stamp)
+ //nv->last_stamp = dri_drawable->last_sarea_stamp;
+}
+
+void
+nouveau_copy_sub_buffer(dri_drawable_t *dri_drawable, struct pipe_surface *surf, int x, int y, int w, int h)
+{
+ if (surf) {
+ drm_clip_rect_t rect;
+ rect.x1 = x;
+ rect.y1 = y;
+ rect.x2 = x + w;
+ rect.y2 = y + h;
+
+ nouveau_copy_buffer(dri_drawable, surf, &rect);
+ }
+}
+
+void
+nouveau_swap_buffers(dri_drawable_t *dri_drawable, struct pipe_surface *surf)
+{
+ if (surf)
+ nouveau_copy_buffer(dri_drawable, surf, NULL);
+}
+
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h
new file mode 100644
index 0000000000..35e934adba
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_swapbuffers.h
@@ -0,0 +1,10 @@
+#ifndef __NOUVEAU_SWAPBUFFERS_H__
+#define __NOUVEAU_SWAPBUFFERS_H__
+
+extern void nouveau_copy_buffer(dri_drawable_t *, struct pipe_surface *,
+ const drm_clip_rect_t *);
+extern void nouveau_copy_sub_buffer(dri_drawable_t *, struct pipe_surface *,
+ int x, int y, int w, int h);
+extern void nouveau_swap_buffers(dri_drawable_t *, struct pipe_surface *);
+
+#endif
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c
new file mode 120000
index 0000000000..ce4052d557
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_winsys.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c
new file mode 100644
index 0000000000..4f6ac9cad0
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c
@@ -0,0 +1,260 @@
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_inlines.h"
+#include "util/u_memory.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;
+ dri_drawable_t *dri_drawable = nv->dri_drawable;
+
+ nouveau_copy_buffer(dri_drawable, surf, NULL);
+}
+
+static const char *
+nouveau_get_name(struct pipe_winsys *pws)
+{
+ return "Nouveau/DRI";
+}
+
+static struct pipe_surface *
+nouveau_surface_alloc(struct pipe_winsys *ws)
+{
+ struct pipe_surface *surf;
+
+ surf = CALLOC_STRUCT(pipe_surface);
+ if (!surf)
+ return NULL;
+
+ surf->refcount = 1;
+ surf->winsys = ws;
+ return surf;
+}
+
+/* Borrowed from Mesa's xm_winsys */
+static unsigned int
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+static int
+nouveau_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 = 256;
+
+ 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;
+ surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * surface->nblocksy);
+
+ return 0;
+}
+
+static void
+nouveau_surface_release(struct pipe_winsys *ws, struct pipe_surface **s)
+{
+ struct pipe_surface *surf = *s;
+
+ *s = NULL;
+ if (--surf->refcount <= 0) {
+ if (surf->buffer)
+ winsys_buffer_reference(ws, &surf->buffer, NULL);
+ free(surf);
+ }
+}
+
+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;
+ }
+
+ 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->surface_alloc = nouveau_surface_alloc;
+ pws->surface_alloc_storage = nouveau_surface_alloc_storage;
+ pws->surface_release = nouveau_surface_release;
+
+ 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/g3dvl/nouveau/nouveau_winsys_pipe.h b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h
new file mode 120000
index 0000000000..9d9460883e
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.h
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_winsys_pipe.h \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c
new file mode 120000
index 0000000000..ec613ecbf6
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_softpipe.c
@@ -0,0 +1 @@
+../../drm/nouveau/nouveau_winsys_softpipe.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c b/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c
new file mode 120000
index 0000000000..4455d8f924
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nv04_surface.c
@@ -0,0 +1 @@
+../../drm/nouveau/nv04_surface.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c b/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c
new file mode 120000
index 0000000000..19f102001e
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/nouveau/nv50_surface.c
@@ -0,0 +1 @@
+../../drm/nouveau/nv50_surface.c \ No newline at end of file
diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h
new file mode 100644
index 0000000000..c83db28dd9
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/vl_winsys.h
@@ -0,0 +1,14 @@
+#ifndef vl_winsys_h
+#define vl_winsys_h
+
+#include <X11/Xlib.h>
+
+struct pipe_context;
+
+struct pipe_context* create_pipe_context(Display *display, int screen);
+int destroy_pipe_context(struct pipe_context *pipe);
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable);
+int unbind_pipe_drawable(struct pipe_context *pipe);
+
+#endif
+
diff --git a/src/gallium/winsys/g3dvl/xsp_winsys.c b/src/gallium/winsys/g3dvl/xsp_winsys.c
new file mode 100644
index 0000000000..68be2c2ea3
--- /dev/null
+++ b/src/gallium/winsys/g3dvl/xsp_winsys.c
@@ -0,0 +1,336 @@
+#include "vl_winsys.h"
+#include <X11/Xutil.h>
+#include <pipe/p_winsys.h>
+#include <pipe/p_state.h>
+#include <pipe/p_inlines.h>
+#include <util/u_memory.h>
+#include <softpipe/sp_winsys.h>
+
+/* pipe_winsys implementation */
+
+struct xsp_pipe_winsys
+{
+ struct pipe_winsys base;
+ XImage fbimage;
+};
+
+struct xsp_context
+{
+ Display *display;
+ int screen;
+ Drawable drawable;
+ int drawable_bound;
+};
+
+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;
+ surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * surface->nblocksy);
+
+ 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)
+ {
+ winsys_buffer_reference(pws, &s->buffer, NULL);
+ free(s);
+ }
+
+ *surface = NULL;
+}
+
+static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
+{
+ assert(pws);
+ assert(ptr);
+ assert(fence);
+}
+
+static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
+{
+ assert(pws);
+ assert(fence);
+
+ return 0;
+}
+
+static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
+{
+ assert(pws);
+ assert(fence);
+
+ return 0;
+}
+
+static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
+{
+ struct xsp_pipe_winsys *xsp_winsys;
+ struct xsp_context *xsp_context;
+
+ assert(pws);
+ assert(surface);
+ assert(context_private);
+
+ xsp_winsys = (struct xsp_pipe_winsys*)pws;
+ xsp_context = (struct xsp_context*)context_private;
+
+ if (!xsp_context->drawable_bound)
+ return;
+
+ 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_context->display,
+ xsp_context->drawable,
+ XDefaultGC(xsp_context->display, xsp_context->screen),
+ &xsp_winsys->fbimage,
+ 0,
+ 0,
+ 0,
+ 0,
+ surface->width,
+ surface->height
+ );
+ XFlush(xsp_context->display);
+ pipe_surface_unmap(surface);
+}
+
+static const char* xsp_get_name(struct pipe_winsys *pws)
+{
+ assert(pws);
+ return "X11 SoftPipe";
+}
+
+/* Show starts here */
+
+int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
+{
+ struct xsp_context *xsp_context;
+
+ assert(pipe);
+
+ xsp_context = pipe->priv;
+ xsp_context->drawable = drawable;
+ xsp_context->drawable_bound = 1;
+
+ return 0;
+}
+
+int unbind_pipe_drawable(struct pipe_context *pipe)
+{
+ struct xsp_context *xsp_context;
+
+ assert(pipe);
+
+ xsp_context = pipe->priv;
+ xsp_context->drawable_bound = 0;
+
+ return 0;
+}
+
+struct pipe_context* create_pipe_context(Display *display, int screen)
+{
+ struct xsp_pipe_winsys *xsp_winsys;
+ struct xsp_context *xsp_context;
+ struct pipe_screen *sp_screen;
+ struct pipe_context *sp_pipe;
+
+ 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.fence_reference = xsp_fence_reference;
+ xsp_winsys->base.fence_signalled = xsp_fence_signalled;
+ xsp_winsys->base.fence_finish = xsp_fence_finish;
+ xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
+ xsp_winsys->base.get_name = xsp_get_name;
+
+ {
+ /* 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_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
+ sp_pipe = softpipe_create(sp_screen, (struct pipe_winsys*)xsp_winsys, NULL);
+
+ xsp_context = calloc(1, sizeof(struct xsp_context));
+ xsp_context->display = display;
+ xsp_context->screen = screen;
+
+ sp_pipe->priv = xsp_context;
+
+ return sp_pipe;
+}
+
+int destroy_pipe_context(struct pipe_context *pipe)
+{
+ struct pipe_screen *screen;
+ struct pipe_winsys *winsys;
+
+ assert(pipe);
+
+ screen = pipe->screen;
+ winsys = pipe->winsys;
+ free(pipe->priv);
+ pipe->destroy(pipe);
+ screen->destroy(screen);
+ free(winsys);
+
+ return 0;
+}
diff --git a/src/libXvMC/Makefile b/src/libXvMC/Makefile
new file mode 100644
index 0000000000..4de26e9620
--- /dev/null
+++ b/src/libXvMC/Makefile
@@ -0,0 +1,73 @@
+TARGET = libXvMCg3dvl.so
+SONAME = libXvMCg3dvl.so.1
+GALLIUMDIR = ../gallium
+
+OBJECTS = block.o surface.o context.o subpicture.o attributes.o
+
+ifeq (${DRIVER}, softpipe)
+OBJECTS += ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
+endif
+
+CFLAGS += -g -fPIC -Wall \
+ -I${GALLIUMDIR}/state_trackers/g3dvl \
+ -I${GALLIUMDIR}/winsys/g3dvl \
+ -I${GALLIUMDIR}/include \
+ -I${GALLIUMDIR}/auxiliary \
+ -I${GALLIUMDIR}/drivers
+
+ifeq (${DRIVER}, softpipe)
+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
+else
+LDFLAGS += -L${GALLIUMDIR}/state_trackers/g3dvl \
+ -L${GALLIUMDIR}/winsys/g3dvl/nouveau \
+ -L${GALLIUMDIR}/auxiliary/util
+endif
+
+ifeq (${DRIVER}, softpipe)
+LIBS += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lm
+else
+LIBS += -lg3dvl -lnouveau_dri -lutil
+endif
+
+#############################################
+
+ifeq (${DRIVER}, softpipe)
+.PHONY = all clean g3dvl
+else
+.PHONY = all clean g3dvl nouveau_winsys
+endif
+
+all: ${TARGET}
+
+ifeq (${DRIVER}, softpipe)
+${TARGET}: ${OBJECTS} g3dvl
+ $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
+
+g3dvl:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
+
+clean:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
+else
+${TARGET}: ${OBJECTS} g3dvl nouveau_winsys
+ $(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
+
+g3dvl:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
+
+nouveau_winsys:
+ cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE}
+
+clean:
+ cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
+ cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE} clean
+ rm -rf ${OBJECTS} ${TARGET}
+endif
diff --git a/src/libXvMC/attributes.c b/src/libXvMC/attributes.c
new file mode 100644
index 0000000000..674524b8b8
--- /dev/null
+++ b/src/libXvMC/attributes.c
@@ -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
index 0000000000..328b035576
--- /dev/null
+++ b/src/libXvMC/block.c
@@ -0,0 +1,79 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+
+#define BLOCK_SIZE (64 * 2)
+
+Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
+{
+ struct vlContext *vl_ctx;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ vl_ctx = context->privData;
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ 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 vlContext *vl_ctx;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (num_blocks == 0)
+ return BadValue;
+
+ assert(blocks);
+
+ vl_ctx = context->privData;
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ 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
index 0000000000..698410d4c2
--- /dev/null
+++ b/src/libXvMC/context.c
@@ -0,0 +1,201 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMClib.h>
+#include <pipe/p_context.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+#include <vl_winsys.h>
+
+static Status Validate
+(
+ Display *display,
+ XvPortID port,
+ int surface_type_id,
+ unsigned int width,
+ unsigned int height,
+ int flags,
+ int *found_port,
+ int *chroma_format,
+ int *mc_type
+)
+{
+ 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);
+
+ *found_port = 0;
+
+ 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;
+ *mc_type = surface_info[k].mc_type;
+ }
+ }
+
+ 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 vlProfile ProfileToVL(int xvmc_profile)
+{
+ if (xvmc_profile & XVMC_MPEG_1)
+ assert(0);
+ else if (xvmc_profile & XVMC_MPEG_2)
+ return vlProfileMpeg2Main;
+ else if (xvmc_profile & XVMC_H263)
+ assert(0);
+ else if (xvmc_profile & XVMC_MPEG_4)
+ assert(0);
+ else
+ assert(0);
+
+ return -1;
+}
+
+static enum vlEntryPoint EntryToVL(int xvmc_entry)
+{
+ return xvmc_entry & XVMC_IDCT ? vlEntryPointIDCT : vlEntryPointMC;
+}
+
+static enum vlFormat FormatToVL(int xvmc_format)
+{
+ switch (xvmc_format)
+ {
+ case XVMC_CHROMA_FORMAT_420:
+ return vlFormatYCbCr420;
+ case XVMC_CHROMA_FORMAT_422:
+ return vlFormatYCbCr422;
+ case XVMC_CHROMA_FORMAT_444:
+ return vlFormatYCbCr444;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
+{
+ int found_port;
+ int chroma_format;
+ int mc_type;
+ Status ret;
+ struct vlDisplay *vl_dpy;
+ struct vlScreen *vl_scrn;
+ struct vlContext *vl_ctx;
+ struct pipe_context *pipe;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
+
+ /* XXX: Success and XvBadPort have the same value */
+ if (ret != Success || !found_port)
+ return ret;
+
+ /* XXX: Assumes default screen, should check which screen port is on */
+ pipe = create_pipe_context(display, XDefaultScreen(display));
+
+ assert(pipe);
+
+ vlCreateDisplay(display, &vl_dpy);
+ vlCreateScreen(vl_dpy, XDefaultScreen(display), pipe->screen, &vl_scrn);
+ vlCreateContext
+ (
+ vl_scrn,
+ pipe,
+ width,
+ height,
+ FormatToVL(chroma_format),
+ ProfileToVL(mc_type),
+ EntryToVL(mc_type),
+ &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 vlContext *vl_ctx;
+ struct pipe_context *pipe;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ vl_ctx = context->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ pipe = vlGetPipeContext(vl_ctx);
+ vlDestroyContext(vl_ctx);
+ destroy_pipe_context(pipe);
+
+ return Success;
+}
diff --git a/src/libXvMC/subpicture.c b/src/libXvMC/subpicture.c
new file mode 100644
index 0000000000..c8f70c90d0
--- /dev/null
+++ b/src/libXvMC/subpicture.c
@@ -0,0 +1,215 @@
+#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
+)
+{
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+
+ assert(subpicture);
+
+ if (width > 2048 || height > 2048)
+ return BadValue;
+
+ if (xvimage_id != 123)
+ return BadMatch;
+
+ subpicture->subpicture_id = XAllocID(display);
+ subpicture->context_id = context->context_id;
+ subpicture->xvimage_id = xvimage_id;
+ subpicture->width = width;
+ subpicture->height = height;
+ subpicture->num_palette_entries = 0;
+ subpicture->entry_bytes = 0;
+ subpicture->component_order[0] = 0;
+ subpicture->component_order[1] = 0;
+ subpicture->component_order[2] = 0;
+ subpicture->component_order[3] = 0;
+ /* TODO: subpicture->privData = ;*/
+
+ return Success;
+}
+
+Status XvMCClearSubpicture
+(
+ Display *display,
+ XvMCSubpicture *subpicture,
+ short x,
+ short y,
+ unsigned short width,
+ unsigned short height,
+ unsigned int color
+)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ /* TODO: Assert clear rect is within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCCompositeSubpicture
+(
+ Display *display,
+ XvMCSubpicture *subpicture,
+ XvImage *image,
+ short srcx,
+ short srcy,
+ unsigned short width,
+ unsigned short height,
+ short dstx,
+ short dsty
+)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(image);
+
+ if (subpicture->xvimage_id != image->id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+
+ return Success;
+}
+
+Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return BadImplementation;
+}
+
+Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(palette);
+
+ /* We don't support paletted subpictures */
+ return BadMatch;
+}
+
+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
+)
+{
+ assert(display);
+
+ if (!target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (target_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+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
+)
+{
+ assert(display);
+
+ if (!source_surface || !target_surface)
+ return XvMCBadSurface;
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ if (source_surface->context_id != subpicture->context_id)
+ return BadMatch;
+
+ /* TODO: Assert rects are within bounds? Or clip? */
+ return Success;
+}
+
+Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ return Success;
+}
+
+Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status)
+{
+ assert(display);
+
+ if (!subpicture)
+ return XvMCBadSubpicture;
+
+ assert(status);
+
+ /* TODO */
+ *status = 0;
+
+ return Success;
+}
+
diff --git a/src/libXvMC/surface.c b/src/libXvMC/surface.c
new file mode 100644
index 0000000000..6031b39d10
--- /dev/null
+++ b/src/libXvMC/surface.c
@@ -0,0 +1,350 @@
+#include <assert.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XvMC.h>
+#include <vl_display.h>
+#include <vl_screen.h>
+#include <vl_context.h>
+#include <vl_surface.h>
+#include <vl_types.h>
+
+static enum vlMacroBlockType TypeToVL(int xvmc_mb_type)
+{
+ if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
+ return vlMacroBlockTypeIntra;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
+ return vlMacroBlockTypeFwdPredicted;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
+ return vlMacroBlockTypeBkwdPredicted;
+ if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
+ return vlMacroBlockTypeBiPredicted;
+
+ assert(0);
+
+ return -1;
+}
+
+static enum vlPictureType PictureToVL(int xvmc_pic)
+{
+ switch (xvmc_pic)
+ {
+ case XVMC_TOP_FIELD:
+ return vlPictureTypeTopField;
+ case XVMC_BOTTOM_FIELD:
+ return vlPictureTypeBottomField;
+ case XVMC_FRAME_PICTURE:
+ return vlPictureTypeFrame;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+static enum vlMotionType MotionToVL(int xvmc_motion_type, int xvmc_dct_type)
+{
+ switch (xvmc_motion_type)
+ {
+ case XVMC_PREDICTION_FRAME:
+ return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ? vlMotionType16x8 : vlMotionTypeFrame;
+ case XVMC_PREDICTION_FIELD:
+ return vlMotionTypeField;
+ case XVMC_PREDICTION_DUAL_PRIME:
+ return vlMotionTypeDualPrime;
+ default:
+ assert(0);
+ }
+
+ return -1;
+}
+
+Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
+{
+ struct vlContext *vl_ctx;
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!context)
+ return XvMCBadContext;
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_ctx = context->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ vlCreateSurface
+ (
+ vlContextGetScreen(vl_ctx),
+ context->width,
+ context->height,
+ vlGetPictureFormat(vl_ctx),
+ &vl_sfc
+ );
+
+ vlBindToContext(vl_sfc, vl_ctx);
+
+ 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 vlContext *vl_ctx;
+ struct vlSurface *target_vl_surface;
+ struct vlSurface *past_vl_surface;
+ struct vlSurface *future_vl_surface;
+ struct vlMpeg2MacroBlockBatch batch;
+ struct vlMpeg2MacroBlock vl_macroblocks[num_macroblocks];
+ 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 == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
+
+ 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(context->context_id == target_surface->context_id);
+ assert(!past_surface || context->context_id == past_surface->context_id);
+ assert(!future_surface || context->context_id == future_surface->context_id);
+
+ 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);
+
+ batch.past_surface = past_vl_surface;
+ batch.future_surface = future_vl_surface;
+ batch.picture_type = PictureToVL(picture_structure);
+ batch.field_order = flags & XVMC_SECOND_FIELD ? vlFieldOrderSecond : vlFieldOrderFirst;
+ batch.num_macroblocks = num_macroblocks;
+ batch.macroblocks = vl_macroblocks;
+
+ for (i = 0; i < num_macroblocks; ++i)
+ {
+ unsigned int j = first_macroblock + i;
+
+ unsigned int k, l, m;
+
+ batch.macroblocks[i].mbx = macroblocks->macro_blocks[j].x;
+ batch.macroblocks[i].mby = macroblocks->macro_blocks[j].y;
+ batch.macroblocks[i].mb_type = TypeToVL(macroblocks->macro_blocks[j].macroblock_type);
+ if (batch.macroblocks[i].mb_type != vlMacroBlockTypeIntra)
+ batch.macroblocks[i].mo_type = MotionToVL(macroblocks->macro_blocks[j].motion_type, macroblocks->macro_blocks[j].dct_type);
+ batch.macroblocks[i].dct_type = macroblocks->macro_blocks[j].dct_type == XVMC_DCT_TYPE_FIELD ? vlDCTTypeFieldCoded : vlDCTTypeFrameCoded;
+
+ for (k = 0; k < 2; ++k)
+ for (l = 0; l < 2; ++l)
+ for (m = 0; m < 2; ++m)
+ batch.macroblocks[i].PMV[k][l][m] = macroblocks->macro_blocks[j].PMV[k][l][m];
+
+ batch.macroblocks[i].cbp = macroblocks->macro_blocks[j].coded_block_pattern;
+ batch.macroblocks[i].blocks = blocks->blocks + (macroblocks->macro_blocks[j].index * 64);
+ }
+
+ vlRenderMacroBlocksMpeg2(&batch, target_vl_surface);
+
+ return Success;
+}
+
+Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceFlush(vl_sfc);
+
+ return Success;
+}
+
+Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceSync(vl_sfc);
+
+ return Success;
+}
+
+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 vlSurface *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;
+
+ vlPutPicture(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, width, height, PictureToVL(flags));
+
+ return Success;
+}
+
+Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
+{
+ struct vlSurface *vl_sfc;
+ enum vlResourceStatus res_status;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ assert(status);
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlSurfaceGetStatus(vl_sfc, &res_status);
+
+ switch (res_status)
+ {
+ case vlResourceStatusFree:
+ {
+ *status = 0;
+ break;
+ }
+ case vlResourceStatusRendering:
+ {
+ *status = XVMC_RENDERING;
+ break;
+ }
+ case vlResourceStatusDisplaying:
+ {
+ *status = XVMC_DISPLAYING;
+ break;
+ }
+ default:
+ assert(0);
+ }
+
+ return Success;
+}
+
+Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ vlDestroySurface(vl_sfc);
+
+ return Success;
+}
+
+Status XvMCHideSurface(Display *display, XvMCSurface *surface)
+{
+ struct vlSurface *vl_sfc;
+
+ assert(display);
+
+ if (!surface)
+ return XvMCBadSurface;
+
+ vl_sfc = surface->privData;
+
+ assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
+
+ /* No op, only for overlaid rendering */
+
+ return Success;
+}
diff --git a/src/libXvMC/tests/.gitignore b/src/libXvMC/tests/.gitignore
new file mode 100644
index 0000000000..e1d2f9023d
--- /dev/null
+++ b/src/libXvMC/tests/.gitignore
@@ -0,0 +1,5 @@
+test_context
+test_surface
+test_blocks
+test_rendering
+xvmc_bench
diff --git a/src/libXvMC/tests/Makefile b/src/libXvMC/tests/Makefile
new file mode 100644
index 0000000000..de095161d2
--- /dev/null
+++ b/src/libXvMC/tests/Makefile
@@ -0,0 +1,27 @@
+CFLAGS += -g -Wall
+LDFLAGS +=
+LIBS += -lXvMCW -lXvMC -lXv
+
+#############################################
+
+.PHONY = all clean
+
+all: test_context test_surface test_blocks test_rendering xvmc_bench
+
+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}
+
+xvmc_bench: xvmc_bench.o testlib.o
+ $(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
+
+clean:
+ rm -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench
diff --git a/src/libXvMC/tests/test_blocks.c b/src/libXvMC/tests/test_blocks.c
new file mode 100644
index 0000000000..dc80adfa65
--- /dev/null
+++ b/src/libXvMC/tests/test_blocks.c
@@ -0,0 +1,84 @@
+#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 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 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
index 0000000000..53f7449cd0
--- /dev/null
+++ b/src/libXvMC/tests/test_context.c
@@ -0,0 +1,92 @@
+#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);
+ }
+
+ /* Test NULL context */
+ /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */
+ assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext);
+ /* Test invalid port */
+ /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */
+ assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort);
+ /* Test invalid surface */
+ assert(XvMCCreateContext(display, port_num, -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
index 0000000000..1e7467a3aa
--- /dev/null
+++ b/src/libXvMC/tests/test_rendering.c
@@ -0,0 +1,287 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include "testlib.h"
+
+#define BLOCK_WIDTH 8
+#define BLOCK_HEIGHT 8
+#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
+#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define INPUT_WIDTH 16
+#define INPUT_HEIGHT 16
+#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
+#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
+#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
+
+#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
+#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
+#define DEFAULT_ACCEPTABLE_ERR 0.01
+
+void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
+{
+ int fail = 0;
+ int i;
+
+ *output_width = DEFAULT_OUTPUT_WIDTH;
+ *output_height = DEFAULT_OUTPUT_WIDTH;
+ *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
+ *prompt = 1;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-w"))
+ {
+ if (sscanf(argv[++i], "%u", output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-h"))
+ {
+ if (sscanf(argv[++i], "%u", output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-e"))
+ {
+ if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
+ fail = 1;
+ }
+ else if (strcmp(argv[i], "-n"))
+ *prompt = 0;
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-w <width>\tOutput width\n"
+ "\t-h <height>\tOutput height\n"
+ "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
+ "\t-n\tDon't prompt for quit\n",
+ argv[0]
+ );
+}
+
+void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal)
+{
+ unsigned int x, y;
+ unsigned int range = stop - start;
+
+ if (horizontal)
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1)));
+ }
+ else
+ {
+ for (y = 0; y < BLOCK_HEIGHT; ++y)
+ for (x = 0; x < BLOCK_WIDTH; ++x)
+ block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1)));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ unsigned int output_width;
+ unsigned int output_height;
+ double acceptable_error;
+ int prompt;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ int mbx, mby, bx, by;
+ XvMCMacroBlock *mb;
+ short *blocks;
+ int quit = 0;
+
+ ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt);
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ INPUT_WIDTH,
+ INPUT_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, output_width, output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
+
+ mb = mb_array.macro_blocks;
+ blocks = block_array.blocks;
+
+ for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
+ for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
+ {
+ mb->x = mbx;
+ mb->y = mby;
+ mb->macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb->dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb->coded_block_pattern = 0x3F;
+
+ mb++;
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
+ {
+ const int start = 16, stop = 235, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+
+ for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
+ for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
+ {
+ const int start = 16, stop = 240, range = stop - start;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+
+ Gradient
+ (
+ blocks,
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
+ (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
+ 1
+ );
+
+ blocks += BLOCK_SIZE;
+ }
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ /* Test NULL context */
+ assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
+ /* Test NULL surface */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
+ /* Test bad picture structure */
+ assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
+ /* Test valid params */
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
+
+ /* Test NULL surface */
+ assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
+ /* Test bad window */
+ /* XXX: 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);*/
+
+ if (prompt)
+ {
+ puts("Press any button to quit...");
+
+ while (!quit)
+ {
+ if (XPending(display) > 0)
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch (event.type)
+ {
+ case Expose:
+ {
+ /* Test valid params */
+ assert
+ (
+ XvMCPutSurface
+ (
+ display, &surface, window,
+ 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
+ 0, 0, output_width, output_height,
+ XVMC_FRAME_PICTURE
+ ) == Success
+ );
+ break;
+ }
+ case KeyPress:
+ {
+ quit = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ 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
index 0000000000..25ebdcc4fc
--- /dev/null
+++ b/src/libXvMC/tests/test_surface.c
@@ -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
index 0000000000..59a03ca813
--- /dev/null
+++ b/src/libXvMC/tests/testlib.c
@@ -0,0 +1,119 @@
+#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;
+}
+
+unsigned int align(unsigned int value, unsigned int alignment)
+{
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+/* From the glibc manual */
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
+{
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_usec < y->tv_usec)
+ {
+ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+ y->tv_usec -= 1000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if (x->tv_usec - y->tv_usec > 1000000)
+ {
+ int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+ y->tv_usec += 1000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /*
+ * Compute the time remaining to wait.
+ * tv_usec is certainly positive.
+ */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_usec = x->tv_usec - y->tv_usec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
diff --git a/src/libXvMC/tests/testlib.h b/src/libXvMC/tests/testlib.h
new file mode 100644
index 0000000000..af71ad74e1
--- /dev/null
+++ b/src/libXvMC/tests/testlib.h
@@ -0,0 +1,42 @@
+#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 <sys/time.h>
+#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
+);
+
+unsigned int align(unsigned int value, unsigned int alignment);
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y);
+
+#endif
diff --git a/src/libXvMC/tests/xvmc_bench.c b/src/libXvMC/tests/xvmc_bench.c
new file mode 100644
index 0000000000..d5a39ecf17
--- /dev/null
+++ b/src/libXvMC/tests/xvmc_bench.c
@@ -0,0 +1,271 @@
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <sys/time.h>
+#include "testlib.h"
+
+#define MACROBLOCK_WIDTH 16
+#define MACROBLOCK_HEIGHT 16
+#define BLOCKS_PER_MACROBLOCK 6
+
+#define DEFAULT_INPUT_WIDTH 720
+#define DEFAULT_INPUT_HEIGHT 480
+#define DEFAULT_REPS 100
+
+#define PIPELINE_STEP_MC 1
+#define PIPELINE_STEP_CSC 2
+#define PIPELINE_STEP_SWAP 4
+
+#define MB_TYPE_I 1
+#define MB_TYPE_P 2
+#define MB_TYPE_B 4
+
+struct Config
+{
+ unsigned int input_width;
+ unsigned int input_height;
+ unsigned int output_width;
+ unsigned int output_height;
+ unsigned int pipeline;
+ unsigned int mb_types;
+ unsigned int reps;
+};
+
+void ParseArgs(int argc, char **argv, struct Config *config)
+{
+ int fail = 0;
+ int i;
+
+ config->input_width = DEFAULT_INPUT_WIDTH;
+ config->input_height = DEFAULT_INPUT_HEIGHT;
+ config->output_width = 0;
+ config->output_height = 0;
+ config->pipeline = 0;
+ config->mb_types = 0;
+ config->reps = DEFAULT_REPS;
+
+ for (i = 1; i < argc && !fail; ++i)
+ {
+ if (!strcmp(argv[i], "-iw"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ih"))
+ {
+ if (sscanf(argv[++i], "%u", &config->input_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-ow"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_width) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-oh"))
+ {
+ if (sscanf(argv[++i], "%u", &config->output_height) != 1)
+ fail = 1;
+ }
+ else if (!strcmp(argv[i], "-p"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (!strcmp(token, "mc"))
+ config->pipeline |= PIPELINE_STEP_MC;
+ else if (!strcmp(token, "csc"))
+ config->pipeline |= PIPELINE_STEP_CSC;
+ else if (!strcmp(token, "swp"))
+ config->pipeline |= PIPELINE_STEP_SWAP;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-mb"))
+ {
+ char *token = strtok(argv[++i], ",");
+
+ while (token && !fail)
+ {
+ if (strcmp(token, "i"))
+ config->mb_types |= MB_TYPE_I;
+ else if (strcmp(token, "p"))
+ config->mb_types |= MB_TYPE_P;
+ else if (strcmp(token, "b"))
+ config->mb_types |= MB_TYPE_B;
+ else
+ fail = 1;
+
+ if (!fail)
+ token = strtok(NULL, ",");
+ }
+ }
+ else if (!strcmp(argv[i], "-r"))
+ {
+ if (sscanf(argv[++i], "%u", &config->reps) != 1)
+ fail = 1;
+ }
+ else
+ fail = 1;
+ }
+
+ if (fail)
+ error
+ (
+ 1, 0,
+ "Bad argument.\n"
+ "\n"
+ "Usage: %s [options]\n"
+ "\t-iw <width>\tInput width\n"
+ "\t-ih <height>\tInput height\n"
+ "\t-ow <width>\tOutput width\n"
+ "\t-oh <height>\tOutput height\n"
+ "\t-p <pipeline>\tPipeline to test\n"
+ "\t-mb <mb type>\tMacroBlock types to use\n"
+ "\t-r <reps>\tRepetitions\n\n"
+ "\tPipeline steps: mc,csc,swap\n"
+ "\tMB types: i,p,b\n",
+ argv[0]
+ );
+
+ if (config->output_width == 0)
+ config->output_width = config->input_width;
+ if (config->output_height == 0)
+ config->output_height = config->input_height;
+ if (!config->pipeline)
+ config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
+ if (!config->mb_types)
+ config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
+}
+
+int main(int argc, char **argv)
+{
+ struct Config config;
+ Display *display;
+ Window root, window;
+ const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
+ XvPortID port_num;
+ int surface_type_id;
+ unsigned int is_overlay, intra_unsigned;
+ int colorkey;
+ XvMCContext context;
+ XvMCSurface surface;
+ XvMCBlockArray block_array;
+ XvMCMacroBlockArray mb_array;
+ unsigned int mbw, mbh;
+ unsigned int mbx, mby;
+ unsigned int reps;
+ struct timeval start, stop, diff;
+ double diff_secs;
+
+ ParseArgs(argc, argv, &config);
+
+ mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+ mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+
+ display = XOpenDisplay(NULL);
+
+ if (!GetPort
+ (
+ display,
+ config.input_width,
+ config.input_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, config.output_width, config.output_height, 0, 0, colorkey);
+
+ assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
+ assert(XvMCCreateSurface(display, &context, &surface) == Success);
+ assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
+ assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
+
+ for (mby = 0; mby < mbh; ++mby)
+ for (mbx = 0; mbx < mbw; ++mbx)
+ {
+ mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
+ mb_array.macro_blocks[mby * mbw + mbx].y = mby;
+ mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
+ /*mb->motion_type = ;*/
+ /*mb->motion_vertical_field_select = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
+ /*mb->PMV[0][0][0] = ;
+ mb->PMV[0][0][1] = ;
+ mb->PMV[0][1][0] = ;
+ mb->PMV[0][1][1] = ;
+ mb->PMV[1][0][0] = ;
+ mb->PMV[1][0][1] = ;
+ mb->PMV[1][1][0] = ;
+ mb->PMV[1][1][1] = ;*/
+ mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
+ mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
+ }
+
+ XSelectInput(display, window, ExposureMask | KeyPressMask);
+ XMapWindow(display, window);
+ XSync(display, 0);
+
+ gettimeofday(&start, NULL);
+
+ for (reps = 0; reps < config.reps; ++reps)
+ {
+ if (config.pipeline & PIPELINE_STEP_MC)
+ {
+ assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
+ assert(XvMCFlushSurface(display, &surface) == Success);
+ }
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success);
+ }
+
+ gettimeofday(&stop, NULL);
+
+ timeval_subtract(&diff, &stop, &start);
+ diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
+
+ printf("XvMC Benchmark\n");
+ printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
+ printf("Pipeline: ");
+ if (config.pipeline & PIPELINE_STEP_MC)
+ printf("|mc|");
+ if (config.pipeline & PIPELINE_STEP_CSC)
+ printf("|csc|");
+ if (config.pipeline & PIPELINE_STEP_SWAP)
+ printf("|swap|");
+ printf("\n");
+ printf("Reps: %u\n", config.reps);
+ printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
+
+ assert(XvMCDestroyBlocks(display, &block_array) == Success);
+ assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
+ assert(XvMCDestroySurface(display, &surface) == Success);
+ assert(XvMCDestroyContext(display, &context) == Success);
+
+ XvUngrabPort(display, port_num, CurrentTime);
+ XDestroyWindow(display, window);
+ XCloseDisplay(display);
+
+ return 0;
+}
diff --git a/src/mesa/x86-64/glapi_x86-64.S b/src/mesa/x86-64/glapi_x86-64.S
index f8337ff93e..cb34061b36 100644
--- a/src/mesa/x86-64/glapi_x86-64.S
+++ b/src/mesa/x86-64/glapi_x86-64.S
@@ -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)