blob: 786b075daf4738c56e60689daeb7d7343a0e411f [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
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
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000299 if (testDeviceLost(false))
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000300 {
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
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000367// set notify to true to broadcast a message to all contexts of the device loss
368bool Renderer::testDeviceLost(bool notify)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000369{
370 bool isLost = false;
371
372 if (mDeviceEx)
373 {
374 isLost = FAILED(mDeviceEx->CheckDeviceState(NULL));
375 }
376 else if (mDevice)
377 {
378 isLost = FAILED(mDevice->TestCooperativeLevel());
379 }
380 else
381 {
382 // No device yet, so no reset required
383 }
384
385 if (isLost)
386 {
387 // ensure we note the device loss --
388 // we'll probably get this done again by markDeviceLost
389 // but best to remember it!
390 // Note that we don't want to clear the device loss status here
391 // -- this needs to be done by resetDevice
392 mDeviceLost = true;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000393 if (notify)
394 {
395 mDisplay->notifyDeviceLost();
396 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000397 }
398
399 return isLost;
400}
401
402bool Renderer::testDeviceResettable()
403{
404 HRESULT status = D3D_OK;
405
406 if (mDeviceEx)
407 {
408 status = mDeviceEx->CheckDeviceState(NULL);
409 }
410 else if (mDevice)
411 {
412 status = mDevice->TestCooperativeLevel();
413 }
414
415 switch (status)
416 {
417 case D3DERR_DEVICENOTRESET:
418 case D3DERR_DEVICEHUNG:
419 return true;
420 default:
421 return false;
422 }
423}
424
425bool Renderer::resetDevice()
426{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000427 releaseDeviceResources();
428
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000429 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
430
431 HRESULT result = D3D_OK;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000432 bool lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000433 int attempts = 3;
434
435 while (lost && attempts > 0)
436 {
437 if (mDeviceEx)
438 {
439 Sleep(500); // Give the graphics driver some CPU time
440 result = mDeviceEx->ResetEx(&presentParameters, NULL);
441 }
442 else
443 {
444 result = mDevice->TestCooperativeLevel();
445 while (result == D3DERR_DEVICELOST)
446 {
447 Sleep(100); // Give the graphics driver some CPU time
448 result = mDevice->TestCooperativeLevel();
449 }
450
451 if (result == D3DERR_DEVICENOTRESET)
452 {
453 result = mDevice->Reset(&presentParameters);
454 }
455 }
456
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000457 lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000458 attempts --;
459 }
460
461 if (FAILED(result))
462 {
463 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
464 return false;
465 }
466
467 // reset device defaults
468 initializeDevice();
469 mDeviceLost = false;
470
471 return true;
472}
473
474void Renderer::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
475{
476 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
477 {
478 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
479 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
480
481 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
482 }
483}
484
485bool Renderer::getDXT1TextureSupport()
486{
487 D3DDISPLAYMODE currentDisplayMode;
488 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
489
490 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
491}
492
493bool Renderer::getDXT3TextureSupport()
494{
495 D3DDISPLAYMODE currentDisplayMode;
496 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
497
498 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
499}
500
501bool Renderer::getDXT5TextureSupport()
502{
503 D3DDISPLAYMODE currentDisplayMode;
504 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
505
506 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
507}
508
509// we use INTZ for depth textures in Direct3D9
510// we also want NULL texture support to ensure the we can make depth-only FBOs
511// see http://aras-p.info/texts/D3D9GPUHacks.html
512bool Renderer::getDepthTextureSupport() const
513{
514 D3DDISPLAYMODE currentDisplayMode;
515 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
516
517 bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
518 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
519 bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
520 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
521
522 return intz && null;
523}
524
525bool Renderer::getFloat32TextureSupport(bool *filtering, bool *renderable)
526{
527 D3DDISPLAYMODE currentDisplayMode;
528 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
529
530 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
531 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
532 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
533 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
534
535 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
536 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
537 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
538 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
539
540 if (!*filtering && !*renderable)
541 {
542 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
543 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
544 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
545 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
546 }
547 else
548 {
549 return true;
550 }
551}
552
553bool Renderer::getFloat16TextureSupport(bool *filtering, bool *renderable)
554{
555 D3DDISPLAYMODE currentDisplayMode;
556 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
557
558 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
559 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
560 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
561 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
562
563 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
564 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
565 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
566 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
567
568 if (!*filtering && !*renderable)
569 {
570 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
571 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
572 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
573 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
574 }
575 else
576 {
577 return true;
578 }
579}
580
581bool Renderer::getLuminanceTextureSupport()
582{
583 D3DDISPLAYMODE currentDisplayMode;
584 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
585
586 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
587}
588
589bool Renderer::getLuminanceAlphaTextureSupport()
590{
591 D3DDISPLAYMODE currentDisplayMode;
592 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
593
594 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
595}
596
597float Renderer::getTextureFilterAnisotropySupport() const
598{
599 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
600 if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2))
601 {
602 return mDeviceCaps.MaxAnisotropy;
603 }
604 return 1.0f;
605}
606
607bool Renderer::getEventQuerySupport()
608{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000609 IDirect3DQuery9 *query = allocateEventQuery();
610 if (query)
611 {
612 freeEventQuery(query);
613 return true;
614 }
615 else
616 {
617 return false;
618 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000619 return true;
620}
621
622// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
623// We test this using D3D9 by checking support for the R16F format.
624bool Renderer::getVertexTextureSupport() const
625{
626 if (!mDevice || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
627 {
628 return false;
629 }
630
631 D3DDISPLAYMODE currentDisplayMode;
632 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
633
634 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
635
636 return SUCCEEDED(result);
637}
638
639bool Renderer::getNonPower2TextureSupport() const
640{
641 return mSupportsNonPower2Textures;
642}
643
644bool Renderer::getOcclusionQuerySupport() const
645{
646 if (!mDevice)
647 {
648 return false;
649 }
650
651 IDirect3DQuery9 *query = NULL;
652 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
653 if (SUCCEEDED(result) && query)
654 {
655 query->Release();
656 return true;
657 }
658 else
659 {
660 return false;
661 }
662}
663
664bool Renderer::getInstancingSupport() const
665{
666 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
667}
668
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000669bool Renderer::getShareHandleSupport() const
670{
671 // PIX doesn't seem to support using share handles, so disable them.
672 // D3D9_REPLACE
673 return isD3d9ExDevice() && !gl::perfActive();
674}
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000675
676D3DPOOL Renderer::getBufferPool(DWORD usage) const
677{
678 if (mD3d9Ex != NULL)
679 {
680 return D3DPOOL_DEFAULT;
681 }
682 else
683 {
684 if (!(usage & D3DUSAGE_DYNAMIC))
685 {
686 return D3DPOOL_MANAGED;
687 }
688 }
689
690 return D3DPOOL_DEFAULT;
691}
692
693D3DPOOL Renderer::getTexturePool(DWORD usage) const
694{
695 if (mD3d9Ex != NULL)
696 {
697 return D3DPOOL_DEFAULT;
698 }
699 else
700 {
701 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
702 {
703 return D3DPOOL_MANAGED;
704 }
705 }
706
707 return D3DPOOL_DEFAULT;
708}
709
710}