blob: baacc80278e18e4779be5ca0f578ebfa2e0c4273 [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
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +000059 if (testDeviceLost(false))
daniel@transgaming.com621ce052012-10-31 17:52:29 +000060 {
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
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000202 mVertexShaderCache.initialize(mDevice);
203 mPixelShaderCache.initialize(mDevice);
204
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000205 initializeDevice();
206
207 return EGL_SUCCESS;
208}
209
210// do any one-time device initialization
211// NOTE: this is also needed after a device lost/reset
212// to reset the scene status and ensure the default states are reset.
213void Renderer::initializeDevice()
214{
215 // Permanent non-default states
216 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
217 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
218
219 if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
220 {
221 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
222 }
223 else
224 {
225 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
226 }
227
228 mSceneStarted = false;
229}
230
231D3DPRESENT_PARAMETERS Renderer::getDefaultPresentParameters()
232{
233 D3DPRESENT_PARAMETERS presentParameters = {0};
234
235 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
236 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
237 presentParameters.BackBufferCount = 1;
238 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
239 presentParameters.BackBufferWidth = 1;
240 presentParameters.BackBufferHeight = 1;
241 presentParameters.EnableAutoDepthStencil = FALSE;
242 presentParameters.Flags = 0;
243 presentParameters.hDeviceWindow = mDeviceWindow;
244 presentParameters.MultiSampleQuality = 0;
245 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
246 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
247 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
248 presentParameters.Windowed = TRUE;
249
250 return presentParameters;
251}
252
253void Renderer::startScene()
254{
255 if (!mSceneStarted)
256 {
257 long result = mDevice->BeginScene();
258 if (SUCCEEDED(result)) {
259 // This is defensive checking against the device being
260 // lost at unexpected times.
261 mSceneStarted = true;
262 }
263 }
264}
265
266void Renderer::endScene()
267{
268 if (mSceneStarted)
269 {
270 // EndScene can fail if the device was lost, for example due
271 // to a TDR during a draw call.
272 mDevice->EndScene();
273 mSceneStarted = false;
274 }
275}
276
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000277// D3D9_REPLACE
278void Renderer::sync(bool block)
279{
280 HRESULT result;
281
282 IDirect3DQuery9* query = allocateEventQuery();
283 if (!query)
284 {
285 return;
286 }
287
288 result = query->Issue(D3DISSUE_END);
289 ASSERT(SUCCEEDED(result));
290
291 do
292 {
293 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
294
295 if(block && result == S_FALSE)
296 {
297 // Keep polling, but allow other threads to do something useful first
298 Sleep(0);
299 // explicitly check for device loss
300 // some drivers seem to return S_FALSE even if the device is lost
301 // instead of D3DERR_DEVICELOST like they should
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000302 if (testDeviceLost(false))
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000303 {
304 result = D3DERR_DEVICELOST;
305 }
306 }
307 }
308 while(block && result == S_FALSE);
309
310 freeEventQuery(query);
311
312 if (isDeviceLostError(result))
313 {
314 mDisplay->notifyDeviceLost();
315 }
316}
317
318// D3D9_REPLACE
319IDirect3DQuery9* Renderer::allocateEventQuery()
320{
321 IDirect3DQuery9 *query = NULL;
322
323 if (mEventQueryPool.empty())
324 {
325 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
326 ASSERT(SUCCEEDED(result));
327 }
328 else
329 {
330 query = mEventQueryPool.back();
331 mEventQueryPool.pop_back();
332 }
333
334 return query;
335}
336
337// D3D9_REPLACE
338void Renderer::freeEventQuery(IDirect3DQuery9* query)
339{
340 if (mEventQueryPool.size() > 1000)
341 {
342 query->Release();
343 }
344 else
345 {
346 mEventQueryPool.push_back(query);
347 }
348}
349
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000350IDirect3DVertexShader9 *Renderer::createVertexShader(const DWORD *function, size_t length)
351{
352 return mVertexShaderCache.create(function, length);
353}
354
355IDirect3DPixelShader9 *Renderer::createPixelShader(const DWORD *function, size_t length)
356{
357 return mPixelShaderCache.create(function, length);
358}
359
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000360void Renderer::releaseDeviceResources()
361{
362 while (!mEventQueryPool.empty())
363 {
364 mEventQueryPool.back()->Release();
365 mEventQueryPool.pop_back();
366 }
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000367
368 mVertexShaderCache.clear();
369 mPixelShaderCache.clear();
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000370}
371
372
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000373void Renderer::markDeviceLost()
374{
375 mDeviceLost = true;
376}
377
378bool Renderer::isDeviceLost()
379{
380 return mDeviceLost;
381}
382
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000383// set notify to true to broadcast a message to all contexts of the device loss
384bool Renderer::testDeviceLost(bool notify)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000385{
386 bool isLost = false;
387
388 if (mDeviceEx)
389 {
390 isLost = FAILED(mDeviceEx->CheckDeviceState(NULL));
391 }
392 else if (mDevice)
393 {
394 isLost = FAILED(mDevice->TestCooperativeLevel());
395 }
396 else
397 {
398 // No device yet, so no reset required
399 }
400
401 if (isLost)
402 {
403 // ensure we note the device loss --
404 // we'll probably get this done again by markDeviceLost
405 // but best to remember it!
406 // Note that we don't want to clear the device loss status here
407 // -- this needs to be done by resetDevice
408 mDeviceLost = true;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000409 if (notify)
410 {
411 mDisplay->notifyDeviceLost();
412 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000413 }
414
415 return isLost;
416}
417
418bool Renderer::testDeviceResettable()
419{
420 HRESULT status = D3D_OK;
421
422 if (mDeviceEx)
423 {
424 status = mDeviceEx->CheckDeviceState(NULL);
425 }
426 else if (mDevice)
427 {
428 status = mDevice->TestCooperativeLevel();
429 }
430
431 switch (status)
432 {
433 case D3DERR_DEVICENOTRESET:
434 case D3DERR_DEVICEHUNG:
435 return true;
436 default:
437 return false;
438 }
439}
440
441bool Renderer::resetDevice()
442{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000443 releaseDeviceResources();
444
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000445 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
446
447 HRESULT result = D3D_OK;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000448 bool lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000449 int attempts = 3;
450
451 while (lost && attempts > 0)
452 {
453 if (mDeviceEx)
454 {
455 Sleep(500); // Give the graphics driver some CPU time
456 result = mDeviceEx->ResetEx(&presentParameters, NULL);
457 }
458 else
459 {
460 result = mDevice->TestCooperativeLevel();
461 while (result == D3DERR_DEVICELOST)
462 {
463 Sleep(100); // Give the graphics driver some CPU time
464 result = mDevice->TestCooperativeLevel();
465 }
466
467 if (result == D3DERR_DEVICENOTRESET)
468 {
469 result = mDevice->Reset(&presentParameters);
470 }
471 }
472
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000473 lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000474 attempts --;
475 }
476
477 if (FAILED(result))
478 {
479 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
480 return false;
481 }
482
483 // reset device defaults
484 initializeDevice();
485 mDeviceLost = false;
486
487 return true;
488}
489
490void Renderer::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
491{
492 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
493 {
494 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
495 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
496
497 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
498 }
499}
500
501bool Renderer::getDXT1TextureSupport()
502{
503 D3DDISPLAYMODE currentDisplayMode;
504 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
505
506 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
507}
508
509bool Renderer::getDXT3TextureSupport()
510{
511 D3DDISPLAYMODE currentDisplayMode;
512 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
513
514 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
515}
516
517bool Renderer::getDXT5TextureSupport()
518{
519 D3DDISPLAYMODE currentDisplayMode;
520 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
521
522 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
523}
524
525// we use INTZ for depth textures in Direct3D9
526// we also want NULL texture support to ensure the we can make depth-only FBOs
527// see http://aras-p.info/texts/D3D9GPUHacks.html
528bool Renderer::getDepthTextureSupport() const
529{
530 D3DDISPLAYMODE currentDisplayMode;
531 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
532
533 bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
534 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
535 bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
536 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
537
538 return intz && null;
539}
540
541bool Renderer::getFloat32TextureSupport(bool *filtering, bool *renderable)
542{
543 D3DDISPLAYMODE currentDisplayMode;
544 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
545
546 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
547 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
548 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
549 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
550
551 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
552 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
553 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
554 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
555
556 if (!*filtering && !*renderable)
557 {
558 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
559 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
560 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
561 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
562 }
563 else
564 {
565 return true;
566 }
567}
568
569bool Renderer::getFloat16TextureSupport(bool *filtering, bool *renderable)
570{
571 D3DDISPLAYMODE currentDisplayMode;
572 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
573
574 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
575 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
576 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
577 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
578
579 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
580 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
581 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
582 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
583
584 if (!*filtering && !*renderable)
585 {
586 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
587 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
588 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
589 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
590 }
591 else
592 {
593 return true;
594 }
595}
596
597bool Renderer::getLuminanceTextureSupport()
598{
599 D3DDISPLAYMODE currentDisplayMode;
600 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
601
602 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
603}
604
605bool Renderer::getLuminanceAlphaTextureSupport()
606{
607 D3DDISPLAYMODE currentDisplayMode;
608 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
609
610 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
611}
612
613float Renderer::getTextureFilterAnisotropySupport() const
614{
615 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
616 if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
617 {
618 return mDeviceCaps.MaxAnisotropy;
619 }
620 return 1.0f;
621}
622
623bool Renderer::getEventQuerySupport()
624{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000625 IDirect3DQuery9 *query = allocateEventQuery();
626 if (query)
627 {
628 freeEventQuery(query);
629 return true;
630 }
631 else
632 {
633 return false;
634 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000635 return true;
636}
637
638// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
639// We test this using D3D9 by checking support for the R16F format.
640bool Renderer::getVertexTextureSupport() const
641{
642 if (!mDevice || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
643 {
644 return false;
645 }
646
647 D3DDISPLAYMODE currentDisplayMode;
648 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
649
650 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
651
652 return SUCCEEDED(result);
653}
654
655bool Renderer::getNonPower2TextureSupport() const
656{
657 return mSupportsNonPower2Textures;
658}
659
660bool Renderer::getOcclusionQuerySupport() const
661{
662 if (!mDevice)
663 {
664 return false;
665 }
666
667 IDirect3DQuery9 *query = NULL;
668 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
669 if (SUCCEEDED(result) && query)
670 {
671 query->Release();
672 return true;
673 }
674 else
675 {
676 return false;
677 }
678}
679
680bool Renderer::getInstancingSupport() const
681{
682 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
683}
684
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000685bool Renderer::getShareHandleSupport() const
686{
687 // PIX doesn't seem to support using share handles, so disable them.
688 // D3D9_REPLACE
689 return isD3d9ExDevice() && !gl::perfActive();
690}
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000691
692D3DPOOL Renderer::getBufferPool(DWORD usage) const
693{
694 if (mD3d9Ex != NULL)
695 {
696 return D3DPOOL_DEFAULT;
697 }
698 else
699 {
700 if (!(usage & D3DUSAGE_DYNAMIC))
701 {
702 return D3DPOOL_MANAGED;
703 }
704 }
705
706 return D3DPOOL_DEFAULT;
707}
708
709D3DPOOL Renderer::getTexturePool(DWORD usage) const
710{
711 if (mD3d9Ex != NULL)
712 {
713 return D3DPOOL_DEFAULT;
714 }
715 else
716 {
717 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
718 {
719 return D3DPOOL_MANAGED;
720 }
721 }
722
723 return D3DPOOL_DEFAULT;
724}
725
726}