📄 renderer.c
字号:
GF_Err e; if (!sr || !framebuffer) return GF_BAD_PARAM; gf_mx_p(sr->mx); e = sr->visual_renderer->GetScreenBuffer(sr->visual_renderer, framebuffer); if (e != GF_OK) gf_mx_v(sr->mx); return e;}GF_Err gf_sr_release_screen_buffer(GF_Renderer *sr, GF_VideoSurface *framebuffer){ GF_Err e; if (!sr || !framebuffer) return GF_BAD_PARAM; e = sr->visual_renderer->ReleaseScreenBuffer(sr->visual_renderer, framebuffer); gf_mx_v(sr->mx); return e;}Double gf_sr_get_fps(GF_Renderer *sr, Bool absoluteFPS){ Double fps; u32 ind, num, frames, run_time; /*start from last frame and get first frame time*/ ind = sr->current_frame; frames = 0; run_time = sr->frame_time[ind]; for (num=0; num<GF_SR_FPS_COMPUTE_SIZE; num++) { if (absoluteFPS) { run_time += sr->frame_time[ind]; } else { run_time += MAX(sr->frame_time[ind], sr->frame_duration); } frames++; if (frames==GF_SR_FPS_COMPUTE_SIZE) break; if (!ind) { ind = GF_SR_FPS_COMPUTE_SIZE; } else { ind--; } } if (!run_time) return (Double) sr->frame_rate; fps = 1000*frames; fps /= run_time; return fps;}void gf_sr_register_time_node(GF_Renderer *sr, GF_TimeNode *tn){ /*may happen with DEF/USE */ if (tn->is_registered) return; if (tn->needs_unregister) return; gf_list_add(sr->time_nodes, tn); tn->is_registered = 1;}void gf_sr_unregister_time_node(GF_Renderer *sr, GF_TimeNode *tn){ gf_list_del_item(sr->time_nodes, tn);}GF_Node *gf_sr_pick_node(GF_Renderer *sr, s32 X, s32 Y){ return NULL;}static u32 last_lclick_time = 0;static void SR_ForwardUserEvent(GF_Renderer *sr, GF_Event *ev){ GF_USER_SENDEVENT(sr->user, ev); if ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) { u32 now; GF_Event event; /*emulate doubleclick*/ now = gf_sys_clock(); if (now - last_lclick_time < 250) { event.type = GF_EVENT_MOUSEDOUBLECLICK; event.mouse.key_states = sr->key_states; event.mouse.x = ev->mouse.x; event.mouse.y = ev->mouse.y; GF_USER_SENDEVENT(sr->user, &event); } last_lclick_time = now; }}void gf_sr_simulation_tick(GF_Renderer *sr){ u32 in_time, end_time, i, count; /*lock renderer for the whole render cycle*/ gf_sr_lock(sr, 1); /*first thing to do, let the video output handle user event if it is not threaded*/ sr->video_out->ProcessEvent(sr->video_out, NULL); if (sr->freeze_display) { gf_sr_lock(sr, 0); gf_sleep(sr->frame_duration); return; } gf_sr_reconfig_task(sr); /* if there is no scene, we draw a black screen to flush the screen */ if (!sr->scene) { sr->visual_renderer->DrawScene(sr->visual_renderer); gf_sr_lock(sr, 0); gf_sleep(sr->frame_duration); return; }// GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[General] Time %f - Composing new frame #%d\n", gf_node_get_scene_time(gf_sg_get_root_node(sr->scene)), sr->frame_number)); in_time = gf_sys_clock(); if (sr->reset_graphics) sr->draw_next_frame = 1;#ifdef GF_SR_EVENT_QUEUE /*process pending user events*/ gf_mx_p(sr->ev_mx); while (gf_list_count(sr->events)) { GF_Event *ev = (GF_Event*)gf_list_get(sr->events, 0); gf_list_rem(sr->events, 0); if (!sr->visual_renderer->ExecuteEvent(sr->visual_renderer, ev)) { SR_ForwardUserEvent(sr, ev); } free(ev); } gf_mx_v(sr->ev_mx);#endif#if 0 if (sr->frame_number == 0 && sr->user->EventProc) { GF_Event evt; evt.type = GF_EVENT_UPDATE_RTI; evt.caption.caption = "UPDATE - Before first call to draw scene"; sr->user->EventProc(sr->user->opaque, &evt); }#endif /*execute all routes before updating textures, otherwise nodes inside composite texture may never see their dirty flag set*/ gf_sg_activate_routes(sr->scene);#ifndef GPAC_DISABLE_SVG#if SVG_FIXME { /* Experimental (Not SVG compliant system events (i.e. battery, cpu ...) triggered to the root node)*/ GF_Node *root = gf_sg_get_root_node(sr->scene); GF_DOM_Event evt; if (gf_dom_listener_count(root)) { u32 i, count; count = gf_dom_listener_count(root); for (i=0;i<count; i++) { SVG_SA_listenerElement *l = gf_dom_listener_get(root, i); if (l->event.type == GF_EVENT_CPU) { GF_SystemRTInfo sys_rti; if (gf_sys_get_rti(500, &sys_rti, GF_RTI_ALL_PROCESSES_TIMES)) { evt.type = GF_EVENT_CPU; evt.cpu_percentage = sys_rti.total_cpu_usage; //printf("%d\n",sys_rti.total_cpu_usage); gf_dom_event_fire(root, NULL, &evt); } } else if (l->event.type == GF_EVENT_BATTERY) { //&& l->observer.target == (SVG_SA_Element *)node) { evt.type = GF_EVENT_BATTERY; gf_sys_get_battery_state(&evt.onBattery, &evt.batteryState, &evt.batteryLevel); gf_dom_event_fire(root, NULL, &evt); } } } }#endif if (gf_smil_notify_timed_elements(sr->scene)) { sr->draw_next_frame = 1; }#if 0 for (i=0; i<gf_list_count(sr->secondary_scenes); i++) { if (gf_smil_notify_timed_elements(gf_list_get(sr->secondary_scenes, i))) { sr->draw_next_frame = 1; } }#endif#endif /*update all textures*/ count = gf_list_count(sr->textures); for (i=0; i<count; i++) { GF_TextureHandler *st = (GF_TextureHandler *)gf_list_get(sr->textures, i); /*signal graphics reset before updating*/ if (sr->reset_graphics && st->hwtx) sr->visual_renderer->TextureHWReset(st); st->update_texture_fcnt(st); } /*if invalidated, draw*/ if (sr->draw_next_frame) { /*video flush only*/ if (sr->draw_next_frame==2) { GF_Window rc; rc.x = rc.y = 0; rc.w = sr->width; rc.h = sr->height; sr->draw_next_frame = 0; sr->video_out->Flush(sr->video_out, &rc); } else { sr->draw_next_frame = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Redrawing scene\n")); sr->visual_renderer->DrawScene(sr->visual_renderer);#if 0 if (sr->frame_number == 0 && sr->user->EventProc) { GF_Event evt; evt.type = GF_EVENT_UPDATE_RTI; evt.caption.caption = "Before first call to draw scene"; sr->user->EventProc(sr->user->opaque, &evt); }#endif } sr->reset_graphics = 0; GF_LOG(GF_LOG_INFO, GF_LOG_RENDER, ("[Render] Scene drawn in %d ms\n", gf_sys_clock() - in_time)); if (sr->stress_mode) { sr->draw_next_frame = 1; sr->reset_graphics = 1; } } /*release all textures - we must release them to handle a same OD being used by several textures*/ count = gf_list_count(sr->textures); for (i=0; i<count; i++) { GF_TextureHandler *st = (GF_TextureHandler *)gf_list_get(sr->textures, i); gf_sr_texture_release_stream(st); } /*update all timed nodes */ for (i=0; i<gf_list_count(sr->time_nodes); i++) { GF_TimeNode *tn = (GF_TimeNode *)gf_list_get(sr->time_nodes, i); if (!tn->needs_unregister) tn->UpdateTimeNode(tn); if (tn->needs_unregister) { tn->is_registered = 0; tn->needs_unregister = 0; gf_list_rem(sr->time_nodes, i); i--; continue; } } end_time = gf_sys_clock() - in_time; gf_sr_lock(sr, 0); sr->current_frame = (sr->current_frame+1) % GF_SR_FPS_COMPUTE_SIZE; sr->frame_time[sr->current_frame] = end_time; sr->frame_number++;#if 0 if (sr->user->EventProc) { char legend[100]; GF_Event evt; evt.type = GF_EVENT_UPDATE_RTI; sprintf(legend, "After rendering of frame %d", sr->frame_number); evt.caption.caption = legend; sr->user->EventProc(sr->user->opaque, &evt); }#endif /*step mode on, pause and return*/ if (sr->step_mode) { sr->step_mode = 0; if (sr->term) gf_term_set_option(sr->term, GF_OPT_PLAY_STATE, GF_STATE_PAUSED); return; } /*not threaded, let the owner decide*/ if ((sr->user->init_flags & GF_TERM_NO_VISUAL_THREAD) || !sr->frame_duration) return; /*compute sleep time till next frame, otherwise we'll kill the CPU*/ i=1; while (i * sr->frame_duration < end_time) i++; in_time = i * sr->frame_duration - end_time; gf_sleep(in_time);}GF_Err gf_sr_get_viewpoint(GF_Renderer *sr, u32 viewpoint_idx, const char **outName, Bool *is_bound){ if (!sr->visual_renderer->GetViewpoint) return GF_NOT_SUPPORTED; return sr->visual_renderer->GetViewpoint(sr->visual_renderer, viewpoint_idx, outName, is_bound);}GF_Err gf_sr_set_viewpoint(GF_Renderer *sr, u32 viewpoint_idx, const char *viewpoint_name){ if (!sr->visual_renderer->SetViewpoint) return GF_NOT_SUPPORTED; return sr->visual_renderer->SetViewpoint(sr->visual_renderer, viewpoint_idx, viewpoint_name);}void gf_sr_render_inline(GF_Renderer *sr, GF_Node *inline_parent, GF_Node *inline_root, void *rs){ if (sr->visual_renderer->RenderInline) sr->visual_renderer->RenderInline(sr->visual_renderer, inline_parent, inline_root, rs);}static Bool SR_UserInputIntern(GF_Renderer *sr, GF_Event *event, Bool from_user){#ifdef GF_SR_EVENT_QUEUE GF_Event *ev;#else Bool ret;#endif if (sr->term && (sr->interaction_level & GF_INTERACT_INPUT_SENSOR) && (event->type<=GF_EVENT_MOUSEWHEEL)) gf_term_mouse_input(sr->term, &event->mouse); if (!sr->interaction_level || (sr->interaction_level==GF_INTERACT_INPUT_SENSOR) ) { if (!from_user) { GF_USER_SENDEVENT(sr->user, event); } return 0; }#ifdef GF_SR_EVENT_QUEUE switch (event->type) { case GF_EVENT_MOUSEMOVE: { u32 i, count; gf_mx_p(sr->ev_mx); count = gf_list_count(sr->events); for (i=0; i<count; i++) { ev = (GF_Event *)gf_list_get(sr->events, i); if (ev->type == GF_EVENT_MOUSEMOVE) { ev->mouse = event->mouse; gf_mx_v(sr->ev_mx); return 1; } } gf_mx_v(sr->ev_mx); } default: ev = (GF_Event *)malloc(sizeof(GF_Event)); ev->type = event->type; if (event->type<=GF_EVENT_MOUSEWHEEL) { ev->mouse = event->mouse; } else if (event->type==GF_EVENT_TEXTINPUT) { ev->character = event->character; } else { ev->key = event->key; } gf_mx_p(sr->ev_mx); gf_list_add(sr->events, ev); gf_mx_v(sr->ev_mx); break; } return 0;#else gf_sr_lock(sr, 1); ret = sr->visual_renderer->ExecuteEvent(sr->visual_renderer, event); gf_sr_lock(sr, 0); if (!ret && !from_user) { SR_ForwardUserEvent(sr, event); } return ret;#endif}static Bool gf_sr_on_event_ex(GF_Renderer *sr , GF_Event *event, Bool from_user){ /*not assigned yet*/ if (!sr || !sr->visual_renderer) return 0; /*we're reconfiguring the video output, cancel all messages*/ if (sr->msg_type & GF_SR_IN_RECONFIG) return 0; switch (event->type) { case GF_EVENT_REFRESH: if (!sr->draw_next_frame) sr->draw_next_frame = 2; break; case GF_EVENT_VIDEO_SETUP: gf_sr_reset_graphics(sr); break; case GF_EVENT_SIZE: /*resize message from plugin: if we own the output, resize*/ if (!sr->user->os_window_handler) { /*EXTRA CARE HERE: the caller (video output) is likely a different thread than the renderer one, and the renderer may be locked on the video output (flush or whatever)!! */ Bool lock_ok = gf_mx_try_lock(sr->mx); sr->new_width = event->size.width; sr->new_height = event->size.height; sr->msg_type |= GF_SR_CFG_SET_SIZE; if (lock_ok) gf_sr_lock(sr, 0); } /*otherwise let the user decide*/ else { GF_USER_SENDEVENT(sr->user, event); } break; case GF_EVENT_KEYDOWN: case GF_EVENT_KEYUP: switch (event->key.key_code) { case GF_KEY_SHIFT: if (event->type==GF_EVENT_KEYDOWN) { sr->key_states |= GF_KEY_MOD_SHIFT; } else { sr->key_states &= ~GF_KEY_MOD_SHIFT; } break; case GF_KEY_CONTROL: if (event->type==GF_EVENT_KEYDOWN) { sr->key_states |= GF_KEY_MOD_CTRL; } else { sr->key_states &= ~GF_KEY_MOD_CTRL; } break; case GF_KEY_ALT: if (event->type==GF_EVENT_KEYDOWN) { sr->key_states |= GF_KEY_MOD_ALT; } else { sr->key_states &= ~GF_KEY_MOD_ALT; } break; } event->key.flags |= sr->key_states; /*key sensor*/ if (sr->term && (sr->interaction_level & GF_INTERACT_INPUT_SENSOR) ) { gf_term_keyboard_input(sr->term, event->key.key_code, event->key.hw_code, (event->type==GF_EVENT_KEYUP) ? 1 : 0); } return SR_UserInputIntern(sr, event, from_user); case GF_EVENT_TEXTINPUT: if (sr->term && (sr->interaction_level & GF_INTERACT_INPUT_SENSOR) ) gf_term_string_input(sr->term , event->character.unicode_char); return SR_UserInputIntern(sr, event, from_user); /*switch fullscreen off!!!*/ case GF_EVENT_SHOWHIDE: gf_sr_set_option(sr, GF_OPT_FULLSCREEN, !sr->fullscreen); break; case GF_EVENT_SET_CAPTION: sr->video_out->ProcessEvent(sr->video_out, event); break; case GF_EVENT_MOUSEMOVE: event->mouse.button = 0; case GF_EVENT_MOUSEDOWN: case GF_EVENT_MOUSEUP: case GF_EVENT_MOUSEWHEEL: event->mouse.key_states = sr->key_states; return SR_UserInputIntern(sr, event, from_user); /*when we process events we don't forward them to the user*/ default: GF_USER_SENDEVENT(sr->user, event); break; } return 1;}static void gf_sr_on_event(void *cbck, GF_Event *event){ gf_sr_on_event_ex((GF_Renderer *)cbck, event, 0);}Bool gf_sr_user_event(GF_Renderer *sr, GF_Event *event){ switch (event->type) { case GF_EVENT_SHOWHIDE: case GF_EVENT_MOVE: case GF_EVENT_SET_CAPTION: sr->video_out->ProcessEvent(sr->video_out, event); return 0; default: return gf_sr_on_event_ex(sr, event, 1); }}void gf_sr_register_extra_graph(GF_Renderer *sr, GF_SceneGraph *extra_scene, Bool do_remove){ gf_sr_lock(sr, 1); if (do_remove) gf_list_del_item(sr->extra_scenes, extra_scene); else if (gf_list_find(sr->extra_scenes, extra_scene)<0) gf_list_add(sr->extra_scenes, extra_scene); gf_sr_lock(sr, 0);}u32 gf_sr_get_audio_delay(GF_Renderer *sr){ return sr->audio_renderer ? sr->audio_renderer->audio_delay : 0;}void *gf_sr_get_visual_renderer(GF_Renderer *sr){ return sr->visual_renderer;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -