FrameControl FrameControl_Create( void ) { FrameControl ctx; ctx = NEW( FrameControlRec, 1 ); ctx->temp_fps = 0; ctx->current_fps = 0; ctx->pause_time = 0; ctx->one_frame_remain_time = 10; ctx->prev_frame_start_time = LCUI_GetTime(); ctx->prev_fps_update_time = LCUI_GetTime(); LCUICond_Init( &ctx->cond ); LCUIMutex_Init( &ctx->mutex ); return ctx; }
StepTimer StepTimer_Create( void ) { StepTimer timer; timer = NEW( StepTimerRec, 1 ); timer->temp_fps = 0; timer->current_fps = 0; timer->pause_time = 0; timer->one_frame_remain_time = 10; timer->prev_frame_start_time = LCUI_GetTime(); timer->prev_fps_update_time = LCUI_GetTime(); LCUICond_Init( &timer->cond ); LCUIMutex_Init( &timer->mutex ); return timer; }
void FrameControl_Remain( FrameControl ctx ) { int64_t current_time; unsigned int n_ms, lost_ms; if( ctx->state == STATE_QUIT ) { return; } lost_ms = 0; current_time = LCUI_GetTime(); LCUIMutex_Lock( &ctx->mutex ); n_ms = (unsigned int)(current_time - ctx->prev_frame_start_time); if( n_ms > ctx->one_frame_remain_time ) { goto normal_exit; } n_ms = ctx->one_frame_remain_time - n_ms; if( n_ms < 1 ) { goto normal_exit; } /* 睡眠一段时间 */ while( lost_ms < n_ms && ctx->state == STATE_RUN ) { LCUICond_TimedWait( &ctx->cond, &ctx->mutex, n_ms - lost_ms ); lost_ms = (unsigned int)LCUI_GetTimeDelta( current_time ); } /* 睡眠结束后,如果当前状态为 PAUSE,则说明睡眠是因为要暂停而终止的 */ if( ctx->state == STATE_PAUSE ) { current_time = LCUI_GetTime(); /* 等待状态改为“继续” */ while( ctx->state == STATE_PAUSE ) { LCUICond_Wait( &ctx->cond, &ctx->mutex ); } lost_ms = (unsigned int)LCUI_GetTimeDelta( current_time ); ctx->pause_time = lost_ms; ctx->prev_frame_start_time += lost_ms; LCUIMutex_Unlock( &ctx->mutex ); return; } normal_exit:; current_time = LCUI_GetTime(); if( current_time - ctx->prev_fps_update_time >= 1000 ) { ctx->current_fps = ctx->temp_fps; ctx->prev_fps_update_time = current_time; ctx->temp_fps = 0; } ctx->prev_frame_start_time = current_time; ++ctx->temp_fps; LCUIMutex_Unlock( &ctx->mutex ); }
int64_t LCUI_GetTimeDelta(int64_t start) { int64_t now = LCUI_GetTime(); if (now < start) { return (TIME_WRAP_VALUE - start) + now; } return now - start; }
void LCUIWidget_StepTask( void ) { LinkedListNode *node; self.is_timeout = FALSE; self.timeout = LCUI_GetTime() + 20; Widget_UpdateEx( LCUIWidget_GetRoot(), TRUE ); /* 删除无用部件 */ node = self.trash.head.next; while( node ) { LinkedListNode *next = node->next; LinkedList_Unlink( &self.trash, node ); Widget_ExecDestroy( node->data ); node = next; } }
int Widget_UpdateEx( LCUI_Widget w, LCUI_BOOL has_timeout ) { int i; LCUI_BOOL *buffer; LinkedListNode *node, *next; /* 如果该部件没有任务需要处理、或者被其它线程占用 */ if( !w->task.for_self || LCUIMutex_TryLock( &w->mutex ) != 0 ) { goto proc_children_task; } w->task.for_self = FALSE; buffer = w->task.buffer; /* 如果有用户自定义任务 */ if( buffer[WTT_USER] ) { LCUI_WidgetClass *wc; wc = LCUIWidget_GetClass( w->type ); wc ? wc->task_handler( w ) : FALSE; } for( i = 0; i < WTT_USER; ++i ) { if( buffer[i] ) { buffer[i] = FALSE; if( self.handlers[i] ) { self.handlers[i]( w ); } } else { buffer[i] = FALSE; } } LCUIMutex_Unlock( &w->mutex ); /* 如果部件还处于未准备完毕的状态 */ if( w->state < WSTATE_READY ) { w->state |= WSTATE_UPDATED; /* 如果部件已经准备完毕则触发 ready 事件 */ if( w->state == WSTATE_READY ) { LCUI_WidgetEventRec e; e.type = WET_READY; e.cancel_bubble = TRUE; Widget_TriggerEvent( w, &e, NULL ); w->state = WSTATE_NORMAL; } } self.count += 1; proc_children_task: if( !w->task.for_children ) { return w->task.for_self; } /* 如果子级部件中有待处理的部件,则递归进去 */ w->task.for_children = FALSE; node = w->children.head.next; while( node ) { LCUI_Widget child = node->data; /* 如果当前部件有销毁任务,结点空间会连同部件一起被 * 释放,为避免因访问非法空间而出现异常,预先保存下 * 个结点。 */ next = node->next; /* 如果该级部件的任务需要留到下次再处理 */ if( Widget_UpdateEx( child, has_timeout ) ) { w->task.for_children = TRUE; } if( has_timeout ) { if( !self.is_timeout && self.count >= 50 ) { self.count = 0; if( LCUI_GetTime() >= self.timeout ) { self.is_timeout = TRUE; } } if( self.is_timeout ) { break; } } node = next; } return w->task.for_self || w->task.for_children; }
void LCUIStats_Begin(LCUI_Stats stats) { memset(stats, 0, sizeof(LCUI_StatsRec)); stats->start_time = LCUI_GetTime(); stats->frame = LCUI_GetFrameCount(); }