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

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: Validate fbo color image format and fragment shader output variable type. 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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 read_buffer_(GL_COLOR_ATTACHMENT0) { 375 read_buffer_(GL_COLOR_ATTACHMENT0) {
376 manager->StartTracking(this); 376 manager->StartTracking(this);
377 DCHECK_GT(manager->max_draw_buffers_, 0u); 377 DCHECK_GT(manager->max_draw_buffers_, 0u);
378 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]); 378 draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
379 adjusted_draw_buffers_.reset(new GLenum[manager->max_draw_buffers_]);
379 draw_buffers_[0] = GL_COLOR_ATTACHMENT0; 380 draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
380 for (uint32_t i = 1; i < manager->max_draw_buffers_; ++i) 381 adjusted_draw_buffers_[0] = GL_COLOR_ATTACHMENT0;
381 draw_buffers_[i] = GL_NONE; 382 for (uint32_t ii = 1; ii < manager->max_draw_buffers_; ++ii) {
383 draw_buffers_[ii] = GL_NONE;
384 adjusted_draw_buffers_[ii] = GL_NONE;
385 }
386
387 color_attachment_base_types_.reset(
388 new ShaderVariableBaseType[manager->max_draw_buffers_]);
389 ResetColorAttachmentBaseTypes();
382 } 390 }
383 391
384 Framebuffer::~Framebuffer() { 392 Framebuffer::~Framebuffer() {
385 if (manager_) { 393 if (manager_) {
386 if (manager_->have_context_) { 394 if (manager_->have_context_) {
387 GLuint id = service_id(); 395 GLuint id = service_id();
388 glDeleteFramebuffersEXT(1, &id); 396 glDeleteFramebuffersEXT(1, &id);
389 } 397 }
390 manager_->StopTracking(this); 398 manager_->StopTracking(this);
391 manager_ = NULL; 399 manager_ = NULL;
392 } 400 }
393 } 401 }
394 402
403 void Framebuffer::ResetColorAttachmentBaseTypes() {
404 for (size_t ii = 1; ii < manager_->max_draw_buffers_; ++ii) {
405 color_attachment_base_types_[ii] = SHADER_VARIABLE_UNDEFINED_TYPE;
406 }
407 }
408
395 bool Framebuffer::HasUnclearedAttachment( 409 bool Framebuffer::HasUnclearedAttachment(
396 GLenum attachment) const { 410 GLenum attachment) const {
397 AttachmentMap::const_iterator it = 411 AttachmentMap::const_iterator it =
398 attachments_.find(attachment); 412 attachments_.find(attachment);
399 if (it != attachments_.end()) { 413 if (it != attachments_.end()) {
400 const Attachment* attachment = it->second.get(); 414 const Attachment* attachment = it->second.get();
401 return !attachment->cleared(); 415 return !attachment->cleared();
402 } 416 }
403 return false; 417 return false;
404 } 418 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 case GL_SRGB_EXT: 477 case GL_SRGB_EXT:
464 case GL_SRGB_ALPHA_EXT: 478 case GL_SRGB_ALPHA_EXT:
465 return true; 479 return true;
466 default: 480 default:
467 break; 481 break;
468 } 482 }
469 } 483 }
470 return false; 484 return false;
471 } 485 }
472 486
473 bool Framebuffer::PrepareDrawBuffersForClear() const { 487 bool Framebuffer::PrepareDrawBuffersForClearingUninitializedAttachments(
488 ) const {
474 std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]); 489 std::unique_ptr<GLenum[]> buffers(new GLenum[manager_->max_draw_buffers_]);
475 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) 490 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i)
476 buffers[i] = GL_NONE; 491 buffers[i] = GL_NONE;
477 for (AttachmentMap::const_iterator it = attachments_.begin(); 492 for (AttachmentMap::const_iterator it = attachments_.begin();
478 it != attachments_.end(); ++it) { 493 it != attachments_.end(); ++it) {
479 if (it->first >= GL_COLOR_ATTACHMENT0 && 494 if (it->first >= GL_COLOR_ATTACHMENT0 &&
480 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ && 495 it->first < GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_ &&
481 !it->second->cleared()) { 496 !it->second->cleared()) {
482 // There should be no partially cleared images, uncleared int/3d images. 497 // There should be no partially cleared images, uncleared int/3d images.
483 // This is because ClearUnclearedIntOr3DImagesOrPartiallyClearedImages() 498 // This is because ClearUnclearedIntOr3DImagesOrPartiallyClearedImages()
484 // is called before this. 499 // is called before this.
485 DCHECK(!GLES2Util::IsIntegerFormat(it->second->internal_format())); 500 DCHECK(!GLES2Util::IsIntegerFormat(it->second->internal_format()));
486 DCHECK(!it->second->IsPartiallyCleared()); 501 DCHECK(!it->second->IsPartiallyCleared());
487 DCHECK(!it->second->Is3D()); 502 DCHECK(!it->second->Is3D());
488 buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first; 503 buffers[it->first - GL_COLOR_ATTACHMENT0] = it->first;
489 } 504 }
490 } 505 }
491 bool different = false; 506 bool different = false;
492 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) { 507 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) {
493 if (buffers[i] != draw_buffers_[i]) { 508 if (buffers[i] != adjusted_draw_buffers_[i]) {
494 different = true; 509 different = true;
495 break; 510 break;
496 } 511 }
497 } 512 }
498 if (different) 513 if (different)
499 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get()); 514 glDrawBuffersARB(manager_->max_draw_buffers_, buffers.get());
500 return different; 515 return different;
501 } 516 }
502 517
503 void Framebuffer::RestoreDrawBuffersAfterClear() const { 518 void Framebuffer::RestoreDrawBuffers() const {
504 glDrawBuffersARB(manager_->max_draw_buffers_, draw_buffers_.get()); 519 glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
520 }
521
522 bool Framebuffer::ValidateAndAdjustDrawBuffers(
523 const ShaderVariableBaseType* fragment_output_base_types) {
524 bool adjust = false;
525 for (size_t ii = 0; ii < manager_->max_draw_buffers_; ++ii) {
piman 2016/07/13 22:35:55 This loop seems kind of expensive... Truth is, we
526 if (draw_buffers_[ii] == GL_NONE) {
527 DCHECK_EQ(static_cast<GLenum>(GL_NONE), adjusted_draw_buffers_[ii]);
528 continue;
529 }
530 if (color_attachment_base_types_[ii] == SHADER_VARIABLE_UNDEFINED_TYPE) {
531 if (adjusted_draw_buffers_[ii] != GL_NONE)
532 adjust = true;
533 continue;
534 }
535 if (fragment_output_base_types) { // Draw call cases.
536 if (fragment_output_base_types[ii] == SHADER_VARIABLE_UNDEFINED_TYPE) {
537 if (adjusted_draw_buffers_[ii] != GL_NONE)
538 adjust = true;
539 continue;
540 }
541 if (fragment_output_base_types[ii] != color_attachment_base_types_[ii]) {
542 return false;
543 }
544 } else { // Clear call cases.
545 if (color_attachment_base_types_[ii] != SHADER_VARIABLE_FLOAT) {
546 if (adjusted_draw_buffers_[ii] != GL_NONE)
547 adjust = true;
548 continue;
549 }
550 }
551 }
552 if (adjust) {
553 // This won't be reached in every draw/clear call - only when framebuffer
554 // or program has changed.
555 for (size_t ii = 0; ii < manager_->max_draw_buffers_; ++ii) {
556 if (draw_buffers_[ii] == GL_NONE)
557 continue;
558 if (color_attachment_base_types_[ii] == SHADER_VARIABLE_UNDEFINED_TYPE) {
559 adjusted_draw_buffers_[ii] = GL_NONE;
560 continue;
561 }
562 if (fragment_output_base_types) { // Draw call cases.
563 if (fragment_output_base_types[ii] == SHADER_VARIABLE_UNDEFINED_TYPE) {
564 adjusted_draw_buffers_[ii] = GL_NONE;
565 }
566 } else { // Clear call cases.
567 if (color_attachment_base_types_[ii] != SHADER_VARIABLE_FLOAT) {
568 adjusted_draw_buffers_[ii] = GL_NONE;
569 }
570 }
571 }
572 glDrawBuffersARB(manager_->max_draw_buffers_, adjusted_draw_buffers_.get());
573 }
574 return true;
505 } 575 }
506 576
507 void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures( 577 void Framebuffer::ClearUnclearedIntOr3DTexturesOrPartiallyClearedTextures(
508 GLES2Decoder* decoder, 578 GLES2Decoder* decoder, TextureManager* texture_manager) {
509 TextureManager* texture_manager) {
510 for (AttachmentMap::const_iterator it = attachments_.begin(); 579 for (AttachmentMap::const_iterator it = attachments_.begin();
511 it != attachments_.end(); ++it) { 580 it != attachments_.end(); ++it) {
512 if (!it->second->IsTextureAttachment() || it->second->cleared()) 581 if (!it->second->IsTextureAttachment() || it->second->cleared())
513 continue; 582 continue;
514 TextureAttachment* attachment = 583 TextureAttachment* attachment =
515 reinterpret_cast<TextureAttachment*>(it->second.get()); 584 reinterpret_cast<TextureAttachment*>(it->second.get());
516 if (attachment->IsPartiallyCleared() || attachment->Is3D() || 585 if (attachment->IsPartiallyCleared() || attachment->Is3D() ||
517 GLES2Util::IsIntegerFormat(attachment->internal_format())) { 586 GLES2Util::IsIntegerFormat(attachment->internal_format())) {
518 texture_manager->ClearTextureLevel(decoder, 587 texture_manager->ClearTextureLevel(decoder,
519 attachment->texture(), 588 attachment->texture(),
520 attachment->target(), 589 attachment->target(),
521 attachment->level()); 590 attachment->level());
522 } 591 }
523 } 592 }
524 } 593 }
525 594
526 void Framebuffer::MarkAttachmentAsCleared( 595 void Framebuffer::MarkAttachmentAsCleared(
527 RenderbufferManager* renderbuffer_manager, 596 RenderbufferManager* renderbuffer_manager,
528 TextureManager* texture_manager, 597 TextureManager* texture_manager,
529 GLenum attachment, 598 GLenum attachment,
530 bool cleared) { 599 bool cleared) {
531 AttachmentMap::iterator it = attachments_.find(attachment); 600 AttachmentMap::iterator it = attachments_.find(attachment);
532 if (it != attachments_.end()) { 601 if (it != attachments_.end()) {
533 Attachment* a = it->second.get(); 602 Attachment* a = it->second.get();
534 if (a->cleared() != cleared) { 603 if (a->cleared() != cleared) {
535 a->SetCleared(renderbuffer_manager, 604 a->SetCleared(renderbuffer_manager,
536 texture_manager, 605 texture_manager,
537 cleared); 606 cleared);
538 } 607 }
539 } 608 }
540 } 609 }
541 610
542 void Framebuffer::MarkAttachmentsAsCleared( 611 void Framebuffer::MarkAttachmentsAsCleared(
543 RenderbufferManager* renderbuffer_manager, 612 RenderbufferManager* renderbuffer_manager,
544 TextureManager* texture_manager, 613 TextureManager* texture_manager,
545 bool cleared) { 614 bool cleared) {
546 for (AttachmentMap::iterator it = attachments_.begin(); 615 for (AttachmentMap::iterator it = attachments_.begin();
547 it != attachments_.end(); ++it) { 616 it != attachments_.end(); ++it) {
548 Attachment* attachment = it->second.get(); 617 Attachment* attachment = it->second.get();
549 if (attachment->cleared() != cleared) { 618 if (attachment->cleared() != cleared) {
550 attachment->SetCleared(renderbuffer_manager, texture_manager, cleared); 619 attachment->SetCleared(renderbuffer_manager, texture_manager, cleared);
551 } 620 }
552 } 621 }
553 } 622 }
554 623
555 bool Framebuffer::HasColorAttachment(int index) const { 624 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 { 807 GLenum Framebuffer::GetDrawBuffer(GLenum draw_buffer) const {
739 GLsizei index = static_cast<GLsizei>( 808 GLsizei index = static_cast<GLsizei>(
740 draw_buffer - GL_DRAW_BUFFER0_ARB); 809 draw_buffer - GL_DRAW_BUFFER0_ARB);
741 CHECK(index >= 0 && 810 CHECK(index >= 0 &&
742 index < static_cast<GLsizei>(manager_->max_draw_buffers_)); 811 index < static_cast<GLsizei>(manager_->max_draw_buffers_));
743 return draw_buffers_[index]; 812 return draw_buffers_[index];
744 } 813 }
745 814
746 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) { 815 void Framebuffer::SetDrawBuffers(GLsizei n, const GLenum* bufs) {
747 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_)); 816 DCHECK(n <= static_cast<GLsizei>(manager_->max_draw_buffers_));
748 for (GLsizei i = 0; i < n; ++i) 817 for (GLsizei i = 0; i < n; ++i) {
749 draw_buffers_[i] = bufs[i]; 818 draw_buffers_[i] = bufs[i];
819 adjusted_draw_buffers_[i] = bufs[i];
820 }
750 } 821 }
751 822
752 bool Framebuffer::HasAlphaMRT() const { 823 bool Framebuffer::HasAlphaMRT() const {
753 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) { 824 for (uint32_t i = 0; i < manager_->max_draw_buffers_; ++i) {
754 if (draw_buffers_[i] != GL_NONE) { 825 if (draw_buffers_[i] != GL_NONE) {
755 const Attachment* attachment = GetAttachment(draw_buffers_[i]); 826 const Attachment* attachment = GetAttachment(draw_buffers_[i]);
756 if (!attachment) 827 if (!attachment)
757 continue; 828 continue;
758 if ((GLES2Util::GetChannelsForFormat( 829 if ((GLES2Util::GetChannelsForFormat(
759 attachment->internal_format()) & 0x0008) != 0) 830 attachment->internal_format()) & 0x0008) != 0)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 // TODO(gman): manually detach texture. 882 // TODO(gman): manually detach texture.
812 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0); 883 // glFramebufferTexture2DEXT(target, it->first, GL_TEXTURE_2D, 0, 0);
813 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0); 884 AttachTexture(it->first, NULL, GL_TEXTURE_2D, 0, 0);
814 done = false; 885 done = false;
815 break; 886 break;
816 } 887 }
817 } 888 }
818 } while (!done); 889 } while (!done);
819 } 890 }
820 891
892 void Framebuffer::UpdateColorAttachmentBaseTypes() {
893 ResetColorAttachmentBaseTypes();
894 for (AttachmentMap::const_iterator it = attachments_.begin();
895 it != attachments_.end(); ++it) {
896 if (it->first < GL_COLOR_ATTACHMENT0 ||
897 it->first >= GL_COLOR_ATTACHMENT0 + manager_->max_draw_buffers_) {
piman 2016/07/13 22:35:55 this should be manager_->max_color_attachments_
898 continue;
899 }
900 size_t index = it->first - GL_COLOR_ATTACHMENT0;
piman 2016/07/13 22:35:55 I think there's confusion about how color_attachme
piman 2016/07/13 23:16:36 Ok, so I now understand, this works in ES because
901 Attachment* attachment = it->second.get();
902 GLenum internal_format = attachment->internal_format();
903 if (GLES2Util::IsSignedIntegerFormat(internal_format)) {
904 color_attachment_base_types_[index] = SHADER_VARIABLE_INT;
905 } else if (GLES2Util::IsUnsignedIntegerFormat(internal_format)) {
906 color_attachment_base_types_[index] = SHADER_VARIABLE_UINT;
907 } else {
908 color_attachment_base_types_[index] = SHADER_VARIABLE_FLOAT;
909 }
910 }
911 }
912
821 Framebuffer* FramebufferManager::GetFramebuffer( 913 Framebuffer* FramebufferManager::GetFramebuffer(
822 GLuint client_id) { 914 GLuint client_id) {
823 FramebufferMap::iterator it = framebuffers_.find(client_id); 915 FramebufferMap::iterator it = framebuffers_.find(client_id);
824 return it != framebuffers_.end() ? it->second.get() : NULL; 916 return it != framebuffers_.end() ? it->second.get() : NULL;
825 } 917 }
826 918
827 void FramebufferManager::RemoveFramebuffer(GLuint client_id) { 919 void FramebufferManager::RemoveFramebuffer(GLuint client_id) {
828 FramebufferMap::iterator it = framebuffers_.find(client_id); 920 FramebufferMap::iterator it = framebuffers_.find(client_id);
829 if (it != framebuffers_.end()) { 921 if (it != framebuffers_.end()) {
830 it->second->MarkAsDeleted(); 922 it->second->MarkAsDeleted();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 1026
935 bool FramebufferManager::IsComplete( 1027 bool FramebufferManager::IsComplete(
936 Framebuffer* framebuffer) { 1028 Framebuffer* framebuffer) {
937 DCHECK(framebuffer); 1029 DCHECK(framebuffer);
938 return framebuffer->framebuffer_complete_state_count_id() == 1030 return framebuffer->framebuffer_complete_state_count_id() ==
939 framebuffer_state_change_count_; 1031 framebuffer_state_change_count_;
940 } 1032 }
941 1033
942 } // namespace gles2 1034 } // namespace gles2
943 } // namespace gpu 1035 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/framebuffer_manager.h ('k') | gpu/command_buffer/service/framebuffer_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698