17117f1b4Smrg/**************************************************************************
201e04c3fSmrg *
3af69d88dSmrg * Copyright 2005 VMware, Inc.
47117f1b4Smrg * All Rights Reserved.
501e04c3fSmrg *
67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77117f1b4Smrg * copy of this software and associated documentation files (the
87117f1b4Smrg * "Software"), to deal in the Software without restriction, including
97117f1b4Smrg * without limitation the rights to use, copy, modify, merge, publish,
107117f1b4Smrg * distribute, sub license, and/or sell copies of the Software, and to
117117f1b4Smrg * permit persons to whom the Software is furnished to do so, subject to
127117f1b4Smrg * the following conditions:
1301e04c3fSmrg *
147117f1b4Smrg * The above copyright notice and this permission notice (including the
157117f1b4Smrg * next paragraph) shall be included in all copies or substantial portions
167117f1b4Smrg * of the Software.
1701e04c3fSmrg *
187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
207117f1b4Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
227117f1b4Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
237117f1b4Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
247117f1b4Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2501e04c3fSmrg *
267117f1b4Smrg **************************************************************************/
277117f1b4Smrg
2801e04c3fSmrg#include <stdio.h>
29c1f859d4Smrg#include "main/context.h"
30c1f859d4Smrg#include "main/glheader.h"
31c1f859d4Smrg#include "main/enums.h"
327ec681f3Smrg#include "main/mesa_private.h"
33cdc920a0Smrg#include "main/dispatch.h"
34c1f859d4Smrg#include "glapi/glapi.h"
357117f1b4Smrg
3601e04c3fSmrg#include "vbo_private.h"
377117f1b4Smrg
387117f1b4Smrg
3901e04c3fSmrgtypedef void (*attr_func)(struct gl_context *ctx, GLint index, const GLfloat *);
407117f1b4Smrg
417117f1b4Smrg
427117f1b4Smrg/* This file makes heavy use of the aliasing of NV vertex attributes
437117f1b4Smrg * with the legacy attributes, and also with ARB and Material
447117f1b4Smrg * attributes as currently implemented.
457117f1b4Smrg */
4601e04c3fSmrgstatic void
4701e04c3fSmrgVertexAttrib1fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
487117f1b4Smrg{
4901e04c3fSmrg   CALL_VertexAttrib1fvNV(ctx->Exec, (index, v));
507117f1b4Smrg}
517117f1b4Smrg
5201e04c3fSmrg
5301e04c3fSmrgstatic void
5401e04c3fSmrgVertexAttrib2fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
557117f1b4Smrg{
5601e04c3fSmrg   CALL_VertexAttrib2fvNV(ctx->Exec, (index, v));
577117f1b4Smrg}
587117f1b4Smrg
5901e04c3fSmrg
6001e04c3fSmrgstatic void
6101e04c3fSmrgVertexAttrib3fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
627117f1b4Smrg{
6301e04c3fSmrg   CALL_VertexAttrib3fvNV(ctx->Exec, (index, v));
647117f1b4Smrg}
657117f1b4Smrg
6601e04c3fSmrg
6701e04c3fSmrgstatic void
6801e04c3fSmrgVertexAttrib4fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
697117f1b4Smrg{
7001e04c3fSmrg   CALL_VertexAttrib4fvNV(ctx->Exec, (index, v));
717117f1b4Smrg}
727117f1b4Smrg
7301e04c3fSmrg
747117f1b4Smrgstatic attr_func vert_attrfunc[4] = {
757117f1b4Smrg   VertexAttrib1fvNV,
767117f1b4Smrg   VertexAttrib2fvNV,
777117f1b4Smrg   VertexAttrib3fvNV,
787117f1b4Smrg   VertexAttrib4fvNV
797117f1b4Smrg};
807117f1b4Smrg
8101e04c3fSmrg
827117f1b4Smrgstruct loopback_attr {
8301e04c3fSmrg   enum vbo_attrib index;
8401e04c3fSmrg   GLuint offset;
857117f1b4Smrg   attr_func func;
867117f1b4Smrg};
877117f1b4Smrg
8801e04c3fSmrg
8901e04c3fSmrg/**
9001e04c3fSmrg * Don't emit ends and begins on wrapped primitives.  Don't replay
91cdc920a0Smrg * wrapped vertices.  If we get here, it's probably because the
927117f1b4Smrg * precalculated wrapping is wrong.
937117f1b4Smrg */
9401e04c3fSmrgstatic void
9501e04c3fSmrgloopback_prim(struct gl_context *ctx,
9601e04c3fSmrg              const GLubyte *buffer,
9701e04c3fSmrg              const struct _mesa_prim *prim,
9801e04c3fSmrg              GLuint wrap_count,
9901e04c3fSmrg              GLuint stride,
10001e04c3fSmrg              const struct loopback_attr *la, GLuint nr)
1017117f1b4Smrg{
10201e04c3fSmrg   GLuint start = prim->start;
10301e04c3fSmrg   const GLuint end = start + prim->count;
10401e04c3fSmrg   const GLubyte *data;
1057117f1b4Smrg
1067117f1b4Smrg   if (0)
10701e04c3fSmrg      printf("loopback prim %s(%s,%s) verts %d..%d  vsize %d\n",
10801e04c3fSmrg             _mesa_lookup_prim_by_nr(prim->mode),
10901e04c3fSmrg             prim->begin ? "begin" : "..",
11001e04c3fSmrg             prim->end ? "end" : "..",
11101e04c3fSmrg             start, end,
11201e04c3fSmrg             stride);
1137117f1b4Smrg
1147117f1b4Smrg   if (prim->begin) {
1157ec681f3Smrg      CALL_Begin(ctx->Exec, (prim->mode));
1167117f1b4Smrg   }
1177117f1b4Smrg   else {
1187117f1b4Smrg      start += wrap_count;
1197117f1b4Smrg   }
1207117f1b4Smrg
12101e04c3fSmrg   data = buffer + start * stride;
1227117f1b4Smrg
12301e04c3fSmrg   for (GLuint j = start; j < end; j++) {
12401e04c3fSmrg      for (GLuint k = 0; k < nr; k++)
12501e04c3fSmrg         la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset));
1267117f1b4Smrg
12701e04c3fSmrg      data += stride;
1287117f1b4Smrg   }
1297117f1b4Smrg
1307117f1b4Smrg   if (prim->end) {
1317ec681f3Smrg      CALL_End(ctx->Exec, ());
1327117f1b4Smrg   }
1337117f1b4Smrg}
1347117f1b4Smrg
13501e04c3fSmrg
13601e04c3fSmrgstatic inline void
13701e04c3fSmrgappend_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
13801e04c3fSmrg            const struct gl_vertex_array_object *vao)
1397117f1b4Smrg{
14001e04c3fSmrg   la[*nr].index = shift + i;
14101e04c3fSmrg   la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
1428a1362adSmaya   la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Format.Size - 1];
14301e04c3fSmrg   (*nr)++;
1447117f1b4Smrg}
1457117f1b4Smrg
1467117f1b4Smrg
14701e04c3fSmrgvoid
14801e04c3fSmrg_vbo_loopback_vertex_list(struct gl_context *ctx,
1497ec681f3Smrg                          const struct vbo_save_vertex_list* node,
1507ec681f3Smrg                          fi_type *buffer)
1517117f1b4Smrg{
1527117f1b4Smrg   struct loopback_attr la[VBO_ATTRIB_MAX];
15301e04c3fSmrg   GLuint nr = 0;
1547117f1b4Smrg
1557117f1b4Smrg   /* All Legacy, NV, ARB and Material attributes are routed through
1567117f1b4Smrg    * the NV attributes entrypoints:
1577117f1b4Smrg    */
15801e04c3fSmrg   const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF];
1598a1362adSmaya   GLbitfield mask = vao->Enabled & VERT_BIT_MAT_ALL;
16001e04c3fSmrg   while (mask) {
16101e04c3fSmrg      const int i = u_bit_scan(&mask);
16201e04c3fSmrg      append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao);
16301e04c3fSmrg   }
16401e04c3fSmrg
16501e04c3fSmrg   vao = node->VAO[VP_MODE_SHADER];
1668a1362adSmaya   mask = vao->Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0);
16701e04c3fSmrg   while (mask) {
16801e04c3fSmrg      const int i = u_bit_scan(&mask);
16901e04c3fSmrg      append_attr(&nr, la, i, 0, vao);
17001e04c3fSmrg   }
17101e04c3fSmrg
17201e04c3fSmrg   /* The last in the list should be the vertex provoking attribute */
1738a1362adSmaya   if (vao->Enabled & VERT_BIT_GENERIC0) {
17401e04c3fSmrg      append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao);
1758a1362adSmaya   } else if (vao->Enabled & VERT_BIT_POS) {
17601e04c3fSmrg      append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao);
17701e04c3fSmrg   }
17801e04c3fSmrg
1797ec681f3Smrg   const GLuint wrap_count = node->cold->wrap_count;
18001e04c3fSmrg   const GLuint stride = _vbo_save_get_stride(node);
1817117f1b4Smrg
18201e04c3fSmrg   /* Replay the primitives */
1837ec681f3Smrg   const struct _mesa_prim *prims = node->cold->prims;
1847ec681f3Smrg   const GLuint prim_count = node->cold->prim_count;
1857ec681f3Smrg
18601e04c3fSmrg   for (GLuint i = 0; i < prim_count; i++) {
1877ec681f3Smrg      loopback_prim(ctx, (GLubyte*)buffer + vao->BufferBinding[0].Offset,
1887ec681f3Smrg                    &prims[i], wrap_count, stride, la, nr);
1897117f1b4Smrg   }
1907117f1b4Smrg}
191