diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Config.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Config.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Config.cpp b/gfx/angle/checkout/src/libANGLE/Config.cpp new file mode 100644 index 0000000000..127480db1f --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Config.cpp @@ -0,0 +1,416 @@ +// +// Copyright 2002 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), + bindToTextureTarget(EGL_TEXTURE_2D), + colorBufferType(EGL_RGB_BUFFER), + 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), + framebufferTarget(EGL_FALSE), // TODO: http://anglebug.com/4208 + yInverted(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: + if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) + { + match = config.transparentBlueValue == attributeValue; + } + break; + case EGL_TRANSPARENT_GREEN_VALUE: + if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) + { + match = config.transparentGreenValue == attributeValue; + } + break; + case EGL_TRANSPARENT_RED_VALUE: + if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) + { + 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_BIND_TO_TEXTURE_TARGET_ANGLE: + match = config.bindToTextureTarget == static_cast<EGLenum>(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; + case EGL_FRAMEBUFFER_TARGET_ANDROID: + match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue); + break; + case EGL_Y_INVERTED_NOK: + match = config.yInverted == static_cast<EGLBoolean>(attributeValue); + break; + case EGL_MATCH_FORMAT_KHR: + if (attributeValue == EGL_NONE) + { + match = (config.surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == 0; + } + else + { + match = config.matchFormat == 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 |