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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/buffer_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/gles2_cmd_utils.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "gpu/command_buffer/service/context_state.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "gpu/command_buffer/service/error_state.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gpu/command_buffer/service/feature_info.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/memory_tracking.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_bindings.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gles2 { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BufferManager::BufferManager( 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MemoryTracker* memory_tracker, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FeatureInfo* feature_info) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : memory_tracker_( 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)), 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) feature_info_(feature_info), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allow_buffers_on_multiple_targets_(false), 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer_count_(0), 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) have_context_(true), 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_client_side_arrays_for_stream_buffers_( 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) feature_info ? feature_info->workarounds( 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ).use_client_side_arrays_for_stream_buffers : 0) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferManager::~BufferManager() { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(buffers_.empty()); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(buffer_count_, 0u); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferManager::Destroy(bool have_context) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_context_ = have_context; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffers_.clear(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, memory_tracker_->GetMemRepresented()); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::CreateBuffer(GLuint client_id, GLuint service_id) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<Buffer> buffer(new Buffer(this, service_id)); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::pair<BufferMap::iterator, bool> result = 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffers_.insert(std::make_pair(client_id, buffer)); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result.second); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer* BufferManager::GetBuffer( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint client_id) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferMap::iterator it = buffers_.find(client_id); 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return it != buffers_.end() ? it->second.get() : NULL; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::RemoveBuffer(GLuint client_id) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferMap::iterator it = buffers_.find(client_id); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != buffers_.end()) { 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Buffer* buffer = it->second.get(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer->MarkAsDeleted(); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffers_.erase(it); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::StartTracking(Buffer* /* buffer */) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++buffer_count_; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::StopTracking(Buffer* buffer) { 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_tracker_->TrackMemFree(buffer->size()); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --buffer_count_; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer::Buffer(BufferManager* manager, GLuint service_id) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : manager_(manager), 77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) size_(0), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deleted_(false), 79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) shadowed_(false), 80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) is_client_side_array_(false), 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_id_(service_id), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_(0), 83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) usage_(GL_STATIC_DRAW) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_->StartTracking(this); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer::~Buffer() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (manager_) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (manager_->have_context_) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint id = service_id(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteBuffersARB(1, &id); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_->StopTracking(this); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manager_ = NULL; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Buffer::SetInfo( 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLsizeiptr size, GLenum usage, bool shadow, const GLvoid* data, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_client_side_array) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usage_ = usage; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_client_side_array_ = is_client_side_array; 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ClearCache(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size != size_ || shadow != shadowed_) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shadowed_ = shadow; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = size; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shadowed_) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shadow_.reset(new int8[size]); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shadow_.reset(); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (shadowed_) { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(shadow_.get(), data, size); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(shadow_.get(), 0, size); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Buffer::CheckRange( 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLintptr offset, GLsizeiptr size) const { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 end = 0; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return offset >= 0 && size >= 0 && 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset <= std::numeric_limits<int32>::max() && 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size <= std::numeric_limits<int32>::max() && 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeAddInt32(offset, size, &end) && end <= size_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Buffer::SetRange( 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLintptr offset, GLsizeiptr size, const GLvoid * data) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CheckRange(offset, size)) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shadowed_) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(shadow_.get() + offset, data, size); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearCache(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const void* Buffer::GetRange( 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLintptr offset, GLsizeiptr size) const { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shadowed_) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CheckRange(offset, size)) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shadow_.get() + offset; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Buffer::ClearCache() { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range_set_.clear(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint max_value = 0; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* element = reinterpret_cast<const T*>( 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<const int8*>(data) + offset); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* end = element + count; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; element < end; ++element) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*element > max_value) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_value = *element; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return max_value; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Buffer::GetMaxValueForRange( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint offset, GLsizei count, GLenum type, GLuint* max_value) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Range range(offset, count, type); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RangeToMaxValueMap::iterator it = range_set_.find(range); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != range_set_.end()) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_value = it->second; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SafeMultiplyUint32( 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count, GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type), &size)) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SafeAddUint32(offset, size, &size)) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > static_cast<uint32>(size_)) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shadowed_) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scan the range for the max value and store 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint max_v = 0; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GL_UNSIGNED_BYTE: 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_v = GetMaxValue<uint8>(shadow_.get(), offset, count); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GL_UNSIGNED_SHORT: 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check we are not accessing an odd byte for a 2 byte value. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((offset & 1) != 0) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_v = GetMaxValue<uint16>(shadow_.get(), offset, count); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GL_UNSIGNED_INT: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check we are not accessing a non aligned address for a 4 byte value. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((offset & 3) != 0) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_v = GetMaxValue<uint32>(shadow_.get(), offset, count); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); // should never get here by validation. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range_set_.insert(std::make_pair(range, max_v)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_value = max_v; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This doesn't need to be fast. It's only used during slow queries. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (BufferMap::const_iterator it = buffers_.begin(); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != buffers_.end(); ++it) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->second->service_id() == service_id) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *client_id = it->first; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BufferManager::IsUsageClientSideArray(GLenum usage) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return usage == GL_STREAM_DRAW && use_client_side_arrays_for_stream_buffers_; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool BufferManager::UseNonZeroSizeForClientSideArrayBuffer() { 2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return feature_info_.get() && 2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) feature_info_->workarounds() 2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) .use_non_zero_size_for_client_side_stream_buffers; 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferManager::SetInfo( 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data) { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(buffer); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_tracker_->TrackMemFree(buffer->size()); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_client_side_array = IsUsageClientSideArray(usage); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool shadow = buffer->target() == GL_ELEMENT_ARRAY_BUFFER || 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) allow_buffers_on_multiple_targets_ || 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_client_side_array; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->SetInfo(size, usage, shadow, data, is_client_side_array); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memory_tracker_->TrackMemAlloc(buffer->size()); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid BufferManager::ValidateAndDoBufferData( 2639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ContextState* context_state, GLenum target, GLsizeiptr size, 2649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const GLvoid * data, GLenum usage) { 2659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ErrorState* error_state = context_state->GetErrorState(); 2669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!feature_info_->validators()->buffer_target.IsValid(target)) { 2679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 2689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch error_state, "glBufferData", target, "target"); 2699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 2709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!feature_info_->validators()->buffer_usage.IsValid(usage)) { 2729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR_INVALID_ENUM( 2739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch error_state, "glBufferData", usage, "usage"); 2749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 2759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (size < 0) { 2779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR( 2789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch error_state, GL_INVALID_VALUE, "glBufferData", "size < 0"); 2799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 2809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch Buffer* buffer = GetBufferInfoForTarget(context_state, target); 2839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!buffer) { 2849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR( 2859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch error_state, GL_INVALID_VALUE, "glBufferData", "unknown buffer"); 2869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 2879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!memory_tracker_->EnsureGPUMemoryAvailable(size)) { 2909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR( 2919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch error_state, GL_OUT_OF_MEMORY, "glBufferData", "out of memory"); 2929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 2939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch DoBufferData(error_state, buffer, size, usage, data); 2969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 2979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::DoBufferData( 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ErrorState* error_state, 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Buffer* buffer, 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLsizeiptr size, 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLenum usage, 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GLvoid* data) { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clear the buffer to 0 if no initial data was passed in. 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<int8[]> zero; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data) { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zero.reset(new int8[size]); 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(zero.get(), 0, size); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data = zero.get(); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glBufferData"); 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsUsageClientSideArray(usage)) { 315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GLsizei empty_size = UseNonZeroSizeForClientSideArrayBuffer() ? 1 : 0; 316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) glBufferData(buffer->target(), empty_size, NULL, usage); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) glBufferData(buffer->target(), size, data, usage); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glBufferData"); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error == GL_NO_ERROR) { 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetInfo(buffer, size, usage, data); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetInfo(buffer, 0, usage, NULL); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid BufferManager::ValidateAndDoBufferSubData( 3299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ContextState* context_state, GLenum target, GLintptr offset, GLsizeiptr size, 3309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const GLvoid * data) { 3319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ErrorState* error_state = context_state->GetErrorState(); 3329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch Buffer* buffer = GetBufferInfoForTarget(context_state, target); 3339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!buffer) { 3349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, "glBufferSubData", 3359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch "unknown buffer"); 3369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 3379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 3389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 3399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch DoBufferSubData(error_state, buffer, offset, size, data); 3409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 3419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferManager::DoBufferSubData( 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ErrorState* error_state, 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Buffer* buffer, 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLintptr offset, 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GLsizeiptr size, 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GLvoid* data) { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buffer->SetRange(offset, size, data)) { 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERRORSTATE_SET_GL_ERROR( 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) error_state, GL_INVALID_VALUE, "glBufferSubData", "out of range"); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buffer->IsClientSideArray()) { 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) glBufferSubData(buffer->target(), offset, size, data); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid BufferManager::ValidateAndDoGetBufferParameteriv( 3609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ContextState* context_state, GLenum target, GLenum pname, GLint* params) { 3619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch Buffer* buffer = GetBufferInfoForTarget(context_state, target); 3629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!buffer) { 3639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERRORSTATE_SET_GL_ERROR( 3649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch context_state->GetErrorState(), GL_INVALID_OPERATION, 3659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch "glGetBufferParameteriv", "no buffer bound for target"); 3669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 3679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 3689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch switch (pname) { 3699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch case GL_BUFFER_SIZE: 3709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *params = buffer->size(); 3719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch break; 3729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch case GL_BUFFER_USAGE: 3739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *params = buffer->usage(); 3749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch break; 3759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch default: 3769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch NOTREACHED(); 3779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 3789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 3799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BufferManager::SetTarget(Buffer* buffer, GLenum target) { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that we are not trying to bind it to a different target. 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buffer->target() != 0 && buffer->target() != target && 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !allow_buffers_on_multiple_targets_) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buffer->target() == 0) { 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->set_target(target); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Since one BufferManager can be shared by multiple decoders, ContextState is 3939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// passed in each time and not just passed in during initialization. 3949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochBuffer* BufferManager::GetBufferInfoForTarget( 3959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ContextState* state, GLenum target) { 3969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); 3979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (target == GL_ARRAY_BUFFER) { 3989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return state->bound_array_buffer.get(); 3999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } else { 4009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return state->vertex_attrib_manager->element_array_buffer(); 4019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 4029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 4039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gles2 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 408