Support glCopyTex[Sub]Image to LUMA formats on the core profile.
BUG=577144
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_optional_gpu_tests_rel;tryserver.chromium.mac:mac_optional_gpu_tests_rel;tryserver.chromium.win:win_optional_gpu_tests_rel
Review-Url: https://codereview.chromium.org/2027703003
Cr-Commit-Position: refs/heads/master@{#399545}
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 41da83d..c19fa7e7 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -56,6 +56,8 @@
"gl_utils.h",
"gles2_cmd_clear_framebuffer.cc",
"gles2_cmd_clear_framebuffer.h",
+ "gles2_cmd_copy_tex_image.cc",
+ "gles2_cmd_copy_tex_image.h",
"gles2_cmd_copy_texture_chromium.cc",
"gles2_cmd_copy_texture_chromium.h",
"gles2_cmd_decoder.cc",
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc
new file mode 100644
index 0000000..b9e6130
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc
@@ -0,0 +1,273 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h"
+
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "ui/gl/gl_version_info.h"
+
+namespace {
+
+void CompileShader(GLuint shader, const char* shader_source) {
+ glShaderSource(shader, 1, &shader_source, 0);
+ glCompileShader(shader);
+#ifndef NDEBUG
+ GLint compile_status;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
+ if (GL_TRUE != compile_status)
+ DLOG(ERROR) << "CopyTexImage: shader compilation failure.";
+#endif
+}
+
+} // anonymous namespace
+
+namespace gpu {
+
+CopyTexImageResourceManager::CopyTexImageResourceManager(
+ const gles2::FeatureInfo* feature_info)
+ : feature_info_(feature_info) {
+ DCHECK(feature_info->gl_version_info().is_desktop_core_profile);
+}
+
+CopyTexImageResourceManager::~CopyTexImageResourceManager() {}
+
+void CopyTexImageResourceManager::Initialize(
+ const gles2::GLES2Decoder* decoder) {
+ if (initialized_) {
+ return;
+ }
+
+ blit_program_ = glCreateProgram();
+
+ // Compile the fragment shader
+ const char* vs_source =
+ "#version 150\n"
+ "out vec2 v_texcoord;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " const vec2 quad_positions[6] = vec2[6]\n"
+ " (\n"
+ " vec2(0.0f, 0.0f),\n"
+ " vec2(0.0f, 1.0f),\n"
+ " vec2(1.0f, 0.0f),\n"
+ "\n"
+ " vec2(0.0f, 1.0f),\n"
+ " vec2(1.0f, 0.0f),\n"
+ " vec2(1.0f, 1.0f)\n"
+ " );\n"
+ "\n"
+ " gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, "
+ "1.0);\n"
+ " v_texcoord = quad_positions[gl_VertexID];\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ CompileShader(vs, vs_source);
+ glAttachShader(blit_program_, vs);
+ glDeleteShader(vs);
+
+ // Compile the vertex shader
+ const char* fs_source =
+ "#version 150\n"
+ "uniform sampler2D u_source_texture;\n"
+ "in vec2 v_texcoord;\n"
+ "out vec4 output_color;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " output_color = texture(u_source_texture, v_texcoord);\n"
+ "}\n";
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ CompileShader(fs, fs_source);
+ glAttachShader(blit_program_, fs);
+ glDeleteShader(fs);
+
+ glLinkProgram(blit_program_);
+#ifndef NDEBUG
+ GLint linked = 0;
+ glGetProgramiv(blit_program_, GL_LINK_STATUS, &linked);
+ if (!linked) {
+ DLOG(ERROR) << "CopyTexImage: program link failure.";
+ }
+#endif
+
+ GLuint texture_uniform =
+ glGetUniformLocation(blit_program_, "u_source_texture");
+ glUseProgram(blit_program_);
+ glUniform1i(texture_uniform, 0);
+
+ glGenTextures(scratch_textures_.size(), scratch_textures_.data());
+ glActiveTexture(GL_TEXTURE0);
+ for (auto scratch_texture : scratch_textures_) {
+ glBindTexture(GL_TEXTURE_2D, scratch_texture);
+
+ // Use nearest, non-mipmapped sampling with the scratch texture
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
+
+ glGenFramebuffersEXT(1, &scratch_fbo_);
+ glGenVertexArraysOES(1, &vao_);
+
+ decoder->RestoreTextureUnitBindings(0);
+ decoder->RestoreActiveTexture();
+ decoder->RestoreProgramBindings();
+
+ initialized_ = true;
+}
+
+void CopyTexImageResourceManager::Destroy() {
+ if (!initialized_) {
+ return;
+ }
+
+ glDeleteProgram(blit_program_);
+ blit_program_ = 0;
+
+ glDeleteTextures(scratch_textures_.size(), scratch_textures_.data());
+ scratch_textures_.fill(0);
+
+ glDeleteFramebuffersEXT(1, &scratch_fbo_);
+ scratch_fbo_ = 0;
+
+ glDeleteVertexArraysOES(1, &vao_);
+ vao_ = 0;
+
+ initialized_ = false;
+}
+
+void CopyTexImageResourceManager::DoCopyTexImage2DToLUMAComatabilityTexture(
+ const gles2::GLES2Decoder* decoder,
+ GLuint dest_texture,
+ GLenum dest_texture_target,
+ GLenum dest_target,
+ GLenum luma_format,
+ GLenum luma_type,
+ GLint level,
+ GLenum internal_format,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLuint source_framebuffer,
+ GLenum source_framebuffer_internal_format) {
+ GLenum adjusted_internal_format =
+ gles2::TextureManager::AdjustTexInternalFormat(feature_info_.get(),
+ internal_format);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ GLenum adjusted_format = gles2::TextureManager::AdjustTexFormat(
+ feature_info_.get(), internal_format);
+ glTexImage2D(dest_target, level, adjusted_internal_format, width, height, 0,
+ adjusted_format, luma_type, nullptr);
+ DoCopyTexSubImage2DToLUMAComatabilityTexture(
+ decoder, dest_texture, dest_texture_target, dest_target, luma_format,
+ luma_type, level, 0, 0, x, y, width, height, source_framebuffer,
+ source_framebuffer_internal_format);
+}
+
+void CopyTexImageResourceManager::DoCopyTexSubImage2DToLUMAComatabilityTexture(
+ const gles2::GLES2Decoder* decoder,
+ GLuint dest_texture,
+ GLenum dest_texture_target,
+ GLenum dest_target,
+ GLenum luma_format,
+ GLenum luma_type,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLuint source_framebuffer,
+ GLenum source_framebuffer_internal_format) {
+ DCHECK(initialized_);
+
+ // Copy the framebuffer to the first scratch texture
+ // TODO(geofflang): This could be optimized further by detecting if the source
+ // framebuffer is copying from a texture and sample directly from that texture
+ // instead of doing an extra copy
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER, source_framebuffer);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, source_framebuffer_internal_format, x, y,
+ width, height, 0);
+
+ // Set the swizzle of the scratch texture so that the channels sample into the
+ // correct emulated LUMA channels.
+ GLint swizzle[4] = {
+ (luma_format == GL_ALPHA) ? GL_ALPHA : GL_RED,
+ (luma_format == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO,
+ GL_ZERO,
+ };
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+
+ // Make a temporary framebuffer using the second scratch texture to render the
+ // swizzled result to.
+ // TODO(geofflang): Could be optimized more by rendering directly to the
+ // destination texture but this isn't always possible because the destination
+ // may be an incomplete cube map
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ GLenum compatability_format =
+ gles2::TextureManager::AdjustTexFormat(feature_info_.get(), luma_format);
+ glBindTexture(GL_TEXTURE_2D, scratch_textures_[1]);
+ glTexImage2D(GL_TEXTURE_2D, 0, compatability_format, width, height, 0,
+ compatability_format, luma_type, nullptr);
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER, scratch_fbo_);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ scratch_textures_[1], 0);
+
+ // Render to the destination texture, sampling from the scratch texture
+ glUseProgram(blit_program_);
+ glViewport(0, 0, width, height);
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_CULL_FACE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_BLEND);
+ glDisable(GL_DITHER);
+
+ glBindTexture(GL_TEXTURE_2D, scratch_textures_[0]);
+ glBindVertexArrayOES(vao_);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ // Finally, copy the swizzled texture to the destination texture
+ glBindTexture(dest_texture_target, dest_texture);
+ glCopyTexSubImage2D(dest_target, level, xoffset, yoffset, 0, 0, width,
+ height);
+
+ // Restore state
+ decoder->RestoreAllAttributes();
+ decoder->RestoreTextureUnitBindings(0);
+ decoder->RestoreActiveTexture();
+ decoder->RestoreProgramBindings();
+ decoder->RestoreBufferBindings();
+ decoder->RestoreFramebufferBindings();
+ decoder->RestoreGlobalState();
+}
+
+// static
+bool CopyTexImageResourceManager::CopyTexImageRequiresBlit(
+ const gles2::FeatureInfo* feature_info,
+ GLenum dest_texture_format) {
+ if (feature_info->gl_version_info().is_desktop_core_profile) {
+ switch (dest_texture_format) {
+ case GL_LUMINANCE:
+ case GL_ALPHA:
+ case GL_LUMINANCE_ALPHA:
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
new file mode 100644
index 0000000..503862da
--- /dev/null
+++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEX_IMAGE_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEX_IMAGE_H_
+
+#include <array>
+
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "gpu/command_buffer/service/feature_info.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+namespace gles2 {
+
+class GLES2Decoder;
+
+} // namespace gles2.
+
+// This class encapsulates the resources required to implement the
+// glCopyTexImage and glCopyTexSubImage commands. These commands somtimes
+// require a blit.
+class GPU_EXPORT CopyTexImageResourceManager {
+ public:
+ explicit CopyTexImageResourceManager(const gles2::FeatureInfo* feature_info);
+ ~CopyTexImageResourceManager();
+
+ void Initialize(const gles2::GLES2Decoder* decoder);
+ void Destroy();
+
+ void DoCopyTexImage2DToLUMAComatabilityTexture(
+ const gles2::GLES2Decoder* decoder,
+ GLuint dest_texture,
+ GLenum dest_texture_target,
+ GLenum dest_target,
+ GLenum luma_format,
+ GLenum luma_type,
+ GLint level,
+ GLenum internal_format,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLuint source_framebuffer,
+ GLenum source_framebuffer_internal_format);
+
+ void DoCopyTexSubImage2DToLUMAComatabilityTexture(
+ const gles2::GLES2Decoder* decoder,
+ GLuint dest_texture,
+ GLenum dest_texture_target,
+ GLenum dest_target,
+ GLenum luma_format,
+ GLenum luma_type,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLuint source_framebuffer,
+ GLenum source_framebuffer_internal_format);
+
+ static bool CopyTexImageRequiresBlit(const gles2::FeatureInfo* feature_info,
+ GLenum dest_texture_format);
+
+ private:
+ scoped_refptr<const gles2::FeatureInfo> feature_info_;
+
+ bool initialized_ = false;
+
+ GLuint blit_program_ = 0;
+
+ std::array<GLuint, 2> scratch_textures_ = {{0, 0}};
+ GLuint scratch_fbo_ = 0;
+
+ GLuint vao_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(CopyTexImageResourceManager);
+};
+
+} // namespace gpu.
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_COPY_TEX_IMAGE_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 6ec2b0a..d5a7355b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -40,6 +40,7 @@
#include "gpu/command_buffer/service/gl_stream_texture_image.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h"
+#include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
@@ -1973,6 +1974,7 @@
GLuint* source_texture_service_id,
GLenum* source_texture_target);
+ bool InitializeCopyTexImageBlitter(const char* function_name);
bool InitializeCopyTextureCHROMIUM(const char* function_name);
// Generate a member function prototype for each command in an automated and
// typesafe way.
@@ -2155,6 +2157,7 @@
// Log extra info.
bool service_logging_;
+ std::unique_ptr<CopyTexImageResourceManager> copy_tex_image_blit_;
std::unique_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_;
std::unique_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_;
@@ -4276,6 +4279,11 @@
}
ReleaseAllBackTextures();
if (have_context) {
+ if (copy_tex_image_blit_.get()) {
+ copy_tex_image_blit_->Destroy();
+ copy_tex_image_blit_.reset();
+ }
+
if (copy_texture_CHROMIUM_.get()) {
copy_texture_CHROMIUM_->Destroy();
copy_texture_CHROMIUM_.reset();
@@ -4347,6 +4355,7 @@
// state_.current_program object.
state_.current_program = NULL;
+ copy_tex_image_blit_.reset();
copy_texture_CHROMIUM_.reset();
clear_framebuffer_blit_.reset();
@@ -12374,6 +12383,14 @@
framebuffer_state_.clear_state_dirty = true;
}
+ bool requires_luma_blit =
+ CopyTexImageResourceManager::CopyTexImageRequiresBlit(feature_info_.get(),
+ format);
+ if (requires_luma_blit &&
+ !InitializeCopyTexImageBlitter("glCopyTexSubImage2D")) {
+ return;
+ }
+
// Clip to size to source dimensions
GLint copyX = 0;
GLint copyY = 0;
@@ -12389,21 +12406,29 @@
// some part was clipped so clear the rect.
std::unique_ptr<char[]> zero(new char[pixels_size]);
memset(zero.get(), 0, pixels_size);
- glTexImage2D(target, level,
- texture_manager()->AdjustTexInternalFormat(internal_format),
+ glTexImage2D(target, level, TextureManager::AdjustTexInternalFormat(
+ feature_info_.get(), internal_format),
width, height, border, format, type, zero.get());
if (copyHeight > 0 && copyWidth > 0) {
GLint dx = copyX - x;
GLint dy = copyY - y;
GLint destX = dx;
GLint destY = dy;
- glCopyTexSubImage2D(target, level,
- destX, destY, copyX, copyY,
- copyWidth, copyHeight);
+ if (requires_luma_blit) {
+ copy_tex_image_blit_->DoCopyTexSubImage2DToLUMAComatabilityTexture(
+ this, texture->service_id(), texture->target(), target, format,
+ type, level, destX, destY, copyX, copyY, copyWidth, copyHeight,
+ framebuffer_state_.bound_read_framebuffer->service_id(),
+ framebuffer_state_.bound_read_framebuffer
+ ->GetReadBufferInternalFormat());
+ } else {
+ glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY,
+ copyWidth, copyHeight);
+ }
}
} else {
- GLenum final_internal_format =
- texture_manager()->AdjustTexInternalFormat(internal_format);
+ GLenum final_internal_format = TextureManager::AdjustTexInternalFormat(
+ feature_info_.get(), internal_format);
// The service id and target of the texture attached to READ_FRAMEBUFFER.
GLuint source_texture_service_id = 0;
@@ -12413,6 +12438,7 @@
final_internal_format, channels_exist, &source_texture_service_id,
&source_texture_target);
if (use_workaround) {
+ DCHECK(!requires_luma_blit);
GLenum dest_texture_target = target;
GLenum framebuffer_target = features().chromium_framebuffer_multisample
? GL_READ_FRAMEBUFFER_EXT
@@ -12453,8 +12479,17 @@
glDeleteTextures(1, &temp_texture);
} else {
- glCopyTexImage2D(target, level, final_internal_format, copyX, copyY,
- copyWidth, copyHeight, border);
+ if (requires_luma_blit) {
+ copy_tex_image_blit_->DoCopyTexImage2DToLUMAComatabilityTexture(
+ this, texture->service_id(), texture->target(), target, format,
+ type, level, internal_format, copyX, copyY, copyWidth, copyHeight,
+ framebuffer_state_.bound_read_framebuffer->service_id(),
+ framebuffer_state_.bound_read_framebuffer
+ ->GetReadBufferInternalFormat());
+ } else {
+ glCopyTexImage2D(target, level, final_internal_format, copyX, copyY,
+ copyWidth, copyHeight, border);
+ }
}
}
GLenum error = LOCAL_PEEK_GL_ERROR(func_name);
@@ -12554,9 +12589,21 @@
}
if (copyHeight > 0 && copyWidth > 0) {
- glCopyTexSubImage2D(target, level,
- destX, destY, copyX, copyY,
- copyWidth, copyHeight);
+ if (CopyTexImageResourceManager::CopyTexImageRequiresBlit(
+ feature_info_.get(), internal_format)) {
+ if (!InitializeCopyTexImageBlitter("glCopyTexSubImage2D")) {
+ return;
+ }
+ copy_tex_image_blit_->DoCopyTexSubImage2DToLUMAComatabilityTexture(
+ this, texture->service_id(), texture->target(), target,
+ internal_format, type, level, xoffset, yoffset, x, y, width, height,
+ framebuffer_state_.bound_read_framebuffer->service_id(),
+ framebuffer_state_.bound_read_framebuffer
+ ->GetReadBufferInternalFormat());
+ } else {
+ glCopyTexSubImage2D(target, level, destX, destY, copyX, copyY, copyWidth,
+ copyHeight);
+ }
}
// This may be a slow command. Exit command processing to allow for
@@ -14448,11 +14495,12 @@
// Ensure that the glTexImage2D succeeds.
LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(kFunctionName);
glBindTexture(dest_target, dest_texture->service_id());
- glTexImage2D(dest_target, 0,
- texture_manager()->AdjustTexInternalFormat(internal_format),
- source_width, source_height, 0,
- texture_manager()->AdjustTexFormat(internal_format), dest_type,
- NULL);
+ glTexImage2D(
+ dest_target, 0, TextureManager::AdjustTexInternalFormat(
+ feature_info_.get(), internal_format),
+ source_width, source_height, 0,
+ TextureManager::AdjustTexFormat(feature_info_.get(), internal_format),
+ dest_type, NULL);
GLenum error = LOCAL_PEEK_GL_ERROR(kFunctionName);
if (error != GL_NO_ERROR) {
RestoreCurrentTextureBindings(&state_, dest_target);
@@ -14693,6 +14741,19 @@
unpack_premultiply_alpha == GL_TRUE, unpack_unmultiply_alpha == GL_TRUE);
}
+bool GLES2DecoderImpl::InitializeCopyTexImageBlitter(
+ const char* function_name) {
+ if (!copy_tex_image_blit_.get()) {
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name);
+ copy_tex_image_blit_.reset(
+ new CopyTexImageResourceManager(feature_info_.get()));
+ copy_tex_image_blit_->Initialize(this);
+ if (LOCAL_PEEK_GL_ERROR(function_name) != GL_NO_ERROR)
+ return false;
+ }
+ return true;
+}
+
bool GLES2DecoderImpl::InitializeCopyTextureCHROMIUM(
const char* function_name) {
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 4813a0f..f3cc1d1 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -272,6 +272,7 @@
{GL_LUMINANCE_ALPHA, GL_RG, GL_RED, GL_RED, GL_RED, GL_GREEN},
};
+// static
const Texture::CompatibilitySwizzle* GetCompatibilitySwizzle(GLenum format) {
size_t count = arraysize(kSwizzledFormats);
for (size_t i = 0; i < count; ++i) {
@@ -2675,23 +2676,28 @@
// to look it up.
if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
glTexImage3D(args.target, args.level, internal_format, args.width,
- args.height, args.depth, 0, AdjustTexFormat(args.format),
- args.type, args.pixels);
- } else {
- glTexImage2D(args.target, args.level,
- AdjustTexInternalFormat(internal_format), args.width,
- args.height, 0, AdjustTexFormat(args.format), args.type,
+ args.height, args.depth, 0,
+ AdjustTexFormat(feature_info_.get(), args.format), args.type,
args.pixels);
+ } else {
+ glTexImage2D(
+ args.target, args.level,
+ AdjustTexInternalFormat(feature_info_.get(), internal_format),
+ args.width, args.height, 0,
+ AdjustTexFormat(feature_info_.get(), args.format), args.type,
+ args.pixels);
}
} else {
ScopedTextureUploadTimer timer(texture_state);
if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
args.zoffset, args.width, args.height, args.depth,
- AdjustTexFormat(args.format), args.type, args.pixels);
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, args.pixels);
} else {
glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
- args.width, args.height, AdjustTexFormat(args.format),
+ args.width, args.height,
+ AdjustTexFormat(feature_info_.get(), args.format),
args.type, args.pixels);
}
}
@@ -2711,7 +2717,8 @@
if (args.height > 1) {
glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
args.width, args.height - 1,
- AdjustTexFormat(args.format), args.type, args.pixels);
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, args.pixels);
GLint actual_width = state->unpack_row_length > 0 ?
state->unpack_row_length : args.width;
uint32_t size;
@@ -2729,9 +2736,9 @@
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(args.target, args.level, args.xoffset,
- args.yoffset + args.height - 1,
- args.width, 1, AdjustTexFormat(args.format), args.type,
- reinterpret_cast<const void *>(offset));
+ args.yoffset + args.height - 1, args.width, 1,
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, reinterpret_cast<const void*>(offset));
glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
{
uint32_t size;
@@ -2749,7 +2756,8 @@
if (args.depth > 1) {
glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
args.zoffset, args.width, args.height, args.depth - 1,
- AdjustTexFormat(args.format), args.type, args.pixels);
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, args.pixels);
GLint actual_height = state->unpack_image_height > 0 ?
state->unpack_image_height : args.height;
uint32_t size;
@@ -2769,7 +2777,8 @@
if (args.height > 1) {
glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
args.zoffset + args.depth - 1, args.width,
- args.height - 1, 1, AdjustTexFormat(args.format),
+ args.height - 1, 1,
+ AdjustTexFormat(feature_info_.get(), args.format),
args.type, reinterpret_cast<const void*>(offset));
uint32_t size;
uint32_t padding;
@@ -2787,9 +2796,9 @@
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage3D(args.target, args.level, args.xoffset,
args.yoffset + args.height - 1,
- args.zoffset + args.depth - 1,
- args.width, 1, 1, AdjustTexFormat(args.format), args.type,
- reinterpret_cast<const void *>(offset));
+ args.zoffset + args.depth - 1, args.width, 1, 1,
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, reinterpret_cast<const void*>(offset));
glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
{
uint32_t size;
@@ -2815,7 +2824,7 @@
DCHECK_EQ(0, state->unpack_skip_rows);
DCHECK_EQ(0, state->unpack_skip_images);
- GLenum format = AdjustTexFormat(args.format);
+ GLenum format = AdjustTexFormat(feature_info_.get(), args.format);
GLsizei row_bytes = unpack_params.row_length *
GLES2Util::ComputeImageGroupSize(format, args.type);
@@ -2856,8 +2865,11 @@
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_params.row_length);
}
-GLenum TextureManager::AdjustTexInternalFormat(GLenum format) const {
- if (feature_info_->gl_version_info().is_desktop_core_profile) {
+// static
+GLenum TextureManager::AdjustTexInternalFormat(
+ const gles2::FeatureInfo* feature_info,
+ GLenum format) {
+ if (feature_info->gl_version_info().is_desktop_core_profile) {
const Texture::CompatibilitySwizzle* swizzle =
GetCompatibilitySwizzle(format);
if (swizzle)
@@ -2866,16 +2878,18 @@
return format;
}
-GLenum TextureManager::AdjustTexFormat(GLenum format) const {
+// static
+GLenum TextureManager::AdjustTexFormat(const gles2::FeatureInfo* feature_info,
+ GLenum format) {
// TODO(bajones): GLES 3 allows for internal format and format to differ.
// This logic may need to change as a result.
- if (gl::GetGLImplementation() == gl::kGLImplementationDesktopGL) {
+ if (!feature_info->gl_version_info().is_es) {
if (format == GL_SRGB_EXT)
return GL_RGB;
if (format == GL_SRGB_ALPHA_EXT)
return GL_RGBA;
}
- if (feature_info_->gl_version_info().is_desktop_core_profile) {
+ if (feature_info->gl_version_info().is_desktop_core_profile) {
const Texture::CompatibilitySwizzle* swizzle =
GetCompatibilitySwizzle(format);
if (swizzle)
@@ -2934,7 +2948,8 @@
args.format, args.type, args.pixels);
} else {
glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
- AdjustTexFormat(args.format), args.type, args.pixels);
+ AdjustTexFormat(feature_info_.get(), args.format),
+ args.type, args.pixels);
}
}
SetLevelInfo(texture_ref, args.target, args.level, args.internal_format,
@@ -2952,10 +2967,12 @@
args.height, args.depth, args.border, args.format,
args.type, args.pixels);
} else {
- glTexImage2D(args.target, args.level,
- AdjustTexInternalFormat(args.internal_format), args.width,
- args.height, args.border, AdjustTexFormat(args.format),
- args.type, args.pixels);
+ glTexImage2D(
+ args.target, args.level,
+ AdjustTexInternalFormat(feature_info_.get(), args.internal_format),
+ args.width, args.height, args.border,
+ AdjustTexFormat(feature_info_.get(), args.format), args.type,
+ args.pixels);
}
}
GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name);
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index 6eca1fb..50d55956 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -1076,8 +1076,10 @@
uint32_t GetServiceIdGeneration() const;
void IncrementServiceIdGeneration();
- GLenum AdjustTexInternalFormat(GLenum format) const;
- GLenum AdjustTexFormat(GLenum format) const;
+ static GLenum AdjustTexInternalFormat(const gles2::FeatureInfo* feature_info,
+ GLenum format);
+ static GLenum AdjustTexFormat(const gles2::FeatureInfo* feature_info,
+ GLenum format);
private:
friend class Texture;
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 320b4e1..c75c35e 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -60,6 +60,8 @@
'command_buffer/service/gl_utils.h',
'command_buffer/service/gles2_cmd_clear_framebuffer.cc',
'command_buffer/service/gles2_cmd_clear_framebuffer.h',
+ 'command_buffer/service/gles2_cmd_copy_tex_image.cc',
+ 'command_buffer/service/gles2_cmd_copy_tex_image.h',
'command_buffer/service/gles2_cmd_copy_texture_chromium.cc',
'command_buffer/service/gles2_cmd_copy_texture_chromium.h',
'command_buffer/service/gles2_cmd_decoder.cc',