15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "gpu/command_buffer/service/buffer_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/logging.h" 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "gpu/command_buffer/common/gles2_cmd_utils.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gpu/command_buffer/service/context_state.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "gpu/command_buffer/service/error_state.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "gpu/command_buffer/service/feature_info.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "gpu/command_buffer/service/memory_tracking.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gles2 { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferManager::BufferManager( 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryTracker* memory_tracker, 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FeatureInfo* feature_info) 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : memory_tracker_( 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)), 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) feature_info_(feature_info), 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) allow_buffers_on_multiple_targets_(false), 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) buffer_count_(0), 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu have_context_(true), 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu use_client_side_arrays_for_stream_buffers_( 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu feature_info ? feature_info->workarounds( 306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ).use_client_side_arrays_for_stream_buffers : 0) { 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBufferManager::~BufferManager() { 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(buffers_.empty()); 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_EQ(buffer_count_, 0u); 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BufferManager::Destroy(bool have_context) { 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) have_context_ = have_context; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) buffers_.clear(); 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(0u, memory_tracker_->GetMemRepresented()); 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BufferManager::CreateBuffer(GLuint client_id, GLuint service_id) { 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_refptr<Buffer> buffer(new Buffer(this, service_id)); 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::pair<BufferMap::iterator, bool> result = 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) buffers_.insert(std::make_pair(client_id, buffer)); 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(result.second); 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Buffer* BufferManager::GetBuffer( 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLuint client_id) { 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BufferMap::iterator it = buffers_.find(client_id); 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return it != buffers_.end() ? it->second.get() : NULL; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void BufferManager::RemoveBuffer(GLuint client_id) { 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BufferMap::iterator it = buffers_.find(client_id); 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (it != buffers_.end()) { 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer = it->second.get(); 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) buffer->MarkAsDeleted(); 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu buffers_.erase(it); 630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid BufferManager::StartTracking(Buffer* /* buffer */) { 670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++buffer_count_; 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void BufferManager::StopTracking(Buffer* buffer) { 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu memory_tracker_->TrackMemFree(buffer->size()); 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) --buffer_count_; 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Buffer::Buffer(BufferManager* manager, GLuint service_id) 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : manager_(manager), 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_(0), 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) deleted_(false), 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shadowed_(false), 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_client_side_array_(false), 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) service_id_(service_id), 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) target_(0), 836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) usage_(GL_STATIC_DRAW) { 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) manager_->StartTracking(this); 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Buffer::~Buffer() { 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (manager_) { 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (manager_->have_context_) { 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLuint id = service_id(); 916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) glDeleteBuffersARB(1, &id); 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) manager_->StopTracking(this); 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) manager_ = NULL; 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Buffer::SetInfo( 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool is_client_side_array) { 1016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) usage_ = usage; 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_client_side_array_ = is_client_side_array; 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ClearCache(); 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (size != size_ || shadow != shadowed_) { 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shadowed_ = shadow; 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_ = size; 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (shadowed_) { 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shadow_.reset(new int8[size]); 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shadow_.reset(); 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (shadowed_) { 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (data) { 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memcpy(shadow_.get(), data, size); 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memset(shadow_.get(), 0, size); 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Buffer::CheckRange( 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLintptr offset, GLsizeiptr size) const { 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int32 end = 0; 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return offset >= 0 && size >= 0 && 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) offset <= std::numeric_limits<int32>::max() && 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size <= std::numeric_limits<int32>::max() && 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SafeAddInt32(offset, size, &end) && end <= size_; 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Buffer::SetRange( 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLintptr offset, GLsizeiptr size, const GLvoid * data) { 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!CheckRange(offset, size)) { 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (shadowed_) { 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch memcpy(shadow_.get() + offset, data, size); 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ClearCache(); 1396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return true; 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 1426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 1436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)const void* Buffer::GetRange( 1446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) GLintptr offset, GLsizeiptr size) const { 1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!shadowed_) { 1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return NULL; 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (!CheckRange(offset, size)) { 1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return NULL; 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return shadow_.get() + offset; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Buffer::ClearCache() { 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci range_set_.clear(); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)template <typename T> 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count) { 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GLuint max_value = 0; 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const T* element = reinterpret_cast<const T*>( 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static_cast<const int8*>(data) + offset); 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const T* end = element + count; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; element < end; ++element) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*element > max_value) { 1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu max_value = *element; 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return max_value; 1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool Buffer::GetMaxValueForRange( 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GLuint offset, GLsizei count, GLenum type, GLuint* max_value) { 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Range range(offset, count, type); 1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RangeToMaxValueMap::iterator it = range_set_.find(range); 1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (it != range_set_.end()) { 1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *max_value = it->second; 1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return true; 1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint32 size; 1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!SafeMultiplyUint32( 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) count, GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type), &size)) { 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!SafeAddUint32(offset, size, &size)) { 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (size > static_cast<uint32>(size_)) { 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!shadowed_) { 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Scan the range for the max value and store 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GLuint max_v = 0; 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (type) { 20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case GL_UNSIGNED_BYTE: 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_v = GetMaxValue<uint8>(shadow_.get(), offset, count); 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case GL_UNSIGNED_SHORT: 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Check we are not accessing an odd byte for a 2 byte value. 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if ((offset & 1) != 0) { 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) max_v = GetMaxValue<uint16>(shadow_.get(), offset, count); 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case GL_UNSIGNED_INT: 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Check we are not accessing a non aligned address for a 4 byte value. 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((offset & 3) != 0) { 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci max_v = GetMaxValue<uint32>(shadow_.get(), offset, count); 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED(); // should never get here by validation. 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci range_set_.insert(std::make_pair(range, max_v)); 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *max_value = max_v; 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This doesn't need to be fast. It's only used during slow queries. 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (BufferMap::const_iterator it = buffers_.begin(); 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it != buffers_.end(); ++it) { 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it->second->service_id() == service_id) { 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *client_id = it->first; 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool BufferManager::IsUsageClientSideArray(GLenum usage) { 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; 24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return feature_info_.get() && 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) feature_info_->workarounds() 247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch .use_non_zero_size_for_client_side_stream_buffers; 248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 249e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid BufferManager::SetInfo( 251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data) { 252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(buffer); 253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch memory_tracker_->TrackMemFree(buffer->size()); 254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool is_client_side_array = IsUsageClientSideArray(usage); 255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool shadow = buffer->target() == GL_ELEMENT_ARRAY_BUFFER || 25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) allow_buffers_on_multiple_targets_ || 2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch is_client_side_array; 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch buffer->SetInfo(size, usage, shadow, data, is_client_side_array); 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch memory_tracker_->TrackMemAlloc(buffer->size()); 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid BufferManager::ValidateAndDoBufferData( 263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ContextState* context_state, GLenum target, GLsizeiptr size, 2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const GLvoid * data, GLenum usage) { 2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ErrorState* error_state = context_state->GetErrorState(); 266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!feature_info_->validators()->buffer_target.IsValid(target)) { 267e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch error_state, "glBufferData", target, "target"); 269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 270e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!feature_info_->validators()->buffer_usage.IsValid(usage)) { 272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci error_state, "glBufferData", usage, "usage"); 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (size < 0) { 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ERRORSTATE_SET_GL_ERROR( 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci error_state, GL_INVALID_VALUE, "glBufferData", "size < 0"); 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer = GetBufferInfoForTarget(context_state, target); 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!buffer) { 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERRORSTATE_SET_GL_ERROR( 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) error_state, GL_INVALID_VALUE, "glBufferData", "unknown buffer"); 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!memory_tracker_->EnsureGPUMemoryAvailable(size)) { 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ERRORSTATE_SET_GL_ERROR( 2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) error_state, GL_OUT_OF_MEMORY, "glBufferData", "out of memory"); 2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DoBufferData(error_state, buffer, size, usage, data); 2966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 2976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BufferManager::DoBufferData( 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ErrorState* error_state, 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer, 3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLsizeiptr size, 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GLenum usage, 3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GLvoid* data) { 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Clear the buffer to 0 if no initial data was passed in. 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<int8[]> zero; 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!data) { 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) zero.reset(new int8[size]); 3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu memset(zero.get(), 0, size); 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data = zero.get(); 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); 314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (IsUsageClientSideArray(usage)) { 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci glBufferData(buffer->target(), empty_size, NULL, usage); 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci glBufferData(buffer->target(), size, data, usage); 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (error == GL_NO_ERROR) { 3226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) SetInfo(buffer, size, usage, data); 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) SetInfo(buffer, 0, usage, NULL); 3256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 3266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 3276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 3286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BufferManager::ValidateAndDoBufferSubData( 3296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GLvoid * data) { 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ErrorState* error_state = context_state->GetErrorState(); 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer = GetBufferInfoForTarget(context_state, target); 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!buffer) { 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "unknown buffer"); 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DoBufferSubData(error_state, buffer, offset, size, data); 3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void BufferManager::DoBufferSubData( 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ErrorState* error_state, 3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer, 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLintptr offset, 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GLsizeiptr size, 3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GLvoid* data) { 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!buffer->SetRange(offset, size, data)) { 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERRORSTATE_SET_GL_ERROR( 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) error_state, GL_INVALID_VALUE, "glBufferSubData", "out of range"); 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!buffer->IsClientSideArray()) { 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) glBufferSubData(buffer->target(), offset, size, data); 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BufferManager::ValidateAndDoGetBufferParameteriv( 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ContextState* context_state, GLenum target, GLenum pname, GLint* params) { 3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Buffer* buffer = GetBufferInfoForTarget(context_state, target); 3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!buffer) { 3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERRORSTATE_SET_GL_ERROR( 3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) context_state->GetErrorState(), GL_INVALID_OPERATION, 3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "glGetBufferParameteriv", "no buffer bound for target"); 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (pname) { 369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case GL_BUFFER_SIZE: 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *params = buffer->size(); 3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case GL_BUFFER_USAGE: 3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *params = buffer->usage(); 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOTREACHED(); 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool BufferManager::SetTarget(Buffer* buffer, GLenum target) { 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Check that we are not trying to bind it to a different target. 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (buffer->target() != 0 && buffer->target() != target && 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !allow_buffers_on_multiple_targets_) { 384 return false; 385 } 386 if (buffer->target() == 0) { 387 buffer->set_target(target); 388 } 389 return true; 390} 391 392// Since one BufferManager can be shared by multiple decoders, ContextState is 393// passed in each time and not just passed in during initialization. 394Buffer* BufferManager::GetBufferInfoForTarget( 395 ContextState* state, GLenum target) { 396 DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); 397 if (target == GL_ARRAY_BUFFER) { 398 return state->bound_array_buffer.get(); 399 } else { 400 return state->vertex_attrib_manager->element_array_buffer(); 401 } 402} 403 404} // namespace gles2 405} // namespace gpu 406 407 408