summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo <zmo@chromium.org>2015-08-06 22:54:43 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-07 05:55:11 +0000
commit40baada6914eab3e953ec91b85f19585b02dafb1 (patch)
tree566a98dc864f3ee63019c23f3be2e513ee6250b0 /gpu
parent271400d6a7360cccbb4dca303f38d1992ff2167e (diff)
downloadchromium_src-40baada6914eab3e953ec91b85f19585b02dafb1.zip
chromium_src-40baada6914eab3e953ec91b85f19585b02dafb1.tar.gz
chromium_src-40baada6914eab3e953ec91b85f19585b02dafb1.tar.bz2
Upgrade ReadPixels to ES3 semantic in command buffer.
Move backbuffer's draw buffer setting out of context group and into per context. With this CL, ReadPixels accepts integer types in command buffer. One thing left to be dealt with is the IMPLEMENTATION_COLOR_READ_FORMAT and IMPLEMENTATION_COLOR_READ_TYPE. BUG=429053 TEST=gpu_unittests, webgl 2 conformance R=piman@chromium.org NOTRY=true Review URL: https://codereview.chromium.org/1257093004 Cr-Commit-Position: refs/heads/master@{#342306}
Diffstat (limited to 'gpu')
-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[] = {