Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: gpu/command_buffer/service/framebuffer_manager.cc

Issue 2142353002: Validate fbo color image format and fragment shader output variable type. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: revision addressed piman review comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/framebuffer_manager.h" 5 #include "gpu/command_buffer/service/framebuffer_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 DCHECK(result.second); 365 DCHECK(result.second);
366 } 366 }
367 367
368 Framebuffer::Framebuffer( 368 Framebuffer::Framebuffer(
369 FramebufferManager* manager, GLuint service_id) 369 FramebufferManager* manager, GLuint service_id)
370 : manager_(manager), 370 : manager_(manager),
371 deleted_(false), 371 deleted_(false),
372 service_id_(service_id), 372 service_id_(service_id),
373 has_been_bound_(false), 373 has_been_bound_(false),
374 framebuffer_complete_state_count_id_(0), 374 framebuffer_complete_state_count_id_(0),
375 draw_buffer_type_mask_(0u),
376 draw_buffer_bound_mask_(0u),
375 read_buffer_(GL_COLOR_ATTACHMENT0) { 377 read_buffer_(GL_COLOR_ATTACHMENT0) {
376 manager->StartTracking(this); 378 manager->StartTracking(this);
377 DCHECK_GT(manager->max_draw_buffers_, 0u); 379 DCHECK_GT(manager->max_draw_buffers_, 0u);
378 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]); 380 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
381 adjusted_draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
379 draw_buffers_[0] = GL_COLOR_ATTACHMENT0; 382 draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
380 for (uint32_t i = 1; i < manager->max_draw_buffers_; ++i) 383 adjusted_draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
381 draw_buffers_[i] = GL_NONE; 384 for (uint32_t ii = 1; ii < manager->max_draw_buffers_; ++ii) {
385 draw_buffers_[ii] = GL_NONE;
386 adjusted_draw_buffers_[ii] = GL_NONE;
387 }
382 } 388 }
383 389
384 Framebuffer::~Framebuffer() { 390 Framebuffer::~Framebuffer() {
385 if (manager_) { 391 if (manager_) {
386 if (manager_->have_context_) { 392 if (manager_->have_context_) {
387 GLuint id = service_id(); 393 GLuint id = service_id();
388 glDeleteFramebuffersEXT(1, &id); 394 glDeleteFramebuffersEXT(1, &id);
389 } 395 }
390 manager_->StopTracking(this); 396 manager_->StopTracking(this);
391 manager_ = NULL; 397 manager_ = NULL;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 case GL_SRGB_EXT: 469 case GL_SRGB_EXT:
464 case GL_SRGB_ALPHA_EXT: 470 case GL_SRGB_ALPHA_EXT:
465 return true; 471 return true;
466 default: 472 default:
467 break; 473 break;
468 } 474 }
469 } 475 }
470 return false; 476 return false;
471 } 477 }
472 478
473 bool Framebuffer::PrepareDrawBuffersForClear() const { 479 bool Framebuffer::PrepareDrawBuffersForClearingUninitializedAttachments(
480 ) const {
474 std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); 481 std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
475 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) 482 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i)
476 buffers[i] = GL_NONE; 483 buffers[i] = GL_NONE;
477 for (AttachmentMap::const_iterator it = attachments_.begin(); 484 for (auto const& it : attachments_) {
478 it != attachments_.end(); ++it) { 485 if (it.first >= GL_COLOR_ATTACHMENT0 &&
479 if (it->first >= GL_COLOR_ATTACHMENT0 && 486 it.first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
480 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ && 487 !it.second->cleared()) {
481 !it->second->cleared()) {
482 // There should be no partially cleared images, uncleared int/3d images. 488 // There should be no partially cleared images, uncleared int/3d images.
483 // This is because ClearUnclearedIntOr3DImagesOrPartiallyClearedImages() 489 // This is because ClearUnclearedIntOr3DImagesOrPartiallyClearedImages()
484 // is called before this. 490 // is called before this.
485 DCHECK(!GLES2Util::IsIntegerFormat(it->second->internal_format())); 491 DCHECK(!GLES2Util::IsIntegerFormat(it.second->internal_format()));
486 DCHECK(!it->second->IsPartiallyCleared()); 492 DCHECK(!it.second->IsPartiallyCleared());
487 DCHECK(!it->second->Is3D()); 493 DCHECK(!it.second->Is3D());
488 buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first; 494 buffers[it.first - GL_COLOR_ATTACHMENT0] = it.first;
489 } 495 }
490 } 496 }
491 bool different = false; 497 bool different = false;
492 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) { 498 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) {
493 if (buffers[i] != draw_buffers_[i]) { 499 if (buffers[i] != adjusted_draw_buffers_[i]) {
494 different = true; 500 different = true;
495 break; 501 break;
496 } 502 }
497 } 503 }
498 if (different) 504 if (different)
499 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get()); 505 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get());
500 return different; 506 return different;
501 } 507 }
502 508
503 void Framebuffer::RestoreDrawBuffersAfterClear() const { 509 void Framebuffer::RestoreDrawBuffers() const {
504 glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get()); 510 glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
511 }
512
513 bool Framebuffer::ValidateAndAdjustDrawBuffers(
514 uint32_t fragment_output_type_mask, uint32_t fragment_output_written_mask) {
515 uint32_t mask = draw_buffer_bound_mask_ & fragment_output_written_mask;
516 if ((mask & fragment_output_type_mask) != (mask & draw_buffer_type_mask_))
517 return false;
518
519 if (draw_buffer_bound_mask_ & ~fragment_output_written_mask) {
520 // This won't be reached in every draw/clear call - only when framebuffer
521 // or program has changed.
522 for (uint32_t ii = 0; ii < manager_->max_draw_buffers_; ++ii) {
523 adjusted_draw_buffers_[ii] = draw_buffers_[ii];
524 uint32_t shift_bits = ii * 2;
525 uint32_t mask = 0x33 << shift_bits;
piman 2016/07/14 23:41:14 Did you mean 0x3 instead of 0x33?
piman 2016/07/14 23:41:14 nit: this |mask| hides the variable on l.515 - it
Zhenyao Mo 2016/07/15 02:41:15 Done.
526 if ((draw_buffer_bound_mask_ & mask) == 0u) {
527 adjusted_draw_buffers_[ii] = GL_NONE;
528 continue;
529 }
530 if ((fragment_output_written_mask & mask) == 0u) {
531 adjusted_draw_buffers_[ii] = GL_NONE;
532 }
533 }
534 glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
535 }
536 return true;
537 }
538
539 bool Framebuffer::ContainsActiveIntegerAttachments() const {
540 // SHADER_VARIABLE_FLOAT is 0x3.
piman 2016/07/14 23:41:14 nit: if you want to defend against this changing,
Zhenyao Mo 2016/07/15 02:41:15 Ha, nice trick. Thanks.
541 uint32_t mask = 0xFFFFFFFF & draw_buffer_bound_mask_;
542 return draw_buffer_type_mask_ != mask;
505 } 543 }
506 544
507 void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures( 545 void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures(
508 GLES2Decoder* decoder, 546 GLES2Decoder* decoder, TextureManager* texture_manager) {
509 TextureManager* texture_manager) {
510 for (AttachmentMap::const_iterator it = attachments_.begin(); 547 for (AttachmentMap::const_iterator it = attachments_.begin();
511 it != attachments_.end(); ++it) { 548 it != attachments_.end(); ++it) {
512 if (!it->second->IsTextureAttachment() || it->second->cleared()) 549 if (!it->second->IsTextureAttachment() || it->second->cleared())
513 continue; 550 continue;
514 TextureAttachment* attachment = 551 TextureAttachment* attachment =
515 reinterpret_cast<TextureAttachment*>(it->second.get()); 552 reinterpret_cast<TextureAttachment*>(it->second.get());
516 if (attachment->IsPartiallyCleared() || attachment->Is3D() || 553 if (attachment->IsPartiallyCleared() || attachment->Is3D() ||
517 GLES2Util::IsIntegerFormat(attachment->internal_format())) { 554 GLES2Util::IsIntegerFormat(attachment->internal_format())) {
518 texture_manager->ClearTextureLevel(decoder, 555 texture_manager->ClearTextureLevel(decoder,
519 attachment->texture(), 556 attachment->texture(),
520 attachment->target(), 557 attachment->target(),
521 attachment->level()); 558 attachment->level());
522 } 559 }
523 } 560 }
524 } 561 }
525 562
526 void Framebuffer::MarkAttachmentAsCleared( 563 void Framebuffer::MarkAttachmentAsCleared(
527 RenderbufferManager* renderbuffer_manager, 564 RenderbufferManager* renderbuffer_manager,
528 TextureManager* texture_manager, 565 TextureManager* texture_manager,
529 GLenum attachment, 566 GLenum attachment,
530 bool cleared) { 567 bool cleared) {
531 AttachmentMap::iterator it = attachments_.find(attachment); 568 AttachmentMap::iterator it = attachments_.find(attachment);
532 if (it != attachments_.end()) { 569 if (it != attachments_.end()) {
533 Attachment* a = it->second.get(); 570 Attachment* a = it->second.get();
534 if (a->cleared() != cleared) { 571 if (a->cleared() != cleared) {
535 a->SetCleared(renderbuffer_manager, 572 a->SetCleared(renderbuffer_manager,
536 texture_manager, 573 texture_manager,
537 cleared); 574 cleared);
538 } 575 }
539 } 576 }
540 } 577 }
541 578
542 void Framebuffer::MarkAttachmentsAsCleared( 579 void Framebuffer::MarkAttachmentsAsCleared(
543 RenderbufferManager* renderbuffer_manager, 580 RenderbufferManager* renderbuffer_manager,
544 TextureManager* texture_manager, 581 TextureManager* texture_manager,
545 bool cleared) { 582 bool cleared) {
546 for (AttachmentMap::iterator it = attachments_.begin(); 583 for (AttachmentMap::iterator it = attachments_.begin();
547 it != attachments_.end(); ++it) { 584 it != attachments_.end(); ++it) {
548 Attachment* attachment = it->second.get(); 585 Attachment* attachment = it->second.get();
549 if (attachment->cleared() != cleared) { 586 if (attachment->cleared() != cleared) {
550 attachment->SetCleared(renderbuffer_manager, texture_manager, cleared); 587 attachment->SetCleared(renderbuffer_manager, texture_manager, cleared);
551 } 588 }
552 } 589 }
553 } 590 }
554 591
555 bool Framebuffer::HasColorAttachment(int index) const { 592 bool Framebuffer::HasColorAttachment(int index) const {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const { 775 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
739 GLsizei index = static_cast<GLsizei>( 776 GLsizei index = static_cast<GLsizei>(
740 draw_buffer - GL_DRAW_BUFFER0_ARB); 777 draw_buffer - GL_DRAW_BUFFER0_ARB);
741 CHECK(index >= 0 && 778 CHECK(index >= 0 &&
742 index < static_cast<GLsizei>(manager_->max_draw_buffers_)); 779 index < static_cast<GLsizei>(manager_->max_draw_buffers_));
743 return draw_buffers_[index]; 780 return draw_buffers_[index];
744 } 781 }
745 782
746 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) { 783 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
747 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_)); 784 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
748 for (GLsizei i = 0; i < n; ++i) 785 for (GLsizei ii = 0; ii < n; ++ii) {
749 draw_buffers_[i] = bufs[i]; 786 draw_buffers_[ii] = bufs[ii];
787 adjusted_draw_buffers_[ii] = bufs[ii];
788 }
789 for (uint32_t ii = n; ii < manager_->max_draw_buffers_; ++ii) {
790 draw_buffers_[ii] = GL_NONE;
791 adjusted_draw_buffers_[ii] = GL_NONE;
792 }
793 UpdateDrawBufferMasks();
750 } 794 }
751 795
752 bool Framebuffer::HasAlphaMRT() const { 796 bool Framebuffer::HasAlphaMRT() const {
753 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) { 797 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) {
754 if (draw_buffers_[i] != GL_NONE) { 798 if (draw_buffers_[i] != GL_NONE) {
755 const Attachment* attachment = GetAttachment(draw_buffers_[i]); 799 const Attachment* attachment = GetAttachment(draw_buffers_[i]);
756 if (!attachment) 800 if (!attachment)
757 continue; 801 continue;
758 if ((GLES2Util::GetChannelsForFormat( 802 if ((GLES2Util::GetChannelsForFormat(
759 attachment->internal_format()) & 0x0008) != 0) 803 attachment->internal_format()) & 0x0008) != 0)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 // TODO(gman): manually detach texture. 855 // TODO(gman): manually detach texture.
812 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0); 856 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
813 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0); 857 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
814 done = false; 858 done = false;
815 break; 859 break;
816 } 860 }
817 } 861 }
818 } while (!done); 862 } while (!done);
819 } 863 }
820 864
865 void Framebuffer::UpdateDrawBufferMasks() {
866 draw_buffer_type_mask_ = 0u;
867 draw_buffer_bound_mask_ = 0u;
868 for (GLenum ii = GL_COLOR_ATTACHMENT0;
869 ii < GL_COLOR_ATTACHMENT0 + manager_->max_color_attachments_; ++ii) {
piman 2016/07/14 23:41:14 nit: how about: for (size_t index = 0; index < man
Zhenyao Mo 2016/07/15 02:41:15 Done.
870 size_t index = ii - GL_COLOR_ATTACHMENT0;
871 if (draw_buffers_[index] == GL_NONE)
872 continue;
873 auto iter = attachments_.find(ii);
874 if (iter == attachments_.end())
875 continue;
876 scoped_refptr<Attachment> attachment = iter->second;
877 GLenum internal_format = attachment->internal_format();
878 ShaderVariableBaseType base_type = SHADER_VARIABLE_UNDEFINED_TYPE;
879 if (GLES2Util::IsSignedIntegerFormat(internal_format)) {
880 base_type = SHADER_VARIABLE_INT;
881 } else if (GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
882 base_type = SHADER_VARIABLE_UINT;
883 } else {
884 base_type = SHADER_VARIABLE_FLOAT;
885 }
886 size_t shift_bits = index * 2;
887 draw_buffer_type_mask_ |= base_type << shift_bits;
888 draw_buffer_bound_mask_ |= 0x3 << shift_bits;
889 }
890 }
891
821 Framebuffer* FramebufferManager::GetFramebuffer( 892 Framebuffer* FramebufferManager::GetFramebuffer(
822 GLuint client_id) { 893 GLuint client_id) {
823 FramebufferMap::iterator it = framebuffers_.find(client_id); 894 FramebufferMap::iterator it = framebuffers_.find(client_id);
824 return it != framebuffers_.end() ? it->second.get() : NULL; 895 return it != framebuffers_.end() ? it->second.get() : NULL;
825 } 896 }
826 897
827 void FramebufferManager::RemoveFramebuffer(GLuint client_id) { 898 void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
828 FramebufferMap::iterator it = framebuffers_.find(client_id); 899 FramebufferMap::iterator it = framebuffers_.find(client_id);
829 if (it != framebuffers_.end()) { 900 if (it != framebuffers_.end()) {
830 it->second->MarkAsDeleted(); 901 it->second->MarkAsDeleted();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 1005
935 bool FramebufferManager::IsComplete( 1006 bool FramebufferManager::IsComplete(
936 Framebuffer* framebuffer) { 1007 Framebuffer* framebuffer) {
937 DCHECK(framebuffer); 1008 DCHECK(framebuffer);
938 return framebuffer->framebuffer_complete_state_count_id() == 1009 return framebuffer->framebuffer_complete_state_count_id() ==
939 framebuffer_state_change_count_; 1010 framebuffer_state_change_count_;
940 } 1011 }
941 1012
942 } // namespace gles2 1013 } // namespace gles2
943 } // namespace gpu 1014 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698