| Index: gpu/command_buffer/service/framebuffer_manager.cc
|
| diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
|
| index 0c5d96708e856d8e9c3d8578eb785c9f2d18c71e..cec5b104b7ab678b71a164d4da999293e99df8a8 100644
|
| --- a/gpu/command_buffer/service/framebuffer_manager.cc
|
| +++ b/gpu/command_buffer/service/framebuffer_manager.cc
|
| @@ -372,13 +372,20 @@ Framebuffer::Framebuffer(
|
| service_id_(service_id),
|
| has_been_bound_(false),
|
| framebuffer_complete_state_count_id_(0),
|
| + draw_buffer_type_mask_(0u),
|
| + draw_buffer_bound_mask_(0u),
|
| + adjusted_draw_buffer_bound_mask_(0u),
|
| read_buffer_(GL_COLOR_ATTACHMENT0) {
|
| manager->StartTracking(this);
|
| DCHECK_GT(manager->max_draw_buffers_, 0u);
|
| draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
|
| + adjusted_draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
|
| draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
|
| - for (uint32_t i = 1; i < manager->max_draw_buffers_; ++i)
|
| - draw_buffers_[i] = GL_NONE;
|
| + adjusted_draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
|
| + for (uint32_t ii = 1; ii < manager->max_draw_buffers_; ++ii) {
|
| + draw_buffers_[ii] = GL_NONE;
|
| + adjusted_draw_buffers_[ii] = GL_NONE;
|
| + }
|
| }
|
|
|
| Framebuffer::~Framebuffer() {
|
| @@ -470,27 +477,27 @@ bool Framebuffer::HasSRGBAttachments() const {
|
| return false;
|
| }
|
|
|
| -bool Framebuffer::PrepareDrawBuffersForClear() const {
|
| +bool Framebuffer::PrepareDrawBuffersForClearingUninitializedAttachments(
|
| + ) const {
|
| std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
|
| for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i)
|
| buffers[i] = GL_NONE;
|
| - for (AttachmentMap::const_iterator it = attachments_.begin();
|
| - it != attachments_.end(); ++it) {
|
| - if (it->first >= GL_COLOR_ATTACHMENT0 &&
|
| - it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
|
| - !it->second->cleared()) {
|
| + for (auto const& it : attachments_) {
|
| + if (it.first >= GL_COLOR_ATTACHMENT0 &&
|
| + it.first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
|
| + !it.second->cleared()) {
|
| // There should be no partially cleared images, uncleared int/3d images.
|
| // This is because ClearUnclearedIntOr3DImagesOrPartiallyClearedImages()
|
| // is called before this.
|
| - DCHECK(!GLES2Util::IsIntegerFormat(it->second->internal_format()));
|
| - DCHECK(!it->second->IsPartiallyCleared());
|
| - DCHECK(!it->second->Is3D());
|
| - buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first;
|
| + DCHECK(!GLES2Util::IsIntegerFormat(it.second->internal_format()));
|
| + DCHECK(!it.second->IsPartiallyCleared());
|
| + DCHECK(!it.second->Is3D());
|
| + buffers[it.first - GL_COLOR_ATTACHMENT0] = it.first;
|
| }
|
| }
|
| bool different = false;
|
| for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) {
|
| - if (buffers[i] != draw_buffers_[i]) {
|
| + if (buffers[i] != adjusted_draw_buffers_[i]) {
|
| different = true;
|
| break;
|
| }
|
| @@ -500,13 +507,42 @@ bool Framebuffer::PrepareDrawBuffersForClear() const {
|
| return different;
|
| }
|
|
|
| -void Framebuffer::RestoreDrawBuffersAfterClear() const {
|
| - glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get());
|
| +void Framebuffer::RestoreDrawBuffers() const {
|
| + glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
|
| +}
|
| +
|
| +bool Framebuffer::ValidateAndAdjustDrawBuffers(
|
| + uint32_t fragment_output_type_mask, uint32_t fragment_output_written_mask) {
|
| + uint32_t mask = draw_buffer_bound_mask_ & fragment_output_written_mask;
|
| + if ((mask & fragment_output_type_mask) != (mask & draw_buffer_type_mask_))
|
| + return false;
|
| +
|
| + if (mask != adjusted_draw_buffer_bound_mask_) {
|
| + // This won't be reached in every draw/clear call - only when framebuffer
|
| + // or program has changed.
|
| + for (uint32_t ii = 0; ii < manager_->max_draw_buffers_; ++ii) {
|
| + adjusted_draw_buffers_[ii] = draw_buffers_[ii];
|
| + uint32_t shift_bits = ii * 2;
|
| + uint32_t buffer_mask = 0x3 << shift_bits;
|
| + if ((buffer_mask & mask) == 0u) {
|
| + adjusted_draw_buffers_[ii] = GL_NONE;
|
| + }
|
| + }
|
| + adjusted_draw_buffer_bound_mask_ = mask;
|
| + glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Framebuffer::ContainsActiveIntegerAttachments() const {
|
| + // 0x55555555 broadcasts SHADER_VARIABLE_FLOAT to all slots.
|
| + uint32_t mask = 0x55555555u * SHADER_VARIABLE_FLOAT;
|
| + mask &= draw_buffer_bound_mask_;
|
| + return draw_buffer_type_mask_ != mask;
|
| }
|
|
|
| void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures(
|
| - GLES2Decoder* decoder,
|
| - TextureManager* texture_manager) {
|
| + GLES2Decoder* decoder, TextureManager* texture_manager) {
|
| for (AttachmentMap::const_iterator it = attachments_.begin();
|
| it != attachments_.end(); ++it) {
|
| if (!it->second->IsTextureAttachment() || it->second->cleared())
|
| @@ -524,10 +560,10 @@ void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures(
|
| }
|
|
|
| void Framebuffer::MarkAttachmentAsCleared(
|
| - RenderbufferManager* renderbuffer_manager,
|
| - TextureManager* texture_manager,
|
| - GLenum attachment,
|
| - bool cleared) {
|
| + RenderbufferManager* renderbuffer_manager,
|
| + TextureManager* texture_manager,
|
| + GLenum attachment,
|
| + bool cleared) {
|
| AttachmentMap::iterator it = attachments_.find(attachment);
|
| if (it != attachments_.end()) {
|
| Attachment* a = it->second.get();
|
| @@ -540,9 +576,9 @@ void Framebuffer::MarkAttachmentAsCleared(
|
| }
|
|
|
| void Framebuffer::MarkAttachmentsAsCleared(
|
| - RenderbufferManager* renderbuffer_manager,
|
| - TextureManager* texture_manager,
|
| - bool cleared) {
|
| + RenderbufferManager* renderbuffer_manager,
|
| + TextureManager* texture_manager,
|
| + bool cleared) {
|
| for (AttachmentMap::iterator it = attachments_.begin();
|
| it != attachments_.end(); ++it) {
|
| Attachment* attachment = it->second.get();
|
| @@ -745,8 +781,16 @@ GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
|
|
|
| void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
|
| DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
|
| - for (GLsizei i = 0; i < n; ++i)
|
| - draw_buffers_[i] = bufs[i];
|
| + for (GLsizei ii = 0; ii < n; ++ii) {
|
| + draw_buffers_[ii] = bufs[ii];
|
| + adjusted_draw_buffers_[ii] = bufs[ii];
|
| + }
|
| + for (uint32_t ii = n; ii < manager_->max_draw_buffers_; ++ii) {
|
| + draw_buffers_[ii] = GL_NONE;
|
| + adjusted_draw_buffers_[ii] = GL_NONE;
|
| + }
|
| + UpdateDrawBufferMasks();
|
| + adjusted_draw_buffer_bound_mask_ = draw_buffer_bound_mask_;
|
| }
|
|
|
| bool Framebuffer::HasAlphaMRT() const {
|
| @@ -818,6 +862,32 @@ void Framebuffer::UnbindTexture(
|
| } while (!done);
|
| }
|
|
|
| +void Framebuffer::UpdateDrawBufferMasks() {
|
| + draw_buffer_type_mask_ = 0u;
|
| + draw_buffer_bound_mask_ = 0u;
|
| + for (uint32_t index = 0; index < manager_->max_color_attachments_; ++index) {
|
| + GLenum draw_buffer = draw_buffers_[index];
|
| + if (draw_buffer == GL_NONE)
|
| + continue;
|
| + auto iter = attachments_.find(draw_buffer);
|
| + if (iter == attachments_.end())
|
| + continue;
|
| + scoped_refptr<Attachment> attachment = iter->second;
|
| + GLenum internal_format = attachment->internal_format();
|
| + ShaderVariableBaseType base_type = SHADER_VARIABLE_UNDEFINED_TYPE;
|
| + if (GLES2Util::IsSignedIntegerFormat(internal_format)) {
|
| + base_type = SHADER_VARIABLE_INT;
|
| + } else if (GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
|
| + base_type = SHADER_VARIABLE_UINT;
|
| + } else {
|
| + base_type = SHADER_VARIABLE_FLOAT;
|
| + }
|
| + size_t shift_bits = index * 2;
|
| + draw_buffer_type_mask_ |= base_type << shift_bits;
|
| + draw_buffer_bound_mask_ |= 0x3 << shift_bits;
|
| + }
|
| +}
|
| +
|
| Framebuffer* FramebufferManager::GetFramebuffer(
|
| GLuint client_id) {
|
| FramebufferMap::iterator it = framebuffers_.find(client_id);
|
|
|