unsigned long easeout_to_frame(GCContext *context, unsigned long destination_frame, int seconds) { GCVDPAUContext *vdpau = &context->VDPAU_context; Movie *movie = context->movie_context; unsigned long frames = 0; unsigned long sf = movie->frame_offset; long df = 0; int i = 0; // GTimer *timer = g_timer_new(); df = destination_frame - sf; frames = seconds * FPS; // g_timer_start(timer); for (i=0; i < frames; i++) { float c = (float)df * (powf((float)i / (float)frames - 1, 3) + 1); movie->frame_offset = sf + c; movie->fract_frame_count = movie->frame_offset; movie->pre_load_surface = display_surface(context, movie->pre_load_surface); load_frame(context, movie->frame_offset, movie->pre_load_surface); if (movie->new_frame) break; } // g_message("Ease done in %f seconds, at frame %lu", g_timer_elapsed(timer, NULL), movie->frame_offset); // g_timer_destroy(timer); return movie->frame_offset; }
/** Display gallium surface in X window */ static void flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *psurf, void *context_private) { struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private; display_surface(pws, psurf, xsurf); }
gpointer display_thread(gpointer data) { GCContext *context = (GCContext*)data; GCConfig *config = context->config; GCVDPAUContext *vdpau = &context->VDPAU_context; Movie *movie = context->movie_context; gint64 timeout = 0; int current_direction = DIRECTION_FORWARD; if (!context) g_error("Missing context\n"); movie->pre_load_surface = vdpau->surface_queue.next; load_frame(context, movie->frame_offset, movie->pre_load_surface); do { movie->pre_load_surface = display_surface(context, movie->pre_load_surface); timeout = g_get_monotonic_time() + config->seconds_per_frame * G_TIME_SPAN_SECOND; g_mutex_lock(&movie->tick_lock); if (movie->ease_to) { movie->new_frame = FALSE; easeout_to_frame(context, movie->ease_to_frame, config->easing_factor); movie->ease_to = FALSE; } while (!movie->new_frame && !movie->ease_to && !context->exit) { if (!g_cond_wait_until(&movie->tick_cond, &movie->tick_lock, timeout)) { movie->frame_offset++; movie->fract_frame_count++; movie->play_direction = DIRECTION_FORWARD; movie->new_frame = TRUE; //g_message("tick: %lu", movie->frame_offset); break; } } movie->new_frame = FALSE; g_mutex_unlock(&movie->tick_lock); load_frame(context, movie->frame_offset, movie->pre_load_surface); } while (!context->exit); munmap(movie->planes, config->movie_size); close(movie->fd_movie); vdpau_exit(context); x11_exit(context); g_main_loop_quit(context->g_main_loop); return NULL; }
static EGLBoolean xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) { /* error checking step: */ if (!_eglSwapBuffers(drv, dpy, draw)) return EGL_FALSE; { struct xlib_egl_surface *xsurf = lookup_surface(draw); struct pipe_winsys *pws = xsurf->winsys; struct pipe_surface *psurf = st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT); st_notify_swapbuffers(xsurf->Framebuffer); display_surface(pws, psurf, xsurf); check_and_update_buffer_size(xsurf); } return EGL_TRUE; }