static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); if (_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) _save_OBE_DrawElements( mode, count, type, indices ); }
void GLAPIENTRY _mesa_noop_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); if (_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) CALL_DrawElements(GET_DISPATCH(), (mode, count, type, indices)); }
static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) { GET_CURRENT_CONTEXT(ctx); struct vbo_save_context *save = &vbo_context(ctx)->save; if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count, type, indices, 0)) return; if (save->out_of_memory) return; _save_OBE_DrawElements(mode, count, type, indices); }
/** * Called by glDrawRangeElementsBaseVertex() in immediate mode. */ static void GLAPIENTRY vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex) { static GLuint warnCount = 0; GLboolean index_bounds_valid = GL_TRUE; GLuint max_element; GET_CURRENT_CONTEXT(ctx); if (MESA_VERBOSE & VERBOSE_DRAW) _mesa_debug(ctx, "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n", _mesa_lookup_enum_by_nr(mode), start, end, count, _mesa_lookup_enum_by_nr(type), indices, basevertex); if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices, basevertex )) return; if (ctx->Const.CheckArrayBounds) { /* _MaxElement was computed, so we can use it. * This path is used for drivers which need strict bounds checking. */ max_element = ctx->Array.ArrayObj->_MaxElement; } else { /* Generally, hardware drivers don't need to know the buffer bounds * if all vertex attributes are in VBOs. * However, if none of vertex attributes are in VBOs, _MaxElement * is always set to some random big number anyway, so bounds checking * is mostly useless. * * This is only useful to catch invalid values in the "end" parameter * like ~0. */ max_element = 2 * 1000 * 1000 * 1000; /* just a big number */ } if ((int) end + basevertex < 0 || start + basevertex >= max_element) { /* The application requested we draw using a range of indices that's * outside the bounds of the current VBO. This is invalid and appears * to give undefined results. The safest thing to do is to simply * ignore the range, in case the application botched their range tracking * but did provide valid indices. Also issue a warning indicating that * the application is broken. */ if (warnCount++ < 10) { _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, " "basevertex %d, count %d, type 0x%x, indices=%p):\n" "\trange is outside VBO bounds (max=%u); ignoring.\n" "\tThis should be fixed in the application.", start, end, basevertex, count, type, indices, max_element - 1); } index_bounds_valid = GL_FALSE; } /* NOTE: It's important that 'end' is a reasonable value. * in _tnl_draw_prims(), we use end to determine how many vertices * to transform. If it's too large, we can unnecessarily split prims * or we can read/write out of memory in several different places! */ /* Catch/fix some potential user errors */ if (type == GL_UNSIGNED_BYTE) { start = MIN2(start, 0xff); end = MIN2(end, 0xff); } else if (type == GL_UNSIGNED_SHORT) { start = MIN2(start, 0xffff); end = MIN2(end, 0xffff); } if (0) { printf("glDraw[Range]Elements{,BaseVertex}" "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, " "base %d\n", start, end, type, count, ctx->Array.ArrayObj->ElementArrayBufferObj->Name, basevertex); } if ((int) start + basevertex < 0 || end + basevertex >= max_element) index_bounds_valid = GL_FALSE; #if 0 check_draw_elements_data(ctx, count, type, indices); #else (void) check_draw_elements_data; #endif vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end, count, type, indices, basevertex, 1, 0); }
static void GLAPIENTRY vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; struct _mesa_index_buffer ib; struct _mesa_prim prim[1]; if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) return; FLUSH_CURRENT( ctx, 0 ); if (ctx->NewState) _mesa_update_state( ctx ); if (!vbo_validate_shaders(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements(bad shader)"); return; } bind_arrays( ctx ); ib.count = count; ib.type = type; ib.obj = ctx->Array.ElementArrayBufferObj; ib.ptr = indices; prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; prim[0].pad = 0; prim[0].mode = mode; prim[0].start = 0; prim[0].count = count; prim[0].indexed = 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 ); }