/* Validate state derived from shaders and the rasterizer cso. */
void
nv50_validate_derived_rs(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   uint32_t color, psize;

   nv50_sprite_coords_validate(nv50);

   if (nv50->dirty & NV50_NEW_FRAGPROG)
      return;
   psize = nv50->state.semantic_psize & ~NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK;
   color = nv50->state.semantic_color & ~NV50_3D_MAP_SEMANTIC_0_CLMP_EN;

   if (nv50->rast->pipe.clamp_vertex_color)
      color |= NV50_3D_MAP_SEMANTIC_0_CLMP_EN;

   if (color != nv50->state.semantic_color) {
      nv50->state.semantic_color = color;
      BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_0), 1);
      OUT_RING  (chan, color);
   }

   if (nv50->rast->pipe.point_size_per_vertex)
      psize |= NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK;

   if (psize != nv50->state.semantic_psize) {
      nv50->state.semantic_psize = psize;
      BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_3), 1);
      OUT_RING  (chan, psize);
   }
}
void
nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
	struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
	struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	unsigned txf;
	unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
	unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod);

	txf = sv->u.nv40.fmt[ps->compare] | ps->fmt;

	MARK_RING(chan, 11, 2);
	OUT_RING(chan, RING_3D(NV30_3D_TEX_OFFSET(unit), 8));
	OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
	OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
			NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
	OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
	OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7));
	OUT_RING(chan, sv->swizzle);
	OUT_RING(chan, ps->filt | sv->filt);
	OUT_RING(chan, sv->npot_size);
	OUT_RING(chan, ps->bcol);
	OUT_RING(chan, RING_3D(NV40_3D_TEX_SIZE1(unit), 1));
	OUT_RING(chan, sv->u.nv40.npot_size2);

	nvfx->hw_txf[unit] = txf;
	nvfx->hw_samplers |= (1 << unit);
}
Beispiel #3
0
void
nvc0_vertprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *vp = nvc0->vertprog;

   if (nvc0->clip.nr > vp->vp.num_ucps) {
      assert(nvc0->clip.nr <= 6);
      vp->vp.num_ucps = 6;

      if (vp->translated)
         nvc0_program_destroy(nvc0, vp);
   }

   if (!nvc0_program_validate(nvc0, vp))
         return;
   nvc0_program_update_context_state(nvc0, vp, 0);

   BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2);
   OUT_RING  (chan, 0x11);
   OUT_RING  (chan, vp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(1)), 1);
   OUT_RING  (chan, vp->max_gpr);

   if (!nvc0->gmtyprog && !nvc0->tevlprog)
      nvc0_program_validate_clip(nvc0, vp);

   // BEGIN_RING(chan, RING_3D_(0x163c), 1);
   // OUT_RING  (chan, 0);
}
void
nv50_gp_linkage_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct nv50_program *vp = nv50->vertprog;
   struct nv50_program *gp = nv50->gmtyprog;
   int m = 0;
   int n;
   uint8_t map[64];

   if (!gp)
      return;
   memset(map, 0, sizeof(map));

   m = nv50_vp_gp_mapping(map, m, vp, gp);

   n = (m + 3) / 4;

   BEGIN_RING(chan, RING_3D(VP_GP_BUILTIN_ATTR_EN), 1);
   OUT_RING  (chan, vp->vp.attrs[2] | gp->vp.attrs[2]);

   BEGIN_RING(chan, RING_3D(VP_RESULT_MAP_SIZE), 1);
   OUT_RING  (chan, m);
   BEGIN_RING(chan, RING_3D(VP_RESULT_MAP(0)), n);
   OUT_RINGp (chan, map, n);
}
Beispiel #5
0
static INLINE void
nvc0_program_update_context_state(struct nvc0_context *nvc0,
                                  struct nvc0_program *prog, int stage)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;

   if (prog->hdr[1])
      nvc0->state.tls_required |= 1 << stage;
   else
      nvc0->state.tls_required &= ~(1 << stage);

   if (prog->immd_size) {
      const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;

      BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
      /* NOTE: may overlap code of a different shader */
      OUT_RING  (chan, align(prog->immd_size, 0x100));
      OUT_RELOCh(chan, nvc0->screen->text, prog->immd_base, rl);
      OUT_RELOCl(chan, nvc0->screen->text, prog->immd_base, rl);
      BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
      OUT_RING  (chan, (14 << 4) | 1);

      nvc0->state.c14_bound |= 1 << stage;
   } else
   if (nvc0->state.c14_bound & (1 << stage)) {
      BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1);
      OUT_RING  (chan, (14 << 4) | 0);

      nvc0->state.c14_bound &= ~(1 << stage);
   }
}
Beispiel #6
0
void
nvc0_tevlprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *tp = nvc0->tevlprog;

   if (!tp) {
      BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
      OUT_RING  (chan, 0x30);
      return;
   }
   if (!nvc0_program_validate(nvc0, tp))
         return;
   nvc0_program_update_context_state(nvc0, tp, 2);

   if (tp->tp.tess_mode != ~0) {
      BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
      OUT_RING  (chan, tp->tp.tess_mode);
   }
   BEGIN_RING(chan, RING_3D(TEP_SELECT), 1);
   OUT_RING  (chan, 0x31);
   BEGIN_RING(chan, RING_3D(SP_START_ID(3)), 1);
   OUT_RING  (chan, tp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(3)), 1);
   OUT_RING  (chan, tp->max_gpr);

   if (!nvc0->gmtyprog)
      nvc0_program_validate_clip(nvc0, tp);
}
Beispiel #7
0
void
nvc0_tctlprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *tp = nvc0->tctlprog;

   if (!tp) {
      BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 1);
      OUT_RING  (chan, 0x20);
      return;
   }
   if (!nvc0_program_validate(nvc0, tp))
         return;
   nvc0_program_update_context_state(nvc0, tp, 1);

   if (tp->tp.tess_mode != ~0) {
      BEGIN_RING(chan, RING_3D(TESS_MODE), 1);
      OUT_RING  (chan, tp->tp.tess_mode);
   }
   BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2);
   OUT_RING  (chan, 0x21);
   OUT_RING  (chan, tp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(2)), 1);
   OUT_RING  (chan, tp->max_gpr);

   if (tp->tp.input_patch_size <= 32)
      IMMED_RING(chan, RING_3D(PATCH_VERTICES), tp->tp.input_patch_size);
}
Beispiel #8
0
static void
nvc0_texture_barrier(struct pipe_context *pipe)
{
   struct nouveau_channel *chan = nvc0_context(pipe)->screen->base.channel;

   IMMED_RING(chan, RING_3D(SERIALIZE), 0);
   IMMED_RING(chan, RING_3D(TEX_CACHE_CTL), 0);
}
static void
nv50_sprite_coords_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   uint32_t pntc[8], mode;
   struct nv50_program *fp = nv50->fragprog;
   unsigned i, c;
   unsigned m = (nv50->state.interpolant_ctrl >> 8) & 0xff;

   if (!nv50->rast->pipe.point_quad_rasterization) {
      if (nv50->state.point_sprite) {
         BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8);
         for (i = 0; i < 8; ++i)
            OUT_RING(chan, 0);

         nv50->state.point_sprite = FALSE;
      }
      return;
   } else {
      nv50->state.point_sprite = TRUE;
   }

   memset(pntc, 0, sizeof(pntc));

   for (i = 0; i < fp->in_nr; i++) {
      unsigned n = util_bitcount(fp->in[i].mask);

      if (fp->in[i].sn != TGSI_SEMANTIC_GENERIC) {
         m += n;
         continue;
      }
      if (!(nv50->rast->pipe.sprite_coord_enable & (1 << fp->in[i].si))) {
         m += n;
         continue;
      }

      for (c = 0; c < 4; ++c) {
         if (fp->in[i].mask & (1 << c)) {
            pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
            ++m;
         }
      }
   }

   if (nv50->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
      mode = 0x00;
   else
      mode = 0x10;

   BEGIN_RING(chan, RING_3D(POINT_SPRITE_CTRL), 1);
   OUT_RING  (chan, mode);

   BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8);
   OUT_RINGp (chan, pntc, 8);
}
Beispiel #10
0
void
nv50_clear(struct pipe_context *pipe, unsigned buffers,
           const float *rgba, double depth, unsigned stencil)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct pipe_framebuffer_state *fb = &nv50->framebuffer;
   unsigned i;
   const unsigned dirty = nv50->dirty;
   uint32_t mode = 0;

   /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
   nv50->dirty &= NV50_NEW_FRAMEBUFFER;
   if (!nv50_state_validate(nv50, 9 + (fb->nr_cbufs * 2)))
      return;

   if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
      BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
      OUT_RINGf (chan, rgba[0]);
      OUT_RINGf (chan, rgba[1]);
      OUT_RINGf (chan, rgba[2]);
      OUT_RINGf (chan, rgba[3]);
      mode =
         NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G |
         NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A;
   }

   if (buffers & PIPE_CLEAR_DEPTH) {
      BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
      OUT_RING  (chan, fui(depth));
      mode |= NV50_3D_CLEAR_BUFFERS_Z;
   }

   if (buffers & PIPE_CLEAR_STENCIL) {
      BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
      OUT_RING  (chan, stencil & 0xff);
      mode |= NV50_3D_CLEAR_BUFFERS_S;
   }

   BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
   OUT_RING  (chan, mode);

   for (i = 1; i < fb->nr_cbufs; i++) {
      BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
      OUT_RING  (chan, (i << 6) | 0x3c);
   }

   nv50->dirty = dirty & ~NV50_NEW_FRAMEBUFFER;
}
Beispiel #11
0
static void
emit_edgeflag(struct push_context *ctx, boolean enabled)
{
   struct nouveau_channel *chan = ctx->nvc0->screen->base.channel;
   
   IMMED_RING(chan, RING_3D(EDGEFLAG_ENABLE), enabled);
}
void
nvfx_vbo_relocate(struct nvfx_context *nvfx)
{
	struct nouveau_channel* chan;
	unsigned vb_flags;
	int i;

        if(!nvfx->use_vertex_buffers)
                return;

	chan = nvfx->screen->base.channel;
	vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY;

	MARK_RING(chan, 2 * 16 + 3, 2 * 16 + 3);
        for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
                struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
                struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
                struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;

                OUT_RELOC(chan, bo, RING_3D(NV30_3D_VTXBUF(ve->idx), 1),
				vb_flags, 0, 0);
                OUT_RELOC(chan, bo, vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
				vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
				0, NV30_3D_VTXBUF_DMA1);
	}
        nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
}
static INLINE void
emit_elt16(void* priv, unsigned start, unsigned vc)
{
	struct push_context* ctx = priv;
	struct nouveau_channel *chan = ctx->chan;
	uint16_t *elts = (uint16_t *)ctx->idxbuf + start;
	int idxbias = ctx->idxbias;

	if (vc & 1) {
		OUT_RING(chan, RING_3D(NV30_3D_VB_ELEMENT_U32, 1));
		OUT_RING  (chan, elts[0]);
		elts++; vc--;
	}

	while (vc) {
		unsigned i;
		unsigned push = MIN2(vc, 2047 * 2);

		OUT_RING(chan, RING_3D_NI(NV30_3D_VB_ELEMENT_U16, push >> 1));
		for (i = 0; i < push; i+=2)
			OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias));

		vc -= push;
		elts += push;
	}
}
Beispiel #14
0
void
nvfx_fragtex_relocate(struct nvfx_context *nvfx)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	unsigned samplers, unit;
	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;

	samplers = nvfx->hw_samplers;
	while (samplers) {
		struct nvfx_miptree* mt;
		struct nouveau_bo *bo;

		unit = ffs(samplers) - 1;
		samplers &= ~(1 << unit);

		mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture;
		bo = mt->base.bo;

		MARK_RING(chan, 3, 3);
		OUT_RELOC(chan, bo, RING_3D(NV30_3D_TEX_OFFSET(unit), 2), tex_flags | NOUVEAU_BO_DUMMY, 0, 0);
		OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_DUMMY, 0, 0);
		OUT_RELOC(chan, bo, nvfx->hw_txf[unit], tex_flags | NOUVEAU_BO_OR | NOUVEAU_BO_DUMMY,
				NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
	}
	nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
}
static void
emit_ranges(void* priv, unsigned start, unsigned vc, unsigned reg)
{
	struct push_context* ctx = priv;
	struct nouveau_channel *chan = ctx->chan;
	unsigned nr = (vc & 0xff);
	if (nr) {
		OUT_RING(chan, RING_3D(reg, 1));
		OUT_RING  (chan, ((nr - 1) << 24) | start);
		start += nr;
	}

	nr = vc >> 8;
	while (nr) {
		unsigned push = nr > 2047 ? 2047 : nr;

		nr -= push;

		OUT_RING(chan, RING_3D_NI(reg, push));
		while (push--) {
			OUT_RING(chan, ((0x100 - 1) << 24) | start);
			start += 0x100;
		}
	}
}
static void
emit_edgeflag(void *priv, boolean enabled)
{
	struct push_context* ctx = priv;
	struct nouveau_channel *chan = ctx->chan;

	OUT_RING(chan, RING_3D(NV30_3D_EDGEFLAG, 1));
	OUT_RING(chan, enabled ? 1 : 0);
}
Beispiel #17
0
static void
nvc0_program_validate_clip(struct nvc0_context *nvc0, struct nvc0_program *vp)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;

   if (nvc0->vertprog->vp.num_ucps)
      return;

   if (nvc0->state.clip_enable != vp->vp.clip_enable) {
      nvc0->state.clip_enable = vp->vp.clip_enable;
      IMMED_RING(chan, RING_3D(CLIP_DISTANCE_ENABLE), vp->vp.clip_enable);
   }
   if (nvc0->state.clip_mode != vp->vp.clip_mode) {
      nvc0->state.clip_mode = vp->vp.clip_mode;
      BEGIN_RING(chan, RING_3D(CLIP_DISTANCE_MODE), 1);
      OUT_RING  (chan, vp->vp.clip_mode);
   }
}
void
nv50_vertprog_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct nv50_program *vp = nv50->vertprog;

   if (!nv50_program_validate(nv50, vp))
         return;

   BEGIN_RING(chan, RING_3D(VP_ATTR_EN(0)), 2);
   OUT_RING  (chan, vp->vp.attrs[0]);
   OUT_RING  (chan, vp->vp.attrs[1]);
   BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_RESULT), 1);
   OUT_RING  (chan, vp->max_out);
   BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_TEMP), 1);
   OUT_RING  (chan, vp->max_gpr);
   BEGIN_RING(chan, RING_3D(VP_START_ID), 1);
   OUT_RING  (chan, vp->code_base);
}
void
nv50_fragprog_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct nv50_program *fp = nv50->fragprog;

   if (!nv50_program_validate(nv50, fp))
         return;

   BEGIN_RING(chan, RING_3D(FP_REG_ALLOC_TEMP), 1);
   OUT_RING  (chan, fp->max_gpr);
   BEGIN_RING(chan, RING_3D(FP_RESULT_COUNT), 1);
   OUT_RING  (chan, fp->max_out);
   BEGIN_RING(chan, RING_3D(FP_CONTROL), 1);
   OUT_RING  (chan, fp->fp.flags[0]);
   BEGIN_RING(chan, RING_3D(FP_CTRL_UNK196C), 1);
   OUT_RING  (chan, fp->fp.flags[1]);
   BEGIN_RING(chan, RING_3D(FP_START_ID), 1);
   OUT_RING  (chan, fp->code_base);
}
static void
nvfx_idxbuf_emit(struct nvfx_context* nvfx, unsigned ib_flags)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	unsigned ib_format = (nvfx->idxbuf.index_size == 2) ? NV30_3D_IDXBUF_FORMAT_TYPE_U16 : NV30_3D_IDXBUF_FORMAT_TYPE_U32;
	struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf.buffer)->bo;
	ib_flags |= nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD;

	assert(nvfx->screen->index_buffer_reloc_flags);

	MARK_RING(chan, 3, 3);
	if(ib_flags & NOUVEAU_BO_DUMMY)
		OUT_RELOC(chan, bo, RING_3D(NV30_3D_IDXBUF_OFFSET, 2), ib_flags, 0, 0);
	else
		OUT_RING(chan, RING_3D(NV30_3D_IDXBUF_OFFSET, 2));
	OUT_RELOC(chan, bo, nvfx->idxbuf.offset + 1, ib_flags | NOUVEAU_BO_LOW, 0, 0);
	OUT_RELOC(chan, bo, ib_format, ib_flags | NOUVEAU_BO_OR,
			0, NV30_3D_IDXBUF_FORMAT_DMA1);
	nvfx->relocs_needed &=~ NVFX_RELOCATE_IDXBUF;
}
void
nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
{
	struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
	struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
	struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	unsigned txf;
	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	unsigned use_rect;
	unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
	unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ;

	if(sv->u.nv30.rect < 0)
	{
		/* in the case of compressed or 1D textures, we can get away with this,
		 * since the layout is the same
		 */
		use_rect = ps->fmt;
	}
	else
	{
		static boolean warned = FALSE;
		if( !!ps->fmt != sv->u.nv30.rect && !warned) {
			warned = TRUE;
			fprintf(stderr,
					"Unimplemented: coordinate normalization mismatch. Possible reasons:\n"
					"1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n"
					"2. The state tracker is not using the appropriate coordinate normalization\n"
					"3. The state tracker is not supported\n");
		}

		use_rect  = sv->u.nv30.rect;
	}

	txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)];

	MARK_RING(chan, 9, 2);
	OUT_RING(chan, RING_3D(NV30_3D_TEX_OFFSET(unit), 8));
	OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
	OUT_RELOC(chan, bo, txf,
		tex_flags | NOUVEAU_BO_OR,
		NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
	OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
	OUT_RING(chan, ps->en | (min_lod << NV30_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT) | (max_lod << NV30_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT));
	OUT_RING(chan, sv->swizzle);
	OUT_RING(chan, ps->filt | sv->filt);
	OUT_RING(chan, sv->npot_size);
	OUT_RING(chan, ps->bcol);

	nvfx->hw_txf[unit] = txf;
	nvfx->hw_samplers |= (1 << unit);
}
Beispiel #22
0
void
nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *gp = nvc0->gmtyprog;

   if (gp)
      nvc0_program_validate(nvc0, gp);
   /* we allow GPs with no code for specifying stream output state only */
   if (!gp || !gp->code_size) {
      BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
      OUT_RING  (chan, 0x40);
      IMMED_RING(chan, RING_3D(LAYER), 0);
      return;
   }
   nvc0_program_update_context_state(nvc0, gp, 3);

   BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
   OUT_RING  (chan, 0x41);
   BEGIN_RING(chan, RING_3D(SP_START_ID(4)), 1);
   OUT_RING  (chan, gp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
   OUT_RING  (chan, gp->max_gpr);
   BEGIN_RING(chan, RING_3D(LAYER), 1);
   OUT_RING  (chan, (gp->hdr[13] & (1 << 9)) ? NVC0_3D_LAYER_USE_GP : 0);

   nvc0_program_validate_clip(nvc0, gp);
}
Beispiel #23
0
void
nvc0_fragprog_validate(struct nvc0_context *nvc0)
{
   struct nouveau_channel *chan = nvc0->screen->base.channel;
   struct nvc0_program *fp = nvc0->fragprog;

   if (!nvc0_program_validate(nvc0, fp))
         return;
   nvc0_program_update_context_state(nvc0, fp, 4);

   BEGIN_RING(chan, RING_3D(SP_SELECT(5)), 2);
   OUT_RING  (chan, 0x51);
   OUT_RING  (chan, fp->code_base);
   BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(5)), 1);
   OUT_RING  (chan, fp->max_gpr);

   BEGIN_RING(chan, RING_3D_(0x0360), 2);
   OUT_RING  (chan, 0x20164010);
   OUT_RING  (chan, 0x20);
   BEGIN_RING(chan, RING_3D_(0x196c), 1);
   OUT_RING  (chan, fp->flags[0]);
}
void
nv50_gmtyprog_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   struct nv50_program *gp = nv50->gmtyprog;

   if (!gp) /* GP_ENABLE is updated in linkage validation */
      return;
   if (!nv50_program_validate(nv50, gp))
      return;

   BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_TEMP), 1);
   OUT_RING  (chan, gp->max_gpr);
   BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_RESULT), 1);
   OUT_RING  (chan, gp->max_out);
   BEGIN_RING(chan, RING_3D(GP_OUTPUT_PRIMITIVE_TYPE), 1);
   OUT_RING  (chan, gp->gp.prim_type);
   BEGIN_RING(chan, RING_3D(GP_VERTEX_OUTPUT_COUNT), 1);
   OUT_RING  (chan, gp->gp.vert_count);
   BEGIN_RING(chan, RING_3D(GP_START_ID), 1);
   OUT_RING  (chan, gp->code_base);
}
Beispiel #25
0
static void
nv50_clear_depth_stencil(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         unsigned clear_flags,
                         double depth,
                         unsigned stencil,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct nv50_screen *screen = nv50->screen;
   struct nouveau_channel *chan = screen->base.channel;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;
   uint32_t mode = 0;

   if (clear_flags & PIPE_CLEAR_DEPTH) {
      BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1);
      OUT_RINGf (chan, depth);
      mode |= NV50_3D_CLEAR_BUFFERS_Z;
   }

   if (clear_flags & PIPE_CLEAR_STENCIL) {
      BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1);
      OUT_RING  (chan, stencil & 0xff);
      mode |= NV50_3D_CLEAR_BUFFERS_S;
   }

   if (MARK_RING(chan, 17, 2))
      return;

   BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
   OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RING  (chan, nv50_format_table[dst->format].rt);
   OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
   OUT_RING  (chan, 0);
   BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
   OUT_RING  (chan, 1);
   BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
   OUT_RING  (chan, sf->width);
   OUT_RING  (chan, sf->height);
   OUT_RING  (chan, (1 << 16) | 1);

   BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
   OUT_RING  (chan, (width << 16) | dstx);
   OUT_RING  (chan, (height << 16) | dsty);

   BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
   OUT_RING  (chan, mode);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}
static void
nvfx_render_flush(struct draw_stage *stage, unsigned flags)
{
	struct nvfx_render_stage *rs = nvfx_render_stage(stage);
	struct nvfx_context *nvfx = rs->nvfx;
	struct nouveau_channel *chan = nvfx->screen->base.channel;

	if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
		assert(AVAIL_RING(chan) >= 2);
		OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1));
		OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
		rs->prim = NV30_3D_VERTEX_BEGIN_END_STOP;
	}
}
void
nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx)
{
	struct nouveau_channel* chan = nvfx->screen->base.channel;
	unsigned num_outputs = nvfx->vertprog->draw_elements;
	int elements = MAX2(num_outputs, nvfx->hw_vtxelt_nr);

	if (!elements)
		return;

	WAIT_RING(chan, (1 + 6 + 1 + 2) + elements * 2);

	OUT_RING(chan, RING_3D(NV30_3D_VTXFMT(0), elements));
	for(unsigned i = 0; i < num_outputs; ++i)
		OUT_RING(chan, (4 << NV30_3D_VTXFMT_SIZE__SHIFT) | NV30_3D_VTXFMT_TYPE_V32_FLOAT);
	for(unsigned i = num_outputs; i < elements; ++i)
		OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT);

	if(nvfx->is_nv4x) {
		unsigned i;
		/* seems to be some kind of cache flushing */
		for(i = 0; i < 3; ++i) {
			OUT_RING(chan, RING_3D(0x1718, 1));
			OUT_RING(chan, 0);
		}
	}

	OUT_RING(chan, RING_3D(NV30_3D_VTXBUF(0), elements));
	for (unsigned i = 0; i < elements; i++)
		OUT_RING(chan, 0);

	OUT_RING(chan, RING_3D(0x1710, 1));
	OUT_RING(chan, 0);

	nvfx->hw_vtxelt_nr = num_outputs;
	nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
}
Beispiel #28
0
static INLINE void
emit_vertex(struct push_context *ctx, unsigned n)
{
   struct nouveau_channel *chan = ctx->nvc0->screen->base.channel;
   int i;

   if (ctx->edgeflag_input < 32) {
      /* TODO */
   }

   BEGIN_RING_NI(chan, RING_3D(VERTEX_DATA), ctx->vertex_size);
   for (i = 0; i < ctx->num_attrs; ++i)
      ctx->attr[i].push(chan,
                        (uint8_t *)ctx->attr[i].map + n * ctx->attr[i].stride);
}
Beispiel #29
0
void
nvc0_cb_push(struct nouveau_context *nv,
             struct nouveau_bo *bo, unsigned domain,
             unsigned base, unsigned size,
             unsigned offset, unsigned words, const uint32_t *data)
{
   struct nouveau_channel *chan = nv->screen->channel;

   assert(!(offset & 3));
   size = align(size, 0x100);

   MARK_RING (chan, 16, 2);
   BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
   OUT_RING  (chan, size);
   OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR);

   while (words) {
      unsigned nr = AVAIL_RING(chan);
      nr = MIN2(nr, words);
      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);

      BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
      OUT_RING  (chan, offset);
      OUT_RINGp (chan, data, nr);

      words -= nr;
      data += nr;
      offset += nr * 4;

      if (words) {
         MARK_RING(chan, 6, 1);
         nouveau_bo_validate(chan, bo, domain | NOUVEAU_BO_WR);
      }
   }
}
Beispiel #30
0
static void
nv50_clear_render_target(struct pipe_context *pipe,
                         struct pipe_surface *dst,
                         const float *rgba,
                         unsigned dstx, unsigned dsty,
                         unsigned width, unsigned height)
{
   struct nv50_context *nv50 = nv50_context(pipe);
   struct nv50_screen *screen = nv50->screen;
   struct nouveau_channel *chan = screen->base.channel;
   struct nv50_miptree *mt = nv50_miptree(dst->texture);
   struct nv50_surface *sf = nv50_surface(dst);
   struct nouveau_bo *bo = mt->base.bo;

   BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
   OUT_RINGf (chan, rgba[0]);
   OUT_RINGf (chan, rgba[1]);
   OUT_RINGf (chan, rgba[2]);
   OUT_RINGf (chan, rgba[3]);

   if (MARK_RING(chan, 18, 2))
      return;

   BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
   OUT_RING  (chan, 1);
   BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 5);
   OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
   OUT_RING  (chan, nv50_format_table[dst->format].rt);
   OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
   OUT_RING  (chan, 0);
   BEGIN_RING(chan, RING_3D(RT_HORIZ(0)), 2);
   OUT_RING  (chan, sf->width);
   OUT_RING  (chan, sf->height);
   BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
   OUT_RING  (chan, 1);

   /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */

   BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
   OUT_RING  (chan, (width << 16) | dstx);
   OUT_RING  (chan, (height << 16) | dsty);

   BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
   OUT_RING  (chan, 0x3c);

   nv50->dirty |= NV50_NEW_FRAMEBUFFER;
}