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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/service/buffer_manager.cc
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index e1a2171e1bd122f16e261b7a66fe072f1464f9b1..8c470fc1063300010b73a8e2ebc4d92534ed3443 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -47,7 +47,8 @@ BufferManager::BufferManager(MemoryTracker* memory_tracker,
feature_info
? feature_info->workarounds()
.use_client_side_arrays_for_stream_buffers
- : 0) {
+ : 0),
+ mapped_buffer_count_(0) {
// When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
// so don't register a dump provider.
if (memory_tracker_) {
@@ -142,8 +143,9 @@ Buffer::~Buffer() {
GLuint id = service_id();
glDeleteBuffersARB(1, &id);
}
+ RemoveMappedRange();
manager_->StopTracking(this);
- manager_ = NULL;
+ manager_ = nullptr;
}
}
@@ -158,6 +160,7 @@ const GLvoid* Buffer::StageShadow(bool use_shadow,
static_cast<const uint8_t*>(data) + size);
} else {
shadow_.resize(size);
+ memset(shadow_.data(), 0, static_cast<size_t>(size));
}
return shadow_.data();
} else {
@@ -190,16 +193,13 @@ bool Buffer::CheckRange(GLintptr offset, GLsizeiptr size) const {
return max.IsValid() && max.ValueOrDefault(0) <= size_;
}
-bool Buffer::SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data) {
- if (!CheckRange(offset, size)) {
- return false;
- }
+void Buffer::SetRange(GLintptr offset, GLsizeiptr size, const GLvoid * data) {
+ DCHECK(CheckRange(offset, size));
if (!shadow_.empty()) {
DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
memcpy(shadow_.data() + offset, data, size);
ClearCache();
}
- return true;
}
const void* Buffer::GetRange(GLintptr offset, GLsizeiptr size) const {
@@ -334,6 +334,20 @@ bool Buffer::GetMaxValueForRange(
return true;
}
+void Buffer::SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access,
+ void* pointer, scoped_refptr<gpu::Buffer> shm,
+ unsigned int shm_offset) {
+ mapped_range_.reset(
+ new MappedRange(offset, size, access, pointer, shm, shm_offset));
+ manager_->IncreaseMappedBufferCount();
+}
+
+void Buffer::RemoveMappedRange() {
+ if (mapped_range_.get())
+ manager_->DecreaseMappedBufferCount();
+ mapped_range_.reset(nullptr);
+}
+
bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const {
// This doesn't need to be fast. It's only used during slow queries.
for (BufferMap::const_iterator it = buffers_.begin();
@@ -443,14 +457,24 @@ void BufferManager::DoBufferData(
ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
if (IsUsageClientSideArray(usage)) {
GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0;
- glBufferData(target, empty_size, NULL, usage);
+ glBufferData(target, empty_size, nullptr, usage);
} else {
- glBufferData(target, size, data, usage);
+ if (data || !size) {
+ glBufferData(target, size, data, usage);
+ } else {
+ std::unique_ptr<char[]> zero(new char[size]);
+ memset(zero.get(), 0, size);
+ glBufferData(target, size, zero.get(), usage);
+ }
}
GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
if (error != GL_NO_ERROR) {
+ DCHECK_EQ(static_cast<GLenum>(GL_OUT_OF_MEMORY), error);
size = 0;
+ // TODO(zmo): This doesn't seem correct. There might be shadow data from
+ // a previous successful BufferData() call.
buffer->StageShadow(false, 0, nullptr); // Also clear the shadow.
+ return;
}
SetInfo(buffer, target, size, usage, use_shadow);
@@ -459,37 +483,18 @@ void BufferManager::DoBufferData(
void BufferManager::ValidateAndDoBufferSubData(
ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size,
const GLvoid * data) {
- const char* func_name = "glBufferSubData";
-
- ErrorState* error_state = context_state->GetErrorState();
- Buffer* buffer = GetBufferInfoForTarget(context_state, target);
+ Buffer* buffer = RequestBufferAccess(
+ context_state, target, offset, size, "glBufferSubData");
if (!buffer) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
- "unknown buffer");
return;
}
-
- if (buffer->GetMappedRange()) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
- "buffer is mapped");
- return;
- }
-
- DoBufferSubData(error_state, buffer, target, offset, size, data);
+ DoBufferSubData(buffer, target, offset, size, data);
}
void BufferManager::DoBufferSubData(
- ErrorState* error_state,
- Buffer* buffer,
- GLenum target,
- GLintptr offset,
- GLsizeiptr size,
+ Buffer* buffer, GLenum target, GLintptr offset, GLsizeiptr size,
const GLvoid* data) {
- if (!buffer->SetRange(offset, size, data)) {
- ERRORSTATE_SET_GL_ERROR(
- error_state, GL_INVALID_VALUE, "glBufferSubData", "out of range");
- return;
- }
+ buffer->SetRange(offset, size, data);
if (!buffer->IsClientSideArray()) {
glBufferSubData(target, offset, size, data);
@@ -500,42 +505,16 @@ void BufferManager::ValidateAndDoCopyBufferSubData(
ContextState* context_state, GLenum readtarget, GLenum writetarget,
GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size) {
const char* func_name = "glCopyBufferSubData";
- ErrorState* error_state = context_state->GetErrorState();
-
- Buffer* readbuffer = GetBufferInfoForTarget(context_state, readtarget);
- if (!readbuffer) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
- "no buffer is bound to readtarget");
+ Buffer* readbuffer = RequestBufferAccess(
+ context_state, readtarget, readoffset, size, func_name);
+ if (!readbuffer)
return;
- }
- if (readbuffer->GetMappedRange()) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
- "buffer bound to readtarget is mapped");
+ Buffer* writebuffer = RequestBufferAccess(
+ context_state, writetarget, writeoffset, size, func_name);
+ if (!writebuffer)
return;
- }
- if (!readbuffer->CheckRange(readoffset, size)) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
- "readoffset/size out of range");
- return;
- }
-
- Buffer* writebuffer = GetBufferInfoForTarget(context_state, writetarget);
- if (!writebuffer) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
- "no buffer is bound to writetarget");
- return;
- }
- if (writebuffer->GetMappedRange()) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
- "buffer bound to writetarget is mapped");
- return;
- }
- if (!writebuffer->CheckRange(writeoffset, size)) {
- ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, func_name,
- "writeoffset/size out of range");
- return;
- }
+ ErrorState* error_state = context_state->GetErrorState();
if (readbuffer == writebuffer &&
((writeoffset >= readoffset && writeoffset < readoffset + size) ||
(readoffset >= writeoffset && readoffset < writeoffset + size))) {
@@ -572,8 +551,7 @@ void BufferManager::DoCopyBufferSubData(
if (writebuffer->shadowed()) {
const void* data = readbuffer->GetRange(readoffset, size);
DCHECK(data);
- bool success = writebuffer->SetRange(writeoffset, size, data);
- DCHECK(success);
+ writebuffer->SetRange(writeoffset, size, data);
}
glCopyBufferSubData(readtarget, writetarget, readoffset, writeoffset, size);
@@ -757,5 +735,71 @@ bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
return true;
}
+Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const char* func_name) {
+ DCHECK(context_state);
+ ErrorState* error_state = context_state->GetErrorState();
+
+ std::string msg_tag = base::StringPrintf("bound to target 0x%04x", target);
+ Buffer* buffer = GetBufferInfoForTarget(context_state, target);
+ if (!RequestBufferAccess(error_state, buffer, func_name, msg_tag.c_str())) {
+ return nullptr;
+ }
+ if (!buffer->CheckRange(offset, size)) {
+ std::string msg = base::StringPrintf(
+ "%s : offset/size out of range", msg_tag.c_str());
+ ERRORSTATE_SET_GL_ERROR(
+ error_state, GL_INVALID_VALUE, func_name, msg.c_str());
+ return nullptr;
+ }
+ return buffer;
+}
+
+Buffer* BufferManager::RequestBufferAccess(ContextState* context_state,
+ GLenum target,
+ const char* func_name) {
+ DCHECK(context_state);
+ ErrorState* error_state = context_state->GetErrorState();
+
+ std::string msg_tag = base::StringPrintf("bound to target 0x%04x", target);
+ Buffer* buffer = GetBufferInfoForTarget(context_state, target);
+ return RequestBufferAccess(
+ error_state, buffer, func_name, msg_tag.c_str()) ? buffer : nullptr;
+}
+
+bool BufferManager::RequestBufferAccess(ErrorState* error_state,
+ Buffer* buffer,
+ const char* func_name,
+ const char* message_tag) {
+ DCHECK(error_state);
+
+ if (!buffer || buffer->IsDeleted()) {
+ std::string msg = base::StringPrintf("%s : no buffer", message_tag);
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
+ msg.c_str());
+ return false;
+ }
+ if (buffer->GetMappedRange()) {
+ std::string msg = base::StringPrintf("%s : buffer is mapped", message_tag);
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, func_name,
+ msg.c_str());
+ return false;
+ }
+ return true;
+}
+
+void BufferManager::IncreaseMappedBufferCount() {
+ DCHECK_GT(std::numeric_limits<uint32_t>::max(), mapped_buffer_count_);
+ mapped_buffer_count_++;
+}
+
+void BufferManager::DecreaseMappedBufferCount() {
+ DCHECK_LT(0u, mapped_buffer_count_);
+ mapped_buffer_count_--;
+}
+
} // namespace gles2
} // namespace gpu

Powered by Google App Engine
This is Rietveld 408576698