Edit

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

Branch :

  • Show log

    Commit

  • Author : Ian Elliott
    Date : 2019-02-01 15:43:59
    Hash : 3d6e3004
    Message : Implement EGL_ANDROID_recordable for Vulkan back-end. This initial implementation provides the extension, and always answers that the ANativeWindow is not recordable. BUG=angleproject:2511 Change-Id: Id3c57351dd1029bff7adf7166f9c82eee6e634b3 Reviewed-on: https://chromium-review.googlesource.com/c/1412507 Commit-Queue: Ian Elliott <ianelliott@google.com> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/libANGLE/Config.cpp
  • //
    // Copyright (c) 2002-2010 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.
    //
    
    // Config.cpp: Implements the egl::Config class, describing the format, type
    // and size for an egl::Surface. Implements EGLConfig and related functionality.
    // [EGL 1.5] section 3.4 page 19.
    
    #include "libANGLE/Config.h"
    #include "libANGLE/AttributeMap.h"
    
    #include <algorithm>
    #include <vector>
    
    #include <EGL/eglext.h>
    #include "angle_gl.h"
    
    #include "common/debug.h"
    
    namespace egl
    {
    
    Config::Config()
        : renderTargetFormat(GL_NONE),
          depthStencilFormat(GL_NONE),
          bufferSize(0),
          redSize(0),
          greenSize(0),
          blueSize(0),
          luminanceSize(0),
          alphaSize(0),
          alphaMaskSize(0),
          bindToTextureRGB(EGL_FALSE),
          bindToTextureRGBA(EGL_FALSE),
          colorBufferType(EGL_NONE),
          configCaveat(EGL_NONE),
          configID(0),
          conformant(0),
          depthSize(0),
          level(0),
          matchNativePixmap(EGL_FALSE),
          maxPBufferWidth(0),
          maxPBufferHeight(0),
          maxPBufferPixels(0),
          maxSwapInterval(0),
          minSwapInterval(0),
          nativeRenderable(EGL_FALSE),
          nativeVisualID(0),
          nativeVisualType(0),
          renderableType(0),
          sampleBuffers(0),
          samples(0),
          stencilSize(0),
          surfaceType(0),
          transparentType(EGL_NONE),
          transparentRedValue(0),
          transparentGreenValue(0),
          transparentBlueValue(0),
          optimalOrientation(0),
          colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
          recordable(EGL_FALSE)
    {}
    
    Config::~Config() {}
    
    Config::Config(const Config &other) = default;
    
    Config &Config::operator=(const Config &other) = default;
    
    ConfigSet::ConfigSet() = default;
    
    ConfigSet::ConfigSet(const ConfigSet &other) = default;
    
    ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
    
    ConfigSet::~ConfigSet() = default;
    
    EGLint ConfigSet::add(const Config &config)
    {
        // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
        EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
    
        Config copyConfig(config);
        copyConfig.configID = id;
        mConfigs.insert(std::make_pair(id, copyConfig));
    
        return id;
    }
    
    const Config &ConfigSet::get(EGLint id) const
    {
        ASSERT(mConfigs.find(id) != mConfigs.end());
        return mConfigs.find(id)->second;
    }
    
    void ConfigSet::clear()
    {
        mConfigs.clear();
    }
    
    size_t ConfigSet::size() const
    {
        return mConfigs.size();
    }
    
    bool ConfigSet::contains(const Config *config) const
    {
        for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
        {
            const Config &item = i->second;
            if (config == &item)
            {
                return true;
            }
        }
    
        return false;
    }
    
    // Function object used by STL sorting routines for ordering Configs according to [EGL 1.5]
    // section 3.4.1.2 page 28.
    class ConfigSorter
    {
      public:
        explicit ConfigSorter(const AttributeMap &attributeMap)
            : mWantRed(false),
              mWantGreen(false),
              mWantBlue(false),
              mWantAlpha(false),
              mWantLuminance(false)
        {
            scanForWantedComponents(attributeMap);
        }
    
        bool operator()(const Config *x, const Config *y) const { return (*this)(*x, *y); }
    
        bool operator()(const Config &x, const Config &y) const
        {
    #define SORT(attribute)                       \
        do                                        \
        {                                         \
            if (x.attribute != y.attribute)       \
                return x.attribute < y.attribute; \
        } while (0)
    
            static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG,
                          "Unexpected EGL enum value.");
            SORT(configCaveat);
    
            static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
                          "Unexpected order of EGL enums.");
            SORT(colorComponentType);
    
            static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
            SORT(colorBufferType);
    
            // By larger total number of color bits, only considering those that are requested to be >
            // 0.
            EGLint xComponentsSize = wantedComponentsSize(x);
            EGLint yComponentsSize = wantedComponentsSize(y);
            if (xComponentsSize != yComponentsSize)
            {
                return xComponentsSize > yComponentsSize;
            }
    
            SORT(bufferSize);
            SORT(sampleBuffers);
            SORT(samples);
            SORT(depthSize);
            SORT(stencilSize);
            SORT(alphaMaskSize);
            SORT(nativeVisualType);
            SORT(configID);
    
    #undef SORT
    
            return false;
        }
    
      private:
        static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
        {
            // [EGL 1.5] section 3.4.1.2 page 30
            // Sorting rule #3: by larger total number of color bits, not considering
            // components that are 0 or don't-care.
            EGLAttrib value = attributeMap.get(component, 0);
            return value != 0 && value != EGL_DONT_CARE;
        }
    
        void scanForWantedComponents(const AttributeMap &attributeMap)
        {
            mWantRed       = wantsComponent(attributeMap, EGL_RED_SIZE);
            mWantGreen     = wantsComponent(attributeMap, EGL_GREEN_SIZE);
            mWantBlue      = wantsComponent(attributeMap, EGL_BLUE_SIZE);
            mWantAlpha     = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
            mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
        }
    
        EGLint wantedComponentsSize(const Config &config) const
        {
            EGLint total = 0;
    
            if (mWantRed)
                total += config.redSize;
            if (mWantGreen)
                total += config.greenSize;
            if (mWantBlue)
                total += config.blueSize;
            if (mWantAlpha)
                total += config.alphaSize;
            if (mWantLuminance)
                total += config.luminanceSize;
    
            return total;
        }
    
        bool mWantRed;
        bool mWantGreen;
        bool mWantBlue;
        bool mWantAlpha;
        bool mWantLuminance;
    };
    
    std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) const
    {
        std::vector<const Config *> result;
        result.reserve(mConfigs.size());
    
        for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
        {
            const Config &config = configIter->second;
            bool match           = true;
    
            for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
            {
                EGLAttrib attributeKey   = attribIter->first;
                EGLAttrib attributeValue = attribIter->second;
    
                if (attributeValue == EGL_DONT_CARE)
                {
                    continue;
                }
    
                switch (attributeKey)
                {
                    case EGL_BUFFER_SIZE:
                        match = config.bufferSize >= attributeValue;
                        break;
                    case EGL_ALPHA_SIZE:
                        match = config.alphaSize >= attributeValue;
                        break;
                    case EGL_BLUE_SIZE:
                        match = config.blueSize >= attributeValue;
                        break;
                    case EGL_GREEN_SIZE:
                        match = config.greenSize >= attributeValue;
                        break;
                    case EGL_RED_SIZE:
                        match = config.redSize >= attributeValue;
                        break;
                    case EGL_DEPTH_SIZE:
                        match = config.depthSize >= attributeValue;
                        break;
                    case EGL_STENCIL_SIZE:
                        match = config.stencilSize >= attributeValue;
                        break;
                    case EGL_CONFIG_CAVEAT:
                        match = config.configCaveat == static_cast<EGLenum>(attributeValue);
                        break;
                    case EGL_CONFIG_ID:
                        match = config.configID == attributeValue;
                        break;
                    case EGL_LEVEL:
                        match = config.level >= attributeValue;
                        break;
                    case EGL_NATIVE_RENDERABLE:
                        match = config.nativeRenderable == static_cast<EGLBoolean>(attributeValue);
                        break;
                    case EGL_NATIVE_VISUAL_TYPE:
                        match = config.nativeVisualType == attributeValue;
                        break;
                    case EGL_SAMPLES:
                        match = config.samples >= attributeValue;
                        break;
                    case EGL_SAMPLE_BUFFERS:
                        match = config.sampleBuffers >= attributeValue;
                        break;
                    case EGL_SURFACE_TYPE:
                        match = (config.surfaceType & attributeValue) == attributeValue;
                        break;
                    case EGL_TRANSPARENT_TYPE:
                        match = config.transparentType == static_cast<EGLenum>(attributeValue);
                        break;
                    case EGL_TRANSPARENT_BLUE_VALUE:
                        match = config.transparentBlueValue == attributeValue;
                        break;
                    case EGL_TRANSPARENT_GREEN_VALUE:
                        match = config.transparentGreenValue == attributeValue;
                        break;
                    case EGL_TRANSPARENT_RED_VALUE:
                        match = config.transparentRedValue == attributeValue;
                        break;
                    case EGL_BIND_TO_TEXTURE_RGB:
                        match = config.bindToTextureRGB == static_cast<EGLBoolean>(attributeValue);
                        break;
                    case EGL_BIND_TO_TEXTURE_RGBA:
                        match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue);
                        break;
                    case EGL_MIN_SWAP_INTERVAL:
                        match = config.minSwapInterval == attributeValue;
                        break;
                    case EGL_MAX_SWAP_INTERVAL:
                        match = config.maxSwapInterval == attributeValue;
                        break;
                    case EGL_LUMINANCE_SIZE:
                        match = config.luminanceSize >= attributeValue;
                        break;
                    case EGL_ALPHA_MASK_SIZE:
                        match = config.alphaMaskSize >= attributeValue;
                        break;
                    case EGL_COLOR_BUFFER_TYPE:
                        match = config.colorBufferType == static_cast<EGLenum>(attributeValue);
                        break;
                    case EGL_RENDERABLE_TYPE:
                        match = (config.renderableType & attributeValue) == attributeValue;
                        break;
                    case EGL_MATCH_NATIVE_PIXMAP:
                        match = false;
                        UNIMPLEMENTED();
                        break;
                    case EGL_CONFORMANT:
                        match = (config.conformant & attributeValue) == attributeValue;
                        break;
                    case EGL_MAX_PBUFFER_WIDTH:
                        match = config.maxPBufferWidth >= attributeValue;
                        break;
                    case EGL_MAX_PBUFFER_HEIGHT:
                        match = config.maxPBufferHeight >= attributeValue;
                        break;
                    case EGL_MAX_PBUFFER_PIXELS:
                        match = config.maxPBufferPixels >= attributeValue;
                        break;
                    case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
                        match = config.optimalOrientation == attributeValue;
                        break;
                    case EGL_COLOR_COMPONENT_TYPE_EXT:
                        match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
                        break;
                    case EGL_RECORDABLE_ANDROID:
                        match = config.recordable == static_cast<EGLBoolean>(attributeValue);
                        break;
                    default:
                        UNREACHABLE();
                }
    
                if (!match)
                {
                    break;
                }
            }
    
            if (match)
            {
                result.push_back(&config);
            }
        }
    
        // Sort the result
        std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
    
        return result;
    }
    
    ConfigSet::ConfigMap::iterator ConfigSet::begin()
    {
        return mConfigs.begin();
    }
    
    ConfigSet::ConfigMap::iterator ConfigSet::end()
    {
        return mConfigs.end();
    }
    }  // namespace egl