/**************************************************************************
- *
- * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ *
+ * Copyright 2005 VMware, Inc.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
+#include <stdio.h>
#include "main/context.h"
#include "main/glheader.h"
#include "main/enums.h"
-#include "main/imports.h"
-#include "main/mtypes.h"
-#include "glapi/dispatch.h"
+#include "util/imports.h"
+#include "main/dispatch.h"
#include "glapi/glapi.h"
-#include "vbo_context.h"
+#include "vbo_private.h"
-
-typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
+typedef void (*attr_func)(struct gl_context *ctx, GLint index, const GLfloat *);
/* This file makes heavy use of the aliasing of NV vertex attributes
* with the legacy attributes, and also with ARB and Material
* attributes as currently implemented.
*/
-static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+static void
+VertexAttrib1fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
{
- CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
+ CALL_VertexAttrib1fvNV(ctx->Exec, (index, v));
}
-static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib2fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
{
- CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
+ CALL_VertexAttrib2fvNV(ctx->Exec, (index, v));
}
-static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib3fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
{
- CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
+ CALL_VertexAttrib3fvNV(ctx->Exec, (index, v));
}
-static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib4fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
{
- CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
+ CALL_VertexAttrib4fvNV(ctx->Exec, (index, v));
}
+
static attr_func vert_attrfunc[4] = {
VertexAttrib1fvNV,
VertexAttrib2fvNV,
VertexAttrib4fvNV
};
+
struct loopback_attr {
- GLint target;
- GLint sz;
+ enum vbo_attrib index;
+ GLuint offset;
attr_func func;
};
-/* Don't emit ends and begins on wrapped primitives. Don't replay
- * wrapped vertices. If we get here, it's probably because the the
+
+/**
+ * Don't emit ends and begins on wrapped primitives. Don't replay
+ * wrapped vertices. If we get here, it's probably because the
* precalculated wrapping is wrong.
*/
-static void loopback_prim( GLcontext *ctx,
- const GLfloat *buffer,
- const struct _mesa_prim *prim,
- GLuint wrap_count,
- GLuint vertex_size,
- const struct loopback_attr *la, GLuint nr )
+static void
+loopback_prim(struct gl_context *ctx,
+ const GLubyte *buffer,
+ const struct _mesa_prim *prim,
+ GLuint wrap_count,
+ GLuint stride,
+ const struct loopback_attr *la, GLuint nr)
{
- GLint start = prim->start;
- GLint end = start + prim->count;
- const GLfloat *data;
- GLint j;
- GLuint k;
+ GLuint start = prim->start;
+ const GLuint end = start + prim->count;
+ const GLubyte *data;
if (0)
- _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
- _mesa_lookup_prim_by_nr(prim->mode),
- prim->begin ? "begin" : "..",
- prim->end ? "end" : "..",
- start,
- end);
+ printf("loopback prim %s(%s,%s) verts %d..%d vsize %d\n",
+ _mesa_lookup_prim_by_nr(prim->mode),
+ prim->begin ? "begin" : "..",
+ prim->end ? "end" : "..",
+ start, end,
+ stride);
if (prim->begin) {
- CALL_Begin(GET_DISPATCH(), ( prim->mode ));
+ CALL_Begin(GET_DISPATCH(), (prim->mode));
}
else {
- assert(start == 0);
start += wrap_count;
}
- data = buffer + start * vertex_size;
+ data = buffer + start * stride;
- for (j = start ; j < end ; j++) {
- const GLfloat *tmp = data + la[0].sz;
+ for (GLuint j = start; j < end; j++) {
+ for (GLuint k = 0; k < nr; k++)
+ la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset));
- for (k = 1 ; k < nr ; k++) {
- la[k].func( ctx, la[k].target, tmp );
- tmp += la[k].sz;
- }
-
- /* Fire the vertex
- */
- la[0].func( ctx, VBO_ATTRIB_POS, data );
- data = tmp;
+ data += stride;
}
if (prim->end) {
}
}
-/* Primitives generated by DrawArrays/DrawElements/Rectf may be
- * caught here. If there is no primitive in progress, execute them
- * normally, otherwise need to track and discard the generated
- * primitives.
- */
-static void loopback_weak_prim( GLcontext *ctx,
- const struct _mesa_prim *prim )
+
+static inline void
+append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
+ const struct gl_vertex_array_object *vao)
{
- /* Use the prim_weak flag to ensure that if this primitive
- * wraps, we don't mistake future vertex_lists for part of the
- * surrounding primitive.
- *
- * While this flag is set, we are simply disposing of data
- * generated by an operation now known to be a noop.
- */
- if (prim->begin)
- ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
- if (prim->end)
- ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
+ la[*nr].index = shift + i;
+ la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
+ la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Format.Size - 1];
+ (*nr)++;
}
-void vbo_loopback_vertex_list( GLcontext *ctx,
- const GLfloat *buffer,
- const GLubyte *attrsz,
- const struct _mesa_prim *prim,
- GLuint prim_count,
- GLuint wrap_count,
- GLuint vertex_size)
+void
+_vbo_loopback_vertex_list(struct gl_context *ctx,
+ const struct vbo_save_vertex_list* node)
{
struct loopback_attr la[VBO_ATTRIB_MAX];
- GLuint i, nr = 0;
+ GLuint nr = 0;
/* All Legacy, NV, ARB and Material attributes are routed through
* the NV attributes entrypoints:
*/
- for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
- if (attrsz[i]) {
- la[nr].target = i;
- la[nr].sz = attrsz[i];
- la[nr].func = vert_attrfunc[attrsz[i]-1];
- nr++;
- }
+ const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF];
+ GLbitfield mask = vao->Enabled & VERT_BIT_MAT_ALL;
+ while (mask) {
+ const int i = u_bit_scan(&mask);
+ append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao);
+ }
+
+ vao = node->VAO[VP_MODE_SHADER];
+ mask = vao->Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0);
+ while (mask) {
+ const int i = u_bit_scan(&mask);
+ append_attr(&nr, la, i, 0, vao);
+ }
+
+ /* The last in the list should be the vertex provoking attribute */
+ if (vao->Enabled & VERT_BIT_GENERIC0) {
+ append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao);
+ } else if (vao->Enabled & VERT_BIT_POS) {
+ append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao);
+ }
+
+ const GLuint wrap_count = node->wrap_count;
+ const GLuint stride = _vbo_save_get_stride(node);
+ const GLubyte *buffer = NULL;
+ if (0 < nr) {
+ /* Compute the minimal offset into the vertex buffer object */
+ GLuint offset = ~0u;
+ for (GLuint i = 0; i < nr; ++i)
+ offset = MIN2(offset, la[i].offset);
+ for (GLuint i = 0; i < nr; ++i)
+ la[i].offset -= offset;
+
+ /* Get the mapped base pointer, assert sufficient mapping */
+ struct gl_buffer_object *bufferobj = vao->BufferBinding[0].BufferObj;
+ assert(bufferobj && bufferobj->Mappings[MAP_INTERNAL].Pointer);
+ buffer = bufferobj->Mappings[MAP_INTERNAL].Pointer;
+ assert(bufferobj->Mappings[MAP_INTERNAL].Offset
+ <= vao->BufferBinding[0].Offset + offset
+ + stride*(_vbo_save_get_min_index(node) + wrap_count));
+ buffer += vao->BufferBinding[0].Offset + offset
+ - bufferobj->Mappings[MAP_INTERNAL].Offset;
+ assert(stride*(_vbo_save_get_vertex_count(node) - wrap_count)
+ <= bufferobj->Mappings[MAP_INTERNAL].Length);
}
- for (i = 0 ; i < prim_count ; i++) {
- if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
- (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
- {
- loopback_weak_prim( ctx, &prim[i] );
- }
- else
- {
- loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
- }
+ /* Replay the primitives */
+ const struct _mesa_prim *prims = node->prims;
+ const GLuint prim_count = node->prim_count;
+ for (GLuint i = 0; i < prim_count; i++) {
+ loopback_prim(ctx, buffer, &prims[i], wrap_count, stride, la, nr);
}
}