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..ce0f1070137a373b9a8fb670fbc25d8f00919d50 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,44 @@ 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"); |
+ source += std::string("#version 150\n"); |
Zhenyao Mo
2016/11/14 20:04:50
This is incorrect. Now we have
1) desktop core pr
qiankun
2016/11/18 01:25:40
I updated the shaders per underlying context. I th
|
} else { |
- source += std::string("\ |
- #define ATTRIBUTE attribute\n\ |
- #define VARYING varying\n"); |
+ source += std::string("#version 300 es\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,45 +133,66 @@ 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 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"); |
+ source += std::string("#version 150\n"); |
} else { |
- 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("#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"); |
+ } |
} |
- source += std::string("\ |
- #define VARYING varying\n\ |
- #define FRAGCOLOR gl_FragColor\n"); |
} |
+ // Preamble for texture precision. |
+ source += std::string(kShaderPrecisionPreamble); |
+ |
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(format)) { |
+ source += std::string("#define TextureType ivec4\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(format)) { |
+ source += std::string("#define TextureType uvec4\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"); |
+ 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"); |
+ } |
+ } |
+ source += std::string( |
+ "out TextureType frag_color;\n" |
+ "#define VARYING in\n" |
+ "#define FRAGCOLOR frag_color\n" |
+ "#define TextureLookup texture\n"); |
+ |
// Preamble for sampler type. |
switch (target) { |
case GL_TEXTURE_2D: |
@@ -189,42 +209,72 @@ 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"); |
+ 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"); |
+ source += std::string( |
+ "if (FRAGCOLOR.a > 0.0)\n" |
+ " FRAGCOLOR.rgb /= FRAGCOLOR.a;\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: |
+ case GL_R16F: |
+ case GL_R32F: |
+ case GL_RG16F: |
+ case GL_RG32F: |
+ case GL_R11F_G11F_B10F: |
+ case GL_RGB9_E5: |
+ case GL_RGB16F: |
+ case GL_RGB32F: |
+ case GL_RGBA16F: |
+ case GL_RGBA32F: |
+ return GL_RGBA; |
+ 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) |
+ if (GL_TRUE != compile_status) { |
DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure."; |
+ char buffer[1024]; |
+ GLsizei length = 0; |
+ glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); |
+ std::string log(buffer, length); |
+ } |
#endif |
} |
@@ -419,21 +469,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 +489,30 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
return; |
} |
+ GLenum adjusted_internal_format = getIntermediateFormat(dest_internal_format); |
+ GLuint adjusted_texture = dest_id; |
+ if (method == DRAW_AND_COPY) { |
+ glGenTextures(1, &adjusted_texture); |
+ glBindTexture(dest_target, adjusted_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, |
+ adjusted_texture, adjusted_internal_format, width, height, flip_y, |
+ premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); |
+ |
+ if (method == DRAW_AND_COPY) { |
+ DoCopyTexImage2D(decoder, dest_target, adjusted_texture, dest_target, |
+ dest_id, dest_internal_format, width, height, |
+ framebuffer_); |
+ } |
} |
void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
@@ -472,7 +535,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,19 +546,12 @@ 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; |
@@ -529,18 +586,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 +609,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, |
@@ -627,7 +689,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
*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); |