From a413ef0bb0d1663b8a33707f2a51e52ca68f33c4 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Wed, 10 Aug 2016 11:26:26 -0700 Subject: [PATCH] If GrGLContext setup fails, log OpenGL platform specific information. (#2897) --- flow/BUILD.gn | 2 + flow/gl_connection.cc | 183 ++++++++++++++++++++++++++ flow/gl_connection.h | 72 ++++++++++ sky/shell/gpu/direct/ganesh_canvas.cc | 17 +++ 4 files changed, 274 insertions(+) create mode 100644 flow/gl_connection.cc create mode 100644 flow/gl_connection.h diff --git a/flow/BUILD.gn b/flow/BUILD.gn index 206040fd8..f993e6e0b 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -6,6 +6,8 @@ source_set("flow") { sources = [ "compositor_context.cc", "compositor_context.h", + "gl_connection.cc", + "gl_connection.h", "instrumentation.cc", "instrumentation.h", "layers/backdrop_filter_layer.cc", diff --git a/flow/gl_connection.cc b/flow/gl_connection.cc new file mode 100644 index 000000000..c26be4b0e --- /dev/null +++ b/flow/gl_connection.cc @@ -0,0 +1,183 @@ +// Copyright 2016 The Chromium 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 "gl_connection.h" + +#include +#include +#include +#include + +namespace flow { + +static std::string GLGetString(GLenum name) { + auto string = reinterpret_cast(glGetString(name)); + return string != nullptr ? string : ""; +} + +static GLConnection::Version GLGetVersion(GLenum name) { + GLConnection::Version version; + + auto versionString = GLGetString(name); + + if (versionString.length() == 0) { + return version; + } + + { + // Check for the GLSL ES prefix. + const std::string glslesPrefix("OpenGL ES GLSL ES "); + if (versionString.compare(0, glslesPrefix.length(), glslesPrefix) == 0) { + version.isES = true; + versionString = versionString.substr(glslesPrefix.length()); + } + } + + { + // Check for the GL ES prefix. + const std::string glesPrefix("OpenGL ES "); + if (versionString.compare(0, glesPrefix.length(), glesPrefix) == 0) { + version.isES = true; + versionString = versionString.substr(glesPrefix.length()); + } + } + + std::istringstream stream(versionString); + + for (size_t i = 0; i < 3; i++) { + size_t item = 0; + if (stream >> item) { + version.items[i] = item; + + if (stream.peek() == ' ') { + stream.ignore(1); // space + stream >> version.vendorString; + break; + } else { + stream.ignore(1); // dot + } + } else { + break; + } + } + + return version; +} + +static std::string VersionToString(GLConnection::Version version) { + if (version.major == 0 && version.minor == 0 && version.release == 0) { + return "Unknown"; + } + + std::stringstream stream; + + stream << version.major << "." << version.minor; + + if (version.release != 0) { + stream << "." << version.release; + } + + if (version.vendorString.size() != 0) { + stream << " " << version.vendorString; + } + + if (version.isES) { + stream << " ES"; + } + + return stream.str(); +} + +GLConnection::GLConnection() + : vendor_(GLGetString(GL_VENDOR)), + renderer_(GLGetString(GL_RENDERER)), + version_(GLGetVersion(GL_VERSION)), + shading_language_version_(GLGetVersion(GL_SHADING_LANGUAGE_VERSION)) { + std::istringstream extensionsStream(GLGetString(GL_EXTENSIONS)); + extensionsStream >> std::skipws; + std::string extension; + while (extensionsStream >> extension) { + extensions_.emplace(std::move(extension)); + } +} + +GLConnection::~GLConnection() = default; + +const std::string& GLConnection::Vendor() const { + return vendor_; +} + +const std::string& GLConnection::Renderer() const { + return renderer_; +} + +const GLConnection::Version& GLConnection::GLVersion() const { + return version_; +} + +std::string GLConnection::VersionString() const { + return VersionToString(version_); +} + +const GLConnection::Version& GLConnection::ShadingLanguageVersion() const { + return shading_language_version_; +} + +std::string GLConnection::ShadingLanguageVersionString() const { + return VersionToString(shading_language_version_); +} + +std::string GLConnection::Platform() const { + std::stringstream stream; + stream << Vendor() << ": " << Renderer(); + return stream.str(); +} + +const std::set& GLConnection::Extensions() const { + return extensions_; +} + +std::string GLConnection::Description() const { + std::vector> items; + + items.emplace_back("Vendor", Vendor()); + items.emplace_back("Renderer", Renderer()); + items.emplace_back("Version", VersionString()); + items.emplace_back("Shader Version", ShadingLanguageVersionString()); + + std::string extensionsLabel("Extensions"); + + size_t padding = extensionsLabel.size(); + + for (const auto& item : items) { + padding = std::max(padding, item.first.size()); + } + + padding += 1; + + std::stringstream stream; + + stream << std::endl; + + for (const auto& item : items) { + stream << std::setw(padding) << item.first << std::setw(0) << ": " + << item.second << std::endl; + } + + if (extensions_.size() != 0) { + std::string paddingString; + paddingString.resize(padding + 2, ' '); + + stream << std::setw(padding) << extensionsLabel << std::setw(0) << ": " + << extensions_.size() << " Available" << std::endl; + + for (const auto& extension : extensions_) { + stream << paddingString << extension << std::endl; + } + } + + return stream.str(); +} + +} // namespace flow diff --git a/flow/gl_connection.h b/flow/gl_connection.h new file mode 100644 index 000000000..76ec31ee4 --- /dev/null +++ b/flow/gl_connection.h @@ -0,0 +1,72 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLOW_GL_CONNECTION_H_ +#define FLOW_GL_CONNECTION_H_ + +#include "lib/ftl/macros.h" +#include "open_gl.h" + +#include +#include + +namespace flow { + +class GLConnection { + public: + struct Version { + union { + struct { + size_t major; + size_t minor; + size_t release; + }; + size_t items[3]; + }; + + std::string vendorString; + + bool isES; + + Version() : major(0), minor(0), release(0), isES(false) {} + + Version(size_t theMajor, size_t theMinor, size_t theRelease) + : major(theMajor), minor(theMinor), release(theRelease), isES(false) {} + }; + + GLConnection(); + + ~GLConnection(); + + const std::string& Vendor() const; + + const std::string& Renderer() const; + + std::string Platform() const; + + const Version& GLVersion() const; + + std::string VersionString() const; + + const Version& ShadingLanguageVersion() const; + + std::string ShadingLanguageVersionString() const; + + const std::set& Extensions() const; + + std::string Description() const; + + private: + std::string vendor_; + std::string renderer_; + Version version_; + Version shading_language_version_; + std::set extensions_; + + FTL_DISALLOW_COPY_AND_ASSIGN(GLConnection); +}; + +} // namespace flow + +#endif // FLOW_GL_CONNECTION_H_ \ No newline at end of file diff --git a/sky/shell/gpu/direct/ganesh_canvas.cc b/sky/shell/gpu/direct/ganesh_canvas.cc index 922175104..90d14d014 100644 --- a/sky/shell/gpu/direct/ganesh_canvas.cc +++ b/sky/shell/gpu/direct/ganesh_canvas.cc @@ -7,6 +7,7 @@ #include "lib/ftl/arraysize.h" #include "lib/ftl/logging.h" #include "third_party/skia/include/gpu/gl/GrGLInterface.h" +#include "flutter/flow/gl_connection.h" namespace sky { namespace shell { @@ -32,6 +33,22 @@ bool GaneshCanvas::SetupGrGLInterface() { kOpenGL_GrBackend, reinterpret_cast(GrGLCreateNativeInterface()))); +#ifndef NDEBUG + // In debug mode, always log the GL connection description. + { + flow::GLConnection connection; + FTL_LOG(INFO) << connection.Description(); + } +#else + // In release mode, log the GL connection description in case of gr_context + // setup failure. + if (gr_context_ == nullptr) { + flow::GLConnection connection; + FTL_LOG(INFO) << "Failed to setup GL context. Aborting."; + FTL_LOG(INFO) << connection.Description(); + } +#endif + if (!gr_context_) return false; -- GitLab