Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| index b1039c98a9deef97378f9c15553905196c95305a..74f2736ec184825ed183475738022ac254c16c8f 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -44,6 +44,7 @@ |
| #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" |
| #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" |
| +#include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h" |
| #include "gpu/command_buffer/service/gles2_cmd_validation.h" |
| #include "gpu/command_buffer/service/gpu_preferences.h" |
| #include "gpu/command_buffer/service/gpu_state_tracer.h" |
| @@ -884,10 +885,14 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| // or regular back buffer). |
| gfx::Size GetBoundReadFramebufferSize(); |
| - // Get the service side ID for the bound read frame buffer. |
| + // Get the service side ID for the bound read framebuffer. |
| // If it's back buffer, 0 is returned. |
| GLuint GetBoundReadFramebufferServiceId(); |
| + // Get the service side ID for the bound draw framebuffer. |
| + // If it's back buffer, 0 is returned. |
| + GLuint GetBoundDrawFramebufferServiceId(); |
| + |
| // Get the format/type of the currently bound frame buffer (either FBO or |
| // regular back buffer). |
| // If the color image is a renderbuffer, returns 0 for type. |
| @@ -2131,6 +2136,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| bool InitializeCopyTexImageBlitter(const char* function_name); |
| bool InitializeCopyTextureCHROMIUM(const char* function_name); |
| + bool InitializeSRGBDecoder(const char* function_name); |
| + bool InitializeSRGBEncoder(const char* function_name); |
| // Generate a member function prototype for each command in an automated and |
| // typesafe way. |
| #define GLES2_CMD_OP(name) \ |
| @@ -2322,6 +2329,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| apply_framebuffer_attachment_cmaa_intel_; |
| std::unique_ptr<CopyTexImageResourceManager> copy_tex_image_blit_; |
| std::unique_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; |
| + std::unique_ptr<SRGBConverter> srgb_converter_; |
| std::unique_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_; |
| // Cached values of the currently assigned viewport dimensions. |
| @@ -4294,14 +4302,6 @@ bool GLES2DecoderImpl::CheckBoundFramebufferValid(const char* func_name) { |
| Framebuffer* read_framebuffer = GetFramebufferInfoForTarget(target); |
| valid = valid && CheckFramebufferValid( |
| read_framebuffer, target, GL_INVALID_FRAMEBUFFER_OPERATION, func_name); |
| - |
| - if (valid && feature_info_->feature_flags().desktop_srgb_support) { |
| - bool enable_framebuffer_srgb = |
| - (draw_framebuffer && draw_framebuffer->HasSRGBAttachments()) || |
| - (read_framebuffer && read_framebuffer->HasSRGBAttachments()); |
| - state_.EnableDisableFramebufferSRGB(enable_framebuffer_srgb); |
| - } |
| - |
| return valid; |
| } |
| @@ -4367,6 +4367,21 @@ GLuint GLES2DecoderImpl::GetBoundReadFramebufferServiceId() { |
| return 0; |
| } |
| +GLuint GLES2DecoderImpl::GetBoundDrawFramebufferServiceId() { |
| + Framebuffer* framebuffer = |
| + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); |
| + if (framebuffer) { |
| + return framebuffer->service_id(); |
| + } |
| + if (offscreen_target_frame_buffer_.get()) { |
| + return offscreen_target_frame_buffer_->id(); |
| + } |
| + if (surface_.get()) { |
| + return surface_->GetBackingFramebufferObject(); |
| + } |
| + return 0; |
| +} |
| + |
| GLenum GLES2DecoderImpl::GetBoundReadFramebufferTextureType() { |
| Framebuffer* framebuffer = |
| GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); |
| @@ -4603,6 +4618,11 @@ void GLES2DecoderImpl::Destroy(bool have_context) { |
| copy_texture_CHROMIUM_.reset(); |
| } |
| + if (srgb_converter_.get()) { |
| + srgb_converter_->Destroy(); |
| + srgb_converter_.reset(); |
| + } |
| + |
| clear_framebuffer_blit_.reset(); |
| if (state_.current_program.get()) { |
| @@ -4695,6 +4715,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { |
| apply_framebuffer_attachment_cmaa_intel_.reset(); |
| copy_tex_image_blit_.reset(); |
| copy_texture_CHROMIUM_.reset(); |
| + srgb_converter_.reset(); |
| clear_framebuffer_blit_.reset(); |
| if (query_manager_.get()) { |
| @@ -7601,12 +7622,17 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( |
| return; |
| } |
| - GLenum src_format = GetBoundReadFramebufferInternalFormat(); |
| + GLenum src_internal_format = GetBoundReadFramebufferInternalFormat(); |
| GLenum src_type = GetBoundReadFramebufferTextureType(); |
| + bool read_buffer_has_srgb = |
| + GetColorEncodingFromInternalFormat(src_internal_format) == GL_SRGB; |
| + bool draw_buffers_has_srgb = false; |
| if ((mask & GL_COLOR_BUFFER_BIT) != 0) { |
| - bool is_src_signed_int = GLES2Util::IsSignedIntegerFormat(src_format); |
| - bool is_src_unsigned_int = GLES2Util::IsUnsignedIntegerFormat(src_format); |
| + bool is_src_signed_int = |
| + GLES2Util::IsSignedIntegerFormat(src_internal_format); |
| + bool is_src_unsigned_int = |
| + GLES2Util::IsUnsignedIntegerFormat(src_internal_format); |
| DCHECK(!is_src_signed_int || !is_src_unsigned_int); |
| if ((is_src_signed_int || is_src_unsigned_int) && filter == GL_LINEAR) { |
| @@ -7616,13 +7642,15 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( |
| } |
| GLenum src_sized_format = |
| - GLES2Util::ConvertToSizedFormat(src_format, src_type); |
| + GLES2Util::ConvertToSizedFormat(src_internal_format, src_type); |
| for (uint32_t ii = 0; ii < group_->max_draw_buffers(); ++ii) { |
| GLenum dst_format = GetBoundColorDrawBufferInternalFormat( |
| static_cast<GLint>(ii)); |
| GLenum dst_type = GetBoundColorDrawBufferType(static_cast<GLint>(ii)); |
| if (dst_format == 0) |
| continue; |
| + if (GetColorEncodingFromInternalFormat(dst_format) == GL_SRGB) |
| + draw_buffers_has_srgb = true; |
| if (read_buffer_samples > 0 && |
| (src_sized_format != |
| GLES2Util::ConvertToSizedFormat(dst_format, dst_type))) { |
| @@ -7659,11 +7687,99 @@ void GLES2DecoderImpl::DoBlitFramebufferCHROMIUM( |
| } |
| } |
| - state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); |
| - BlitFramebufferHelper( |
| - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); |
| - state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, |
| + bool enable_srgb = read_buffer_has_srgb || draw_buffers_has_srgb; |
| + if (!enable_srgb || |
| + !feature_info_->feature_flags().desktop_srgb_support || |
| + gl_version_info().IsAtLeastGL(4, 4)) { |
| + if (enable_srgb && gl_version_info().IsAtLeastGL(4, 4)) { |
| + state_.EnableDisableFramebufferSRGB(enable_srgb); |
| + } |
| + |
| + // TODO(yunchao) Need to revisit here. In GLES spec, blitFramebuffer |
| + // should do scissor test per fragment operation. |
| + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); |
| + BlitFramebufferHelper( |
| + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); |
| + state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, |
| state_.enable_flags.scissor_test); |
| + return; |
| + } |
| + |
| + // emulate srgb for desktop core profile when GL version < 4.4 |
| + // TODO(yunchao): Need to handle this situation: |
| + // There are multiple draw buffers. Some of them are srgb images. |
| + // The others are not. |
| + if (read_buffer_has_srgb && !draw_buffers_has_srgb) { |
| + state_.EnableDisableFramebufferSRGB(false); |
| + if (!InitializeSRGBDecoder(func_name)) { |
| + return; |
| + } |
| + srgb_converter_->SRGBToLinear(this, srcX0, srcY0, srcX1, srcY1, |
| + dstX0, dstY0, dstX1, dstY1, |
| + mask, filter, |
| + GetBoundReadFramebufferSize(), |
| + GetBoundReadFramebufferServiceId(), |
| + src_internal_format, |
| + GetBoundDrawFramebufferServiceId()); |
| + } |
| + |
| + if (draw_buffers_has_srgb && !read_buffer_has_srgb) { |
| + state_.EnableDisableFramebufferSRGB(false); |
|
piman
2016/09/13 00:39:23
Once more. Why do you do disable GL_FRAMEBUFFER_SR
yunchao
2016/09/13 08:37:17
I am not sure whether I understand you correctly.
|
| + if (!InitializeSRGBEncoder(func_name)) { |
| + return; |
| + } |
| + GLenum src_format = |
| + TextureManager::ExtractFormatFromStorageFormat(src_internal_format); |
| + srgb_converter_->LinearToSRGB(this, srcX0, srcY0, srcX1, srcY1, |
| + dstX0, dstY0, dstX1, dstY1, |
| + mask, filter, |
| + GetBoundReadFramebufferServiceId(), |
| + src_internal_format, src_format, src_type, |
| + GetBoundDrawFramebufferServiceId()); |
| + } |
| + |
| + if (read_buffer_has_srgb && draw_buffers_has_srgb) { |
| + state_.EnableDisableFramebufferSRGB(false); |
| + if (!InitializeSRGBDecoder(func_name) || |
| + !InitializeSRGBEncoder(func_name)) { |
| + return; |
| + } |
| + srgb_converter_->SRGBToSRGB(this, srcX0, srcY0, srcX1, srcY1, |
| + dstX0, dstY0, dstX1, dstY1, |
| + mask, filter, |
| + GetBoundReadFramebufferSize(), |
| + GetBoundReadFramebufferServiceId(), |
| + src_internal_format, |
| + GetBoundDrawFramebufferServiceId()); |
| + } |
| +} |
| + |
| +bool GLES2DecoderImpl::InitializeSRGBDecoder( |
| + const char* function_name) { |
| + if (!srgb_converter_.get()) { |
| + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name); |
| + srgb_converter_.reset( |
| + new SRGBConverter(feature_info_.get())); |
| + } |
| + srgb_converter_->InitializeSRGBDecoder(this); |
| + if (LOCAL_PEEK_GL_ERROR(function_name) != GL_NO_ERROR) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool GLES2DecoderImpl::InitializeSRGBEncoder( |
| + const char* function_name) { |
| + if (!srgb_converter_.get()) { |
| + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name); |
| + srgb_converter_.reset( |
| + new SRGBConverter(feature_info_.get())); |
| + } |
| + srgb_converter_->InitializeSRGBEncoder(this); |
| + if (LOCAL_PEEK_GL_ERROR(function_name) != GL_NO_ERROR) { |
| + return false; |
| + } |
| + return true; |
| } |
| void GLES2DecoderImpl::EnsureRenderbufferBound() { |