1 // Created on: 2015-06-10
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2015 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
18 #include <D3DHost_View.hxx>
20 #include <D3DHost_GraphicDriver.hxx>
21 #include <TCollection_ExtendedString.hxx>
23 IMPLEMENT_STANDARD_RTTIEXT(D3DHost_View,OpenGl_View)
25 // =======================================================================
26 // function : d3dFormatError
28 // =======================================================================
29 TCollection_AsciiString D3DHost_View::d3dFormatError (const long theErrCode)
33 case D3D_OK: return "OK";
34 case D3DERR_DEVICELOST: return "Device lost";
35 case D3DERR_DEVICEREMOVED: return "Device removed";
36 case D3DERR_DRIVERINTERNALERROR: return "Driver internal error";
37 case D3DERR_OUTOFVIDEOMEMORY: return "Out of video memory";
38 case D3DERR_INVALIDCALL: return "Invalid call";
39 default: return TCollection_AsciiString ("Error #") + int(theErrCode) + ")";
43 // =======================================================================
44 // function : D3DHost_View
46 // =======================================================================
47 D3DHost_View::D3DHost_View (const Handle(Graphic3d_StructureManager)& theMgr,
48 const Handle(D3DHost_GraphicDriver)& theDriver,
49 const Handle(OpenGl_Caps)& theCaps,
50 OpenGl_StateCounter* theCounter)
51 : OpenGl_View (theMgr, theDriver, theCaps, theCounter),
54 myD3dParams (new D3DPRESENT_PARAMETERS()),
55 myRefreshRate (D3DPRESENT_RATE_DEFAULT),
58 memset(myD3dParams.operator->(), 0, sizeof(D3DPRESENT_PARAMETERS));
60 myD3dParams->Windowed = TRUE;
61 myD3dParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
62 myD3dParams->BackBufferFormat = D3DFMT_X8R8G8B8;
63 myD3dParams->BackBufferCount = 1;
64 myD3dParams->BackBufferHeight = 2;
65 myD3dParams->BackBufferWidth = 2;
66 myD3dParams->EnableAutoDepthStencil = FALSE;
67 myD3dParams->AutoDepthStencilFormat = D3DFMT_D16_LOCKABLE;
68 myD3dParams->FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
69 myD3dParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
72 // =======================================================================
73 // function : ~D3DHost_View
75 // =======================================================================
76 D3DHost_View::~D3DHost_View()
78 if (!myD3dWglFbo.IsNull())
80 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
81 myD3dWglFbo.Nullify();
83 if (myD3dDevice != NULL)
85 myD3dDevice->Release();
95 // =======================================================================
96 // function : D3dColorSurface
98 // =======================================================================
99 IDirect3DSurface9* D3DHost_View::D3dColorSurface() const
101 return myD3dWglFbo->D3dColorSurface();
104 // =======================================================================
105 // function : SetWindow
107 // =======================================================================
108 void D3DHost_View::SetWindow (const Handle(Aspect_Window)& theWindow,
109 const Aspect_RenderingContext theContext)
111 if (!myD3dWglFbo.IsNull())
113 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
114 myD3dWglFbo.Nullify();
116 if (myD3dDevice != NULL)
118 myD3dDevice->Release();
122 OpenGl_View::SetWindow (theWindow, theContext);
124 if (!myWindow.IsNull())
127 d3dCreateRenderTarget();
131 // =======================================================================
132 // function : d3dInitLib
134 // =======================================================================
135 bool D3DHost_View::d3dInitLib()
137 if (myD3dLib == NULL)
139 IDirect3D9Ex* aD3dLibEx = NULL;
140 // we link against d3d (using Direct3DCreate9 symbol), thus it should be already loaded
141 HMODULE aLib = GetModuleHandleW (L"d3d9");
144 // retrieve D3D9Ex function dynamically (available only since Vista+)
145 typedef HRESULT (WINAPI* Direct3DCreate9Ex_t)(UINT , IDirect3D9Ex** );
146 Direct3DCreate9Ex_t Direct3DCreate9ExProc = (Direct3DCreate9Ex_t )GetProcAddress (aLib, "Direct3DCreate9Ex");
147 if (Direct3DCreate9ExProc != NULL)
149 Direct3DCreate9ExProc(D3D_SDK_VERSION, &aD3dLibEx);
152 myD3dLib = aD3dLibEx;
153 myIsD3dEx = aD3dLibEx != NULL;
154 if (myD3dLib == NULL)
156 myD3dLib = Direct3DCreate9 (D3D_SDK_VERSION);
159 return myD3dLib != NULL;
162 // =======================================================================
163 // function : d3dInit
165 // =======================================================================
166 bool D3DHost_View::d3dInit()
170 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Direct3DCreate9 failed!");
174 UINT anAdapterId = D3DADAPTER_DEFAULT;
176 // setup the present parameters
177 D3DDISPLAYMODE aCurrMode;
178 memset(&aCurrMode, 0, sizeof(aCurrMode));
179 if (myD3dLib->GetAdapterDisplayMode (anAdapterId, &aCurrMode) == D3D_OK)
181 myD3dParams->BackBufferFormat = aCurrMode.Format;
182 myRefreshRate = aCurrMode.RefreshRate;
184 myD3dParams->Windowed = TRUE;
185 myD3dParams->BackBufferWidth = myWindow->Width();
186 myD3dParams->BackBufferHeight = myWindow->Height();
187 myD3dParams->hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
189 // create the Video Device
190 HRESULT isOK = myD3dLib->CreateDevice (anAdapterId, D3DDEVTYPE_HAL,
191 (HWND )myWindow->PlatformWindow()->NativeHandle(),
192 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
193 myD3dParams.get(), &myD3dDevice);
199 return myD3dDevice != NULL;
202 // =======================================================================
203 // function : d3dReset
205 // =======================================================================
206 bool D3DHost_View::d3dReset()
208 if (myD3dDevice == NULL)
213 myD3dParams->Windowed = TRUE;
214 myD3dParams->BackBufferWidth = myWindow->Width();
215 myD3dParams->BackBufferHeight = myWindow->Height();
216 myD3dParams->hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
217 myD3dParams->FullScreen_RefreshRateInHz = !myD3dParams->Windowed ? myRefreshRate : 0;
219 HRESULT isOK = myD3dDevice->Reset(myD3dParams.get());
220 return isOK == D3D_OK;
223 // =======================================================================
224 // function : d3dCreateRenderTarget
226 // =======================================================================
227 bool D3DHost_View::d3dCreateRenderTarget()
229 bool toD3dFallback = false;
230 if (myD3dWglFbo.IsNull())
232 myD3dWglFbo = new D3DHost_FrameBuffer();
236 toD3dFallback = myD3dWglFbo->D3dFallback();
241 toD3dFallback = !myD3dWglFbo->InitD3dInterop (myWorkspace->GetGlContext(),
246 0); // do not request depth-stencil attachment since buffer will be flipped using addition FBO (myToFlipOutput)
250 if (!myD3dWglFbo->InitD3dFallback (myWorkspace->GetGlContext(),
255 GL_DEPTH24_STENCIL8))
261 myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
265 // =======================================================================
266 // function : d3dBeginRender
268 // =======================================================================
269 void D3DHost_View::d3dBeginRender()
271 if (myD3dDevice == NULL)
276 // clear the back buffer
277 myD3dDevice->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
278 myD3dDevice->BeginScene();
281 // =======================================================================
282 // function : d3dEndRender
284 // =======================================================================
285 void D3DHost_View::d3dEndRender()
287 if (myD3dDevice != NULL)
289 myD3dDevice->EndScene();
293 // =======================================================================
294 // function : d3dSwap
296 // =======================================================================
297 bool D3DHost_View::d3dSwap()
299 if (myD3dDevice == NULL)
304 const HRESULT isOK = myD3dDevice->Present (NULL, NULL, NULL, NULL);
307 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
308 TCollection_AsciiString("Direct3D9, Present device failed, ") + d3dFormatError (isOK));
310 return isOK == D3D_OK;
313 // =======================================================================
316 // =======================================================================
317 void D3DHost_View::Redraw()
319 if (!myWorkspace->Activate()
320 || myD3dDevice == NULL)
324 else if (!myFBO.IsNull())
326 OpenGl_View::Redraw();
330 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
331 if (myWindow->PlatformWindow()->IsVirtual()
332 && aCtx->arbFBO == NULL)
334 // do a dirty hack in extreme fallback mode with OpenGL driver not supporting FBO,
335 // the back buffer of hidden window is used for rendering as offscreen buffer
336 myTransientDrawToFront = false;
337 int aWinSizeX = 0, aWinSizeY = 0;
338 myWindow->PlatformWindow()->Size (aWinSizeX, aWinSizeY);
339 WINDOWPLACEMENT aPlace;
340 GetWindowPlacement ((HWND )myWindow->PlatformWindow()->NativeHandle(), &aPlace);
341 if (aPlace.rcNormalPosition.right - aPlace.rcNormalPosition.left != aWinSizeX
342 || aPlace.rcNormalPosition.bottom - aPlace.rcNormalPosition.top != aWinSizeY)
344 aPlace.rcNormalPosition.right = aPlace.rcNormalPosition.left + aWinSizeX;
345 aPlace.rcNormalPosition.bottom = aPlace.rcNormalPosition.top + aWinSizeY;
346 aPlace.showCmd = SW_HIDE;
347 SetWindowPlacement ((HWND )myWindow->PlatformWindow()->NativeHandle(), &aPlace);
351 myD3dWglFbo->LockSurface (aCtx);
352 if (myD3dWglFbo->IsValid())
354 myToFlipOutput = Standard_True;
357 OpenGl_View::Redraw();
359 myD3dWglFbo->UnlockSurface (aCtx);
360 myToFlipOutput = Standard_False;
361 if (aCtx->caps->buffersNoSwap)
366 // blit result to the D3D back buffer and swap
369 IDirect3DSurface9* aBackbuffer = NULL;
370 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
371 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
372 aBackbuffer->Release();
378 // =======================================================================
379 // function : RedrawImmediate
381 // =======================================================================
382 void D3DHost_View::RedrawImmediate()
384 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
385 if (!myTransientDrawToFront
386 || !myBackBufferRestored
387 || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
392 else if (!myWorkspace->Activate()
393 || myD3dDevice == NULL)
397 else if (!myFBO.IsNull())
399 OpenGl_View::Redraw();
403 myD3dWglFbo->LockSurface (aCtx);
404 if (myD3dWglFbo->IsValid())
406 myToFlipOutput = Standard_True;
409 OpenGl_View::RedrawImmediate();
411 myD3dWglFbo->UnlockSurface (aCtx);
412 myToFlipOutput = Standard_False;
413 if (aCtx->caps->buffersNoSwap)
418 // blit result to the D3D back buffer and swap
421 IDirect3DSurface9* aBackbuffer = NULL;
422 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
423 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
424 aBackbuffer->Release();
430 // =======================================================================
433 // =======================================================================
434 void D3DHost_View::Resized()
436 const Standard_Integer aWidthOld = myWindow->Width();
437 const Standard_Integer aHeightOld = myWindow->Height();
438 OpenGl_View::Resized();
439 if (aWidthOld == myWindow->Width()
440 && aHeightOld == myWindow->Height())
445 if (!myD3dWglFbo.IsNull())
447 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
449 if (!myWorkspace->GetGlContext()->caps->buffersNoSwap)
453 d3dCreateRenderTarget();