blob: 43cbf3200e5f56b18b582fd0c8a54a73b4845eae [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 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// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libEGL/Display.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
daniel@transgaming.com16973022010-03-11 19:22:19 +000013#include <algorithm>
14#include <vector>
15
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000016#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018#include "libEGL/main.h"
19
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +000020#define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
21#define ENABLE_D3D9EX 1 // Enables use of the IDirect3D9Ex interface, when available
daniel@transgaming.com741a5882010-05-20 19:17:29 +000022
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023namespace egl
24{
25Display::Display(HDC deviceContext) : mDc(deviceContext)
26{
apatrick@chromium.org94e19342010-08-17 22:19:58 +000027 mD3d9Module = NULL;
28
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029 mD3d9 = NULL;
apatrick@chromium.org94e19342010-08-17 22:19:58 +000030 mD3d9ex = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031 mDevice = NULL;
daniel@transgaming.comda6e2632010-07-28 19:21:18 +000032 mDeviceWindow = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033
34 mAdapter = D3DADAPTER_DEFAULT;
daniel@transgaming.com741a5882010-05-20 19:17:29 +000035
daniel@transgaming.com8b9f4cc2010-05-20 19:17:35 +000036 #if REF_RAST == 1 || defined(FORCE_REF_RAST)
daniel@transgaming.com741a5882010-05-20 19:17:29 +000037 mDeviceType = D3DDEVTYPE_REF;
38 #else
39 mDeviceType = D3DDEVTYPE_HAL;
40 #endif
daniel@transgaming.com616ffcf2010-05-07 19:01:49 +000041
42 mMinSwapInterval = 1;
43 mMaxSwapInterval = 1;
44 setSwapInterval(1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045}
46
47Display::~Display()
48{
49 terminate();
50}
51
52bool Display::initialize()
53{
54 if (isInitialized())
55 {
56 return true;
57 }
58
apatrick@chromium.org94e19342010-08-17 22:19:58 +000059 mD3d9Module = LoadLibrary(TEXT("d3d9.dll"));
60 if (mD3d9Module == NULL)
61 {
62 terminate();
63 return false;
64 }
65
66 typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT);
67 Direct3DCreate9Func Direct3DCreate9Ptr = reinterpret_cast<Direct3DCreate9Func>(GetProcAddress(mD3d9Module, "Direct3DCreate9"));
68
69 if (Direct3DCreate9Ptr == NULL)
70 {
71 terminate();
72 return false;
73 }
74
75 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
76 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
77
78 // Use Direct3D9Ex if available. Among other things, this version is less
79 // inclined to report a lost context, for example when the user switches
80 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +000081 if (ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
apatrick@chromium.org94e19342010-08-17 22:19:58 +000082 {
83 ASSERT(mD3d9ex);
84 mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
85 ASSERT(mD3d9);
86 }
87 else
88 {
89 mD3d9 = Direct3DCreate9Ptr(D3D_SDK_VERSION);
90 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091
92 if (mD3d9)
93 {
94 if (mDc != NULL)
95 {
daniel@transgaming.com02bc1592010-03-30 03:36:13 +000096 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097 }
98
daniel@transgaming.com353569a2010-06-24 13:02:12 +000099 HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
101 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
102 {
103 return error(EGL_BAD_ALLOC, false);
104 }
105
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000106 ASSERT(SUCCEEDED(result));
107
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000108 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109 {
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000110 terminate();
111 return error(EGL_NOT_INITIALIZED, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112 }
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000113
114 mMinSwapInterval = 4;
115 mMaxSwapInterval = 0;
116
117 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
118 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
119 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
120 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
121 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
122
123 const D3DFORMAT renderTargetFormats[] =
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 {
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000125 D3DFMT_A1R5G5B5,
126 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
127 D3DFMT_A8R8G8B8,
128 D3DFMT_R5G6B5,
129 D3DFMT_X1R5G5B5,
130 D3DFMT_X8R8G8B8
131 };
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000133 const D3DFORMAT depthStencilFormats[] =
134 {
135 // D3DFMT_D16_LOCKABLE,
136 D3DFMT_D32,
137 // D3DFMT_D15S1,
138 D3DFMT_D24S8,
139 D3DFMT_D24X8,
140 // D3DFMT_D24X4S4,
141 D3DFMT_D16,
142 // D3DFMT_D32F_LOCKABLE,
143 // D3DFMT_D24FS8
144 };
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000146 D3DDISPLAYMODE currentDisplayMode;
147 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
148
149 ConfigSet configSet;
150
151 for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
152 {
153 D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
154
155 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
156
157 if (SUCCEEDED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158 {
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000159 for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160 {
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000161 D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
162 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
163
164 if (SUCCEEDED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165 {
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000166 HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167
168 if (SUCCEEDED(result))
169 {
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000170 // FIXME: enumerate multi-sampling
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000171
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000172 configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173 }
174 }
175 }
176 }
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000177 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000179 // Give the sorted configs a unique ID and store them internally
180 EGLint index = 1;
181 for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
182 {
183 Config configuration = *config;
184 configuration.mConfigID = index;
185 index++;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000186
apatrick@chromium.org6ad6ce82010-08-12 00:16:16 +0000187 mConfigSet.mSet.insert(configuration);
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000188 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189 }
190
191 if (!isInitialized())
192 {
193 terminate();
194
195 return false;
196 }
197
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000198 static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
199 static const TCHAR className[] = TEXT("STATIC");
200
201 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
202
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203 return true;
204}
205
206void Display::terminate()
207{
208 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
209 {
210 delete *surface;
211 }
212
213 for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
214 {
215 glDestroyContext(*context);
216 }
217
218 if (mDevice)
219 {
220 mDevice->Release();
221 mDevice = NULL;
222 }
223
224 if (mD3d9)
225 {
226 mD3d9->Release();
227 mD3d9 = NULL;
228 }
daniel@transgaming.comda6e2632010-07-28 19:21:18 +0000229
230 if (mDeviceWindow)
231 {
232 DestroyWindow(mDeviceWindow);
233 mDeviceWindow = NULL;
234 }
apatrick@chromium.org94e19342010-08-17 22:19:58 +0000235
236 if (mD3d9ex)
237 {
238 mD3d9ex->Release();
239 mD3d9ex = NULL;
240 }
241
242 if (mD3d9Module)
243 {
244 FreeLibrary(mD3d9Module);
245 mD3d9Module = NULL;
246 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247}
248
daniel@transgaming.comae072af2010-05-05 18:47:28 +0000249void Display::startScene()
250{
251 if (!mSceneStarted)
252 {
253 long result = mDevice->BeginScene();
254 ASSERT(SUCCEEDED(result));
255 mSceneStarted = true;
256 }
257}
258
259void Display::endScene()
260{
261 if (mSceneStarted)
262 {
263 long result = mDevice->EndScene();
264 ASSERT(SUCCEEDED(result));
265 mSceneStarted = false;
266 }
267}
268
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
270{
271 return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
272}
273
274bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
275{
276 const egl::Config *configuration = mConfigSet.get(config);
277
278 switch (attribute)
279 {
280 case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
281 case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
282 case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
283 case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
284 case EGL_RED_SIZE: *value = configuration->mRedSize; break;
285 case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
286 case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
287 case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
288 case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
289 case EGL_LEVEL: *value = configuration->mLevel; break;
290 case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
291 case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
292 case EGL_SAMPLES: *value = configuration->mSamples; break;
293 case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
294 case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
295 case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
296 case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
297 case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
298 case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
299 case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
300 case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
301 case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
302 case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
303 case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
304 case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
305 case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
306 case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000307 case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308 case EGL_CONFORMANT: *value = configuration->mConformant; break;
309 default:
310 return false;
311 }
312
313 return true;
314}
315
daniel@transgaming.com37fa3c82010-07-28 19:21:21 +0000316bool Display::createDevice()
317{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000318 D3DPRESENT_PARAMETERS presentParameters = getPresentParameters();
daniel@transgaming.com37fa3c82010-07-28 19:21:21 +0000319 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
320
321 HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
322
323 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
324 {
325 return error(EGL_BAD_ALLOC, false);
326 }
327
328 if (FAILED(result))
329 {
330 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
331
332 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
333 {
334 return error(EGL_BAD_ALLOC, false);
335 }
336 }
337
338 ASSERT(SUCCEEDED(result));
339
340 // Permanent non-default states
341 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
342
343 mSceneStarted = false;
344
345 return true;
daniel@transgaming.comda6e2632010-07-28 19:21:18 +0000346}
347
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000348Surface *Display::createWindowSurface(HWND window, EGLConfig config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349{
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000350 const Config *configuration = mConfigSet.get(config);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
daniel@transgaming.comda6e2632010-07-28 19:21:18 +0000352 Surface *surface = new Surface(this, configuration, window);
353 mSurfaceSet.insert(surface);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000354
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355 return surface;
356}
357
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000358EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000360 if (!mDevice)
361 {
362 if (!createDevice())
363 {
364 return NULL;
365 }
366 }
367 else if (FAILED(mDevice->TestCooperativeLevel())) // Lost device
368 {
369 D3DPRESENT_PARAMETERS presentParameters = getPresentParameters();
370 HRESULT result;
371
372 do
373 {
374 Sleep(0); // Give the graphics driver some CPU time
375
376 result = mDevice->Reset(&presentParameters);
377 }
378 while (result == D3DERR_DEVICELOST);
379
380 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICEREMOVED || result == D3DERR_DRIVERINTERNALERROR)
381 {
382 return error(EGL_BAD_ALLOC, (EGLContext)NULL);
383 }
384
385 ASSERT(SUCCEEDED(result));
386
387 // Restore any surfaces that may have been lost
388 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
389 {
390 (*surface)->resetSwapChain();
391 }
392 }
393
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394 const egl::Config *config = mConfigSet.get(configHandle);
395
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000396 gl::Context *context = glCreateContext(config, shareContext);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397 mContextSet.insert(context);
398
399 return context;
400}
401
402void Display::destroySurface(egl::Surface *surface)
403{
404 delete surface;
405 mSurfaceSet.erase(surface);
406}
407
408void Display::destroyContext(gl::Context *context)
409{
410 glDestroyContext(context);
411 mContextSet.erase(context);
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000412
413 if (mContextSet.empty() && mDevice && FAILED(mDevice->TestCooperativeLevel())) // Last context of a lost device
414 {
415 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
416 {
417 (*surface)->release();
418 }
419 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420}
421
422bool Display::isInitialized()
423{
424 return mD3d9 != NULL && mConfigSet.size() > 0;
425}
426
427bool Display::isValidConfig(EGLConfig config)
428{
429 return mConfigSet.get(config) != NULL;
430}
431
432bool Display::isValidContext(gl::Context *context)
433{
434 return mContextSet.find(context) != mContextSet.end();
435}
436
437bool Display::isValidSurface(egl::Surface *surface)
438{
439 return mSurfaceSet.find(surface) != mSurfaceSet.end();
440}
441
442bool Display::hasExistingWindowSurface(HWND window)
443{
444 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
445 {
446 if ((*surface)->getWindowHandle() == window)
447 {
448 return true;
449 }
450 }
451
452 return false;
453}
454
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000455void Display::setSwapInterval(GLint interval)
456{
457 mSwapInterval = interval;
daniel@transgaming.com616ffcf2010-05-07 19:01:49 +0000458 mSwapInterval = std::max(mSwapInterval, mMinSwapInterval);
459 mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval);
460
461 mPresentInterval = convertInterval(mSwapInterval);
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000462}
463
daniel@transgaming.com616ffcf2010-05-07 19:01:49 +0000464DWORD Display::getPresentInterval()
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000465{
daniel@transgaming.com616ffcf2010-05-07 19:01:49 +0000466 return mPresentInterval;
467}
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000468
daniel@transgaming.com616ffcf2010-05-07 19:01:49 +0000469DWORD Display::convertInterval(GLint interval)
470{
daniel@transgaming.comb6bd7272010-05-05 18:48:22 +0000471 switch(interval)
472 {
473 case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
474 case 1: return D3DPRESENT_INTERVAL_ONE;
475 case 2: return D3DPRESENT_INTERVAL_TWO;
476 case 3: return D3DPRESENT_INTERVAL_THREE;
477 case 4: return D3DPRESENT_INTERVAL_FOUR;
478 default: UNREACHABLE();
479 }
480
481 return D3DPRESENT_INTERVAL_DEFAULT;
482}
483
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484IDirect3DDevice9 *Display::getDevice()
485{
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000486 if (!mDevice)
487 {
488 if (!createDevice())
489 {
490 return NULL;
491 }
492 }
493
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494 return mDevice;
495}
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000496
497D3DCAPS9 Display::getDeviceCaps()
498{
499 return mDeviceCaps;
500}
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000501
502void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
503{
504 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
505 {
506 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
507 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
508
509 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
510 }
511}
daniel@transgaming.com01868132010-08-24 19:21:17 +0000512
513bool Display::getCompressedTextureSupport()
514{
515 D3DDISPLAYMODE currentDisplayMode;
516 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
517
518 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
519}
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000520
521bool Display::getFloatTextureSupport(bool *filtering)
522{
523 D3DDISPLAYMODE currentDisplayMode;
524 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
525
526 if (SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
527 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
528 {
529 *filtering = true;
530 return true;
531 }
532 else
533 {
534 *filtering = false;
535 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
536 D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
537 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
538 D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
539 }
540}
541
542bool Display::getHalfFloatTextureSupport(bool *filtering)
543{
544 D3DDISPLAYMODE currentDisplayMode;
545 mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
546
547 if (SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
548 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)))
549 {
550 *filtering = true;
551 return true;
552 }
553 else
554 {
555 *filtering = false;
556 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
557 D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
558 SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
559 D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
560 }
561}
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000562
563bool Display::getEventQuerySupport()
564{
565 IDirect3DQuery9 *query;
566 HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
567 if (SUCCEEDED(result))
568 {
569 query->Release();
570 }
571
572 return result != D3DERR_NOTAVAILABLE;
573}
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000574
575D3DPRESENT_PARAMETERS Display::getPresentParameters()
576{
577 D3DPRESENT_PARAMETERS presentParameters = {0};
578
579 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
580 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
581 presentParameters.BackBufferCount = 1;
582 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
583 presentParameters.BackBufferWidth = 1;
584 presentParameters.BackBufferHeight = 1;
585 presentParameters.EnableAutoDepthStencil = FALSE;
586 presentParameters.Flags = 0;
587 presentParameters.hDeviceWindow = mDeviceWindow;
588 presentParameters.MultiSampleQuality = 0;
589 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
590 presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
591 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
592 presentParameters.Windowed = TRUE;
593
594 return presentParameters;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595}
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000596}