static void
nv30_draw_elements(struct nv30_context *nv30, boolean shorten,
                   unsigned mode, unsigned start, unsigned count,
                   unsigned instance_count, int32_t index_bias)
{
   const unsigned index_size = nv30->idxbuf.index_size;
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_object *eng3d = nv30->screen->eng3d;
   unsigned prim = nv30_prim_gl(mode);

#if 0 /*XXX*/
   if (index_bias != nv30->state.index_bias) {
      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1);
      PUSH_DATA (push, index_bias);
      nv30->state.index_bias = index_bias;
   }
#endif

   if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 &&
       nv30->idxbuf.buffer) {
      struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer);
      unsigned offset = nv30->idxbuf.offset;

      assert(nouveau_resource_mapped_by_gpu(&res->base));

      BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2);
      PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset,
                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0);
      PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo,
                       (index_size == 2) ? 0x00000010 : 0x00000000,
                       res->domain | NOUVEAU_BO_RD,
                       0, NV30_3D_IDXBUF_FORMAT_DMA1);
      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
      PUSH_DATA (push, prim);
      while (count) {
         const unsigned mpush = 2047 * 256;
         unsigned npush  = (count > mpush) ? mpush : count;
         unsigned wpush  = ((npush + 255) & ~255) >> 8;

         count -= npush;

         BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush);
         while (npush >= 256) {
            PUSH_DATA (push, 0xff000000 | start);
            start += 256;
            npush -= 256;
         }

         if (npush)
            PUSH_DATA (push, ((npush - 1) << 24) | start);
      }
      BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
      PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
      PUSH_RESET(push, BUFCTX_IDXBUF);
   } else {
Exemplo n.º 2
0
static void
nv30_render_draw_elements(struct vbuf_render *render,
                          const ushort *indices, uint count)
{
   struct nv30_render *r = nv30_render(render);
   struct nv30_context *nv30 = r->nv30;
   struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
   unsigned i;

   BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
   for (i = 0; i < r->vertex_info.num_attribs; i++) {
      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
                       nv04_resource(r->buffer), r->offset + r->vtxptr[i],
                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1);
   }

   if (!nv30_state_validate(nv30, FALSE))
      return;

   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, r->prim);

   if (count & 1) {
      BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1);
      PUSH_DATA (push, *indices++);
   }

   count >>= 1;
   while (count) {
      unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
      count -= npush;

      BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush);
      while (npush--) {
         PUSH_DATA(push, (indices[1] << 16) | indices[0]);
         indices += 2;
      }
   }

   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
   PUSH_RESET(push, BUFCTX_VTXTMP);
}
static void
nv30_update_user_vbufs(struct nv30_context *nv30)
{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   uint32_t base, offset, size;
   int i;
   uint32_t written = 0;

   for (i = 0; i < nv30->vertex->num_elements; i++) {
      struct pipe_vertex_element *ve = &nv30->vertex->pipe[i];
      const int b = ve->vertex_buffer_index;
      struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b];
      struct nv04_resource *buf = nv04_resource(vb->buffer);

      if (!(nv30->vbo_user & (1 << b)))
         continue;

      if (!vb->stride) {
         nv30_emit_vtxattr(nv30, vb, ve, i);
         continue;
      }
      nv30_vbuf_range(nv30, b, &base, &size);

      if (!(written & (1 << b))) {
         written |= 1 << b;
         nouveau_user_buffer_upload(&nv30->base, buf, base, size);
      }

      offset = vb->buffer_offset + ve->src_offset;

      BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset,
                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
                       0, NV30_3D_VTXBUF_DMA1);
   }
   nv30->base.vbo_dirty = TRUE;
}
Exemplo n.º 4
0
static void
nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr)
{
   struct nv30_render *r = nv30_render(render);
   struct nv30_context *nv30 = r->nv30;
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   unsigned fn = nr >> 8, pn = nr & 0xff;
   unsigned ps = fn + (pn ? 1 : 0);
   unsigned i;

   BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
   for (i = 0; i < r->vertex_info.num_attribs; i++) {
      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP,
                       nv04_resource(r->buffer), r->offset + r->vtxptr[i],
                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1);
   }

   if (!nv30_state_validate(nv30, FALSE))
      return;

   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, r->prim);

   BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps);
   while (fn--) {
      PUSH_DATA (push, 0xff000000 | start);
      start += 256;
   }

   if (pn)
      PUSH_DATA (push, ((pn - 1) << 24) | start);

   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
   PUSH_RESET(push, BUFCTX_VTXTMP);
}
void
nv30_vbo_validate(struct nv30_context *nv30)
{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nv30_vertex_stateobj *vertex = nv30->vertex;
   struct pipe_vertex_element *ve;
   struct pipe_vertex_buffer *vb;
   unsigned i, redefine;

   nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF);
   if (!nv30->vertex || nv30->draw_flags)
      return;

   if (unlikely(vertex->need_conversion)) {
      nv30->vbo_fifo = ~0;
      nv30->vbo_user = 0;
   } else {
      nv30_prevalidate_vbufs(nv30);
   }

   if (!PUSH_SPACE(push, 128))
      return;

   redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts);
   BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine);

   for (i = 0; i < vertex->num_elements; i++) {
      ve = &vertex->pipe[i];
      vb = &nv30->vtxbuf[ve->vertex_buffer_index];

      if (likely(vb->stride) || nv30->vbo_fifo)
         PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state);
      else
         PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
   }

   for (; i < nv30->state.num_vtxelts; i++) {
      PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
   }

   for (i = 0; i < vertex->num_elements; i++) {
      struct nv04_resource *res;
      unsigned offset;
      boolean user;

      ve = &vertex->pipe[i];
      vb = &nv30->vtxbuf[ve->vertex_buffer_index];
      user = (nv30->vbo_user & (1 << ve->vertex_buffer_index));

      res = nv04_resource(vb->buffer);

      if (nv30->vbo_fifo || unlikely(vb->stride == 0)) {
         if (!nv30->vbo_fifo)
            nv30_emit_vtxattr(nv30, vb, ve, i);
         continue;
      }

      offset = ve->src_offset + vb->buffer_offset;

      BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1);
      PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF,
                       res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD,
                       0, NV30_3D_VTXBUF_DMA1);
   }

   nv30->state.num_vtxelts = vertex->num_elements;
}
Exemplo n.º 6
0
void
nv30_fragprog_validate(struct nv30_context *nv30)
{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_object *eng3d = nv30->screen->eng3d;
   struct nv30_fragprog *fp = nv30->fragprog.program;
   bool upload = false;
   int i;

   if (!fp->translated) {
      _nvfx_fragprog_translate(eng3d->oclass, fp);
      if (!fp->translated)
         return;

      upload = true;
   }

   /* update constants, also needs to be done on every fp switch as we
    * have no idea whether the constbuf changed in the meantime
    */
   if (nv30->fragprog.constbuf) {
      struct pipe_resource *constbuf = nv30->fragprog.constbuf;
      uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data;

      for (i = 0; i < fp->nr_consts; i++) {
         unsigned off = fp->consts[i].offset;
         unsigned idx = fp->consts[i].index * 4;

         if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4))
            continue;
         memcpy(&fp->insn[off], &cbuf[idx], 4 * 4);
         upload = true;
      }
   }

   if (upload)
      nv30_fragprog_upload(nv30);

   /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts
    * were updated.  TEX_CACHE_CTL magic is not enough to convince the
    * GPU that it should re-read the fragprog from VRAM... sigh.
    */
   if (nv30->state.fragprog != fp || upload) {
      struct nv04_resource *r = nv04_resource(fp->buffer);

      if (!PUSH_SPACE(push, 8))
         return;
      PUSH_RESET(push, BUFCTX_FRAGPROG);

      BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
      PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0,
                       NOUVEAU_BO_LOW | NOUVEAU_BO_RD | NOUVEAU_BO_OR,
                       NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
                       NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
      BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
      PUSH_DATA (push, fp->fp_control);
      if (eng3d->oclass < NV40_3D_CLASS) {
         BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1);
         PUSH_DATA (push, 0x00010004);
         BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1);
         PUSH_DATA (push, fp->texcoords);
      } else {
         BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
         PUSH_DATA (push, 0x00000000);
      }

      nv30->state.fragprog = fp;
   }
}