blob: f79d4b8ccf1313b3513c9e51eaec8a40e90f8380 [file] [log] [blame]
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001//
daniel@transgaming.com3b1703f2011-05-11 15:36:26 +00002// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.come979ead2010-09-23 18:03:14 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Display.cpp: Implements the egl::Display class, representing the abstract
8// display on which graphics are drawn. Implements EGLDisplay.
9// [EGL 1.4] section 2.1.2 page 3.
10
11#include "libEGL/Display.h"
12
13#include <algorithm>
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000014#include <map>
daniel@transgaming.come979ead2010-09-23 18:03:14 +000015#include <vector>
16
17#include "common/debug.h"
jbauman@chromium.org06d7a752011-04-30 01:02:52 +000018#include "libGLESv2/mathutil.h"
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +000019#include "libGLESv2/utilities.h"
daniel@transgaming.come979ead2010-09-23 18:03:14 +000020
21#include "libEGL/main.h"
22
baustin@google.com250f06c2011-06-06 16:59:53 +000023// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
24#define REF_RAST 0
25
26// The "Debug This Pixel..." feature in PIX often fails when using the
27// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
28// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file.
29#if !defined(ANGLE_ENABLE_D3D9EX)
30// Enables use of the IDirect3D9Ex interface, when available
31#define ANGLE_ENABLE_D3D9EX 1
32#endif // !defined(ANGLE_ENABLE_D3D9EX)
daniel@transgaming.come979ead2010-09-23 18:03:14 +000033
34namespace egl
35{
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000036namespace
37{
38 typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
39 DisplayMap displays;
40}
41
42egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
43{
44 if (displays.find(displayId) != displays.end())
45 {
46 return displays[displayId];
47 }
48
49 egl::Display *display = NULL;
50
51 if (displayId == EGL_DEFAULT_DISPLAY)
52 {
53 display = new egl::Display(displayId, (HDC)NULL, false);
54 }
55 else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
56 {
57 display = new egl::Display(displayId, (HDC)NULL, true);
58 }
59 else
60 {
61 // FIXME: Check if displayId is a valid display device context
62
63 display = new egl::Display(displayId, (HDC)displayId, false);
64 }
65
66 displays[displayId] = display;
67 return display;
68}
69
70Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
daniel@transgaming.come979ead2010-09-23 18:03:14 +000071{
72 mD3d9Module = NULL;
73
74 mD3d9 = NULL;
apatrick@chromium.org9e83b592011-02-10 22:04:34 +000075 mD3d9Ex = NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +000076 mDevice = NULL;
apatrick@chromium.org9e83b592011-02-10 22:04:34 +000077 mDeviceEx = NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +000078 mDeviceWindow = NULL;
79
80 mAdapter = D3DADAPTER_DEFAULT;
81
82 #if REF_RAST == 1 || defined(FORCE_REF_RAST)
83 mDeviceType = D3DDEVTYPE_REF;
84 #else
85 mDeviceType = D3DDEVTYPE_HAL;
86 #endif
87
88 mMinSwapInterval = 1;
89 mMaxSwapInterval = 1;
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000090 mSoftwareDevice = software;
91 mDisplayId = displayId;
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +000092 mDeviceLost = false;
daniel@transgaming.come979ead2010-09-23 18:03:14 +000093}
94
95Display::~Display()
96{
97 terminate();
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +000098
99 DisplayMap::iterator thisDisplay = displays.find(mDisplayId);
100
101 if (thisDisplay != displays.end())
102 {
103 displays.erase(thisDisplay);
104 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000105}
106
107bool Display::initialize()
108{
109 if (isInitialized())
110 {
111 return true;
112 }
113
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +0000114 if (mSoftwareDevice)
115 {
116 mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
117 }
118 else
119 {
120 mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
121 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000122 if (mD3d9Module == NULL)
123 {
124 terminate();
125 return false;
126 }
127
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000128 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
129 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
130
131 // Use Direct3D9Ex if available. Among other things, this version is less
132 // inclined to report a lost context, for example when the user switches
133 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
baustin@google.com250f06c2011-06-06 16:59:53 +0000134 if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000135 {
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000136 ASSERT(mD3d9Ex);
137 mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000138 ASSERT(mD3d9);
139 }
140 else
141 {
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000142 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000143 }
144
145 if (mD3d9)
146 {
147 if (mDc != NULL)
148 {
149 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
150 }
151
152 HRESULT result;
153
apatrick@chromium.org1c768012010-10-07 00:35:24 +0000154 // Give up on getting device caps after about one second.
155 for (int i = 0; i < 10; ++i)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000156 {
157 result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
apatrick@chromium.org1c768012010-10-07 00:35:24 +0000158
159 if (SUCCEEDED(result))
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000160 {
apatrick@chromium.org1c768012010-10-07 00:35:24 +0000161 break;
162 }
163 else if (result == D3DERR_NOTAVAILABLE)
164 {
165 Sleep(100); // Give the driver some time to initialize/recover
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000166 }
167 else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
168 {
apatrick@chromium.org1c768012010-10-07 00:35:24 +0000169 terminate();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000170 return error(EGL_BAD_ALLOC, false);
171 }
172 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000173
174 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
175 {
176 terminate();
177 return error(EGL_NOT_INITIALIZED, false);
178 }
179
apatrick@chromium.org1c768012010-10-07 00:35:24 +0000180 // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
181 // This is required by Texture2D::convertToRenderTarget.
182 if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
183 {
184 terminate();
185 return error(EGL_NOT_INITIALIZED, false);
186 }
187
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000188 mMinSwapInterval = 4;
189 mMaxSwapInterval = 0;
190
191 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
192 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
193 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
194 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
195 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
196
jbauman@chromium.org03208d52011-06-15 01:15:24 +0000197 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
198
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000199 const D3DFORMAT renderTargetFormats[] =
200 {
201 D3DFMT_A1R5G5B5,
202 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
203 D3DFMT_A8R8G8B8,
204 D3DFMT_R5G6B5,
daniel@transgaming.com73a5db62010-10-15 17:58:13 +0000205 // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000206 D3DFMT_X8R8G8B8
207 };
208
209 const D3DFORMAT depthStencilFormats[] =
210 {
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000211 D3DFMT_UNKNOWN,
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000212 // D3DFMT_D16_LOCKABLE,
213 D3DFMT_D32,
214 // D3DFMT_D15S1,
215 D3DFMT_D24S8,
216 D3DFMT_D24X8,
217 // D3DFMT_D24X4S4,
218 D3DFMT_D16,
219 // D3DFMT_D32F_LOCKABLE,
220 // D3DFMT_D24FS8
221 };
222
223 D3DDISPLAYMODE currentDisplayMode;
224 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
225
226 ConfigSet configSet;
227
228 for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
229 {
230 D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
231
232 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
233
234 if (SUCCEEDED(result))
235 {
236 for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
237 {
238 D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000239 HRESULT result = D3D_OK;
240
241 if(depthStencilFormat != D3DFMT_UNKNOWN)
242 {
243 result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
244 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000245
246 if (SUCCEEDED(result))
247 {
daniel@transgaming.coma114c272011-04-22 04:18:50 +0000248 if(depthStencilFormat != D3DFMT_UNKNOWN)
249 {
250 result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
251 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000252
253 if (SUCCEEDED(result))
254 {
255 // FIXME: enumerate multi-sampling
256
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000257 configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
258 mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000259 }
260 }
261 }
262 }
263 }
264
265 // Give the sorted configs a unique ID and store them internally
266 EGLint index = 1;
267 for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
268 {
269 Config configuration = *config;
270 configuration.mConfigID = index;
271 index++;
272
273 mConfigSet.mSet.insert(configuration);
274 }
275 }
276
277 if (!isInitialized())
278 {
279 terminate();
280
281 return false;
282 }
283
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000284 initExtensionString();
285
daniel@transgaming.come979ead2010-09-23 18:03:14 +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 return true;
292}
293
294void Display::terminate()
295{
296 while (!mSurfaceSet.empty())
297 {
298 destroySurface(*mSurfaceSet.begin());
299 }
300
301 while (!mContextSet.empty())
302 {
303 destroyContext(*mContextSet.begin());
304 }
305
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000306 while (!mEventQueryPool.empty())
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000307 {
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000308 mEventQueryPool.back()->Release();
309 mEventQueryPool.pop_back();
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000310 }
311
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000312 if (mDevice)
313 {
314 // If the device is lost, reset it first to prevent leaving the driver in an unstable state
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000315 if (testDeviceLost())
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000316 {
317 resetDevice();
318 }
319
320 mDevice->Release();
321 mDevice = NULL;
322 }
323
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000324 if (mDeviceEx)
325 {
326 mDeviceEx->Release();
327 mDeviceEx = NULL;
328 }
329
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000330 if (mD3d9)
331 {
332 mD3d9->Release();
333 mD3d9 = NULL;
334 }
335
336 if (mDeviceWindow)
337 {
338 DestroyWindow(mDeviceWindow);
339 mDeviceWindow = NULL;
340 }
341
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000342 if (mD3d9Ex)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000343 {
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000344 mD3d9Ex->Release();
345 mD3d9Ex = NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000346 }
347
348 if (mD3d9Module)
349 {
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000350 mD3d9Module = NULL;
351 }
352}
353
354void Display::startScene()
355{
356 if (!mSceneStarted)
357 {
358 long result = mDevice->BeginScene();
kbr@chromium.org1a2cd262011-07-08 17:30:18 +0000359 if (SUCCEEDED(result)) {
360 // This is defensive checking against the device being
361 // lost at unexpected times.
362 mSceneStarted = true;
363 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000364 }
365}
366
367void Display::endScene()
368{
369 if (mSceneStarted)
370 {
kbr@chromium.org1a2cd262011-07-08 17:30:18 +0000371 // EndScene can fail if the device was lost, for example due
372 // to a TDR during a draw call.
373 mDevice->EndScene();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000374 mSceneStarted = false;
375 }
376}
377
378bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
379{
380 return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
381}
382
383bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
384{
385 const egl::Config *configuration = mConfigSet.get(config);
386
387 switch (attribute)
388 {
389 case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
390 case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
391 case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
392 case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
393 case EGL_RED_SIZE: *value = configuration->mRedSize; break;
394 case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
395 case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
396 case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
397 case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
398 case EGL_LEVEL: *value = configuration->mLevel; break;
399 case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
400 case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
401 case EGL_SAMPLES: *value = configuration->mSamples; break;
402 case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
403 case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
404 case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
405 case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
406 case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
407 case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
408 case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
409 case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
410 case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
411 case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
412 case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
413 case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
414 case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
415 case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
416 case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
417 case EGL_CONFORMANT: *value = configuration->mConformant; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000418 case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
419 case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
420 case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000421 default:
422 return false;
423 }
424
425 return true;
426}
427
428bool Display::createDevice()
429{
430 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
431 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
432
433 HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
434
435 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
436 {
437 return error(EGL_BAD_ALLOC, false);
438 }
439
440 if (FAILED(result))
441 {
442 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
443
444 if (FAILED(result))
445 {
446 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
447 return error(EGL_BAD_ALLOC, false);
448 }
449 }
450
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000451 if (mD3d9Ex)
452 {
453 result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
454 ASSERT(SUCCEEDED(result));
455 }
456
daniel@transgaming.come19d8322011-12-13 17:30:48 +0000457 initializeDevice();
458
459 return true;
460}
461
462// do any one-time device initialization
463// NOTE: this is also needed after a device lost/reset
464// to reset the scene status and ensure the default states are reset.
465void Display::initializeDevice()
466{
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000467 // Permanent non-default states
468 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
daniel@transgaming.com7a2fdc92011-11-24 22:34:09 +0000469 mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000470
471 mSceneStarted = false;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000472}
473
474bool Display::resetDevice()
475{
476 D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000477
daniel@transgaming.com10435352011-11-09 17:44:21 +0000478 HRESULT result = D3D_OK;
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000479 bool lost = testDeviceLost();
daniel@transgaming.com10435352011-11-09 17:44:21 +0000480 int attempts = 3;
daniel@transgaming.com94910c92011-11-09 17:44:15 +0000481
daniel@transgaming.com10435352011-11-09 17:44:21 +0000482 while (lost && attempts > 0)
daniel@transgaming.com94910c92011-11-09 17:44:15 +0000483 {
daniel@transgaming.com10435352011-11-09 17:44:21 +0000484 if (mDeviceEx)
485 {
486 Sleep(500); // Give the graphics driver some CPU time
487 result = mDeviceEx->ResetEx(&presentParameters, NULL);
488 }
489 else
490 {
491 result = mDevice->TestCooperativeLevel();
492
493 while (result == D3DERR_DEVICELOST)
494 {
495 Sleep(100); // Give the graphics driver some CPU time
496 result = mDevice->TestCooperativeLevel();
497 }
498
499 if (result == D3DERR_DEVICENOTRESET)
500 {
501 result = mDevice->Reset(&presentParameters);
502 }
503 }
504
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000505 lost = testDeviceLost();
daniel@transgaming.com10435352011-11-09 17:44:21 +0000506 attempts --;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000507 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000508
509 if (FAILED(result))
510 {
daniel@transgaming.com10435352011-11-09 17:44:21 +0000511 ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000512 return error(EGL_BAD_ALLOC, false);
513 }
514
daniel@transgaming.come19d8322011-12-13 17:30:48 +0000515 // reset device defaults
516 initializeDevice();
517
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000518 return true;
519}
520
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000521EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000522{
523 const Config *configuration = mConfigSet.get(config);
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000524 EGLint postSubBufferSupported = EGL_FALSE;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000525
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000526 if (attribList)
527 {
528 while (*attribList != EGL_NONE)
529 {
530 switch (attribList[0])
531 {
532 case EGL_RENDER_BUFFER:
533 switch (attribList[1])
534 {
535 case EGL_BACK_BUFFER:
536 break;
537 case EGL_SINGLE_BUFFER:
538 return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
539 default:
540 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
541 }
542 break;
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000543 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
544 postSubBufferSupported = attribList[1];
545 break;
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000546 case EGL_VG_COLORSPACE:
547 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
548 case EGL_VG_ALPHA_FORMAT:
549 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
550 default:
551 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
552 }
553
554 attribList += 2;
555 }
556 }
557
558 if (hasExistingWindowSurface(window))
559 {
560 return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
561 }
562
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000563 if (testDeviceLost())
564 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000565 if (!restoreLostDevice())
566 return EGL_NO_SURFACE;
567 }
568
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +0000569 Surface *surface = new Surface(this, configuration, window, postSubBufferSupported);
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000570
571 if (!surface->initialize())
572 {
573 delete surface;
574 return EGL_NO_SURFACE;
575 }
576
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000577 mSurfaceSet.insert(surface);
578
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000579 return success(surface);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000580}
581
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000582EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000583{
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000584 EGLint width = 0, height = 0;
585 EGLenum textureFormat = EGL_NO_TEXTURE;
586 EGLenum textureTarget = EGL_NO_TEXTURE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000587 const Config *configuration = mConfigSet.get(config);
588
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000589 if (attribList)
590 {
591 while (*attribList != EGL_NONE)
592 {
593 switch (attribList[0])
594 {
595 case EGL_WIDTH:
596 width = attribList[1];
597 break;
598 case EGL_HEIGHT:
599 height = attribList[1];
600 break;
601 case EGL_LARGEST_PBUFFER:
602 if (attribList[1] != EGL_FALSE)
603 UNIMPLEMENTED(); // FIXME
604 break;
605 case EGL_TEXTURE_FORMAT:
606 switch (attribList[1])
607 {
608 case EGL_NO_TEXTURE:
609 case EGL_TEXTURE_RGB:
610 case EGL_TEXTURE_RGBA:
611 textureFormat = attribList[1];
612 break;
613 default:
614 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
615 }
616 break;
617 case EGL_TEXTURE_TARGET:
618 switch (attribList[1])
619 {
620 case EGL_NO_TEXTURE:
621 case EGL_TEXTURE_2D:
622 textureTarget = attribList[1];
623 break;
624 default:
625 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
626 }
627 break;
628 case EGL_MIPMAP_TEXTURE:
629 if (attribList[1] != EGL_FALSE)
630 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
631 break;
632 case EGL_VG_COLORSPACE:
633 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
634 case EGL_VG_ALPHA_FORMAT:
635 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
636 default:
637 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
638 }
639
640 attribList += 2;
641 }
642 }
643
644 if (width < 0 || height < 0)
645 {
646 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
647 }
648
649 if (width == 0 || height == 0)
650 {
651 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
652 }
653
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +0000654 if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height)))
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000655 {
656 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
657 }
658
659 if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
660 (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
661 {
662 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
663 }
664
665 if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
666 {
667 return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
668 }
669
670 if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
671 (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
672 {
673 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
674 }
675
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000676 if (testDeviceLost())
677 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000678 if (!restoreLostDevice())
679 return EGL_NO_SURFACE;
680 }
681
jbauman@chromium.org4e297702011-05-12 23:04:07 +0000682 Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
683
684 if (!surface->initialize())
685 {
686 delete surface;
687 return EGL_NO_SURFACE;
688 }
689
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000690 mSurfaceSet.insert(surface);
691
jbauman@chromium.org06d7a752011-04-30 01:02:52 +0000692 return success(surface);
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000693}
694
daniel@transgaming.com4ff960d2011-11-09 17:47:09 +0000695EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000696{
697 if (!mDevice)
698 {
699 if (!createDevice())
700 {
701 return NULL;
702 }
703 }
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000704 else if (testDeviceLost()) // Lost device
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000705 {
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000706 if (!restoreLostDevice())
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000707 return NULL;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000708 }
709
710 const egl::Config *config = mConfigSet.get(configHandle);
711
daniel@transgaming.com4ff960d2011-11-09 17:47:09 +0000712 gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000713 mContextSet.insert(context);
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000714 mDeviceLost = false;
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000715
716 return context;
717}
718
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000719bool Display::restoreLostDevice()
720{
daniel@transgaming.comcf23c452011-11-09 17:47:26 +0000721 for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
722 {
723 if ((*ctx)->isResetNotificationEnabled())
724 return false; // If reset notifications have been requested, application must delete all contexts first
725 }
726
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000727 // Release surface resources to make the Reset() succeed
728 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
729 {
730 (*surface)->release();
731 }
732
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000733 while (!mEventQueryPool.empty())
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000734 {
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000735 mEventQueryPool.back()->Release();
736 mEventQueryPool.pop_back();
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000737 }
738
vangelis@google.com8c9c4522011-09-09 18:22:28 +0000739 if (!resetDevice())
740 {
741 return false;
742 }
743
744 // Restore any surfaces that may have been lost
745 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
746 {
747 (*surface)->resetSwapChain();
748 }
749
750 return true;
751}
752
753
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000754void Display::destroySurface(egl::Surface *surface)
755{
daniel@transgaming.comc556fa52011-05-26 14:13:29 +0000756 delete surface;
757 mSurfaceSet.erase(surface);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000758}
759
760void Display::destroyContext(gl::Context *context)
761{
762 glDestroyContext(context);
763 mContextSet.erase(context);
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000764}
765
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000766void Display::notifyDeviceLost()
767{
768 for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
769 {
770 (*context)->markContextLost();
771 }
772 mDeviceLost = true;
773 error(EGL_CONTEXT_LOST);
774}
775
776bool Display::isDeviceLost()
777{
778 return mDeviceLost;
779}
780
daniel@transgaming.com3b1703f2011-05-11 15:36:26 +0000781bool Display::isInitialized() const
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000782{
783 return mD3d9 != NULL && mConfigSet.size() > 0;
784}
785
786bool Display::isValidConfig(EGLConfig config)
787{
788 return mConfigSet.get(config) != NULL;
789}
790
791bool Display::isValidContext(gl::Context *context)
792{
793 return mContextSet.find(context) != mContextSet.end();
794}
795
796bool Display::isValidSurface(egl::Surface *surface)
797{
daniel@transgaming.comc556fa52011-05-26 14:13:29 +0000798 return mSurfaceSet.find(surface) != mSurfaceSet.end();
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000799}
800
801bool Display::hasExistingWindowSurface(HWND window)
802{
803 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
804 {
805 if ((*surface)->getWindowHandle() == window)
806 {
807 return true;
808 }
809 }
810
811 return false;
812}
813
814EGLint Display::getMinSwapInterval()
815{
816 return mMinSwapInterval;
817}
818
819EGLint Display::getMaxSwapInterval()
820{
821 return mMaxSwapInterval;
822}
823
824IDirect3DDevice9 *Display::getDevice()
825{
826 if (!mDevice)
827 {
828 if (!createDevice())
829 {
830 return NULL;
831 }
832 }
833
834 return mDevice;
835}
836
837D3DCAPS9 Display::getDeviceCaps()
838{
839 return mDeviceCaps;
840}
841
jbauman@chromium.org03208d52011-06-15 01:15:24 +0000842D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
843{
844 return &mAdapterIdentifier;
845}
846
daniel@transgaming.com09fcc9f2011-11-09 17:46:47 +0000847bool Display::testDeviceLost()
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000848{
849 if (mDeviceEx)
850 {
851 return FAILED(mDeviceEx->CheckDeviceState(NULL));
852 }
daniel@transgaming.com17f548c2011-11-09 17:47:02 +0000853 else if (mDevice)
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000854 {
855 return FAILED(mDevice->TestCooperativeLevel());
856 }
daniel@transgaming.comfe4b0c92011-09-13 00:53:11 +0000857
858 return false; // No device yet, so no reset required
apatrick@chromium.org9e83b592011-02-10 22:04:34 +0000859}
860
daniel@transgaming.com17f548c2011-11-09 17:47:02 +0000861bool Display::testDeviceResettable()
862{
863 HRESULT status = D3D_OK;
864
865 if (mDeviceEx)
866 {
867 status = mDeviceEx->CheckDeviceState(NULL);
868 }
869 else if (mDevice)
870 {
871 status = mDevice->TestCooperativeLevel();
872 }
873
874 switch (status)
875 {
876 case D3DERR_DEVICENOTRESET:
877 case D3DERR_DEVICEHUNG:
878 return true;
879 default:
880 return false;
881 }
882}
883
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000884void Display::sync(bool block)
885{
886 HRESULT result;
887
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000888 IDirect3DQuery9* query = allocateEventQuery();
889 if (!query)
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000890 {
891 return;
892 }
893
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000894 result = query->Issue(D3DISSUE_END);
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000895 ASSERT(SUCCEEDED(result));
896
897 do
898 {
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000899 result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000900
901 if(block && result == S_FALSE)
902 {
903 // Keep polling, but allow other threads to do something useful first
904 Sleep(0);
905 // explicitly check for device loss
906 // some drivers seem to return S_FALSE even if the device is lost
907 // instead of D3DERR_DEVICELOST like they should
908 if (testDeviceLost())
909 {
910 result = D3DERR_DEVICELOST;
911 }
912 }
913 }
914 while(block && result == S_FALSE);
915
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000916 freeEventQuery(query);
917
daniel@transgaming.com2678b342012-01-18 16:29:40 +0000918 if (isDeviceLostError(result))
919 {
920 notifyDeviceLost();
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000921 }
922}
923
924IDirect3DQuery9* Display::allocateEventQuery()
925{
926 IDirect3DQuery9 *query = NULL;
927
928 if (mEventQueryPool.empty())
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000929 {
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +0000930 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
931 ASSERT(SUCCEEDED(result));
932 }
933 else
934 {
935 query = mEventQueryPool.back();
936 mEventQueryPool.pop_back();
937 }
938
939 return query;
940}
941
942void Display::freeEventQuery(IDirect3DQuery9* query)
943{
944 if (mEventQueryPool.size() > 1000)
945 {
946 query->Release();
947 }
948 else
949 {
950 mEventQueryPool.push_back(query);
apatrick@chromium.orga5ddde92012-01-10 23:00:07 +0000951 }
952}
953
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000954void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
955{
956 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
957 {
958 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
959 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
960
961 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
962 }
963}
964
gman@chromium.org50c526d2011-08-10 05:19:44 +0000965bool Display::getDXT1TextureSupport()
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000966{
967 D3DDISPLAYMODE currentDisplayMode;
968 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
969
970 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
971}
972
gman@chromium.org50c526d2011-08-10 05:19:44 +0000973bool Display::getDXT3TextureSupport()
974{
975 D3DDISPLAYMODE currentDisplayMode;
976 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
977
978 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
979}
980
981bool Display::getDXT5TextureSupport()
982{
983 D3DDISPLAYMODE currentDisplayMode;
984 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
985
986 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
987}
988
daniel@transgaming.combbeffbb2011-11-09 17:46:11 +0000989bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.come979ead2010-09-23 18:03:14 +0000990{
991 D3DDISPLAYMODE currentDisplayMode;
992 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
993
994 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
995 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
996 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
997 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
998
999 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
1000 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&&
1001 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
1002 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
1003
daniel@transgaming.combb5223d2012-01-24 13:38:10 +00001004 if (!*filtering && !*renderable)
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001005 {
1006 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
1007 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
1008 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
1009 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
1010 }
1011 else
1012 {
1013 return true;
1014 }
1015}
1016
daniel@transgaming.combbeffbb2011-11-09 17:46:11 +00001017bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable)
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001018{
1019 D3DDISPLAYMODE currentDisplayMode;
1020 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
1021
1022 *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
1023 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
1024 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
1025 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
1026
1027 *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
1028 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
1029 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
1030 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
1031
daniel@transgaming.combb5223d2012-01-24 13:38:10 +00001032 if (!*filtering && !*renderable)
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001033 {
1034 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
1035 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
1036 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
1037 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
1038 }
1039 else
1040 {
1041 return true;
1042 }
1043}
1044
daniel@transgaming.comed828e52010-10-15 17:57:30 +00001045bool Display::getLuminanceTextureSupport()
1046{
1047 D3DDISPLAYMODE currentDisplayMode;
1048 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
1049
1050 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
1051}
1052
1053bool Display::getLuminanceAlphaTextureSupport()
1054{
1055 D3DDISPLAYMODE currentDisplayMode;
1056 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
1057
1058 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
1059}
1060
daniel@transgaming.comee04e452011-01-08 05:46:27 +00001061D3DPOOL Display::getBufferPool(DWORD usage) const
daniel@transgaming.com37b141e2011-01-08 05:46:13 +00001062{
apatrick@chromium.org9e83b592011-02-10 22:04:34 +00001063 if (mD3d9Ex != NULL)
daniel@transgaming.comee04e452011-01-08 05:46:27 +00001064 {
1065 return D3DPOOL_DEFAULT;
1066 }
1067 else
1068 {
1069 if (!(usage & D3DUSAGE_DYNAMIC))
1070 {
1071 return D3DPOOL_MANAGED;
1072 }
1073 }
1074
1075 return D3DPOOL_DEFAULT;
daniel@transgaming.com37b141e2011-01-08 05:46:13 +00001076}
1077
daniel@transgaming.com59580a32011-11-12 04:23:44 +00001078D3DPOOL Display::getTexturePool(bool renderable) const
1079{
1080 if (mD3d9Ex != NULL)
1081 {
1082 return D3DPOOL_DEFAULT;
1083 }
1084 else
1085 {
1086 if (!renderable)
1087 {
1088 return D3DPOOL_MANAGED;
1089 }
1090 }
1091
1092 return D3DPOOL_DEFAULT;
1093}
1094
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001095bool Display::getEventQuerySupport()
1096{
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +00001097 IDirect3DQuery9 *query = allocateEventQuery();
1098 if (query)
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001099 {
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +00001100 freeEventQuery(query);
1101 return true;
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001102 }
apatrick@chromium.orgf289ee82012-01-11 20:03:29 +00001103 else
1104 {
1105 return false;
1106 }
daniel@transgaming.come979ead2010-09-23 18:03:14 +00001107}
1108
1109D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters()
1110{
1111 D3DPRESENT_PARAMETERS presentParameters = {0};
1112
1113 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
1114 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1115 presentParameters.BackBufferCount = 1;
1116 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
1117 presentParameters.BackBufferWidth = 1;
1118 presentParameters.BackBufferHeight = 1;
1119 presentParameters.EnableAutoDepthStencil = FALSE;
1120 presentParameters.Flags = 0;
1121 presentParameters.hDeviceWindow = mDeviceWindow;
1122 presentParameters.MultiSampleQuality = 0;
1123 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
1124 presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
1125 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1126 presentParameters.Windowed = TRUE;
1127
1128 return presentParameters;
1129}
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +00001130
1131void Display::initExtensionString()
1132{
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +00001133 HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
daniel@transgaming.com1a1fe242011-09-26 18:25:45 +00001134 bool isd3d9ex = isD3d9ExDevice();
1135
1136 mExtensionString = "";
1137
daniel@transgaming.com8747f182011-11-09 17:50:38 +00001138 // Multi-vendor (EXT) extensions
1139 mExtensionString += "EGL_EXT_create_context_robustness ";
1140
1141 // ANGLE-specific extensions
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +00001142 if (isd3d9ex)
1143 {
daniel@transgaming.com1a1fe242011-09-26 18:25:45 +00001144 mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer ";
1145 }
1146
1147 mExtensionString += "EGL_ANGLE_query_surface_pointer ";
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +00001148
1149 if (swiftShader)
1150 {
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +00001151 mExtensionString += "EGL_ANGLE_software_display ";
jbauman@chromium.org84d7cbc2011-07-14 22:53:19 +00001152 }
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +00001153
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +00001154 if (isd3d9ex)
1155 {
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +00001156 mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle ";
1157 }
1158
apatrick@chromium.orgf4490e22011-12-06 02:05:22 +00001159 mExtensionString += "EGL_NV_post_sub_buffer";
1160
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +00001161 std::string::size_type end = mExtensionString.find_last_not_of(' ');
1162 if (end != std::string::npos)
1163 {
1164 mExtensionString.resize(end+1);
1165 }
1166}
1167
1168const char *Display::getExtensionString() const
1169{
1170 return mExtensionString.c_str();
1171}
1172
daniel@transgaming.com3b1703f2011-05-11 15:36:26 +00001173// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
1174// We test this using D3D9 by checking support for the R16F format.
1175bool Display::getVertexTextureSupport() const
1176{
daniel@transgaming.com3b1703f2011-05-11 15:36:26 +00001177 if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0))
1178 {
1179 return false;
1180 }
1181
1182 D3DDISPLAYMODE currentDisplayMode;
1183 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
1184
1185 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F);
1186
1187 return SUCCEEDED(result);
1188}
1189
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001190bool Display::getNonPower2TextureSupport() const
1191{
1192 return !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
1193 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
1194 !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
1195}
1196
daniel@transgaming.com86bdb822012-01-20 18:24:39 +00001197bool Display::getOcclusionQuerySupport() const
1198{
1199 if (!isInitialized())
1200 {
1201 return false;
1202 }
1203
1204 IDirect3DQuery9 *query = NULL;
1205 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query);
1206
1207 if (SUCCEEDED(result) && query)
1208 {
1209 query->Release();
1210 return true;
1211 }
1212 else
1213 {
1214 return false;
1215 }
1216}
1217
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +00001218}