Commit be20a16a authored by Yuri Wiitala's avatar Yuri Wiitala Committed by Commit Bot

GLScaler: Add scaler stages and overscan pixel tests.

Refactors and cleans-up code, transforming GLHelperScaling's internal
"ScalerImpl" class into a GLScaler::ScalerStage class. A ScalerStage
chains together with other ScalerStages to perform each step from the
source input to ultimate scaled output. (A future change will provide
the logic for deciding how to create/configure ScalerStages and chain
them together.)

A major change other than the refactoring: The math that calculates each
shader's "overscan" padding has been revisited and corrected. New math
is included in this change, along with pixel tests that confirm it is
correct (i.e., tests the math, but also runs the shader programs to
prove the numbers jive).

Bug: 870036
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel
Change-Id: I3dbbbb8f8cca45006895faed6d7501ceab5cc1cb
Reviewed-on: https://chromium-review.googlesource.com/c/1285328Reviewed-by: default avatarXiangjun Zhang <xjz@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601341}
parent 04843c10
...@@ -218,6 +218,7 @@ viz_source_set("unit_tests") { ...@@ -218,6 +218,7 @@ viz_source_set("unit_tests") {
"frame_sinks/copy_output_util_unittest.cc", "frame_sinks/copy_output_util_unittest.cc",
"frame_sinks/delay_based_time_source_unittest.cc", "frame_sinks/delay_based_time_source_unittest.cc",
"gl_helper_unittest.cc", "gl_helper_unittest.cc",
"gl_scaler_overscan_pixeltest.cc",
"gl_scaler_shader_pixeltest.cc", "gl_scaler_shader_pixeltest.cc",
"gl_scaler_test_util.cc", "gl_scaler_test_util.cc",
"gl_scaler_test_util.h", "gl_scaler_test_util.h",
......
This diff is collapsed.
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <tuple> #include <tuple>
#include <utility>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/macros.h" #include "base/macros.h"
...@@ -18,14 +19,13 @@ ...@@ -18,14 +19,13 @@
#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"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
namespace gfx { namespace gfx {
class ColorTransform; class ColorTransform;
class Vector2dF;
class Rect;
class RectF;
class Size;
} // namespace gfx } // namespace gfx
namespace viz { namespace viz {
...@@ -232,7 +232,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -232,7 +232,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// and wrap_s/t set to CLAMP_TO_EDGE in this call. // and wrap_s/t set to CLAMP_TO_EDGE in this call.
bool Scale(GLuint src_texture, bool Scale(GLuint src_texture,
const gfx::Size& src_texture_size, const gfx::Size& src_texture_size,
const gfx::Vector2dF& src_offset, const gfx::Vector2d& src_offset,
GLuint dest_texture, GLuint dest_texture,
const gfx::Rect& output_rect) WARN_UNUSED_RESULT { const gfx::Rect& output_rect) WARN_UNUSED_RESULT {
return ScaleToMultipleOutputs(src_texture, src_texture_size, src_offset, return ScaleToMultipleOutputs(src_texture, src_texture_size, src_offset,
...@@ -243,28 +243,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -243,28 +243,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// (see Parameters::ExportFormat). // (see Parameters::ExportFormat).
bool ScaleToMultipleOutputs(GLuint src_texture, bool ScaleToMultipleOutputs(GLuint src_texture,
const gfx::Size& src_texture_size, const gfx::Size& src_texture_size,
const gfx::Vector2dF& src_offset, const gfx::Vector2d& src_offset,
GLuint dest_texture_0, GLuint dest_texture_0,
GLuint dest_texture_1, GLuint dest_texture_1,
const gfx::Rect& output_rect) WARN_UNUSED_RESULT; const gfx::Rect& output_rect) WARN_UNUSED_RESULT;
// Given the |src_texture_size|, |src_offset| and |output_rect| arguments that
// would be passed to Scale(), compute the region of pixels in the source
// texture that would be sampled to produce a scaled result. The result is
// stored in |sampling_rect|, along with the |offset| to the (0,0) point
// relative to |sampling_rect|'s origin. Returns true to indicate success, or
// false if this GLScaler is not valid.
//
// This is used by clients that need to know the minimal portion of a source
// buffer that must be copied without affecting Scale()'s results. This
// method also accounts for vertical flipping.
bool ComputeRegionOfInfluence(const gfx::Size& src_texture_size,
const gfx::Vector2dF& src_offset,
const gfx::Rect& output_rect,
gfx::Rect* sampling_rect,
gfx::Vector2dF* offset) const
WARN_UNUSED_RESULT;
// Returns true if from:to represent the same scale ratio as that specified in // Returns true if from:to represent the same scale ratio as that specified in
// |params|. // |params|.
static bool ParametersHasSameScaleRatio(const Parameters& params, static bool ParametersHasSameScaleRatio(const Parameters& params,
...@@ -272,6 +255,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -272,6 +255,7 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
const gfx::Vector2d& to); const gfx::Vector2d& to);
private: private:
friend class GLScalerOverscanPixelTest;
friend class GLScalerShaderPixelTest; friend class GLScalerShaderPixelTest;
using GLES2Interface = gpu::gles2::GLES2Interface; using GLES2Interface = gpu::gles2::GLES2Interface;
...@@ -313,9 +297,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -313,9 +297,11 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
// attribute buffer. |src_texture_size| is the size of the entire source // attribute buffer. |src_texture_size| is the size of the entire source
// texture, regardless of which region is to be sampled. |src_rect| is the // texture, regardless of which region is to be sampled. |src_rect| is the
// source region, not including overscan pixels past the edges. // source region, not including overscan pixels past the edges.
// |primary_axis| configures certain programs which scale in only one // |primary_axis| determines whether multiple texture samplings occur in one
// particular direction. |flip_y| causes the |src_rect| to be scanned // direction or the other (for some shaders). Note that this cannot
// upside-down, to produce a vertically-flipped result. // necessarily be determined by just comparing the src and dst sizes.
// |flip_y| causes the |src_rect| to be scanned upside-down, to produce a
// vertically-flipped result.
void UseProgram(const gfx::Size& src_texture_size, void UseProgram(const gfx::Size& src_texture_size,
const gfx::RectF& src_rect, const gfx::RectF& src_rect,
const gfx::Size& dst_size, const gfx::Size& dst_size,
...@@ -356,6 +342,80 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -356,6 +342,80 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
DISALLOW_COPY_AND_ASSIGN(ShaderProgram); DISALLOW_COPY_AND_ASSIGN(ShaderProgram);
}; };
// One scaling stage in a chain of scaler pipeline stages. Each ScalerStage
// owns the previous ScalerStage in the chain: At execution time, a "working
// backwards" approach is used: The previous "input" stage renders an
// intermediate result that will be used as input for the current stage.
//
// Each ScalerStage caches textures and framebuffers to avoid reallocating
// them for each separate image scaling, which can be expensive on some
// platforms/drivers.
class VIZ_COMMON_EXPORT ScalerStage {
public:
ScalerStage(GLES2Interface* gl,
Shader shader,
Axis primary_axis,
const gfx::Vector2d& scale_from,
const gfx::Vector2d& scale_to);
~ScalerStage();
Shader shader() const { return shader_; }
const gfx::Vector2d& scale_from() const { return scale_from_; }
const gfx::Vector2d& scale_to() const { return scale_to_; }
ScalerStage* input_stage() const { return input_stage_.get(); }
void set_input_stage(std::unique_ptr<ScalerStage> stage) {
input_stage_ = std::move(stage);
}
void set_shader_program(ShaderProgram* program) { program_ = program; }
bool is_flipped_source() const { return is_flipped_source_; }
void set_is_flipped_source(bool flipped) { is_flipped_source_ = flipped; }
bool flip_output() const { return flip_output_; }
void set_flip_output(bool flip) { flip_output_ = flip; }
void ScaleToMultipleOutputs(GLuint src_texture,
gfx::Size src_texture_size,
const gfx::Vector2d& src_offset,
GLuint dest_texture_0,
GLuint dest_texture_1,
const gfx::Rect& output_rect);
private:
friend class GLScalerOverscanPixelTest;
// Returns the given |output_rect| mapped to the input stage's coordinate
// system.
gfx::RectF ToSourceRect(const gfx::Rect& output_rect) const;
// Returns the given |source_rect| padded to include the overscan pixels the
// shader program will access.
gfx::Rect ToInputRect(gfx::RectF source_rect) const;
// Generates the intermediate texture and/or re-defines it if its size has
// changed.
void EnsureIntermediateTextureDefined(const gfx::Size& size);
GLES2Interface* const gl_;
const Shader shader_;
const Axis primary_axis_;
const gfx::Vector2d scale_from_;
const gfx::Vector2d scale_to_;
std::unique_ptr<ScalerStage> input_stage_;
ShaderProgram* program_ = nullptr;
bool is_flipped_source_ = false;
bool flip_output_ = false;
GLuint intermediate_texture_ = 0;
gfx::Size intermediate_texture_size_;
GLuint dest_framebuffer_ = 0;
DISALLOW_COPY_AND_ASSIGN(ScalerStage);
};
// ContextLostObserver implementation. // ContextLostObserver implementation.
void OnContextLost() final; void OnContextLost() final;
...@@ -383,6 +443,14 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver { ...@@ -383,6 +443,14 @@ class VIZ_COMMON_EXPORT GLScaler : public ContextLostObserver {
tuple<Shader, GLint, gfx::ColorSpace, gfx::ColorSpace, GLenum, GLenum>; tuple<Shader, GLint, 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
// data for sweeping the source area when a ScalerStage draws a quad (to
// execute its shader program).
GLuint vertex_attributes_buffer_ = 0;
// The chain of ScalerStages.
std::unique_ptr<ScalerStage> chain_;
DISALLOW_COPY_AND_ASSIGN(GLScaler); DISALLOW_COPY_AND_ASSIGN(GLScaler);
}; };
......
This diff is collapsed.
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