-
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.1
*
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2007 Brian Paul 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"),
* Keith Whitwell <keith@tungstengraphics.com>
*/
-#include "glheader.h"
-#include "context.h"
-#include "imports.h"
-#include "state.h"
-#include "mtypes.h"
-#include "macros.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/state.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
#include "t_context.h"
#include "t_pipeline.h"
-static GLfloat *get_space(GLcontext *ctx, GLuint bytes)
+static GLubyte *get_space(GLcontext *ctx, GLuint bytes)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLubyte *space = _mesa_malloc(bytes);
tnl->block[tnl->nr_blocks++] = space;
- return (GLfloat *)space;
+ return space;
}
} while (0)
+/**
+ * Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
+ * \param ptr input/ubyte array
+ * \param fptr output/float array
+ */
+static void
+convert_bgra_to_float(const struct gl_client_array *input,
+ const GLubyte *ptr, GLfloat *fptr,
+ GLuint count )
+{
+ GLuint i;
+ assert(input->Normalized);
+ assert(input->Size == 4);
+ for (i = 0; i < count; i++) {
+ const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
+ *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
+ *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
+ *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
+ *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
+ ptr += input->StrideB;
+ }
+}
+
/* Adjust pointer to point at first requested element, convert to
* floating point, populate VB->AttribPtr[].
*/
static void _tnl_import_array( GLcontext *ctx,
GLuint attrib,
- GLuint start,
- GLuint end,
+ GLuint count,
const struct gl_client_array *input,
- const char *ptr )
+ const GLubyte *ptr )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- const GLuint count = end - start;
GLuint stride = input->StrideB;
- ptr += start * stride;
-
if (input->Type != GL_FLOAT) {
const GLuint sz = input->Size;
- GLfloat *fptr = get_space(ctx, count * sz * sizeof(GLfloat));
+ GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
+ GLfloat *fptr = (GLfloat *)buf;
switch (input->Type) {
case GL_BYTE:
CONVERT(GLbyte, BYTE_TO_FLOAT);
break;
case GL_UNSIGNED_BYTE:
- CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ if (input->Format == GL_BGRA) {
+ /* See GL_EXT_vertex_array_bgra */
+ convert_bgra_to_float(input, ptr, fptr, count);
+ }
+ else {
+ CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ }
break;
case GL_SHORT:
CONVERT(GLshort, SHORT_TO_FLOAT);
break;
}
- ptr = (const char *)fptr;
+ ptr = buf;
stride = sz * sizeof(GLfloat);
}
static void bind_inputs( GLcontext *ctx,
const struct gl_client_array *inputs[],
- GLint start, GLint end,
+ GLint count,
struct gl_buffer_object **bo,
GLuint *nr_bo )
{
if (inputs[i]->BufferObj->Name) {
if (!inputs[i]->BufferObj->Pointer) {
bo[*nr_bo] = inputs[i]->BufferObj;
- *nr_bo++;
+ (*nr_bo)++;
ctx->Driver.MapBuffer(ctx,
GL_ARRAY_BUFFER,
GL_READ_ONLY_ARB,
ptr = inputs[i]->Ptr;
/* Just make sure the array is floating point, otherwise convert to
- * temporary storage. Rebase arrays so that 'start' becomes
- * element zero.
+ * temporary storage.
*
* XXX: remove the GLvector4f type at some stage and just use
* client arrays.
*/
- _tnl_import_array(ctx, i, start, end, inputs[i], ptr);
+ _tnl_import_array(ctx, i, count, inputs[i], ptr);
}
+ /* We process only the vertices between min & max index:
+ */
+ VB->Count = count;
+
+
/* Legacy pointers -- remove one day.
*/
VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS];
VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
VB->Count );
}
-
+ else {
+ /* the data previously pointed to by EdgeFlag may have been freed */
+ VB->EdgeFlag = NULL;
+ }
}
/* Translate indices to GLuints and store in VB->Elts.
*/
-static void bind_indicies( GLcontext *ctx,
- const struct _mesa_index_buffer *ib,
- struct gl_buffer_object **bo,
- GLuint *nr_bo)
+static void bind_indices( GLcontext *ctx,
+ const struct _mesa_index_buffer *ib,
+ struct gl_buffer_object **bo,
+ GLuint *nr_bo)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+ void *ptr;
- if (!ib)
+ if (!ib) {
+ VB->Elts = NULL;
return;
+ }
if (ib->obj->Name && !ib->obj->Pointer) {
bo[*nr_bo] = ib->obj;
- *nr_bo++;
+ (*nr_bo)++;
ctx->Driver.MapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER,
GL_READ_ONLY_ARB,
assert(ib->obj->Pointer);
}
- VB->Elts = (GLuint *)ADD_POINTERS(ib->obj->Pointer,
- ib->ptr);
-
- VB->Elts += ib->rebase;
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
- switch (ib->type) {
- case GL_UNSIGNED_INT:
- return;
- case GL_UNSIGNED_SHORT:
- break;
- case GL_UNSIGNED_BYTE:
- break;
+ if (ib->type == GL_UNSIGNED_INT) {
+ VB->Elts = (GLuint *) ptr;
+ }
+ else {
+ GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
+ VB->Elts = elts;
+
+ if (ib->type == GL_UNSIGNED_SHORT) {
+ const GLushort *in = (GLushort *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++);
+ }
+ else {
+ const GLubyte *in = (GLubyte *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++);
+ }
}
}
+static void bind_prims( GLcontext *ctx,
+ const struct _mesa_prim *prim,
+ GLuint nr_prims )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ VB->Primitive = prim;
+ VB->PrimitiveCount = nr_prims;
+}
+
static void unmap_vbos( GLcontext *ctx,
struct gl_buffer_object **bo,
GLuint nr_bo )
GLuint max_index)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct vertex_buffer *VB = &tnl->vb;
+ const GLuint TEST_SPLIT = 0;
+ const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
- /* May need to map a vertex buffer object for every attribute plus
- * one for the index buffer.
- */
- struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
- GLuint nr_bo = 0;
+ if (0)
+ {
+ GLuint i;
+ _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ for (i = 0; i < nr_prims; i++)
+ _mesa_printf("prim %d: %s start %d count %d\n", i,
+ _mesa_lookup_enum_by_nr(prim[i].mode),
+ prim[i].start,
+ prim[i].count);
+ }
- /* Binding inputs may imply mapping some vertex buffer objects.
- * They will need to be unmapped below.
- */
- bind_inputs(ctx, arrays, min_index, max_index, bo, &nr_bo);
- bind_indicies(ctx, ib, bo, &nr_bo);
+ if (min_index) {
+ /* We always translate away calls with min_index != 0.
+ */
+ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index,
+ _tnl_draw_prims );
+ return;
+ }
+ else if (max_index > max) {
+ /* The software TNL pipeline has a fixed amount of storage for
+ * vertices and it is necessary to split incoming drawing commands
+ * if they exceed that limit.
+ */
+ struct split_limits limits;
+ limits.max_verts = max;
+ limits.max_vb_size = ~0;
+ limits.max_indices = ~0;
- VB->Primitive = prim;
- VB->PrimitiveCount = nr_prims;
- VB->Count = max_index - min_index;
+ /* This will split the buffers one way or another and
+ * recursively call back into this function.
+ */
+ vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
+ 0, max_index,
+ _tnl_draw_prims,
+ &limits );
+ }
+ else {
+ /* May need to map a vertex buffer object for every attribute plus
+ * one for the index buffer.
+ */
+ struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
+ GLuint nr_bo = 0;
- TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
+ /* Binding inputs may imply mapping some vertex buffer objects.
+ * They will need to be unmapped below.
+ */
+ bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
+ bind_indices(ctx, ib, bo, &nr_bo);
+ bind_prims(ctx, prim, nr_prims );
- unmap_vbos(ctx, bo, nr_bo);
- free_space(ctx);
+ TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
+
+ unmap_vbos(ctx, bo, nr_bo);
+ free_space(ctx);
+ }
}