blob: 5e128b7d98b50be6ba9f4c5647a4f3c93091508e [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
daniel@transgaming.com1d6aff22012-11-28 19:30:42 +00007// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
daniel@transgaming.com621ce052012-10-31 17:52:29 +00008
daniel@transgaming.com621ce052012-10-31 17:52:29 +00009#include "common/debug.h"
10#include "libGLESv2/utilities.h"
daniel@transgaming.com2507f412012-10-31 18:46:48 +000011#include "libGLESv2/renderer/Renderer9.h"
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000012#include "libGLESv2/renderer/renderer9_utils.h"
daniel@transgaming.com9d4346f2012-10-31 19:52:04 +000013#include "libGLESv2/renderer/TextureStorage.h"
daniel@transgaming.com1d80eee2012-11-28 19:33:31 +000014#include "libGLESv2/renderer/Image.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
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000030namespace rx
daniel@transgaming.com621ce052012-10-31 17:52:29 +000031{
daniel@transgaming.com222ee082012-11-28 19:31:49 +000032static const D3DFORMAT RenderTargetFormats[] =
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.com222ee082012-11-28 19:31:49 +000042static const D3DFORMAT DepthStencilFormats[] =
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.com95ffbc12012-10-31 19:55:27 +000056Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
daniel@transgaming.com621ce052012-10-31 17:52:29 +000057{
daniel@transgaming.com95ffbc12012-10-31 19:55:27 +000058 mD3d9Module = NULL;
daniel@transgaming.com621ce052012-10-31 17:52:29 +000059
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{
daniel@transgaming.com95ffbc12012-10-31 19:55:27 +0000133 if (mSoftwareDevice)
134 {
135 mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
136 }
137 else
138 {
139 mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
140 }
141
142 if (mD3d9Module == NULL)
143 {
144 ERR("No D3D9 module found - aborting!\n");
145 return EGL_NOT_INITIALIZED;
146 }
147
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000148 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
149 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
150
151 // Use Direct3D9Ex if available. Among other things, this version is less
152 // inclined to report a lost context, for example when the user switches
153 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
154 if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
155 {
156 ASSERT(mD3d9Ex);
157 mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
158 ASSERT(mD3d9);
159 }
160 else
161 {
162 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
163 }
164
165 if (!mD3d9)
166 {
167 ERR("Could not create D3D9 device - aborting!\n");
168 return EGL_NOT_INITIALIZED;
169 }
170 if (mDc != NULL)
171 {
172 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
173 }
174
175 HRESULT result;
176
177 // Give up on getting device caps after about one second.
178 for (int i = 0; i < 10; ++i)
179 {
180 result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
181 if (SUCCEEDED(result))
182 {
183 break;
184 }
185 else if (result == D3DERR_NOTAVAILABLE)
186 {
187 Sleep(100); // Give the driver some time to initialize/recover
188 }
189 else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
190 {
191 ERR("failed to get device caps (0x%x)\n", result);
192 return EGL_NOT_INITIALIZED;
193 }
194 }
195
196 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
197 {
198 ERR("Renderer does not support PS 2.0. aborting!\n");
199 return EGL_NOT_INITIALIZED;
200 }
201
202 // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
203 // This is required by Texture2D::convertToRenderTarget.
204 if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
205 {
206 ERR("Renderer does not support stretctrect from textures!\n");
207 return EGL_NOT_INITIALIZED;
208 }
209
210 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
211
212 // ATI cards on XP have problems with non-power-of-two textures.
213 mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
214 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
215 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
216 !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
217
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000218 // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
219 mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
220
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000221 mMinSwapInterval = 4;
222 mMaxSwapInterval = 0;
223
224 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
225 {
226 mMinSwapInterval = std::min(mMinSwapInterval, 0);
227 mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
228 }
229 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
230 {
231 mMinSwapInterval = std::min(mMinSwapInterval, 1);
232 mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
233 }
234 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
235 {
236 mMinSwapInterval = std::min(mMinSwapInterval, 2);
237 mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
238 }
239 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
240 {
241 mMinSwapInterval = std::min(mMinSwapInterval, 3);
242 mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
243 }
244 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
245 {
246 mMinSwapInterval = std::min(mMinSwapInterval, 4);
247 mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
248 }
249
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000250 int max = 0;
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000251 for (int i = 0; i < sizeof(RenderTargetFormats) / sizeof(D3DFORMAT); ++i)
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000252 {
253 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000254 getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
255 mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
daniel@transgaming.com92955622012-10-31 18:38:41 +0000256
257 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
258 {
259 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
260 {
261 max = j;
262 }
263 }
264 }
265
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000266 for (int i = 0; i < sizeof(DepthStencilFormats) / sizeof(D3DFORMAT); ++i)
daniel@transgaming.com92955622012-10-31 18:38:41 +0000267 {
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000268 if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
daniel@transgaming.com92955622012-10-31 18:38:41 +0000269 continue;
270
271 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000272 getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
273 mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000274
275 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
276 {
277 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
278 {
279 max = j;
280 }
281 }
282 }
283
284 mMaxSupportedSamples = max;
285
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000286 static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
287 static const TCHAR className[] = TEXT("STATIC");
288
289 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
290
291 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
292 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
293
294 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
295 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
296 {
297 return EGL_BAD_ALLOC;
298 }
299
300 if (FAILED(result))
301 {
302 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
303
304 if (FAILED(result))
305 {
306 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
307 return EGL_BAD_ALLOC;
308 }
309 }
310
311 if (mD3d9Ex)
312 {
313 result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
314 ASSERT(SUCCEEDED(result));
315 }
316
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000317 mVertexShaderCache.initialize(mDevice);
318 mPixelShaderCache.initialize(mDevice);
319
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000320 initializeDevice();
321
322 return EGL_SUCCESS;
323}
324
325// do any one-time device initialization
326// NOTE: this is also needed after a device lost/reset
327// to reset the scene status and ensure the default states are reset.
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000328void Renderer9::initializeDevice()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000329{
330 // Permanent non-default states
331 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
332 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
333
334 if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
335 {
336 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
337 }
338 else
339 {
340 mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
341 }
342
343 mSceneStarted = false;
344}
345
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000346D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000347{
348 D3DPRESENT_PARAMETERS presentParameters = {0};
349
350 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
351 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
352 presentParameters.BackBufferCount = 1;
353 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
354 presentParameters.BackBufferWidth = 1;
355 presentParameters.BackBufferHeight = 1;
356 presentParameters.EnableAutoDepthStencil = FALSE;
357 presentParameters.Flags = 0;
358 presentParameters.hDeviceWindow = mDeviceWindow;
359 presentParameters.MultiSampleQuality = 0;
360 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
361 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
362 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
363 presentParameters.Windowed = TRUE;
364
365 return presentParameters;
366}
367
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000368int Renderer9::generateConfigs(ConfigDesc **configDescList)
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000369{
370 D3DDISPLAYMODE currentDisplayMode;
371 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
372
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000373 int numRenderFormats = sizeof(RenderTargetFormats) / sizeof(RenderTargetFormats[0]);
374 int numDepthFormats = sizeof(DepthStencilFormats) / sizeof(DepthStencilFormats[0]);
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000375 (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
376 int numConfigs = 0;
377
378 for (int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
379 {
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000380 D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000381
382 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
383
384 if (SUCCEEDED(result))
385 {
386 for (int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
387 {
daniel@transgaming.com222ee082012-11-28 19:31:49 +0000388 D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000389 HRESULT result = D3D_OK;
390
391 if(depthStencilFormat != D3DFMT_UNKNOWN)
392 {
393 result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
394 }
395
396 if (SUCCEEDED(result))
397 {
398 if(depthStencilFormat != D3DFMT_UNKNOWN)
399 {
400 result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
401 }
402
403 if (SUCCEEDED(result))
404 {
405 ConfigDesc newConfig;
406 newConfig.renderTargetFormat = dx2es::ConvertBackBufferFormat(renderTargetFormat);
407 newConfig.depthStencilFormat = dx2es::ConvertDepthStencilFormat(depthStencilFormat);
408 newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
409 newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
410
411 (*configDescList)[numConfigs++] = newConfig;
412 }
413 }
414 }
415 }
416 }
417
418 return numConfigs;
419}
420
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000421void Renderer9::deleteConfigs(ConfigDesc *configDescList)
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000422{
423 delete [] (configDescList);
424}
425
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000426void Renderer9::startScene()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000427{
428 if (!mSceneStarted)
429 {
430 long result = mDevice->BeginScene();
431 if (SUCCEEDED(result)) {
432 // This is defensive checking against the device being
433 // lost at unexpected times.
434 mSceneStarted = true;
435 }
436 }
437}
438
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000439void Renderer9::endScene()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000440{
441 if (mSceneStarted)
442 {
443 // EndScene can fail if the device was lost, for example due
444 // to a TDR during a draw call.
445 mDevice->EndScene();
446 mSceneStarted = false;
447 }
448}
449
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000450// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000451void Renderer9::sync(bool block)
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000452{
453 HRESULT result;
454
455 IDirect3DQuery9* query = allocateEventQuery();
456 if (!query)
457 {
458 return;
459 }
460
461 result = query->Issue(D3DISSUE_END);
462 ASSERT(SUCCEEDED(result));
463
464 do
465 {
466 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
467
468 if(block && result == S_FALSE)
469 {
470 // Keep polling, but allow other threads to do something useful first
471 Sleep(0);
472 // explicitly check for device loss
473 // some drivers seem to return S_FALSE even if the device is lost
474 // instead of D3DERR_DEVICELOST like they should
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000475 if (testDeviceLost(false))
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000476 {
477 result = D3DERR_DEVICELOST;
478 }
479 }
480 }
481 while(block && result == S_FALSE);
482
483 freeEventQuery(query);
484
485 if (isDeviceLostError(result))
486 {
487 mDisplay->notifyDeviceLost();
488 }
489}
490
491// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000492IDirect3DQuery9* Renderer9::allocateEventQuery()
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000493{
494 IDirect3DQuery9 *query = NULL;
495
496 if (mEventQueryPool.empty())
497 {
498 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
499 ASSERT(SUCCEEDED(result));
500 }
501 else
502 {
503 query = mEventQueryPool.back();
504 mEventQueryPool.pop_back();
505 }
506
507 return query;
508}
509
510// D3D9_REPLACE
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000511void Renderer9::freeEventQuery(IDirect3DQuery9* query)
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000512{
513 if (mEventQueryPool.size() > 1000)
514 {
515 query->Release();
516 }
517 else
518 {
519 mEventQueryPool.push_back(query);
520 }
521}
522
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000523IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000524{
525 return mVertexShaderCache.create(function, length);
526}
527
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000528IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000529{
530 return mPixelShaderCache.create(function, length);
531}
532
daniel@transgaming.com113f0eb2012-10-31 18:46:58 +0000533HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
534{
535 D3DPOOL Pool = getBufferPool(Usage);
536 return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
537}
538
539HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
540{
541 D3DPOOL Pool = getBufferPool(Usage);
542 return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
543}
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000544
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000545void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000546{
547 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
548 int d3dSampler = index + d3dSamplerOffset;
549
550 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(samplerState.wrapS));
551 mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(samplerState.wrapT));
552
553 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
554 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
555 es2dx::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
556 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
557 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
558 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
559 if (mSupportsTextureFilterAnisotropy)
560 {
561 mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
562 }
563}
564
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000565void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
daniel@transgaming.coma734f272012-10-31 18:07:48 +0000566{
567 int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
568 int d3dSampler = index + d3dSamplerOffset;
569 IDirect3DBaseTexture9 *d3dTexture = NULL;
570
571 if (texture)
572 {
daniel@transgaming.com9d4346f2012-10-31 19:52:04 +0000573 gl::TextureStorage *texStorage = texture->getNativeTexture();
574 if (texStorage)
575 {
576 d3dTexture = texStorage->getBaseTexture();
577 }
578 // If we get NULL back from getBaseTexture here, something went wrong
daniel@transgaming.coma734f272012-10-31 18:07:48 +0000579 // in the texture class and we're unexpectedly missing the d3d texture
580 ASSERT(d3dTexture != NULL);
581 }
582
583 mDevice->SetTexture(d3dSampler, d3dTexture);
584}
585
586
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000587void Renderer9::releaseDeviceResources()
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000588{
589 while (!mEventQueryPool.empty())
590 {
591 mEventQueryPool.back()->Release();
592 mEventQueryPool.pop_back();
593 }
daniel@transgaming.come4733d72012-10-31 18:07:01 +0000594
595 mVertexShaderCache.clear();
596 mPixelShaderCache.clear();
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000597}
598
599
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000600void Renderer9::markDeviceLost()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000601{
602 mDeviceLost = true;
603}
604
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000605bool Renderer9::isDeviceLost()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000606{
607 return mDeviceLost;
608}
609
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000610// set notify to true to broadcast a message to all contexts of the device loss
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000611bool Renderer9::testDeviceLost(bool notify)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000612{
613 bool isLost = false;
614
615 if (mDeviceEx)
616 {
617 isLost = FAILED(mDeviceEx->CheckDeviceState(NULL));
618 }
619 else if (mDevice)
620 {
621 isLost = FAILED(mDevice->TestCooperativeLevel());
622 }
623 else
624 {
625 // No device yet, so no reset required
626 }
627
628 if (isLost)
629 {
630 // ensure we note the device loss --
631 // we'll probably get this done again by markDeviceLost
632 // but best to remember it!
633 // Note that we don't want to clear the device loss status here
634 // -- this needs to be done by resetDevice
635 mDeviceLost = true;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000636 if (notify)
637 {
638 mDisplay->notifyDeviceLost();
639 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000640 }
641
642 return isLost;
643}
644
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000645bool Renderer9::testDeviceResettable()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000646{
647 HRESULT status = D3D_OK;
648
649 if (mDeviceEx)
650 {
651 status = mDeviceEx->CheckDeviceState(NULL);
652 }
653 else if (mDevice)
654 {
655 status = mDevice->TestCooperativeLevel();
656 }
657
658 switch (status)
659 {
660 case D3DERR_DEVICENOTRESET:
661 case D3DERR_DEVICEHUNG:
662 return true;
663 default:
664 return false;
665 }
666}
667
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000668bool Renderer9::resetDevice()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000669{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000670 releaseDeviceResources();
671
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000672 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
673
674 HRESULT result = D3D_OK;
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000675 bool lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000676 int attempts = 3;
677
678 while (lost && attempts > 0)
679 {
680 if (mDeviceEx)
681 {
682 Sleep(500); // Give the graphics driver some CPU time
683 result = mDeviceEx->ResetEx(&presentParameters, NULL);
684 }
685 else
686 {
687 result = mDevice->TestCooperativeLevel();
688 while (result == D3DERR_DEVICELOST)
689 {
690 Sleep(100); // Give the graphics driver some CPU time
691 result = mDevice->TestCooperativeLevel();
692 }
693
694 if (result == D3DERR_DEVICENOTRESET)
695 {
696 result = mDevice->Reset(&presentParameters);
697 }
698 }
699
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000700 lost = testDeviceLost(false);
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000701 attempts --;
702 }
703
704 if (FAILED(result))
705 {
706 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
707 return false;
708 }
709
710 // reset device defaults
711 initializeDevice();
712 mDeviceLost = false;
713
714 return true;
715}
716
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000717DWORD Renderer9::getAdapterVendor() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000718{
719 return mAdapterIdentifier.VendorId;
720}
721
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000722const char *Renderer9::getAdapterDescription() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000723{
724 return mAdapterIdentifier.Description;
725}
726
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000727GUID Renderer9::getAdapterIdentifier() const
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +0000728{
729 return mAdapterIdentifier.DeviceIdentifier;
730}
731
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000732void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000733{
734 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
735 {
736 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
737 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
738
739 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
740 }
741}
742
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000743bool Renderer9::getDXT1TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000744{
745 D3DDISPLAYMODE currentDisplayMode;
746 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
747
748 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
749}
750
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000751bool Renderer9::getDXT3TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000752{
753 D3DDISPLAYMODE currentDisplayMode;
754 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
755
756 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
757}
758
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000759bool Renderer9::getDXT5TextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000760{
761 D3DDISPLAYMODE currentDisplayMode;
762 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
763
764 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
765}
766
767// we use INTZ for depth textures in Direct3D9
768// we also want NULL texture support to ensure the we can make depth-only FBOs
769// see http://aras-p.info/texts/D3D9GPUHacks.html
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000770bool Renderer9::getDepthTextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000771{
772 D3DDISPLAYMODE currentDisplayMode;
773 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
774
775 bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
776 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ));
777 bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
778 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
779
780 return intz && null;
781}
782
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000783bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000784{
785 D3DDISPLAYMODE currentDisplayMode;
786 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
787
788 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
789 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
790 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
791 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
792
793 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
794 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
795 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
796 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
797
798 if (!*filtering && !*renderable)
799 {
800 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
801 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
802 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
803 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
804 }
805 else
806 {
807 return true;
808 }
809}
810
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000811bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000812{
813 D3DDISPLAYMODE currentDisplayMode;
814 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
815
816 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
817 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
818 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
819 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
820
821 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
822 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
823 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
824 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
825
826 if (!*filtering && !*renderable)
827 {
828 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
829 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
830 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
831 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
832 }
833 else
834 {
835 return true;
836 }
837}
838
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000839bool Renderer9::getLuminanceTextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000840{
841 D3DDISPLAYMODE currentDisplayMode;
842 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
843
844 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
845}
846
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000847bool Renderer9::getLuminanceAlphaTextureSupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000848{
849 D3DDISPLAYMODE currentDisplayMode;
850 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
851
852 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
853}
854
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000855bool Renderer9::getTextureFilterAnisotropySupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000856{
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000857 return mSupportsTextureFilterAnisotropy;
858}
859
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000860float Renderer9::getTextureMaxAnisotropy() const
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000861{
862 if (mSupportsTextureFilterAnisotropy)
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000863 {
864 return mDeviceCaps.MaxAnisotropy;
865 }
866 return 1.0f;
867}
868
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000869bool Renderer9::getEventQuerySupport()
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000870{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000871 IDirect3DQuery9 *query = allocateEventQuery();
872 if (query)
873 {
874 freeEventQuery(query);
875 return true;
876 }
877 else
878 {
879 return false;
880 }
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000881 return true;
882}
883
884// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
885// We test this using D3D9 by checking support for the R16F format.
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000886bool Renderer9::getVertexTextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000887{
888 if (!mDevice || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
889 {
890 return false;
891 }
892
893 D3DDISPLAYMODE currentDisplayMode;
894 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
895
896 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
897
898 return SUCCEEDED(result);
899}
900
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000901bool Renderer9::getNonPower2TextureSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000902{
903 return mSupportsNonPower2Textures;
904}
905
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000906bool Renderer9::getOcclusionQuerySupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000907{
908 if (!mDevice)
909 {
910 return false;
911 }
912
913 IDirect3DQuery9 *query = NULL;
914 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
915 if (SUCCEEDED(result) && query)
916 {
917 query->Release();
918 return true;
919 }
920 else
921 {
922 return false;
923 }
924}
925
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000926bool Renderer9::getInstancingSupport() const
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000927{
928 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
929}
930
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000931bool Renderer9::getShareHandleSupport() const
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000932{
933 // PIX doesn't seem to support using share handles, so disable them.
934 // D3D9_REPLACE
daniel@transgaming.com7cb796e2012-10-31 18:46:44 +0000935 return (mD3d9Ex != NULL) && !gl::perfActive();
daniel@transgaming.com313e3922012-10-31 17:52:39 +0000936}
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000937
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000938bool Renderer9::getShaderModel3Support() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000939{
940 return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
941}
942
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000943float Renderer9::getMaxPointSize() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000944{
945 return mDeviceCaps.MaxPointSize;
946}
947
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000948int Renderer9::getMaxTextureWidth() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000949{
950 return (int)mDeviceCaps.MaxTextureWidth;
951}
952
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000953int Renderer9::getMaxTextureHeight() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000954{
955 return (int)mDeviceCaps.MaxTextureHeight;
956}
957
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000958bool Renderer9::get32BitIndexSupport() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000959{
960 return mDeviceCaps.MaxVertexIndex >= (1 << 16);
961}
962
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000963DWORD Renderer9::getCapsDeclTypes() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000964{
965 return mDeviceCaps.DeclTypes;
966}
967
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000968int Renderer9::getMinSwapInterval() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000969{
970 return mMinSwapInterval;
971}
972
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000973int Renderer9::getMaxSwapInterval() const
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000974{
975 return mMaxSwapInterval;
976}
977
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000978int Renderer9::getMaxSupportedSamples() const
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000979{
980 return mMaxSupportedSamples;
981}
982
daniel@transgaming.com2507f412012-10-31 18:46:48 +0000983int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000984{
985 if (requested == 0)
986 {
987 return requested;
988 }
989
990 std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
991 if (itr == mMultiSampleSupport.end())
992 {
daniel@transgaming.com92955622012-10-31 18:38:41 +0000993 if (format == D3DFMT_UNKNOWN)
994 return 0;
daniel@transgaming.comb7833982012-10-31 18:31:46 +0000995 return -1;
996 }
997
998 for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
999 {
1000 if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
1001 {
1002 return i;
1003 }
1004 }
1005
1006 return -1;
1007}
1008
daniel@transgaming.coma9571682012-11-28 19:33:08 +00001009D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
1010{
1011 switch (internalformat)
1012 {
1013 case GL_DEPTH_COMPONENT16:
1014 case GL_DEPTH_COMPONENT32_OES:
1015 case GL_DEPTH24_STENCIL8_OES:
1016 return D3DFMT_INTZ;
1017 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1018 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1019 return D3DFMT_DXT1;
1020 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1021 return D3DFMT_DXT3;
1022 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1023 return D3DFMT_DXT5;
1024 case GL_RGBA32F_EXT:
1025 case GL_RGB32F_EXT:
1026 case GL_ALPHA32F_EXT:
1027 case GL_LUMINANCE32F_EXT:
1028 case GL_LUMINANCE_ALPHA32F_EXT:
1029 return D3DFMT_A32B32G32R32F;
1030 case GL_RGBA16F_EXT:
1031 case GL_RGB16F_EXT:
1032 case GL_ALPHA16F_EXT:
1033 case GL_LUMINANCE16F_EXT:
1034 case GL_LUMINANCE_ALPHA16F_EXT:
1035 return D3DFMT_A16B16G16R16F;
1036 case GL_LUMINANCE8_EXT:
1037 if (getLuminanceTextureSupport())
1038 {
1039 return D3DFMT_L8;
1040 }
1041 break;
1042 case GL_LUMINANCE8_ALPHA8_EXT:
1043 if (getLuminanceAlphaTextureSupport())
1044 {
1045 return D3DFMT_A8L8;
1046 }
1047 break;
1048 case GL_RGB8_OES:
1049 case GL_RGB565:
1050 return D3DFMT_X8R8G8B8;
1051 }
1052
1053 return D3DFMT_A8R8G8B8;
1054}
1055
daniel@transgaming.com1d80eee2012-11-28 19:33:31 +00001056bool Renderer9::copyToRenderTarget(gl::TextureStorage2D *dest, gl::TextureStorage2D *source)
1057{
1058 bool result = false;
1059
1060 if (source && dest)
1061 {
1062 int levels = source->levelCount();
1063 for (int i = 0; i < levels; ++i)
1064 {
1065 IDirect3DSurface9 *srcSurf = source->getSurfaceLevel(i, false);
1066 IDirect3DSurface9 *dstSurf = dest->getSurfaceLevel(i, false);
1067
1068 result = copyToRenderTarget(dstSurf, srcSurf, source->isManaged());
1069
1070 if (srcSurf) srcSurf->Release();
1071 if (dstSurf) dstSurf->Release();
1072
1073 if (!result)
1074 return false;
1075 }
1076 }
1077
1078 return result;
1079}
1080
1081bool Renderer9::copyToRenderTarget(gl::TextureStorageCubeMap *dest, gl::TextureStorageCubeMap *source)
1082{
1083 bool result = false;
1084
1085 if (source && dest)
1086 {
1087 int levels = source->levelCount();
1088 for (int f = 0; f < 6; f++)
1089 {
1090 for (int i = 0; i < levels; i++)
1091 {
1092 IDirect3DSurface9 *srcSurf = source->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
1093 IDirect3DSurface9 *dstSurf = dest->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
1094
1095 result = copyToRenderTarget(dstSurf, srcSurf, source->isManaged());
1096
1097 if (srcSurf) srcSurf->Release();
1098 if (dstSurf) dstSurf->Release();
1099
1100 if (!result)
1101 return false;
1102 }
1103 }
1104 }
1105
1106 return result;
1107}
1108
daniel@transgaming.com2507f412012-10-31 18:46:48 +00001109D3DPOOL Renderer9::getBufferPool(DWORD usage) const
daniel@transgaming.com621ce052012-10-31 17:52:29 +00001110{
1111 if (mD3d9Ex != NULL)
1112 {
1113 return D3DPOOL_DEFAULT;
1114 }
1115 else
1116 {
1117 if (!(usage & D3DUSAGE_DYNAMIC))
1118 {
1119 return D3DPOOL_MANAGED;
1120 }
1121 }
1122
1123 return D3DPOOL_DEFAULT;
1124}
1125
daniel@transgaming.com2507f412012-10-31 18:46:48 +00001126D3DPOOL Renderer9::getTexturePool(DWORD usage) const
daniel@transgaming.com621ce052012-10-31 17:52:29 +00001127{
1128 if (mD3d9Ex != NULL)
1129 {
1130 return D3DPOOL_DEFAULT;
1131 }
1132 else
1133 {
1134 if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
1135 {
1136 return D3DPOOL_MANAGED;
1137 }
1138 }
1139
1140 return D3DPOOL_DEFAULT;
1141}
1142
daniel@transgaming.com1d80eee2012-11-28 19:33:31 +00001143bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
1144{
1145 if (source && dest)
1146 {
1147 HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
1148 IDirect3DDevice9 *device = getDevice(); // D3D9_REPLACE
1149
1150 if (fromManaged)
1151 {
1152 D3DSURFACE_DESC desc;
1153 source->GetDesc(&desc);
1154
1155 IDirect3DSurface9 *surf = 0;
1156 result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
1157
1158 if (SUCCEEDED(result))
1159 {
1160 gl::Image::CopyLockableSurfaces(surf, source);
1161 result = device->UpdateSurface(surf, NULL, dest, NULL);
1162 surf->Release();
1163 }
1164 }
1165 else
1166 {
1167 endScene();
1168 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1169 }
1170
1171 if (FAILED(result))
1172 {
1173 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1174 return false;
1175 }
1176 }
1177
1178 return true;
1179}
1180
daniel@transgaming.com621ce052012-10-31 17:52:29 +00001181}