Use new rebase helper. Remove other rebase code.
This commit is contained in:
@@ -198,7 +198,9 @@ static void brw_merge_inputs( struct brw_context *brw,
|
|||||||
brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
|
brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX: could split the primitive list to fallback only on the
|
||||||
|
* non-conformant primitives.
|
||||||
|
*/
|
||||||
static GLboolean check_fallbacks( struct brw_context *brw,
|
static GLboolean check_fallbacks( struct brw_context *brw,
|
||||||
const struct _mesa_prim *prim,
|
const struct _mesa_prim *prim,
|
||||||
GLuint nr_prims )
|
GLuint nr_prims )
|
||||||
@@ -251,7 +253,9 @@ static GLboolean check_fallbacks( struct brw_context *brw,
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* May fail if out of video memory for texture or vbo upload, or on
|
||||||
|
* fallback conditions.
|
||||||
|
*/
|
||||||
static GLboolean brw_try_draw_prims( GLcontext *ctx,
|
static GLboolean brw_try_draw_prims( GLcontext *ctx,
|
||||||
const struct gl_client_array *arrays[],
|
const struct gl_client_array *arrays[],
|
||||||
const struct _mesa_prim *prim,
|
const struct _mesa_prim *prim,
|
||||||
@@ -376,6 +380,33 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLboolean brw_need_rebase( GLcontext *ctx,
|
||||||
|
const struct gl_client_array *arrays[],
|
||||||
|
const struct _mesa_index_buffer *ib,
|
||||||
|
GLuint min_index )
|
||||||
|
{
|
||||||
|
if (min_index == 0)
|
||||||
|
return GL_FALSE;
|
||||||
|
|
||||||
|
if (ib) {
|
||||||
|
if (!vbo_all_varyings_in_vbos(arrays))
|
||||||
|
return GL_TRUE;
|
||||||
|
else
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Hmm. This isn't quite what I wanted. BRW can actually
|
||||||
|
* handle the mixed case well enough that we shouldn't need to
|
||||||
|
* rebase. However, it's probably not very common, nor hugely
|
||||||
|
* expensive to do it this way:
|
||||||
|
*/
|
||||||
|
if (!vbo_all_varyings_in_vbos(arrays))
|
||||||
|
return GL_TRUE;
|
||||||
|
else
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void brw_draw_prims( GLcontext *ctx,
|
void brw_draw_prims( GLcontext *ctx,
|
||||||
const struct gl_client_array *arrays[],
|
const struct gl_client_array *arrays[],
|
||||||
@@ -388,6 +419,21 @@ void brw_draw_prims( GLcontext *ctx,
|
|||||||
struct intel_context *intel = intel_context(ctx);
|
struct intel_context *intel = intel_context(ctx);
|
||||||
GLboolean retval;
|
GLboolean retval;
|
||||||
|
|
||||||
|
/* Decide if we want to rebase. If so we end up recursing once
|
||||||
|
* only into this function.
|
||||||
|
*/
|
||||||
|
if (brw_need_rebase( ctx, arrays, ib, min_index )) {
|
||||||
|
vbo_rebase_prims( ctx, arrays,
|
||||||
|
prim, nr_prims,
|
||||||
|
ib, min_index, max_index,
|
||||||
|
brw_draw_prims );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Make a first attempt at drawing:
|
||||||
|
*/
|
||||||
retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
|
retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
|
||||||
|
|
||||||
|
|
||||||
@@ -440,14 +486,13 @@ void brw_draw_init( struct brw_context *brw )
|
|||||||
for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) {
|
for (i = 0; i < BRW_NR_UPLOAD_BUFS; i++) {
|
||||||
brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
|
brw->vb.upload.vbo[i] = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
|
||||||
|
|
||||||
/* XXX: Set these to no-backing-store
|
/* NOTE: These are set to no-backing-store.
|
||||||
*/
|
*/
|
||||||
bmBufferSetInvalidateCB(&brw->intel,
|
bmBufferSetInvalidateCB(&brw->intel,
|
||||||
intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])),
|
intel_bufferobj_buffer(intel_buffer_object(brw->vb.upload.vbo[i])),
|
||||||
brw_invalidate_vbo_cb,
|
brw_invalidate_vbo_cb,
|
||||||
&brw->intel,
|
&brw->intel,
|
||||||
GL_TRUE);
|
GL_TRUE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->Driver.BufferData( ctx,
|
ctx->Driver.BufferData( ctx,
|
||||||
|
@@ -309,7 +309,6 @@ copy_array_to_vbo_array( struct brw_context *brw,
|
|||||||
GLuint i,
|
GLuint i,
|
||||||
const struct gl_client_array *array,
|
const struct gl_client_array *array,
|
||||||
GLuint element_size,
|
GLuint element_size,
|
||||||
GLuint min_index,
|
|
||||||
GLuint count)
|
GLuint count)
|
||||||
{
|
{
|
||||||
GLcontext *ctx = &brw->intel.ctx;
|
GLcontext *ctx = &brw->intel.ctx;
|
||||||
@@ -347,7 +346,7 @@ copy_array_to_vbo_array( struct brw_context *brw,
|
|||||||
map += offset;
|
map += offset;
|
||||||
|
|
||||||
copy_strided_array( map,
|
copy_strided_array( map,
|
||||||
array->Ptr + min_index * array->StrideB,
|
array->Ptr,
|
||||||
element_size,
|
element_size,
|
||||||
array->StrideB,
|
array->StrideB,
|
||||||
count);
|
count);
|
||||||
@@ -438,10 +437,8 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
upload[nr_uploads++] = input;
|
upload[nr_uploads++] = input;
|
||||||
input->vbo_rebase_offset = 0;
|
assert(min_index == 0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
input->vbo_rebase_offset = min_index * input->glarray->StrideB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Upload interleaved arrays if all uploads are interleaved
|
/* Upload interleaved arrays if all uploads are interleaved
|
||||||
@@ -454,7 +451,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
|
|||||||
input0->glarray = copy_array_to_vbo_array(brw, 0,
|
input0->glarray = copy_array_to_vbo_array(brw, 0,
|
||||||
input0->glarray,
|
input0->glarray,
|
||||||
interleave,
|
interleave,
|
||||||
min_index,
|
|
||||||
input0->count);
|
input0->count);
|
||||||
|
|
||||||
for (i = 1; i < nr_uploads; i++) {
|
for (i = 1; i < nr_uploads; i++) {
|
||||||
@@ -472,7 +468,6 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
|
|||||||
input->glarray = copy_array_to_vbo_array(brw, i,
|
input->glarray = copy_array_to_vbo_array(brw, i,
|
||||||
input->glarray,
|
input->glarray,
|
||||||
input->element_size,
|
input->element_size,
|
||||||
min_index,
|
|
||||||
input->count);
|
input->count);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -520,9 +515,9 @@ GLboolean brw_upload_vertices( struct brw_context *brw,
|
|||||||
vbp.vb[i].vb0.bits.pad = 0;
|
vbp.vb[i].vb0.bits.pad = 0;
|
||||||
vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA;
|
vbp.vb[i].vb0.bits.access_type = BRW_VERTEXBUFFER_ACCESS_VERTEXDATA;
|
||||||
vbp.vb[i].vb0.bits.vb_index = i;
|
vbp.vb[i].vb0.bits.vb_index = i;
|
||||||
vbp.vb[i].offset = (GLuint)input->glarray->Ptr + input->vbo_rebase_offset;
|
vbp.vb[i].offset = (GLuint)input->glarray->Ptr;
|
||||||
vbp.vb[i].buffer = array_buffer(input->glarray);
|
vbp.vb[i].buffer = array_buffer(input->glarray);
|
||||||
vbp.vb[i].max_index = max_index - min_index;
|
vbp.vb[i].max_index = max_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -563,93 +558,31 @@ static GLuint element_size( GLenum type )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void brw_upload_indices( struct brw_context *brw,
|
||||||
static void rebase_indices_to_vbo_indices( struct brw_context *brw,
|
const struct _mesa_index_buffer *index_buffer )
|
||||||
const struct _mesa_index_buffer *index_buffer,
|
|
||||||
struct gl_buffer_object **vbo_return,
|
|
||||||
GLuint *offset_return )
|
|
||||||
{
|
{
|
||||||
GLcontext *ctx = &brw->intel.ctx;
|
GLcontext *ctx = &brw->intel.ctx;
|
||||||
GLuint min_index = index_buffer->rebase;
|
|
||||||
const void *indices = index_buffer->ptr;
|
|
||||||
GLsizei count = index_buffer->count;
|
|
||||||
GLenum type = index_buffer->type;
|
|
||||||
GLuint size = element_size(type) * count;
|
|
||||||
struct gl_buffer_object *bufferobj;
|
|
||||||
GLuint offset;
|
|
||||||
GLuint i;
|
|
||||||
|
|
||||||
get_space(brw, size, &bufferobj, &offset);
|
|
||||||
|
|
||||||
*vbo_return = bufferobj;
|
|
||||||
*offset_return = offset;
|
|
||||||
|
|
||||||
if (min_index == 0) {
|
|
||||||
/* Straight upload
|
|
||||||
*/
|
|
||||||
ctx->Driver.BufferSubData( ctx,
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
|
||||||
offset,
|
|
||||||
size,
|
|
||||||
indices,
|
|
||||||
bufferobj);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
void *map = ctx->Driver.MapBuffer(ctx,
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
|
||||||
GL_DYNAMIC_DRAW_ARB,
|
|
||||||
bufferobj);
|
|
||||||
|
|
||||||
map += offset;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case GL_UNSIGNED_INT: {
|
|
||||||
GLuint *ui_map = (GLuint *)map;
|
|
||||||
const GLuint *ui_indices = (const GLuint *)indices;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
ui_map[i] = ui_indices[i] - min_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_UNSIGNED_SHORT: {
|
|
||||||
GLushort *us_map = (GLushort *)map;
|
|
||||||
const GLushort *us_indices = (const GLushort *)indices;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
us_map[i] = us_indices[i] - min_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GL_UNSIGNED_BYTE: {
|
|
||||||
GLubyte *ub_map = (GLubyte *)map;
|
|
||||||
const GLubyte *ub_indices = (const GLubyte *)indices;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
ub_map[i] = ub_indices[i] - min_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->Driver.UnmapBuffer(ctx,
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
|
||||||
bufferobj);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void brw_upload_indices( struct brw_context *brw,
|
|
||||||
const struct _mesa_index_buffer *index_buffer)
|
|
||||||
{
|
|
||||||
struct intel_context *intel = &brw->intel;
|
struct intel_context *intel = &brw->intel;
|
||||||
GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
|
GLuint ib_size = get_size(index_buffer->type) * index_buffer->count;
|
||||||
struct gl_buffer_object *bufferobj = index_buffer->obj;
|
struct gl_buffer_object *bufferobj = index_buffer->obj;
|
||||||
GLuint offset = (GLuint)index_buffer->ptr;
|
GLuint offset = (GLuint)index_buffer->ptr;
|
||||||
|
|
||||||
/* Already turned into a proper VBO:
|
/* Turn into a proper VBO:
|
||||||
*/
|
*/
|
||||||
if (!index_buffer->obj->Name) {
|
if (!bufferobj->Name) {
|
||||||
rebase_indices_to_vbo_indices(brw, index_buffer, &bufferobj, &offset );
|
|
||||||
|
/* Get new bufferobj, offset:
|
||||||
|
*/
|
||||||
|
get_space(brw, ib_size, &bufferobj, &offset);
|
||||||
|
|
||||||
|
/* Straight upload
|
||||||
|
*/
|
||||||
|
ctx->Driver.BufferSubData( ctx,
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||||
|
offset,
|
||||||
|
ib_size,
|
||||||
|
index_buffer->ptr,
|
||||||
|
bufferobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit the indexbuffer packet:
|
/* Emit the indexbuffer packet:
|
||||||
|
@@ -95,18 +95,14 @@ static void free_space(GLcontext *ctx)
|
|||||||
*/
|
*/
|
||||||
static void _tnl_import_array( GLcontext *ctx,
|
static void _tnl_import_array( GLcontext *ctx,
|
||||||
GLuint attrib,
|
GLuint attrib,
|
||||||
GLuint start,
|
GLuint count,
|
||||||
GLuint end,
|
|
||||||
const struct gl_client_array *input,
|
const struct gl_client_array *input,
|
||||||
const GLubyte *ptr )
|
const GLubyte *ptr )
|
||||||
{
|
{
|
||||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||||
struct vertex_buffer *VB = &tnl->vb;
|
struct vertex_buffer *VB = &tnl->vb;
|
||||||
const GLuint count = end - start;
|
|
||||||
GLuint stride = input->StrideB;
|
GLuint stride = input->StrideB;
|
||||||
|
|
||||||
ptr += start * stride;
|
|
||||||
|
|
||||||
if (input->Type != GL_FLOAT) {
|
if (input->Type != GL_FLOAT) {
|
||||||
const GLuint sz = input->Size;
|
const GLuint sz = input->Size;
|
||||||
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
|
GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
|
||||||
@@ -183,7 +179,7 @@ static GLboolean *_tnl_import_edgeflag( GLcontext *ctx,
|
|||||||
|
|
||||||
static void bind_inputs( GLcontext *ctx,
|
static void bind_inputs( GLcontext *ctx,
|
||||||
const struct gl_client_array *inputs[],
|
const struct gl_client_array *inputs[],
|
||||||
GLint min_index, GLint max_index,
|
GLint count,
|
||||||
struct gl_buffer_object **bo,
|
struct gl_buffer_object **bo,
|
||||||
GLuint *nr_bo )
|
GLuint *nr_bo )
|
||||||
{
|
{
|
||||||
@@ -215,18 +211,17 @@ static void bind_inputs( GLcontext *ctx,
|
|||||||
ptr = inputs[i]->Ptr;
|
ptr = inputs[i]->Ptr;
|
||||||
|
|
||||||
/* Just make sure the array is floating point, otherwise convert to
|
/* Just make sure the array is floating point, otherwise convert to
|
||||||
* temporary storage. Rebase arrays so that 'min_index' becomes
|
* temporary storage.
|
||||||
* element zero.
|
|
||||||
*
|
*
|
||||||
* XXX: remove the GLvector4f type at some stage and just use
|
* XXX: remove the GLvector4f type at some stage and just use
|
||||||
* client arrays.
|
* client arrays.
|
||||||
*/
|
*/
|
||||||
_tnl_import_array(ctx, i, min_index, max_index, inputs[i], ptr);
|
_tnl_import_array(ctx, i, count, inputs[i], ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We process only the vertices between min & max index:
|
/* We process only the vertices between min & max index:
|
||||||
*/
|
*/
|
||||||
VB->Count = max_index - min_index;
|
VB->Count = count;
|
||||||
|
|
||||||
|
|
||||||
/* Legacy pointers -- remove one day.
|
/* Legacy pointers -- remove one day.
|
||||||
@@ -264,7 +259,6 @@ static void bind_inputs( GLcontext *ctx,
|
|||||||
*/
|
*/
|
||||||
static void bind_indices( GLcontext *ctx,
|
static void bind_indices( GLcontext *ctx,
|
||||||
const struct _mesa_index_buffer *ib,
|
const struct _mesa_index_buffer *ib,
|
||||||
GLuint min_index,
|
|
||||||
struct gl_buffer_object **bo,
|
struct gl_buffer_object **bo,
|
||||||
GLuint *nr_bo)
|
GLuint *nr_bo)
|
||||||
{
|
{
|
||||||
@@ -273,8 +267,10 @@ static void bind_indices( GLcontext *ctx,
|
|||||||
GLuint i;
|
GLuint i;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
if (!ib)
|
if (!ib) {
|
||||||
|
VB->Elts = NULL;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ib->obj->Name && !ib->obj->Pointer) {
|
if (ib->obj->Name && !ib->obj->Pointer) {
|
||||||
bo[*nr_bo] = ib->obj;
|
bo[*nr_bo] = ib->obj;
|
||||||
@@ -289,60 +285,34 @@ static void bind_indices( GLcontext *ctx,
|
|||||||
|
|
||||||
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
|
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
|
||||||
|
|
||||||
if (ib->type == GL_UNSIGNED_INT && min_index == 0) {
|
if (ib->type == GL_UNSIGNED_INT) {
|
||||||
VB->Elts = (GLuint *) ptr;
|
VB->Elts = (GLuint *) ptr;
|
||||||
VB->Elts += ib->rebase;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
|
GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
|
||||||
VB->Elts = elts;
|
VB->Elts = elts;
|
||||||
|
|
||||||
switch (ib->type) {
|
if (ib->type == GL_UNSIGNED_SHORT) {
|
||||||
case GL_UNSIGNED_INT: {
|
const GLushort *in = (GLushort *)ptr;
|
||||||
const GLuint *in = ((GLuint *)ptr) + ib->rebase;
|
|
||||||
for (i = 0; i < ib->count; i++)
|
for (i = 0; i < ib->count; i++)
|
||||||
*elts++ = *in++ - min_index;
|
*elts++ = (GLuint)(*in++);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case GL_UNSIGNED_SHORT: {
|
else {
|
||||||
const GLushort *in = ((GLushort *)ptr) + ib->rebase;
|
const GLubyte *in = (GLubyte *)ptr;
|
||||||
for (i = 0; i < ib->count; i++)
|
for (i = 0; i < ib->count; i++)
|
||||||
*elts++ = (GLuint)(*in++) - min_index;
|
*elts++ = (GLuint)(*in++);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case GL_UNSIGNED_BYTE: {
|
|
||||||
const GLubyte *in = ((GLubyte *)ptr) + ib->rebase;
|
|
||||||
for (i = 0; i < ib->count; i++)
|
|
||||||
*elts++ = (GLuint)(*in++) - min_index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bind_prims( GLcontext *ctx,
|
static void bind_prims( GLcontext *ctx,
|
||||||
const struct _mesa_prim *prim,
|
const struct _mesa_prim *prim,
|
||||||
GLuint nr_prims,
|
GLuint nr_prims )
|
||||||
GLuint min_index )
|
|
||||||
{
|
{
|
||||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||||
struct vertex_buffer *VB = &tnl->vb;
|
struct vertex_buffer *VB = &tnl->vb;
|
||||||
GLuint i;
|
|
||||||
|
|
||||||
if (min_index != 0) {
|
|
||||||
struct _mesa_prim *tmp = (struct _mesa_prim *)get_space(ctx, nr_prims * sizeof(*prim));
|
|
||||||
|
|
||||||
for (i = 0; i < nr_prims; i++) {
|
|
||||||
tmp[i] = prim[i];
|
|
||||||
tmp[i].start -= min_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
VB->Primitive = tmp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VB->Primitive = prim;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
VB->Primitive = prim;
|
||||||
VB->PrimitiveCount = nr_prims;
|
VB->PrimitiveCount = nr_prims;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,19 +343,10 @@ void _tnl_draw_prims( GLcontext *ctx,
|
|||||||
GLuint max_index)
|
GLuint max_index)
|
||||||
{
|
{
|
||||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||||
struct vertex_buffer *VB = &tnl->vb;
|
const GLuint TEST_SPLIT = 0;
|
||||||
GLint max = VB->Size;
|
const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
|
||||||
|
|
||||||
#ifdef TEST_SPLIT
|
if (0)
|
||||||
max = 8 + MAX_CLIPPED_VERTICES;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert(max_index > min_index);
|
|
||||||
assert(!(max_index & 0x80000000));
|
|
||||||
|
|
||||||
VB->Elts = NULL;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
{
|
||||||
GLuint i;
|
GLuint i;
|
||||||
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
|
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
|
||||||
@@ -395,15 +356,22 @@ void _tnl_draw_prims( GLcontext *ctx,
|
|||||||
prim[i].start,
|
prim[i].start,
|
||||||
prim[i].count);
|
prim[i].count);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The software TNL pipeline has a fixed amount of storage for
|
if (min_index) {
|
||||||
* vertices and it is necessary to split incoming drawing commands
|
/* We always translate away calls with min_index != 0.
|
||||||
* if they exceed that limit.
|
*/
|
||||||
*/
|
vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
|
||||||
if (max_index - min_index >= max - MAX_CLIPPED_VERTICES) {
|
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;
|
struct split_limits limits;
|
||||||
limits.max_verts = max - MAX_CLIPPED_VERTICES;
|
limits.max_verts = max;
|
||||||
limits.max_vb_size = ~0;
|
limits.max_vb_size = ~0;
|
||||||
limits.max_indices = ~0;
|
limits.max_indices = ~0;
|
||||||
|
|
||||||
@@ -411,7 +379,7 @@ void _tnl_draw_prims( GLcontext *ctx,
|
|||||||
* recursively call back into this function.
|
* recursively call back into this function.
|
||||||
*/
|
*/
|
||||||
vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
|
vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
|
||||||
min_index, max_index,
|
0, max_index,
|
||||||
_tnl_draw_prims,
|
_tnl_draw_prims,
|
||||||
&limits );
|
&limits );
|
||||||
}
|
}
|
||||||
@@ -425,9 +393,9 @@ void _tnl_draw_prims( GLcontext *ctx,
|
|||||||
/* Binding inputs may imply mapping some vertex buffer objects.
|
/* Binding inputs may imply mapping some vertex buffer objects.
|
||||||
* They will need to be unmapped below.
|
* They will need to be unmapped below.
|
||||||
*/
|
*/
|
||||||
bind_inputs(ctx, arrays, min_index, max_index+1, bo, &nr_bo);
|
bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo);
|
||||||
bind_indices(ctx, ib, min_index, bo, &nr_bo);
|
bind_indices(ctx, ib, bo, &nr_bo);
|
||||||
bind_prims(ctx, prim, nr_prims, VB->Elts ? 0 : min_index );
|
bind_prims(ctx, prim, nr_prims );
|
||||||
|
|
||||||
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
|
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
|
||||||
|
|
||||||
|
@@ -55,7 +55,6 @@ struct _mesa_index_buffer {
|
|||||||
GLenum type;
|
GLenum type;
|
||||||
struct gl_buffer_object *obj;
|
struct gl_buffer_object *obj;
|
||||||
const void *ptr;
|
const void *ptr;
|
||||||
GLuint rebase;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -34,45 +34,55 @@
|
|||||||
|
|
||||||
#include "vbo_context.h"
|
#include "vbo_context.h"
|
||||||
|
|
||||||
static GLuint get_max_index( GLuint count, GLuint type,
|
/* Compute min and max elements for drawelements calls.
|
||||||
const GLvoid *indices )
|
*/
|
||||||
|
static void get_minmax_index( GLuint count, GLuint type,
|
||||||
|
const GLvoid *indices,
|
||||||
|
GLuint *min_index,
|
||||||
|
GLuint *max_index)
|
||||||
{
|
{
|
||||||
GLint i;
|
GLint i;
|
||||||
|
|
||||||
/* Compute max element. This is only needed for upload of non-VBO,
|
|
||||||
* non-constant data elements.
|
|
||||||
*
|
|
||||||
* XXX: Postpone this calculation until it is known that it is
|
|
||||||
* needed. Otherwise could scan this pointlessly in the all-vbo
|
|
||||||
* case.
|
|
||||||
*/
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case GL_UNSIGNED_INT: {
|
case GL_UNSIGNED_INT: {
|
||||||
const GLuint *ui_indices = (const GLuint *)indices;
|
const GLuint *ui_indices = (const GLuint *)indices;
|
||||||
GLuint max_ui = 0;
|
GLuint max_ui = ui_indices[0];
|
||||||
for (i = 0; i < count; i++)
|
GLuint min_ui = ui_indices[0];
|
||||||
if (ui_indices[i] > max_ui)
|
for (i = 1; i < count; i++) {
|
||||||
max_ui = ui_indices[i];
|
if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
|
||||||
return max_ui;
|
if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
|
||||||
|
}
|
||||||
|
*min_index = min_ui;
|
||||||
|
*max_index = max_ui;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case GL_UNSIGNED_SHORT: {
|
case GL_UNSIGNED_SHORT: {
|
||||||
const GLushort *us_indices = (const GLushort *)indices;
|
const GLushort *us_indices = (const GLushort *)indices;
|
||||||
GLuint max_us = 0;
|
GLuint max_us = us_indices[0];
|
||||||
for (i = 0; i < count; i++)
|
GLuint min_us = us_indices[0];
|
||||||
if (us_indices[i] > max_us)
|
for (i = 1; i < count; i++) {
|
||||||
max_us = us_indices[i];
|
if (us_indices[i] > max_us) max_us = us_indices[i];
|
||||||
return max_us;
|
if (us_indices[i] < min_us) min_us = us_indices[i];
|
||||||
|
}
|
||||||
|
*min_index = min_us;
|
||||||
|
*max_index = max_us;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case GL_UNSIGNED_BYTE: {
|
case GL_UNSIGNED_BYTE: {
|
||||||
const GLubyte *ub_indices = (const GLubyte *)indices;
|
const GLubyte *ub_indices = (const GLubyte *)indices;
|
||||||
GLuint max_ub = 0;
|
GLuint max_ub = ub_indices[0];
|
||||||
for (i = 0; i < count; i++)
|
GLuint min_ub = ub_indices[0];
|
||||||
if (ub_indices[i] > max_ub)
|
for (i = 1; i < count; i++) {
|
||||||
max_ub = ub_indices[i];
|
if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
|
||||||
return max_ub;
|
if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
|
||||||
|
}
|
||||||
|
*min_index = min_ub;
|
||||||
|
*max_index = max_ub;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0;
|
assert(0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,31 +251,12 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
|
|||||||
prim[0].end = 1;
|
prim[0].end = 1;
|
||||||
prim[0].weak = 0;
|
prim[0].weak = 0;
|
||||||
prim[0].pad = 0;
|
prim[0].pad = 0;
|
||||||
|
prim[0].mode = mode;
|
||||||
|
prim[0].start = start;
|
||||||
|
prim[0].count = count;
|
||||||
|
prim[0].indexed = 0;
|
||||||
|
|
||||||
if (exec->array.inputs[0]->BufferObj->Name) {
|
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 );
|
||||||
/* Use vertex attribute as a hint to tell us if we expect all
|
|
||||||
* arrays to be in VBO's and if so, don't worry about avoiding
|
|
||||||
* the upload of elements < start.
|
|
||||||
*/
|
|
||||||
prim[0].mode = mode;
|
|
||||||
prim[0].start = start;
|
|
||||||
prim[0].count = count;
|
|
||||||
prim[0].indexed = 0;
|
|
||||||
|
|
||||||
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* If not using VBO's, we don't want to upload any more elements
|
|
||||||
* than necessary from the arrays as they will not be valid next
|
|
||||||
* time the application tries to draw with them.
|
|
||||||
*/
|
|
||||||
prim[0].mode = mode;
|
|
||||||
prim[0].start = 0;
|
|
||||||
prim[0].count = count;
|
|
||||||
prim[0].indexed = 0;
|
|
||||||
|
|
||||||
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -296,20 +287,6 @@ vbo_exec_DrawRangeElements(GLenum mode,
|
|||||||
ib.obj = ctx->Array.ElementArrayBufferObj;
|
ib.obj = ctx->Array.ElementArrayBufferObj;
|
||||||
ib.ptr = indices;
|
ib.ptr = indices;
|
||||||
|
|
||||||
if (ctx->Array.ElementArrayBufferObj->Name) {
|
|
||||||
/* Use the fact that indices are in a VBO as a hint that the
|
|
||||||
* program has put all the arrays in VBO's and we don't have to
|
|
||||||
* worry about performance implications of start > 0.
|
|
||||||
*
|
|
||||||
* XXX: consider passing start as min_index to draw_prims instead.
|
|
||||||
* XXX: don't rebase because it didn't work.
|
|
||||||
*/
|
|
||||||
ib.rebase = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ib.rebase = /*start*/ 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
prim[0].begin = 1;
|
prim[0].begin = 1;
|
||||||
prim[0].end = 1;
|
prim[0].end = 1;
|
||||||
prim[0].weak = 0;
|
prim[0].weak = 0;
|
||||||
@@ -319,15 +296,46 @@ vbo_exec_DrawRangeElements(GLenum mode,
|
|||||||
prim[0].count = count;
|
prim[0].count = count;
|
||||||
prim[0].indexed = 1;
|
prim[0].indexed = 1;
|
||||||
|
|
||||||
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, /*ib.rebase*/ start, end+1 );
|
/* Need to give special consideration to rendering a range of
|
||||||
}
|
* indices starting somewhere above zero. Typically the
|
||||||
|
* application is issuing multiple DrawRangeElements() to draw
|
||||||
|
* successive primitives layed out linearly in the vertex arrays.
|
||||||
|
* Unless the vertex arrays are all in a VBO (or locked as with
|
||||||
|
* CVA), the OpenGL semantics imply that we need to re-read or
|
||||||
|
* re-upload the vertex data on each draw call.
|
||||||
|
*
|
||||||
|
* In the case of hardware tnl, we want to avoid starting the
|
||||||
|
* upload at zero, as it will mean every draw call uploads an
|
||||||
|
* increasing amount of not-used vertex data. Worse - in the
|
||||||
|
* software tnl module, all those vertices might be transformed and
|
||||||
|
* lit but never rendered.
|
||||||
|
*
|
||||||
|
* If we just upload or transform the vertices in start..end,
|
||||||
|
* however, the indices will be incorrect.
|
||||||
|
*
|
||||||
|
* At this level, we don't know exactly what the requirements of
|
||||||
|
* the backend are going to be, though it will likely boil down to
|
||||||
|
* either:
|
||||||
|
*
|
||||||
|
* 1) Do nothing, everything is in a VBO and is processed once
|
||||||
|
* only.
|
||||||
|
*
|
||||||
|
* 2) Adjust the indices and vertex arrays so that start becomes
|
||||||
|
* zero.
|
||||||
|
*
|
||||||
|
* Rather than doing anything here, I'll provide a helper function
|
||||||
|
* for the latter case elsewhere.
|
||||||
|
*/
|
||||||
|
|
||||||
|
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
|
||||||
|
}
|
||||||
|
|
||||||
static void GLAPIENTRY
|
static void GLAPIENTRY
|
||||||
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
|
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
GLuint max_index;
|
GLuint min_index = 0;
|
||||||
|
GLuint max_index = 0;
|
||||||
|
|
||||||
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
|
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
|
||||||
return;
|
return;
|
||||||
@@ -338,17 +346,17 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind
|
|||||||
GL_READ_ONLY,
|
GL_READ_ONLY,
|
||||||
ctx->Array.ElementArrayBufferObj);
|
ctx->Array.ElementArrayBufferObj);
|
||||||
|
|
||||||
max_index = get_max_index(count, type, ADD_POINTERS(map, indices));
|
get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index);
|
||||||
|
|
||||||
ctx->Driver.UnmapBuffer(ctx,
|
ctx->Driver.UnmapBuffer(ctx,
|
||||||
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||||
ctx->Array.ElementArrayBufferObj);
|
ctx->Array.ElementArrayBufferObj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
max_index = get_max_index(count, type, indices);
|
get_minmax_index(count, type, indices, &min_index, &max_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices);
|
vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -123,7 +123,8 @@ void vbo_rebase_prims( GLcontext *ctx,
|
|||||||
|
|
||||||
assert(min_index != 0);
|
assert(min_index != 0);
|
||||||
|
|
||||||
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
|
if (0)
|
||||||
|
_mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
|
||||||
|
|
||||||
if (ib) {
|
if (ib) {
|
||||||
/* Unfortunately need to adjust each index individually.
|
/* Unfortunately need to adjust each index individually.
|
||||||
|
@@ -479,7 +479,6 @@ static void replay_init( struct copy_context *copy )
|
|||||||
copy->dstib.type = GL_UNSIGNED_INT;
|
copy->dstib.type = GL_UNSIGNED_INT;
|
||||||
copy->dstib.obj = ctx->Array.NullBufferObj;
|
copy->dstib.obj = ctx->Array.NullBufferObj;
|
||||||
copy->dstib.ptr = copy->dstelt;
|
copy->dstib.ptr = copy->dstelt;
|
||||||
copy->dstib.rebase = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -223,7 +223,6 @@ static void split_prims( struct split_context *split)
|
|||||||
ib.type = GL_UNSIGNED_INT;
|
ib.type = GL_UNSIGNED_INT;
|
||||||
ib.obj = split->ctx->Array.NullBufferObj;
|
ib.obj = split->ctx->Array.NullBufferObj;
|
||||||
ib.ptr = elts;
|
ib.ptr = elts;
|
||||||
ib.rebase = 0; /* ? */
|
|
||||||
|
|
||||||
tmpprim = *prim;
|
tmpprim = *prim;
|
||||||
tmpprim.indexed = 1;
|
tmpprim.indexed = 1;
|
||||||
|
Reference in New Issue
Block a user