blob: 6f3ae0b6b5628025d0b81c1b65d210ecbbd06ece [file] [log] [blame]
daniel@transgaming.com621ce052012-10-31 17:52:29 +00001//
2// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Renderer.cpp: Implements a back-end specific class that hides the details of the
8// implementation-specific renderer.
9
10#include "libGLESv2/renderer/Renderer.h"
11#include "common/debug.h"
12#include "libGLESv2/utilities.h"
13
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000014#include "libEGL/Display.h"
15
daniel@transgaming.com621ce052012-10-31 17:52:29 +000016// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
17#define REF_RAST 0
18
19// The "Debug This Pixel..." feature in PIX often fails when using the
20// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
21// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
22#if !defined(ANGLE_ENABLE_D3D9EX)
23// Enables use of the IDirect3D9Ex interface, when available
24#define ANGLE_ENABLE_D3D9EX 1
25#endif // !defined(ANGLE_ENABLE_D3D9EX)
26
27namespace renderer
28{
29
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000030Renderer::Renderer(egl::Display *display, HMODULE hModule, HDC hDc): mDc(hDc)
daniel@transgaming.com621ce052012-10-31 17:52:29 +000031{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000032 mDisplay = display;
daniel@transgaming.com621ce052012-10-31 17:52:29 +000033 mD3d9Module = hModule;
34
35 mD3d9 = NULL;
36 mD3d9Ex = NULL;
37 mDevice = NULL;
38 mDeviceEx = NULL;
39 mDeviceWindow = NULL;
40
41 mAdapter = D3DADAPTER_DEFAULT;
42
43 #if REF_RAST == 1 || defined(FORCE_REF_RAST)
44 mDeviceType = D3DDEVTYPE_REF;
45 #else
46 mDeviceType = D3DDEVTYPE_HAL;
47 #endif
48
49 mDeviceLost = false;
50}
51
52Renderer::~Renderer()
53{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000054 releaseDeviceResources();
55
daniel@transgaming.com621ce052012-10-31 17:52:29 +000056 if (mDevice)
57 {
58 // If the device is lost, reset it first to prevent leaving the driver in an unstable state
59 if (testDeviceLost())
60 {
61 resetDevice();
62 }
63
64 mDevice->Release();
65 mDevice = NULL;
66 }
67
68 if (mDeviceEx)
69 {
70 mDeviceEx->Release();
71 mDeviceEx = NULL;
72 }
73
74 if (mD3d9)
75 {
76 mD3d9->Release();
77 mD3d9 = NULL;
78 }
79
80 if (mDeviceWindow)
81 {
82 DestroyWindow(mDeviceWindow);
83 mDeviceWindow = NULL;
84 }
85
86 if (mD3d9Ex)
87 {
88 mD3d9Ex->Release();
89 mD3d9Ex = NULL;
90 }
91
92 if (mD3d9Module)
93 {
94 mD3d9Module = NULL;
95 }
96
97}
98
99EGLint Renderer::initialize()
100{
101 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
102 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
103
104 // Use Direct3D9Ex if available. Among other things, this version is less
105 // inclined to report a lost context, for example when the user switches
106 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
107 if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
108 {
109 ASSERT(mD3d9Ex);
110 mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
111 ASSERT(mD3d9);
112 }
113 else
114 {
115 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
116 }
117
118 if (!mD3d9)
119 {
120 ERR("Could not create D3D9 device - aborting!\n");
121 return EGL_NOT_INITIALIZED;
122 }
123 if (mDc != NULL)
124 {
125 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
126 }
127
128 HRESULT result;
129
130 // Give up on getting device caps after about one second.
131 for (int i = 0; i < 10; ++i)
132 {
133 result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
134 if (SUCCEEDED(result))
135 {
136 break;
137 }
138 else if (result == D3DERR_NOTAVAILABLE)
139 {
140 Sleep(100); // Give the driver some time to initialize/recover
141 }
142 else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
143 {
144 ERR("failed to get device caps (0x%x)\n", result);
145 return EGL_NOT_INITIALIZED;
146 }
147 }
148
149 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
150 {
151 ERR("Renderer does not support PS 2.0. aborting!\n");
152 return EGL_NOT_INITIALIZED;
153 }
154
155 // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
156 // This is required by Texture2D::convertToRenderTarget.
157 if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
158 {
159 ERR("Renderer does not support stretctrect from textures!\n");
160 return EGL_NOT_INITIALIZED;
161 }
162
163 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
164
165 // ATI cards on XP have problems with non-power-of-two textures.
166 mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
167 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
168 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
169 !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
170
171 static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
172 static const TCHAR className[] = TEXT("STATIC");
173
174 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
175
176 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
177 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
178
179 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
180 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
181 {
182 return EGL_BAD_ALLOC;
183 }
184
185 if (FAILED(result))
186 {
187 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
188
189 if (FAILED(result))
190 {
191 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
192 return EGL_BAD_ALLOC;
193 }
194 }
195
196 if (mD3d9Ex)
197 {
198 result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
199 ASSERT(SUCCEEDED(result));
200 }
201
202 initializeDevice();
203
204 return EGL_SUCCESS;
205}
206
207// do any one-time device initialization
208// NOTE: this is also needed after a device lost/reset
209// to reset the scene status and ensure the default states are reset.
210void Renderer::initializeDevice()
211{
212 // Permanent non-default states
213 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
214 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
215
216 if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
217 {
218 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
219 }
220 else
221 {
222 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
223 }
224
225 mSceneStarted = false;
226}
227
228D3DPRESENT_PARAMETERS Renderer::getDefaultPresentParameters()
229{
230 D3DPRESENT_PARAMETERS presentParameters = {0};
231
232 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
233 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
234 presentParameters.BackBufferCount = 1;
235 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
236 presentParameters.BackBufferWidth = 1;
237 presentParameters.BackBufferHeight = 1;
238 presentParameters.EnableAutoDepthStencil = FALSE;
239 presentParameters.Flags = 0;
240 presentParameters.hDeviceWindow = mDeviceWindow;
241 presentParameters.MultiSampleQuality = 0;
242 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
243 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
244 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
245 presentParameters.Windowed = TRUE;
246
247 return presentParameters;
248}
249
250void Renderer::startScene()
251{
252 if (!mSceneStarted)
253 {
254 long result = mDevice->BeginScene();
255 if (SUCCEEDED(result)) {
256 // This is defensive checking against the device being
257 // lost at unexpected times.
258 mSceneStarted = true;
259 }
260 }
261}
262
263void Renderer::endScene()
264{
265 if (mSceneStarted)
266 {
267 // EndScene can fail if the device was lost, for example due
268 // to a TDR during a draw call.
269 mDevice->EndScene();
270 mSceneStarted = false;
271 }
272}
273
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000274// D3D9_REPLACE
275void Renderer::sync(bool block)
276{
277 HRESULT result;
278
279 IDirect3DQuery9* query = allocateEventQuery();
280 if (!query)
281 {
282 return;
283 }
284
285 result = query->Issue(D3DISSUE_END);
286 ASSERT(SUCCEEDED(result));
287
288 do
289 {
290 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
291
292 if(block && result == S_FALSE)
293 {
294 // Keep polling, but allow other threads to do something useful first
295 Sleep(0);
296 // explicitly check for device loss
297 // some drivers seem to return S_FALSE even if the device is lost
298 // instead of D3DERR_DEVICELOST like they should
299 if (testDeviceLost())
300 {
301 result = D3DERR_DEVICELOST;
302 }
303 }
304 }
305 while(block && result == S_FALSE);
306
307 freeEventQuery(query);
308
309 if (isDeviceLostError(result))
310 {
311 mDisplay->notifyDeviceLost();
312 }
313}
314
315// D3D9_REPLACE
316IDirect3DQuery9* Renderer::allocateEventQuery()
317{
318 IDirect3DQuery9 *query = NULL;
319
320 if (mEventQueryPool.empty())
321 {
322 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
323 ASSERT(SUCCEEDED(result));
324 }
325 else
326 {
327 query = mEventQueryPool.back();
328 mEventQueryPool.pop_back();
329 }
330
331 return query;
332}
333
334// D3D9_REPLACE
335void Renderer::freeEventQuery(IDirect3DQuery9* query)
336{
337 if (mEventQueryPool.size() > 1000)
338 {
339 query->Release();
340 }
341 else
342 {
343 mEventQueryPool.push_back(query);
344 }
345}
346
347void Renderer::releaseDeviceResources()
348{
349 while (!mEventQueryPool.empty())
350 {
351 mEventQueryPool.back()->Release();
352 mEventQueryPool.pop_back();
353 }
354}
355
356
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000357void Renderer::markDeviceLost()
358{
359 mDeviceLost = true;
360}
361
362bool Renderer::isDeviceLost()
363{
364 return mDeviceLost;
365}
366
367bool Renderer::testDeviceLost()
368{
369 bool isLost = false;
370
371 if (mDeviceEx)
372 {
373 isLost = FAILED(mDeviceEx->CheckDeviceState(NULL));
374 }
375 else if (mDevice)
376 {
377 isLost = FAILED(mDevice->TestCooperativeLevel());
378 }
379 else
380 {
381 // No device yet, so no reset required
382 }
383
384 if (isLost)
385 {
386 // ensure we note the device loss --
387 // we'll probably get this done again by markDeviceLost
388 // but best to remember it!
389 // Note that we don't want to clear the device loss status here
390 // -- this needs to be done by resetDevice
391 mDeviceLost = true;
392 }
393
394 return isLost;
395}
396
397bool Renderer::testDeviceResettable()
398{
399 HRESULT status = D3D_OK;
400
401 if (mDeviceEx)
402 {
403 status = mDeviceEx->CheckDeviceState(NULL);
404 }
405 else if (mDevice)
406 {
407 status = mDevice->TestCooperativeLevel();
408 }
409
410 switch (status)
411 {
412 case D3DERR_DEVICENOTRESET:
413 case D3DERR_DEVICEHUNG:
414 return true;
415 default:
416 return false;
417 }
418}
419
420bool Renderer::resetDevice()
421{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000422 releaseDeviceResources();
423
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000424 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
425
426 HRESULT result = D3D_OK;
427 bool lost = testDeviceLost();
428 int attempts = 3;
429
430 while (lost && attempts > 0)
431 {
432 if (mDeviceEx)
433 {
434 Sleep(500); // Give the graphics driver some CPU time
435 result = mDeviceEx->ResetEx(&presentParameters, NULL);
436 }
437 else
438 {
439 result = mDevice->TestCooperativeLevel();
440 while (result == D3DERR_DEVICELOST)
441 {
442 Sleep(100); // Give the graphics driver some CPU time
443 result = mDevice->TestCooperativeLevel();
444 }
445
446 if (result == D3DERR_DEVICENOTRESET)
447 {
448 result = mDevice->Reset(&presentParameters);
449 }
450 }
451
452 lost = testDeviceLost();
453 attempts --;
454 }
455
456 if (FAILED(result))
457 {
458 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
459 return false;
460 }
461
462 // reset device defaults
463 initializeDevice();
464 mDeviceLost = false;
465
466 return true;
467}
468
469void Renderer::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
470{
471 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
472 {
473 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
474 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
475
476 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
477 }
478}
479
480bool Renderer::getDXT1TextureSupport()
481{
482 D3DDISPLAYMODE currentDisplayMode;
483 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
484
485 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
486}
487
488bool Renderer::getDXT3TextureSupport()
489{
490 D3DDISPLAYMODE currentDisplayMode;
491 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
492
493 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
494}
495
496bool Renderer::getDXT5TextureSupport()
497{
498 D3DDISPLAYMODE currentDisplayMode;
499 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
500
501 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
502}
503
504// we use INTZ for depth textures in Direct3D9
505// we also want NULL texture support to ensure the we can make depth-only FBOs
506// see http://aras-p.info/texts/D3D9GPUHacks.html
507bool Renderer::getDepthTextureSupport() const
508{
509 D3DDISPLAYMODE currentDisplayMode;
510 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
511
512 bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
513 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
514 bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
515 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
516
517 return intz && null;
518}
519
520bool Renderer::getFloat32TextureSupport(bool *filtering, bool *renderable)
521{
522 D3DDISPLAYMODE currentDisplayMode;
523 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
524
525 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
526 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
527 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
528 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
529
530 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
531 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
532 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
533 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
534
535 if (!*filtering && !*renderable)
536 {
537 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
538 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
539 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
540 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
541 }
542 else
543 {
544 return true;
545 }
546}
547
548bool Renderer::getFloat16TextureSupport(bool *filtering, bool *renderable)
549{
550 D3DDISPLAYMODE currentDisplayMode;
551 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
552
553 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
554 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
555 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
556 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
557
558 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
559 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
560 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
561 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
562
563 if (!*filtering && !*renderable)
564 {
565 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
566 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
567 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
568 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
569 }
570 else
571 {
572 return true;
573 }
574}
575
576bool Renderer::getLuminanceTextureSupport()
577{
578 D3DDISPLAYMODE currentDisplayMode;
579 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
580
581 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
582}
583
584bool Renderer::getLuminanceAlphaTextureSupport()
585{
586 D3DDISPLAYMODE currentDisplayMode;
587 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
588
589 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
590}
591
592float Renderer::getTextureFilterAnisotropySupport() const
593{
594 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
595 if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
596 {
597 return mDeviceCaps.MaxAnisotropy;
598 }
599 return 1.0f;
600}
601
602bool Renderer::getEventQuerySupport()
603{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000604 IDirect3DQuery9 *query = allocateEventQuery();
605 if (query)
606 {
607 freeEventQuery(query);
608 return true;
609 }
610 else
611 {
612 return false;
613 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000614 return true;
615}
616
617// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
618// We test this using D3D9 by checking support for the R16F format.
619bool Renderer::getVertexTextureSupport() const
620{
621 if (!mDevice || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
622 {
623 return false;
624 }
625
626 D3DDISPLAYMODE currentDisplayMode;
627 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
628
629 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
630
631 return SUCCEEDED(result);
632}
633
634bool Renderer::getNonPower2TextureSupport() const
635{
636 return mSupportsNonPower2Textures;
637}
638
639bool Renderer::getOcclusionQuerySupport() const
640{
641 if (!mDevice)
642 {
643 return false;
644 }
645
646 IDirect3DQuery9 *query = NULL;
647 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
648 if (SUCCEEDED(result) && query)
649 {
650 query->Release();
651 return true;
652 }
653 else
654 {
655 return false;
656 }
657}
658
659bool Renderer::getInstancingSupport() const
660{
661 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
662}
663
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000664bool Renderer::getShareHandleSupport() const
665{
666 // PIX doesn't seem to support using share handles, so disable them.
667 // D3D9_REPLACE
668 return isD3d9ExDevice() && !gl::perfActive();
669}
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000670
671D3DPOOL Renderer::getBufferPool(DWORD usage) const
672{
673 if (mD3d9Ex != NULL)
674 {
675 return D3DPOOL_DEFAULT;
676 }
677 else
678 {
679 if (!(usage & D3DUSAGE_DYNAMIC))
680 {
681 return D3DPOOL_MANAGED;
682 }
683 }
684
685 return D3DPOOL_DEFAULT;
686}
687
688D3DPOOL Renderer::getTexturePool(DWORD usage) const
689{
690 if (mD3d9Ex != NULL)
691 {
692 return D3DPOOL_DEFAULT;
693 }
694 else
695 {
696 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
697 {
698 return D3DPOOL_MANAGED;
699 }
700 }
701
702 return D3DPOOL_DEFAULT;
703}
704
705}