| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "impeller/renderer/backend/gles/description_gles.h" |
| |
| #include <algorithm> |
| #include <cctype> |
| #include <iomanip> |
| #include <sstream> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "impeller/base/strings.h" |
| #include "impeller/base/validation.h" |
| #include "impeller/renderer/backend/gles/proc_table_gles.h" |
| |
| namespace impeller { |
| |
| static std::string GetGLString(const ProcTableGLES& gl, GLenum name) { |
| auto str = gl.GetString(name); |
| if (str == nullptr) { |
| return ""; |
| } |
| return reinterpret_cast<const char*>(str); |
| } |
| |
| static bool DetermineIfES(const std::string& version) { |
| return HasPrefix(version, "OpenGL ES"); |
| } |
| |
| static std::optional<Version> DetermineVersion(std::string version) { |
| // Format for OpenGL "OpenGL<space>ES<space><version |
| // number><space><vendor-specific information>". |
| // |
| // Format for OpenGL SL "OpenGL<space>ES<space>GLSL<space>ES<space><version |
| // number><space><vendor-specific information>" |
| // |
| // The prefixes appear to be absent on Desktop GL. |
| |
| version = StripPrefix(version, "OpenGL ES "); |
| version = StripPrefix(version, "GLSL ES "); |
| |
| if (version.empty()) { |
| return std::nullopt; |
| } |
| |
| std::stringstream stream; |
| for (size_t i = 0; i < version.size(); i++) { |
| const auto character = version[i]; |
| if (std::isdigit(character) || character == '.') { |
| stream << character; |
| } else { |
| break; |
| } |
| } |
| std::istringstream istream; |
| istream.str(stream.str()); |
| std::vector<size_t> version_components; |
| for (std::string version_component; |
| std::getline(istream, version_component, '.');) { |
| version_components.push_back(std::stoul(version_component)); |
| } |
| return Version::FromVector(version_components); |
| } |
| |
| DescriptionGLES::DescriptionGLES(const ProcTableGLES& gl) |
| : vendor_(GetGLString(gl, GL_VENDOR)), |
| renderer_(GetGLString(gl, GL_RENDERER)), |
| gl_version_string_(GetGLString(gl, GL_VERSION)), |
| sl_version_string_(GetGLString(gl, GL_SHADING_LANGUAGE_VERSION)) { |
| const auto extensions = GetGLString(gl, GL_EXTENSIONS); |
| std::stringstream extensions_stream(extensions); |
| std::string extension; |
| while (std::getline(extensions_stream, extension, ' ')) { |
| extensions_.insert(extension); |
| } |
| |
| is_es_ = DetermineIfES(gl_version_string_); |
| |
| auto gl_version = DetermineVersion(gl_version_string_); |
| if (!gl_version.has_value()) { |
| VALIDATION_LOG << "Could not determine GL version."; |
| return; |
| } |
| gl_version_ = gl_version.value(); |
| |
| auto sl_version = DetermineVersion(sl_version_string_); |
| if (!sl_version.has_value()) { |
| VALIDATION_LOG << "Could not determine SL version."; |
| return; |
| } |
| sl_version_ = sl_version.value(); |
| |
| is_valid_ = true; |
| } |
| |
| DescriptionGLES::~DescriptionGLES() = default; |
| |
| bool DescriptionGLES::IsValid() const { |
| return is_valid_; |
| } |
| |
| std::string DescriptionGLES::GetString() const { |
| if (!IsValid()) { |
| return "Unknown Renderer."; |
| } |
| |
| std::vector<std::pair<std::string, std::string>> items; |
| |
| items.emplace_back(std::make_pair("Vendor", vendor_)); |
| items.emplace_back(std::make_pair("Renderer", renderer_)); |
| items.emplace_back(std::make_pair("GL Version", gl_version_string_)); |
| items.emplace_back( |
| std::make_pair("Shading Language Version", sl_version_string_)); |
| items.emplace_back( |
| std::make_pair("Extensions", std::to_string(extensions_.size()))); |
| |
| size_t max_width = 0u; |
| for (const auto& item : items) { |
| max_width = std::max(max_width, item.first.size()); |
| } |
| |
| std::stringstream stream; |
| stream << "OpenGL Renderer:" << std::endl; |
| for (const auto& item : items) { |
| stream << std::setw(max_width + 1) << item.first << ": " << item.second |
| << std::endl; |
| } |
| |
| const auto pad = std::string(max_width + 3, ' '); |
| for (const auto& extension : extensions_) { |
| stream << pad << extension << std::endl; |
| } |
| |
| return stream.str(); |
| } |
| |
| bool DescriptionGLES::IsES() const { |
| return is_es_; |
| } |
| |
| bool DescriptionGLES::HasExtension(const std::string& ext) const { |
| return extensions_.find(ext) != extensions_.end(); |
| } |
| |
| bool DescriptionGLES::HasDebugExtension() const { |
| return HasExtension("GL_KHR_debug"); |
| } |
| |
| } // namespace impeller |