static void r300DrawPrims(GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { GLboolean retval; /* This check should get folded into just the places that * min/max index are really needed. */ if (!index_bounds_valid) { vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); } if (min_index) { radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT, "%s: Rebasing primitives. %p nr_prims %d min_index %u max_index %u\n", __func__, prim, nr_prims, min_index, max_index); vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, r300DrawPrims ); return; } /* Make an attempt at drawing */ retval = r300TryDrawPrims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); /* If failed run tnl pipeline - it should take care of fallbacks */ if (!retval) _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); }
void brw_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLuint min_index, GLuint max_index ) { struct intel_context *intel = intel_context(ctx); 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); /* This looks like out-of-memory but potentially we have * situation where there is enough memory but it has become * fragmented. Clear out all heaps and start from scratch by * faking a contended lock event: (done elsewhere) */ if (!retval && !intel->Fallback && bmError(intel)) { DBG("retrying\n"); /* Then try a second time only to upload textures and draw the * primitives: */ retval = brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } /* Otherwise, we really are out of memory. Pass the drawing * command to the software tnl module and which will in turn call * swrast to do the drawing. */ if (!retval) { _swsetup_Wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } if (intel->aub_file && (INTEL_DEBUG & DEBUG_SYNC)) { intelFinish( &intel->ctx ); intel->aub_wrap = 1; } }
void brw_draw_prims( struct gl_context *ctx, const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, GLuint max_index, struct gl_transform_feedback_object *tfb_vertcount ) { const struct gl_client_array **arrays = ctx->Array._DrawArrays; bool retval; if (!_mesa_check_conditional_render(ctx)) return; /* Handle primitive restart if needed */ if (brw_handle_primitive_restart(ctx, prim, nr_prims, ib)) { /* The draw was handled, so we can exit now */ return; } if (!vbo_all_varyings_in_vbos(arrays)) { if (!index_bounds_valid) vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims); /* Decide if we want to rebase. If so we end up recursing once * only into this function. */ if (min_index != 0 && !vbo_any_varyings_in_vbos(arrays)) { 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); /* Otherwise, we really are out of memory. Pass the drawing * command to the software tnl module and which will in turn call * swrast to do the drawing. */ if (!retval) { _swsetup_Wakeup(ctx); _tnl_wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } }
void brw_draw_prims( struct gl_context *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, GLuint max_index ) { GLboolean retval; if (!_mesa_check_conditional_render(ctx)) return; if (!vbo_all_varyings_in_vbos(arrays)) { if (!index_bounds_valid) vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); /* Decide if we want to rebase. If so we end up recursing once * only into this function. */ if (min_index != 0 && !vbo_any_varyings_in_vbos(arrays)) { 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); /* Otherwise, we really are out of memory. Pass the drawing * command to the software tnl module and which will in turn call * swrast to do the drawing. */ if (!retval) { _swsetup_Wakeup(ctx); _tnl_wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } }
static void evergreenDrawPrims(GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLboolean index_bounds_valid, GLuint min_index, GLuint max_index) { GLboolean retval = GL_FALSE; context_t *context = EVERGREEN_CONTEXT(ctx); radeonContextPtr radeon = &context->radeon; radeon_prepare_render(radeon); /* This check should get folded into just the places that * min/max index are really needed. */ if (!vbo_all_varyings_in_vbos(arrays)) { if (!index_bounds_valid) vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); /* do we want to rebase, minimizes the * amount of data to upload? */ if (min_index) { vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, evergreenDrawPrims ); return; } } /* Make an attempt at drawing */ retval = evergreenTryDrawPrims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); /* If failed run tnl pipeline - it should take care of fallbacks */ if (!retval) { _swsetup_Wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } }
void brw_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLuint min_index, GLuint max_index ) { 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); /* Otherwise, we really are out of memory. Pass the drawing * command to the software tnl module and which will in turn call * swrast to do the drawing. */ if (!retval) { _swsetup_Wakeup(ctx); _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); } }
/* This is the main entrypoint into the slimmed-down software tnl * module. In a regular swtnl driver, this can be plugged straight * into the vbo->Driver.DrawPrims() callback. */ void _tnl_draw_prims( struct gl_context *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLuint min_index, GLuint max_index) { TNLcontext *tnl = TNL_CONTEXT(ctx); const GLuint TEST_SPLIT = 0; const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; GLint max_basevertex = prim->basevertex; GLuint i; /* Mesa core state should have been validated already */ assert(ctx->NewState == 0x0); if (!_mesa_check_conditional_render(ctx)) return; /* don't draw */ for (i = 1; i < nr_prims; i++) max_basevertex = MAX2(max_basevertex, prim[i].basevertex); if (0) { printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); for (i = 0; i < nr_prims; i++) printf("prim %d: %s start %d count %d\n", i, _mesa_lookup_enum_by_nr(prim[i].mode), prim[i].start, prim[i].count); } 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_vbo_draw_prims ); return; } else if ((GLint)max_index + max_basevertex > 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; /* 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 + prim->basevertex, _tnl_vbo_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; GLuint inst; for (i = 0; i < nr_prims;) { GLuint this_nr_prims; /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices * will rebase the elements to the basevertex, and we'll only * emit strings of prims with the same basevertex in one draw call. */ for (this_nr_prims = 1; i + this_nr_prims < nr_prims; this_nr_prims++) { if (prim[i].basevertex != prim[i + this_nr_prims].basevertex) break; } assert(prim[i].num_instances > 0); /* Binding inputs may imply mapping some vertex buffer objects. * They will need to be unmapped below. */ for (inst = 0; inst < prim[i].num_instances; inst++) { bind_prims(ctx, &prim[i], this_nr_prims); bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1, bo, &nr_bo); bind_indices(ctx, ib, bo, &nr_bo); tnl->CurInstance = inst; TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); unmap_vbos(ctx, bo, nr_bo); free_space(ctx); } i += this_nr_prims; } } }
/* This is the main entrypoint into the slimmed-down software tnl * module. In a regular swtnl driver, this can be plugged straight * into the vbo->Driver.DrawPrims() callback. */ void _tnl_draw_prims( GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLuint min_index, GLuint max_index) { TNLcontext *tnl = TNL_CONTEXT(ctx); const GLuint TEST_SPLIT = 0; const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; 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); } 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; /* 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; /* 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 ); TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); unmap_vbos(ctx, bo, nr_bo); free_space(ctx); } }