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