diff options
Diffstat (limited to 'gfx/angle/src/libANGLE/Display.cpp')
-rwxr-xr-x | gfx/angle/src/libANGLE/Display.cpp | 1033 |
1 files changed, 1033 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/Display.cpp b/gfx/angle/src/libANGLE/Display.cpp new file mode 100755 index 000000000..39851f9f8 --- /dev/null +++ b/gfx/angle/src/libANGLE/Display.cpp @@ -0,0 +1,1033 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Display.cpp: Implements the egl::Display class, representing the abstract +// display on which graphics are drawn. Implements EGLDisplay. +// [EGL 1.4] section 2.1.2 page 3. + +#include "libANGLE/Display.h" + +#include <algorithm> +#include <iterator> +#include <map> +#include <sstream> +#include <vector> + +#include <platform/Platform.h> +#include <EGL/eglext.h> + +#include "common/debug.h" +#include "common/mathutil.h" +#include "common/platform.h" +#include "common/utilities.h" +#include "libANGLE/Context.h" +#include "libANGLE/Device.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/Image.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Stream.h" +#include "libANGLE/renderer/DisplayImpl.h" +#include "libANGLE/renderer/ImageImpl.h" +#include "third_party/trace_event/trace_event.h" + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/DisplayD3D.h" +#endif + +#if defined(ANGLE_ENABLE_OPENGL) +# if defined(ANGLE_PLATFORM_WINDOWS) +# include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +# elif defined(ANGLE_USE_X11) +# include "libANGLE/renderer/gl/glx/DisplayGLX.h" +# elif defined(ANGLE_PLATFORM_APPLE) +# include "libANGLE/renderer/gl/cgl/DisplayCGL.h" +# elif defined(ANGLE_USE_OZONE) +# include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h" +# elif defined(ANGLE_PLATFORM_ANDROID) +# include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h" +# else +# error Unsupported OpenGL platform. +# endif +#endif + +#if defined(ANGLE_ENABLE_NULL) +#include "libANGLE/renderer/null/DisplayNULL.h" +#endif + +namespace egl +{ + +namespace +{ + +class DefaultPlatform : public angle::Platform +{ +public: + DefaultPlatform() {} + ~DefaultPlatform() override {} +}; + +DefaultPlatform *defaultPlatform = nullptr; + +void InitDefaultPlatformImpl() +{ + if (ANGLEPlatformCurrent() == nullptr) + { + if (defaultPlatform == nullptr) + { + defaultPlatform = new DefaultPlatform(); + } + + ANGLEPlatformInitialize(defaultPlatform); + } +} + +typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap; +// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface +// associated with it. +static WindowSurfaceMap *GetWindowSurfaces() +{ + static WindowSurfaceMap windowSurfaces; + return &windowSurfaces; +} + +typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap; +static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap() +{ + static ANGLEPlatformDisplayMap displays; + return &displays; +} + +typedef std::map<Device *, Display *> DevicePlatformDisplayMap; +static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap() +{ + static DevicePlatformDisplayMap displays; + return &displays; +} + +rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice) +{ + rx::DisplayImpl *impl = nullptr; + + switch (eglDevice->getType()) + { +#if defined(ANGLE_ENABLE_D3D11) + case EGL_D3D11_DEVICE_ANGLE: + impl = new rx::DisplayD3D(); + break; +#endif +#if defined(ANGLE_ENABLE_D3D9) + case EGL_D3D9_DEVICE_ANGLE: + // Currently the only way to get EGLDeviceEXT representing a D3D9 device + // is to retrieve one from an already-existing EGLDisplay. + // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT, + // the already-existing display should be returned. + // Therefore this codepath to create a new display from the device + // should never be hit. + UNREACHABLE(); + break; +#endif + default: + UNREACHABLE(); + break; + } + + ASSERT(impl != nullptr); + return impl; +} + +rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap) +{ + rx::DisplayImpl *impl = nullptr; + EGLAttrib displayType = + attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + switch (displayType) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + // Default to D3D displays + impl = new rx::DisplayD3D(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#elif defined(ANGLE_PLATFORM_APPLE) + impl = new rx::DisplayCGL(); +#elif defined(ANGLE_USE_OZONE) + impl = new rx::DisplayOzone(); +#elif defined(ANGLE_PLATFORM_ANDROID) + impl = new rx::DisplayAndroid(); +#else + // No display available + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + impl = new rx::DisplayD3D(); +#else + // A D3D display was requested on a platform that doesn't support it + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: +#if defined(ANGLE_ENABLE_OPENGL) +#if defined(ANGLE_PLATFORM_WINDOWS) + impl = new rx::DisplayWGL(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#elif defined(ANGLE_PLATFORM_APPLE) + impl = new rx::DisplayCGL(); +#elif defined(ANGLE_USE_OZONE) + // This might work but has never been tried, so disallow for now. + impl = nullptr; +#elif defined(ANGLE_PLATFORM_ANDROID) + // No GL support on this platform, fail display creation. + impl = nullptr; +#else +#error Unsupported OpenGL platform. +#endif +#else + UNREACHABLE(); +#endif + break; + +#if defined(ANGLE_ENABLE_OPENGL) + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: +#if defined(ANGLE_PLATFORM_WINDOWS) + impl = new rx::DisplayWGL(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#elif defined(ANGLE_USE_OZONE) + impl = new rx::DisplayOzone(); +#elif defined(ANGLE_PLATFORM_ANDROID) + impl = new rx::DisplayAndroid(); +#else + // No GLES support on this platform, fail display creation. + impl = nullptr; +#endif + break; +#endif + +#if defined(ANGLE_ENABLE_NULL) + case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE: + impl = new rx::DisplayNULL(); + break; +#endif + + default: + UNREACHABLE(); + break; + } + + return impl; +} + +} + +Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap) +{ + // Initialize the global platform if not already + InitDefaultPlatformImpl(); + + Display *display = nullptr; + + EGLNativeDisplayType displayId = reinterpret_cast<EGLNativeDisplayType>(native_display); + + ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); + ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId); + if (iter != displays->end()) + { + display = iter->second; + } + + if (display == nullptr) + { + // Validate the native display + if (!Display::isValidNativeDisplay(displayId)) + { + return NULL; + } + + display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr); + displays->insert(std::make_pair(displayId, display)); + } + + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap); + if (impl == nullptr) + { + // No valid display implementation for these attributes + return nullptr; + } + + display->setAttributes(impl, attribMap); + } + + return display; +} + +Display *Display::GetDisplayFromDevice(void *native_display) +{ + // Initialize the global platform if not already + InitDefaultPlatformImpl(); + + Display *display = nullptr; + + Device *eglDevice = reinterpret_cast<Device *>(native_display); + ASSERT(Device::IsValidDevice(eglDevice)); + + ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap(); + DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap(); + + // First see if this eglDevice is in use by a Display created using ANGLE platform + for (auto &displayMapEntry : *anglePlatformDisplays) + { + egl::Display *iterDisplay = displayMapEntry.second; + if (iterDisplay->getDevice() == eglDevice) + { + display = iterDisplay; + } + } + + if (display == nullptr) + { + // See if the eglDevice is in use by a Display created using the DEVICE platform + DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice); + if (iter != devicePlatformDisplays->end()) + { + display = iter->second; + } + } + + if (display == nullptr) + { + // Otherwise create a new Display + display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice); + devicePlatformDisplays->insert(std::make_pair(eglDevice, display)); + } + + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice); + display->setAttributes(impl, egl::AttributeMap()); + } + + return display; +} + +Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice) + : mImplementation(nullptr), + mDisplayId(displayId), + mAttributeMap(), + mConfigSet(), + mContextSet(), + mStreamSet(), + mInitialized(false), + mDeviceLost(false), + mCaps(), + mDisplayExtensions(), + mDisplayExtensionString(), + mVendorString(), + mDevice(eglDevice), + mPlatform(platform) +{ +} + +Display::~Display() +{ + terminate(); + + if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE) + { + ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); + ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) + { + displays->erase(iter); + } + } + else if (mPlatform == EGL_PLATFORM_DEVICE_EXT) + { + DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap(); + DevicePlatformDisplayMap::iterator iter = displays->find(mDevice); + if (iter != displays->end()) + { + displays->erase(iter); + } + } + else + { + UNREACHABLE(); + } + + SafeDelete(mDevice); + SafeDelete(mImplementation); +} + +void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap) +{ + ASSERT(!mInitialized); + + ASSERT(impl != nullptr); + SafeDelete(mImplementation); + mImplementation = impl; + + mAttributeMap = attribMap; +} + +Error Display::initialize() +{ + // Re-initialize default platform if it's needed + InitDefaultPlatformImpl(); + + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS"); + TRACE_EVENT0("gpu.angle", "egl::Display::initialize"); + + ASSERT(mImplementation != nullptr); + + if (isInitialized()) + { + return egl::Error(EGL_SUCCESS); + } + + Error error = mImplementation->initialize(this); + if (error.isError()) + { + // Log extended error message here + std::stringstream errorStream; + errorStream << "ANGLE Display::initialize error " << error.getID() << ": " + << error.getMessage(); + ANGLEPlatformCurrent()->logError(errorStream.str().c_str()); + return error; + } + + mCaps = mImplementation->getCaps(); + + mConfigSet = mImplementation->generateConfigs(); + if (mConfigSet.size() == 0) + { + mImplementation->terminate(); + return Error(EGL_NOT_INITIALIZED); + } + + initDisplayExtensions(); + initVendorString(); + + // Populate the Display's EGLDeviceEXT if the Display wasn't created using one + if (mPlatform != EGL_PLATFORM_DEVICE_EXT) + { + if (mDisplayExtensions.deviceQuery) + { + rx::DeviceImpl *impl = nullptr; + ANGLE_TRY(mImplementation->getDevice(&impl)); + ANGLE_TRY(Device::CreateDevice(this, impl, &mDevice)); + } + else + { + mDevice = nullptr; + } + } + else + { + // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using + // an external device + ASSERT(mDevice != nullptr); + } + + mInitialized = true; + + return egl::Error(EGL_SUCCESS); +} + +void Display::terminate() +{ + makeCurrent(nullptr, nullptr, nullptr); + + while (!mContextSet.empty()) + { + destroyContext(*mContextSet.begin()); + } + + while (!mImageSet.empty()) + { + destroyImage(*mImageSet.begin()); + } + + while (!mStreamSet.empty()) + { + destroyStream(*mStreamSet.begin()); + } + + while (!mImplementation->getSurfaceSet().empty()) + { + destroySurface(*mImplementation->getSurfaceSet().begin()); + } + + mConfigSet.clear(); + + if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr) + { + // Don't delete the device if it was created externally using eglCreateDeviceANGLE + // We also shouldn't set it to null in case eglInitialize() is called again later + SafeDelete(mDevice); + } + + mImplementation->terminate(); + + mInitialized = false; + + // Never de-init default platform.. terminate is not that final. +} + +std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const +{ + return mConfigSet.filter(attribs); +} + +bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value) +{ + switch (attribute) + { + case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break; + case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break; + case EGL_BLUE_SIZE: *value = configuration->blueSize; break; + case EGL_GREEN_SIZE: *value = configuration->greenSize; break; + case EGL_RED_SIZE: *value = configuration->redSize; break; + case EGL_DEPTH_SIZE: *value = configuration->depthSize; break; + case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break; + case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break; + case EGL_CONFIG_ID: *value = configuration->configID; break; + case EGL_LEVEL: *value = configuration->level; break; + case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break; + case EGL_NATIVE_VISUAL_ID: *value = configuration->nativeVisualID; break; + case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break; + case EGL_SAMPLES: *value = configuration->samples; break; + case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break; + case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break; + case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break; + case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break; + case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break; + case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break; + case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break; + case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break; + case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break; + case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break; + case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break; + case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break; + case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break; + case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break; + case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: *value = configuration->conformant; break; + case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break; + case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break; + case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break; + + case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE: + if (!getExtensions().surfaceOrientation) + { + return false; + } + *value = configuration->optimalOrientation; + break; + + default: + return false; + } + + return true; +} + +Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs, + Surface **outSurface) +{ + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + std::unique_ptr<Surface> surface( + new WindowSurface(mImplementation, configuration, window, attribs)); + ANGLE_TRY(surface->initialize()); + + ASSERT(outSurface != nullptr); + *outSurface = surface.release(); + mImplementation->getSurfaceSet().insert(*outSurface); + + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end()); + windowSurfaces->insert(std::make_pair(window, *outSurface)); + + return egl::Error(EGL_SUCCESS); +} + +Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + std::unique_ptr<Surface> surface(new PbufferSurface(mImplementation, configuration, attribs)); + ANGLE_TRY(surface->initialize()); + + ASSERT(outSurface != nullptr); + *outSurface = surface.release(); + mImplementation->getSurfaceSet().insert(*outSurface); + + return egl::Error(EGL_SUCCESS); +} + +Error Display::createPbufferFromClientBuffer(const Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const AttributeMap &attribs, + Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + std::unique_ptr<Surface> surface( + new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs)); + ANGLE_TRY(surface->initialize()); + + ASSERT(outSurface != nullptr); + *outSurface = surface.release(); + mImplementation->getSurfaceSet().insert(*outSurface); + + return egl::Error(EGL_SUCCESS); +} + +Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, + Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + std::unique_ptr<Surface> surface( + new PixmapSurface(mImplementation, configuration, nativePixmap, attribs)); + ANGLE_TRY(surface->initialize()); + + ASSERT(outSurface != nullptr); + *outSurface = surface.release(); + mImplementation->getSurfaceSet().insert(*outSurface); + + return egl::Error(EGL_SUCCESS); +} + +Error Display::createImage(gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const AttributeMap &attribs, + Image **outImage) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + egl::ImageSibling *sibling = nullptr; + if (IsTextureTarget(target)) + { + sibling = context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + } + else if (IsRenderbufferTarget(target)) + { + sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + } + else + { + UNREACHABLE(); + } + ASSERT(sibling != nullptr); + + rx::ImageImpl *imageImpl = mImplementation->createImage(target, sibling, attribs); + ASSERT(imageImpl != nullptr); + + ANGLE_TRY(imageImpl->initialize()); + + Image *image = new Image(imageImpl, target, sibling, attribs); + + ASSERT(outImage != nullptr); + *outImage = image; + + // Add this image to the list of all images and hold a ref to it. + image->addRef(); + mImageSet.insert(image); + + return egl::Error(EGL_SUCCESS); +} + +Error Display::createStream(const AttributeMap &attribs, Stream **outStream) +{ + ASSERT(isInitialized()); + + Stream *stream = new Stream(this, attribs); + + ASSERT(stream != nullptr); + mStreamSet.insert(stream); + + ASSERT(outStream != nullptr); + *outStream = stream; + + return Error(EGL_SUCCESS); +} + +Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + ANGLE_TRY(restoreLostDevice()); + } + + gl::Context *context = new gl::Context(mImplementation, configuration, shareContext, attribs); + + ASSERT(context != nullptr); + mContextSet.insert(context); + + ASSERT(outContext != nullptr); + *outContext = context; + return egl::Error(EGL_SUCCESS); +} + +Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context)); + + if (context != nullptr && drawSurface != nullptr) + { + ASSERT(readSurface == drawSurface); + context->makeCurrent(drawSurface); + } + + return egl::Error(EGL_SUCCESS); +} + +Error Display::restoreLostDevice() +{ + for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) + { + if ((*ctx)->isResetNotificationEnabled()) + { + // If reset notifications have been requested, application must delete all contexts first + return Error(EGL_CONTEXT_LOST); + } + } + + return mImplementation->restoreLostDevice(); +} + +void Display::destroySurface(Surface *surface) +{ + if (surface->getType() == EGL_WINDOW_BIT) + { + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + bool surfaceRemoved = false; + for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++) + { + if (iter->second == surface) + { + windowSurfaces->erase(iter); + surfaceRemoved = true; + break; + } + } + + ASSERT(surfaceRemoved); + } + + mImplementation->destroySurface(surface); +} + +void Display::destroyImage(egl::Image *image) +{ + auto iter = mImageSet.find(image); + ASSERT(iter != mImageSet.end()); + (*iter)->release(); + mImageSet.erase(iter); +} + +void Display::destroyStream(egl::Stream *stream) +{ + mStreamSet.erase(stream); + SafeDelete(stream); +} + +void Display::destroyContext(gl::Context *context) +{ + mContextSet.erase(context); + SafeDelete(context); +} + +bool Display::isDeviceLost() const +{ + ASSERT(isInitialized()); + return mDeviceLost; +} + +bool Display::testDeviceLost() +{ + ASSERT(isInitialized()); + + if (!mDeviceLost && mImplementation->testDeviceLost()) + { + notifyDeviceLost(); + } + + return mDeviceLost; +} + +void Display::notifyDeviceLost() +{ + if (mDeviceLost) + { + return; + } + + for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) + { + (*context)->markContextLost(); + } + + mDeviceLost = true; +} + +Error Display::waitClient() const +{ + return mImplementation->waitClient(); +} + +Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const +{ + return mImplementation->waitNative(engine, drawSurface, readSurface); +} + +const Caps &Display::getCaps() const +{ + return mCaps; +} + +bool Display::isInitialized() const +{ + return mInitialized; +} + +bool Display::isValidConfig(const Config *config) const +{ + return mConfigSet.contains(config); +} + +bool Display::isValidContext(const gl::Context *context) const +{ + return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end(); +} + +bool Display::isValidSurface(const Surface *surface) const +{ + return mImplementation->getSurfaceSet().find(const_cast<Surface *>(surface)) != + mImplementation->getSurfaceSet().end(); +} + +bool Display::isValidImage(const Image *image) const +{ + return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end(); +} + +bool Display::isValidStream(const Stream *stream) const +{ + return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end(); +} + +bool Display::hasExistingWindowSurface(EGLNativeWindowType window) +{ + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + return windowSurfaces->find(window) != windowSurfaces->end(); +} + +static ClientExtensions GenerateClientExtensions() +{ + ClientExtensions extensions; + + extensions.clientExtensions = true; + extensions.platformBase = true; + extensions.platformANGLE = true; + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + extensions.platformANGLED3D = true; + extensions.platformDevice = true; +#endif + +#if defined(ANGLE_ENABLE_OPENGL) + extensions.platformANGLEOpenGL = true; +#endif + +#if defined(ANGLE_ENABLE_NULL) + extensions.platformANGLENULL = true; +#endif + +#if defined(ANGLE_ENABLE_D3D11) + extensions.deviceCreation = true; + extensions.deviceCreationD3D11 = true; + extensions.experimentalPresentPath = true; +#endif + +#if defined(ANGLE_USE_X11) + extensions.x11Visual = true; +#endif + + extensions.clientGetAllProcAddresses = true; + + return extensions; +} + +template <typename T> +static std::string GenerateExtensionsString(const T &extensions) +{ + std::vector<std::string> extensionsVector = extensions.getStrings(); + + std::ostringstream stream; + std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " ")); + return stream.str(); +} + +const ClientExtensions &Display::getClientExtensions() +{ + static const ClientExtensions clientExtensions = GenerateClientExtensions(); + return clientExtensions; +} + +const std::string &Display::getClientExtensionString() +{ + static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions()); + return clientExtensionsString; +} + +void Display::initDisplayExtensions() +{ + mDisplayExtensions = mImplementation->getExtensions(); + + // Some extensions are always available because they are implemented in the EGL layer. + mDisplayExtensions.createContext = true; + mDisplayExtensions.createContextNoError = true; + mDisplayExtensions.createContextWebGLCompatibility = true; + mDisplayExtensions.createContextBindGeneratesResource = true; + + // Force EGL_KHR_get_all_proc_addresses on. + mDisplayExtensions.getAllProcAddresses = true; + + mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); +} + +bool Display::isValidNativeWindow(EGLNativeWindowType window) const +{ + return mImplementation->isValidNativeWindow(window); +} + +Error Display::validateClientBuffer(const Config *configuration, + EGLenum buftype, + EGLClientBuffer clientBuffer, + const AttributeMap &attribs) +{ + return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs); +} + +bool Display::isValidDisplay(const egl::Display *display) +{ + const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap(); + for (const auto &displayPair : *anglePlatformDisplayMap) + { + if (displayPair.second == display) + { + return true; + } + } + + const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap(); + for (const auto &displayPair : *devicePlatformDisplayMap) + { + if (displayPair.second == display) + { + return true; + } + } + + return false; +} + +bool Display::isValidNativeDisplay(EGLNativeDisplayType display) +{ + // TODO(jmadill): handle this properly + if (display == EGL_DEFAULT_DISPLAY) + { + return true; + } + +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (display == EGL_SOFTWARE_DISPLAY_ANGLE || + display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + display == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return true; + } + return (WindowFromDC(display) != NULL); +#else + return true; +#endif +} + +void Display::initVendorString() +{ + mVendorString = mImplementation->getVendorString(); +} + +const DisplayExtensions &Display::getExtensions() const +{ + return mDisplayExtensions; +} + +const std::string &Display::getExtensionString() const +{ + return mDisplayExtensionString; +} + +const std::string &Display::getVendorString() const +{ + return mVendorString; +} + +Device *Display::getDevice() const +{ + return mDevice; +} + +gl::Version Display::getMaxSupportedESVersion() const +{ + return mImplementation->getMaxSupportedESVersion(); +} +} |