2

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

我只需要以高帧率显示一些图形缓冲区。最好> 60fps而不需要太多时间。我现在实现它的方式太慢了。我只能以 800x800 像素的分辨率获得 10fps。绘图不是问题,Xorg 一直在占用。

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

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

我认为缓慢的部分是我需要打电话cairo_set_source_surface()来实际显示一些东西。

代码中最重要部分的摘要。on_plot_event每次有新的音频样本准备好显示时调用。

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;

}

用开罗不可能创造出我想要的东西吗?我应该改用openGL还是类似的东西?还是我只是做错了什么?

编辑:到目前为止添加了指向我丑陋程序的链接。 http://ubuntuone.com/4dphKneXOgQPTR8fZydKpo

4

3 回答 3

1

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

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

在我遇到的 99.9% 的图形应用程序(更大的显示器和帧速率)中,我不同意在背景中用所有复杂的精灵、条形等重绘图片,而不是一次全部翻转。即使这听起来违反直觉,我建议,你应该试试这个


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

于 2013-04-02T20:52:23.803 回答
0

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

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

另外,为什么会出现以下情况?只需使用 cairo_image_surface_create() 而不是调用 malloc() 和 ...create_for_data()。

plotdata = malloc (16000000);
crsurfplot = cairo_image_surface_create_for_data    (plotdata,CAIRO_FORMAT_RGB24,plotwidth,plotheight,plotstride);
plotdata = cairo_image_surface_get_data(crsurfplot);
于 2013-04-03T15:20:07.890 回答
0

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

gtk_widget_set_double_buffered (GTK_WIDGET (plot), FALSE);

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

gtk_widget_set_double_buffered 文档

于 2013-04-04T11:29:48.767 回答