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); |