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