Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2015-02-17 16:03:16
    Hash : 5feea562
    Message : Add ANGLE platform implementation template. The platform implementation allows the app layer to pass in an object, on which ANGLE can call virtual methods. Our current platform will handle trace events, for app profiling, and histogram records for statistics. The platform approach gives a much more robust approach than using entry points for every piece of functionality, and is based on the interop with Blink. The default platform implementation does a no-op on every call. The destructor is also private, to ensure we do not call the destructor of the passed-in class. BUG=436191 Change-Id: I05641b89a48a9cff81ced059518fceb5aa6c883b Reviewed-on: https://chromium-review.googlesource.com/248631 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Zhenyao Mo <zmo@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 (angle::Platform::current() == nullptr)
        {
            if (defaultPlatform == nullptr)
            {
                defaultPlatform = new DefaultPlatform();
            }
    
            angle::Platform::initialize(defaultPlatform);
        }
    }
    
    void DeinitDefaultPlatformImpl()
    {
        if (defaultPlatform != nullptr)
        {
            if (angle::Platform::current() == defaultPlatform)
            {
                angle::Platform::shutdown();
            }
    
            SafeDelete(defaultPlatform);
        }
    }
    
    typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
    static DisplayMap *GetDisplayMap()
    {
        static DisplayMap displays;
        return &displays;
    }
    
    }
    
    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;
        }
        else
        {
            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);
    
            display = new Display(impl, displayId);
    
            // Validate the native display
            if (!display->isValidNativeDisplay(displayId))
            {
                // Still returns success
                SafeDelete(display);
                return NULL;
            }
    
            displays->insert(std::make_pair(displayId, display));
        }
    
        // Apply new attributes if the display is not initialized yet.
        if (!display->isInitialized())
        {
            display->setAttributes(attribMap);
        }
    
        return display;
    }
    
    Display::Display(rx::DisplayImpl *impl, EGLNativeDisplayType displayId)
        : mImplementation(impl),
          mDisplayId(displayId),
          mAttributeMap(),
          mInitialized(false)
    {
        ASSERT(mImplementation != nullptr);
    }
    
    Display::~Display()
    {
        terminate();
    
        DisplayMap *displays = GetDisplayMap();
        DisplayMap::iterator iter = displays->find(mDisplayId);
        if (iter != displays->end())
        {
            displays->erase(iter);
        }
    
        SafeDelete(mImplementation);
    }
    
    void Display::setAttributes(const AttributeMap &attribMap)
    {
        mAttributeMap = attribMap;
    }
    
    Error Display::initialize()
    {
        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) const
    {
        // 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;
    }
    
    }