//---------------------------------------------------------------------------------------------------------------------- // init_command_line_params //---------------------------------------------------------------------------------------------------------------------- static bool init_command_line_params(int argc, char *argv[]) { VOGL_FUNC_TRACER command_line_params::parse_config parse_cfg; parse_cfg.m_single_minus_params = true; parse_cfg.m_double_minus_params = true; if (!g_command_line_params().parse(get_command_line_params(argc, argv), VOGL_ARRAY_SIZE(g_command_line_param_descs), g_command_line_param_descs, parse_cfg)) { vogl_error_printf("%s: Failed parsing command line parameters!\n", VOGL_FUNCTION_NAME); return false; } if (!init_logfile()) return false; if (g_command_line_params().get_value_as_bool("help") || g_command_line_params().get_value_as_bool("?")) { tool_print_help(); return false; } return true; }
eConsoleMessageType console::get_message_type_from_str(const char *str) { dynamic_string msgname = str; for (uint32_t type = 0; type < VOGL_ARRAY_SIZE(s_msgnames); type++) { if (msgname.compare(s_msgnames[type], false) == 0) return (eConsoleMessageType)type; } return (eConsoleMessageType)-1; }
//---------------------------------------------------------------------------------------------------------------------- // tool_print_help //---------------------------------------------------------------------------------------------------------------------- static void tool_print_help() { VOGL_FUNC_TRACER vogl_printf("Usage: voglsyms [ -option ... ] input_file optional_output_file [ -option ... ]\n"); vogl_printf("Command line options may begin with single minus \"-\" or double minus \"--\"\n"); vogl_printf("\nCommand line options:\n"); dump_command_line_info(VOGL_ARRAY_SIZE(g_command_line_param_descs), g_command_line_param_descs, "--"); }
//---------------------------------------------------------------------------------------------------------------------- // Globals //---------------------------------------------------------------------------------------------------------------------- static const vogl_internal_tex_format *get_vogl_internal_texture_formats(uint32_t *count) { static const vogl_internal_tex_format s_vogl_internal_texture_formats[] = { // TODO: Test ALL of these format mappings on AMD and Intel Mesa. // TODO: This table mapping internal texture formats was composed by calling NVidia's driver. // We should also compose tables for other drivers, and a generic table. #include "vogl_internal_texture_formats.inc" }; *count = VOGL_ARRAY_SIZE(s_vogl_internal_texture_formats); return s_vogl_internal_texture_formats; }
bool vogl_framebuffer_attachment::snapshot(const vogl_context_info &context_info, vogl_handle_remapper &remapper, GLenum attachment, GLenum type) { VOGL_FUNC_TRACER VOGL_NOTE_UNUSED(remapper); VOGL_NOTE_UNUSED(context_info); clear(); m_attachment = attachment; m_type = type; #define DO_QUERY(e) \ do \ { \ int val = 0; \ GL_ENTRYPOINT(glGetFramebufferAttachmentParameteriv)(GL_FRAMEBUFFER, attachment, e, &val); \ VOGL_CHECK_GL_ERROR; \ m_params.insert(e, val); \ } while (0) // TODO: Is this query really valid on default framebuffer FBO's? DO_QUERY(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); static const GLenum s_common_queries[] = { GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING }; for (uint32_t i = 0; i < VOGL_ARRAY_SIZE(s_common_queries); i++) { DO_QUERY(s_common_queries[i]); } if (m_type == GL_TEXTURE) { DO_QUERY(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL); DO_QUERY(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE); DO_QUERY(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER); // only need to query LAYERED if GS supported if (context_info.supports_extension("GL_ARB_geometry_shader4")) DO_QUERY(GL_FRAMEBUFFER_ATTACHMENT_LAYERED); } #undef DO_QUERY return true; }
const char *console::get_message_type_str(eConsoleMessageType type) { if (type >= 0 && (type < VOGL_ARRAY_SIZE(s_msgnames))) return s_msgnames[type]; return "??"; }
//---------------------------------------------------------------------------------------------------------------------- // Function vogl_init_gl_entrypoint_descs //---------------------------------------------------------------------------------------------------------------------- void vogl_init_gl_entrypoint_descs() { gl_entrypoint_param_desc_t *pDst = &g_vogl_entrypoint_param_descs[0][0]; #define DEF_FUNCTION_BEGIN(exported, category, ret, ret_type, num_params, name, args, params) #define DEF_FUNCTION_INFO(namespace_index, return_spectype, category, version, profile, deprecated, is_whitelisted, is_nullable, whitelisted_for_displaylists, listable) #define DEF_FUNCTION_BEGIN_PARAMS \ { \ gl_entrypoint_param_desc_t *pCur = pDst; #define DEF_FUNCTION_IN_VALUE_PARAM(namespace_index, spectype, type, ctype, name) \ { \ pCur->m_pSpec_type = #spectype; \ pCur->m_pName = #name; \ pCur->m_ctype = ctype; \ pCur->m_class = VOGL_VALUE_PARAM; \ pCur->m_input = true; \ pCur->m_namespace = (vogl_namespace_t)namespace_index; \ ++pCur; \ } #define DEF_FUNCTION_IN_REFERENCE_PARAM(namespace_index, spectype, type, ctype, name) \ { \ pCur->m_pSpec_type = #spectype; \ pCur->m_pName = #name; \ pCur->m_ctype = ctype; \ pCur->m_class = VOGL_REF_PARAM; \ pCur->m_input = true; \ pCur->m_namespace = (vogl_namespace_t)namespace_index; \ ++pCur; \ } #define DEF_FUNCTION_IN_ARRAY_PARAM(namespace_index, spectype, type, ctype, name, size) \ { \ pCur->m_pSpec_type = #spectype; \ pCur->m_pName = #name; \ pCur->m_ctype = ctype; \ pCur->m_class = VOGL_ARRAY_PARAM; \ pCur->m_input = true; \ pCur->m_pSize = #size; \ pCur->m_namespace = (vogl_namespace_t)namespace_index; \ ++pCur; \ } #define DEF_FUNCTION_OUT_REFERENCE_PARAM(namespace_index, spectype, type, ctype, name) \ { \ pCur->m_pSpec_type = #spectype; \ pCur->m_pName = #name; \ pCur->m_ctype = ctype; \ pCur->m_class = VOGL_ARRAY_PARAM; \ pCur->m_input = false; \ pCur->m_namespace = (vogl_namespace_t)namespace_index; \ ++pCur; \ } #define DEF_FUNCTION_OUT_ARRAY_PARAM(namespace_index, spectype, type, ctype, name, size) \ { \ pCur->m_pSpec_type = #spectype; \ pCur->m_pName = #name; \ pCur->m_ctype = ctype; \ pCur->m_class = VOGL_ARRAY_PARAM; \ pCur->m_input = false; \ pCur->m_pSize = #size; \ pCur->m_namespace = (vogl_namespace_t)namespace_index; \ ++pCur; \ } #define DEF_FUNCTION_END_PARAMS \ VOGL_ASSERT((pCur - pDst) <= VOGL_MAX_ENTRYPOINT_PARAMETERS); \ } #define DEF_FUNCTION_RETURN(spectype, type, ctype) #define DEF_FUNCTION_END(exported, category, ret, ret_type, num_params, name, args, params) pDst += VOGL_MAX_ENTRYPOINT_PARAMETERS; #include "gl_glx_cgl_wgl_func_descs.inc" for (uint32_t i = 0; i < VOGL_ARRAY_SIZE(g_custom_array_size_macro_indices); i++) { uint32_t idx = g_custom_array_size_macro_indices[i]; uint32_t func = idx >> 16; uint32_t param = idx & 0xFFFF; VOGL_ASSERT(func < VOGL_NUM_ENTRYPOINTS); VOGL_ASSERT(param < g_vogl_entrypoint_descs[func].m_num_params); g_vogl_entrypoint_param_descs[func][param].m_has_custom_array_size_macro = true; } for (uint32_t i = 0; i < VOGL_NUM_ENTRYPOINTS; i++) { gl_entrypoint_desc_t &desc = g_vogl_entrypoint_descs[i]; VOGL_ASSERT(desc.m_return_namespace >= VOGL_NAMESPACE_UNKNOWN); VOGL_ASSERT(desc.m_return_namespace < VOGL_TOTAL_NAMESPACES); if (strcmp(desc.m_pName, "glGenTextures") == 0) { if (g_vogl_entrypoint_param_descs[i][1].m_namespace != VOGL_NAMESPACE_TEXTURES) { vogl_error_printf("vogl_namespace_t enum is bad, please rebuild"); exit(EXIT_FAILURE); } } if (desc.m_return_ctype != VOGL_VOID) { if ((size_t)get_vogl_process_gl_ctypes()[desc.m_return_ctype].m_size < 1) vogl_warning_printf("function %s's return ctype %s is too small\n", desc.m_pName, get_vogl_process_gl_ctypes()[desc.m_return_ctype].m_pName); if ((size_t)get_vogl_process_gl_ctypes()[desc.m_return_ctype].m_size > sizeof(uint64_t)) vogl_warning_printf("function %s's return ctype %s is too large\n", desc.m_pName, get_vogl_process_gl_ctypes()[desc.m_return_ctype].m_pName); } for (uint32_t j = 0; j < desc.m_num_params; j++) { if ((size_t)get_vogl_process_gl_ctypes()[g_vogl_entrypoint_param_descs[i][j].m_ctype].m_size < 1) vogl_warning_printf("param %u of function %s ctype %s is too small\n", j, desc.m_pName, get_vogl_process_gl_ctypes()[g_vogl_entrypoint_param_descs[i][j].m_ctype].m_pName); if ((size_t)get_vogl_process_gl_ctypes()[g_vogl_entrypoint_param_descs[i][j].m_ctype].m_size > sizeof(uint64_t)) vogl_warning_printf("param %u of function %s ctype %s is too large\n", j, desc.m_pName, get_vogl_process_gl_ctypes()[g_vogl_entrypoint_param_descs[i][j].m_ctype].m_pName); } desc.m_pAPI_prefix = "GL"; // FIXME: Add more prefixes as we add platforms. voglgen should probably supply this. // They must correspond with the GL enum prefixes in glx_enum_desc.inc, gl_enum_desc.inc, etc. if ((desc.m_pName[0] == 'w') && (desc.m_pName[1] == 'g') && (desc.m_pName[2] == 'l')) desc.m_pAPI_prefix = "WGL"; else if ((desc.m_pName[0] == 'C') && (desc.m_pName[1] == 'G') && (desc.m_pName[2] == 'L')) desc.m_pAPI_prefix = "CGL"; else if ((desc.m_pName[0] == 'g') && (desc.m_pName[1] == 'l') && (desc.m_pName[2] == 'X')) desc.m_pAPI_prefix = "GLX"; else if ((desc.m_pName[0] == 'g') && (desc.m_pName[1] == 'l')) desc.m_pAPI_prefix = "GL"; else { vogl_warning_printf("Unknown function prefix: %s\n", desc.m_pName); } } for (uint32_t i = 0; i < VOGL_NUM_ENTRYPOINTS; i++) { get_vogl_entrypoint_hashmap().insert(g_vogl_entrypoint_descs[i].m_pName, static_cast<gl_entrypoint_id_t>(i)); } }
//---------------------------------------------------------------------------------------------------------------------- // vogl_devel_dump_internal_texture_formats // This func is only for testing various internal GL format related API's // This func is used to generate vogl_internal_texture_formats.inc //---------------------------------------------------------------------------------------------------------------------- void vogl_devel_dump_internal_texture_formats(const vogl_context_info &context_info) { VOGL_FUNC_TRACER VOGL_CHECK_GL_ERROR; vogl_scoped_binding_state orig_texture; orig_texture.save_textures(&context_info); vogl_scoped_state_saver state_saver(cGSTPixelStore, cGSTPixelTransfer); vogl_reset_pixel_store_states(); vogl_reset_pixel_transfer_states(context_info); #if 0 // silly experiment { GLuint handle; ACTUAL_GL_ENTRYPOINT(glGenTextures)(1, &handle); VOGL_CHECK_GL_ERROR; ACTUAL_GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle); VOGL_CHECK_GL_ERROR; for (uint32_t i = 0; i < 256; i++) { uint8_t vals[4] = { i, 0, 0, 0 }; //ACTUAL_GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, GL_R8_SNORM, 1, 1, 0, GL_RED, GL_BYTE, vals); //float vals[1] = { ( i - 128.0f) / 127.0f }; //float vals[1] = { i / 255.0f }; //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_SCALE, .5f); //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_BIAS, 0.5f); ACTUAL_GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, GL_RGB8UI, 1, 1, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, vals); //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_SCALE, 1.0f); //ACTUAL_GL_ENTRYPOINT(glPixelTransferf)(GL_RED_BIAS, 0.0f); VOGL_CHECK_GL_ERROR; uint16_t gvals[4] = { 0, 0, 0, 0 }; ACTUAL_GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, gvals); VOGL_CHECK_GL_ERROR; printf("%u %u %u %u, %u %u %u %u\n", vals[0], vals[1], vals[2], vals[3], gvals[0], gvals[1], gvals[2], gvals[3]); } ACTUAL_GL_ENTRYPOINT(glDeleteTextures)(1, &handle); } #endif typedef vogl::map<GLenum, vogl_internal_tex_format> tex_format_map; tex_format_map internal_formats; // Iterate through the base internal fmts, which need some special handling (argh) because the actual internal fmt != the requested internal fmt GLenum base_internal_formats[] = { GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_ALPHA, GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_INTENSITY, GL_SLUMINANCE, GL_SLUMINANCE_ALPHA, GL_SRGB, GL_SRGB_ALPHA }; for (uint32_t i = 0; i < VOGL_ARRAY_SIZE(base_internal_formats); i++) { printf("%s\n", get_gl_enums().find_gl_name(base_internal_formats[i])); GLuint handle; GL_ENTRYPOINT(glGenTextures)(1, &handle); VOGL_CHECK_GL_ERROR; GLenum target = GL_TEXTURE_2D; GL_ENTRYPOINT(glBindTexture)(target, handle); GLenum base_internal_fmt = base_internal_formats[i]; vogl_internal_tex_format f; GL_ENTRYPOINT(glGetInternalformativ)(target, base_internal_fmt, GL_GET_TEXTURE_IMAGE_TYPE, sizeof(f.m_optimum_get_image_type), (GLint *)&f.m_optimum_get_image_type); GL_ENTRYPOINT(glGetInternalformativ)(target, base_internal_fmt, GL_GET_TEXTURE_IMAGE_FORMAT, sizeof(f.m_optimum_get_image_fmt), (GLint *)&f.m_optimum_get_image_fmt); VOGL_CHECK_GL_ERROR; GLenum &get_fmt = f.m_optimum_get_image_fmt; GLenum &get_type = f.m_optimum_get_image_type; // manual fixups, ARGH switch (base_internal_fmt) { case GL_DEPTH_COMPONENT: { get_fmt = GL_DEPTH_COMPONENT; get_type = GL_FLOAT; break; } case GL_RG: { get_fmt = GL_RG; get_type = GL_UNSIGNED_BYTE; break; } case GL_RGB: { get_fmt = GL_RGB; get_type = GL_UNSIGNED_BYTE; break; } case GL_RED: { get_fmt = GL_RED; get_type = GL_UNSIGNED_BYTE; break; } case GL_COMPRESSED_LUMINANCE: { get_fmt = GL_LUMINANCE; get_type = GL_UNSIGNED_BYTE; break; } case GL_COMPRESSED_LUMINANCE_ALPHA: { get_fmt = GL_LUMINANCE_ALPHA; get_type = GL_UNSIGNED_BYTE; break; } case GL_COMPRESSED_RGB: { get_fmt = GL_RGBA; get_type = GL_UNSIGNED_BYTE; break; } case GL_COMPRESSED_RGBA: { get_fmt = GL_RGBA; get_type = GL_UNSIGNED_BYTE; break; } case GL_LUMINANCE_ALPHA: { get_fmt = GL_LUMINANCE_ALPHA; get_type = GL_UNSIGNED_BYTE; break; } case GL_SLUMINANCE_ALPHA: { get_fmt = GL_LUMINANCE_ALPHA; get_type = GL_UNSIGNED_BYTE; break; } case GL_SRGB: { get_fmt = GL_RGB; get_type = GL_UNSIGNED_BYTE; break; } case GL_SRGB_ALPHA: { get_fmt = GL_RGBA; get_type = GL_UNSIGNED_BYTE; break; } default: { break; } } VOGL_VERIFY(get_fmt != GL_NONE); VOGL_VERIFY(get_type != GL_NONE); GL_ENTRYPOINT(glTexImage2D)(target, 0, base_internal_fmt, 32, 32, 0, get_fmt, get_type, NULL); VOGL_VERIFY(!vogl_check_gl_error()); //bool any_gl_errors = false; #define GET_INT(dst, gl_enum) \ do \ { \ int values[4]; \ utils::zero_object(values); \ GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \ (dst) = values[0]; \ } while (0) #define GET_BOOL(dst, gl_enum) \ do \ { \ int values[4]; \ utils::zero_object(values); \ GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \ (dst) = values[0] != 0; \ } while (0) GLenum actual_internal_fmt; GET_INT(actual_internal_fmt, GL_TEXTURE_INTERNAL_FORMAT); f.m_tex_image_flags = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); f.m_fmt = base_internal_fmt; f.m_actual_internal_fmt = actual_internal_fmt; f.m_name = get_gl_enums().find_name(base_internal_fmt, "gl"); GET_INT(f.m_comp_sizes[cTCRed], GL_TEXTURE_RED_SIZE); GET_INT(f.m_comp_sizes[cTCGreen], GL_TEXTURE_GREEN_SIZE); GET_INT(f.m_comp_sizes[cTCBlue], GL_TEXTURE_BLUE_SIZE); GET_INT(f.m_comp_sizes[cTCAlpha], GL_TEXTURE_ALPHA_SIZE); GET_INT(f.m_comp_sizes[cTCStencil], GL_TEXTURE_STENCIL_SIZE); GET_INT(f.m_comp_sizes[cTCDepth], GL_TEXTURE_DEPTH_SIZE); GET_INT(f.m_comp_sizes[cTCIntensity], GL_TEXTURE_INTENSITY_SIZE); GET_INT(f.m_comp_sizes[cTCLuminance], GL_TEXTURE_LUMINANCE_SIZE); GET_INT(f.m_comp_types[cTCRed], GL_TEXTURE_RED_TYPE); GET_INT(f.m_comp_types[cTCGreen], GL_TEXTURE_GREEN_TYPE); GET_INT(f.m_comp_types[cTCBlue], GL_TEXTURE_BLUE_TYPE); GET_INT(f.m_comp_types[cTCAlpha], GL_TEXTURE_ALPHA_TYPE); GET_INT(f.m_comp_types[cTCDepth], GL_TEXTURE_DEPTH_TYPE); GET_INT(f.m_comp_types[cTCIntensity], GL_TEXTURE_INTENSITY_TYPE); GET_INT(f.m_comp_types[cTCLuminance], GL_TEXTURE_LUMINANCE_TYPE); GET_INT(f.m_shared_size, GL_TEXTURE_SHARED_SIZE); GET_BOOL(f.m_compressed, GL_TEXTURE_COMPRESSED); printf("base_internal_fmt: %s get_fmt: %s get_type: %s, actual_internal_fmt: %s compressed: %u\n", get_gl_enums().find_gl_name(base_internal_fmt), get_gl_enums().find_gl_name(get_fmt), get_gl_enums().find_gl_name(get_type), get_gl_enums().find_gl_name(actual_internal_fmt), f.m_compressed); #undef GET_INT #undef GET_BOOL //VOGL_ASSERT(!any_gl_errors); VOGL_ASSERT(f.m_actual_internal_fmt != GL_NONE); VOGL_ASSERT(f.m_optimum_get_image_fmt != GL_NONE); VOGL_ASSERT(f.m_optimum_get_image_type != GL_NONE); VOGL_ASSERT(!f.m_compressed); VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(f.m_fmt) && !ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt)); VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_fmt) == 0 && ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) == 0); if (!internal_formats.insert(base_internal_fmt, f).second) { internal_formats.find_value(base_internal_fmt)->m_tex_image_flags |= ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); } GL_ENTRYPOINT(glBindTexture)(target, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteTextures)(1, &handle); VOGL_CHECK_GL_ERROR; } for (uint32_t t = 0; t < 5; t++) { GLenum target = GL_NONE; switch (t) { case 0: { target = GL_TEXTURE_1D; break; } case 1: { target = GL_TEXTURE_2D; break; } case 2: { target = GL_TEXTURE_3D; break; } case 3: { target = GL_TEXTURE_2D_MULTISAMPLE; break; } case 4: { target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; break; } default: { VOGL_ASSERT_ALWAYS; break; } } for (uint32_t fmt = 0; fmt <= 0xFFFF; fmt++) { GLuint handle; GL_ENTRYPOINT(glGenTextures)(1, &handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(target, handle); vogl_debug_message_control(context_info, GL_INVALID_ENUM, false); vogl_debug_message_control(context_info, GL_INVALID_OPERATION, false); bool failed = false; switch (t) { case 0: { GL_ENTRYPOINT(glTexStorage1D)(target, 1, fmt, 32); failed = vogl_check_gl_error_suppress_message(); break; } case 1: { GL_ENTRYPOINT(glTexStorage2D)(target, 1, fmt, 32, 32); failed = vogl_check_gl_error_suppress_message(); break; } case 2: { GL_ENTRYPOINT(glTexStorage3D)(target, 1, fmt, 32, 32, 32); failed = vogl_check_gl_error_suppress_message(); break; } case 3: { GL_ENTRYPOINT(glTexStorage2DMultisample)(target, 2, fmt, 32, 32, GL_TRUE); failed = vogl_check_gl_error_suppress_message(); break; } case 4: { GL_ENTRYPOINT(glTexStorage3DMultisample)(target, 2, fmt, 32, 32, 2, GL_TRUE); failed = vogl_check_gl_error_suppress_message(); break; } } vogl_debug_message_control(context_info, GL_INVALID_ENUM, true); vogl_debug_message_control(context_info, GL_INVALID_OPERATION, true); if (failed) continue; bool any_gl_errors = false; VOGL_NOTE_UNUSED(any_gl_errors); vogl_internal_tex_format f; f.m_tex_image_flags = (1 << t); f.m_fmt = fmt; f.m_actual_internal_fmt = fmt; // this assumes the actual internal fmt will match here! f.m_name = get_gl_enums().find_name(fmt, "gl"); #define GET_INT(dst, gl_enum) \ do \ { \ int values[4]; \ utils::zero_object(values); \ GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \ (dst) = values[0]; \ } while (0) #define GET_BOOL(dst, gl_enum) \ do \ { \ int values[4]; \ utils::zero_object(values); \ GL_ENTRYPOINT(glGetTexLevelParameteriv)(target, 0, (gl_enum), values); \ (dst) = values[0] != 0; \ } while (0) GLenum internal_fmt; GET_INT(internal_fmt, GL_TEXTURE_INTERNAL_FORMAT); VOGL_ASSERT(internal_fmt == fmt); GET_INT(f.m_comp_sizes[cTCRed], GL_TEXTURE_RED_SIZE); GET_INT(f.m_comp_sizes[cTCGreen], GL_TEXTURE_GREEN_SIZE); GET_INT(f.m_comp_sizes[cTCBlue], GL_TEXTURE_BLUE_SIZE); GET_INT(f.m_comp_sizes[cTCAlpha], GL_TEXTURE_ALPHA_SIZE); GET_INT(f.m_comp_sizes[cTCStencil], GL_TEXTURE_STENCIL_SIZE); GET_INT(f.m_comp_sizes[cTCDepth], GL_TEXTURE_DEPTH_SIZE); GET_INT(f.m_comp_sizes[cTCIntensity], GL_TEXTURE_INTENSITY_SIZE); GET_INT(f.m_comp_sizes[cTCLuminance], GL_TEXTURE_LUMINANCE_SIZE); GET_INT(f.m_comp_types[cTCRed], GL_TEXTURE_RED_TYPE); GET_INT(f.m_comp_types[cTCGreen], GL_TEXTURE_GREEN_TYPE); GET_INT(f.m_comp_types[cTCBlue], GL_TEXTURE_BLUE_TYPE); GET_INT(f.m_comp_types[cTCAlpha], GL_TEXTURE_ALPHA_TYPE); GET_INT(f.m_comp_types[cTCDepth], GL_TEXTURE_DEPTH_TYPE); GET_INT(f.m_comp_types[cTCIntensity], GL_TEXTURE_INTENSITY_TYPE); GET_INT(f.m_comp_types[cTCLuminance], GL_TEXTURE_LUMINANCE_TYPE); GET_INT(f.m_shared_size, GL_TEXTURE_SHARED_SIZE); GET_BOOL(f.m_compressed, GL_TEXTURE_COMPRESSED); #undef GET_INT #undef GET_BOOL VOGL_ASSERT(!any_gl_errors); GL_ENTRYPOINT(glGetInternalformativ)(target, fmt, GL_GET_TEXTURE_IMAGE_TYPE, sizeof(f.m_optimum_get_image_type), (GLint *)&f.m_optimum_get_image_type); GL_ENTRYPOINT(glGetInternalformativ)(target, fmt, GL_GET_TEXTURE_IMAGE_FORMAT, sizeof(f.m_optimum_get_image_fmt), (GLint *)&f.m_optimum_get_image_fmt); VOGL_CHECK_GL_ERROR; if (f.m_compressed) { f.m_optimum_get_image_fmt = GL_RGBA; f.m_optimum_get_image_type = GL_UNSIGNED_BYTE; } else { #define HANDLE_FMT(gl_enum, fmt, type) \ case gl_enum: \ { \ f.m_optimum_get_image_fmt = fmt; \ f.m_optimum_get_image_type = type; \ break; \ } bool unhandled = false; switch (fmt) { HANDLE_FMT(GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV); HANDLE_FMT(GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV); HANDLE_FMT(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); HANDLE_FMT(GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT); HANDLE_FMT(GL_INTENSITY32F_ARB, GL_RED, GL_FLOAT); HANDLE_FMT(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE); HANDLE_FMT(3, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_RGB8I, GL_RGB_INTEGER, GL_BYTE); HANDLE_FMT(GL_RGB10, GL_RGB, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RGB12, GL_RGB, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RGBA12, GL_RGB, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RG8, GL_RG, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_RG16, GL_RG, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RG16F, GL_RG, GL_HALF_FLOAT); HANDLE_FMT(GL_RG32F, GL_RG, GL_FLOAT); HANDLE_FMT(GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_BYTE); HANDLE_FMT(GL_RGB32I, GL_RGB_INTEGER, GL_INT); HANDLE_FMT(GL_RGB16I, GL_RGB_INTEGER, GL_SHORT); HANDLE_FMT(GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT); HANDLE_FMT(GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT); HANDLE_FMT(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_INT); HANDLE_FMT(GL_SIGNED_RGBA8_NV, GL_RGBA, GL_BYTE); HANDLE_FMT(GL_SIGNED_RGB8_NV, GL_RGB, GL_BYTE); HANDLE_FMT(GL_SIGNED_LUMINANCE8_ALPHA8_NV, GL_LUMINANCE_ALPHA, GL_BYTE); HANDLE_FMT(GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV, GL_RGBA, GL_BYTE); HANDLE_FMT(GL_RG8_SNORM, GL_RG, GL_BYTE); HANDLE_FMT(GL_RGB8_SNORM, GL_RGB, GL_BYTE); HANDLE_FMT(GL_RG16_SNORM, GL_RG, GL_SHORT); HANDLE_FMT(GL_RGB16_SNORM, GL_RGB, GL_SHORT); HANDLE_FMT(GL_RGB32F, GL_RGB, GL_FLOAT); HANDLE_FMT(GL_RGB16F, GL_RGB, GL_HALF_FLOAT); // TODO: Research oddball formats HANDLE_FMT(GL_PALETTE4_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_PALETTE4_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_PALETTE8_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_PALETTE8_R5_G6_B5_OES, GL_RGB, GL_UNSIGNED_BYTE); HANDLE_FMT(GL_HILO16_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_SIGNED_HILO16_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_DSDT8_MAG8_INTENSITY8_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_HILO8_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_SIGNED_HILO8_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_DSDT8_NV, GL_NONE, GL_NONE); HANDLE_FMT(GL_DSDT8_MAG8_NV, GL_NONE, GL_NONE); default: unhandled = true; break; } if ((unhandled) && ((f.m_optimum_get_image_fmt == GL_NONE) || (f.m_optimum_get_image_type == GL_NONE))) { printf("INVALID: %s %s %s\n", f.m_name.get_ptr(), get_gl_enums().find_name(f.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(f.m_optimum_get_image_type, "gl")); } } #undef HANDLE_FMT VOGL_ASSERT(f.m_actual_internal_fmt != GL_NONE); if ((f.m_optimum_get_image_fmt == GL_NONE) || (f.m_optimum_get_image_type == GL_NONE)) vogl_warning_printf("Don't have an optimal get format/type for internal format %s\n", get_gl_enums().find_gl_name(fmt)); VOGL_ASSERT(fmt != GL_LUMINANCE); VOGL_ASSERT(f.m_fmt == f.m_actual_internal_fmt); if (!f.m_compressed) { VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(f.m_fmt) && !ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt)); VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_fmt) == 0 && ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) == 0); } else { VOGL_ASSERT(ktx_is_compressed_ogl_fmt(f.m_actual_internal_fmt)); VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(f.m_actual_internal_fmt) != 0); } if (!internal_formats.insert(fmt, f).second) { internal_formats.find_value(fmt)->m_tex_image_flags |= (1 << t); } GL_ENTRYPOINT(glBindTexture)(target, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteTextures)(1, &handle); VOGL_CHECK_GL_ERROR; } } const char *pOutput_filename = "internal_texture_formats.inc"; FILE *pFile = vogl_fopen(pOutput_filename, "w"); VOGL_VERIFY(pFile); if (!pFile) return; for (tex_format_map::const_iterator it = internal_formats.begin(); it != internal_formats.end(); ++it) { vogl_internal_tex_format fmt(it->second); uint32_t actual_size = 0; if (!fmt.m_compressed) { VOGL_ASSERT(!ktx_is_compressed_ogl_fmt(fmt.m_fmt)); VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(fmt.m_fmt) == 0); } else { VOGL_ASSERT(ktx_is_compressed_ogl_fmt(fmt.m_fmt)); VOGL_ASSERT(ktx_get_ogl_compressed_base_internal_fmt(fmt.m_fmt) != 0); } if ((!fmt.m_compressed) && (fmt.m_optimum_get_image_fmt != GL_NONE) && (fmt.m_optimum_get_image_type != GL_NONE)) { GLuint handle; GL_ENTRYPOINT(glGenTextures)(1, &handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle); VOGL_CHECK_GL_ERROR; uint8_t vals[128]; utils::zero_object(vals); vals[1] = 64; GL_ENTRYPOINT(glTexImage2D)(GL_TEXTURE_2D, 0, fmt.m_fmt, 1, 1, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, vals); if (vogl_check_gl_error()) { printf("glTexImage2D FAILED: %s %s %s\n", fmt.m_name.get_ptr(), get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl")); } uint8_t gvals[128]; memset(gvals, 0xCD, sizeof(gvals)); GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, gvals); uint32_t actual_size0 = 0; for (actual_size0 = 0; actual_size0 < sizeof(gvals); actual_size0++) if (gvals[actual_size0] == 0xCD) break; memset(gvals, 0x12, sizeof(gvals)); GL_ENTRYPOINT(glGetTexImage)(GL_TEXTURE_2D, 0, fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type, gvals); uint32_t actual_size1 = 0; for (actual_size1 = 0; actual_size1 < sizeof(gvals); actual_size1++) if (gvals[actual_size1] == 0x12) break; VOGL_VERIFY(actual_size0 == actual_size1); //printf("glGetTexImage() wrote %u bytes\n", actual_size0); if (vogl_check_gl_error()) // || gvals[1] != vals[1]) { printf("glGetTexImage() failed: %s %s %s\n", fmt.m_name.get_ptr(), get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl")); } GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteTextures)(1, &handle); actual_size = actual_size0; uint32_t s = vogl_get_image_format_size_in_bytes(fmt.m_optimum_get_image_fmt, fmt.m_optimum_get_image_type); VOGL_VERIFY(s); if (s != actual_size0) { VOGL_VERIFY(0); } vogl::ktx_texture ktx_tex; GLenum img_fmt; GLenum img_type; img_fmt = fmt.m_optimum_get_image_fmt; img_type = fmt.m_optimum_get_image_type; uint32_t block_dim, bytes_per_block; bool success = ktx_get_ogl_fmt_desc(img_fmt, img_type, block_dim, bytes_per_block); VOGL_VERIFY(success); VOGL_VERIFY(block_dim == 1); VOGL_VERIFY(bytes_per_block == actual_size); if (!ktx_tex.init_2D(1, 1, 1, fmt.m_fmt, img_fmt, img_type)) { printf("ktx_texture::init_2D() failed: %s %s %s\n", fmt.m_name.get_ptr(), get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl")); } } else if (fmt.m_compressed) { GLuint handle; GL_ENTRYPOINT(glGenTextures)(1, &handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, handle); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glTexStorage2D)(GL_TEXTURE_2D, 1, fmt.m_fmt, 1, 1); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glGetTexLevelParameteriv)(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&actual_size); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glBindTexture)(GL_TEXTURE_2D, 0); VOGL_CHECK_GL_ERROR; GL_ENTRYPOINT(glDeleteTextures)(1, &handle); VOGL_CHECK_GL_ERROR; uint32_t block_width = 0, block_height = 0, block_size = 0; GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_WIDTH, sizeof(int), reinterpret_cast<GLint *>(&block_width)); GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT, sizeof(int), reinterpret_cast<GLint *>(&block_height)); GL_ENTRYPOINT(glGetInternalformativ)(GL_TEXTURE_2D, fmt.m_fmt, GL_TEXTURE_COMPRESSED_BLOCK_SIZE, sizeof(int), reinterpret_cast<GLint *>(&block_size)); VOGL_CHECK_GL_ERROR; if (block_size == actual_size * 8U) block_size /= 8; uint32_t block_dim, bytes_per_block; bool success = ktx_get_ogl_fmt_desc(fmt.m_fmt, GL_UNSIGNED_BYTE, block_dim, bytes_per_block); if ((!success) || (block_dim != block_width) || (block_dim != block_height) || (bytes_per_block != actual_size) || (bytes_per_block != block_size)) { printf("ktx_get_ogl_fmt_desc on compressed format failed: %s %s %s %u %i %i %i\n", fmt.m_name.get_ptr(), get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl"), actual_size, block_width, block_height, block_size); } fmt.m_block_width = block_width; fmt.m_block_height = block_height; vogl::ktx_texture ktx_tex; if (!ktx_tex.init_2D(1, 1, 1, fmt.m_fmt, GL_NONE, GL_NONE)) { printf("ktx_texture::init_2D() compressed failed: %s %s %s\n", fmt.m_name.get_ptr(), get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl")); } } fmt.m_image_bytes_per_pixel_or_block = actual_size; fprintf(pFile, " vogl_internal_tex_format(0x%04X, \"%s\", 0x%04X,\n", fmt.m_fmt, fmt.m_name.get_ptr(), fmt.m_actual_internal_fmt); fprintf(pFile, " "); for (uint32_t i = 0; i < cTCTotalComponents; i++) fprintf(pFile, "%u, ", fmt.m_comp_sizes[i]); fprintf(pFile, "\n"); fprintf(pFile, " "); for (uint32_t i = 0; i < cTCTotalComponents; i++) fprintf(pFile, "%s, ", get_gl_enums().find_name(fmt.m_comp_types[i], "gl")); fprintf(pFile, "\n"); fprintf(pFile, " %u, 0x%02X, %u, \n", fmt.m_shared_size, fmt.m_tex_image_flags, fmt.m_compressed); fprintf(pFile, " %s, %s, %u, %u, %u),\n", get_gl_enums().find_name(fmt.m_optimum_get_image_fmt, "gl"), get_gl_enums().find_name(fmt.m_optimum_get_image_type, "gl"), fmt.m_image_bytes_per_pixel_or_block, fmt.m_block_width, fmt.m_block_height); #if 0 uint32_t tex_formats_count; static const vogl_internal_tex_format *tex_formats = get_vogl_internal_texture_formats(&tex_formats_count); for (uint32_t q = 0; q < tex_formats_count; q++) { if (tex_formats[q].m_fmt == fmt.m_fmt) { if (!tex_formats[q].compare(fmt)) { VOGL_ASSERT_ALWAYS; } break; } } if (q == tex_formats_count) { VOGL_ASSERT_ALWAYS; } #endif } vogl_fclose(pFile); printf("Wrote file %s\n", pOutput_filename); }
bool tool_trace_mode(vogl::vector<command_line_param_desc> *desc) { arguments_t args; if (desc) { desc->append(g_command_line_param_descs_dump, VOGL_ARRAY_SIZE(g_command_line_param_descs_dump)); desc->append(g_tracer_cmdline_opts, VOGL_ARRAY_SIZE(g_tracer_cmdline_opts)); return true; } // Get steam gameid / local application name. args.gameid = g_command_line_params().get_value_as_string_or_empty("", 1); if (!args.gameid.size()) errorf(VOGL_FUNCTION_INFO_CSTR, "ERROR: No application or steamid specified.\n"); // Get logfile and tracefile names. args.vogl_tracefile = g_command_line_params().get_value_as_string("vogl_tracefile"); args.vogl_logfile = g_command_line_params().get_value_as_string("vogl_logfile"); args.dryrun = g_command_line_params().get_value_as_bool("dry-run"); args.xterm = g_command_line_params().get_value_as_bool("xterm"); // Loop through all the arguments looking for "vogl_*". for (vogl::command_line_params::param_map_const_iterator param = g_command_line_params().begin(); param != g_command_line_params().end(); ++param) { const dynamic_string &first = param->first; // If this is a vogl command and it's not logfile / tracefile, add it to the vogl_cmdline. const dynamic_string prefix = param->first.get_clone().left(5); if (prefix == "vogl_" && (first != "vogl_logfile" && first != "vogl_tracefile")) { args.vogl_cmdline += " --" + first; for (uint32_t i = 0; i < param->second.m_values.size(); i++) { args.vogl_cmdline += " " + param->second.m_values[i]; } } } // Check for -- or --args and add everything after to game_args. const dynamic_string& command_line = get_command_line(); int args_index = command_line.find_left("-- "); if (args_index == -1) args_index = command_line.find_left("--args "); if (args_index != -1) { args_index = command_line.find_left(' ', args_index); if (args_index != -1) { args.game_args += command_line.get_clone().right(args_index + 1); } } bool is_steam_file = true; if (atoi(args.gameid.c_str()) == 0) { if (access(args.gameid.c_str(), F_OK)) errorf(VOGL_FUNCTION_INFO_CSTR, "\nCould not find executable '%s'\n", args.gameid.c_str()); char *filename = realpath(args.gameid.c_str(), NULL); if (filename) { // This is a local executable. is_steam_file = false; args.gameid = filename; free(filename); } } int steam_appid = is_steam_file ? atoi(args.gameid.c_str()) : -1; if (!steam_appid) errorf(VOGL_FUNCTION_INFO_CSTR, "ERROR: Could not find game number for %s\n", args.gameid.c_str()); dynamic_string gameid_str; if (is_steam_file) { gameid_str = "appid" + args.gameid; vogl_printf("\nGame AppID: %d", steam_appid); const char *game_name = get_game_name(steam_appid); if (game_name) { dynamic_string game_name_str(cVarArg, "%s", game_name); vogl_printf(" (%s)", game_name_str.c_str()); // Trim some characters that don't go well with filenames. game_name_str.replace(" ", "_"); game_name_str.replace(":", ""); game_name_str.replace("'", ""); game_name_str.replace("!", ""); game_name_str.replace("?", ""); gameid_str += "_" + game_name_str; } vogl_printf("\n"); } else { gameid_str = basename((char *)args.gameid.c_str()); vogl_printf("\nGame: %s\n", args.gameid.c_str()); } // If a tracefile / logfile wasn't specified, set em up. if (!args.vogl_tracefile.size() || !args.vogl_logfile.size()) { char timestr[200]; time_t t = time(NULL); timestr[0] = 0; struct tm *tmp = localtime(&t); if (tmp) { strftime(timestr, sizeof(timestr), "%Y_%m_%d-%H_%M_%S", tmp); } dynamic_string fname(cVarArg, "%s/vogltrace.%s.%s", P_tmpdir, gameid_str.c_str(), timestr); if (!args.vogl_tracefile.size()) args.vogl_tracefile = fname + ".bin"; if (!args.vogl_logfile.size()) args.vogl_logfile = fname + ".log"; } vogl_printf("\n"); vogl_message_printf("Tracefile: %s\n", args.vogl_tracefile.c_str()); vogl_message_printf("Logfile: %s", args.vogl_logfile.c_str()); vogl_printf(" (will have PID appended)\n"); dynamic_string vogltracepath32 = getfullpath("libvogltrace32.so"); dynamic_string vogltracepath64 = getfullpath("libvogltrace64.so"); // set up LD_PRELOAD string dynamic_string LD_PRELOAD = "LD_PRELOAD=\""; LD_PRELOAD += vogltracepath32 + ":" + vogltracepath64; if (is_steam_file || getenv("LD_PRELOAD")) LD_PRELOAD += ":$LD_PRELOAD"; LD_PRELOAD += "\" "; vogl_printf("\n%s\n", LD_PRELOAD.c_str()); // set up VOGL_CMD_LINE string dynamic_string VOGL_CMD_LINE = "VOGL_CMD_LINE=\""; VOGL_CMD_LINE += "--vogl_tracefile " + args.vogl_tracefile; VOGL_CMD_LINE += " --vogl_logfile " + args.vogl_logfile; VOGL_CMD_LINE += args.vogl_cmdline; VOGL_CMD_LINE += "\""; vogl_printf("\n%s\n", VOGL_CMD_LINE.c_str()); dynamic_string xterm_str; if (args.xterm) { xterm_str = "xterm -geom 120x80+20+20"; const char *env_user = getenv("USER"); // If this is mikesart, specify using the Consolas font (which he likes). if (env_user && !strcmp(env_user, "mikesart")) xterm_str += " -fa Consolas -fs 10"; // Add the xterm command part. xterm_str += " -e "; } if (is_steam_file) { // set up xterm string dynamic_string steam_cmd_str; steam_cmd_str = xterm_str + "%command% " + args.game_args; steam_cmd_str.trim(); // set up steam string dynamic_string steam_str = "steam steam://run/" + args.gameid + "//"; dynamic_string steam_args = VOGL_CMD_LINE + " " + LD_PRELOAD + steam_cmd_str; dynamic_string steam_fullcmd = steam_str + url_encode(steam_args.c_str()); // Spew this whole mess out. vogl_printf("\nLaunch string:\n%s\n", (steam_str + steam_args).c_str()); vogl_printf("\nURL encoded launch string:\n%s\n", steam_fullcmd.c_str()); // And launch it... if (!args.dryrun) system(steam_fullcmd.c_str()); } else { dynamic_string system_cmd; system_cmd = VOGL_CMD_LINE + " " + LD_PRELOAD + " " + xterm_str + args.gameid + " " + args.game_args; vogl_printf("\nlaunch string:\n%s\n", system_cmd.c_str()); if (!args.dryrun) system(system_cmd.c_str()); } return true; }