GtkDrawingArea /开罗视觉故障

时间:2019-07-04 04:41:57

标签: animation gtk gtk3 cairo visual-glitch

我正在创建一个GTK + 3应用程序,该应用程序在GtkDrawingArea小部件中使用Cairo绘制动画。我遇到了视觉故障,例如下图所示。这些仅针对单个帧出现,每帧可能不存在,或者一个或多个。我正在寻求帮助来确定可能的问题。这是我的代码的详细信息:

在我的主要方法中,在开始gtk_main()循环之前,我挂了一个超时。

g_timeout_add(50, queue_draw, gtk_builder_get_object(builder, "window")); 

"window"是我的GtkWindow的ID。 queue_draw函数如下:

gboolean queue_draw(gpointer user_data)
{
  gtk_widget_queue_draw(GTK_WIDGET(user_data));
  return TRUE;
}

我认为我可以将GtkDrawingArea对象而不是整个GtkWindow传递给此函数,但是在那种情况下动画会消失。我也对此行为感兴趣,但这不是我的主要问题。

我的GtkDrawingArea的绘制信号被钩接到函数gboolean drawing_area_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)上。在这种方法中,我通过惰性画家的算法绘制3D条形图,每个条形由三个平行四边形组成,并且这些条形按z顺序绘制。

这不是我的计算机无法跟上帧渲染,以某种方式损坏帧缓冲区的问题。我将超时设置为1000ms,以捕获下面的图像。

我尚未致电gtk_widget_set_double_buffered()

我无法使用XMing作为X服务器在Linux的Windows子系统(WSL)上观察到该问题,这使我认为这可能是库问题或某些行为不明确的问题。

第一张图片是我的程序在正常运行期间的视觉故障。在第二篇中,我修改了代码,并将条形的高度固定为平缓的渐变。这样可以更好地了解问题,但仍然令人困惑。

image of glitch image of glitch

开发库软件包详细信息:

$ dpkg --list | egrep 'lib(cairo|gtk).*-dev'
ii  libcairo2-dev:amd64                                1.15.10-2ubuntu0.1                           amd64        Development files for the Cairo 2D graphics library
ii  libgtk-3-dev:amd64                                 3.22.30-1ubuntu3                             amd64        development files for the GTK+ library

图书馆元信息的详细信息:

$ pkg-config --modversion gtk+-3.0 glib-2.0 gdk-pixbuf-2.0 cairo
3.22.30
2.58.1
2.36.11
1.15.10

x11详细信息:

$ xdpyinfo | head -n 5
name of display:    :0
version number:    11.0
vendor string:    The X.Org Foundation
vendor release number:    12001000
X.Org version: 1.20.1

Linux详细信息(实际上是Zorin OS 15而非Ubuntu 18.04):

$ uname -a
Linux <hostname> 4.18.0-25-generic #26~18.04.1-Ubuntu SMP Thu Jun 27 07:28:31 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

编辑:这是该问题的另一个非常有趣的屏幕截图。

image of glitch

1 个答案:

答案 0 :(得分:3)

拳头,在主窗口上调用gtk_widget_queue_draw没有意义,因为仅需要GtkDrawingArea进行高频更新。重新绘制您未与之交互的控件会增加开销,而没有任何价值。

接下来,我在您的UI中看不到任何想要不断重绘绘图区域的内容。您应该对事件做出反应来重新绘制:左侧面板中已更改的参数值,或者用户单击绘图区域以更改视点(如果您支持的话)。您可能会触发超时,以响应控制更改,并在更改另一个更改时重新初始化该超时,以便让用户在半秒钟内更改所需的所有设置,然后显示最终结果而不是中间更改。当控件的值可以像您使用的GtkSpinButton一样快速变化时,这很有用。

从您的测试中,如果每秒而不是每50ms调用一次绘图代码会为您提供结果,那么问题很可能出在您的绘图代码中,而不是GTK +绘制它的方式上。为确保这种情况,您可以禁用重绘的超时源,并添加一个按钮,当单击该按钮时将触发单个重绘。这样,整个频率问题就变得不那么重要了,您仍然应该拥有那些渲染错误。

下一步是向我们展示draw信号处理程序中的代码,因为该错误可能位于此处。如果要调试它,则可以拆分图形,以便在绘制每个直方图条之后将要绘制的开罗曲面保存到文件中。然后使用图像编辑器逐个查看更改,您将看到问题发生在哪个图像上。通过一些日志记录,您将看到哪些值触发了问题。