2015-12-28 65 views
0

出於測試目的,我真的很想能夠手動控制我的GTK3應用程序的幀刷新率。慢下來很容易,我只是睡在渲染功能。但是,我可以實現的最大幀速率是我的顯示器60Hz的刷新率。手動控制GTK小部件重繪打勾速率

我發現,我可以添加一個不封頂更新插槽插使用gdk_threads_add_idle主循環,但即使我稱之爲gtk_gl_area_queue_render這個函數實際渲染功能只能運行在我的顯示器的刷新率內。

有沒有辦法強制重新渲染是「立即」的要求?我試過手動調用渲染槽,這會導致重新渲染函數立即被調用,但它根本不會更新屏幕。

void update_auto(gpointer user_data) 
{ 
    // ... do some update stuff 
    // somehow get the appropriate GtkGLArea from user_data 
    GtkGLArea* area = get_area(user_data); 
    gtk_gl_area_queue_render(area); 
    // capped at 60Hz 
} 

void update_manual(gpointer user_data) 
{ 
    // ... do some update stuff 
    // somehow get the appropriate GtkGLArea from user_data 
    GtkGLArea* area = get_area(user_data); 
    gtk_gl_area_make_current(area); 
    render(area,gtk_gl_area_get_context(area), user_data); 
    // even though render was called, screen never updates 
} 

void render(GtkGLArea* area, GdkGLContext* context, gpointer user_data) 
{ 
    // ... render 
} 

void setup_widget() 
{ 
    // ... some init stuff 
    // only one of these is used at a time 
#if TEST_FLAG == 0 
    gdk_threads_add_idle(update_manual, user_data); 
#elif TEST_FLAG == 1 
    gdk_threads_add_idle(update_auto, user_data); 
#elif TEST_FLAG == 2 
    gtk_widget_add_tick_callback((GtkWidget*) area, update_auto, user_data, NULL); 
#else 
    gtk_widget_add_tick_callback((GtkWidget*) area, update_manual, user_data, NULL); 
#endif 
} 
+0

渲染速度比顯示器的刷新速度還要快嗎? –

+0

我現在的一個原因是性能測試。我感興趣的是渲染循環中的各種代碼更改如何影響性能,我寧願不必使用足夠大的場景來顯着減慢渲染循環。我也想調試一些不規則的框架口吃問題,在較大的場景發生。 – helloworld922

+0

也許渲染引擎*不會更快地刷新。我不知道這是否適用於LED/LCD顯示器,但是舊的CRT刷新是在反激期完成的,以創建平滑的幀過渡。 –

回答

0

我發現一個黑客迫使立即重新抽籤:

GtkGLArea擴展GtkWidget類,這樣我就可以使用繪圖功能立即重新繪製。

// inside update 
// get the proper clipping so we don't draw over other widgets 
GtkAllocation reg; 
gtk_widget_get_allocation((GtkWidget*)area, &reg); 
cairo_region_t *creg = cairo_region_create_rectangle(&reg); 
cairo_t *cr = gdk_cairo_create(gtk_widget_get_window((GtkWidget*)area)); 
gdk_cairo_region(cr, creg); 
cairo_clip(cr); 

gtk_widget_draw((GtkWidget*)area, cr); 
cairo_destroy(cr); 
cairo_region_destroy(creg); 

然後我就可以使用,如果需要,gdk_threads_add_idle函數會很樂意儘可能快地調用更新功能。

即使沒有使用gdk_threads_add_idle,我已經注意到即使使用這種方法與gtk_widget_add_tick_callback也具有明顯更一致的幀速率。在我注意到幀率在15/30/60 fps之間零星跳躍之前,似乎表明它缺少一兩個重繪更新週期。這個問題現在已經完全消失了,我得到了一個近乎恆定的N fps,其中N被限制在60,適用於小場景。

我還沒有遇到任何問題,但這樣做,但這似乎與Windows不止包含一個單一的GtkWidget。我沒有嘗試重疊的小部件,但我懷疑這裏唯一的解決方案是也重繪任何重疊的小部件。