Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 void* Buffer::MappedRange::GetShmPointer() const { | 112 void* Buffer::MappedRange::GetShmPointer() const { |
| 113 DCHECK(shm.get()); | 113 DCHECK(shm.get()); |
| 114 return shm->GetDataAddress(static_cast<unsigned int>(offset), | 114 return shm->GetDataAddress(static_cast<unsigned int>(offset), |
| 115 static_cast<unsigned int>(size)); | 115 static_cast<unsigned int>(size)); |
| 116 } | 116 } |
| 117 | 117 |
| 118 Buffer::Buffer(BufferManager* manager, GLuint service_id) | 118 Buffer::Buffer(BufferManager* manager, GLuint service_id) |
| 119 : manager_(manager), | 119 : manager_(manager), |
| 120 size_(0), | 120 size_(0), |
| 121 deleted_(false), | 121 deleted_(false), |
| 122 shadowed_(false), | |
| 123 is_client_side_array_(false), | 122 is_client_side_array_(false), |
| 124 service_id_(service_id), | 123 service_id_(service_id), |
| 125 initial_target_(0), | 124 initial_target_(0), |
| 126 usage_(GL_STATIC_DRAW) { | 125 usage_(GL_STATIC_DRAW) { |
| 127 manager_->StartTracking(this); | 126 manager_->StartTracking(this); |
| 128 } | 127 } |
| 129 | 128 |
| 130 Buffer::~Buffer() { | 129 Buffer::~Buffer() { |
| 131 if (manager_) { | 130 if (manager_) { |
| 132 if (manager_->have_context_) { | 131 if (manager_->have_context_) { |
| 133 GLuint id = service_id(); | 132 GLuint id = service_id(); |
| 134 glDeleteBuffersARB(1, &id); | 133 glDeleteBuffersARB(1, &id); |
| 135 } | 134 } |
| 136 manager_->StopTracking(this); | 135 manager_->StopTracking(this); |
| 137 manager_ = NULL; | 136 manager_ = NULL; |
| 138 } | 137 } |
| 139 } | 138 } |
| 140 | 139 |
| 140 const GLvoid* Buffer::StageShadow(bool use_shadow, GLsizeiptr size, | |
| 141 const GLvoid* data) { | |
| 142 if (use_shadow) { | |
| 143 shadow_.resize(size); | |
|
piman
2016/04/01 00:09:46
Why the change to std::vector? We never need to ap
David Yen
2016/04/01 17:00:53
The reason I changed it to a vector was to reduce
| |
| 144 if (data) { | |
| 145 memcpy(shadow_.data(), data, size); | |
| 146 } else { | |
| 147 memset(shadow_.data(), 0, size); | |
| 148 } | |
| 149 return shadow_.data(); | |
| 150 } else { | |
| 151 shadow_.clear(); | |
| 152 return data; | |
| 153 } | |
| 154 } | |
| 155 | |
| 141 void Buffer::SetInfo( | 156 void Buffer::SetInfo( |
| 142 GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, | 157 GLsizeiptr size, GLenum usage, bool shadow, bool is_client_side_array) { |
|
Ken Russell (switch to Gerrit)
2016/03/31 23:28:04
It might be more clear now to rename "shadow" to "
David Yen
2016/04/01 17:00:53
Done.
| |
| 143 bool is_client_side_array) { | |
| 144 usage_ = usage; | 158 usage_ = usage; |
| 145 is_client_side_array_ = is_client_side_array; | 159 is_client_side_array_ = is_client_side_array; |
| 146 ClearCache(); | 160 ClearCache(); |
| 147 if (size != size_ || shadow != shadowed_) { | 161 |
| 148 shadowed_ = shadow; | 162 // Shadow must have been setup already. |
| 149 size_ = size; | 163 DCHECK_EQ(shadow_.size(), static_cast<size_t>(shadow ? size : 0u)); |
| 150 if (shadowed_) { | 164 size_ = size; |
| 151 shadow_.reset(new int8_t[size]); | 165 |
| 152 } else { | |
| 153 shadow_.reset(); | |
| 154 } | |
| 155 } | |
| 156 if (shadowed_) { | |
| 157 if (data) { | |
| 158 memcpy(shadow_.get(), data, size); | |
| 159 } else { | |
| 160 memset(shadow_.get(), 0, size); | |
| 161 } | |
| 162 } | |
| 163 mapped_range_.reset(nullptr); | 166 mapped_range_.reset(nullptr); |
| 164 } | 167 } |
| 165 | 168 |
| 166 bool Buffer::CheckRange( | 169 bool Buffer::CheckRange( |
| 167 GLintptr offset, GLsizeiptr size) const { | 170 GLintptr offset, GLsizeiptr size) const { |
| 168 int32_t end = 0; | 171 int32_t end = 0; |
| 169 return offset >= 0 && size >= 0 && | 172 return offset >= 0 && size >= 0 && |
| 170 offset <= std::numeric_limits<int32_t>::max() && | 173 offset <= std::numeric_limits<int32_t>::max() && |
| 171 size <= std::numeric_limits<int32_t>::max() && | 174 size <= std::numeric_limits<int32_t>::max() && |
| 172 SafeAddInt32(offset, size, &end) && end <= size_; | 175 SafeAddInt32(offset, size, &end) && end <= size_; |
| 173 } | 176 } |
| 174 | 177 |
| 175 bool Buffer::SetRange( | 178 bool Buffer::SetRange( |
| 176 GLintptr offset, GLsizeiptr size, const GLvoid * data) { | 179 GLintptr offset, GLsizeiptr size, const GLvoid * data) { |
| 177 if (!CheckRange(offset, size)) { | 180 if (!CheckRange(offset, size)) { |
| 178 return false; | 181 return false; |
| 179 } | 182 } |
| 180 if (shadowed_) { | 183 if (!shadow_.empty()) { |
| 181 memcpy(shadow_.get() + offset, data, size); | 184 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); |
| 185 memcpy(shadow_.data() + offset, data, size); | |
| 182 ClearCache(); | 186 ClearCache(); |
| 183 } | 187 } |
| 184 return true; | 188 return true; |
| 185 } | 189 } |
| 186 | 190 |
| 187 const void* Buffer::GetRange( | 191 const void* Buffer::GetRange( |
| 188 GLintptr offset, GLsizeiptr size) const { | 192 GLintptr offset, GLsizeiptr size) const { |
| 189 if (!shadowed_) { | 193 if (shadow_.empty()) { |
| 190 return NULL; | 194 return NULL; |
| 191 } | 195 } |
| 192 if (!CheckRange(offset, size)) { | 196 if (!CheckRange(offset, size)) { |
| 193 return NULL; | 197 return NULL; |
| 194 } | 198 } |
| 195 return shadow_.get() + offset; | 199 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); |
| 200 return shadow_.data() + offset; | |
| 196 } | 201 } |
| 197 | 202 |
| 198 void Buffer::ClearCache() { | 203 void Buffer::ClearCache() { |
| 199 range_set_.clear(); | 204 range_set_.clear(); |
| 200 } | 205 } |
| 201 | 206 |
| 202 template <typename T> | 207 template <typename T> |
| 203 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, | 208 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, |
| 204 GLuint primitive_restart_index) { | 209 GLuint primitive_restart_index) { |
| 205 GLuint max_value = 0; | 210 GLuint max_value = 0; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 } | 278 } |
| 274 | 279 |
| 275 if (!SafeAddUint32(offset, size, &size)) { | 280 if (!SafeAddUint32(offset, size, &size)) { |
| 276 return false; | 281 return false; |
| 277 } | 282 } |
| 278 | 283 |
| 279 if (size > static_cast<uint32_t>(size_)) { | 284 if (size > static_cast<uint32_t>(size_)) { |
| 280 return false; | 285 return false; |
| 281 } | 286 } |
| 282 | 287 |
| 283 if (!shadowed_) { | 288 if (shadow_.empty()) { |
| 284 return false; | 289 return false; |
| 285 } | 290 } |
| 286 | 291 |
| 287 // Scan the range for the max value and store | 292 // Scan the range for the max value and store |
| 288 GLuint max_v = 0; | 293 GLuint max_v = 0; |
| 289 switch (type) { | 294 switch (type) { |
| 290 case GL_UNSIGNED_BYTE: | 295 case GL_UNSIGNED_BYTE: |
| 291 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, | 296 max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count, |
| 292 primitive_restart_index); | 297 primitive_restart_index); |
| 293 break; | 298 break; |
| 294 case GL_UNSIGNED_SHORT: | 299 case GL_UNSIGNED_SHORT: |
| 295 // Check we are not accessing an odd byte for a 2 byte value. | 300 // Check we are not accessing an odd byte for a 2 byte value. |
| 296 if ((offset & 1) != 0) { | 301 if ((offset & 1) != 0) { |
| 297 return false; | 302 return false; |
| 298 } | 303 } |
| 299 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, | 304 max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count, |
| 300 primitive_restart_index); | 305 primitive_restart_index); |
| 301 break; | 306 break; |
| 302 case GL_UNSIGNED_INT: | 307 case GL_UNSIGNED_INT: |
| 303 // Check we are not accessing a non aligned address for a 4 byte value. | 308 // Check we are not accessing a non aligned address for a 4 byte value. |
| 304 if ((offset & 3) != 0) { | 309 if ((offset & 3) != 0) { |
| 305 return false; | 310 return false; |
| 306 } | 311 } |
| 307 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, | 312 max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count, |
| 308 primitive_restart_index); | 313 primitive_restart_index); |
| 309 break; | 314 break; |
| 310 default: | 315 default: |
| 311 NOTREACHED(); // should never get here by validation. | 316 NOTREACHED(); // should never get here by validation. |
| 312 break; | 317 break; |
| 313 } | 318 } |
| 314 range_set_.insert(std::make_pair(range, max_v)); | 319 range_set_.insert(std::make_pair(range, max_v)); |
| 315 *max_value = max_v; | 320 *max_value = max_v; |
| 316 return true; | 321 return true; |
| 317 } | 322 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 331 bool BufferManager::IsUsageClientSideArray(GLenum usage) { | 336 bool BufferManager::IsUsageClientSideArray(GLenum usage) { |
| 332 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; | 337 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; |
| 333 } | 338 } |
| 334 | 339 |
| 335 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { | 340 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { |
| 336 return feature_info_.get() && | 341 return feature_info_.get() && |
| 337 feature_info_->workarounds() | 342 feature_info_->workarounds() |
| 338 .use_non_zero_size_for_client_side_stream_buffers; | 343 .use_non_zero_size_for_client_side_stream_buffers; |
| 339 } | 344 } |
| 340 | 345 |
| 341 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, | 346 bool BufferManager::UseShadowBuffer(GLenum target, GLenum usage) { |
| 342 GLenum usage, const GLvoid* data) { | |
| 343 DCHECK(buffer); | |
| 344 memory_type_tracker_->TrackMemFree(buffer->size()); | |
| 345 const bool is_client_side_array = IsUsageClientSideArray(usage); | 347 const bool is_client_side_array = IsUsageClientSideArray(usage); |
| 346 const bool support_fixed_attribs = | 348 const bool support_fixed_attribs = |
| 347 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | 349 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| 350 | |
| 348 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. | 351 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. |
| 349 const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER || | 352 return (target == GL_ELEMENT_ARRAY_BUFFER || |
| 350 allow_buffers_on_multiple_targets_ || | 353 allow_buffers_on_multiple_targets_ || |
| 351 (allow_fixed_attribs_ && !support_fixed_attribs) || | 354 (allow_fixed_attribs_ && !support_fixed_attribs) || |
| 352 is_client_side_array; | 355 is_client_side_array); |
| 353 buffer->SetInfo(size, usage, shadow, data, is_client_side_array); | 356 } |
| 357 | |
| 358 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, | |
| 359 GLenum usage, bool use_shadow) { | |
| 360 DCHECK(buffer); | |
| 361 memory_type_tracker_->TrackMemFree(buffer->size()); | |
| 362 buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage)); | |
| 354 memory_type_tracker_->TrackMemAlloc(buffer->size()); | 363 memory_type_tracker_->TrackMemAlloc(buffer->size()); |
| 355 } | 364 } |
| 356 | 365 |
| 357 void BufferManager::ValidateAndDoBufferData( | 366 void BufferManager::ValidateAndDoBufferData( |
| 358 ContextState* context_state, GLenum target, GLsizeiptr size, | 367 ContextState* context_state, GLenum target, GLsizeiptr size, |
| 359 const GLvoid* data, GLenum usage) { | 368 const GLvoid* data, GLenum usage) { |
| 360 ErrorState* error_state = context_state->GetErrorState(); | 369 ErrorState* error_state = context_state->GetErrorState(); |
| 361 if (!feature_info_->validators()->buffer_target.IsValid(target)) { | 370 if (!feature_info_->validators()->buffer_target.IsValid(target)) { |
| 362 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( | 371 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( |
| 363 error_state, "glBufferData", target, "target"); | 372 error_state, "glBufferData", target, "target"); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 391 } | 400 } |
| 392 | 401 |
| 393 | 402 |
| 394 void BufferManager::DoBufferData( | 403 void BufferManager::DoBufferData( |
| 395 ErrorState* error_state, | 404 ErrorState* error_state, |
| 396 Buffer* buffer, | 405 Buffer* buffer, |
| 397 GLenum target, | 406 GLenum target, |
| 398 GLsizeiptr size, | 407 GLsizeiptr size, |
| 399 GLenum usage, | 408 GLenum usage, |
| 400 const GLvoid* data) { | 409 const GLvoid* data) { |
| 401 // Clear the buffer to 0 if no initial data was passed in. | 410 |
| 402 scoped_ptr<int8_t[]> zero; | 411 // Stage the shadow buffer first if we are using a shadow buffer so that we |
|
Ken Russell (switch to Gerrit)
2016/03/31 23:28:04
Is the indentation off here?
David Yen
2016/04/01 17:00:53
Done. I just ran cl format.
| |
| 403 if (!data) { | 412 // validate what we store internally. |
| 404 zero.reset(new int8_t[size]); | 413 const bool use_shadow = UseShadowBuffer(target, usage); |
| 405 memset(zero.get(), 0, size); | 414 data = buffer->StageShadow(use_shadow, size, data); |
| 406 data = zero.get(); | |
| 407 } | |
| 408 | 415 |
| 409 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); | 416 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); |
| 410 if (IsUsageClientSideArray(usage)) { | 417 if (IsUsageClientSideArray(usage)) { |
| 411 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; | 418 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; |
| 412 glBufferData(target, empty_size, NULL, usage); | 419 glBufferData(target, empty_size, NULL, usage); |
| 413 } else { | 420 } else { |
| 414 glBufferData(target, size, data, usage); | 421 glBufferData(target, size, data, usage); |
| 415 } | 422 } |
| 416 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); | 423 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); |
| 417 if (error == GL_NO_ERROR) { | 424 if (error != GL_NO_ERROR) { |
| 418 SetInfo(buffer, target, size, usage, data); | 425 size = 0; |
| 419 } else { | 426 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow. |
| 420 SetInfo(buffer, target, 0, usage, NULL); | |
| 421 } | 427 } |
| 428 | |
| 429 SetInfo(buffer, target, size, usage, use_shadow); | |
| 422 } | 430 } |
| 423 | 431 |
| 424 void BufferManager::ValidateAndDoBufferSubData( | 432 void BufferManager::ValidateAndDoBufferSubData( |
| 425 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, | 433 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, |
| 426 const GLvoid * data) { | 434 const GLvoid * data) { |
| 427 ErrorState* error_state = context_state->GetErrorState(); | 435 ErrorState* error_state = context_state->GetErrorState(); |
| 428 Buffer* buffer = GetBufferInfoForTarget(context_state, target); | 436 Buffer* buffer = GetBufferInfoForTarget(context_state, target); |
| 429 if (!buffer) { | 437 if (!buffer) { |
| 430 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", | 438 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", |
| 431 "unknown buffer"); | 439 "unknown buffer"); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 624 auto guid = gfx::GetGLBufferGUIDForTracing( | 632 auto guid = gfx::GetGLBufferGUIDForTracing( |
| 625 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); | 633 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); |
| 626 pmd->CreateSharedGlobalAllocatorDump(guid); | 634 pmd->CreateSharedGlobalAllocatorDump(guid); |
| 627 pmd->AddOwnershipEdge(dump->guid(), guid); | 635 pmd->AddOwnershipEdge(dump->guid(), guid); |
| 628 } | 636 } |
| 629 return true; | 637 return true; |
| 630 } | 638 } |
| 631 | 639 |
| 632 } // namespace gles2 | 640 } // namespace gles2 |
| 633 } // namespace gpu | 641 } // namespace gpu |
| OLD | NEW |