0

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:

PNG of black square created with Cairo API

After making the call to IDirect3D9::CreateDevice, the same Cairo API calls create a blank .PNG:

Blank PNG created with Cairo API when it should contain a black square

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:

  • How is it that the code compiles without error, and returns no error status at run-time, but the behaviour of the Cairo API calls varies significantly?
  • Is there a way of parameterising the IDirect3D9::CreateDevice call to prevent this, or a way of recovering the expected behaviour of the Cairo API with subsequent function calls?
Jeff
  • 71
  • 10
  • Why in particular do you need to use the legacy Direct3D 9 API? Be sure to see [MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx) and [this post](https://blogs.msdn.microsoft.com/chuckw/2012/11/26/visual-studio-2012-update-1/) w.r.t. to the legacy DirectX SDK. – Chuck Walbourn Feb 01 '17 at 18:38
  • @ChuckWalbourn the platform toolset being used is v140_xp (VS 2015). Legacy D3D9 API has always been used by this project to target clients running the Windows XP operating system. Is there a known incompatibility between the APIs listed above? – Jeff Feb 01 '17 at 21:07
  • @ChuckWalbourn there are numerous D3DX calls made in the code base, which is why the standalone library is being used. "Note: D3DX is only available for download in previous versions of the DirectX SDK" - [Where is the DirectX SDK?](https://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx) – Jeff Feb 01 '17 at 21:38

1 Answers1

0

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:

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

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.

Jeff
  • 71
  • 10
  • GTK and dependencies like cairo are provided for Windows through the MSYS2 project. You can find cairo 1.15.4 (released on 2016-12-08) there: http://repo.msys2.org/mingw/x86_64/ – liberforce Feb 03 '17 at 12:02