Esempio n. 1
0
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->screen->base.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;
}
Esempio n. 2
0
static INLINE void
emit_elt32(void* priv, unsigned start, unsigned vc)
{
	struct push_context* ctx = priv;
	struct nouveau_grobj *eng3d = ctx->eng3d;
	struct nouveau_channel *chan = ctx->chan;
	uint32_t *elts = (uint32_t *)ctx->idxbuf + start;
	int idxbias = ctx->idxbias;

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

		BEGIN_RING_NI(chan, eng3d, NV30_3D_VB_ELEMENT_U32, push);
		if(idxbias)
		{
			for(unsigned i = 0; i < push; ++i)
				OUT_RING(chan, elts[i] + idxbias);
		}
		else
			OUT_RINGp(chan, elts, push);

		vc -= push;
		elts += push;
	}
}
Esempio n. 3
0
static void
emit_ranges(void* priv, unsigned start, unsigned vc, unsigned reg)
{
	struct push_context* ctx = priv;
	struct nouveau_grobj *eng3d = ctx->eng3d;
	struct nouveau_channel *chan = ctx->chan;
	unsigned nr = (vc & 0xff);
	if (nr) {
		BEGIN_RING(chan, eng3d, reg, 1);
		OUT_RING  (chan, ((nr - 1) << 24) | start);
		start += nr;
	}

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

		nr -= push;

		BEGIN_RING_NI(chan, eng3d, reg, push);
		while (push--) {
			OUT_RING(chan, ((0x100 - 1) << 24) | start);
			start += 0x100;
		}
	}
}
Esempio n. 4
0
static void
nvc0_m2mf_push_rect(struct pipe_screen *pscreen,
                    const struct nv50_m2mf_rect *dst,
                    const void *data,
                    unsigned nblocksx, unsigned nblocksy)
{
   struct nouveau_channel *chan;
   const uint8_t *src = (const uint8_t *)data;
   const int cpp = dst->cpp;
   const int line_len = nblocksx * cpp;
   int dy = dst->y;

   assert(nouveau_bo_tile_layout(dst->bo));

   BEGIN_RING(chan, RING_MF(TILING_MODE_OUT), 5);
   OUT_RING  (chan, dst->tile_mode);
   OUT_RING  (chan, dst->width * cpp);
   OUT_RING  (chan, dst->height);
   OUT_RING  (chan, dst->depth);
   OUT_RING  (chan, dst->z);

   while (nblocksy) {
      int line_count, words;
      int size = MIN2(AVAIL_RING(chan), NV04_PFIFO_MAX_PACKET_LEN);

      if (size < (12 + words)) {
         FIRE_RING(chan);
         continue;
      }
      line_count = (size * 4) / line_len;
      words = (line_count * line_len + 3) / 4;

      BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
      OUT_RELOCh(chan, dst->bo, dst->base, dst->domain | NOUVEAU_BO_WR);
      OUT_RELOCl(chan, dst->bo, dst->base, dst->domain | NOUVEAU_BO_WR);

      BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT_X), 2);
      OUT_RING  (chan, dst->x * cpp);
      OUT_RING  (chan, dy);
      BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
      OUT_RING  (chan, line_len);
      OUT_RING  (chan, line_count);
      BEGIN_RING(chan, RING_MF(EXEC), 1);
      OUT_RING  (chan, (1 << NVC0_M2MF_EXEC_INC__SHIFT) |
                 NVC0_M2MF_EXEC_PUSH | NVC0_M2MF_EXEC_LINEAR_IN);

      BEGIN_RING_NI(chan, RING_MF(DATA), words);
      OUT_RINGp (chan, src, words);

      dy += line_count;
      src += line_len * line_count;
      nblocksy -= line_count;
   }
}
Esempio n. 5
0
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;
}
Esempio n. 6
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);
}
Esempio n. 7
0
static void
emit_vertices(void *priv, unsigned start, unsigned count)
{
        struct push_context *ctx = priv;
        struct nouveau_grobj *eng3d = ctx->eng3d;

        while(count)
        {
		unsigned push = MIN2(count, ctx->max_vertices_per_packet);
		unsigned length = push * ctx->vertex_length;

		BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
		ctx->translate->run(ctx->translate, start, push, 0, ctx->chan->cur);
		ctx->chan->cur += length;

		count -= push;
		start += push;
        }
}
Esempio n. 8
0
static void
emit_vertices_lookup32(void *priv, unsigned start, unsigned count)
{
        struct push_context *ctx = priv;
        struct nouveau_grobj *eng3d = ctx->eng3d;
        uint32_t* elts = (uint32_t*)ctx->idxbuf + start;

        while(count)
        {
                unsigned push = MIN2(count, ctx->max_vertices_per_packet);
                unsigned length = push * ctx->vertex_length;

                BEGIN_RING_NI(ctx->chan, eng3d, NV30_3D_VERTEX_DATA, length);
                ctx->translate->run_elts(ctx->translate, elts, push, 0, ctx->chan->cur);
                ctx->chan->cur += length;

                count -= push;
                elts += push;
        }
}
Esempio n. 9
0
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;
	}
}
Esempio n. 10
0
void
nvc0_m2mf_push_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned offset, unsigned domain,
                      unsigned size, void *data)
{
   struct nouveau_channel *chan = nv->screen->channel;
   uint32_t *src = (uint32_t *)data;
   unsigned count = (size + 3) / 4;

   MARK_RING (chan, 8, 2);

   BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
   OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
   OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
   BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
   OUT_RING  (chan, size);
   OUT_RING  (chan, 1);
   BEGIN_RING(chan, RING_MF(EXEC), 1);
   OUT_RING  (chan, 0x100111);

   while (count) {
      unsigned nr = AVAIL_RING(chan);

      if (nr < 9) {
         FIRE_RING(chan);
         nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR);
         continue;
      }
      nr = MIN2(count, nr - 1);
      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);
   
      BEGIN_RING_NI(chan, RING_MF(DATA), nr);
      OUT_RINGp (chan, src, nr);

      src += nr;
      count -= nr;
   }
}
Esempio n. 11
0
static INLINE void
emit_vertex(struct push_context *ctx, unsigned n)
{
   struct nouveau_grobj *tesla = ctx->nv50->screen->tesla;
   struct nouveau_channel *chan = tesla->channel;
   int i;

   if (ctx->edgeflag_attr < 16) {
      float *edgeflag = (float *)
         ((uint8_t *)ctx->attr[ctx->edgeflag_attr].map +
          ctx->attr[ctx->edgeflag_attr].stride * n);

      if (*edgeflag != ctx->edgeflag) {
         BEGIN_RING(chan, tesla, NV50TCL_EDGEFLAG_ENABLE, 1);
         OUT_RING  (chan, *edgeflag ? 1 : 0);
         ctx->edgeflag = *edgeflag;
      }
   }

   BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, ctx->vtx_size);
   for (i = 0; i < ctx->attr_nr; i++)
      ctx->attr[i].push(chan,
			(uint8_t *)ctx->attr[i].map + ctx->attr[i].stride * n);
}
Esempio n. 12
0
void
nvc0_m2mf_push_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned offset, unsigned domain,
                      unsigned size, const void *data)
{
   struct nouveau_channel *chan = nv->screen->channel;
   uint32_t *src = (uint32_t *)data;
   unsigned count = (size + 3) / 4;

   while (count) {
      unsigned nr;

      MARK_RING (chan, 16, 2);

      nr = AVAIL_RING(chan) - 9;
      nr = MIN2(count, nr);
      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN);

      BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2);
      OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR);
      OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR);
      BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2);
      OUT_RING  (chan, nr * 4);
      OUT_RING  (chan, 1);
      BEGIN_RING(chan, RING_MF(EXEC), 1);
      OUT_RING  (chan, 0x100111);

      /* must not be interrupted (trap on QUERY fence, 0x50 works however) */
      BEGIN_RING_NI(chan, RING_MF(DATA), nr);
      OUT_RINGp (chan, src, nr);

      count -= nr;
      src += nr;
      offset += nr * 4;
   }
}
Esempio n. 13
0
void
nv50_constbufs_validate(struct nv50_context *nv50)
{
   struct nouveau_channel *chan = nv50->screen->base.channel;
   unsigned s;

   for (s = 0; s < 3; ++s) {
      struct nv04_resource *res;
      int i;
      unsigned p, b;

      if (s == PIPE_SHADER_FRAGMENT)
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT;
      else
      if (s == PIPE_SHADER_GEOMETRY)
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_GEOMETRY;
      else
         p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;

      while (nv50->constbuf_dirty[s]) {
         struct nouveau_bo *bo;
         unsigned start = 0;
         unsigned words = 0;

         i = ffs(nv50->constbuf_dirty[s]) - 1;
         nv50->constbuf_dirty[s] &= ~(1 << i);

         res = nv04_resource(nv50->constbuf[s][i]);
         if (!res) {
            if (i != 0) {
               BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
               OUT_RING  (chan, (i << 8) | p | 0);
            }
            continue;
         }

         if (i == 0) {
            b = NV50_CB_PVP + s;

            /* always upload GL uniforms through CB DATA */
            bo = nv50->screen->uniforms;
            words = res->base.width0 / 4;
         } else {
            b = s * 16 + i;

            assert(0);

            if (!nouveau_resource_mapped_by_gpu(&res->base)) {
               nouveau_buffer_migrate(&nv50->base, res, NOUVEAU_BO_VRAM);

               BEGIN_RING(chan, RING_3D(CODE_CB_FLUSH), 1);
               OUT_RING  (chan, 0);
            }
            MARK_RING (chan, 6, 2);
            BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3);
            OUT_RESRCh(chan, res, 0, NOUVEAU_BO_RD);
            OUT_RESRCl(chan, res, 0, NOUVEAU_BO_RD);
            OUT_RING  (chan, (b << 16) | (res->base.width0 & 0xffff));
            BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1);
            OUT_RING  (chan, (b << 12) | (i << 8) | p | 1);

            bo = res->bo;

            nv50_bufctx_add_resident(nv50, NV50_BUFCTX_CONSTANT, res,
                                     res->domain | NOUVEAU_BO_RD);
         }

         if (words) {
            MARK_RING(chan, 8, 1);

            nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
         }

         while (words) {
            unsigned nr = AVAIL_RING(chan);

            if (nr < 16) {
               FIRE_RING(chan);
               nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR);
               continue;
            }
            nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);

            BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
            OUT_RING  (chan, (start << 8) | b);
            BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr);
            OUT_RINGp (chan, &res->data[start * 4], nr);

            start += nr;
            words -= nr;
         }
      }
   }
}
Esempio n. 14
0
static INLINE void
nvfx_render_prim(struct draw_stage *stage, struct prim_header *prim,
	       unsigned mode, unsigned count)
{
	struct nvfx_render_stage *rs = nvfx_render_stage(stage);
	struct nvfx_context *nvfx = rs->nvfx;

	struct nvfx_screen *screen = nvfx->screen;
	struct nouveau_channel *chan = screen->base.channel;
	struct nouveau_grobj *eng3d = screen->eng3d;
	boolean no_elements = nvfx->vertprog->draw_no_elements;
	unsigned num_attribs = nvfx->vertprog->draw_elements;

	/* we need to account the flush as well here even if it is done afterthis
	 * function
	 */
	if (AVAIL_RING(chan) < ((1 + count * num_attribs * 4) + 6 + 64)) {
		nvfx_render_flush(stage, 0);
		FIRE_RING(chan);
		nvfx_state_emit(nvfx);

		assert(AVAIL_RING(chan) >= ((1 + count * num_attribs * 4) + 6 + 64));
	}

	/* Switch primitive modes if necessary */
	if (rs->prim != mode) {
		if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) {
			BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
			OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP);
		}

		/* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
		/* this seems to cause issues on nv3x, and also be unneeded there */
		if(nvfx->is_nv4x)
		{
			int i;
			for(i = 0; i < 32; ++i)
			{
				BEGIN_RING(chan, eng3d, 0x1dac, 1);
				OUT_RING(chan, 0);
			}
		}

		BEGIN_RING(chan, eng3d, NV30_3D_VERTEX_BEGIN_END, 1);
		OUT_RING  (chan, mode);
		rs->prim = mode;
	}

	if(no_elements) {
		BEGIN_RING_NI(chan, eng3d, NV30_3D_VERTEX_DATA, 4);
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
		OUT_RING(chan, 0);
	} else {
		BEGIN_RING_NI(chan, eng3d, NV30_3D_VERTEX_DATA, num_attribs * 4 * count);
		for (unsigned i = 0; i < count; ++i)
		{
			struct vertex_header* v = prim->v[i];
			/* TODO: disable divide where it's causing the problem, and remove this hack */
			OUT_RING(chan, fui(v->data[0][0] / v->data[0][3]));
			OUT_RING(chan, fui(v->data[0][1] / v->data[0][3]));
			OUT_RING(chan, fui(v->data[0][2] / v->data[0][3]));
			OUT_RING(chan, fui(1.0f / v->data[0][3]));
			OUT_RINGp(chan, &v->data[1][0], 4 * (num_attribs - 1));
		}
	}
}