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:
После вызова IDirect3D9:: CreateDevice те же вызовы Cairo 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
Вопрос в том:
- Как получается, что код компилируется без ошибок и не возвращает статус ошибки во время выполнения, но поведение вызовов 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 обеспечивает более высокий уровень точности при выполнении своих расчетов цвета:
Исправление для этой ошибки было введено немедленно:
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, вам нужно будет создать свои собственные версии двоичных файлов.
Огромное спасибо загадочному другу, который использовал их поиск-фу, чтобы найти оригинальную ветку, касающуюся каирской ошибки.