0026734: Visualization, D3DHost_View - drop outdated UserDraw interfaces
[occt.git] / src / D3DHost / D3DHost_View.cxx
... / ...
CommitLineData
1// Created on: 2015-06-10
2// Created by: Kirill Gavrilov
3// Copyright (c) 2015 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <D3DHost_View.hxx>
17
18#include <D3DHost_GraphicDriver.hxx>
19#include <TCollection_ExtendedString.hxx>
20
21// =======================================================================
22// function : d3dFormatError
23// purpose :
24// =======================================================================
25TCollection_AsciiString D3DHost_View::d3dFormatError (HRESULT theErrCode)
26{
27 switch (theErrCode)
28 {
29 case D3D_OK: return "OK";
30 case D3DERR_DEVICELOST: return "Device lost";
31 case D3DERR_DEVICEREMOVED: return "Device removed";
32 case D3DERR_DRIVERINTERNALERROR: return "Driver internal error";
33 case D3DERR_OUTOFVIDEOMEMORY: return "Out of video memory";
34 case D3DERR_INVALIDCALL: return "Invalid call";
35 default: return TCollection_AsciiString ("Error #") + int(theErrCode) + ")";
36 }
37}
38
39// =======================================================================
40// function : D3DHost_View
41// purpose :
42// =======================================================================
43D3DHost_View::D3DHost_View (const Handle(Graphic3d_StructureManager)& theMgr,
44 const Handle(D3DHost_GraphicDriver)& theDriver,
45 const Handle(OpenGl_Caps)& theCaps,
46 Standard_Boolean& theDeviceLostFlag,
47 OpenGl_StateCounter* theCounter)
48: OpenGl_View (theMgr, theDriver, theCaps, theDeviceLostFlag, theCounter),
49 myD3dLib (NULL),
50 myD3dDevice (NULL),
51 myRefreshRate (D3DPRESENT_RATE_DEFAULT),
52 myIsD3dEx (false)
53{
54 myD3dParams = {};
55 myCurrMode = {};
56 myD3dParams.Windowed = TRUE;
57 myD3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
58 myD3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
59 myD3dParams.BackBufferCount = 1;
60 myD3dParams.BackBufferHeight = 2;
61 myD3dParams.BackBufferWidth = 2;
62 myD3dParams.EnableAutoDepthStencil = FALSE;
63 myD3dParams.AutoDepthStencilFormat = D3DFMT_D16_LOCKABLE;
64 myD3dParams.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
65 myD3dParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
66}
67
68// =======================================================================
69// function : ~D3DHost_View
70// purpose :
71// =======================================================================
72D3DHost_View::~D3DHost_View()
73{
74 if (!myD3dWglFbo.IsNull())
75 {
76 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
77 myD3dWglFbo.Nullify();
78 }
79 if (myD3dDevice != NULL)
80 {
81 myD3dDevice->Release();
82 myD3dDevice = NULL;
83 }
84 if (myD3dLib != NULL)
85 {
86 myD3dLib->Release();
87 myD3dLib = NULL;
88 }
89}
90
91// =======================================================================
92// function : SetWindow
93// purpose :
94// =======================================================================
95void D3DHost_View::SetWindow (const Handle(Aspect_Window)& theWindow,
96 const Aspect_RenderingContext theContext)
97{
98 if (!myD3dWglFbo.IsNull())
99 {
100 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
101 myD3dWglFbo.Nullify();
102 }
103 if (myD3dDevice != NULL)
104 {
105 myD3dDevice->Release();
106 myD3dDevice = NULL;
107 }
108
109 OpenGl_View::SetWindow (theWindow, theContext);
110
111 if (!myWindow.IsNull())
112 {
113 d3dInit();
114 d3dCreateRenderTarget();
115 }
116}
117
118// =======================================================================
119// function : d3dInitLib
120// purpose :
121// =======================================================================
122bool D3DHost_View::d3dInitLib()
123{
124 if (myD3dLib == NULL)
125 {
126 IDirect3D9Ex* aD3dLibEx = NULL;
127 // we link against d3d (using Direct3DCreate9 symbol), thus it should be already loaded
128 HMODULE aLib = GetModuleHandleW (L"d3d9");
129 if (aLib != NULL)
130 {
131 // retrieve D3D9Ex function dynamically (available only since Vista+)
132 typedef HRESULT (WINAPI* Direct3DCreate9Ex_t)(UINT , IDirect3D9Ex** );
133 Direct3DCreate9Ex_t Direct3DCreate9ExProc = (Direct3DCreate9Ex_t )GetProcAddress (aLib, "Direct3DCreate9Ex");
134 if (Direct3DCreate9ExProc != NULL)
135 {
136 Direct3DCreate9ExProc(D3D_SDK_VERSION, &aD3dLibEx);
137 }
138 }
139 myD3dLib = aD3dLibEx;
140 myIsD3dEx = aD3dLibEx != NULL;
141 if (myD3dLib == NULL)
142 {
143 myD3dLib = Direct3DCreate9 (D3D_SDK_VERSION);
144 }
145 }
146 return myD3dLib != NULL;
147}
148
149// =======================================================================
150// function : d3dInit
151// purpose :
152// =======================================================================
153bool D3DHost_View::d3dInit()
154{
155 if (!d3dInitLib())
156 {
157 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
158 GL_DEBUG_TYPE_ERROR_ARB,
159 0,
160 GL_DEBUG_SEVERITY_HIGH_ARB,
161 "Direct3DCreate9 failed!");
162 return false;
163 }
164
165 UINT anAdapterId = D3DADAPTER_DEFAULT;
166
167 // setup the present parameters
168 if (myD3dLib->GetAdapterDisplayMode (anAdapterId, &myCurrMode) == D3D_OK)
169 {
170 myD3dParams.BackBufferFormat = myCurrMode.Format;
171 myRefreshRate = myCurrMode.RefreshRate;
172 }
173 myD3dParams.Windowed = TRUE;
174 myD3dParams.BackBufferWidth = myWindow->Width();
175 myD3dParams.BackBufferHeight = myWindow->Height();
176 myD3dParams.hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
177
178 // create the Video Device
179 HRESULT isOK = myD3dLib->CreateDevice (anAdapterId, D3DDEVTYPE_HAL,
180 (HWND )myWindow->PlatformWindow()->NativeHandle(),
181 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
182 &myD3dParams, &myD3dDevice);
183 if (isOK < 0)
184 {
185 return false;
186 }
187
188 return myD3dDevice != NULL;
189}
190
191// =======================================================================
192// function : d3dReset
193// purpose :
194// =======================================================================
195bool D3DHost_View::d3dReset()
196{
197 if (myD3dDevice == NULL)
198 {
199 return false;
200 }
201
202 myD3dParams.Windowed = TRUE;
203 myD3dParams.BackBufferWidth = myWindow->Width();
204 myD3dParams.BackBufferHeight = myWindow->Height();
205 myD3dParams.hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
206 myD3dParams.FullScreen_RefreshRateInHz = !myD3dParams.Windowed ? myRefreshRate : 0;
207
208 HRESULT isOK = myD3dDevice->Reset(&myD3dParams);
209 return isOK == D3D_OK;
210}
211
212// =======================================================================
213// function : d3dCreateRenderTarget
214// purpose :
215// =======================================================================
216bool D3DHost_View::d3dCreateRenderTarget()
217{
218 if (myD3dWglFbo.IsNull())
219 {
220 myD3dWglFbo = new D3DHost_FrameBuffer();
221 }
222 if (!myD3dWglFbo->Init (myWorkspace->GetGlContext(),
223 myD3dDevice,
224 myIsD3dEx,
225 myWindow->Width(),
226 myWindow->Height()))
227 {
228 return false;
229 }
230
231 myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
232 return true;
233}
234
235// =======================================================================
236// function : d3dBeginRender
237// purpose :
238// =======================================================================
239void D3DHost_View::d3dBeginRender()
240{
241 if (myD3dDevice == NULL)
242 {
243 return;
244 }
245
246 // clear the back buffer
247 myD3dDevice->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
248 myD3dDevice->BeginScene();
249}
250
251// =======================================================================
252// function : d3dEndRender
253// purpose :
254// =======================================================================
255void D3DHost_View::d3dEndRender()
256{
257 if (myD3dDevice != NULL)
258 {
259 myD3dDevice->EndScene();
260 }
261}
262
263// =======================================================================
264// function : d3dSwap
265// purpose :
266// =======================================================================
267bool D3DHost_View::d3dSwap()
268{
269 if (myD3dDevice == NULL)
270 {
271 return false;
272 }
273
274 const HRESULT isOK = myD3dDevice->Present (NULL, NULL, NULL, NULL);
275 if (isOK != D3D_OK)
276 {
277 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
278 + "Direct3D9, Present device failed, " + d3dFormatError (isOK);
279 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
280 GL_DEBUG_TYPE_ERROR_ARB,
281 0,
282 GL_DEBUG_SEVERITY_HIGH_ARB,
283 aMsg);
284 }
285 return isOK == D3D_OK;
286}
287
288// =======================================================================
289// function : Redraw
290// purpose :
291// =======================================================================
292void D3DHost_View::Redraw()
293{
294 if (!myWorkspace->Activate()
295 || myD3dDevice == NULL)
296 {
297 return;
298 }
299
300 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
301 myToFlipOutput = Standard_True;
302 myD3dWglFbo->LockSurface (aCtx);
303 OpenGl_View::Redraw();
304 myD3dWglFbo->UnlockSurface (aCtx);
305 myToFlipOutput = Standard_False;
306 if (aCtx->caps->buffersNoSwap)
307 {
308 return;
309 }
310
311 // blit result to the D3D back buffer and swap
312 d3dBeginRender();
313
314 IDirect3DSurface9* aBackbuffer = NULL;
315 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
316 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
317 aBackbuffer->Release();
318
319 d3dEndRender();
320 d3dSwap();
321}
322
323// =======================================================================
324// function : RedrawImmediate
325// purpose :
326// =======================================================================
327void D3DHost_View::RedrawImmediate()
328{
329 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
330 if (!myTransientDrawToFront
331 || !myBackBufferRestored
332 || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
333 {
334 Redraw();
335 return;
336 }
337 else if (!myWorkspace->Activate()
338 || myD3dDevice == NULL)
339 {
340 return;
341 }
342
343 myToFlipOutput = Standard_True;
344 myD3dWglFbo->LockSurface (aCtx);
345 OpenGl_View::RedrawImmediate();
346 myD3dWglFbo->UnlockSurface (aCtx);
347 myToFlipOutput = Standard_False;
348 if (aCtx->caps->buffersNoSwap)
349 {
350 return;
351 }
352
353 // blit result to the D3D back buffer and swap
354 d3dBeginRender();
355
356 IDirect3DSurface9* aBackbuffer = NULL;
357 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
358 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
359 aBackbuffer->Release();
360
361 d3dEndRender();
362 d3dSwap();
363}
364
365// =======================================================================
366// function : Resize
367// purpose :
368// =======================================================================
369void D3DHost_View::Resized()
370{
371 const Standard_Integer aWidthOld = myWindow->Width();
372 const Standard_Integer aHeightOld = myWindow->Height();
373 OpenGl_View::Resized();
374 if (aWidthOld == myWindow->Width()
375 && aHeightOld == myWindow->Height())
376 {
377 return;
378 }
379
380 if (!myD3dWglFbo.IsNull())
381 {
382 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
383 }
384 if (!myWorkspace->GetGlContext()->caps->buffersNoSwap)
385 {
386 d3dReset();
387 }
388 d3dCreateRenderTarget();
389}