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.
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.
11 #include "libEGL/Display.h"
16 #include "common/debug.h"
18 #include "libEGL/main.h"
20 #define REF_RAST 0 // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
24 Display::Display(HDC deviceContext) : mDc(deviceContext)
33 mAdapter = D3DADAPTER_DEFAULT;
35 #if REF_RAST == 1 || defined(FORCE_REF_RAST)
36 mDeviceType = D3DDEVTYPE_REF;
38 mDeviceType = D3DDEVTYPE_HAL;
51 bool Display::initialize()
58 mD3d9Module = LoadLibrary(TEXT("d3d9.dll"));
59 if (mD3d9Module == NULL)
65 typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT);
66 Direct3DCreate9Func Direct3DCreate9Ptr = reinterpret_cast<Direct3DCreate9Func>(GetProcAddress(mD3d9Module, "Direct3DCreate9"));
68 if (Direct3DCreate9Ptr == NULL)
74 typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
75 Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
77 // Use Direct3D9Ex if available. Among other things, this version is less
78 // inclined to report a lost context, for example when the user switches
79 // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
80 if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
83 mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
88 mD3d9 = Direct3DCreate9Ptr(D3D_SDK_VERSION);
95 // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
98 HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
100 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
102 return error(EGL_BAD_ALLOC, false);
105 if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
108 return error(EGL_NOT_INITIALIZED, false);
111 mMinSwapInterval = 4;
112 mMaxSwapInterval = 0;
114 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);}
115 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);}
116 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);}
117 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
118 if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
120 const D3DFORMAT renderTargetFormats[] =
123 // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
130 const D3DFORMAT depthStencilFormats[] =
132 // D3DFMT_D16_LOCKABLE,
139 // D3DFMT_D32F_LOCKABLE,
143 D3DDISPLAYMODE currentDisplayMode;
144 mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
148 for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
150 D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];
152 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
154 if (SUCCEEDED(result))
156 for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
158 D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
159 HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
161 if (SUCCEEDED(result))
163 HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
165 if (SUCCEEDED(result))
167 // FIXME: enumerate multi-sampling
169 configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
176 // Give the sorted configs a unique ID and store them internally
178 for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
180 Config configuration = *config;
181 configuration.mConfigID = index;
184 mConfigSet.mSet.insert(configuration);
195 if (!isInitialized())
205 void Display::terminate()
207 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
212 for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
214 glDestroyContext(*context);
231 DestroyWindow(mDeviceWindow);
232 mDeviceWindow = NULL;
243 FreeLibrary(mD3d9Module);
248 void Display::startScene()
252 long result = mDevice->BeginScene();
253 ASSERT(SUCCEEDED(result));
254 mSceneStarted = true;
258 void Display::endScene()
262 long result = mDevice->EndScene();
263 ASSERT(SUCCEEDED(result));
264 mSceneStarted = false;
268 bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
270 return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
273 bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
275 const egl::Config *configuration = mConfigSet.get(config);
279 case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
280 case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
281 case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
282 case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
283 case EGL_RED_SIZE: *value = configuration->mRedSize; break;
284 case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
285 case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
286 case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
287 case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
288 case EGL_LEVEL: *value = configuration->mLevel; break;
289 case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
290 case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
291 case EGL_SAMPLES: *value = configuration->mSamples; break;
292 case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
293 case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
294 case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
295 case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
296 case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
297 case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
298 case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
299 case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
300 case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
301 case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
302 case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
303 case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
304 case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
305 case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
306 case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
307 case EGL_CONFORMANT: *value = configuration->mConformant; break;
315 bool Display::createDevice()
317 static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
318 static const TCHAR className[] = TEXT("STATIC");
320 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
322 D3DPRESENT_PARAMETERS presentParameters = {0};
324 // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
325 presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
326 presentParameters.BackBufferCount = 1;
327 presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
328 presentParameters.BackBufferWidth = 1;
329 presentParameters.BackBufferHeight = 1;
330 presentParameters.EnableAutoDepthStencil = FALSE;
331 presentParameters.Flags = 0;
332 presentParameters.hDeviceWindow = mDeviceWindow;
333 presentParameters.MultiSampleQuality = 0;
334 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
335 presentParameters.PresentationInterval = convertInterval(mMinSwapInterval);
336 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
337 presentParameters.Windowed = TRUE;
339 DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
341 HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
343 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
345 return error(EGL_BAD_ALLOC, false);
350 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
352 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
354 return error(EGL_BAD_ALLOC, false);
358 ASSERT(SUCCEEDED(result));
360 // Permanent non-default states
361 mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
363 mSceneStarted = false;
368 Surface *Display::createWindowSurface(HWND window, EGLConfig config)
370 const Config *configuration = mConfigSet.get(config);
372 Surface *surface = new Surface(this, configuration, window);
373 mSurfaceSet.insert(surface);
378 EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext)
380 const egl::Config *config = mConfigSet.get(configHandle);
382 gl::Context *context = glCreateContext(config, shareContext);
383 mContextSet.insert(context);
388 void Display::destroySurface(egl::Surface *surface)
391 mSurfaceSet.erase(surface);
394 void Display::destroyContext(gl::Context *context)
396 glDestroyContext(context);
397 mContextSet.erase(context);
400 bool Display::isInitialized()
402 return mD3d9 != NULL && mConfigSet.size() > 0;
405 bool Display::isValidConfig(EGLConfig config)
407 return mConfigSet.get(config) != NULL;
410 bool Display::isValidContext(gl::Context *context)
412 return mContextSet.find(context) != mContextSet.end();
415 bool Display::isValidSurface(egl::Surface *surface)
417 return mSurfaceSet.find(surface) != mSurfaceSet.end();
420 bool Display::hasExistingWindowSurface(HWND window)
422 for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
424 if ((*surface)->getWindowHandle() == window)
433 void Display::setSwapInterval(GLint interval)
435 mSwapInterval = interval;
436 mSwapInterval = std::max(mSwapInterval, mMinSwapInterval);
437 mSwapInterval = std::min(mSwapInterval, mMaxSwapInterval);
439 mPresentInterval = convertInterval(mSwapInterval);
442 DWORD Display::getPresentInterval()
444 return mPresentInterval;
447 DWORD Display::convertInterval(GLint interval)
451 case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
452 case 1: return D3DPRESENT_INTERVAL_ONE;
453 case 2: return D3DPRESENT_INTERVAL_TWO;
454 case 3: return D3DPRESENT_INTERVAL_THREE;
455 case 4: return D3DPRESENT_INTERVAL_FOUR;
456 default: UNREACHABLE();
459 return D3DPRESENT_INTERVAL_DEFAULT;
462 IDirect3DDevice9 *Display::getDevice()
467 D3DCAPS9 Display::getDeviceCaps()
472 void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
474 for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
476 HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
477 TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
479 multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
483 bool Display::getCompressedTextureSupport()
485 D3DDISPLAYMODE currentDisplayMode;
486 mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode);
488 return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));