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 |