//DEF_LONG_TYPE(VOGL_CURSOR);
#undef DEF_LONG_TYPE
+ // Special case the XVisualInfo struct because its size differs between 32-bit and 64-bit - argh this sucks and we need a MUCH cleaner way of handling this.
+ // In practice this only fixes an assertion, because the packets always describe the exact length of objects.
+ m_vogl_ctype_descs[VOGL_XVISUALINFO].m_size = (trace_ptr_size == 8) ? 64 : 40;
+
#if 1
// sanity check
for (uint ctype_iter = 0; ctype_iter < VOGL_NUM_CTYPES; ctype_iter++)
}
case GL_RENDERBUFFER:
{
- GLuint handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, attachment_obj.get_handle()));
- if (!handle)
- goto handle_error;
+ GLuint trace_handle = attachment_obj.get_handle();
+ if (trace_handle)
+ {
+ GLuint handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_RENDER_BUFFERS, trace_handle));
+ if (!handle)
+ goto handle_error;
- GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment_target, GL_RENDERBUFFER, handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment_target, GL_RENDERBUFFER, handle);
+ VOGL_CHECK_GL_ERROR;
+ }
break;
}
case GL_TEXTURE:
{
- GLuint handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, attachment_obj.get_handle()));
- if (!handle)
- goto handle_error;
-
- //const GLenum tex_target = vogl_determine_texture_target(context_info, handle);
- GLenum tex_target = GL_NONE;
- if (!remapper.determine_to_object_target(VOGL_NAMESPACE_TEXTURES, handle, tex_target))
+ GLuint trace_handle = attachment_obj.get_handle();
+ if (trace_handle)
{
- vogl_error_printf("%s: Failed determining FBO texture attachment's target, trace FBO handle %u GL handle %u, trace texture handle %u GL handle %u\n", VOGL_METHOD_NAME, m_snapshot_handle, static_cast<uint32>(handle), attachment_obj.get_handle(), handle);
- goto handle_error;
- }
-
- const int cube_map_face = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0);
- const int layer = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0);
- const int level = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
- const int layered = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_LAYERED, GL_FALSE);
+ GLuint handle = static_cast<GLuint>(remapper.remap_handle(VOGL_NAMESPACE_TEXTURES, trace_handle));
+ if (!handle)
+ goto handle_error;
- if (layered)
- {
- // GL_FRAMEBUFFER_ATTACHMENT_LAYERED can only be true if glFramebufferTexture was used to attach.
- GL_ENTRYPOINT(glFramebufferTexture)(GL_DRAW_FRAMEBUFFER, attachment_target, handle, level);
- }
- else
- {
- switch (tex_target)
+ //const GLenum tex_target = vogl_determine_texture_target(context_info, handle);
+ GLenum tex_target = GL_NONE;
+ if (!remapper.determine_to_object_target(VOGL_NAMESPACE_TEXTURES, handle, tex_target))
{
- case GL_TEXTURE_1D:
- {
- GL_ENTRYPOINT(glFramebufferTexture1D)(GL_DRAW_FRAMEBUFFER, attachment_target, tex_target, handle, level);
- break;
- }
- case GL_TEXTURE_2D:
- case GL_TEXTURE_2D_MULTISAMPLE:
- case GL_TEXTURE_RECTANGLE:
- {
- GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, tex_target, handle, level);
- break;
- }
- case GL_TEXTURE_CUBE_MAP:
- {
- VOGL_ASSERT((cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_X) || (cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || (cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_Z) ||
- (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z));
+ vogl_error_printf("%s: Failed determining FBO texture attachment's target, trace FBO handle %u GL handle %u, trace texture handle %u GL handle %u\n", VOGL_METHOD_NAME, m_snapshot_handle, static_cast<uint32>(handle), attachment_obj.get_handle(), handle);
+ goto handle_error;
+ }
- GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, cube_map_face, handle, level);
- break;
- }
- case GL_TEXTURE_3D:
- case GL_TEXTURE_1D_ARRAY:
- case GL_TEXTURE_2D_ARRAY:
- case GL_TEXTURE_CUBE_MAP_ARRAY:
- case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
- {
- GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, attachment_target, handle, level, layer);
- break;
- }
- default:
+ const int cube_map_face = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0);
+ const int layer = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0);
+ const int level = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0);
+ const int layered = attachment_obj.get_param(GL_FRAMEBUFFER_ATTACHMENT_LAYERED, GL_FALSE);
+
+ if (layered)
+ {
+ // GL_FRAMEBUFFER_ATTACHMENT_LAYERED can only be true if glFramebufferTexture was used to attach.
+ GL_ENTRYPOINT(glFramebufferTexture)(GL_DRAW_FRAMEBUFFER, attachment_target, handle, level);
+ }
+ else
+ {
+ switch (tex_target)
{
- vogl_error_printf("%s: Don't know how to attach texture with target %s to FBO, trace FBO handle %u GL handle %u, trace texture handle %u GL handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(tex_target), m_snapshot_handle, static_cast<uint32>(handle), attachment_obj.get_handle(), handle);
- goto handle_error;
+ case GL_TEXTURE_1D:
+ {
+ GL_ENTRYPOINT(glFramebufferTexture1D)(GL_DRAW_FRAMEBUFFER, attachment_target, tex_target, handle, level);
+ break;
+ }
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_RECTANGLE:
+ {
+ GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, tex_target, handle, level);
+ break;
+ }
+ case GL_TEXTURE_CUBE_MAP:
+ {
+ VOGL_ASSERT((cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_X) || (cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || (cube_map_face == GL_TEXTURE_CUBE_MAP_POSITIVE_Z) ||
+ (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || (cube_map_face == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z));
+
+ GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment_target, cube_map_face, handle, level);
+ break;
+ }
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ {
+ GL_ENTRYPOINT(glFramebufferTextureLayer)(GL_DRAW_FRAMEBUFFER, attachment_target, handle, level, layer);
+ break;
+ }
+ default:
+ {
+ vogl_error_printf("%s: Don't know how to attach texture with target %s to FBO, trace FBO handle %u GL handle %u, trace texture handle %u GL handle %u\n", VOGL_METHOD_NAME, g_gl_enums.find_gl_name(tex_target), m_snapshot_handle, static_cast<uint32>(handle), attachment_obj.get_handle(), handle);
+ goto handle_error;
+ }
}
}
+
+ VOGL_CHECK_GL_ERROR;
}
- VOGL_CHECK_GL_ERROR;
break;
}
default:
clear();
- GL_ENTRYPOINT(glGetPolygonStipple)(reinterpret_cast<GLubyte *>(m_pattern));
+ vogl_scoped_state_saver pixelstore_state_saver(cGSTPixelStore);
+ vogl_reset_pixel_store_states();
+ GL_ENTRYPOINT(glGetPolygonStipple)(m_pattern);
VOGL_CHECK_GL_ERROR;
m_valid = true;
VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glPolygonStipple)(reinterpret_cast<const GLubyte *>(m_pattern));
+ vogl_scoped_state_saver pixelstore_state_saver(cGSTPixelStore);
+ vogl_reset_pixel_store_states();
+ GL_ENTRYPOINT(glPolygonStipple)(m_pattern);
VOGL_CHECK_GL_ERROR;
return true;
return false;
json_node &arr_node = node.add_array("pattern");
- for (uint i = 0; i < 32; i++)
+ for (uint i = 0; i < VOGL_ARRAY_SIZE(m_pattern); i++)
arr_node.add_value(m_pattern[i]);
return true;
if (!pArr_node)
return false;
- if ((pArr_node->size() != 32) || (!pArr_node->are_all_children_values()))
+ if (!pArr_node->are_all_children_values())
return false;
- for (uint i = 0; i < 32; i++)
- m_pattern[i] = pArr_node->value_as_uint32(i);
+ // An earlier version wrote the wrong size, so ignore that data.
+ if (pArr_node->size() == VOGL_ARRAY_SIZE(m_pattern))
+ {
+ for (uint i = 0; i < VOGL_ARRAY_SIZE(m_pattern); i++)
+ m_pattern[i] = static_cast<uint8>(pArr_node->value_as_uint32(i));
+ }
+ else
+ {
+ vogl_warning_printf("%s: Polygon stipple data is not valid in this older trace file so it's being ignored - please recapture (sorry)\n", VOGL_METHOD_NAME);
+ }
m_valid = true;
return 32;
}
-uint32 vogl_polygon_stipple_state::get_pattern_row(uint rowIndex) const
+uint32 vogl_polygon_stipple_state::get_pattern_row(uint row_index) const
{
- VOGL_ASSERT(rowIndex < 32);
- return m_pattern[rowIndex];
+ VOGL_ASSERT(row_index < 32);
+
+ return m_pattern[4 * row_index] | (m_pattern[4 * row_index + 1] << 8U) | (m_pattern[4 * row_index + 2] << 16U) | (m_pattern[4 * row_index + 3] << 24U);
}
bool deserialize(const json_node &node, const vogl_blob_manager &blob_manager);
uint get_num_pattern_rows() const;
- uint32 get_pattern_row(uint rowIndex) const;
+ uint32 get_pattern_row(uint row_index) const;
private:
bool m_valid;
- uint32 m_pattern[32];
+ uint8 m_pattern[32 * 4];
};
#endif // VOGL_BASIC_CONTEXT_STATE_H
{
VOGL_FUNC_TRACER
- GLint replay_location = trace_location;
+ // Seems better to return -1 when we can't find the uniform (which can happen if the driver optimizes the program differently vs. tracing).
+ // Otherwise, we can pass an invalid handle down to the driver and this will crash AMD's fglrx.
+ //GLint replay_location = trace_location;
+ GLint replay_location = -1;
glsl_program_hash_map::iterator it = get_shared_state()->m_glsl_program_hash_map.find(trace_program);
if (it == get_shared_state()->m_glsl_program_hash_map.end())
GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
0, 0x1F, 0,
GL_RG, GL_HALF_FLOAT, 4, 0, 0),
+ vogl_internal_tex_format(0x8886, "GL_FLOAT_RG16_NV", 0x8886,
+ 16, 16, 0, 0, 0, 0, 0, 0,
+ GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
+ 0, 0x1F, 0,
+ GL_RG, GL_HALF_FLOAT, 4, 0, 0),
vogl_internal_tex_format(0x8230, "GL_RG32F", 0x8230,
32, 32, 0, 0, 0, 0, 0, 0,
GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
if (!m_desc.snapshot(context_info))
return false;
- vogl_scoped_state_saver framebuffer_state_saver(cGSTReadBuffer, cGSTDrawBuffer);
- vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE);
-
- const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
-
- bool capture_status = false;
-
- GLenum internal_fmt = m_desc.m_internal_format;
- const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
- if ((pInternal_tex_fmt) && (pInternal_tex_fmt->m_optimum_get_image_fmt != GL_NONE) && (pInternal_tex_fmt->m_optimum_get_image_type != GL_NONE))
+ if ((!m_desc.m_width) || (!m_desc.m_height) || (!m_desc.m_internal_format))
{
- // Create texture
- GLuint tex_handle = 0;
- GL_ENTRYPOINT(glGenTextures)(1, &tex_handle);
- VOGL_CHECK_GL_ERROR;
+ // Renderbuffer was only genned - no need to spit out warning
+ //vogl_warning_printf("%s: Unable to retrieve description renderbuffer %" PRIu64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(handle));
+ }
+ else
+ {
+ vogl_scoped_state_saver framebuffer_state_saver(cGSTReadBuffer, cGSTDrawBuffer);
+ vogl_scoped_binding_state orig_framebuffers(GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, GL_TEXTURE_2D, GL_TEXTURE_2D_MULTISAMPLE);
- GL_ENTRYPOINT(glBindTexture)(tex_target, tex_handle);
- VOGL_CHECK_GL_ERROR;
+ const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
- if (m_desc.m_samples > 1)
- {
- GL_ENTRYPOINT(glTexImage2DMultisample)(tex_target,
- m_desc.m_samples,
- internal_fmt,
- m_desc.m_width,
- m_desc.m_height,
- GL_TRUE);
- }
- else
- {
- GL_ENTRYPOINT(glTexImage2D)(tex_target,
- 0,
- internal_fmt,
- m_desc.m_width,
- m_desc.m_height,
- 0,
- pInternal_tex_fmt->m_optimum_get_image_fmt,
- pInternal_tex_fmt->m_optimum_get_image_type,
- NULL);
- }
+ bool capture_status = false;
- if (!vogl_check_gl_error_internal())
+ GLenum internal_fmt = m_desc.m_internal_format;
+ const vogl_internal_tex_format *pInternal_tex_fmt = vogl_find_internal_texture_format(internal_fmt);
+ if ((pInternal_tex_fmt) && (pInternal_tex_fmt->m_optimum_get_image_fmt != GL_NONE) && (pInternal_tex_fmt->m_optimum_get_image_type != GL_NONE))
{
- GL_ENTRYPOINT(glTexParameteri)(tex_target, GL_TEXTURE_MAX_LEVEL, 0);
+ // Create texture
+ GLuint tex_handle = 0;
+ GL_ENTRYPOINT(glGenTextures)(1, &tex_handle);
VOGL_CHECK_GL_ERROR;
- GLenum attachment = GL_COLOR_ATTACHMENT0;
- GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
- GLenum blit_type = GL_COLOR_BUFFER_BIT;
+ GL_ENTRYPOINT(glBindTexture)(tex_target, tex_handle);
+ VOGL_CHECK_GL_ERROR;
- if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
+ if (m_desc.m_samples > 1)
{
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
+ GL_ENTRYPOINT(glTexImage2DMultisample)(tex_target,
+ m_desc.m_samples,
+ internal_fmt,
+ m_desc.m_width,
+ m_desc.m_height,
+ GL_TRUE);
}
- else if (m_desc.m_depth_size)
+ else
{
- attachment = GL_DEPTH_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_DEPTH_BUFFER_BIT;
+ GL_ENTRYPOINT(glTexImage2D)(tex_target,
+ 0,
+ internal_fmt,
+ m_desc.m_width,
+ m_desc.m_height,
+ 0,
+ pInternal_tex_fmt->m_optimum_get_image_fmt,
+ pInternal_tex_fmt->m_optimum_get_image_type,
+ NULL);
}
- else if (m_desc.m_stencil_size)
+
+ if (!vogl_check_gl_error_internal())
{
- attachment = GL_STENCIL_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_STENCIL_BUFFER_BIT;
- }
+ GL_ENTRYPOINT(glTexParameteri)(tex_target, GL_TEXTURE_MAX_LEVEL, 0);
+ VOGL_CHECK_GL_ERROR;
- GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
+ GLenum attachment = GL_COLOR_ATTACHMENT0;
+ GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
+ GLenum blit_type = GL_COLOR_BUFFER_BIT;
- // Source FBO
- GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
+ {
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
+ }
+ else if (m_desc.m_depth_size)
+ {
+ attachment = GL_DEPTH_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_DEPTH_BUFFER_BIT;
+ }
+ else if (m_desc.m_stencil_size)
+ {
+ attachment = GL_STENCIL_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_STENCIL_BUFFER_BIT;
+ }
- GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
- GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, m_snapshot_handle);
- VOGL_CHECK_GL_ERROR;
+ // Source FBO
+ GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- // Dest FBO
- GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_READ_FRAMEBUFFER, attachment, GL_RENDERBUFFER, m_snapshot_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
- VOGL_CHECK_GL_ERROR;
+ // Dest FBO
+ GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glFramebufferTexture2D)(GL_DRAW_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
+ VOGL_CHECK_GL_ERROR;
- GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
+ VOGL_CHECK_GL_ERROR;
- if ((read_status == GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
- {
- GL_ENTRYPOINT(glBlitFramebuffer)(
- 0, 0, m_desc.m_width, m_desc.m_height,
- 0, 0, m_desc.m_width, m_desc.m_height,
- blit_type,
- GL_NEAREST);
+ GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
+ VOGL_CHECK_GL_ERROR;
- if (!vogl_check_gl_error_internal())
+ GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
+ VOGL_CHECK_GL_ERROR;
+
+ if ((read_status == GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
{
- vogl_handle_remapper def_handle_remapper;
- if (m_texture.snapshot(context_info, def_handle_remapper, tex_handle, tex_target))
- capture_status = true;
+ GL_ENTRYPOINT(glBlitFramebuffer)(
+ 0, 0, m_desc.m_width, m_desc.m_height,
+ 0, 0, m_desc.m_width, m_desc.m_height,
+ blit_type,
+ GL_NEAREST);
+
+ if (!vogl_check_gl_error_internal())
+ {
+ vogl_handle_remapper def_handle_remapper;
+ if (m_texture.snapshot(context_info, def_handle_remapper, tex_handle, tex_target))
+ capture_status = true;
+ }
}
- }
- // Delete FBO
- GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
- VOGL_CHECK_GL_ERROR;
+ // Delete FBO
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
+
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
+ GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
+ }
+
+ GL_ENTRYPOINT(glBindTexture)(tex_target, 0);
VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
+ GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
VOGL_CHECK_GL_ERROR;
}
- GL_ENTRYPOINT(glBindTexture)(tex_target, 0);
- VOGL_CHECK_GL_ERROR;
-
- GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
- VOGL_CHECK_GL_ERROR;
- }
-
- if (!capture_status)
- {
- vogl_error_printf("%s: Failed blitting renderbuffer data to texture for renderbuffer %" PRIu64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(handle));
+ if (!capture_status)
+ {
+ vogl_error_printf("%s: Failed blitting renderbuffer data to texture for renderbuffer %" PRIu64 "\n", VOGL_METHOD_NAME, static_cast<uint64_t>(handle));
+ }
}
m_is_valid = true;
if (vogl_check_gl_error())
goto handle_error;
- if (!m_desc.restore(context_info))
- goto handle_error;
-
- if (m_texture.is_valid())
+ if ((m_desc.m_width) && (m_desc.m_height) && (m_desc.m_internal_format))
{
- GLenum attachment = GL_COLOR_ATTACHMENT0;
- GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
- GLenum blit_type = GL_COLOR_BUFFER_BIT;
+ if (!m_desc.restore(context_info))
+ goto handle_error;
- if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
- {
- attachment = GL_DEPTH_STENCIL_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
- }
- else if (m_desc.m_depth_size)
- {
- attachment = GL_DEPTH_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_DEPTH_BUFFER_BIT;
- }
- else if (m_desc.m_stencil_size)
+ if (m_texture.is_valid())
{
- attachment = GL_STENCIL_ATTACHMENT;
- draw_and_read_buf = GL_NONE;
- blit_type = GL_STENCIL_BUFFER_BIT;
- }
+ GLenum attachment = GL_COLOR_ATTACHMENT0;
+ GLenum draw_and_read_buf = GL_COLOR_ATTACHMENT0;
+ GLenum blit_type = GL_COLOR_BUFFER_BIT;
- bool restore_status = false;
+ if ((m_desc.m_depth_size) && (m_desc.m_stencil_size))
+ {
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
+ }
+ else if (m_desc.m_depth_size)
+ {
+ attachment = GL_DEPTH_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_DEPTH_BUFFER_BIT;
+ }
+ else if (m_desc.m_stencil_size)
+ {
+ attachment = GL_STENCIL_ATTACHMENT;
+ draw_and_read_buf = GL_NONE;
+ blit_type = GL_STENCIL_BUFFER_BIT;
+ }
- GLuint64 tex_handle64 = 0;
- vogl_handle_remapper def_handle_remapper;
- if (m_texture.restore(context_info, def_handle_remapper, tex_handle64))
- {
- GLuint tex_handle = static_cast<GLuint>(tex_handle64);
+ bool restore_status = false;
- const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
+ GLuint64 tex_handle64 = 0;
+ vogl_handle_remapper def_handle_remapper;
+ if (m_texture.restore(context_info, def_handle_remapper, tex_handle64))
+ {
+ GLuint tex_handle = static_cast<GLuint>(tex_handle64);
- GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
+ const GLenum tex_target = (m_desc.m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
- // Source FBO
- GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GLuint src_fbo_handle = 0, dst_fbo_handle = 0;
- GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ // Source FBO
+ GL_ENTRYPOINT(glGenFramebuffers)(1, &src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glFramebufferTexture2D)(GL_READ_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glFramebufferTexture2D)(GL_READ_FRAMEBUFFER, attachment, tex_target, tex_handle, 0);
+ VOGL_CHECK_GL_ERROR;
- // Dest FBO
- GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glReadBuffer)(draw_and_read_buf);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ // Dest FBO
+ GL_ENTRYPOINT(glGenFramebuffers)(1, &dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, static_cast<GLuint>(handle));
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glFramebufferRenderbuffer)(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, static_cast<GLuint>(handle));
+ VOGL_CHECK_GL_ERROR;
- GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glDrawBuffers)(1, &draw_and_read_buf);
+ VOGL_CHECK_GL_ERROR;
- GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
- VOGL_CHECK_GL_ERROR;
+ GLenum read_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_READ_FRAMEBUFFER);
+ VOGL_CHECK_GL_ERROR;
- if ((read_status = GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
- {
-#if 0
- // HACK HACK HACK
- if (m_texture.get_num_samples() > 1)
- {
- uint base_level = m_texture.get_params().get_value<GLenum>(GL_TEXTURE_BASE_LEVEL);
+ GLenum draw_status = GL_ENTRYPOINT(glCheckFramebufferStatus)(GL_DRAW_FRAMEBUFFER);
+ VOGL_CHECK_GL_ERROR;
- if (base_level < m_texture.get_num_levels())
+ if ((read_status = GL_FRAMEBUFFER_COMPLETE) && (draw_status == GL_FRAMEBUFFER_COMPLETE))
+ {
+ #if 0
+ // HACK HACK HACK
+ if (m_texture.get_num_samples() > 1)
{
- const vogl_state_vector &state_vec = m_texture.get_level_params(0, base_level);
+ uint base_level = m_texture.get_params().get_value<GLenum>(GL_TEXTURE_BASE_LEVEL);
- uint clear_mask = 0;
- if (state_vec.get_value<GLenum>(GL_TEXTURE_DEPTH_SIZE))
- {
- clear_mask |= GL_DEPTH_BUFFER_BIT;
- }
- if (state_vec.get_value<GLenum>(GL_TEXTURE_STENCIL_SIZE))
- {
- clear_mask |= GL_STENCIL_BUFFER_BIT;
- }
- if (state_vec.get_value<GLenum>(GL_TEXTURE_RED_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_GREEN_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_BLUE_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_ALPHA_SIZE) +
- state_vec.get_value<GLenum>(GL_TEXTURE_INTENSITY_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_LUMINANCE_SIZE))
+ if (base_level < m_texture.get_num_levels())
{
- clear_mask |= GL_COLOR_BUFFER_BIT;
+ const vogl_state_vector &state_vec = m_texture.get_level_params(0, base_level);
+
+ uint clear_mask = 0;
+ if (state_vec.get_value<GLenum>(GL_TEXTURE_DEPTH_SIZE))
+ {
+ clear_mask |= GL_DEPTH_BUFFER_BIT;
+ }
+ if (state_vec.get_value<GLenum>(GL_TEXTURE_STENCIL_SIZE))
+ {
+ clear_mask |= GL_STENCIL_BUFFER_BIT;
+ }
+ if (state_vec.get_value<GLenum>(GL_TEXTURE_RED_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_GREEN_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_BLUE_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_ALPHA_SIZE) +
+ state_vec.get_value<GLenum>(GL_TEXTURE_INTENSITY_SIZE) + state_vec.get_value<GLenum>(GL_TEXTURE_LUMINANCE_SIZE))
+ {
+ clear_mask |= GL_COLOR_BUFFER_BIT;
+ }
+
+ GL_ENTRYPOINT(glClearColor)(1.0f, 0.0f, 1.0f, 1.0f);
+ GL_ENTRYPOINT(glClearDepth)(.5f);
+ GL_ENTRYPOINT(glClearStencil)(128);
+ GL_ENTRYPOINT(glClear)(clear_mask);
+
+ VOGL_CHECK_GL_ERROR;
}
-
- GL_ENTRYPOINT(glClearColor)(1.0f, 0.0f, 1.0f, 1.0f);
- GL_ENTRYPOINT(glClearDepth)(.5f);
- GL_ENTRYPOINT(glClearStencil)(128);
- GL_ENTRYPOINT(glClear)(clear_mask);
-
- VOGL_CHECK_GL_ERROR;
}
- }
- else
-#endif
- {
- GL_ENTRYPOINT(glBlitFramebuffer)(
- 0, 0, m_desc.m_width, m_desc.m_height,
- 0, 0, m_desc.m_width, m_desc.m_height,
- blit_type,
- GL_NEAREST);
-
- if (!vogl_check_gl_error_internal())
+ else
+ #endif
{
- restore_status = true;
+ GL_ENTRYPOINT(glBlitFramebuffer)(
+ 0, 0, m_desc.m_width, m_desc.m_height,
+ 0, 0, m_desc.m_width, m_desc.m_height,
+ blit_type,
+ GL_NEAREST);
+
+ if (!vogl_check_gl_error_internal())
+ {
+ restore_status = true;
+ }
}
}
- }
- // Delete FBO
- GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
- VOGL_CHECK_GL_ERROR;
+ // Delete FBO
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_DRAW_FRAMEBUFFER, 0);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glDeleteFramebuffers)(1, &dst_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glBindFramebuffer)(GL_READ_FRAMEBUFFER, 0);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
- VOGL_CHECK_GL_ERROR;
+ GL_ENTRYPOINT(glDeleteFramebuffers)(1, &src_fbo_handle);
+ VOGL_CHECK_GL_ERROR;
- GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
- VOGL_CHECK_GL_ERROR;
- }
+ GL_ENTRYPOINT(glDeleteTextures)(1, &tex_handle);
+ VOGL_CHECK_GL_ERROR;
+ }
- if (!restore_status)
- {
- vogl_error_printf("%s: Failed restoring contents of renderbuffer %u\n", VOGL_METHOD_NAME, static_cast<GLuint>(handle));
+ if (!restore_status)
+ {
+ vogl_error_printf("%s: Failed restoring contents of renderbuffer %u\n", VOGL_METHOD_NAME, static_cast<GLuint>(handle));
+ }
}
}
void vogleditor_QTimelineView::paintEvent(QPaintEvent *event)
{
+ // Don't bother drawing if the rect is too small.
+ // For some reason this is happening at unexpected times.
+ int rectHeight = event->rect().height();
+ int rectWidth = event->rect().width();
+ if (rectHeight < 100 || rectWidth < 100)
+ {
+ return;
+ }
+
QPainter painter;
painter.begin(this);
paint(&painter, event);
if (m_pPixmap != NULL)
{
- if (m_pPixmap->height() != event->rect().height() ||
- m_pPixmap->width() != event->rect().width())
+ int rectHeight = event->rect().height();
+ int rectWidth = event->rect().width();
+ int pmHeight = m_pPixmap->height();
+ int pmWidth = m_pPixmap->width();
+
+ float widthPctDelta = (float)(rectWidth - pmWidth) / (float)pmWidth;
+ float heightPctDelta = (float)(rectHeight - pmHeight) / (float)pmHeight;
+
+ // If the resize is of a 'signficant' amount, then delete the pixmap so that it will be regenerated at the new size.
+ if (fabs(widthPctDelta) > 0.2 ||
+ fabs(heightPctDelta) > 0.2)
{
deletePixmap();
}
pixmapPainter.setBrush(m_triangleBrush);
pixmapPainter.setPen(m_trianglePen);
+ float minimumOffset = 0;
for (int c = 0; c < numChildren; c++)
{
vogleditor_timelineItem* pChild = m_pModel->get_root_item()->child(c);
- drawTimelineItem(&pixmapPainter, pChild, height);
+ drawTimelineItem(&pixmapPainter, pChild, height, minimumOffset);
}
}
- painter->drawPixmap(event->rect(), *m_pPixmap, event->rect());
+ painter->drawPixmap(event->rect(), *m_pPixmap, m_pPixmap->rect());
// translate drawing to vertical center of rect
// everything will have a small gap on the left and right sides
float vogleditor_QTimelineView::scaleDurationHorizontally(float value)
{
float scaled = value * m_horizontalScale;
- if (scaled <= 0)
+ if (scaled <= m_horizontalScale)
{
- scaled = 1;
+ scaled = m_horizontalScale;
}
return scaled;
return offset;
}
-void vogleditor_QTimelineView::drawTimelineItem(QPainter* painter, vogleditor_timelineItem *pItem, int height)
+void vogleditor_QTimelineView::drawTimelineItem(QPainter* painter, vogleditor_timelineItem *pItem, int height, float& minimumOffset)
{
float duration = pItem->getDuration();
if (duration < 0)
}
else
{
- float durationRatio = duration / m_maxItemDuration;
- int intensity = std::min(255, (int)(durationRatio * 255.0f));
- // painter->setBrush(*(pItem->getBrush()));
- QColor color(intensity, 255-intensity, 0);
- painter->setBrush(QBrush(color));
- painter->setPen(color);
- QRectF rect;
- rect.setLeft(scalePositionHorizontally(pItem->getBeginTime()));
- rect.setTop(-height/2);
- rect.setWidth(scaleDurationHorizontally(duration));
- rect.setHeight(height);
- painter->drawRect(rect);
-
- // now draw all children
- int numChildren = pItem->childCount();
- for (int c = 0; c < numChildren; c++)
- {
- drawTimelineItem(painter, pItem->child(c), height-1);
- }
+ // only draw if the item will extend beyond the minimum offset
+ float leftOffset = scalePositionHorizontally(pItem->getBeginTime());
+ float scaledWidth = scaleDurationHorizontally(duration);
+ if (minimumOffset < leftOffset + scaledWidth)
+ {
+ float durationRatio = duration / m_maxItemDuration;
+ int intensity = std::min(255, (int)(durationRatio * 255.0f));
+ // painter->setBrush(*(pItem->getBrush()));
+ QColor color(intensity, 255-intensity, 0);
+ painter->setBrush(QBrush(color));
+ painter->setPen(color);
+
+ // Clamp the item so that it is 1 pixel wide.
+ // This is intentionally being done before updating the minimum offset
+ // so that small items after the current item will not be drawn
+ if (scaledWidth < 1)
+ {
+ scaledWidth = 1;
+ }
+
+ // update minimum offset
+ minimumOffset = leftOffset + scaledWidth;
+
+ // draw the colored box that represents this item
+ QRectF rect;
+ rect.setLeft(leftOffset);
+ rect.setTop(-height/2);
+ rect.setWidth(scaledWidth);
+ rect.setHeight(height);
+ painter->drawRect(rect);
+
+ // now draw all children
+ int numChildren = pItem->childCount();
+ for (int c = 0; c < numChildren; c++)
+ {
+ drawTimelineItem(painter, pItem->child(c), height-1, minimumOffset);
+ }
+ }
}
painter->restore();
QPixmap* m_pPixmap;
void drawBaseTimeline(QPainter* painter, const QRect& rect, int gap);
- void drawTimelineItem(QPainter* painter, vogleditor_timelineItem* pItem, int height);
+ void drawTimelineItem(QPainter* painter, vogleditor_timelineItem* pItem, int height, float &minimumOffset);
float scaleDurationHorizontally(float value);
float scalePositionHorizontally(float value);
vogleditor_timelineItem::~vogleditor_timelineItem()
{
+ for (int i = 0; i < m_childItems.size(); i++)
+ {
+ delete m_childItems[i];
+ m_childItems[i] = NULL;
+ }
+ m_childItems.clear();
}
void vogleditor_timelineItem::appendChild(vogleditor_timelineItem* child)
{
- childItems.append(child);
+ m_childItems.append(child);
- if (childItems.size() == 1)
+ if (m_childItems.size() == 1)
{
// just added the first child, so overwrite the current maxChildDuration
m_maxChildDuration = child->getMaxChildDuration();
vogleditor_timelineItem* vogleditor_timelineItem::child(int row)
{
- return childItems[row];
+ return m_childItems[row];
}
int vogleditor_timelineItem::childCount() const
{
- return childItems.size();
+ return m_childItems.size();
}
vogleditor_timelineItem* vogleditor_timelineItem::parent()
bool m_isSpan;
float m_maxChildDuration;
- QList<vogleditor_timelineItem*> childItems;
+ QList<vogleditor_timelineItem*> m_childItems;
vogleditor_timelineItem* m_parentItem;
vogleditor_frameItem* m_pFrameItem;
// find specific
{ "find_func", 1, false, "Find: Limit the find to only the specified function name POSIX regex pattern" },
{ "find_param", 1, false, "Find: The parameter value to find, hex, decimal integers, or GL enum strings OK" },
- { "find_namespace", 1, false, "Find: Optionally limits -handle to only parameters using the specified handle namespace: invalid, GLhandleARB, GLframebuffer, GLtexture, GLrenderbuffer, GLquery, GLsampler, GLprogramARB, GLprogram, GLarray, GLlist, GLlocation, GLlocationARB, GLfence, GLsync, GLpipeline, GLshader, GLbuffer, GLfeedback, GLarrayAPPLE, GLfragmentShaderATI" },
- { "find_param_name", 1, false, "Find: Optionally limits the find to only params with the specified name (specify \"return\" to limit search to only return values)" },
- { "find_frame_low", 1, false, "Find: Optionally limit the find to frames beginning at the specified frame index" },
- { "find_frame_high", 1, false, "Find: Optionally limit the find to frames up to and including the specified frame index" },
- { "find_call_low", 1, false, "Find: Optionally limit the find to GL calls beginning at the specified call index" },
- { "find_call_high", 1, false, "Find: Optionally limit the find to GL calls up to and including the specified call index" },
+ { "find_namespace", 1, false, "Find: Limits --find_param to only parameters using the specified handle namespace: invalid, GLhandleARB, GLframebuffer, GLtexture, GLrenderbuffer, GLquery, GLsampler, GLprogramARB, GLprogram, GLarray, GLlist, GLlocation, GLlocationARB, GLfence, GLsync, GLpipeline, GLshader, GLbuffer, GLfeedback, GLarrayAPPLE, GLfragmentShaderATI" },
+ { "find_param_name", 1, false, "Find: Limits the find to only params with the specified name (specify \"return\" to limit search to only return values)" },
+ { "find_frame_low", 1, false, "Find: Limit the find to frames beginning at the specified frame index" },
+ { "find_frame_high", 1, false, "Find: Limit the find to frames up to and including the specified frame index" },
+ { "find_call_low", 1, false, "Find: Limit the find to GL calls beginning at the specified call index" },
+ { "find_call_high", 1, false, "Find: Limit the find to GL calls up to and including the specified call index" },
// compare_hash_files specific
{ "sum_compare_threshold", 1, false, "compare_hash_files: Only report mismatches greater than the specified threshold, use with --sum_hashing" },