diff options
10 files changed, 215 insertions, 127 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index afabe48..b7d708f 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1605,6 +1605,7 @@ _NAMED_TYPE_INFO = { 'GL_UNSIGNED_INT', 'GL_INT', 'GL_FLOAT', + 'GL_UNSIGNED_INT_2_10_10_10_REV', ], 'deprecated_es3': [ 'GL_UNSIGNED_SHORT_5_6_5', diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 1fd3b97..aa7d230 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -4188,6 +4188,7 @@ std::string GLES2Util::GetStringReadPixelType(uint32_t value) { {GL_UNSIGNED_INT, "GL_UNSIGNED_INT"}, {GL_INT, "GL_INT"}, {GL_FLOAT, "GL_FLOAT"}, + {GL_UNSIGNED_INT_2_10_10_10_REV, "GL_UNSIGNED_INT_2_10_10_10_REV"}, }; return GLES2Util::GetQualifiedEnumString(string_table, arraysize(string_table), value); diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 41a739b..f575429 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -53,8 +53,7 @@ ContextGroup::ContextGroup( max_color_attachments_(1u), max_draw_buffers_(1u), program_cache_(NULL), - feature_info_(feature_info), - draw_buffer_(GL_BACK) { + feature_info_(feature_info) { { if (!mailbox_manager_.get()) mailbox_manager_ = new MailboxManagerImpl; @@ -148,7 +147,6 @@ bool ContextGroup::Initialize( GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_); if (max_draw_buffers_ < 1) max_draw_buffers_ = 1; - draw_buffer_ = GL_BACK; } buffer_manager_.reset( diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 65a81e4..ea62823 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -179,14 +179,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { // Loses all the context associated with this group. void LoseContexts(error::ContextLostReason reason); - // EXT_draw_buffer related states for backbuffer. - GLenum draw_buffer() const { - return draw_buffer_; - } - void set_draw_buffer(GLenum buf) { - draw_buffer_ = buf; - } - bool GetBufferServiceId(GLuint client_id, GLuint* service_id) const; void AddSamplerId(GLuint client_id, GLuint service_id) { @@ -309,8 +301,6 @@ class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> { base::hash_map<GLuint, GLuint> transformfeedbacks_id_map_; base::hash_map<GLuint, GLsync> syncs_id_map_; - GLenum draw_buffer_; - DISALLOW_COPY_AND_ASSIGN(ContextGroup); }; diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc index 7a5bf5b..9a1b77c 100644 --- a/gpu/command_buffer/service/framebuffer_manager.cc +++ b/gpu/command_buffer/service/framebuffer_manager.cc @@ -440,8 +440,10 @@ bool Framebuffer::HasStencilAttachment() const { attachments_.find(GL_STENCIL_ATTACHMENT) != attachments_.end(); } -GLenum Framebuffer::GetColorAttachmentFormat() const { - AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0); +GLenum Framebuffer::GetReadBufferInternalFormat() const { + if (read_buffer_ == GL_NONE) + return 0; + AttachmentMap::const_iterator it = attachments_.find(read_buffer_); if (it == attachments_.end()) { return 0; } @@ -449,8 +451,10 @@ GLenum Framebuffer::GetColorAttachmentFormat() const { return attachment->internal_format(); } -GLenum Framebuffer::GetColorAttachmentTextureType() const { - AttachmentMap::const_iterator it = attachments_.find(GL_COLOR_ATTACHMENT0); +GLenum Framebuffer::GetReadBufferTextureType() const { + if (read_buffer_ == GL_NONE) + return 0; + AttachmentMap::const_iterator it = attachments_.find(read_buffer_); if (it == attachments_.end()) { return 0; } @@ -584,6 +588,23 @@ bool Framebuffer::HasAlphaMRT() const { return false; } +bool Framebuffer::HasSameInternalFormatsMRT() const { + GLenum internal_format = 0; + for (uint32 i = 0; i < manager_->max_draw_buffers_; ++i) { + if (draw_buffers_[i] != GL_NONE) { + const Attachment* attachment = GetAttachment(draw_buffers_[i]); + if (!attachment) + continue; + if (!internal_format) { + internal_format = attachment->internal_format(); + } else if (internal_format != attachment->internal_format()) { + return false; + } + } + } + return true; +} + void Framebuffer::UnbindRenderbuffer( GLenum target, Renderbuffer* renderbuffer) { bool done; diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h index a5ee819..9bf440a 100644 --- a/gpu/command_buffer/service/framebuffer_manager.h +++ b/gpu/command_buffer/service/framebuffer_manager.h @@ -116,10 +116,11 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { bool HasDepthAttachment() const; bool HasStencilAttachment() const; - GLenum GetColorAttachmentFormat() const; + GLenum GetDrawBufferInternalFormat() const; + GLenum GetReadBufferInternalFormat() const; // If the color attachment is a texture, returns its type; otherwise, // returns 0. - GLenum GetColorAttachmentTextureType() const; + GLenum GetReadBufferTextureType() const; // Verify all the rules in OpenGL ES 2.0.25 4.4.5 are followed. // Returns GL_FRAMEBUFFER_COMPLETE if there are no reasons we know we can't @@ -151,6 +152,10 @@ class GPU_EXPORT Framebuffer : public base::RefCounted<Framebuffer> { // Return true if any draw buffers has an alpha channel. bool HasAlphaMRT() const; + // Return false if any two active color attachments have different internal + // formats. + bool HasSameInternalFormatsMRT() const; + static void ClearFramebufferCompleteComboMap(); static bool AllowFramebufferComboCompleteMapForTesting() { diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index 1944971..c7133ac 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -181,7 +181,8 @@ TEST_F(FramebufferInfoTest, Basic) { EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), framebuffer_->IsPossiblyComplete()); EXPECT_TRUE(framebuffer_->IsCleared()); - EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); + EXPECT_EQ(static_cast<GLenum>(0), + framebuffer_->GetReadBufferInternalFormat()); EXPECT_FALSE(manager_.IsComplete(framebuffer_)); } @@ -229,7 +230,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(GL_RGBA4), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_FALSE(framebuffer_->HasDepthAttachment()); EXPECT_FALSE(framebuffer_->HasStencilAttachment()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), @@ -246,7 +247,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { renderbuffer_manager_->SetInfo( renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_FALSE(framebuffer_->HasDepthAttachment()); EXPECT_FALSE(framebuffer_->HasStencilAttachment()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), @@ -263,7 +264,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_TRUE(framebuffer_->HasDepthAttachment()); EXPECT_FALSE(framebuffer_->HasStencilAttachment()); // The attachment has a size of 0,0 so depending on the order of the map @@ -305,7 +306,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer3); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_TRUE(framebuffer_->HasDepthAttachment()); EXPECT_TRUE(framebuffer_->HasStencilAttachment()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), @@ -316,7 +317,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { renderbuffer_manager_->SetInfo( renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_TRUE(framebuffer_->HasDepthAttachment()); EXPECT_TRUE(framebuffer_->HasStencilAttachment()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), @@ -382,7 +383,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, NULL); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_TRUE(framebuffer_->HasDepthAttachment()); EXPECT_FALSE(framebuffer_->HasStencilAttachment()); @@ -448,7 +449,8 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), framebuffer_->IsPossiblyComplete()); EXPECT_TRUE(framebuffer_->IsCleared()); - EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); + EXPECT_EQ(static_cast<GLenum>(0), + framebuffer_->GetReadBufferInternalFormat()); // Try format that doesn't work with COLOR_ATTACHMENT0 texture_manager_->SetTarget(texture1.get(), GL_TEXTURE_2D); @@ -472,7 +474,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { framebuffer_->IsPossiblyComplete()); EXPECT_TRUE(framebuffer_->IsCleared()); EXPECT_EQ(static_cast<GLenum>(kFormat1), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); const Framebuffer::Attachment* attachment = framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0); @@ -496,7 +498,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { framebuffer_->AttachTexture( GL_COLOR_ATTACHMENT0, texture2.get(), kTarget2, kLevel2, kSamples2); EXPECT_EQ(static_cast<GLenum>(kFormat2), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); EXPECT_TRUE(framebuffer_->IsCleared()); @@ -521,7 +523,7 @@ TEST_F(FramebufferInfoTest, AttachTexture) { EXPECT_EQ(kFormat3, attachment->internal_format()); EXPECT_FALSE(attachment->cleared()); EXPECT_EQ(static_cast<GLenum>(kFormat3), - framebuffer_->GetColorAttachmentFormat()); + framebuffer_->GetReadBufferInternalFormat()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); EXPECT_FALSE(framebuffer_->IsCleared()); @@ -536,7 +538,8 @@ TEST_F(FramebufferInfoTest, AttachTexture) { // Check removing it. framebuffer_->AttachTexture(GL_COLOR_ATTACHMENT0, NULL, 0, 0, 0); EXPECT_TRUE(framebuffer_->GetAttachment(GL_COLOR_ATTACHMENT0) == NULL); - EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); + EXPECT_EQ(static_cast<GLenum>(0), + framebuffer_->GetReadBufferInternalFormat()); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), framebuffer_->IsPossiblyComplete()); @@ -674,7 +677,8 @@ TEST_F(FramebufferInfoFloatTest, AttachFloatTexture) { framebuffer_->AttachTexture( GL_COLOR_ATTACHMENT0, texture.get(), kTarget, kLevel, kSamples); - EXPECT_EQ(static_cast<GLenum>(0), framebuffer_->GetColorAttachmentFormat()); + EXPECT_EQ(static_cast<GLenum>(0), + framebuffer_->GetReadBufferInternalFormat()); texture_manager_->SetTarget(texture.get(), GL_TEXTURE_2D); texture_manager_->SetLevelInfo(texture.get(), GL_TEXTURE_2D, kLevel, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 7d7ad95..5c3bf03 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -731,9 +731,8 @@ class GLES2DecoderImpl : public GLES2Decoder, // These check the state of the currently bound framebuffer or the // backbuffer if no framebuffer is bound. - // If all_draw_buffers is false, only check with COLOR_ATTACHMENT0, otherwise - // check with all attached and enabled color attachments. - bool BoundFramebufferHasColorAttachmentWithAlpha(bool all_draw_buffers); + // Check with all attached and enabled color attachments. + bool BoundFramebufferHasColorAttachmentWithAlpha(); bool BoundFramebufferHasDepthAttachment(); bool BoundFramebufferHasStencilAttachment(); @@ -900,11 +899,11 @@ class GLES2DecoderImpl : public GLES2Decoder, // or regular back buffer). gfx::Size GetBoundReadFrameBufferSize(); - // Get the format of the currently bound frame buffer (either FBO or regular - // back buffer) + // 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. GLenum GetBoundReadFrameBufferTextureType(); GLenum GetBoundReadFrameBufferInternalFormat(); - GLenum GetBoundDrawFrameBufferInternalFormat(); // Wrapper for CompressedTexImage2D commands. error::Error DoCompressedTexImage2D( @@ -1872,6 +1871,17 @@ class GLES2DecoderImpl : public GLES2Decoder, return error::kNoError; } + bool BackBufferHasAlpha() const { + if (back_buffer_draw_buffer_ == GL_NONE) + return false; + if (offscreen_target_frame_buffer_.get()) { + return (offscreen_target_color_format_ == GL_RGBA || + offscreen_target_color_format_ == GL_RGBA8); + } + return (back_buffer_color_format_ == GL_RGBA || + back_buffer_color_format_ == GL_RGBA8); + } + // Set remaining commands to process to 0 to force DoCommands to return // and allow context preemption and GPU watchdog checks in GpuScheduler(). void ExitCommandProcessingEarly() { commands_to_process_ = 0; } @@ -1969,10 +1979,13 @@ class GLES2DecoderImpl : public GLES2Decoder, GLenum back_buffer_color_format_; bool back_buffer_has_depth_; bool back_buffer_has_stencil_; - // This tracks read buffer for both offscreen/onscreen backbuffer cases. + + // Tracks read buffer and draw buffer for backbuffer, whether it's onscreen + // or offscreen. // TODO(zmo): when ES3 APIs are exposed to Nacl, make sure read_buffer_ // setting is set correctly when SwapBuffers(). GLenum back_buffer_read_buffer_; + GLenum back_buffer_draw_buffer_; bool surfaceless_; @@ -2538,6 +2551,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) back_buffer_has_depth_(false), back_buffer_has_stencil_(false), back_buffer_read_buffer_(GL_BACK), + back_buffer_draw_buffer_(GL_BACK), surfaceless_(false), backbuffer_needs_clear_bits_(0), current_decoder_error_(error::kNoError), @@ -3644,7 +3658,7 @@ bool GLES2DecoderImpl::CheckFramebufferValid( state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false); bool reset_draw_buffer = false; if ((backbuffer_needs_clear_bits_ & GL_COLOR_BUFFER_BIT) != 0 && - group_->draw_buffer() == GL_NONE) { + back_buffer_draw_buffer_ == GL_NONE) { reset_draw_buffer = true; GLenum buf = GL_BACK; if (GetBackbufferServiceId() != 0) // emulated backbuffer @@ -3773,9 +3787,11 @@ gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() { Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); - if (framebuffer != NULL) { - return framebuffer->GetColorAttachmentTextureType(); - } else { + if (framebuffer) { + return framebuffer->GetReadBufferTextureType(); + } else { // Back buffer. + if (back_buffer_read_buffer_ == GL_NONE) + return 0; return GL_UNSIGNED_BYTE; } } @@ -3783,23 +3799,14 @@ GLenum GLES2DecoderImpl::GetBoundReadFrameBufferTextureType() { GLenum GLES2DecoderImpl::GetBoundReadFrameBufferInternalFormat() { Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_READ_FRAMEBUFFER_EXT); - if (framebuffer != NULL) { - return framebuffer->GetColorAttachmentFormat(); - } else if (offscreen_target_frame_buffer_.get()) { - return offscreen_target_color_format_; - } else { - return back_buffer_color_format_; - } -} - -GLenum GLES2DecoderImpl::GetBoundDrawFrameBufferInternalFormat() { - Framebuffer* framebuffer = - GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); - if (framebuffer != NULL) { - return framebuffer->GetColorAttachmentFormat(); - } else if (offscreen_target_frame_buffer_.get()) { - return offscreen_target_color_format_; - } else { + if (framebuffer) { + return framebuffer->GetReadBufferInternalFormat(); + } else { // Back buffer. + if (back_buffer_read_buffer_ == GL_NONE) + return 0; + if (offscreen_target_frame_buffer_.get()) { + return offscreen_target_color_format_; + } return back_buffer_color_format_; } } @@ -4208,8 +4215,7 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { // Clear the target frame buffer. { ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id()); - glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat( - offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1.f); + glClearColor(0, 0, 0, BackBufferHasAlpha() ? 0 : 1.f); state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearStencil(0); state_.SetDeviceStencilMaskSeparate(GL_FRONT, kDefaultStencilMask); @@ -4475,15 +4481,12 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) { glBindBuffer(target, service_id); } -bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha( - bool all_draw_buffers) { +bool GLES2DecoderImpl::BoundFramebufferHasColorAttachmentWithAlpha() { Framebuffer* framebuffer = GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); - if (!all_draw_buffers || !framebuffer) { - return (GLES2Util::GetChannelsForFormat( - GetBoundDrawFrameBufferInternalFormat()) & 0x0008) != 0; - } - return framebuffer->HasAlphaMRT(); + if (framebuffer) + return framebuffer->HasAlphaMRT(); + return BackBufferHasAlpha(); } bool GLES2DecoderImpl::BoundFramebufferHasDepthAttachment() { @@ -4513,7 +4516,7 @@ bool GLES2DecoderImpl::BoundFramebufferHasStencilAttachment() { void GLES2DecoderImpl::ApplyDirtyState() { if (framebuffer_state_.clear_state_dirty) { - bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true); + bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(); state_.SetDeviceColorMask(state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue, @@ -5086,21 +5089,23 @@ bool GLES2DecoderImpl::GetHelper( *num_written = 1; if (params) { GLint v = 0; - if (feature_info_->gl_version_info().is_desktop_core_profile) { - Framebuffer* framebuffer = - GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); - if (framebuffer) { - glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v); - } else { - v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0); + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + if (framebuffer) { + if (framebuffer->HasAlphaMRT() && + framebuffer->HasSameInternalFormatsMRT()) { + if (feature_info_->gl_version_info().is_desktop_core_profile) { + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v); + } else { + glGetIntegerv(GL_ALPHA_BITS, &v); + } } } else { - glGetIntegerv(GL_ALPHA_BITS, &v); + v = (BackBufferHasAlpha() ? 8 : 0); } - params[0] = - BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0; + params[0] = v; } return true; case GL_DEPTH_BITS: @@ -5377,7 +5382,7 @@ bool GLES2DecoderImpl::GetHelper( params[0] = framebuffer->GetDrawBuffer(pname); } else { // backbuffer if (pname == GL_DRAW_BUFFER0_ARB) - params[0] = group_->draw_buffer(); + params[0] = back_buffer_draw_buffer_; else params[0] = GL_NONE; } @@ -5732,11 +5737,10 @@ void GLES2DecoderImpl::ClearUnclearedAttachments( } GLbitfield clear_bits = 0; if (framebuffer->HasUnclearedColorAttachments()) { - glClearColor( - 0.0f, 0.0f, 0.0f, - (GLES2Util::GetChannelsForFormat( - framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f : - 1.0f); + // We should always use alpha == 0 here, because 1) some draw buffers may + // have alpha and some may not; 2) we won't have the same situation as the + // back buffer where alpha channel exists but is not requested. + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); clear_bits |= GL_COLOR_BUFFER_BIT; if (feature_info_->feature_flags().ext_draw_buffers) @@ -8452,22 +8456,91 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size, LOCAL_SET_GL_ERROR_INVALID_ENUM("glReadPixels", type, "type"); return error::kNoError; } - if ((format != GL_RGBA && format != GL_BGRA_EXT && format != GL_RGB && - format != GL_ALPHA) || type != GL_UNSIGNED_BYTE) { + + GLenum src_internal_format = GetBoundReadFrameBufferInternalFormat(); + if (src_internal_format == 0) { + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glReadPixels", + "no valid read buffer source"); + return error::kNoError; + } + std::vector<GLenum> accepted_formats; + std::vector<GLenum> accepted_types; + switch (src_internal_format) { + case GL_RGB10_A2UI: + accepted_formats.push_back(GL_RGBA); + accepted_types.push_back(GL_UNSIGNED_INT_2_10_10_10_REV); + case GL_R8UI: + case GL_R16UI: + case GL_R32UI: + case GL_RG8UI: + case GL_RG16UI: + case GL_RG32UI: + // All the RGB_INTEGER formats are not renderable. + case GL_RGBA8UI: + case GL_RGBA16UI: + case GL_RGBA32UI: + accepted_formats.push_back(GL_RGBA_INTEGER); + accepted_types.push_back(GL_UNSIGNED_INT); + break; + case GL_R8I: + case GL_R16I: + case GL_R32I: + case GL_RG8I: + case GL_RG16I: + case GL_RG32I: + case GL_RGBA8I: + case GL_RGBA16I: + case GL_RGBA32I: + accepted_formats.push_back(GL_RGBA_INTEGER); + accepted_types.push_back(GL_INT); + break; + default: + accepted_formats.push_back(GL_RGBA); + { + GLenum src_type = GetBoundReadFrameBufferTextureType(); + switch (src_type) { + case GL_HALF_FLOAT: + case GL_HALF_FLOAT_OES: + case GL_FLOAT: + case GL_UNSIGNED_INT_10F_11F_11F_REV: + accepted_types.push_back(GL_FLOAT); + break; + default: + accepted_types.push_back(GL_UNSIGNED_BYTE); + break; + } + } + break; + } + if (!IsWebGLContext()) { + accepted_formats.push_back(GL_BGRA_EXT); + accepted_types.push_back(GL_UNSIGNED_BYTE); + } + DCHECK_EQ(accepted_formats.size(), accepted_types.size()); + bool format_type_acceptable = false; + for (size_t ii = 0; ii < accepted_formats.size(); ++ii) { + if (format == accepted_formats[ii] && type == accepted_types[ii]) { + format_type_acceptable = true; + break; + } + } + if (!format_type_acceptable) { // format and type are acceptable enums but not guaranteed to be supported // for this framebuffer. Have to ask gl if they are valid. GLint preferred_format = 0; DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &preferred_format); GLint preferred_type = 0; DoGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &preferred_type); - if (format != static_cast<GLenum>(preferred_format) || - type != static_cast<GLenum>(preferred_type)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_OPERATION, "glReadPixels", "format and type incompatible " - "with the current read framebuffer"); - return error::kNoError; + if (format == static_cast<GLenum>(preferred_format) && + type == static_cast<GLenum>(preferred_type)) { + format_type_acceptable = true; } } + if (!format_type_acceptable) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels", + "format and type incompatible with the current read framebuffer"); + return error::kNoError; + } if (width == 0 || height == 0) { return error::kNoError; } @@ -8483,10 +8556,6 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size, return error::kNoError; } - if (!CheckBoundReadFramebufferColorAttachment("glReadPixels")) { - return error::kNoError; - } - if (!CheckBoundFramebuffersValid("glReadPixels")) { return error::kNoError; } @@ -13397,7 +13466,7 @@ void GLES2DecoderImpl::DoDrawBuffersEXT( mapped_buf = GL_COLOR_ATTACHMENT0; } glDrawBuffersARB(count, &mapped_buf); - group_->set_draw_buffer(bufs[0]); + back_buffer_draw_buffer_ = bufs[0]; } } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc index 6e47194..8349ffa 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc @@ -381,13 +381,14 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x, bool init) { const GLsizei kWidth = 5; const GLsizei kHeight = 3; - const GLint kBytesPerPixel = 3; + const GLint kBytesPerPixel = 4; const GLint kPackAlignment = 4; - const GLenum kFormat = GL_RGB; - static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, - 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, - 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, + const GLenum kFormat = GL_RGBA; + static const uint8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 255, 18, 19, 18, 255, 19, 12, 13, 255, 14, 18, 19, 255, + 18, 19, 13, 255, 29, 28, 23, 255, 22, 21, 22, 255, 21, 29, 28, 255, + 23, 22, 21, 255, 22, 21, 28, 255, 31, 34, 39, 255, 37, 32, 37, 255, + 32, 31, 34, 255, 39, 37, 32, 255, 37, 32, 34, 255 }; ClearSharedMemory(); @@ -499,10 +500,13 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x, // check padding if (yy != in_read_height - 1) { - GLint num_padding_bytes = - (kPackAlignment - 1) - (unpadded_row_size % kPackAlignment); - EXPECT_EQ(0, - memcmp(pack.get(), row + unpadded_row_size, num_padding_bytes)); + GLint temp = unpadded_row_size + kPackAlignment - 1; + GLint padded_row_size = (temp / kPackAlignment ) * kPackAlignment; + GLint num_padding_bytes = padded_row_size - unpadded_row_size; + if (num_padding_bytes) { + EXPECT_EQ(0, memcmp(pack.get(), + row + unpadded_row_size, num_padding_bytes)); + } } } } @@ -510,12 +514,13 @@ void GLES2DecoderTest::CheckReadPixelsOutOfRange(GLint in_read_x, TEST_P(GLES2DecoderTest, ReadPixels) { const GLsizei kWidth = 5; const GLsizei kHeight = 3; - const GLint kBytesPerPixel = 3; + const GLint kBytesPerPixel = 4; const GLint kPackAlignment = 4; - static const int8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { - 12, 13, 14, 18, 19, 18, 19, 12, 13, 14, 18, 19, 18, 19, 13, - 29, 28, 23, 22, 21, 22, 21, 29, 28, 23, 22, 21, 22, 21, 28, - 31, 34, 39, 37, 32, 37, 32, 31, 34, 39, 37, 32, 37, 32, 34, + static const uint8 kSrcPixels[kWidth * kHeight * kBytesPerPixel] = { + 12, 13, 14, 255, 18, 19, 18, 255, 19, 12, 13, 255, 14, 18, 19, 255, + 18, 19, 13, 255, 29, 28, 23, 255, 22, 21, 22, 255, 21, 29, 28, 255, + 23, 22, 21, 255, 22, 21, 28, 255, 31, 34, 39, 255, 37, 32, 37, 255, + 32, 31, 34, 255, 39, 37, 32, 255, 37, 32, 34, 255 }; surface_->SetSize(gfx::Size(INT_MAX, INT_MAX)); @@ -534,14 +539,14 @@ TEST_P(GLES2DecoderTest, ReadPixels) { .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); EXPECT_CALL(*gl_, - ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _)) + ReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, _)) .WillOnce(Invoke(&emu, &ReadPixelsEmulator::ReadPixels)); ReadPixels cmd; cmd.Init(0, 0, kWidth, kHeight, - GL_RGB, + GL_RGBA, GL_UNSIGNED_BYTE, pixels_shm_id, pixels_shm_offset, @@ -767,7 +772,7 @@ TEST_P(GLES2DecoderManualInitTest, ReadPixelsAsyncError) { .RetiresOnSaturation(); EXPECT_CALL(*gl_, - ReadPixels(0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE, _)) + ReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, _)) .Times(1); EXPECT_CALL(*gl_, GenBuffersARB(1, _)).Times(1); EXPECT_CALL(*gl_, DeleteBuffersARB(1, _)).Times(1); @@ -781,7 +786,7 @@ TEST_P(GLES2DecoderManualInitTest, ReadPixelsAsyncError) { 0, kWidth, kHeight, - GL_RGB, + GL_RGBA, GL_UNSIGNED_BYTE, pixels_shm_id, pixels_shm_offset, @@ -938,9 +943,6 @@ TEST_P(GLES2DecoderManualInitTest, ActualAlphaMatchesRequestedAlpha) { .RetiresOnSaturation(); typedef GetIntegerv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); result->size = 0; GetIntegerv cmd2; cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); @@ -963,9 +965,6 @@ TEST_P(GLES2DecoderManualInitTest, ActualAlphaDoesNotMatchRequestedAlpha) { .RetiresOnSaturation(); typedef GetIntegerv::Result Result; Result* result = static_cast<Result*>(shared_memory_address_); - EXPECT_CALL(*gl_, GetIntegerv(GL_ALPHA_BITS, _)) - .WillOnce(SetArgumentPointee<1>(8)) - .RetiresOnSaturation(); result->size = 0; GetIntegerv cmd2; cmd2.Init(GL_ALPHA_BITS, shared_memory_id_, shared_memory_offset_); diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 7092ef09..3b06b56 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -547,7 +547,7 @@ static const GLenum valid_read_pixel_type_table[] = { }; static const GLenum valid_read_pixel_type_table_es3[] = { - GL_UNSIGNED_INT, GL_INT, GL_FLOAT, + GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_INT_2_10_10_10_REV, }; static const GLenum deprecated_read_pixel_type_table_es3[] = { |