| 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 |
| 141 void Buffer::SetInfo( | 140 const GLvoid* Buffer::StageShadow(bool use_shadow, |
| 142 GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, | 141 GLsizeiptr size, |
| 143 bool is_client_side_array) { | 142 const GLvoid* data) { |
| 143 shadow_.clear(); |
| 144 if (use_shadow) { |
| 145 if (data) { |
| 146 shadow_.insert(shadow_.begin(), |
| 147 static_cast<const uint8_t*>(data), |
| 148 static_cast<const uint8_t*>(data) + size); |
| 149 } else { |
| 150 shadow_.resize(size); |
| 151 } |
| 152 return shadow_.data(); |
| 153 } else { |
| 154 return data; |
| 155 } |
| 156 } |
| 157 |
| 158 void Buffer::SetInfo(GLsizeiptr size, |
| 159 GLenum usage, |
| 160 bool use_shadow, |
| 161 bool is_client_side_array) { |
| 144 usage_ = usage; | 162 usage_ = usage; |
| 145 is_client_side_array_ = is_client_side_array; | 163 is_client_side_array_ = is_client_side_array; |
| 146 ClearCache(); | 164 ClearCache(); |
| 147 if (size != size_ || shadow != shadowed_) { | 165 |
| 148 shadowed_ = shadow; | 166 // Shadow must have been setup already. |
| 149 size_ = size; | 167 DCHECK_EQ(shadow_.size(), static_cast<size_t>(use_shadow ? size : 0u)); |
| 150 if (shadowed_) { | 168 size_ = size; |
| 151 shadow_.reset(new int8_t[size]); | 169 |
| 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); | 170 mapped_range_.reset(nullptr); |
| 164 } | 171 } |
| 165 | 172 |
| 166 bool Buffer::CheckRange( | 173 bool Buffer::CheckRange( |
| 167 GLintptr offset, GLsizeiptr size) const { | 174 GLintptr offset, GLsizeiptr size) const { |
| 168 int32_t end = 0; | 175 int32_t end = 0; |
| 169 return offset >= 0 && size >= 0 && | 176 return offset >= 0 && size >= 0 && |
| 170 offset <= std::numeric_limits<int32_t>::max() && | 177 offset <= std::numeric_limits<int32_t>::max() && |
| 171 size <= std::numeric_limits<int32_t>::max() && | 178 size <= std::numeric_limits<int32_t>::max() && |
| 172 SafeAddInt32(offset, size, &end) && end <= size_; | 179 SafeAddInt32(offset, size, &end) && end <= size_; |
| 173 } | 180 } |
| 174 | 181 |
| 175 bool Buffer::SetRange( | 182 bool Buffer::SetRange( |
| 176 GLintptr offset, GLsizeiptr size, const GLvoid * data) { | 183 GLintptr offset, GLsizeiptr size, const GLvoid * data) { |
| 177 if (!CheckRange(offset, size)) { | 184 if (!CheckRange(offset, size)) { |
| 178 return false; | 185 return false; |
| 179 } | 186 } |
| 180 if (shadowed_) { | 187 if (!shadow_.empty()) { |
| 181 memcpy(shadow_.get() + offset, data, size); | 188 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); |
| 189 memcpy(shadow_.data() + offset, data, size); |
| 182 ClearCache(); | 190 ClearCache(); |
| 183 } | 191 } |
| 184 return true; | 192 return true; |
| 185 } | 193 } |
| 186 | 194 |
| 187 const void* Buffer::GetRange( | 195 const void* Buffer::GetRange( |
| 188 GLintptr offset, GLsizeiptr size) const { | 196 GLintptr offset, GLsizeiptr size) const { |
| 189 if (!shadowed_) { | 197 if (shadow_.empty()) { |
| 190 return NULL; | 198 return NULL; |
| 191 } | 199 } |
| 192 if (!CheckRange(offset, size)) { | 200 if (!CheckRange(offset, size)) { |
| 193 return NULL; | 201 return NULL; |
| 194 } | 202 } |
| 195 return shadow_.get() + offset; | 203 DCHECK_LE(static_cast<size_t>(offset + size), shadow_.size()); |
| 204 return shadow_.data() + offset; |
| 196 } | 205 } |
| 197 | 206 |
| 198 void Buffer::ClearCache() { | 207 void Buffer::ClearCache() { |
| 199 range_set_.clear(); | 208 range_set_.clear(); |
| 200 } | 209 } |
| 201 | 210 |
| 202 template <typename T> | 211 template <typename T> |
| 203 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, | 212 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, |
| 204 GLuint primitive_restart_index) { | 213 GLuint primitive_restart_index) { |
| 205 GLuint max_value = 0; | 214 GLuint max_value = 0; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 } | 282 } |
| 274 | 283 |
| 275 if (!SafeAddUint32(offset, size, &size)) { | 284 if (!SafeAddUint32(offset, size, &size)) { |
| 276 return false; | 285 return false; |
| 277 } | 286 } |
| 278 | 287 |
| 279 if (size > static_cast<uint32_t>(size_)) { | 288 if (size > static_cast<uint32_t>(size_)) { |
| 280 return false; | 289 return false; |
| 281 } | 290 } |
| 282 | 291 |
| 283 if (!shadowed_) { | 292 if (shadow_.empty()) { |
| 284 return false; | 293 return false; |
| 285 } | 294 } |
| 286 | 295 |
| 287 // Scan the range for the max value and store | 296 // Scan the range for the max value and store |
| 288 GLuint max_v = 0; | 297 GLuint max_v = 0; |
| 289 switch (type) { | 298 switch (type) { |
| 290 case GL_UNSIGNED_BYTE: | 299 case GL_UNSIGNED_BYTE: |
| 291 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, | 300 max_v = GetMaxValue<uint8_t>(shadow_.data(), offset, count, |
| 292 primitive_restart_index); | 301 primitive_restart_index); |
| 293 break; | 302 break; |
| 294 case GL_UNSIGNED_SHORT: | 303 case GL_UNSIGNED_SHORT: |
| 295 // Check we are not accessing an odd byte for a 2 byte value. | 304 // Check we are not accessing an odd byte for a 2 byte value. |
| 296 if ((offset & 1) != 0) { | 305 if ((offset & 1) != 0) { |
| 297 return false; | 306 return false; |
| 298 } | 307 } |
| 299 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, | 308 max_v = GetMaxValue<uint16_t>(shadow_.data(), offset, count, |
| 300 primitive_restart_index); | 309 primitive_restart_index); |
| 301 break; | 310 break; |
| 302 case GL_UNSIGNED_INT: | 311 case GL_UNSIGNED_INT: |
| 303 // Check we are not accessing a non aligned address for a 4 byte value. | 312 // Check we are not accessing a non aligned address for a 4 byte value. |
| 304 if ((offset & 3) != 0) { | 313 if ((offset & 3) != 0) { |
| 305 return false; | 314 return false; |
| 306 } | 315 } |
| 307 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, | 316 max_v = GetMaxValue<uint32_t>(shadow_.data(), offset, count, |
| 308 primitive_restart_index); | 317 primitive_restart_index); |
| 309 break; | 318 break; |
| 310 default: | 319 default: |
| 311 NOTREACHED(); // should never get here by validation. | 320 NOTREACHED(); // should never get here by validation. |
| 312 break; | 321 break; |
| 313 } | 322 } |
| 314 range_set_.insert(std::make_pair(range, max_v)); | 323 range_set_.insert(std::make_pair(range, max_v)); |
| 315 *max_value = max_v; | 324 *max_value = max_v; |
| 316 return true; | 325 return true; |
| 317 } | 326 } |
| 318 | 327 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 331 bool BufferManager::IsUsageClientSideArray(GLenum usage) { | 340 bool BufferManager::IsUsageClientSideArray(GLenum usage) { |
| 332 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; | 341 return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; |
| 333 } | 342 } |
| 334 | 343 |
| 335 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { | 344 bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { |
| 336 return feature_info_.get() && | 345 return feature_info_.get() && |
| 337 feature_info_->workarounds() | 346 feature_info_->workarounds() |
| 338 .use_non_zero_size_for_client_side_stream_buffers; | 347 .use_non_zero_size_for_client_side_stream_buffers; |
| 339 } | 348 } |
| 340 | 349 |
| 341 void BufferManager::SetInfo(Buffer* buffer, GLenum target, GLsizeiptr size, | 350 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); | 351 const bool is_client_side_array = IsUsageClientSideArray(usage); |
| 346 const bool support_fixed_attribs = | 352 const bool support_fixed_attribs = |
| 347 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | 353 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| 354 |
| 348 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. | 355 // TODO(zmo): Don't shadow buffer data on ES3. crbug.com/491002. |
| 349 const bool shadow = target == GL_ELEMENT_ARRAY_BUFFER || | 356 return ( |
| 350 allow_buffers_on_multiple_targets_ || | 357 target == GL_ELEMENT_ARRAY_BUFFER || allow_buffers_on_multiple_targets_ || |
| 351 (allow_fixed_attribs_ && !support_fixed_attribs) || | 358 (allow_fixed_attribs_ && !support_fixed_attribs) || is_client_side_array); |
| 352 is_client_side_array; | 359 } |
| 353 buffer->SetInfo(size, usage, shadow, data, is_client_side_array); | 360 |
| 361 void BufferManager::SetInfo(Buffer* buffer, |
| 362 GLenum target, |
| 363 GLsizeiptr size, |
| 364 GLenum usage, |
| 365 bool use_shadow) { |
| 366 DCHECK(buffer); |
| 367 memory_type_tracker_->TrackMemFree(buffer->size()); |
| 368 buffer->SetInfo(size, usage, use_shadow, IsUsageClientSideArray(usage)); |
| 354 memory_type_tracker_->TrackMemAlloc(buffer->size()); | 369 memory_type_tracker_->TrackMemAlloc(buffer->size()); |
| 355 } | 370 } |
| 356 | 371 |
| 357 void BufferManager::ValidateAndDoBufferData( | 372 void BufferManager::ValidateAndDoBufferData( |
| 358 ContextState* context_state, GLenum target, GLsizeiptr size, | 373 ContextState* context_state, GLenum target, GLsizeiptr size, |
| 359 const GLvoid* data, GLenum usage) { | 374 const GLvoid* data, GLenum usage) { |
| 360 ErrorState* error_state = context_state->GetErrorState(); | 375 ErrorState* error_state = context_state->GetErrorState(); |
| 361 if (!feature_info_->validators()->buffer_target.IsValid(target)) { | 376 if (!feature_info_->validators()->buffer_target.IsValid(target)) { |
| 362 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( | 377 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( |
| 363 error_state, "glBufferData", target, "target"); | 378 error_state, "glBufferData", target, "target"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 391 } | 406 } |
| 392 | 407 |
| 393 | 408 |
| 394 void BufferManager::DoBufferData( | 409 void BufferManager::DoBufferData( |
| 395 ErrorState* error_state, | 410 ErrorState* error_state, |
| 396 Buffer* buffer, | 411 Buffer* buffer, |
| 397 GLenum target, | 412 GLenum target, |
| 398 GLsizeiptr size, | 413 GLsizeiptr size, |
| 399 GLenum usage, | 414 GLenum usage, |
| 400 const GLvoid* data) { | 415 const GLvoid* data) { |
| 401 // Clear the buffer to 0 if no initial data was passed in. | 416 // Stage the shadow buffer first if we are using a shadow buffer so that we |
| 402 scoped_ptr<int8_t[]> zero; | 417 // validate what we store internally. |
| 403 if (!data) { | 418 const bool use_shadow = UseShadowBuffer(target, usage); |
| 404 zero.reset(new int8_t[size]); | 419 data = buffer->StageShadow(use_shadow, size, data); |
| 405 memset(zero.get(), 0, size); | |
| 406 data = zero.get(); | |
| 407 } | |
| 408 | 420 |
| 409 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); | 421 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); |
| 410 if (IsUsageClientSideArray(usage)) { | 422 if (IsUsageClientSideArray(usage)) { |
| 411 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; | 423 GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; |
| 412 glBufferData(target, empty_size, NULL, usage); | 424 glBufferData(target, empty_size, NULL, usage); |
| 413 } else { | 425 } else { |
| 414 glBufferData(target, size, data, usage); | 426 glBufferData(target, size, data, usage); |
| 415 } | 427 } |
| 416 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); | 428 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); |
| 417 if (error == GL_NO_ERROR) { | 429 if (error != GL_NO_ERROR) { |
| 418 SetInfo(buffer, target, size, usage, data); | 430 size = 0; |
| 419 } else { | 431 buffer->StageShadow(false, 0, nullptr); // Also clear the shadow. |
| 420 SetInfo(buffer, target, 0, usage, NULL); | |
| 421 } | 432 } |
| 433 |
| 434 SetInfo(buffer, target, size, usage, use_shadow); |
| 422 } | 435 } |
| 423 | 436 |
| 424 void BufferManager::ValidateAndDoBufferSubData( | 437 void BufferManager::ValidateAndDoBufferSubData( |
| 425 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, | 438 ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, |
| 426 const GLvoid * data) { | 439 const GLvoid * data) { |
| 427 ErrorState* error_state = context_state->GetErrorState(); | 440 ErrorState* error_state = context_state->GetErrorState(); |
| 428 Buffer* buffer = GetBufferInfoForTarget(context_state, target); | 441 Buffer* buffer = GetBufferInfoForTarget(context_state, target); |
| 429 if (!buffer) { | 442 if (!buffer) { |
| 430 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", | 443 ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", |
| 431 "unknown buffer"); | 444 "unknown buffer"); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 auto guid = gfx::GetGLBufferGUIDForTracing( | 637 auto guid = gfx::GetGLBufferGUIDForTracing( |
| 625 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); | 638 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); |
| 626 pmd->CreateSharedGlobalAllocatorDump(guid); | 639 pmd->CreateSharedGlobalAllocatorDump(guid); |
| 627 pmd->AddOwnershipEdge(dump->guid(), guid); | 640 pmd->AddOwnershipEdge(dump->guid(), guid); |
| 628 } | 641 } |
| 629 return true; | 642 return true; |
| 630 } | 643 } |
| 631 | 644 |
| 632 } // namespace gles2 | 645 } // namespace gles2 |
| 633 } // namespace gpu | 646 } // namespace gpu |
| OLD | NEW |