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..ce09a0dcc95f6ae1e4ef1f34ce7184de96d71957 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 { |
@@ -19,113 +20,311 @@ const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, |
0.0f, 0.0f, 1.0f, 0.0f, |
0.0f, 0.0f, 0.0f, 1.0f}; |
-enum FragmentShaderId { |
- FRAGMENT_SHADER_COPY_TEXTURE_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, |
- NUM_FRAGMENT_SHADERS, |
+enum { |
+ SAMPLER_2D, |
+ SAMPLER_RECTANGLE_ARB, |
+ SAMPLER_EXTERNAL_OES, |
+ NUM_SAMPLERS |
}; |
+enum { |
+ S_FORMAT_ALPHA, |
+ S_FORMAT_LUMINANCE, |
+ S_FORMAT_LUMINANCE_ALPHA, |
+ S_FORMAT_RED, |
+ S_FORMAT_RGB, |
+ S_FORMAT_RGBA, |
+ S_FORMAT_RGB8, |
+ S_FORMAT_RGBA8, |
+ S_FORMAT_BGRA_EXT, |
+ S_FORMAT_BGRA8_EXT, |
+ S_FORMAT_RGB_YCBCR_420V_CHROMIUM, |
+ S_FORMAT_RGB_YCBCR_422_CHROMIUM, |
+ S_FORMAT_COMPRESSED, |
+ NUM_S_FORMAT |
+}; |
+ |
+enum { |
+ D_FORMAT_RGB, |
+ D_FORMAT_RGBA, |
+ D_FORMAT_RGB8, |
+ D_FORMAT_RGBA8, |
+ D_FORMAT_BGRA_EXT, |
+ D_FORMAT_BGRA8_EXT, |
+ D_FORMAT_SRGB_EXT, |
+ D_FORMAT_SRGB_ALPHA_EXT, |
+ D_FORMAT_R8, |
+ D_FORMAT_R8UI, |
+ D_FORMAT_RG8, |
+ D_FORMAT_RG8UI, |
+ D_FORMAT_SRGB8, |
+ D_FORMAT_RGB565, |
+ D_FORMAT_RGB8UI, |
+ D_FORMAT_SRGB8_ALPHA8, |
+ D_FORMAT_RGB5_A1, |
+ D_FORMAT_RGBA4, |
+ D_FORMAT_RGBA8UI, |
+ D_FORMAT_RGB9_E5, |
+ D_FORMAT_R16F, |
+ D_FORMAT_R32F, |
+ D_FORMAT_RG16F, |
+ D_FORMAT_RG32F, |
+ D_FORMAT_RGB16F, |
+ D_FORMAT_RGB32F, |
+ D_FORMAT_RGBA16F, |
+ D_FORMAT_RGBA32F, |
+ D_FORMAT_R11F_G11F_B10F, |
+ NUM_D_FORMAT |
+}; |
+ |
+const unsigned kNumVertexShaders = NUM_SAMPLERS; |
+const unsigned kNumFragmentShaders = |
+ 4 * NUM_SAMPLERS * NUM_S_FORMAT * NUM_D_FORMAT; |
+ |
+typedef unsigned ShaderId; |
+ |
+ShaderId GetVertexShaderId(GLenum target) { |
+ ShaderId id = 0; |
+ switch (target) { |
+ case GL_TEXTURE_2D: |
+ id = SAMPLER_2D; |
+ break; |
+ case GL_TEXTURE_RECTANGLE_ARB: |
+ id = SAMPLER_RECTANGLE_ARB; |
+ break; |
+ case GL_TEXTURE_EXTERNAL_OES: |
+ id = SAMPLER_EXTERNAL_OES; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return id; |
+} |
+ |
// Returns the correct fragment shader id to evaluate the copy operation for |
// the premultiply alpha pixel store settings and target. |
-FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, |
+ShaderId GetFragmentShaderId(bool premultiply_alpha, |
bool unpremultiply_alpha, |
- GLenum target) { |
- enum { |
- SAMPLER_2D, |
- SAMPLER_RECTANGLE_ARB, |
- SAMPLER_EXTERNAL_OES, |
- NUM_SAMPLERS |
- }; |
- |
- // bit 0: premultiply alpha |
- // bit 1: unpremultiply alpha |
- static FragmentShaderId shader_ids[][NUM_SAMPLERS] = { |
- { |
- FRAGMENT_SHADER_COPY_TEXTURE_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
- }, |
- { |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, |
- }, |
- { |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, |
- }, |
- { |
- FRAGMENT_SHADER_COPY_TEXTURE_2D, |
- FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
- FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
- }}; |
- |
- unsigned index = (premultiply_alpha ? (1 << 0) : 0) | |
- (unpremultiply_alpha ? (1 << 1) : 0); |
+ GLenum target, |
+ GLenum source_format, |
+ GLenum dest_format) { |
+ unsigned alphaIndex = 0; |
+ unsigned targetIndex = 0; |
+ unsigned sourceFormatIndex = 0; |
+ unsigned destFormatIndex = 0; |
+ |
+ alphaIndex = (premultiply_alpha ? (1 << 0) : 0) | |
+ (unpremultiply_alpha ? (1 << 1) : 0); |
switch (target) { |
case GL_TEXTURE_2D: |
- return shader_ids[index][SAMPLER_2D]; |
+ targetIndex = SAMPLER_2D; |
+ break; |
case GL_TEXTURE_RECTANGLE_ARB: |
- return shader_ids[index][SAMPLER_RECTANGLE_ARB]; |
+ targetIndex = SAMPLER_RECTANGLE_ARB; |
+ break; |
case GL_TEXTURE_EXTERNAL_OES: |
- return shader_ids[index][SAMPLER_EXTERNAL_OES]; |
+ targetIndex = SAMPLER_EXTERNAL_OES; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ switch (source_format) { |
+ case GL_ALPHA: |
+ sourceFormatIndex = S_FORMAT_ALPHA; |
+ break; |
+ case GL_LUMINANCE: |
+ sourceFormatIndex = S_FORMAT_LUMINANCE; |
+ break; |
+ case GL_LUMINANCE_ALPHA: |
+ sourceFormatIndex = S_FORMAT_LUMINANCE_ALPHA; |
+ break; |
+ case GL_RED: |
+ sourceFormatIndex = S_FORMAT_RED; |
+ break; |
+ case GL_RGB: |
+ sourceFormatIndex = S_FORMAT_RGB; |
+ break; |
+ case GL_RGBA: |
+ sourceFormatIndex = S_FORMAT_RGBA; |
+ break; |
+ case GL_RGB8: |
+ sourceFormatIndex = S_FORMAT_RGB8; |
+ break; |
+ case GL_RGBA8: |
+ sourceFormatIndex = S_FORMAT_RGBA8; |
+ break; |
+ case GL_BGRA_EXT: |
+ sourceFormatIndex = S_FORMAT_BGRA_EXT; |
+ break; |
+ case GL_BGRA8_EXT: |
+ sourceFormatIndex = S_FORMAT_BGRA8_EXT; |
+ break; |
+ case GL_RGB_YCBCR_420V_CHROMIUM: |
+ sourceFormatIndex = S_FORMAT_RGB_YCBCR_420V_CHROMIUM; |
+ break; |
+ case GL_RGB_YCBCR_422_CHROMIUM: |
+ sourceFormatIndex = S_FORMAT_RGB_YCBCR_422_CHROMIUM; |
+ break; |
+ case GL_ATC_RGB_AMD: |
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: |
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
+ case GL_ETC1_RGB8_OES: |
+ sourceFormatIndex = S_FORMAT_COMPRESSED; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ switch (dest_format) { |
+ case GL_RGB: |
+ destFormatIndex = D_FORMAT_RGB; |
+ break; |
+ case GL_RGBA: |
+ destFormatIndex = D_FORMAT_RGBA; |
+ break; |
+ case GL_RGB8: |
+ destFormatIndex = D_FORMAT_RGB8; |
+ break; |
+ case GL_RGBA8: |
+ destFormatIndex = D_FORMAT_RGBA8; |
+ break; |
+ case GL_BGRA_EXT: |
+ destFormatIndex = D_FORMAT_BGRA_EXT; |
+ break; |
+ case GL_BGRA8_EXT: |
+ destFormatIndex = D_FORMAT_BGRA8_EXT; |
+ break; |
+ case GL_SRGB_EXT: |
+ destFormatIndex = D_FORMAT_SRGB_EXT; |
+ break; |
+ case GL_SRGB_ALPHA_EXT: |
+ destFormatIndex = D_FORMAT_SRGB_ALPHA_EXT; |
+ break; |
+ case GL_R8: |
+ destFormatIndex = D_FORMAT_R8; |
+ break; |
+ case GL_R8UI: |
+ destFormatIndex = D_FORMAT_R8UI; |
+ break; |
+ case GL_RG8: |
+ destFormatIndex = D_FORMAT_RG8; |
+ break; |
+ case GL_RG8UI: |
+ destFormatIndex = D_FORMAT_RG8UI; |
+ break; |
+ case GL_SRGB8: |
+ destFormatIndex = D_FORMAT_SRGB8; |
+ break; |
+ case GL_RGB565: |
+ destFormatIndex = D_FORMAT_RGB565; |
+ break; |
+ case GL_RGB8UI: |
+ destFormatIndex = D_FORMAT_RGB8UI; |
+ break; |
+ case GL_SRGB8_ALPHA8: |
+ destFormatIndex = D_FORMAT_SRGB8_ALPHA8; |
+ break; |
+ case GL_RGB5_A1: |
+ destFormatIndex = D_FORMAT_RGB5_A1; |
+ break; |
+ case GL_RGBA4: |
+ destFormatIndex = D_FORMAT_RGBA4; |
+ break; |
+ case GL_RGBA8UI: |
+ destFormatIndex = D_FORMAT_RGBA8UI; |
+ break; |
+ case GL_RGB9_E5: |
+ destFormatIndex = D_FORMAT_RGB9_E5; |
+ break; |
+ case GL_R16F: |
+ destFormatIndex = D_FORMAT_R16F; |
+ break; |
+ case GL_R32F: |
+ destFormatIndex = D_FORMAT_R32F; |
+ break; |
+ case GL_RG16F: |
+ destFormatIndex = D_FORMAT_RG16F; |
+ break; |
+ case GL_RG32F: |
+ destFormatIndex = D_FORMAT_RG32F; |
+ break; |
+ case GL_RGB16F: |
+ destFormatIndex = D_FORMAT_RGB16F; |
+ break; |
+ case GL_RGB32F: |
+ destFormatIndex = D_FORMAT_RGB32F; |
+ break; |
+ case GL_RGBA16F: |
+ destFormatIndex = D_FORMAT_RGBA16F; |
+ break; |
+ case GL_RGBA32F: |
+ destFormatIndex = D_FORMAT_RGBA32F; |
+ break; |
+ case GL_R11F_G11F_B10F: |
+ destFormatIndex = D_FORMAT_R11F_G11F_B10F; |
+ break; |
default: |
+ NOTREACHED(); |
break; |
} |
- NOTREACHED(); |
- return shader_ids[0][SAMPLER_2D]; |
+ return alphaIndex + targetIndex * 4 + sourceFormatIndex * 4 * NUM_SAMPLERS + |
+ destFormatIndex * 4 * NUM_SAMPLERS * NUM_S_FORMAT; |
} |
-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 GetVertexShaderSource(const gl::GLVersionInfo& gl_version_info, |
+ GLenum target) { |
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 || gl_version_info.IsLowerThanGL(3, 2)) { |
+ if (gl_version_info.is_es3 && target != GL_TEXTURE_EXTERNAL_OES) { |
+ source += "#version 300 es\n"; |
+ source += |
+ "#define ATTRIBUTE in\n" |
+ "#define VARYING out\n"; |
+ } else { |
+ source += |
+ "#define ATTRIBUTE attribute\n" |
+ "#define VARYING varying\n"; |
+ } |
} else { |
- source += std::string("\ |
- #define ATTRIBUTE attribute\n\ |
- #define VARYING varying\n"); |
+ source += "#version 150\n"; |
+ source += |
+ "#define ATTRIBUTE in\n" |
+ "#define VARYING out\n"; |
} |
// Preamble for texture precision. |
- source += std::string(kShaderPrecisionPreamble); |
+ source += 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 += |
+ "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 =\n" |
+ " 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,97 +333,175 @@ 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 || gl_version_info.IsLowerThanGL(3, 2)) { |
+ if (gl_version_info.is_es3 && target != GL_TEXTURE_EXTERNAL_OES) { |
+ source += "#version 300 es\n"; |
+ } |
+ if (target == GL_TEXTURE_EXTERNAL_OES) { |
+ source += "#extension GL_OES_EGL_image_external : enable\n"; |
+ |
+ if (nv_egl_stream_consumer_external) { |
+ source += "#extension GL_NV_EGL_stream_consumer_external : enable\n"; |
+ } |
+ } |
+ } else { |
+ source += "#version 150\n"; |
+ } |
+ |
+ // Preamble for texture precision. |
+ source += kShaderPrecisionPreamble; |
+ |
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(dest_format)) { |
+ source += "#define TextureType ivec4\n"; |
+ source += "#define ZERO 0\n"; |
+ source += "#define MAX_COLOR 255\n"; |
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format)) |
+ source += "#define InnerScaleValue 1\n"; |
+ else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format)) |
+ source += "#define InnerScaleValue 1u\n"; |
+ else |
+ source += "#define InnerScaleValue 255.0\n"; |
+ source += "#define OuterScaleValue 1\n"; |
+ } else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(dest_format)) { |
+ source += "#define TextureType uvec4\n"; |
+ source += "#define ZERO 0u\n"; |
+ source += "#define MAX_COLOR 255u\n"; |
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format)) |
+ source += "#define InnerScaleValue 1\n"; |
+ else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format)) |
+ source += "#define InnerScaleValue 1u\n"; |
+ else |
+ source += "#define InnerScaleValue 255.0\n"; |
+ source += "#define OuterScaleValue 1u\n"; |
} else { |
+ source += "#define TextureType vec4\n"; |
+ source += "#define ZERO 0.0\n"; |
+ source += "#define MAX_COLOR 1.0\n"; |
+ if (gpu::gles2::GLES2Util::IsSignedIntegerFormat(source_format)) { |
+ source += "#define InnerScaleValue 1\n"; |
+ source += "#define OuterScaleValue (1.0 / 255.0)\n"; |
+ } else if (gpu::gles2::GLES2Util::IsUnsignedIntegerFormat(source_format)) { |
+ source += "#define InnerScaleValue 1u\n"; |
+ source += "#define OuterScaleValue (1.0 / 255.0)\n"; |
+ } else { |
+ source += "#define InnerScaleValue 1.0\n"; |
+ source += "#define OuterScaleValue 1.0\n"; |
+ } |
+ } |
+ if (gl_version_info.is_es2 || gl_version_info.IsLowerThanGL(3, 2) || |
+ target == GL_TEXTURE_EXTERNAL_OES) { |
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"); |
+ source += "#define TextureLookup texture2D\n"; |
break; |
default: |
NOTREACHED(); |
break; |
} |
- source += std::string("\ |
- #define VARYING varying\n\ |
- #define FRAGCOLOR gl_FragColor\n"); |
+ |
+ source += |
+ "#define VARYING varying\n" |
+ "#define FRAGCOLOR gl_FragColor\n"; |
+ } else { |
+ source += |
+ "#define VARYING in\n" |
+ "out TextureType frag_color;\n" |
+ "#define FRAGCOLOR frag_color\n" |
+ "#define TextureLookup texture\n"; |
} |
// Preamble for sampler type. |
switch (target) { |
case GL_TEXTURE_2D: |
- source += std::string("#define SamplerType sampler2D\n"); |
+ source += "#define SamplerType sampler2D\n"; |
break; |
case GL_TEXTURE_RECTANGLE_ARB: |
- source += std::string("#define SamplerType sampler2DRect\n"); |
+ source += "#define SamplerType sampler2DRect\n"; |
break; |
case GL_TEXTURE_EXTERNAL_OES: |
- source += std::string("#define SamplerType samplerExternalOES\n"); |
+ source += "#define SamplerType samplerExternalOES\n"; |
break; |
default: |
NOTREACHED(); |
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 += |
+ "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 =\n" |
+ " 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 += " FRAGCOLOR.rgb *= FRAGCOLOR.a;\n"; |
+ source += " FRAGCOLOR.rgb /= MAX_COLOR;\n"; |
+ } |
+ if (unpremultiply_alpha) { |
+ source += |
+ " if (FRAGCOLOR.a > ZERO) {\n" |
+ " FRAGCOLOR.rgb /= FRAGCOLOR.a;\n" |
+ " FRAGCOLOR.rgb *= MAX_COLOR;\n" |
+ " }\n"; |
+ } |
} |
// Main function end. |
- source += std::string(" }\n"); |
+ source += "}\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 |
+#if DCHECK_IS_ON() |
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; |
+ } |
#endif |
} |
@@ -327,8 +604,8 @@ namespace gles2 { |
CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
: initialized_(false), |
nv_egl_stream_consumer_external_(false), |
- vertex_shader_(0u), |
- fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), |
+ vertex_shaders_(kNumVertexShaders, 0u), |
+ fragment_shaders_(kNumFragmentShaders, 0u), |
vertex_array_object_id_(0u), |
buffer_id_(0u), |
framebuffer_(0u) {} |
@@ -393,7 +670,8 @@ void CopyTextureCHROMIUMResourceManager::Destroy() { |
glDeleteFramebuffersEXT(1, &framebuffer_); |
framebuffer_ = 0; |
- DeleteShader(vertex_shader_); |
+ std::for_each( |
+ vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); |
std::for_each( |
fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); |
@@ -419,21 +697,14 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
GLsizei height, |
bool flip_y, |
bool premultiply_alpha, |
- bool unpremultiply_alpha) { |
+ bool unpremultiply_alpha, |
+ CopyTextureMethod 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 +717,35 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
return; |
} |
+ GLuint dest_texture = dest_id; |
+ GLuint intermediate_texture = 0; |
+ if (method == DRAW_AND_COPY) { |
+ GLenum adjusted_internal_format = |
+ getIntermediateFormat(dest_internal_format); |
+ 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); |
+ dest_texture = intermediate_texture; |
+ dest_internal_format = adjusted_internal_format; |
+ } |
// 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, |
+ dest_texture, dest_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 +768,8 @@ void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
GLsizei source_height, |
bool flip_y, |
bool premultiply_alpha, |
- bool unpremultiply_alpha) { |
+ bool unpremultiply_alpha, |
+ CopyTextureMethod 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,29 +779,53 @@ 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; |
} |
+ GLint dest_xoffset = xoffset; |
+ GLint dest_yoffset = yoffset; |
+ GLuint dest_texture = dest_id; |
+ GLuint intermediate_texture = 0; |
+ if (method == DRAW_AND_COPY) { |
+ GLenum adjusted_internal_format = |
+ getIntermediateFormat(dest_internal_format); |
+ 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); |
+ dest_texture = intermediate_texture; |
+ dest_internal_format = adjusted_internal_format; |
+ dest_xoffset = 0; |
+ dest_yoffset = 0; |
+ dest_width = width; |
+ dest_height = height; |
+ } |
+ |
DoCopySubTextureWithTransform( |
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, kIdentityMatrix); |
+ dest_texture, dest_internal_format, dest_xoffset, dest_yoffset, x, y, |
+ width, height, dest_width, dest_height, source_width, source_height, |
+ flip_y, premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); |
+ |
+ if (method == DRAW_AND_COPY) { |
+ DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture, dest_target, |
+ dest_id, xoffset, yoffset, 0, 0, width, height, |
+ framebuffer_); |
+ glDeleteTextures(1, &intermediate_texture); |
+ } |
} |
void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform( |
@@ -529,18 +850,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 +873,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, |
@@ -607,8 +933,11 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); |
} |
- FragmentShaderId fragment_shader_id = GetFragmentShaderId( |
- premultiply_alpha, unpremultiply_alpha, source_target); |
+ ShaderId vertex_shader_id = GetVertexShaderId(source_target); |
+ DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); |
+ ShaderId fragment_shader_id = GetFragmentShaderId( |
+ premultiply_alpha, unpremultiply_alpha, source_target, |
+ source_format, dest_format); |
DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); |
ProgramMapKey key(fragment_shader_id); |
@@ -616,18 +945,21 @@ void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
// Create program if necessary. |
if (!info->program) { |
info->program = glCreateProgram(); |
- if (!vertex_shader_) { |
- vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); |
- std::string source = GetVertexShaderSource(gl_version_info); |
- CompileShader(vertex_shader_, source.c_str()); |
+ GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; |
+ if (!*vertex_shader) { |
+ *vertex_shader = glCreateShader(GL_VERTEX_SHADER); |
+ std::string source = |
+ GetVertexShaderSource(gl_version_info, source_target); |
+ CompileShader(*vertex_shader, source.c_str()); |
} |
- glAttachShader(info->program, vertex_shader_); |
+ glAttachShader(info->program, *vertex_shader); |
GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; |
if (!*fragment_shader) { |
*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); |