static void *
nv30_vertex_state_create(struct pipe_context *pipe, unsigned num_elements,
                         const struct pipe_vertex_element *elements)
{
    struct nv30_vertex_stateobj *so;
    struct translate_key transkey;
    unsigned i;

    assert(num_elements);

    so = MALLOC(sizeof(*so) + sizeof(*so->element) * num_elements);
    if (!so)
        return NULL;
    memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
    so->num_elements = num_elements;
    so->need_conversion = FALSE;

    transkey.nr_elements = 0;
    transkey.output_stride = 0;

    for (i = 0; i < num_elements; i++) {
        const struct pipe_vertex_element *ve = &elements[i];
        const unsigned vbi = ve->vertex_buffer_index;
        enum pipe_format fmt = ve->src_format;

        so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
        if (!so->element[i].state) {
            switch (util_format_get_nr_components(fmt)) {
            case 1: fmt = PIPE_FORMAT_R32_FLOAT; break;
            case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break;
            case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break;
            case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break;
            default:
                assert(0);
                return NULL;
            }
            so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw;
            so->need_conversion = TRUE;
        }

        if (1) {
            unsigned j = transkey.nr_elements++;

            transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL;
            transkey.element[j].input_format = ve->src_format;
            transkey.element[j].input_buffer = vbi;
            transkey.element[j].input_offset = ve->src_offset;
            transkey.element[j].instance_divisor = ve->instance_divisor;

            transkey.element[j].output_format = fmt;
            transkey.element[j].output_offset = transkey.output_stride;
            transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3;
        }
    }

    so->translate = translate_create(&transkey);
    so->vtx_size = transkey.output_stride / 4;
    so->vtx_per_packet_max = NV04_PFIFO_MAX_PACKET_LEN / MAX2(so->vtx_size, 1);
    return so;
}
Ejemplo n.º 2
0
static boolean
vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx)
{
   struct nv30_screen *screen = r->nv30->screen;
   struct nv30_fragprog *fp = r->nv30->fragprog.program;
   struct vertex_info *vinfo = &r->vertex_info;
   enum pipe_format format;
   uint emit = EMIT_OMIT;
   uint result = *idx;

   if (sem == TGSI_SEMANTIC_GENERIC) {
      uint num_texcoords = (screen->eng3d->oclass < NV40_3D_CLASS) ? 8 : 10;
      for (result = 0; result < num_texcoords; result++) {
         if (fp->texcoord[result] == *idx + 8) {
            sem = TGSI_SEMANTIC_TEXCOORD;
            emit = vroute[sem].emit;
            break;
         }
      }
   } else {
      emit = vroute[sem].emit;
   }

   if (emit == EMIT_OMIT)
      return FALSE;

   draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib);
   format = draw_translate_vinfo_format(emit);

   r->vtxfmt[attrib] = nv30_vtxfmt(&screen->base.base, format)->hw;
   r->vtxptr[attrib] = vinfo->size;
   vinfo->size += draw_translate_vinfo_size(emit);

   if (screen->eng3d->oclass < NV40_3D_CLASS) {
      r->vtxprog[attrib][0] = 0x001f38d8;
      r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9);
      r->vtxprog[attrib][2] = 0x0836106c;
      r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2;
   } else {
      r->vtxprog[attrib][0] = 0x401f9c6c;
      r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8);
      r->vtxprog[attrib][2] = 0x8106c083;
      r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2;
   }

   if (result < 8)
      *idx = vroute[sem].ow40 << result;
   else {
      assert(sem == TGSI_SEMANTIC_TEXCOORD);
      *idx = 0x00001000 << (result - 8);
   }
   return TRUE;
}