0028890: Visualization - After closing all views and then display the view again...
[occt.git] / src / D3DHost / D3DHost_View.cxx
CommitLineData
62e1beed 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
d2eddacc 16#include <d3d9.h>
17
c357e426 18#include <D3DHost_View.hxx>
62e1beed 19
c357e426 20#include <D3DHost_GraphicDriver.hxx>
62e1beed 21#include <TCollection_ExtendedString.hxx>
22
92efcf78 23IMPLEMENT_STANDARD_RTTIEXT(D3DHost_View,OpenGl_View)
24
62e1beed 25// =======================================================================
26// function : d3dFormatError
27// purpose :
28// =======================================================================
d2eddacc 29TCollection_AsciiString D3DHost_View::d3dFormatError (const long theErrCode)
62e1beed 30{
31 switch (theErrCode)
32 {
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) + ")";
40 }
41}
42
43// =======================================================================
c357e426 44// function : D3DHost_View
62e1beed 45// purpose :
46// =======================================================================
c357e426 47D3DHost_View::D3DHost_View (const Handle(Graphic3d_StructureManager)& theMgr,
48 const Handle(D3DHost_GraphicDriver)& theDriver,
49 const Handle(OpenGl_Caps)& theCaps,
c357e426 50 OpenGl_StateCounter* theCounter)
851dacdb 51: OpenGl_View (theMgr, theDriver, theCaps, theCounter),
62e1beed 52 myD3dLib (NULL),
53 myD3dDevice (NULL),
d2eddacc 54 myD3dParams (new D3DPRESENT_PARAMETERS()),
62e1beed 55 myRefreshRate (D3DPRESENT_RATE_DEFAULT),
56 myIsD3dEx (false)
57{
d2eddacc 58 memset(myD3dParams.operator->(), 0, sizeof(D3DPRESENT_PARAMETERS));
59
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;
62e1beed 70}
71
72// =======================================================================
c357e426 73// function : ~D3DHost_View
62e1beed 74// purpose :
75// =======================================================================
c357e426 76D3DHost_View::~D3DHost_View()
62e1beed 77{
78 if (!myD3dWglFbo.IsNull())
79 {
c357e426 80 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
62e1beed 81 myD3dWglFbo.Nullify();
82 }
83 if (myD3dDevice != NULL)
84 {
85 myD3dDevice->Release();
86 myD3dDevice = NULL;
87 }
88 if (myD3dLib != NULL)
89 {
90 myD3dLib->Release();
91 myD3dLib = NULL;
92 }
93}
94
c357e426 95// =======================================================================
96// function : SetWindow
97// purpose :
98// =======================================================================
99void D3DHost_View::SetWindow (const Handle(Aspect_Window)& theWindow,
7aa74f30 100 const Aspect_RenderingContext theContext)
c357e426 101{
102 if (!myD3dWglFbo.IsNull())
103 {
104 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
105 myD3dWglFbo.Nullify();
106 }
107 if (myD3dDevice != NULL)
108 {
109 myD3dDevice->Release();
110 myD3dDevice = NULL;
111 }
112
7aa74f30 113 OpenGl_View::SetWindow (theWindow, theContext);
c357e426 114
115 if (!myWindow.IsNull())
116 {
117 d3dInit();
118 d3dCreateRenderTarget();
119 }
120}
121
62e1beed 122// =======================================================================
123// function : d3dInitLib
124// purpose :
125// =======================================================================
c357e426 126bool D3DHost_View::d3dInitLib()
62e1beed 127{
128 if (myD3dLib == NULL)
129 {
130 IDirect3D9Ex* aD3dLibEx = NULL;
131 // we link against d3d (using Direct3DCreate9 symbol), thus it should be already loaded
132 HMODULE aLib = GetModuleHandleW (L"d3d9");
133 if (aLib != NULL)
134 {
135 // retrieve D3D9Ex function dynamically (available only since Vista+)
136 typedef HRESULT (WINAPI* Direct3DCreate9Ex_t)(UINT , IDirect3D9Ex** );
137 Direct3DCreate9Ex_t Direct3DCreate9ExProc = (Direct3DCreate9Ex_t )GetProcAddress (aLib, "Direct3DCreate9Ex");
138 if (Direct3DCreate9ExProc != NULL)
139 {
140 Direct3DCreate9ExProc(D3D_SDK_VERSION, &aD3dLibEx);
141 }
142 }
143 myD3dLib = aD3dLibEx;
144 myIsD3dEx = aD3dLibEx != NULL;
145 if (myD3dLib == NULL)
146 {
147 myD3dLib = Direct3DCreate9 (D3D_SDK_VERSION);
148 }
149 }
150 return myD3dLib != NULL;
151}
152
153// =======================================================================
154// function : d3dInit
155// purpose :
156// =======================================================================
c357e426 157bool D3DHost_View::d3dInit()
62e1beed 158{
159 if (!d3dInitLib())
160 {
c357e426 161 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
162 GL_DEBUG_TYPE_ERROR_ARB,
163 0,
164 GL_DEBUG_SEVERITY_HIGH_ARB,
165 "Direct3DCreate9 failed!");
62e1beed 166 return false;
167 }
168
169 UINT anAdapterId = D3DADAPTER_DEFAULT;
170
171 // setup the present parameters
d2eddacc 172 D3DDISPLAYMODE aCurrMode;
173 memset(&aCurrMode, 0, sizeof(aCurrMode));
174 if (myD3dLib->GetAdapterDisplayMode (anAdapterId, &aCurrMode) == D3D_OK)
62e1beed 175 {
d2eddacc 176 myD3dParams->BackBufferFormat = aCurrMode.Format;
177 myRefreshRate = aCurrMode.RefreshRate;
62e1beed 178 }
d2eddacc 179 myD3dParams->Windowed = TRUE;
180 myD3dParams->BackBufferWidth = myWindow->Width();
181 myD3dParams->BackBufferHeight = myWindow->Height();
182 myD3dParams->hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
62e1beed 183
184 // create the Video Device
185 HRESULT isOK = myD3dLib->CreateDevice (anAdapterId, D3DDEVTYPE_HAL,
c357e426 186 (HWND )myWindow->PlatformWindow()->NativeHandle(),
62e1beed 187 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
d2eddacc 188 myD3dParams.get(), &myD3dDevice);
62e1beed 189 if (isOK < 0)
190 {
191 return false;
192 }
193
194 return myD3dDevice != NULL;
195}
196
197// =======================================================================
198// function : d3dReset
199// purpose :
200// =======================================================================
c357e426 201bool D3DHost_View::d3dReset()
62e1beed 202{
203 if (myD3dDevice == NULL)
204 {
205 return false;
206 }
207
d2eddacc 208 myD3dParams->Windowed = TRUE;
209 myD3dParams->BackBufferWidth = myWindow->Width();
210 myD3dParams->BackBufferHeight = myWindow->Height();
211 myD3dParams->hDeviceWindow = (HWND )myWindow->PlatformWindow()->NativeHandle();
212 myD3dParams->FullScreen_RefreshRateInHz = !myD3dParams->Windowed ? myRefreshRate : 0;
62e1beed 213
d2eddacc 214 HRESULT isOK = myD3dDevice->Reset(myD3dParams.get());
62e1beed 215 return isOK == D3D_OK;
216}
217
218// =======================================================================
219// function : d3dCreateRenderTarget
220// purpose :
221// =======================================================================
c357e426 222bool D3DHost_View::d3dCreateRenderTarget()
62e1beed 223{
224 if (myD3dWglFbo.IsNull())
225 {
226 myD3dWglFbo = new D3DHost_FrameBuffer();
227 }
c357e426 228 if (!myD3dWglFbo->Init (myWorkspace->GetGlContext(),
229 myD3dDevice,
230 myIsD3dEx,
231 myWindow->Width(),
232 myWindow->Height()))
62e1beed 233 {
234 return false;
235 }
236
237 myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
238 return true;
239}
240
241// =======================================================================
242// function : d3dBeginRender
243// purpose :
244// =======================================================================
c357e426 245void D3DHost_View::d3dBeginRender()
62e1beed 246{
247 if (myD3dDevice == NULL)
248 {
249 return;
250 }
251
252 // clear the back buffer
253 myD3dDevice->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
254 myD3dDevice->BeginScene();
255}
256
257// =======================================================================
258// function : d3dEndRender
259// purpose :
260// =======================================================================
c357e426 261void D3DHost_View::d3dEndRender()
62e1beed 262{
263 if (myD3dDevice != NULL)
264 {
265 myD3dDevice->EndScene();
266 }
267}
268
269// =======================================================================
270// function : d3dSwap
271// purpose :
272// =======================================================================
c357e426 273bool D3DHost_View::d3dSwap()
62e1beed 274{
275 if (myD3dDevice == NULL)
276 {
277 return false;
278 }
279
280 const HRESULT isOK = myD3dDevice->Present (NULL, NULL, NULL, NULL);
281 if (isOK != D3D_OK)
282 {
283 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
284 + "Direct3D9, Present device failed, " + d3dFormatError (isOK);
c357e426 285 myWorkspace->GetGlContext()->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
286 GL_DEBUG_TYPE_ERROR_ARB,
287 0,
288 GL_DEBUG_SEVERITY_HIGH_ARB,
289 aMsg);
62e1beed 290 }
291 return isOK == D3D_OK;
292}
293
294// =======================================================================
295// function : Redraw
296// purpose :
297// =======================================================================
c357e426 298void D3DHost_View::Redraw()
62e1beed 299{
c357e426 300 if (!myWorkspace->Activate()
62e1beed 301 || myD3dDevice == NULL)
302 {
303 return;
304 }
b128c892 305 else if (!myFBO.IsNull())
d2eddacc 306 {
307 OpenGl_View::Redraw();
308 return;
309 }
62e1beed 310
c357e426 311 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
62e1beed 312 myToFlipOutput = Standard_True;
c357e426 313 myD3dWglFbo->LockSurface (aCtx);
b128c892 314 myFBO = myD3dWglFbo;
c357e426 315 OpenGl_View::Redraw();
b128c892 316 myFBO.Nullify();
c357e426 317 myD3dWglFbo->UnlockSurface (aCtx);
62e1beed 318 myToFlipOutput = Standard_False;
c357e426 319 if (aCtx->caps->buffersNoSwap)
62e1beed 320 {
321 return;
322 }
323
324 // blit result to the D3D back buffer and swap
325 d3dBeginRender();
326
327 IDirect3DSurface9* aBackbuffer = NULL;
328 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
329 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
330 aBackbuffer->Release();
331
332 d3dEndRender();
333 d3dSwap();
334}
335
336// =======================================================================
337// function : RedrawImmediate
338// purpose :
339// =======================================================================
c357e426 340void D3DHost_View::RedrawImmediate()
62e1beed 341{
c357e426 342 Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
62e1beed 343 if (!myTransientDrawToFront
344 || !myBackBufferRestored
c357e426 345 || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
62e1beed 346 {
c357e426 347 Redraw();
62e1beed 348 return;
349 }
c357e426 350 else if (!myWorkspace->Activate()
62e1beed 351 || myD3dDevice == NULL)
352 {
353 return;
354 }
b128c892 355 else if (!myFBO.IsNull())
d2eddacc 356 {
357 OpenGl_View::Redraw();
358 return;
359 }
62e1beed 360
361 myToFlipOutput = Standard_True;
c357e426 362 myD3dWglFbo->LockSurface (aCtx);
b128c892 363 myFBO = myD3dWglFbo;
c357e426 364 OpenGl_View::RedrawImmediate();
b128c892 365 myFBO.Nullify();
c357e426 366 myD3dWglFbo->UnlockSurface (aCtx);
62e1beed 367 myToFlipOutput = Standard_False;
c357e426 368 if (aCtx->caps->buffersNoSwap)
62e1beed 369 {
370 return;
371 }
372
373 // blit result to the D3D back buffer and swap
374 d3dBeginRender();
375
376 IDirect3DSurface9* aBackbuffer = NULL;
377 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
378 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
379 aBackbuffer->Release();
380
381 d3dEndRender();
382 d3dSwap();
383}
384
385// =======================================================================
386// function : Resize
387// purpose :
388// =======================================================================
c357e426 389void D3DHost_View::Resized()
62e1beed 390{
c357e426 391 const Standard_Integer aWidthOld = myWindow->Width();
392 const Standard_Integer aHeightOld = myWindow->Height();
393 OpenGl_View::Resized();
394 if (aWidthOld == myWindow->Width()
395 && aHeightOld == myWindow->Height())
62e1beed 396 {
397 return;
398 }
399
400 if (!myD3dWglFbo.IsNull())
401 {
c357e426 402 myD3dWglFbo->Release (myWorkspace->GetGlContext().operator->());
62e1beed 403 }
c357e426 404 if (!myWorkspace->GetGlContext()->caps->buffersNoSwap)
62e1beed 405 {
c357e426 406 d3dReset();
62e1beed 407 }
408 d3dCreateRenderTarget();
409}