| /* |
| * Copyright 2015 Google Inc. All Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "glimp/egl/config.h" |
| |
| #include <algorithm> |
| |
| #include "starboard/log.h" |
| |
| namespace glimp { |
| namespace egl { |
| |
| namespace { |
| bool AttributeKeyAndValueAreValid(int key, int value) { |
| switch (key) { |
| // Deal with the size keys where all values are valid. |
| case EGL_RED_SIZE: |
| case EGL_GREEN_SIZE: |
| case EGL_BLUE_SIZE: |
| case EGL_ALPHA_SIZE: |
| case EGL_BUFFER_SIZE: |
| case EGL_LUMINANCE_SIZE: |
| case EGL_STENCIL_SIZE: { |
| return true; |
| } |
| |
| // Deal with the mask keys where all values are valid. |
| case EGL_CONFORMANT: |
| case EGL_RENDERABLE_TYPE: |
| case EGL_SURFACE_TYPE: { |
| return true; |
| } |
| |
| // Deal with boolean values. |
| case EGL_BIND_TO_TEXTURE_RGBA: { |
| switch (value) { |
| case EGL_DONT_CARE: |
| case EGL_TRUE: |
| case EGL_FALSE: { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| case EGL_COLOR_BUFFER_TYPE: { |
| switch (value) { |
| case EGL_RGB_BUFFER: |
| case EGL_LUMINANCE_BUFFER: { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |
| |
| // If the switch statement didn't catch the key, this is an unknown |
| // key values. |
| // TODO: glimp doesn't support all values yet, and will return false for keys |
| // that it doesn't support. |
| return false; |
| } |
| } // namespace |
| |
| bool ValidateConfigAttribList(const AttribMap& attribs) { |
| for (AttribMap::const_iterator iter = attribs.begin(); iter != attribs.end(); |
| ++iter) { |
| if (!AttributeKeyAndValueAreValid(iter->first, iter->second)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| namespace { |
| // Returns whether or not a single attribute (the parameters |key| and |value|) |
| // matches a config or not. |
| bool ConfigMatchesAttribute(const Config& config, int key, int value) { |
| SB_DCHECK(AttributeKeyAndValueAreValid(key, value)); |
| SB_DCHECK(value != EGL_DONT_CARE); |
| |
| switch (key) { |
| case EGL_RED_SIZE: |
| case EGL_GREEN_SIZE: |
| case EGL_BLUE_SIZE: |
| case EGL_ALPHA_SIZE: |
| case EGL_BUFFER_SIZE: |
| case EGL_LUMINANCE_SIZE: |
| case EGL_STENCIL_SIZE: { |
| // We match if our config's bit depth is greater than or equal to the |
| // requested value. |
| return config.find(key)->second >= value; |
| } |
| |
| case EGL_CONFORMANT: |
| case EGL_RENDERABLE_TYPE: |
| case EGL_SURFACE_TYPE: { |
| // We match if our config's bit mask includes the requested bit mask. |
| return (config.find(key)->second & value) == value; |
| } |
| |
| case EGL_BIND_TO_TEXTURE_RGBA: { |
| // Our config matches booleans if the requested boolean is not true, or |
| // else if the config's corresponding boolean is also true. |
| return value != EGL_TRUE || config.find(key)->second == EGL_TRUE; |
| } |
| |
| case EGL_COLOR_BUFFER_TYPE: { |
| // We match if our config value matches the requested value exactly. |
| return config.find(key)->second == value; |
| } |
| } |
| |
| // The attributes should have been validated when this function is called, |
| // so if we reach this point, then there is an inconsistency between |
| // this function and AttributeKeyAndValueAreValid(). |
| SB_NOTREACHED(); |
| return false; |
| } |
| |
| bool ConfigMatchesAttributes(const Config& config, |
| const AttribMap& attrib_list) { |
| for (AttribMap::const_iterator iter = attrib_list.begin(); |
| iter != attrib_list.end(); ++iter) { |
| if (iter->second != EGL_DONT_CARE) { |
| if (!ConfigMatchesAttribute(config, iter->first, iter->second)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| } // namespace |
| |
| std::vector<Config*> FilterConfigs(const std::set<Config*>& configs, |
| const AttribMap& attrib_list) { |
| std::vector<Config*> ret; |
| |
| for (std::set<Config*>::const_iterator iter = configs.begin(); |
| iter != configs.end(); ++iter) { |
| if (ConfigMatchesAttributes(**iter, attrib_list)) { |
| ret.push_back(*iter); |
| } |
| } |
| |
| return ret; |
| } |
| |
| namespace { |
| |
| class ConfigSorter { |
| public: |
| explicit ConfigSorter(const AttribMap& attrib_list) |
| : attrib_list_(attrib_list) {} |
| |
| // We define this such that it sorts in decreasing order of preference. |
| bool operator()(const Config* lhs, const Config* rhs) const { |
| // Bit depth must be sorted in ascending order as a total over all |
| // channels that are specified by the config. |
| if (GetTotalBitDepth(*lhs) > GetTotalBitDepth(*rhs)) { |
| return true; |
| } |
| return false; |
| } |
| |
| private: |
| // Returns the bit depth for a given channel, or 0 if we don't care about |
| // it's value (e.g. it is not in the specified attribute list). |
| int GetTotalBitDepthForChannel(const Config& config, int key) const { |
| AttribMap::const_iterator found = attrib_list_.find(key); |
| if (found == attrib_list_.end() || found->second == EGL_DONT_CARE) { |
| return 0; |
| } else { |
| return found->second; |
| } |
| } |
| |
| // Gets the total depth for all color channels, to be used to decide the |
| // sort order. |
| int GetTotalBitDepth(const Config& config) const { |
| int total_bit_depth = 0; |
| total_bit_depth += GetTotalBitDepthForChannel(config, EGL_RED_SIZE); |
| total_bit_depth += GetTotalBitDepthForChannel(config, EGL_GREEN_SIZE); |
| total_bit_depth += GetTotalBitDepthForChannel(config, EGL_BLUE_SIZE); |
| total_bit_depth += GetTotalBitDepthForChannel(config, EGL_ALPHA_SIZE); |
| return total_bit_depth; |
| } |
| |
| const AttribMap& attrib_list_; |
| }; |
| } // namespace |
| |
| void SortConfigs(const AttribMap& attrib_list, |
| std::vector<Config*>* in_out_configs) { |
| ConfigSorter config_sorter(attrib_list); |
| std::sort(in_out_configs->begin(), in_out_configs->end(), config_sorter); |
| } |
| |
| EGLConfig ToEGLConfig(Config* config) { |
| return reinterpret_cast<EGLConfig>(config); |
| } |
| |
| } // namespace egl |
| } // namespace glimp |