QT中IDirect3DDevice9的Present方法失败情况的处理笔记
这几天在试着使用QT做编辑器,然后打算使用Irrlicht作为渲染引擎。结果在集成的时候遇到了问题。
使用了Irrlicht论坛里面有人提供的QIrrlichtWidget,结果什么都画不出来。仔细跟踪了一下,结果是IDirect3DDevice9的Present函数返回了E_FAIL。
查了下文档,文档只说是内部错误,没有说具体会是什么原因造成的。网上找原因,按照大家说的使用D3D的debug模式,看到了如下的输出信息:
Direct3D9: (ERROR) :GetClientRect Failed ?
Direct3D9: (ERROR) :GetClientRect Failed ?
Direct3D9: (ERROR) :BitBlt or StretchBlt failed in Present
有人遇到了类似的问题,是先销毁窗口然后继续使用Present函数就会这样,于是我就怀疑到是不是窗口系统出了什么问题。
结果发现了,在创建device的时候获得的winId(),竟然和Present的时候的winId()不同。
于是我怀疑,是我使用QT的窗口系统不当,初始化的时候获得了跟显示出Widget时不同的winId,导致最后Present失败。
于是我使用了下列代码做了实验,代码如下:
1 QApplication app(argc, argv);
2
3 MainWindow mainWin;
4
5 QVBoxLayout *layout = new QVBoxLayout();
6
7 QIrrlichtWidget* irrWidget = new QIrrlichtWidget();
8 QIrrlichtWidget* irrWidget1 = new QIrrlichtWidget();
9
10 HWND id1 = irrWidget->winId();
11
12 layout->addWidget(irrWidget);
13 layout->addWidget(irrWidget1);
14
15 //如果初始化代码在这里,就会导致Present失败,什么都绘制不出来
16 //irrWidget->init();
17 //irrWidget1->init();
18 //setupIrrlicht( irrWidget->getIrrlichtDevice() );
19 //setupIrrlicht( irrWidget1->getIrrlichtDevice() );
20
21 HWND id2 = irrWidget->winId();
22
23 mainWin.centralwidget->setLayout(layout);
24
25 //在这里winId()的返回值就不同了
26 HWND id3 = irrWidget->winId();
27
28 mainWin.resize(400,400);
29
30 HWND id4 = irrWidget->winId();
31
32 //在拥有了正确的winId之后,就可以初始化设备了
33 irrWidget->init();
34 irrWidget1->init();
35
36 setupIrrlicht( irrWidget->getIrrlichtDevice() );
37 setupIrrlicht( irrWidget1->getIrrlichtDevice() );
38
39 mainWin.show();
40
41 HWND id7 = irrWidget->winId();
42
43 return app.exec();
上述代码将两个QIrrlichtWidget垂直排列放到一个QVBoxLayout中,init方法就是初始化设备,setupIrrlicht是向场景中添加些绘制的元素,代码都是参照
来写的。
上面的代码,注释中标记了什么时候winId改变了,以及错误的初始化位置。我没有深入研究QT中winId相关的内容,只是知道了以后要在什么时候初始化,以防再次遇到这样的问题。
特此记录下来与大家分享。