Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc

Issue 1547873002: Allow GL_TEXTURE_RECTANGLE_ARB to be the destination target for copyTextureCHROMIUM. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments from kbr. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
index f5a9001e26eee412aefb5cd2bd6e922a89f191ba..d84cbdef71f9ebf12c17cbdd9bcabba0e1ca9521 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -19,12 +19,6 @@ const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
-enum VertexShaderId {
- VERTEX_SHADER_COPY_TEXTURE,
- VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
- NUM_VERTEX_SHADERS,
-};
-
enum FragmentShaderId {
FRAGMENT_SHADER_COPY_TEXTURE_2D,
FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB,
@@ -38,19 +32,6 @@ enum FragmentShaderId {
NUM_FRAGMENT_SHADERS,
};
-// Returns the correct vertex shader id to evaluate the copy operation for
-// the CHROMIUM_flipy setting.
-VertexShaderId GetVertexShaderId(bool flip_y) {
- // bit 0: flip y
- static VertexShaderId shader_ids[] = {
- VERTEX_SHADER_COPY_TEXTURE,
- VERTEX_SHADER_COPY_TEXTURE_FLIP_Y,
- };
-
- unsigned index = flip_y ? 1 : 0;
- return shader_ids[index];
-}
-
// Returns the correct fragment shader id to evaluate the copy operation for
// the premultiply alpha pixel store settings and target.
FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
@@ -116,7 +97,7 @@ const char* kShaderPrecisionPreamble = "\
#define TexCoordPrecision\n\
#endif\n";
-std::string GetVertexShaderSource(bool flip_y) {
+std::string GetVertexShaderSource() {
std::string source;
// Preamble for core and compatibility mode.
@@ -135,23 +116,19 @@ std::string GetVertexShaderSource(bool flip_y) {
// Preamble for texture precision.
source += std::string(kShaderPrecisionPreamble);
- // Preamble to differentiate based on |flip_y|.
- if (flip_y) {
- source += std::string("#define SIGN -\n");
- } else {
- source += std::string("#define SIGN\n");
- }
-
// Main shader source.
source += std::string("\
- uniform vec2 u_vertex_translate;\n\
- uniform vec2 u_half_size;\n\
+ uniform vec2 u_vertex_dest_mult;\n\
+ uniform vec2 u_vertex_dest_add;\n\
+ uniform vec2 u_vertex_source_mult;\n\
+ uniform vec2 u_vertex_source_add;\n\
ATTRIBUTE vec4 a_position;\n\
VARYING TexCoordPrecision vec2 v_uv;\n\
void main(void) {\n\
- gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);\n\
- v_uv = a_position.xy * vec2(u_half_size.s, SIGN u_half_size.t) +\n\
- vec2(u_half_size.s, u_half_size.t);\n\
+ gl_Position = a_position;\n\
+ gl_Position.xy = a_position.xy * u_vertex_dest_mult + \
+ u_vertex_dest_add;\n\
+ v_uv = a_position.xy * u_vertex_source_mult + u_vertex_source_add;\n\
}\n");
return source;
@@ -285,20 +262,21 @@ bool BindFramebufferTexture2D(GLenum target,
void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
+ GLenum dest_target,
GLuint dest_id,
GLenum dest_internal_format,
GLsizei width,
GLsizei height,
GLuint framebuffer) {
- DCHECK(source_target == GL_TEXTURE_2D ||
- source_target == GL_TEXTURE_RECTANGLE_ARB);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), source_target);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target);
if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
- glBindTexture(GL_TEXTURE_2D, dest_id);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format,
+ glBindTexture(dest_target, dest_id);
+ glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glCopyTexImage2D(dest_target, 0 /* level */, dest_internal_format,
0 /* x */, 0 /* y */, width, height, 0 /* border */);
}
@@ -312,6 +290,7 @@ void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
+ GLenum dest_target,
GLuint dest_id,
GLint xoffset,
GLint yoffset,
@@ -322,13 +301,14 @@ void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
GLuint framebuffer) {
DCHECK(source_target == GL_TEXTURE_2D ||
source_target == GL_TEXTURE_RECTANGLE_ARB);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target);
if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) {
- glBindTexture(GL_TEXTURE_2D, dest_id);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset,
+ glBindTexture(dest_target, dest_id);
+ glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glCopyTexSubImage2D(dest_target, 0 /* level */, xoffset, yoffset,
source_x, source_y, source_width, source_height);
}
@@ -345,7 +325,7 @@ namespace gpu {
CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager()
: initialized_(false),
- vertex_shaders_(NUM_VERTEX_SHADERS, 0u),
+ vertex_shader_(0u),
fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u),
buffer_id_(0u),
framebuffer_(0u) {}
@@ -389,7 +369,7 @@ void CopyTextureCHROMIUMResourceManager::Destroy() {
glDeleteFramebuffersEXT(1, &framebuffer_);
framebuffer_ = 0;
- std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader);
+ DeleteShader(vertex_shader_);
std::for_each(
fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader);
@@ -408,6 +388,7 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
GLenum source_target,
GLuint source_id,
GLenum source_internal_format,
+ GLenum dest_target,
GLuint dest_id,
GLenum dest_internal_format,
GLsizei width,
@@ -426,11 +407,13 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
(source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
// GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
// so restrict this to GL_TEXTURE_2D.
- if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
+ if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D &&
+ !flip_y && !premultiply_alpha_change &&
source_format_contain_superset_of_dest_format) {
DoCopyTexImage2D(decoder,
source_target,
source_id,
+ dest_target,
dest_id,
dest_internal_format,
width,
@@ -440,8 +423,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
}
// Use kIdentityMatrix if no transform passed in.
- DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width,
- height, flip_y, premultiply_alpha,
+ DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target,
+ dest_id, width, height, flip_y, premultiply_alpha,
unpremultiply_alpha, kIdentityMatrix);
}
@@ -450,6 +433,7 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
GLenum source_target,
GLuint source_id,
GLenum source_internal_format,
+ GLenum dest_target,
GLuint dest_id,
GLenum dest_internal_format,
GLint xoffset,
@@ -476,23 +460,25 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
(source_internal_format == GL_RGBA && dest_internal_format == GL_RGB);
// GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2,
// so restrict this to GL_TEXTURE_2D.
- if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
+ if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D &&
+ !flip_y && !premultiply_alpha_change &&
source_format_contain_superset_of_dest_format) {
- DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset,
- yoffset, x, y, width, height, framebuffer_);
+ DoCopyTexSubImage2D(decoder, source_target, source_id, dest_target, dest_id,
+ xoffset, yoffset, x, y, width, height, framebuffer_);
return;
}
- DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset,
- yoffset, x, y, width, height, dest_width, dest_height,
- source_width, source_height, flip_y, premultiply_alpha,
- unpremultiply_alpha, kIdentityMatrix);
+ DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id,
+ xoffset, yoffset, x, y, width, height, dest_width, dest_height,
+ source_width, source_height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, kIdentityMatrix);
}
void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
const gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
+ GLenum dest_target,
GLuint dest_id,
GLsizei width,
GLsizei height,
@@ -502,16 +488,17 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
const GLfloat transform_matrix[16]) {
GLsizei dest_width = width;
GLsizei dest_height = height;
- DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0,
- width, height, dest_width, dest_height, width, height,
- flip_y, premultiply_alpha, unpremultiply_alpha,
- transform_matrix);
+ DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id,
+ 0, 0, 0, 0, width, height, dest_width, dest_height,
+ width, height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, transform_matrix);
}
void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
const gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
+ GLenum dest_target,
GLuint dest_id,
GLint xoffset,
GLint yoffset,
@@ -530,33 +517,37 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
DCHECK(source_target == GL_TEXTURE_2D ||
source_target == GL_TEXTURE_RECTANGLE_ARB ||
source_target == GL_TEXTURE_EXTERNAL_OES);
+ DCHECK(dest_target == GL_TEXTURE_2D ||
+ dest_target == GL_TEXTURE_RECTANGLE_ARB);
DCHECK_GE(xoffset, 0);
DCHECK_LE(xoffset + width, dest_width);
DCHECK_GE(yoffset, 0);
DCHECK_LE(yoffset + height, dest_height);
+ if (dest_width == 0 || dest_height == 0 || source_width == 0 ||
+ source_height == 0) {
+ return;
+ }
+
if (!initialized_) {
DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
return;
}
- VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y);
- DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size());
FragmentShaderId fragment_shader_id = GetFragmentShaderId(
premultiply_alpha, unpremultiply_alpha, source_target);
DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size());
- ProgramMapKey key(vertex_shader_id, fragment_shader_id);
+ ProgramMapKey key(fragment_shader_id);
ProgramInfo* info = &programs_[key];
// Create program if necessary.
if (!info->program) {
info->program = glCreateProgram();
- GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id];
- if (!*vertex_shader) {
- *vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- std::string source = GetVertexShaderSource(flip_y);
- CompileShader(*vertex_shader, source.c_str());
+ if (!vertex_shader_) {
+ vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
+ std::string source = GetVertexShaderSource();
+ CompileShader(vertex_shader_, source.c_str());
}
- glAttachShader(info->program, *vertex_shader);
+ glAttachShader(info->program, vertex_shader_);
GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
if (!*fragment_shader) {
*fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
@@ -573,11 +564,17 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
if (!linked)
DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure.";
#endif
- info->vertex_translate_handle = glGetUniformLocation(info->program,
- "u_vertex_translate");
+ info->vertex_dest_mult_handle =
+ glGetUniformLocation(info->program, "u_vertex_dest_mult");
+ info->vertex_dest_add_handle =
+ glGetUniformLocation(info->program, "u_vertex_dest_add");
+ info->vertex_source_mult_handle =
+ glGetUniformLocation(info->program, "u_vertex_source_mult");
+ info->vertex_source_add_handle =
+ glGetUniformLocation(info->program, "u_vertex_source_add");
+
info->tex_coord_transform_handle =
glGetUniformLocation(info->program, "u_tex_coord_transform");
- info->half_size_handle = glGetUniformLocation(info->program, "u_half_size");
info->sampler_handle = glGetUniformLocation(info->program, "u_sampler");
}
glUseProgram(info->program);
@@ -585,27 +582,75 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE,
transform_matrix);
- GLint x_translate = xoffset - x;
- GLint y_translate = yoffset - y;
- if (!x_translate && !y_translate) {
- glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f);
- } else {
- // transform offsets from ([0, dest_width], [0, dest_height]) coord.
- // to ([-1, 1], [-1, 1]) coord.
- GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width);
- GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height);
-
- // Pass translation to the shader program.
- glUniform2f(info->vertex_translate_handle, x_translate_on_vertex,
- y_translate_on_vertex);
- }
- if (source_target == GL_TEXTURE_RECTANGLE_ARB)
- glUniform2f(info->half_size_handle, source_width / 2.0f,
- source_height / 2.0f);
- else
- glUniform2f(info->half_size_handle, 0.5f, 0.5f);
-
- if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) {
+ // Note: For simplicity, the calculations in this comment block use a single
+ // dimension. All calculations trivially extend to the x-y plane.
+ // The target subrange in the destination texture has coordinates
+ // [xoffset, xoffset + width]. The full destination texture has range
+ // [0, dest_width].
+ //
+ // We want to find A and B such that:
+ // A * X + B = Y
+ // C * Y + D = Z
+ //
+ // where X = [-1, 1], Z = [xoffset, xoffset + width]
+ // and C, D satisfy the relationship C * [-1, 1] + D = [0, dest_width].
+ //
+ // Math shows:
+ // C = D = dest_width / 2
+ // Y = [(xoffset * 2 / dest_width) - 1,
+ // (xoffset + width) * 2 / dest_width) - 1]
+ // A = width / dest_width
+ // B = (xoffset * 2 + width - dest_width) / dest_width
+ glUniform2f(info->vertex_dest_mult_handle, width * 1.f / dest_width,
+ height * 1.f / dest_height);
+ glUniform2f(info->vertex_dest_add_handle,
+ (xoffset * 2.f + width - dest_width) / dest_width,
+ (yoffset * 2.f + height - dest_height) / dest_height);
+
+ // Note: For simplicity, the calculations in this comment block use a single
+ // dimension. All calculations trivially extend to the x-y plane.
+ // The target subrange in the source texture has coordinates [x, x + width].
+ // The full source texture has range [0, source_width]. We need to transform
+ // the subrange into texture space ([0, M]), assuming that [0, source_width]
+ // gets mapped to [0, M]. If source_target == GL_TEXTURE_RECTANGLE_ARB, M =
+ // source_width. Otherwise, M = 1.
+ //
+ // We want to find A and B such that:
+ // A * X + B = Y
+ // C * Y + D = Z
+ //
+ // where X = [-1, 1], Z = [x, x + width]
+ // and C, D satisfy the relationship C * [0, M] + D = [0, source_width].
+ //
+ // Math shows:
+ // D = 0
+ // C = source_width / M
+ // Y = [x * M / source_width, (x + width) * M / source_width]
+ // B = (x + w/2) * M / source_width
+ // A = (w/2) * M / source_width
+ //
+ // When flip_y is true, we run the same calcluation, but with Z = [x + width,
+ // x]. (I'm intentionally keeping the x-plane notation, although the
+ // calculation only gets applied to the y-plane).
+ //
+ // Math shows:
+ // D = 0
+ // C = source_width / M
+ // Y = [(x + width) * M / source_width, x * M / source_width]
+ // B = (x + w/2) * M / source_width
+ // A = (-w/2) * M / source_width
+ //
+ // So everything is the same but the sign of A is flipped.
+ GLfloat m_x = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_width : 1;
+ GLfloat m_y = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_height : 1;
+ GLfloat sign_a = flip_y ? -1 : 1;
+ glUniform2f(info->vertex_source_mult_handle, width / 2.f * m_x / source_width,
+ height / 2.f * m_y / source_height * sign_a);
+ glUniform2f(info->vertex_source_add_handle,
+ (x + width / 2.f) * m_x / source_width,
+ (y + height / 2.f) * m_y / source_height);
+
+ if (BindFramebufferTexture2D(dest_target, dest_id, framebuffer_)) {
#ifndef NDEBUG
// glValidateProgram of MACOSX validates FBO unlike other platforms, so
// glValidateProgram must be called after FBO binding. crbug.com/463439
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698