summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc196
1 files changed, 158 insertions, 38 deletions
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 9098aba..e3c9b6a 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -32,6 +32,11 @@
namespace {
+const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.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,
@@ -188,7 +193,6 @@ void DeleteShader(GLuint shader) {
bool BindFramebufferTexture2D(GLenum target,
GLuint texture_id,
- GLint level,
GLuint framebuffer) {
DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB);
glActiveTexture(GL_TEXTURE0);
@@ -200,8 +204,8 @@ bool BindFramebufferTexture2D(GLenum target,
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
- glFramebufferTexture2DEXT(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture_id, level);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
+ texture_id, 0);
#ifndef NDEBUG
GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
@@ -217,28 +221,20 @@ void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
GLuint dest_id,
- GLint dest_level,
GLenum dest_internal_format,
GLsizei width,
GLsizei height,
GLuint framebuffer) {
DCHECK(source_target == GL_TEXTURE_2D ||
source_target == GL_TEXTURE_RECTANGLE_ARB);
- if (BindFramebufferTexture2D(
- source_target, source_id, 0 /* level */, framebuffer)) {
+ 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,
- dest_level,
- dest_internal_format,
- 0 /* x */,
- 0 /* y */,
- width,
- height,
- 0 /* border */);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format,
+ 0 /* x */, 0 /* y */, width, height, 0 /* border */);
}
decoder->RestoreTextureState(source_id);
@@ -248,6 +244,45 @@ void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder,
decoder->RestoreFramebufferBindings();
}
+void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder,
+ GLenum source_target,
+ GLuint source_id,
+ GLuint dest_id,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei source_width,
+ GLsizei source_height,
+ GLuint framebuffer) {
+ DCHECK(source_target == GL_TEXTURE_2D ||
+ source_target == GL_TEXTURE_RECTANGLE_ARB);
+ 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,
+ 0 /* x */, 0 /* y */, source_width, source_height);
+ }
+
+ decoder->RestoreTextureState(source_id);
+ decoder->RestoreTextureState(dest_id);
+ decoder->RestoreTextureUnitBindings(0);
+ decoder->RestoreActiveTexture();
+ decoder->RestoreFramebufferBindings();
+}
+
+// Copy from SkMatrix44::preTranslate
+void PreTranslate(GLfloat* matrix, GLfloat dx, GLfloat dy, GLfloat dz) {
+ if (!dx && !dy && !dz)
+ return;
+
+ for (int i = 0; i < 4; ++i) {
+ matrix[(3 * 4) + i] = matrix[(0 * 4) + i] * dx + matrix[(1 * 4) + i] * dy +
+ matrix[(2 * 4) + i] * dz + matrix[(3 * 4) + i];
+ }
+}
+
} // namespace
namespace gpu {
@@ -318,7 +353,6 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
GLuint source_id,
GLenum source_internal_format,
GLuint dest_id,
- GLint dest_level,
GLenum dest_internal_format,
GLsizei width,
GLsizei height,
@@ -342,7 +376,6 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
source_target,
source_id,
dest_id,
- dest_level,
dest_internal_format,
width,
height,
@@ -350,22 +383,51 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
return;
}
- // Use default transform matrix if no transform passed in.
- const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
- DoCopyTextureWithTransform(decoder,
- source_target,
- source_id,
- dest_id,
- dest_level,
- width,
- height,
- flip_y,
- premultiply_alpha,
- unpremultiply_alpha,
- default_matrix);
+ // Use kIdentityMatrix if no transform passed in.
+ DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width,
+ height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, kIdentityMatrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
+ const gles2::GLES2Decoder* decoder,
+ GLenum source_target,
+ GLuint source_id,
+ GLenum source_internal_format,
+ GLuint dest_id,
+ GLenum dest_internal_format,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei dest_width,
+ GLsizei dest_height,
+ GLsizei source_width,
+ GLsizei source_height,
+ bool flip_y,
+ bool premultiply_alpha,
+ bool unpremultiply_alpha) {
+ bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha;
+ // GL_INVALID_OPERATION is generated if the currently bound framebuffer's
+ // format does not contain a superset of the components required by the base
+ // format of internalformat.
+ // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml
+ bool source_format_contain_superset_of_dest_format =
+ (source_internal_format == dest_internal_format &&
+ source_internal_format != GL_BGRA_EXT) ||
+ (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 &&
+ source_format_contain_superset_of_dest_format) {
+ DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset,
+ yoffset, source_width, source_height, framebuffer_);
+ return;
+ }
+
+ // Use kIdentityMatrix if no transform passed in.
+ DoCopySubTextureWithTransform(
+ decoder, source_target, source_id, dest_id, xoffset, yoffset, dest_width,
+ dest_height, source_width, source_height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, kIdentityMatrix);
}
void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
@@ -373,16 +435,61 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
GLenum source_target,
GLuint source_id,
GLuint dest_id,
- GLint dest_level,
GLsizei width,
GLsizei height,
bool flip_y,
bool premultiply_alpha,
bool unpremultiply_alpha,
const GLfloat transform_matrix[16]) {
+ GLsizei dest_width = width;
+ GLsizei dest_height = height;
+ DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0,
+ dest_width, dest_height, width, height, flip_y,
+ premultiply_alpha, unpremultiply_alpha,
+ transform_matrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform(
+ const gles2::GLES2Decoder* decoder,
+ GLenum source_target,
+ GLuint source_id,
+ GLuint dest_id,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei dest_width,
+ GLsizei dest_height,
+ GLsizei source_width,
+ GLsizei source_height,
+ bool flip_y,
+ bool premultiply_alpha,
+ bool unpremultiply_alpha,
+ const GLfloat transform_matrix[16]) {
+ DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset,
+ yoffset, dest_width, dest_height, source_width,
+ source_height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, transform_matrix);
+}
+
+void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
+ const gles2::GLES2Decoder* decoder,
+ GLenum source_target,
+ GLuint source_id,
+ GLuint dest_id,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei dest_width,
+ GLsizei dest_height,
+ GLsizei source_width,
+ GLsizei source_height,
+ bool flip_y,
+ bool premultiply_alpha,
+ bool unpremultiply_alpha,
+ const GLfloat transform_matrix[16]) {
DCHECK(source_target == GL_TEXTURE_2D ||
source_target == GL_TEXTURE_RECTANGLE_ARB ||
source_target == GL_TEXTURE_EXTERNAL_OES);
+ DCHECK(xoffset >= 0 && xoffset + source_width <= dest_width);
+ DCHECK(yoffset >= 0 && yoffset + source_height <= dest_height);
if (!initialized_) {
DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager.";
return;
@@ -436,14 +543,27 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
}
#endif
- glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix);
+ if (!xoffset && !yoffset) {
+ glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, transform_matrix);
+ } else {
+ // transform offsets from ([0, dest_width], [0, dest_height]) coord.
+ // to ([-1, 1], [-1, 1]) coord.
+ GLfloat xoffset_on_vertex = ((2.f * xoffset) / dest_width);
+ GLfloat yoffset_on_vertex = ((2.f * yoffset) / dest_height);
+
+ // Pass view_matrix * offset_matrix to the program.
+ GLfloat view_transform[16];
+ memcpy(view_transform, transform_matrix, 16 * sizeof(GLfloat));
+ PreTranslate(view_transform, xoffset_on_vertex, yoffset_on_vertex, 0);
+ glUniformMatrix4fv(info->matrix_handle, 1, GL_FALSE, view_transform);
+ }
if (source_target == GL_TEXTURE_RECTANGLE_ARB)
- glUniform2f(info->half_size_handle, width / 2.0f, height / 2.0f);
+ 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, dest_level, framebuffer_)) {
+ if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) {
decoder->ClearAllAttributes();
glEnableVertexAttribArray(kVertexPositionAttrib);
@@ -466,7 +586,7 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
- glViewport(0, 0, width, height);
+ glViewport(0, 0, dest_width, dest_height);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}