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

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

Issue 2435803004: Initialize buffers before allowing access to them. (Closed)
Patch Set: win failure Created 4 years, 2 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/buffer_manager.h" 5 #include "gpu/command_buffer/service/buffer_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
(...skipping 29 matching lines...) Expand all
40 max_buffer_size_(kDefaultMaxBufferSize), 40 max_buffer_size_(kDefaultMaxBufferSize),
41 allow_buffers_on_multiple_targets_(false), 41 allow_buffers_on_multiple_targets_(false),
42 allow_fixed_attribs_(false), 42 allow_fixed_attribs_(false),
43 buffer_count_(0), 43 buffer_count_(0),
44 primitive_restart_fixed_index_(0), 44 primitive_restart_fixed_index_(0),
45 lost_context_(false), 45 lost_context_(false),
46 use_client_side_arrays_for_stream_buffers_( 46 use_client_side_arrays_for_stream_buffers_(
47 feature_info 47 feature_info
48 ? feature_info->workarounds() 48 ? feature_info->workarounds()
49 .use_client_side_arrays_for_stream_buffers 49 .use_client_side_arrays_for_stream_buffers
50 : 0) { 50 : 0),
51 mapped_buffer_count_(0) {
51 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_| 52 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
52 // so don't register a dump provider. 53 // so don't register a dump provider.
53 if (memory_tracker_) { 54 if (memory_tracker_) {
54 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( 55 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
55 this, "gpu::BufferManager", base::ThreadTaskRunnerHandle::Get()); 56 this, "gpu::BufferManager", base::ThreadTaskRunnerHandle::Get());
56 } 57 }
57 } 58 }
58 59
59 BufferManager::~BufferManager() { 60 BufferManager::~BufferManager() {
60 DCHECK(buffers_.empty()); 61 DCHECK(buffers_.empty());
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 usage_(GL_STATIC_DRAW) { 136 usage_(GL_STATIC_DRAW) {
136 manager_->StartTracking(this); 137 manager_->StartTracking(this);
137 } 138 }
138 139
139 Buffer::~Buffer() { 140 Buffer::~Buffer() {
140 if (manager_) { 141 if (manager_) {
141 if (!manager_->lost_context_) { 142 if (!manager_->lost_context_) {
142 GLuint id = service_id(); 143 GLuint id = service_id();
143 glDeleteBuffersARB(1, &id); 144 glDeleteBuffersARB(1, &id);
144 } 145 }
146 RemoveMappedRange();
145 manager_->StopTracking(this); 147 manager_->StopTracking(this);
146 manager_ = NULL; 148 manager_ = nullptr;
147 } 149 }
148 } 150 }
149 151
150 const GLvoid* Buffer::StageShadow(bool use_shadow, 152 const GLvoid* Buffer::StageShadow(bool use_shadow,
151 GLsizeiptr size, 153 GLsizeiptr size,
152 const GLvoid* data) { 154 const GLvoid* data) {
153 shadow_.clear(); 155 shadow_.clear();
154 if (use_shadow) { 156 if (use_shadow) {
155 if (data) { 157 if (data) {
156 shadow_.insert(shadow_.begin(), 158 shadow_.insert(shadow_.begin(),
157 static_cast<const uint8_t*>(data), 159 static_cast<const uint8_t*>(data),
158 static_cast<const uint8_t*>(data) + size); 160 static_cast<const uint8_t*>(data) + size);
159 } else { 161 } else {
160 shadow_.resize(size); 162 shadow_.resize(size);
163 memset(shadow_.data(), 0, static_cast<size_t>(size));
161 } 164 }
162 return shadow_.data(); 165 return shadow_.data();
163 } else { 166 } else {
164 return data; 167 return data;
165 } 168 }
166 } 169 }
167 170
168 void Buffer::SetInfo(GLsizeiptr size, 171 void Buffer::SetInfo(GLsizeiptr size,
169 GLenum usage, 172 GLenum usage,
170 bool use_shadow, 173 bool use_shadow,
(...skipping 12 matching lines...) Expand all
183 bool Buffer::CheckRange(GLintptr offset, GLsizeiptr size) const { 186 bool Buffer::CheckRange(GLintptr offset, GLsizeiptr size) const {
184 if (offset < 0 || offset > std::numeric_limits<int32_t>::max() || 187 if (offset < 0 || offset > std::numeric_limits<int32_t>::max() ||
185 size < 0 || size > std::numeric_limits<int32_t>::max()) { 188 size < 0 || size > std::numeric_limits<int32_t>::max()) {
186 return false; 189 return false;
187 } 190 }
188 base::CheckedNumeric<int32_t> max = offset; 191 base::CheckedNumeric<int32_t> max = offset;
189 max += size; 192 max += size;
190 return max.IsValid() && max.ValueOrDefault(0) <= size_; 193 return max.IsValid() && max.ValueOrDefault(0) <= size_;
191 } 194 }
192 195
193 bool Buffer::SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data) { 196 void Buffer::SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data) {
194 if (!CheckRange(offset, size)) { 197 DCHECK(CheckRange(offset, size));
195 return false;
196 }
197 if (!shadow_.empty()) { 198 if (!shadow_.empty()) {
198 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); 199 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
199 memcpy(shadow_.data() + offset, data, size); 200 memcpy(shadow_.data() + offset, data, size);
200 ClearCache(); 201 ClearCache();
201 } 202 }
202 return true;
203 } 203 }
204 204
205 const void* Buffer::GetRange(GLintptr offset, GLsizeiptr size) const { 205 const void* Buffer::GetRange(GLintptr offset, GLsizeiptr size) const {
206 if (shadow_.empty()) { 206 if (shadow_.empty()) {
207 return NULL; 207 return NULL;
208 } 208 }
209 if (!CheckRange(offset, size)) { 209 if (!CheckRange(offset, size)) {
210 return NULL; 210 return NULL;
211 } 211 }
212 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); 212 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 break; 327 break;
328 default: 328 default:
329 NOTREACHED(); // should never get here by validation. 329 NOTREACHED(); // should never get here by validation.
330 break; 330 break;
331 } 331 }
332 range_set_.insert(std::make_pair(range, max_v)); 332 range_set_.insert(std::make_pair(range, max_v));
333 *max_value = max_v; 333 *max_value = max_v;
334 return true; 334 return true;
335 } 335 }
336 336
337 void Buffer::SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
338 void* pointer, scoped_refptr<gpu::Buffer> shm,
339 unsigned int shm_offset) {
340 mapped_range_.reset(
341 new MappedRange(offset, size, access, pointer, shm, shm_offset));
342 manager_->IncreaseMappedBufferCount();
343 }
344
345 void Buffer::RemoveMappedRange() {
346 if (mapped_range_.get())
347 manager_->DecreaseMappedBufferCount();
348 mapped_range_.reset(nullptr);
349 }
350
337 bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { 351 bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const {
338 // This doesn't need to be fast. It's only used during slow queries. 352 // This doesn't need to be fast. It's only used during slow queries.
339 for (BufferMap::const_iterator it = buffers_.begin(); 353 for (BufferMap::const_iterator it = buffers_.begin();
340 it != buffers_.end(); ++it) { 354 it != buffers_.end(); ++it) {
341 if (it->second->service_id() == service_id) { 355 if (it->second->service_id() == service_id) {
342 *client_id = it->first; 356 *client_id = it->first;
343 return true; 357 return true;
344 } 358 }
345 } 359 }
346 return false; 360 return false;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 GLenum usage, 450 GLenum usage,
437 const GLvoid* data) { 451 const GLvoid* data) {
438 // Stage the shadow buffer first if we are using a shadow buffer so that we 452 // Stage the shadow buffer first if we are using a shadow buffer so that we
439 // validate what we store internally. 453 // validate what we store internally.
440 const bool use_shadow = UseShadowBuffer(buffer->initial_target(), usage); 454 const bool use_shadow = UseShadowBuffer(buffer->initial_target(), usage);
441 data = buffer->StageShadow(use_shadow, size, data); 455 data = buffer->StageShadow(use_shadow, size, data);
442 456
443 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); 457 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
444 if (IsUsageClientSideArray(usage)) { 458 if (IsUsageClientSideArray(usage)) {
445 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; 459 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
446 glBufferData(target, empty_size, NULL, usage); 460 glBufferData(target, empty_size, nullptr, usage);
447 } else { 461 } else {
448 glBufferData(target, size, data, usage); 462 if (data || !size) {
463 glBufferData(target, size, data, usage);
464 } else {
465 std::unique_ptr<char[]> zero(new char[size]);
466 memset(zero.get(), 0, size);
467 glBufferData(target, size, zero.get(), usage);
468 }
449 } 469 }
450 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); 470 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
451 if (error != GL_NO_ERROR) { 471 if (error != GL_NO_ERROR) {
472 DCHECK_EQ(static_cast<GLenum>(GL_OUT_OF_MEMORY), error);
452 size = 0; 473 size = 0;
474 // TODO(zmo): This doesn't seem correct. There might be shadow data from
475 // a previous successful BufferData() call.
453 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow. 476 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow.
477 return;
454 } 478 }
455 479
456 SetInfo(buffer, target, size, usage, use_shadow); 480 SetInfo(buffer, target, size, usage, use_shadow);
457 } 481 }
458 482
459 void BufferManager::ValidateAndDoBufferSubData( 483 void BufferManager::ValidateAndDoBufferSubData(
460 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, 484 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
461 const GLvoid * data) { 485 const GLvoid * data) {
462 const char* func_name = "glBufferSubData"; 486 Buffer* buffer = RequestBufferAccess(
463 487 context_state, target, offset, size, "glBufferSubData");
464 ErrorState* error_state = context_state->GetErrorState();
465 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
466 if (!buffer) { 488 if (!buffer) {
467 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
468 "unknown buffer");
469 return; 489 return;
470 } 490 }
471 491 DoBufferSubData(buffer, target, offset, size, data);
472 if (buffer->GetMappedRange()) {
473 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
474 "buffer is mapped");
475 return;
476 }
477
478 DoBufferSubData(error_state, buffer, target, offset, size, data);
479 } 492 }
480 493
481 void BufferManager::DoBufferSubData( 494 void BufferManager::DoBufferSubData(
482 ErrorState* error_state, 495 Buffer* buffer, GLenum target, GLintptr offset, GLsizeiptr size,
483 Buffer* buffer,
484 GLenum target,
485 GLintptr offset,
486 GLsizeiptr size,
487 const GLvoid* data) { 496 const GLvoid* data) {
488 if (!buffer->SetRange(offset, size, data)) { 497 buffer->SetRange(offset, size, data);
489 ERRORSTATE_SET_GL_ERROR(
490 error_state, GL_INVALID_VALUE, "glBufferSubData", "out of range");
491 return;
492 }
493 498
494 if (!buffer->IsClientSideArray()) { 499 if (!buffer->IsClientSideArray()) {
495 glBufferSubData(target, offset, size, data); 500 glBufferSubData(target, offset, size, data);
496 } 501 }
497 } 502 }
498 503
499 void BufferManager::ValidateAndDoCopyBufferSubData( 504 void BufferManager::ValidateAndDoCopyBufferSubData(
500 ContextState* context_state, GLenum readtarget, GLenum writetarget, 505 ContextState* context_state, GLenum readtarget, GLenum writetarget,
501 GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) { 506 GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
502 const char* func_name = "glCopyBufferSubData"; 507 const char* func_name = "glCopyBufferSubData";
508 Buffer* readbuffer = RequestBufferAccess(
509 context_state, readtarget, readoffset, size, func_name);
510 if (!readbuffer)
511 return;
512 Buffer* writebuffer = RequestBufferAccess(
513 context_state, writetarget, writeoffset, size, func_name);
514 if (!writebuffer)
515 return;
516
503 ErrorState* error_state = context_state->GetErrorState(); 517 ErrorState* error_state = context_state->GetErrorState();
504
505 Buffer* readbuffer = GetBufferInfoForTarget(context_state, readtarget);
506 if (!readbuffer) {
507 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
508 "no buffer is bound to readtarget");
509 return;
510 }
511 if (readbuffer->GetMappedRange()) {
512 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
513 "buffer bound to readtarget is mapped");
514 return;
515 }
516 if (!readbuffer->CheckRange(readoffset, size)) {
517 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
518 "readoffset/size out of range");
519 return;
520 }
521
522 Buffer* writebuffer = GetBufferInfoForTarget(context_state, writetarget);
523 if (!writebuffer) {
524 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
525 "no buffer is bound to writetarget");
526 return;
527 }
528 if (writebuffer->GetMappedRange()) {
529 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
530 "buffer bound to writetarget is mapped");
531 return;
532 }
533 if (!writebuffer->CheckRange(writeoffset, size)) {
534 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
535 "writeoffset/size out of range");
536 return;
537 }
538
539 if (readbuffer == writebuffer && 518 if (readbuffer == writebuffer &&
540 ((writeoffset >= readoffset && writeoffset < readoffset + size) || 519 ((writeoffset >= readoffset && writeoffset < readoffset + size) ||
541 (readoffset >= writeoffset && readoffset < writeoffset + size))) { 520 (readoffset >= writeoffset && readoffset < writeoffset + size))) {
542 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name, 521 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
543 "read/write ranges overlap"); 522 "read/write ranges overlap");
544 return; 523 return;
545 } 524 }
546 525
547 if (!allow_buffers_on_multiple_targets_) { 526 if (!allow_buffers_on_multiple_targets_) {
548 if ((readbuffer->initial_target() == GL_ELEMENT_ARRAY_BUFFER && 527 if ((readbuffer->initial_target() == GL_ELEMENT_ARRAY_BUFFER &&
(...skipping 16 matching lines...) Expand all
565 GLintptr readoffset, 544 GLintptr readoffset,
566 Buffer* writebuffer, 545 Buffer* writebuffer,
567 GLenum writetarget, 546 GLenum writetarget,
568 GLintptr writeoffset, 547 GLintptr writeoffset,
569 GLsizeiptr size) { 548 GLsizeiptr size) {
570 DCHECK(readbuffer); 549 DCHECK(readbuffer);
571 DCHECK(writebuffer); 550 DCHECK(writebuffer);
572 if (writebuffer->shadowed()) { 551 if (writebuffer->shadowed()) {
573 const void* data = readbuffer->GetRange(readoffset, size); 552 const void* data = readbuffer->GetRange(readoffset, size);
574 DCHECK(data); 553 DCHECK(data);
575 bool success = writebuffer->SetRange(writeoffset, size, data); 554 writebuffer->SetRange(writeoffset, size, data);
576 DCHECK(success);
577 } 555 }
578 556
579 glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size); 557 glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size);
580 } 558 }
581 559
582 void BufferManager::ValidateAndDoGetBufferParameteri64v( 560 void BufferManager::ValidateAndDoGetBufferParameteri64v(
583 ContextState* context_state, GLenum target, GLenum pname, GLint64* params) { 561 ContextState* context_state, GLenum target, GLenum pname, GLint64* params) {
584 Buffer* buffer = GetBufferInfoForTarget(context_state, target); 562 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
585 if (!buffer) { 563 if (!buffer) {
586 ERRORSTATE_SET_GL_ERROR( 564 ERRORSTATE_SET_GL_ERROR(
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 static_cast<uint64_t>(buffer->size())); 728 static_cast<uint64_t>(buffer->size()));
751 729
752 auto guid = gl::GetGLBufferGUIDForTracing(share_group_tracing_guid, 730 auto guid = gl::GetGLBufferGUIDForTracing(share_group_tracing_guid,
753 client_buffer_id); 731 client_buffer_id);
754 pmd->CreateSharedGlobalAllocatorDump(guid); 732 pmd->CreateSharedGlobalAllocatorDump(guid);
755 pmd->AddOwnershipEdge(dump->guid(), guid); 733 pmd->AddOwnershipEdge(dump->guid(), guid);
756 } 734 }
757 return true; 735 return true;
758 } 736 }
759 737
738 Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
739 GLenum target,
740 GLintptr offset,
741 GLsizeiptr size,
742 const char* func_name) {
743 DCHECK(context_state);
744 ErrorState* error_state = context_state->GetErrorState();
745
746 std::string msg_tag = base::StringPrintf("bound to target 0x%04x", target);
747 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
748 if (!RequestBufferAccess(error_state, buffer, func_name, msg_tag.c_str())) {
749 return nullptr;
750 }
751 if (!buffer->CheckRange(offset, size)) {
752 std::string msg = base::StringPrintf(
753 "%s : offset/size out of range", msg_tag.c_str());
754 ERRORSTATE_SET_GL_ERROR(
755 error_state, GL_INVALID_VALUE, func_name, msg.c_str());
756 return nullptr;
757 }
758 return buffer;
759 }
760
761 Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
762 GLenum target,
763 const char* func_name) {
764 DCHECK(context_state);
765 ErrorState* error_state = context_state->GetErrorState();
766
767 std::string msg_tag = base::StringPrintf("bound to target 0x%04x", target);
768 Buffer* buffer = GetBufferInfoForTarget(context_state, target);
769 return RequestBufferAccess(
770 error_state, buffer, func_name, msg_tag.c_str()) ? buffer : nullptr;
771 }
772
773 bool BufferManager::RequestBufferAccess(ErrorState* error_state,
774 Buffer* buffer,
775 const char* func_name,
776 const char* message_tag) {
777 DCHECK(error_state);
778
779 if (!buffer || buffer->IsDeleted()) {
780 std::string msg = base::StringPrintf("%s : no buffer", message_tag);
781 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
782 msg.c_str());
783 return false;
784 }
785 if (buffer->GetMappedRange()) {
786 std::string msg = base::StringPrintf("%s : buffer is mapped", message_tag);
787 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
788 msg.c_str());
789 return false;
790 }
791 return true;
792 }
793
794 void BufferManager::IncreaseMappedBufferCount() {
795 DCHECK_GT(std::numeric_limits<uint32_t>::max(), mapped_buffer_count_);
796 mapped_buffer_count_++;
797 }
798
799 void BufferManager::DecreaseMappedBufferCount() {
800 DCHECK_LT(0u, mapped_buffer_count_);
801 mapped_buffer_count_--;
802 }
803
760 } // namespace gles2 804 } // namespace gles2
761 } // namespace gpu 805 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698