static inline GLuint _glMultiDrawElementsIndirect_count(GLenum type, const GLvoid *indirect, GLsizei drawcount, GLsizei stride) { const DrawElementsIndirectCommand *cmd; GLvoid *temp = 0; if (drawcount <= 0) { return 0; } if (stride == 0) { stride = sizeof *cmd; } GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING); if (draw_indirect_buffer) { // Read commands from indirect buffer object GLintptr offset = (GLintptr)indirect; GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride; GLvoid *temp = malloc(size); if (!temp) { return 0; } memset(temp, 0, size); _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp); indirect = temp; } else { if (!indirect) { return 0; } } cmd = (const DrawElementsIndirectCommand *)indirect; GLuint count = 0; for (GLsizei i = 0; i < drawcount; ++i) { cmd = (const DrawElementsIndirectCommand *)((const GLbyte *)indirect + i * stride); GLuint count_i = _glDrawElementsInstancedBaseVertexBaseInstance_count( cmd->count, type, (GLvoid *)(uintptr_t)(cmd->firstIndex * _gl_type_size(type)), cmd->primCount, cmd->baseVertex, cmd->baseInstance ); count = std::max(count, count_i); } if (draw_indirect_buffer) { free(temp); } return count; }
static inline GLuint _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex) { GLvoid *temp = 0; if (!count) { return 0; } GLint element_array_buffer = _element_array_buffer_binding(); if (element_array_buffer) { // Read indices from index buffer object GLintptr offset = (GLintptr)indices; GLsizeiptr size = count*_gl_type_size(type); temp = malloc(size); if (!temp) { return 0; } memset(temp, 0, size); _shadow_glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp); indices = temp; } else { if (!indices) { return 0; } } GLuint maxindex = 0; GLboolean restart_enabled = _glIsEnabled(GL_PRIMITIVE_RESTART); while ((_glGetError() == GL_INVALID_ENUM)) ; GLuint restart_index = 0; if (restart_enabled) { restart_index = (GLuint)_glGetInteger(GL_PRIMITIVE_RESTART_INDEX); } GLsizei i; if (type == GL_UNSIGNED_BYTE) { const GLubyte *p = (const GLubyte *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else if (type == GL_UNSIGNED_SHORT) { const GLushort *p = (const GLushort *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else if (type == GL_UNSIGNED_INT) { const GLuint *p = (const GLuint *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else { os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); } if (element_array_buffer) { free(temp); } maxindex += basevertex; return maxindex + 1; }
static inline GLint _element_array_buffer_binding(void) { return _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING); }
GLuint _glDraw_count(gltrace::Context *ctx, const DrawElementsParams ¶ms) { if (params.end < params.start || params.count <= 0) { return 0; } if (params.end != ~0U) { return params.end + params.basevertex + 1; } GLuint count = params.count; GLenum type = params.type; const void *indices = params.indices; GLvoid *temp = 0; if (!count) { return 0; } GLint element_array_buffer = _element_array_buffer_binding(); if (element_array_buffer) { // Read indices from index buffer object if (ctx->profile.es()) { // We could try to implement this on top of GL_OES_mapbuffer but should seldom be needed os::log("apitrace: warning: %s: element array buffer with memory vertex arrays no longer supported on ES\n", __FUNCTION__); return 0; } GLintptr offset = (GLintptr)indices; GLsizeiptr size = count*_gl_type_size(type); temp = malloc(size); if (!temp) { return 0; } memset(temp, 0, size); _glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp); indices = temp; } else { if (!indices) { return 0; } } GLuint maxindex = 0; GLboolean restart_enabled = GL_FALSE; GLuint restart_index = 0; if (ctx->features.primitive_restart) { _glIsEnabled(GL_PRIMITIVE_RESTART); if (restart_enabled) { restart_index = (GLuint)_glGetInteger(GL_PRIMITIVE_RESTART_INDEX); } } GLsizei i; if (type == GL_UNSIGNED_BYTE) { const GLubyte *p = (const GLubyte *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else if (type == GL_UNSIGNED_SHORT) { const GLushort *p = (const GLushort *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else if (type == GL_UNSIGNED_INT) { const GLuint *p = (const GLuint *)indices; for (i = 0; i < count; ++i) { GLuint index = p[i]; if (restart_enabled && index == restart_index) { continue; } if (index > maxindex) { maxindex = index; } } } else { os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); } if (element_array_buffer) { free(temp); } maxindex += params.basevertex; return maxindex + 1; }