Krita、OpenGL和Qt

2020-07-18 12:24:22

Adrian Page在2005年首次为Krita编写了一个基于OpenGL的Canvas实现。那是在QT3时代。OpenGL当时相当简单,但是我们必须复制我们所有的画布处理代码,一旦用OpenGL实现,一旦用QPainter实现,我们就必须复制所有的画布处理代码。

Krita的画布代码分三个阶段执行。这里有图像投影,也就是合并所有图层的结果,这是首先绘制的。然后我们绘制画布装饰:即选择轮廓、向导、助手、参考图像等。然后我们绘制工具装饰:那就是轮廓光标、直线或标尺工具的线条等等。

显然,实现这一切两次,一次是在OpenGL中,一次是使用QPainter,这并不理想。

所以当Qt4出现的时候,我们都很高兴。Qt4附带了基于OpenGL的QPainter引擎。这很理想;我们可以拆分我们的画布代码。图像将使用纯OpenGL在QGLWidget上绘制,或者使用QPainter在QWidget上绘制,画布装饰和工具装饰将使用QPainter绘制在任一画布上。

Qt文档甚至附带了一个很好的示例,说明如何做到这一点。

然而,Qt开发人员显然更多地将OpenGL QPainter引擎视为加快QWidget绘制速度的一种方式,而不是应用程序开发人员会使用的东西。而且OpenGL QPainter引擎永远无法完全正确地呈现复杂的应用程序。

因此,在某个时候,引擎在MacOS上停止工作。主要是因为苹果公司不想让人们使用OpenGL,所以他们的驱动程序在开发中匮乏,但也因为Qt开发人员认为OpenGL QPainter引擎是一个失败的实验,因为它在绘制他们的小部件时没有提高性能:他们忘记了应用程序开发人员在他们的OpenGL应用程序中使用QPainter。甚至告诉他们不要这么做。尽管文件从未反映过这一观点。

这很糟糕,因为我们需要它,2016年我们不得不花了一个夏天的代码槽来修复OpenGL QPainter引擎,这样它就可以在带有OpenGL 3.2核心配置文件的MacOS上运行。降落在Qt的飞机上。

随着从Qt4迁移到Qt5,又发生了一些事情:Qt4QML基于QGraphicsView。我一直怀疑QGraphicsView是为需要地图软件的公司创建的,但在诺基亚时代,有几次尝试将QGraphicsView作为移动UI框架DUI的基础(我能找到的最好的链接;这里有严重的历史损失)。

这些尝试都失败了,直到有人想出了QML,它最初也是用QGraphicsView呈现的。

我们使用QML创建了Krita Sketch和Krita Gemini。因为它是基于QGraphicsView的,所以我们创建的触摸式UI可以与基于OpenGL的画布无缝协作。

Qt5问世时,QML是基于OpenGL和场景图的。我们花了几个月和相当多的钱试图将我们的OpenGL画布集成到新的场景图中,但就是不起作用。完全没有。它无法工作,Krita Sketch和Krita Gemini死了。

(顺便说一句:将OpenGL代码从Qt4移植到Qt5比我们预期的要困难得多。事实上,这是一个巨大的麻烦。)。

Windows上的OpenGL驱动程序的质量总是参差不齐,有时甚至非常糟糕。我们在开发Krita Sketch时就已经遇到过这种情况,当时我们突然有了很多Windows用户。

Angel将OpenGL无缝转换为Direct3D。一旦Chrome使用了这一点,他们所有的崩溃都消失了。

GPU制造商没有理由再修复他们的驱动程序,所以他们没有这么做。游戏将使用Direct3D,Chrome将使用Angel,很快Qt也增加了使用Angel的选项,因为否则Windows上基于QML的应用程序将不断崩溃。

这对我们来说是个极好的消息。我们开始使用Angel,错误报告的数量大幅下降。当我们想在Windows上支持HDR屏幕时,我们已经使用了Angel这一事实是很棒的,因为这使我们能够使HDR工作,因为在Windows上,HDR只能在使用Direct3D渲染窗口时才能工作。

HDR补丁还没有登陆Qt,所以我们随身携带了它们,还有很多其他补丁需要让Krita工作得很好。

我们定期将这些补丁移植到较新版本的Qt5,但我们所有的Krita二进制版本都是使用Qt5.12构建的,因为从5.12开始的每个Qt版本都有太多错误,无法使用。例如:在5.15中,在子窗口模式下使用QMdiArea将在Windows上挂起。

除了Krita Sketch仍然死了,我们正在移植到Android,移动UI应该很好,一切都很好。

因为,显然,Qt的角度构建选项的存在只是为了确保QML应用程序可以在windows上运行,而不是为了任何目的,所以Qt6已经放弃了角度选项…。

因为将会有一个新的框架,它将直接使用各种GPU API(Metal、Vulkan、Direct3D、OpenGL),在它们上面有一个抽象层(),用于渲染QML场景图。不过,看起来这一切都是Qt内部的。

确实很难找到文档,但看起来QPainter将使用这些模块进行渲染;但不清楚的是,当我们在QOpenGLWidget上使用QPainter时会发生什么。或者,我们是否必须实现一个Metal画布、一个Direct3画布和一个OpenGL画布?我们是否能够在Windows上访问HDR功能?