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 @@
#include <sstream>
#include <string>
#include <utility>
#include "base/logging.h"
#include "components/viz/common/gpu/context_provider.h"
#include "gpu/GLES2/gl2chromium.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "ui/gfx/color_transform.h"
#include "ui/gfx/geometry/rect_conversions.h"
......@@ -34,8 +32,12 @@ bool GLScaler::SupportsPreciseColorManagement() const {
if (!context_provider_) {
return false;
}
const gpu::Capabilities& caps = context_provider_->ContextCapabilities();
return caps.texture_half_float_linear && caps.color_buffer_half_float_rgba;
if (!supports_half_floats_.has_value()) {
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 {
......@@ -48,13 +50,8 @@ int GLScaler::GetMaxDrawBuffersSupported() const {
// present, the actual platform-supported maximum.
GLES2Interface* const gl = context_provider_->ContextGL();
DCHECK(gl);
if (const auto* extensions = gl->GetString(GL_EXTENSIONS)) {
const std::string extensions_string =
" " + 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 (AreAllGLExtensionsPresent(gl, {"GL_EXT_draw_buffers"})) {
gl->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_);
}
if (max_draw_buffers_ < 1) {
......@@ -223,12 +220,12 @@ void GLScaler::OnContextLost() {
GLScaler::ShaderProgram* GLScaler::GetShaderProgram(
Shader shader,
GLint texture_format,
GLenum texture_type,
const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]) {
const ShaderCacheKey key{
shader,
texture_format,
texture_type,
color_transform ? color_transform->GetSrcColorSpace() : gfx::ColorSpace(),
color_transform ? color_transform->GetDstColorSpace() : gfx::ColorSpace(),
swizzle[0],
......@@ -239,13 +236,31 @@ GLScaler::ShaderProgram* GLScaler::GetShaderProgram(
DCHECK(gl);
it = shader_programs_
.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))
.first;
}
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;
......@@ -260,12 +275,12 @@ const GLfloat GLScaler::ShaderProgram::kVertexAttributes[16] = {
GLScaler::ShaderProgram::ShaderProgram(
gpu::gles2::GLES2Interface* gl,
GLScaler::Shader shader,
GLint texture_format,
GLenum texture_type,
const gfx::ColorTransform* color_transform,
const GLenum swizzle[2])
: gl_(gl),
shader_(shader),
texture_format_(texture_format),
texture_type_(texture_type),
program_(gl_->CreateProgram()) {
DCHECK(program_);
......@@ -283,12 +298,16 @@ GLScaler::ShaderProgram::ShaderProgram(
"uniform vec4 src_rect;\n");
fragment_header << "precision mediump float;\n";
if (texture_format_ == GL_RGBA16F_EXT) {
fragment_header << "precision mediump sampler2D;\n";
} else if (texture_format_ == GL_RGBA) {
fragment_header << "precision lowp sampler2D;\n";
} else {
NOTIMPLEMENTED();
switch (texture_type_) {
case GL_FLOAT:
fragment_header << "precision highp sampler2D;\n";
break;
case GL_HALF_FLOAT_OES:
fragment_header << "precision mediump sampler2D;\n";
break;
default:
fragment_header << "precision lowp sampler2D;\n";
break;
}
fragment_header << "uniform sampler2D s_texture;\n";
......@@ -1088,8 +1107,8 @@ void GLScaler::ScalerStage::EnsureIntermediateTextureDefined(
gl_->BindTexture(GL_TEXTURE_2D, intermediate_texture_);
// Note: Not setting the filter or wrap parameters on the texture here
// because that will be done in ScaleToMultipleOutputs() anyway.
gl_->TexImage2D(GL_TEXTURE_2D, 0, program_->texture_format(), size.width(),
size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
GL_RGBA, program_->texture_type(), nullptr);
intermediate_texture_size_ = size;
}
}
......
......@@ -9,12 +9,15 @@
#include <map>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "components/viz/common/gpu/context_lost_observer.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/client/gles2_interface.h"
......@@ -285,13 +288,13 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
public:
ShaderProgram(GLES2Interface* gl,
Shader shader,
GLint texture_format,
GLenum texture_type,
const gfx::ColorTransform* color_transform,
const GLenum swizzle[2]);
~ShaderProgram();
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
// attribute buffer. |src_texture_size| is the size of the entire source
......@@ -320,7 +323,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
private:
GLES2Interface* const gl_;
const Shader shader_;
const GLint texture_format_;
const GLenum texture_type_;
// A program for copying a source texture into a destination texture.
const GLuint program_;
......@@ -421,10 +424,15 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// Returns a cached ShaderProgram, creating one on-demand if necessary.
ShaderProgram* GetShaderProgram(Shader shader,
GLint texture_format,
GLenum texture_type,
const gfx::ColorTransform* color_transform,
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
// valid and GLScaler is observing for context loss.
scoped_refptr<ContextProvider> context_provider_;
......@@ -432,7 +440,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// Set by Configure() to the resolved set of Parameters.
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."
mutable int max_draw_buffers_ = -1;
......@@ -440,7 +452,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// to the arguments of GetShaderProgram(): the shader, the texture format, the
// source and output color spaces (color transform), and the two swizzles.
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_;
// The GL_ARRAY_BUFFER that holds the vertices and the texture coordinates
......
......@@ -39,7 +39,7 @@ class GLScalerOverscanPixelTest : public cc::PixelTest,
scaler_->chain_ = std::make_unique<ScalerStage>(gl_, shader, primary_axis,
scale_from, scale_to);
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
......
......@@ -74,7 +74,8 @@ class GLScalerShaderPixelTest
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) {
......@@ -135,7 +136,9 @@ class GLScalerShaderPixelTest
GLuint result = texture;
if (is_swizzling_output()) {
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,
Axis::HORIZONTAL, false);
result = RenderToNewTexture(result, size);
......@@ -146,8 +149,8 @@ class GLScalerShaderPixelTest
gfx::ColorTransform::Intent::INTENT_ABSOLUTE);
const GLenum swizzle[2] = {GL_RGBA, GL_RGBA};
scaler_
->GetShaderProgram(Shader::BILINEAR, GL_RGBA, transform.get(),
swizzle)
->GetShaderProgram(Shader::BILINEAR, GL_UNSIGNED_BYTE,
transform.get(), swizzle)
->UseProgram(size, gfx::RectF(gfx::Rect(size)), size,
Axis::HORIZONTAL, false);
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