blob: 8afe33aad358d30f4ede01367e369288484581be [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
daniel@transgaming.com621ce052012-10-31 17:52:29 +000010#include "common/debug.h"
11#include "libGLESv2/utilities.h"
daniel@transgaming.com2507f412012-10-31 18:46:48 +000012#include "libGLESv2/renderer/Renderer9.h"
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000013#include "libGLESv2/renderer/renderer9_utils.h"
daniel@transgaming.com9d4346f2012-10-31 19:52:04 +000014#include "libGLESv2/renderer/TextureStorage.h"
daniel@transgaming.com621ce052012-10-31 17:52:29 +000015
daniel@transgaming.com3281f972012-10-31 18:38:51 +000016#include "libEGL/Config.h"
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000017#include "libEGL/Display.h"
18
daniel@transgaming.com621ce052012-10-31 17:52:29 +000019// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
20#define REF_RAST 0
21
22// The "Debug This Pixel..." feature in PIX often fails when using the
23// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
24// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
25#if !defined(ANGLE_ENABLE_D3D9EX)
26// Enables use of the IDirect3D9Ex interface, when available
27#define ANGLE_ENABLE_D3D9EX 1
28#endif // !defined(ANGLE_ENABLE_D3D9EX)
29
30namespace renderer
31{
daniel@transgaming.com2507f412012-10-31 18:46:48 +000032const D3DFORMAT Renderer9::mRenderTargetFormats[] =
daniel@transgaming.com92955622012-10-31 18:38:41 +000033 {
34 D3DFMT_A1R5G5B5,
35 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
36 D3DFMT_A8R8G8B8,
37 D3DFMT_R5G6B5,
38 // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
39 D3DFMT_X8R8G8B8
40 };
41
daniel@transgaming.com2507f412012-10-31 18:46:48 +000042const D3DFORMAT Renderer9::mDepthStencilFormats[] =
daniel@transgaming.com92955622012-10-31 18:38:41 +000043 {
44 D3DFMT_UNKNOWN,
45 // D3DFMT_D16_LOCKABLE,
46 D3DFMT_D32,
47 // D3DFMT_D15S1,
48 D3DFMT_D24S8,
49 D3DFMT_D24X8,
50 // D3DFMT_D24X4S4,
51 D3DFMT_D16,
52 // D3DFMT_D32F_LOCKABLE,
53 // D3DFMT_D24FS8
54 };
daniel@transgaming.com621ce052012-10-31 17:52:29 +000055
daniel@transgaming.com2507f412012-10-31 18:46:48 +000056Renderer9::Renderer9(egl::Display *display, HMODULE hModule, HDC hDc) : Renderer(display), mDc(hDc)
daniel@transgaming.com621ce052012-10-31 17:52:29 +000057{
58 mD3d9Module = hModule;
59
60 mD3d9 = NULL;
61 mD3d9Ex = NULL;
62 mDevice = NULL;
63 mDeviceEx = NULL;
64 mDeviceWindow = NULL;
65
66 mAdapter = D3DADAPTER_DEFAULT;
67
68 #if REF_RAST == 1 || defined(FORCE_REF_RAST)
69 mDeviceType = D3DDEVTYPE_REF;
70 #else
71 mDeviceType = D3DDEVTYPE_HAL;
72 #endif
73
74 mDeviceLost = false;
daniel@transgaming.comb7833982012-10-31 18:31:46 +000075
76 mMaxSupportedSamples = 0;
daniel@transgaming.com621ce052012-10-31 17:52:29 +000077}
78
daniel@transgaming.com2507f412012-10-31 18:46:48 +000079Renderer9::~Renderer9()
daniel@transgaming.com621ce052012-10-31 17:52:29 +000080{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +000081 releaseDeviceResources();
82
daniel@transgaming.com621ce052012-10-31 17:52:29 +000083 if (mDevice)
84 {
85 // 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 +000086 if (testDeviceLost(false))
daniel@transgaming.com621ce052012-10-31 17:52:29 +000087 {
88 resetDevice();
89 }
90
91 mDevice->Release();
92 mDevice = NULL;
93 }
94
95 if (mDeviceEx)
96 {
97 mDeviceEx->Release();
98 mDeviceEx = NULL;
99 }
100
101 if (mD3d9)
102 {
103 mD3d9->Release();
104 mD3d9 = NULL;
105 }
106
107 if (mDeviceWindow)
108 {
109 DestroyWindow(mDeviceWindow);
110 mDeviceWindow = NULL;
111 }
112
113 if (mD3d9Ex)
114 {
115 mD3d9Ex->Release();
116 mD3d9Ex = NULL;
117 }
118
119 if (mD3d9Module)
120 {
121 mD3d9Module = NULL;
122 }
123
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000124 while (!mMultiSampleSupport.empty())
125 {
126 delete [] mMultiSampleSupport.begin()->second;
127 mMultiSampleSupport.erase(mMultiSampleSupport.begin());
128 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000129}
130
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000131EGLint Renderer9::initialize()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000132{
133 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
134 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
135
136 // Use Direct3D9Ex if available. Among other things, this version is less
137 // inclined to report a lost context, for example when the user switches
138 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
139 if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
140 {
141 ASSERT(mD3d9Ex);
142 mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
143 ASSERT(mD3d9);
144 }
145 else
146 {
147 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
148 }
149
150 if (!mD3d9)
151 {
152 ERR("Could not create D3D9 device - aborting!\n");
153 return EGL_NOT_INITIALIZED;
154 }
155 if (mDc != NULL)
156 {
157 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
158 }
159
160 HRESULT result;
161
162 // Give up on getting device caps after about one second.
163 for (int i = 0; i < 10; ++i)
164 {
165 result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
166 if (SUCCEEDED(result))
167 {
168 break;
169 }
170 else if (result == D3DERR_NOTAVAILABLE)
171 {
172 Sleep(100); // Give the driver some time to initialize/recover
173 }
174 else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
175 {
176 ERR("failed to get device caps (0x%x)\n", result);
177 return EGL_NOT_INITIALIZED;
178 }
179 }
180
181 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
182 {
183 ERR("Renderer does not support PS 2.0. aborting!\n");
184 return EGL_NOT_INITIALIZED;
185 }
186
187 // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
188 // This is required by Texture2D::convertToRenderTarget.
189 if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
190 {
191 ERR("Renderer does not support stretctrect from textures!\n");
192 return EGL_NOT_INITIALIZED;
193 }
194
195 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
196
197 // ATI cards on XP have problems with non-power-of-two textures.
198 mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
199 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
200 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
201 !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
202
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000203 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
204 mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
205
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000206 mMinSwapInterval = 4;
207 mMaxSwapInterval = 0;
208
209 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
210 {
211 mMinSwapInterval = std::min(mMinSwapInterval, 0);
212 mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
213 }
214 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
215 {
216 mMinSwapInterval = std::min(mMinSwapInterval, 1);
217 mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
218 }
219 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
220 {
221 mMinSwapInterval = std::min(mMinSwapInterval, 2);
222 mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
223 }
224 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
225 {
226 mMinSwapInterval = std::min(mMinSwapInterval, 3);
227 mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
228 }
229 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
230 {
231 mMinSwapInterval = std::min(mMinSwapInterval, 4);
232 mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
233 }
234
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000235 int max = 0;
daniel@transgaming.com92955622012-10-31 18:38:41 +0000236 for (int i = 0; i < sizeof(mRenderTargetFormats) / sizeof(D3DFORMAT); ++i)
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000237 {
238 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
daniel@transgaming.com92955622012-10-31 18:38:41 +0000239 getMultiSampleSupport(mRenderTargetFormats[i], multisampleArray);
240 mMultiSampleSupport[mRenderTargetFormats[i]] = multisampleArray;
241
242 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
243 {
244 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
245 {
246 max = j;
247 }
248 }
249 }
250
251 for (int i = 0; i < sizeof(mDepthStencilFormats) / sizeof(D3DFORMAT); ++i)
252 {
253 if (mDepthStencilFormats[i] == D3DFMT_UNKNOWN)
254 continue;
255
256 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
257 getMultiSampleSupport(mDepthStencilFormats[i], multisampleArray);
258 mMultiSampleSupport[mDepthStencilFormats[i]] = multisampleArray;
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000259
260 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
261 {
262 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
263 {
264 max = j;
265 }
266 }
267 }
268
269 mMaxSupportedSamples = max;
270
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000271 static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
272 static const TCHAR className[] = TEXT("STATIC");
273
274 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
275
276 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
277 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
278
279 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
280 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
281 {
282 return EGL_BAD_ALLOC;
283 }
284
285 if (FAILED(result))
286 {
287 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
288
289 if (FAILED(result))
290 {
291 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
292 return EGL_BAD_ALLOC;
293 }
294 }
295
296 if (mD3d9Ex)
297 {
298 result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
299 ASSERT(SUCCEEDED(result));
300 }
301
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000302 mVertexShaderCache.initialize(mDevice);
303 mPixelShaderCache.initialize(mDevice);
304
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000305 initializeDevice();
306
307 return EGL_SUCCESS;
308}
309
310// do any one-time device initialization
311// NOTE: this is also needed after a device lost/reset
312// to reset the scene status and ensure the default states are reset.
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000313void Renderer9::initializeDevice()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000314{
315 // Permanent non-default states
316 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
317 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
318
319 if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
320 {
321 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
322 }
323 else
324 {
325 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
326 }
327
328 mSceneStarted = false;
329}
330
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000331D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000332{
333 D3DPRESENT_PARAMETERS presentParameters = {0};
334
335 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
336 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
337 presentParameters.BackBufferCount = 1;
338 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
339 presentParameters.BackBufferWidth = 1;
340 presentParameters.BackBufferHeight = 1;
341 presentParameters.EnableAutoDepthStencil = FALSE;
342 presentParameters.Flags = 0;
343 presentParameters.hDeviceWindow = mDeviceWindow;
344 presentParameters.MultiSampleQuality = 0;
345 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
346 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
347 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
348 presentParameters.Windowed = TRUE;
349
350 return presentParameters;
351}
352
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000353int Renderer9::generateConfigs(ConfigDesc **configDescList)
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000354{
355 D3DDISPLAYMODE currentDisplayMode;
356 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
357
358 int numRenderFormats = sizeof(mRenderTargetFormats) / sizeof(mRenderTargetFormats[0]);
359 int numDepthFormats = sizeof(mDepthStencilFormats) / sizeof(mDepthStencilFormats[0]);
360 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
361 int numConfigs = 0;
362
363 for (int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
364 {
365 D3DFORMAT renderTargetFormat = mRenderTargetFormats[formatIndex];
366
367 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
368
369 if (SUCCEEDED(result))
370 {
371 for (int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
372 {
373 D3DFORMAT depthStencilFormat = mDepthStencilFormats[depthStencilIndex];
374 HRESULT result = D3D_OK;
375
376 if(depthStencilFormat != D3DFMT_UNKNOWN)
377 {
378 result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
379 }
380
381 if (SUCCEEDED(result))
382 {
383 if(depthStencilFormat != D3DFMT_UNKNOWN)
384 {
385 result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
386 }
387
388 if (SUCCEEDED(result))
389 {
390 ConfigDesc newConfig;
391 newConfig.renderTargetFormat = dx2es::ConvertBackBufferFormat(renderTargetFormat);
392 newConfig.depthStencilFormat = dx2es::ConvertDepthStencilFormat(depthStencilFormat);
393 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
394 newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
395
396 (*configDescList)[numConfigs++] = newConfig;
397 }
398 }
399 }
400 }
401 }
402
403 return numConfigs;
404}
405
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000406void Renderer9::deleteConfigs(ConfigDesc *configDescList)
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000407{
408 delete [] (configDescList);
409}
410
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000411void Renderer9::startScene()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000412{
413 if (!mSceneStarted)
414 {
415 long result = mDevice->BeginScene();
416 if (SUCCEEDED(result)) {
417 // This is defensive checking against the device being
418 // lost at unexpected times.
419 mSceneStarted = true;
420 }
421 }
422}
423
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000424void Renderer9::endScene()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000425{
426 if (mSceneStarted)
427 {
428 // EndScene can fail if the device was lost, for example due
429 // to a TDR during a draw call.
430 mDevice->EndScene();
431 mSceneStarted = false;
432 }
433}
434
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000435// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000436void Renderer9::sync(bool block)
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000437{
438 HRESULT result;
439
440 IDirect3DQuery9* query = allocateEventQuery();
441 if (!query)
442 {
443 return;
444 }
445
446 result = query->Issue(D3DISSUE_END);
447 ASSERT(SUCCEEDED(result));
448
449 do
450 {
451 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
452
453 if(block && result == S_FALSE)
454 {
455 // Keep polling, but allow other threads to do something useful first
456 Sleep(0);
457 // explicitly check for device loss
458 // some drivers seem to return S_FALSE even if the device is lost
459 // instead of D3DERR_DEVICELOST like they should
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000460 if (testDeviceLost(false))
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000461 {
462 result = D3DERR_DEVICELOST;
463 }
464 }
465 }
466 while(block && result == S_FALSE);
467
468 freeEventQuery(query);
469
470 if (isDeviceLostError(result))
471 {
472 mDisplay->notifyDeviceLost();
473 }
474}
475
476// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000477IDirect3DQuery9* Renderer9::allocateEventQuery()
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000478{
479 IDirect3DQuery9 *query = NULL;
480
481 if (mEventQueryPool.empty())
482 {
483 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
484 ASSERT(SUCCEEDED(result));
485 }
486 else
487 {
488 query = mEventQueryPool.back();
489 mEventQueryPool.pop_back();
490 }
491
492 return query;
493}
494
495// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000496void Renderer9::freeEventQuery(IDirect3DQuery9* query)
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000497{
498 if (mEventQueryPool.size() > 1000)
499 {
500 query->Release();
501 }
502 else
503 {
504 mEventQueryPool.push_back(query);
505 }
506}
507
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000508IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000509{
510 return mVertexShaderCache.create(function, length);
511}
512
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000513IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000514{
515 return mPixelShaderCache.create(function, length);
516}
517
daniel@transgaming.com113f0eb2012-10-31 18:46:58 +0000518HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
519{
520 D3DPOOL Pool = getBufferPool(Usage);
521 return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
522}
523
524HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
525{
526 D3DPOOL Pool = getBufferPool(Usage);
527 return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
528}
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000529
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000530void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000531{
532 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
533 int d3dSampler = index + d3dSamplerOffset;
534
535 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(samplerState.wrapS));
536 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(samplerState.wrapT));
537
538 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
539 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
540 es2dx::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
541 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
542 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
543 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
544 if (mSupportsTextureFilterAnisotropy)
545 {
546 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
547 }
548}
549
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000550void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
daniel@transgaming.coma734f272012-10-31 18:07:48 +0000551{
552 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
553 int d3dSampler = index + d3dSamplerOffset;
554 IDirect3DBaseTexture9 *d3dTexture = NULL;
555
556 if (texture)
557 {
daniel@transgaming.com9d4346f2012-10-31 19:52:04 +0000558 gl::TextureStorage *texStorage = texture->getNativeTexture();
559 if (texStorage)
560 {
561 d3dTexture = texStorage->getBaseTexture();
562 }
563 // If we get NULL back from getBaseTexture here, something went wrong
daniel@transgaming.coma734f272012-10-31 18:07:48 +0000564 // in the texture class and we're unexpectedly missing the d3d texture
565 ASSERT(d3dTexture != NULL);
566 }
567
568 mDevice->SetTexture(d3dSampler, d3dTexture);
569}
570
571
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000572void Renderer9::releaseDeviceResources()
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000573{
574 while (!mEventQueryPool.empty())
575 {
576 mEventQueryPool.back()->Release();
577 mEventQueryPool.pop_back();
578 }
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000579
580 mVertexShaderCache.clear();
581 mPixelShaderCache.clear();
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000582}
583
584
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000585void Renderer9::markDeviceLost()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000586{
587 mDeviceLost = true;
588}
589
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000590bool Renderer9::isDeviceLost()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000591{
592 return mDeviceLost;
593}
594
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000595// set notify to true to broadcast a message to all contexts of the device loss
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000596bool Renderer9::testDeviceLost(bool notify)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000597{
598 bool isLost = false;
599
600 if (mDeviceEx)
601 {
602 isLost = FAILED(mDeviceEx->CheckDeviceState(NULL));
603 }
604 else if (mDevice)
605 {
606 isLost = FAILED(mDevice->TestCooperativeLevel());
607 }
608 else
609 {
610 // No device yet, so no reset required
611 }
612
613 if (isLost)
614 {
615 // ensure we note the device loss --
616 // we'll probably get this done again by markDeviceLost
617 // but best to remember it!
618 // Note that we don't want to clear the device loss status here
619 // -- this needs to be done by resetDevice
620 mDeviceLost = true;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000621 if (notify)
622 {
623 mDisplay->notifyDeviceLost();
624 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000625 }
626
627 return isLost;
628}
629
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000630bool Renderer9::testDeviceResettable()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000631{
632 HRESULT status = D3D_OK;
633
634 if (mDeviceEx)
635 {
636 status = mDeviceEx->CheckDeviceState(NULL);
637 }
638 else if (mDevice)
639 {
640 status = mDevice->TestCooperativeLevel();
641 }
642
643 switch (status)
644 {
645 case D3DERR_DEVICENOTRESET:
646 case D3DERR_DEVICEHUNG:
647 return true;
648 default:
649 return false;
650 }
651}
652
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000653bool Renderer9::resetDevice()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000654{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000655 releaseDeviceResources();
656
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000657 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
658
659 HRESULT result = D3D_OK;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000660 bool lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000661 int attempts = 3;
662
663 while (lost && attempts > 0)
664 {
665 if (mDeviceEx)
666 {
667 Sleep(500); // Give the graphics driver some CPU time
668 result = mDeviceEx->ResetEx(&presentParameters, NULL);
669 }
670 else
671 {
672 result = mDevice->TestCooperativeLevel();
673 while (result == D3DERR_DEVICELOST)
674 {
675 Sleep(100); // Give the graphics driver some CPU time
676 result = mDevice->TestCooperativeLevel();
677 }
678
679 if (result == D3DERR_DEVICENOTRESET)
680 {
681 result = mDevice->Reset(&presentParameters);
682 }
683 }
684
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000685 lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000686 attempts --;
687 }
688
689 if (FAILED(result))
690 {
691 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
692 return false;
693 }
694
695 // reset device defaults
696 initializeDevice();
697 mDeviceLost = false;
698
699 return true;
700}
701
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000702DWORD Renderer9::getAdapterVendor() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000703{
704 return mAdapterIdentifier.VendorId;
705}
706
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000707const char *Renderer9::getAdapterDescription() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000708{
709 return mAdapterIdentifier.Description;
710}
711
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000712GUID Renderer9::getAdapterIdentifier() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000713{
714 return mAdapterIdentifier.DeviceIdentifier;
715}
716
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000717void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000718{
719 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
720 {
721 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
722 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
723
724 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
725 }
726}
727
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000728bool Renderer9::getDXT1TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000729{
730 D3DDISPLAYMODE currentDisplayMode;
731 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
732
733 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
734}
735
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000736bool Renderer9::getDXT3TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000737{
738 D3DDISPLAYMODE currentDisplayMode;
739 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
740
741 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
742}
743
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000744bool Renderer9::getDXT5TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000745{
746 D3DDISPLAYMODE currentDisplayMode;
747 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
748
749 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
750}
751
752// we use INTZ for depth textures in Direct3D9
753// we also want NULL texture support to ensure the we can make depth-only FBOs
754// see http://aras-p.info/texts/D3D9GPUHacks.html
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000755bool Renderer9::getDepthTextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000756{
757 D3DDISPLAYMODE currentDisplayMode;
758 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
759
760 bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
761 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
762 bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
763 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
764
765 return intz && null;
766}
767
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000768bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000769{
770 D3DDISPLAYMODE currentDisplayMode;
771 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
772
773 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
774 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
775 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
776 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
777
778 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
779 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
780 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
781 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
782
783 if (!*filtering && !*renderable)
784 {
785 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
786 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
787 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
788 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
789 }
790 else
791 {
792 return true;
793 }
794}
795
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000796bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000797{
798 D3DDISPLAYMODE currentDisplayMode;
799 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
800
801 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
802 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
803 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
804 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
805
806 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
807 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
808 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
809 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
810
811 if (!*filtering && !*renderable)
812 {
813 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
814 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
815 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
816 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
817 }
818 else
819 {
820 return true;
821 }
822}
823
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000824bool Renderer9::getLuminanceTextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000825{
826 D3DDISPLAYMODE currentDisplayMode;
827 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
828
829 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
830}
831
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000832bool Renderer9::getLuminanceAlphaTextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000833{
834 D3DDISPLAYMODE currentDisplayMode;
835 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
836
837 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
838}
839
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000840bool Renderer9::getTextureFilterAnisotropySupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000841{
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000842 return mSupportsTextureFilterAnisotropy;
843}
844
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000845float Renderer9::getTextureMaxAnisotropy() const
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000846{
847 if (mSupportsTextureFilterAnisotropy)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000848 {
849 return mDeviceCaps.MaxAnisotropy;
850 }
851 return 1.0f;
852}
853
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000854bool Renderer9::getEventQuerySupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000855{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000856 IDirect3DQuery9 *query = allocateEventQuery();
857 if (query)
858 {
859 freeEventQuery(query);
860 return true;
861 }
862 else
863 {
864 return false;
865 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000866 return true;
867}
868
869// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
870// We test this using D3D9 by checking support for the R16F format.
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000871bool Renderer9::getVertexTextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000872{
873 if (!mDevice || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
874 {
875 return false;
876 }
877
878 D3DDISPLAYMODE currentDisplayMode;
879 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
880
881 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
882
883 return SUCCEEDED(result);
884}
885
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000886bool Renderer9::getNonPower2TextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000887{
888 return mSupportsNonPower2Textures;
889}
890
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000891bool Renderer9::getOcclusionQuerySupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000892{
893 if (!mDevice)
894 {
895 return false;
896 }
897
898 IDirect3DQuery9 *query = NULL;
899 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
900 if (SUCCEEDED(result) && query)
901 {
902 query->Release();
903 return true;
904 }
905 else
906 {
907 return false;
908 }
909}
910
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000911bool Renderer9::getInstancingSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000912{
913 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
914}
915
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000916bool Renderer9::getShareHandleSupport() const
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000917{
918 // PIX doesn't seem to support using share handles, so disable them.
919 // D3D9_REPLACE
daniel@transgaming.com7cb796e2012-10-31 18:46:44 +0000920 return (mD3d9Ex != NULL) && !gl::perfActive();
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000921}
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000922
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000923bool Renderer9::getShaderModel3Support() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000924{
925 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
926}
927
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000928float Renderer9::getMaxPointSize() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000929{
930 return mDeviceCaps.MaxPointSize;
931}
932
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000933int Renderer9::getMaxTextureWidth() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000934{
935 return (int)mDeviceCaps.MaxTextureWidth;
936}
937
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000938int Renderer9::getMaxTextureHeight() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000939{
940 return (int)mDeviceCaps.MaxTextureHeight;
941}
942
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000943bool Renderer9::get32BitIndexSupport() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000944{
945 return mDeviceCaps.MaxVertexIndex >= (1 << 16);
946}
947
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000948DWORD Renderer9::getCapsDeclTypes() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000949{
950 return mDeviceCaps.DeclTypes;
951}
952
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000953int Renderer9::getMinSwapInterval() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000954{
955 return mMinSwapInterval;
956}
957
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000958int Renderer9::getMaxSwapInterval() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000959{
960 return mMaxSwapInterval;
961}
962
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000963int Renderer9::getMaxSupportedSamples() const
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000964{
965 return mMaxSupportedSamples;
966}
967
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000968int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000969{
970 if (requested == 0)
971 {
972 return requested;
973 }
974
975 std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
976 if (itr == mMultiSampleSupport.end())
977 {
daniel@transgaming.com92955622012-10-31 18:38:41 +0000978 if (format == D3DFMT_UNKNOWN)
979 return 0;
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000980 return -1;
981 }
982
983 for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
984 {
985 if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
986 {
987 return i;
988 }
989 }
990
991 return -1;
992}
993
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000994D3DPOOL Renderer9::getBufferPool(DWORD usage) const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000995{
996 if (mD3d9Ex != NULL)
997 {
998 return D3DPOOL_DEFAULT;
999 }
1000 else
1001 {
1002 if (!(usage & D3DUSAGE_DYNAMIC))
1003 {
1004 return D3DPOOL_MANAGED;
1005 }
1006 }
1007
1008 return D3DPOOL_DEFAULT;
1009}
1010
daniel@transgaming.com2507f412012-10-31 18:46:48 +00001011D3DPOOL Renderer9::getTexturePool(DWORD usage) const
daniel@transgaming.com621ce052012-10-31 17:52:29 +00001012{
1013 if (mD3d9Ex != NULL)
1014 {
1015 return D3DPOOL_DEFAULT;
1016 }
1017 else
1018 {
1019 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
1020 {
1021 return D3DPOOL_MANAGED;
1022 }
1023 }
1024
1025 return D3DPOOL_DEFAULT;
1026}
1027
1028}