Edit

kc3-lang/angle/src/libANGLE/Display.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2015-03-13 10:45:27
    Hash : 6bd58312
    Message : Make Platform methods global. This will allow them to be imported dynamically without name mangling. This is necessary because sometimes SwiftShader overrides libGLESv2 and libEGL, so we need to determine at run-time if we are running with "actual" ANGLE. BUG=466735 Change-Id: I396d717b79066feb8ed0d577ee7386b33eb1d160 Reviewed-on: https://chromium-review.googlesource.com/259954 Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/Display.cpp
  • //
    // 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 "libANGLE/Context.h"
    #include "libANGLE/Surface.h"
    #include "libANGLE/renderer/DisplayImpl.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"
    #   else
    #       error Unsupported OpenGL platform.
    #   endif
    #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);
        }
    }
    
    void DeinitDefaultPlatformImpl()
    {
        if (defaultPlatform != nullptr)
        {
            if (ANGLEPlatformCurrent() == defaultPlatform)
            {
                ANGLEPlatformShutdown();
            }
    
            SafeDelete(defaultPlatform);
        }
    }
    
    typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
    static DisplayMap *GetDisplayMap()
    {
        static DisplayMap displays;
        return &displays;
    }
    
    rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
    {
        rx::DisplayImpl *impl = nullptr;
        EGLint 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();
    #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();
    #else
    #error Unsupported OpenGL platform.
    #endif
    #else
            UNREACHABLE();
    #endif
            break;
    
          default:
            UNREACHABLE();
            break;
        }
    
        ASSERT(impl != nullptr);
        return impl;
    }
    
    }
    
    Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
    {
        // Initialize the global platform if not already
        InitDefaultPlatformImpl();
    
        Display *display = NULL;
    
        DisplayMap *displays = GetDisplayMap();
        DisplayMap::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(displayId);
            displays->insert(std::make_pair(displayId, display));
        }
    
        // Apply new attributes if the display is not initialized yet.
        if (!display->isInitialized())
        {
            rx::DisplayImpl* impl = CreateDisplayImpl(attribMap);
            display->setAttributes(impl, attribMap);
        }
    
        return display;
    }
    
    Display::Display(EGLNativeDisplayType displayId)
        : mImplementation(nullptr),
          mDisplayId(displayId),
          mAttributeMap(),
          mConfigSet(),
          mContextSet(),
          mInitialized(false),
          mCaps(),
          mDisplayExtensions(),
          mDisplayExtensionString(),
          mVendorString()
    {
    }
    
    Display::~Display()
    {
        terminate();
    
        DisplayMap *displays = GetDisplayMap();
        DisplayMap::iterator iter = displays->find(mDisplayId);
        if (iter != displays->end())
        {
            displays->erase(iter);
        }
    
        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()
    {
        ASSERT(mImplementation != nullptr);
    
        if (isInitialized())
        {
            return Error(EGL_SUCCESS);
        }
    
        Error error = mImplementation->initialize(this);
        if (error.isError())
        {
            return error;
        }
    
        mCaps = mImplementation->getCaps();
    
        mConfigSet = mImplementation->generateConfigs();
        if (mConfigSet.size() == 0)
        {
            mImplementation->terminate();
            return Error(EGL_NOT_INITIALIZED);
        }
    
        initDisplayExtensions();
        initVendorString();
    
        mInitialized = true;
        return Error(EGL_SUCCESS);
    }
    
    void Display::terminate()
    {
        makeCurrent(nullptr, nullptr, nullptr);
    
        while (!mContextSet.empty())
        {
            destroyContext(*mContextSet.begin());
        }
    
        mConfigSet.clear();
    
        mImplementation->terminate();
        mInitialized = false;
    
        // De-init default platform
        DeinitDefaultPlatformImpl();
    }
    
    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_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;
          default:
            return false;
        }
    
        return true;
    }
    
    Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
                                       Surface **outSurface)
    {
        if (mImplementation->testDeviceLost())
        {
            Error error = restoreLostDevice();
            if (error.isError())
            {
                return error;
            }
        }
    
        rx::SurfaceImpl *surfaceImpl = nullptr;
        Error error = mImplementation->createWindowSurface(configuration, window, attribs, &surfaceImpl);
        if (error.isError())
        {
            return error;
        }
    
        ASSERT(surfaceImpl != nullptr);
        Surface *surface = new Surface(surfaceImpl);
        mImplementation->getSurfaceSet().insert(surface);
    
        ASSERT(outSurface != nullptr);
        *outSurface = surface;
        return Error(EGL_SUCCESS);
    }
    
    Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
    {
        ASSERT(isInitialized());
    
        if (mImplementation->testDeviceLost())
        {
            Error error = restoreLostDevice();
            if (error.isError())
            {
                return error;
            }
        }
    
        rx::SurfaceImpl *surfaceImpl = nullptr;
        Error error = mImplementation->createPbufferSurface(configuration, attribs, &surfaceImpl);
        if (error.isError())
        {
            return error;
        }
    
        ASSERT(surfaceImpl != nullptr);
        Surface *surface = new Surface(surfaceImpl);
        mImplementation->getSurfaceSet().insert(surface);
    
        ASSERT(outSurface != nullptr);
        *outSurface = surface;
        return Error(EGL_SUCCESS);
    }
    
    Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle,
                                                 const AttributeMap &attribs, Surface **outSurface)
    {
        ASSERT(isInitialized());
    
        if (mImplementation->testDeviceLost())
        {
            Error error = restoreLostDevice();
            if (error.isError())
            {
                return error;
            }
        }
    
        rx::SurfaceImpl *surfaceImpl = nullptr;
        Error error = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs, &surfaceImpl);
        if (error.isError())
        {
            return error;
        }
    
        ASSERT(surfaceImpl != nullptr);
        Surface *surface = new Surface(surfaceImpl);
        mImplementation->getSurfaceSet().insert(surface);
    
        ASSERT(outSurface != nullptr);
        *outSurface = surface;
        return Error(EGL_SUCCESS);
    }
    
    Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
                                 gl::Context **outContext)
    {
        ASSERT(isInitialized());
    
        if (mImplementation->testDeviceLost())
        {
            Error error = restoreLostDevice();
            if (error.isError())
            {
                return error;
            }
        }
    
        gl::Context *context = nullptr;
        Error error = mImplementation->createContext(configuration, shareContext, attribs, &context);
        if (error.isError())
        {
            return error;
        }
    
        ASSERT(context != nullptr);
        mContextSet.insert(context);
    
        ASSERT(outContext != nullptr);
        *outContext = context;
        return Error(EGL_SUCCESS);
    }
    
    Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
    {
        Error error = mImplementation->makeCurrent(drawSurface, readSurface, context);
        if (error.isError())
        {
            return error;
        }
    
        if (context && 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)
    {
        mImplementation->destroySurface(surface);
    }
    
    void Display::destroyContext(gl::Context *context)
    {
        mContextSet.erase(context);
        SafeDelete(context);
    }
    
    bool Display::isDeviceLost() const
    {
        ASSERT(isInitialized());
        return mImplementation->isDeviceLost();
    }
    
    bool Display::testDeviceLost()
    {
        ASSERT(isInitialized());
        return mImplementation->testDeviceLost();
    }
    
    void Display::notifyDeviceLost()
    {
        for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
        {
            (*context)->markContextLost();
        }
    }
    
    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(gl::Context *context) const
    {
        return mContextSet.find(context) != mContextSet.end();
    }
    
    bool Display::isValidSurface(Surface *surface) const
    {
        return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end();
    }
    
    bool Display::hasExistingWindowSurface(EGLNativeWindowType window) const
    {
        for (const auto &surfaceIt : mImplementation->getSurfaceSet())
        {
            if (surfaceIt->getWindowHandle() == window)
            {
                return true;
            }
        }
    
        return false;
    }
    
    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;
    #endif
    
    #if defined(ANGLE_ENABLE_OPENGL)
        extensions.platformANGLEOpenGL = true;
    #endif
    
        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();
        mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
    }
    
    bool Display::isValidNativeWindow(EGLNativeWindowType window) const
    {
        return mImplementation->isValidNativeWindow(window);
    }
    
    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;
    }
    
    }