首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何快速重绘图像缓冲区

如何快速重绘图像缓冲区
EN

Stack Overflow用户
提问于 2013-04-03 04:42:48
回答 3查看 2.6K关注 0票数 2

我正在开发某种音频应用程序,其中我需要显示一些图形。想一想:高帧率的实时振荡器图像。

所有我需要的是在一个高帧率显示一些图形缓冲区。最好大于60fps,不需要花费太多时间。我现在实现它的方式太慢了。我只能得到分辨率为800x800像素的10fps。绘图不是问题所在,Xorg一直都在使用。

我现在使用的方法是创建一个cairo_image_surface,然后在需要更改的像素处操作cairo_images_surface中的数据(这是相当快的)

因为我正在编写类似于示波器的程序,所以我不需要一直重新绘制所有像素。所以画东西并不是很慢。

我认为最慢的部分是我需要调用cairo_set_source_surface()来实际显示一些东西。

代码中最重要部分的摘要。每当有新的音频样本可供显示时,就会调用on_plot_event

代码语言:javascript
复制
static gboolean on_plot_event(GtkWidget *widget,cairo_t *cr,gpointer user_data){
    cairo_set_source_surface(cr,crsurfplot,0,0);
    cairo_paint(cr);
    return FALSE;
}

int doplot(jack_default_audio_sample_t *in,jack_nframes_t nframes){
    cairo_surface_flush(crsurfplot);
    char *p;
    unsigned char *pixstart;
    pixstart = plotdata;
 //drawing stuff, manipulate pixels at pixstart
    cairo_surface_mark_dirty(crsurfplot);
    if(drawcount%10 ==0){
    gdk_threads_enter();
    gtk_widget_queue_draw(window);
    gdk_threads_leave();
    }
}


int main(int argc,char *argv[]){
    gdk_threads_init();
    gtk_init (&argc, &argv);
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    plotstride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24,plotwidth);
    plotdata = malloc (16000000);
    crsurfplot = cairo_image_surface_create_for_data    (plotdata,CAIRO_FORMAT_RGB24,plotwidth,plotheight,plotstride);
    plotdata = cairo_image_surface_get_data(crsurfplot);    

    plot = gtk_drawing_area_new();  
    gtk_container_add(GTK_CONTAINER(window),plot);

    g_signal_connect(G_OBJECT(plot),"draw",G_CALLBACK(on_plot_event),NULL);
    g_signal_connect(G_OBJECT(plot),"configure-event",G_CALLBACK(on_confev),NULL);

    gtk_widget_show_all (window);
    gtk_widget_show (window2);
    printf("test\n");

    crplot=gdk_cairo_create(gtk_widget_get_window(plot));
    cairo_set_source_surface(crplot,crsurfplot,0,0);

    gtk_main ();

    jack_client_close(client);
    return 0;

}

用Cairo创建我想要的东西是不可能的吗?我应该使用openGL或类似的东西来代替吗?或者我只是做错了什么?

编辑:添加了到我丑陋的程序的链接。http://ubuntuone.com/4dphKneXOgQPTR8fZydKpo

EN

回答 3

Stack Overflow用户

发布于 2013-04-03 04:52:24

我现在使用的方法是创建一个cairo_image_surface,然后在需要更改的像素处操作cairo_images_surface中的数据(这是相当快的)

因为我正在编写类似于示波器的程序,所以我不需要一直重新绘制所有像素。所以画东西并不是很慢。

我不同意在我遇到的99.9%的图形应用程序(更大的显示器和帧速率)中,用所有复杂的精灵、条形图等在背景中重新绘制图片比一次翻转要快得多。尽管这听起来有悖于直觉,但我建议您应该尝试一下。

开罗应该能处理好你想要的。

票数 1
EN

Stack Overflow用户

发布于 2013-04-03 23:20:08

使用cairo_surface_create_similar_image()可能比创建新的图像表面更快。这允许cairo使用共享内存,这将大大加快图像的上传速度。

(当然,不调用cairo_set_source_surface()会更快:在这种情况下,cairo不必上传图像表面,而只需告诉X11服务器“用黑色填充所有内容”)

另外,为什么要这样做呢?只需使用cairo_image_surface_create()而不是调用malloc()和...create_for_data()。

代码语言:javascript
复制
plotdata = malloc (16000000);
crsurfplot = cairo_image_surface_create_for_data    (plotdata,CAIRO_FORMAT_RGB24,plotwidth,plotheight,plotstride);
plotdata = cairo_image_surface_get_data(crsurfplot);
票数 0
EN

Stack Overflow用户

发布于 2013-04-04 19:29:49

关闭绘图区域的GtkWidget双缓冲系统可能会有所帮助。

代码语言:javascript
复制
gtk_widget_set_double_buffered (GTK_WIDGET (plot), FALSE);

这将阻止Gtk在您的图像被绘制到窗口之前引入一个中间步骤。

gtk_widget_set_double_buffered documentation

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15773965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档