0025789: Visualization - get rid of obsolete 2d layers implementation
[occt.git] / src / D3DHost / D3DHost_Workspace.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
16#include <d3d9.h>
17
18#include <D3DHost_Workspace.hxx>
19
20#include <TCollection_ExtendedString.hxx>
21
22// =======================================================================
23// function : d3dFormatError
24// purpose :
25// =======================================================================
26TCollection_AsciiString D3DHost_Workspace::d3dFormatError (HRESULT theErrCode)
27{
28 switch (theErrCode)
29 {
30 case D3D_OK: return "OK";
31 case D3DERR_DEVICELOST: return "Device lost";
32 case D3DERR_DEVICEREMOVED: return "Device removed";
33 case D3DERR_DRIVERINTERNALERROR: return "Driver internal error";
34 case D3DERR_OUTOFVIDEOMEMORY: return "Out of video memory";
35 case D3DERR_INVALIDCALL: return "Invalid call";
36 default: return TCollection_AsciiString ("Error #") + int(theErrCode) + ")";
37 }
38}
39
40// =======================================================================
41// function : D3DHost_Workspace
42// purpose :
43// =======================================================================
44D3DHost_Workspace::D3DHost_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver,
45 const CALL_DEF_WINDOW& theCWindow,
46 Aspect_RenderingContext theGContext,
47 const Handle(OpenGl_Caps)& theCaps,
48 const Handle(OpenGl_Context)& theShareCtx)
49: OpenGl_Workspace (theDriver, theCWindow, theGContext, theCaps, theShareCtx),
50 myD3dLib (NULL),
51 myD3dDevice (NULL),
52 myRefreshRate (D3DPRESENT_RATE_DEFAULT),
53 myIsD3dEx (false)
54{
55 myD3dParams = {};
56 myCurrMode = {};
57 myD3dParams.Windowed = TRUE;
58 myD3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
59 myD3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
60 myD3dParams.BackBufferCount = 1;
61 myD3dParams.BackBufferHeight = 2;
62 myD3dParams.BackBufferWidth = 2;
63 myD3dParams.EnableAutoDepthStencil = FALSE;
64 myD3dParams.AutoDepthStencilFormat = D3DFMT_D16_LOCKABLE;
65 myD3dParams.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
66 myD3dParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
67
68 d3dInit (theCWindow);
69 d3dCreateRenderTarget();
70}
71
72// =======================================================================
73// function : ~D3DHost_Workspace
74// purpose :
75// =======================================================================
76D3DHost_Workspace::~D3DHost_Workspace()
77{
78 if (!myD3dWglFbo.IsNull())
79 {
80 myD3dWglFbo->Release (myGlContext.operator->());
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
95// =======================================================================
96// function : d3dInitLib
97// purpose :
98// =======================================================================
99bool D3DHost_Workspace::d3dInitLib()
100{
101 if (myD3dLib == NULL)
102 {
103 IDirect3D9Ex* aD3dLibEx = NULL;
104 // we link against d3d (using Direct3DCreate9 symbol), thus it should be already loaded
105 HMODULE aLib = GetModuleHandleW (L"d3d9");
106 if (aLib != NULL)
107 {
108 // retrieve D3D9Ex function dynamically (available only since Vista+)
109 typedef HRESULT (WINAPI* Direct3DCreate9Ex_t)(UINT , IDirect3D9Ex** );
110 Direct3DCreate9Ex_t Direct3DCreate9ExProc = (Direct3DCreate9Ex_t )GetProcAddress (aLib, "Direct3DCreate9Ex");
111 if (Direct3DCreate9ExProc != NULL)
112 {
113 Direct3DCreate9ExProc(D3D_SDK_VERSION, &aD3dLibEx);
114 }
115 }
116 myD3dLib = aD3dLibEx;
117 myIsD3dEx = aD3dLibEx != NULL;
118 if (myD3dLib == NULL)
119 {
120 myD3dLib = Direct3DCreate9 (D3D_SDK_VERSION);
121 }
122 }
123 return myD3dLib != NULL;
124}
125
126// =======================================================================
127// function : d3dInit
128// purpose :
129// =======================================================================
130bool D3DHost_Workspace::d3dInit (const CALL_DEF_WINDOW& theCWindow)
131{
132 if (!d3dInitLib())
133 {
134 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
135 GL_DEBUG_TYPE_ERROR_ARB,
136 0,
137 GL_DEBUG_SEVERITY_HIGH_ARB,
138 "Direct3DCreate9 failed!");
139 return false;
140 }
141
142 UINT anAdapterId = D3DADAPTER_DEFAULT;
143
144 // setup the present parameters
145 if (myD3dLib->GetAdapterDisplayMode (anAdapterId, &myCurrMode) == D3D_OK)
146 {
147 myD3dParams.BackBufferFormat = myCurrMode.Format;
148 myRefreshRate = myCurrMode.RefreshRate;
149 }
150 myD3dParams.Windowed = TRUE;
151 myD3dParams.BackBufferWidth = theCWindow.dx;
152 myD3dParams.BackBufferHeight = theCWindow.dy;
153 myD3dParams.hDeviceWindow = (HWND )theCWindow.XWindow;
154
155 // create the Video Device
156 HRESULT isOK = myD3dLib->CreateDevice (anAdapterId, D3DDEVTYPE_HAL,
157 (HWND )theCWindow.XWindow,
158 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
159 &myD3dParams, &myD3dDevice);
160 if (isOK < 0)
161 {
162 return false;
163 }
164
165 return myD3dDevice != NULL;
166}
167
168// =======================================================================
169// function : d3dReset
170// purpose :
171// =======================================================================
172bool D3DHost_Workspace::d3dReset (const CALL_DEF_WINDOW& theCWindow)
173{
174 if (myD3dDevice == NULL)
175 {
176 return false;
177 }
178
179 myD3dParams.Windowed = TRUE;
180 myD3dParams.BackBufferWidth = theCWindow.dx;
181 myD3dParams.BackBufferHeight = theCWindow.dy;
182 myD3dParams.hDeviceWindow = (HWND )theCWindow.XWindow;
183 myD3dParams.FullScreen_RefreshRateInHz = !myD3dParams.Windowed ? myRefreshRate : 0;
184
185 HRESULT isOK = myD3dDevice->Reset(&myD3dParams);
186 return isOK == D3D_OK;
187}
188
189// =======================================================================
190// function : d3dCreateRenderTarget
191// purpose :
192// =======================================================================
193bool D3DHost_Workspace::d3dCreateRenderTarget()
194{
195 if (myD3dWglFbo.IsNull())
196 {
197 myD3dWglFbo = new D3DHost_FrameBuffer();
198 }
199 if (!myD3dWglFbo->Init (myGlContext, myD3dDevice, myIsD3dEx, myWidth, myHeight))
200 {
201 return false;
202 }
203
204 myD3dDevice->SetRenderTarget (0, myD3dWglFbo->D3dColorSurface());
205 return true;
206}
207
208// =======================================================================
209// function : d3dBeginRender
210// purpose :
211// =======================================================================
212void D3DHost_Workspace::d3dBeginRender()
213{
214 if (myD3dDevice == NULL)
215 {
216 return;
217 }
218
219 // clear the back buffer
220 myD3dDevice->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
221 myD3dDevice->BeginScene();
222}
223
224// =======================================================================
225// function : d3dEndRender
226// purpose :
227// =======================================================================
228void D3DHost_Workspace::d3dEndRender()
229{
230 if (myD3dDevice != NULL)
231 {
232 myD3dDevice->EndScene();
233 }
234}
235
236// =======================================================================
237// function : d3dSwap
238// purpose :
239// =======================================================================
240bool D3DHost_Workspace::d3dSwap()
241{
242 if (myD3dDevice == NULL)
243 {
244 return false;
245 }
246
247 const HRESULT isOK = myD3dDevice->Present (NULL, NULL, NULL, NULL);
248 if (isOK != D3D_OK)
249 {
250 TCollection_ExtendedString aMsg = TCollection_ExtendedString()
251 + "Direct3D9, Present device failed, " + d3dFormatError (isOK);
252 myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
253 GL_DEBUG_TYPE_ERROR_ARB,
254 0,
255 GL_DEBUG_SEVERITY_HIGH_ARB,
256 aMsg);
257 }
258 return isOK == D3D_OK;
259}
260
261// =======================================================================
262// function : Redraw
263// purpose :
264// =======================================================================
27f85086 265void D3DHost_Workspace::Redraw (const Graphic3d_CView& theCView)
62e1beed 266{
267 if (!Activate()
268 || myD3dDevice == NULL)
269 {
270 return;
271 }
272
273 myToFlipOutput = Standard_True;
274 myD3dWglFbo->LockSurface (myGlContext);
27f85086 275 OpenGl_Workspace::Redraw (theCView);
62e1beed 276 myD3dWglFbo->UnlockSurface (myGlContext);
277 myToFlipOutput = Standard_False;
278 if (myGlContext->caps->buffersNoSwap)
279 {
280 return;
281 }
282
283 // blit result to the D3D back buffer and swap
284 d3dBeginRender();
285
286 IDirect3DSurface9* aBackbuffer = NULL;
287 myD3dDevice->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &aBackbuffer);
288 myD3dDevice->StretchRect (myD3dWglFbo->D3dColorSurface(), NULL, aBackbuffer, NULL, D3DTEXF_LINEAR);
289 aBackbuffer->Release();
290
291 d3dEndRender();
292 d3dSwap();
293}
294
295// =======================================================================
296// function : RedrawImmediate
297// purpose :
298// =======================================================================
27f85086 299void D3DHost_Workspace::RedrawImmediate (const Graphic3d_CView& theCView)
62e1beed 300{
301 if (!myTransientDrawToFront
302 || !myBackBufferRestored
303 || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
304 {
27f85086 305 Redraw (theCView);
62e1beed 306 return;
307 }
308 else if (!Activate()
309 || myD3dDevice == NULL)
310 {
311 return;
312 }
313
314 myToFlipOutput = Standard_True;
315 myD3dWglFbo->LockSurface (myGlContext);
27f85086 316 OpenGl_Workspace::RedrawImmediate (theCView);
62e1beed 317 myD3dWglFbo->UnlockSurface (myGlContext);
318 myToFlipOutput = Standard_False;
319 if (myGlContext->caps->buffersNoSwap)
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 : Resize
338// purpose :
339// =======================================================================
340void D3DHost_Workspace::Resize (const CALL_DEF_WINDOW& theCWindow)
341{
342 const Standard_Integer aWidthOld = myWidth;
343 const Standard_Integer aHeightOld = myHeight;
344 OpenGl_Workspace::Resize (theCWindow);
345 if (aWidthOld == myWidth
346 && aHeightOld == myHeight)
347 {
348 return;
349 }
350
351 if (!myD3dWglFbo.IsNull())
352 {
353 myD3dWglFbo->Release (myGlContext.operator->());
354 }
355 if (!myGlContext->caps->buffersNoSwap)
356 {
357 d3dReset (theCWindow);
358 }
359 d3dCreateRenderTarget();
360}