Commit 935ff6ca authored by reveman@chromium.org's avatar reveman@chromium.org

gpu: Optimize and cleanup shader code used for CHROMIUM_copy_texture.

Removes all dependent texture lookups and makes sure we're not using
unnecessarily high precision for texture coordinates.

BUG=269808

Review URL: https://codereview.chromium.org/257803011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266801 0039d316-1c4b-4281-b951-d872f2087c98
parent 8f73bc9e
...@@ -4,15 +4,19 @@ ...@@ -4,15 +4,19 @@
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include <string.h> #include <algorithm>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "gpu/command_buffer/common/types.h" #include "gpu/command_buffer/common/types.h"
#include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#define SHADER(src) \ #define SHADER(src) \
"#ifdef GL_ES\n" \ "#ifdef GL_ES\n" \
"precision mediump float;\n" \ "precision mediump float;\n" \
"#define TexCoordPrecision mediump\n" \
"#else\n" \
"#define TexCoordPrecision\n" \
"#endif\n" #src "#endif\n" #src
#define SHADER_2D(src) \ #define SHADER_2D(src) \
"#define SamplerType sampler2D\n" \ "#define SamplerType sampler2D\n" \
...@@ -21,135 +25,133 @@ ...@@ -21,135 +25,133 @@
"#extension GL_OES_EGL_image_external : require\n" \ "#extension GL_OES_EGL_image_external : require\n" \
"#define SamplerType samplerExternalOES\n" \ "#define SamplerType samplerExternalOES\n" \
"#define TextureLookup texture2D\n" SHADER(src) "#define TextureLookup texture2D\n" SHADER(src)
#define SHADERS(src) \ #define FRAGMENT_SHADERS(src) \
{ SHADER_2D(src), SHADER_EXTERNAL_OES(src) } SHADER_2D(src), SHADER_EXTERNAL_OES(src)
namespace { namespace {
const GLfloat kQuadVertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, enum VertexShaderId {
1.0f, -1.0f, 0.0f, 1.0f, VERTEX_SHADER_COPY_TEXTURE,
1.0f, 1.0f, 0.0f, 1.0f, VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
-1.0f, 1.0f, 0.0f, 1.0f }; NUM_VERTEX_SHADERS,
enum ShaderId {
SHADER_COPY_TEXTURE,
SHADER_COPY_TEXTURE_FLIP_Y,
SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA,
SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA,
SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIP_Y,
SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIP_Y,
NUM_SHADERS,
}; };
enum SamplerId { enum FragmentShaderId {
SAMPLER_TEXTURE_2D, FRAGMENT_SHADER_COPY_TEXTURE_2D,
SAMPLER_TEXTURE_EXTERNAL_OES, FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
NUM_SAMPLERS, FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
NUM_FRAGMENT_SHADERS,
}; };
const char* vertex_shader_source = const char* vertex_shader_source[NUM_VERTEX_SHADERS] = {
// VERTEX_SHADER_COPY_TEXTURE
SHADER( SHADER(
uniform mat4 u_matrix; uniform mat4 u_matrix;
attribute vec4 a_position; attribute vec4 a_position;
varying vec2 v_uv; varying TexCoordPrecision vec2 v_uv;
void main(void) { void main(void) {
gl_Position = u_matrix * a_position; gl_Position = u_matrix * a_position;
v_uv = a_position.xy * 0.5 + vec2(0.5, 0.5); v_uv = a_position.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5);
});
const char* fragment_shader_source[NUM_SHADERS][NUM_SAMPLERS] = {
// SHADER_COPY_TEXTURE
SHADERS(
uniform SamplerType u_texSampler;
varying vec2 v_uv;
void main(void) {
gl_FragColor = TextureLookup(u_texSampler, v_uv.st);
}),
// SHADER_COPY_TEXTURE_FLIP_Y
SHADERS(
uniform SamplerType u_texSampler;
varying vec2 v_uv;
void main(void) {
gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t));
}), }),
// SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA // VERTEX_SHADER_COPY_TEXTURE_FLIP_Y
SHADERS( SHADER(
uniform SamplerType u_texSampler; uniform mat4 u_matrix;
varying vec2 v_uv; attribute vec4 a_position;
varying TexCoordPrecision vec2 v_uv;
void main(void) { void main(void) {
gl_FragColor = TextureLookup(u_texSampler, v_uv.st); gl_Position = u_matrix * a_position;
gl_FragColor.rgb *= gl_FragColor.a; v_uv = a_position.xy * vec2(0.5, -0.5) + vec2(0.5, 0.5);
}), }),
// SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA };
SHADERS(
uniform SamplerType u_texSampler; const char* fragment_shader_source[NUM_FRAGMENT_SHADERS] = {
varying vec2 v_uv; // FRAGMENT_SHADER_COPY_TEXTURE_*
FRAGMENT_SHADERS(
uniform SamplerType u_sampler;
varying TexCoordPrecision vec2 v_uv;
void main(void) { void main(void) {
gl_FragColor = TextureLookup(u_texSampler, v_uv.st); gl_FragColor = TextureLookup(u_sampler, v_uv.st);
if (gl_FragColor.a > 0.0)
gl_FragColor.rgb /= gl_FragColor.a;
}), }),
// SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIP_Y // FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_*
SHADERS( FRAGMENT_SHADERS(
uniform SamplerType u_texSampler; uniform SamplerType u_sampler;
varying vec2 v_uv; varying TexCoordPrecision vec2 v_uv;
void main(void) { void main(void) {
gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); gl_FragColor = TextureLookup(u_sampler, v_uv.st);
gl_FragColor.rgb *= gl_FragColor.a; gl_FragColor.rgb *= gl_FragColor.a;
}), }),
// SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIP_Y // FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_*
SHADERS( FRAGMENT_SHADERS(
uniform SamplerType u_texSampler; uniform SamplerType u_sampler;
varying vec2 v_uv; varying TexCoordPrecision vec2 v_uv;
void main(void) { void main(void) {
gl_FragColor = TextureLookup(u_texSampler, vec2(v_uv.s, 1.0 - v_uv.t)); gl_FragColor = TextureLookup(u_sampler, v_uv.st);
if (gl_FragColor.a > 0.0) if (gl_FragColor.a > 0.0)
gl_FragColor.rgb /= gl_FragColor.a; gl_FragColor.rgb /= gl_FragColor.a;
}), }),
}; };
// Returns the correct shader id to evaluate the copy operation for // Returns the correct vertex shader id to evaluate the copy operation for
// the CHROMIUM_flipy and premultiply alpha pixel store settings. // the CHROMIUM_flipy setting.
ShaderId GetShaderId(bool flip_y, VertexShaderId GetVertexShaderId(bool flip_y) {
bool premultiply_alpha, // bit 0: flip y
bool unpremultiply_alpha) { static VertexShaderId shader_ids[] = {
// If both pre-multiply and unpremultiply are requested, then perform no VERTEX_SHADER_COPY_TEXTURE,
// alpha manipulation. VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
if (premultiply_alpha && unpremultiply_alpha) {
premultiply_alpha = false;
unpremultiply_alpha = false;
}
// bit 0: Flip_y
// bit 1: Premult
// bit 2: Unpremult
static ShaderId shader_ids[] = {
SHADER_COPY_TEXTURE,
SHADER_COPY_TEXTURE_FLIP_Y, // F
SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA, // P
SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_FLIP_Y, // F P
SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA, // U
SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_FLIP_Y, // F U
SHADER_COPY_TEXTURE, // P U
SHADER_COPY_TEXTURE_FLIP_Y, // F P U
}; };
unsigned index = (flip_y ? (1 << 0) : 0) | unsigned index = flip_y ? 1 : 0;
(premultiply_alpha ? (1 << 1) : 0) |
(unpremultiply_alpha ? (1 << 2) : 0);
return shader_ids[index]; return shader_ids[index];
} }
SamplerId GetSamplerId(GLenum source_target) { // Returns the correct fragment shader id to evaluate the copy operation for
switch (source_target) { // the premultiply alpha pixel store settings and target.
FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
bool unpremultiply_alpha,
GLenum target) {
enum {
SAMPLER_2D,
SAMPLER_EXTERNAL_OES,
NUM_SAMPLERS
};
// bit 0: premultiply alpha
// bit 1: unpremultiply alpha
static FragmentShaderId shader_ids[][NUM_SAMPLERS] = {
{
FRAGMENT_SHADER_COPY_TEXTURE_2D,
FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
},
{
FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D,
FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES,
},
{
FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D,
FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES,
},
{
FRAGMENT_SHADER_COPY_TEXTURE_2D,
FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES,
}};
unsigned index = (premultiply_alpha ? (1 << 0) : 0) |
(unpremultiply_alpha ? (1 << 1) : 0);
switch (target) {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
return SAMPLER_TEXTURE_2D; return shader_ids[index][SAMPLER_2D];
case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_EXTERNAL_OES:
return SAMPLER_TEXTURE_EXTERNAL_OES; return shader_ids[index][SAMPLER_EXTERNAL_OES];
default:
break;
} }
NOTREACHED(); NOTREACHED();
return SAMPLER_TEXTURE_2D; return shader_ids[index][SAMPLER_2D];
} }
void CompileShader(GLuint shader, const char* shader_source) { void CompileShader(GLuint shader, const char* shader_source) {
...@@ -163,13 +165,21 @@ void CompileShader(GLuint shader, const char* shader_source) { ...@@ -163,13 +165,21 @@ void CompileShader(GLuint shader, const char* shader_source) {
#endif #endif
} }
void DeleteShader(GLuint shader) {
if (shader)
glDeleteShader(shader);
}
} // namespace } // namespace
namespace gpu { namespace gpu {
CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager()
: initialized_(false), buffer_id_(0), framebuffer_(0), vertex_shader_(0) { : initialized_(false),
} vertex_shaders_(NUM_VERTEX_SHADERS, 0u),
fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u),
buffer_id_(0u),
framebuffer_(0u) {}
CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {} CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() {}
...@@ -182,14 +192,15 @@ void CopyTextureCHROMIUMResourceManager::Initialize( ...@@ -182,14 +192,15 @@ void CopyTextureCHROMIUMResourceManager::Initialize(
// Initialize all of the GPU resources required to perform the copy. // Initialize all of the GPU resources required to perform the copy.
glGenBuffersARB(1, &buffer_id_); glGenBuffersARB(1, &buffer_id_);
glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, const GLfloat kQuadVertices[] = {-1.0f, -1.0f,
GL_STATIC_DRAW); 1.0f, -1.0f,
1.0f, 1.0f,
-1.0f, 1.0f};
glBufferData(
GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
glGenFramebuffersEXT(1, &framebuffer_); glGenFramebuffersEXT(1, &framebuffer_);
vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
CompileShader(vertex_shader_, vertex_shader_source);
decoder->RestoreBufferBindings(); decoder->RestoreBufferBindings();
initialized_ = true; initialized_ = true;
...@@ -201,7 +212,10 @@ void CopyTextureCHROMIUMResourceManager::Destroy() { ...@@ -201,7 +212,10 @@ void CopyTextureCHROMIUMResourceManager::Destroy() {
glDeleteFramebuffersEXT(1, &framebuffer_); glDeleteFramebuffersEXT(1, &framebuffer_);
glDeleteShader(vertex_shader_); std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader);
std::for_each(
fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader);
for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end();
++it) { ++it) {
const ProgramInfo& info = it->second; const ProgramInfo& info = it->second;
...@@ -253,19 +267,30 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( ...@@ -253,19 +267,30 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
return; return;
} }
ShaderId shader_id = VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y);
GetShaderId(flip_y, premultiply_alpha, unpremultiply_alpha); DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size());
SamplerId sampler_id = GetSamplerId(source_target); GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id];
if (!*vertex_shader) {
*vertex_shader = glCreateShader(GL_VERTEX_SHADER);
CompileShader(*vertex_shader, vertex_shader_source[vertex_shader_id]);
}
FragmentShaderId fragment_shader_id = GetFragmentShaderId(
premultiply_alpha, unpremultiply_alpha, source_target);
DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size());
GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
if (!*fragment_shader) {
*fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
CompileShader(*fragment_shader, fragment_shader_source[fragment_shader_id]);
}
ProgramMapKey key(shader_id, sampler_id); ProgramMapKey key(vertex_shader_id, fragment_shader_id);
ProgramInfo* info = &programs_[key]; ProgramInfo* info = &programs_[key];
// Create program if necessary. // Create program if necessary.
if (!info->program) { if (!info->program) {
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
CompileShader(shader, fragment_shader_source[shader_id][sampler_id]);
info->program = glCreateProgram(); info->program = glCreateProgram();
glAttachShader(info->program, vertex_shader_); glAttachShader(info->program, *vertex_shader);
glAttachShader(info->program, shader); glAttachShader(info->program, *fragment_shader);
glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position");
glLinkProgram(info->program); glLinkProgram(info->program);
#ifndef NDEBUG #ifndef NDEBUG
...@@ -274,10 +299,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( ...@@ -274,10 +299,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
if (!linked) if (!linked)
DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure.";
#endif #endif
info->sampler_locations =
glGetUniformLocation(info->program, "u_texSampler");
info->matrix_handle = glGetUniformLocation(info->program, "u_matrix"); info->matrix_handle = glGetUniformLocation(info->program, "u_matrix");
glDeleteShader(shader); info->sampler_handle = glGetUniformLocation(info->program, "u_sampler");
} }
glUseProgram(info->program); glUseProgram(info->program);
...@@ -315,10 +338,9 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( ...@@ -315,10 +338,9 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
glEnableVertexAttribArray(kVertexPositionAttrib); glEnableVertexAttribArray(kVertexPositionAttrib);
glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); glBindBuffer(GL_ARRAY_BUFFER, buffer_id_);
glVertexAttribPointer(kVertexPositionAttrib, 4, GL_FLOAT, GL_FALSE, glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
4 * sizeof(GLfloat), 0);
glUniform1i(info->sampler_locations, 0); glUniform1i(info->sampler_handle, 0);
glBindTexture(source_target, source_id); glBindTexture(source_target, source_id);
glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(source_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
...@@ -349,5 +371,4 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( ...@@ -349,5 +371,4 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
decoder->RestoreGlobalState(); decoder->RestoreGlobalState();
} }
} // namespace } // namespace gpu
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_
#include <vector>
#include "base/containers/hash_tables.h" #include "base/containers/hash_tables.h"
#include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/gpu_export.h" #include "gpu/gpu_export.h"
...@@ -48,20 +50,22 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { ...@@ -48,20 +50,22 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager {
private: private:
struct ProgramInfo { struct ProgramInfo {
ProgramInfo() : program(0u), matrix_handle(0u), sampler_locations(0u) {} ProgramInfo() : program(0u), matrix_handle(0u), sampler_handle(0u) {}
GLuint program; GLuint program;
GLuint matrix_handle; GLuint matrix_handle;
GLuint sampler_locations; GLuint sampler_handle;
}; };
bool initialized_; bool initialized_;
typedef std::vector<GLuint> ShaderVector;
ShaderVector vertex_shaders_;
ShaderVector fragment_shaders_;
typedef std::pair<int, int> ProgramMapKey; typedef std::pair<int, int> ProgramMapKey;
typedef base::hash_map<ProgramMapKey, ProgramInfo> ProgramMap; typedef base::hash_map<ProgramMapKey, ProgramInfo> ProgramMap;
ProgramMap programs_; ProgramMap programs_;
GLuint buffer_id_; GLuint buffer_id_;
GLuint framebuffer_; GLuint framebuffer_;
GLuint vertex_shader_;
DISALLOW_COPY_AND_ASSIGN(CopyTextureCHROMIUMResourceManager); DISALLOW_COPY_AND_ASSIGN(CopyTextureCHROMIUMResourceManager);
}; };
...@@ -69,5 +73,3 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager { ...@@ -69,5 +73,3 @@ class GPU_EXPORT CopyTextureCHROMIUMResourceManager {
} // namespace gpu. } // namespace gpu.
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_ #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEXTURE_CHROMIUM_H_
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