Commit 917e3cae authored by Yuri Wiitala's avatar Yuri Wiitala Committed by Commit Bot

GLScaler: Fix detection and use of half-floats.

Fixes GLScaler::SupportsPreciseColorManagement() by using GL extension
strings to detect the required GLES2 extensions. Also, use of half-
floats in textures is governed by the "type" argument to glTexImage2d(),
and not the "internal format" argument.

Bug: 870036
Change-Id: I67e90cbadeb0b185025bce01c56b0f9e89e70a71
Reviewed-on: https://chromium-review.googlesource.com/c/1298643Reviewed-by: default avatarXiangjun Zhang <xjz@chromium.org>
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603236}
parent 727b8744
...@@ -6,13 +6,11 @@ ...@@ -6,13 +6,11 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <utility>
#include "base/logging.h" #include "base/logging.h"
#include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/context_provider.h"
#include "gpu/GLES2/gl2chromium.h" #include "gpu/GLES2/gl2chromium.h"
#include "gpu/GLES2/gl2extchromium.h" #include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "ui/gfx/color_transform.h" #include "ui/gfx/color_transform.h"
#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rect_conversions.h"
...@@ -34,8 +32,12 @@ bool GLScaler::SupportsPreciseColorManagement() const { ...@@ -34,8 +32,12 @@ bool GLScaler::SupportsPreciseColorManagement() const {
if (!context_provider_) { if (!context_provider_) {
return false; return false;
} }
const gpu::Capabilities& caps = context_provider_->ContextCapabilities(); if (!supports_half_floats_.has_value()) {
return caps.texture_half_float_linear && caps.color_buffer_half_float_rgba; supports_half_floats_ = AreAllGLExtensionsPresent(
context_provider_->ContextGL(),
{"GL_EXT_color_buffer_half_float", "GL_OES_texture_half_float_linear"});
}
return supports_half_floats_.value();
} }
int GLScaler::GetMaxDrawBuffersSupported() const { int GLScaler::GetMaxDrawBuffersSupported() const {
...@@ -48,13 +50,8 @@ int GLScaler::GetMaxDrawBuffersSupported() const { ...@@ -48,13 +50,8 @@ int GLScaler::GetMaxDrawBuffersSupported() const {
// present, the actual platform-supported maximum. // present, the actual platform-supported maximum.
GLES2Interface* const gl = context_provider_->ContextGL(); GLES2Interface* const gl = context_provider_->ContextGL();
DCHECK(gl); DCHECK(gl);
if (const auto* extensions = gl->GetString(GL_EXTENSIONS)) { if (AreAllGLExtensionsPresent(gl, {"GL_EXT_draw_buffers"})) {
const std::string extensions_string = gl->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
" " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
if (extensions_string.find(" GL_EXT_draw_buffers ") !=
std::string::npos) {
gl->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
}
} }
if (max_draw_buffers_ < 1) { if (max_draw_buffers_ < 1) {
...@@ -223,12 +220,12 @@ void GLScaler::OnContextLost() { ...@@ -223,12 +220,12 @@ void GLScaler::OnContextLost() {
GLScaler::ShaderProgram* GLScaler::GetShaderProgram( GLScaler::ShaderProgram* GLScaler::GetShaderProgram(
Shader shader, Shader shader,
GLint texture_format, GLenum texture_type,
const gfx::ColorTransform* color_transform, const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]) { const GLenum swizzle[2]) {
const ShaderCacheKey key{ const ShaderCacheKey key{
shader, shader,
texture_format, texture_type,
color_transform ? color_transform->GetSrcColorSpace() : gfx::ColorSpace(), color_transform ? color_transform->GetSrcColorSpace() : gfx::ColorSpace(),
color_transform ? color_transform->GetDstColorSpace() : gfx::ColorSpace(), color_transform ? color_transform->GetDstColorSpace() : gfx::ColorSpace(),
swizzle[0], swizzle[0],
...@@ -239,13 +236,31 @@ GLScaler::ShaderProgram* GLScaler::GetShaderProgram( ...@@ -239,13 +236,31 @@ GLScaler::ShaderProgram* GLScaler::GetShaderProgram(
DCHECK(gl); DCHECK(gl);
it = shader_programs_ it = shader_programs_
.emplace(std::piecewise_construct, std::forward_as_tuple(key), .emplace(std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(gl, shader, texture_format, std::forward_as_tuple(gl, shader, texture_type,
color_transform, swizzle)) color_transform, swizzle))
.first; .first;
} }
return &it->second; return &it->second;
} }
// static
bool GLScaler::AreAllGLExtensionsPresent(
gpu::gles2::GLES2Interface* gl,
const std::vector<std::string>& names) {
DCHECK(gl);
if (const auto* extensions = gl->GetString(GL_EXTENSIONS)) {
const std::string extensions_string =
" " + std::string(reinterpret_cast<const char*>(extensions)) + " ";
for (const std::string& name : names) {
if (extensions_string.find(" " + name + " ") == std::string::npos) {
return false;
}
}
return true;
}
return false;
}
GLScaler::Parameters::Parameters() = default; GLScaler::Parameters::Parameters() = default;
GLScaler::Parameters::~Parameters() = default; GLScaler::Parameters::~Parameters() = default;
...@@ -260,12 +275,12 @@ const GLfloat GLScaler::ShaderProgram::kVertexAttributes[16] = { ...@@ -260,12 +275,12 @@ const GLfloat GLScaler::ShaderProgram::kVertexAttributes[16] = {
GLScaler::ShaderProgram::ShaderProgram( GLScaler::ShaderProgram::ShaderProgram(
gpu::gles2::GLES2Interface* gl, gpu::gles2::GLES2Interface* gl,
GLScaler::Shader shader, GLScaler::Shader shader,
GLint texture_format, GLenum texture_type,
const gfx::ColorTransform* color_transform, const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]) const GLenum swizzle[2])
: gl_(gl), : gl_(gl),
shader_(shader), shader_(shader),
texture_format_(texture_format), texture_type_(texture_type),
program_(gl_->CreateProgram()) { program_(gl_->CreateProgram()) {
DCHECK(program_); DCHECK(program_);
...@@ -283,12 +298,16 @@ GLScaler::ShaderProgram::ShaderProgram( ...@@ -283,12 +298,16 @@ GLScaler::ShaderProgram::ShaderProgram(
"uniform vec4 src_rect;\n"); "uniform vec4 src_rect;\n");
fragment_header << "precision mediump float;\n"; fragment_header << "precision mediump float;\n";
if (texture_format_ == GL_RGBA16F_EXT) { switch (texture_type_) {
fragment_header << "precision mediump sampler2D;\n"; case GL_FLOAT:
} else if (texture_format_ == GL_RGBA) { fragment_header << "precision highp sampler2D;\n";
fragment_header << "precision lowp sampler2D;\n"; break;
} else { case GL_HALF_FLOAT_OES:
NOTIMPLEMENTED(); fragment_header << "precision mediump sampler2D;\n";
break;
default:
fragment_header << "precision lowp sampler2D;\n";
break;
} }
fragment_header << "uniform sampler2D s_texture;\n"; fragment_header << "uniform sampler2D s_texture;\n";
...@@ -1088,8 +1107,8 @@ void GLScaler::ScalerStage::EnsureIntermediateTextureDefined( ...@@ -1088,8 +1107,8 @@ void GLScaler::ScalerStage::EnsureIntermediateTextureDefined(
gl_->BindTexture(GL_TEXTURE_2D, intermediate_texture_); gl_->BindTexture(GL_TEXTURE_2D, intermediate_texture_);
// Note: Not setting the filter or wrap parameters on the texture here // Note: Not setting the filter or wrap parameters on the texture here
// because that will be done in ScaleToMultipleOutputs() anyway. // because that will be done in ScaleToMultipleOutputs() anyway.
gl_->TexImage2D(GL_TEXTURE_2D, 0, program_->texture_format(), size.width(), gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); GL_RGBA, program_->texture_type(), nullptr);
intermediate_texture_size_ = size; intermediate_texture_size_ = size;
} }
} }
......
...@@ -9,12 +9,15 @@ ...@@ -9,12 +9,15 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <string>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "components/viz/common/gpu/context_lost_observer.h" #include "components/viz/common/gpu/context_lost_observer.h"
#include "components/viz/common/viz_common_export.h" #include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
...@@ -285,13 +288,13 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -285,13 +288,13 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
public: public:
ShaderProgram(GLES2Interface* gl, ShaderProgram(GLES2Interface* gl,
Shader shader, Shader shader,
GLint texture_format, GLenum texture_type,
const gfx::ColorTransform* color_transform, const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]); const GLenum swizzle[2]);
~ShaderProgram(); ~ShaderProgram();
Shader shader() const { return shader_; } Shader shader() const { return shader_; }
GLint texture_format() const { return texture_format_; } GLenum texture_type() const { return texture_type_; }
// UseProgram must be called with GL_ARRAY_BUFFER bound to a vertex // UseProgram must be called with GL_ARRAY_BUFFER bound to a vertex
// attribute buffer. |src_texture_size| is the size of the entire source // attribute buffer. |src_texture_size| is the size of the entire source
...@@ -320,7 +323,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -320,7 +323,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
private: private:
GLES2Interface* const gl_; GLES2Interface* const gl_;
const Shader shader_; const Shader shader_;
const GLint texture_format_; const GLenum texture_type_;
// A program for copying a source texture into a destination texture. // A program for copying a source texture into a destination texture.
const GLuint program_; const GLuint program_;
...@@ -421,10 +424,15 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -421,10 +424,15 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// Returns a cached ShaderProgram, creating one on-demand if necessary. // Returns a cached ShaderProgram, creating one on-demand if necessary.
ShaderProgram* GetShaderProgram(Shader shader, ShaderProgram* GetShaderProgram(Shader shader,
GLint texture_format, GLenum texture_type,
const gfx::ColorTransform* color_transform, const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]); const GLenum swizzle[2]);
// Returns true if the given |gl| context mentions all of |names| in its
// extensions string.
static bool AreAllGLExtensionsPresent(gpu::gles2::GLES2Interface* gl,
const std::vector<std::string>& names);
// The provider of the GL context. This is non-null while the GL context is // The provider of the GL context. This is non-null while the GL context is
// valid and GLScaler is observing for context loss. // valid and GLScaler is observing for context loss.
scoped_refptr<ContextProvider> context_provider_; scoped_refptr<ContextProvider> context_provider_;
...@@ -432,7 +440,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -432,7 +440,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// Set by Configure() to the resolved set of Parameters. // Set by Configure() to the resolved set of Parameters.
Parameters params_; Parameters params_;
// The maximum number of simultaneous draw buffers, lazy initialized by // If set to true, half-float textures are supported. This is lazy-initialized
// by SupportsPreciseColorManagement().
mutable base::Optional<bool> supports_half_floats_;
// The maximum number of simultaneous draw buffers, lazy-initialized by
// GetMaxDrawBuffersSupported(). -1 means "not yet known." // GetMaxDrawBuffersSupported(). -1 means "not yet known."
mutable int max_draw_buffers_ = -1; mutable int max_draw_buffers_ = -1;
...@@ -440,7 +452,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -440,7 +452,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// to the arguments of GetShaderProgram(): the shader, the texture format, the // to the arguments of GetShaderProgram(): the shader, the texture format, the
// source and output color spaces (color transform), and the two swizzles. // source and output color spaces (color transform), and the two swizzles.
using ShaderCacheKey = std:: using ShaderCacheKey = std::
tuple<Shader, GLint, gfx::ColorSpace, gfx::ColorSpace, GLenum, GLenum>; tuple<Shader, GLenum, gfx::ColorSpace, gfx::ColorSpace, GLenum, GLenum>;
std::map<ShaderCacheKey, ShaderProgram> shader_programs_; std::map<ShaderCacheKey, ShaderProgram> shader_programs_;
// The GL_ARRAY_BUFFER that holds the vertices and the texture coordinates // The GL_ARRAY_BUFFER that holds the vertices and the texture coordinates
......
...@@ -39,7 +39,7 @@ class GLScalerOverscanPixelTest : public cc::PixelTest, ...@@ -39,7 +39,7 @@ class GLScalerOverscanPixelTest : public cc::PixelTest,
scaler_->chain_ = std::make_unique<ScalerStage>(gl_, shader, primary_axis, scaler_->chain_ = std::make_unique<ScalerStage>(gl_, shader, primary_axis,
scale_from, scale_to); scale_from, scale_to);
scaler_->chain_->set_shader_program(scaler_->GetShaderProgram( scaler_->chain_->set_shader_program(scaler_->GetShaderProgram(
shader, GL_RGBA, nullptr, GLScaler::Parameters().swizzle)); shader, GL_UNSIGNED_BYTE, nullptr, GLScaler::Parameters().swizzle));
} }
// Converts the given |source_rect| into a possibly-larger one that includes // Converts the given |source_rect| into a possibly-larger one that includes
......
...@@ -74,7 +74,8 @@ class GLScalerShaderPixelTest ...@@ -74,7 +74,8 @@ class GLScalerShaderPixelTest
is_swizzling_output() ? GL_BGRA_EXT : GL_RGBA, is_swizzling_output() ? GL_BGRA_EXT : GL_RGBA,
is_swizzling_output() ? GL_BGRA_EXT : GL_RGBA, is_swizzling_output() ? GL_BGRA_EXT : GL_RGBA,
}; };
return scaler_->GetShaderProgram(shader, GL_RGBA, transform.get(), swizzle); return scaler_->GetShaderProgram(shader, GL_UNSIGNED_BYTE, transform.get(),
swizzle);
} }
GLuint CreateTexture(const gfx::Size& size) { GLuint CreateTexture(const gfx::Size& size) {
...@@ -135,7 +136,9 @@ class GLScalerShaderPixelTest ...@@ -135,7 +136,9 @@ class GLScalerShaderPixelTest
GLuint result = texture; GLuint result = texture;
if (is_swizzling_output()) { if (is_swizzling_output()) {
const GLenum swizzle[2] = {GL_BGRA_EXT, GL_BGRA_EXT}; const GLenum swizzle[2] = {GL_BGRA_EXT, GL_BGRA_EXT};
scaler_->GetShaderProgram(Shader::BILINEAR, GL_RGBA, nullptr, swizzle) scaler_
->GetShaderProgram(Shader::BILINEAR, GL_UNSIGNED_BYTE, nullptr,
swizzle)
->UseProgram(size, gfx::RectF(gfx::Rect(size)), size, ->UseProgram(size, gfx::RectF(gfx::Rect(size)), size,
Axis::HORIZONTAL, false); Axis::HORIZONTAL, false);
result = RenderToNewTexture(result, size); result = RenderToNewTexture(result, size);
...@@ -146,8 +149,8 @@ class GLScalerShaderPixelTest ...@@ -146,8 +149,8 @@ class GLScalerShaderPixelTest
gfx::ColorTransform::Intent::INTENT_ABSOLUTE); gfx::ColorTransform::Intent::INTENT_ABSOLUTE);
const GLenum swizzle[2] = {GL_RGBA, GL_RGBA}; const GLenum swizzle[2] = {GL_RGBA, GL_RGBA};
scaler_ scaler_
->GetShaderProgram(Shader::BILINEAR, GL_RGBA, transform.get(), ->GetShaderProgram(Shader::BILINEAR, GL_UNSIGNED_BYTE,
swizzle) transform.get(), swizzle)
->UseProgram(size, gfx::RectF(gfx::Rect(size)), size, ->UseProgram(size, gfx::RectF(gfx::Rect(size)), size,
Axis::HORIZONTAL, false); Axis::HORIZONTAL, false);
result = RenderToNewTexture(result, size); result = RenderToNewTexture(result, size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment