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

Unified 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: Fix 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 side-by-side diff with in-line comments
Download patch
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);
« 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