1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libEGL/Display.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,537 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +// Display.cpp: Implements the egl::Display class, representing the abstract 1.11 +// display on which graphics are drawn. Implements EGLDisplay. 1.12 +// [EGL 1.4] section 2.1.2 page 3. 1.13 + 1.14 +#include "libEGL/Display.h" 1.15 + 1.16 +#include <algorithm> 1.17 +#include <map> 1.18 +#include <vector> 1.19 + 1.20 +#include "common/debug.h" 1.21 +#include "libGLESv2/mathutil.h" 1.22 +#include "libGLESv2/main.h" 1.23 +#include "libGLESv2/Context.h" 1.24 +#include "libGLESv2/renderer/SwapChain.h" 1.25 + 1.26 +#include "libEGL/main.h" 1.27 +#include "libEGL/Surface.h" 1.28 + 1.29 +namespace egl 1.30 +{ 1.31 +namespace 1.32 +{ 1.33 + typedef std::map<EGLNativeDisplayType, Display*> DisplayMap; 1.34 + DisplayMap displays; 1.35 +} 1.36 + 1.37 +egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) 1.38 +{ 1.39 + if (displays.find(displayId) != displays.end()) 1.40 + { 1.41 + return displays[displayId]; 1.42 + } 1.43 + 1.44 + // FIXME: Check if displayId is a valid display device context 1.45 + 1.46 + egl::Display *display = new egl::Display(displayId, (HDC)displayId); 1.47 + 1.48 + displays[displayId] = display; 1.49 + return display; 1.50 +} 1.51 + 1.52 +Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext) 1.53 +{ 1.54 + mDisplayId = displayId; 1.55 + mRenderer = NULL; 1.56 +} 1.57 + 1.58 +Display::~Display() 1.59 +{ 1.60 + terminate(); 1.61 + 1.62 + DisplayMap::iterator thisDisplay = displays.find(mDisplayId); 1.63 + 1.64 + if (thisDisplay != displays.end()) 1.65 + { 1.66 + displays.erase(thisDisplay); 1.67 + } 1.68 +} 1.69 + 1.70 +bool Display::initialize() 1.71 +{ 1.72 + if (isInitialized()) 1.73 + { 1.74 + return true; 1.75 + } 1.76 + 1.77 + mRenderer = glCreateRenderer(this, mDc, mDisplayId); 1.78 + 1.79 + if (!mRenderer) 1.80 + { 1.81 + terminate(); 1.82 + return error(EGL_NOT_INITIALIZED, false); 1.83 + } 1.84 + 1.85 + EGLint minSwapInterval = mRenderer->getMinSwapInterval(); 1.86 + EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); 1.87 + EGLint maxTextureWidth = mRenderer->getMaxTextureWidth(); 1.88 + EGLint maxTextureHeight = mRenderer->getMaxTextureHeight(); 1.89 + 1.90 + rx::ConfigDesc *descList; 1.91 + int numConfigs = mRenderer->generateConfigs(&descList); 1.92 + ConfigSet configSet; 1.93 + 1.94 + for (int i = 0; i < numConfigs; ++i) 1.95 + configSet.add(descList[i], minSwapInterval, maxSwapInterval, 1.96 + maxTextureWidth, maxTextureHeight); 1.97 + 1.98 + // Give the sorted configs a unique ID and store them internally 1.99 + EGLint index = 1; 1.100 + for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) 1.101 + { 1.102 + Config configuration = *config; 1.103 + configuration.mConfigID = index; 1.104 + index++; 1.105 + 1.106 + mConfigSet.mSet.insert(configuration); 1.107 + } 1.108 + 1.109 + mRenderer->deleteConfigs(descList); 1.110 + descList = NULL; 1.111 + 1.112 + if (!isInitialized()) 1.113 + { 1.114 + terminate(); 1.115 + return false; 1.116 + } 1.117 + 1.118 + initExtensionString(); 1.119 + initVendorString(); 1.120 + 1.121 + return true; 1.122 +} 1.123 + 1.124 +void Display::terminate() 1.125 +{ 1.126 + while (!mSurfaceSet.empty()) 1.127 + { 1.128 + destroySurface(*mSurfaceSet.begin()); 1.129 + } 1.130 + 1.131 + while (!mContextSet.empty()) 1.132 + { 1.133 + destroyContext(*mContextSet.begin()); 1.134 + } 1.135 + 1.136 + glDestroyRenderer(mRenderer); 1.137 + mRenderer = NULL; 1.138 +} 1.139 + 1.140 +bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) 1.141 +{ 1.142 + return mConfigSet.getConfigs(configs, attribList, configSize, numConfig); 1.143 +} 1.144 + 1.145 +bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) 1.146 +{ 1.147 + const egl::Config *configuration = mConfigSet.get(config); 1.148 + 1.149 + switch (attribute) 1.150 + { 1.151 + case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break; 1.152 + case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break; 1.153 + case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break; 1.154 + case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break; 1.155 + case EGL_RED_SIZE: *value = configuration->mRedSize; break; 1.156 + case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break; 1.157 + case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break; 1.158 + case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break; 1.159 + case EGL_CONFIG_ID: *value = configuration->mConfigID; break; 1.160 + case EGL_LEVEL: *value = configuration->mLevel; break; 1.161 + case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break; 1.162 + case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break; 1.163 + case EGL_SAMPLES: *value = configuration->mSamples; break; 1.164 + case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break; 1.165 + case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break; 1.166 + case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break; 1.167 + case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break; 1.168 + case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break; 1.169 + case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break; 1.170 + case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break; 1.171 + case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break; 1.172 + case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break; 1.173 + case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break; 1.174 + case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break; 1.175 + case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break; 1.176 + case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break; 1.177 + case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break; 1.178 + case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; 1.179 + case EGL_CONFORMANT: *value = configuration->mConformant; break; 1.180 + case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break; 1.181 + case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break; 1.182 + case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break; 1.183 + default: 1.184 + return false; 1.185 + } 1.186 + 1.187 + return true; 1.188 +} 1.189 + 1.190 + 1.191 + 1.192 +EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) 1.193 +{ 1.194 + const Config *configuration = mConfigSet.get(config); 1.195 + EGLint postSubBufferSupported = EGL_FALSE; 1.196 + 1.197 + if (attribList) 1.198 + { 1.199 + while (*attribList != EGL_NONE) 1.200 + { 1.201 + switch (attribList[0]) 1.202 + { 1.203 + case EGL_RENDER_BUFFER: 1.204 + switch (attribList[1]) 1.205 + { 1.206 + case EGL_BACK_BUFFER: 1.207 + break; 1.208 + case EGL_SINGLE_BUFFER: 1.209 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported 1.210 + default: 1.211 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.212 + } 1.213 + break; 1.214 + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: 1.215 + postSubBufferSupported = attribList[1]; 1.216 + break; 1.217 + case EGL_VG_COLORSPACE: 1.218 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.219 + case EGL_VG_ALPHA_FORMAT: 1.220 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.221 + default: 1.222 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.223 + } 1.224 + 1.225 + attribList += 2; 1.226 + } 1.227 + } 1.228 + 1.229 + if (hasExistingWindowSurface(window)) 1.230 + { 1.231 + return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); 1.232 + } 1.233 + 1.234 + if (mRenderer->testDeviceLost(false)) 1.235 + { 1.236 + if (!restoreLostDevice()) 1.237 + return EGL_NO_SURFACE; 1.238 + } 1.239 + 1.240 + Surface *surface = new Surface(this, configuration, window, postSubBufferSupported); 1.241 + 1.242 + if (!surface->initialize()) 1.243 + { 1.244 + delete surface; 1.245 + return EGL_NO_SURFACE; 1.246 + } 1.247 + 1.248 + mSurfaceSet.insert(surface); 1.249 + 1.250 + return success(surface); 1.251 +} 1.252 + 1.253 +EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList) 1.254 +{ 1.255 + EGLint width = 0, height = 0; 1.256 + EGLenum textureFormat = EGL_NO_TEXTURE; 1.257 + EGLenum textureTarget = EGL_NO_TEXTURE; 1.258 + const Config *configuration = mConfigSet.get(config); 1.259 + 1.260 + if (attribList) 1.261 + { 1.262 + while (*attribList != EGL_NONE) 1.263 + { 1.264 + switch (attribList[0]) 1.265 + { 1.266 + case EGL_WIDTH: 1.267 + width = attribList[1]; 1.268 + break; 1.269 + case EGL_HEIGHT: 1.270 + height = attribList[1]; 1.271 + break; 1.272 + case EGL_LARGEST_PBUFFER: 1.273 + if (attribList[1] != EGL_FALSE) 1.274 + UNIMPLEMENTED(); // FIXME 1.275 + break; 1.276 + case EGL_TEXTURE_FORMAT: 1.277 + switch (attribList[1]) 1.278 + { 1.279 + case EGL_NO_TEXTURE: 1.280 + case EGL_TEXTURE_RGB: 1.281 + case EGL_TEXTURE_RGBA: 1.282 + textureFormat = attribList[1]; 1.283 + break; 1.284 + default: 1.285 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.286 + } 1.287 + break; 1.288 + case EGL_TEXTURE_TARGET: 1.289 + switch (attribList[1]) 1.290 + { 1.291 + case EGL_NO_TEXTURE: 1.292 + case EGL_TEXTURE_2D: 1.293 + textureTarget = attribList[1]; 1.294 + break; 1.295 + default: 1.296 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.297 + } 1.298 + break; 1.299 + case EGL_MIPMAP_TEXTURE: 1.300 + if (attribList[1] != EGL_FALSE) 1.301 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.302 + break; 1.303 + case EGL_VG_COLORSPACE: 1.304 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.305 + case EGL_VG_ALPHA_FORMAT: 1.306 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.307 + default: 1.308 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.309 + } 1.310 + 1.311 + attribList += 2; 1.312 + } 1.313 + } 1.314 + 1.315 + if (width < 0 || height < 0) 1.316 + { 1.317 + return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1.318 + } 1.319 + 1.320 + if (width == 0 || height == 0) 1.321 + { 1.322 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.323 + } 1.324 + 1.325 + if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) 1.326 + { 1.327 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.328 + } 1.329 + 1.330 + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || 1.331 + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) 1.332 + { 1.333 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.334 + } 1.335 + 1.336 + if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) 1.337 + { 1.338 + return error(EGL_BAD_MATCH, EGL_NO_SURFACE); 1.339 + } 1.340 + 1.341 + if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || 1.342 + (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) 1.343 + { 1.344 + return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1.345 + } 1.346 + 1.347 + if (mRenderer->testDeviceLost(false)) 1.348 + { 1.349 + if (!restoreLostDevice()) 1.350 + return EGL_NO_SURFACE; 1.351 + } 1.352 + 1.353 + Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); 1.354 + 1.355 + if (!surface->initialize()) 1.356 + { 1.357 + delete surface; 1.358 + return EGL_NO_SURFACE; 1.359 + } 1.360 + 1.361 + mSurfaceSet.insert(surface); 1.362 + 1.363 + return success(surface); 1.364 +} 1.365 + 1.366 +EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) 1.367 +{ 1.368 + if (!mRenderer) 1.369 + { 1.370 + return NULL; 1.371 + } 1.372 + else if (mRenderer->testDeviceLost(false)) // Lost device 1.373 + { 1.374 + if (!restoreLostDevice()) 1.375 + return NULL; 1.376 + } 1.377 + 1.378 + gl::Context *context = glCreateContext(shareContext, mRenderer, notifyResets, robustAccess); 1.379 + mContextSet.insert(context); 1.380 + 1.381 + return context; 1.382 +} 1.383 + 1.384 +bool Display::restoreLostDevice() 1.385 +{ 1.386 + for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) 1.387 + { 1.388 + if ((*ctx)->isResetNotificationEnabled()) 1.389 + return false; // If reset notifications have been requested, application must delete all contexts first 1.390 + } 1.391 + 1.392 + // Release surface resources to make the Reset() succeed 1.393 + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) 1.394 + { 1.395 + (*surface)->release(); 1.396 + } 1.397 + 1.398 + if (!mRenderer->resetDevice()) 1.399 + { 1.400 + return error(EGL_BAD_ALLOC, false); 1.401 + } 1.402 + 1.403 + // Restore any surfaces that may have been lost 1.404 + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) 1.405 + { 1.406 + (*surface)->resetSwapChain(); 1.407 + } 1.408 + 1.409 + return true; 1.410 +} 1.411 + 1.412 + 1.413 +void Display::destroySurface(egl::Surface *surface) 1.414 +{ 1.415 + delete surface; 1.416 + mSurfaceSet.erase(surface); 1.417 +} 1.418 + 1.419 +void Display::destroyContext(gl::Context *context) 1.420 +{ 1.421 + glDestroyContext(context); 1.422 + mContextSet.erase(context); 1.423 +} 1.424 + 1.425 +void Display::notifyDeviceLost() 1.426 +{ 1.427 + for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) 1.428 + { 1.429 + (*context)->markContextLost(); 1.430 + } 1.431 + egl::error(EGL_CONTEXT_LOST); 1.432 +} 1.433 + 1.434 +void Display::recreateSwapChains() 1.435 +{ 1.436 + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) 1.437 + { 1.438 + (*surface)->getSwapChain()->recreate(); 1.439 + } 1.440 +} 1.441 + 1.442 +bool Display::isInitialized() const 1.443 +{ 1.444 + return mRenderer != NULL && mConfigSet.size() > 0; 1.445 +} 1.446 + 1.447 +bool Display::isValidConfig(EGLConfig config) 1.448 +{ 1.449 + return mConfigSet.get(config) != NULL; 1.450 +} 1.451 + 1.452 +bool Display::isValidContext(gl::Context *context) 1.453 +{ 1.454 + return mContextSet.find(context) != mContextSet.end(); 1.455 +} 1.456 + 1.457 +bool Display::isValidSurface(egl::Surface *surface) 1.458 +{ 1.459 + return mSurfaceSet.find(surface) != mSurfaceSet.end(); 1.460 +} 1.461 + 1.462 +bool Display::hasExistingWindowSurface(HWND window) 1.463 +{ 1.464 + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) 1.465 + { 1.466 + if ((*surface)->getWindowHandle() == window) 1.467 + { 1.468 + return true; 1.469 + } 1.470 + } 1.471 + 1.472 + return false; 1.473 +} 1.474 + 1.475 +void Display::initExtensionString() 1.476 +{ 1.477 + HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); 1.478 + bool shareHandleSupported = mRenderer->getShareHandleSupport(); 1.479 + 1.480 + mExtensionString = ""; 1.481 + 1.482 + // Multi-vendor (EXT) extensions 1.483 + mExtensionString += "EGL_EXT_create_context_robustness "; 1.484 + 1.485 + // ANGLE-specific extensions 1.486 + if (shareHandleSupported) 1.487 + { 1.488 + mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; 1.489 + } 1.490 + 1.491 + mExtensionString += "EGL_ANGLE_query_surface_pointer "; 1.492 + 1.493 + if (swiftShader) 1.494 + { 1.495 + mExtensionString += "EGL_ANGLE_software_display "; 1.496 + } 1.497 + 1.498 + if (shareHandleSupported) 1.499 + { 1.500 + mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; 1.501 + } 1.502 + 1.503 + if (mRenderer->getPostSubBufferSupport()) 1.504 + { 1.505 + mExtensionString += "EGL_NV_post_sub_buffer"; 1.506 + } 1.507 + 1.508 + std::string::size_type end = mExtensionString.find_last_not_of(' '); 1.509 + if (end != std::string::npos) 1.510 + { 1.511 + mExtensionString.resize(end+1); 1.512 + } 1.513 +} 1.514 + 1.515 +const char *Display::getExtensionString() const 1.516 +{ 1.517 + return mExtensionString.c_str(); 1.518 +} 1.519 + 1.520 +void Display::initVendorString() 1.521 +{ 1.522 + mVendorString = "Google Inc."; 1.523 + 1.524 + LUID adapterLuid = {0}; 1.525 + 1.526 + if (mRenderer && mRenderer->getLUID(&adapterLuid)) 1.527 + { 1.528 + char adapterLuidString[64]; 1.529 + sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); 1.530 + 1.531 + mVendorString += adapterLuidString; 1.532 + } 1.533 +} 1.534 + 1.535 +const char *Display::getVendorString() const 1.536 +{ 1.537 + return mVendorString.c_str(); 1.538 +} 1.539 + 1.540 +}