summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv30/nv30_state_validate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nv30/nv30_state_validate.c')
-rw-r--r--src/gallium/drivers/nv30/nv30_state_validate.c535
1 files changed, 535 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv30/nv30_state_validate.c b/src/gallium/drivers/nv30/nv30_state_validate.c
new file mode 100644
index 00000000000..df0170bb8e4
--- /dev/null
+++ b/src/gallium/drivers/nv30/nv30_state_validate.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ *
+ */
+
+#include "util/u_format.h"
+#include "util/u_math.h"
+#include "util/u_half.h"
+
+#include "nouveau/nv_object.xml.h"
+#include "nv30-40_3d.xml.h"
+#include "nv30_context.h"
+#include "nv30_format.h"
+
+static void
+nv30_validate_fb(struct nv30_context *nv30)
+{
+ struct pipe_screen *pscreen = &nv30->screen->base.base;
+ struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_object *eng3d = nv30->screen->eng3d;
+ uint32_t rt_format;
+ int h = fb->height;
+ int w = fb->width;
+ int x = 0;
+ int y = 0;
+
+ nv30->state.rt_enable = (NV30_3D_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
+ if (nv30->state.rt_enable > 1)
+ nv30->state.rt_enable |= NV30_3D_RT_ENABLE_MRT;
+
+ rt_format = 0;
+ if (fb->nr_cbufs > 0) {
+ struct nv30_miptree *mt = nv30_miptree(fb->cbufs[0]->texture);
+ rt_format |= nv30_format(pscreen, fb->cbufs[0]->format)->hw;
+ rt_format |= mt->ms_mode;
+ if (mt->swizzled)
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ } else {
+ if (fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) > 2)
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
+ }
+
+ if (fb->zsbuf) {
+ rt_format |= nv30_format(pscreen, fb->zsbuf->format)->hw;
+ if (nv30_miptree(fb->zsbuf->texture)->swizzled)
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
+ } else {
+ if (fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) > 2)
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
+ else
+ rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
+ }
+
+ /* hardware rounds down render target offset to 64 bytes, but surfaces
+ * with a size of 2x2 pixel (16bpp) or 1x1 pixel (32bpp) have an
+ * unaligned start aaddress. For these two important square formats
+ * we can hack around this limitation by adjusting the viewport origin
+ */
+ if (nv30->state.rt_enable) {
+ int off = nv30_surface(fb->cbufs[0])->offset & 63;
+ if (off) {
+ x += off / (util_format_get_blocksize(fb->cbufs[0]->format) * 2);
+ w = 16;
+ h = 2;
+ }
+ }
+
+ if (rt_format & NV30_3D_RT_FORMAT_TYPE_SWIZZLED) {
+ rt_format |= util_logbase2(w) << 16;
+ rt_format |= util_logbase2(h) << 24;
+ }
+
+ if (!PUSH_SPACE(push, 64))
+ return;
+ PUSH_RESET(push, BUFCTX_FB);
+
+ BEGIN_NV04(push, SUBC_3D(0x1da4), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
+ PUSH_DATA (push, w << 16);
+ PUSH_DATA (push, h << 16);
+ PUSH_DATA (push, rt_format);
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
+ PUSH_DATA (push, w << 16);
+ PUSH_DATA (push, h << 16);
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 1);
+ PUSH_DATA (push, (y << 16) | x);
+
+ if ((nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR0) || fb->zsbuf) {
+ struct nv30_surface *rsf = nv30_surface(fb->cbufs[0]);
+ struct nv30_surface *zsf = nv30_surface(fb->zsbuf);
+ struct nouveau_bo *rbo, *zbo;
+
+ if (!rsf) rsf = zsf;
+ else if (!zsf) zsf = rsf;
+ rbo = nv30_miptree(rsf->base.texture)->base.bo;
+ zbo = nv30_miptree(zsf->base.texture)->base.bo;
+
+ if (eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
+ PUSH_DATA (push, zsf->pitch);
+ BEGIN_NV04(push, NV40_3D(COLOR0_PITCH), 3);
+ PUSH_DATA (push, rsf->pitch);
+ } else {
+ BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 3);
+ PUSH_DATA (push, (zsf->pitch << 16) | rsf->pitch);
+ }
+ PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), BUFCTX_FB, rbo, rsf->offset & ~63,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ PUSH_MTHDl(push, NV30_3D(ZETA_OFFSET), BUFCTX_FB, zbo, zsf->offset & ~63,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ }
+
+ if (nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR1) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[1]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV30_3D(COLOR1_OFFSET), 2);
+ PUSH_MTHDl(push, NV30_3D(COLOR1_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ PUSH_DATA (push, sf->pitch);
+ }
+
+ if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR2) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[2]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV40_3D(COLOR2_OFFSET), 1);
+ PUSH_MTHDl(push, NV40_3D(COLOR2_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ BEGIN_NV04(push, NV40_3D(COLOR2_PITCH), 1);
+ PUSH_DATA (push, sf->pitch);
+ }
+
+ if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR3) {
+ struct nv30_surface *sf = nv30_surface(fb->cbufs[3]);
+ struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
+
+ BEGIN_NV04(push, NV40_3D(COLOR3_OFFSET), 1);
+ PUSH_MTHDl(push, NV40_3D(COLOR3_OFFSET), BUFCTX_FB, bo, sf->offset,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ BEGIN_NV04(push, NV40_3D(COLOR3_PITCH), 1);
+ PUSH_DATA (push, sf->pitch);
+ }
+}
+
+static void
+nv30_validate_blend_colour(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ float *rgba = nv30->blend_colour.color;
+
+ if (nv30->framebuffer.nr_cbufs) {
+ switch (nv30->framebuffer.cbufs[0]->format) {
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
+ PUSH_DATA (push, (util_float_to_half(rgba[0]) << 0) |
+ (util_float_to_half(rgba[1]) << 16));
+ BEGIN_NV04(push, SUBC_3D(0x037c), 1);
+ PUSH_DATA (push, (util_float_to_half(rgba[2]) << 0) |
+ (util_float_to_half(rgba[3]) << 16));
+ break;
+ default:
+ break;
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
+ PUSH_DATA (push, (float_to_ubyte(rgba[3]) << 24) |
+ (float_to_ubyte(rgba[0]) << 16) |
+ (float_to_ubyte(rgba[1]) << 8) |
+ (float_to_ubyte(rgba[2]) << 0));
+}
+
+static void
+nv30_validate_stencil_ref(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(0)), 1);
+ PUSH_DATA (push, nv30->stencil_ref.ref_value[0]);
+ BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(1)), 1);
+ PUSH_DATA (push, nv30->stencil_ref.ref_value[1]);
+}
+
+static void
+nv30_validate_stipple(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
+ PUSH_DATAp(push, nv30->stipple.stipple, 32);
+}
+
+static void
+nv30_validate_scissor(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct pipe_scissor_state *s = &nv30->scissor;
+
+ if (!(nv30->dirty & NV30_NEW_SCISSOR) &&
+ nv30->rast->pipe.scissor != nv30->state.scissor_off)
+ return;
+ nv30->state.scissor_off = !nv30->rast->pipe.scissor;
+
+ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
+ if (nv30->rast->pipe.scissor) {
+ PUSH_DATA (push, ((s->maxx - s->minx) << 16) | s->minx);
+ PUSH_DATA (push, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ PUSH_DATA (push, 0x10000000);
+ PUSH_DATA (push, 0x10000000);
+ }
+}
+
+static void
+nv30_validate_viewport(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct pipe_viewport_state *vp = &nv30->viewport;
+
+ BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
+ PUSH_DATAf(push, vp->translate[0]);
+ PUSH_DATAf(push, vp->translate[1]);
+ PUSH_DATAf(push, vp->translate[2]);
+ PUSH_DATAf(push, vp->translate[3]);
+ PUSH_DATAf(push, vp->scale[0]);
+ PUSH_DATAf(push, vp->scale[1]);
+ PUSH_DATAf(push, vp->scale[2]);
+ PUSH_DATAf(push, vp->scale[3]);
+ BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
+ PUSH_DATAf(push, vp->translate[2] - fabsf(vp->scale[2]));
+ PUSH_DATAf(push, vp->translate[2] + fabsf(vp->scale[2]));
+}
+
+static void
+nv30_validate_clip(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ unsigned i;
+ uint32_t clpd_enable = 0;
+
+ for (i = 0; i < 6; i++) {
+ if (nv30->rast->pipe.clip_plane_enable & (1 << i)) {
+ if (nv30->dirty & NV30_NEW_CLIP) {
+ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
+ PUSH_DATA (push, i);
+ PUSH_DATAp(push, nv30->clip.ucp[i], 4);
+ }
+
+ clpd_enable |= 1 << (1 + 4*i);
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
+ PUSH_DATA (push, clpd_enable);
+}
+
+static void
+nv30_validate_blend(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->blend->size);
+ PUSH_DATAp(push, nv30->blend->data, nv30->blend->size);
+}
+
+static void
+nv30_validate_zsa(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->zsa->size);
+ PUSH_DATAp(push, nv30->zsa->data, nv30->zsa->size);
+}
+
+static void
+nv30_validate_rasterizer(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+
+ PUSH_SPACE(push, nv30->rast->size);
+ PUSH_DATAp(push, nv30->rast->data, nv30->rast->size);
+}
+
+static void
+nv30_validate_multisample(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
+ struct pipe_blend_state *blend = &nv30->blend->pipe;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ uint32_t ctrl = nv30->sample_mask << 16;
+
+ if (blend->alpha_to_one)
+ ctrl |= 0x00000100;
+ if (blend->alpha_to_coverage)
+ ctrl |= 0x00000010;
+ if (rasterizer->multisample)
+ ctrl |= 0x00000001;
+
+ BEGIN_NV04(push, NV30_3D(MULTISAMPLE_CONTROL), 1);
+ PUSH_DATA (push, ctrl);
+}
+
+static void
+nv30_validate_fragment(struct nv30_context *nv30)
+{
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+
+ BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
+ PUSH_DATA (push, nv30->state.rt_enable & ~fp->rt_enable);
+ BEGIN_NV04(push, NV30_3D(COORD_CONVENTIONS), 1);
+ PUSH_DATA (push, fp->coord_conventions | nv30->framebuffer.height);
+}
+
+static void
+nv30_validate_point_coord(struct nv30_context *nv30)
+{
+ struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nv30_fragprog *fp = nv30->fragprog.program;
+ uint32_t hw = 0x00000000;
+
+ if (rasterizer) {
+ hw |= (nv30->rast->pipe.sprite_coord_enable & 0xff) << 8;
+ if (fp)
+ hw |= fp->point_sprite_control;
+
+ if (rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) {
+ if (hw)
+ nv30->draw_flags |= NV30_NEW_RASTERIZER;
+ } else
+ if (rasterizer->point_quad_rasterization) {
+ hw |= NV30_3D_POINT_SPRITE_ENABLE;
+ }
+ }
+
+ BEGIN_NV04(push, NV30_3D(POINT_SPRITE), 1);
+ PUSH_DATA (push, hw);
+}
+
+struct state_validate {
+ void (*func)(struct nv30_context *);
+ uint32_t mask;
+};
+
+static struct state_validate hwtnl_validate_list[] = {
+ { nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_blend, NV30_NEW_BLEND },
+ { nv30_validate_zsa, NV30_NEW_ZSA },
+ { nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
+ { nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
+ NV30_NEW_RASTERIZER },
+ { nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
+ NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
+ { nv30_validate_stipple, NV30_NEW_STIPPLE },
+ { nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
+ { nv30_validate_viewport, NV30_NEW_VIEWPORT },
+ { nv30_validate_clip, NV30_NEW_CLIP },
+ { nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
+ { nv30_vertprog_validate, NV30_NEW_VERTPROG | NV30_NEW_VERTCONST |
+ NV30_NEW_FRAGPROG | NV30_NEW_RASTERIZER },
+ { nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
+ { nv30_validate_point_coord, NV30_NEW_RASTERIZER | NV30_NEW_FRAGPROG },
+ { nv30_fragtex_validate, NV30_NEW_FRAGTEX },
+ { nv40_verttex_validate, NV30_NEW_VERTTEX },
+ { nv30_vbo_validate, NV30_NEW_VERTEX | NV30_NEW_ARRAYS },
+ {}
+};
+
+#define NV30_SWTNL_MASK (NV30_NEW_VIEWPORT | \
+ NV30_NEW_CLIP | \
+ NV30_NEW_VERTPROG | \
+ NV30_NEW_VERTCONST | \
+ NV30_NEW_VERTTEX | \
+ NV30_NEW_VERTEX | \
+ NV30_NEW_ARRAYS)
+
+static struct state_validate swtnl_validate_list[] = {
+ { nv30_validate_fb, NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_blend, NV30_NEW_BLEND },
+ { nv30_validate_zsa, NV30_NEW_ZSA },
+ { nv30_validate_rasterizer, NV30_NEW_RASTERIZER },
+ { nv30_validate_multisample, NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
+ NV30_NEW_RASTERIZER },
+ { nv30_validate_blend_colour, NV30_NEW_BLEND_COLOUR |
+ NV30_NEW_FRAMEBUFFER },
+ { nv30_validate_stencil_ref, NV30_NEW_STENCIL_REF },
+ { nv30_validate_stipple, NV30_NEW_STIPPLE },
+ { nv30_validate_scissor, NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
+ { nv30_fragprog_validate, NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
+ { nv30_validate_fragment, NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
+ { nv30_fragtex_validate, NV30_NEW_FRAGTEX },
+ {}
+};
+
+static void
+nv30_state_context_switch(struct nv30_context *nv30)
+{
+ struct nv30_context *prev = nv30->screen->cur_ctx;
+
+ if (prev)
+ nv30->state = prev->state;
+ nv30->dirty = NV30_NEW_ALL;
+
+ if (!nv30->vertex)
+ nv30->dirty &= ~(NV30_NEW_VERTEX | NV30_NEW_ARRAYS);
+
+ if (!nv30->vertprog.program)
+ nv30->dirty &= ~NV30_NEW_VERTPROG;
+ if (!nv30->fragprog.program)
+ nv30->dirty &= ~NV30_NEW_FRAGPROG;
+
+ if (!nv30->blend)
+ nv30->dirty &= ~NV30_NEW_BLEND;
+ if (!nv30->rast)
+ nv30->dirty &= ~NV30_NEW_RASTERIZER;
+ if (!nv30->zsa)
+ nv30->dirty &= ~NV30_NEW_ZSA;
+
+ nv30->screen->cur_ctx = nv30;
+ nv30->base.pushbuf->user_priv = &nv30->bufctx;
+}
+
+boolean
+nv30_state_validate(struct nv30_context *nv30, boolean hwtnl)
+{
+ struct nouveau_screen *screen = &nv30->screen->base;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
+ struct nouveau_bufctx *bctx = nv30->bufctx;
+ struct nouveau_bufref *bref;
+ struct state_validate *validate;
+
+ if (nv30->screen->cur_ctx != nv30)
+ nv30_state_context_switch(nv30);
+
+ if (hwtnl) {
+ nv30->draw_dirty |= nv30->dirty;
+ if (nv30->draw_flags) {
+ nv30->draw_flags &= ~nv30->dirty;
+ if (!nv30->draw_flags)
+ nv30->dirty |= NV30_SWTNL_MASK;
+ }
+ }
+
+ if (!nv30->draw_flags)
+ validate = hwtnl_validate_list;
+ else
+ validate = swtnl_validate_list;
+
+ if (nv30->dirty) {
+ while (validate->func) {
+ if (nv30->dirty & validate->mask)
+ validate->func(nv30);
+ validate++;
+ }
+
+ nv30->dirty = 0;
+ }
+
+ nouveau_pushbuf_bufctx(push, bctx);
+ if (nouveau_pushbuf_validate(push)) {
+ nouveau_pushbuf_bufctx(push, NULL);
+ return FALSE;
+ }
+
+ /*XXX*/
+ BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
+ PUSH_DATA (push, 0);
+ if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
+ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
+ PUSH_DATA (push, 2);
+ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
+ PUSH_DATA (push, 1);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NV04(push, NV30_3D(R1718), 1);
+ PUSH_DATA (push, 0);
+ }
+
+ LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) {
+ struct nv04_resource *res = bref->priv;
+ if (res && res->mm) {
+ nouveau_fence_ref(screen->fence.current, &res->fence);
+
+ if (bref->flags & NOUVEAU_BO_RD)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
+
+ if (bref->flags & NOUVEAU_BO_WR) {
+ nouveau_fence_ref(screen->fence.current, &res->fence_wr);
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+void
+nv30_state_release(struct nv30_context *nv30)
+{
+ nouveau_pushbuf_bufctx(nv30->base.pushbuf, NULL);
+}