summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h1
-rw-r--r--gpu/command_buffer/service/context_group.cc4
-rw-r--r--gpu/command_buffer/service/context_group.h10
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.cc29
-rw-r--r--gpu/command_buffer/service/framebuffer_manager.h9
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc30
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc207
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc49
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h2
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[] = {