I need to call the Cairo Graphics API (included with GTK+ 2.24.10 bundle), whilst also using the Direct3D 9 API (DirectX SDK March 2009).
To test, I make basic Cairo function calls as follows:
#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);
...
If these Cairo API calls are made before a call to IDirect3D9::CreateDevice, then the following .PNG is output:
After making the call to IDirect3D9::CreateDevice, the same Cairo API calls create a blank .PNG:
The IDirect3D9::CreateDevice call is parameterised as follows:
Direct3DCreate9(D3D_SDK_VERSION)->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, WindowHandle, D3DCREATE_HARDWARE_VERTEXPROCESSING, &PresentParameters, &PDevice);
Where the object parameters contain the following member variables:
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
The question is:
This behaviour is a result of an incompatibility between the Direct3D 9 API (DirectX SDK March 2009) and Cairo Graphics API (1.10.2).
The following mailing list thread from 2006-10-16 details how creating a Direct3D 9 device alters the FPU to single-precision mode, and that this version of the Cairo API assumed a higher level of precision when making its colour calculations:
A fix for this bug was introduced immediately:
https://bugs.freedesktop.org/show_bug.cgi?id=7497
Cairo v1.10.2 was released 2010-12-25, which postdates this fix by 4 years, but the erroneous behaviour is still present.
However, the fix must have made it into the Cairo code base at some point, as there is no evidence of the bug in Cairo v1.14.6, which can be downloaded from the HexChat project:
https://github.com/hexchat/gtk-win32
N.B. the libraries in this project's distribution are not Windows XP compatible. If you target Windows XP, you will need to build your own versions of the binaries.
A massive thank you to the mystery friend who used their search-fu to find the original thread concerning the Cairo bug.