Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_srgb_converter.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc b/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc |
| index ffbaf3059e5384432e264139e5a5b321788246b6..53d68225e098bb33913766509c6fccacdcadcc60 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc |
| @@ -322,5 +322,265 @@ void SRGBConverter::Blit( |
| decoder->RestoreGlobalState(); |
| } |
| +void SRGBConverter::InitializeSRGBEncoder(const gles2::GLES2Decoder* decoder) { |
| + if (srgb_encoder_initialized_) { |
| + return; |
| + } |
| + |
| + GLuint srgb_encoder_program_ = 0; |
| + |
| + std::array<GLuint, 1> srgb_encoder_textures_ = {{0}}; |
| + GLuint srgb_encoder_fbo_ = 0; |
| + GLuint srgb_encoder_vao_ = 0; |
| + |
| + srgb_encoder_program_ = glCreateProgram(); |
| + |
| + 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" |
| + " vec2 xy = vec2((quad_positions[gl_VertexID] * 2.0) - 1.0);\n" |
| + " gl_Position = vec4(xy, 0.0, 1.0);\n" |
| + " v_texcoord = quad_positions[gl_VertexID];\n" |
| + "}\n"; |
| + |
| + // Compile the vertex shader |
| + GLuint vs = glCreateShader(GL_VERTEX_SHADER); |
| + CompileShader(vs, vs_source); |
| + glAttachShader(srgb_encoder_program_, vs); |
| + glDeleteShader(vs); |
| + |
| + // Compile the fragment shader |
| + |
| + // Sampling texels from a srgb texture to a linear image, it will convert |
| + // the srgb color space to linear color space automatically as a part of |
| + // filtering. See the section <sRGB Texture Color Conversion> in GLES and |
| + // OpenGL spec. So in decoder, we don't need to decode again. |
| + // However, sampling texels from a linear texture to a srgb image, it will |
| + // not convert linear to srgb automatically. Shader should always operates |
| + // in linear space. So in encoder, we need to encode explicitly in 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" |
| + "float encode(float color)\n" |
| + "{\n" |
| + " float encoded_color;\n" |
| + " if (color <= 0.0) {\n" |
| + " return 0.0;\n" |
| + " } else if (color < 0.0031308) {\n" |
| + " return color * 12.92;\n" |
| + " } else if (color < 1) {\n" |
| + " return pow(color, 0.41666) * 1.055 - 0.055;\n" |
| + " } else {\n" |
| + " return 1.0;\n" |
| + " }\n" |
| + "}\n" |
| + "\n" |
| + "void main()\n" |
| + "{\n" |
| + " vec4 c = texture(u_source_texture, v_texcoord);\n" |
| + " output_color = vec4(encode(c.r), encode(c.g), encode(c.b), c.a);\n" |
| + "}\n"; |
| + /* 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" |
| + " vec4 c = texture(u_source_texture, v_texcoord);\n" |
| + " output_color = c;\n" |
| + "}\n";*/ |
| + |
| + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); |
| + CompileShader(fs, fs_source); |
| + glAttachShader(srgb_encoder_program_, fs); |
| + glDeleteShader(fs); |
| + |
| + glLinkProgram(srgb_encoder_program_); |
| +#ifndef NDEBUG |
| + GLint linked = 0; |
| + glGetProgramiv(srgb_encoder_program_, GL_LINK_STATUS, &linked); |
| + if (!linked) { |
| + DLOG(ERROR) << "SRGB Encoder for BlitFramebuffer: program link failure."; |
| + } |
| +#endif |
| + |
| + GLuint texture_uniform = |
| + glGetUniformLocation(srgb_encoder_program_, "u_source_texture"); |
| + glUseProgram(srgb_encoder_program_); |
| + glUniform1i(texture_uniform, 0); |
| + |
| + glGenTextures(srgb_encoder_textures_.size(), srgb_encoder_textures_.data()); |
| + glActiveTexture(GL_TEXTURE0); |
| + for (auto srgb_encoder_texture : srgb_encoder_textures_) { |
| + glBindTexture(GL_TEXTURE_2D, srgb_encoder_texture); |
| + |
| + // Use linear, non-mipmapped sampling with the srgb encoder texture |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + } |
| + |
| + glGenFramebuffersEXT(1, &srgb_encoder_fbo_); |
| + glGenVertexArraysOES(1, &srgb_encoder_vao_); |
| + |
| + decoder->RestoreTextureUnitBindings(0); |
| + decoder->RestoreActiveTexture(); |
| + decoder->RestoreProgramBindings(); |
| + |
| + srgb_encoder_initialized_ = true; |
| +} |
|
yunchao
2016/09/19 15:25:48
Please remove this function above, Yizhou.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| +void SRGBConverter::SRGBGenerateMipmap(const gles2::GLES2Decoder* decoder, |
| + Texture* tex, |
| + GLenum target) { |
| + DCHECK(srgb_converter_initialized_); |
| + |
| + GLsizei width; |
| + GLsizei height; |
| + GLsizei depth; |
| + GLenum type = 0; |
| + GLenum internal_format = 0; |
| + GLsizei base_level = tex->base_level(); |
| + tex->GetLevelSize(target, base_level, &width, &height, &depth); |
| + tex->GetLevelType(target, 0, &type, &internal_format); |
| + const GLint mipmap_level = |
| + TextureManager::ComputeMipMapCount(target, width, height, depth); |
| + |
| + // copy tex to srgb_decoder_textures_[0] with srgb format |
| + glBindTexture(target, tex->service_id()); |
| + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); |
| + glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| + GL_TEXTURE_2D, tex->service_id(), 0); |
| + |
| + GLenum error = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER); |
| + error = glGetError(); |
|
yunchao
2016/09/19 15:25:48
please remove the debugging code.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[0]); |
| + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_SRGB, |
| + GL_UNSIGNED_BYTE, nullptr); |
|
yunchao
2016/09/19 15:25:48
This is not necessary, copyTexImage2D will allocat
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glCopyTexImage2D(GL_TEXTURE_2D, 0, internal_format, 0, 0, width, height, 0); |
| + error = glGetError(); |
| + unsigned char bytes3[width * height * 4]; |
| + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes3); |
|
yunchao
2016/09/19 15:25:48
please remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + // bind srgb_decoder_textures_[1] to draw framebuffer |
| + glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); |
| + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, |
| + GL_UNSIGNED_BYTE, nullptr); |
| + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, srgb_decoder_fbo_); |
| + glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| + GL_TEXTURE_2D, srgb_converter_textures_[1], 0); |
| + |
| + error = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER); |
| + error = glGetError(); |
| + unsigned char bytes2[width * height * 4]; |
| + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes2); |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + // bind texture with srgb format and render with srgb_decoder_program_ |
| + glUseProgram(srgb_converter_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); |
| + glEnable(GL_BLEND); |
|
yunchao
2016/09/19 15:25:48
glDisable blend
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glDisable(GL_DITHER); |
| + |
| + glBindVertexArrayOES(srgb_converter_vao_); |
| + glActiveTexture(GL_TEXTURE0); |
| + glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[0]); |
| + |
| + error = glGetError(); |
|
yunchao
2016/09/19 15:25:48
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + glDrawArrays(GL_TRIANGLES, 0, 6); |
| + |
| + error = glGetError(); |
| + unsigned char bytes1[width * height * 4]; |
| + glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); |
| + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes1); |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + // generateMipmap for tex and srgb_decoder_textures_[1] |
| + glBindTexture(GL_TEXTURE_2D, tex->service_id()); |
| + glGenerateMipmapEXT(GL_TEXTURE_2D); |
| + glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); |
| + glGenerateMipmapEXT(GL_TEXTURE_2D); |
| + |
| + error = glGetError(); |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + // bind tex with rgba format and render with srgb_encoder_program_ |
| + |
| + glClearColor(0, 0, 0, 255); |
|
yunchao
2016/09/19 15:25:47
It is not necessary to set clear color.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glBindTexture(GL_TEXTURE_2D, tex->service_id()); |
| + glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); |
| + |
| + //InitializeSRGBEncoder(decoder); |
| + //glUseProgram(srgb_encoder_program_); |
| + |
| + /*glDeleteProgram(srgb_converter_program_); |
| + srgb_converter_program_ = 0; |
| + srgb_converter_initialized_ = false; |
| + InitializeSRGBConverterProgram(); |
| + */ |
|
yunchao
2016/09/19 15:25:47
remove debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glUseProgram(srgb_converter_program_); |
| + |
| + glBindVertexArrayOES(srgb_converter_vao_); |
|
yunchao
2016/09/19 15:25:48
These two lines are not necessary, you have called
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + for (GLint level = base_level; level < mipmap_level; level++) { |
| + glBindTexture(GL_TEXTURE_2D, tex->service_id()); |
|
yunchao
2016/09/19 15:25:47
This is not necessary.
yizhou.jiang
2016/09/20 07:00:26
Done.
|
| + glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); |
|
yunchao
2016/09/19 15:25:48
move this outside the for loop.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, |
| + GL_TEXTURE_2D, tex->service_id(), level); |
| + |
| + error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); |
| + error = glGetError(); |
| + unsigned char bytes2[width * height * 4]; |
| + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes2); |
|
yunchao
2016/09/19 15:25:48
remove debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + glActiveTexture(GL_TEXTURE0); |
|
yunchao
2016/09/19 15:25:48
This is not necessary.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); |
|
yunchao
2016/09/19 15:25:48
move these two lines outside the for loop.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + glViewport(0, 0, width, height); |
| + glDrawArrays(GL_TRIANGLES, 0, 6); |
| + |
| + error = glGetError(); |
| + unsigned char bytes[width * height * 4]; |
| + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes); |
|
yunchao
2016/09/19 15:25:48
remove the debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
|
| + |
| + width /= 2; |
| + height /= 2; |
| + } |
| + |
| + // Restore state |
| + decoder->RestoreAllAttributes(); |
| + decoder->RestoreTextureUnitBindings(0); |
| + decoder->RestoreActiveTexture(); |
| + decoder->RestoreProgramBindings(); |
| + decoder->RestoreBufferBindings(); |
| + decoder->RestoreFramebufferBindings(); |
| + decoder->RestoreGlobalState(); |
| +} |
| + |
| } // namespace gles2. |
| } // namespace gpu |