IDirect3D9::CreateDevice предотвращает рендеринг GTK+ 2 Cairo

Мне нужно вызвать Cairo Graphics API (входит в комплект GTK+ 2.24.10), а также использовать Direct3D 9 API (DirectX SDK, март 2009 г.).

Чтобы проверить, я делаю основные вызовы функции Каира следующим образом:

#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:

PNG черного квадрата, созданный с помощью Cairo API

После вызова IDirect3D9:: CreateDevice те же вызовы Cairo API создают пустой.PNG:

Пустой PNG, созданный с помощью Cairo API, когда он должен содержать черный квадрат

Вызов 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

Вопрос в том:

  • Как получается, что код компилируется без ошибок и не возвращает статус ошибки во время выполнения, но поведение вызовов Cairo API значительно варьируется?
  • Есть ли способ параметризации вызова IDirect3D9::CreateDevice, чтобы предотвратить это, или способ восстановления ожидаемого поведения Cairo API с последующими вызовами функций?

1 ответ

Решение

Такое поведение является результатом несовместимости между Direct3D 9 API (DirectX SDK, март 2009 г.) и Cairo Graphics API (1.10.2).

В следующей ветке списка рассылки 2006-10-16 подробно рассказывается, как создание устройства Direct3D 9 переводит FPU в режим одинарной точности и что эта версия 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

Обратите внимание, что библиотеки из этого проекта не совместимы с Windows XP. Если вы ориентируетесь на Windows XP, вам нужно будет создать свои собственные версии двоичных файлов.

Огромное спасибо загадочному другу, который использовал их поиск-фу, чтобы найти оригинальную ветку, касающуюся каирской ошибки.

Другие вопросы по тегам