IDirect3D9::CreateDevice 阻止 GTK+ 2 Cairo 渲染

IDirect3D9::CreateDevice prevents GTK+ 2 Cairo rendering

我需要调用 Cairo Graphics API(包含在 GTK+ 2.24.10 包中),同时还使用 Direct3D 9 API(DirectX SDK March 2009)。

为了测试,我按如下方式调用基本的 Cairo 函数:

#include <cairo\cairo.h>

...

cairo_surface_t *surface;
cairo_t *cr;
cairo_status_t status;

surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 390, 60);
status = cairo_surface_status(surface);

cr = cairo_create(surface);
status = cairo_status(cr);

cairo_set_source_rgba(cr, 0, 0, 0, 1);
status = cairo_status(cr);

cairo_rectangle(cr, 175, 10, 40, 40);
status = cairo_status(cr);

cairo_fill(cr);
status = cairo_status(cr);

cairo_surface_flush(surface);
status = cairo_surface_write_to_png(surface, "c:\cairo_test.png");

cairo_destroy(cr);
cairo_surface_destroy(surface);

...

如果这些 Cairo API 调用是在调用 IDirect3D9::CreateDevice 之前进行的,则输出以下 .PNG:

调用 IDirect3D9::CreateDevice 后,相同的开罗 API 调用创建一个空白 .PNG:

IDirect3D9::CreateDevice调用参数化如下:

Direct3DCreate9(D3D_SDK_VERSION)->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, WindowHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, &PresentParameters, &PDevice);

其中对象参数包含以下成员变量:

WindowHandle    0x001b07f8 {unused=13111204 }   HWND__ *
    unused  13111204    int

PresentParameters   {BackBufferWidth=0 BackBufferHeight=0 BackBufferFormat=D3DFMT_UNKNOWN (0) ...}  _D3DPRESENT_PARAMETERS_
        BackBufferWidth 0   unsigned int
        BackBufferHeight    0   unsigned int
        BackBufferFormat    D3DFMT_UNKNOWN (0)  _D3DFORMAT
        BackBufferCount 1   unsigned int
        MultiSampleType D3DMULTISAMPLE_NONE (0) _D3DMULTISAMPLE_TYPE
        MultiSampleQuality  0   unsigned long
        SwapEffect  D3DSWAPEFFECT_DISCARD (1)   _D3DSWAPEFFECT
+       hDeviceWindow   0x001b07f8 {unused=13111204 }   HWND__ *
        Windowed    1   int
        EnableAutoDepthStencil  0   int
        AutoDepthStencilFormat  D3DFMT_UNKNOWN (0)  _D3DFORMAT
        Flags   1   unsigned long
        FullScreen_RefreshRateInHz  0   unsigned int
        PresentationInterval    0   unsigned int

PDevice 0x00000000 <NULL>   IDirect3DDevice9 *
+       IUnknown    <struct at NULL>    IUnknown

问题是:

此行为是 Direct3D 9 API(DirectX SDK 2009 年 3 月)和 Cairo Graphics API (1.10.2) 之间不兼容的结果。

来自 2006-10-16 的以下邮件列表线程详细说明了创建 Direct3D 9 设备如何改变 FPU to single-precision mode,并且此版本的 Cairo API 在进行颜色计算:

http://cairo.cairographics.narkive.com/L9XYWFkQ/cairo-direct3d-interaction-bug-and-fix-x86-fpu-precision

立即引入了针对此错误的修复程序:

https://bugs.freedesktop.org/show_bug.cgi?id=7497

Cairo v1.10.2 于 2010 年 12 月 25 日发布,比此修复晚了 4 年,但错误行为仍然存在。

但是,修复程序肯定在某个时候进入了 Cairo 代码库,因为没有证据表明 Cairo v1.14.6 中存在错误,可以从 HexChat 项目下载:

https://github.com/hexchat/gtk-win32

N.B。该项目发行版中的库与 Windows XP 不兼容。如果您的目标是 Windows XP,您将需要构建您自己的二进制文件版本。

非常感谢使用他们的 search-fu 找到有关 Cairo 错误的原始线程的神秘朋友。