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

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

Issue 2479513002: Reland of Extend CopyTextureCHROMIUM to more ES 3.0 texture formats. (Closed)
Patch Set: fix comments from zmo #17 Created 4 years, 1 month 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 e6e3035c9e868ccbd11a5107ad5e919d9d4fca64..538388cb33f745db616e1e4e6737f8b45bdf3f01 100644
--- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
+++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -10,6 +10,7 @@
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/texture_manager.h"
#include "ui/gl/gl_version_info.h"
namespace {
@@ -86,46 +87,52 @@ FragmentShaderId GetFragmentShaderId(bool premultiply_alpha,
return shader_ids[0][SAMPLER_2D];
}
-const char* kShaderPrecisionPreamble = "\
- #ifdef GL_ES\n\
- precision mediump float;\n\
- #define TexCoordPrecision mediump\n\
- #else\n\
- #define TexCoordPrecision\n\
- #endif\n";
+const char* kShaderPrecisionPreamble =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#define TexCoordPrecision mediump\n"
+ "#else\n"
+ "#define TexCoordPrecision\n"
+ "#endif\n";
std::string GetVertexShaderSource(const gl::GLVersionInfo& gl_version_info) {
std::string source;
- // Preamble for core and compatibility mode.
- if (gl_version_info.is_desktop_core_profile) {
- source += std::string("\
- #version 150\n\
- #define ATTRIBUTE in\n\
- #define VARYING out\n");
+ if (gl_version_info.is_es) {
+ if (gl_version_info.is_es3) {
+ source += std::string("#version 300 es\n");
+ source += std::string(
+ "#define ATTRIBUTE in\n"
+ "#define VARYING out\n");
+ } else {
+ source += std::string(
+ "#define ATTRIBUTE attribute\n"
+ "#define VARYING varying\n");
+ }
} else {
- source += std::string("\
- #define ATTRIBUTE attribute\n\
- #define VARYING varying\n");
+ source += std::string("#version 150\n");
+ source += std::string(
+ "#define ATTRIBUTE in\n"
+ "#define VARYING out\n");
}
// Preamble for texture precision.
source += std::string(kShaderPrecisionPreamble);
// Main shader source.
- source += std::string("\
- 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 vec2 a_position;\n\
- VARYING TexCoordPrecision vec2 v_uv;\n\
- void main(void) {\n\
- gl_Position = vec4(0, 0, 0, 1);\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");
+ source += std::string(
+ "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 vec2 a_position;\n"
+ "VARYING TexCoordPrecision vec2 v_uv;\n"
+ "void main(void) {\n"
+ " gl_Position = vec4(0, 0, 0, 1);\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;
}
@@ -134,43 +141,88 @@ std::string GetFragmentShaderSource(const gl::GLVersionInfo& gl_version_info,
bool premultiply_alpha,
bool unpremultiply_alpha,
bool nv_egl_stream_consumer_external,
- GLenum target) {
+ GLenum target,
+ GLenum source_format,
+ GLenum dest_format) {
std::string source;
// Preamble for core and compatibility mode.
- if (gl_version_info.is_desktop_core_profile) {
- source += std::string("\
- #version 150\n\
- out vec4 frag_color;\n\
- #define VARYING in\n\
- #define FRAGCOLOR frag_color\n\
- #define TextureLookup texture\n");
+ if (gl_version_info.is_es) {
+ if (gl_version_info.is_es3) {
+ source += std::string("#version 300 es\n");
+ }
+ if (target == GL_TEXTURE_EXTERNAL_OES) {
+ source += std::string("#extension GL_OES_EGL_image_external : enable\n");
+
+ if (nv_egl_stream_consumer_external) {
+ source += std::string(
+ "#extension GL_NV_EGL_stream_consumer_external : enable\n");
+ }
+ }
} else {
+ source += std::string("#version 150\n");
+ }
+
+ // Preamble for texture precision.
+ source += std::string(kShaderPrecisionPreamble);
+
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(dest_format)) {
+ source += std::string("#define TextureType ivec4\n");
+ source += std::string("#define ZERO 0\n");
+ source += std::string("#define MAX_COLOR 255\n");
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format))
+ source += std::string("#define InnerScaleValue 1\n");
+ else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format))
+ source += std::string("#define InnerScaleValue 1u\n");
+ else
+ source += std::string("#define InnerScaleValue 255.0\n");
+ source += std::string("#define OuterScaleValue 1\n");
+ } else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(dest_format)) {
+ source += std::string("#define TextureType uvec4\n");
+ source += std::string("#define ZERO 0u\n");
+ source += std::string("#define MAX_COLOR 255u\n");
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format))
+ source += std::string("#define InnerScaleValue 1\n");
+ else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format))
+ source += std::string("#define InnerScaleValue 1u\n");
+ else
+ source += std::string("#define InnerScaleValue 255.0\n");
+ source += std::string("#define OuterScaleValue 1u\n");
+ } else {
+ source += std::string("#define TextureType vec4\n");
+ source += std::string("#define ZERO 0.0\n");
+ source += std::string("#define MAX_COLOR 1.0\n");
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format)) {
+ source += std::string("#define InnerScaleValue 1\n");
+ source += std::string("#define OuterScaleValue (1.0 / 255.0)\n");
+ } else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format)) {
+ source += std::string("#define InnerScaleValue 1u\n");
+ source += std::string("#define OuterScaleValue (1.0 / 255.0)\n");
+ } else {
+ source += std::string("#define InnerScaleValue 1.0\n");
+ source += std::string("#define OuterScaleValue 1.0\n");
+ }
+ }
+ if (gl_version_info.is_es2) {
switch (target) {
case GL_TEXTURE_2D:
- source += std::string("#define TextureLookup texture2D\n");
- break;
- case GL_TEXTURE_RECTANGLE_ARB:
- source += std::string("#define TextureLookup texture2DRect\n");
- break;
case GL_TEXTURE_EXTERNAL_OES:
- source +=
- std::string("#extension GL_OES_EGL_image_external : enable\n");
-
- if (nv_egl_stream_consumer_external) {
- source += std::string(
- "#extension GL_NV_EGL_stream_consumer_external : enable\n");
- }
-
source += std::string("#define TextureLookup texture2D\n");
break;
default:
NOTREACHED();
break;
}
- source += std::string("\
- #define VARYING varying\n\
- #define FRAGCOLOR gl_FragColor\n");
+
+ source += std::string(
+ "#define VARYING varying\n"
+ "#define FRAGCOLOR gl_FragColor\n");
+ } else {
+ source += std::string(
+ "#define VARYING in\n"
+ "out TextureType frag_color;\n"
+ "#define FRAGCOLOR frag_color\n"
+ "#define TextureLookup texture\n");
}
// Preamble for sampler type.
@@ -189,42 +241,76 @@ std::string GetFragmentShaderSource(const gl::GLVersionInfo& gl_version_info,
break;
}
- // Preamble for texture precision.
- source += std::string(kShaderPrecisionPreamble);
-
// Main shader source.
- source += std::string("\
- uniform SamplerType u_sampler;\n\
- uniform mat4 u_tex_coord_transform;\n\
- VARYING TexCoordPrecision vec2 v_uv;\n\
- void main(void) {\n\
- TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, 1);\n\
- FRAGCOLOR = TextureLookup(u_sampler, uv.st);\n");
+ source += std::string(
+ "uniform mediump SamplerType u_sampler;\n"
+ "uniform mat4 u_tex_coord_transform;\n"
+ "VARYING TexCoordPrecision vec2 v_uv;\n"
+ "void main(void) {\n"
+ " TexCoordPrecision vec4 uv = u_tex_coord_transform * vec4(v_uv, 0, "
+ "1);\n"
+ " vec4 color = TextureLookup(u_sampler, uv.st);\n"
+ " FRAGCOLOR = TextureType(color * InnerScaleValue) * "
+ "OuterScaleValue;\n");
// Post-processing to premultiply or un-premultiply alpha.
- if (premultiply_alpha) {
- source += std::string(" FRAGCOLOR.rgb *= FRAGCOLOR.a;\n");
- }
- if (unpremultiply_alpha) {
- source += std::string("\
- if (FRAGCOLOR.a > 0.0)\n\
- FRAGCOLOR.rgb /= FRAGCOLOR.a;\n");
+ // Check dest format has alpha channel first.
+ if ((gpu::gles2::GLES2Util::GetChannelsForFormat(dest_format) & 0x0008) !=
+ 0) {
+ if (premultiply_alpha) {
+ source += std::string(" FRAGCOLOR.rgb *= FRAGCOLOR.a;\n");
+ source += std::string(" FRAGCOLOR.rgb /= MAX_COLOR;\n");
+ }
+ if (unpremultiply_alpha) {
+ source += std::string(
+ " if (FRAGCOLOR.a > ZERO) {\n"
+ " FRAGCOLOR.rgb /= FRAGCOLOR.a;\n"
+ " FRAGCOLOR.rgb *= MAX_COLOR;\n"
+ " }\n");
+ }
}
// Main function end.
- source += std::string(" }\n");
+ source += std::string("}\n");
return source;
}
+GLenum getIntermediateFormat(GLenum format) {
+ switch (format) {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE:
+ case GL_ALPHA:
+ return GL_RGBA;
+ case GL_SRGB_EXT:
+ return GL_SRGB_ALPHA_EXT;
+ case GL_RGB16F:
+ return GL_RGBA16F;
+ case GL_RGB9_E5:
+ case GL_RGB32F:
+ return GL_RGBA32F;
+ case GL_SRGB8:
+ return GL_SRGB8_ALPHA8;
+ case GL_RGB8UI:
+ return GL_RGBA8UI;
+ default:
+ return format;
+ }
+}
+
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) << "CopyTextureCHROMIUM: shader compilation failure.";
+ if (GL_TRUE != compile_status) {
+ char buffer[1024];
+ GLsizei length = 0;
+ glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer);
+ std::string log(buffer, length);
+ DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure." << log;
Zhenyao Mo 2016/12/01 01:34:02 nit: '.' -> ': '
qiankun 2016/12/02 16:53:46 Done.
+ }
#endif
}
@@ -419,21 +505,14 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
GLsizei height,
bool flip_y,
bool premultiply_alpha,
- bool unpremultiply_alpha) {
+ bool unpremultiply_alpha,
+ SupportedCopyMethodByFormat method) {
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 && dest_target == GL_TEXTURE_2D &&
- !flip_y && !premultiply_alpha_change &&
- source_format_contain_superset_of_dest_format) {
+ !flip_y && !premultiply_alpha_change && method == DIRECT_COPY) {
DoCopyTexImage2D(decoder,
source_target,
source_id,
@@ -446,10 +525,31 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture(
return;
}
+ GLenum adjusted_internal_format = getIntermediateFormat(dest_internal_format);
+ GLuint intermediate_texture = dest_id;
+ if (method == DRAW_AND_COPY) {
+ glGenTextures(1, &intermediate_texture);
+ glBindTexture(dest_target, intermediate_texture);
+ GLenum format = TextureManager::ExtractFormatFromStorageFormat(
+ adjusted_internal_format);
+ GLenum type =
+ TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format);
+
+ glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0,
+ format, type, nullptr);
+ }
// Use kIdentityMatrix if no transform passed in.
- DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target,
- dest_id, width, height, flip_y, premultiply_alpha,
- unpremultiply_alpha, kIdentityMatrix);
+ DoCopyTextureWithTransform(
+ decoder, source_target, source_id, source_internal_format, dest_target,
+ intermediate_texture, adjusted_internal_format, width, height, flip_y,
+ premultiply_alpha, unpremultiply_alpha, kIdentityMatrix);
+
+ if (method == DRAW_AND_COPY) {
+ DoCopyTexImage2D(decoder, dest_target, intermediate_texture, dest_target,
+ dest_id, dest_internal_format, width, height,
+ framebuffer_);
+ glDeleteTextures(1, &intermediate_texture);
+ }
}
void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
@@ -472,7 +572,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
GLsizei source_height,
bool flip_y,
bool premultiply_alpha,
- bool unpremultiply_alpha) {
+ bool unpremultiply_alpha,
+ SupportedCopyMethodByFormat method) {
bool use_gl_copy_tex_sub_image_2d = true;
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
// glDrawArrays is faster than glCopyTexSubImage2D on IA Mesa driver,
@@ -482,24 +583,42 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture(
use_gl_copy_tex_sub_image_2d = false;
#endif
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 (use_gl_copy_tex_sub_image_2d && source_target == GL_TEXTURE_2D &&
dest_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change &&
- source_format_contain_superset_of_dest_format) {
+ method == DIRECT_COPY) {
DoCopyTexSubImage2D(decoder, source_target, source_id, dest_target, dest_id,
xoffset, yoffset, x, y, width, height, framebuffer_);
return;
}
+ if (method == DRAW_AND_COPY) {
Zhenyao Mo 2016/12/01 01:34:02 This style is different from DoCopyTexture (which
qiankun 2016/12/02 16:53:46 Done.
+ GLenum adjusted_internal_format =
+ getIntermediateFormat(dest_internal_format);
+ GLuint intermediate_texture = 0;
+ glGenTextures(1, &intermediate_texture);
+ glBindTexture(dest_target, intermediate_texture);
+ GLenum format = TextureManager::ExtractFormatFromStorageFormat(
+ adjusted_internal_format);
+ GLenum type =
+ TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format);
+
+ glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0,
+ format, type, nullptr);
+ DoCopySubTextureWithTransform(
+ decoder, source_target, source_id, source_internal_format, dest_target,
+ intermediate_texture, dest_internal_format, 0, 0, x, y, width, height,
+ width, height, source_width, source_height, flip_y, premultiply_alpha,
+ unpremultiply_alpha, kIdentityMatrix);
+ DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture, dest_target,
+ dest_id, xoffset, yoffset, 0, 0, width, height,
+ framebuffer_);
+ glDeleteTextures(1, &intermediate_texture);
+ return;
+ }
+
DoCopySubTextureWithTransform(
decoder, source_target, source_id, source_internal_format, dest_target,
dest_id, dest_internal_format, xoffset, yoffset, x, y, width, height,
@@ -529,18 +648,21 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform(
bool premultiply_alpha,
bool unpremultiply_alpha,
const GLfloat transform_matrix[16]) {
- 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, transform_matrix);
+ DoCopyTextureInternal(
+ decoder, source_target, source_id, source_internal_format, dest_target,
+ dest_id, dest_internal_format, xoffset, yoffset, x, y, width, height,
+ dest_width, dest_height, source_width, source_height, flip_y,
+ premultiply_alpha, unpremultiply_alpha, transform_matrix);
}
void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
const gles2::GLES2Decoder* decoder,
GLenum source_target,
GLuint source_id,
+ GLenum source_format,
GLenum dest_target,
GLuint dest_id,
+ GLenum dest_format,
GLsizei width,
GLsizei height,
bool flip_y,
@@ -549,18 +671,20 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform(
const GLfloat transform_matrix[16]) {
GLsizei dest_width = width;
GLsizei dest_height = height;
- 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);
+ DoCopyTextureInternal(
+ decoder, source_target, source_id, source_format, dest_target, dest_id,
+ dest_format, 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 source_format,
GLenum dest_target,
GLuint dest_id,
+ GLenum dest_format,
GLint xoffset,
GLint yoffset,
GLint x,
@@ -613,8 +737,12 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
ProgramMapKey key(fragment_shader_id);
ProgramInfo* info = &programs_[key];
+ // TODO(qiankun.miao@intel.com): check if it is possible to cache program and
+ // shader for ES3 and WEBGL2 context.
// Create program if necessary.
- if (!info->program) {
+ if (!info->program ||
+ decoder->GetFeatureInfo()->context_type() == CONTEXT_TYPE_OPENGLES3 ||
+ decoder->GetFeatureInfo()->context_type() == CONTEXT_TYPE_WEBGL2) {
info->program = glCreateProgram();
if (!vertex_shader_) {
vertex_shader_ = glCreateShader(GL_VERTEX_SHADER);
@@ -623,11 +751,14 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal(
}
glAttachShader(info->program, vertex_shader_);
GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id];
- if (!*fragment_shader) {
+ if (!*fragment_shader ||
+ decoder->GetFeatureInfo()->context_type() == CONTEXT_TYPE_OPENGLES3 ||
+ decoder->GetFeatureInfo()->context_type() == CONTEXT_TYPE_WEBGL2) {
*fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
std::string source = GetFragmentShaderSource(
gl_version_info, premultiply_alpha, unpremultiply_alpha,
- nv_egl_stream_consumer_external_, source_target);
+ nv_egl_stream_consumer_external_, source_target, source_format,
+ dest_format);
CompileShader(*fragment_shader, source.c_str());
}
glAttachShader(info->program, *fragment_shader);

Powered by Google App Engine
This is Rietveld 408576698