static double update_video_nocorrect_pts(struct MPContext *mpctx) { struct sh_video *sh_video = mpctx->sh_video; double frame_time = 0; while (1) { // In nocorrect-pts mode there is no way to properly time these frames if (load_next_vo_frame(mpctx, false)) break; frame_time = sh_video->next_frame_time; if (mpctx->restart_playback) frame_time = 0; struct demux_packet *pkt = video_read_frame(mpctx); if (!pkt) return -1; if (mpctx->sh_audio) mpctx->delay -= frame_time; // video_read_frame can change fps (e.g. for ASF video) update_fps(mpctx); int framedrop_type = check_framedrop(mpctx, frame_time); void *decoded_frame = decode_video(sh_video, pkt, framedrop_type, sh_video->pts); talloc_free(pkt); if (decoded_frame) { filter_video(mpctx, decoded_frame); } break; } return frame_time; }
int osd_update(mame_time emutime) { win_window_info *window; // if we're throttling, paused, or if the UI is up, synchronize if (effective_throttle()) update_throttle(emutime); // update the FPS computations update_fps(emutime); // update all the windows, but only if we're not skipping this frame if (!skiptable[effective_frameskip()][frameskip_counter]) { profiler_mark(PROFILER_BLIT); for (window = win_window_list; window != NULL; window = window->next) winwindow_video_window_update(window); profiler_mark(PROFILER_END); } // if we're throttling and autoframeskip is on, adjust if (effective_throttle() && effective_autoframeskip() && frameskip_counter == 0) update_autoframeskip(); // poll the joystick values here winwindow_process_events(TRUE); wininput_poll(); check_osd_inputs(); // increment the frameskip counter frameskip_counter = (frameskip_counter + 1) % FRAMESKIP_LEVELS; // return whether or not to skip the next frame return skiptable[effective_frameskip()][frameskip_counter]; }
static void run_game() { game_data game; initialize_game(&game, wsi::milliseconds()); running = true; for (;;) { wsi::update(&screen); bool rendering = wsi::should_render(); int64_t millisecond_clock_now = wsi::milliseconds(); unsigned ticks_elapsed = 0; float fractional_ticks = 0; calc_game_elapsed_time(&game, &ticks_elapsed, &fractional_ticks, millisecond_clock_now); game_command action = { 0 }; process_inputs(&action); if (!running) break; update_game(&game, ticks_elapsed, &action, millisecond_clock_now); update_fps(); if (action.toggle_pause) { pause_eviz_dx12(game.paused); } if (rendering) { float dpi = (float)screen.dpi.cx; float x_dips = screen.dimensions.cx * 96.0f / dpi; float y_dips = screen.dimensions.cy * 96.0f / dpi; set_swapchain_options_dx12(&wsi::screen_window, NULL, x_dips, y_dips, dpi, &swapchain_opts); rebuild_hud_string(&game); dx12_render_stats stats; render_game_dx12(hud_string, &game, fractional_ticks, screen.prefs.vsync, &stats); if (stats.latency) { const float alpha = 0.1f; frame_latency = (1-alpha)*frame_latency + alpha*stats.latency; frame_latency_stddev = stats.stddev_jitter; frame_latency_minmaxd = stats.minmax_jitter; current_frametime_cpu = (1 - alpha)*current_frametime_cpu + alpha*stats.cpu_frame_time; current_frametime_gpu = (1 - alpha)*current_frametime_gpu + alpha*stats.gpu_frame_time; } } //wsi::limit_fps(max_fps); } }
void fps_break() { /* calculate how long that frame took and store time passed in globals */ int current_ticks = SDL_GetTicks(); int tick_wait = (current_ticks - fps_last_ticks) < fps_ticks_per_frame ? (fps_ticks_per_frame - (current_ticks - fps_last_ticks)) : 0; /* block for 60fps*/ SDL_Delay(tick_wait); /* store total frame ticks for FPS display */ fps_current_frame_ticks = (current_ticks - fps_last_ticks) + tick_wait; fps_last_ticks = current_ticks; update_fps(NULL); return; }
static void frame_callback(void *data, struct wl_callback *callback, uint32_t time) { struct gears *gears = data; update_fps(gears, time); gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0; window_schedule_redraw(gears->window); if (callback) wl_callback_destroy(callback); }
void render() { glClearColor(0.0, 0.0, 0.1, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glPolygonOffset(0.0, 0.0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); do_render(false); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonOffset(-1.0, -1.0); glLineWidth(2.0f); do_render(true); glutSwapBuffers(); update_fps(); }
void c_RendererViewer::display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); //glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glColor3f(1.0f, 0.f, 0.f); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glShadeModel(GL_SMOOTH); draw(""); glutSwapBuffers(); update_fps(); check_gl_errors(); return; }
static int motion_redraw(RASPITEX_STATE *raspitex_state) { // Start with a clear screen //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); RedrawGui(); /* GLCHK(glUseProgram(motion_shader.program)); GLCHK(glUniform1i(motion_shader.uniform_locations[0], 0)); // Bind the OES texture which is used to render the camera preview glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_EXTERNAL_OES, raspitex_state->texture); // Bind score texture glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, guiBuffer.id); GLCHK(glEnableVertexAttribArray(motion_shader.attribute_locations[0])); GLCHK(glVertexAttribPointer(motion_shader.attribute_locations[0], 2, GL_FLOAT, GL_FALSE, 0, varray)); GLCHK(glDrawArrays(GL_TRIANGLES, 0, 6)); GLCHK(glDisableVertexAttribArray(motion_shader.attribute_locations[0])); GLCHK(glBindTexture(GL_TEXTURE_2D, 0)); glActiveTexture(GL_TEXTURE0); GLCHK(glUseProgram(0)); */ motion_video1(raspitex_state); GLCHK(glEnable(GL_BLEND)); GLCHK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); RedrawTextures(); GLCHK(glDisable(GL_BLEND)); update_fps(); return 0; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (!glfwInit()) { return -1; } #ifdef __APPLE__ glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #endif if (!glfwOpenWindow(800, 600, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) { return -1; } glfwSwapInterval(VSYNC); glfwDisable(GLFW_MOUSE_CURSOR); glfwSetWindowTitle("Modern GL"); glfwSetKeyCallback(on_key); glfwSetMouseButtonCallback(on_mouse_button); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint vertex_array; glGenVertexArrays(1, &vertex_array); glBindVertexArray(vertex_array); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glfwLoadTexture2D("texture.tga", 0); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; int px = 0; int py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetMousePos(&px, &py); double previous = glfwGetTime(); while (glfwGetWindowParam(GLFW_OPENED)) { update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive) { int mx, my; glfwGetMousePos(&mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetMousePos(&px, &py); } if (left_click) { left_click = 0; int hx, hy, hz; if (hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz)) { if (hy > 0) { set_block(chunks, chunk_count, hx, hy, hz, 0); } } } if (right_click) { right_click = 0; int hx, hy, hz; if (hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type); } } } int sz = 0; int sx = 0; ortho = glfwGetKey(GLFW_KEY_LSHIFT); if (glfwGetKey('Q')) break; if (glfwGetKey('W')) sz--; if (glfwGetKey('S')) sz++; if (glfwGetKey('A')) sx--; if (glfwGetKey('D')) sx++; if (dy == 0 && glfwGetKey(GLFW_KEY_SPACE)) { dy = 8; } float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); ensure_chunks(chunks, &chunk_count, p, q, 0); update_matrix_3d(matrix, x, y, z, rx, ry); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (!chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; if (hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_cube_buffer(hx, hy, hz, 0.51); draw_lines(buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); } update_matrix_2d(matrix); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_line_buffer(); draw_lines(buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); glfwSwapBuffers(); } db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (argc == 2 || argc == 3) { char *hostname = argv[1]; int port = DEFAULT_PORT; if (argc == 3) { port = atoi(argv[2]); } db_disable(); client_enable(); client_connect(hostname, port); client_start(); } if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetMouseButtonCallback(window, on_mouse_button); glfwSetScrollCallback(window, on_scroll); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; Player players[MAX_PLAYERS]; int player_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } int sz = 0; int sx = 0; ortho = glfwGetKey(window, 'F'); fov = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) ? 15.0 : 65.0; if (glfwGetKey(window, 'Q')) break; if (glfwGetKey(window, 'W')) sz--; if (glfwGetKey(window, 'S')) sz++; if (glfwGetKey(window, 'A')) sx--; if (glfwGetKey(window, 'D')) sx++; float m = dt * 1.0; if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m; if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m; if (glfwGetKey(window, GLFW_KEY_UP)) ry += m; if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m; float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (glfwGetKey(window, GLFW_KEY_SPACE)) { if (flying) { vy = 1; } else if (dy == 0) { dy = 8; } } if (glfwGetKey(window, 'Z')) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, 'X')) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, 'C')) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, 'V')) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, 'B')) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, 'N')) { vx = 0; vy = 0; vz = 1; } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } if (y < 0) { y = highest_block(chunks, chunk_count, x, z) + 2; } for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; chunk->dirty = 0; } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0, 1); } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type, 1); } } } if (middle_click) { middle_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_selectable(hw)) { block_type = hw; } } if (teleport) { teleport = 0; if (player_count) { int index = rand_int(player_count); Player *player = players + index; x = player->x; y = player->y; z = player->z; rx = player->rx; ry = player->ry; ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); } } client_position(x, y, z, rx, ry); char buffer[RECV_BUFFER_SIZE]; while (client_recv(buffer, RECV_BUFFER_SIZE)) { float ux, uy, uz, urx, ury; if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f", &ux, &uy, &uz, &urx, &ury) == 5) { x = ux; y = uy; z = uz; rx = urx; ry = ury; ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); y = highest_block(chunks, chunk_count, x, z) + 2; } int bx, by, bz, bw; if (sscanf(buffer, "B,%*d,%*d,%d,%d,%d,%d", &bx, &by, &bz, &bw) == 4) { set_block(chunks, chunk_count, bx, by, bz, bw, 0); if ((int)roundf(x) == bx && (int)roundf(z) == bz) { y = highest_block(chunks, chunk_count, x, z) + 2; } } int pid; float px, py, pz, prx, pry; if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f", &pid, &px, &py, &pz, &prx, &pry) == 6) { Player *player = find_player(players, player_count, pid); if (!player && player_count < MAX_PLAYERS) { player = players + player_count; player_count++; player->id = pid; player->position_buffer = 0; player->normal_buffer = 0; player->uv_buffer = 0; printf("%d other players are online\n", player_count); } if (player) { update_player(player, px, py, pz, prx, pry); } } if (sscanf(buffer, "D,%d", &pid) == 1) { delete_player(players, &player_count, pid); printf("%d other players are online\n", player_count); } } for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk->dirty) { update_chunk(chunk); } } int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); ensure_chunks(chunks, &chunk_count, p, q, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); update_matrix_3d(matrix, x, y, z, rx, ry); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (!chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render players for (int i = 0; i < player_count; i++) { Player *player = players + i; draw_player(player, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test( chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint cube_buffer = make_cube_buffer(hx, hy, hz, 0.51); draw_lines(cube_buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &cube_buffer); glDisable(GL_COLOR_LOGIC_OP); } update_matrix_2d(matrix); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint line_buffer = make_line_buffer(); draw_lines(line_buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &line_buffer); glDisable(GL_COLOR_LOGIC_OP); // render selected item update_matrix_item(matrix); if (block_type != previous_block_type) { previous_block_type = block_type; make_single_cube( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); glDisable(GL_DEPTH_TEST); draw_single_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); glEnable(GL_DEPTH_TEST); glfwSwapBuffers(window); glfwPollEvents(); } client_stop(); db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
static inline void run_tick() { static bool can_tick = true; static bool last_freezekey = false; static bool last_framekey = false; static int frameskip = 0; input_poll(); // input handling for a few global things if (justpushed(ESCKEY)) { if (settings->instant_quit) { game.running = false; } else if (!game.paused) // no pause from Options { game.pause(GP_PAUSED); } } else if (justpushed(F3KEY)) { game.pause(GP_OPTIONS); } // freeze frame if (settings->enable_debug_keys) { if (inputs[FREEZE_FRAME_KEY] && !last_freezekey) { can_tick = true; freezeframe ^= 1; framecount = 0; } if (inputs[FRAME_ADVANCE_KEY] && !last_framekey) { can_tick = true; if (!freezeframe) { freezeframe = 1; framecount = 0; } } last_freezekey = inputs[FREEZE_FRAME_KEY]; last_framekey = inputs[FRAME_ADVANCE_KEY]; } // fast-forward key (F5) if (inputs[FFWDKEY] && (settings->enable_debug_keys || Replay::IsPlaying())) { game.ffwdtime = 2; } if (can_tick) { game.tick(); if (freezeframe) { char buf[1024]; sprintf(buf, "[] Tick %d", framecount++); font_draw_shaded(4, (SCREEN_HEIGHT-GetFontHeight()-4), buf, 0, &greenfont); can_tick = false; } else { Replay::DrawStatus(); } if (settings->show_fps) { update_fps(); } if (!flipacceltime) { //platform_sync_to_vblank(); screen->Flip(); } else { flipacceltime--; if (--frameskip < 0) { screen->Flip(); frameskip = 256; } } memcpy(lastinputs, inputs, sizeof(lastinputs)); } else { // frame is frozen; don't hog CPU SDL_Delay(20); } // immediately after a game tick is when we have the most amount of time before // the game needs to run again. so now's as good a time as any for some // BGM audio processing, wouldn't you say? org_run(); }
void write_video(struct MPContext *mpctx, double endpts) { struct MPOpts *opts = mpctx->opts; struct vo *vo = mpctx->video_out; if (!mpctx->d_video) return; // Actual playback starts when both audio and video are ready. if (mpctx->video_status == STATUS_READY) return; if (mpctx->paused && mpctx->video_status >= STATUS_READY) return; update_fps(mpctx); int r = video_output_image(mpctx, endpts); MP_TRACE(mpctx, "video_output_image: %d\n", r); if (r < 0) goto error; if (r == VD_WAIT) // Demuxer will wake us up for more packets to decode. return; if (r == VD_EOF) { mpctx->video_status = vo_still_displaying(vo) ? STATUS_DRAINING : STATUS_EOF; mpctx->delay = 0; mpctx->last_av_difference = 0; MP_VERBOSE(mpctx, "video EOF (status=%d)\n", mpctx->video_status); return; } if (mpctx->video_status > STATUS_PLAYING) mpctx->video_status = STATUS_PLAYING; mpctx->time_frame -= get_relative_time(mpctx); update_avsync_before_frame(mpctx); if (r != VD_NEW_FRAME) { mpctx->sleeptime = 0; // Decode more in next iteration. return; } // Filter output is different from VO input? struct mp_image_params p = mpctx->next_frame[0]->params; if (!vo->params || !mp_image_params_equal(&p, vo->params)) { // Changing config deletes the current frame; wait until it's finished. if (vo_still_displaying(vo)) return; const struct vo_driver *info = mpctx->video_out->driver; char extra[20] = {0}; if (p.w != p.d_w || p.h != p.d_h) snprintf(extra, sizeof(extra), " => %dx%d", p.d_w, p.d_h); MP_INFO(mpctx, "VO: [%s] %dx%d%s %s\n", info->name, p.w, p.h, extra, vo_format_name(p.imgfmt)); MP_VERBOSE(mpctx, "VO: Description: %s\n", info->description); int vo_r = vo_reconfig(vo, &p, 0); if (vo_r < 0) { mpctx->error_playing = MPV_ERROR_VO_INIT_FAILED; goto error; } init_vo(mpctx); mpctx->time_frame = 0; // display immediately } double time_frame = MPMAX(mpctx->time_frame, -1); int64_t pts = mp_time_us() + (int64_t)(time_frame * 1e6); // wait until VO wakes us up to get more frames if (!vo_is_ready_for_frame(vo, pts)) { if (video_feed_async_filter(mpctx) < 0) goto error; return; } int64_t duration = -1; double diff = -1; double vpts0 = mpctx->next_frame[0] ? mpctx->next_frame[0]->pts : MP_NOPTS_VALUE; double vpts1 = mpctx->next_frame[1] ? mpctx->next_frame[1]->pts : MP_NOPTS_VALUE; if (vpts0 != MP_NOPTS_VALUE && vpts1 != MP_NOPTS_VALUE) diff = vpts1 - vpts0; if (diff < 0 && mpctx->d_video->fps > 0) diff = 1.0 / mpctx->d_video->fps; // fallback to demuxer-reported fps if (diff >= 0) { // expected A/V sync correction is ignored diff /= opts->playback_speed; if (mpctx->time_frame < 0) diff += mpctx->time_frame; duration = MPCLAMP(diff, 0, 10) * 1e6; } mpctx->video_pts = mpctx->next_frame[0]->pts; mpctx->last_vo_pts = mpctx->video_pts; mpctx->playback_pts = mpctx->video_pts; mpctx->osd_force_update = true; update_osd_msg(mpctx); update_subtitles(mpctx); vo_queue_frame(vo, mpctx->next_frame[0], pts, duration); mpctx->next_frame[0] = NULL; mpctx->shown_vframes++; if (mpctx->video_status < STATUS_PLAYING) { mpctx->video_status = STATUS_READY; // After a seek, make sure to wait until the first frame is visible. vo_wait_frame(vo); } update_avsync_after_frame(mpctx); screenshot_flip(mpctx); mp_notify(mpctx, MPV_EVENT_TICK, NULL); if (!mpctx->sync_audio_to_video) mpctx->video_status = STATUS_EOF; if (mpctx->video_status != STATUS_EOF) { if (mpctx->step_frames > 0) { mpctx->step_frames--; if (!mpctx->step_frames && !opts->pause) pause_player(mpctx); } if (mpctx->max_frames == 0) mpctx->stop_play = AT_END_OF_FILE; if (mpctx->max_frames > 0) mpctx->max_frames--; } mpctx->sleeptime = 0; return; error: MP_FATAL(mpctx, "Could not initialize video chain.\n"); uninit_video_chain(mpctx); error_on_track(mpctx, mpctx->current_track[STREAM_VIDEO][0]); handle_force_window(mpctx, true); mpctx->sleeptime = 0; }
void write_video(struct MPContext *mpctx, double endpts) { struct MPOpts *opts = mpctx->opts; struct vo *vo = mpctx->video_out; if (!mpctx->d_video) return; update_fps(mpctx); // Whether there's still at least 1 video frame that can be shown. // If false, it means we can reconfig the VO if needed (normally, this // would disrupt playback, so only do it on !still_playing). bool still_playing = vo_has_next_frame(vo, true); // For the last frame case (frame is being displayed). still_playing |= mpctx->playing_last_frame; still_playing |= mpctx->last_frame_duration > 0; double frame_time = 0; int r = update_video(mpctx, endpts, !still_playing, &frame_time); MP_TRACE(mpctx, "update_video: %d (still_playing=%d)\n", r, still_playing); if (r == VD_WAIT) // Demuxer will wake us up for more packets to decode. return; if (r < 0) { MP_FATAL(mpctx, "Could not initialize video chain.\n"); int uninit = INITIALIZED_VCODEC; if (!opts->force_vo) uninit |= INITIALIZED_VO; uninit_player(mpctx, uninit); if (!mpctx->current_track[STREAM_AUDIO]) mpctx->stop_play = PT_NEXT_ENTRY; mpctx->error_playing = true; handle_force_window(mpctx, true); return; // restart loop } if (r == VD_EOF) { if (!mpctx->playing_last_frame && mpctx->last_frame_duration > 0) { mpctx->time_frame += mpctx->last_frame_duration; mpctx->last_frame_duration = 0; mpctx->playing_last_frame = true; MP_VERBOSE(mpctx, "showing last frame\n"); } } if (r == VD_NEW_FRAME) { MP_TRACE(mpctx, "frametime=%5.3f\n", frame_time); if (mpctx->video_status > STATUS_PLAYING) mpctx->video_status = STATUS_PLAYING; if (mpctx->video_status >= STATUS_READY) { mpctx->time_frame += frame_time / opts->playback_speed; adjust_sync(mpctx, frame_time); } } else if (r == VD_EOF && mpctx->playing_last_frame) { // Let video timing code continue displaying. mpctx->video_status = STATUS_DRAINING; MP_VERBOSE(mpctx, "still showing last frame\n"); } else if (r <= 0) { // EOF or error mpctx->delay = 0; mpctx->last_av_difference = 0; mpctx->video_status = STATUS_EOF; MP_VERBOSE(mpctx, "video EOF\n"); return; } else { if (mpctx->video_status > STATUS_PLAYING) mpctx->video_status = STATUS_PLAYING; // Decode more in next iteration. mpctx->sleeptime = 0; MP_TRACE(mpctx, "filtering more video\n"); } // Actual playback starts when both audio and video are ready. if (mpctx->video_status == STATUS_READY) return; if (mpctx->paused && mpctx->video_status >= STATUS_READY) return; mpctx->time_frame -= get_relative_time(mpctx); double audio_pts = playing_audio_pts(mpctx); if (!mpctx->sync_audio_to_video || mpctx->video_status < STATUS_READY) { mpctx->time_frame = 0; } else if (mpctx->audio_status == STATUS_PLAYING && mpctx->video_status == STATUS_PLAYING) { double buffered_audio = ao_get_delay(mpctx->ao); MP_TRACE(mpctx, "audio delay=%f\n", buffered_audio); if (opts->autosync) { /* Smooth reported playback position from AO by averaging * it with the value expected based on previus value and * time elapsed since then. May help smooth video timing * with audio output that have inaccurate position reporting. * This is badly implemented; the behavior of the smoothing * now undesirably depends on how often this code runs * (mainly depends on video frame rate). */ float predicted = (mpctx->delay / opts->playback_speed + mpctx->time_frame); float difference = buffered_audio - predicted; buffered_audio = predicted + difference / opts->autosync; } mpctx->time_frame = (buffered_audio - mpctx->delay / opts->playback_speed); } else { /* If we're more than 200 ms behind the right playback * position, don't try to speed up display of following * frames to catch up; continue with default speed from * the current frame instead. * If untimed is set always output frames immediately * without sleeping. */ if (mpctx->time_frame < -0.2 || opts->untimed || vo->untimed) mpctx->time_frame = 0; } double vsleep = mpctx->time_frame - vo->flip_queue_offset; if (vsleep > 0.050) { mpctx->sleeptime = MPMIN(mpctx->sleeptime, vsleep - 0.040); return; } mpctx->sleeptime = 0; mpctx->playing_last_frame = false; // last frame case if (r != VD_NEW_FRAME) return; //=================== FLIP PAGE (VIDEO BLT): ====================== mpctx->video_pts = mpctx->video_next_pts; mpctx->last_vo_pts = mpctx->video_pts; mpctx->playback_pts = mpctx->video_pts; update_subtitles(mpctx); update_osd_msg(mpctx); MP_STATS(mpctx, "vo draw frame"); vo_new_frame_imminent(vo); MP_STATS(mpctx, "vo sleep"); mpctx->time_frame -= get_relative_time(mpctx); mpctx->time_frame -= vo->flip_queue_offset; if (mpctx->time_frame > 0.001) mpctx->time_frame = timing_sleep(mpctx, mpctx->time_frame); mpctx->time_frame += vo->flip_queue_offset; int64_t t2 = mp_time_us(); /* Playing with playback speed it's possible to get pathological * cases with mpctx->time_frame negative enough to cause an * overflow in pts_us calculation, thus the MPMAX. */ double time_frame = MPMAX(mpctx->time_frame, -1); int64_t pts_us = mpctx->last_time + time_frame * 1e6; int duration = -1; double pts2 = vo_get_next_pts(vo, 0); // this is the next frame PTS if (mpctx->video_pts != MP_NOPTS_VALUE && pts2 == MP_NOPTS_VALUE) { // Make up a frame duration. Using the frame rate is not a good // choice, since the frame rate could be unset/broken/random. float fps = mpctx->d_video->fps; double frame_duration = fps > 0 ? 1.0 / fps : 0; pts2 = mpctx->video_pts + MPCLAMP(frame_duration, 0.0, 5.0); } if (pts2 != MP_NOPTS_VALUE) { // expected A/V sync correction is ignored double diff = (pts2 - mpctx->video_pts); diff /= opts->playback_speed; if (mpctx->time_frame < 0) diff += mpctx->time_frame; if (diff < 0) diff = 0; if (diff > 10) diff = 10; duration = diff * 1e6; mpctx->last_frame_duration = diff; } if (mpctx->video_status != STATUS_PLAYING) duration = -1; MP_STATS(mpctx, "start flip"); vo_flip_page(vo, pts_us | 1, duration); MP_STATS(mpctx, "end flip"); if (audio_pts != MP_NOPTS_VALUE) MP_STATS(mpctx, "value %f ptsdiff", mpctx->video_pts - audio_pts); mpctx->last_vo_flip_duration = (mp_time_us() - t2) * 0.000001; if (vo->driver->flip_page_timed) { // No need to adjust sync based on flip speed mpctx->last_vo_flip_duration = 0; // For print_status - VO call finishing early is OK for sync mpctx->time_frame -= get_relative_time(mpctx); } mpctx->shown_vframes++; if (mpctx->video_status < STATUS_PLAYING) mpctx->video_status = STATUS_READY; update_avsync(mpctx); screenshot_flip(mpctx); mp_notify(mpctx, MPV_EVENT_TICK, NULL); if (!mpctx->sync_audio_to_video) mpctx->video_status = STATUS_EOF; }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetMouseButtonCallback(window, on_mouse_button); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint vertex_array; glGenVertexArrays(1, &vertex_array); glBindVertexArray(vertex_array); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, floorf(roundf(x) / CHUNK_SIZE), floorf(roundf(z) / CHUNK_SIZE), 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0); } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type); } } } int sz = 0; int sx = 0; ortho = glfwGetKey(window, 'F'); fov = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) ? 15.0 : 65.0; if (glfwGetKey(window, 'Q')) break; if (glfwGetKey(window, 'W')) sz--; if (glfwGetKey(window, 'S')) sz++; if (glfwGetKey(window, 'A')) sx--; if (glfwGetKey(window, 'D')) sx++; if (dy == 0 && glfwGetKey(window, GLFW_KEY_SPACE)) { dy = 8; } float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (glfwGetKey(window, 'Z')) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, 'X')) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, 'C')) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, 'V')) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, 'B')) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, 'N')) { vx = 0; vy = 0; vz = 1; } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } int p = floorf(roundf(x) / CHUNK_SIZE); int q = floorf(roundf(z) / CHUNK_SIZE); ensure_chunks(chunks, &chunk_count, p, q, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); update_matrix_3d(matrix, x, y, z, rx, ry); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (!chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_cube_buffer(hx, hy, hz, 0.51); draw_lines(buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); } update_matrix_2d(matrix); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint buffer = make_line_buffer(); draw_lines(buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &buffer); glDisable(GL_COLOR_LOGIC_OP); // render selected item update_matrix_item(matrix); if (block_type != previous_block_type) { previous_block_type = block_type; make_single_cube( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, block_type); } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); glDisable(GL_DEPTH_TEST); draw_single_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); glEnable(GL_DEPTH_TEST); glfwSwapBuffers(window); glfwPollEvents(); } db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; assert(!mpctx->d_video); struct track *track = mpctx->current_track[0][STREAM_VIDEO]; struct sh_stream *sh = track ? track->stream : NULL; if (!sh) goto no_video; MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n", sh->format, sh->video->disp_w, sh->video->disp_h, sh->video->fps); //================== Init VIDEO (codec & libvo) ========================== if (!opts->fixed_vo || !mpctx->video_out) { struct vo_extra ex = { .input_ctx = mpctx->input, .osd = mpctx->osd, .encode_lavc_ctx = mpctx->encode_lavc_ctx, .opengl_cb_context = mpctx->gl_cb_ctx, }; mpctx->video_out = init_best_video_out(mpctx->global, &ex); if (!mpctx->video_out) { MP_FATAL(mpctx, "Error opening/initializing " "the selected video_out (-vo) device.\n"); mpctx->error_playing = MPV_ERROR_VO_INIT_FAILED; goto err_out; } mpctx->mouse_cursor_visible = true; } update_window_title(mpctx, true); struct dec_video *d_video = talloc_zero(NULL, struct dec_video); mpctx->d_video = d_video; d_video->global = mpctx->global; d_video->log = mp_log_new(d_video, mpctx->log, "!vd"); d_video->opts = mpctx->opts; d_video->header = sh; d_video->fps = sh->video->fps; d_video->vo = mpctx->video_out; if (opts->force_fps) { d_video->fps = opts->force_fps; MP_INFO(mpctx, "FPS forced to %5.3f.\n", d_video->fps); MP_INFO(mpctx, "Use --no-correct-pts to force FPS based timing.\n"); } update_fps(mpctx); vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info); recreate_video_filters(mpctx); if (!video_init_best_codec(d_video, opts->video_decoders)) goto err_out; bool saver_state = opts->pause || !opts->stop_screensaver; vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER : VOCTRL_KILL_SCREENSAVER, NULL); vo_set_paused(mpctx->video_out, mpctx->paused); mpctx->sync_audio_to_video = !sh->attached_picture; mpctx->vo_pts_history_seek_ts++; // If we switch on video again, ensure audio position matches up. if (mpctx->d_audio) mpctx->audio_status = STATUS_SYNCING; reset_video_state(mpctx); reset_subtitle_state(mpctx); return 1; err_out: no_video: uninit_video_chain(mpctx); if (track) error_on_track(mpctx, track); handle_force_window(mpctx, true); return 0; } // Try to refresh the video by doing a precise seek to the currently displayed // frame. This can go wrong in all sorts of ways, so use sparingly. void mp_force_video_refresh(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; struct dec_video *d_video = mpctx->d_video; if (!d_video || !d_video->decoder_output.imgfmt) return; // If not paused, the next frame should come soon enough. if (opts->pause && mpctx->last_vo_pts != MP_NOPTS_VALUE) queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->last_vo_pts, 2, true); } static int check_framedrop(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; // check for frame-drop: if (mpctx->video_status == STATUS_PLAYING && !mpctx->paused && mpctx->audio_status == STATUS_PLAYING && !ao_untimed(mpctx->ao)) { float fps = mpctx->d_video->fps; double frame_time = fps > 0 ? 1.0 / fps : 0; // we should avoid dropping too many frames in sequence unless we // are too late. and we allow 100ms A-V delay here: if (mpctx->last_av_difference - 0.100 > mpctx->dropped_frames * frame_time) return !!(opts->frame_dropping & 2); } return 0; } // Read a packet, store decoded image into d_video->waiting_decoded_mpi // returns VD_* code static int decode_image(struct MPContext *mpctx) { struct dec_video *d_video = mpctx->d_video; if (d_video->header->attached_picture) { d_video->waiting_decoded_mpi = video_decode(d_video, d_video->header->attached_picture, 0); return VD_EOF; } struct demux_packet *pkt; if (demux_read_packet_async(d_video->header, &pkt) == 0) return VD_WAIT; if (pkt && pkt->pts != MP_NOPTS_VALUE) pkt->pts += mpctx->video_offset; if ((pkt && pkt->pts >= mpctx->hrseek_pts - .005) || d_video->has_broken_packet_pts || !mpctx->opts->hr_seek_framedrop) { mpctx->hrseek_framedrop = false; } bool hrseek = mpctx->hrseek_active && mpctx->video_status == STATUS_SYNCING; int framedrop_type = hrseek && mpctx->hrseek_framedrop ? 2 : check_framedrop(mpctx); d_video->waiting_decoded_mpi = video_decode(d_video, pkt, framedrop_type); bool had_packet = !!pkt; talloc_free(pkt); if (had_packet && !d_video->waiting_decoded_mpi && mpctx->video_status == STATUS_PLAYING) { mpctx->dropped_frames_total++; mpctx->dropped_frames++; } return had_packet ? VD_PROGRESS : VD_EOF; } // Called after video reinit. This can be generally used to try to insert more // filters using the filter chain edit functionality in command.c. static void init_filter_params(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; // Note that the filter chain is already initialized. This code might // recreate the chain a second time, which is not very elegant, but allows // us to test whether enabling deinterlacing works with the current video // format and other filters. if (opts->deinterlace >= 0) mp_property_do("deinterlace", M_PROPERTY_SET, &opts->deinterlace, mpctx); } // Feed newly decoded frames to the filter, take care of format changes. // If eof=true, drain the filter chain, and return VD_EOF if empty. static int video_filter(struct MPContext *mpctx, bool eof) { struct dec_video *d_video = mpctx->d_video; struct vf_chain *vf = d_video->vfilter; if (vf->initialized < 0) return VD_ERROR; // There is already a filtered frame available. // If vf_needs_input() returns > 0, the filter wants input anyway. if (vf_output_frame(vf, eof) > 0 && vf_needs_input(vf) < 1) return VD_PROGRESS; // Decoder output is different from filter input? bool need_vf_reconfig = !vf->input_params.imgfmt || vf->initialized < 1 || !mp_image_params_equal(&d_video->decoder_output, &vf->input_params); // (If imgfmt==0, nothing was decoded yet, and the format is unknown.) if (need_vf_reconfig && d_video->decoder_output.imgfmt) { // Drain the filter chain. if (vf_output_frame(vf, true) > 0) return VD_PROGRESS; // The filter chain is drained; execute the filter format change. filter_reconfig(mpctx, false); if (vf->initialized == 0) return VD_PROGRESS; // hw decoding fallback; try again if (vf->initialized < 1) return VD_ERROR; init_filter_params(mpctx); return VD_RECONFIG; } // If something was decoded, and the filter chain is ready, filter it. if (!need_vf_reconfig && d_video->waiting_decoded_mpi) { vf_filter_frame(vf, d_video->waiting_decoded_mpi); d_video->waiting_decoded_mpi = NULL; return VD_PROGRESS; } return eof ? VD_EOF : VD_PROGRESS; } // Make sure at least 1 filtered image is available, decode new video if needed. // returns VD_* code // A return value of VD_PROGRESS doesn't necessarily output a frame, but makes // the promise that calling this function again will eventually do something. static int video_decode_and_filter(struct MPContext *mpctx) { struct dec_video *d_video = mpctx->d_video; int r = video_filter(mpctx, false); if (r < 0) return r; if (!d_video->waiting_decoded_mpi) { // Decode a new image, or at least feed the decoder a packet. r = decode_image(mpctx); if (r == VD_WAIT) return r; if (d_video->waiting_decoded_mpi) d_video->decoder_output = d_video->waiting_decoded_mpi->params; } bool eof = !d_video->waiting_decoded_mpi && (r == VD_EOF || r < 0); r = video_filter(mpctx, eof); if (r == VD_RECONFIG) // retry feeding decoded image r = video_filter(mpctx, eof); return r; } static int video_feed_async_filter(struct MPContext *mpctx) { struct dec_video *d_video = mpctx->d_video; struct vf_chain *vf = d_video->vfilter; if (vf->initialized < 0) return VD_ERROR; if (vf_needs_input(vf) < 1) return 0; mpctx->sleeptime = 0; // retry until done return video_decode_and_filter(mpctx); } /* Modify video timing to match the audio timeline. There are two main * reasons this is needed. First, video and audio can start from different * positions at beginning of file or after a seek (MPlayer starts both * immediately even if they have different pts). Second, the file can have * audio timestamps that are inconsistent with the duration of the audio * packets, for example two consecutive timestamp values differing by * one second but only a packet with enough samples for half a second * of playback between them. */ static void adjust_sync(struct MPContext *mpctx, double v_pts, double frame_time) { struct MPOpts *opts = mpctx->opts; if (mpctx->audio_status != STATUS_PLAYING) return; double a_pts = written_audio_pts(mpctx) + mpctx->audio_delay - mpctx->delay; double av_delay = a_pts - v_pts; double change = av_delay * 0.1; double max_change = opts->default_max_pts_correction >= 0 ? opts->default_max_pts_correction : frame_time * 0.1; if (change < -max_change) change = -max_change; else if (change > max_change) change = max_change; mpctx->delay += change; mpctx->total_avsync_change += change; } // Enough video filtered already to push one frame to the VO? static bool have_new_frame(struct MPContext *mpctx) { bool need_2nd = !!(mpctx->opts->frame_dropping & 1) // we need the duration && mpctx->video_pts != MP_NOPTS_VALUE; // ...except for the 1st frame return mpctx->next_frame[0] && (!need_2nd || mpctx->next_frame[1]); }
int main(int argc, char **argv) { srand(time(NULL)); rand(); if (argc == 2 || argc == 3) { char *hostname = argv[1]; int port = DEFAULT_PORT; if (argc == 3) { port = atoi(argv[2]); } db_disable(); client_enable(); client_connect(hostname, port); client_start(); } if (!glfwInit()) { return -1; } create_window(); if (!window) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSwapInterval(VSYNC); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetKeyCallback(window, on_key); glfwSetCharCallback(window, on_char); glfwSetMouseButtonCallback(window, on_mouse_button); glfwSetScrollCallback(window, on_scroll); #ifndef __APPLE__ if (glewInit() != GLEW_OK) { return -1; } #endif if (db_init()) { return -1; } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LINE_SMOOTH); glLogicOp(GL_INVERT); glClearColor(0.53, 0.81, 0.92, 1.00); GLuint texture; glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); load_png_texture("texture.png"); GLuint font; glGenTextures(1, &font); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, font); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); load_png_texture("font.png"); GLuint block_program = load_program( "shaders/block_vertex.glsl", "shaders/block_fragment.glsl"); GLuint matrix_loc = glGetUniformLocation(block_program, "matrix"); GLuint camera_loc = glGetUniformLocation(block_program, "camera"); GLuint sampler_loc = glGetUniformLocation(block_program, "sampler"); GLuint timer_loc = glGetUniformLocation(block_program, "timer"); GLuint position_loc = glGetAttribLocation(block_program, "position"); GLuint normal_loc = glGetAttribLocation(block_program, "normal"); GLuint uv_loc = glGetAttribLocation(block_program, "uv"); GLuint line_program = load_program( "shaders/line_vertex.glsl", "shaders/line_fragment.glsl"); GLuint line_matrix_loc = glGetUniformLocation(line_program, "matrix"); GLuint line_position_loc = glGetAttribLocation(line_program, "position"); GLuint text_program = load_program( "shaders/text_vertex.glsl", "shaders/text_fragment.glsl"); GLuint text_matrix_loc = glGetUniformLocation(text_program, "matrix"); GLuint text_sampler_loc = glGetUniformLocation(text_program, "sampler"); GLuint text_position_loc = glGetAttribLocation(text_program, "position"); GLuint text_uv_loc = glGetAttribLocation(text_program, "uv"); GLuint item_position_buffer = 0; GLuint item_normal_buffer = 0; GLuint item_uv_buffer = 0; int previous_block_type = 0; char messages[MAX_MESSAGES][TEXT_BUFFER_SIZE] = {0}; int message_index = 0; Chunk chunks[MAX_CHUNKS]; int chunk_count = 0; Player players[MAX_PLAYERS]; int player_count = 0; FPS fps = {0, 0}; float matrix[16]; float x = (rand_double() - 0.5) * 10000; float z = (rand_double() - 0.5) * 10000; float y = 0; float dy = 0; float rx = 0; float ry = 0; double px = 0; double py = 0; int loaded = db_load_state(&x, &y, &z, &rx, &ry); ensure_chunks(chunks, &chunk_count, x, y, z, 1); if (!loaded) { y = highest_block(chunks, chunk_count, x, z) + 2; } glfwGetCursorPos(window, &px, &py); double previous = glfwGetTime(); while (!glfwWindowShouldClose(window)) { int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); update_fps(&fps, SHOW_FPS); double now = glfwGetTime(); double dt = MIN(now - previous, 0.2); previous = now; if (exclusive && (px || py)) { double mx, my; glfwGetCursorPos(window, &mx, &my); float m = 0.0025; rx += (mx - px) * m; ry -= (my - py) * m; if (rx < 0) { rx += RADIANS(360); } if (rx >= RADIANS(360)){ rx -= RADIANS(360); } ry = MAX(ry, -RADIANS(90)); ry = MIN(ry, RADIANS(90)); px = mx; py = my; } else { glfwGetCursorPos(window, &px, &py); } int sz = 0; int sx = 0; if (!typing) { float m = dt * 1.0; ortho = glfwGetKey(window, CRAFT_KEY_ORTHO); fov = glfwGetKey(window, CRAFT_KEY_ZOOM) ? 15.0 : 65.0; if (glfwGetKey(window, CRAFT_KEY_QUIT)) break; if (glfwGetKey(window, CRAFT_KEY_FORWARD)) sz--; if (glfwGetKey(window, CRAFT_KEY_BACKWARD)) sz++; if (glfwGetKey(window, CRAFT_KEY_LEFT)) sx--; if (glfwGetKey(window, CRAFT_KEY_RIGHT)) sx++; if (glfwGetKey(window, GLFW_KEY_LEFT)) rx -= m; if (glfwGetKey(window, GLFW_KEY_RIGHT)) rx += m; if (glfwGetKey(window, GLFW_KEY_UP)) ry += m; if (glfwGetKey(window, GLFW_KEY_DOWN)) ry -= m; } float vx, vy, vz; get_motion_vector(flying, sz, sx, rx, ry, &vx, &vy, &vz); if (!typing) { if (glfwGetKey(window, CRAFT_KEY_JUMP)) { if (flying) { vy = 1; } else if (dy == 0) { dy = 8; } } if (glfwGetKey(window, CRAFT_KEY_XM)) { vx = -1; vy = 0; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_XP)) { vx = 1; vy = 0; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_YM)) { vx = 0; vy = -1; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_YP)) { vx = 0; vy = 1; vz = 0; } if (glfwGetKey(window, CRAFT_KEY_ZM)) { vx = 0; vy = 0; vz = -1; } if (glfwGetKey(window, CRAFT_KEY_ZP)) { vx = 0; vy = 0; vz = 1; } } float speed = flying ? 20 : 5; int step = 8; float ut = dt / step; vx = vx * ut * speed; vy = vy * ut * speed; vz = vz * ut * speed; for (int i = 0; i < step; i++) { if (flying) { dy = 0; } else { dy -= ut * 25; dy = MAX(dy, -250); } x += vx; y += vy + dy * ut; z += vz; if (collide(chunks, chunk_count, 2, &x, &y, &z)) { dy = 0; } } if (y < 0) { y = highest_block(chunks, chunk_count, x, z) + 2; } if (left_click) { left_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (hy > 0 && is_destructable(hw)) { set_block(chunks, chunk_count, hx, hy, hz, 0); int above = get_block(chunks, chunk_count, hx, hy + 1, hz); if (is_plant(above)) { set_block(chunks, chunk_count, hx, hy + 1, hz, 0); } } } if (right_click) { right_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 1, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { if (!player_intersects_block(2, x, y, z, hx, hy, hz)) { set_block(chunks, chunk_count, hx, hy, hz, block_type); } } } if (middle_click) { middle_click = 0; int hx, hy, hz; int hw = hit_test(chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_selectable(hw)) { block_type = hw; } } if (teleport) { teleport = 0; if (player_count) { int index = rand_int(player_count); Player *player = players + index; x = player->x; y = player->y; z = player->z; rx = player->rx; ry = player->ry; ensure_chunks(chunks, &chunk_count, x, y, z, 1); } } client_position(x, y, z, rx, ry); char buffer[RECV_BUFFER_SIZE]; while (client_recv(buffer, RECV_BUFFER_SIZE)) { float ux, uy, uz, urx, ury; if (sscanf(buffer, "U,%*d,%f,%f,%f,%f,%f", &ux, &uy, &uz, &urx, &ury) == 5) { x = ux; y = uy; z = uz; rx = urx; ry = ury; ensure_chunks(chunks, &chunk_count, x, y, z, 1); y = highest_block(chunks, chunk_count, x, z) + 2; } int bp, bq, bx, by, bz, bw; if (sscanf(buffer, "B,%d,%d,%d,%d,%d,%d", &bp, &bq, &bx, &by, &bz, &bw) == 6) { _set_block(chunks, chunk_count, bp, bq, bx, by, bz, bw); if (player_intersects_block(2, x, y, z, bx, by, bz)) { y = highest_block(chunks, chunk_count, x, z) + 2; } } int pid; float px, py, pz, prx, pry; if (sscanf(buffer, "P,%d,%f,%f,%f,%f,%f", &pid, &px, &py, &pz, &prx, &pry) == 6) { Player *player = find_player(players, player_count, pid); if (!player && player_count < MAX_PLAYERS) { player = players + player_count; player_count++; player->id = pid; player->position_buffer = 0; player->normal_buffer = 0; player->uv_buffer = 0; } if (player) { update_player(player, px, py, pz, prx, pry); } } if (sscanf(buffer, "D,%d", &pid) == 1) { delete_player(players, &player_count, pid); } if (buffer[0] == 'T' && buffer[1] == ',') { char *text = buffer + 2; printf("%s\n", text); snprintf( messages[message_index], TEXT_BUFFER_SIZE, "%s", text); message_index = (message_index + 1) % MAX_MESSAGES; } } int p = chunked(x); int q = chunked(z); ensure_chunks(chunks, &chunk_count, x, y, z, 0); // RENDER 3-D SCENE // glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); set_matrix_3d(matrix, width, height, x, y, z, rx, ry, fov, ortho); // render chunks glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, x, y, z); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); for (int i = 0; i < chunk_count; i++) { Chunk *chunk = chunks + i; if (chunk_distance(chunk, p, q) > RENDER_CHUNK_RADIUS) { continue; } if (y < 100 && !chunk_visible(chunk, matrix)) { continue; } draw_chunk(chunk, position_loc, normal_loc, uv_loc); } // render players for (int i = 0; i < player_count; i++) { Player *player = players + i; draw_player(player, position_loc, normal_loc, uv_loc); } // render focused block wireframe int hx, hy, hz; int hw = hit_test( chunks, chunk_count, 0, x, y, z, rx, ry, &hx, &hy, &hz); if (is_obstacle(hw)) { glUseProgram(line_program); glLineWidth(1); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint wireframe_buffer = gen_wireframe_buffer(hx, hy, hz, 0.51); draw_lines(wireframe_buffer, line_position_loc, 3, 48); glDeleteBuffers(1, &wireframe_buffer); glDisable(GL_COLOR_LOGIC_OP); } // RENDER 2-D HUD PARTS // glClear(GL_DEPTH_BUFFER_BIT); set_matrix_2d(matrix, width, height); // render crosshairs glUseProgram(line_program); glLineWidth(4); glEnable(GL_COLOR_LOGIC_OP); glUniformMatrix4fv(line_matrix_loc, 1, GL_FALSE, matrix); GLuint crosshair_buffer = gen_crosshair_buffer(width, height); draw_lines(crosshair_buffer, line_position_loc, 2, 4); glDeleteBuffers(1, &crosshair_buffer); glDisable(GL_COLOR_LOGIC_OP); // render text glUseProgram(text_program); glUniformMatrix4fv(text_matrix_loc, 1, GL_FALSE, matrix); glUniform1i(text_sampler_loc, 1); char text_buffer[1024]; float ts = 12; float tx = ts / 2; float ty = height - ts; snprintf( text_buffer, 1024, "%d, %d, %.2f, %.2f, %.2f [%d, %d]", p, q, x, y, z, player_count, chunk_count); print( text_position_loc, text_uv_loc, tx, ty, ts, text_buffer); for (int i = 0; i < MAX_MESSAGES; i++) { int index = (message_index + i) % MAX_MESSAGES; if (strlen(messages[index])) { ty -= ts * 2; print( text_position_loc, text_uv_loc, tx, ty, ts, messages[index]); } } if (typing) { ty -= ts * 2; snprintf(text_buffer, 1024, "> %s", typing_buffer); print( text_position_loc, text_uv_loc, tx, ty, ts, text_buffer); } // RENDER 3-D HUD PARTS // set_matrix_item(matrix, width, height); // render selected item if (block_type != previous_block_type) { previous_block_type = block_type; if (is_plant(block_type)) { gen_plant_buffers( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } else { gen_cube_buffers( &item_position_buffer, &item_normal_buffer, &item_uv_buffer, 0, 0, 0, 0.5, block_type); } } glUseProgram(block_program); glUniformMatrix4fv(matrix_loc, 1, GL_FALSE, matrix); glUniform3f(camera_loc, 0, 0, 5); glUniform1i(sampler_loc, 0); glUniform1f(timer_loc, glfwGetTime()); if (is_plant(block_type)) { draw_plant( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); } else { draw_cube( item_position_buffer, item_normal_buffer, item_uv_buffer, position_loc, normal_loc, uv_loc); } // swap buffers glfwSwapBuffers(window); glfwPollEvents(); } client_stop(); db_save_state(x, y, z, rx, ry); db_close(); glfwTerminate(); return 0; }
int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC)); init_demux_stream(mpctx, STREAM_VIDEO); sh_video_t *sh_video = mpctx->sh_video; if (!sh_video) goto no_video; MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n", mpctx->sh_video->format, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, mpctx->sh_video->fps); if (opts->force_fps) mpctx->sh_video->fps = opts->force_fps; update_fps(mpctx); if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) { MP_ERR(mpctx, "FPS not specified in the " "header or invalid, use the -fps option.\n"); } double ar = -1.0; //================== Init VIDEO (codec & libvo) ========================== if (!opts->fixed_vo || !(mpctx->initialized_flags & INITIALIZED_VO)) { mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input, mpctx->encode_lavc_ctx); if (!mpctx->video_out) { MP_FATAL(mpctx, "Error opening/initializing " "the selected video_out (-vo) device.\n"); goto err_out; } mpctx->mouse_cursor_visible = true; mpctx->initialized_flags |= INITIALIZED_VO; } // dynamic allocation only to make stheader.h lighter talloc_free(sh_video->hwdec_info); sh_video->hwdec_info = talloc_zero(sh_video, struct mp_hwdec_info); vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, sh_video->hwdec_info); update_window_title(mpctx, true); if (stream_control(mpctx->sh_video->gsh->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) mpctx->sh_video->stream_aspect = ar; recreate_video_filters(mpctx); init_best_video_codec(sh_video, opts->video_decoders); if (!sh_video->initialized) goto err_out; mpctx->initialized_flags |= INITIALIZED_VCODEC; bool saver_state = opts->pause || !opts->stop_screensaver; vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER : VOCTRL_KILL_SCREENSAVER, NULL); vo_control(mpctx->video_out, mpctx->paused ? VOCTRL_PAUSE : VOCTRL_RESUME, NULL); sh_video->last_pts = MP_NOPTS_VALUE; sh_video->num_buffered_pts = 0; sh_video->next_frame_time = 0; mpctx->last_vf_reconfig_count = 0; mpctx->restart_playback = true; mpctx->sync_audio_to_video = !sh_video->gsh->attached_picture; mpctx->delay = 0; mpctx->vo_pts_history_seek_ts++; vo_seek_reset(mpctx->video_out); reset_subtitles(mpctx); return 1; err_out: no_video: uninit_player(mpctx, INITIALIZED_VCODEC | (opts->force_vo ? 0 : INITIALIZED_VO)); cleanup_demux_stream(mpctx, STREAM_VIDEO); mpctx->current_track[STREAM_VIDEO] = NULL; handle_force_window(mpctx, true); MP_INFO(mpctx, "Video: no video\n"); return 0; }
int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC)); assert(!mpctx->d_video); struct track *track = mpctx->current_track[0][STREAM_VIDEO]; struct sh_stream *sh = init_demux_stream(mpctx, track); if (!sh) goto no_video; MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n", sh->format, sh->video->disp_w, sh->video->disp_h, sh->video->fps); double ar = -1.0; //================== Init VIDEO (codec & libvo) ========================== if (!opts->fixed_vo || !(mpctx->initialized_flags & INITIALIZED_VO)) { mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input, mpctx->encode_lavc_ctx); if (!mpctx->video_out) { MP_FATAL(mpctx, "Error opening/initializing " "the selected video_out (-vo) device.\n"); goto err_out; } mpctx->mouse_cursor_visible = true; mpctx->initialized_flags |= INITIALIZED_VO; } update_window_title(mpctx, true); struct dec_video *d_video = talloc_zero(NULL, struct dec_video); mpctx->d_video = d_video; d_video->global = mpctx->global; d_video->log = mp_log_new(d_video, mpctx->log, "!vd"); d_video->opts = mpctx->opts; d_video->header = sh; d_video->fps = sh->video->fps; d_video->vo = mpctx->video_out; mpctx->initialized_flags |= INITIALIZED_VCODEC; vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info); if (stream_control(sh->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) d_video->stream_aspect = ar; recreate_video_filters(mpctx); if (!video_init_best_codec(d_video, opts->video_decoders)) goto err_out; bool saver_state = opts->pause || !opts->stop_screensaver; vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER : VOCTRL_KILL_SCREENSAVER, NULL); vo_control(mpctx->video_out, mpctx->paused ? VOCTRL_PAUSE : VOCTRL_RESUME, NULL); mpctx->restart_playback = true; mpctx->sync_audio_to_video = !sh->attached_picture; mpctx->delay = 0; mpctx->video_next_pts = MP_NOPTS_VALUE; mpctx->playing_last_frame = false; mpctx->last_frame_duration = 0; mpctx->vo_pts_history_seek_ts++; vo_seek_reset(mpctx->video_out); reset_subtitles(mpctx, 0); reset_subtitles(mpctx, 1); if (opts->force_fps) { d_video->fps = opts->force_fps; MP_INFO(mpctx, "FPS forced to be %5.3f.\n", d_video->fps); } if (!sh->video->fps && !opts->force_fps && !opts->correct_pts) { MP_ERR(mpctx, "FPS not specified in the " "header or invalid, use the -fps option.\n"); } update_fps(mpctx); return 1; err_out: no_video: uninit_player(mpctx, INITIALIZED_VCODEC | (opts->force_vo ? 0 : INITIALIZED_VO)); mp_deselect_track(mpctx, track); handle_force_window(mpctx, true); MP_INFO(mpctx, "Video: no video\n"); return 0; }
int Game::on_frame(void) { // Handle OS events float delta_x = 0.0f; float delta_y = 0.0f; const SystemEvent* event = app_pop_event(); while (event) { switch(event->type) { case kEventResize: _render->resize(event->data.resize.width, event->data.resize.height); printf("W: %d H: %d\n", event->data.resize.width, event->data.resize.height); break; case kEventKeyDown: if(event->data.key == KEY_ESCAPE) return 1; if(event->data.key == KEY_F1) _render->toggle_debug_graphics(); if(event->data.key == KEY_F2) _render->toggle_deferred(); break; case kEventMouseDown: if(event->data.mouse.button == MOUSE_LEFT) app_lock_and_hide_cursor(); debug_output("Mouse: %.0f %.0f\n", event->data.mouse.x, event->data.mouse.y); break; case kEventMouseUp: if(event->data.mouse.button == MOUSE_LEFT) app_unlock_and_show_cursor(); break; case kEventMouseMove: delta_x += event->data.mouse.x; delta_y += event->data.mouse.y; break; default: break; } event = app_pop_event(); } // Beginning of frame stuff _delta_time = (float)timer_delta_time(&_timer); update_fps(&_fps, _delta_time); float3 xaxis = {1.0f, 0.0f, 0.0f}; quaternion q = quaternionFromAxisAngle(&xaxis, _delta_time*0.15f); Transform t = _world.entity(_sun_id)->transform(); t.orientation = quaternionMultiply(&q, &t.orientation); //_world.entity(_sun_id)->set_transform(t); if(quaternionGetZAxis(&t.orientation).y > 0.0f) { //_world.entity(_sun_id)->deactivate_component(kLightComponent); } else { //_world.entity(_sun_id)->activate_component(kLightComponent); } // Frame _control_camera(delta_x, delta_y); float4x4 view = TransformGetMatrix(&_camera); _render->set_3d_view_matrix(view); _world.update(_delta_time); _render->render(); // End of frame stuff if(++_frame_count % 16 == 0) { debug_output("%.2fms (%.0f FPS)\n", get_frametime(&_fps), get_fps(&_fps)); } return 0; }
int reinit_video_chain(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; assert(!mpctx->d_video); struct track *track = mpctx->current_track[0][STREAM_VIDEO]; struct sh_stream *sh = track ? track->stream : NULL; if (!sh) goto no_video; MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n", sh->format, sh->video->disp_w, sh->video->disp_h, sh->video->fps); //================== Init VIDEO (codec & libvo) ========================== if (!opts->fixed_vo || !mpctx->video_out) { mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input, mpctx->osd, mpctx->encode_lavc_ctx); if (!mpctx->video_out) { MP_FATAL(mpctx, "Error opening/initializing " "the selected video_out (-vo) device.\n"); mpctx->error_playing = MPV_ERROR_VO_INIT_FAILED; goto err_out; } mpctx->mouse_cursor_visible = true; } update_window_title(mpctx, true); struct dec_video *d_video = talloc_zero(NULL, struct dec_video); mpctx->d_video = d_video; d_video->global = mpctx->global; d_video->log = mp_log_new(d_video, mpctx->log, "!vd"); d_video->opts = mpctx->opts; d_video->header = sh; d_video->fps = sh->video->fps; d_video->vo = mpctx->video_out; vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, &d_video->hwdec_info); recreate_video_filters(mpctx); if (!video_init_best_codec(d_video, opts->video_decoders)) goto err_out; bool saver_state = opts->pause || !opts->stop_screensaver; vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER : VOCTRL_KILL_SCREENSAVER, NULL); vo_set_paused(mpctx->video_out, mpctx->paused); mpctx->sync_audio_to_video = !sh->attached_picture; mpctx->vo_pts_history_seek_ts++; // If we switch on video again, ensure audio position matches up. if (mpctx->d_audio) mpctx->audio_status = STATUS_SYNCING; reset_video_state(mpctx); reset_subtitle_state(mpctx); if (opts->force_fps) { d_video->fps = opts->force_fps; MP_INFO(mpctx, "FPS forced to be %5.3f.\n", d_video->fps); } if (!sh->video->fps && !opts->force_fps && !opts->correct_pts) { MP_ERR(mpctx, "FPS not specified in the " "header or invalid, use the -fps option.\n"); } update_fps(mpctx); return 1; err_out: no_video: uninit_video_chain(mpctx); if (track) error_on_track(mpctx, track); handle_force_window(mpctx, true); return 0; }
/** Preview worker thread. * Ensures camera preview is supplied with buffers and sends preview frames to GL. * @param arg Pointer to state. * @return NULL always. */ static void *preview_worker(void *arg) { RASPITEX_STATE* state = arg; MMAL_PORT_T *preview_port = state->preview_port; MMAL_BUFFER_HEADER_T *buf; MMAL_STATUS_T st; int rc; vcos_log_trace("%s: port %p", VCOS_FUNCTION, preview_port); rc = state->ops.create_native_window(state); if (rc != 0) goto end; else vcos_log_info("%s: create_native_window=%d", VCOS_FUNCTION, rc); rc = state->ops.gl_init(state); if (rc != 0) goto end; else vcos_log_info("%s: gl_init=%d", VCOS_FUNCTION, rc); // ------------------------------------------------------------------------------------- /* Send empty buffers to camera preview port */ while ((buf = mmal_queue_get(state->preview_pool->queue)) != NULL) { st = mmal_port_send_buffer(preview_port, buf); if (st != MMAL_SUCCESS) { vcos_log_error("Failed to send buffer to %s", preview_port->name); } } // ------------------------------------------------------------------------------------- //S_COPY_FRAME_DATA rec_frame_data; while (state->preview_stop == 0) { /* Send empty buffers to camera preview port */ /*while ((buf = mmal_queue_get(state->preview_pool->queue)) != NULL) { st = mmal_port_send_buffer(preview_port, buf); if (st != MMAL_SUCCESS) { vcos_log_info("Failed to send buffer to %s", preview_port->name); } }*/ //int nLen = mmal_queue_length( state->preview_queue ); //vcos_log_info("SHIT!!! - LEN=%d", nLen ); //while ((buf = mmal_queue_get(state->preview_pool->queue)) != NULL) //if (buf) int nExistBufferInQueue = 0; while ((buf = mmal_queue_get(state->preview_queue)) != NULL) { nExistBufferInQueue = 1; //vcos_log_info("DATA READ!!!" ); rc = raspitex_draw(state, buf); // block complete chain!!! if (rc != 0) { vcos_log_info("%s: Error drawing frame. Stopping.", VCOS_FUNCTION); state->preview_stop = 1; } st = mmal_port_send_buffer(preview_port, buf); if (st != MMAL_SUCCESS) { vcos_log_info("Failed to send buffer to %s", preview_port->name); } // ------------------------------------------------------------------------------------- //vcos_sleep( 100 ); // now is main chain already free - now can block this thread // rc = state->ops.safe_redraw(state); if (rc != 0) { vcos_log_info("%s: Error drawing frame. Stopping.", VCOS_FUNCTION); state->preview_stop = 1; } else { update_fps( ); } // ------------------------------------------------------------------------------------- break; } if (!nExistBufferInQueue) // slow down while cycle otherwise 100% CPU { vcos_sleep( 10 ); } /*if (preview_process_returned_bufs(state) != 0) { vcos_log_info("SHIT!!!" ); } else { vcos_log_info("DATA READ!!!" ); }*/ /*if (begin_read_frame( state->preview_pool->queue, &rec_frame_data )) { vcos_log_info("DATA READ!!!" ); //if (state->m_nGetData) { rc = raspitex_draw(state, buf); // block complete chain!!! if (rc != 0) { vcos_log_info("%s: Error drawing frame. Stopping.", VCOS_FUNCTION); state->preview_stop = 1; } } end_read_frame( preview_port, state->preview_pool, &rec_frame_data ); } else { vcos_log_info("SHIT!!!" ); }*/ //vcos_sleep( 500 ); /* Process returned buffers */ /*if (preview_process_returned_bufs(state) != 0) { vcos_log_error("Preview error. Exiting."); state->preview_stop = 1; } else { }*/ } // ------------------------------------------------------------------------------------- end: /* Make sure all buffers are returned on exit */ while ((buf = mmal_queue_get(state->preview_queue)) != NULL) mmal_buffer_header_release(buf); /* Tear down GL */ state->ops.gl_term(state); vcos_log_trace("Exiting preview worker"); return NULL; }
/** * Draws the next preview frame. If a new preview buffer is available then the * preview texture is updated first. * * @param state RASPITEX STATE * @param video_frame MMAL buffer header containing the opaque buffer handle. * @return Zero if successful. */ static int raspitex_draw(RASPITEX_STATE *state, MMAL_BUFFER_HEADER_T *buf) { int rc = 0; /* If buf is non-NULL then there is a new viewfinder frame available * from the camera so the texture should be updated. * * Although it's possible to have multiple textures mapped to different * viewfinder frames this can consume a lot of GPU memory for high-resolution * viewfinders. */ if (buf) { /* Update the texture to the new viewfinder image which should */ if (state->ops.update_texture) { rc = state->ops.update_texture(state, (EGLClientBuffer) buf->data); if (rc != 0) { vcos_log_error("%s: Failed to update RGBX texture %d", VCOS_FUNCTION, rc); goto end; } } if (state->ops.update_y_texture) { rc = state->ops.update_y_texture(state, (EGLClientBuffer) buf->data); if (rc != 0) { vcos_log_error("%s: Failed to update Y' plane texture %d", VCOS_FUNCTION, rc); goto end; } } if (state->ops.update_u_texture) { rc = state->ops.update_u_texture(state, (EGLClientBuffer) buf->data); if (rc != 0) { vcos_log_error("%s: Failed to update U plane texture %d", VCOS_FUNCTION, rc); goto end; } } if (state->ops.update_v_texture) { rc = state->ops.update_v_texture(state, (EGLClientBuffer) buf->data); if (rc != 0) { vcos_log_error("%s: Failed to update V texture %d", VCOS_FUNCTION, rc); goto end; } } /* Now return the PREVIOUS MMAL buffer header back to the camera preview. */ if (state->preview_buf) mmal_buffer_header_release(state->preview_buf); state->preview_buf = buf; } /* Do the drawing */ if (check_egl_image(state) == 0) { rc = state->ops.update_model(state); if (rc != 0) goto end; rc = state->ops.redraw(state); if (rc != 0) goto end; raspitex_do_capture(state); eglSwapBuffers(state->display, state->surface); update_fps(); } else { // vcos_log_trace("%s: No preview image", VCOS_FUNCTION); } end: return rc; }