| 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 261b2edd10b18f5935d0b9325b6493d487ae7f4a..3281d763a6423c0639260452a503fdf2edd0d17e 100644
|
| --- a/gpu/command_buffer/service/buffer_manager.cc
|
| +++ b/gpu/command_buffer/service/buffer_manager.cc
|
| @@ -119,7 +119,6 @@ Buffer::Buffer(BufferManager* manager, GLuint service_id)
|
| : manager_(manager),
|
| size_(0),
|
| deleted_(false),
|
| - shadowed_(false),
|
| is_client_side_array_(false),
|
| service_id_(service_id),
|
| initial_target_(0),
|
| @@ -138,28 +137,36 @@ Buffer::~Buffer() {
|
| }
|
| }
|
|
|
| -void Buffer::SetInfo(
|
| - GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data,
|
| - bool is_client_side_array) {
|
| - usage_ = usage;
|
| - is_client_side_array_ = is_client_side_array;
|
| - ClearCache();
|
| - if (size != size_ || shadow != shadowed_) {
|
| - shadowed_ = shadow;
|
| - size_ = size;
|
| - if (shadowed_) {
|
| - shadow_.reset(new int8_t[size]);
|
| - } else {
|
| - shadow_.reset();
|
| - }
|
| - }
|
| - if (shadowed_) {
|
| +const GLvoid* Buffer::StageShadow(bool use_shadow,
|
| + GLsizeiptr size,
|
| + const GLvoid* data) {
|
| + shadow_.clear();
|
| + if (use_shadow) {
|
| if (data) {
|
| - memcpy(shadow_.get(), data, size);
|
| + shadow_.insert(shadow_.begin(),
|
| + static_cast<const uint8_t*>(data),
|
| + static_cast<const uint8_t*>(data) + size);
|
| } else {
|
| - memset(shadow_.get(), 0, size);
|
| + shadow_.resize(size);
|
| }
|
| + return shadow_.data();
|
| + } else {
|
| + return data;
|
| }
|
| +}
|
| +
|
| +void Buffer::SetInfo(GLsizeiptr size,
|
| + GLenum usage,
|
| + bool use_shadow,
|
| + bool is_client_side_array) {
|
| + usage_ = usage;
|
| + is_client_side_array_ = is_client_side_array;
|
| + ClearCache();
|
| +
|
| + // Shadow must have been setup already.
|
| + DCHECK_EQ(shadow_.size(), static_cast<size_t>(use_shadow ? size : 0u));
|
| + size_ = size;
|
| +
|
| mapped_range_.reset(nullptr);
|
| }
|
|
|
| @@ -177,8 +184,9 @@ bool Buffer::SetRange(
|
| if (!CheckRange(offset, size)) {
|
| return false;
|
| }
|
| - if (shadowed_) {
|
| - memcpy(shadow_.get() + offset, data, size);
|
| + if (!shadow_.empty()) {
|
| + DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
|
| + memcpy(shadow_.data() + offset, data, size);
|
| ClearCache();
|
| }
|
| return true;
|
| @@ -186,13 +194,14 @@ bool Buffer::SetRange(
|
|
|
| const void* Buffer::GetRange(
|
| GLintptr offset, GLsizeiptr size) const {
|
| - if (!shadowed_) {
|
| + if (shadow_.empty()) {
|
| return NULL;
|
| }
|
| if (!CheckRange(offset, size)) {
|
| return NULL;
|
| }
|
| - return shadow_.get() + offset;
|
| + DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size());
|
| + return shadow_.data() + offset;
|
| }
|
|
|
| void Buffer::ClearCache() {
|
| @@ -280,7 +289,7 @@ bool Buffer::GetMaxValueForRange(
|
| return false;
|
| }
|
|
|
| - if (!shadowed_) {
|
| + if (shadow_.empty()) {
|
| return false;
|
| }
|
|
|
| @@ -288,24 +297,24 @@ bool Buffer::GetMaxValueForRange(
|
| GLuint max_v = 0;
|
| switch (type) {
|
| case GL_UNSIGNED_BYTE:
|
| - max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count,
|
| - primitive_restart_index);
|
| + max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count,
|
| + primitive_restart_index);
|
| break;
|
| case GL_UNSIGNED_SHORT:
|
| // Check we are not accessing an odd byte for a 2 byte value.
|
| if ((offset & 1) != 0) {
|
| return false;
|
| }
|
| - max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count,
|
| - primitive_restart_index);
|
| + max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count,
|
| + primitive_restart_index);
|
| break;
|
| case GL_UNSIGNED_INT:
|
| // Check we are not accessing a non aligned address for a 4 byte value.
|
| if ((offset & 3) != 0) {
|
| return false;
|
| }
|
| - max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count,
|
| - primitive_restart_index);
|
| + max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count,
|
| + primitive_restart_index);
|
| break;
|
| default:
|
| NOTREACHED(); // should never get here by validation.
|
| @@ -338,19 +347,25 @@ bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() {
|
| .use_non_zero_size_for_client_side_stream_buffers;
|
| }
|
|
|
| -void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size,
|
| - GLenum usage, const GLvoid* data) {
|
| - DCHECK(buffer);
|
| - memory_type_tracker_->TrackMemFree(buffer->size());
|
| +bool BufferManager::UseShadowBuffer(GLenum target, GLenum usage) {
|
| const bool is_client_side_array = IsUsageClientSideArray(usage);
|
| const bool support_fixed_attribs =
|
| gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
|
| +
|
| // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002.
|
| - const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER ||
|
| - allow_buffers_on_multiple_targets_ ||
|
| - (allow_fixed_attribs_ && !support_fixed_attribs) ||
|
| - is_client_side_array;
|
| - buffer->SetInfo(size, usage, shadow, data, is_client_side_array);
|
| + return (
|
| + target == GL_ELEMENT_ARRAY_BUFFER || allow_buffers_on_multiple_targets_ ||
|
| + (allow_fixed_attribs_ && !support_fixed_attribs) || is_client_side_array);
|
| +}
|
| +
|
| +void BufferManager::SetInfo(Buffer* buffer,
|
| + GLenum target,
|
| + GLsizeiptr size,
|
| + GLenum usage,
|
| + bool use_shadow) {
|
| + DCHECK(buffer);
|
| + memory_type_tracker_->TrackMemFree(buffer->size());
|
| + buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage));
|
| memory_type_tracker_->TrackMemAlloc(buffer->size());
|
| }
|
|
|
| @@ -398,13 +413,10 @@ void BufferManager::DoBufferData(
|
| GLsizeiptr size,
|
| GLenum usage,
|
| const GLvoid* data) {
|
| - // Clear the buffer to 0 if no initial data was passed in.
|
| - scoped_ptr<int8_t[]> zero;
|
| - if (!data) {
|
| - zero.reset(new int8_t[size]);
|
| - memset(zero.get(), 0, size);
|
| - data = zero.get();
|
| - }
|
| + // Stage the shadow buffer first if we are using a shadow buffer so that we
|
| + // validate what we store internally.
|
| + const bool use_shadow = UseShadowBuffer(target, usage);
|
| + data = buffer->StageShadow(use_shadow, size, data);
|
|
|
| ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData");
|
| if (IsUsageClientSideArray(usage)) {
|
| @@ -414,11 +426,12 @@ void BufferManager::DoBufferData(
|
| glBufferData(target, size, data, usage);
|
| }
|
| GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData");
|
| - if (error == GL_NO_ERROR) {
|
| - SetInfo(buffer, target, size, usage, data);
|
| - } else {
|
| - SetInfo(buffer, target, 0, usage, NULL);
|
| + if (error != GL_NO_ERROR) {
|
| + size = 0;
|
| + buffer->StageShadow(false, 0, nullptr); // Also clear the shadow.
|
| }
|
| +
|
| + SetInfo(buffer, target, size, usage, use_shadow);
|
| }
|
|
|
| void BufferManager::ValidateAndDoBufferSubData(
|
|
|