static bool printNextDebugMessage() { if (!hasPendingDebugMessage()) { return false; } GLint msgLen = 0; glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB, &msgLen); SCP_vector<GLchar> msg; msg.resize(msgLen + 1); // Includes null character, needs to be removed later GLenum source; GLenum type; GLenum severity; GLuint id; GLsizei length; GLuint numFound = glGetDebugMessageLogARB(1, static_cast<GLsizei>(msg.size()), &source, &type, &id, &severity, &length, &msg[0]); if (numFound < 1) { return false; } debug_callback(source, type, id, severity, length, msg.data(), nullptr); return true; }
static void cache_program_binary(GLuint program, const SCP_string& hash) { if (!do_shader_caching()) { return; } GR_DEBUG_SCOPE("Saving shader binary"); GLint size; glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &size); if (size <= 0) { // No binary available (I'm looking at you Mesa...) return; } SCP_vector<uint8_t> binary; binary.resize((size_t) size); GLenum binary_fmt; GLsizei length; glGetProgramBinary(program, (GLsizei) binary.size(), &length, &binary_fmt, binary.data()); if (length == 0) { return; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata_name = base_filename + ".json"; auto binary_name = base_filename + ".bin"; auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!metadata_fp) { mprintf(("Could not open shader cache metadata file!\n")); return; } auto metadata = json_pack("{sI}", "format", (json_int_t)binary_fmt); if (json_dump_callback(metadata, json_write_callback, metadata_fp, 0) != 0) { mprintf(("Failed to write shader cache metadata file!\n")); cfclose(metadata_fp); return; } cfclose(metadata_fp); json_decref(metadata); auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!binary_fp) { mprintf(("Could not open shader cache binary file!\n")); return; } cfwrite(binary.data(), 1, (int) binary.size(), binary_fp); cfclose(binary_fp); }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_string& hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); bool supported = false; for (auto supported_fmt : GL_binary_formats) { if ((GLenum)supported_fmt == binary_format) { supported = true; break; } } if (!supported) { // This can happen in case an implementation stops supporting a particular binary format nprintf(("ShaderCache", "Unsupported binary format %d encountered in shader cache.\n", binary_format)); return false; } auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }
void credits_init() { int i; credits_screen_buttons *b; // pre-initialize Credits_num_images = DEFAULT_NUM_IMAGES; Credits_artwork_index = -1; // this is moved up here so we can override it if desired strcpy_s(Credits_music_name, "Cinema"); // parse credits early so as to set up any overrides (for music and such) Credits_parsed = false; credits_parse(); // we could conceivably have specified a number of images but not an index, // so if that's the case, set the value here if (Credits_artwork_index < 0) { Credits_artwork_index = rand() % Credits_num_images; } int credits_spooled_music_index = event_music_get_spooled_music_index(Credits_music_name); if(credits_spooled_music_index != -1){ char *credits_wavfile_name = Spooled_music[credits_spooled_music_index].filename; if(credits_wavfile_name != NULL){ credits_load_music(credits_wavfile_name); } } // Use this id to trigger the start of music playing on the briefing screen Credits_music_begin_timestamp = timestamp(Credits_music_delay); Credits_frametime = 0; Credits_last_time = timer_get_milliseconds(); if (!Credits_parsed) { Credit_text_parts.push_back(SCP_string("No credits available.\n")); } else { switch (SCP_credits_position) { case START: Credit_text_parts.insert(Credit_text_parts.begin(), fs2_open_credit_text); break; case END: Credit_text_parts.push_back(fs2_open_credit_text); break; default: Error(LOCATION, "Unimplemented credits position %d. Get a coder!", (int) SCP_credits_position); break; } } int ch; SCP_vector<SCP_string>::iterator iter; for (iter = Credit_text_parts.begin(); iter != Credit_text_parts.end(); ++iter) { for (SCP_string::iterator ii = iter->begin(); ii != iter->end(); ++ii) { ch = *ii; switch (ch) { case -4: ch = 129; break; case -28: ch = 132; break; case -10: ch = 148; break; case -23: ch = 130; break; case -30: ch = 131; break; case -25: ch = 135; break; case -21: ch = 137; break; case -24: ch = 138; break; case -17: ch = 139; break; case -18: ch = 140; break; case -60: ch = 142; break; case -55: ch = 144; break; case -12: ch = 147; break; case -14: ch = 149; break; case -5: ch = 150; break; case -7: ch = 151; break; case -42: ch = 153; break; case -36: ch = 154; break; case -31: ch = 160; break; case -19: ch = 161; break; case -13: ch = 162; break; case -6: ch = 163; break; case -32: ch = 133; break; case -22: ch = 136; break; case -20: ch = 141; break; } *ii = (char) ch; } } int temp_h; int h = 0; for (iter = Credit_text_parts.begin(); iter != Credit_text_parts.end(); ++iter) { gr_get_string_size(NULL, &temp_h, iter->c_str(), (int)iter->length()); h = h + temp_h; } Credit_start_pos = i2fl(Credits_text_coords[gr_screen.res][CREDITS_H_COORD]); Credit_stop_pos = -i2fl(h); Credit_position = Credit_start_pos; Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0); Ui_window.set_mask_bmap(Credits_bitmap_mask_fname[gr_screen.res]); common_set_interface_palette("InterfacePalette"); // set the interface palette for (i=0; i<NUM_BUTTONS; i++) { b = &Buttons[i][gr_screen.res]; b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1); // set up callback for when a mouse first goes over a button b->button.set_highlight_action(common_play_highlight_sound); b->button.set_bmaps(b->filename); b->button.link_hotspot(b->hotspot); } // add some text Ui_window.add_XSTR("Technical Database", 1055, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].xt, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].yt, &Buttons[TECH_DATABASE_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[SIMULATOR_BUTTON][gr_screen.res].xt, Buttons[SIMULATOR_BUTTON][gr_screen.res].yt, &Buttons[SIMULATOR_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Cutscenes", 1057, Buttons[CUTSCENES_BUTTON][gr_screen.res].xt, Buttons[CUTSCENES_BUTTON][gr_screen.res].yt, &Buttons[CUTSCENES_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Credits", 1058, Buttons[CREDITS_BUTTON][gr_screen.res].xt, Buttons[CREDITS_BUTTON][gr_screen.res].yt, &Buttons[CREDITS_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Exit", 1420, Buttons[EXIT_BUTTON][gr_screen.res].xt, Buttons[EXIT_BUTTON][gr_screen.res].yt, &Buttons[EXIT_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_PINK); if (Player->flags & PLAYER_FLAGS_IS_MULTI) { Buttons[SIMULATOR_BUTTON][gr_screen.res].button.disable(); Buttons[CUTSCENES_BUTTON][gr_screen.res].button.disable(); } Buttons[EXIT_BUTTON][gr_screen.res].button.set_hotkey(KEY_CTRLED | KEY_ENTER); Background_bitmap = bm_load(Credits_bitmap_fname[gr_screen.res]); Credits_bmps.resize(Credits_num_images); for (i=0; i<Credits_num_images; i++) { Credits_bmps[i] = -1; } }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, SCP_string hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }